# Copyright (C) 2019 Intel Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
import parser_lib
import subprocess
MEM_PATH = ['/proc/iomem', '/proc/meminfo']
TTY_PATH = '/sys/class/tty/'
SYS_IRQ_PATH = '/proc/interrupts'
CPU_INFO_PATH = '/sys/devices/system/cpu/possible'
# Please refer kernel_src/include/linux/serial_core.h
ttys_type = {
'0': 'PORT', # 8b I/O port access
'2': 'MMIO', # driver-specific
'3': 'MMIO', # 32b little endian
'6': 'MMIO', # 32b big endian
}
ttys_irqs = []
def read_ttys_node(path):
with open(path, 'rt') as info:
ret_value = info.readline().strip()
return ret_value
def detected_ttys():
ttys_cnt = 8
tty_used_list = []
for s_inc in range(ttys_cnt):
cmd = 'stty -F /dev/ttyS{}'.format(s_inc)
res = parser_lib.cmd_execute('{}'.format(cmd))
while True:
line = res.stdout.readline().decode('ascii')
line_len = len(line.split())
if not line_len or line.split()[-1] == 'error':
break
ttys_n = "/dev/ttyS{}".format(s_inc)
tty_used_list.append(ttys_n)
break
return tty_used_list
def is_bdf_format(bdf):
is_bdf = False
if len(bdf) == 7 and len(bdf.split(':')[0]) == 2 and len(bdf.split(':')[1].split('.')[0]) == 2 and len(bdf.split(".")[1]) == 1:
is_bdf = True
return is_bdf
def iomem2bdf(base):
bdf = ''
base_iomem = base.strip('0x').lower()
with open(MEM_PATH[0], 'rt') as mem_info:
while True:
line = mem_info.readline().strip('\n')
if not line:
break
if base_iomem in line and '0000:' in line:
bdf = line.split(" ")[-1].lstrip("0000").lstrip(":")
if not is_bdf_format(bdf):
continue
else:
break
return bdf
def dump_ttys_info(ttys_list, config):
for ttys in ttys_list:
ttys_n = ttys.split('/')[-1]
type_path = '{}{}/io_type'.format(TTY_PATH, ttys_n)
serial_type = read_ttys_node(type_path)
irq_path = '{}{}/irq'.format(TTY_PATH, ttys_n)
irq = read_ttys_node(irq_path)
ttys_irqs.append(irq)
if ttys_type[serial_type] == 'PORT':
base_path = '{}{}/port'.format(TTY_PATH, ttys_n)
base = read_ttys_node(base_path)
print("\tseri:{} type:portio base:{} irq:{}".format(ttys, base, irq), file=config)
elif ttys_type[serial_type] == 'MMIO':
base_path = '{}{}/iomem_base'.format(TTY_PATH, ttys_n)
base = read_ttys_node(base_path)
bdf = iomem2bdf(base)
if bdf:
print('\tseri:{} type:mmio base:{} irq:{} bdf:"{}"'.format(ttys, base, irq, bdf), file=config)
else:
print('\tseri:{} type:mmio base:{} irq:{}'.format(ttys, base, irq), file=config)
def dump_ttys(config):
"""This will get systemd ram which are usable
:param config: file pointer that opened for writing board config information
"""
print("\t", file=config)
ttys_list = detected_ttys()
dump_ttys_info(ttys_list, config)
print("\t", file=config)
print("", file=config)
def dump_free_irqs(config):
irq_list = ['3', '4', '5', '6', '7', '8', '10', '11', '12', '13', '14', '15']
for tty_irq in ttys_irqs:
if tty_irq in irq_list:
irq_list.remove(tty_irq)
print("\t", file=config)
with open(SYS_IRQ_PATH, 'rt') as irq_config:
while True:
line = irq_config.readline().strip()
if ':' not in line:
continue
irq_num = line.split(':')[0]
if not line or int(irq_num) >= 16:
break
if irq_num in irq_list:
irq_list.remove(irq_num)
i_cnt = 0
print("\t", end="", file=config)
for irq in irq_list:
i_cnt += 1
if i_cnt == len(irq_list):
print("{}".format(irq), file=config)
else:
print("{}, ".format(irq), end="", file=config)
print("\t", file=config)
print("", file=config)
def dump_system_ram(config):
"""This will get systemd ram which are usable
:param config: file pointer that opened for writing board config information
"""
print("\t", file=config)
with open(MEM_PATH[0], 'rt') as mem_info:
while True:
line = mem_info.readline().strip('\n')
if not line:
break
print("\t{}".format(line), file=config)
print("\t", file=config)
print("", file=config)
def dump_block_dev(config):
"""This will get available block device
:param config: file pointer that opened for writing board config information
"""
cmd = 'blkid'
desc = 'BLOCK_DEVICE_INFO'
parser_lib.dump_execute(cmd, desc, config)
print("", file=config)
def dump_total_mem(config):
total_mem = 0
print("\t", file=config)
with open(MEM_PATH[1], 'rt') as mem_info:
while True:
line = mem_info.readline().strip()
if not line:
break
if ':' in line and line.split(':')[0].strip() == "MemTotal":
total_mem = line.split(':')[1]
print("\t{}".format(total_mem.strip()), file=config)
print("\t", file=config)
print("", file=config)
def dump_cpu_core_info(config):
print("\t", file=config)
with open(CPU_INFO_PATH, 'rt') as cpu_info:
line = cpu_info.readline()
processor_id = int(line.split('-')[0].strip())
print("\t{}".format(processor_id), end="", file=config)
processor_id += 1
while (processor_id <= int(line.split('-')[1].strip())):
print(", {}".format(processor_id), end="", file=config)
processor_id += 1
print("", file=config)
print("\t", file=config)
print("", file=config)
def dump_max_msix_table_num(config):
msix_table_num_list = []
max_msix_table_num = 1
cmd = 'lspci -vv | grep "MSI-X" | grep "Count="'
res_lines = parser_lib.get_output_lines(cmd)
for line in res_lines:
tmp_num = line.split('=')[1].split()[0]
msix_table_num_list.append(int(tmp_num))
if msix_table_num_list:
max_msix_table_num = max(msix_table_num_list)
print("\t", file=config)
print("\t{}".format(max_msix_table_num), file=config)
print("\t", file=config)
def dump_dev_config_info(config):
dump_max_msix_table_num(config)
print("", file=config)
def generate_info(board_info):
"""Get System Ram information
:param board_info: this is the file which stores the hardware board information
"""
with open(board_info, 'a+') as config:
dump_system_ram(config)
dump_block_dev(config)
dump_ttys(config)
dump_free_irqs(config)
dump_total_mem(config)
dump_cpu_core_info(config)
dump_dev_config_info(config)