mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-09-16 14:28:56 +00:00
board-inspector: reorganize the scripts
This patch reorganize the files of the board inspector as follows. 1. Rename the directory name from `target` to `board_inspector`, in order to align with the name used in ACRN documentation. 2. Move the scripts that generate the current board XML into the `legacy` sub-directory. The legacy nodes will be removed after transitioning to the new board XML schema completely, 3. Add the main script `cli.py` which is the command line interface of the board inspector. v1 -> v2: - Rename `run.py` to `cli.py`. Tracked-On: #5922 Signed-off-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
661
misc/config_tools/board_inspector/legacy/acpi.py
Normal file
661
misc/config_tools/board_inspector/legacy/acpi.py
Normal file
@@ -0,0 +1,661 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import shutil
|
||||
from collections import defaultdict
|
||||
import dmar
|
||||
import parser_lib
|
||||
|
||||
|
||||
SYS_PATH = ['/proc/cpuinfo', '/sys/firmware/acpi/tables/', '/sys/devices/system/cpu/']
|
||||
|
||||
ACPI_OP = {
|
||||
'AML_ZERO_OP':0x00,
|
||||
'AML_ONE_OP':0x01,
|
||||
'AML_ALIAS_OP':0x06,
|
||||
'AML_NAME_OP':0x08,
|
||||
'AML_BYTE_OP':0x0a,
|
||||
'AML_WORD_OP':0x0b,
|
||||
'AML_DWORD_OP':0x0c,
|
||||
'AML_PACKAGE_OP':0x12,
|
||||
'AML_VARIABLE_PACKAGE_OP':0x13,
|
||||
}
|
||||
|
||||
SPACE_ID = {
|
||||
0:'SPACE_SYSTEM_MEMORY',
|
||||
1:'SPACE_SYSTEM_IO',
|
||||
2:'SPACE_PCI_CONFIG',
|
||||
3:'SPACE_Embedded_Control',
|
||||
4:'SPACE_SMBUS',
|
||||
10:'SPACE_PLATFORM_COMM',
|
||||
0x7F:'SPACE_FFixedHW',
|
||||
}
|
||||
|
||||
FACP_OFF = {
|
||||
'facs_addr':36,
|
||||
'reset_addr':116,
|
||||
'reset_value':128,
|
||||
'pm1a_evt':148,
|
||||
'pm1b_evt':160,
|
||||
'pm1a_cnt':172,
|
||||
'pm1b_cnt':184,
|
||||
}
|
||||
|
||||
class SxPkg:
|
||||
"""This is Sx state structure for power"""
|
||||
def __init__(self):
|
||||
# This is Sx state structure for power
|
||||
self.val_pm1a = ''
|
||||
self.val_pm1b = ''
|
||||
self.reserved = ''
|
||||
|
||||
def style_check_1(self):
|
||||
"""Style check if have public method"""
|
||||
self.val_pm1a = ''
|
||||
|
||||
def style_check_2(self):
|
||||
"""Style check if have public method"""
|
||||
self.val_pm1a = ''
|
||||
|
||||
class GasType:
|
||||
"""This is generic address structure for power"""
|
||||
def __init__(self):
|
||||
self.space_id_8b = 0
|
||||
self.bit_width_8b = 0
|
||||
self.bit_offset_8b = 0
|
||||
self.access_size_8b = 0
|
||||
self.address_64b = 0
|
||||
|
||||
def style_check_1(self):
|
||||
"""Style check if have public method"""
|
||||
self.space_id_8b = ''
|
||||
|
||||
def style_check_2(self):
|
||||
"""Style check if have public method"""
|
||||
self.space_id_8b = ''
|
||||
|
||||
class PxPkg:
|
||||
"""This is Px state structure for power"""
|
||||
def __init__(self):
|
||||
self.core_freq = 0
|
||||
self.power = 0
|
||||
self.trans_latency = 0
|
||||
self.bus_latency = 0
|
||||
self.control = 0
|
||||
self.status = 0
|
||||
|
||||
def style_check_1(self):
|
||||
"""Style check if have public method"""
|
||||
self.power = ''
|
||||
|
||||
def style_check_2(self):
|
||||
"""Style check if have public method"""
|
||||
self.power = ''
|
||||
|
||||
class ResetReg:
|
||||
"""This is Reset Registers meta data"""
|
||||
def __init__(self):
|
||||
self.reset_reg_addr = 0
|
||||
self.reset_reg_space_id = 0
|
||||
self.reset_reg_val = 0
|
||||
|
||||
def style_check_1(self):
|
||||
"""Style check if have public method"""
|
||||
self.reset_reg_val = ''
|
||||
|
||||
def style_check_2(self):
|
||||
"""Style check if have public method"""
|
||||
self.reset_reg_val = ''
|
||||
|
||||
DWORD_LEN = 4
|
||||
PACK_TYPE_LEN = 12
|
||||
WAKE_VECTOR_OFFSET_32 = 12
|
||||
WAKE_VECTOR_OFFSET_64 = 24
|
||||
MCFG_OFFSET = 4
|
||||
MCFG_ENTRY1_OFFSET = 60
|
||||
MCFG_ENTRY0_BASE_OFFSET = 44
|
||||
|
||||
S3_PKG = SxPkg()
|
||||
S5_PKG = SxPkg()
|
||||
PackedGas = GasType
|
||||
PackedCx = GasType
|
||||
|
||||
|
||||
def store_cpu_info(sysnode, config):
|
||||
"""This will get CPU information
|
||||
:param sysnode: the path to get cpu information, like: /proc/cpuifo
|
||||
:param config: file pointer that opened for writing board config information
|
||||
"""
|
||||
with open(sysnode, 'r') as f_node:
|
||||
line = f_node.readline()
|
||||
while line:
|
||||
if len(line.split(':')) >= 2:
|
||||
if line.split(':')[0].strip() == "model name":
|
||||
model_name = line.split(':')[1].strip()
|
||||
print('\t"{0}"'.format(model_name), file=config)
|
||||
break
|
||||
line = f_node.readline()
|
||||
|
||||
|
||||
def write_reset_reg(rst_reg_addr, rst_reg_space_id, rst_reg_val, config):
|
||||
"""Write reset register info
|
||||
:param rst_reg_addr: reset register address
|
||||
:param rst_reg_space_id: reset register space id
|
||||
:param rst_reg_val: reset register value
|
||||
:param config: file pointer that opened for writing board config information
|
||||
"""
|
||||
print("\t{0}".format("<RESET_REGISTER_INFO>"), file=config)
|
||||
print("\t#define RESET_REGISTER_ADDRESS 0x{:0>2X}UL".format(
|
||||
rst_reg_addr), file=config)
|
||||
print("\t#define RESET_REGISTER_SPACE_ID {0}".format(
|
||||
SPACE_ID[rst_reg_space_id]), file=config)
|
||||
print("\t#define RESET_REGISTER_VALUE {0}U".format(
|
||||
rst_reg_val), file=config)
|
||||
print("\t{0}\n".format("</RESET_REGISTER_INFO>"), file=config)
|
||||
|
||||
|
||||
def get_vector_reset(sysnode, config):
|
||||
"""This will get reset register value
|
||||
:param sysnode: the system node of Px power state, like:/sys/firmware/acpi/tables/FACP
|
||||
:param config: file pointer that opened for writing board config information
|
||||
"""
|
||||
reset_reg = ResetReg()
|
||||
for key, offset in FACP_OFF.items():
|
||||
with open(sysnode, 'rb') as f_node:
|
||||
f_node.seek(offset, 0)
|
||||
if key == 'facs_addr':
|
||||
packed_data = f_node.read(DWORD_LEN)
|
||||
packed_data_32 = int.from_bytes(packed_data, 'little')+WAKE_VECTOR_OFFSET_32
|
||||
packed_data_64 = int.from_bytes(packed_data, 'little')+WAKE_VECTOR_OFFSET_64
|
||||
print("\t{0}".format("<WAKE_VECTOR_INFO>"), file=config)
|
||||
print("\t#define WAKE_VECTOR_32 0x{:0>2X}UL".format(
|
||||
packed_data_32), file=config)
|
||||
print("\t#define WAKE_VECTOR_64 0x{:0>2X}UL".format(
|
||||
packed_data_64), file=config)
|
||||
print("\t{0}\n".format("</WAKE_VECTOR_INFO>"), file=config)
|
||||
elif key == 'reset_addr':
|
||||
packed_data = f_node.read(PACK_TYPE_LEN)
|
||||
reset_reg.reset_reg_space_id = packed_data[0]
|
||||
reset_reg.reset_reg_addr = int.from_bytes(packed_data[4:11], 'little')
|
||||
elif key == 'reset_value':
|
||||
packed_data = f_node.read(1)
|
||||
reset_reg.reset_reg_val = hex(packed_data[0])
|
||||
|
||||
write_reset_reg(reset_reg.reset_reg_addr, reset_reg.reset_reg_space_id,
|
||||
reset_reg.reset_reg_val, config)
|
||||
|
||||
|
||||
def read_pm_sstate(sysnode, config):
|
||||
"""This will read Px state of power
|
||||
:param sysnode: the system node of Px power state, like:/sys/firmware/acpi/tables/FACP
|
||||
:param config: file pointer that opened for writing board config information
|
||||
"""
|
||||
get_vector_reset(sysnode, config)
|
||||
print("\t{0}".format("<PM_INFO>"), file=config)
|
||||
for key, offset in FACP_OFF.items():
|
||||
with open(sysnode, 'rb') as f_node:
|
||||
f_node.seek(offset, 0)
|
||||
|
||||
packed_data = f_node.read(PACK_TYPE_LEN)
|
||||
PackedGas.space_id_8b = packed_data[0]
|
||||
PackedGas.bit_width_8b = packed_data[1]
|
||||
PackedGas.bit_offset_8b = packed_data[2]
|
||||
PackedGas.access_size_8b = packed_data[3]
|
||||
PackedGas.address_64b = int.from_bytes(packed_data[4:11], 'little')
|
||||
|
||||
if key == 'pm1a_evt':
|
||||
print("\t#define PM1A_EVT_SPACE_ID {0}".format(
|
||||
SPACE_ID[PackedGas.space_id_8b]), file=config)
|
||||
print("\t#define PM1A_EVT_BIT_WIDTH {0}U".format(
|
||||
hex(PackedGas.bit_width_8b)), file=config)
|
||||
print("\t#define PM1A_EVT_BIT_OFFSET {0}U".format(
|
||||
hex(PackedGas.bit_offset_8b)), file=config)
|
||||
print("\t#define PM1A_EVT_ADDRESS {0}UL".format(
|
||||
hex(PackedGas.address_64b)), file=config)
|
||||
print("\t#define PM1A_EVT_ACCESS_SIZE {0}U".format(
|
||||
hex(PackedGas.access_size_8b)), file=config)
|
||||
elif key == 'pm1a_cnt':
|
||||
print("\t#define PM1A_CNT_SPACE_ID {0}".format(
|
||||
SPACE_ID[PackedGas.space_id_8b]), file=config)
|
||||
print("\t#define PM1A_CNT_BIT_WIDTH {0}U".format(
|
||||
hex(PackedGas.bit_width_8b)), file=config)
|
||||
print("\t#define PM1A_CNT_BIT_OFFSET {0}U".format(
|
||||
hex(PackedGas.bit_offset_8b)), file=config)
|
||||
print("\t#define PM1A_CNT_ADDRESS {0}UL".format(
|
||||
hex(PackedGas.address_64b)), file=config)
|
||||
print("\t#define PM1A_CNT_ACCESS_SIZE {0}U".format(
|
||||
hex(PackedGas.access_size_8b)), file=config)
|
||||
elif key == 'pm1b_evt':
|
||||
print("\t#define PM1B_EVT_SPACE_ID {0}".format(
|
||||
SPACE_ID[PackedGas.space_id_8b]), file=config)
|
||||
print("\t#define PM1B_EVT_BIT_WIDTH {0}U".format(
|
||||
hex(PackedGas.bit_width_8b)), file=config)
|
||||
print("\t#define PM1B_EVT_BIT_OFFSET {0}U".format(
|
||||
hex(PackedGas.bit_offset_8b)), file=config)
|
||||
print("\t#define PM1B_EVT_ADDRESS {0}UL".format(
|
||||
hex(PackedGas.address_64b)), file=config)
|
||||
print("\t#define PM1B_EVT_ACCESS_SIZE {0}U".format(
|
||||
hex(PackedGas.access_size_8b)), file=config)
|
||||
elif key == 'pm1b_cnt':
|
||||
print("\t#define PM1B_CNT_SPACE_ID {0}".format(
|
||||
SPACE_ID[PackedGas.space_id_8b]), file=config)
|
||||
print("\t#define PM1B_CNT_BIT_WIDTH {0}U".format(
|
||||
hex(PackedGas.bit_width_8b)), file=config)
|
||||
print("\t#define PM1B_CNT_BIT_OFFSET {0}U".format(
|
||||
hex(PackedGas.bit_offset_8b)), file=config)
|
||||
print("\t#define PM1B_CNT_ADDRESS {0}UL".format(
|
||||
hex(PackedGas.address_64b)), file=config)
|
||||
print("\t#define PM1B_CNT_ACCESS_SIZE {0}U".format(
|
||||
hex(PackedGas.access_size_8b)), file=config)
|
||||
print("\t{0}\n".format("</PM_INFO>"), file=config)
|
||||
|
||||
|
||||
def if_sx_name(sx_name, f_node):
|
||||
"""If sx name in this field
|
||||
:param sx_name: Sx name in DSDT of apci table, like _s3_, _s5_
|
||||
:param f_node: f_node: file pointer that opened for reading sx from
|
||||
"""
|
||||
need_break = need_continue = 0
|
||||
name_buf = f_node.read(4)
|
||||
if not name_buf:
|
||||
need_break = True
|
||||
return (need_break, need_continue)
|
||||
|
||||
try:
|
||||
if name_buf.decode('ascii').find(sx_name) != -1:
|
||||
pass
|
||||
else:
|
||||
need_continue = True
|
||||
except ValueError:
|
||||
need_continue = True
|
||||
return (need_break, need_continue)
|
||||
else:
|
||||
pass
|
||||
|
||||
return (need_break, need_continue)
|
||||
|
||||
|
||||
def read_sx_locate(sx_name, f_node):
|
||||
"""Read the location of sx
|
||||
:param sx_name: Sx name in DSDT of apci table, like _s3_, _s5_
|
||||
:param f_node: file pointer that opened for sx reading from
|
||||
"""
|
||||
need_continue = need_break = pkg_len = 0
|
||||
|
||||
(need_break, need_continue) = if_sx_name(sx_name, f_node)
|
||||
|
||||
tmp_char = f_node.read(1)
|
||||
if not tmp_char:
|
||||
need_break = True
|
||||
return (need_break, need_continue, pkg_len)
|
||||
if hex(int.from_bytes(tmp_char, 'little')) != hex(ACPI_OP['AML_PACKAGE_OP']):
|
||||
need_continue = True
|
||||
return (need_break, need_continue, pkg_len)
|
||||
|
||||
pkg_len = f_node.read(1)
|
||||
if not pkg_len:
|
||||
need_break = True
|
||||
return (need_break, need_continue, pkg_len)
|
||||
if int.from_bytes(pkg_len, 'little') < 5 or int.from_bytes(pkg_len, 'little') > 28:
|
||||
need_continue = True
|
||||
return (need_break, need_continue, pkg_len)
|
||||
|
||||
return (need_break, need_continue, pkg_len)
|
||||
|
||||
|
||||
def decode_sx_pkg(pkg_len, f_node):
|
||||
"""Parse and decode the sx pkg
|
||||
:param pkg_len: the length of sx package read from f_node
|
||||
:param f_node: file pointer that opened for sx reading from
|
||||
"""
|
||||
pkg_val_pm1a = pkg_val_pm1b = pkg_val_resv = need_break = 0
|
||||
pkg_buf = f_node.read(int.from_bytes(pkg_len, 'little'))
|
||||
if hex(pkg_buf[1]) == ACPI_OP['AML_ZERO_OP'] or \
|
||||
hex(pkg_buf[1]) == hex(ACPI_OP['AML_ONE_OP']):
|
||||
pkg_val_pm1a = pkg_buf[1]
|
||||
if hex(pkg_buf[2]) == hex(ACPI_OP['AML_ZERO_OP']) or \
|
||||
hex(pkg_buf[2]) == hex(ACPI_OP['AML_ONE_OP']):
|
||||
pkg_val_pm1b = pkg_buf[2]
|
||||
pkg_val_resv = pkg_buf[3:5]
|
||||
elif hex(pkg_buf[2]) == hex(ACPI_OP['AML_BYTE_OP']):
|
||||
pkg_val_pm1b = pkg_buf[3]
|
||||
pkg_val_resv = pkg_buf[4:6]
|
||||
else:
|
||||
need_break = True
|
||||
return (pkg_val_pm1a, pkg_val_pm1b, pkg_val_resv, need_break)
|
||||
|
||||
elif hex(pkg_buf[1]) == hex(ACPI_OP['AML_BYTE_OP']):
|
||||
pkg_val_pm1a = pkg_buf[2]
|
||||
if hex(pkg_buf[3]) == hex(ACPI_OP['AML_ZERO_OP']) or \
|
||||
hex(pkg_buf[3]) == hex(ACPI_OP['AML_ONE_OP']):
|
||||
pkg_val_pm1b = pkg_buf[3]
|
||||
pkg_val_resv = pkg_buf[4:6]
|
||||
elif hex(pkg_buf[3]) == hex(ACPI_OP['AML_BYTE_OP']):
|
||||
pkg_val_pm1b = pkg_buf[4]
|
||||
pkg_val_resv = pkg_buf[5:7]
|
||||
else:
|
||||
need_break = True
|
||||
return (pkg_val_pm1a, pkg_val_pm1b, pkg_val_resv, need_break)
|
||||
else:
|
||||
need_break = True
|
||||
|
||||
return (pkg_val_pm1a, pkg_val_pm1b, pkg_val_resv, need_break)
|
||||
|
||||
|
||||
def set_default_sx_value(sx_name, config):
|
||||
print("\t/* {} is not supported by BIOS */".format(sx_name), file=config)
|
||||
print("\t#define {}_PKG_VAL_PM1A 0x0U".format(sx_name), file=config)
|
||||
print("\t#define {}_PKG_VAL_PM1B 0x0U".format(sx_name), file=config)
|
||||
print("\t#define {}_PKG_RESERVED 0x0U".format(sx_name), file=config)
|
||||
|
||||
|
||||
def read_pm_sdata(sysnode, sx_name, config):
|
||||
"""This will read pm Sx state of power
|
||||
:param sysnode: the system node of Sx power state, like:/sys/firmware/acpi/tables/DSDT
|
||||
:param sx_name: Sx name in DSDT of apci table, like _s3_, _s5_
|
||||
:param config: file pointer that opened for writing board config information
|
||||
"""
|
||||
with open(sysnode, 'rb') as f_node:
|
||||
while True:
|
||||
inc = f_node.read(1)
|
||||
if inc:
|
||||
if hex(int.from_bytes(inc, 'little')) != hex(ACPI_OP['AML_NAME_OP']):
|
||||
continue
|
||||
|
||||
(need_break, need_continue, pkg_len) = read_sx_locate(sx_name, f_node)
|
||||
if need_break:
|
||||
# BIOS dose not support for SX, set it to default value
|
||||
s_name = ''
|
||||
if 'S3' in sx_name:
|
||||
s_name = 'S3'
|
||||
else:
|
||||
s_name = 'S5'
|
||||
|
||||
set_default_sx_value(s_name, config)
|
||||
break
|
||||
if need_continue:
|
||||
continue
|
||||
|
||||
# decode sx pkg
|
||||
(pkg_val_pm1a, pkg_val_pm1b, pkg_val_resv, need_break) =\
|
||||
decode_sx_pkg(pkg_len, f_node)
|
||||
if need_break:
|
||||
break
|
||||
|
||||
else:
|
||||
break
|
||||
|
||||
if sx_name == '_S3_':
|
||||
S3_PKG.val_pm1a = pkg_val_pm1a
|
||||
S3_PKG.val_pm1b = pkg_val_pm1b
|
||||
S3_PKG.reserved = pkg_val_resv
|
||||
print("\t#define S3_PKG_VAL_PM1A {0}".format(
|
||||
hex(S3_PKG.val_pm1a))+'U', file=config)
|
||||
print("\t#define S3_PKG_VAL_PM1B {0}".format(
|
||||
S3_PKG.val_pm1b)+'U', file=config)
|
||||
print("\t#define S3_PKG_RESERVED {0}".format(
|
||||
hex(int.from_bytes(S3_PKG.reserved, 'little')))+'U', file=config)
|
||||
|
||||
if sx_name == "_S5_":
|
||||
S5_PKG.val_pm1a = pkg_val_pm1a
|
||||
S5_PKG.val_pm1b = pkg_val_pm1b
|
||||
S5_PKG.reserved = pkg_val_resv
|
||||
print("\t#define S5_PKG_VAL_PM1A {0}".format(
|
||||
hex(S5_PKG.val_pm1a))+'U', file=config)
|
||||
print("\t#define S5_PKG_VAL_PM1B {0}".format(
|
||||
S5_PKG.val_pm1b)+'U', file=config)
|
||||
print("\t#define S5_PKG_RESERVED {0}".format(
|
||||
hex(int.from_bytes(S5_PKG.reserved, 'little')))+'U', file=config)
|
||||
|
||||
|
||||
def get_value_after_str(cstate_str, hw_type):
|
||||
""" Get the value after cstate string """
|
||||
idx = 0
|
||||
cstate_list = cstate_str.split()
|
||||
for idx_hw_type, val in enumerate(cstate_list):
|
||||
if val.find(hw_type) != -1:
|
||||
idx = idx_hw_type
|
||||
break
|
||||
|
||||
return cstate_list[idx + 1]
|
||||
|
||||
|
||||
def store_cx_data(sysnode1, sysnode2, config):
|
||||
"""This will get Cx data of power and store it to PackedCx
|
||||
:param sysnode1: the path of cx power state driver
|
||||
:param sysnode2: the path of cpuidle
|
||||
:param config: file pointer that opened for writing board config information
|
||||
"""
|
||||
i = 0
|
||||
state_cpus = {}
|
||||
try:
|
||||
with open(sysnode1, 'r') as acpi_idle:
|
||||
idle_driver = acpi_idle.read(32)
|
||||
|
||||
if idle_driver.find("acpi_idle") == -1:
|
||||
parser_lib.print_yel("The Cx data for ACRN relies on " +\
|
||||
"acpi_idle driver but it is not found, ", warn=True, end=False)
|
||||
if idle_driver.find("intel_idle") == 0:
|
||||
print("please add idle=nomwait in kernel " +\
|
||||
"cmdline to fall back to acpi_idle driver")
|
||||
else:
|
||||
parser_lib.print_yel("please make sure ACPI Cstate is enabled in BIOS.", warn=True)
|
||||
print("\t/* Cx data is not available */", file=config)
|
||||
return
|
||||
except IOError:
|
||||
parser_lib.print_yel("No idle driver found.", warn=True)
|
||||
print("\t/* Cx data is not available */", file=config)
|
||||
return
|
||||
|
||||
files = os.listdir(sysnode2)
|
||||
for d_path in files:
|
||||
if os.path.isdir(sysnode2+d_path):
|
||||
state_cpus[d_path] = sysnode2+d_path
|
||||
|
||||
state_cpus = sorted(state_cpus.keys())
|
||||
del state_cpus[0]
|
||||
cpu_state = ['desc', 'latency', 'power']
|
||||
acpi_hw_type = ['HLT', 'MWAIT', 'IOPORT']
|
||||
|
||||
cx_state = defaultdict(dict)
|
||||
c_cnt = 1
|
||||
for state in state_cpus:
|
||||
i += 1
|
||||
for item in cpu_state:
|
||||
cx_data_file = open(sysnode2+state+'/'+item, 'r')
|
||||
cx_state[state][item] = cx_data_file.read().strip()
|
||||
cx_state[state]['type'] = i
|
||||
|
||||
PackedCx.space_id_8b = SPACE_ID[0x7F]
|
||||
if cx_state[state][cpu_state[0]].find(acpi_hw_type[0]) != -1:
|
||||
PackedCx.bit_width_8b = 0
|
||||
PackedCx.bit_offset_8b = 0
|
||||
PackedCx.access_size_8b = 0
|
||||
PackedCx.address_64b = 0
|
||||
elif cx_state[state][cpu_state[0]].find(acpi_hw_type[1]) != -1:
|
||||
PackedCx.bit_width_8b = 1
|
||||
PackedCx.bit_offset_8b = 2
|
||||
PackedCx.access_size_8b = 1
|
||||
addr_val = get_value_after_str(cx_state[state][cpu_state[0]], acpi_hw_type[1])
|
||||
PackedCx.address_64b = addr_val
|
||||
elif cx_state[state][cpu_state[0]].find(acpi_hw_type[2]) != -1:
|
||||
PackedCx.space_id_8b = SPACE_ID[1]
|
||||
PackedCx.bit_width_8b = 8
|
||||
PackedCx.bit_offset_8b = 0
|
||||
PackedCx.access_size_8b = 0
|
||||
addr_val = get_value_after_str(cx_state[state][cpu_state[0]], acpi_hw_type[2])
|
||||
PackedCx.address_64b = addr_val
|
||||
print("\t{{{{{}, 0x{:0>2X}U, 0x{:0>2X}U, 0x{:0>2X}U, ".format(
|
||||
PackedCx.space_id_8b, PackedCx.bit_width_8b, PackedCx.bit_offset_8b,
|
||||
PackedCx.access_size_8b), file=config, end="")
|
||||
print("0x{:0>2X}UL}}, 0x{:0>2X}U, 0x{:0>2X}U, 0x{:0>2X}U}},\t/* C{} */".format(
|
||||
int(str(PackedCx.address_64b), 16),
|
||||
cx_state[state]['type'], int(cx_state[state][cpu_state[1]]),
|
||||
int(cx_state[state][cpu_state[2]]), c_cnt), file=config)
|
||||
c_cnt += 1
|
||||
|
||||
|
||||
def store_px_data(sysnode, config):
|
||||
"""This will get Px data of power and store it to px data
|
||||
:param sysnode: the path of system power state, such as: /sys/devices/system/cpu/
|
||||
:param config: file pointer that opened for writing board config information
|
||||
"""
|
||||
px_tmp = PxPkg()
|
||||
px_data = {}
|
||||
|
||||
try:
|
||||
with open(sysnode+'cpu0/cpufreq/scaling_driver', 'r') as f_node:
|
||||
freq_driver = f_node.read()
|
||||
if freq_driver.find("acpi-cpufreq") == -1:
|
||||
parser_lib.print_yel("The Px data for ACRN relies on " +\
|
||||
"acpi-cpufreq driver but it is not found, ", warn=True, end=False)
|
||||
if freq_driver.find("intel_pstate") == 0:
|
||||
print("please add intel_pstate=disable in kernel " +\
|
||||
"cmdline to fall back to acpi-cpufreq driver")
|
||||
else:
|
||||
parser_lib.print_yel("please make sure ACPI Pstate is enabled in BIOS.", warn=True)
|
||||
print("\t/* Px data is not available */", file=config)
|
||||
return
|
||||
except IOError:
|
||||
parser_lib.print_yel("No scaling_driver found.", warn=True)
|
||||
print("\t/* Px data is not available */", file=config)
|
||||
return
|
||||
|
||||
try:
|
||||
with open(sysnode+'cpufreq/boost', 'r') as f_node:
|
||||
boost = f_node.read()
|
||||
except IOError:
|
||||
boost = 0
|
||||
parser_lib.print_yel("CPU turbo is not enabled!")
|
||||
|
||||
with open(sysnode + 'cpu0/cpufreq/scaling_available_frequencies', 'r') as f_node:
|
||||
freqs = f_node.read()
|
||||
with open(sysnode + 'cpu0/cpufreq/cpuinfo_transition_latency') as f_node:
|
||||
latency = int(f_node.read().strip())
|
||||
latency = latency//1000
|
||||
|
||||
i = 0
|
||||
p_cnt = 0
|
||||
for freq in freqs.split():
|
||||
if boost != 0 and i == 0:
|
||||
try:
|
||||
subprocess.check_call('/usr/sbin/rdmsr 0x1ad', shell=True, stdout=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError:
|
||||
parser_lib.print_red("MSR 0x1ad not support in this platform!", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
res = subprocess.Popen('/usr/sbin/rdmsr 0x1ad', shell=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
|
||||
result = res.stdout.readline().strip()
|
||||
#max_ratio_cpu = result[-2:]
|
||||
ctl_state = int(result[-2:], 16) << 8
|
||||
i += 1
|
||||
else:
|
||||
ctl_state = int(freq)//100000 << 8
|
||||
|
||||
px_tmp.core_freq = int(int(freq) / 1000)
|
||||
px_tmp.power = 0
|
||||
px_tmp.trans_latency = latency
|
||||
px_tmp.bus_latency = latency
|
||||
px_tmp.control = ctl_state
|
||||
px_tmp.status = ctl_state
|
||||
px_data[freq] = px_tmp
|
||||
print("\t{{0x{:0>2X}UL, 0x{:0>2X}UL, 0x{:0>2X}UL, ".format(
|
||||
px_data[freq].core_freq, px_data[freq].power,
|
||||
px_data[freq].trans_latency), file=config, end="")
|
||||
print("0x{:0>2X}UL, 0x{:0>6X}UL, 0x{:0>6X}UL}},\t/* P{} */".format(
|
||||
px_data[freq].bus_latency, px_data[freq].control,
|
||||
px_data[freq].status, p_cnt), file=config)
|
||||
|
||||
p_cnt += 1
|
||||
|
||||
def store_mmcfg_base_data(mmcfg_node, config):
|
||||
|
||||
print("\t/* PCI mmcfg base of MCFG */", file=config)
|
||||
with open(mmcfg_node, 'rb') as mmcfg:
|
||||
mmcfg.read(MCFG_OFFSET)
|
||||
mmcfg_len_obj = mmcfg.read(DWORD_LEN)
|
||||
mmcfg_len_int = int.from_bytes(mmcfg_len_obj, 'little')
|
||||
|
||||
if mmcfg_len_int > MCFG_ENTRY1_OFFSET:
|
||||
parser_lib.print_red("Multiple PCI segment groups is not supported!", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
mmcfg.seek(MCFG_ENTRY0_BASE_OFFSET, 0)
|
||||
mmcfg_base_addr_obj = mmcfg.read(DWORD_LEN)
|
||||
mmcfg_base_addr = int.from_bytes(mmcfg_base_addr_obj, 'little')
|
||||
print("\t#define DEFAULT_PCI_MMCFG_BASE {}UL".format(hex(mmcfg_base_addr)), file=config)
|
||||
|
||||
|
||||
def read_tpm_data(config):
|
||||
'''get TPM information from ACPI tables
|
||||
:param config: file pointer that opened for writing board config information
|
||||
:return:
|
||||
'''
|
||||
try:
|
||||
acpi_table_output = subprocess.check_output('ls -l /sys/firmware/acpi/tables/'.split()).decode('utf8')
|
||||
except:
|
||||
acpi_table_output = ''
|
||||
if 'TPM2' in acpi_table_output:
|
||||
print("\tTPM2", file=config)
|
||||
else:
|
||||
print("\t/* no TPM device */", file=config)
|
||||
|
||||
|
||||
def gen_acpi_info(config):
|
||||
"""This will parser the sys node form SYS_PATH and generate ACPI info
|
||||
:param config: file pointer that opened for writing board config information
|
||||
"""
|
||||
read_pm_sstate(SYS_PATH[1] + 'FACP', config)
|
||||
|
||||
print("{0}".format("\t<S3_INFO>"), file=config)
|
||||
read_pm_sdata(SYS_PATH[1] + 'DSDT', '_S3_', config)
|
||||
print("{0}".format("\t</S3_INFO>\n"), file=config)
|
||||
|
||||
print("{0}".format("\t<S5_INFO>"), file=config)
|
||||
read_pm_sdata(SYS_PATH[1] + 'DSDT', '_S5_', config)
|
||||
print("{0}".format("\t</S5_INFO>\n"), file=config)
|
||||
|
||||
print("{0}".format("\t<DRHD_INFO>"), file=config)
|
||||
dmar.write_dmar_data(SYS_PATH[1] + 'DMAR', config)
|
||||
print("{0}".format("\t</DRHD_INFO>\n"), file=config)
|
||||
|
||||
print("{0}".format("\t<CPU_BRAND>"), file=config)
|
||||
store_cpu_info(SYS_PATH[0], config)
|
||||
print("{0}".format("\t</CPU_BRAND>\n"), file=config)
|
||||
|
||||
print("{0}".format("\t<CX_INFO>"), file=config)
|
||||
store_cx_data(SYS_PATH[2]+'cpuidle/current_driver', SYS_PATH[2]+'cpu0/cpuidle/', config)
|
||||
print("{0}".format("\t</CX_INFO>\n"), file=config)
|
||||
|
||||
print("{0}".format("\t<PX_INFO>"), file=config)
|
||||
store_px_data(SYS_PATH[2], config)
|
||||
print("{0}".format("\t</PX_INFO>\n"), file=config)
|
||||
|
||||
print("{0}".format("\t<MMCFG_BASE_INFO>"), file=config)
|
||||
store_mmcfg_base_data(SYS_PATH[1] + 'MCFG', config)
|
||||
print("{0}".format("\t</MMCFG_BASE_INFO>\n"), file=config)
|
||||
|
||||
print("{0}".format("\t<TPM_INFO>"), file=config)
|
||||
read_tpm_data(config)
|
||||
print("{0}".format("\t</TPM_INFO>\n"), file=config)
|
||||
|
||||
|
||||
def generate_info(board_file):
|
||||
"""This will generate ACPI info from board file
|
||||
:param board_file: this is the file which stores the hardware board information
|
||||
"""
|
||||
# Generate board info
|
||||
with open(board_file, 'a+') as config:
|
||||
gen_acpi_info(config)
|
||||
|
||||
# get the PTCT table from native environment
|
||||
out_dir = os.path.dirname(board_file)
|
||||
if os.path.isfile(SYS_PATH[1] + 'PTCT'):
|
||||
shutil.copy(SYS_PATH[1] + 'PTCT', out_dir)
|
||||
print("PTCT table has been saved to {} successfully!".format(os.path.join(out_dir, 'PTCT')))
|
144
misc/config_tools/board_inspector/legacy/board_parser.py
Executable file
144
misc/config_tools/board_inspector/legacy/board_parser.py
Executable file
@@ -0,0 +1,144 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import argparse
|
||||
import subprocess
|
||||
import pci_dev
|
||||
import dmi
|
||||
import acpi
|
||||
import clos
|
||||
import misc
|
||||
import parser_lib
|
||||
import rtct
|
||||
|
||||
OUTPUT = "./out/"
|
||||
PY_CACHE = "__pycache__"
|
||||
|
||||
# This file store information which query from hw board
|
||||
BIN_LIST = ['cpuid', 'rdmsr', 'lspci', ' dmidecode', 'blkid', 'stty']
|
||||
|
||||
CPU_VENDOR = "GenuineIntel"
|
||||
|
||||
|
||||
def check_permission():
|
||||
"""Check if it is root permission"""
|
||||
if os.getuid():
|
||||
parser_lib.print_red("You need run this tool with root privileges (sudo)!")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def native_check():
|
||||
"""Check if this is natvie os"""
|
||||
cmd = "cpuid -r -l 0x01"
|
||||
res = parser_lib.cmd_execute(cmd)
|
||||
while True:
|
||||
line = parser_lib.decode_stdout(res)
|
||||
|
||||
if line:
|
||||
|
||||
if len(line.split()) <= 2:
|
||||
continue
|
||||
|
||||
reg_value = line.split()[4].split('=')[1]
|
||||
break
|
||||
|
||||
return int(reg_value, 16) & 0x80000000 == 0
|
||||
|
||||
|
||||
def vendor_check():
|
||||
"""Check the CPU vendor"""
|
||||
with open("/proc/cpuinfo", 'r') as f_node:
|
||||
while True:
|
||||
line = f_node.readline()
|
||||
if len(line.split(':')) == 2:
|
||||
if line.split(':')[0].strip() == "vendor_id":
|
||||
vendor_name = line.split(':')[1].strip()
|
||||
return vendor_name == CPU_VENDOR
|
||||
|
||||
|
||||
def check_env():
|
||||
"""Check if there is appropriate environment on this system"""
|
||||
if os.path.exists(PY_CACHE):
|
||||
shutil.rmtree(PY_CACHE)
|
||||
|
||||
# check cpu vendor id
|
||||
if not vendor_check():
|
||||
parser_lib.print_red("Please run this tools on {}!".format(CPU_VENDOR))
|
||||
sys.exit(1)
|
||||
|
||||
# check if required tools are exists
|
||||
for excute in BIN_LIST:
|
||||
res = subprocess.Popen("which {}".format(excute),
|
||||
shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, close_fds=True)
|
||||
|
||||
line = res.stdout.readline().decode('ascii')
|
||||
if not line:
|
||||
parser_lib.print_yel("'{}' not found, please install it!".format(excute))
|
||||
sys.exit(1)
|
||||
|
||||
if excute == 'cpuid':
|
||||
res = subprocess.Popen("cpuid -v",
|
||||
shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, close_fds=True)
|
||||
line = res.stdout.readline().decode('ascii')
|
||||
version = line.split()[2]
|
||||
if int(version) < 20170122:
|
||||
parser_lib.print_yel("Need CPUID version >= 20170122")
|
||||
sys.exit(1)
|
||||
|
||||
if not native_check():
|
||||
parser_lib.print_red("Please run this tools in a native OS environment!")
|
||||
sys.exit(1)
|
||||
|
||||
if os.path.exists(OUTPUT):
|
||||
shutil.rmtree(OUTPUT)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
check_permission()
|
||||
|
||||
check_env()
|
||||
|
||||
# arguments to parse
|
||||
PARSER = argparse.ArgumentParser(usage='%(prog)s <board_name> [--out board_info_file]')
|
||||
PARSER.add_argument('board_name', help=": the name of the board that runs the ACRN hypervisor")
|
||||
PARSER.add_argument('--out', help=": the name of board info file.")
|
||||
ARGS = PARSER.parse_args()
|
||||
|
||||
if not ARGS.out:
|
||||
os.makedirs(OUTPUT)
|
||||
BOARD_INFO = OUTPUT + ARGS.board_name + ".xml"
|
||||
else:
|
||||
BOARD_INFO = ARGS.out
|
||||
|
||||
with open(BOARD_INFO, 'w+') as f:
|
||||
print('<acrn-config board="{}">'.format(ARGS.board_name), file=f)
|
||||
|
||||
# Get bios and base board info and store to board info
|
||||
dmi.generate_info(BOARD_INFO)
|
||||
|
||||
# Get pci devicse table and store pci info to board info
|
||||
pci_dev.generate_info(BOARD_INFO)
|
||||
|
||||
# Generate board info
|
||||
acpi.generate_info(BOARD_INFO)
|
||||
|
||||
# Generate clos info
|
||||
clos.generate_info(BOARD_INFO)
|
||||
|
||||
# Generate misc info
|
||||
misc.generate_info(BOARD_INFO)
|
||||
|
||||
# Generate pseudo RAM info
|
||||
rtct.generate_info(BOARD_INFO)
|
||||
|
||||
with open(BOARD_INFO, 'a+') as f:
|
||||
print("</acrn-config>", file=f)
|
||||
|
||||
print("{} has been generated successfully!".format(BOARD_INFO))
|
100
misc/config_tools/board_inspector/legacy/clos.py
Normal file
100
misc/config_tools/board_inspector/legacy/clos.py
Normal file
@@ -0,0 +1,100 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import parser_lib
|
||||
|
||||
RDT_TYPE = {
|
||||
"L2":4,
|
||||
"L3":2,
|
||||
"MBA":8
|
||||
}
|
||||
|
||||
|
||||
def dump_cpuid_reg(cmd, reg):
|
||||
"""execute the cmd of cpuid, and return the register value by reg
|
||||
:param cmd: command what can be executed in shell
|
||||
:param reg: register name
|
||||
"""
|
||||
res = parser_lib.cmd_execute(cmd)
|
||||
if reg == "eax":
|
||||
idx = 2
|
||||
if reg == "ebx":
|
||||
idx = 3
|
||||
if reg == "edx":
|
||||
idx = 5
|
||||
|
||||
while True:
|
||||
line = parser_lib.decode_stdout(res)
|
||||
|
||||
if not line:
|
||||
break
|
||||
|
||||
if len(line.split()) <= 2:
|
||||
continue
|
||||
|
||||
reg_value = line.split()[idx].split('=')[1]
|
||||
|
||||
if reg == "eax":
|
||||
res_info = int(reg_value, 16) + 1
|
||||
break
|
||||
elif reg == "ebx":
|
||||
res_info = []
|
||||
if int(reg_value, 16) & RDT_TYPE['L2'] != 0:
|
||||
res_info.append("L2")
|
||||
if int(reg_value, 16) & RDT_TYPE['L3'] != 0:
|
||||
res_info.append("L3")
|
||||
if int(reg_value, 16) & RDT_TYPE['MBA'] != 0:
|
||||
res_info.append("MBA")
|
||||
break
|
||||
elif reg == "edx":
|
||||
res_info = int(reg_value, 16) + 1
|
||||
break
|
||||
|
||||
return res_info
|
||||
|
||||
|
||||
def get_clos_info():
|
||||
"""Get max clos, mask supported and clos cache type"""
|
||||
rdt_res = []
|
||||
rdt_clos_max = []
|
||||
rdt_mask_max = []
|
||||
cmd = "cpuid -1 -r -l 0x10"
|
||||
rdt_res = dump_cpuid_reg(cmd, "ebx")
|
||||
|
||||
if len(rdt_res) == 0:
|
||||
parser_lib.print_yel("Resource Allocation is not supported!")
|
||||
else:
|
||||
for i in range(len(rdt_res)):
|
||||
if rdt_res[i] == "L2":
|
||||
cmd = "cpuid -1 -r -l 0x10 --subleaf 2"
|
||||
rdt_clos_max.append(dump_cpuid_reg(cmd, "edx"))
|
||||
l2_info = dump_cpuid_reg(cmd, "eax")
|
||||
rdt_mask_max.append(hex((1 << l2_info) - 1))
|
||||
if rdt_res[i] == "L3":
|
||||
cmd = "cpuid -1 -r -l 0x10 --subleaf 1"
|
||||
rdt_clos_max.append(dump_cpuid_reg(cmd, "edx"))
|
||||
l3_info = dump_cpuid_reg(cmd, "eax")
|
||||
rdt_mask_max.append(hex((1 << l3_info) - 1))
|
||||
if rdt_res[i] == "MBA":
|
||||
cmd = "cpuid -1 -r -l 0x10 --subleaf 3"
|
||||
rdt_clos_max.append(dump_cpuid_reg(cmd, "edx"))
|
||||
rdt_mask_max.append(hex(dump_cpuid_reg(cmd, "eax")))
|
||||
|
||||
return (rdt_res, rdt_clos_max, rdt_mask_max)
|
||||
|
||||
|
||||
def generate_info(board_info):
|
||||
"""Generate clos information
|
||||
:param board_info: this is the file which stores the hardware board information
|
||||
"""
|
||||
(rdt_res, rdt_res_clos_max, rdt_res_mask_max) = get_clos_info()
|
||||
|
||||
with open(board_info, 'a+') as config:
|
||||
print("\t<CLOS_INFO>", file=config)
|
||||
if ((len(rdt_res) != 0) and (len(rdt_res_clos_max) != 0)):
|
||||
print("\trdt resources supported:", ', '.join(rdt_res), file=config)
|
||||
print("\trdt resource clos max:",str(rdt_res_clos_max).strip('[]'), file=config)
|
||||
print("\trdt resource mask max:",str(rdt_res_mask_max).strip('[]'), file=config)
|
||||
print("\t</CLOS_INFO>\n", file=config)
|
400
misc/config_tools/board_inspector/legacy/dmar.py
Normal file
400
misc/config_tools/board_inspector/legacy/dmar.py
Normal file
@@ -0,0 +1,400 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import sys
|
||||
import ctypes
|
||||
import parser_lib
|
||||
|
||||
ACPI_DMAR_TYPE = {
|
||||
'ACPI_DMAR_TYPE_HARDWARE_UNIT':0,
|
||||
'ACPI_DMAR_TYPE_RESERVED_MEMORY':1,
|
||||
'ACPI_DMAR_TYPE_ROOT_ATS':2,
|
||||
'ACPI_DMAR_TYPE_HARDWARE_AFFINITY':3,
|
||||
'ACPI_DMAR_TYPE_NAMESPACE':4,
|
||||
'ACPI_DMAR_TYPE_RESERVED':5,
|
||||
}
|
||||
|
||||
ACPI_DEV_SCOPE_TYPE = {
|
||||
'ACPI_DMAR_SCOPE_TYPE_NOT_USED':0,
|
||||
'ACPI_DMAR_SCOPE_TYPE_ENDPOINT':1,
|
||||
'ACPI_DMAR_SCOPE_TYPE_BRIDGE':2,
|
||||
'ACPI_DMAR_SCOPE_TYPE_IOAPIC':3,
|
||||
'ACPI_DMAR_SCOPE_TYPE_HPET':4,
|
||||
'ACPI_DMAR_SCOPE_TYPE_NAMESPACE':5,
|
||||
'ACPI_DMAR_SCOPE_TYPE_RESERVED':6,
|
||||
}
|
||||
|
||||
class DmarHeader(ctypes.Structure):
|
||||
"""DMAR Header"""
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('signature', ctypes.c_char*4),
|
||||
('length', ctypes.c_uint32),
|
||||
('revision', ctypes.c_ubyte),
|
||||
('checksum', ctypes.c_ubyte),
|
||||
('oem_id', ctypes.c_char*6),
|
||||
('oem_table_id', ctypes.c_char*8),
|
||||
('oem_revision', ctypes.c_uint32),
|
||||
('asl_compiler_id', ctypes.c_char*4),
|
||||
('asl_compiler_revision', ctypes.c_uint32),
|
||||
('host_addr_width', ctypes.c_ubyte),
|
||||
('flags', ctypes.c_ubyte),
|
||||
('reserved', ctypes.c_ubyte*10),
|
||||
]
|
||||
|
||||
def style_check_1(self):
|
||||
"""Style check if have public method"""
|
||||
self._pack_ = 0
|
||||
|
||||
def style_check_2(self):
|
||||
"""Style check if have public method"""
|
||||
self._pack_ = 0
|
||||
|
||||
|
||||
class DmarDevScope(ctypes.Structure):
|
||||
"""DMAR Device Scope"""
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('entry_type', ctypes.c_uint8),
|
||||
('scope_length', ctypes.c_uint8),
|
||||
('reserved', ctypes.c_uint16),
|
||||
('enumeration_id', ctypes.c_uint8),
|
||||
('bus', ctypes.c_uint8),
|
||||
]
|
||||
|
||||
def style_check_1(self):
|
||||
"""Style check if have public method"""
|
||||
self._pack_ = 0
|
||||
|
||||
def style_check_2(self):
|
||||
"""Style check if have public method"""
|
||||
self._pack_ = 0
|
||||
|
||||
|
||||
class DmarHwUnit(ctypes.Structure):
|
||||
"""DMAR Hardware Unit"""
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('type', ctypes.c_uint16),
|
||||
('length', ctypes.c_uint16),
|
||||
('flags', ctypes.c_uint8),
|
||||
('reserved', ctypes.c_uint8),
|
||||
('segment', ctypes.c_uint16),
|
||||
('address', ctypes.c_uint64),
|
||||
]
|
||||
|
||||
def style_check_1(self):
|
||||
"""Style check if have public method"""
|
||||
self._pack_ = 0
|
||||
|
||||
def style_check_2(self):
|
||||
"""Style check if have public method"""
|
||||
self._pack_ = 0
|
||||
|
||||
|
||||
class DevScopePath(ctypes.Structure):
|
||||
"""DEVICE Scope Path"""
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
("device", ctypes.c_uint8),
|
||||
("function", ctypes.c_uint8),
|
||||
]
|
||||
|
||||
def style_check_1(self):
|
||||
"""Style check if have public method"""
|
||||
self._pack_ = 0
|
||||
|
||||
def style_check_2(self):
|
||||
"""Style check if have public method"""
|
||||
self._pack_ = 0
|
||||
|
||||
|
||||
class DmarHwList:
|
||||
"""DMAR HW List"""
|
||||
def __init__(self):
|
||||
self.hw_segment_list = []
|
||||
self.hw_flags_list = []
|
||||
self.hw_address_list = []
|
||||
self.hw_ignore = {}
|
||||
|
||||
def style_check_1(self):
|
||||
"""Style check if have public method"""
|
||||
self.hw_ignore = {}
|
||||
|
||||
def style_check_2(self):
|
||||
"""Style check if have public method"""
|
||||
self.hw_ignore = {}
|
||||
|
||||
|
||||
class DmarDevList:
|
||||
"""DMAR DEV List"""
|
||||
def __init__(self):
|
||||
self.dev_scope_cnt_list = []
|
||||
self.dev_bus_list = []
|
||||
self.dev_path_list = []
|
||||
self.dev_scope_id_list = []
|
||||
self.dev_scope_type_list = []
|
||||
|
||||
def style_check_1(self):
|
||||
"""Style check if have public method"""
|
||||
self.dev_bus_list = []
|
||||
|
||||
def style_check_2(self):
|
||||
"""Style check if have public method"""
|
||||
self.dev_bus_list = []
|
||||
|
||||
|
||||
class DmarTbl:
|
||||
"""DMAR TBL"""
|
||||
def __init__(self):
|
||||
self.drhd_offset = 0
|
||||
self.dmar_drhd = 0
|
||||
self.dmar_dev_scope = 0
|
||||
self.dev_scope_offset = 0
|
||||
self.dev_scope_cnt = 0
|
||||
self.path_offset = 0
|
||||
|
||||
def style_check_1(self):
|
||||
"""Style check if have public method"""
|
||||
self.path_offset = 0
|
||||
|
||||
def style_check_2(self):
|
||||
"""Style check if have public method"""
|
||||
self.path_offset = 0
|
||||
|
||||
|
||||
# TODO: Get board information is independent part of acrn-config tools, it does not get the GPU_SBDF default
|
||||
# config from the other part of tools, so hard code the GPU_SBDF to gernerate DRHDx_IGNORE macro
|
||||
CONFIG_GPU_SBDF = 0x10
|
||||
|
||||
PCI_BRIDGE_HEADER = 1
|
||||
|
||||
class PathDevFun:
|
||||
"""Path Device Function meta data"""
|
||||
def __init__(self):
|
||||
self.path = 0
|
||||
self.device = 0
|
||||
self.function = 0
|
||||
|
||||
def style_check_1(self):
|
||||
"""Style check if have public method"""
|
||||
self.path = 0
|
||||
|
||||
def style_check_2(self):
|
||||
"""Style check if have public method"""
|
||||
self.path = 0
|
||||
|
||||
|
||||
def get_secondary_bus(dmar_tbl, tmp_dev, tmp_fun):
|
||||
|
||||
cmd = "lspci -xxx"
|
||||
secondary_bus_str = ''
|
||||
found_pci_bdf = False
|
||||
pci_bridge_header_type = False
|
||||
res = parser_lib.cmd_execute(cmd)
|
||||
|
||||
while True:
|
||||
line = res.stdout.readline().decode("ascii")
|
||||
|
||||
if not line:
|
||||
break
|
||||
|
||||
if ':' not in line or len(line.strip().split(":")) < 1:
|
||||
continue
|
||||
|
||||
if not found_pci_bdf:
|
||||
if '.' not in line.strip():
|
||||
continue
|
||||
|
||||
bus = int(line.strip().split(":")[0], 16)
|
||||
dev = int(line.strip().split()[0].split(":")[1].split(".")[0], 16)
|
||||
fun = int(line.strip().split()[0].split(":")[1].split(".")[1].strip(), 16)
|
||||
if bus == dmar_tbl.dmar_dev_scope.bus and dev == tmp_dev and fun == tmp_fun:
|
||||
found_pci_bdf = True
|
||||
continue
|
||||
else:
|
||||
if "00:" == line.strip().split()[0]:
|
||||
# PCI Header type stores in 0xE
|
||||
if len(line.split()) >= 16 and int(line.strip().split()[15], 16) & 0x7 == PCI_BRIDGE_HEADER:
|
||||
pci_bridge_header_type = True
|
||||
continue
|
||||
|
||||
if not pci_bridge_header_type:
|
||||
continue
|
||||
|
||||
# found the pci device, parse the secondary bus
|
||||
if "10:" == line.strip().split()[0]:
|
||||
# Secondary PCI BUS number stores in 0x18
|
||||
secondary_bus_str = line.split()[9]
|
||||
found_pci_bdf = False
|
||||
pci_bridge_header_type = False
|
||||
break
|
||||
|
||||
# the pci device has secondary bus
|
||||
if secondary_bus_str:
|
||||
dmar_tbl.dmar_dev_scope.bus = int(secondary_bus_str, 16)
|
||||
|
||||
|
||||
def walk_pci_bus(tmp_pdf, dmar_tbl, dmar_hw_list, drhd_cnt):
|
||||
"""Walk Pci bus
|
||||
:param tmp_pdf: it is a class what contains path,device,function in dmar device scope region
|
||||
:param dmar_tbl: it is a class to describe dmar which contains Device Scope and DRHD
|
||||
:param dmar_hw_list: it is a class to describe hardware scope in DMAR table
|
||||
:param drhd_cnt: it is a counter to calculate the DRHD in DMAR table
|
||||
"""
|
||||
# initialize DRHDx_IGNORE to false
|
||||
dmar_hw_list.hw_ignore[drhd_cnt] = 'false'
|
||||
# path offset is in end of device spcope
|
||||
dmar_tbl.path_offset = dmar_tbl.dev_scope_offset + ctypes.sizeof(DmarDevScope)
|
||||
n_cnt = (dmar_tbl.dmar_dev_scope.scope_length - ctypes.sizeof(DmarDevScope)) // 2
|
||||
while n_cnt:
|
||||
scope_path = DevScopePath.from_address(dmar_tbl.path_offset)
|
||||
tmp_pdf.device = scope_path.device
|
||||
tmp_pdf.function = scope_path.function
|
||||
tmp_pdf.path = (((tmp_pdf.device & 0x1F) << 3) | ((tmp_pdf.function & 0x7)))
|
||||
|
||||
# walk the secondary pci bus
|
||||
get_secondary_bus(dmar_tbl, tmp_pdf.device, tmp_pdf.function)
|
||||
|
||||
if ((dmar_tbl.dmar_drhd.segment << 16) | (
|
||||
dmar_tbl.dmar_dev_scope.bus << 8) | tmp_pdf.path) == CONFIG_GPU_SBDF:
|
||||
dmar_hw_list.hw_ignore[drhd_cnt] = 'true'
|
||||
|
||||
dmar_tbl.path_offset += ctypes.sizeof(DevScopePath)
|
||||
n_cnt -= 1
|
||||
|
||||
|
||||
def walk_dev_scope(dmar_tbl, dmar_dev_list, dmar_hw_list, drhd_cnt):
|
||||
"""Walk device scope
|
||||
:param dmar_tbl: it is a class to describe dmar which contains Device Scope and DRHD
|
||||
:param dmar_dev_list: it is a class to describe device scope in DMAR table
|
||||
:param dmar_hw_list: it is a class to describe DRHD in DMAR table
|
||||
:param drhd_cnt: it is a counter to calculate the DRHD in DMAR table
|
||||
"""
|
||||
dmar_tbl.dev_scope_offset = dmar_tbl.drhd_offset + ctypes.sizeof(DmarHwUnit)
|
||||
scope_end = dmar_tbl.dev_scope_offset + dmar_tbl.dmar_drhd.length
|
||||
dmar_tbl.dev_scope_cnt = 0
|
||||
|
||||
while dmar_tbl.dev_scope_offset < scope_end:
|
||||
dmar_tbl.dmar_dev_scope = DmarDevScope.from_address(dmar_tbl.dev_scope_offset)
|
||||
if dmar_tbl.dmar_dev_scope.scope_length <= 0:
|
||||
break
|
||||
if dmar_tbl.dmar_dev_scope.entry_type != \
|
||||
ACPI_DEV_SCOPE_TYPE['ACPI_DMAR_SCOPE_TYPE_NOT_USED'] and \
|
||||
dmar_tbl.dmar_dev_scope.entry_type < \
|
||||
ACPI_DEV_SCOPE_TYPE['ACPI_DMAR_SCOPE_TYPE_RESERVED']:
|
||||
dmar_tbl.dev_scope_cnt += 1
|
||||
|
||||
# get type and id from device scope
|
||||
dmar_dev_list.dev_scope_type_list.append(dmar_tbl.dmar_dev_scope.entry_type)
|
||||
dmar_dev_list.dev_scope_id_list.append(dmar_tbl.dmar_dev_scope.enumeration_id)
|
||||
|
||||
# walk the pci bus with path deep, and find the {Device,Function}
|
||||
tmp_pdf = PathDevFun()
|
||||
walk_pci_bus(tmp_pdf, dmar_tbl, dmar_hw_list, drhd_cnt)
|
||||
dmar_dev_list.dev_bus_list.append(dmar_tbl.dmar_dev_scope.bus)
|
||||
dmar_dev_list.dev_path_list.append(tmp_pdf.path)
|
||||
|
||||
dmar_tbl.dev_scope_offset += dmar_tbl.dmar_dev_scope.scope_length
|
||||
|
||||
|
||||
def walk_dmar_table(dmar_tbl, dmar_hw_list, dmar_dev_list, sysnode):
|
||||
"""Walk dmar table and get information
|
||||
:param dmar_tbl: it is a class to describe dmar which contains Device Scope and DRHD
|
||||
:param dmar_hw_list: it is a class to describe hardware scope in DMAR table
|
||||
:param dmar_dev_list: it is a class to describe device scope in DMAR table
|
||||
:param sysnode: the system device node of acpi table, such as: /sys/firmware/acpi/tables/DMAR
|
||||
"""
|
||||
data = open(sysnode, 'rb').read()
|
||||
buf = ctypes.create_string_buffer(data, len(data))
|
||||
addr = ctypes.addressof(buf)
|
||||
|
||||
# contain the dmar tbl_header
|
||||
dmar_tbl_header = DmarHeader.from_address(addr)
|
||||
|
||||
# cytpes.c_int16.from_address(addr) reade int16 from ad1
|
||||
# in end of tbl header is remapping structure(DRHD/sub tbl)
|
||||
dmar_tbl.drhd_offset = addr + ctypes.sizeof(DmarHeader)
|
||||
drhd_cnt = 0
|
||||
while True:
|
||||
# get one DRHD type in sub table
|
||||
dmar_tbl.dmar_drhd = DmarHwUnit.from_address(dmar_tbl.drhd_offset)
|
||||
dmar_type = dmar_tbl.dmar_drhd.type
|
||||
dmar_len = dmar_tbl.dmar_drhd.length
|
||||
|
||||
if dmar_tbl.drhd_offset - addr >= dmar_tbl_header.length:
|
||||
break
|
||||
|
||||
if dmar_type != ACPI_DMAR_TYPE['ACPI_DMAR_TYPE_HARDWARE_UNIT']:
|
||||
dmar_tbl.drhd_offset += dmar_len
|
||||
continue
|
||||
|
||||
dmar_hw_list.hw_segment_list.append(dmar_tbl.dmar_drhd.segment)
|
||||
dmar_hw_list.hw_flags_list.append(dmar_tbl.dmar_drhd.flags)
|
||||
dmar_hw_list.hw_address_list.append(dmar_tbl.dmar_drhd.address)
|
||||
|
||||
# in end of DRHD/sub tbl header is dev scope, then enumerate the device scope
|
||||
walk_dev_scope(dmar_tbl, dmar_dev_list, dmar_hw_list, drhd_cnt)
|
||||
dmar_dev_list.dev_scope_cnt_list.append(dmar_tbl.dev_scope_cnt)
|
||||
|
||||
drhd_cnt += 1
|
||||
dmar_tbl.drhd_offset += dmar_len
|
||||
|
||||
return (dmar_tbl, dmar_hw_list, dmar_dev_list, drhd_cnt)
|
||||
|
||||
|
||||
def write_dmar_data(sysnode, config):
|
||||
"""Write the DMAR data to board info
|
||||
:param sysnode: the system device node of acpi table, such as: /sys/firmware/acpi/tables/DMAR
|
||||
:param config: file pointer that opened for writing board information
|
||||
"""
|
||||
|
||||
dmar_hw_list = DmarHwList()
|
||||
dmar_dev_list = DmarDevList()
|
||||
dmar_tbl = DmarTbl()
|
||||
|
||||
(dmar_tbl, dmar_hw_list, dmar_dev_list, drhd_cnt) = walk_dmar_table(
|
||||
dmar_tbl, dmar_hw_list, dmar_dev_list, sysnode)
|
||||
|
||||
print("\t#define DRHD_COUNT {0}U".format(drhd_cnt), file=config)
|
||||
print("", file=config)
|
||||
prev_dev_scope_num = 0
|
||||
for drhd_hw_i in range(drhd_cnt):
|
||||
dev_scope_num = dmar_dev_list.dev_scope_cnt_list[drhd_hw_i]
|
||||
print("\t#define DRHD"+str(drhd_hw_i)+"_DEV_CNT {0}U".format(
|
||||
hex(dmar_dev_list.dev_scope_cnt_list[drhd_hw_i])), file=config)
|
||||
print("\t#define DRHD"+str(drhd_hw_i)+"_SEGMENT {0}U".format(
|
||||
hex(dmar_hw_list.hw_segment_list[drhd_hw_i])), file=config)
|
||||
print("\t#define DRHD"+str(drhd_hw_i)+"_FLAGS {0}U".format(
|
||||
hex(dmar_hw_list.hw_flags_list[drhd_hw_i])), file=config)
|
||||
print("\t#define DRHD"+str(drhd_hw_i)+"_REG_BASE 0x{:0>2X}UL".format(
|
||||
dmar_hw_list.hw_address_list[drhd_hw_i]), file=config)
|
||||
if drhd_hw_i in dmar_hw_list.hw_ignore.keys():
|
||||
print("\t#define DRHD"+str(drhd_hw_i)+"_IGNORE {0}".format(
|
||||
dmar_hw_list.hw_ignore[drhd_hw_i]), file=config)
|
||||
for dev_scope_i in range(dev_scope_num):
|
||||
print("\t#define DRHD"+str(drhd_hw_i)+"_DEVSCOPE"+str(dev_scope_i),
|
||||
file=config, end="")
|
||||
print("_TYPE {0}U".format(
|
||||
hex(dmar_dev_list.dev_scope_type_list[prev_dev_scope_num + dev_scope_i])),
|
||||
file=config)
|
||||
print("\t#define DRHD"+str(drhd_hw_i)+"_DEVSCOPE"+str(dev_scope_i),
|
||||
file=config, end="")
|
||||
print("_ID {0}U".format(
|
||||
hex(dmar_dev_list.dev_scope_id_list[prev_dev_scope_num + dev_scope_i])),
|
||||
file=config)
|
||||
print("\t#define DRHD"+str(drhd_hw_i)+"_DEVSCOPE"+str(dev_scope_i),
|
||||
file=config, end="")
|
||||
print("_BUS {0}U".format(hex(
|
||||
dmar_dev_list.dev_bus_list[prev_dev_scope_num + dev_scope_i])),
|
||||
file=config)
|
||||
print("\t#define DRHD"+str(drhd_hw_i)+"_DEVSCOPE"+str(dev_scope_i),
|
||||
file=config, end="")
|
||||
print("_PATH {0}U".format(hex(
|
||||
dmar_dev_list.dev_path_list[prev_dev_scope_num + dev_scope_i])),
|
||||
file=config)
|
||||
|
||||
print("", file=config)
|
||||
prev_dev_scope_num += dev_scope_num
|
22
misc/config_tools/board_inspector/legacy/dmi.py
Normal file
22
misc/config_tools/board_inspector/legacy/dmi.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import parser_lib
|
||||
|
||||
CMDS = {
|
||||
'BIOS_INFO':"dmidecode -t 0",
|
||||
'BASE_BOARD_INFO':"dmidecode -t 2",
|
||||
}
|
||||
|
||||
|
||||
def generate_info(board_info):
|
||||
"""Get bios and base board information
|
||||
:param board_info: this is the file which stores the hardware board information
|
||||
"""
|
||||
with open(board_info, 'a+') as config:
|
||||
parser_lib.dump_execute(CMDS['BIOS_INFO'], 'BIOS_INFO', config)
|
||||
print("", file=config)
|
||||
parser_lib.dump_execute(CMDS['BASE_BOARD_INFO'], 'BASE_BOARD_INFO', config)
|
||||
print("", file=config)
|
260
misc/config_tools/board_inspector/legacy/misc.py
Normal file
260
misc/config_tools/board_inspector/legacy/misc.py
Normal file
@@ -0,0 +1,260 @@
|
||||
# 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<TTYS_INFO>", file=config)
|
||||
ttys_list = detected_ttys()
|
||||
|
||||
dump_ttys_info(ttys_list, config)
|
||||
|
||||
print("\t</TTYS_INFO>", 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<AVAILABLE_IRQ_INFO>", 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</AVAILABLE_IRQ_INFO>", 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<IOMEM_INFO>", 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</IOMEM_INFO>", 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<TOTAL_MEM_INFO>", 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</TOTAL_MEM_INFO>", file=config)
|
||||
print("", file=config)
|
||||
|
||||
|
||||
def dump_cpu_core_info(config):
|
||||
|
||||
print("\t<CPU_PROCESSOR_INFO>", 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</CPU_PROCESSOR_INFO>", 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<MAX_MSIX_TABLE_NUM>", file=config)
|
||||
print("\t{}".format(max_msix_table_num), file=config)
|
||||
print("\t</MAX_MSIX_TABLE_NUM>", 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)
|
168
misc/config_tools/board_inspector/legacy/parser_lib.py
Normal file
168
misc/config_tools/board_inspector/legacy/parser_lib.py
Normal file
@@ -0,0 +1,168 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
BIOS_INFO_KEY = ['BIOS Information', 'Vendor:', 'Version:', 'Release Date:', 'BIOS Revision:']
|
||||
|
||||
BASE_BOARD_KEY = ['Base Board Information', 'Manufacturer:', 'Product Name:', 'Version:']
|
||||
|
||||
|
||||
def check_dmi():
|
||||
"""Check if this tool run on native os"""
|
||||
return os.path.exists("/sys/firmware/dmi")
|
||||
|
||||
|
||||
def print_yel(msg, warn=False, end=True):
|
||||
"""Output the message with the color of yellow
|
||||
:param msg: the stings which will be output to STDOUT
|
||||
:param warn: the condition if needs to be output the color of yellow with 'Warning'
|
||||
:param end: The flag of it needs to combine with the next line for stdout
|
||||
"""
|
||||
if warn:
|
||||
if end:
|
||||
print("\033[1;33mWarning\033[0m:"+msg)
|
||||
else:
|
||||
print("\033[1;33mWarning\033[0m:"+msg, end="")
|
||||
else:
|
||||
if end:
|
||||
print("\033[1;33m{}\033[0m".format(msg))
|
||||
else:
|
||||
print("\033[1;33m{}\033[0m".format(msg), end="")
|
||||
|
||||
|
||||
def print_red(msg, err=False):
|
||||
"""Output the messag with the color of red
|
||||
:param msg: the stings which will be output to STDOUT
|
||||
:param err: the condition if needs to be output the color of red with 'Error'
|
||||
"""
|
||||
if err:
|
||||
print("\033[1;31mError\033[0m:"+msg)
|
||||
else:
|
||||
print("\033[1;31m{0}\033[0m".format(msg))
|
||||
|
||||
|
||||
def decode_stdout(resource):
|
||||
"""Decode the information and return one line of the decoded information
|
||||
:param resource: it contains information produced by subprocess.Popen method
|
||||
"""
|
||||
line = resource.stdout.readline().decode('ascii')
|
||||
return line
|
||||
|
||||
|
||||
def handle_hw_info(line, hw_info):
|
||||
"""Handle the hardware information
|
||||
:param line: one line of information which had decoded to 'ASCII'
|
||||
:param hw_info: the list which contains key strings what can describe bios/board
|
||||
"""
|
||||
for board_line in hw_info:
|
||||
if board_line == " ".join(line.split()[0:1]) or \
|
||||
board_line == " ".join(line.split()[0:2]) or \
|
||||
board_line == " ".join(line.split()[0:3]):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def handle_pci_dev(line):
|
||||
"""Handle if it match PCI device information pattern
|
||||
:param line: one line of information which had decoded to 'ASCII'
|
||||
"""
|
||||
if "Region" in line and "Memory at" in line:
|
||||
return True
|
||||
|
||||
if line != '\n':
|
||||
if line.split()[0][2:3] == ':' and line.split()[0][5:6] == '.':
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def cmd_execute(cmd):
|
||||
"""Excute cmd and retrun raw information
|
||||
:param cmd: command what can be executed in shell
|
||||
"""
|
||||
res = subprocess.Popen(cmd, shell=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def handle_block_dev(line):
|
||||
"""Handle if it match root device information pattern
|
||||
:param line: one line of information which had decoded to 'ASCII'
|
||||
"""
|
||||
block_format = ''
|
||||
for root_type in line.split():
|
||||
if "ext4" in root_type or "ext3" in root_type:
|
||||
block_type = ''
|
||||
block_dev = line.split()[0]
|
||||
for type_str in line.split():
|
||||
if "TYPE=" in type_str:
|
||||
block_type = type_str
|
||||
|
||||
block_format = block_dev + " " + block_type
|
||||
return block_format
|
||||
|
||||
return block_format
|
||||
|
||||
|
||||
def dump_execute(cmd, desc, config):
|
||||
"""Execute cmd and get information
|
||||
:param cmd: command what can be executed in shell
|
||||
:param desc: the string indicated what class information store to board.xml
|
||||
:param config: file pointer that opened for writing board information
|
||||
"""
|
||||
val_dmi = check_dmi()
|
||||
print("\t<{0}>".format(desc), file=config)
|
||||
|
||||
if not val_dmi and "dmidecode" in cmd:
|
||||
print("\t\t</{0}>".format(desc), file=config)
|
||||
return
|
||||
|
||||
res = cmd_execute(cmd)
|
||||
while True:
|
||||
line = res.stdout.readline().decode('ascii')
|
||||
|
||||
if not line:
|
||||
break
|
||||
|
||||
if desc == "PCI_DEVICE":
|
||||
if "prog-if" in line:
|
||||
line = line.rsplit('(', 1)[0] + '\n'
|
||||
ret = handle_pci_dev(line)
|
||||
if not ret:
|
||||
continue
|
||||
|
||||
if desc == "BIOS_INFO":
|
||||
ret = handle_hw_info(line, BIOS_INFO_KEY)
|
||||
if not ret:
|
||||
continue
|
||||
|
||||
if desc == "BASE_BOARD_INFO":
|
||||
ret = handle_hw_info(line, BASE_BOARD_KEY)
|
||||
if not ret:
|
||||
continue
|
||||
|
||||
if desc == "BLOCK_DEVICE_INFO":
|
||||
line = handle_block_dev(line)
|
||||
if not line:
|
||||
continue
|
||||
|
||||
print("\t{}".format(line.strip()), file=config)
|
||||
|
||||
print("\t</{0}>".format(desc), file=config)
|
||||
|
||||
|
||||
def get_output_lines(cmd):
|
||||
res_lines = []
|
||||
res = cmd_execute(cmd)
|
||||
while True:
|
||||
line = res.stdout.readline().decode('ascii')
|
||||
if not line:
|
||||
break
|
||||
res_lines.append(line.strip())
|
||||
|
||||
return res_lines
|
22
misc/config_tools/board_inspector/legacy/pci_dev.py
Normal file
22
misc/config_tools/board_inspector/legacy/pci_dev.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import parser_lib
|
||||
|
||||
CMDS = {
|
||||
'PCI_DEVICE':"lspci -vv",
|
||||
'PCI_VID_PID':"lspci -n",
|
||||
}
|
||||
|
||||
|
||||
def generate_info(board_info):
|
||||
"""Get the pci info
|
||||
:param board_info: this is the file which stores the hardware board information
|
||||
"""
|
||||
with open(board_info, 'a+') as config:
|
||||
parser_lib.dump_execute(CMDS['PCI_DEVICE'], 'PCI_DEVICE', config)
|
||||
print("", file=config)
|
||||
parser_lib.dump_execute(CMDS['PCI_VID_PID'], 'PCI_VID_PID', config)
|
||||
print("", file=config)
|
43
misc/config_tools/board_inspector/legacy/rtct.py
Normal file
43
misc/config_tools/board_inspector/legacy/rtct.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# Copyright (C) 2021 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import os
|
||||
from acpiparser import parse_rtct
|
||||
import acpiparser.rtct
|
||||
import parser_lib
|
||||
|
||||
def dump_psram(config):
|
||||
print("\t<RTCT>", file=config)
|
||||
|
||||
rtct = None
|
||||
if os.path.exists("/sys/firmware/acpi/tables/PTCT"):
|
||||
rtct = parse_rtct(path="/sys/firmware/acpi/tables/PTCT")
|
||||
elif os.path.exists("/sys/firmware/acpi/tables/RTCT"):
|
||||
rtct = parse_rtct(path="/sys/firmware/acpi/tables/RTCT")
|
||||
|
||||
if rtct:
|
||||
for entry in rtct.entries:
|
||||
if entry.type == acpiparser.rtct.ACPI_RTCT_TYPE_SoftwareSRAM:
|
||||
print("\t\t<SoftwareSRAM>", file=config)
|
||||
print("\t\t\t<cache_level>{}</cache_level>".format(entry.cache_level), file=config)
|
||||
print("\t\t\t<base>{}</base>".format(hex(entry.base)), file=config)
|
||||
print("\t\t\t<ways>{}</ways>".format(hex(entry.ways)), file=config)
|
||||
print("\t\t\t<size>{}</size>".format(hex(entry.size)), file=config)
|
||||
for apic_id in entry.apic_id_tbl:
|
||||
print("\t\t\t<apic_id>{}</apic_id>".format(hex(apic_id)), file=config)
|
||||
print("\t\t</SoftwareSRAM>", file=config)
|
||||
else:
|
||||
parser_lib.print_yel("No PTCT or RTCT found. The platform may not support pseudo RAM.")
|
||||
|
||||
print("\t</RTCT>", file=config)
|
||||
print("", file=config)
|
||||
|
||||
|
||||
def generate_info(board_info):
|
||||
"""Get system pseudo RAM information
|
||||
:param board_info: this is the file which stores the hardware board information
|
||||
"""
|
||||
with open(board_info, 'a+') as config:
|
||||
dump_psram(config)
|
Reference in New Issue
Block a user