1# Copyright (C) 2019-2022 Intel Corporation. 2# 3# SPDX-License-Identifier: BSD-3-Clause 4# 5 6import parser_lib, os, re 7from inspectorlib import external_tools 8from extractors.helpers import get_bdf_from_realpath 9 10MEM_PATH = ['/proc/iomem', '/proc/meminfo'] 11TTY_PATH = '/sys/class/tty/' 12SYS_IRQ_PATH = '/proc/interrupts' 13CPU_INFO_PATH = '/sys/devices/system/cpu/possible' 14 15# Please refer kernel_src/include/linux/serial_core.h 16ttys_type = { 17 '0': 'PORT', # 8b I/O port access 18 '2': 'MMIO', # driver-specific 19 '3': 'MMIO', # 32b little endian 20 '6': 'MMIO', # 32b big endian 21} 22 23 24ttys_irqs = [] 25 26 27def read_ttys_node(path): 28 with open(path, 'rt') as info: 29 ret_value = info.readline().strip() 30 31 return ret_value 32 33 34def detected_ttys(): 35 ttys_cnt = 8 36 tty_used_list = [] 37 for s_inc in range(ttys_cnt): 38 cmd = 'stty -F /dev/ttyS{}'.format(s_inc) 39 res = external_tools.run('{}'.format(cmd)) 40 41 while True: 42 line = res.stdout.readline().decode('ascii') 43 44 line_len = len(line.split()) 45 if not line_len or line.split()[-1] == 'error': 46 break 47 48 ttys_n = "/dev/ttyS{}".format(s_inc) 49 tty_used_list.append(ttys_n) 50 break 51 52 return tty_used_list 53 54 55def is_bdf_format(bdf): 56 is_bdf = False 57 58 if len(bdf) == 7 and len(bdf.split(':')[0]) == 2 and len(bdf.split(':')[1].split('.')[0]) == 2 and len(bdf.split(".")[1]) == 1: 59 is_bdf = True 60 61 return is_bdf 62 63 64def iomem2bdf(base): 65 bdf = '' 66 base_iomem = base.strip('0x').lower() 67 with open(MEM_PATH[0], 'rt') as mem_info: 68 69 while True: 70 line = mem_info.readline().strip('\n') 71 if not line: 72 break 73 74 if base_iomem in line and '0000:' in line: 75 bdf = line.split(" ")[-1].lstrip("0000").lstrip(":") 76 if not is_bdf_format(bdf): 77 continue 78 else: 79 break 80 81 return bdf 82 83def dump_ttys_info(ttys_list, config): 84 for ttys in ttys_list: 85 ttys_n = ttys.split('/')[-1] 86 type_path = '{}{}/io_type'.format(TTY_PATH, ttys_n) 87 serial_type = read_ttys_node(type_path) 88 89 irq_path = '{}{}/irq'.format(TTY_PATH, ttys_n) 90 irq = read_ttys_node(irq_path) 91 ttys_irqs.append(irq) 92 93 if ttys_type[serial_type] == 'PORT': 94 base_path = '{}{}/port'.format(TTY_PATH, ttys_n) 95 base = read_ttys_node(base_path) 96 try: 97 b = get_bdf_from_realpath(os.path.join(TTY_PATH, ttys_n, 'device')) 98 bdf = f'{b[0]}:{b[1]}.{b[2]}' 99 except AssertionError: 100 bdf = '' 101 if bdf: 102 print("\tseri:{} type:portio base:{} irq:{} bdf:{}".format(ttys, base, irq, bdf), file=config) 103 else: 104 print("\tseri:{} type:portio base:{} irq:{}".format(ttys, base, irq), file=config) 105 elif ttys_type[serial_type] == 'MMIO': 106 base_path = '{}{}/iomem_base'.format(TTY_PATH, ttys_n) 107 base = read_ttys_node(base_path) 108 bdf = iomem2bdf(base) 109 if bdf: 110 print('\tseri:{} type:mmio base:{} irq:{} bdf:"{}"'.format(ttys, base, irq, bdf), file=config) 111 else: 112 print('\tseri:{} type:mmio base:{} irq:{}'.format(ttys, base, irq), file=config) 113 114 115def dump_ttys(config): 116 """This will get systemd ram which are usable 117 :param config: file pointer that opened for writing board config information 118 """ 119 print("\t<TTYS_INFO>", file=config) 120 ttys_list = detected_ttys() 121 122 dump_ttys_info(ttys_list, config) 123 124 print("\t</TTYS_INFO>", file=config) 125 print("", file=config) 126 127 128def dump_free_irqs(config): 129 irq_list = ['3', '4', '5', '6', '7', '8', '10', '11', '12', '13', '14', '15'] 130 for tty_irq in ttys_irqs: 131 if tty_irq in irq_list: 132 irq_list.remove(tty_irq) 133 134 print("\t<AVAILABLE_IRQ_INFO>", file=config) 135 with open(SYS_IRQ_PATH, 'rt') as irq_config: 136 137 while True: 138 line = irq_config.readline().strip() 139 if ':' not in line: 140 continue 141 142 irq_num = line.split(':')[0] 143 if not line or int(irq_num) >= 16: 144 break 145 146 if irq_num in irq_list: 147 irq_list.remove(irq_num) 148 149 i_cnt = 0 150 print("\t", end="", file=config) 151 for irq in irq_list: 152 i_cnt += 1 153 154 if i_cnt == len(irq_list): 155 print("{}".format(irq), file=config) 156 else: 157 print("{}, ".format(irq), end="", file=config) 158 159 print("\t</AVAILABLE_IRQ_INFO>", file=config) 160 print("", file=config) 161 162 163def dump_system_ram(config): 164 """This will get systemd ram which are usable 165 :param config: file pointer that opened for writing board config information 166 """ 167 print("\t<IOMEM_INFO>", file=config) 168 with open(MEM_PATH[0], 'rt', errors='ignore') as mem_info: 169 170 while True: 171 line = mem_info.readline().strip('\n') 172 line = re.sub('[^!-~]+', ' ', line) 173 174 if not line: 175 break 176 177 print("\t{}".format(line), file=config) 178 179 print("\t</IOMEM_INFO>", file=config) 180 print("", file=config) 181 182 183def dump_block_dev(config): 184 """This will get available block device 185 :param config: file pointer that opened for writing board config information 186 """ 187 cmd = 'blkid' 188 desc = 'BLOCK_DEVICE_INFO' 189 parser_lib.dump_execute(cmd, desc, config) 190 print("", file=config) 191 192 193 194def dump_total_mem(config): 195 196 total_mem = 0 197 print("\t<TOTAL_MEM_INFO>", file=config) 198 with open(MEM_PATH[1], 'rt') as mem_info: 199 while True: 200 line = mem_info.readline().strip() 201 202 if not line: 203 break 204 205 if ':' in line and line.split(':')[0].strip() == "MemTotal": 206 total_mem = line.split(':')[1] 207 print("\t{}".format(total_mem.strip()), file=config) 208 209 print("\t</TOTAL_MEM_INFO>", file=config) 210 print("", file=config) 211 212 213def dump_cpu_core_info(config): 214 215 print("\t<CPU_PROCESSOR_INFO>", file=config) 216 with open(CPU_INFO_PATH, 'rt') as cpu_info: 217 line = cpu_info.readline() 218 219 processor_id = int(line.split('-')[0].strip()) 220 print("\t{}".format(processor_id), end="", file=config) 221 222 processor_id += 1 223 while (processor_id <= int(line.split('-')[1].strip())): 224 print(", {}".format(processor_id), end="", file=config) 225 processor_id += 1 226 227 print("", file=config) 228 print("\t</CPU_PROCESSOR_INFO>", file=config) 229 print("", file=config) 230 231def dump_max_msix_table_num(config): 232 233 msix_table_num_list = [] 234 max_msix_table_num = 1 235 cmd = 'lspci -vv | grep "MSI-X" | grep "Count="' 236 res_lines = parser_lib.get_output_lines(cmd) 237 for line in res_lines: 238 tmp_num = line.split('=')[1].split()[0] 239 msix_table_num_list.append(int(tmp_num)) 240 241 if msix_table_num_list: 242 max_msix_table_num = max(msix_table_num_list) 243 print("\t<MAX_MSIX_TABLE_NUM>", file=config) 244 print("\t{}".format(max_msix_table_num), file=config) 245 print("\t</MAX_MSIX_TABLE_NUM>", file=config) 246 247 248def dump_dev_config_info(config): 249 250 dump_max_msix_table_num(config) 251 print("", file=config) 252 253def generate_info(board_info): 254 """Get System Ram information 255 :param board_info: this is the file which stores the hardware board information 256 """ 257 with open(board_info, 'a+') as config: 258 259 dump_system_ram(config) 260 261 dump_block_dev(config) 262 263 dump_ttys(config) 264 265 dump_free_irqs(config) 266 267 dump_total_mem(config) 268 269 dump_cpu_core_info(config) 270 271 dump_dev_config_info(config) 272