diff --git a/hypervisor/Makefile b/hypervisor/Makefile index b0da1d744..1e70bb5e0 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -395,7 +395,7 @@ pre_build: $(HV_CONFIG_H) $(HV_CONFIG_TIMESTAMP) $(MAKE) -C $(PRE_BUILD_DIR) BOARD=$(BOARD) SCENARIO=$(SCENARIO) TARGET_DIR=$(HV_CONFIG_DIR) @$(HV_OBJDIR)/hv_prebuild_check.out @echo "generate the binary of ACPI tables for pre-launched VMs ..." - python3 ../misc/config_tools/acpi_gen/bin_gen.py --board $(BOARD) --scenario $(SCENARIO) --asl $(HV_CONFIG_DIR) --out $(HV_OBJDIR)/acpi + python3 ../misc/config_tools/acpi_gen/bin_gen.py --board $(HV_OBJDIR)/.board.xml --scenario $(HV_OBJDIR)/.scenario.xml --asl $(HV_CONFIG_DIR) --out $(HV_OBJDIR) .PHONY: header header: $(VERSION) $(HV_CONFIG_H) $(HV_CONFIG_TIMESTAMP) diff --git a/misc/config_tools/acpi_gen/bin_gen.py b/misc/config_tools/acpi_gen/bin_gen.py index 9a03cc835..75ed5200f 100644 --- a/misc/config_tools/acpi_gen/bin_gen.py +++ b/misc/config_tools/acpi_gen/bin_gen.py @@ -5,9 +5,14 @@ """ +import logging import os, sys, subprocess, argparse, re, shutil +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'board_inspector')) +import lxml.etree from acpi_const import * - +import acpiparser.tpm2 +import lib.cdata +import common def asl_to_aml(dest_vm_acpi_path, dest_vm_acpi_bin_path): ''' @@ -61,9 +66,38 @@ def asl_to_aml(dest_vm_acpi_path, dest_vm_acpi_bin_path): print('compile ACPI ASL code to {} successfully'.format(dest_vm_acpi_bin_path)) return rmsg +def tpm2_acpi_gen(acpi_bin, board_etree, scenario_etree, allocation_etree): + tpm2_enabled = common.get_node("//vm[@id = '0']/mmio_resources/TPM2/text()", scenario_etree) + if tpm2_enabled is not None and tpm2_enabled == 'y': + tpm2_node = common.get_node("//device[@id = 'MSFT0101' or compatible_id = 'MSFT0101']", board_etree) + if tpm2_node is not None: + _data_len = 0x4c if common.get_node("//capability[@id = 'log_area']", board_etree) is not None else 0x40 + _data = bytearray(_data_len) + ctype_data = acpiparser.tpm2.TPM2(_data) + ctype_data.header.signature = "TPM2".encode() + ctype_data.header.length = _data_len + ctype_data.header.revision = 0x3 + ctype_data.header.oemid = "ACRN ".encode() + ctype_data.header.oemtableid = "ACRNTPM2".encode() + ctype_data.header.oemrevision = 0x1 + ctype_data.header.creatorid = "INTL".encode() + ctype_data.header.creatorrevision = 0x20190703 + ctype_data.address_of_control_area = 0xFED40040 + ctype_data.start_method = int(common.get_node("//capability[@id = 'start_method']/value/text()", tpm2_node), 16) + start_method_parameters = tpm2_node.xpath("//parameter/text()") + for i in range(len(start_method_parameters)): + ctype_data.start_method_specific_parameters[i] = int(start_method_parameters[i], 16) + if common.get_node("//capability[@id = 'log_area']", board_etree) is not None: + ctype_data.log_area_minimum_length = int(common.get_node("//log_area_minimum_length/text()", allocation_etree), 16) + ctype_data.log_area_start_address = int(common.get_node("//log_area_start_address/text()", allocation_etree), 16) + ctype_data.header.checksum = (~(sum(lib.cdata.to_bytes(ctype_data))) + 1) & 0xFF + acpi_bin.seek(ACPI_TPM2_ADDR_OFFSET) + acpi_bin.write(lib.cdata.to_bytes(ctype_data)) + else: + logging.warning("Passtrhough tpm2 is enabled in scenario but the device is not presented on board.") + logging.warning("Check there is tpm2 device on board and re-generate the xml using board inspector with --advanced option.") - -def aml_to_bin(dest_vm_acpi_path, dest_vm_acpi_bin_path, acpi_bin_name): +def aml_to_bin(dest_vm_acpi_path, dest_vm_acpi_bin_path, acpi_bin_name, board_etree, scenario_etree, allocation_etree): ''' create the binary of ACPI table. :param dest_vm_acpi_bin_path: the path of the aml code of ACPI tables @@ -95,11 +129,6 @@ def aml_to_bin(dest_vm_acpi_path, dest_vm_acpi_bin_path, acpi_bin_name): with open(os.path.join(dest_vm_acpi_bin_path, ACPI_TABLE_LIST[4][1]), 'rb') as asl: acpi_bin.write(asl.read()) - if 'tpm2.asl' in os.listdir(dest_vm_acpi_path): - acpi_bin.seek(ACPI_TPM2_ADDR_OFFSET) - with open(os.path.join(dest_vm_acpi_bin_path, ACPI_TABLE_LIST[5][1]), 'rb') as asl: - acpi_bin.write(asl.read()) - acpi_bin.seek(ACPI_DSDT_ADDR_OFFSET) with open(os.path.join(dest_vm_acpi_bin_path, ACPI_TABLE_LIST[6][1]), 'rb') as asl: acpi_bin.write(asl.read()) @@ -113,6 +142,10 @@ def aml_to_bin(dest_vm_acpi_path, dest_vm_acpi_bin_path, acpi_bin_name): with open(os.path.join(dest_vm_acpi_bin_path, ACPI_TABLE_LIST[8][1]), 'rb') as asl: acpi_bin.write(asl.read()) + vm_id = acpi_bin_name.split('.')[0].split('ACPI_VM')[1] + if vm_id == '0': + tpm2_acpi_gen(acpi_bin, board_etree, scenario_etree, allocation_etree) + acpi_bin.seek(0xfffff) acpi_bin.write(b'\0') shutil.move(acpi_bin_file, os.path.join(dest_vm_acpi_bin_path, '..', acpi_bin_name)) @@ -178,16 +211,22 @@ def check_iasl(): def main(args): - board_type = args.board - scenario_name = args.scenario + board_etree = lxml.etree.parse(args.board) + scenario_etree = lxml.etree.parse(args.scenario) + + scenario_name = common.get_node("//@scenario", scenario_etree) + if args.asl is None: DEST_ACPI_PATH = os.path.join(VM_CONFIGS_PATH, 'scenarios', scenario_name) else: DEST_ACPI_PATH = os.path.join(common.SOURCE_ROOT_DIR, args.asl, 'scenarios', scenario_name) if args.out is None: - DEST_ACPI_BIN_PATH = os.path.join(common.SOURCE_ROOT_DIR, 'build', 'hypervisor', 'acpi') + hypervisor_out = os.path.join(common.SOURCE_ROOT_DIR, 'build', 'hypervisor') else: - DEST_ACPI_BIN_PATH = args.out + hypervisor_out = args.out + DEST_ACPI_BIN_PATH = os.path.join(hypervisor_out, 'acpi') + + allocation_etree = lxml.etree.parse(os.path.join(hypervisor_out, 'configs', 'allocation.xml')) if os.path.isdir(DEST_ACPI_BIN_PATH): shutil.rmtree(DEST_ACPI_BIN_PATH) @@ -204,20 +243,20 @@ def main(args): os.makedirs(dest_vm_acpi_bin_path) if asl_to_aml(dest_vm_acpi_path, dest_vm_acpi_bin_path): return 1 - aml_to_bin(dest_vm_acpi_path, dest_vm_acpi_bin_path, config+'.bin') + aml_to_bin(dest_vm_acpi_path, dest_vm_acpi_bin_path, config+'.bin', board_etree, scenario_etree, allocation_etree) return 0 if __name__ == '__main__': parser = argparse.ArgumentParser(usage="python3 bin_gen.py --board [board] --scenario [scenario]" "[ --out [output dir of acpi ASL code]]", - description="the tool to generate ACPI binary for Pre-launched VMs.") - parser.add_argument("--board", required=True, help="the board type.") - parser.add_argument("--scenario", required=True, help="the scenario name.") + description="the tool to generate ACPI binary for Pre-launched VMs") + parser.add_argument("--board", required=True, help="the XML file summarizing characteristics of the target board") + parser.add_argument("--scenario", required=True, help="the XML file specifying the scenario to be set up") parser.add_argument("--asl", default=None, help="the input folder to store the ACPI ASL code. ") parser.add_argument("--out", default=None, help="the output folder to store the ACPI binary code. " "If not specified, the path for the binary code is" - "build/acpi/") + "build/hypervisor/acpi/") args = parser.parse_args() rc = main(args)