1# Copyright (C) 2019-2022 Intel Corporation. 2# 3# SPDX-License-Identifier: BSD-3-Clause 4# 5 6import os 7import sys 8import copy 9from defusedxml.lxml import parse, tostring 10sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library')) 11sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'hv_config')) 12sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'acpi_gen')) 13from scenario_item import HwInfo, VmInfo 14import board_cfg_lib 15import scenario_cfg_lib 16import acrn_config_utilities 17import hv_cfg_lib 18import board_defconfig 19from hv_item import HvInfo 20import asl_gen 21 22try: 23 import xmlschema 24except ImportError: 25 pass 26 27ACRN_PATH = acrn_config_utilities.SOURCE_ROOT_DIR 28ACRN_CONFIG_DEF = ACRN_PATH + 'misc/config_tools/data/' 29GEN_FILE = ["vm_configurations.h", "vm_configurations.c", "pci_dev.c", ".config", "ivshmem_cfg.h", "pt_intx.c"] 30 31 32def get_scenario_item_values(board_info, scenario_info): 33 """ 34 Glue code to provide user selectable options to config UI tool. 35 Return a dictionary of key-value pairs containing features and corresponding lists of 36 user selectable values to the config UI tool. 37 :param board_info: file that contains board information 38 """ 39 hv_cfg_lib.ERR_LIST = {} 40 scenario_item_values = {} 41 hw_info = HwInfo(board_info) 42 hv_info = HvInfo(scenario_info) 43 44 # get vm count 45 acrn_config_utilities.BOARD_INFO_FILE = board_info 46 acrn_config_utilities.SCENARIO_INFO_FILE = scenario_info 47 acrn_config_utilities.get_vm_num(scenario_info) 48 acrn_config_utilities.get_load_order() 49 50 # per scenario 51 guest_flags = copy.deepcopy(acrn_config_utilities.GUEST_FLAG) 52 guest_flags.remove('0UL') 53 scenario_item_values['vm,vm_type'] = scenario_cfg_lib.LOAD_VM_TYPE 54 scenario_item_values["vm,cpu_affinity"] = hw_info.get_processor_val() 55 scenario_item_values["vm,guest_flags"] = guest_flags 56 scenario_item_values["vm,clos,vcpu_clos"] = hw_info.get_clos_val() 57 scenario_item_values["vm,pci_devs"] = scenario_cfg_lib.avl_pci_devs() 58 scenario_item_values["vm,os_config,kern_type"] = scenario_cfg_lib.KERN_TYPE_LIST 59 scenario_item_values["vm,mmio_resources,p2sb"] = hv_cfg_lib.N_Y 60 scenario_item_values["vm,mmio_resources,TPM2"] = hv_cfg_lib.N_Y 61 scenario_item_values.update(scenario_cfg_lib.avl_vuart_ui_select(scenario_info)) 62 scenario_item_values["vm,console_vuart,base"] = ['INVALID_PCI_BASE', 'PCI_VUART'] 63 scenario_item_values["vm,communication_vuart,base"] = ['INVALID_PCI_BASE', 'PCI_VUART'] 64 65 # board 66 67 scenario_item_values["hv,DEBUG_OPTIONS,RELEASE"] = hv_cfg_lib.N_Y 68 scenario_item_values["hv,DEBUG_OPTIONS,NPK_LOGLEVEL"] = hv_cfg_lib.get_select_range("DEBUG_OPTIONS", "LOG_LEVEL") 69 scenario_item_values["hv,DEBUG_OPTIONS,MEM_LOGLEVEL"] = hv_cfg_lib.get_select_range("DEBUG_OPTIONS", "LOG_LEVEL") 70 scenario_item_values["hv,DEBUG_OPTIONS,CONSOLE_LOGLEVEL"] = hv_cfg_lib.get_select_range("DEBUG_OPTIONS", "LOG_LEVEL") 71 scenario_item_values["hv,DEBUG_OPTIONS,SERIAL_CONSOLE"] = board_cfg_lib.get_native_ttys_info(board_info) 72 73 scenario_item_values["hv,CAPACITIES,MAX_IOAPIC_NUM"] = hv_cfg_lib.get_select_range("CAPACITIES", "IOAPIC_NUM") 74 75 scenario_item_values["hv,FEATURES,MULTIBOOT2_ENABLED"] = hv_cfg_lib.N_Y 76 scenario_item_values["hv,FEATURES,RDT,RDT_ENABLED"] = board_cfg_lib.get_rdt_select_opt() 77 scenario_item_values["hv,FEATURES,RDT,CDP_ENABLED"] = board_cfg_lib.get_rdt_select_opt() 78 scenario_item_values["hv,FEATURES,SCHEDULER"] = hv_cfg_lib.SCHEDULER_TYPE 79 scenario_item_values["hv,FEATURES,RELOC_ENABLED"] = hv_cfg_lib.N_Y 80 scenario_item_values["hv,FEATURES,HYPERV_ENABLED"] = hv_cfg_lib.N_Y 81 scenario_item_values["hv,FEATURES,ACPI_PARSE_ENABLED"] = hv_cfg_lib.N_Y 82 scenario_item_values["hv,FEATURES,L1D_VMENTRY_ENABLED"] = hv_cfg_lib.N_Y 83 scenario_item_values["hv,FEATURES,MCE_ON_PSC_DISABLED"] = hv_cfg_lib.N_Y 84 scenario_item_values["hv,FEATURES,IOMMU_ENFORCE_SNP"] = hv_cfg_lib.N_Y 85 scenario_item_values["hv,FEATURES,IVSHMEM,IVSHMEM_ENABLED"] = hv_cfg_lib.N_Y 86 scenario_item_values["hv,FEATURES,SSRAM,SSRAM_ENABLED"] = hv_cfg_lib.N_Y 87 88 scenario_cfg_lib.ERR_LIST.update(hv_cfg_lib.ERR_LIST) 89 return scenario_item_values 90 91 92def validate_scenario_schema(scenario_info): 93 """ 94 Validate settings in scenario xml if there is scenario schema 95 :param xsd_doc: scenario schema 96 :param scenario_info: scenario file 97 """ 98 99 """ 100 XMLSchema does not process XInclude. 101 Use lxml to expand the schema which is feed to XMLSchema as a string. 102 """ 103 xsd_doc = parse(acrn_config_utilities.SCENARIO_SCHEMA_FILE) 104 xsd_doc.xinclude() 105 my_schema = xmlschema.XMLSchema11(tostring(xsd_doc, encoding="unicode")) 106 107 it = my_schema.iter_errors(scenario_info) 108 for idx, validation_error in enumerate(it, start=1): 109 key = "" 110 if not validation_error: 111 continue 112 else: 113 path = str(validation_error.path).split("/") 114 cnt = 0 115 for p in path: 116 if '[' in p: 117 idx = int(p.split("[")[1].split("]")[0]) - 1 118 p = p.split("[")[0] + ":id=" + str(idx) 119 path[cnt] = p 120 cnt = cnt + 1 121 key =','.join(path[2:]) 122 element = "'" + path[-1] + "' " 123 reason = validation_error.reason + ": last call: " + str(validation_error.obj) 124 scenario_cfg_lib.ERR_LIST[key] = element + reason 125 126def apply_data_checks(board_info, scenario_info): 127 xsd_doc = parse(acrn_config_utilities.DATACHECK_SCHEMA_FILE) 128 xsd_doc.xinclude() 129 datachecks_schema = xmlschema.XMLSchema11(tostring(xsd_doc, encoding="unicode")) 130 131 main_etree = parse(board_info) 132 scenario_etree = parse(scenario_info) 133 main_etree.getroot().extend(scenario_etree.getroot()[:]) 134 # FIXME: Figure out proper error keys for data check failures 135 error_key = "" 136 137 it = datachecks_schema.iter_errors(main_etree) 138 for idx, error in enumerate(it, start=1): 139 anno = error.validator.annotation 140 description = anno.documentation[0].text 141 severity = anno.elem.get("{https://projectacrn.org}severity") 142 143 if severity == "error": 144 if error_key in scenario_cfg_lib.ERR_LIST.keys(): 145 scenario_cfg_lib.ERR_LIST[error_key].append("\n" + description) 146 else: 147 scenario_cfg_lib.ERR_LIST[error_key] = description 148 149def validate_scenario_setting(board_info, scenario_info): 150 hv_cfg_lib.ERR_LIST = {} 151 scenario_cfg_lib.ERR_LIST = {} 152 153 if "xmlschema" in sys.modules.keys(): 154 validate_scenario_schema(scenario_info) 155 apply_data_checks(board_info, scenario_info) 156 157 """ 158 Validate settings in scenario xml 159 :param board_info: board file 160 :param scenario_info: scenario file 161 :return: return a dictionary that contains errors 162 """ 163 acrn_config_utilities.BOARD_INFO_FILE = board_info 164 acrn_config_utilities.SCENARIO_INFO_FILE = scenario_info 165 166 hv_info = HvInfo(scenario_info) 167 hv_info.get_info() 168 hv_info.check_item() 169 170 scenario_info_items = {} 171 vm_info = VmInfo(board_info, scenario_info) 172 vm_info.get_info() 173 vm_info.set_ivshmem(hv_info.mem.ivshmem_region) 174 vm_info.check_item() 175 176 scenario_info_items['vm'] = vm_info 177 scenario_info_items['hv'] = hv_info 178 179 scenario_cfg_lib.ERR_LIST.update(hv_cfg_lib.ERR_LIST) 180 return (scenario_cfg_lib.ERR_LIST, scenario_info_items) 181 182 183def main(args): 184 """ 185 Generate board related source code 186 :param args: command line args 187 """ 188 err_dic = {} 189 190 (err_dic, params) = acrn_config_utilities.get_param(args) 191 if err_dic: 192 return err_dic 193 194 # check env 195 err_dic = acrn_config_utilities.prepare() 196 if err_dic: 197 return err_dic 198 199 acrn_config_utilities.BOARD_INFO_FILE = params['--board'] 200 acrn_config_utilities.SCENARIO_INFO_FILE = params['--scenario'] 201 acrn_config_utilities.get_vm_num(params['--scenario']) 202 acrn_config_utilities.get_load_order() 203 204 # get board name 205 (err_dic, board_name) = acrn_config_utilities.get_board_name() 206 207 # get scenario name 208 (err_dic, scenario) = acrn_config_utilities.get_scenario_name() 209 if err_dic: 210 return err_dic 211 212 if acrn_config_utilities.VM_COUNT > acrn_config_utilities.MAX_VM_NUM: 213 err_dic['vm count'] = "Number of VMs in scenario xml file should be no greater than hv/CAPACITIES/MAX_VM_NUM ! " \ 214 "Now this value is {}.".format(acrn_config_utilities.MAX_VM_NUM) 215 return err_dic 216 217 if params['--out']: 218 if os.path.isabs(params['--out']): 219 scen_output = params['--out'] + "/scenarios/" + scenario + "/" 220 else: 221 scen_output = ACRN_PATH + params['--out'] + "/scenarios/" + scenario + "/" 222 else: 223 scen_output = ACRN_CONFIG_DEF + "/" + scenario + "/" 224 225 scen_board = scen_output + "/" 226 acrn_config_utilities.mkdir(scen_board) 227 acrn_config_utilities.mkdir(scen_output) 228 229 vm_config_h = scen_output + GEN_FILE[0] 230 vm_config_c = scen_output + GEN_FILE[1] 231 pci_config_c = scen_board + GEN_FILE[2] 232 config_hv = scen_board + board_name + GEN_FILE[3] 233 ivshmem_config_h = scen_board + GEN_FILE[4] 234 pt_intx_config_c = scen_board + GEN_FILE[5] 235 236 # parse the scenario.xml 237 get_scenario_item_values(params['--board'], params['--scenario']) 238 (err_dic, scenario_items) = validate_scenario_setting(params['--board'], params['--scenario']) 239 if err_dic: 240 acrn_config_utilities.print_red("Scenario xml file validation failed:", err=True) 241 return err_dic 242 243 # generate board defconfig 244 with open(config_hv, 'w+') as config: 245 err_dic = board_defconfig.generate_file(scenario_items['hv'], config) 246 if err_dic: 247 return err_dic 248 249 # generate ASL code of ACPI tables for Pre-launched VMs 250 if not err_dic: 251 err_dic = asl_gen.main(args) 252 253 if not err_dic: 254 print("Scenario configuration files were created successfully.") 255 else: 256 print("Failed to create scenario configuration files.") 257 258 return err_dic 259 260 261def ui_entry_api(board_info, scenario_info, out=''): 262 263 arg_list = ['scenario_cfg_gen.py', '--board', board_info, '--scenario', scenario_info, '--out', out] 264 265 err_dic = acrn_config_utilities.prepare() 266 if err_dic: 267 return err_dic 268 269 err_dic = main(arg_list) 270 271 return err_dic 272 273 274if __name__ == '__main__': 275 276 ARGS = sys.argv 277 err_dic = main(ARGS) 278 if err_dic: 279 for err_k, err_v in err_dic.items(): 280 acrn_config_utilities.print_red("{}: {}".format(err_k, err_v), err=True) 281 sys.exit(1 if err_dic else 0) 282