diff --git a/SetupDataPkg/Include/Library/PlatformConfigDataLib.h b/SetupDataPkg/Include/Library/PlatformConfigDataLib.h index 7096e028..041d6f60 100644 --- a/SetupDataPkg/Include/Library/PlatformConfigDataLib.h +++ b/SetupDataPkg/Include/Library/PlatformConfigDataLib.h @@ -16,6 +16,7 @@ #include #include +extern CHAR8 *gSchemaXmlHash; extern KNOB_DATA gKnobData[]; extern UINTN gNumKnobs; extern PROFILE gProfileData[]; diff --git a/SetupDataPkg/Tools/BoardMiscInfo.py b/SetupDataPkg/Tools/BoardMiscInfo.py index 581cee6b..663c6abb 100644 --- a/SetupDataPkg/Tools/BoardMiscInfo.py +++ b/SetupDataPkg/Tools/BoardMiscInfo.py @@ -30,6 +30,27 @@ def get_mfci_policy(): return result +def get_schema_xml_hash_from_bios(): + """ + Function to get SCHEMA_XML_HASH variable from BIOS + Returns the SCHEMA_XML_HASH in hexadecimal format or 'Unknown' if an error occurs. + """ + SCHEMA_XML_HASH_VAR_NAME = "SCHEMA_XML_HASH" + SCHEMA_XML_HASH_GUID = "1321e012-14c5-42db-8ca9-e7971d881518" + + UefiVar = UefiVariable() + (errorcode, data) = UefiVar.GetUefiVar(SCHEMA_XML_HASH_VAR_NAME, SCHEMA_XML_HASH_GUID) + + result = None + if errorcode == 0: + # Remove null byte if exist + if data[-1] == 0: + data = data[:-1] + result = data.decode("utf-8") + + return result + + def locate_smbios_data(): # Define constants FIRMWARE_TABLE_ID = 0x52534D42 # 'RSMB' ascii signature for smbios table diff --git a/SetupDataPkg/Tools/CommonUtility.py b/SetupDataPkg/Tools/CommonUtility.py index 3ba45bcf..f3afa2ff 100644 --- a/SetupDataPkg/Tools/CommonUtility.py +++ b/SetupDataPkg/Tools/CommonUtility.py @@ -11,6 +11,8 @@ # Import Modules # import string +import hashlib +import xml.etree.ElementTree as ET def print_bytes(data, indent=0, offset=0, show_ascii=False): @@ -97,3 +99,32 @@ def array_str_to_value(val_str): each = each.strip() value = (value << 8) | int(each, 0) return value + + +def get_xml_full_hash(xml_path): + # Parse the XML file + tree = ET.parse(xml_path) + root = tree.getroot() + + # List to store all tags, attributes, and values + hash_content = [] + + def traverse(element): + # Add tag name + hash_content.append(element.tag) + + # Add attribute names and values + for key, value in sorted(element.attrib.items()): + hash_content.append(f"{key}={value}") + + # Recursively process each child element + for child in element: + traverse(child) + + # Start traversing the root node + traverse(root) + + # Combine all items in hash_content list into a single string + combined_string = ''.join(hash_content) + + return hashlib.md5(combined_string.encode('utf-8')).hexdigest() diff --git a/SetupDataPkg/Tools/ConfigEditor.py b/SetupDataPkg/Tools/ConfigEditor.py index 903ce7b6..df490f96 100644 --- a/SetupDataPkg/Tools/ConfigEditor.py +++ b/SetupDataPkg/Tools/ConfigEditor.py @@ -28,6 +28,7 @@ bytes_to_bracket_str, value_to_bytes, array_str_to_value, + get_xml_full_hash ) @@ -393,6 +394,8 @@ def __init__(self, master=None): # self.page_cfg_map[page_id] = cfg_data_idx self.page_cfg_map = {} + self.bios_schema_xml_hash = None + # Check if current directory contains a file with a .yaml extension # if not default self.last_dir to a Platform directory where it is # easier to locate *BoardPkg\CfgData\*Def.yaml files @@ -559,6 +562,8 @@ def __init__(self, master=None): Manufacturing_enabled = (char_ext2_data & (0x1 << 6)) >> 6 print(f"Manufacturing : {Manufacturing_enabled:02X}") + self.bios_schema_xml_hash = BoardMiscInfo.get_schema_xml_hash_from_bios() + # get mfci policy mfci_policy_result = BoardMiscInfo.get_mfci_policy() self.canvas = tkinter.Canvas(master, width=240, height=50, bg=master['bg'], highlightthickness=0) @@ -968,6 +973,15 @@ def load_cfg_file(self, path, file_id, clear_config): self.config_xml_path = path self.output_current_status(f"{path} file is loaded") + # load xml file and get the hash value of all xml nodes + config_xml_hash = get_xml_full_hash(self.config_xml_path) + + # Compare the xml hash and the hash claimed in FW. + if self.bios_schema_xml_hash is not None and config_xml_hash != self.bios_schema_xml_hash: + self.output_current_status("WARNING: Config xml file hash mismatches with system FW", color="red") + self.output_current_status(f"FW ConfigXml Hash = {self.bios_schema_xml_hash}", color="red") + self.output_current_status(f"{self.config_xml_path} Hash = {config_xml_hash}", color="red") + return 0 def load_from_ml_and_clear(self): @@ -1399,9 +1413,15 @@ def update_config_data_on_page(self): self.right_grid, self.update_config_data_from_widget ) - def output_current_status(self, output_log): - self.status.insert(tkinter.END, output_log + "\n") - self.status.see(tkinter.END) + def output_current_status(self, output_log, color="black"): + unique_tag = f"color_{color}" + # Configure the color tag only if it hasn't been set before + if unique_tag not in self.status.tag_names(): + self.status.tag_config(unique_tag, foreground=color) + + # Insert the log with the unique color tag + self.status.insert(tkinter.END, output_log + "\n", (unique_tag,)) + self.status.see(tkinter.END) # Auto-scroll to the bottom if __name__ == "__main__": diff --git a/SetupDataPkg/Tools/KnobService.py b/SetupDataPkg/Tools/KnobService.py index 550f2445..5312d1c6 100644 --- a/SetupDataPkg/Tools/KnobService.py +++ b/SetupDataPkg/Tools/KnobService.py @@ -11,6 +11,7 @@ import argparse import re import VariableList +from CommonUtility import get_xml_full_hash # Converts a type name from standard C to UEFI @@ -632,6 +633,7 @@ def generate_cached_implementation(schema, header_path, efi_type=False, no_chang out.write("// Generated Header" + get_line_ending(efi_type)) out.write("// Script: {}".format(sys.argv[0]) + get_line_ending(efi_type)) out.write("// Schema: {}".format(schema.path) + get_line_ending(efi_type)) + out.write('CHAR8 *gSchemaXmlHash = "' + get_xml_full_hash(schema.path) + '";' + get_line_ending(efi_type)) out.write("" + get_line_ending(efi_type)) out.write("typedef struct {" + get_line_ending(efi_type))