diff --git a/misc/acrn-config/board_config/acpi_platform_h.py b/misc/acrn-config/board_config/acpi_platform_h.py index 351b22c06..6a087acd4 100644 --- a/misc/acrn-config/board_config/acpi_platform_h.py +++ b/misc/acrn-config/board_config/acpi_platform_h.py @@ -14,24 +14,26 @@ PLATFORM_HEADER = r"""/* DO NOT MODIFY THIS FILE UNLESS YOU KNOW WHAT YOU ARE DO PLATFORM_END_HEADER = "\n#endif /* PLATFORM_ACPI_INFO_H */" + class OverridAccessSize(): - """The Pm access size which are needed to redefine""" + """ The Pm access size which are needed to redefine """ def __init__(self): self.pm1a_cnt_ac_sz = True self.pm1b_cnt_ac_sz = True self.pm1b_evt_ac_sz = True def style_check_1(self): - """Style check if have public method""" + """ Style check if have public method """ self.pm1a_cnt_ac_sz = True def style_check_2(self): - """Style check if have public method""" + """ Style check if have public method """ self.pm1a_cnt_ac_sz = True def multi_parser(line, s_line, pm_ac_sz, config): - """Multi parser the line + """ + Multi parse the line :param line: it is a line read from default_acpi_info.h :param s_line: it is a line read from board information file :param pm_ac_sz: it is a class for access size which would be override @@ -76,7 +78,8 @@ def multi_parser(line, s_line, pm_ac_sz, config): def multi_info_parser(config, default_platform, msg_s, msg_e): - """Parser multi information + """ + Parse multi information :param config: it is a file pointer to write acpi information :param default_platform: it is the default_acpi_info.h in acrn-hypervisor :param msg_s: it is a pattern of key stings what start to match from board information @@ -109,7 +112,8 @@ def multi_info_parser(config, default_platform, msg_s, msg_e): def write_direct_info_parser(config, msg_s, msg_e): - """Direct to write + """ + Direct to write :param config: it is a file pointer to write acpi information :param msg_s: it is a pattern of key stings what start to match from board information :param msg_e: it is a pattern of key stings what end to match from board information @@ -123,7 +127,8 @@ def write_direct_info_parser(config, msg_s, msg_e): def drhd_info_parser(config): - """Parser DRHD information + """ + Parse DRHD information :param config: it is a file pointer to write acpi information """ prev_num = 0 @@ -149,7 +154,8 @@ def drhd_info_parser(config): def platform_info_parser(config, default_platform): - """Parser ACPI information + """ + Parse ACPI information :param config: it is a file pointer to write acpi information :param default_platform: it is the default_acpi_info.h in acrn-hypervisor """ @@ -165,7 +171,8 @@ def platform_info_parser(config, default_platform): def generate_file(config, default_platform): - """write board_name_acpi_info.h + """ + write board_name_acpi_info.h :param config: it is a file pointer to write acpi information :param default_platform: it is the default_acpi_info.h in acrn-hypervisor """ @@ -174,7 +181,7 @@ def generate_file(config, default_platform): print("{}".format(PLATFORM_HEADER), file=config) board_cfg_lib.handle_bios_info(config) - # parser for the platform info + # parse for the platform info platform_info_parser(config, default_platform) print("{}".format(PLATFORM_END_HEADER), file=config) diff --git a/misc/acrn-config/board_config/board_c.py b/misc/acrn-config/board_config/board_c.py index 07c66a55c..8346b0814 100644 --- a/misc/acrn-config/board_config/board_c.py +++ b/misc/acrn-config/board_config/board_c.py @@ -7,32 +7,17 @@ import sys import board_cfg_lib -def clos_info_parser(): - """Parser CLOS information""" - - cache_support = False - clos_max = 0 - - cat_lines = board_cfg_lib.get_info( - board_cfg_lib.BOARD_INFO_FILE, "", "") - - for line in cat_lines: - if line.split(':')[0] == "clos supported by cache": - cache_support = line.split(':')[1].strip() - elif line.split(':')[0] == "clos max": - clos_max = int(line.split(':')[1]) - - return (cache_support, clos_max) - - def gen_cat(config): - """Get CAT information + """ + Get CAT information :param config: it is a file pointer of board information for writing to """ - (cache_support, clos_max) = clos_info_parser() + err_dic = {} + (cache_support, clos_max) = board_cfg_lib.clos_info_parser(board_cfg_lib.BOARD_INFO_FILE) print("\n#include ", file=config) print("#include ", file=config) + print("#include ", file=config) if cache_support == "False" or clos_max == 0: print("\nstruct platform_clos_info platform_clos_array[0];", file=config) @@ -50,9 +35,8 @@ def gen_cat(config): elif cache_support == "L3": print("\t\t.msr_index = {0}U,".format(hex(0x00000C90+i_cnt)), file=config) else: - board_cfg_lib.print_red("The input of {} was corrupted!".format( - board_cfg_lib.BOARD_INFO_FILE)) - sys.exit(1) + err_dic['board config: generate board.c failed'] = "The input of {} was corrupted!".format(board_cfg_lib.BOARD_INFO_FILE) + return err_dic print("\t},", file=config) print("};\n", file=config) @@ -61,10 +45,12 @@ def gen_cat(config): file=config) print("", file=config) + return err_dic def gen_px_cx(config): - """Get Px/Cx and store them to board.c + """ + Get Px/Cx and store them to board.c :param config: it is a file pointer of board information for writing to """ cpu_brand_lines = board_cfg_lib.get_info( @@ -97,16 +83,22 @@ def gen_px_cx(config): def generate_file(config): - """Start to generate board.c + """ + Start to generate board.c :param config: it is a file pointer of board information for writing to """ + err_dic = {} print("{0}".format(board_cfg_lib.HEADER_LICENSE), file=config) # insert bios info into board.c board_cfg_lib.handle_bios_info(config) # start to parser to get CAT info - gen_cat(config) + err_dic = gen_cat(config) + if err_dic: + return err_dic # start to parser PX/CX info gen_px_cx(config) + + return err_dic diff --git a/misc/acrn-config/board_config/board_cfg_gen.py b/misc/acrn-config/board_config/board_cfg_gen.py index 0eeb70091..5595a306f 100755 --- a/misc/acrn-config/board_config/board_cfg_gen.py +++ b/misc/acrn-config/board_config/board_cfg_gen.py @@ -6,79 +6,53 @@ import os import sys -import shutil -import subprocess +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library')) import board_cfg_lib import board_c import pci_devices_h import acpi_platform_h +import misc_cfg_h +import ve820_c +import new_board_kconfig -ACRN_PATH = "../../../" +ACRN_PATH = board_cfg_lib.SOURCE_ROOT_DIR ACRN_CONFIG = ACRN_PATH + "hypervisor/arch/x86/configs/" BOARD_NAMES = ['apl-mrb', 'apl-nuc', 'apl-up2', 'dnv-cb2', 'nuc6cayh', 'nuc7i7dnb', 'kbl-nuc-i7', 'icl-rvp'] ACRN_DEFAULT_PLATFORM = ACRN_PATH + "hypervisor/include/arch/x86/default_acpi_info.h" -GEN_FILE = ["vm_configurations.h", "vm_configurations.c", "pt_dev.c", "pci_devices.h", - "board.c", "_acpi_info.h"] - -PY_CACHES = ["__pycache__", "board_config/__pycache__"] -BIN_LIST = ['git'] +GEN_FILE = ["pci_devices.h", "board.c", "_acpi_info.h", "misc_cfg.h", "ve820.c", ".config"] -def prepare(): - """Prepare to check the environment""" - 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: - board_cfg_lib.print_yel("'{}' not found, please install it!".format(excute)) - sys.exit(1) - - if excute == "git": - res = subprocess.Popen("git tag -l", shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, close_fds=True) - line = res.stdout.readline().decode("ascii") - - if "acrn" not in line: - board_cfg_lib.print_red("Run this tool in acrn-hypervisor mainline source code!") - sys.exit(1) - - for py_cache in PY_CACHES: - if os.path.exists(py_cache): - shutil.rmtree(py_cache) - - -def gen_patch(srcs_list, board_name): - """Generate patch and apply to local source code - :param srcs_list: it is a list what contains source files - :param board_name: board name +def main(args): """ - changes = ' '.join(srcs_list) - git_add = "git add {}".format(changes) - subprocess.call(git_add, shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, close_fds=True) - - # commit this changes - git_commit = 'git commit -sm "acrn-config: config board patch for {}"'.format(board_name) - subprocess.call(git_commit, shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, close_fds=True) - - -def main(board_info_file): - """This is main function to start generate source code related with board - :param board_info_file: it is a file what contains board information for script to read from + This is main function to start generate source code related with board + :param args: it is a command line args for the script """ - board = '' + err_dic = {} config_srcs = [] config_dirs = [] + (err_dic, board_info_file, scenario_info_file) = board_cfg_lib.get_param(args) + if err_dic: + return err_dic + + board_cfg_lib.BOARD_INFO_FILE = board_info_file + board_cfg_lib.SCENARIO_INFO_FILE = scenario_info_file + board_cfg_lib.get_vm_count(scenario_info_file) + # get board name - board = board_cfg_lib.get_board_name(board_info_file) + (err_dic, board) = board_cfg_lib.get_board_name() + if err_dic: + return err_dic + board_cfg_lib.BOARD_NAME = board + + # check if this is the scenario config which matched board info + (err_dic, status) = board_cfg_lib.is_config_file_match() + if not status: + err_dic['board config: Not match'] = "The board xml and scenario xml should be matched" + return err_dic config_dirs.append(ACRN_CONFIG + board) if board not in BOARD_NAMES: @@ -86,17 +60,25 @@ def main(board_info_file): if not os.path.exists(config_dir): os.makedirs(config_dir) - config_pci = config_dirs[0] + '/' + GEN_FILE[3] - config_board = config_dirs[0] + '/' + GEN_FILE[4] - config_platform = config_dirs[0] + '/' + board + GEN_FILE[5] + config_pci = config_dirs[0] + '/' + GEN_FILE[0] + config_board = config_dirs[0] + '/' + GEN_FILE[1] + config_platform = config_dirs[0] + '/' + board + GEN_FILE[2] + config_misc_cfg = config_dirs[0] + '/' + GEN_FILE[3] + config_ve820 = config_dirs[0] + '/' + GEN_FILE[4] + config_board_kconfig = ACRN_CONFIG + board + GEN_FILE[5] config_srcs.append(config_pci) config_srcs.append(config_board) config_srcs.append(config_platform) + config_srcs.append(config_misc_cfg) + config_srcs.append(config_ve820) + config_srcs.append(config_board_kconfig) # generate board.c with open(config_board, 'w+') as config: - board_c.generate_file(config) + err_dic = board_c.generate_file(config) + if err_dic: + return err_dic # generate pci_devices.h with open(config_pci, 'w+') as config: @@ -106,36 +88,61 @@ def main(board_info_file): with open(config_platform, 'w+') as config: acpi_platform_h.generate_file(config, ACRN_DEFAULT_PLATFORM) - # move changes to patch, and apply to the source code - gen_patch(config_srcs, board) + # generate acpi_platform.h + with open(config_ve820, 'w+') as config: + err_dic = ve820_c.generate_file(config) + if err_dic: + return err_dic + # generate acpi_platform.h + with open(config_misc_cfg, 'w+') as config: + err_dic = misc_cfg_h.generate_file(config) + if err_dic: + return err_dic + + # generate new board_name.config if board not in BOARD_NAMES: + with open(config_board_kconfig, 'w+') as config: + err_dic = new_board_kconfig.generate_file(config) + if err_dic: + return err_dic + + # move changes to patch, and apply to the source code + err_dic = board_cfg_lib.gen_patch(config_srcs, board) + + if board not in BOARD_NAMES and not err_dic: print("Config patch for NEW board {} is committed successfully!".format(board)) - else: + elif not err_dic: print("Config patch for {} is committed successfully!".format(board)) + else: + print("Config patch for {} is failed".format(board)) + + return err_dic -def usage(): - """This is usage for how to use this tool""" - print("usage= [h] --board '") - print('board_info_file, : file name of the board info"') - sys.exit(1) +def ui_entry_api(board_info,scenario_info): + + arg_list = ['board_cfg_gen.py', '--board', board_info, '--scenario', scenario_info] + + err_dic = board_cfg_lib.prepare() + if err_dic: + return err_dic + + err_dic = main(arg_list) + + return err_dic if __name__ == '__main__': - prepare() - ARGS = sys.argv[1:] - - if ARGS[0] != '--board': - usage() + err_dic = board_cfg_lib.prepare() + if err_dic: + for err_k, err_v in err_dic.items(): + board_cfg_lib.print_red("{}: {}".format(err_k, err_v), err=True) sys.exit(1) - BOARD_INFO_FILE = ARGS[1] - if not os.path.exists(BOARD_INFO_FILE): - board_cfg_lib.print_red("{} is not exist!".format(BOARD_INFO_FILE)) - sys.exit(1) - - board_cfg_lib.BOARD_INFO_FILE = BOARD_INFO_FILE - - main(BOARD_INFO_FILE) + ARGS = sys.argv + err_dic = main(ARGS) + if err_dic: + for err_k, err_v in err_dic.items(): + board_cfg_lib.print_red("{}: {}".format(err_k, err_v), err=True) diff --git a/misc/acrn-config/board_config/board_cfg_lib.py b/misc/acrn-config/board_config/board_cfg_lib.py deleted file mode 100644 index 9c884ae13..000000000 --- a/misc/acrn-config/board_config/board_cfg_lib.py +++ /dev/null @@ -1,138 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause -# - -import sys - -HV_LICENSE_FILE = '../library/hypervisor_license' -BOARD_INFO_FILE = "board_info.txt" - -BIOS_INFO = ['BIOS Information', 'Vendor:', 'Version:', 'Release Date:', 'BIOS Revision:'] - -BASE_BOARD = ['Base Board Information', 'Manufacturer:', 'Product Name:', 'Version:'] - - -def open_license(): - """Get the license""" - with open(HV_LICENSE_FILE, 'r') as f_licence: - license_s = f_licence.read().strip() - return license_s - - -HEADER_LICENSE = open_license() + "\n" - -#LOGICAL_PT_PROFILE = {} -#LOGICAL_PCI_DEV = {} -#LOGICAL_PCI_LINE = {} - - -def print_yel(msg, warn=False): - """Print the message with 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' - """ - if warn: - print("\033[1;33mWarning\033[0m:"+msg) - else: - print("\033[1;33m{0}\033[0m".format(msg)) - - -def print_red(msg, err=False): - """Print the message with 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 get_board_name(board_info): - """Get board name from board.xml at fist line - :param board_info: it is a file what contains board information for script to read from - """ - with open(board_info, 'rt') as f_board: - line = f_board.readline() - if not "board=" in line: - print_red("acrn-config board info xml was corrupted!") - sys.exit(1) - - board = line.split('"')[1].strip('"') - return board - - -def get_info(board_info, msg_s, msg_e): - """Get information which specify by argument - :param board_info: it is a file what contains board information for script to read from - :param msg_s: it is a pattern of key stings what start to match from board information - :param msg_e: it is a pattern of key stings what end to match from board information - """ - info_start = False - info_end = False - info_lines = [] - num = len(msg_s.split()) - - try: - with open(board_info, 'rt') as f_board: - while True: - - line = f_board.readline() - if not line: - break - - if " ".join(line.split()[0:num]) == msg_s: - info_start = True - info_end = False - continue - - if " ".join(line.split()[0:num]) == msg_e: - info_start = False - info_end = True - continue - - if info_start and not info_end: - info_lines.append(line) - continue - - if not info_start and info_end: - return info_lines - - except IOError as err: - print_red(str(err), err=True) - sys.exit(1) - - -def handle_bios_info(config): - """Handle bios information - :param config: it is a file pointer of bios information for writing to - """ - bios_lines = get_info(BOARD_INFO_FILE, "", "") - board_lines = get_info(BOARD_INFO_FILE, "", "") - print("/*", file=config) - - if not bios_lines or not board_lines: - print(" * DMI info is not found", file=config) - else: - i_cnt = 0 - bios_board = BIOS_INFO + BASE_BOARD - - # remove the same value and keep origin sort - bios_board_info = list(set(bios_board)) - bios_board_info.sort(key=bios_board.index) - - bios_board_lines = bios_lines + board_lines - bios_info_len = len(bios_lines) - for line in bios_board_lines: - if i_cnt == bios_info_len: - print(" *", file=config) - - i_cnt += 1 - - for misc_info in bios_board_info: - if misc_info == " ".join(line.split()[0:1]) or misc_info == \ - " ".join(line.split()[0:2]) or misc_info == " ".join(line.split()[0:3]): - print(" * {0}".format(line.strip()), file=config) - - print(" */", file=config) diff --git a/misc/acrn-config/board_config/misc_cfg_h.py b/misc/acrn-config/board_config/misc_cfg_h.py new file mode 100644 index 000000000..d00f7d848 --- /dev/null +++ b/misc/acrn-config/board_config/misc_cfg_h.py @@ -0,0 +1,151 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import board_cfg_lib + +MISC_CFG_HEADER = """ +#ifndef MISC_CFG_H +#define MISC_CFG_H +""" + +MISC_CFG_END = """#endif /* MISC_CFG_H */""" + +class Vuart: + + t_vm_id = [] + t_vuart_id = [] + v_type = [] + v_base = [] + v_irq = [] + + def style_check_1(self): + self.v_irq = [] + + def style_check_2(self): + self.v_irq = [] + + +def sos_bootarg_diff(sos_cmdlines, config): + + if sos_cmdlines: + sos_len = len(sos_cmdlines) + i = 0 + for sos_cmdline in sos_cmdlines: + if not sos_cmdline: + continue + + i += 1 + if i == 1: + if sos_len == 1: + print('#define SOS_BOOTARGS_DIFF\t{}'.format(sos_cmdline), file=config) + else: + print('#define SOS_BOOTARGS_DIFF\t"{} " \\'.format(sos_cmdline), file=config) + else: + if i < sos_len: + print('\t\t\t\t"{} "\t\\'.format(sos_cmdline), file=config) + else: + print('\t\t\t\t"{}"'.format(sos_cmdline), file=config) + + +def parse_boot_info(): + + err_dic = {} + vm_types = [] + + (err_dic, scenario_name) = board_cfg_lib.get_scenario_name() + if err_dic: + return (err_dic, sos_cmdlines, sos_rootfs, vuart0_dic, vuart1_dic, vm_types) + + if scenario_name != "logical_partition": + sos_cmdlines = board_cfg_lib.get_sub_leaf_tag(board_cfg_lib.SCENARIO_INFO_FILE, "board_private", "bootargs") + sos_rootfs = board_cfg_lib.get_sub_leaf_tag(board_cfg_lib.SCENARIO_INFO_FILE, "board_private", "rootfs") + (err_dic, vuart0_dic, vuart1_dic) = board_cfg_lib.get_board_private_vuart("board_private", "console") + else: + sos_cmdlines = board_cfg_lib.get_sub_leaf_tag(board_cfg_lib.SCENARIO_INFO_FILE, "os_config", "bootargs") + + sos_rootfs = board_cfg_lib.get_sub_leaf_tag(board_cfg_lib.SCENARIO_INFO_FILE, "os_config", "rootfs") + (err_dic, vuart0_dic, vuart1_dic) = board_cfg_lib.get_board_private_vuart("os_config", "console") + + if err_dic: + return (err_dic, sos_cmdlines, sos_rootfs, vuart0_dic, vuart1_dic, vm_types) + + for i in range(board_cfg_lib.VM_COUNT): + vm_type = board_cfg_lib.get_order_type_by_vmid(i) + vm_types.append(vm_type) + + return (err_dic, sos_cmdlines, sos_rootfs, vuart0_dic, vuart1_dic, vm_types) + + +def generate_file(config): + """ + Start to generate board.c + :param config: it is a file pointer of board information for writing to + """ + board_cfg_lib.get_valid_irq(board_cfg_lib.BOARD_INFO_FILE) + + # get the vuart0/vuart1 which user chosed from scenario.xml of board_private section + (err_dic, ttys_n) = board_cfg_lib.parser_vuart_console() + if err_dic: + return err_dic + + # parse sos_bootargs/rootfs/console + (err_dic, sos_cmdlines, sos_rootfs, vuart0_dic, vuart1_dic, vm_types) = parse_boot_info() + if err_dic: + return err_dic + + # parse to get poart/base of vuart0/vuart1 + vuart0_port_base = board_cfg_lib.TTY_CONSOLE[list(vuart0_dic.keys())[0]] + vuart0_irq = vuart0_dic[list(vuart0_dic.keys())[0]] + vuart1_port_base = board_cfg_lib.TTY_CONSOLE[list(vuart1_dic.keys())[0]] + vuart1_irq = vuart1_dic[list(vuart1_dic.keys())[0]] + + # parse the setting ttys vuatx dic: {vmid:base/irq} + vuart0_setting = Vuart() + vuart1_setting = Vuart() + vuart0_setting = board_cfg_lib.get_vuart_info_id(board_cfg_lib.SCENARIO_INFO_FILE, 0) + vuart1_setting = board_cfg_lib.get_vuart_info_id(board_cfg_lib.SCENARIO_INFO_FILE, 1) + + # sos command lines information + sos_cmdlines = [i for i in sos_cmdlines[0].split() if i != ''] + + # get native rootfs list from board_info.xml + (root_devs, root_dev_num) = board_cfg_lib.get_rootfs(board_cfg_lib.BOARD_INFO_FILE) + + # start to generate misc_cfg.h + print("{0}".format(board_cfg_lib.HEADER_LICENSE), file=config) + print("{}".format(MISC_CFG_HEADER), file=config) + + # define rootfs with macro + for i in range(root_dev_num): + print('#define ROOTFS_{}\t\t"root={} "'.format(i, root_devs[i]), file=config) + + # sos rootfs and console + print("", file=config) + if "SOS_VM" in vm_types: + print('#define SOS_ROOTFS\t\t"root={} "'.format(sos_rootfs[0]), file=config) + print('#define SOS_CONSOLE\t\t"console={} "'.format(ttys_n), file=config) + + # sos com base/irq + i_type = 0 + for vm_type in vm_types: + if vm_type == "SOS_VM": + break + i_type += 1 + + if "SOS_VM" in vm_types: + print("#define SOS_COM1_BASE\t\t{}U".format(vuart0_port_base), file=config) + print("#define SOS_COM1_IRQ\t\t{}U".format(vuart0_irq), file=config) + if vuart1_setting[i_type]['base'] != "INVALID_COM_BASE": + print("#define SOS_COM2_BASE\t\t{}U".format(vuart1_port_base), file=config) + print("#define SOS_COM2_IRQ\t\t{}U".format(vuart1_irq), file=config) + + + # sos boot command line + print("", file=config) + if "SOS_VM" in vm_types: + sos_bootarg_diff(sos_cmdlines, config) + print("{}".format(MISC_CFG_END), file=config) + + return err_dic diff --git a/misc/acrn-config/board_config/new_board_kconfig.py b/misc/acrn-config/board_config/new_board_kconfig.py new file mode 100644 index 000000000..eb8984792 --- /dev/null +++ b/misc/acrn-config/board_config/new_board_kconfig.py @@ -0,0 +1,92 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import sys +import board_cfg_lib + + +DESC = """ +# New board kconfig generated by vm config tool +# Modified by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) +""" + +VM_NUM_MAP_TOTAL_HV_RAM_SIZE = { + # 120M + 2:'0x7800000', + # 150M + 3:'0x9600000', + # 180M + 4:'0xB400000', + # 210M + 5:'0xD200000', + # 240M + 6:'0xF000000', + # 270M + 7:'0x10E00000', +} + + +def get_addr_for_hv(ram_range, hpa_size): + """ + This is get hv address from System RAM as host physical size + :param ram_range: System RAM mapping + :param hpa_size: fixed host physical size + :return: start host physical address + """ + ret_start_addr = 0 + tmp_order_key = 0 + + tmp_order_key = sorted(ram_range) + for start_addr in tmp_order_key: + mem_range = ram_range[start_addr] + if mem_range > int(hpa_size, 16): + ret_start_addr = start_addr + break + + return hex(ret_start_addr) + + +def get_ram_range(): + """ Get System RAM range mapping """ + # read system ram from board_info.xml + ram_range = {} + + sys_mem_lines = board_cfg_lib.get_info( + board_cfg_lib.BOARD_INFO_FILE, "", "") + for line in sys_mem_lines: + start_addr = int(line.split('-')[0], 16) + end_addr = int(line.split('-')[1].split(':')[0], 16) + mem_range = end_addr - start_addr + ram_range[start_addr] = mem_range + + return ram_range + + +def generate_file(config): + """Start to generate board.c + :param config: it is a file pointer of board information for writing to + """ + err_dic = {} + # this dictonary mapped with 'address start':'mem range' + ram_range = {} + + if board_cfg_lib.VM_COUNT in list(VM_NUM_MAP_TOTAL_HV_RAM_SIZE.keys()): + hv_ram_size = VM_NUM_MAP_TOTAL_HV_RAM_SIZE[board_cfg_lib.VM_COUNT] + else: + board_cfg_lib.print_red("VM num should not greater than 8", err=True) + err_dic["baord config: total vm number error"] = "VM num should not greater than 8" + return err_dic + + ram_range = get_ram_range() + hv_start_addr = get_addr_for_hv(ram_range, hv_ram_size) + + print('CONFIG_BOARD="{}"'.format(board_cfg_lib.BOARD_NAME), file=config) + print("{}".format(DESC), file=config) + + print("CONFIG_HV_RAM_START={}".format(hv_start_addr), file=config) + + print("CONFIG_HV_RAM_SIZE={}".format(hv_ram_size), file=config) + + return err_dic diff --git a/misc/acrn-config/board_config/pci_devices_h.py b/misc/acrn-config/board_config/pci_devices_h.py index 4bd0999e2..5c3bf5a03 100644 --- a/misc/acrn-config/board_config/pci_devices_h.py +++ b/misc/acrn-config/board_config/pci_devices_h.py @@ -15,7 +15,7 @@ PCI_END_HEADER = r""" def parser_pci(): - """Parser PCI lines""" + """ Parse PCI lines """ cur_bdf = 0 prev_bdf = 0 tmp_bar_dic = {} @@ -42,9 +42,7 @@ def parser_pci(): pci_dev_dic[pci_bdf] = pci_sub_name cur_bdf = pci_bdf - #board_cfg_lib.LOGICAL_PCI_LINE[pci_bdf] = line - # skipt the first init value if not prev_bdf: prev_bdf = cur_bdf @@ -57,18 +55,29 @@ def parser_pci(): # output all the pci device list to pci_device.h sub_name_count = collections.Counter(pci_dev_dic.values()) - # share the pci profile with pt_dev - #board_cfg_lib.LOGICAL_PT_PROFILE = sub_name_count - #board_cfg_lib.LOGICAL_PCI_DEV = pci_dev_dic - if tmp_bar_dic: pci_bar_dic[cur_bdf] = tmp_bar_dic return (pci_dev_dic, pci_bar_dic, sub_name_count) + +def undline_name(name): + """ + This convert name which has contain '-' to '_' + :param name: name which contain '-' + :return: + """ + name_list = name + if '-' in name: + name_list = "_".join(name.split('-')) + + return name_list + + def write_pbdf(i_cnt, bdf, subname, config): - """Parser and generate pbdf + """ + Parser and generate pbdf :param i_cnt: the number of pci devices have the same PCI subname :param bdf: it is a string what contains BDF :param subname: it is a string belong to PIC subname @@ -78,7 +87,10 @@ def write_pbdf(i_cnt, bdf, subname, config): if i_cnt == 0 and subname.upper() == "HOST BRIDGE": tmp_sub_name = "_".join(subname.split()).upper() else: - tmp_sub_name = "_".join(subname.split()).upper() + "_" + str(i_cnt) + if '-' in subname: + tmp_sub_name = undline_name(subname) + else: + tmp_sub_name = "_".join(subname.split()).upper() + "_" + str(i_cnt) bus = int(bdf.split(':')[0], 16) dev = int(bdf.split(':')[1].split('.')[0], 16) @@ -89,7 +101,8 @@ def write_pbdf(i_cnt, bdf, subname, config): def write_vbar(bdf, pci_bar_dic, config): - """Parser and generate vbar + """ + Parser and generate vbar :param bdf: it is a string what contains BDF :param pci_bar_dic: it is a dictionary of pci vbar for those BDF :param config: it is a file pointer of pci information for writing to @@ -119,7 +132,8 @@ def write_vbar(bdf, pci_bar_dic, config): def generate_file(config): - """Get PCI device and generate pci_devices.h + """ + Get PCI device and generate pci_devices.h :param config: it is a file pointer of pci information for writing to """ diff --git a/misc/acrn-config/board_config/ve820_c.py b/misc/acrn-config/board_config/ve820_c.py new file mode 100644 index 000000000..f95bdef09 --- /dev/null +++ b/misc/acrn-config/board_config/ve820_c.py @@ -0,0 +1,147 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import sys +import board_cfg_lib + + +TOTAL_MEM_SIZE = 4 * 1024 * 1024 * 1024 +LOW_MEM_TO_PCI_HOLE = 0x20000000 + + +def undline_board_name(board_name): + """ + This convert board name which has contain '-' to '_' + :param board_name: + :return: + """ + name_list = board_name + if '-' in board_name: + name_list = "_".join(board_name.split('-')) + + return name_list + + +def ve820_per_launch(config, hpa_size): + """ + Start to generate board.c + :param config: it is a file pointer of board information for writing to + """ + (err_dic, board_name) = board_cfg_lib.get_board_name() + if err_dic: + return err_dic + + board_name = undline_board_name(board_name) + + low_mem_to_pci_hole_len = '0xA0000000' + low_mem_to_pci_hole = '0x20000000' + pci_hole_addr = '0xe0000000' + pci_hole_len = '0x20000000' + start_low_hpa = 0x100000 + hpa_len = int(hpa_size, 16) - 1 * 1024 * 1024 + + # pre_launch memroy: mem_size is the ve820 length + print("#include ", file=config) + print("#include ", file=config) + print("", file=config) + print("#define VE820_ENTRIES_{}\t{}U".format(board_name.upper(), 5), file=config) + print("static const struct e820_entry ve820_entry[{}] = {{".format( + "VE820_ENTRIES_{}".format(board_name.upper())), file=config) + print("\t{\t/* usable RAM under 1MB */", file=config) + print("\t\t.baseaddr = 0x0UL,", file=config) + print("\t\t.length = 0xF0000UL,\t\t/* 960KB */", file=config) + print("\t\t.type = E820_TYPE_RAM", file=config) + print("\t},", file=config) + print("", file=config) + print("\t{\t/* mptable */", file=config) + print("\t\t.baseaddr = 0xF0000UL,\t\t/* 960KB */", file=config) + print("\t\t.length = 0x10000UL,\t\t/* 16KB */", file=config) + print("\t\t.type = E820_TYPE_RESERVED", file=config) + print("\t},", file=config) + print("", file=config) + + print("\t{\t/* lowmem */", file=config) + + print("\t\t.baseaddr = {}UL,\t\t/* 1MB */".format( + hex(start_low_hpa)), file=config) + print("\t\t.length = {}UL,\t/* {}MB */".format( + hex(hpa_len), hpa_len / 1024 / 1024), file=config) + + print("\t\t.type = E820_TYPE_RAM", file=config) + print("\t},", file=config) + print("", file=config) + + print("\t{\t/* between lowmem and PCI hole */", file=config) + print("\t\t.baseaddr = {}UL,\t/* {}MB */".format( + low_mem_to_pci_hole, int(low_mem_to_pci_hole, 16) / 1024 / 1024), file=config) + print("\t\t.length = {}UL,\t/* {}MB */".format( + low_mem_to_pci_hole_len, int(low_mem_to_pci_hole_len, 16) / 1024 / 1024), file=config) + print("\t\t.type = E820_TYPE_RESERVED", file=config) + print("\t},", file=config) + print("", file=config) + print("\t{{\t/* between PCI hole and {}GB */".format( + TOTAL_MEM_SIZE / 1024 / 1024 / 1024), file=config) + print("\t\t.baseaddr = {}UL,\t/* {}GB */".format( + hex(int(pci_hole_addr, 16)), int(pci_hole_addr, 16) / 1024 / 1024 / 1024), file=config) + print("\t\t.length = {}UL,\t/* {}MB */".format( + hex(int(pci_hole_len, 16)), int(pci_hole_len, 16) / 1024 / 1024), file=config) + print("\t\t.type = E820_TYPE_RESERVED", file=config) + print("\t},", file=config) + print("};", file=config) + print("", file=config) + print("/**", file=config) + print(" * @pre vm != NULL", file=config) + print("*/", file=config) + print("void create_prelaunched_vm_e820(struct acrn_vm *vm)", file=config) + print("{", file=config) + print("\tvm->e820_entry_num = VE820_ENTRIES_{};".format(board_name.upper()), file=config) + print("\tvm->e820_entries = ve820_entry;", file=config) + print("}", file=config) + + return err_dic + + +def non_ve820_pre_launch(config): + """ + This is none pre launch vm setting + :param config: + :return: + """ + print("#include ", file=config) + print("#include ", file=config) + print("/**", file=config) + print(" * @pre vm != NULL", file=config) + print("*/", file=config) + print("void create_prelaunched_vm_e820(struct acrn_vm *vm)", file=config) + print("{", file=config) + print("\tvm->e820_entry_num = 0;", file=config) + print("\tvm->e820_entries = NULL;", file=config) + print("}", file=config) + + +def generate_file(config): + """Start to generate board.c + :param config: it is a file pointer of board information for writing to + """ + err_dic = {} + print("{0}".format(board_cfg_lib.HEADER_LICENSE), file=config) + pre_vm_cnt = board_cfg_lib.get_pre_launch_cnt(board_cfg_lib.SCENARIO_INFO_FILE) + + # read mem size from scenario.xml + hpa_size_list = board_cfg_lib.get_sub_leaf_tag( + board_cfg_lib.SCENARIO_INFO_FILE, "memory", "size") + ret = board_cfg_lib.is_hpa_size(hpa_size_list) + if not ret: + board_cfg_lib.print_red("Unknow type of host physical address size", err=True) + err_dic['board config: generate ve820.c failed'] = "Unknow type of host physical address size" + return err_dic + + hpa_size = hpa_size_list[0] + if pre_vm_cnt != 0 and ('0x' in hpa_size or '0X' in hpa_size): + err_dic = ve820_per_launch(config, hpa_size) + else: + non_ve820_pre_launch(config) + + return err_dic diff --git a/misc/acrn-config/library/board_cfg_lib.py b/misc/acrn-config/library/board_cfg_lib.py new file mode 100644 index 000000000..6c52a3b26 --- /dev/null +++ b/misc/acrn-config/library/board_cfg_lib.py @@ -0,0 +1,422 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import sys +import common + +SOURCE_ROOT_DIR = common.SOURCE_PATH +BOARD_NAME = '' +BOARD_INFO_FILE = "board_info.txt" +SCENARIO_INFO_FILE = "" + +BIOS_INFO = ['BIOS Information', 'Vendor:', 'Version:', 'Release Date:', 'BIOS Revision:'] + +BASE_BOARD = ['Base Board Information', 'Manufacturer:', 'Product Name:', 'Version:'] + +TTY_CONSOLE = { + 'ttyS0':'0x3F8', + 'ttyS1':'0x2F8', + 'ttyS2':'0x3E8', + 'ttyS3':'0x2E8', +} + +NATIVE_CONSOLE_DIC = {} +VALID_LEGACY_IRQ = [] +VM_COUNT = 0 + +ERR_LIST = {} + +HEADER_LICENSE = common.open_license() + "\n" + + +def prepare(): + """ check environment """ + return common.check_env() + + +def print_yel(msg, warn=False): + """ + Print the message with 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' + """ + common.print_if_yel(msg, warn) + + +def print_red(msg, err=False): + """ + Print the message with 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' + """ + common.print_if_red(msg, err) + + +def get_board_name(): + """ + Get board name from board.xml at fist line + :param board_info: it is a file what contains board information for script to read from + """ + (err_dic, board) = common.get_xml_attrib(BOARD_INFO_FILE, "board") + return (err_dic, board) + + +def get_scenario_name(): + """ + Get scenario name from scenario.xml at fist line + :param scenario_info: it is a file what contains board information for script to read from + """ + (err_dic, board) = common.get_xml_attrib(SCENARIO_INFO_FILE, "scenario") + return (err_dic, board) + + +def is_config_file_match(): + + (err_dic, scenario_for_board) = common.get_xml_attrib(SCENARIO_INFO_FILE, "board") + (err_dic, board_name) = common.get_xml_attrib(BOARD_INFO_FILE, "board") + + if scenario_for_board == board_name: + return (err_dic, True) + else: + return (err_dic, False) + + +def usage(file_name): + """ This is usage for how to use this tool """ + common.usage(file_name) + + +def get_param(args): + """ + Get the script parameters from command line + :param args: this the command line of string for the script without script name + """ + return common.get_param(args) + + +def get_info(board_info, msg_s, msg_e): + """ + Get information which specify by argument + :param board_info: it is a file what contains information for script to read from + :param msg_s: it is a pattern of key stings what start to match from board information + :param msg_e: it is a pattern of key stings what end to match from board information + """ + info_lines = common.get_board_info(board_info, msg_s, msg_e) + return info_lines + + +def handle_bios_info(config): + """ + Handle bios information + :param config: it is a file pointer of bios information for writing to + """ + bios_lines = get_info(BOARD_INFO_FILE, "", "") + board_lines = get_info(BOARD_INFO_FILE, "", "") + print("/*", file=config) + + if not bios_lines or not board_lines: + print(" * DMI info is not found", file=config) + else: + i_cnt = 0 + bios_board = BIOS_INFO + BASE_BOARD + + # remove the same value and keep origin sort + bios_board_info = list(set(bios_board)) + bios_board_info.sort(key=bios_board.index) + + bios_board_lines = bios_lines + board_lines + bios_info_len = len(bios_lines) + for line in bios_board_lines: + if i_cnt == bios_info_len: + print(" *", file=config) + + i_cnt += 1 + + for misc_info in bios_board_info: + if misc_info == " ".join(line.split()[0:1]) or misc_info == \ + " ".join(line.split()[0:2]) or misc_info == " ".join(line.split()[0:3]): + print(" * {0}".format(line.strip()), file=config) + + print(" */", file=config) + + +def get_tree_tag(config_file, tag_str): + """ + This is get tag value by tag_str from config file + :param config_file: it is a file what contains information for script to read from + :param tag_str: it is key of pattern to config file item + :return: value of tag_str item + """ + return common.get_tree_tag_val(config_file, tag_str) + + +def get_sub_tree_tag(config_file, tag_str): + """ + This is get tag value by tag_str from config file + :param config_file: it is a file what contains information for script to read from + :param tag_str: it is key of pattern to config file item + :return: value of tag_str item + """ + return common.get_branch_tag_val(config_file, tag_str) + + +def get_sub_leaf_tag(config_file, branch_tag, tag_str): + """ + This is get tag value by tag_str from config file + :param config_file: it is a file what contains information for script to read from + :param branch_tag: it is key of patter to config file branch tag item + :param tag_str: it is key of pattern to config file leaf tag item + :return: value of tag_str item + """ + return common.get_leaf_tag_val(config_file, branch_tag, tag_str) + + +def gen_patch(srcs_list, board_name): + """ + Generate patch and apply to local source code + :param srcs_list: it is a list what contains source files + :param board_name: board name + """ + err_dic = common.add_to_patch(srcs_list, board_name) + return err_dic + + +def is_hpa_size(hpa_size_list): + """ + This is identify if the host physical size list is correct format + :param hpa_size_list: host physical size list + :return: True if good format + """ + ret = common.check_hpa_size(hpa_size_list) + return ret + + +def get_rootfs(config_file): + """ + This will get rootfs partition from board information + :param config_file: it is a file which contain board information + :return: rootfs partition list + """ + rootfs_lines = get_info(config_file, "", "") + root_dev_list = [] + + for rootfs_line in rootfs_lines: + root_dev = rootfs_line.strip().split(':')[0] + root_dev_list.append(root_dev) + + return (root_dev_list, len(root_dev_list)) + + +def clos_info_parser(board_info): + """ Parse CLOS information """ + return common.get_max_clos(board_info) + + +def get_pre_launch_cnt(config_file): + """ + This is get pre launched vm count + :param config_file: it is a file what contains vm information for script to read from + :return: number of per launched vm + """ + pre_launch_cnt = common.vm_pre_launch_cnt(config_file) + return pre_launch_cnt + + +def get_vm_count(config_file): + """ + This is get vm count + :param config_file: it is a file what contains vm information for script to read from + :return: number of vm + """ + global VM_COUNT + VM_COUNT = common.get_vm_count(config_file) + + +def get_order_type_by_vmid(idx): + """ + This is get pre launched vm count + :param idx: index of vm id + :return: idx and vm type mapping + """ + (err_dic, order_id_dic) = common.get_load_order_by_vmid(SCENARIO_INFO_FILE, VM_COUNT, idx) + if err_dic: + ERR_LIST.update(err_dic) + + return order_id_dic + + +def get_valid_irq(board_info): + """ + This is get available irq from board info file + :param board_info: it is a file what contains board information for script to read from + :return: None + """ + global VALID_LEGACY_IRQ + val_irq = [] + irq_info_lines = get_info(board_info, "", "") + for irq_string in irq_info_lines: + val_irq = [x.strip() for x in irq_string.split(',')] + + VALID_LEGACY_IRQ = val_irq + + +def alloc_irq(): + """ + This is allocated an available irq + :return: free irq + """ + irq_val = VALID_LEGACY_IRQ.pop(0) + + return irq_val + + +def get_valid_console(): + """ Get valid console with mapping {ttyS:irq} returned """ + used_console_lines = get_info(BOARD_INFO_FILE, "", "") + + vuart0_valid_console = [] + vuart1_valid_console = ['ttyS0', 'ttyS1', 'ttyS2', 'ttyS3', 'ttyS4', 'ttyS5', 'ttyS6', 'ttyS7'] + if used_console_lines: + vuart0_valid_console.clear() + for console in used_console_lines: + tty = console.split('/')[2].split()[0] + ttys_irq = console.split(':')[-1].strip() + NATIVE_CONSOLE_DIC[tty] = ttys_irq + vuart0_valid_console.append(tty) + if tty: + vuart1_valid_console.remove(tty) + + return (vuart0_valid_console, vuart1_valid_console) + + +def console_to_show(board_info): + """ + This is get available console from board info file + :param board_info: it is a file what contains board information for script to read from + :return: available console + """ + show_vuart1 = False + (vuart0_valid_console, vuart1_valid_console) = get_valid_console() + if not vuart1_valid_console: + print_yel("Console are full used, sos_console/vuart1 have to chose one:", warn=True) + vuart0_valid_console = ['ttyS0', 'ttyS1', 'ttyS2', 'ttyS3'] + vuart1_valid_console = ['ttyS0', 'ttyS1', 'ttyS2', 'ttyS3'] + show_vuart1 = True + + return (vuart0_valid_console, vuart1_valid_console, show_vuart1) + + +def parser_vuart_console(): + """ + There may be 3 types in the console item + 1. BDF:(00:18.2) seri:/dev/ttyS2 + 2. /dev/ttyS2 + 3. ttyS2 + """ + ttys_n = '' + (err_dic, scenario_name) = get_scenario_name() + + if scenario_name != "logical_partition": + ttys = get_sub_leaf_tag(SCENARIO_INFO_FILE, "board_private", "console") + else: + ttys = get_sub_leaf_tag(SCENARIO_INFO_FILE, "os_config", "console") + + if ttys and 'BDF' in ttys[0] or '/dev' in ttys[0]: + ttys_n = ttys[0].split('/')[2] + else: + # sdc/sdc2 is different from logical_partition + ttys_n = ttys[0] + + return (err_dic, ttys_n) + + +def get_board_private_vuart(branch_tag, tag_console): + """ + Get vuart_console from board setting + :param tag_console: TTYS_INFO + :return: vuart0/vuart1 console dictionary + """ + err_dic = {} + vuart0_console_dic = {} + vuart1_console_dic = {} + + (err_dic, ttys_n) = parser_vuart_console() + if err_dic: + return err_dic + + if not ttys_n or ttys_n not in list(TTY_CONSOLE.keys()): + err_dic["board config: ttyS not available"] = "console should be set in scenario.xml of board_private section" + return (err_dic, vuart0_console_dic, vuart1_console_dic) + + (vuart0_valid_console, vuart1_valid_console, show_vuart1) = console_to_show(BOARD_INFO_FILE) + + # VUART0 + if ttys_n not in list(NATIVE_CONSOLE_DIC.keys()): + vuart0_console_dic[ttys_n] = alloc_irq() + else: + if int(NATIVE_CONSOLE_DIC[ttys_n]) >= 16: + vuart0_console_dic[ttys_n] = alloc_irq() + else: + vuart0_console_dic[ttys_n] = NATIVE_CONSOLE_DIC[ttys_n] + + # VUART1 + if len(vuart1_valid_console) == 4: + ttys_n = get_sub_leaf_tag(SCENARIO_INFO_FILE, branch_tag, "vuart1_console") + vuart1_console_dic[ttys_n] = alloc_irq() + else: + vuart1_console_dic[vuart1_valid_console[0]] = alloc_irq() + + return (err_dic, vuart0_console_dic, vuart1_console_dic) + + +def get_vuart_id(tmp_vuart, leaf_tag, leaf_text): + """ + Get all vuart id member of class + :param leaf_tag: key pattern of item tag + :param tmp_vuart: a dictionary to store member:value + :param leaf_text: key pattern of item tag's value + :return: a dictionary to which stored member:value + """ + if leaf_tag == "type": + tmp_vuart['type'] = leaf_text + if leaf_tag == "base": + tmp_vuart['base'] = leaf_text + if leaf_tag == "irq": + tmp_vuart['irq'] = leaf_text + + if leaf_tag == "target_vm_id": + tmp_vuart['target_vm_id'] = leaf_text + if leaf_tag == "target_uart_id": + tmp_vuart['target_uart_id'] = leaf_text + + return tmp_vuart + + +def get_vuart_info_id(config_file, idx): + """ + Get vuart information by vuart id indexx + :param config_file: it is a file what contains information for script to read from + :param idx: vuart index in range: [0,1] + :return: dictionary which stored the vuart-id + """ + tmp_tag = [] + vm_id = 0 + root = common.get_config_root(config_file) + for item in root: + for sub in item: + tmp_vuart = {} + for leaf in sub: + if sub.tag == "vuart" and int(sub.attrib['id']) == idx: + tmp_vuart = get_vuart_id(tmp_vuart, leaf.tag, leaf.text) + + # append vuart for each vm + if tmp_vuart and sub.tag == "vuart": + #tmp_vuart[vm_id] = tmp_vuart + tmp_tag.append(tmp_vuart) + + if item.tag == "vm": + vm_id += 1 + + return tmp_tag diff --git a/misc/acrn-config/library/common.py b/misc/acrn-config/library/common.py new file mode 100644 index 000000000..c237a2021 --- /dev/null +++ b/misc/acrn-config/library/common.py @@ -0,0 +1,555 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import os +import sys +import getopt +import shutil +import subprocess +import xml.etree.ElementTree as ET + +SOURCE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../../') +HV_LICENSE_FILE = SOURCE_PATH + 'misc/acrn-config/library/hypervisor_license' + + +PY_CACHES = ["__pycache__", "../board_config/__pycache__", "../scenario_config/__pycache__"] +BIN_LIST = ['git'] +GUEST_FLAG = ["0UL", "GUEST_FLAG_SECURE_WORLD_ENABLED", "GUEST_FLAG_LAPIC_PASSTHROUGH", + "GUEST_FLAG_IO_COMPLETION_POLLING", "GUEST_FLAG_CLOS_REQUIRED", + "GUEST_FLAG_HIDE_MTRR", "GUEST_FLAG_RT", "GUEST_FLAG_HIGHEST_SEVERITY"] +# Support 512M, 1G, 2G +# pre launch less then 2G, sos vm less than 24G +START_HPA_SIZE_LIST = ['0x20000000', '0x40000000', '0x80000000', 'CONFIG_SOS_RAM_SIZE', 'VM0_MEM_SIZE'] + + +def open_license(): + """ Get the license """ + with open(HV_LICENSE_FILE, 'r') as f_licence: + license_s = f_licence.read().strip() + return license_s + + +def print_if_yel(msg, warn=False): + """ + Print the message with 'Warning' if warn is true + :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' + """ + if warn: + print("\033[1;33mWarning\033[0m: "+msg) + else: + print("\033[1;33m{0}\033[0m".format(msg)) + + +def print_if_red(msg, err=False): + """ + Print the message with 'Error' if err is true + :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 usage(file_name): + """ This is usage for how to use this tool """ + print("usage= {} [h] ".format(file_name), end="") + print("--board --scenario ") + print('board_info_file : file name of the board info') + print('scenario_info_file : file name of the scenario info') + + +def get_param(args): + """ + Get the script parameters from command line + :param args: this the command line of string for the script without script name + """ + err_dic = {} + board_info_file = False + scenario_info_file = False + + if '--board' not in args or '--scenario' not in args: + usage(args[0]) + err_dic['common error: get wrong parameter'] = "wrong usage" + return (err_dic, board_info_file, scenario_info_file) + + args_list = args[1:] + (optlist, args_list) = getopt.getopt(args_list, '', ['board=', 'scenario=']) + for arg_k, arg_v in optlist: + if arg_k == '--board': + board_info_file = arg_v + if arg_k == '--scenario': + scenario_info_file = arg_v + + if not board_info_file or not scenario_info_file: + usage(args[0]) + err_dic['common error: get wrong parameter'] = "wrong usage" + return (err_dic, board_info_file, scenario_info_file) + + if not os.path.exists(board_info_file): + err_dic['common error: get wrong parameter'] = "{} is not exist!".format(board_info_file) + return (err_dic, board_info_file, scenario_info_file) + + if not os.path.exists(scenario_info_file): + err_dic['common error: get wrong parameter'] = "{} is not exist!".format(scenario_info_file) + return (err_dic, board_info_file, scenario_info_file) + + return (err_dic, board_info_file, scenario_info_file) + + +def check_env(): + """ Prepare to check the environment """ + err_dic = {} + 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: + err_dic['commn error: check env failed'] = "'{}' not found, please install it!".format(excute) + + if excute == "git": + res = subprocess.Popen("git tag -l", shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, close_fds=True) + line = res.stdout.readline().decode("ascii") + + if "acrn" not in line: + err_dic['commn error: check env failed'] = "Run this tool in acrn-hypervisor mainline source code!" + + usr_dir = os.environ['HOME'] + if not os.path.isfile("{}/.gitconfig".format(usr_dir)): + err_dic['commn error: check env failed'] = "git not configured!" + + for py_cache in PY_CACHES: + if os.path.exists(py_cache): + shutil.rmtree(py_cache) + + return err_dic + +def check_hpa_size(hpa_size_list): + """ + This is identify if the host physical size list is correct format + :param hpa_size_list: host physical size list + :return: True if good format + """ + for hpa_size in hpa_size_list: + hpa_sz_strip_ul = hpa_size.strip('UL') + hpa_sz_strip_u = hpa_size.strip('U') + if hpa_sz_strip_u not in START_HPA_SIZE_LIST and hpa_sz_strip_ul not in START_HPA_SIZE_LIST: + if '0x' not in hpa_size and '0X' not in hpa_size: + return False + + return True + + +def get_xml_attrib(config_file, attrib): + """ + Get attribute from xml at fist line + :param config_file: it is a file what contains board information for script to read from + :param attrib: attribute of item in xml + """ + value = '' + err_dic = {} + with open(config_file, 'rt') as fp_info: + while True: + line = fp_info.readline() + if not line: + break + + if 'board=' in line or 'scenario=' in line: + + if attrib not in line: + err_dic['common error: Not match'] = "The root item is not in xml file" + return (err_dic, value) + + attrib_list = line.split() + for attrib_value in attrib_list: + if attrib in attrib_value: + value = attrib_value.split('"')[1].strip('"') + + return (err_dic, value) + + +def get_board_info(board_info, msg_s, msg_e): + """ + Get information which specify by argument + :param board_info: it is a file what contains board information for script to read from + :param msg_s: it is a pattern of key stings what start to match from board information + :param msg_e: it is a pattern of key stings what end to match from board information + """ + info_start = False + info_end = False + info_lines = [] + num = len(msg_s.split()) + + with open(board_info, 'rt') as f_board: + while True: + + line = f_board.readline() + if not line: + break + + if " ".join(line.split()[0:num]) == msg_s: + info_start = True + info_end = False + continue + + if " ".join(line.split()[0:num]) == msg_e: + info_start = False + info_end = True + continue + + if info_start and not info_end: + info_lines.append(line) + continue + + if not info_start and info_end: + return info_lines + + +def find_index_guest_flag(flag): + """ + Find the index in GUEST_FLAG by flag + :param flag: flag contained by GUEST_FLAG + :return: index of GUEST_FLAG + """ + if not flag or flag == '0': + return '0' + + if not flag.isnumeric(): + for i in range(len(GUEST_FLAG)): + if flag == GUEST_FLAG[i]: + flag_str = i + return flag_str + +def find_tmp_flag(leaf_text): + """ + Get flag and append the value + :param leaf_text: it is a value of guest flag item + :return: a list of flag or none + """ + tmp_flag = [] + tmp_flag = find_index_guest_flag(leaf_text) + #flag_index = find_index_guest_flag(leaf_text) + #if flag_index == '0': + # tmp_flag.append(0) + #else: + # tmp_flag.append(flag_index) + + return tmp_flag + + +def get_config_root(config_file): + """ + This is get root of xml config + :param config_file: it is a file what contains information for script to read from + :return: top of root entry + """ + # create element tree object + tree = ET.parse(config_file) + # get root element + root = tree.getroot() + + return root + + +def get_vm_count(config_file): + """ + Get vm number + :param config_file: it is a file what contains information for script to read from + :return: total vm number + """ + vm_count = 0 + root = get_config_root(config_file) + for item in root: + # vm number in scenario + if item.tag == "vm": + vm_count += 1 + + return vm_count + + +def get_post_vm_count(config_file): + """ + Get post vm number + :param config_file: it is a file what contains information for script to read from + :return: total post vm number in launch file + """ + post_vm_count = 0 + + # get post vm number + root = get_config_root(config_file) + for item in root: + for sub in item: + if sub.tag == "load_order" and sub.text == "POST_LAUNCHED_VM": + post_vm_count += 1 + + return post_vm_count + + +def get_tree_tag_val(config_file, tag_str): + """ + This is get tag value by tag_str from config file + :param config_file: it is a file what contains information for script to read from + :param tag_str: it is key of pattern to config file item + :return: value of tag_str item + """ + root = get_config_root(config_file) + for item in root: + if item.tag == tag_str: + return item.text + + return False + + +def get_branch_tag(config_file, tag_str): + """ + This is get tag value by tag_str from config file + :param config_file: it is a file what contains information for script to read from + :param tag_str: it is key of pattern to config file item + :return: value of tag_str item list + """ + tmp_tag = [] + root = get_config_root(config_file) + for item in root: + + for sub in item: + if sub.tag == tag_str: + tmp_tag.append(sub.text) + + return tmp_tag + + +def get_branch_tag_val(config_file, tag_str): + """ + This is get tag value by tag_str from config file + :param config_file: it is a file what contains information for script to read from + :param tag_str: it is key of pattern to config file item + :return: value of tag_str item list + """ + tmp_tag = [] + root = get_config_root(config_file) + for item in root: + for sub in item: + if sub.tag == tag_str: + tmp_tag.append(sub.text) + + return tmp_tag + + +def get_branch_tag_map(config_file, tag_str): + """ + This is get tag value by tag_str from config file + :param config_file: it is a file what contains information for script to read from + :param tag_str: it is key of pattern to config file item + :return: value of tag_str item dictionary + """ + tmp_tag = {} + vm_id = 0 + root = get_config_root(config_file) + for item in root: + for sub in item: + if sub.tag == tag_str: + tmp_tag[vm_id] = sub.text + + if item.tag == "vm": + vm_id += 1 + + return tmp_tag + + +def get_leaf_tag_val(config_file, branch_tag, tag_str): + """ + This is get tag value by tag_str from config file + :param config_file: it is a file what contains information for script to read from + :param branch_tag: it is key of patter to config file branch tag item + :param tag_str: it is key of pattern to config file leaf tag item + :return: value of tag_str item + """ + tmp_tag = [] + root = get_config_root(config_file) + for item in root: + for sub in item: + tmp_flag = [] + tmp_cpus = [] + if sub.tag == branch_tag: + for leaf in sub: + if leaf.tag == tag_str and tag_str != "guest_flag" and tag_str != "pcpu_id" and\ + sub.tag != "vuart": + tmp_tag.append(leaf.text) + continue + + # get guest flag for logical partition vm1 + if leaf.tag == "guest_flag" and tag_str == "guest_flag": + t_flag = find_tmp_flag(leaf.text) + tmp_flag.append(t_flag) + #continue + + # get cpu for vm + if leaf.tag == "pcpu_id" and tag_str == "pcpu_id": + tmp_cpus.append(leaf.text) + continue + + # append guest flags for each vm + if tmp_flag and tag_str == "guest_flag": + tmp_tag.append(tmp_flag) + continue + + # append cpus for vm + if tmp_cpus and tag_str == "pcpu_id": + tmp_tag.append(tmp_cpus) + continue + + + return tmp_tag + + +def get_leaf_tag_map(config_file, branch_tag, tag_str): + """ + This is get tag value by tag_str from config file + :param config_file: it is a file what contains information for script to read from + :param branch_tag: it is key of patter to config file branch tag item + :param tag_str: it is key of pattern to config file leaf tag item + :return: value of tag_str item map + """ + tmp_tag = {} + vm_id = 0 + root = get_config_root(config_file) + for item in root: + for sub in item: + tmp_flag = [] + tmp_cpus = [] + if sub.tag == branch_tag: + for leaf in sub: + if leaf.tag == tag_str and tag_str != "guest_flag" and tag_str != "pcpu_id"\ + and sub.tag != "vuart": + tmp_tag[vm_id] = leaf.text + continue + + # get guest flag for logical partition vm1 + if leaf.tag == "guest_flag" and tag_str == "guest_flag": + tmp_flag = find_tmp_flag(tmp_flag, leaf.text) + continue + + # get cpu for vm + if leaf.tag == "pcpu_id" and tag_str == "pcpu_id": + tmp_cpus.append(leaf.text) + continue + + # append guest flags for each vm + if tmp_flag and tag_str == "guest_flag": + tmp_tag[vm_id] = tmp_flag + continue + + # append cpus for vm + if tmp_cpus and tag_str == "pcpu_id": + tmp_tag[vm_id] = tmp_cpus + continue + + if item.tag == "vm": + vm_id += 1 + + + return tmp_tag + + +def order_type_map_vmid(config_file, vm_count): + """ + This is mapping table for {id:order type} + :param config_file: it is a file what contains information for script to read from + :param vm_count: vm number + :return: table of id:order type dictionary + """ + order_id_dic = {} + load_type_list = get_branch_tag_val(config_file, "load_order") + for i in range(vm_count): + order_id_dic[i] = load_type_list[i] + + return order_id_dic + + +def get_load_order_by_vmid(config_file, vm_count, idx): + """ + Get load order by vm id + :param config_file: it is a file what contains information for script to read from + :param vm_count: vm number + :param idx: index of vm id + :return: table of id:order type dictionary + """ + err_dic = {} + order_id_dic = order_type_map_vmid(config_file, vm_count) + if idx >= vm_count or not order_id_dic: + err_dic['vm number: failue'] = "Toatal vm number is less than index number" + + return (err_dic, order_id_dic[idx]) + + +def add_to_patch(srcs_list, commit_name): + """ + Generate patch and apply to local source code + :param srcs_list: it is a list what contains source files + :param commit_name: distinguish the key commit message for the patch + """ + err_dic = {} + changes = ' '.join(srcs_list) + git_add = "git add {}".format(changes) + ret = subprocess.call(git_add, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, close_fds=True) + if ret: + err_dic['add patch: failue'] = "Add patch failue" + return err_dic + + # commit this changes + git_commit = 'git commit -sm "acrn-config: config board patch for {}"'.format(commit_name) + + try: + ret = subprocess.call(git_commit, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, close_fds=True) + if ret < 0: + err_dic['commit patch: commit patch failue'] = "Commit patch failue" + except (OSError, subprocess.CalledProcessError) as e: + err_dic['commit patch: commit patch failue'] = "Commit patch failue" + + return err_dic + + +def vm_pre_launch_cnt(config_file): + """ + Calculate the pre launched vm number + :param config_file: it is a file what contains information for script to read from + :return: number of pre launched vm + """ + pre_launch_cnt = 0 + load_type_list = get_branch_tag_val(config_file, "load_order") + + for vm_type in load_type_list: + if vm_type == "PRE_LAUNCHED_VM": + pre_launch_cnt += 1 + + return pre_launch_cnt + + +def get_max_clos(board_file): + """ + Parse CLOS information + :param board_file: it is a file what contains board information for script to read from + :return: type of cache support for clos and clos max number + """ + + cache_support = False + clos_max = 0 + + cat_lines = get_board_info(board_file, "", "") + + for line in cat_lines: + if line.split(':')[0].strip() == "clos supported by cache": + cache_support = line.split(':')[1].strip() + elif line.split(':')[0].strip() == "clos max": + clos_max = int(line.split(':')[1]) + + return (cache_support, clos_max) diff --git a/misc/acrn-config/library/scenario_cfg_lib.py b/misc/acrn-config/library/scenario_cfg_lib.py new file mode 100644 index 000000000..053255be8 --- /dev/null +++ b/misc/acrn-config/library/scenario_cfg_lib.py @@ -0,0 +1,785 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import common + +SOURCE_ROOT_DIR = common.SOURCE_PATH +HEADER_LICENSE = common.open_license() +BOARD_INFO_FILE = "board_info.txt" +SCENARIO_INFO_FILE = "" + +VM_COUNT = 0 +LOAD_ORDER_TYPE = ['PRE_LAUNCHED_VM', 'SOS_VM', 'POST_LAUNCHED_VM'] +START_HPA_LIST = ['0', '0x100000000', '0x120000000'] + +KERN_TYPE_LIST = ['KERNEL_BZIMAGE', 'KERNEL_ZEPHYR'] +KERN_BOOT_ADDR_LIST = ['0x100000'] + +GUEST_FLAG = common.GUEST_FLAG +VUART_TYPE = ['VUART_LEGACY_PIO', 'VUART_PCI'] +VUART_BASE = ['SOS_COM1_BASE', 'SOS_COM2_BASE', 'COM1_BASE', + 'COM2_BASE', 'COM3_BASE', 'COM4_BASE', 'INVALID_COM_BASE'] + +AVALIBLE_COM1_BASE = ['INVALID_COM_BASE', 'COM1_BASE'] +AVALIBLE_COM2_BASE = ['INVALID_COM_BASE', 'COM2_BASE'] + +VUART_IRQ = ['SOS_COM1_IRQ', 'SOS_COM2_IRQ', 'COM1_IRQ', 'COM2_IRQ', 'COM3_IRQ', + 'COM4_IRQ', 'CONFIG_COM_IRQ', '3', '4', '6', '7'] + +PCI_DEV_NUM_LIST = ['SOS_EMULATED_PCI_DEV_NUM', 'VM0_CONFIG_PCI_DEV_NUM', 'VM1_CONFIG_PCI_DEV_NUM'] +PCI_DEVS_LIST = ['sos_pci_devs', 'vm0_pci_devs', 'vm1_pci_devs'] + +COMMUNICATE_VM_ID = [] + +ERR_LIST = {} + +def prepare(): + """ Check environment """ + return common.check_env() + + +def print_yel(msg, warn=False): + """ + Print the message with 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' + """ + common.print_if_yel(msg, warn) + + +def print_red(msg, err=False): + """ + Print the message with 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' + """ + common.print_if_red(msg, err) + + +def usage(file_name): + """ This is usage for how to use this tool """ + common.usage(file_name) + + +def get_param(args): + """ + Get the script parameters from command line + :param args: this the command line of string for the script without script name + """ + return common.get_param(args) + + +def get_scenario_name(): + """ + Get board name from scenario.xml at fist line + :param scenario_file: it is a file what contains scenario information for script to read from + """ + (err_dic, scenario) = common.get_xml_attrib(SCENARIO_INFO_FILE, "scenario") + + return (err_dic, scenario) + + +def is_config_file_match(): + + (err_dic, scenario_for_board) = common.get_xml_attrib(SCENARIO_INFO_FILE, "board") + (err_dic, board_name) = common.get_xml_attrib(BOARD_INFO_FILE, "board") + + if scenario_for_board == board_name: + return (err_dic, True) + else: + return (err_dic, False) + + +def get_info(board_info, msg_s, msg_e): + """ + Get information which specify by argument + :param board_info: it is a file what contains board information for script to read from + :param msg_s: it is a pattern of key stings what start to match from board information + :param msg_e: it is a pattern of key stings what end to match from board information + """ + info_lines = common.get_board_info(board_info, msg_s, msg_e) + return info_lines + + +def get_processor_info(board_info): + """ + Get cpu core list + :param board_info: it is a file what contains board information for script to read from + :return: cpu processor which one cpu has + """ + processor_list = [] + tmp_list = [] + processor_info = get_info(board_info, "", "") + + if not processor_info: + key = "vm:id=0,pcpu_ids" + ERR_LIST[key] = "CPU core is not exists" + return processor_list + + for processor_line in processor_info: + if not processor_line: + break + + processor_list = processor_line.strip().split(',') + for processor in processor_list: + tmp_list.append(processor.strip()) + break + + return tmp_list + + +def get_rootdev_info(board_info): + """ + Get root devices from board info + :param board_info: it is a file what contains board information for script to read from + :return: root devices list + """ + rootdev_list = [] + rootdev_info = get_info(board_info, "", "") + + for rootdev_line in rootdev_info: + if not rootdev_line: + break + + root_dev = rootdev_line.strip().split(':')[0] + rootdev_list.append(root_dev) + + return rootdev_list + + +def get_ttys_info(board_info): + """ + Get ttySn from board info + :param board_info: it is a file what contains board information for script to read from + :return: serial console list + """ + ttys_list = [] + ttys_info = get_info(board_info, "", "") + + for ttys_line in ttys_info: + if not ttys_line: + break + + #ttys_dev = " ".join(ttys_line.strip().split()[:-2]) + ttys_dev = ttys_line.split()[1].split(':')[1] + ttys_list.append(ttys_dev) + + return ttys_list + + +def get_board_private_info(config_file): + + (err_dic, scenario_name) = get_scenario_name() + + if scenario_name == "logical_partition": + branch_tag = "os_config" + else: + branch_tag = "board_private" + + private_info = {} + dev_private_tags = ['rootfs', 'console'] + for tag_str in dev_private_tags: + dev_setting = get_sub_leaf_tag(config_file, branch_tag, tag_str) + #dev_info = get_sub_tree_tag(config_file, ) + if not dev_setting and tag_str == "console": + continue + + private_info[tag_str] = dev_setting + + return (err_dic, private_info) + + +def check_board_private_info(): + + (err_dic, private_info) = get_board_private_info(SCENARIO_INFO_FILE) + + if not private_info['rootfs'] and err_dic: + ERR_LIST['vm,id=0,boot_private,rootfs'] = "The board have to chose one rootfs partition" + ERR_LIST.update(err_dic) + + +def get_vm_num(config_file): + """ + This is get vm count + :param config_file: it is a file what contains vm information for script to read from + :return: number of vm + """ + return common.get_vm_count(config_file) + + +def get_sub_tree_tag(config_file, tag_str): + """ + This is get tag value by tag_str from config file + :param config_file: it is a file what contains information for script to read from + :param tag_str: it is key of pattern to config file item + :return: value of tag_str item + """ + return common.get_branch_tag_val(config_file, tag_str) + + +def get_sub_leaf_tag(config_file, branch_tag, tag_str): + """ + This is get tag value by tag_str from config file + :param config_file: it is a file what contains information for script to read from + :param branch_tag: it is key of patter to config file branch tag item + :param tag_str: it is key of pattern to config file leaf tag item + :return: value of tag_str item + """ + return common.get_leaf_tag_val(config_file, branch_tag, tag_str) + + +def get_order_type_by_vmid(idx): + """ + Get load order by vm id + + :param idx: index of vm id + :return: load order type of vm + """ + (err_dic, order_id_dic) = common.get_load_order_by_vmid(SCENARIO_INFO_FILE, VM_COUNT, idx) + if err_dic: + ERR_LIST.update(err_dic) + + return order_id_dic + + +def get_vmid_by_order_type(type_str): + """ + This is mapping table for {id:order type} + :param type_str: vm loader type + :return: table of id:order type dictionary + """ + + idx_list = [] + order_id_dic = common.order_type_map_vmid(SCENARIO_INFO_FILE, VM_COUNT) + + for idx, order_type in order_id_dic.items(): + if type_str == order_type: + idx_list.append(idx) + + return idx_list + + +def is_pre_launch_vm(idx): + """ + Identification the vm id loader type is pre launched + :param idx: vm id number + :return: True if it is a pre launched vm + """ + order_type = get_order_type_by_vmid(idx) + if order_type == "PRE_LAUNCHED_VM": + status = True + else: + status = False + + return status + +def pre_launch_vm_ids(): + """ Get pre launched vm ids as list """ + pre_vm = [] + + for i in range(VM_COUNT): + if is_pre_launch_vm(i): + pre_vm.append(i) + + return pre_vm + + +def vm_name_check(vm_names, item): + """ + Check vm name + :param vm_names: list of vm name + :param item: vm name item in xml + :return: None + """ + for name_i in range(len(vm_names)): + name_len = len(vm_names[name_i]) + if name_len > 32 or name_len == 0: + key = "vm:id={},{}".format(name_i, item) + ERR_LIST[key] = "VM name length should be in range [1,32] bytes" + + +def load_order_check(load_orders, item): + """ + Check load order type + :param load_orders: list of vm load_order + :param item: vm name item in xml + :return: None + """ + for order_i in range(len(load_orders)): + load_str = load_orders[order_i] + + if not load_str: + key = "vm:id={},{}".format(order_i, item) + ERR_LIST[key] = "VM load should not empty" + return + + if load_str not in LOAD_ORDER_TYPE: + key = "vm:id={},{}".format(order_i, item) + ERR_LIST[key] = "VM load order unknown" + + +def guest_flag_check(guest_flag_idx, branch_tag, leaf_tag): + + guest_flag_len = len(common.GUEST_FLAG) + guest_num = len(guest_flag_idx) + + for vm_i in range(guest_num): + flag_len = len(guest_flag_idx[vm_i]) + if flag_len <= guest_flag_len: + continue + else: + key = "vm:id={},{},{}".format(vm_i, branch_tag, leaf_tag) + ERR_LIST[key] = "Unknow guest flag" + # for flag_i in range(flag_len): + # if guest_flag_idx[vm_i][flag_i] in common.GUEST_FLAG: + # continue + # else: + # key = "vm:id={},{},{}".format(vm_i, branch_tag, leaf_tag) + # ERR_LIST[key] = "Invalid guest flag" + + +def uuid_format_check(uuid_lists, item): + """ + Check uuid + :param uuid_lists: list of vm uuid + :param item: vm uuid item in xml + :return: None + """ + uuid_len = 36 + + for uuid_i in range(len(uuid_lists)): + uuid_str = uuid_lists[uuid_i] + + if not uuid_str: + key = "vm:id={},{}".format(uuid_i, item) + ERR_LIST[key] = "VM uuid should not empty" + return + + uuid_str_list = list(uuid_str) + key = "vm:id={},{}".format(uuid_i, item) + + if len(uuid_str) != uuid_len: + ERR_LIST[key] = "VM uuid length should be 36 bytes" + + if uuid_str_list[8] != '-': + ERR_LIST[key] = "VM uuid format unknown" + + +def cpus_per_vm_check(item): + """ + Check cpu of per vm + :param item: vm pcpu_id item in xml + :return: None + """ + prime_item = "pcpu_ids" + id_cpus_per_vm_dic = common.get_leaf_tag_map(SCENARIO_INFO_FILE, prime_item, item) + + for id_key in id_cpus_per_vm_dic.keys(): + vm_type = get_order_type_by_vmid(id_key) + cpus_vm_i = id_cpus_per_vm_dic[id_key] + if not cpus_vm_i and vm_type == "PRE_LAUNCHED_VM": + key = "vm:id={},{}".format(id_key, item) + ERR_LIST[key] = "VM have no assignment cpus" + + +def mem_start_hpa_check(item): + """ + Check host physical address + :param item: vm start_hpa item in xml + :return: None + """ + prime_item = "memory" + id_start_hpa_dic = common.get_leaf_tag_map(SCENARIO_INFO_FILE, prime_item, item) + + for id_key, hpa_str in id_start_hpa_dic.items(): + hpa_strip_ul = hpa_str.strip('UL') + hpa_strip_u = hpa_str.strip('U') + + if not hpa_str: + key = "vm:id={},{}".format(id_key, item) + ERR_LIST[key] = "VM start host physical memory address should not empty" + return + + if hpa_strip_ul not in START_HPA_LIST and hpa_strip_u not in START_HPA_LIST: + key = "vm:id={},{},{}".format(id_key, prime_item, item) + if '0x' not in hpa_str and '0X' not in hpa_str: + ERR_LIST[key] = "Address should be Hex format" + + +def mem_size_check(item): + """ + Check host physical size + :param item: vm size item in xml + :return: None + """ + prime_item = "memory" + id_hpa_size_dic = common.get_leaf_tag_map(SCENARIO_INFO_FILE, prime_item, item) + + for id_key, hpa_size in id_hpa_size_dic.items(): + hpa_sz_strip_ul = hpa_size.strip('UL') + hpa_sz_strip_u = hpa_size.strip('U') + + if not hpa_size: + key = "vm:id={},{}".format(id_key, item) + ERR_LIST[key] = "VM start host physical memory size should not empty" + return + + if hpa_sz_strip_ul not in common.START_HPA_SIZE_LIST and hpa_sz_strip_u not in \ + common.START_HPA_SIZE_LIST: + key = "vm:id={},{},{}".format(id_key, prime_item, item) + mem_max = 2 * 1024 * 1024 * 1024 + if '0x' not in hpa_size and '0X' not in hpa_size: + ERR_LIST[key] = "Mem size should be Hex format" + elif int(hpa_sz_strip_ul, 16) > mem_max or int(hpa_sz_strip_u, 16) > mem_max: + ERR_LIST[key] = "Mem size should less than 2GB" + + +def os_kern_name_check(item): + """ + Check os kernel name + :param item: vm os config name item in xml + :return: None + """ + prime_item = "os_config" + id_kern_name_dic = common.get_leaf_tag_map(SCENARIO_INFO_FILE, prime_item, item) + + for id_key, kern_name in id_kern_name_dic.items(): + if len(kern_name) > 32 or len(kern_name) == 0: + key = "vm:id={},{},{}".format(id_key, prime_item, item) + ERR_LIST[key] = "VM os config kernel name length should be in range [1,32] bytes" + + +def os_kern_type_check(item): + """ + Check os kernel type + :param item: vm os config type item in xml + :return: None + """ + prime_item = "os_config" + id_kern_type_dic = common.get_leaf_tag_map(SCENARIO_INFO_FILE, prime_item, item) + + for id_key, kern_type in id_kern_type_dic.items(): + + if not kern_type: + key = "vm:id={},{}".format(id_key, item) + ERR_LIST[key] = "VM os config kernel type should not empty" + return + + if kern_type not in KERN_TYPE_LIST: + key = "vm:id={},{},{}".format(id_key, prime_item, item) + ERR_LIST[key] = "VM os config kernel type unknown" + + +def os_kern_mod_check(item): + """ + Check os kernel mod + :param item: vm os config mod item in xml + :return: None + """ + prime_item = "os_config" + id_kern_mod_dic = common.get_leaf_tag_map(SCENARIO_INFO_FILE, prime_item, item) + + for id_key, kern_mod in id_kern_mod_dic.items(): + if len(kern_mod) > 32 or len(kern_mod) == 0: + key = "vm:id={},{},{}".format(id_key, prime_item, item) + ERR_LIST[key] = "VM os config kernel mod tag should be in range [1,32] bytes" + + +def os_kern_args_check(item): + """ + Check os kernel args + :param item: vm os config args item in xml + :return: None + """ + prime_item = "os_config" + id_kern_args_dic = common.get_leaf_tag_map(SCENARIO_INFO_FILE, prime_item, item) + + for id_key, kern_args in id_kern_args_dic.items(): + vm_type = get_order_type_by_vmid(id_key) + + if vm_type == "SOS_VM" and kern_args != "SOS_VM_BOOTARGS": + key = "vm:id={},{},{}".format(id_key, prime_item, item) + ERR_LIST[key] = "VM os config kernel service os should be SOS_VM_BOOTARGS" + + +def os_kern_console_check(item): + """ + Check os kernel console + :param item: vm os config console item in xml + :return: None + """ + prime_item = "os_config" + id_kern_console_dic = common.get_leaf_tag_map(SCENARIO_INFO_FILE, prime_item, item) + + for id_key, kern_console in id_kern_console_dic.items(): + if kern_console and "ttyS" not in kern_console: + key = "vm:id={},{},{}".format(id_key, prime_item, item) + ERR_LIST[key] = "VM os config kernel console should be ttyS[0..3]" + + +def os_kern_load_addr_check(item): + """ + Check os kernel load address + :param item: vm os config load address item in xml + :return: None + """ + prime_item = "os_config" + id_kern_load_addr_dic = common.get_leaf_tag_map(SCENARIO_INFO_FILE, prime_item, item) + + for id_key, kern_load_addr in id_kern_load_addr_dic.items(): + + if not kern_load_addr: + key = "vm:id={},{},{}".format(id_key, prime_item, item) + ERR_LIST[key] = "VM os config kernel load address should not empty" + return + + if '0x' not in kern_load_addr and '0X' not in kern_load_addr: + key = "vm:id={},{},{}".format(id_key, prime_item, item) + ERR_LIST[key] = "VM os config kernel load address should Hex format" + + +def os_kern_entry_addr_check(item): + """ + Check os kernel entry address + :param item: vm os config entry address item in xml + :return: None + """ + prime_item = "os_config" + id_kern_entry_addr_dic = common.get_leaf_tag_map(SCENARIO_INFO_FILE, prime_item, item) + + for id_key, kern_entry_addr in id_kern_entry_addr_dic.items(): + + if not kern_entry_addr: + key = "vm:id={},{},{}".format(id_key, prime_item, item) + ERR_LIST[key] = "VM os config kernel entry address should not empty" + return + + if '0x' not in kern_entry_addr and '0X' not in kern_entry_addr: + key = "vm:id={},{},{}".format(id_key, prime_item, item) + ERR_LIST[key] = "VM os config kernel entry address should Hex format" + + +def os_kern_root_dev_check(item): + """ + Check os kernel rootfs partitions + :param item: vm os config rootdev item in xml + :return: None + """ + prime_item = "os_config" + id_kern_rootdev_dic = common.get_leaf_tag_map(SCENARIO_INFO_FILE, prime_item, item) + + for id_key, kern_rootdev in id_kern_rootdev_dic.items(): + if not kern_rootdev: + key = "vm:id={},{},{}".format(id_key, prime_item, item) + ERR_LIST[key] = "VM os config kernel root device should not empty" + + +def pci_dev_num_check(item): + """ + Check vm pci device number + :param item: vm pci_dev_num item in xml + :return: None + """ + id_dev_num_dic = common.get_branch_tag_map(SCENARIO_INFO_FILE, item) + + for id_key, pci_dev_num in id_dev_num_dic.items(): + + vm_type = get_order_type_by_vmid(id_key) + if vm_type != "POST_LAUNCHED_VM" and pci_dev_num: + if pci_dev_num not in PCI_DEV_NUM_LIST: + key = "vm:id={},{}".format(id_key, item) + ERR_LIST[key] = "VM pci device number shoud be one of {}".format(PCI_DEV_NUM_LIST) + +def pci_devs_check(item): + """ + Check vm pci devices + :param item: vm pci_devs item in xml + :return: None + """ + id_devs_dic = common.get_branch_tag_map(SCENARIO_INFO_FILE, item) + + for id_key, pci_dev in id_devs_dic.items(): + + vm_type = get_order_type_by_vmid(id_key) + if vm_type != "POST_LAUNCHED_VM" and pci_dev: + if pci_dev not in PCI_DEVS_LIST: + key = "vm:id={},{}".format(id_key, item) + ERR_LIST[key] = "VM pci device shoud be one of {}".format(PCI_DEVS_LIST) + + +def get_vuart1_vmid(vm_vuart1): + """ + Get vmid:vuart1 dictionary + :param vm_vuart1: vm_vuart1 setting from xml + :return: dictionary of vmid:vuart1 + """ + vm_id_dic = {} + for i in range(VM_COUNT): + for key in vm_vuart1[i].keys(): + if key == "target_vm_id": + vm_id_dic[i] = vm_vuart1[i][key] + + # remove the unavailable vimid:target_vmid from dictonary + vmid_list = list(vm_id_dic.keys()) + + for vmid in vmid_list: + new_vmid = vm_id_dic[vmid] + if int(new_vmid) in vmid_list and vmid == int(vm_id_dic[int(new_vmid)]): + continue + else: + vm_id_dic.pop(vmid) + + return vm_id_dic + + +def cpus_assignment(cpus_per_vm, index): + """ + Get cpu id assignment for vm by vm index + :param cpus_per_vm: a dictionary by vmid:cpus + :param index: vm index + :return: cpu assignment string + """ + vm_cpu_bmp = {} + + for i in range(len(cpus_per_vm[index])): + if i == 0: + if len(cpus_per_vm[index]) == 1: + cpu_str = "(PLUG_CPU({0}))".format(cpus_per_vm[index][0]) + else: + cpu_str = "(PLUG_CPU({0})".format(cpus_per_vm[index][0]) + else: + if i == len(cpus_per_vm[index]) - 1: + cpu_str = cpu_str + " | PLUG_CPU({0}))".format(cpus_per_vm[index][i]) + else: + cpu_str = cpu_str + " | PLUG_CPU({0})".format(cpus_per_vm[index][i]) + + vm_cpu_bmp['cpu_map'] = cpu_str + vm_cpu_bmp['cpu_num'] = len(cpus_per_vm[index]) + return vm_cpu_bmp + + +def gen_patch(srcs_list, scenario_name): + """ + Generate patch and apply to local source code + :param srcs_list: it is a list what contains source files + :param scenario_name: scenario name + """ + err_dic = common.add_to_patch(srcs_list, scenario_name) + return err_dic + + +def get_vuart_id(tmp_vuart, leaf_tag, leaf_text): + """ + Get all vuart id member of class + :param tmp_vuart: a dictionary to store member:value + :param leaf_tag: key pattern of item tag + :param leaf_text: key pattern of item tag's value + :return: a dictionary to which stored member:value + """ + if leaf_tag == "type": + tmp_vuart['type'] = leaf_text + if leaf_tag == "base": + tmp_vuart['base'] = leaf_text + if leaf_tag == "irq": + tmp_vuart['irq'] = leaf_text + + if leaf_tag == "target_vm_id": + tmp_vuart['target_vm_id'] = leaf_text + if leaf_tag == "target_uart_id": + tmp_vuart['target_uart_id'] = leaf_text + + return tmp_vuart + + +def get_vuart_info_id(config_file, idx): + """ + Get vuart information by vuart id indexx + :param config_file: it is a file what contains information for script to read from + :param idx: vuart index in range: [0,1] + :return: dictionary which stored the vuart-id + """ + tmp_tag = {} + vm_id = 0 + root = common.get_config_root(config_file) + for item in root: + for sub in item: + tmp_vuart = {} + for leaf in sub: + if sub.tag == "vuart" and int(sub.attrib['id']) == idx: + tmp_vuart = get_vuart_id(tmp_vuart, leaf.tag, leaf.text) + + # append vuart for each vm + if tmp_vuart and sub.tag == "vuart": + tmp_tag[vm_id] = tmp_vuart + + if item.tag == "vm": + vm_id += 1 + + return tmp_tag + + +def avl_vuart_ui_select(scenario_info): + vm_num = get_vm_num(scenario_info) + tmp_vuart = {} + for vm_i in range(vm_num): + vm_type = get_order_type_by_vmid(vm_i) + + if vm_type == "SOS_VM": + key = "vm={},vuart=0,base".format(vm_i) + tmp_vuart[key] = ['SOS_COM1_BASE', 'INVALID_COM_BASE'] + key = "vm={},vuart=1,base".format(vm_i) + tmp_vuart[key] = ['SOS_COM2_BASE', 'INVALID_COM_BASE'] + else: + key = "vm={},vuart=0,base".format(vm_i) + tmp_vuart[key] = ['INVALID_COM_BASE', 'COM1_BASE'] + key = "vm={},vuart=1,base".format(vm_i) + tmp_vuart[key] = ['INVALID_COM_BASE', 'COM2_BASE'] + + #print(tmp_vuart) + return tmp_vuart + + +def vmid_map_epc(config_file, tag, item): + """ + This is mapping table for {id:item} + :param config_file: it is a file what contains information for script to read from + :param item: the item in xml file + :return: table of id:item type dictionary + """ + epc_order = {} + vm_cnt = VM_COUNT + + item_list = common.get_leaf_tag_val(config_file, tag, item) + load_type_list = common.get_branch_tag_val(config_file, "load_order") + + if 'SOS_VM' in load_type_list: + vm_cnt = VM_COUNT - 1 + for i in range(vm_cnt): + epc_order[i] = item_list[i] + + return epc_order + + +def get_epc_base(scenario_info): + + base_dic = {} + base_dic = vmid_map_epc(scenario_info, "epc_section", "base") + return base_dic + + +def get_epc_size(scenario_info): + + size_dic = {} + size_dic = vmid_map_epc(scenario_info, "epc_section", "size") + return size_dic + +def get_first_post_vm(): + + for i in range(VM_COUNT): + (err_dic, vm_type) = common.get_load_order_by_vmid(SCENARIO_INFO_FILE, VM_COUNT, i) + if vm_type == "POST_LAUNCHED_VM": + break + + return (err_dic, i) diff --git a/misc/acrn-config/scenario_config/pci_dev_c.py b/misc/acrn-config/scenario_config/pci_dev_c.py new file mode 100644 index 000000000..a6a736fe3 --- /dev/null +++ b/misc/acrn-config/scenario_config/pci_dev_c.py @@ -0,0 +1,50 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import scenario_cfg_lib +PCI_DEV_TYPE = ['PCI_DEV_TYPE_HVEMUL', 'PCI_DEV_TYPE_PTDEV'] + + +def generate_file(config): + """ + Generate pci_dev.c while logical_partition scenario + :param config: it is pointer for for file write to + :return: None + """ + print("{}".format(scenario_cfg_lib.HEADER_LICENSE), file=config) + print("#include ", file=config) + print("#include ", file=config) + print("#include ", file=config) + print("", file=config) + print("/* The vbar_base info of pt devices is included in device MACROs which defined in", + file=config) + print(" * arch/x86/configs/$(CONFIG_BOARD)/pci_devices.h.", file=config) + print(" * The memory range of vBAR should exactly match with the e820 layout of VM.", + file=config) + print(" */", file=config) + for i in range(scenario_cfg_lib.VM_COUNT): + print("struct acrn_vm_pci_dev_config " + + "vm{}_pci_devs[VM{}_CONFIG_PCI_DEV_NUM] = {{".format(i, i), file=config) + print("\t{", file=config) + print("\t\t.emu_type = {},".format(PCI_DEV_TYPE[0]), file=config) + print("\t\t.vbdf.bits = {.b = 0x00U, .d = 0x00U, .f = 0x00U},", file=config) + print("\t\t.vdev_ops = &vhostbridge_ops,", file=config) + print("\t},", file=config) + print("\t{", file=config) + print("\t\t.emu_type = {},".format(PCI_DEV_TYPE[1]), file=config) + print("\t\t.vbdf.bits = {.b = 0x00U, .d = 0x01U, .f = 0x00U},", file=config) + print("\t\tVM{}_STORAGE_CONTROLLER".format(i), file=config) + print("\t},", file=config) + if i != 0: + print("#if defined(VM{}_NETWORK_CONTROLLER)".format(i), file=config) + print("\t{", file=config) + print("\t\t.emu_type = {},".format(PCI_DEV_TYPE[1]), file=config) + print("\t\t.vbdf.bits = {.b = 0x00U, .d = 0x02U, .f = 0x00U},", file=config) + print("\t\tVM{}_NETWORK_CONTROLLER".format(i), file=config) + print("\t},", file=config) + if i != 0: + print("#endif", file=config) + print("};", file=config) + print("", file=config) diff --git a/misc/acrn-config/scenario_config/scenario_cfg_gen.py b/misc/acrn-config/scenario_config/scenario_cfg_gen.py new file mode 100755 index 000000000..91536b607 --- /dev/null +++ b/misc/acrn-config/scenario_config/scenario_cfg_gen.py @@ -0,0 +1,164 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import os +import sys +import copy +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library')) +from scenario_item import HwInfo, VmInfo +import scenario_cfg_lib +import vm_configurations_c +import vm_configurations_h +import pci_dev_c + +ACRN_PATH = scenario_cfg_lib.SOURCE_ROOT_DIR +SCENARIO_PATH = ACRN_PATH + 'hypervisor/scenarios' +GEN_FILE = ["vm_configurations.h", "vm_configurations.c", "pci_dev.c"] + + +def get_scenario_item_values(board_info, scenario_info): + """ + Get items which capable multi select for user + :param board_info: it is a file what contains board information for script to read from + """ + scenario_item_values = {} + hw_info = HwInfo(board_info) + + # get vm count + scenario_cfg_lib.SCENARIO_INFO_FILE = scenario_info + scenario_cfg_lib.BOARD_INFO_FILE = board_info + scenario_cfg_lib.VM_COUNT = scenario_cfg_lib.get_vm_num(scenario_info) + + # pre scenario + guest_flags = copy.deepcopy(scenario_cfg_lib.GUEST_FLAG) + guest_flags.remove('0UL') + scenario_item_values["vm,pcpu_ids"] = hw_info.get_processor_val() + scenario_item_values["vm,guest_flags"] = guest_flags + scenario_item_values["vm,clos"] = hw_info.get_clos_val() + scenario_item_values["vm,os_config,kern_type"] = scenario_cfg_lib.KERN_TYPE_LIST + scenario_item_values.update(scenario_cfg_lib.avl_vuart_ui_select(scenario_info)) + + # pre board_private + scenario_item_values["vm,board_private,rootfs"] = scenario_cfg_lib.get_rootdev_info(board_info) + scenario_item_values["vm,board_private,console"] = scenario_cfg_lib.get_ttys_info(board_info) + + # os config + scenario_item_values["vm,os_config,rootfs"] = scenario_cfg_lib.get_rootdev_info(board_info) + + return scenario_item_values + + +def validate_scenario_setting(board_info, scenario_info): + """ + This is validate the data setting from scenario xml + :param board_info: it is a file what contains board information for script to read from + :param scenario_info: it is a file what user have already setting to + :return: return a dictionary contain errors + """ + scenario_cfg_lib.ERR_LIST = {} + scenario_cfg_lib.BOARD_INFO_FILE = board_info + scenario_cfg_lib.SCENARIO_INFO_FILE = scenario_info + + vm_info = VmInfo(board_info, scenario_info) + + vm_info.get_info() + + vm_info.check_item() + + return (scenario_cfg_lib.ERR_LIST, vm_info) + + +def main(args): + """ + This is main function to start generate source code related with board + :param args: it is a command line args for the script + """ + err_dic = {} + config_srcs = [] + + (err_dic, board_info_file, scenario_info_file) = scenario_cfg_lib.get_param(args) + if err_dic: + return err_dic + + scenario_cfg_lib.BOARD_INFO_FILE = board_info_file + scenario_cfg_lib.SCENARIO_INFO_FILE = scenario_info_file + + # get scenario name + (err_dic, scenario) = scenario_cfg_lib.get_scenario_name() + if err_dic: + return err_dic + + # check if this is the scenario config which matched board info + (err_dic, status) = scenario_cfg_lib.is_config_file_match() + if not status: + err_dic['scenario config: Not match'] = "The board xml and scenario xml should be matched!" + return err_dic + + vm_config_h = SCENARIO_PATH + '/' + scenario + '/' + GEN_FILE[0] + vm_config_c = SCENARIO_PATH + '/' + scenario + '/' + GEN_FILE[1] + pci_config_c = SCENARIO_PATH + '/' + scenario + '/' + GEN_FILE[2] + + config_srcs.append(vm_config_h) + config_srcs.append(vm_config_c) + if scenario == "logical_partition": + config_srcs.append(pci_config_c) + + # parse the scenario.xml + get_scenario_item_values(board_info_file, scenario_info_file) + (err_dic, vm_info) = validate_scenario_setting(board_info_file, scenario_info_file) + if err_dic: + scenario_cfg_lib.print_red("Validate the scenario item failue", err=True) + return err_dic + + # generate vm_configuration.h + with open(vm_config_h, 'w') as config: + vm_configurations_h.generate_file(scenario, vm_info, config) + + # generate vm_configuration.c + with open(vm_config_c, 'w') as config: + err_dic = vm_configurations_c.generate_file(scenario, vm_info, config) + if err_dic: + return err_dic + + # generate pci_dev.c if scenario is logical_partition + if scenario == 'logical_partition': + with open(pci_config_c, 'w') as config: + pci_dev_c.generate_file(config) + + # move changes to patch, and apply to the source code + err_dic = scenario_cfg_lib.gen_patch(config_srcs, scenario) + if not err_dic: + print("Config patch for {} is committed successfully!".format(scenario)) + else: + print("Config patch for {} is failed".format(scenario)) + + return err_dic + + +def ui_entry_api(board_info, scenario_info): + arg_list = ['board_cfg_gen.py', '--board', board_info, '--scenario', scenario_info] + err_dic = scenario_cfg_lib.prepare() + if err_dic: + return err_dic + + err_dic = main(arg_list) + + return err_dic + + +if __name__ == '__main__': + + err_dic = scenario_cfg_lib.prepare() + if err_dic: + for err_k, err_v in err_dic.items(): + scenario_cfg_lib.print_red("{}: {}".format(err_k, err_v), err=True) + sys.exit(1) + + ARGS = sys.argv + err_dic = main(ARGS) + if err_dic: + for err_k, err_v in err_dic.items(): + scenario_cfg_lib.print_red("{}: {}".format(err_k, err_v), err=True) + diff --git a/misc/acrn-config/scenario_config/scenario_item.py b/misc/acrn-config/scenario_config/scenario_item.py new file mode 100644 index 000000000..336cc920a --- /dev/null +++ b/misc/acrn-config/scenario_config/scenario_item.py @@ -0,0 +1,314 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import scenario_cfg_lib +import board_cfg_lib + + +class HwInfo: + """ This is Abstract of class of Hardware information """ + processor_val = [] + clos_val = [] + root_dev_val = [] + ttys_val = [] + + def __init__(self, board_file): + self.board_info = board_file + + def get_processor_val(self): + """ + Get cpu core list + :return: cpu processor which one cpu has + """ + self.processor_val = scenario_cfg_lib.get_processor_info(self.board_info) + return self.processor_val + + def get_rootdev_val(self): + """ + Get root devices from board info + :return: root devices list + """ + self.root_dev_val = scenario_cfg_lib.get_rootdev_info(self.board_info) + return self.root_dev_val + + def get_ttys_val(self): + """ + Get ttySn from board info + :return: serial console list + """ + self.ttys_val = scenario_cfg_lib.get_ttys_info(self.board_info) + return self.ttys_val + + def get_clos_val(self): + """ + Get clos max number from board info + :return: clos support list + """ + self.clos_val = [] + (clos_support, clos_max) = board_cfg_lib.clos_info_parser(self.board_info) + if clos_support: + for i_cnt in range(clos_max): + self.clos_val.append(str(i_cnt)) + + return self.clos_val + + def get_info(self): + """ + Get all items which belong to this class + :return: None + """ + self.processor_val = self.get_processor_val() + self.get_rootdev_val() + self.get_ttys_val() + self.get_clos_val() + + +class CfgOsKern: + """ This is Abstract of class of configuration of vm os kernel setting """ + kern_name = [] + kern_type = [] + kern_mod = [] + kern_args = [] + kern_console = [] + kern_load_addr = [] + kern_entry_addr = [] + kern_root_dev = [] + kern_args_append = [] + + def __init__(self, scenario_file): + self.scenario_info = scenario_file + + def get_info(self): + """ + Get all items which belong to this class + :return: None + """ + self.kern_name = scenario_cfg_lib.get_sub_leaf_tag(self.scenario_info, "os_config", "name") + self.kern_type = scenario_cfg_lib.get_sub_leaf_tag( + self.scenario_info, "os_config", "kern_type") + self.kern_mod = scenario_cfg_lib.get_sub_leaf_tag( + self.scenario_info, "os_config", "kern_mod") + self.kern_args = scenario_cfg_lib.get_sub_leaf_tag( + self.scenario_info, "os_config", "bootargs") + self.kern_console = scenario_cfg_lib.get_sub_leaf_tag( + self.scenario_info, "os_config", "console") + self.kern_load_addr = scenario_cfg_lib.get_sub_leaf_tag( + self.scenario_info, "os_config", "kern_load_addr") + self.kern_entry_addr = scenario_cfg_lib.get_sub_leaf_tag( + self.scenario_info, "os_config", "kern_entry_addr") + self.kern_root_dev = scenario_cfg_lib.get_sub_leaf_tag( + self.scenario_info, "os_config", "rootfs") + self.kern_args_append = scenario_cfg_lib.get_sub_leaf_tag( + self.scenario_info, "boot_private", "bootargs") + + @staticmethod + def check_item(): + """ + Check all items in this class + :return: None + """ + scenario_cfg_lib.os_kern_name_check("name") + scenario_cfg_lib.os_kern_type_check("kern_type") + scenario_cfg_lib.os_kern_mod_check("kern_mod") + scenario_cfg_lib.os_kern_args_check("kern_args") + scenario_cfg_lib.os_kern_console_check("console") + scenario_cfg_lib.os_kern_load_addr_check("kern_load_addr") + scenario_cfg_lib.os_kern_entry_addr_check("kern_entry_addr") + scenario_cfg_lib.os_kern_root_dev_check("rootdev") + + +class VuartTarget: + """ This is Abstract of class of vm target vuart """ + t_vm_id = [] + t_vuart_id = [] + + def __init__(self): + self.t_vm_id = [] + + def style_check_1(self): + """ This is public method for style check""" + self.t_vm_id = [] + + def style_check_2(self): + """ This is public method for style check""" + self.t_vm_id = [] + + +class VuartCfg(VuartTarget): + """ This is Abstract of class of vm vuart configuration """ + v_type = [] + v_base = [] + v_irq = [] + target = VuartTarget() + + def __init__(self): + self.v1_type = [] + + def style_check_1(self): + """ This is public method for style check""" + self.v1_type = [] + + +class VuartInfo: + """ This is Abstract of class of vm vuart setting """ + v0_vuart = VuartCfg() + v1_vuart = VuartCfg() + + def __init__(self, scenario_file): + self.scenario_info = scenario_file + + def style_check_1(self): + """ This is public method for style check""" + self.v1_vuart = [] + + def get_info(self): + """ + Get all items which belong to this class + :return: None + """ + self.v0_vuart = scenario_cfg_lib.get_vuart_info_id(self.scenario_info, 0) + self.v1_vuart = scenario_cfg_lib.get_vuart_info_id(self.scenario_info, 1) + scenario_cfg_lib.check_board_private_info() + + +class MemInfo: + """ This is Abstract of class of memory setting information """ + mem_start_hpa = [] + mem_size = [] + + def __init__(self, scenario_file): + self.scenario_info = scenario_file + + def get_info(self): + """ + Get all items which belong to this class + :return: None + """ + self.mem_start_hpa = scenario_cfg_lib.get_sub_leaf_tag( + self.scenario_info, "memory", "start_hpa") + self.mem_size = scenario_cfg_lib.get_sub_leaf_tag( + self.scenario_info, "memory", "size") + + @staticmethod + def check_item(): + """ + Check all items in this class + :return: None + """ + scenario_cfg_lib.mem_start_hpa_check("start_hpa") + scenario_cfg_lib.mem_size_check("size") + + +class CfgPci: + """ This is Abstract of class of PCi devices setting information """ + pci_dev_num = [] + pci_devs = [] + + def __init__(self, scenario_file): + self.scenario_info = scenario_file + + def get_pci_dev_num(self): + """ + Get pci device number items + :return: None + """ + self.pci_dev_num = scenario_cfg_lib.get_sub_tree_tag(self.scenario_info, "pci_dev_num") + + def get_pci_devs(self): + """ + Get pci devices items + :return: None + """ + self.pci_devs = scenario_cfg_lib.get_sub_tree_tag(self.scenario_info, "pci_devs") + + def get_info(self): + """ + Get all items which belong to this class + :return: None + """ + self.get_pci_dev_num() + self.get_pci_devs() + + @staticmethod + def check_item(): + """ Check all items in this class + :return: None + """ + scenario_cfg_lib.pci_dev_num_check("pci_dev_num") + scenario_cfg_lib.pci_devs_check("pci_devs") + + +class EpcSection: + base = {} + size = {} + + def __init__(self, scenario_info): + self.scenario_info = scenario_info + + def get_info(self): + self.base = scenario_cfg_lib.get_epc_base(self.scenario_info) + self.size = scenario_cfg_lib.get_epc_size(self.scenario_info) + + +class VmInfo: + """ This is Abstract of class of VM setting """ + name = [] + load_order = [] + uuid = [] + clos_set = [] + guest_flag_idx = [] + cpus_per_vm = [] + + def __init__(self, board_file, scenario_file): + self.board_info = board_file + self.scenario_info = scenario_file + scenario_cfg_lib.VM_COUNT = scenario_cfg_lib.get_vm_num(self.scenario_info) + + self.epc_section = EpcSection(self.scenario_info) + self.mem_info = MemInfo(self.scenario_info) + self.os_cfg = CfgOsKern(self.scenario_info) + self.vuart = VuartInfo(self.scenario_info) + self.cfg_pci = CfgPci(self.scenario_info) + + def get_info(self): + """ + Get all items which belong to this class + :return: None + """ + self.name = scenario_cfg_lib.get_sub_tree_tag(self.scenario_info, "name") + self.load_order = scenario_cfg_lib.get_sub_tree_tag(self.scenario_info, "load_order") + self.uuid = scenario_cfg_lib.get_sub_tree_tag(self.scenario_info, "uuid") + self.guest_flag_idx = scenario_cfg_lib.get_sub_leaf_tag( + self.scenario_info, "guest_flags", "guest_flag") + self.cpus_per_vm = scenario_cfg_lib.get_sub_leaf_tag( + self.scenario_info, "pcpu_ids", "pcpu_id") + self.clos_set = scenario_cfg_lib.get_sub_tree_tag(self.scenario_info, "clos") + self.epc_section.get_info() + self.mem_info.get_info() + self.os_cfg.get_info() + self.vuart.get_info() + self.cfg_pci.get_info() + + def get_cpu_bitmap(self, index): + """ + :param index: index list in GUESF_FLAGS + :return: cpus per vm and their vm id + """ + return scenario_cfg_lib.cpus_assignment(self.cpus_per_vm, index) + + def check_item(self): + """ + Check all items in this class + :return: None + """ + scenario_cfg_lib.vm_name_check(self.name, "name") + scenario_cfg_lib.load_order_check(self.load_order, "load_order") + scenario_cfg_lib.uuid_format_check(self.uuid, "uuid") + scenario_cfg_lib.guest_flag_check(self.guest_flag_idx, "guest_flags", "guest_flag") + scenario_cfg_lib.cpus_per_vm_check("pcpu_id") + + self.mem_info.check_item() + self.os_cfg.check_item() + self.cfg_pci.check_item() diff --git a/misc/acrn-config/scenario_config/vm_configurations_c.py b/misc/acrn-config/scenario_config/vm_configurations_c.py new file mode 100644 index 000000000..10d78af3e --- /dev/null +++ b/misc/acrn-config/scenario_config/vm_configurations_c.py @@ -0,0 +1,608 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import sys +import scenario_cfg_lib +import common + +C_HEADER = scenario_cfg_lib.HEADER_LICENSE + r""" +#include +#include +#include +""" + + +def uuid2str(uuid): + """ + This is convert uuid format string to string format + :param uuid: uuid number generate by uuid + :return: string uuid + """ + str1 = "" + tmp_uuid = uuid.split('-') + tmp_uuid = str1.join(tmp_uuid) + return tmp_uuid + + +def uuid_output(uuid, uuid_string, config): + """ + This is generate uuid information + :param uuid: + :param uuid_string: + :param config: + :return: + """ + # UUID + print("\t\t.uuid = {{0x{0}U, 0x{1}U, 0x{2}U, 0x{3}U, 0x{4}U, 0x{5}U, 0x{6}U, 0x{7}U,\t\\". + format(uuid[0:2], uuid[2:4], uuid[4:6], uuid[6:8], + uuid[8:10], uuid[10:12], uuid[12:14], uuid[14:16]), file=config) + print("\t\t\t 0x{0}U, 0x{1}U, 0x{2}U, 0x{3}U, 0x{4}U, 0x{5}U, 0x{6}U, 0x{7}U}},". + format(uuid[16:18], uuid[18:20], uuid[20:22], uuid[22:24], + uuid[24:26], uuid[26:28], uuid[28:30], uuid[30:32]), file=config) + print("\t\t\t/* {0} */".format(uuid_string), file=config) + + +def vuart0_output(i, vm_type, vm_info, config): + """ + This is generate vuart 0 setting + :param i: vm id number + :param vm_type: vm load order type + :param vm_info: it is the class which contain all user setting information + :param config: it is the pointer which file write to + :return: None + """ + # SOS_VM vuart[0] + print("\t\t.vuart[0] = {", file=config) + print("\t\t\t.type = {0},".format(vm_info.vuart.v0_vuart[i]['type']), file=config) + if vm_type == "SOS_VM": + print("\t\t\t.addr.port_base = SOS_COM1_BASE,", file=config) + print("\t\t\t.irq = SOS_COM1_IRQ,", file=config) + elif vm_type == "PRE_LAUNCHED_VM": + print("\t\t\t.addr.port_base = COM1_BASE,", file=config) + print("\t\t\t.irq = COM1_IRQ,", file=config) + elif vm_type == "POST_LAUNCHED_VM": + print("\t\t\t.addr.port_base = {0},".format( + vm_info.vuart.v0_vuart[i]['base']), file=config) + if vm_info.vuart.v0_vuart[i]['base'] != "INVALID_COM_BASE": + print("\t\t\t.irq = {0},".format( + vm_info.vuart.v0_vuart[i]['irq']), file=config) + print("\t\t},", file=config) + + +def vuart1_output(i, vm_type, vuart1_vmid_dic, vm_info, config): + """ + This is generate vuart 1 setting + :param i: vm id number + :param vm_type: vm load order type + :param vuart1_vmid_dic: vuart1 and vm id mapping + :param vm_info: it is the class which contain all user setting information + :param config: it is the pointer which file write to + :return: None + """ + # vuart1: {vmid:target_vmid} + print("\t\t.vuart[1] = {", file=config) + print("\t\t\t.type = {0},".format(vm_info.vuart.v1_vuart[i]['type']), file=config) + if vm_type == "SOS_VM": + if vm_info.vuart.v1_vuart[i]['base'] != "INVALID_COM_BASE": + print("\t\t\t.addr.port_base = SOS_COM2_BASE,", file=config) + else: + print("\t\t\t.addr.port_base = INVALID_COM_BASE,", file=config) + else: + print("\t\t\t.addr.port_base = {0},".format( + vm_info.vuart.v1_vuart[i]['base']), file=config) + if vuart1_vmid_dic and i in vuart1_vmid_dic.keys(): + if vm_type == "SOS_VM": + if vm_info.vuart.v1_vuart[i]['base'] != "INVALID_COM_BASE": + print("\t\t\t.irq = SOS_COM2_IRQ,", file=config) + else: + if vm_info.vuart.v1_vuart[i]['base'] != "INVALID_COM_BASE": + print("\t\t\t.irq = COM2_IRQ,", file=config) + + if vm_info.vuart.v1_vuart[i]['base'] != "INVALID_COM_BASE": + print("\t\t\t.t_vuart.vm_id = {0}U,".format( + vm_info.vuart.v1_vuart[i]['target_vm_id']), file=config) + print("\t\t\t.t_vuart.vuart_id = {0}U,".format( + vm_info.vuart.v1_vuart[i]['target_uart_id']), file=config) + + +def vuart_output(i, vm_info, config): + """ + This is generate vuart setting + :param i: vm id number + :param vm_info: it is the class which contain all user setting information + :param config: it is the pointer which file write to + :return: None + """ + vuart1_vmid_dic = {} + vuart1_vmid_dic = scenario_cfg_lib.get_vuart1_vmid(vm_info.vuart.v1_vuart) + vm_type = scenario_cfg_lib.get_order_type_by_vmid(i) + + vuart0_output(i, vm_type, vm_info, config) + vuart1_output(i, vm_type, vuart1_vmid_dic, vm_info, config) + print("\t\t},", file=config) + + # pci_dev_num/pci_devs only for SOS_VM or logical_partition pre_launched_vm + if vm_type == "SOS_VM": + print("\t\t.pci_dev_num = {},".format(vm_info.cfg_pci.pci_dev_num[0]), file=config) + print("\t\t.pci_devs = {},".format(vm_info.cfg_pci.pci_devs[0]), file=config) + + (err_dic, scenario_name) = scenario_cfg_lib.get_scenario_name() + if err_dic: + return err_dic + + if scenario_name == "logical_partition": + print("\t\t.pci_dev_num = VM{}_CONFIG_PCI_DEV_NUM,".format(i), file=config) + print("\t\t.pci_devs = vm{}_pci_devs,".format(i), file=config) + print("\t},", file=config) + + return err_dic + + +def is_need_epc(epc_section, i, config): + if epc_section.base[i] == '0' and epc_section.size[i] == '0': + return + else: + print("\t\t.epc= {", file=config) + print('\t\t\t.base = "{0}",'.format(epc_section.base), file=config) + print('\t\t\t.size = {0},'.format(epc_section.size), file=config) + print("\t\t},", file=config) + +def get_guest_flag(flag_index): + """ + This is get flag index list + :param flag_index: + :return: flag index list in GUEST_FLAGS + """ + err_dic = {} + flag_str = '' + if not flag_index: + err_dic['guest flags'] = "No assign flag to the guest" + return (err_dic, flag_str) + + for i in range(len(flag_index)): + if i == 0: + if len(flag_index) == 1: + # get the guest flag 0UL + if flag_index[0] == 0: + return (err_dic, common.GUEST_FLAG[flag_index[0]]) + flag_str = "{0}".format(common.GUEST_FLAG[int(flag_index[0])]) + else: + flag_str = "({0}".format(common.GUEST_FLAG[int(flag_index[0])]) + + else: + # flag_index lenght already minus 1 + if i == len(flag_index) - 1: + flag_str = flag_str + " | {0})".format(common.GUEST_FLAG[int(flag_index[i])]) + else: + flag_str = flag_str + " | {0}".format(common.GUEST_FLAG[int(flag_index[i])]) + + return (err_dic, flag_str) + + +def gen_source_header(config): + """ + This is the common header for vm_configuration.c + :param config: it is the pointer which file write to + :return: None + """ + print("{0}".format(C_HEADER), file=config) + + +def gen_sdc_source(vm_info, config): + """ + Generate vm_configuration.c of sdc scenario + :param vm_info: it is the class which contain all user setting information + :param config: it is the pointer which file write to + :return: None + """ + uuid_0 = uuid2str(vm_info.uuid[0]) + uuid_1 = uuid2str(vm_info.uuid[1]) + uuid_2 = uuid2str(vm_info.uuid[2]) + + (err_dic, sos_guest_flags) = get_guest_flag(vm_info.guest_flag_idx[0]) + if err_dic: + return err_dic + + gen_source_header(config) + # VM0 + print("struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {", file=config) + print("\t{", file=config) + print("\t\t.load_order = {0},".format( + vm_info.load_order[0]), file=config) + print('\t\t.name = "{0}",'.format(vm_info.name[0]), file=config) + # UUID + uuid_output(uuid_0, vm_info.uuid[0], config) + print("", file=config) + print("\t\t/* Allow SOS to reboot the host since " + + "there is supposed to be the highest severity guest */", file=config) + print("\t\t.guest_flags = {0},".format(sos_guest_flags), file=config) + if not vm_info.clos_set[0].strip(): + print("\t\t.clos = {0}U,".format(0), file=config) + else: + print("\t\t.clos = {0}U,".format(vm_info.clos_set[0]), file=config) + print("\t\t.memory = {", file=config) + print("\t\t\t.start_hpa = {}UL,".format(vm_info.mem_info.mem_start_hpa[0]), file=config) + print("\t\t\t.size = {0},".format("CONFIG_SOS_RAM_SIZE"), file=config) + print("\t\t},", file=config) + print("\t\t.os_config = {", file=config) + print('\t\t\t.name = "{0}",'.format(vm_info.os_cfg.kern_name[0]), file=config) + print('\t\t\t.kernel_type = {0},'.format(vm_info.os_cfg.kern_type[0]), file=config) + print('\t\t\t.kernel_mod_tag = "{0}",'.format( + vm_info.os_cfg.kern_mod[0]), file=config) + print('\t\t\t.bootargs = {0},'.format(vm_info.os_cfg.kern_args[0]), file=config) + print("\t\t},", file=config) + # VUART + err_dic = vuart_output(0, vm_info, config) + if err_dic: + return err_dic + # VM1 + print("\t{", file=config) + print("\t\t.load_order = {0},".format(vm_info.load_order[1]), file=config) + # UUID + uuid_output(uuid_1, vm_info.uuid[1], config) + is_need_epc(vm_info.epc_section, 0, config) + # VUART + err_dic = vuart_output(1, vm_info, config) + if err_dic: + return err_dic + # VM2 + print("#if CONFIG_MAX_KATA_VM_NUM > 0", file=config) + print("\t{", file=config) + print("\t\t.load_order = POST_LAUNCHED_VM,", file=config) + uuid_output(uuid_2, vm_info.uuid[2], config) + is_need_epc(vm_info.epc_section, 1, config) + print("\t\t.vuart[0] = {", file=config) + print("\t\t\t.type = VUART_LEGACY_PIO,", file=config) + print("\t\t\t.addr.port_base = INVALID_COM_BASE,", file=config) + print("\t\t},", file=config) + print("\t\t.vuart[1] = {", file=config) + print("\t\t\t.type = VUART_LEGACY_PIO,", file=config) + print("\t\t\t.addr.port_base = INVALID_COM_BASE,", file=config) + print("\t\t}", file=config) + print("\t},", file=config) + print("#endif", file=config) + print("};", file=config) + + return err_dic + + +def gen_sdc2_source(vm_info, config): + """ + Generate vm_configuration.c of sdc2 scenario + :param vm_info: it is the class which contain all user setting information + :param config: it is the pointer which file write to + :return: None + """ + uuid_0 = uuid2str(vm_info.uuid[0]) + uuid_1 = uuid2str(vm_info.uuid[1]) + uuid_2 = uuid2str(vm_info.uuid[2]) + uuid_3 = uuid2str(vm_info.uuid[3]) + + (err_dic, sos_guest_flags) = get_guest_flag(vm_info.guest_flag_idx[0]) + if err_dic: + return err_dic + + gen_source_header(config) + + # VM0 + print("struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {", file=config) + print("\t{", file=config) + print("\t\t.load_order = {0},".format( + vm_info.load_order[0]), file=config) + print('\t\t.name = "{0}",'.format(vm_info.name[0]), file=config) + # UUID + uuid_output(uuid_0, vm_info.uuid[0], config) + print("", file=config) + print("\t\t/* Allow SOS to reboot the host since " + + "there is supposed to be the highest severity guest */", file=config) + print("\t\t.guest_flags = {0},".format(sos_guest_flags), file=config) + if not vm_info.clos_set[0].strip(): + print("\t\t.clos = {0}U,".format(0), file=config) + else: + print("\t\t.clos = {0}U,".format(vm_info.clos_set[0]), file=config) + print("\t\t.memory = {", file=config) + print("\t\t\t.start_hpa = {}UL,".format(vm_info.mem_info.mem_start_hpa[0]), file=config) + print("\t\t\t.size = {0},".format("CONFIG_SOS_RAM_SIZE"), file=config) + print("\t\t},", file=config) + print("\t\t.os_config = {", file=config) + print('\t\t\t.name = "{0}",'.format(vm_info.os_cfg.kern_name[0]), file=config) + print('\t\t\t.kernel_type = {0},'.format(vm_info.os_cfg.kern_type[0]), file=config) + print('\t\t\t.kernel_mod_tag = "{0}",'.format( + vm_info.os_cfg.kern_mod[0]), file=config) + print('\t\t\t.bootargs = {0},'.format(vm_info.os_cfg.kern_args[0]), file=config) + print("\t\t},", file=config) + # VUART + err_dic = vuart_output(0, vm_info, config) + if err_dic: + return err_dic + + # VM1 + print("\t{", file=config) + print("\t\t.load_order = {0},".format(vm_info.load_order[1]), file=config) + # UUID + uuid_output(uuid_1, vm_info.uuid[1], config) + is_need_epc(vm_info.epc_section, 0, config) + # VUART + err_dic = vuart_output(1, vm_info, config) + if err_dic: + return err_dic + + # VM2 + print("\t{", file=config) + print("\t\t.load_order = {0},".format(vm_info.load_order[1]), file=config) + # UUID + uuid_output(uuid_2, vm_info.uuid[2], config) + is_need_epc(vm_info.epc_section, 1, config) + # VUART + err_dic = vuart_output(1, vm_info, config) + if err_dic: + return err_dic + print("", file=config) + + # VM3 + print("\t{", file=config) + print("\t\t.load_order = POST_LAUNCHED_VM,", file=config) + uuid_output(uuid_3, vm_info.uuid[3], config) + is_need_epc(vm_info.epc_section, 2, config) + print("\t\t.vuart[0] = {", file=config) + print("\t\t\t.type = VUART_LEGACY_PIO,", file=config) + print("\t\t\t.addr.port_base = INVALID_COM_BASE,", file=config) + print("\t\t},", file=config) + print("\t\t.vuart[1] = {", file=config) + print("\t\t\t.type = VUART_LEGACY_PIO,", file=config) + print("\t\t\t.addr.port_base = INVALID_COM_BASE,", file=config) + print("\t\t}", file=config) + print("\t},", file=config) + print("};", file=config) + + return err_dic + + +def split_cmdline(cmd_str, config): + + cmd_list = [i for i in cmd_str.split() if i != ''] + + if cmd_list: + cmd_len = len(cmd_list) + i = 0 + for cmd_arg in cmd_list: + if not cmd_arg.strip(): + continue + + if i == 0: + print('\\\n\t\t\t\t"', end="", file=config) + + if i % 4 == 0 and i != 0: + print("\\\n\t\t\t\t", end="", file=config) + + print('{} '.format(cmd_arg), end="", file=config) + i += 1 + if i == cmd_len: + print('"', file=config) + + + +def gen_logical_partition_source(vm_info, config): + """ + Generate vm_configuration.c of logical_partition scenario + :param vm_info: it is the class which contain all user setting information + :param config: it is the pointer which file write to + :return: None + """ + err_dic = {} + gen_source_header(config) + for i in range(scenario_cfg_lib.VM_COUNT): + print("extern struct acrn_vm_pci_dev_config " + + "vm{0}_pci_devs[VM{1}_CONFIG_PCI_DEV_NUM];".format(i, i), file=config) + print("", file=config) + print("struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {", file=config) + + for i in range(scenario_cfg_lib.VM_COUNT): + uuid = uuid2str(vm_info.uuid[i]) + print("\t{{\t/* VM{0} */".format(i), file=config) + print("\t\t.load_order = {0},".format(vm_info.load_order[i]), file=config) + print('\t\t.name = "{0}",'.format(vm_info.name[i]), file=config) + # UUID + uuid_output(uuid, vm_info.uuid[i], config) + print("\t\t.pcpu_bitmap = VM{0}_CONFIG_PCPU_BITMAP,".format(i), file=config) + # skip the vm0 for guest flag + + # guest flags + (err_dic, guest_flags) = get_guest_flag(vm_info.guest_flag_idx[i]) + if err_dic: + return err_dic + + print("\t\t.guest_flags = {0},".format(guest_flags), file=config) + + if not vm_info.clos_set[i].strip(): + print("\t\t.clos = {0}U,".format(0), file=config) + else: + print("\t\t.clos = {0}U,".format(vm_info.clos_set[i]), file=config) + print("\t\t.memory = {", file=config) + print("\t\t\t.start_hpa = VM{0}_CONFIG_MEM_START_HPA,".format(i), file=config) + print("\t\t\t.size = VM{0}_CONFIG_MEM_SIZE,".format(i), file=config) + print("\t\t},", file=config) + is_need_epc(vm_info.epc_section, i, config) + print("\t\t.os_config = {", file=config) + print('\t\t\t.name = "{0}",'.format(vm_info.os_cfg.kern_name[i]), file=config) + print("\t\t\t.kernel_type = {0},".format( + vm_info.os_cfg.kern_type[i]), file=config) + print('\t\t\t.kernel_mod_tag = "{0}",'.format( + vm_info.os_cfg.kern_mod[i]), file=config) + print("\t\t\t.bootargs = VM{0}_CONFIG_OS_BOOTARG_CONSOLE\t\\".format(i), file=config) + print("\t\t\t\tVM{0}_CONFIG_OS_BOOTARG_MAXCPUS\t\t\\".format(i), file=config) + print("\t\t\t\tVM{0}_CONFIG_OS_BOOTARG_ROOT\t\t\\".format(i), file=config) + #print("\t\t\t\t{0}".format(vm_info.os_cfg.kern_args_append[i].strip()), file=config) + split_cmdline(vm_info.os_cfg.kern_args[i].strip(), config) + print("\t\t},", file=config) + # VUART + err_dic = vuart_output(i, vm_info, config) + if err_dic: + return err_dic + + print("};", file=config) + + return err_dic + + +def gen_industry_source(vm_info, config): + """ + Generate vm_configuration.c of industry scenario + :param vm_info: it is the class which contain all user setting information + :param config: it is the pointer which file write to + :return: None + """ + err_dic = {} + gen_source_header(config) + print("struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {", file=config) + for i in range(scenario_cfg_lib.VM_COUNT): + uuid = uuid2str(vm_info.uuid[i]) + print("\t{", file=config) + print("\t\t.load_order = {0},".format(vm_info.load_order[i]), file=config) + if i == 0: + print('\t\t.name = "{0}",'.format(vm_info.name[i]), file=config) + + # UUID + uuid_output(uuid, vm_info.uuid[i], config) + if i != 0: + is_need_epc(vm_info.epc_section, i - 1, config) + + if i == 0: + (err_dic, sos_guest_flags) = get_guest_flag(vm_info.guest_flag_idx[i]) + if err_dic: + return err_dic + print("\t\t") + print("\t\t.guest_flags = {0},".format(sos_guest_flags), file=config) + if not vm_info.clos_set[i].strip(): + print("\t\t.clos = {0}U,".format(0), file=config) + else: + print("\t\t.clos = {0}U,".format(vm_info.clos_set[i]), file=config) + print("\t\t.memory = {", file=config) + print("\t\t\t.start_hpa = 0UL,", file=config) + print("\t\t\t.size = CONFIG_SOS_RAM_SIZE,", file=config) + print("\t\t},", file=config) + print("\t\t.os_config = {", file=config) + print('\t\t\t.name = "{0}",'.format(vm_info.os_cfg.kern_name[i]), file=config) + print('\t\t\t.kernel_type = {0},'.format( + vm_info.os_cfg.kern_type[i]), file=config) + print('\t\t\t.kernel_mod_tag = "{0}",'.format( + vm_info.os_cfg.kern_mod[i]), file=config) + print("\t\t\t.bootargs = {0}".format( + vm_info.os_cfg.kern_args[i]), file=config) + print("\t\t},", file=config) + + if i == 2: + print("\t\t/* The hard RTVM must be launched as VM2 */", file=config) + (err_dic, vm_guest_flags) = get_guest_flag(vm_info.guest_flag_idx[i]) + if err_dic: + return err_dic + print("\t\t.guest_flags = {0},".format(vm_guest_flags), file=config) + # VUART + err_dic = vuart_output(i, vm_info, config) + if err_dic: + return err_dic + + print("};", file=config) + + return err_dic + + +def gen_hybrid_source(vm_info, config): + """ + Generate vm_configuration.c of hybrid scenario + :param vm_info: it is the class which contain all user setting information + :param config: it is the pointer which file write to + :return: None + """ + err_dic = {} + (err_dic, post_vm_i) = scenario_cfg_lib.get_first_post_vm() + if err_dic: + return err_dic + + gen_source_header(config) + print("struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {", file=config) + + for i in range(scenario_cfg_lib.VM_COUNT): + uuid = uuid2str(vm_info.uuid[i]) + print("\t{{\t/* VM{0} */".format(i), file=config) + print("\t\t.load_order = {0},".format(vm_info.load_order[i]), file=config) + if i != 2: + print('\t\t.name = "{0}",'.format(vm_info.name[i]), file=config) + + # UUID + uuid_output(uuid, vm_info.uuid[i], config) + + if i != 2: + (err_dic, sos_guest_flags) = get_guest_flag(vm_info.guest_flag_idx[i]) + if err_dic: + return err_dic + print("\t\t.guest_flags = {0},".format(sos_guest_flags), file=config) + if i == 0: + print("\t\t.pcpu_bitmap = VM0_CONFIG_PCPU_BITMAP,", file=config) + if not vm_info.clos_set[i].strip(): + print("\t\t.clos = {0}U,".format(0), file=config) + else: + print("\t\t.clos = {0}U,".format(vm_info.clos_set[i]), file=config) + print("\t\t.memory = {", file=config) + if i == 0: + print("\t\t\t.start_hpa = VM0_CONFIG_MEM_START_HPA,", file=config) + print("\t\t\t.size = VM0_CONFIG_MEM_SIZE,", file=config) + elif i == 1: + print("\t\t\t.start_hpa = 0UL,", file=config) + print("\t\t\t.size = CONFIG_SOS_RAM_SIZE,", file=config) + print("\t\t},", file=config) + if i == 0: + is_need_epc(vm_info.epc_section, i, config) + elif i == scenario_cfg_lib.VM_COUNT: + is_need_epc(vm_info.epc_section, i - 1, config) + print("\t\t.os_config = {", file=config) + print('\t\t\t.name = "{0}",'.format(vm_info.os_cfg.kern_name[i]), file=config) + print('\t\t\t.kernel_type = {0},'.format( + vm_info.os_cfg.kern_type[i]), file=config) + print('\t\t\t.kernel_mod_tag = "{0}",'.format( + vm_info.os_cfg.kern_mod[i]), file=config) + + if i < post_vm_i: + if not vm_info.os_cfg.kern_args[i] or not vm_info.os_cfg.kern_args[i].strip(): + print('\t\t\t.bootargs = "",', file=config) + else: + print("\t\t\t.bootargs = {0},".format( + vm_info.os_cfg.kern_args[i]), file=config) + if i == 0: + print("\t\t\t.kernel_load_addr = {0},".format( + vm_info.os_cfg.kern_load_addr[i]), file=config) + print("\t\t\t.kernel_entry_addr = {0},".format( + vm_info.os_cfg.kern_entry_addr[i]), file=config) + + print("\t\t},", file=config) + + # VUART + err_dic = vuart_output(i, vm_info, config) + if err_dic: + return err_dic + print("};", file=config) + + return err_dic + + +def generate_file(scenario, vm_info, config): + """ + Start to generate vm_configurations.c + :param config: it is a file pointer of board information for writing to + """ + err_dic = {} + if scenario == 'sdc': + err_dic = gen_sdc_source(vm_info, config) + elif scenario == 'sdc2': + err_dic = gen_sdc2_source(vm_info, config) + elif scenario == 'logical_partition': + err_dic = gen_logical_partition_source(vm_info, config) + elif scenario == 'industry': + err_dic = gen_industry_source(vm_info, config) + else: + # scenario is 'hybrid' + err_dic = gen_hybrid_source(vm_info, config) + + return err_dic diff --git a/misc/acrn-config/scenario_config/vm_configurations_h.py b/misc/acrn-config/scenario_config/vm_configurations_h.py new file mode 100644 index 000000000..bfefe5623 --- /dev/null +++ b/misc/acrn-config/scenario_config/vm_configurations_h.py @@ -0,0 +1,272 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import scenario_cfg_lib + +VM_HEADER_DEFINE = scenario_cfg_lib.HEADER_LICENSE + r""" +#ifndef VM_CONFIGURATIONS_H +#define VM_CONFIGURATIONS_H +""" +VM_END_DEFINE = r"""#endif /* VM_CONFIGURATIONS_H */""" + + +def gen_common_header(config): + """ + This is common header for vm_configuration.h + :param config: it is the pointer which file write to + :return: None + """ + print("{0}".format(VM_HEADER_DEFINE), file=config) + + +def gen_sdc_header(config): + """ + Generate vm_configuration.h of sdc scenario + :param config: it is the pointer which file write to + :return: None + """ + gen_common_header(config) + print("#include \n", file=config) + print("#define CONFIG_MAX_VM_NUM\t\t({0}U + CONFIG_MAX_KATA_VM_NUM)".format( + scenario_cfg_lib.VM_COUNT - 1), file=config) + print("", file=config) + print("/* Bits mask of guest flags that can be programmed by device model." + + " Other bits are set by hypervisor only */", file=config) + print("#define DM_OWNED_GUEST_FLAG_MASK\t" + + "(GUEST_FLAG_SECURE_WORLD_ENABLED | GUEST_FLAG_LAPIC_PASSTHROUGH | \\\n" + + "\t\t\t\t\t\tGUEST_FLAG_RT | GUEST_FLAG_IO_COMPLETION_POLLING)", file=config) + + print("", file=config) + print("#define SOS_VM_BOOTARGS\t\t\tSOS_ROOTFS\t\\", file=config) + print('\t\t\t\t\t"rw rootwait "\t\\', file=config) + print('\t\t\t\t\t"console=tty0 " \\', file=config) + print("\t\t\t\t\tSOS_CONSOLE\t\\", file=config) + print('\t\t\t\t\t"consoleblank=0 "\t\\', file=config) + print('\t\t\t\t\t"no_timer_check "\t\\', file=config) + print('\t\t\t\t\t"quiet loglevel=3 "\t\\', file=config) + print('\t\t\t\t\t"i915.nuclear_pageflip=1 " \\', file=config) + print('\t\t\t\t\t"i915.avail_planes_per_pipe=0x01010F "\t\\', file=config) + print('\t\t\t\t\t"i915.domain_plane_owners=0x011111110000 " \\', file=config) + print('\t\t\t\t\t"i915.enable_gvt=1 "\t\\', file=config) + print("\t\t\t\t\tSOS_BOOTARGS_DIFF", file=config) + + print("", file=config) + print("{0}".format(VM_END_DEFINE), file=config) + + +def gen_sdc2_header(config): + """ + Generate vm_configuration.h of sdc2 scenario + :param config: it is the pointer which file write to + :return: None + """ + gen_common_header(config) + print("#include \n", file=config) + print("#define CONFIG_MAX_VM_NUM\t\t({0}U + CONFIG_MAX_KATA_VM_NUM)".format( + scenario_cfg_lib.VM_COUNT), file=config) + print("", file=config) + print("/* Bits mask of guest flags that can be programmed by device model." + + " Other bits are set by hypervisor only */", file=config) + print("#define DM_OWNED_GUEST_FLAG_MASK\t" + + "(GUEST_FLAG_SECURE_WORLD_ENABLED | GUEST_FLAG_LAPIC_PASSTHROUGH | \\\n" + + "\t\t\t\t\t\tGUEST_FLAG_RT | GUEST_FLAG_IO_COMPLETION_POLLING)", file=config) + + print("", file=config) + print("#define SOS_VM_BOOTARGS\t\t\tSOS_ROOTFS\t\\", file=config) + print('\t\t\t\t\t"rw rootwait "\t\\', file=config) + print('\t\t\t\t\t"console=tty0 " \\', file=config) + print("\t\t\t\t\tSOS_CONSOLE\t\\", file=config) + print('\t\t\t\t\t"consoleblank=0 "\t\\', file=config) + print('\t\t\t\t\t"no_timer_check "\t\\', file=config) + print('\t\t\t\t\t"quiet loglevel=3 "\t\\', file=config) + print('\t\t\t\t\t"i915.nuclear_pageflip=1 " \\', file=config) + print('\t\t\t\t\t"i915.avail_planes_per_pipe=0x01010F "\t\\', file=config) + print('\t\t\t\t\t"i915.domain_plane_owners=0x011111110000 " \\', file=config) + print('\t\t\t\t\t"i915.enable_gvt=1 "\t\\', file=config) + print("\t\t\t\t\tSOS_BOOTARGS_DIFF", file=config) + + print("", file=config) + print("{0}".format(VM_END_DEFINE), file=config) + + +def logic_max_vm_num(config): + """ + This is logical max vm number comment + :param config: it is the pointer which file write to + :return: None + """ + print("", file=config) + print("#define CONFIG_MAX_VM_NUM\t{0}U".format(scenario_cfg_lib.VM_COUNT), file=config) + print("", file=config) + print("/* The VM CONFIGs like:", file=config) + print(" *\tVMX_CONFIG_PCPU_BITMAP", file=config) + print(" *\tVMX_CONFIG_MEM_START_HPA", file=config) + print(" *\tVMX_CONFIG_MEM_SIZE", file=config) + print(" *\tVMX_CONFIG_OS_BOOTARG_ROOT", file=config) + print(" *\tVMX_CONFIG_OS_BOOTARG_MAX_CPUS", file=config) + print(" *\tVMX_CONFIG_OS_BOOTARG_CONSOLE", file=config) + print(" * might be different on your board, please modify them per your needs.", file=config) + print(" */", file=config) + print("", file=config) + + +def gen_logic_header(vm_info, config): + """ + Generate vm_configuration.h of logical_partition scenario + :param config: it is the pointer which file write to + :return: None + """ + scenario_cfg_lib.vms_count = scenario_cfg_lib.VM_COUNT + gen_common_header(config) + # map all the needed pci sub class + print("#include ", file=config) + print("#include ", file=config) + print("", file=config) + print("/* Bits mask of guest flags that can be programmed by device model." + + " Other bits are set by hypervisor only */", file=config) + print("#define DM_OWNED_GUEST_FLAG_MASK\t0UL", file=config) + + logic_max_vm_num(config) + + for i in range(scenario_cfg_lib.VM_COUNT): + + cpu_bits = vm_info.get_cpu_bitmap(i) + print("#define VM{0}_CONFIG_PCPU_BITMAP\t\t\t{1}".format( + i, cpu_bits['cpu_map']), file=config) + print("#define VM{0}_CONFIG_MEM_START_HPA\t\t{1}UL".format( + i, vm_info.mem_info.mem_start_hpa[i]), file=config) + print("#define VM{0}_CONFIG_MEM_SIZE\t\t\t{1}UL".format( + i, vm_info.mem_info.mem_size[0]), file=config) + print('#define VM{0}_CONFIG_OS_BOOTARG_ROOT\t\t"root={1} "'.format( + i, vm_info.os_cfg.kern_root_dev[i]), file=config) + print('#define VM{0}_CONFIG_OS_BOOTARG_MAXCPUS\t\t"maxcpus={1} "'.format( + i, cpu_bits['cpu_num']), file=config) + print('#define VM{0}_CONFIG_OS_BOOTARG_CONSOLE\t\t"console={1} "'.format( + i, vm_info.os_cfg.kern_console[i]), file=config) + print("", file=config) + + print('/* VM pass-through devices assign policy:', file=config) + print(' * VM0: one Mass Storage controller, one Network controller;', file=config) + print(' * VM1: one Mass Storage controller, one Network controller' + + '(if a secondary Network controller class device exist);', file=config) + print(' */', file=config) + print('#define VM0_STORAGE_CONTROLLER\t\t\tSATA_CONTROLLER_0', file=config) + print('#define VM0_NETWORK_CONTROLLER\t\t\tETHERNET_CONTROLLER_0', file=config) + print('#define VM0_CONFIG_PCI_DEV_NUM\t\t\t3U', file=config) + print('', file=config) + print('#define VM1_STORAGE_CONTROLLER\t\t\tUSB_CONTROLLER_0', file=config) + print('#if defined(ETHERNET_CONTROLLER_1)', file=config) + print('/* if a secondary Ethernet controller subclass exist, assign to VM1 */', file=config) + print('#define VM1_NETWORK_CONTROLLER\t\t\tETHERNET_CONTROLLER_1', file=config) + print('#elif defined(NETWORK_CONTROLLER_0)', file=config) + print('/* if a Network controller subclass exist' + + '(usually it is a wireless network card), assign to VM1 */', file=config) + print('#define VM1_NETWORK_CONTROLLER\t\t\tNETWORK_CONTROLLER_0', file=config) + print('#endif', file=config) + print('', file=config) + print('#if defined(VM1_NETWORK_CONTROLLER)', file=config) + print('#define VM1_CONFIG_PCI_DEV_NUM\t\t\t3U', file=config) + print('#else', file=config) + print('/* no network controller could be assigned to VM1 */', file=config) + print('#define VM1_CONFIG_PCI_DEV_NUM\t\t\t2U', file=config) + print('#endif', file=config) + print("", file=config) + print("{0}".format(VM_END_DEFINE), file=config) + + +def gen_industry_header(config): + """ + Generate vm_configuration.h of industry scenario + :param config: it is the pointer which file write to + :return: None + """ + gen_common_header(config) + print("#include ", file=config) + print("", file=config) + print("#define CONFIG_MAX_VM_NUM\t\t({0}U + CONFIG_MAX_KATA_VM_NUM)".format( + scenario_cfg_lib.VM_COUNT), file=config) + print("", file=config) + print("/* Bits mask of guest flags that can be programmed by device model." + + " Other bits are set by hypervisor only */", file=config) + print("#define DM_OWNED_GUEST_FLAG_MASK\t(GUEST_FLAG_SECURE_WORLD_ENABLED | " + + "GUEST_FLAG_LAPIC_PASSTHROUGH | \\", file=config) + print("\t\t\t\t\t\tGUEST_FLAG_RT | GUEST_FLAG_IO_COMPLETION_POLLING)", file=config) + print("", file=config) + print("#define SOS_VM_BOOTARGS\t\t\tSOS_ROOTFS\t\\", file=config) + print('\t\t\t\t\t"rw rootwait "\t\\', file=config) + print('\t\t\t\t\t"console=tty0 "\t\\', file=config) + print("\t\t\t\t\tSOS_CONSOLE\t\\", file=config) + print('\t\t\t\t\t"consoleblank=0\t"\t\\', file=config) + print('\t\t\t\t\t"no_timer_check "\t\\', file=config) + print('\t\t\t\t\t"quiet loglevel=3 "\t\\', file=config) + print('\t\t\t\t\t"i915.nuclear_pageflip=1 " \\', file=config) + print('\t\t\t\t\t"i915.avail_planes_per_pipe=0x01010F "\t\\', file=config) + print('\t\t\t\t\t"i915.domain_plane_owners=0x011111110000 " \\', file=config) + print('\t\t\t\t\t"i915.enable_gvt=1 "\t\\', file=config) + print("\t\t\t\t\tSOS_BOOTARGS_DIFF", file=config) + print("", file=config) + print("{0}".format(VM_END_DEFINE), file=config) + + +def gen_hybrid_header(vm_info, config): + """ + Generate vm_configuration.h of hybrid scenario + :param vm_info: it is the class which contain all user setting information + :param config: it is the pointer which file write to + :return: None + """ + gen_common_header(config) + print("#include \n", file=config) + print("/* Bits mask of guest flags that can be programmed by device model." + + " Other bits are set by hypervisor only */", file=config) + print("#define DM_OWNED_GUEST_FLAG_MASK\t" + + "(GUEST_FLAG_SECURE_WORLD_ENABLED | GUEST_FLAG_LAPIC_PASSTHROUGH | \\\n" + + "\t\t\t\t\t\tGUEST_FLAG_RT | GUEST_FLAG_IO_COMPLETION_POLLING)", file=config) + + cpu_bits = vm_info.get_cpu_bitmap(0) + print("", file=config) + print("#define CONFIG_MAX_VM_NUM\t\t({0}U + CONFIG_MAX_KATA_VM_NUM)".format( + scenario_cfg_lib.VM_COUNT), file=config) + print("", file=config) + print("#define VM0_CONFIG_PCPU_BITMAP\t\t{0}".format(cpu_bits['cpu_map']), file=config) + print("#define VM0_CONFIG_MEM_START_HPA\t{0}UL".format( + vm_info.mem_info.mem_start_hpa[0]), file=config) + print("#define VM0_CONFIG_MEM_SIZE\t\t{0}UL".format(vm_info.mem_info.mem_size[0]), file=config) + print("", file=config) + print("#define SOS_VM_BOOTARGS\t\t\tSOS_ROOTFS\t\\", file=config) + print('\t\t\t\t\t"rw rootwait "\t\\', file=config) + print('\t\t\t\t\t"console=tty0 " \\', file=config) + print("\t\t\t\t\tSOS_CONSOLE\t\\", file=config) + print('\t\t\t\t\t"consoleblank=0 "\t\\', file=config) + print('\t\t\t\t\t"no_timer_check "\t\\', file=config) + print('\t\t\t\t\t"quiet loglevel=3 "\t\\', file=config) + print('\t\t\t\t\t"i915.nuclear_pageflip=1 " \\', file=config) + print('\t\t\t\t\t"i915.avail_planes_per_pipe=0x01010F "\t\\', file=config) + print('\t\t\t\t\t"i915.domain_plane_owners=0x011111110000 " \\', file=config) + print('\t\t\t\t\t"i915.enable_gvt=1 "\t\\', file=config) + print("\t\t\t\t\tSOS_BOOTARGS_DIFF", file=config) + + print("", file=config) + print("{0}".format(VM_END_DEFINE), file=config) + + +def generate_file(scenario, vm_info, config): + """ + Start to generate vm_configurations.h + :param scenario: it is scenario name + :param vm_info: it is the class which contain all user setting information + :param config: it is a file pointer of board information for writing to + """ + if scenario == 'sdc': + gen_sdc_header(config) + elif scenario == 'sdc2': + gen_sdc2_header(config) + elif scenario == 'logical_partition': + gen_logic_header(vm_info, config) + elif scenario == 'industry': + gen_industry_header(config) + else: + # scenario is 'hybrid' + gen_hybrid_header(vm_info, config) diff --git a/misc/acrn-config/target/acpi.py b/misc/acrn-config/target/acpi.py index d6f4d69ee..2bffce669 100644 --- a/misc/acrn-config/target/acpi.py +++ b/misc/acrn-config/target/acpi.py @@ -305,7 +305,7 @@ def read_sx_locate(sx_name, f_node): def decode_sx_pkg(pkg_len, f_node): - """Parser and decode the sx pkg + """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 """ diff --git a/misc/acrn-config/target/board_parser.py b/misc/acrn-config/target/board_parser.py index e83e1236d..1b3802776 100755 --- a/misc/acrn-config/target/board_parser.py +++ b/misc/acrn-config/target/board_parser.py @@ -19,7 +19,7 @@ OUTPUT = "./out/" PY_CACHE = "__pycache__" # This file store information which query from hw board -BIN_LIST = ['cpuid', 'rdmsr', 'lspci', ' dmidecode', 'blkid'] +BIN_LIST = ['cpuid', 'rdmsr', 'lspci', ' dmidecode', 'blkid', 'stty'] PCI_IDS = ["/usr/share/hwdata/pci.ids", "/usr/share/misc/pci.ids"] CPU_VENDOR = "GenuineIntel" @@ -35,7 +35,7 @@ def check_permission(): def native_check(): """Check if this is natvie os""" cmd = "cpuid -r -l 0x01" - res = parser_lib.cmd_excute(cmd) + res = parser_lib.cmd_execute(cmd) while True: line = parser_lib.decode_stdout(res) diff --git a/misc/acrn-config/target/clos.py b/misc/acrn-config/target/clos.py index 4fccfb35a..3ab34e6c0 100644 --- a/misc/acrn-config/target/clos.py +++ b/misc/acrn-config/target/clos.py @@ -18,7 +18,7 @@ def dump_cpuid_reg(cmd, reg): """ cache_t = '' - res = parser_lib.cmd_excute(cmd) + res = parser_lib.cmd_execute(cmd) if reg == "ebx": idx = 3 diff --git a/misc/acrn-config/target/misc.py b/misc/acrn-config/target/misc.py index f5c5161e4..908b0bf7c 100644 --- a/misc/acrn-config/target/misc.py +++ b/misc/acrn-config/target/misc.py @@ -4,16 +4,148 @@ # import parser_lib +import subprocess -IO_MEM_PATH = '/proc/iomem' +MEM_PATH = ['/proc/iomem', '/proc/meminfo'] +TTY_PATH = '/sys/class/tty/' +SYS_IRQ_PATH = '/proc/interrupts' +CPU_INFO_PATH = '/proc/cpuinfo' + +ttys_type = { + '0': 'PORT', + '3': 'MMIO', +} -def get_system_ram(config): +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 irq2bdf(irq_n): + cmd = 'lspci -vv' + res = parser_lib.cmd_execute(cmd) + bdf = '' + irq = 0 + while True: + line = res.stdout.readline().decode('ascii') + if not line: + break + + if ':' not in line: + continue + + if '.' in line.split()[0]: + bdf = line.split()[0] + + if "Interrupt:" in line.strip(): + irq = line.split()[-1] + if irq == irq_n and bdf: + 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) + + if ttys_type[serial_type] == 'PORT': + base_path = '{}{}/port'.format(TTY_PATH, ttys_n) + elif ttys_type[serial_type] == 'MMIO': + base_path = '{}{}/iomem_base'.format(TTY_PATH, ttys_n) + + base = read_ttys_node(base_path) + + ttys_irqs.append(irq) + bdf = irq2bdf(irq) + print("\tBDF:({}) seri:{} base:{} irq:{}".format(bdf, 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(IO_MEM_PATH, 'rt') as mem_info: + with open(MEM_PATH[0], 'rt') as mem_info: while True: line = mem_info.readline().strip() @@ -28,7 +160,7 @@ def get_system_ram(config): print("", file=config) -def get_root_dev(config): +def dump_root_dev(config): """This will get available root device :param config: file pointer that opened for writing board config information """ @@ -38,13 +170,72 @@ def get_root_dev(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) + processor_id_list = [] + with open(CPU_INFO_PATH, 'rt') as cpu_info: + while True: + line = cpu_info.readline() + + if not line: + break + + if ':' in line and line.split(':')[0].strip() == "processor": + processor_id = line.split(':')[1].strip() + processor_id_list.append(processor_id) + + processor_len = len(processor_id_list) + for processor_id in processor_id_list: + if int(processor_id) == 0: + if processor_len == 1: + print("\t{},".format(processor_id.strip()), file=config) + else: + print("\t{},".format(processor_id.strip()), end="", file=config) + else: + if processor_len == int(processor_id) + 1: + print(" {}".format(processor_id.strip()), file=config) + else: + print(" {},".format(processor_id.strip()), end="", file=config) + + print("\t", file=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: - get_system_ram(config) + dump_system_ram(config) - get_root_dev(config) + dump_root_dev(config) + dump_ttys(config) + + dump_free_irqs(config) + + dump_total_mem(config) + + dump_cpu_core_info(config) diff --git a/misc/acrn-config/target/parser_lib.py b/misc/acrn-config/target/parser_lib.py index f81fe2fc6..d0dce2ac9 100644 --- a/misc/acrn-config/target/parser_lib.py +++ b/misc/acrn-config/target/parser_lib.py @@ -73,7 +73,7 @@ def handle_pci_dev(line): return False -def cmd_excute(cmd): +def cmd_execute(cmd): """Excute cmd and retrun raw information :param cmd: command what can be executed in shell """ @@ -107,7 +107,7 @@ def dump_execute(cmd, desc, config): print("\t\t".format(desc), file=config) return - res = cmd_excute(cmd) + res = cmd_execute(cmd) while True: line = res.stdout.readline().decode('ascii')