config-tools: refine bin_gen.py and create virtual TPM2 acpi table

Create virtual acpi table of tpm2 based on the raw data if the TPM2
device is presented and the passthrough tpm2 is enabled.

Refine the arguments of bin_gen.py. The --board and --scenario take the
path to the XMLs as the argument. The allocation.xml is needed for
bin_gen.py to generate tpm2 acpi table.

Refine the condition of tpm2_acpi_gen. The tpm2 device "MSFT0101" can be
present in device id or compatible_id(CID). Check both attributes and
child node of tpm2 device.

Tracked-On: #6320
Signed-off-by: Yang,Yu-chu <yu-chu.yang@intel.com>
This commit is contained in:
Yang,Yu-chu 2021-07-14 14:57:09 -07:00 committed by wenlingz
parent 53d99d2a68
commit d997f4bbc1
2 changed files with 57 additions and 18 deletions

View File

@ -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) $(MAKE) -C $(PRE_BUILD_DIR) BOARD=$(BOARD) SCENARIO=$(SCENARIO) TARGET_DIR=$(HV_CONFIG_DIR)
@$(HV_OBJDIR)/hv_prebuild_check.out @$(HV_OBJDIR)/hv_prebuild_check.out
@echo "generate the binary of ACPI tables for pre-launched VMs ..." @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 .PHONY: header
header: $(VERSION) $(HV_CONFIG_H) $(HV_CONFIG_TIMESTAMP) header: $(VERSION) $(HV_CONFIG_H) $(HV_CONFIG_TIMESTAMP)

View File

@ -5,9 +5,14 @@
""" """
import logging
import os, sys, subprocess, argparse, re, shutil 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 * 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): 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)) print('compile ACPI ASL code to {} successfully'.format(dest_vm_acpi_bin_path))
return rmsg 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, board_etree, scenario_etree, allocation_etree):
def aml_to_bin(dest_vm_acpi_path, dest_vm_acpi_bin_path, acpi_bin_name):
''' '''
create the binary of ACPI table. create the binary of ACPI table.
:param dest_vm_acpi_bin_path: the path of the aml code of ACPI tables :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: with open(os.path.join(dest_vm_acpi_bin_path, ACPI_TABLE_LIST[4][1]), 'rb') as asl:
acpi_bin.write(asl.read()) 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) 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: with open(os.path.join(dest_vm_acpi_bin_path, ACPI_TABLE_LIST[6][1]), 'rb') as asl:
acpi_bin.write(asl.read()) 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: with open(os.path.join(dest_vm_acpi_bin_path, ACPI_TABLE_LIST[8][1]), 'rb') as asl:
acpi_bin.write(asl.read()) 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.seek(0xfffff)
acpi_bin.write(b'\0') acpi_bin.write(b'\0')
shutil.move(acpi_bin_file, os.path.join(dest_vm_acpi_bin_path, '..', acpi_bin_name)) 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): def main(args):
board_type = args.board board_etree = lxml.etree.parse(args.board)
scenario_name = args.scenario scenario_etree = lxml.etree.parse(args.scenario)
scenario_name = common.get_node("//@scenario", scenario_etree)
if args.asl is None: if args.asl is None:
DEST_ACPI_PATH = os.path.join(VM_CONFIGS_PATH, 'scenarios', scenario_name) DEST_ACPI_PATH = os.path.join(VM_CONFIGS_PATH, 'scenarios', scenario_name)
else: else:
DEST_ACPI_PATH = os.path.join(common.SOURCE_ROOT_DIR, args.asl, 'scenarios', scenario_name) DEST_ACPI_PATH = os.path.join(common.SOURCE_ROOT_DIR, args.asl, 'scenarios', scenario_name)
if args.out is None: 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: 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): if os.path.isdir(DEST_ACPI_BIN_PATH):
shutil.rmtree(DEST_ACPI_BIN_PATH) shutil.rmtree(DEST_ACPI_BIN_PATH)
@ -204,20 +243,20 @@ def main(args):
os.makedirs(dest_vm_acpi_bin_path) os.makedirs(dest_vm_acpi_bin_path)
if asl_to_aml(dest_vm_acpi_path, dest_vm_acpi_bin_path): if asl_to_aml(dest_vm_acpi_path, dest_vm_acpi_bin_path):
return 1 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 return 0
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser(usage="python3 bin_gen.py --board [board] --scenario [scenario]" parser = argparse.ArgumentParser(usage="python3 bin_gen.py --board [board] --scenario [scenario]"
"[ --out [output dir of acpi ASL code]]", "[ --out [output dir of acpi ASL code]]",
description="the tool to generate ACPI binary for Pre-launched VMs.") description="the tool to generate ACPI binary for Pre-launched VMs")
parser.add_argument("--board", required=True, help="the board type.") parser.add_argument("--board", required=True, help="the XML file summarizing characteristics of the target board")
parser.add_argument("--scenario", required=True, help="the scenario name.") 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("--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. " 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" "If not specified, the path for the binary code is"
"build/acpi/") "build/hypervisor/acpi/")
args = parser.parse_args() args = parser.parse_args()
rc = main(args) rc = main(args)