diff --git a/MANIFEST.in b/MANIFEST.in index 94b444c..2916e3f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -12,8 +12,9 @@ include start_xmlcli.sh recursive-include src/xmlcli/cfg * -include src/xmlcli/modules/* -recursive-include src/xmlcli/modules/winContextMenu * +include examples/* + +recursive-include src/xmlcli/modules * include src/xmlcli/out/.gitignore @@ -21,6 +22,7 @@ include src/xmlcli/messages.json include src/xmlcli/xmlcli.config recursive-include src/xmlcli/common * recursive-include src/xmlcli/access/base * +recursive-include src/xmlcli/access/generic * recursive-include src/xmlcli/access/linux * recursive-include src/xmlcli/access/stub * recursive-include src/xmlcli/access/winrwe * @@ -31,6 +33,7 @@ include tests/CommonTests.py include tests/tests.config include tests/UefiParserTest.py include tests/UnitTestHelper.py +include tests/XmlCliTest.py include src/xmlcli/tools/* include docs/user_guide/* diff --git a/Makefile b/Makefile index 2aa3ea4..fd41274 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,29 @@ clean-test: ## remove test and coverage artifacts rm -fr htmlcov/ rm -fr .pytest_cache +lint: ## check style with flake8 + flake8 xmlcli tests + +test: ## run tests quickly with the default Python + python setup.py test + +test-all: ## run tests on every Python version with tox + tox + +coverage: ## check code coverage quickly with the default Python + coverage run --source xmlcli setup.py test + coverage report -m + coverage html + $(BROWSER) htmlcov/index.html + +docs: ## generate Sphinx HTML documentation, including API docs + rm -f docs/xmlcli.rst + rm -f docs/modules.rst + sphinx-apidoc -o docs/ xmlcli + $(MAKE) -C docs clean + $(MAKE) -C docs html + $(BROWSER) docs/_build/html/index.html + dist: clean ## builds source and wheel package mkdir bld python setup.py egg_info --egg-base=bld build --build-base=bld bdist_wheel --universal diff --git a/README.md b/README.md index b0f3ad7..825a94e 100644 --- a/README.md +++ b/README.md @@ -6,16 +6,27 @@ UFFAF allows firmware modification as an efficient operation with scriptable app These reference scripts provides several capabilities including but not limited to: >- Parsing Information of UEFI BIOS Firmware as per [Platform Initialization Specification](https://uefi.org/specs/PI/1.8/) +>- Programming/Reading BIOS knobs with CLI and GUI +>- Fetching Platform XML from target +>- System information +>- CommandLine and web based GUI support for get and set NVAR (UEFI NVRAM variable) >- Context Menu Integration for Windows +These scripts are generic and platform/program independent (as long as BIOS on SUT BIOS supports XML CLI interface). --- ## User Guidelines for usage +These scripts are provided as reference scripts and requires to have bios driver enabled in order to use the functionality. + +As scripts require to read/write memory of the target device/system, valid access interface would be required which can be configured at [config file](src/xmlcli/xmlcli.config). + For Offline Binary modification, these scripts provide easier way to interpret and update the data bytes of binary. Irrespective of these scripts, changing undesired data in binary could be result to unexpected behavior hence, it is individual's responsibility to make sure to use valid configuration. +As Accessing target SUT is only possible at **Elevated Privilege**, we recommend proceeding with caution if service API of these scripts are exposed over network. + ## Supported Interface Types Interface means the way to access memory and I/O of target system. @@ -24,6 +35,7 @@ These interface works only when running with elevated privileges are available. It is responsibility of user to make sure to act with caution before making modification to avoid corrupting memory/registers with unwanted data. + - Windows - LINUX - Offline mode (or stub mode, to enable BIOS/IFWI Editing) @@ -31,6 +43,7 @@ corrupting memory/registers with unwanted data. ## Prerequisites - [Python](https://www.python.org/downloads/) software version 3.6 or above +- If running on Online mode; **elevated privileges** are required to execute commands as it involves accessing hardware memory resource. - For Interface setup please refer README document within interface folder itself. ## Installation @@ -49,6 +62,178 @@ python -m pip install --proxy Refer [Installation-Steps](docs/user_guide/installation.md) for more alternate installation instruction. + +## Setting Interface Type + +Need to select the interface to indicate the scripts on which access method to use (depending on which environment we expect the script to operate in). + +```python +from xmlcli import XmlCli as cli +cli.clb._setCliAccess("") +``` + +Below are listed valid ``: + +| Access Method | Remarks | +| --- | --- | +| `linux` | For using linux as interface, need to open Python Prompt in root permissions. | +| `winrwe` | For using `RW.exe` as Windows interface (**slow**, least recommended). For more details refer [winrwe/README.md](src/xmlcli/access/winrwe/README.md) | + + +## Running popular commands + +After initializing the desired interface, the use may run following commands. + +If the commands `return 0`, it means the operation was `successful`, else there was an error. + +### Standard import steps + +```python +from xmlcli import XmlCli as cli +cli.clb._setCliAccess("linux") # Set desired Interface (for example `linux` if using on `linux` SUT) +``` + +### Step to check XmlCli capability on current System + +```python +from xmlcli import XmlCli as cli +cli.clb.ConfXmlCli() # Check if XmlCli is supported &/ Enabled on the current system. +``` + +| Return value of `cli.clb.ConfXmlCli` | Meaning | +| --- | --- | +| 0 | XmlCli is already **supported & enabled**. | +| 1 | XmlCli is **not supported** on the current BIOS or the System BIOS has not completed Boot. | +| 2 | XmlCli is **supported** but was **not enabled**, the script has now enabled it and **SUT needs reboot** to make use of XmlCli. | + +### To Save Target XML file + +```python +from xmlcli import XmlCli as cli +# For Online +# Run common import steps and make sure `cli.clb.ConfXmlCli()` returns `0` +cli.savexml() # Save Target XML as `/out/PlatformConfig.xml` file. +cli.savexml(r"path/to/file.xml") # Save Target XML as absolute file location for `path/to/file.xml`. + +# For Offline +cli.savexml(0, r"path/to/ifwi-or-bios.bin") # Extract the XML data from desired BIOS or IFWI binary. Will Save Target XML in `/out/` folder. +cli.savexml(r"path/to/file.xml", r"path/to/ifwi-or-bios.bin") # Extract the XML data from desired BIOS or IFWI binary. Will Save Target XML as `path/to/file.xml`. +``` + +### To Read BIOS settings + +> For **Online** command to run successfully, the target must complete BIOS boot. +> For **Offline** mode, you need to pass the link to BIOS or IFWI binary. + +- `Knob_A` & `Knob_B` in the below examples are the knob names taken from the `name` attribute from the `` section in the XML, it is **case sensitive**. + +```python +from xmlcli import XmlCli as cli +cli.CvReadKnobs("Knob_A=Val_1, Knobs_B=Val_2") # Reads the desired Knob_A & Knob_B settings from the SUT and verifies them against Val_1 & Val_2 respectively. +cli.CvReadKnobs() # same as above, just that the Knob entries will be read from the default cfg file (`/cfg/BiosKnobs.ini`). +# For Offline +cli.CvReadKnobs("Knob_A=Val_1, Knobs_B=Val_2", r"path/to/ifwi-or-bios.bin") # Reads & verifies the desired knob settings from the given BIOS or IFWI binary. +cli.CvReadKnobs(0, r"path/to/ifwi-or-bios.bin") # same as above, just that the Knob entries will be read from the `cli.clb.KnobsIniFile` cfg file instead. + +# the default cfg file pointer can be programed to desired cfg file via following command. +cli.clb.KnobsIniFile = r"path/to/bios-config.ini" +``` + +### To Program BIOS settings + +> For **Online** command to run successfully, the target must complete BIOS boot. +> For **Offline** mode, you need to pass the link to BIOS or IFWI binary. + +- `Knob_A` & `Knob_B` in the below examples are the knob names taken from the `name` attribute from the `` section in the XML, it is **case sensitive**. + +```python +from xmlcli import XmlCli as cli +cli.CvProgKnobs("Knob_A=Val_1, Knobs_B=Val_2") # Programs the desired Knob_A & Knob_B settings on the SUT and verifies them against Val_1 & Val_2 respectively. +cli.CvProgKnobs() # same as above, just that the Knob entries will be Programed from the default cfg file (\cfg\BiosKnobs.ini). +# For Offline +cli.CvProgKnobs("Knob_A=Val_1, Knobs_B=Val_2", r"path/to/ifwi-or-bios.bin") # Program the desired knob settings as new default value, operates on BIOS or IFWI binary, new BIOS or IFWI binary will be generated with desired settings. +cli.CvProgKnobs(0, r"path/to/ifwi-or-bios.bin") # same as above, just that the Knob entries will be Programed from the cli.clb.KnobsIniFile cfg file instead. + +# the default cfg file pointer can be programed to desired cfg file via following command. +cli.clb.KnobsIniFile = r"path/to/bios-config.ini" + +# To Load Default BIOS settings on the SUT. Offline mode not supported or not Applicable. +cli.CvLoadDefaults() # Loads/Restores the default value back on the system, also shows which values were restored back to its default Value. +``` + +### To Program only desired BIOS settings and reverting rest all settings back to its default value + +> **Offline** mode not supported or not Applicable. + +- `Knob_A` & `Knob_B` in the below examples are the knob names taken from the `name` attribute from the `` section in the XML, it is **case sensitive**. + +```python +from xmlcli import XmlCli as cli +cli.CvRestoreModifyKnobs("Knob_A=Val_1, Knobs_B=Val_2") # Programs the desired Knob_A & Knob_B settings and restores everything else back to its default value. +cli.CvRestoreModifyKnobs() # same as above, just that the Knob entries will be Programed from the cli.clb.KnobsIniFile cfg file instead. +# the default cfg file pointer can be programed to desired cfg file via following command. +cli.clb.KnobsIniFile = r"path/to/bios-config.ini" +``` + +> Offline editing of BIOS will update FV_BB section of BIOS. +> This is an expected to produce boot issue with Secure Boot profiles (i.e. Secure Profile images) + +To make sure offline Edited BIOSes for Knob changes boot fine with Secure Profile IFWI's, +user need to supply the re-signing script/pkg. This is user's full responsibility to manage an executable script +which syntax should follow as: + +```shell +file/to/executable/signing-resigning.bat input.bin output/path.bin +``` + +```python +from xmlcli import XmlCli as cli + +cli.fwp.SecureProfileEditing = True # if not set to True, Re-Signing Process will be skipped +cli.fwp.ReSigningFile = r'path/to/resigning/executable/ResignIbbForBtG.bat' # by default this variable is empty, please populate this variable with Re-Signing Script File Ptr +cli.CvProgKnobs('BootFirstToShell=1, EfiNetworkSupport=3', r'path/to/ifwi-or-bios.bin') +``` + +> **Note** - Providing Secure Profile resigning script/executable is out of scope of XmlCli, +> User need to gather required executable in order to utilize this functionality on SecureProfile. + + +### Add MSR & IO Read/Write CLI functions (`Only for DCG`) + +#### Usage Syntax + +```python +from xmlcli import XmlCli as cli + +cli.IoAccess("", "", "", "") +cli.MsrAccess("", "", "", "") +``` + +#### Example + +```python +from xmlcli import XmlCli as cli + +cli.IoAccess(cli.clb.IO_WRITE_OPCODE, 0x84, 1, 0xFA) +cli.IoAccess(cli.clb.IO_READ_OPCODE, 0x84, 1) +cli.MsrAccess(cli.clb.READ_MSR_OPCODE, 0x53, 0) +cli.MsrAccess(cli.clb.WRITE_MSR_OPCODE, 0x1A0, 0, 0x1) +``` + +## Execution under EFI Shell + +### Using XmlCli EFI App + +EFI App is located under `tools/XmlCliKnobs.efi`, below commands can be executed on UEFI Shell: + +| Command | Description | +| ------- | ----------- | +| `XmlCliKnobs.efi CX` | Ensure XmlCli is enabled, if it's not enable, this command helps to enable XmlCli, Reboot SUT if XmlCli was not enabled. | +| `XmlCliKnobs.efi -v` | Get version information of the efi App | +| `XmlCliKnobs.efi GX` | Generate Bios Knobs xml dump | +| `XmlCliKnobs.efi` | List out all possible available commands | + + ## Additional Feature and Modules These modules are extension of core XmlCli API also shows example of how it can be consumed in any independent modules. diff --git a/docs/user_guide/compare_setup_knobs.md b/docs/user_guide/compare_setup_knobs.md new file mode 100644 index 0000000..a8fbf01 --- /dev/null +++ b/docs/user_guide/compare_setup_knobs.md @@ -0,0 +1,22 @@ +If you have two different Xml from `cli.savexml()` command you could use below method: + + +Syntax: +```python +from xmlcli import XmlCli as cli + +cli.helpers.generate_knobs_delta( + ref_xml="path/to/reference.xml", + new_xml="path/to/new.xml", + out_file="path/to/difference-delta.txt", + compare_tag="default" # xml attribute to be compared against (default|CurrentVal|size|prompt|depex|...) +) +``` + + +If you have BIOS/IFWI image, instead of doing `cli.savexml` for both image, you could directly use below command syntax: +```python +from xmlcli import XmlCli as cli + +cli.helpers.compare_bios_knobs("", "", result_log_file="") +``` diff --git a/docs/user_guide/uefi_binary_parsing.md b/docs/user_guide/uefi_binary_parsing.md index 55122a0..f6e6df2 100644 --- a/docs/user_guide/uefi_binary_parsing.md +++ b/docs/user_guide/uefi_binary_parsing.md @@ -6,6 +6,17 @@ Key features: - JSON representation, lightweight database with keys and values with ease of readability - Works with both SUT and offline image +Working with SUT: + +Below command to be executed only after enabling applicable access method: + +```python +from xmlcli import XmlCli as cli + +max_bios_size = 12 * (1024**2) # 12 MB - configure based on the platform used +# If max_bios_size argument is not specified then by default it uses 32 MB dump to lookup for BIOS image +bios_image = cli.clb.get_bin_file("linux", max_bios_size=max_bios_size) # variable will have location of bios image dump stored from memory +``` Initiate the Parsing with below commands: diff --git a/examples/BiosKnobs.ini b/examples/BiosKnobs.ini new file mode 100644 index 0000000..aebabac --- /dev/null +++ b/examples/BiosKnobs.ini @@ -0,0 +1,8 @@ +[BiosKnobs] +CvfSupport=1 +MipiCam_ControlLogic0=1 +MipiCam_ControlLogic1=1 +MipiCam_Link0=1 +MipiCam_Link1=1 +MipiCam_Link1_SensorModel=1 +MipiCam_Link1_DriverData_CrdVersion=0x20 diff --git a/examples/__init__.py b/examples/__init__.py new file mode 100644 index 0000000..86ec2a2 --- /dev/null +++ b/examples/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +__author__ = "Gahan Saraiya" + +# Built-in imports + +# Custom imports + + +if __name__ == "__main__": + pass diff --git a/examples/automate_program_knobs.py b/examples/automate_program_knobs.py new file mode 100644 index 0000000..4a3f7ef --- /dev/null +++ b/examples/automate_program_knobs.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +__author__ = "Gahan Saraiya" + +# Built-in imports +import os +import sys +import glob +import shutil + +# Custom imports +from xmlcli import XmlCli as cli +from xmlcli import XmlCliLib as clb +from xmlcli.common.logger import log +from xmlcli import UefiFwParser as fwp + + +def automate_program_knobs(input_bios, config_dir, output_dir, new_major_ver="", new_minor_ver=""): + """Function to perform the CvProgKnobs for multiple bios images using configuration file + + :param input_bios: absolute path to the folder contains bios images or absolute path to the bios file + :param config_dir: absolute path to the folder contains bios knobs configuration file(.ini) + :param output_dir: absolute path of the directory to store the output files + :param new_major_ver: new major version for the file + :param new_minor_ver: new minor version for the file + """ + bios_knob_config_files = glob.glob(os.path.join(config_dir, "*.ini")) + original_knobs_config = clb.KnobsIniFile + input_bios_files = [] + if os.path.isdir(input_bios): + input_bios_files = glob.glob(os.path.join(input_bios, "*.bin")) + elif os.path.isfile(input_bios): + input_bios_files = [input_bios] + for KnobsIni in bios_knob_config_files: + clb.KnobsIniFile = KnobsIni + suffix_text = os.path.splitext(os.path.basename(KnobsIni))[0] + for BiosBinFile in input_bios_files: + log.info(f"Processing BIOS file = {BiosBinFile}") + cli.CvProgKnobs(0, BiosBinFile, suffix_text, True) + temp_file = clb.OutBinFile + fwp.UpdateBiosId(clb.OutBinFile, new_major_ver, new_minor_ver) + if clb.OutBinFile != "": + shutil.move(clb.OutBinFile, output_dir) + clb.RemoveFile(temp_file) + clb.KnobsIniFile = original_knobs_config + + +if __name__ == "__main__": + pass diff --git a/examples/setup_modification.py b/examples/setup_modification.py new file mode 100644 index 0000000..9a42dff --- /dev/null +++ b/examples/setup_modification.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +""" +This file is example to demonstrate usage of XmlCli to modify Values specified +by user. + +Aim: Have various function demonstrating example of usage for xmlcli to modify +setup option values in `ONLINE` mode. Intended to be executed on target platform + +Pre-requisite: +1. Python Software (Python version 3.6 or above [64-bit]) +2. XmlCli source code +3. Elevated Privilege [Execution access to run as administrator/root] + +For the example we are taking setup options below: +------------------------------------|---------------- +Setup Option | Possible Value +------------------------------------|---------------- +CvfSupport | 0,1,2 +MipiCam_ControlLogic0 | 0,1 +MipiCam_ControlLogic1 | 0,1 +MipiCam_Link0 | 0,1 +MipiCam_Link1 | 0,1 +MipiCam_Link1_SensorModel | 0,1 +MipiCam_Link1_DriverData_CrdVersion | 0x10, 0x20 +------------------------------------|---------------- +""" +__author__ = "Gahan Saraiya" + +# Built-in imports +import sys + +# Custom imports +# Importing API for xmlcli +from xmlcli import XmlCli as cli + +KNOBS_TO_MODIFY = [ + "CvfSupport=1", + "MipiCam_ControlLogic0=1", + "MipiCam_ControlLogic1=1", + "MipiCam_Link0=1", + "MipiCam_Link1=1", + "MipiCam_Link1_SensorModel=1", + "MipiCam_Link1_DriverData_CrdVersion=0x20", +] + + +def simple_program_knobs_from_sut(): + """ + Simplest flow to read/program values + :return: + """ + from xmlcli import XmlCli as cli + + cli.clb._setCliAccess("linux") + cli.clb.ConfXmlCli() + cli.CvReadKnobs(", ".join(KNOBS_TO_MODIFY)) # read+verify + cli.CvProgKnobs(", ".join(KNOBS_TO_MODIFY)) # modify + _status = cli.CvReadKnobs(", ".join(KNOBS_TO_MODIFY)) # read+verify + return _status + + +def program_knobs_from_sut(access_method="linux", knob_lis=None, config_file=None): + """ + + :param access_method: + For linux: + linux + For more access method and choices, visit + :param knob_lis: list of setup options to modify + i.e. ["CvfSupport=1", "MipiCam_ControlLogic0=1"] + :param config_file: absolute path to bios knobs configuration file to read knob and value + i.e. refer `cfg/BiosKnobs.ini` under xmlcli source + :return: + """ + cli.clb._setCliAccess(access_method) # on console one should see that the access method is correctly set. + if cli.clb.InterfaceType != access_method: + # validation to confirm interface is selected correctly + # if failed to set interface the return from flow. + return -1 + + return_status = cli.clb.ConfXmlCli() + if return_status == 0: # XmlCli is supported and enabled. + # Here we can perform our desire operation... + if not knob_lis and not config_file: + print("Please either provide knob list or config file") + return -1 + if knob_lis: + knobs = ", ".join(knob_lis) + status = cli.CvReadKnobs(knobs) # result can be observed in detail in log/console + print(f"status of read: {status}") + if status == 0: # all values are set as expected, do nothing + return status + else: # at least one knob is not having expected value + status = cli.CvProgKnobs(knobs) + if status != 0: # unable to modify knobs + return status + else: # Verify the modification status + status = cli.CvReadKnobs(knobs) + if status == 0: # success + print("Successfully modified and verified values") + else: + print("Write was successful but could not verify the value") + return status + elif config_file: + cli.clb.KnobsIniFile = config_file + status = cli.CvReadKnobs() # result can be observed in detail in log/console + print(f"status of read: {status}") + if status == 0: # all values are set as expected, do nothing + return status + else: # at least one knob is not having expected value + status = cli.CvProgKnobs() + if status != 0: # unable to modify knobs + return status + else: # Verify the modification status + status = cli.CvReadKnobs() + if status == 0: # success + print("Successfully modified and verified values") + else: + print("Write was successful but could not verify the value") + return status + elif return_status == 2: # Reboot requires + print("RESTART SYSTEM") + return return_status + else: + print("ERROR...") + return -1 + + +if __name__ == "__main__": + # simple_program_knobs_from_sut() + + # METHOD 1: With Knobs list + status = program_knobs_from_sut(access_method="linux", knob_lis=KNOBS_TO_MODIFY) # [user-param] + print(f"Execution status result={status}") + + # METHOD 2: With config file [comment METHOD 1 and uncomment below line for METHOD 2] + # status = program_knobs_from_sut(access_method="linux", config_file="BiosKnobs.ini") # [user-param] diff --git a/setup.cfg b/setup.cfg index 9042a74..cdb3c84 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,7 +2,7 @@ [metadata] name = xmlcli -version = attr: xmlcli.._version.__version__ +version = attr: xmlcli._version.__version__ url = https://github.com/intel/xml-cli description = "UFFAF - UEFI Firmware Foundational Automation Framework (formerly Xml-Cli)" commit = True @@ -22,6 +22,7 @@ classifiers = Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 author_email = gahan.saraiya@intel.com maintainer_email = xmlcli@intel.com diff --git a/src/xmlcli/UefiFwParser.py b/src/xmlcli/UefiFwParser.py new file mode 100644 index 0000000..526cdbb --- /dev/null +++ b/src/xmlcli/UefiFwParser.py @@ -0,0 +1,1790 @@ +#!/usr/bin/env python +__author__ = ['ashinde', "Gahan Saraiya"] + +# Built-in Imports +import os +import sys +import time +import glob +import copy + +# Custom Imports +from . import XmlCliLib as clb +from . import XmlIniParser as prs +from .common import utils +from .common import compress +from .common import configurations +from .common.logger import log + + +global LogEnabled, FileGuidListDict, FileSystemSaveCount, FwIngredientDict, HiiNvarDict + +FwIngredientDict = {} +FwIngredientDict['FlashDescpValid'] = 0 +FwIngredientDict['FitTablePtr'] = 0 +FwIngredientDict['FlashRegions'] = {} +FwIngredientDict['PCH_STRAPS'] = {} +FwIngredientDict['ME'] = {} +FwIngredientDict['FIT'] = {} +FwIngredientDict['ACM'] = {} +FwIngredientDict['Ucode'] = {} +FwpLogEn = True +FwpPrintEn = False +FileGuidListDict = {} +FileSystemSaveCount = 0 +Parse_Print_Uqi = False +PlatInfoMenuDone = False +ForceOutFile = False +MulSetupDrivers = False +SecureProfileEditing = False +ReSigningFile = '' + +EFI_GUID_DEFINED_SECTION_HDR_SIZE = 0x18 +FFS_FILE_HEADER_SIZE = 0x18 +FFS_FILE_HEADER2_SIZE = 0x20 +FFS_ATTRIB_LARGE_FILE = 0x01 +EFI_COMMON_SECTION_HEADER_SIZE = 0x04 +FV_FILETYPE_FIRMWARE_VOLUME_IMAGE = 0x0B +EFI_FV_HEADER_SIZE = 0x48 +EFI_SECTION_GUID_DEFINED = 0x02 +EFI_SECTION_FIRMWARE_VOLUME_IMAGE = 0x17 + +# FFS File Attributes. +FFS_ATTRIB_FIXED = 0x04 +FFS_ATTRIB_DATA_ALIGNMENT = 0x38 +FFS_ATTRIB_CHECKSUM = 0x40 + +# FFS_FIXED_CHECKSUM is the checksum value used when the FFS_ATTRIB_CHECKSUM attribute bit is clear +FFS_FIXED_CHECKSUM = 0xAA + +EFI_IFR_FORM_SET_OP = 0x0E +EFI_IFR_FORM_OP = 0x01 +EFI_IFR_SUBTITLE_OP = 0x02 +EFI_IFR_TEXT_OP = 0x03 +EFI_IFR_SUPPRESS_IF_OP = 0x0A +EFI_IFR_GRAY_OUT_IF_OP = 0x19 +EFI_IFR_REF_OP = 0x0F +EFI_IFR_VARSTORE_OP = 0x24 +EFI_IFR_VARSTORE_EFI_OP = 0x26 +EFI_IFR_ONE_OF_OP = 0x05 +EFI_IFR_CHECKBOX_OP = 0x06 +EFI_IFR_NUMERIC_OP = 0x07 +EFI_IFR_ONE_OF_OPTION_OP = 0x09 +EFI_IFR_STRING_OP = 0x1C +EFI_HII_PACKAGE_FORMS = 0x02 +EFI_HII_PACKAGE_STRINGS = 0x04 +EFI_IFR_NUMERIC_SIZE = 0x03 +EFI_IFR_END_OP = 0x29 +EFI_IFR_TRUE_OP = 0x46 +EFI_IFR_DEFAULT_OP = 0x5B +EFI_IFR_GUID_OP = 0x5F + +EFI_HII_SIBT_END = 0x00 +EFI_HII_SIBT_STRING_SCSU = 0x10 +EFI_HII_SIBT_STRING_SCSU_FONT = 0x11 +EFI_HII_SIBT_STRINGS_SCSU = 0x12 +EFI_HII_SIBT_STRINGS_SCSU_FONT = 0x13 +EFI_HII_SIBT_STRING_UCS2 = 0x14 +EFI_HII_SIBT_STRING_UCS2_FONT = 0x15 +EFI_HII_SIBT_STRINGS_UCS2 = 0x16 +EFI_HII_SIBT_STRINGS_UCS2_FONT = 0x17 +EFI_HII_SIBT_DUPLICATE = 0x20 +EFI_HII_SIBT_SKIP2 = 0x21 +EFI_HII_SIBT_SKIP1 = 0x22 +EFI_HII_SIBT_EXT1 = 0x30 +EFI_HII_SIBT_EXT2 = 0x31 +EFI_HII_SIBT_EXT4 = 0x32 +EFI_HII_SIBT_FONT = 0x40 + +EFI_IFR_TYPE_NUM_SIZE_8 = 0x00 +EFI_IFR_TYPE_NUM_SIZE_16 = 0x01 +EFI_IFR_TYPE_NUM_SIZE_32 = 0x02 +EFI_IFR_TYPE_NUM_SIZE_64 = 0x03 +EFI_IFR_TYPE_BOOLEAN = 0x04 + +EFI_IFR_OPTION_DEFAULT = 0x10 +EFI_IFR_OPTION_DEFAULT_MFG = 0x20 + +Descriptor_Region = 0 +BIOS_Region = 1 +ME_Region = 2 +GBE_Region = 3 +PDR_Region = 4 +Device_Expan_Region = 5 +Sec_BIOS_Region = 6 +SpiRegionMax = 7 +EC_Region = 8 +Padding_Region = 9 +SpiRegionAll = 0xFE +Invalid_Region = 0xFF +FlashRegionDict = {Descriptor_Region: 'Descriptor', BIOS_Region: 'BIOS', ME_Region: 'ME', GBE_Region: 'GBE', PDR_Region: 'PDR', Device_Expan_Region: 'Device Expansion', Sec_BIOS_Region: 'Secondary BIOS', SpiRegionMax: 'SpiRegionMax', EC_Region: 'EC', Padding_Region: 'Padding'} + +gEfiFirmwareFileSystemGuid = [ 0x7A9354D9, 0x0468, 0x444a, 0x81, 0xCE, 0x0B, 0xF6, 0x17, 0xD8, 0x90, 0xDF ] +gEfiFirmwareFileSystem2Guid = [ 0x8c8ce578, 0x8a3d, 0x4f1c, 0x99, 0x35, 0x89, 0x61, 0x85, 0xc3, 0x2d, 0xd3 ] +gEfiFirmwareFileSystem3Guid = [ 0x5473c07a, 0x3dcb, 0x4dca, 0xbd, 0x6f, 0x1e, 0x96, 0x89, 0xe7, 0x34, 0x9a ] + +gEfiGlobalVariableGuid = [ 0x8BE4DF61, 0x93CA, 0x11D2, 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C ] +gEfiVariableGuid = [ 0xddcf3616, 0x3275, 0x4164, 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d ] +gEfiIfrTianoGuid = [ 0x0f0b1735, 0x87a0, 0x4193, 0xb2, 0x66, 0x53, 0x8c, 0x38, 0xaf, 0x48, 0xce ] +gEdkiiIfrBitVarstoreGuid = [ 0x82DDD68B, 0x9163, 0x4187, 0x9B, 0x27, 0x20, 0xA8, 0xFD, 0x60, 0xA7, 0x1D ] +gEfiAuthenticatedVariableGuid = [ 0xaaf32c78, 0x947b, 0x439a, 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 ] +gTianoCustomDecompressGuid = [ 0xA31280AD, 0x481E, 0x41B6, 0x95, 0xE8, 0x12, 0x7F, 0x4C, 0x98, 0x47, 0x79 ] +gLzmaCustomDecompressGuid = [ 0xEE4E5898, 0x3914, 0x4259, 0x9D, 0x6E, 0xDC, 0x7B, 0xD7, 0x94, 0x03, 0xCF ] +gBrotliCustomDecompressGuid = [ 0x3D532050, 0x5CDA, 0x4FD0, 0x87, 0x9E, 0x0F, 0x7F, 0x63, 0x0D, 0x5A, 0xFB ] +gNvRamFvGuid = [ 0xFFF12B8D, 0x7696, 0x4c8b, 0xa9, 0x85, 0x27, 0x47, 0x07, 0x5b, 0x4f, 0x50 ] +gEfiFirmwareContentsSignedGuid = [ 0x0f9d89e8, 0x9259, 0x4f76, 0xa5, 0xaf, 0xc, 0x89, 0xe3, 0x40, 0x23, 0xdf ] +gEfiCertTypeRsa2048Sha256Guid = [ 0xa7717414, 0xc616, 0x4977, 0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf ] +gEfiHashAlgorithmSha256Guid = [ 0x51AA59DE, 0xFDF2, 0x4EA3, 0xBC, 0x63, 0x87, 0x5F, 0xB7, 0x84, 0x2E, 0xE9 ] + +gBiosCapsuleGuid = [ 0xda4b2d79, 0xfee1, 0x42c6, 0x9b, 0x56, 0x92, 0x36, 0x33, 0x39, 0x8a, 0xeb ] + +gBiosKnobsDataBinGuid = [ 0x615E6021, 0x603D, 0x4124, 0xB7, 0xEA, 0xC4, 0x8A, 0x37, 0x37, 0xBA, 0xCD ] +gBiosKnobsCpxDataBinGuid = [ 0x731DAA2A, 0x9259, 0x4729, 0xA1, 0xB5, 0xF7, 0x72, 0x09, 0xEB, 0xF5, 0x4D ] +# Legacy protocol guid +gXmlCliProtocolGuid = [ 0xe3e49b8d, 0x1987, 0x48d0, 0x9a, 0x1, 0xed, 0xa1, 0x79, 0xca, 0xb, 0xd6 ] +# Core-5.0.0 onwards protocol guid +gXmlCliInterfaceBufferGuid = [0xa8cbbbea, 0xf37c, 0x4da4, 0x5e, 0x81, 0x68, 0x4f, 0x6f, 0xc5, 0x12, 0x49] + +gXmlCliSetupDriverGuid = [0xDFB9BF4C, 0x3520, 0x4a80, 0x90, 0x4E, 0x71, 0xD5, 0xF4, 0x2E, 0x86, 0x6A] +gVtioDriverGuid = [0x03327D04, 0xC807, 0x4B76, 0x96, 0x5F, 0xB3, 0x00, 0x46, 0xF1, 0x53, 0x91] +gDxePlatformFfsGuid = [ 0xABBCE13D, 0xE25A, 0x4d9f, 0xA1, 0xF9, 0x2F, 0x77, 0x10, 0x78, 0x68, 0x92 ] +gGnrDxePlatformFfsGuid = [ 0xDE1E3282, 0xC8D6, 0x40AD, 0x95, 0x7E, 0xFB, 0xED, 0x9A, 0x49, 0x1F, 0x6D ] +gAdvancedPkgListGuid = [ 0xc09c81cb, 0x31e9, 0x4de6, 0xa9, 0xf9, 0x17, 0xa1, 0x44, 0x35, 0x42, 0x45 ] + +gSocketSetupDriverFfsGuid = [ 0x6B6FD380, 0x2C55, 0x42C6, 0x98, 0xBF, 0xCB, 0xBC, 0x5A, 0x9A, 0xA6, 0x66 ] +gSocketPkgListGuid = [ 0x5c0083db, 0x3f7d, 0x4b20, 0xac, 0x9b, 0x73, 0xfc, 0x65, 0x1b, 0x25, 0x03 ] + +gSvSetupDriverFfsGuid = [ 0x5498AB03, 0x63AE, 0x41A5, 0xB4, 0x90, 0x29, 0x94, 0xE2, 0xDA, 0xC6, 0x8D ] +gSvPkgListGuid = [ 0xaec3ff43, 0xa70f, 0x4e01, 0xa3, 0x4b, 0xee, 0x1d, 0x11, 0xaa, 0x21, 0x69 ] + +gFpgaDriverFfsGuid = [ 0xBCEA6548, 0xE204, 0x4486, 0x8F, 0x2A, 0x36, 0xE1, 0x3C, 0x78, 0x38, 0xCE ] +gFpgaPkgListGuid = [ 0x22819110, 0x7f6f, 0x4852, 0xb4, 0xbb, 0x13, 0xa7, 0x70, 0x14, 0x9b, 0x0c ] + +gPcGenSetupDriverFfsGuid = [ 0xCB105C8B, 0x3B1F, 0x4117, 0x99, 0x3B, 0x6D, 0x18, 0x93, 0x39, 0x37, 0x16 ] + +gClientSetupFfsGuid = [ 0xE6A7A1CE, 0x5881, 0x4b49, 0x80, 0xBE, 0x69, 0xC9, 0x18, 0x11, 0x68, 0x5C ] +gClientUiApp1FfsGuid = [ 0xD89A7D8B, 0xD016, 0x4D26, 0x93, 0xE3, 0xEA, 0xB6, 0xB4, 0xD3, 0xB0, 0xA2 ] +gClientUiApp2FfsGuid = [ 0x462CAA21, 0x7614, 0x4503, 0x83, 0x6E, 0x8A, 0xB6, 0xF4, 0x66, 0x23, 0x31 ] +gClientTestMenuSetupFfsGuid = [ 0x21535212, 0x83d1, 0x4d4a, 0xae, 0x58, 0x12, 0xf8, 0x4d, 0x1f, 0x71, 0x0d ] +gDefaultDataOptSizeFileGuid = [ 0x003e7b41, 0x98a2, 0x4be2, 0xb2, 0x7a, 0x6c, 0x30, 0xc7, 0x65, 0x52, 0x25 ] +gDefaultDataFileGuid = [ 0x1ae42876, 0x008f, 0x4161, 0xb2, 0xb7, 0x1c, 0xd, 0x15, 0xc5, 0xef, 0x43 ] +gDefaultDataCpxFileGuid = [ 0x9971614C, 0x8DD6, 0x4275, 0x85, 0x2f, 0xae, 0x7c, 0xbc, 0xd3, 0xad, 0x85 ] +gVpdGuid = [ 0xff7db236, 0xf856, 0x4924, 0x90, 0xf8, 0xcd, 0xf1, 0x2f, 0xb8, 0x75, 0xf3 ] + +gEfiIfrAttractGuid = [ 0xd0bc7cb4, 0x6a47, 0x495f, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 ] +gEfiUniStrAttractGuid = [ 0x8913c5e0, 0x33f6, 0x4d86, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 ] + +gEfiSetupVariableGuid = [ 0xec87d643, 0xeba4, 0x4bb5, 0xa1, 0xe5, 0x3f, 0x3e, 0x36, 0xb2, 0x0d, 0xa9 ] +gEfiBiosIdGuid = [ 0xC3E36D09, 0x8294, 0x4b97, 0xA8, 0x57, 0xD5, 0x28, 0x8F, 0xE3, 0x3E, 0x28 ] +gCpPcBiosIdFileGuid = [ 0x372f8c51, 0xc43b, 0x472a, 0x82, 0xaf, 0x54, 0xb5, 0xc3, 0x23, 0x4d, 0x7f ] + +gEmulationDriverFfsGuid = [ 0x6BB0C4DE, 0xDCA4, 0x4f3e, 0xBC, 0xA8, 0x33, 0x06, 0x35, 0xDA, 0x4E, 0xF3 ] +gEmulatioPkgListGuid = [ 0x52b3b56e, 0xe716, 0x455f, 0xa5, 0xe3, 0xb3, 0x14, 0xf1, 0x8e, 0x6c, 0x5d ] + +gMerlinXAppGuid = [ 0xA3D1DDB4, 0xADB2, 0x4a08, 0xA0, 0x38, 0x73, 0x05, 0x67, 0x30, 0xE8, 0x53 ] + +ZeroGuid = [ 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] +AllFsGuid = [ 0xFFFFFFFF, 0xFFFF, 0xFFFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ] +MICRO_CODE_FIRMWARE_GUIDS = [ + (0x4924F856197DB236, 0xF375B82FF1CDF890), + (0x41fb3b4eb53105f3, 0x97e2f0648f101083), + (0x475E8179A18F0468, 0x9691036FBD6F86A8), + (0x43bcc0438c614c1d, 0x276cc2d608a0eb87), + (0X4F31640B713D38AB, 0X3A2683073E03AB90), + (0X4E93FE18908F49AD, 0X4A87C0FB74D6598C), +] + +FFSfileTypesDict = { 0x00 : 'FV_FILETYPE_ALL', 0x01 : 'FV_FILETYPE_RAW', 0x02 : 'FV_FILETYPE_FREEFORM', 0x03 : 'FV_FILETYPE_SECURITY_CORE', 0x04 : 'FV_FILETYPE_PEI_CORE', 0x05 : 'FV_FILETYPE_DXE_CORE', 0x06 : 'FV_FILETYPE_PEIM', 0x07 : 'FV_FILETYPE_DRIVER', 0x08 : 'FV_FILETYPE_COMBINED_PEIM_DRIVER', 0x09 : 'FV_FILETYPE_APPLICATION', 0x0A : 'FV_FILETYPE_SMM', 0x0B : 'FV_FILETYPE_FIRMWARE_VOLUME_IMAGE', 0x0C : 'FV_FILETYPE_COMBINED_SMM_DXE', 0x0D : 'FV_FILETYPE_SMM_CORE', 0xC0 : 'FV_FILETYPE_OEM_MIN', 0xDF : 'FV_FILETYPE_OEM_MAX', 0xE0 : 'FV_FILETYPE_DEBUG_MIN', 0xEF : 'FV_FILETYPE_DEBUG_MAX', 0xFF : 'FV_FILETYPE_FFS_MAX', 0xF0 : 'FV_FILETYPE_FFS_PAD' } +FFSsectionTypeDict = { 0x00 : 'EFI_SECTION_ALL', 0x01 : 'EFI_SECTION_COMPRESSION', 0x02 : 'EFI_SECTION_GUID_DEFINED', 0x10 : 'EFI_SECTION_PE32', 0x11 : 'EFI_SECTION_PIC', 0x12 : 'EFI_SECTION_TE', 0x13 : 'EFI_SECTION_DXE_DEPEX', 0x14 : 'EFI_SECTION_VERSION', 0x15 : 'EFI_SECTION_USER_INTERFACE', 0x16 : 'EFI_SECTION_COMPATIBILITY16', 0x17 : 'EFI_SECTION_FIRMWARE_VOLUME_IMAGE', 0x18 : 'EFI_SECTION_FREEFORM_SUBTYPE_GUID', 0x19 : 'EFI_SECTION_RAW', 0x1B : 'EFI_SECTION_PEI_DEPEX', 0x1C : 'EFI_SECTION_SMM_DEPEX' } +GuidedSectAtrbDict = { 0x01 : 'EFI_GUIDED_SECTION_PROCESSING_REQUIRED', 0x02 : 'EFI_GUIDED_SECTION_AUTH_STATUS_VALID' } +HiiPkgHdrTypeDict = { 0x00 : 'EFI_HII_PACKAGE_TYPE_ALL', 0x01 : 'EFI_HII_PACKAGE_TYPE_GUID', 0x02 : 'EFI_HII_PACKAGE_FORMS', 0x04 : 'EFI_HII_PACKAGE_STRINGS', 0x05 : 'EFI_HII_PACKAGE_FONTS', 0x06 : 'EFI_HII_PACKAGE_IMAGES', 0x07 : 'EFI_HII_PACKAGE_SIMPLE_FONTS', 0x08 : 'EFI_HII_PACKAGE_DEVICE_PATH', 0x09 : 'EFI_HII_PACKAGE_KEYBOARD_LAYOUT', 0x0A : 'EFI_HII_PACKAGE_ANIMATIONS', 0xDF : 'EFI_HII_PACKAGE_END', 0xE0 : 'EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN', 0xFF : 'EFI_HII_PACKAGE_TYPE_SYSTEM_END' } +IfrOpcodesDict = { 0x01 : 'EFI_IFR_FORM_OP', 0x02 : 'EFI_IFR_SUBTITLE_OP', 0x03 : 'EFI_IFR_TEXT_OP', 0x04 : 'EFI_IFR_IMAGE_OP', 0x05 : 'EFI_IFR_ONE_OF_OP', 0x06 : 'EFI_IFR_CHECKBOX_OP', 0x07 : 'EFI_IFR_NUMERIC_OP', 0x08 : 'EFI_IFR_PASSWORD_OP', 0x09 : 'EFI_IFR_ONE_OF_OPTION_OP', 0x0A : 'EFI_IFR_SUPPRESS_IF_OP', 0x0B : 'EFI_IFR_LOCKED_OP', 0x0C : 'EFI_IFR_ACTION_OP', 0x0D : 'EFI_IFR_RESET_BUTTON_OP', 0x0E : 'EFI_IFR_FORM_SET_OP', 0x0F : 'EFI_IFR_REF_OP', 0x10 : 'EFI_IFR_NO_SUBMIT_IF_OP', 0x11 : 'EFI_IFR_INCONSISTENT_IF_OP', 0x12 : 'EFI_IFR_EQ_ID_VAL_OP', 0x13 : 'EFI_IFR_EQ_ID_ID_OP', 0x14 : 'EFI_IFR_EQ_ID_VAL_LIST_OP', 0x15 : 'EFI_IFR_AND_OP', 0x16 : 'EFI_IFR_OR_OP', 0x17 : 'EFI_IFR_NOT_OP', 0x18 : 'EFI_IFR_RULE_OP', 0x19 : 'EFI_IFR_GRAY_OUT_IF_OP', 0x1A : 'EFI_IFR_DATE_OP', 0x1B : 'EFI_IFR_TIME_OP', 0x1C : 'EFI_IFR_STRING_OP', 0x1D : 'EFI_IFR_REFRESH_OP', 0x1E : 'EFI_IFR_DISABLE_IF_OP', 0x1F : 'EFI_IFR_ANIMATION_OP', 0x20 : 'EFI_IFR_TO_LOWER_OP', 0x21 : 'EFI_IFR_TO_UPPER_OP', 0x22 : 'EFI_IFR_MAP_OP', 0x23 : 'EFI_IFR_ORDERED_LIST_OP', 0x24 : 'EFI_IFR_VARSTORE_OP', 0x25 : 'EFI_IFR_VARSTORE_NAME_VALUE_OP', 0x26 : 'EFI_IFR_VARSTORE_EFI_OP', 0x27 : 'EFI_IFR_VARSTORE_DEVICE_OP', 0x28 : 'EFI_IFR_VERSION_OP', 0x29 : 'EFI_IFR_END_OP', 0x2A : 'EFI_IFR_MATCH_OP', 0x2B : 'EFI_IFR_GET_OP', 0x2C : 'EFI_IFR_SET_OP', 0x2D : 'EFI_IFR_READ_OP', 0x2E : 'EFI_IFR_WRITE_OP', 0x2F : 'EFI_IFR_EQUAL_OP', 0x30 : 'EFI_IFR_NOT_EQUAL_OP', 0x31 : 'EFI_IFR_GREATER_THAN_OP', 0x32 : 'EFI_IFR_GREATER_EQUAL_OP', 0x33 : 'EFI_IFR_LESS_THAN_OP', 0x34 : 'EFI_IFR_LESS_EQUAL_OP', 0x35 : 'EFI_IFR_BITWISE_AND_OP', 0x36 : 'EFI_IFR_BITWISE_OR_OP', 0x37 : 'EFI_IFR_BITWISE_NOT_OP', 0x38 : 'EFI_IFR_SHIFT_LEFT_OP', 0x39 : 'EFI_IFR_SHIFT_RIGHT_OP', 0x3A : 'EFI_IFR_ADD_OP', 0x3B : 'EFI_IFR_SUBTRACT_OP', 0x3C : 'EFI_IFR_MULTIPLY_OP', 0x3D : 'EFI_IFR_DIVIDE_OP', 0x3E : 'EFI_IFR_MODULO_OP', 0x3F : 'EFI_IFR_RULE_REF_OP', 0x40 : 'EFI_IFR_QUESTION_REF1_OP', 0x41 : 'EFI_IFR_QUESTION_REF2_OP', 0x42 : 'EFI_IFR_UINT8_OP', 0x43 : 'EFI_IFR_UINT16_OP', 0x44 : 'EFI_IFR_UINT32_OP', 0x45 : 'EFI_IFR_UINT64_OP', 0x46 : 'EFI_IFR_TRUE_OP', 0x47 : 'EFI_IFR_FALSE_OP', 0x48 : 'EFI_IFR_TO_UINT_OP', 0x49 : 'EFI_IFR_TO_STRING_OP', 0x4A : 'EFI_IFR_TO_BOOLEAN_OP', 0x4B : 'EFI_IFR_MID_OP', 0x4C : 'EFI_IFR_FIND_OP', 0x4D : 'EFI_IFR_TOKEN_OP', 0x4E : 'EFI_IFR_STRING_REF1_OP', 0x4F : 'EFI_IFR_STRING_REF2_OP', 0x50 : 'EFI_IFR_CONDITIONAL_OP', 0x51 : 'EFI_IFR_QUESTION_REF3_OP', 0x52 : 'EFI_IFR_ZERO_OP', 0x53 : 'EFI_IFR_ONE_OP', 0x54 : 'EFI_IFR_ONES_OP', 0x55 : 'EFI_IFR_UNDEFINED_OP', 0x56 : 'EFI_IFR_LENGTH_OP', 0x57 : 'EFI_IFR_DUP_OP', 0x58 : 'EFI_IFR_THIS_OP', 0x59 : 'EFI_IFR_SPAN_OP', 0x5A : 'EFI_IFR_VALUE_OP', 0x5B : 'EFI_IFR_DEFAULT_OP', 0x5C : 'EFI_IFR_DEFAULTSTORE_OP', 0x5D : 'EFI_IFR_FORM_MAP_OP', 0x5E : 'EFI_IFR_CATENATE_OP', 0x5F : 'EFI_IFR_GUID_OP', 0x60 : 'EFI_IFR_SECURITY_OP', 0x61 : 'EFI_IFR_MODAL_TAG_OP', 0x62 : 'EFI_IFR_REFRESH_ID_OP', 0x63 : 'EFI_IFR_WARNING_IF_OP' } + +PrintLogFile = os.path.join(clb.TempFolder, 'UefiFwParser.log') +TabLevel = 0 + +def WriteList(buffer, offset, size, Value): + for count in range (0, size): + buffer[offset+count] = clb.ListInsertVal(Value >> (count*8)) + +def PrintLog(String, LogFile): + global TabLevel + if(FwpLogEn or FwpPrintEn): + Tab = '' + for count in range (0, TabLevel): + Tab = Tab + ' |' + String = '|' + Tab + String + if(FwpPrintEn): + log.result(f'{String}') + if ( (LogFile != 0) and FwpLogEn ): + LogFile.write(String+'\n') + +def DelTempFvFfsFiles(Folder): + DelFileTypes = ['*.fv', '*.ffs', '*.sec', '*.guided', '*.tmp'] + for FileType in DelFileTypes: + TempFvFileList = glob.glob(os.path.join(Folder, FileType)) + for TempFile in TempFvFileList: + clb.RemoveFile(TempFile) + +def ProcessBin(BiosBinListBuff=[], BiosFvBase=0x800000, Files2saveGuidList=[], LogFile=0, SkipGuidedSec=False, IsCmprFv=False, BiosRegionEnd=0): + global TabLevel, FileGuidListDict, FileSystemSaveCount, MulSetupDrivers + + if(BiosRegionEnd == 0): + BiosRegionEnd = len(BiosBinListBuff) + PrintLog('-----------------------------------------------------------------------------------------------------', LogFile) + HeaderGuid = clb.FetchGuid(BiosBinListBuff, BiosFvBase) + if(HeaderGuid == gBiosCapsuleGuid): + BiosFvBase = BiosFvBase + clb.ReadList(BiosBinListBuff, (BiosFvBase + 0x10), 4) + for FvCount in range (0, 8000): + if (BiosFvBase >= BiosRegionEnd): + break + FvZeroVect = clb.FetchGuid(BiosBinListBuff, BiosFvBase) + FvGuid = clb.FetchGuid(BiosBinListBuff, (BiosFvBase + 0x10)) + if( (FvZeroVect == ZeroGuid) and (FvGuid != ZeroGuid) ): # Every valid FV needs to have this zero vector. + FvSize = clb.ReadList(BiosBinListBuff, (BiosFvBase + 0x20), 8) + if ( (FvGuid == AllFsGuid) and (FvSize == 0xFFFFFFFFFFFFFFFF) ): + BiosFvBase = ((BiosFvBase & 0xFFFFF000) + 0x1000) + continue # InValid FV, skip this iteration + if(FvGuid == gEfiFirmwareFileSystemGuid): + FileSystemTypeFound = 1 + elif(FvGuid == gEfiFirmwareFileSystem2Guid): + FileSystemTypeFound = 2 + elif(FvGuid == gEfiFirmwareFileSystem3Guid): + FileSystemTypeFound = 3 + else: + FileSystemTypeFound = 0 + FvSignature = clb.ReadList(BiosBinListBuff, (BiosFvBase + 0x28), 4, clb.ASCII) + if (FvSignature!='_FVH'): #'_FVH' = 0x4856465F + BiosFvBase = ((BiosFvBase & 0xFFFFF000) + 0x1000) + continue # InValid FV, skip this iteration + FvHdrLen = clb.ReadList(BiosBinListBuff, (BiosFvBase + 0x30), 2) + FVChecksum = clb.ReadList(BiosBinListBuff, (BiosFvBase + 0x32), 2) + ExtHdrOffset = clb.ReadList(BiosBinListBuff, (BiosFvBase + 0x34), 2) + FvRev = clb.ReadList(BiosBinListBuff, (BiosFvBase + 0x37), 1) + FvBlocks = clb.ReadList(BiosBinListBuff, (BiosFvBase + 0x38), 4) + BlockLen = clb.ReadList(BiosBinListBuff, (BiosFvBase + 0x3C), 4) + if(ExtHdrOffset): + FvNameGuid = clb.FetchGuid(BiosBinListBuff, (BiosFvBase+ExtHdrOffset)) + ExtHdrSize = clb.ReadList(BiosBinListBuff, (BiosFvBase+ExtHdrOffset+0x10), 4) + FvHdrLen = ExtHdrOffset + ExtHdrSize + PrintLog(' BiosFvBase = 0x%08X FvSize : 0x%X FvSignature = \"%s\" FvHdrLen = 0x%X ExtHdrOfst = 0x%X' %(BiosFvBase, FvSize, FvSignature, FvHdrLen, ExtHdrOffset), LogFile) + if(ExtHdrOffset): + PrintLog(' FvNameGuid = %s' %clb.GuidStr(FvNameGuid), LogFile) + PrintLog(' FVChecksum = 0x%X FvRev = 0x%X NoOfBlocks = 0x%X BlockLen = 0x%X FileSystemType = %d' %(FVChecksum, FvRev, FvBlocks, BlockLen, FileSystemTypeFound), LogFile) + PrintLog(' FvGuid : %s ' %clb.GuidStr(FvGuid), LogFile) + BiosFFsbase = BiosFvBase+FvHdrLen + FileSystembase = (BiosFFsbase + 7 ) & 0xFFFFFFF8 # this is because FileSystem sits on a 8 byte boundary + if (FileSystembase >= (BiosFvBase + FvSize)): + TabLevel = TabLevel - 1 + PrintLog('-------------------------------------------------------------------------------------', LogFile) + BiosFvBase = (BiosFvBase + FvSize) + continue + FirstFsGuid = clb.FetchGuid(BiosBinListBuff, FileSystembase) + if ( FirstFsGuid != AllFsGuid ): + for FileGuid in Files2saveGuidList: + if ( FvGuid == FileGuid ): + FvFileName = os.path.join(clb.TempFolder, '%X_File.fv' %FvGuid[0]) + if(os.path.isfile(FvFileName)): + FvFileName = os.path.join(clb.TempFolder, '%X_Copy_File.fv' %FvGuid[0]) + PrintLog(' ++++++++++ Saving FV file as %s ++++++++++ |' %FvFileName, LogFile) + with open(FvFileName, 'wb') as FfsFile: + FfsFile.write(bytearray(BiosBinListBuff[BiosFvBase:BiosFvBase+FvSize])) + FileGuidListDict[FileSystemSaveCount] = {'FileGuid':FileGuid, 'BiosBinPointer':BiosFvBase, 'FileSystemSize':FvSize} + FileSystemSaveCount = FileSystemSaveCount + 1 + if(FileSystemSaveCount >= len(Files2saveGuidList)): + TabLevel = 0 + return + break + TabLevel = TabLevel + 1 + PrintLog('-------------------------------------------------------------------------------------', LogFile) + for FfsCount in range (0, 8000): + if(FileSystemTypeFound == 0): + PrintLog(' Unknown FileSystem, skipping File System Parsing for current FV....', LogFile) + break + BiosFFsbase = (BiosFFsbase + 7 ) & 0xFFFFFFF8 # this is because FFS sits on a 8 byte boundary + if ((BiosFFsbase >= (BiosFvBase + FvSize)) or ((BiosFFsbase+FFS_FILE_HEADER_SIZE) >= BiosRegionEnd)): + break + FFsGuid = clb.FetchGuid(BiosBinListBuff, BiosFFsbase) + if ( FFsGuid == ZeroGuid ): + break + FFShdrChksm = clb.ReadList(BiosBinListBuff, (BiosFFsbase+0x10), 1) + FFSfileChksm = clb.ReadList(BiosBinListBuff, (BiosFFsbase+0x11), 1) + FFSfileType = clb.ReadList(BiosBinListBuff, (BiosFFsbase+0x12), 1) + FFSAttr = clb.ReadList(BiosBinListBuff, (BiosFFsbase+0x13), 1) + FfsHeaderSize = FFS_FILE_HEADER_SIZE + FFSsize = clb.ReadList(BiosBinListBuff, BiosFFsbase+0x14, 3) + if((FFSsize == 0xFFFFFF) or ((FFSAttr & FFS_ATTRIB_LARGE_FILE) == FFS_ATTRIB_LARGE_FILE)): + FfsHeaderSize = FFS_FILE_HEADER2_SIZE + FFSsize = clb.ReadList(BiosBinListBuff, BiosFFsbase+FFS_FILE_HEADER_SIZE, 4) + if ( ((FFsGuid == AllFsGuid) and (FFSsize == 0xFFFFFFFF)) or (FFSsize == 0) ): + break # InValid FFS, break from FFS loop + FFSsectionSize = clb.ReadList(BiosBinListBuff, BiosFFsbase+FfsHeaderSize, 3) + FFSsectionType = clb.ReadList(BiosBinListBuff, BiosFFsbase+FfsHeaderSize+3, 1) + for FileGuid in Files2saveGuidList: + if ( FFsGuid == FileGuid ): + FfsFileName = os.path.join(clb.TempFolder, '%X_File.ffs' %FFsGuid[0]) + if(os.path.isfile(FfsFileName)): + if(FileGuid in SetupDriverGuidList): + MulSetupDrivers = True + FfsFileName = os.path.join(clb.TempFolder, '%X_Copy_File.ffs' %FFsGuid[0]) + PrintLog(' ++++++++++ Saving FFS file as %s ++++++++++ |' %FfsFileName, LogFile) + with open(FfsFileName, 'wb') as FfsFile: + FfsFile.write(bytearray(BiosBinListBuff[BiosFFsbase:BiosFFsbase+FFSsize])) + FileGuidListDict[FileSystemSaveCount] = {'FileGuid':FileGuid, 'BiosBinPointer':BiosFFsbase, 'FileSystemSize':FFSsize} + FileSystemSaveCount = FileSystemSaveCount + 1 + if(FileSystemSaveCount >= len(Files2saveGuidList)): + TabLevel = 0 + return + break + PrintLog(' BiosFFSbase = 0x%08X FFSsize : 0x%X FFShdrChksm 0x%X FFSfileChksm = 0x%X ' %(BiosFFsbase, FFSsize, FFShdrChksm, FFSfileChksm), LogFile) + PrintLog(' FFSfileType = \"%s\" FFSAttr = 0x%X ' %(FFSfileTypesDict.get(FFSfileType, 'NA'), FFSAttr), LogFile) + PrintLog(' FFSsectionSize = 0x%X FFSsectionType = \"%s\" ' %(FFSsectionSize, FFSsectionTypeDict.get(FFSsectionType, 'NA')), LogFile) + PrintLog(' FFSguid : %s ' %clb.GuidStr(FFsGuid), LogFile) + + if(FFSfileType == FV_FILETYPE_FIRMWARE_VOLUME_IMAGE): + TabLevel = TabLevel + 1 + Temp2Buff = BiosBinListBuff + Temp2BiosFVbase = BiosFvBase + Temp2BiosFFsbase = BiosFFsbase + Temp2FFSsize = FFSsize + Temp2FvSize = FvSize + TempBinPtr = BiosFFsbase + FfsHeaderSize + for SecCount in range (0, 0x8000, 1): + if(TempBinPtr >= (BiosFFsbase+FFSsize)): + break + SectionSize = clb.ReadList(BiosBinListBuff, TempBinPtr, 3) + SectionType = clb.ReadList(BiosBinListBuff, TempBinPtr+3, 1) + SecHdrSize = 4 + if(SectionSize == 0xFFFFFF): + SectionSize = clb.ReadList(BiosBinListBuff, TempBinPtr+4, 4) + SecHdrSize = 8 + if(SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE): + PrintLog(' Section FIRMWARE_VOLUME_IMAGE Found, parsing start...', LogFile) + ProcessBin(BiosBinListBuff[(TempBinPtr+SecHdrSize):(TempBinPtr+SectionSize)], 0, Files2saveGuidList, LogFile, False, False) + PrintLog(' Section FIRMWARE_VOLUME_IMAGE parsing complete...', LogFile) + TempBinPtr = (TempBinPtr + SectionSize + 3) & 0xFFFFFFFC + BiosBinListBuff = Temp2Buff + BiosFvBase = Temp2BiosFVbase + BiosFFsbase = Temp2BiosFFsbase + FFSsize = Temp2FFSsize + FvSize = Temp2FvSize + TabLevel = TabLevel - 1 + + FoundAlgorithmSha256 = False + if( (FFSsectionType == EFI_SECTION_GUID_DEFINED) and (SkipGuidedSec == False) ): + SectionGuid = clb.FetchGuid(BiosBinListBuff, (BiosFFsbase+FfsHeaderSize+4)) + FFSsectionDataStart = 0 + if (SectionGuid == gEfiFirmwareContentsSignedGuid): + SignSecBuffStartOfst = clb.ReadList(BiosBinListBuff, (BiosFFsbase+FfsHeaderSize+4+0x10), 2) + SignSecBuffSize = clb.ReadList(BiosBinListBuff, (BiosFFsbase+FfsHeaderSize+SignSecBuffStartOfst), 4) + if( (gEfiCertTypeRsa2048Sha256Guid == clb.FetchGuid(BiosBinListBuff, (BiosFFsbase+FfsHeaderSize+SignSecBuffStartOfst+8))) and (gEfiHashAlgorithmSha256Guid == clb.FetchGuid(BiosBinListBuff, (BiosFFsbase+FfsHeaderSize+SignSecBuffStartOfst+0x18))) ): + FoundAlgorithmSha256 = True + FFSsectionDataStart = SignSecBuffStartOfst + SignSecBuffSize + FFSsectionSize = clb.ReadList(BiosBinListBuff, (BiosFFsbase+FfsHeaderSize+FFSsectionDataStart), 3) + SectionGuid = clb.FetchGuid(BiosBinListBuff, (BiosFFsbase+FfsHeaderSize+FFSsectionDataStart+4)) + if (SectionGuid == gEfiCertTypeRsa2048Sha256Guid): + SignSecBuffStartOfst = clb.ReadList(BiosBinListBuff, (BiosFFsbase+FfsHeaderSize+4+0x10), 2) + if(gEfiHashAlgorithmSha256Guid == clb.FetchGuid(BiosBinListBuff, (BiosFFsbase+FfsHeaderSize+0x18))): + FoundAlgorithmSha256 = True + FFSsectionDataStart = SignSecBuffStartOfst + 0x210 + FFSsectionSize = clb.ReadList(BiosBinListBuff, (BiosFFsbase+FfsHeaderSize+FFSsectionDataStart), 3) + SectionGuid = clb.FetchGuid(BiosBinListBuff, (BiosFFsbase+FfsHeaderSize+FFSsectionDataStart+4)) + if ((SectionGuid == gLzmaCustomDecompressGuid) or (SectionGuid == gBrotliCustomDecompressGuid)): + if (FFSfileType == FV_FILETYPE_FIRMWARE_VOLUME_IMAGE): + PrintLog(' Current compressed Section is FIRMWARE_VOLUME_IMAGE, decompresing and parsing it...', LogFile) + LzmaBuffStart = FFSsectionDataStart+clb.ReadList(BiosBinListBuff, (BiosFFsbase+FfsHeaderSize+FFSsectionDataStart+4+0x10), 2) + LzmaFvMainCompactBuff = bytearray(BiosBinListBuff[(BiosFFsbase+FfsHeaderSize+LzmaBuffStart):(BiosFFsbase+FfsHeaderSize+FFSsectionDataStart+FFSsectionSize)]) + FvInFileLocation = os.path.join(clb.TempFolder, 'FwComp.sec') + FvOutFileLocation = os.path.join(clb.TempFolder, 'FwVol.fv') + with open(FvInFileLocation, 'wb') as TmpFile: + TmpFile.write(LzmaFvMainCompactBuff) + if SectionGuid == gLzmaCustomDecompressGuid: + PrintLog(' Found LZMA Compressed section', LogFile) + compress.lzma_decompress(FvInFileLocation, FvOutFileLocation) + if SectionGuid == gBrotliCustomDecompressGuid: + PrintLog(' Found Brotli Compressed section', LogFile) + utils.system_call(cmd_lis=[clb.BrotliCompressUtility, "-d", "-i", FvInFileLocation, "-o", FvOutFileLocation]) + with open(FvOutFileLocation, 'rb') as TmpFile: + FvMainListBuffer = list(TmpFile.read()) + + TabLevel = TabLevel + 1 + TempBuff = BiosBinListBuff + TempBiosFVbase = BiosFvBase + TempBiosFFsbase = BiosFFsbase + TempFFSsize = FFSsize + TempFvSize = FvSize + FvMainListSize = len(FvMainListBuffer) + TempBinPtr = 0 + for SecCount in range (0, 0x8000, 1): + if(TempBinPtr >= FvMainListSize): + break + SectionSize = clb.ReadList(FvMainListBuffer, TempBinPtr, 3) + SectionType = clb.ReadList(FvMainListBuffer, TempBinPtr+3, 1) + SecHdrSize = 4 + if(SectionSize == 0xFFFFFF): + SectionSize = clb.ReadList(FvMainListBuffer, TempBinPtr+4, 4) + SecHdrSize = 8 + if(SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE): + PrintLog(' Section FIRMWARE_VOLUME_IMAGE Found, parsing start...', LogFile) + ProcessBin(FvMainListBuffer[(TempBinPtr+SecHdrSize):(TempBinPtr+SectionSize)], 0, Files2saveGuidList, LogFile, False, True) + PrintLog(' Section FIRMWARE_VOLUME_IMAGE parsing complete...', LogFile) + TempBinPtr = (TempBinPtr + SectionSize + 3) & 0xFFFFFFFC + + PrintLog(' Uncompressed FIRMWARE_VOLUME_IMAGE parsing complete...', LogFile) + BiosBinListBuff = TempBuff + BiosFvBase = TempBiosFVbase + BiosFFsbase = TempBiosFFsbase + FFSsize = TempFFSsize + FvSize = TempFvSize + TabLevel = TabLevel - 1 + clb.RemoveFile(FvOutFileLocation) + clb.RemoveFile(FvInFileLocation) + if( (FileSystemSaveCount != 0) and (FileSystemSaveCount >= len(Files2saveGuidList)) ): + TabLevel = 0 + return + BiosFFsbase = (BiosFFsbase + FFSsize + 7 ) & 0xFFFFFFF8 # this is because FFS sits on a 8 byte boundary + PrintLog('-------------------------------------------------------------------------------------', LogFile) + TabLevel = TabLevel - 1 + PrintLog('-----------------------------------------------------------------------------------------------------', LogFile) + BiosFvBase = (BiosFvBase + FvSize) + else: + BiosFvBase = ((BiosFvBase & 0xFFFFF000) + 0x1000) # InValid FV, Adjust FvBaseAccrodingly + +def UpdateBiosId(BiosBinaryFile=0, NewMajorVer='', NewMinorVer='', OutFolder=0, NewBiosVer='', NewTsVer='', NewXxYy=''): + global FileGuidListDict, FwpPrintEn + tmpPrintSts = FwpPrintEn + FwpPrintEn = False + FileGuidListDict = {} + BiosIdFfsToSave = [ gEfiBiosIdGuid ] + BiosIdString = 'Unknown' + NewBiosId = BiosIdString + clb.OutBinFile = '' + + if(OutFolder == 0): + OutFolder = clb.TempFolder + DelTempFvFfsFiles(clb.TempFolder) + with open(BiosBinaryFile, 'rb') as BiosBinFile: + BiosBinListBuff = list(BiosBinFile.read()) + BiosFileName = os.path.basename(BiosBinaryFile) + FlashRegionInfo(BiosBinListBuff, False) + if (FwIngredientDict['FlashDescpValid'] != 0): + BiosRegionBase = FwIngredientDict['FlashRegions'][BIOS_Region]['BaseAddr'] + BiosEnd = FwIngredientDict['FlashRegions'][BIOS_Region]['EndAddr'] + 1 + else: + BiosRegionBase = 0 + BiosEnd = len(BiosBinListBuff) + + if(len(BiosBinListBuff) != 0): + ProcessBin(BiosBinListBuff, BiosRegionBase, BiosIdFfsToSave, 0, True, BiosRegionEnd=BiosEnd) + for FileGuid in BiosIdFfsToSave: # Delete the file once done, dont want the stale file affecting subsequent operation + clb.RemoveFile(os.path.join(clb.TempFolder, '%X_File.ffs' %FileGuid[0])) + clb.RemoveFile(os.path.join(clb.TempFolder, '%X_File.fv' %FileGuid[0])) + for FileCountId in FileGuidListDict: + if(FileGuidListDict[FileCountId]['FileGuid'] == gEfiBiosIdGuid): + BiosIdSecBase = FileGuidListDict[FileCountId]['BiosBinPointer'] + FFS_FILE_HEADER_SIZE + EFI_COMMON_SECTION_HEADER_SIZE + FfsSize = FileGuidListDict[FileCountId]['FileSystemSize'] + BiosIdString = '' + BiosIdSig = clb.ReadList(BiosBinListBuff, BiosIdSecBase, 8) + if(BiosIdSig != 0): + for count in range (0, (FfsSize-FFS_FILE_HEADER_SIZE-EFI_COMMON_SECTION_HEADER_SIZE)): + ChrVal = clb.ReadList(BiosBinListBuff, (BiosIdSecBase+8+(count*2)), 1) + if(ChrVal == 0): + break + BiosIdString = BiosIdString + chr(ChrVal) + log.info( 'Current BIOS ID String is %s' %(BiosIdString)) + NewBiosId = BiosIdString.split('.') + if(BiosIdString != 'Unknown'): + if ((NewBiosVer != '') or (NewMajorVer != '') or (NewMinorVer != '') or (NewTsVer != '')) or ((len(NewBiosId) == 6) and (NewXxYy !='')): + SkipNewBiosVer = False + if(len(NewBiosId) == 6): + TStmpPos = 5 + SkipNewBiosVer = True + if(NewXxYy != ''): + NewBiosId[4] = NewXxYy.zfill(4)[0:4] + else: + TStmpPos = 4 + if(NewMajorVer != ''): + NewBiosId[2] = NewMajorVer.zfill(4)[0:4] + if(NewMinorVer != ''): + NewBiosId[3] = NewMinorVer.zfill(3)[0:3] + if(SkipNewBiosVer == False): + if(NewBiosVer != ''): + NewBiosId[1] = NewBiosVer.zfill(3)[0:3] + else: + NewBiosId[1] = 'E9I' # indicates that the BIOS ID was updated using external Tool. + if(NewTsVer != ''): + NewBiosId[TStmpPos] = NewTsVer.zfill(10)[0:10] + else: + CurTime = time.localtime() + NewBiosId[TStmpPos] = '%02d%02d%02d%02d%02d' %((CurTime[0]-2000), CurTime[1], CurTime[2], CurTime[3], CurTime[4]) + NewBiosIdString = '.'.join(NewBiosId) + log.info(f'Updated BIOS ID String is {NewBiosIdString}') + for count in range (0, len(NewBiosIdString)): + ChrVal = clb.ReadList(BiosBinListBuff, (BiosIdSecBase+8+(count*2)), 1) + if(ChrVal == 0): + break + BiosBinListBuff.pop((BiosIdSecBase+8+(count*2))) + BiosBinListBuff.insert((BiosIdSecBase+8+(count*2)), clb.ListInsertVal(int(clb.HexLiFy(NewBiosIdString[count]), 16))) + NewBiosFileName = BiosFileName.replace(BiosIdString, NewBiosIdString) + if(NewBiosFileName == BiosFileName): + NewBiosFileName = NewBiosIdString+'.bin' + NewBiosBinFile = os.path.join(OutFolder, NewBiosFileName) + clb.OutBinFile = NewBiosBinFile + with open(NewBiosBinFile, 'wb') as ModBiosBinFile: + ModBiosBinFile.write(bytearray(BiosBinListBuff)) + log.info(f'Bios Binary with updated BIOS ID is saved under {NewBiosBinFile}') + else: + log.info('Ver, Major, Minor, and TS are empty, so no action taken.') + break + FwpPrintEn = tmpPrintSts +VARIABLE_HEADER_ALIGNMENT = 4 +VARIABLE_DATA = 0x55AA +VARIABLE_STORE_FORMATTED = 0x5a +VARIABLE_STORE_HEALTHY = 0xfe +VAR_IN_DELETED_TRANSITION = 0xfe # Variable is in obsolete transition. +VAR_DELETED = 0xfd # Variable is obsolete. +VAR_HEADER_VALID_ONLY = 0x7f # Variable header has been valid. +VAR_ADDED = 0x3f # Variable has been completely added. +VARIABLE_STORE_HEADER_SIZE = 0x1C +VARIABLE_HEADER2_SIZE = 0x3C +VARIABLE_HEADER_SIZE = 0x20 + +def ParseNvram(NvRamFvListBuffer, BiosKnobDict, NvRamPointer=0, LogFile=0): + BiosKnobDictLen = len(BiosKnobDict) + PrintLog(' Parse Full NvRam VarStores and Knob details ', LogFile) + NvRamDict = {} + VarCount = 0 + if(NvRamPointer == 0): + for CurrPtr in range (NvRamPointer, (len(NvRamFvListBuffer)-0x10)): + VarStoreHdrGuid = clb.FetchGuid(NvRamFvListBuffer, CurrPtr) + if( (VarStoreHdrGuid == gEfiGlobalVariableGuid) or (VarStoreHdrGuid == gEfiAuthenticatedVariableGuid) or (VarStoreHdrGuid == gEfiVariableGuid) ): + NvRamPointer = CurrPtr + PrintLog(' Found NvRam Start at 0x%X offset' %NvRamPointer, LogFile) + break + for VarStrHdrCount in range (0, 0x100): + if(NvRamPointer >= (len(NvRamFvListBuffer)-VARIABLE_STORE_HEADER_SIZE)): + return NvRamDict + VarStoreHdrGuid = clb.FetchGuid(NvRamFvListBuffer, NvRamPointer) + VarStoreSize = clb.ReadList(NvRamFvListBuffer, (NvRamPointer+0x10), 4) + if( (VarStoreHdrGuid == AllFsGuid) or (VarStoreSize == 0xFFFFFFFF) ): + break + if( (VarStoreHdrGuid == gEfiGlobalVariableGuid) or (VarStoreHdrGuid == gEfiAuthenticatedVariableGuid) ): + HdrSize = VARIABLE_HEADER2_SIZE + NameSzOffst = 0x24 + DataSzOffst = 0x28 + GuidOffset = 0x2C + elif(VarStoreHdrGuid == gEfiVariableGuid): + HdrSize = VARIABLE_HEADER_SIZE + NameSzOffst = 0x08 + DataSzOffst = 0x0C + GuidOffset = 0x10 + else: + HdrSize = VARIABLE_HEADER_SIZE + NameSzOffst = 0x08 + DataSzOffst = 0x0C + GuidOffset = 0x10 + VarStoreFormat = clb.ReadList(NvRamFvListBuffer, (NvRamPointer+0x14), 1) + VarStoreState = clb.ReadList(NvRamFvListBuffer, (NvRamPointer+0x15), 1) + PrintLog(' CurrPtr = 0x%X VarStoreSize = 0x%X' %(NvRamPointer, VarStoreSize), LogFile) + PrintLog(' VarStoreHdr Guid = %s ' %clb.GuidStr(VarStoreHdrGuid), LogFile) + if( (VarStoreFormat != VARIABLE_STORE_FORMATTED) or (VarStoreState != VARIABLE_STORE_HEALTHY) ): + NvRamPointer = NvRamPointer + VarStoreSize + break + CurVarPtr = ((NvRamPointer + VARIABLE_STORE_HEADER_SIZE + 3) & 0xFFFFFFFC) # this one is 4 bytes or dword aligned always + PrintLog ('------------|--------|------------|------------|--------------------------------|-------------', LogFile) + PrintLog (' CurrentPtr | State | Attribute | NvarDataSz | VarName | VarGuid ', LogFile) + PrintLog ('------------|--------|------------|------------|--------------------------------|-------------', LogFile) + for count in range (0, 200): + if(CurVarPtr >= len(NvRamFvListBuffer)): + break + StartId = clb.ReadList(NvRamFvListBuffer, CurVarPtr, 2) + if(StartId != VARIABLE_DATA): + CurVarPtr = CurVarPtr + HdrSize + break + VarState = clb.ReadList(NvRamFvListBuffer, (CurVarPtr+0x2), 1) + VarAtri = clb.ReadList(NvRamFvListBuffer, (CurVarPtr+0x4), 4) + VarNameSize = clb.ReadList(NvRamFvListBuffer, (CurVarPtr+NameSzOffst), 4) + VarDataSize = clb.ReadList(NvRamFvListBuffer, (CurVarPtr+DataSzOffst), 4) + VarGuid = clb.FetchGuid(NvRamFvListBuffer, (CurVarPtr+GuidOffset)) + VarName = '' + for index in range (0, int(VarNameSize/2)): + Val = clb.ReadList(NvRamFvListBuffer, (CurVarPtr+HdrSize+(index*2)), 1) + if(Val == 0): + break + VarName = VarName + chr(Val) + PrintLog (' 0x%-8X | 0x%02X | 0x%08X | 0x%-8X | %-30s | %s' %(CurVarPtr, VarState, VarAtri, VarDataSize, VarName, clb.GuidStr(VarGuid)), LogFile) + PrintLog ('------------|--------|------------|------------|--------------------------------|-------------', LogFile) + if(BiosKnobDictLen): + for VarId in BiosKnobDict: + if( (VarName == BiosKnobDict[VarId]['NvarName']) and ((BiosKnobDict[VarId]['NvarGuid'] == ZeroGuid) or (VarGuid == BiosKnobDict[VarId]['NvarGuid'])) ): + NvRamDict[VarId] = { 'NvarName':VarName, 'NvarGuid':VarGuid, 'NvarSize':VarDataSize, 'VarAttri':VarAtri, 'NvarDataBufPtr':(CurVarPtr+HdrSize+VarNameSize) } + break + else: + NvRamDict[VarCount] = { 'NvarName':VarName, 'NvarGuid':VarGuid, 'NvarSize':VarDataSize, 'VarAttri':VarAtri, 'NvarDataBufPtr':(CurVarPtr+HdrSize+VarNameSize) } + VarCount = VarCount + 1 + CurVarPtr = (CurVarPtr + HdrSize + VarNameSize + VarDataSize + 3) & 0xFFFFFFFC + NvRamPointer = NvRamPointer + VarStoreSize + return NvRamDict + +def GetIfrFormsHdr(HiiDbBinListBuff, HiiDbPointer=0): + if( HiiDbBinListBuff == 0 ): + return 0 + ReturnAddrDict = { 'IfrList' : [], 'StrPkgHdr' : 0, 'UqiPkgHdr' : 0} + BufLen = len(HiiDbBinListBuff) + while(HiiDbPointer < BufLen): + Guid_LowHalf = clb.ReadList(HiiDbBinListBuff, HiiDbPointer, 4) + if (Guid_LowHalf == gEfiIfrTianoGuid[0]): + HiiLstGuid = clb.FetchGuid(HiiDbBinListBuff, HiiDbPointer) + if(HiiLstGuid == gEfiIfrTianoGuid): + IfrOpcode = clb.ReadList(HiiDbBinListBuff, HiiDbPointer - 2, 1) + if (IfrOpcode == EFI_IFR_GUID_OP): + TmpHiiDbPtr = HiiDbPointer - 2 + StartAddress = 0 + if(clb.ReadList(HiiDbBinListBuff, HiiDbPointer - 2 - 0x27, 2) == 0xA70E): # Check if we Find formset opcode + StartAddress = HiiDbPointer - 2 - 0x27 + StartFound = False + for count in range (0, 0x1000): + IfrOpcode = clb.ReadList(HiiDbBinListBuff, TmpHiiDbPtr, 1) + IfrOpLen = (clb.ReadList(HiiDbBinListBuff, (TmpHiiDbPtr+1), 1) & 0x7F) + if ( (IfrOpcode == EFI_IFR_VARSTORE_OP) or (IfrOpcode == EFI_IFR_VARSTORE_EFI_OP) ): + StartFound = True + break + TmpHiiDbPtr = TmpHiiDbPtr + IfrOpLen + if(StartFound): + if(StartAddress != 0): + ReturnAddrDict['IfrList'].append(StartAddress) + HiiDbPointer = TmpHiiDbPtr + if (Guid_LowHalf == 0x552D6E65): # compare with 'en-US' + StringPkgLang = clb.ReadList(HiiDbBinListBuff, HiiDbPointer, 6) + if (StringPkgLang == 0x53552D6E65): # compare with 'en-US' + StringHdr = clb.ReadList(HiiDbBinListBuff, (HiiDbPointer+0x6), 1) + PromptLow = clb.ReadList(HiiDbBinListBuff, (HiiDbPointer+0x7), 8) + PromptHigh = clb.ReadList(HiiDbBinListBuff, (HiiDbPointer+0x7+0x8), 8) + if( (StringHdr == EFI_HII_SIBT_STRING_UCS2) and (PromptLow == 0x6C0067006E0045) and (PromptHigh == 0x6800730069) ): # EFI_HII_SIBT_STRING_UCS2 and 'E.n.g.l.i.s.h' + StringPkgType = clb.ReadList(HiiDbBinListBuff, (HiiDbPointer-0x2B), 1) + StringOffset = clb.ReadList(HiiDbBinListBuff, (HiiDbPointer-0x26), 4) + if(StringPkgType == EFI_HII_PACKAGE_STRINGS): + ReturnAddrDict['StrPkgHdr'] = ((HiiDbPointer + 6) - StringOffset) + if ( (Guid_LowHalf == 0x697175) and (Parse_Print_Uqi) ): # compare with 'uqi' + StringHdr = clb.ReadList(HiiDbBinListBuff, (HiiDbPointer+0x4), 1) + PromptLow = clb.ReadList(HiiDbBinListBuff, (HiiDbPointer+0x5), 6) + if( (StringHdr == EFI_HII_SIBT_STRING_UCS2) and (PromptLow == 0x6900710075) ): # EFI_HII_SIBT_STRING_UCS2 and 'u.q.i' + StringPkgType = clb.ReadList(HiiDbBinListBuff, (HiiDbPointer-0x2B), 1) + StringOffset = clb.ReadList(HiiDbBinListBuff, (HiiDbPointer-0x26), 4) + if(StringPkgType == EFI_HII_PACKAGE_STRINGS): + ReturnAddrDict['UqiPkgHdr'] = ((HiiDbPointer + 4) - StringOffset) + HiiDbPointer = HiiDbPointer + 1 + return ReturnAddrDict + +def ParseIfrForms(HiiDbBinListBuff, BiosKnobDict, HiiStrDict, IfrOpHdrAddr, IfrOpHdrEndAddr, BiosFfsFvBase, FfsFilecount, FrontPageForm, LogFile, outXml=''): + global TabLevel, PlatInfoMenuDone + TabLevel = 0 + SetupPgDict = {} + if(IfrOpHdrEndAddr == 0): + IfrOpHdrEndAddr = len(HiiDbBinListBuff) + PrintLog('========================= Start IFR Forms Parsing =========================|', LogFile) + for VarId in BiosKnobDict: + BiosKnobDict[VarId]['HiiVarId'] = 0xFF + + FormSetCapture = False + bit_wise_form = False + for OpcodeCount in range (0, 0xFFFFF): + if (IfrOpHdrAddr >= IfrOpHdrEndAddr): + break + IfrOpcode = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr, 1) + if bit_wise_form and IfrOpcode == EFI_IFR_END_OP: + bit_wise_form = False + if IfrOpcode == EFI_IFR_GUID_OP and clb.FetchGuid(HiiDbBinListBuff, (IfrOpHdrAddr + 2)) == gEdkiiIfrBitVarstoreGuid: + bit_wise_form = True + IfrOpHdrAddr = IfrOpHdrAddr + 0x12 + continue + if (IfrOpcodesDict.get(IfrOpcode, 'N.A.') == 'N.A.'): + PrintLog('========================= End IFR Forms Parsing =========================|', LogFile) + break + IfrOpcodeSize = clb.ReadList(HiiDbBinListBuff, (IfrOpHdrAddr + 0x01), 1) & 0x7F + if ( (IfrOpcode == EFI_IFR_SUPPRESS_IF_OP) or (IfrOpcode == EFI_IFR_GRAY_OUT_IF_OP) ): + Scope = clb.ReadList(HiiDbBinListBuff, (IfrOpHdrAddr + 0x01), 1) >> 7 + if(Scope): + ScopeLvl = 1 + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + IfrOpcode = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr, 1) + IfrOpcodeSize = clb.ReadList(HiiDbBinListBuff, (IfrOpHdrAddr + 0x01), 1) & 0x7F + Scope = clb.ReadList(HiiDbBinListBuff, (IfrOpHdrAddr + 0x01), 1) >> 7 + if ( (IfrOpcode == EFI_IFR_TRUE_OP) and (Scope == 0) ): + while(ScopeLvl): # go till end of Suppress if TRUE, we need to skip all that stuff + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + IfrOpcode = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr, 1) + IfrOpcodeSize = clb.ReadList(HiiDbBinListBuff, (IfrOpHdrAddr + 0x01), 1) & 0x7F + Scope = clb.ReadList(HiiDbBinListBuff, (IfrOpHdrAddr + 0x01), 1) >> 7 + if(Scope): + ScopeLvl = ScopeLvl + 1 + if(IfrOpcode == EFI_IFR_END_OP): + ScopeLvl = ScopeLvl - 1 + if (IfrOpcode == EFI_IFR_FORM_SET_OP): + FormSetTitle = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+0x12, 2) + PrintLog('FormSet = %s (0x%X)' %(HiiStrDict.get(FormSetTitle), FormSetTitle), LogFile) + FormSetCapture = True + if (IfrOpcode == EFI_IFR_FORM_OP): + CurrentFormId = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+2, 2) + TitlePrompt = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+4, 2) + if(FormSetCapture): + FrontPageForm.append(TitlePrompt) + FormSetCapture = False + PrintLog('\t\tForm = %s (0x%X)' %(HiiStrDict.get(TitlePrompt), TitlePrompt), LogFile) + if(PlatInfoMenuDone == False): + if(HiiStrDict.get(TitlePrompt) == 'Platform Information Menu'): + outXml += '\t<%s>\n' %(HiiStrDict.get(TitlePrompt).replace(' ', '_')) + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + ScopeLvl = 1 + for count in range (0, 0x100, 1): # while(endform) + if(ScopeLvl <= 0): + PlatInfoMenuDone = True + outXml += '\t\n' %(HiiStrDict.get(TitlePrompt).replace(' ', '_')) + break + CurrIfrOpcode = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr, 1) + CurrIfrOpcodeSize = clb.ReadList(HiiDbBinListBuff, (IfrOpHdrAddr + 0x01), 1) & 0x7F + Scope = clb.ReadList(HiiDbBinListBuff, (IfrOpHdrAddr + 0x01), 1) >> 7 + if(Scope): + ScopeLvl = ScopeLvl + 1 + if(CurrIfrOpcode == EFI_IFR_END_OP): + ScopeLvl = ScopeLvl - 1 + if(CurrIfrOpcode == EFI_IFR_SUBTITLE_OP): + Pmpt = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+2, 2) + Hlp = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+4, 2) + if((HiiStrDict.get(Pmpt, 'NF') == 'NF') or (HiiStrDict.get(Pmpt, 'NF') == '')): + outXml += '\n' + else: + outXml += '\t\t\n' %(HiiStrDict.get(Pmpt, 'NF')) + if(CurrIfrOpcode == EFI_IFR_TEXT_OP): + Pmpt = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+2, 2) + Hlp = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+4, 2) + Text2 = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+6, 2) + if((HiiStrDict.get(Pmpt, 'NF') != 'NF') and (HiiStrDict.get(Pmpt, 'NF') != '')): + outXml += '\t\t\n' %(HiiStrDict.get(Pmpt, 'NF'), HiiStrDict.get(Text2, 'NF')) + IfrOpHdrAddr = IfrOpHdrAddr + CurrIfrOpcodeSize + SetupPgDict[CurrentFormId] = {'Prompt': TitlePrompt, 'PromptList': []} + if (IfrOpcode == EFI_IFR_REF_OP): + GotoPrompt = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+2, 2) + PrintLog('\tGotoForm = %s (0x%X)' %(HiiStrDict.get(GotoPrompt), GotoPrompt), LogFile) + FormId = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+0xD, 2) + SetupPgDict[CurrentFormId][FormId] = {'Prompt': GotoPrompt} + if ( (IfrOpcode == EFI_IFR_VARSTORE_OP) or (IfrOpcode == EFI_IFR_VARSTORE_EFI_OP) ): + if(IfrOpcode == EFI_IFR_VARSTORE_OP): + VarGuidOffset = 2 + VarIdOffset = 0x12 + VarSizeOffset = 0x14 + VarNameOffset = 0x16 + else: + VarIdOffset = 2 + VarGuidOffset = 4 + VarSizeOffset = 0x18 + VarNameOffset = 0x1A + IfrVarStoreGuid = clb.FetchGuid(HiiDbBinListBuff, (IfrOpHdrAddr+VarGuidOffset)) + IfrVarStoreId = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+VarIdOffset, 2) + IfrVarStoreSize = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+VarSizeOffset, 2) + IfrVarStoreName = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+VarNameOffset, (IfrOpcodeSize-VarNameOffset), clb.ASCII) + for VarId in BiosKnobDict: + if ( (BiosKnobDict[VarId]['NvarName'] == IfrVarStoreName) and (BiosKnobDict[VarId]['HiiVarId'] == 0xFF) and ((BiosKnobDict[VarId]['NvarGuid'] == ZeroGuid) or (IfrVarStoreGuid == BiosKnobDict[VarId]['NvarGuid'])) ): + BiosKnobDict[VarId]['HiiVarId'] = IfrVarStoreId + BiosKnobDict[VarId]['HiiVarSize'] = IfrVarStoreSize + break + if ( (IfrOpcode == EFI_IFR_ONE_OF_OP) or (IfrOpcode == EFI_IFR_NUMERIC_OP) or (IfrOpcode == EFI_IFR_CHECKBOX_OP) or (IfrOpcode == EFI_IFR_STRING_OP) ): + IfrPrompt = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+2, 2) + IfrHelp = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+4, 2) + IfrVarId = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+8, 2) + KnobOffset = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+0x0A, 2) + if bit_wise_form: + KnobOffset = clb.BITWISE_KNOB_PREFIX + KnobOffset + bit_size = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+0x0D, 1) & 0x3F + SupportedVarFound = False + for VarIndex in BiosKnobDict: + if(BiosKnobDict[VarIndex]['HiiVarId'] == IfrVarId): + CurrIntVarId = VarIndex + SupportedVarFound = True + break + if(SupportedVarFound == False): + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + continue # not part of supported VarID + try: + XmlKnobName = BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['KnobName'] + except KeyError: + XmlKnobName = 'NotFound(%d_0x%04X)' %(CurrIntVarId, KnobOffset) + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + continue + OneOfNumericKnobSz = 0 + CurSetupTypeBin = BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['SetupTypeBin'] + if( (CurSetupTypeBin != clb.INVALID_KNOB_SIZE) and (IfrOpcode != CurSetupTypeBin) ): + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + continue + if ( (IfrOpcode == EFI_IFR_ONE_OF_OP) or (IfrOpcode == EFI_IFR_NUMERIC_OP) ): + IfrOneOfFlags = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+0x0D, 1) + OneOfNumericKnobSz = (1 << (IfrOneOfFlags & EFI_IFR_NUMERIC_SIZE)) + CurKnobSzBin = BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['KnobSzBin'] + if( ((CurKnobSzBin != clb.INVALID_KNOB_SIZE) and (OneOfNumericKnobSz != CurKnobSzBin)) and (bit_wise_form and (bit_size != CurKnobSzBin)) ): + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + continue + KnobProcessed = BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['KnobPrsd'][0] + if(KnobProcessed >= 1): + if(IfrOpcode != BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['KnobPrsd'][1]): + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + continue + CurKnobInDupList = False + for DupIndex in sorted(BiosKnobDict[CurrIntVarId]['DupKnobDict']): + if(XmlKnobName == BiosKnobDict[CurrIntVarId]['DupKnobDict'][DupIndex]['DupKnobName']): + CurKnobInDupList = True + break + if(CurKnobInDupList == False): + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + continue + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['Prompt'] = IfrPrompt + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['Help'] = IfrHelp + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['SetupTypeHii'] = IfrOpcode + if(len(SetupPgDict[CurrentFormId]['PromptList']) == 0): + PromptList = [] + ExitAllLoops = False + CurFormId = CurrentFormId + PreviousForms = [] + while(1): + ProcessCnt = 0 + for FormId in SetupPgDict: + ProcessCnt = ProcessCnt + 1 + if FormId not in PreviousForms: + if (FormId in SetupPgDict): + if (CurFormId in SetupPgDict[FormId]): + PromptList.append(SetupPgDict[FormId][CurFormId]['Prompt']) + PreviousForms.append(FormId) + CurFormId = FormId + break + if (ProcessCnt == len(SetupPgDict)): + PromptList.append(SetupPgDict[CurFormId]['Prompt']) + if(SetupPgDict[CurFormId]['Prompt'] not in FrontPageForm): + PromptList.append(0x10000) # we need to initialize this to '??' + ExitAllLoops = True + break + if(ExitAllLoops): + break + SetupPgDict[CurrentFormId]['PromptList'] = PromptList + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['ParentPromptList'] = SetupPgDict[CurrentFormId]['PromptList'] + CurrOpcode = IfrOpcode + if (IfrOpcode == EFI_IFR_CHECKBOX_OP): + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['KnobSzHii'] = 1 + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['HiiDefVal'] = (clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+0xD, 1) & 1) + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['FvMainOffHiiDb'] = BiosFfsFvBase+IfrOpHdrAddr+0xD + elif (IfrOpcode == EFI_IFR_STRING_OP): + Max = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+0x0E, 1) + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['Min'] = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+0x0D, 1) + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['Max'] = Max + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['KnobSzHii'] = (Max * 2) + elif ( (IfrOpcode == EFI_IFR_ONE_OF_OP) or (IfrOpcode == EFI_IFR_NUMERIC_OP) ): + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['KnobSzHii'] = OneOfNumericKnobSz + if(IfrOpcode == EFI_IFR_NUMERIC_OP): + if bit_wise_form: + OneOfNumericKnobSz = 4 # for BitWise, the Width for min, max, step fields remain UINT32. + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['Min'] = clb.ReadList(HiiDbBinListBuff, (IfrOpHdrAddr+0x0E), OneOfNumericKnobSz) + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['Max'] = clb.ReadList(HiiDbBinListBuff, (IfrOpHdrAddr+0x0E+OneOfNumericKnobSz), OneOfNumericKnobSz) + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['Step'] = clb.ReadList(HiiDbBinListBuff, (IfrOpHdrAddr+0x0E+OneOfNumericKnobSz+OneOfNumericKnobSz), OneOfNumericKnobSz) + while (IfrOpcode != EFI_IFR_END_OP): + if(IfrOpcode == EFI_IFR_DEFAULT_OP): + NumValSize = (clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+4, 1) & 0x0F) + if bit_wise_form: + NumValSize = EFI_IFR_TYPE_NUM_SIZE_32 # for BitWise, the Width fields remain UINT32. + DefValue = 0 + if(NumValSize == EFI_IFR_TYPE_BOOLEAN): + DefValue = int(clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+5, 1) != 0) + elif(NumValSize == EFI_IFR_TYPE_NUM_SIZE_8): + DefValue = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+5, 1) + elif(NumValSize == EFI_IFR_TYPE_NUM_SIZE_16): + DefValue = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+5, 2) + elif(NumValSize == EFI_IFR_TYPE_NUM_SIZE_32): + DefValue = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+5, 4) + elif(NumValSize == EFI_IFR_TYPE_NUM_SIZE_64): + DefValue = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+5, 8) + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['HiiDefVal'] = DefValue + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['FvMainOffHiiDb'] = BiosFfsFvBase+IfrOpHdrAddr+0x5 + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + IfrOpcode = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr, 1) + IfrOpcodeSize = (clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+1, 1) & 0x7F) + elif(IfrOpcode == EFI_IFR_ONE_OF_OP): + OneOfScopeLvl = 0 + OneOfScope = (clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+1, 1) & 0x80) >> 7 + if(OneOfScope): + OneOfScopeLvl = OneOfScopeLvl + 1 + if(IfrOpcode == EFI_IFR_END_OP): + OneOfScopeLvl = OneOfScopeLvl - 1 + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['OneOfOptionsDict'][KnobProcessed] = {} + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['FvMainOffHiiDb'] = BiosFfsFvBase+IfrOpHdrAddr + OptionsCount = 0 + while (OneOfScopeLvl > 0): + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + IfrOpcode = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr, 1) + IfrOpcodeSize = (clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+1, 1) & 0x7F) + OneOfScope = (clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+1, 1) & 0x80) >> 7 + if(OneOfScope): + OneOfScopeLvl = OneOfScopeLvl + 1 + if(IfrOpcode == EFI_IFR_END_OP): + OneOfScopeLvl = OneOfScopeLvl - 1 + if(IfrOpcode == EFI_IFR_ONE_OF_OPTION_OP): + OptionTextPromt = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+2, 2) + OptionFlag = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+4, 1) + OptionTextValSize = (OptionFlag & 0x0F) + if bit_wise_form: + OptionTextValSize = EFI_IFR_TYPE_NUM_SIZE_32 # for BitWise, the Width fields remain UINT32. + TextValue = 0 + if(OptionTextValSize == EFI_IFR_TYPE_BOOLEAN): + TextValue = int(clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+6, 1) != 0) + elif(OptionTextValSize == EFI_IFR_TYPE_NUM_SIZE_8): + TextValue = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+6, 1) + elif(OptionTextValSize == EFI_IFR_TYPE_NUM_SIZE_16): + TextValue = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+6, 2) + elif(OptionTextValSize == EFI_IFR_TYPE_NUM_SIZE_32): + TextValue = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+6, 4) + elif(OptionTextValSize == EFI_IFR_TYPE_NUM_SIZE_64): + TextValue = clb.ReadList(HiiDbBinListBuff, IfrOpHdrAddr+6, 8) + if( (OptionFlag & EFI_IFR_OPTION_DEFAULT) != 0 ): + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['HiiDefVal'] = TextValue + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['OneOfOptionsDict'][KnobProcessed][OptionsCount] = { 'OptionText': OptionTextPromt, 'OptionVal':TextValue } + OptionsCount = OptionsCount + 1 + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['KnobPrsd'][0] = (KnobProcessed+1) + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['KnobPrsd'][1] = CurrOpcode + BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['KnobPrsd'][2] = FfsFilecount + PrintLog('\t\t\tKnob = %s' %(BiosKnobDict[CurrIntVarId]['KnobDict'][KnobOffset]['KnobName']), LogFile) + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + return IfrOpHdrAddr, outXml + +def ParseIfrStrings(HiiDbBinListBuff=0, StringHdrPtr=0, LogFile=0): + HiiStringDict = {} + Prompt = 1 + if(StringHdrPtr == 0): + return HiiStringDict + StringPkgSize = clb.ReadList(HiiDbBinListBuff, StringHdrPtr, 3) + StringOffset = clb.ReadList(HiiDbBinListBuff, (StringHdrPtr+0x8), 4) + CurrStringPtr = (StringHdrPtr + StringOffset) + PrintLog('=========== Hii String Package Parsing Start = 0x%X ==========|' %StringHdrPtr, LogFile) + while(CurrStringPtr < (StringHdrPtr+StringPkgSize)): + BlockType = clb.ReadList(HiiDbBinListBuff, (CurrStringPtr), 1) + CurrStringPtr = CurrStringPtr + 1 + if(BlockType == EFI_HII_SIBT_END): # end of string block? + break + elif(BlockType == EFI_HII_SIBT_STRING_SCSU): + StrSize = 0 + String = '' + while(1): + ChrValue = clb.ReadList(HiiDbBinListBuff, (CurrStringPtr+StrSize), 1) + StrSize = StrSize + 1 + if(ChrValue): + String = String + chr(ChrValue) + else: + break + HiiStringDict[Prompt] = String.replace('<=', ' <e; ').replace('>=', ' >e; ').replace('&', 'n').replace('\"', '"').replace('\'', '').replace('\x13', '').replace('\x19', '').replace('\xB5', 'u').replace('\xAE', '').replace('<', ' < ').replace('>', ' > ').replace('\r\n', ' ').replace('\n', ' ') + Prompt = Prompt + 1 + CurrStringPtr = CurrStringPtr + StrSize + elif(BlockType == EFI_HII_SIBT_STRING_UCS2): + StrSize = 0 + String = '' + while(1): + ChrValue = clb.ReadList(HiiDbBinListBuff, (CurrStringPtr+StrSize), 2) + StrSize = StrSize + 2 + if(ChrValue): + String = String + chr(ChrValue & 0xFF) + else: + break + HiiStringDict[Prompt] = String.replace('<=', ' <e; ').replace('>=', ' >e; ').replace('&', 'n').replace('\"', '"').replace('\'', '').replace('\x13', '').replace('\x19', '').replace('\xB5', 'u').replace('\xAE', '').replace('<', ' < ').replace('>', ' > ').replace('\r\n', ' ').replace('\n', ' ') + Prompt = Prompt + 1 + CurrStringPtr = CurrStringPtr + StrSize + elif(BlockType == EFI_HII_SIBT_STRING_SCSU_FONT): + StrSize = 0 + String = '' + CurrStringPtr = CurrStringPtr + 1 + while(clb.ReadList(HiiDbBinListBuff, (CurrStringPtr+StrSize), 1)): + StrSize = StrSize + 1 + CurrStringPtr = CurrStringPtr + StrSize + 1 + elif(BlockType == EFI_HII_SIBT_STRING_UCS2_FONT): + StrSize = 0 + String = '' + CurrStringPtr = CurrStringPtr + 1 + while(clb.ReadList(HiiDbBinListBuff, (CurrStringPtr+StrSize), 2)): + StrSize = StrSize + 2 + CurrStringPtr = CurrStringPtr + StrSize + 2 + elif(BlockType == EFI_HII_SIBT_SKIP1): + Prompt = Prompt + clb.ReadList(HiiDbBinListBuff, CurrStringPtr, 1) + CurrStringPtr = CurrStringPtr + 1 + elif(BlockType == EFI_HII_SIBT_SKIP2): + Prompt = Prompt + clb.ReadList(HiiDbBinListBuff, CurrStringPtr, 2) + CurrStringPtr = CurrStringPtr + 2 + elif(BlockType == EFI_HII_SIBT_DUPLICATE): + CurrStringPtr = CurrStringPtr + 2 + elif(BlockType == EFI_HII_SIBT_EXT1): + CurrStringPtr = CurrStringPtr + 1 + 1 + elif(BlockType == EFI_HII_SIBT_EXT2): + CurrStringPtr = CurrStringPtr + 1 + 2 + elif(BlockType == EFI_HII_SIBT_EXT4): + CurrStringPtr = CurrStringPtr + 1 + 4 + elif(BlockType == EFI_HII_SIBT_STRINGS_SCSU): + StrSize = 0 + StrCount = clb.ReadList(HiiDbBinListBuff, CurrStringPtr, 2) + CurrStringPtr = CurrStringPtr + 2 + CurStrCnt = 0 + while(CurStrCnt < StrCount): + while(clb.ReadList(HiiDbBinListBuff, (CurrStringPtr+StrSize), 1)): + StrSize = StrSize + 1 + StrSize = StrSize + 1 + CurStrCnt = CurStrCnt + 1 + CurrStringPtr = CurrStringPtr + StrSize + elif(BlockType == EFI_HII_SIBT_STRINGS_SCSU_FONT): + StrSize = 0 + StrCount = clb.ReadList(HiiDbBinListBuff, CurrStringPtr+1, 2) + CurrStringPtr = CurrStringPtr + 3 + CurStrCnt = 0 + while(CurStrCnt < StrCount): + while(clb.ReadList(HiiDbBinListBuff, (CurrStringPtr+StrSize), 1)): + StrSize = StrSize + 1 + StrSize = StrSize + 1 + CurStrCnt = CurStrCnt + 1 + CurrStringPtr = CurrStringPtr + StrSize + elif(BlockType == EFI_HII_SIBT_STRINGS_UCS2): + StrSize = 0 + StrCount = clb.ReadList(HiiDbBinListBuff, CurrStringPtr, 2) + CurrStringPtr = CurrStringPtr + 2 + CurStrCnt = 0 + while(CurStrCnt < StrCount): + while(clb.ReadList(HiiDbBinListBuff, (CurrStringPtr+StrSize), 2)): + StrSize = StrSize + 2 + StrSize = StrSize + 2 + CurStrCnt = CurStrCnt + 1 + CurrStringPtr = CurrStringPtr + StrSize + elif(BlockType == EFI_HII_SIBT_STRINGS_UCS2_FONT): + StrSize = 0 + StrCount = clb.ReadList(HiiDbBinListBuff, CurrStringPtr+1, 2) + CurrStringPtr = CurrStringPtr + 3 + CurStrCnt = 0 + while(CurStrCnt < StrCount): + while(clb.ReadList(HiiDbBinListBuff, (CurrStringPtr+StrSize), 2)): + StrSize = StrSize + 2 + StrSize = StrSize + 2 + CurStrCnt = CurStrCnt + 1 + CurrStringPtr = CurrStringPtr + StrSize + PrintLog('=========== Hii String Package Parsing End = 0x%X ==========|' %CurrStringPtr, LogFile) + return HiiStringDict + +def GenerateKnobsSection(BiosKnobDict, HiiStrDict, HiiUqiStrDict, NvRamFvListBuffer, NvramTblDict, outXmlList, AllXmlKnobs, LogFile=0): + for VarCount in sorted(BiosKnobDict): + for KnobOffset in sorted(BiosKnobDict[VarCount]['KnobDict']): + if(BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['KnobPrsd'][0] == 0): + continue # Skip current Iteration, since current entry was not processed by IFR parser. + CurSetupType = BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['SetupTypeHii'] + CurSetupTypeStr = clb.SetupTypeHiiDict.get(CurSetupType, 'Unknown') + if( CurSetupTypeStr == 'Unknown' ): + continue # don't publish unsupported Setup Type + CurKnobName = BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['KnobName'] + if(CurKnobName not in AllXmlKnobs): + AllXmlKnobs.append(CurKnobName) + else: + continue + nvram_knob_size = BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['KnobSzHii'] + xml_knob_size = nvram_knob_size + CurDepex = BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['Depex'] + IfrPrompt = BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['Prompt'] + IfrHelp = BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['Help'] + HiiDefVal = BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['HiiDefVal'] + PromptList = BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['ParentPromptList'] + SetupPgPtr = HiiStrDict.get(IfrPrompt, 'N.A.') + for cnt in range(0, len(PromptList)): + SetupPgPtr = HiiStrDict.get(PromptList[cnt], '???') + '/' + SetupPgPtr + DefaultVal = HiiDefVal + bit_offset = 0 + knob_offset_str = '0x%04X' %KnobOffset + nvram_knob_offset = KnobOffset + is_bitwise = False + xml_knob_size = BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['KnobSzBin'] + nvram_knob_size = xml_knob_size + if KnobOffset >= clb.BITWISE_KNOB_PREFIX: # bitwise knob? + is_bitwise = True + knob_offset_str = '0x%05X' % KnobOffset + nvram_knob_offset = int((KnobOffset & 0x3FFFF) / 8) + bit_offset = ((KnobOffset & 0x3FFFF) % 8) + nvram_knob_size = bit_offset + xml_knob_size + if nvram_knob_size % 8: + nvram_knob_size = int(nvram_knob_size/8 + 1) + else: + nvram_knob_size = int(nvram_knob_size/8) + if len(NvramTblDict): + try: # Use the Default value from NVRAM FV or Default Data FFS or VPD Region (whichever is availaible and applicable), Default tagging in .hrf/.vfr will be EOL soon. + if is_bitwise: + DefaultVal = (clb.ReadList(NvRamFvListBuffer, (NvramTblDict[VarCount]['NvarDataBufPtr']+nvram_knob_offset), nvram_knob_size) >> bit_offset) & (clb.and_mask(nvram_knob_size) >> ((nvram_knob_size*8) - xml_knob_size)) + else: + DefaultVal = clb.ReadList(NvRamFvListBuffer, (NvramTblDict[VarCount]['NvarDataBufPtr']+nvram_knob_offset), nvram_knob_size) + except KeyError: + pass + CurrentVal = DefaultVal + if not HiiUqiStrDict: + outXmlList.append('\t\t\n') + KnobInstances = len(BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['OneOfOptionsDict']) + CurInst = 1 + for KnobPrsCnt in range (0, KnobInstances): + PrintOptionList = False + if( KnobInstances > 1 ): + FoundInstance = 1 + if(KnobPrsCnt == 0): + PrintOptionList = True + else: + for DupIndex in sorted(BiosKnobDict[VarCount]['DupKnobDict']): + if(CurKnobName == BiosKnobDict[VarCount]['DupKnobDict'][DupIndex]['DupKnobName']): + if(KnobPrsCnt == FoundInstance): + PrintOptionList = True + CurDepex = BiosKnobDict[VarCount]['DupKnobDict'][DupIndex]['DupDepex'] + CurInst = CurInst + 1 + DupXmlKnobName = CurKnobName + '_inst_%d' %CurInst + if (HiiUqiStrDict == {}): + outXmlList.append('\t\t\n' %(CurSetupTypeStr, DupXmlKnobName, VarCount, BiosKnobDict[VarCount]['NvarName'], HiiStrDict.get(IfrPrompt, 'NotFound(0x%04X)' %IfrPrompt), HiiStrDict.get(IfrHelp, 'NotFound(0x%04X)' %IfrHelp), xml_knob_size, knob_offset_str, CurDepex, SetupPgPtr, (nvram_knob_size*2), DefaultVal, (nvram_knob_size*2), CurrentVal)) + else: + outXmlList.append('\t\t\n' %(CurSetupTypeStr, DupXmlKnobName, VarCount, BiosKnobDict[VarCount]['NvarName'], HiiStrDict.get(IfrPrompt, 'NotFound(0x%04X)' %IfrPrompt), HiiStrDict.get(IfrHelp, 'NotFound(0x%04X)' %IfrHelp), HiiUqiStrDict.get(IfrPrompt, ''), xml_knob_size, knob_offset_str, CurDepex, SetupPgPtr, (nvram_knob_size*2), DefaultVal, (nvram_knob_size*2), CurrentVal)) + break + FoundInstance = FoundInstance + 1 + else: + PrintOptionList = True + outXmlList.append('\t\t\t\n') + if (PrintOptionList): + for OptionCount in sorted(BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['OneOfOptionsDict'][KnobPrsCnt]): + OptionText = BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['OneOfOptionsDict'][KnobPrsCnt][OptionCount]['OptionText'] + outXmlList.append('\t\t\t\t\n') + outXmlList.append('\t\t\n') + elif(CurSetupType == EFI_IFR_NUMERIC_OP): + outXmlList.append(' min=\"0x%X\" max=\"0x%X\" step=\"%d\"/>\n' %(BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['Min'], BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['Max'], BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['Step'])) + elif(CurSetupType == EFI_IFR_STRING_OP): + outXmlList.append(' minsize=\"0x%X\" maxsize=\"0x%X\"/>\n' %(BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['Min'], BiosKnobDict[VarCount]['KnobDict'][KnobOffset]['Max'])) + elif(CurSetupType == EFI_IFR_CHECKBOX_OP): + outXmlList.append('/>\n') + else: + outXmlList.append('/>\n') + +def FetchBiosId(BinaryFile, PcBiosId=False): + FileExt = os.path.splitext(BinaryFile)[1][1:].lower() + BiosIdString = 'Unknown' + if (FileExt != 'ffs'): + BiosIdFfsToSave = [ gEfiBiosIdGuid, gCpPcBiosIdFileGuid ] + DelTempFvFfsFiles(clb.TempFolder) + with open(BinaryFile, 'rb') as BiosBinFile: + BiosBinListBuff = list(BiosBinFile.read()) + FlashRegionInfo(BiosBinListBuff, False) + if (FwIngredientDict['FlashDescpValid'] != 0): + BiosRegionBase = FwIngredientDict['FlashRegions'][BIOS_Region]['BaseAddr'] + BiosEnd = FwIngredientDict['FlashRegions'][BIOS_Region]['EndAddr'] + 1 + else: + BiosRegionBase = 0 + BiosEnd = len(BiosBinListBuff) + if(len(BiosBinListBuff) != 0): + ProcessBin(BiosBinListBuff, BiosRegionBase, BiosIdFfsToSave, 0, True, BiosRegionEnd=BiosEnd) + BinaryFile = os.path.join(clb.TempFolder, '%X_File.ffs' %gEfiBiosIdGuid[0]) + if(not os.path.isfile(BinaryFile)): + PcBiosId = True + BinaryFile = os.path.join(clb.TempFolder, '%X_File.ffs' %gCpPcBiosIdFileGuid[0]) + + if(os.path.isfile(BinaryFile)): + with open(BinaryFile, 'rb') as BiosIdFile: + BiosIdListBuff = list(BiosIdFile.read()) + FfsSize = clb.ReadList(BiosIdListBuff, 0x14, 3) + BiosIdString = '' + CharSz = 2 + CharStart = 0x24 + if(PcBiosId): + CharSz = 1 + CharStart = 0x1C + if (FfsSize < 0x100): + for count in range (0, 100): + ChrVal = clb.ReadList(BiosIdListBuff, (CharStart+(count*CharSz)), 1) + if(ChrVal == 0): + break + BiosIdString = BiosIdString + chr(ChrVal) + else: + BiosIdString = 'Unknown' + return BiosIdString + +def ReplOneOfDefFlag(DbBinListBuffer, IfrOpHdrAddr, ReqValue): + IfrOpcodeSize = (clb.ReadList(DbBinListBuffer, IfrOpHdrAddr+1, 1) & 0x7F) + CurIfrOpcode = clb.ReadList(DbBinListBuffer, IfrOpHdrAddr, 1) + while (CurIfrOpcode != EFI_IFR_END_OP): + if(CurIfrOpcode == EFI_IFR_ONE_OF_OPTION_OP): + OptionFlag = clb.ReadList(DbBinListBuffer, IfrOpHdrAddr+4, 1) + OptionTextValSize = (OptionFlag & 0x0F) + OneOfDefVal = 0 + NewOptionFlag = 0 + if(OptionTextValSize == EFI_IFR_TYPE_BOOLEAN): + OneOfDefVal = int(clb.ReadList(DbBinListBuffer, IfrOpHdrAddr+6, 1) != 0) + elif(OptionTextValSize == EFI_IFR_TYPE_NUM_SIZE_8): + OneOfDefVal = clb.ReadList(DbBinListBuffer, IfrOpHdrAddr+6, 1) + elif(OptionTextValSize == EFI_IFR_TYPE_NUM_SIZE_16): + OneOfDefVal = clb.ReadList(DbBinListBuffer, IfrOpHdrAddr+6, 2) + elif(OptionTextValSize == EFI_IFR_TYPE_NUM_SIZE_32): + OneOfDefVal = clb.ReadList(DbBinListBuffer, IfrOpHdrAddr+6, 4) + elif(OptionTextValSize == EFI_IFR_TYPE_NUM_SIZE_64): + OneOfDefVal = clb.ReadList(DbBinListBuffer, IfrOpHdrAddr+6, 8) + if(ReqValue == OneOfDefVal): + NewOptionFlag = (OptionFlag|EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG) + else: + NewOptionFlag = (OptionFlag & (~(EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG) & 0xFF)) + WriteList(DbBinListBuffer, IfrOpHdrAddr+4, 1, NewOptionFlag) + IfrOpHdrAddr = IfrOpHdrAddr + IfrOpcodeSize + IfrOpcodeSize = (clb.ReadList(DbBinListBuffer, IfrOpHdrAddr+1, 1) & 0x7F) + CurIfrOpcode = clb.ReadList(DbBinListBuffer, IfrOpHdrAddr, 1) + +FileGuidListtoSave = [ gNvRamFvGuid, gXmlCliSetupDriverGuid, gVtioDriverGuid, gDxePlatformFfsGuid, gGnrDxePlatformFfsGuid, gBiosKnobsDataBinGuid, gBiosKnobsCpxDataBinGuid, gSocketSetupDriverFfsGuid, gSvSetupDriverFfsGuid, gFpgaDriverFfsGuid, gEfiBiosIdGuid, gCpPcBiosIdFileGuid, gDefaultDataOptSizeFileGuid, gDefaultDataFileGuid, gDefaultDataCpxFileGuid, gVpdGuid, gClientSetupFfsGuid, gClientTestMenuSetupFfsGuid, gPcGenSetupDriverFfsGuid, gEmulationDriverFfsGuid, gClientUiApp1FfsGuid, gClientUiApp2FfsGuid, gMerlinXAppGuid ] +SetupDriverGuidList = [ gXmlCliSetupDriverGuid, gVtioDriverGuid, gDxePlatformFfsGuid, gGnrDxePlatformFfsGuid, gSocketSetupDriverFfsGuid, gSvSetupDriverFfsGuid, gFpgaDriverFfsGuid, gClientSetupFfsGuid, gClientTestMenuSetupFfsGuid , gPcGenSetupDriverFfsGuid, gEmulationDriverFfsGuid, gClientUiApp1FfsGuid, gClientUiApp2FfsGuid ] + +def GetsetBiosKnobsFromBin(BiosBinaryFile=0, BiosOutSufix=0, Operation='genxml', XmlFilename=0, IniFile=0, UpdateHiiDbDef=False, BiosOut='', KnobsStrList=[], BuildType=0xFF, KnobsVerify=False): + global FileGuidListDict, FileSystemSaveCount, FwpPrintEn, FwIngredientDict, PlatInfoMenuDone, MulSetupDrivers + clb.LastErrorSig = 0x0000 + FileGuidListDict = {} + KnobLis = [] + FileSystemSaveCount = 0 + LogFile = open(PrintLogFile, 'w') + clb.OutBinFile = '' + MulSetupDrivers = False + DelTempFvFfsFiles(clb.TempFolder) + + BiosXmlCliVer = '?.?.?' + with open(BiosBinaryFile, 'rb') as BiosBinFile: + BiosBinListBuff = list(BiosBinFile.read()) + FetchFwIngrediantInfo(BiosBinListBuff, False) + if (FwIngredientDict['FlashDescpValid'] != 0): + BiosRegionBase = FwIngredientDict['FlashRegions'][BIOS_Region]['BaseAddr'] + BiosEnd = FwIngredientDict['FlashRegions'][BIOS_Region]['EndAddr'] + 1 + else: + BiosRegionBase = 0 + BiosEnd = len(BiosBinListBuff) + ProcessBin(BiosBinListBuff, BiosRegionBase, FileGuidListtoSave, LogFile, BiosRegionEnd=BiosEnd) + BiosIDFile = os.path.join(clb.TempFolder, '%X_File.ffs' %gEfiBiosIdGuid[0]) + FoundPcBuild = False + if(os.path.isfile(BiosIDFile)): + BiosIdString = FetchBiosId(os.path.join(clb.TempFolder, '%X_File.ffs' %gEfiBiosIdGuid[0])) + else: + FoundPcBuild = True + BiosIdString = FetchBiosId(os.path.join(clb.TempFolder, '%X_File.ffs' %gCpPcBiosIdFileGuid[0]), True) + + log.info(' Fetching Firmware Info from the given Bios Binary...') + if (XmlFilename == 0): + XmlFilename = os.path.join(clb.TempFolder, '%s_FwInfo.xml' %BiosIdString) + file_content = '\n' + '\t\n' %(clb.__version__.version[0], clb.__version__.version[1], clb.__version__.version[2]) + BiosIdLst = BiosIdString.split('.') + BiosDate = BiosIdLst[len(BiosIdLst)-1] + if(FoundPcBuild): + file_content += '\t\n' %(BiosIdString, BiosDate[0:2], BiosDate[2:4], BiosDate[4:8], BiosDate[8:10], BiosDate[10:12]) + else: + file_content += '\t\n' %(BiosIdString, BiosDate[2:4], BiosDate[4:6], '20'+BiosDate[0:2], BiosDate[6:8], BiosDate[8:10]) + file_content += '\t\n' %BiosXmlCliVer + + if (FwIngredientDict['FlashDescpValid'] != 0): + file_content += '\t\n' + for Entry in sorted(FwIngredientDict['FlashRegions']): + if(FwIngredientDict['FlashRegions'][Entry]['BaseAddr'] == FwIngredientDict['FlashRegions'][Entry]['EndAddr']): + continue + file_content += '\t\t\n' %(FwIngredientDict['FlashRegions'][Entry]['Name'], FwIngredientDict['FlashRegions'][Entry]['BaseAddr'], FwIngredientDict['FlashRegions'][Entry]['EndAddr']) + file_content += '\t\n' + if(len(FwIngredientDict['ME']) != 0): + file_content += '\t\n' %(FwIngredientDict['ME']['Version'], FwIngredientDict['ME']['Date'], FwIngredientDict['ME']['Type']) + file_content += '\t\n' %(FwIngredientDict['FlashDescpValid']) + if (FwIngredientDict['FlashDescpValid'] != 0): + for StrapNo in sorted(FwIngredientDict['PCH_STRAPS']): + file_content += '\t\t\n' %(StrapNo, FwIngredientDict['PCH_STRAPS'][StrapNo]) + file_content += '\t\n' + + file_content += '\t\n' + for Entry in sorted(FwIngredientDict['FIT']): + if(FwIngredientDict['FIT'][Entry]['Type'] == FIT_TBL_ENTRY_TYPE_0): + continue + file_content += '\t\t\n' %(FwIngredientDict['FIT'][Entry]['Name'], FwIngredientDict['FIT'][Entry]['Type'], FwIngredientDict['FIT'][Entry]['Address'], FwIngredientDict['FIT'][Entry]['Size']) + file_content += '\t\n' + if (FwIngredientDict['FlashDescpValid'] != 0): + if(len(FwIngredientDict['ACM']) != 0): + file_content += '\t\n' %(FwIngredientDict['ACM']['Version'], FwIngredientDict['ACM']['Date'], FwIngredientDict['ACM']['Type'], FwIngredientDict['ACM']['VendorId']) + file_content += '\t\n' + for Entry in sorted(FwIngredientDict['Ucode']): + file_content += '\t\t\n' %(FwIngredientDict['Ucode'][Entry]['CpuId'], FwIngredientDict['Ucode'][Entry]['Version'], FwIngredientDict['Ucode'][Entry]['Date'], FwIngredientDict['Ucode'][Entry]['UcodeSize']) + file_content += '\t\n' + + if(MulSetupDrivers): + ForLoopCnt = 2 + log.info(' Found BIOS with Unified Binary Build (Build 0 & Build 1)...') + if(BuildType != 0xFF): + log.info(f' Request is to Process Build Type {BuildType:d} ') + else: + ForLoopCnt = 1 + BuildType = 0xFF + BiosDictArray = {} + BiosKnobDict = {} + CreateOutFile = False + BiosKnobsTag = 'biosknobs' + BldType = None + AllXmlKnobs = [] + for FvMainCopyCount in range (0, ForLoopCnt, 1): + if(BuildType != 0xFF): + if(BuildType != FvMainCopyCount): + continue + if(FvMainCopyCount == 0): + BiosKnobsDataFileName = os.path.join(clb.TempFolder, '%X_File.ffs' %gBiosKnobsDataBinGuid[0]) + else: + BiosKnobsDataFileName = os.path.join(clb.TempFolder, '%X_Copy_File.ffs' %gBiosKnobsDataBinGuid[0]) + if (os.path.isfile(BiosKnobsDataFileName) == False): + BiosKnobsDataFileName = os.path.join(clb.TempFolder, '%X_File.ffs' %gBiosKnobsCpxDataBinGuid[0]) + if (os.path.isfile(BiosKnobsDataFileName)): + BiosKnobDict = clb.BiosKnobsDataBinParser(BiosKnobsDataFileName, BiosIdString) + else: + LogFile.close() + log.error('BiosKnobsDataBin not found in the binary, Aborting due to Error!') + clb.LastErrorSig = 0xFE90 # BiosKnobsDataBin not found + file_content += '\n' + with open(XmlFilename,'w') as outXml: + outXml.write(file_content) + clb.SanitizeXml(XmlFilename) + return 1 + NvRamFileName = os.path.join(clb.TempFolder, '%X_File.fv' %gNvRamFvGuid[0]) + with open(NvRamFileName, 'rb') as NvRamFile: + NvRamFvListBuffer = list(NvRamFile.read()) + NvRamDefDataFileGuid = gNvRamFvGuid + NvramTblDict = ParseNvram(NvRamFvListBuffer, BiosKnobDict, 0x48, LogFile) + if(len(NvramTblDict) == 0): + NvRamDefDataFileGuid = gDefaultDataOptSizeFileGuid + NvRamFileName = os.path.join(clb.TempFolder, '%X_File.ffs' %NvRamDefDataFileGuid[0]) + if (os.path.isfile(NvRamFileName) == False): + NvRamDefDataFileGuid = gDefaultDataFileGuid + NvRamFileName = os.path.join(clb.TempFolder, '%X_File.ffs' %NvRamDefDataFileGuid[0]) + if (os.path.isfile(NvRamFileName) == False): + NvRamDefDataFileGuid = gVpdGuid + if( (NvRamDefDataFileGuid == gDefaultDataFileGuid) and (FvMainCopyCount == 1) ): + NvRamDefDataFileGuid = gDefaultDataCpxFileGuid + NvRamFileName = os.path.join(clb.TempFolder, '%X_File.ffs' %NvRamDefDataFileGuid[0]) + if (os.path.isfile(NvRamFileName)): + with open(NvRamFileName, 'rb') as NvRamFile: + NvRamDefDataFileDict = {} + NvRamFvListBuffer = list(NvRamFile.read()) + NvramTblDict = ParseNvram(NvRamFvListBuffer, BiosKnobDict, 0, LogFile) + BiosDictArray[FvMainCopyCount] = {} + KnobStartTag = False + FrontPageForm = [] + outXmlList = [] + for count in range (0, len(SetupDriverGuidList)): + if(FvMainCopyCount == 0): + CurFfsFileName = os.path.join(clb.TempFolder, '%X_File.ffs' %SetupDriverGuidList[count][0]) + else: + CurFfsFileName = os.path.join(clb.TempFolder, '%X_Copy_File.ffs' %SetupDriverGuidList[count][0]) + if (os.path.isfile(CurFfsFileName) == False): + continue # didnt found this file, maybe unsupported driver for following binary + BiosKnobDictNew = copy.deepcopy(BiosKnobDict) + with open(CurFfsFileName, 'rb') as HiiDbBinFile: + HiiDbBinListBuff = list(HiiDbBinFile.read()) + PrintLog('=============== Now Parsing %s binary ================|' %(os.path.join(clb.TempFolder, '%X_File.ffs' %SetupDriverGuidList[count][0])), LogFile) + HiiPkgAddrDict = GetIfrFormsHdr(HiiDbBinListBuff) + for FileCountId in FileGuidListDict: + if(FileGuidListDict[FileCountId]['FileGuid'] == SetupDriverGuidList[count]): + BiosFfsFvBase = FileGuidListDict[FileCountId]['BiosBinPointer'] + if(MulSetupDrivers and (FvMainCopyCount == 0)): + pass + else: + break + PlatInfoMenuDone = False + StringHdrPtr = HiiPkgAddrDict['StrPkgHdr'] + HiiStrDict = ParseIfrStrings(HiiDbBinListBuff, StringHdrPtr, LogFile) + HiiUqiStrDict = {} + if(Parse_Print_Uqi): + HiiUqiStrDict = ParseIfrStrings(HiiDbBinListBuff, HiiPkgAddrDict['UqiPkgHdr'], LogFile) + for IfrFormPkgCount in range (0, (len(HiiPkgAddrDict['IfrList']))): + IfrOpHdrAddr, file_content = ParseIfrForms(HiiDbBinListBuff, BiosKnobDictNew, HiiStrDict, HiiPkgAddrDict['IfrList'][IfrFormPkgCount], 0, BiosFfsFvBase, count, FrontPageForm, LogFile, file_content) + PrintLog('====== Overall End of IFR parsing for Setup Driver count No: %d ==============' %(count), LogFile) + if(KnobStartTag == False): + if(MulSetupDrivers): + BldType='%d' %FvMainCopyCount + outXmlList.append('\t<%s BuildType="%s">\n' %(BiosKnobsTag, BldType)) + else: + BldType = None + outXmlList.append('\t<%s>\n' %BiosKnobsTag) + KnobStartTag = True + GenerateKnobsSection(BiosKnobDictNew, HiiStrDict, HiiUqiStrDict, NvRamFvListBuffer, NvramTblDict, outXmlList, AllXmlKnobs, LogFile) + BiosDictArray[FvMainCopyCount][count] = BiosKnobDictNew + if(KnobStartTag): + outXmlList.append('\t\n' %BiosKnobsTag) + file_content += ''.join(outXmlList) + if(FvMainCopyCount == (ForLoopCnt-1)): + file_content += '\n' + with open(XmlFilename,'w') as outXml: + outXml.write(file_content) + clb.SanitizeXml(XmlFilename) + log.info(f' Fetching Firmware Info Done in {XmlFilename} ') + if( (Operation == 'prog') or (Operation == 'readonly') ): + tmpPrintSts = FwpPrintEn + FwpPrintEn = True + ProgBinfileName=os.path.join(clb.TempFolder, 'biosKnobsdata.bin') + if(IniFile == 0): + if(len(KnobsStrList) != 0): + with open(clb.TmpKnobsIniFile, 'w') as IniFilePart: + IniFilePart.write( + ';-----------------------------------------------------------------\n' + '; FID XmlCli contact: xmlcli@intel.com\n' + '; XML Shared MailBox settings for XmlCli based setup\n' + '; The name entry here should be identical as the name from the XML file (retain the case)\n' + ';-----------------------------------------------------------------\n' + '[BiosKnobs]\n' + ) + for KnobString in KnobsStrList: + IniFilePart.write('%s\n' %KnobString) + IniFile = clb.TmpKnobsIniFile + else: + IniFile = configurations.BIOS_KNOBS_CONFIG + if(MulSetupDrivers): + KnobXmlFile = clb.KnobsXmlFile + with open(KnobXmlFile,'w') as tmpFile: + tmpFile.write(f'\n{"".join(outXmlList)}\n') + else: + KnobXmlFile = XmlFilename + if(clb.FlexConCfgFile): + prs.generate_bios_knobs_config(KnobXmlFile, IniFile, clb.TmpKnobsIniFile, build_type=BldType) + IniFile = clb.TmpKnobsIniFile + TmpBuff = prs.parse_cli_ini_xml(KnobXmlFile, IniFile, ProgBinfileName, build_type=BldType) + if(len(TmpBuff) == 0): + log.error('Aborting due to Error!') + FwpPrintEn = tmpPrintSts + DelTempFvFfsFiles(clb.TempFolder) + FileGuidListDict = {} + FileSystemSaveCount = 0 + LogFile.close() + clb.LastErrorSig = 0xFE91 # GetsetBiosKnobsFromBin: Empty Input Knob List + return 1 + with open(ProgBinfileName, 'rb') as ProgBinfile: + KnobsProgListBuff = list(ProgBinfile.read()) + NvRamUpdateFlag = 0 + if(MulSetupDrivers): + PrintLog(' see below for the results on Build %d...' %FvMainCopyCount, LogFile) + else: + PrintLog(' see below for the results..', LogFile) + PrintLog('|--|-----|----------------------------------------|--|-----------|-----------|', LogFile) + PrintLog('|VI|Ofset| Knob Name |Sz| DefVal | CurVal |', LogFile) + PrintLog('|--|-----|----------------------------------------|--|-----------|-----------|', LogFile) + UnProcessedKnobs = [] + for DriverFilecount in range (0, len(SetupDriverGuidList)): + CurFfsFileName = os.path.join(clb.TempFolder, '%X_File.ffs' %SetupDriverGuidList[DriverFilecount][0]) + if (os.path.isfile(CurFfsFileName) == False): + continue # didnt found this file, maybe unsupported driver for following binary + + if( (Operation == 'prog') or (Operation == 'readonly') ): + if(len(KnobsProgListBuff) > 8): + EntryCount = clb.ReadList(KnobsProgListBuff, 0, 4) + KnobBinPtr = 0x4 + for Count in range (0, EntryCount): + VarStore = clb.ReadList(KnobsProgListBuff, KnobBinPtr, 1) + Offset = clb.ReadList(KnobsProgListBuff, KnobBinPtr+1, 2) + KnobSize = clb.ReadList(KnobsProgListBuff, KnobBinPtr + 3, 1) + NvramOffset = Offset + is_bitwise = False + if Offset & 0x8000: + is_bitwise = True + NvramOffset = Offset & 0x7FFF + Offset = clb.BITWISE_KNOB_PREFIX + ((Offset & 0x7FFF) * 8) + (KnobSize & 0x7) + BitOfst = KnobSize & 0x7 + BitSize = (KnobSize >> 3) & 0x1F + BitEnd = BitOfst + BitSize + if BitEnd % 8: + KnobSize = int(BitEnd / 8) + 1 + else: + KnobSize = int(BitEnd / 8) + ReqValue = clb.ReadList(KnobsProgListBuff, KnobBinPtr+4, KnobSize) + if (is_bitwise): + ReqValue = ReqValue & (clb.and_mask(KnobSize) >> ((KnobSize * 8) - BitSize)) + if( (NvramOffset < BiosDictArray[FvMainCopyCount][DriverFilecount][VarStore]['HiiVarSize']) and (BiosDictArray[FvMainCopyCount][DriverFilecount][VarStore]['KnobDict'][Offset]['KnobPrsd'][2] == DriverFilecount) ): + KnobName = BiosDictArray[FvMainCopyCount][DriverFilecount][VarStore]['KnobDict'][Offset]['KnobName'] + HiiDefVal = BiosDictArray[FvMainCopyCount][DriverFilecount][VarStore]['KnobDict'][Offset]['HiiDefVal'] + DefVal = HiiDefVal + if(len(NvramTblDict)): + try: # Use the Default value from NVRAM FV or Default Data FFS or VPD Region (whichever is availaible and applicable), Default tagging in .hrf/.vfr will be EOL soon. + DefVal = clb.ReadList(NvRamFvListBuffer, (NvramTblDict[VarStore]['NvarDataBufPtr']+NvramOffset), KnobSize) + if (is_bitwise): + DefVal = (DefVal >> BitOfst) & (clb.and_mask(KnobSize) >> ((KnobSize * 8) - BitSize)) + CurValue = DefVal + except: + if(Operation == 'readonly'): + CurValue = HiiDefVal + else: + UnProcessedKnobs.append(KnobName) + KnobBinPtr = KnobBinPtr + 4 + KnobSize + continue + else: + CurValue = HiiDefVal + KnobLis.append({ + "KnobName": KnobName, + "ReqValue": ReqValue, + "CurValue": CurValue, + }) + + if(Operation != 'readonly'): + if( (CurValue != ReqValue) and (len(NvramTblDict)) ): + WriteVal = ReqValue + if (is_bitwise): # if BitWise read modify bit range and then write. + WriteVal = (ReqValue << BitOfst) | ( + clb.ReadList(NvRamFvListBuffer, (NvramTblDict[VarStore]['NvarDataBufPtr'] + NvramOffset), + KnobSize) & ( + ~((clb.and_mask(KnobSize) >> ((KnobSize * 8) - BitSize)) << BitOfst))) + WriteList(NvRamFvListBuffer, (NvramTblDict[VarStore]['NvarDataBufPtr']+NvramOffset), KnobSize, WriteVal) + NvRamUpdateFlag = NvRamUpdateFlag + 1 + else: + ReqValue = CurValue + if(is_bitwise): + PrintLog('|%2X|%5X|%40s|%2X| %8X | %8X |' % (VarStore, Offset, KnobName, BitSize, DefVal, ReqValue), LogFile) + else: + PrintLog('|%2X|%4X|%40s|%2X| %8X | %8X |' %(VarStore, Offset, KnobName, KnobSize, DefVal, ReqValue), LogFile) + PrintLog('|--|-----|----------------------------------------|--|-----------|-----------|', LogFile) + KnobBinPtr = KnobBinPtr + 4 + KnobSize + if( clb.ReadList(KnobsProgListBuff, KnobBinPtr, 4) != 0xE9D0FBF4): + PrintLog('error parsing KnobsProgListBuff', LogFile) + if (len(UnProcessedKnobs) != 0): + PrintLog ('Following Knobs dont exist in Defaut Offline NVRAM Data, hence ignoring them..', LogFile) + PrintLog ('\t [ %s ]' %', '.join(UnProcessedKnobs), LogFile) + if(NvRamUpdateFlag != 0): + for FileCountId in FileGuidListDict: + if(FileGuidListDict[FileCountId]['FileGuid'] == NvRamDefDataFileGuid): + BiosBinBase = FileGuidListDict[FileCountId]['BiosBinPointer'] + FileSystemSz = FileGuidListDict[FileCountId]['FileSystemSize'] + BiosBinListBuff[BiosBinBase: (BiosBinBase+FileSystemSz)] = NvRamFvListBuffer[0:FileSystemSz] + break + CreateOutFile = True + FwpPrintEn = tmpPrintSts + tmpPrintSts = FwpPrintEn + FwpPrintEn = True + if(CreateOutFile == False): + PrintLog ('No Changes detected/applied', LogFile) + if((Operation == 'prog') and ForceOutFile): + PrintLog ('ForceOutFile variable enabled, Preparing to Copy the binary to out folder anyways', LogFile) + CreateOutFile = True + if(CreateOutFile): + BiosFileName, BiosFileExt = os.path.splitext(os.path.basename(BiosBinaryFile)) + NewBiosFileName = BiosFileName.replace(BiosIdString, 'Found') + if(NewBiosFileName == BiosFileName): + NewBiosFileName = BiosFileName + '_' + BiosIdString + else: + NewBiosFileName = BiosFileName + BiosOutFolder = clb.TempFolder + ModBiosBinFileName = '' + if(BiosOut != ''): + if(os.path.lexists(BiosOut)): + BiosOutFolder = BiosOut + elif(os.path.isdir(os.path.dirname(BiosOut))): + ModBiosBinFileName = BiosOut + if(ModBiosBinFileName == ''): + if(BiosOutSufix == 0): + ModBiosBinFileName = os.path.join(BiosOutFolder, '%s_New%s' %(NewBiosFileName, BiosFileExt)) + else: + ModBiosBinFileName = os.path.join(BiosOutFolder, '%s_%s%s' %(NewBiosFileName, BiosOutSufix, BiosFileExt)) + if(SecureProfileEditing): + if(os.path.isfile(ReSigningFile)): + TempRom = os.path.join(clb.TempFolder, 'TempBIOS.rom') + with open(TempRom, 'wb') as TempRomFile: + TempRomFile.write(bytearray(BiosBinListBuff[BiosRegionBase:BiosEnd])) + TempBIOS_resign = os.path.join(clb.TempFolder, 'TempBIOS_resign.rom') + if(os.path.isfile(TempBIOS_resign)): + clb.RemoveFile(TempBIOS_resign) + try: + utils.system_call(cmd_lis=[ReSigningFile, TempRom, TempBIOS_resign]) + except: + PrintLog ('Error Running the Re-signing process, Skip Re-signing..', LogFile) + if(os.path.isfile(TempBIOS_resign)): + with open(TempBIOS_resign, 'rb') as TempRomFile: + BiosBinListBuff[BiosRegionBase:BiosEnd] = list(TempRomFile.read()) + PrintLog ('\n Resigning Process completed Successfully\n', LogFile) + else: + PrintLog ('OutFile not created by Re-signing process, please make sure correct re-signing Pkg and .bat is used\n continue without re-signing...', LogFile) + else: + PrintLog ('SecureProfileEditing Set to True, but cli.fwp.ReSigningFile is empty, skipping the Re-signing process', LogFile) + else: + PrintLog ('SecureProfileEditing Set to False, Please note that the re-generated binary maynot boot with Secure Profile IFWI (Pls ignore this message if Server BIOS)', LogFile) + clb.OutBinFile = ModBiosBinFileName + with open(ModBiosBinFileName, 'wb') as ModBiosBinFile: + ModBiosBinFile.write(bytearray(BiosBinListBuff)) + PrintLog ('Created New updated Bios File %s with desired knob settings' %ModBiosBinFileName, LogFile) + FwpPrintEn = tmpPrintSts + DelTempFvFfsFiles(clb.TempFolder) + FileGuidListDict = {} + FileSystemSaveCount = 0 + LogFile.close() + ReturnVal = 0 + if KnobsVerify and Operation == 'readonly': + VerifyErrCnt = 0 + for KnobCount in range (0, len(KnobLis)): + if(KnobLis[KnobCount]['ReqValue'] != KnobLis[KnobCount]['CurValue']): + VerifyErrCnt = VerifyErrCnt + 1 + log.result( + f'Verify Fail: Knob = {KnobLis[KnobCount]["KnobName"]} ExpectedVal = 0x{KnobLis[KnobCount]["ReqValue"]:X} CurrVal = 0x{KnobLis[KnobCount]["CurValue"]:X} ') + if (VerifyErrCnt == 0): + log.result('Verify Passed!') + else: + log.result('Verify Failed!') + ReturnVal = 1 + clb.LastErrorSig = 0xC42F # XmlCli Knobs Verify Operation Failed + return ReturnVal + +FIT_TBL_ENTRY_TYPE_0 = 0 +UCODE_ENTRY_TYPE_1 = 1 +ACM_ENTRY_TYPE_2 = 2 +START_UP_BIOS_MODULE_TYPE_ENTRY_7 = 7 +TPM_POLICY_TYPE_8 = 8 +BIOS_POLICY_TYPE_9 = 9 +TXT_POLICY_TYPE_A = 0xA +KEY_MANIFEST_TYPE_B = 0xB +BOOT_POLICY_TYPE_C = 0xC +BIOS_DATA_AREA_TYPE_D = 0xD +UNUSED_ENTRY_TYPE_7F = 0x7F +FITChkSum = 0 +FitDict = {FIT_TBL_ENTRY_TYPE_0: 'FIT', UCODE_ENTRY_TYPE_1: 'Ucode', ACM_ENTRY_TYPE_2: 'ACM', START_UP_BIOS_MODULE_TYPE_ENTRY_7: 'Start Up Bios Module', TPM_POLICY_TYPE_8: 'TPM Policy', BIOS_POLICY_TYPE_9: 'Bios Policy', TXT_POLICY_TYPE_A: 'TXT Policy', KEY_MANIFEST_TYPE_B: 'Key Manifest', BOOT_POLICY_TYPE_C: 'Boot Policy', BIOS_DATA_AREA_TYPE_D: 'Bios Data', UNUSED_ENTRY_TYPE_7F: 'Unused'} +AcmTypeDict = {0x4: 'NPW', 0x8: 'Debug'} + +def GetFitTableEntries(BiosBinListBuff): + global FITChkSum, FwIngredientDict + FwIngredientDict['FIT']={} + FwIngredientDict['FitTablePtr'] = 0 + FitTableDict = {} + if (BiosBinListBuff != 0): + BinSize = len(BiosBinListBuff) + else: + BinSize = 0 + FitSig = 0 + FitTablePtr = int(clb.ReadBios(BiosBinListBuff, BinSize, 0xFFFFFFC0, 4)) + if (FitTablePtr >= 0xFF000000): + FitSig = clb.ReadBios(BiosBinListBuff, BinSize, FitTablePtr, 8) + if (FitSig == 0x2020205F5449465F): # '_FIT_ ' + FwIngredientDict['FitTablePtr'] = FitTablePtr & 0xFFFFFFF0 # Has to be 16 Byte aligned address + Entries = clb.ReadBios(BiosBinListBuff, BinSize, FitTablePtr+8, 4) & 0xFFFFFF + if(clb.ReadBios(BiosBinListBuff, BinSize, FitTablePtr+0x0E, 1) & 0x80): # FIT Table Checksum bit Valid? + CheckSum = clb.ReadBios(BiosBinListBuff, BinSize, (FitTablePtr+0x0F), 1) + CurChkSum = 0 + for bytecount in range (0, ((Entries*16))): + CurChkSum = (CurChkSum + clb.ReadBios(BiosBinListBuff, BinSize, (FitTablePtr+bytecount), 1)) & 0xFF + FITChkSum = CurChkSum + if(CurChkSum != 0): + log.warning('FIT Table checksum (0x%X) is not valid, Table seems to be corrupted!' %(CheckSum)) + log.warning('Ignoring FIT Table checksum for now!') + # return FitTableDict + for Count in range (0, Entries): + EntryAddr = clb.ReadBios(BiosBinListBuff, BinSize, (FitTablePtr+(Count*0x10)), 8) + Size = (clb.ReadBios(BiosBinListBuff, BinSize, FitTablePtr+(Count*0x10)+0x8, 4) & 0xFFFFFF) + EntryType = (clb.ReadBios(BiosBinListBuff, BinSize, FitTablePtr+(Count*0x10)+0x0E, 1) & 0x7F) + FitTableDict[Count] = {'Type': EntryType, 'Name': FitDict.get(EntryType, 'reserved') , 'Address': EntryAddr, 'Size': Size} + FwIngredientDict['FIT'] = FitTableDict + return FitTableDict + +def FlashAcmInfo(UefiFwBinListBuff, PrintEn=True): + global FwIngredientDict + FwIngredientDict['ACM']={} + BinSize = len(UefiFwBinListBuff) + FitTableEntries = GetFitTableEntries(UefiFwBinListBuff) + AcmBase = 0 + for count in FitTableEntries: + if(FitTableEntries[count]['Type'] == ACM_ENTRY_TYPE_2): + AcmBase = FitTableEntries[count].get('Address', 0) + break + if(AcmBase == 0): + log.result('ACM Entry not Found in FIT Table!') + return + ACM_ModuleId = clb.ReadBios(UefiFwBinListBuff, BinSize, AcmBase+0x0C, 4) + ACM_VendorId = clb.ReadBios(UefiFwBinListBuff, BinSize, AcmBase+0x10, 4) + ACM_Bld_Date = clb.ReadBios(UefiFwBinListBuff, BinSize, AcmBase+0x14, 4) + ACM_Bld_Date_Str = '%02X.%02X.%04X' %(((ACM_Bld_Date >> 8) & 0xFF), (ACM_Bld_Date & 0xFF), ((ACM_Bld_Date >> 16) & 0xFFFF)) + FwIngredientDict['ACM'] = {'VendorId': ACM_VendorId, 'ModuleId': ACM_ModuleId, 'Version': '??.??.??', 'Date': ACM_Bld_Date_Str, 'Type': AcmTypeDict.get(((ACM_ModuleId >> 28) & 0xFF), '???')} + if PrintEn: + log.info( + f'ACM Module Id = 0x{ACM_ModuleId:X} ACM Vendor Id = 0x{ACM_VendorId:X} ACM Build Date = {ACM_Bld_Date_Str}') + +def FlashRegionInfo(UefiFwBinListBuff, PrintEn=True): + global FwIngredientDict + clb.LastErrorSig = 0x0000 + FwIngredientDict['FlashRegions']={} + FwIngredientDict['FlashDescpValid'] = 0 + DescBase = 0x00 + FlashValSig = clb.ReadList(UefiFwBinListBuff, (DescBase+0x10), 4) + if(FlashValSig != 0x0FF0A55A): + log.warning('Invalid Flash descriptor section!') + FwIngredientDict['FlashDescpValid'] = 0 + clb.LastErrorSig = 0x1FD4 # FlashRegionInfo: Invalid Falsh descriptor section + return 1 + FwIngredientDict['FlashDescpValid'] = 1 + FlashRegBaseOfst = (clb.ReadList(UefiFwBinListBuff, (DescBase+0x16), 1) << 4) + NoOfRegions = ((clb.ReadList(UefiFwBinListBuff, (DescBase+0x17), 1) & 0x7) + 1) + if(NoOfRegions < 10): + NoOfRegions = 10 # temp patch, as some binaries dont have this set correctly. + for region in range (0, NoOfRegions): + RegBase = (clb.ReadList(UefiFwBinListBuff, (DescBase+FlashRegBaseOfst+(region*4)+0), 2) & 0x7FFF) + RegLimit = (clb.ReadList(UefiFwBinListBuff, (DescBase+FlashRegBaseOfst+(region*4)+2), 2) & 0x7FFF) + if( (RegBase == 0x7FFF) and (RegLimit == 0) ): + if PrintEn: + log.info(f'Unused or Invalid Region ({region:d})') + FwIngredientDict['FlashRegions'][region] = {'Name': FlashRegionDict[region], 'BaseAddr': 0xFFFFFFFF, 'EndAddr': 0xFFFFFFFF} + continue + FwIngredientDict['FlashRegions'][region] = {'Name': FlashRegionDict[region], 'BaseAddr': (RegBase << 12), 'EndAddr': ((RegLimit << 12) | 0xFFF)} + if PrintEn: + log.info('|--------|------------------|------------|------------|') + log.info('| Region | Region Name | BaseAddr | End Addr |') + log.info('|--------|------------------|------------|------------|') + for FlashRegion in FwIngredientDict['FlashRegions']: + log.info( + f'| {FlashRegion:d} | {FlashRegionDict[FlashRegion]:<16} | 0x{FwIngredientDict["FlashRegions"][FlashRegion]["BaseAddr"]:<8X} | 0x{FwIngredientDict["FlashRegions"][FlashRegion]["EndAddr"]:<8X} |') + log.info('|--------|------------------|------------|------------|') + return 0 + +def GetMeInfo(UefiFwBinListBuff, PrintEn=True): + global FwIngredientDict + FwIngredientDict['ME']={} + MeBase = FwIngredientDict['FlashRegions'][ME_Region]['BaseAddr'] + if((MeBase >= len(UefiFwBinListBuff)) or (MeBase == 0) ): + return + FPT_Sig = clb.ReadList(UefiFwBinListBuff, (MeBase+0x10), 4) + FTPR_Sig = clb.ReadList(UefiFwBinListBuff, (MeBase+0x30), 4) + if( (FPT_Sig == 0x54504624) and (FTPR_Sig == 0x52505446) ): # compare with '$FPT' & 'FTPR' + CodePartitionOfst = clb.ReadList(UefiFwBinListBuff, (MeBase+0x38), 4) + CodePartitionPtr = MeBase + CodePartitionOfst + CodePartitionSig1 = clb.ReadList(UefiFwBinListBuff, (CodePartitionPtr), 4) + CodePartitionSig2 =clb.ReadList(UefiFwBinListBuff, (CodePartitionPtr+0x10), 8) + if( (CodePartitionSig1 == 0x44504324) and (CodePartitionSig2 == 0x6e616d2e52505446) ): # compare with '$CPD' & 'FTPR.man' + FTPRmanOfst = clb.ReadList(UefiFwBinListBuff, (CodePartitionPtr+0x1C), 4) + ME_Bld_Date = clb.ReadList(UefiFwBinListBuff, (CodePartitionPtr+FTPRmanOfst+0x14), 4) + ME_Version = clb.ReadList(UefiFwBinListBuff, (CodePartitionPtr+FTPRmanOfst+0x24), 8) + MeBldDateStr = '%02X.%02X.%04X' %(((ME_Bld_Date >> 8) & 0xFF), (ME_Bld_Date & 0xFF), ((ME_Bld_Date >> 16) & 0xFFFF)) + MeVerStr = '%d.%d.%d.%d' %((ME_Version & 0xFFFF), ((ME_Version >> 16) & 0xFFFF), ((ME_Version >> 32) & 0xFFFF) , ((ME_Version >> 48) & 0xFFFF)) + if PrintEn: + log.info(f'ME Version = {MeVerStr} ME Build Date = {MeBldDateStr} ') + FwIngredientDict['ME']={'Version': MeVerStr, 'Type': '???', 'Date': MeBldDateStr} # ME Type is tbd + +def GetPchStrapsInfo(UefiFwBinListBuff): + global FwIngredientDict + clb.LastErrorSig = 0x0000 + FwIngredientDict['PCH_STRAPS']={} + DescBase = 0x00 + FlashValSig = clb.ReadList(UefiFwBinListBuff, (DescBase+0x10), 4) + if(FlashValSig != 0x0FF0A55A): + log.warning('Invalid Falsh descriptor section!') + clb.LastErrorSig = 0x1FD4 # FlashRegionInfo: Invalid Falsh descriptor section + return 1 + PchStrapsBaseOfst = (clb.ReadList(UefiFwBinListBuff, (DescBase+0x1A), 1) << 4) + NoOfPchStraps = clb.ReadList(UefiFwBinListBuff, (DescBase+0x1B), 1) + for StrapNo in range (0, NoOfPchStraps): + FwIngredientDict['PCH_STRAPS'][StrapNo] = clb.ReadList(UefiFwBinListBuff, (DescBase+PchStrapsBaseOfst+(StrapNo*4)), 4) + +def FetchFwIngrediantInfo(FwBinListBuff, PrintEn=True): + global FwIngredientDict + FwIngredientDict = {} + FwIngredientDict['FlashDescpValid'] = 0 + FwIngredientDict['FitTablePtr'] = 0 + FwIngredientDict['FlashRegions'] = {} + FwIngredientDict['PCH_STRAPS'] = {} + FwIngredientDict['ME'] = {} + FwIngredientDict['FIT'] = {} + FwIngredientDict['ACM'] = {} + FwIngredientDict['Ucode'] = {} + BiosBase = 0 + BiosLimit = len(FwBinListBuff) + Status = FlashRegionInfo(FwBinListBuff, PrintEn) + if(Status == 0): + GetPchStrapsInfo(FwBinListBuff) + GetMeInfo(FwBinListBuff, PrintEn) + FlashAcmInfo(FwBinListBuff, PrintEn) + BiosBase = FwIngredientDict['FlashRegions'][BIOS_Region]['BaseAddr'] + BiosLimit = FwIngredientDict['FlashRegions'][BIOS_Region]['EndAddr'] diff --git a/src/xmlcli/XmlCli.py b/src/xmlcli/XmlCli.py index 082692c..8a72c8c 100644 --- a/src/xmlcli/XmlCli.py +++ b/src/xmlcli/XmlCli.py @@ -2,10 +2,15 @@ __author__ = ["Gahan Saraiya", "ashinde"] # Built-in Imports +import os # Custom Imports from .common import configurations from .common.logger import log +from . import XmlCliLib as clb +from . import XmlIniParser as prs +from . import UefiFwParser as fwp +from .common.uefi_nvar import get_set_var if not configurations.PERFORMANCE: # Optional helper utilities @@ -13,3 +18,662 @@ from .common import utils utils.run_cleaner() + + +BootOrderDict = {} + + +def cliProcessKnobs(xmlfilename, inifilename, CmdSubType, ignoreXmlgeneration=False, PrintResParams=True, ResBufFilename=0, KnobsVerify=False, KnobsDict={}): + clb.LastErrorSig = 0x0000 + clb.InitInterface() + DRAM_MbAddr = clb.GetDramMbAddr() # Get DRam MAilbox Address. + log.result(f'CLI Spec Version = {clb.GetCliSpecVersion(DRAM_MbAddr)}') + DramSharedMBbuf = clb.memBlock(DRAM_MbAddr,0x200) # Read/save parameter buffer + + Operation = 'Prog' + Retries = 5 + Delay = 2 + if(clb.UfsFlag): + if((CmdSubType == clb.CLI_KNOB_RESTORE_MODIFY) or (CmdSubType == clb.CLI_KNOB_LOAD_DEFAULTS)): + if (CmdSubType == clb.CLI_KNOB_RESTORE_MODIFY): + Operation = 'ResMod' + elif (CmdSubType == clb.CLI_KNOB_LOAD_DEFAULTS): + Operation = 'LoadDef' + CmdSubType = clb.CLI_KNOB_APPEND + Retries = 10 + Delay = 3 + if(ignoreXmlgeneration): + log.info('Skipping XML Download, Using the given XML File') + else: + if (CmdSubType != clb.CLI_KNOB_LOAD_DEFAULTS): + if ( clb.SaveXml(xmlfilename, 1, MbAddr=DRAM_MbAddr) == 1 ): # Check and Save the GBT XML knobs section. + log.error('Aborting due to Error!') + clb.CloseInterface() + return 1 + CLI_ReqBuffAddr = clb.readclireqbufAddr(DramSharedMBbuf) # Get CLI Request Buffer Address + CLI_ResBuffAddr = clb.readcliresbufAddr(DramSharedMBbuf) # Get CLI Response Buffer Address + log.info(f'CLI Request Buffer Addr = 0x{CLI_ReqBuffAddr:X} CLI Response Buffer Addr = 0x{CLI_ResBuffAddr:X}') + if ( (CLI_ReqBuffAddr == 0) or (CLI_ResBuffAddr == 0) ): + log.error('CLI buffers are not valid or not supported, Aborting due to Error!') + clb.CloseInterface() + clb.LastErrorSig = 0xC140 # XmlCli Req or Resp Buffer Address is Zero + return 1 + + CommandId = 0 + if (CmdSubType == clb.CLI_KNOB_APPEND): + CommandId = clb.APPEND_BIOS_KNOBS_CMD_ID + elif (CmdSubType == clb.CLI_KNOB_RESTORE_MODIFY): + CommandId = clb.RESTOREMODIFY_KNOBS_CMD_ID + elif (CmdSubType == clb.CLI_KNOB_READ_ONLY): + CommandId = clb.READ_BIOS_KNOBS_CMD_ID + elif (CmdSubType == clb.CLI_KNOB_LOAD_DEFAULTS): + CommandId = clb.LOAD_DEFAULT_KNOBS_CMD_ID + + SmiLoopCount = 1 + if (CmdSubType != clb.CLI_KNOB_LOAD_DEFAULTS): + binfile = os.path.join(clb.TempFolder, 'biosKnobsdata.bin') + if(clb.FlexConCfgFile): + prs.generate_bios_knobs_config(xmlfilename, inifilename, clb.TmpKnobsIniFile) + inifilename = clb.TmpKnobsIniFile + if(clb.UfsFlag): + BuffDict,tmpBuff = prs.generate_knobs_data_bin(xmlfilename, inifilename, binfile, Operation) + if((len(BuffDict) == 0) or (clb.ReadBuffer(tmpBuff, 0, 4, clb.HEX) == 0)) and (CmdSubType != clb.CLI_KNOB_RESTORE_MODIFY): + log.result('Request buffer is Empty, No Action required, Aborting...') + clb.CloseInterface() + clb.LastErrorSig = 0xC4B0 # XmlCli Request Buffer Empty no action needed on XmlCli Command + return 0 + SmiLoopCount = len(BuffDict) + log.result(f'Number of Nvars to be processed = {SmiLoopCount:d}') + if (CmdSubType == clb.CLI_KNOB_READ_ONLY): + SmiLoopCount = 1 + else: + tmpBuff = prs.parse_cli_ini_xml(xmlfilename, inifilename, binfile) + if((len(tmpBuff) == 0) or (clb.ReadBuffer(tmpBuff, 0, 4, clb.HEX) == 0)) and (CmdSubType != clb.CLI_KNOB_RESTORE_MODIFY): + log.result('Request buffer is Empty, No Action required, Aborting...') + clb.CloseInterface() + clb.LastErrorSig = 0xC4B0 # XmlCli Request Buffer Empty no action needed on XmlCli Command + return 0 + + #For Loop for number of current requested NVAR's + ResParamSize = 0 + for SmiCount in range (0, SmiLoopCount): + # Clear CLI Command & Response buffer headers + clb.ClearCliBuff(CLI_ReqBuffAddr, CLI_ResBuffAddr) + if (CmdSubType != clb.CLI_KNOB_LOAD_DEFAULTS): + if(SmiLoopCount == 1): + log.info(f'Req Buffer Bin file used is {binfile}') + clb.load_data(binfile, CLI_ReqBuffAddr+clb.CLI_REQ_RES_READY_PARAMSZ_OFF) + else: + loopCnt = Index = 0 + for VarId in BuffDict: + Index = VarId + if(loopCnt == SmiCount): + break + loopCnt = loopCnt + 1 + log.result( + f'Processing NVARId = {Index:d} CurrentLoopCount={SmiCount:d} RemCount={(SmiLoopCount - SmiCount - 1):d}') + NewBinfile = os.path.join(clb.TempFolder, 'biosKnobsdata_%d.bin' %Index) + log.info(f'Req Buffer Bin file used is {NewBinfile}') + clb.load_data(NewBinfile, CLI_ReqBuffAddr+clb.CLI_REQ_RES_READY_PARAMSZ_OFF) + clb.RemoveFile(NewBinfile) + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_READY_CMD_OFF, 4, CommandId) + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_READY_SIG_OFF, 4, clb.CLI_REQ_READY_SIG ) + log.info('CLI Mailbox programmed, issuing S/W SMI to program knobs...') + + Status = clb.TriggerXmlCliEntry() # trigger S/W SMI for CLI Entry + if(Status): + log.error('Error while triggering CLI Entry Point, Aborting....') + clb.CloseInterface() + return 1 + + if (clb.WaitForCliResponse(CLI_ResBuffAddr, Delay, Retries) != 0): + log.error('CLI Response not ready, Aborting....') + clb.CloseInterface() + return 1 + + CurParamSize = int(clb.memread(CLI_ResBuffAddr + clb.CLI_REQ_RES_READY_PARAMSZ_OFF, 4)) + ResParambuff = bytearray() + if(CurParamSize != 0): + CurParambuff = clb.memBlock((CLI_ResBuffAddr + clb.CLI_REQ_RES_BUFF_HEADER_SIZE), CurParamSize) + if(SmiCount == 0): + ResParambuff = CurParambuff + else: + ResParambuff = ResParambuff + CurParambuff + ResParamSize = ResParamSize + CurParamSize + #For Loop ends here. + if (ResParamSize == 0): + log.result('BIOS knobs CLI Command ended successfully, CLI Response buffer Parameter size is 0, hence returning..') + clb.CloseInterface() + clb.LastErrorSig = 0xC4E0 # XmlCli Resp Buffer Parameter Size is Zero + return 0 + + if (ResBufFilename == 0): + ResBufFilename = os.path.join(clb.TempFolder, 'RespBuffdata.bin') + with open(ResBufFilename, 'wb') as out_file: # opening for writing + out_file.write(ResParambuff) + + log.result('BIOS knobs CLI Command ended successfully',) + + offsetIn = 4 + Index = 0 + KnobsDict.clear() + if( CmdSubType != clb.CLI_KNOB_LOAD_DEFAULTS ): + with open(binfile, 'rb') as InputFile: + InputFilePart = InputFile.read() + NumberOfEntries = clb.ReadBuffer(InputFilePart, 0, 4, clb.HEX) + else: + NumberOfEntries = 1 + while(NumberOfEntries != 0): + offsetOut = 0 + if( CmdSubType != clb.CLI_KNOB_LOAD_DEFAULTS ): + InVarId = clb.ReadBuffer(InputFilePart, offsetIn+0, 1, clb.HEX) + InKnobOffset = clb.ReadBuffer(InputFilePart, offsetIn+1, 2, clb.HEX) + InKnobSize = clb.ReadBuffer(InputFilePart, offsetIn+3, 1, clb.HEX) + InByteSize = InKnobSize + if InKnobOffset & 0x8000: + InKnobOffset = clb.BITWISE_KNOB_PREFIX + ((InKnobOffset & 0x7FFF) * 8) + (InKnobSize & 0x7) + BitEnd = ( ((InKnobSize >> 3) & 0x3F) + (InKnobSize & 0x7) ) + if BitEnd % 8: + InByteSize = int(BitEnd / 8) + 1 + else: + InByteSize = int(BitEnd / 8) + InKnobSize = ((InKnobSize >> 3) & 0x3F) + InputValue = clb.ReadBuffer(InputFilePart, offsetIn+4, InByteSize, clb.HEX) + else: + InVarId = InKnobOffset = InKnobSize = InByteSize = InputValue = 0 + while(1): + if (offsetOut >= ResParamSize): + break + OutVarId = clb.ReadBuffer(ResParambuff, offsetOut+6, 1, clb.HEX) + OutKnobOffset = clb.ReadBuffer(ResParambuff, offsetOut+7, 2, clb.HEX) + OutKnobSize = clb.ReadBuffer(ResParambuff, offsetOut+9, 1, clb.HEX) + OutByteSize = OutKnobSize + if OutKnobOffset & 0x8000: + OutKnobOffset = clb.BITWISE_KNOB_PREFIX + ((OutKnobOffset & 0x7FFF) * 8) + (OutKnobSize & 0x7) + BitEnd = ( ((OutKnobSize >> 3) & 0x3F) + (OutKnobSize & 0x7) ) + if BitEnd % 8: + OutByteSize = int(BitEnd / 8) + 1 + else: + OutByteSize = int(BitEnd / 8) + OutKnobSize = ((OutKnobSize >> 3) & 0x3F) + if( ((OutVarId == InVarId) and (OutKnobOffset == InKnobOffset) and (OutKnobSize == InKnobSize)) or (CmdSubType == clb.CLI_KNOB_LOAD_DEFAULTS) ): + DefVal = clb.ReadBuffer(ResParambuff, offsetOut+10, OutByteSize, clb.HEX) + OutValue = clb.ReadBuffer(ResParambuff, offsetOut+10+OutByteSize, OutByteSize, clb.HEX) + KnobEntryAdd = clb.ReadBuffer(ResParambuff, offsetOut+0, 4, clb.HEX) + Type, KnobName = clb.findKnobName(KnobEntryAdd) + KnobsDict[Index] = {'Type': Type, 'KnobName': KnobName, 'VarId': OutVarId, 'Offset': OutKnobOffset, 'Size': OutKnobSize, 'InValue': InputValue, 'DefValue': DefVal, 'OutValue': OutValue, 'UqiVal': '', 'Prompt': ''} + Index = Index + 1 + if( CmdSubType != clb.CLI_KNOB_LOAD_DEFAULTS ): + break + offsetOut = offsetOut + 10 + (OutByteSize*2) + offsetIn = offsetIn + 4 + InByteSize + NumberOfEntries = NumberOfEntries-1 + + if (PrintResParams): + log.result(', see below for the results..') + log.result('|--|-----|------------------------------------------|--|-----------|-----------|') + if (CmdSubType == clb.CLI_KNOB_LOAD_DEFAULTS): + log.result('|VI|Ofset| Knob Name |Sz|PreviousVal|RestoredVal|') + else: + log.result('|VI|Ofset| Knob Name |Sz| DefVal | CurVal |') + log.result('|--|-----|------------------------------------------|--|-----------|-----------|') + for KnobCount in range (0, len(KnobsDict)): # read and print the return knobs entry parameters from CLI's response buffer + if(KnobsDict[KnobCount]['Type'] == 'string'): + if (KnobsDict[KnobCount]['DefValue'] == 0): + DefStr = '' + else: + DefStr = clb.UnHexLiFy(KnobsDict[KnobCount]['DefValue'])[::-1] + if (KnobsDict[KnobCount]['OutValue'] == 0): + OutStr = '' + else: + OutStr = clb.UnHexLiFy(KnobsDict[KnobCount]['OutValue'])[::-1] + log.result( + f'|{KnobsDict[KnobCount]["VarId"]:2X}| {KnobsDict[KnobCount]["Offset"]:04X}|{KnobsDict[KnobCount]["KnobName"]:>42}|{KnobsDict[KnobCount]["Size"]:2X}| L\"{DefStr}\" | L\"{OutStr}\" |') + else: + if (KnobsDict[KnobCount]['Offset'] >= clb.BITWISE_KNOB_PREFIX): + OffsetStr = '%05X' %KnobsDict[KnobCount]['Offset'] + else: + OffsetStr = ' %04X' %KnobsDict[KnobCount]['Offset'] + log.result( + f'|{KnobsDict[KnobCount]["VarId"]:2X}|{OffsetStr}|{KnobsDict[KnobCount]["KnobName"]:>42}|{KnobsDict[KnobCount]["Size"]:2X}| {KnobsDict[KnobCount]["DefValue"]:8X} | {KnobsDict[KnobCount]["OutValue"]:8X} |') + log.result('|--|-----|------------------------------------------|--|-----------|-----------|') + else: + log.result(', Print Parameter buff is disabled..') + + ReturnVal = 0 + if( KnobsVerify and (CmdSubType != clb.CLI_KNOB_LOAD_DEFAULTS) ): + VerifyErrCnt = 0 + for KnobCount in range (0, len(KnobsDict)): + if(KnobsDict[KnobCount]['InValue'] != KnobsDict[KnobCount]['OutValue']): + VerifyErrCnt = VerifyErrCnt + 1 + log.result( + f'Verify Fail: Knob = {KnobsDict[KnobCount]["KnobName"]} ExpectedVal = 0x{KnobsDict[KnobCount]["InValue"]:X} CurrVal = 0x{KnobsDict[KnobCount]["OutValue"]:X} ') + if (VerifyErrCnt == 0): + log.result('Verify Passed!') + else: + log.result('Verify Failed!') + ReturnVal = 1 + clb.LastErrorSig = 0xC42F # XmlCli Knobs Verify Operation Failed + clb.CloseInterface() + return ReturnVal + + +def GetSetVar(Operation='get', xmlfile=0, KnobString='', NvarName='', NvarGuidStr='', NvarAttri='0x00', NvarSize='0x00', NvarDataString='', DisplayVarOut=True): + # method implemented as a result of backward command compatibility!!! + + result = get_set_var( + operation=Operation, + xml_file=xmlfile, + knob_string=KnobString, + nvar_name=NvarName, + nvar_guid=utils.guid_formatter(NvarGuidStr, string_format="xmlcli"), + nvar_attrib=NvarAttri, + nvar_size=NvarSize, + nvar_data=NvarDataString, + display_result=DisplayVarOut + ) + status = 0 if result and isinstance(result, dict) else 1 + return status + + +# Descriptor_Region = 0 +# BIOS_Region = 1 +# ME_Region = 2 +# GBE_Region = 3 +# PDR_Region = 4 +# Device_Expan_Region = 5 +# Sec_BIOS_Region = 6 +def CompareFlashRegion(RefBiosFile, NewBiosFile, Region=fwp.ME_Region): + clb.LastErrorSig = 0x0000 + with open(RefBiosFile, 'rb') as BiosRomFile: + DescRegionListBuff = list(BiosRomFile.read(0x1000)) # first 4K region is Descriptor region. + fwp.FlashRegionInfo(DescRegionListBuff, False) + if(fwp.FwIngredientDict['FlashDescpValid'] != 0): + Offset = fwp.FwIngredientDict['FlashRegions'][Region]['BaseAddr'] + RegionSize = (fwp.FwIngredientDict['FlashRegions'][Region]['EndAddr'] - Offset + 1) + with open(RefBiosFile, 'rb') as RefBiosRomFile: + tmpBuff = RefBiosRomFile.read(Offset) + RefRegionBuffList = list(RefBiosRomFile.read(RegionSize)) + with open(NewBiosFile, 'rb') as NewBiosRomFile: + tmpBuff = NewBiosRomFile.read(Offset) + NewRegionBuffList = list(NewBiosRomFile.read(RegionSize)) + log.info( + f'Comparing Region \"{fwp.FlashRegionDict[Region]}\" at Flash binary Offset: 0x{Offset:X} Size: 0x{RegionSize:X} ') + if(RefRegionBuffList == NewRegionBuffList): + log.result(f'Region \"{fwp.FlashRegionDict[Region]}\" matches between the two binaries') + return 0 + else: + log.result(f'Region \"{fwp.FlashRegionDict[Region]}\" is different between the two binaries') + clb.LastErrorSig = 0xFCFA # CompareFlashRegion: Flash Compare Result for given Region is FAIL + return 1 + + +def savexml(filename=clb.PlatformConfigXml, BiosBin=0, BuildType=0xFF): + """ + Save entire/complete Target XML to desired file. + + In this function we will first check if target XML does exist, + if XML exists we will compare XML header and if doesn’t matches we will overwrite current XML. + If XML doesn’t exists we will download complete XML in desired file. + + :param filename: absolute path to xml file + :param BiosBin: (optional) IFWI/BIOS binary to generate xml from + :param BuildType: + :return: + """ + if BiosBin == 0: + status = clb.SaveXml(filename) + else: + status = fwp.GetsetBiosKnobsFromBin(BiosBin, 0, 'genxml', filename, BuildType=BuildType) + return status + + +def CreateTmpIniFile(KnobString): + if (KnobString == 0): + return clb.KnobsIniFile + else: + with open(clb.TmpKnobsIniFile, 'w') as IniFilePart: + IniFilePart.write( + ';-----------------------------------------------------------------\n' + '; FID XmlCli contact: xmlcli@intel.com\n' + '; XML Shared MailBox settings for XmlCli based setup\n' + '; The name entry here should be identical as the name from the XML file (retain the case)\n' + ';-----------------------------------------------------------------\n' + '[BiosKnobs]\n' + ) + KnobString = KnobString.replace(',', '\n') + IniFilePart.write(f'{KnobString}\n') + return clb.TmpKnobsIniFile + + +# Program given BIOS knobs for CV. +def CvProgKnobs(KnobStr=0, BiosBin=0, BinOutSufix=0, UpdateHiiDbDef=False, BiosOut='', BuildType=0xFF): + IniFile = CreateTmpIniFile(KnobStr) + if(BiosBin == 0): + Status = cliProcessKnobs(clb.PlatformConfigXml, IniFile, clb.CLI_KNOB_APPEND, 0, 1, KnobsVerify=True) + else: + Status = fwp.GetsetBiosKnobsFromBin(BiosBin, BinOutSufix, 'prog', clb.PlatformConfigXml, IniFile, UpdateHiiDbDef, BiosOut, BuildType=BuildType) + return Status + +def PrintResults(KnobsDict={}, Operation='read'): + if(len(KnobsDict) == 0): + return + else: + log.result(', see below for the results..') + log.result('|--|----|------------------------------------------|--|-----------|-----------|') + if (Operation == 'loaddefaults'): + log.result('|VI|Ofst| Knob Name |Sz|PreviousVal|RestoredVal|') + else: + log.result('|VI|Ofst| Knob Name |Sz| DefVal | CurVal |') + log.result('|--|----|------------------------------------------|--|-----------|-----------|') + for Knob in KnobsDict: + if(KnobsDict[Knob]['Type'] == 'string'): + DefStr = clb.UnHexLiFy(KnobsDict[Knob]['DefVal'])[::-1] + OutStr = clb.UnHexLiFy(KnobsDict[Knob]['CurVal'])[::-1] + log.result( + f'|{KnobsDict[Knob]["VarId"]:2X}|{KnobsDict[Knob]["Offset"]:4X}|{Knob:>42}|{KnobsDict[Knob]["Size"]:2X}| L\"{DefStr}\" | L\"{OutStr}\" |') + else: + log.result( + f'|{KnobsDict[Knob]["VarId"]:2X}|{KnobsDict[Knob]["Offset"]:4X}|{Knob:>42}|{KnobsDict[Knob]["Size"]:2X}| {KnobsDict[Knob]["DefVal"]:8X} | {KnobsDict[Knob]["CurVal"]:8X} |') + log.result('|--|----|------------------------------------------|--|-----------|-----------|') + VerifyStatus = 0 + for Knob in KnobsDict: + if(KnobsDict[Knob]['ReqVal'] != KnobsDict[Knob]['CurVal']): + log.result( + f'Verify Fail: Knob = {Knob} ExpectedVal = 0x{KnobsDict[Knob]["ReqVal"]:X} CurrVal = 0x{KnobsDict[Knob]["CurVal"]:X} ') + VerifyStatus = VerifyStatus + 1 + if (VerifyStatus == 0): + log.result('Verify Passed!') + else: + log.result('Verify Failed!') + return VerifyStatus + +def getKnobsDict(fname): + with open(fname) as file_ptr: + biosiniList = file_ptr.readlines() + iniDict = {} + knobStart = False + for LineNo in range (0, len(biosiniList)): + line = (biosiniList[LineNo].split(';')[0]).strip() + if(line == ''): + continue + if(knobStart): + (knobName,knobValue)= line.split('=') + iniDict[knobName.strip()] = knobValue.strip() + if (line == '[BiosKnobs]'): + knobStart = True + continue + return iniDict + +# save entire/complete Target XML to desired file. +def savexmllite(filename=clb.PlatformConfigLiteXml): + Status = clb.SaveXmlLite(filename) + return Status + +def ReadKnobsLite(KnobStr=0): + IniFile = CreateTmpIniFile(KnobStr) + MyKnobDict = getKnobsDict(IniFile) + if(len(MyKnobDict) == 0): + log.result('Input knob List is empty, returning!') + return 0 + Status = clb.SaveXmlLite(clb.PlatformConfigLiteXml, Operation='savexml', UserKnobsDict=MyKnobDict) + if (Status == 0): + RetDict, PrevDict = prs.xml_to_knob_map(clb.PlatformConfigLiteXml, MyKnobDict) + Status = PrintResults(RetDict, Operation='prog') + return Status + +def ProgKnobsLite(KnobStr=0): + IniFile = CreateTmpIniFile(KnobStr) + MyKnobDict = getKnobsDict(IniFile) + if(len(MyKnobDict) == 0): + log.result('Input knob List is empty, returning!') + return 0 + Status = clb.SaveXmlLite(clb.PlatformConfigLiteXml, Operation='prog', UserKnobsDict=MyKnobDict) + if (Status == 0): + RetDict, PrevDict = prs.xml_to_knob_map(clb.PlatformConfigLiteXml, MyKnobDict) + Status = PrintResults(RetDict, Operation='prog') + return Status + +def ResModKnobsLite(KnobStr=0): + Status = clb.SaveXmlLite(clb.PlatformConfigLiteXml, Operation='savexml') + if (Status == 0): + IniFile = CreateTmpIniFile(KnobStr) + MyKnobDict = getKnobsDict(IniFile) + RetDict, PrevDict = prs.xml_to_knob_map(clb.PlatformConfigLiteXml, MyKnobDict, operation='restore') + if(len(RetDict) == 0): + log.result('Input knob List is empty and other Knobs already thier Defaults, returning!') + return 0 + Status = clb.SaveXmlLite(clb.PlatformConfigLiteXml, Operation='prog', UserKnobsDict=RetDict) + if (Status == 0): + ResDict, PrevDict = prs.xml_to_knob_map(clb.PlatformConfigLiteXml, RetDict) + Status = PrintResults(ResDict, Operation='prog') + return Status + +def LoadDefaultsLite(): + Status = clb.SaveXmlLite(clb.PlatformConfigLiteXml, Operation='savexml') + if (Status == 0): + PreValDict={} + RetDict, PrevDict = prs.xml_to_knob_map(clb.PlatformConfigLiteXml, operation='restore') + if(len(RetDict) == 0): + log.result('Current Knobs already at their Defaults!') + return 0 + Status = clb.SaveXmlLite(clb.PlatformConfigLiteXml, Operation='prog', UserKnobsDict=RetDict) + if (Status == 0): + ResDict, tempDict = prs.xml_to_knob_map(clb.PlatformConfigLiteXml, RetDict) + for knob in PrevDict: + ResDict[knob]['DefVal'] = clb.Str2Int(PrevDict[knob]) + Status = PrintResults(ResDict, Operation='loaddefaults') + return Status + +# Restore & then modify given BIOS knobs for CV. +def CvRestoreModifyKnobs(KnobStr=0, BiosBin=0): + IniFile = CreateTmpIniFile(KnobStr) + if(BiosBin == 0): + Status = cliProcessKnobs(clb.PlatformConfigXml, IniFile, clb.CLI_KNOB_RESTORE_MODIFY, 0, 1, KnobsVerify=True) + else: + log.error('Restore modify operation is not supported in Offline mode, please use CvProgKnobs with pristine Bios binary to get the same effect') + Status = 0 + return Status + +# Load Default BIOS knobs for CV. +def CvLoadDefaults(BiosBin=0): + if(BiosBin == 0): + Status = cliProcessKnobs(clb.PlatformConfigXml, clb.KnobsIniFile, clb.CLI_KNOB_LOAD_DEFAULTS, 0, 1, KnobsVerify=False) + else: + log.error('Load Defaults operation is not supported in Offline mode, please use pristine Bios binary instead') + Status = 0 + return Status + +# Read BIOS knobs for CV. +def CvReadKnobs(KnobStr=0, BiosBin=0, BuildType=0xFF): + IniFile = CreateTmpIniFile(KnobStr) + if(BiosBin == 0): + Status = cliProcessKnobs(clb.PlatformConfigXml, IniFile, clb.CLI_KNOB_READ_ONLY, 0, 1, KnobsVerify=True) + else: + Status = fwp.GetsetBiosKnobsFromBin(BiosBin, 0, 'readonly', clb.PlatformConfigXml, IniFile, BuildType=BuildType, KnobsVerify=True) + return Status + +def GenBootOrderDict(PcXml, NewBootOrderStr=''): + global BootOrderDict + clb.LastErrorSig = 0x0000 + Tree = prs.ET.parse(PcXml) + BootOrderDict = {} + BootOrderDict['OptionsDict'] = {} + BootOrderDict['OrderList'] = {} + OrderIndex = 0 + for SetupKnobs in Tree.iter(tag='biosknobs'): + for BiosKnob in SetupKnobs: + SETUPTYPE = (prs.nstrip(BiosKnob.get('setupType'))).upper() + KnobName = prs.nstrip(BiosKnob.get('name')) + if (KnobName[0:10] == 'BootOrder_'): + BootOrderDict['OrderList'][OrderIndex] = int(prs.nstrip(BiosKnob.get('CurrentVal')), 16) + if ( (SETUPTYPE == 'ONEOF') and (OrderIndex == 0) ): + OptionsCount = 0 + for options in BiosKnob: + for option in options: + BootOrderDict['OptionsDict'][OptionsCount] = { 'OptionText': prs.nstrip(option.get('text')), 'OptionVal': int(prs.nstrip(option.get('value')), 16) } + OptionsCount = OptionsCount + 1 + OrderIndex = OrderIndex + 1 + if (NewBootOrderStr == ''): + BootOrderLen = len(BootOrderDict['OrderList']) + if(BootOrderLen == 0): + log.result('\tBoot Order Variable not found in XML!') + clb.LastErrorSig = 0xB09F # GenBootOrderDict: Boot Order Variable not found in XML + return 1 + else: + if(len(BootOrderDict['OptionsDict']) == 0): + log.result('\tBoot Order Options is empty!') + clb.LastErrorSig = 0xB09E # GenBootOrderDict: Boot Order Options is empty in XML + return 1 + BootOrderString = '' + for count in range (0, BootOrderLen): + if (count == 0): + BootOrderString = BootOrderString + '%02X' %(BootOrderDict['OrderList'][count]) + else: + BootOrderString = BootOrderString + '-%02X' %(BootOrderDict['OrderList'][count]) + log.result(f'\n\tThe Current Boot Order: {BootOrderString}') + log.result('\n\tList of Boot Devices in the Current Boot Order') + for count in range (0, BootOrderLen): + for count1 in range (0, len(BootOrderDict['OptionsDict'])): + if(BootOrderDict['OrderList'][count] == BootOrderDict['OptionsDict'][count1]['OptionVal']): + log.result( + f'\t\t{BootOrderDict["OptionsDict"][count1]["OptionVal"]:02X} - {BootOrderDict["OptionsDict"][count1]["OptionText"]}') + break + else: + NewBootOrder = NewBootOrderStr.split('-') + KnobString = '' + if(len(NewBootOrder) != len(BootOrderDict['OrderList'])): + log.error('\tGiven Boot order list length doesnt match current, aborting') + clb.LastErrorSig = 0xB09D # GenBootOrderDict: Given Boot order list length doesn't match current list + return 1 + for count in range (0, len(NewBootOrder)): + KnobString = KnobString + 'BootOrder_' + '%d' %count + ' = 0x' + NewBootOrder[count] + ', ' + CvProgKnobs('%s' %KnobString) + return 0 + +def GetBootOrder(): + Return=savexml(clb.PlatformConfigXml) + if (Return==0): + GenBootOrderDict(clb.PlatformConfigXml) + log.result('\n\tRequested operations completed successfully.\n') + return 0 + else: + log.error('\n\tRequested operation is Incomplete\n') + return 1 + +def SetBootOrder(NewBootOrderStr=''): + clb.LastErrorSig = 0x0000 + try: + Return=savexml(clb.PlatformConfigXml) + if (Return==0): + set_operation=GenBootOrderDict(clb.PlatformConfigXml, NewBootOrderStr) + if (set_operation==0): + Return1=savexml(clb.PlatformConfigXml) + if (Return1==0): + GenBootOrderDict(clb.PlatformConfigXml) + log.result('\tRequested operations completed successfully.\n') + return 0 + else: + log.error('\tRequested operation is Incomplete\n') + else: + log.error('\n\tRequested operation is Incomplete\n') + else: + log.error('\n\tRequested operation is Incomplete\n') + clb.LastErrorSig = 0x5B01 # SetBootOrder: Requested operation is Incomplete + except IndexError: + log.error('\n\tInvalid format to bootorder!!!\n') + clb.LastErrorSig = 0x5B1F # SetBootOrder: Invalid format to Set BootOrder + return 1 + + +def MsrAccess(operation, MsrNumber=0xFFFFFFFF, ApicId=0xFFFFFFFF, MsrValue=0): + clb.LastErrorSig = 0x0000 + if( (MsrNumber == 0xFFFFFFFF) or (ApicId == 0xFFFFFFFF)): + return 0 + clb.InitInterface() + DRAM_MbAddr = clb.GetDramMbAddr() # Get Dram Mailbox Address. + log.result(f'CLI Spec Version = {clb.GetCliSpecVersion(DRAM_MbAddr)}') + DramSharedMBbuf = clb.memBlock(DRAM_MbAddr,0x110) # Read/save parameter buffer + CLI_ReqBuffAddr = clb.readclireqbufAddr(DramSharedMBbuf) # Get CLI Request Buffer Adderss + CLI_ResBuffAddr = clb.readcliresbufAddr(DramSharedMBbuf) # Get CLI Response Buffer Address + log.info(f'CLI Request Buffer Addr = 0x{CLI_ReqBuffAddr:X} CLI Response Buffer Addr = 0x{CLI_ResBuffAddr:X}') + if ( (CLI_ReqBuffAddr == 0) or (CLI_ResBuffAddr == 0) ): + log.error('CLI buffers are not valid or not supported, Aborting due to Error!') + clb.CloseInterface() + clb.LastErrorSig = 0xC140 # XmlCli Req or Resp Buffer Address is Zero + return 1 + + # Clear CLI Command & Response buffer headers + clb.ClearCliBuff(CLI_ReqBuffAddr, CLI_ResBuffAddr) + for Count in range (0, 0x20): + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_BUFF_HEADER_SIZE + Count, 8, 0 ) + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_READY_CMD_OFF, 8, operation ) + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_READY_PARAMSZ_OFF, 4, 8 ) + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_BUFF_HEADER_SIZE, 4, MsrNumber ) + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_BUFF_HEADER_SIZE + 4, 4, ApicId ) + if (operation == clb.WRITE_MSR_OPCODE): + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_BUFF_HEADER_SIZE + 8, 8, MsrValue ) + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_READY_SIG_OFF, 4, clb.CLI_REQ_READY_SIG ) + log.info('CLI Mailbox programmed, now issuing S/W SMI to execute the given command..') + + Status = clb.TriggerXmlCliEntry() # trigger S/W SMI for CLI Entry + if(Status): + log.error('Error while triggering CLI Entry Point, Aborting....') + clb.CloseInterface() + return 1 + if (clb.WaitForCliResponse(CLI_ResBuffAddr, 8) != 0): + log.error('CLI Response not ready, Aborting....') + clb.CloseInterface() + return 1 + + if (operation == clb.READ_MSR_OPCODE): + MsrValue = int(clb.memread(CLI_ResBuffAddr + clb.CLI_REQ_RES_BUFF_HEADER_SIZE, 8)) + log.result(f'Msr No. 0x{MsrNumber:X} ApicId = 0x{ApicId:X} MsrValue = 0x{MsrValue:X} ') + clb.CloseInterface() + return 0 + +def IoAccess(operation, IoPort=0xFFFF, Size=0xFF, IoValue=0): + clb.LastErrorSig = 0x0000 + if( (IoPort == 0xFFFF) or (Size == 0xFF)): + return 0 + clb.InitInterface() + DRAM_MbAddr = clb.GetDramMbAddr() # Get Dram Mailbox Address. + log.result(f'CLI Spec Version = {clb.GetCliSpecVersion(DRAM_MbAddr)}') + DramSharedMBbuf = clb.memBlock(DRAM_MbAddr,0x110) # Read/save parameter buffer + CLI_ReqBuffAddr = clb.readclireqbufAddr(DramSharedMBbuf) # Get CLI Request Buffer Address + CLI_ResBuffAddr = clb.readcliresbufAddr(DramSharedMBbuf) # Get CLI Response Buffer Address + log.info(f'CLI Request Buffer Addr = 0x{CLI_ReqBuffAddr:X} CLI Response Buffer Addr = 0x{CLI_ResBuffAddr:X}') + if ( (CLI_ReqBuffAddr == 0) or (CLI_ResBuffAddr == 0) ): + log.error('CLI buffers are not valid or not supported, Aborting due to Error!') + clb.CloseInterface() + clb.LastErrorSig = 0xC140 # XmlCli Req or Resp Buffer Address is Zero + return 1 + + # Clear CLI Command & Response buffer headers + clb.ClearCliBuff(CLI_ReqBuffAddr, CLI_ResBuffAddr) + for Count in range (0, 0x8): + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_BUFF_HEADER_SIZE + Count, 8, 0 ) + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_READY_CMD_OFF, 8, operation ) + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_READY_PARAMSZ_OFF, 4, 8 ) + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_BUFF_HEADER_SIZE, 4, IoPort ) + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_BUFF_HEADER_SIZE + 4, 4, Size ) + if (operation == clb.IO_WRITE_OPCODE): + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_BUFF_HEADER_SIZE + 8, 4, IoValue ) + clb.memwrite( CLI_ReqBuffAddr + clb.CLI_REQ_RES_READY_SIG_OFF, 4, clb.CLI_REQ_READY_SIG ) + log.info('CLI Mailbox programmed, now issuing S/W SMI to execute the given command..') + + Status = clb.TriggerXmlCliEntry() # trigger S/W SMI for CLI Entry + if(Status): + log.error('Error while triggering CLI Entry Point, Aborting....') + clb.CloseInterface() + return 1 + if (clb.WaitForCliResponse(CLI_ResBuffAddr, 8) != 0): + log.error('CLI Response not ready, Aborting....') + clb.CloseInterface() + return 1 + + if (operation == clb.IO_READ_OPCODE): + IoValue = int(clb.memread(CLI_ResBuffAddr + clb.CLI_REQ_RES_BUFF_HEADER_SIZE, 8)) + log.result(f'IO Port 0x{IoPort:X} Size = 0x{Size:X} Value = 0x{IoValue:X} ') + clb.CloseInterface() + return 0 diff --git a/src/xmlcli/XmlCliLib.py b/src/xmlcli/XmlCliLib.py new file mode 100644 index 0000000..107e92e --- /dev/null +++ b/src/xmlcli/XmlCliLib.py @@ -0,0 +1,2031 @@ +#!/usr/bin/env python +__author__ = ['ashinde', 'Gahan Saraiya'] + +# Built-in Imports +import os +import sys +import time +import copy +import binascii +import importlib + + +# Custom Imports +from .common import utils +from .common import configurations +from .common import logger +from .common import compress +from .common.logger import log +from .access.stub import stub +from ._version import __version__ + +try: + from defusedxml import ElementTree as ET +except ModuleNotFoundError as e: + log.warn("Insecure module import used! Please install all the required dependencies by running `pip install -r requirements.txt`") + from xml.etree import ElementTree as ET + +cliaccess = stub.StubAccess("stub") +FlexConCfgFile = False +ForceReInitCliAccess = False +UfsFlag = False +KnobsIniFile = configurations.BIOS_KNOBS_CONFIG +XmlCliToolsDir = configurations.TOOL_DIR +TianoCompressUtility = configurations.TIANO_COMPRESS_BIN +BrotliCompressUtility = configurations.BROTLI_COMPRESS_BIN + +TempFolder = configurations.OUT_DIR + +KnobsXmlFile = os.path.join(TempFolder, 'BiosKnobs.xml') +PlatformConfigXml = os.path.join(TempFolder, 'PlatformConfig.xml') +PlatformConfigLiteXml = os.path.join(TempFolder, 'PlatformConfigLite.xml') +SvXml = os.path.join(TempFolder, 'SvPlatformConfig.xml') + +TmpKnobsIniFile = os.path.join(TempFolder, 'TmpBiosKnobs.ini') +OutBinFile = '' +gDramSharedMbAddr = 0 +MerlinxXmlCliEnableAddr = 0 +InterfaceType = configurations.ACCESS_METHOD +XmlCliLogFile = os.path.join(TempFolder, 'XmlCli.log') +XmlCliRespFlags = {'Status': 0, 'CantExe': 0, 'WrongParam': 0, 'TimedOut': 0, 'SideEffect': 'NoSideEffect'} +LastErrorSig = 0x0000 +LastErrorSigDict = {int(key, 16): value["msg"] for key, value in utils.STATUS_CODE_RECORD.items()} + +log = logger.settings.logger + +CliRespFlags = 0 +_isExeAvailable = True + +SHAREDMB_SIG1 = 0xBA5EBA11 +SHAREDMB_SIG2 = 0xBA5EBA11 +SHARED_MB_LEGMB_SIG_OFF = 0x20 +SHARED_MB_LEGMB_ADDR_OFF = 0x24 +LEGACYMB_SIG = 0x5A7ECAFE +XML_START = '' +XML_END = '' +SHAREDMB_SIG1_OFF = 0x00 +SHAREDMB_SIG2_OFF = 0x08 +CLI_SPEC_VERSION_MINOR_OFF = 0x14 +CLI_SPEC_VERSION_MAJOR_OFF = 0x15 +CLI_SPEC_VERSION_RELEASE_OFF = 0x17 +LEGACYMB_SIG_OFF = 0x20 +LEGACYMB_OFF = 0x24 +LEGACYMB_XML_OFF = 0x0C +MERLINX_XML_CLI_ENABLED_OFF = 0x28 +LEGACYMB_XML_CLI_TEMP_ADDR_OFF = 0x60 +STRING = 0x51 +ASCII = 0xA5 +HEX = 0x16 +SETUP_KNOBS_ADDR_OFF = 0x13C +SETUP_KNOBS_SIZE_OFF = 0x140 +CPUSV_MAILBOX_ADDR_OFF = 0x14C +XML_CLI_DISABLED_SIG = 0xCD15A1ED +SHARED_MB_CLI_REQ_BUFF_SIG = 0xCA11AB1E +SHARED_MB_CLI_RES_BUFF_SIG = 0xCA11B0B0 +SHARED_MB_CLI_REQ_BUFF_SIG_OFF = 0x30 +SHARED_MB_CLI_RES_BUFF_SIG_OFF = 0x40 +SHARED_MB_CLI_REQ_BUFF_ADDR_OFF = 0x34 +SHARED_MB_CLI_RES_BUFF_ADDR_OFF = 0x44 +SHARED_MB_CLI_REQ_BUFF_SIZE_OFF = 0x38 +SHARED_MB_CLI_RES_BUFF_SIZE_OFF = 0x48 +CLI_REQ_READY_SIG = 0xC001C001 +CLI_RES_READY_SIG = 0xCAFECAFE +CLI_REQ_RES_READY_SIG_OFF = 0x00 +CLI_REQ_RES_READY_CMD_OFF = 0x04 +CLI_REQ_RES_READY_FLAGS_OFF = 0x06 +CLI_REQ_RES_READY_STATUS_OFF = 0x08 +CLI_REQ_RES_READY_PARAMSZ_OFF = 0x0C +CLI_REQ_RES_BUFF_HEADER_SIZE = 0x10 +WRITE_MSR_OPCODE = 0x11 +READ_MSR_OPCODE = 0x21 +IO_READ_OPCODE = 0x31 +IO_WRITE_OPCODE = 0x32 +APPEND_BIOS_KNOBS_CMD_ID = 0x48 +RESTOREMODIFY_KNOBS_CMD_ID = 0x49 +READ_BIOS_KNOBS_CMD_ID = 0x4A +LOAD_DEFAULT_KNOBS_CMD_ID = 0x4B +PROG_BIOS_CMD_ID = 0xB4 +FETCH_BIOS_CMD_ID = 0xB5 +BIOS_VERSION_OPCODE = 0xB1 +EXE_SV_SPECIFIC_CODE_OPCODE = 0x300 +READ_BRT_OPCODE = 0x310 +CREATE_FRESH_BRT_OPCODE = 0x311 +ADD_BRT_OPCODE = 0x312 +DEL_BRT_OPCODE = 0x313 +DIS_BRT_OPCODE = 0x314 +GET_SET_VARIABLE_OPCODE = 0x9E5E +CLI_KNOB_APPEND = 0x0 +CLI_KNOB_RESTORE_MODIFY = 0x1 +CLI_KNOB_READ_ONLY = 0x2 +CLI_KNOB_LOAD_DEFAULTS = 0x3 + +CliSpecRelVersion = 0x00 +CliSpecMajorVersion = 0x00 +CliSpecMinorVersion = 0x00 + +CliCmdDict = {APPEND_BIOS_KNOBS_CMD_ID: 'APPEND_BIOS_KNOBS_CMD_ID', RESTOREMODIFY_KNOBS_CMD_ID: 'RESTOREMODIFY_KNOBS_CMD_ID', + READ_BIOS_KNOBS_CMD_ID : 'READ_BIOS_KNOBS_CMD_ID', LOAD_DEFAULT_KNOBS_CMD_ID: 'LOAD_DEFAULT_KNOBS_CMD_ID', + PROG_BIOS_CMD_ID : 'PROG_BIOS_CMD_ID', FETCH_BIOS_CMD_ID: 'FETCH_BIOS_CMD_ID', + BIOS_VERSION_OPCODE : 'BIOS_VERSION_OPCODE', EXE_SV_SPECIFIC_CODE_OPCODE: 'EXE_SV_SPECIFIC_CODE_OPCODE', + READ_MSR_OPCODE : 'READ_MSR_OPCODE', WRITE_MSR_OPCODE: 'WRITE_MSR_OPCODE', + IO_READ_OPCODE : 'IO_READ_OPCODE', IO_WRITE_OPCODE: 'IO_WRITE_OPCODE', + READ_BRT_OPCODE : 'READ_BRT_OPCODE', CREATE_FRESH_BRT_OPCODE: 'CREATE_FRESH_BRT_OPCODE', ADD_BRT_OPCODE: 'ADD_BRT_OPCODE', + DEL_BRT_OPCODE : 'DEL_BRT_OPCODE', DIS_BRT_OPCODE: 'DIS_BRT_OPCODE'} + +# Constants for Bitwise Knobs +BITWISE_KNOB_PREFIX = 0xC0000 + + +def and_mask(width, unit="byte"): + """Generate And Mask with all 1's for bit + + :param width: width of the data, default in bytes + :param unit: unit in which data to be interpreted + :return: + all width bits set to 1 for given width + """ + if unit.lower() in ("byte", "bytes", "b"): + multiplier = 8 + elif unit.lower() in ("kilobyte", "kilobytes", "kb"): + multiplier = 8 * 1024 + else: + multiplier = 1 + return (2 ** (width * multiplier)) - 1 + + +def get_bitwise_knob_details(knob_size, knob_offset, padding=0x8000): + """Calculate Knob width for bitwise and non-bitwise knobs + + :param knob_size: size of the knob as per bios knobs data bin + :param knob_offset: offset of the knob as per bios knobs data bin + :param padding: Add 0x8000 to offset to Set BIT15 of Offset to indicate this is Bitwise knob + :return: knob_width, knob_offset, bit_offset + """ + knob_offset = knob_offset & 0x3FFFF + bit_offset = int(knob_offset % 8) + knob_offset = int(knob_offset / 8) + padding + knob_width = bit_offset + knob_size + if knob_width % 8: + knob_width = int(knob_width / 8 + 1) + else: + knob_width = int(knob_width / 8) + return knob_width, knob_offset, bit_offset + + +class CliLib(object): + def __init__(self, access_request=None, *args, **kwargs): + access_methods = self.get_available_access_methods() + error_flag = access_request not in access_methods + if access_request in access_methods: + access_config_location = os.path.join(configurations.XMLCLI_DIR, access_methods[access_request]) + access_file_name = os.path.splitext(os.path.basename(access_config_location))[0] + if os.path.exists(access_config_location): + self.access_config = configurations.config_read(access_config_location) + access_file = self.access_config.get(access_file_name.upper(), "file") # Source file of access method + access_file_location = "xmlcli.access.{}.{}".format(access_file_name, os.path.splitext(access_file)[0]) + access_file = importlib.import_module(access_file_location) # Import access method + method_class = self.access_config.get(access_file_name.upper(), "method_class") + self.access_instance = getattr(access_file, method_class)(access_file_name) # create instance of Access method class + else: + error_flag = True + if error_flag: + raise utils.XmlCliException(error_code="0x3001") # Refer messages.json for meaning of error code + + @staticmethod + def get_available_access_methods(): + """Gather all the available access method name and it's configuration file from defined in tool configuration file + + :return: dictionary structure {access_method_name: config_file} + """ + access_methods = dict(configurations.XMLCLI_CONFIG['ACCESS_METHODS']) + return access_methods + + def set_cli_access(self, access_request=None): + access_methods = self.get_available_access_methods() + if access_request in access_methods: + access_config = os.path.join(configurations.XMLCLI_DIR, access_methods["access_request"]) + if os.path.exists(access_config): + self.access_config = configurations.config_read(access_config) + + +def is_exe_available(interface_type): + status = True + return status + + +def _setCliAccess(req_access=None): + global cliaccess, InterfaceType, _isExeAvailable, LastErrorSig + if req_access != None: + InterfaceType = req_access + try: + cli_instance = CliLib(InterfaceType.lower()) + cliaccess = cli_instance.access_instance # Assign access method instance + _isExeAvailable = is_exe_available(InterfaceType) + except Exception as e: + InterfaceType = 'stub' + + if InterfaceType == 'stub': + cli_instance = CliLib(InterfaceType.lower()) + cliaccess = cli_instance.access_instance + if req_access not in ('stub', 'offline') and (InterfaceType == 'stub'): + LastErrorSig = 0x19FD # Error initializing the given Interface Type + log.error('**** Error initializing the given Interface Type ****') + else: + LastErrorSig = 0x0000 + log.result(f'**** Using \"{InterfaceType}\" mode as Interface ****') + + +def _checkCliAccess(): + global cliaccess, ForceReInitCliAccess + if ((cliaccess == None) or (ForceReInitCliAccess)): + _setCliAccess() + + +def haltcpu(delay=0): + """ + This function will check the CPU state only when Interface type is + debug interface used between host and target. + + If target CPU is already halted then this function + will return without taking any action. + If target CPU is running it will issue `halt()` command. + + :param delay: wait time in seconds for command execution + :return: status of halt action from interface + """ + global cliaccess + _checkCliAccess() + return cliaccess.halt_cpu(delay) + +def runcpu(): + """ + This function will check the CPU state only when Interface type is + debug interface used between host and target. + + If target CPU is already halted then this function + will return without taking any action. + If target CPU is running it will issue `go()` command. + + :return: status of run cpu action from interface + """ + global cliaccess + _checkCliAccess() + return cliaccess.run_cpu() + +def InitInterface(): + global cliaccess + _checkCliAccess() + return cliaccess.initialize_interface() + +def CloseInterface(): + global cliaccess + _checkCliAccess() + return cliaccess.close_interface() + + +def warmreset(): + """ + Resets system without actually interrupting system power. + Value `0x06` to PCI register `0xCF9` is written to achieve the warm reset. + + :return: + """ + global cliaccess + _checkCliAccess() + return cliaccess.warm_reset() + + +def coldreset(): + """ + Cold reset is one of the type of system reboot whereby the power to the system + is physically turned OFF and back ON again. + Value `0x0E` to PCI register `0xCF9` is written to achieve the cold reset. + + :return: + """ + global cliaccess + _checkCliAccess() + return cliaccess.cold_reset() + + +def memBlock(address, size): + """ + Reads the data block of given size from target memory + starting from given address. + + > The read data is in bit format. + > It is converted in string/ASCII to allow manipulated on byte granularity. + + :param address: address from which memory block needs to be read + :param size: size of block to be read + :return: + """ + global cliaccess + _checkCliAccess() + return cliaccess.mem_block(address, size) + + +def memsave(filename, address, size): + """ + Saves the memory block of given byte size to desired file + + :param filename: destination file where fetched data will be stored + :param address: address from which data is to be copied + :param size: total amount of data to be read + :return: + """ + global cliaccess + _checkCliAccess() + return cliaccess.mem_save(filename, address, size) + + +def memdump(address, size, unit=1): + """ + Dumps the memory content of given byte size in + respective units on to the console + + :param address: address from which data is to be copied + :param size: total amount of data to be read + :param unit: unit length in which data to be displayed (choices are: 1|2|4|8) + :return: + """ + TempDataBinFile = os.path.join(os.path.dirname(KnobsXmlFile), 'MemData_%X.bin' %address) + memsave(TempDataBinFile, address, size) + with open(TempDataBinFile, 'rb') as TempData: + ListBuff = list(TempData.read()) + log.result('________________________________________________________________________________') + if unit == 1: + log.result(' Address | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |') + log.result('---------------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|') + elif unit == 2: + log.result(' Address | 0 | 2 | 4 | 6 | 8 | A | C | E |') + log.result('---------------|-------|-------|-------|-------|-------|-------|-------|-------|') + elif unit == 4: + log.result(' Address | 0 | 4 | 8 | C |') + log.result('---------------|---------------|---------------|---------------|---------------|') + elif unit == 8: + log.result(' Address | 0 | 8 |') + log.result('---------------|-------------------------------|-------------------------------|') + CurAddr = address + for count in range (0, int(size/0x10)): + Value = ListBuff[(count*0x10):((count*0x10)+16)] + if unit == 1: + log.result(' %13s |%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X |' %(('0x%lX' %CurAddr), Value[0], Value[1], Value[2], Value[3], Value[4], Value[5], Value[6], Value[7], Value[8], Value[9], Value[10], Value[11], Value[12], Value[13], Value[14], Value[15])) + elif unit == 2: + log.result(' %13s |0x%02X%02X 0x%02X%02X 0x%02X%02X 0x%02X%02X 0x%02X%02X 0x%02X%02X 0x%02X%02X 0x%02X%02X |' %(('0x%lX' %CurAddr), Value[1], Value[0], Value[3], Value[2], Value[5], Value[4], Value[7], Value[6], Value[9], Value[8], Value[11], Value[10], Value[13], Value[12], Value[15], Value[14])) + elif unit == 4: + log.result(' %13s | 0x%02X%02X%02X%02X 0x%02X%02X%02X%02X 0x%02X%02X%02X%02X 0x%02X%02X%02X%02X |' %(('0x%lX' %CurAddr), Value[3], Value[2], Value[1], Value[0], Value[7], Value[6], Value[5], Value[4], Value[11], Value[10], Value[9], Value[8], Value[15], Value[14], Value[13], Value[12])) + elif unit == 8: + log.result(' %13s | 0x%02X%02X%02X%02X%02X%02X%02X%02X 0x%02X%02X%02X%02X%02X%02X%02X%02X |' %(('0x%lX' %CurAddr), Value[7], Value[6], Value[5], Value[4], Value[3], Value[2], Value[1], Value[0], Value[15], Value[14], Value[13], Value[12], Value[11], Value[10], Value[9], Value[8])) + CurAddr = CurAddr + 0x10 + + RemBytes = int(size%0x10) + if(RemBytes): + Value = ListBuff[(CurAddr-address):((CurAddr-address)+RemBytes)] + ValueStr = '' + if(unit == 1): + for cnt in range(0x0,RemBytes): + ValueStr = ValueStr + '%02X ' %Value[cnt] + elif(unit == 2): + for cnt in range(0x0,int(RemBytes/2)): + Index = cnt*2 + ValueStr = ValueStr + '0x%02X%02X ' %(Value[Index+1], Value[Index]) + elif(unit == 4): + for cnt in range(0x0,int(RemBytes/4)): + Index = cnt*4 + ValueStr = ValueStr + ' 0x%02X%02X%02X%02X ' %(Value[Index+3], Value[Index+2], Value[Index+1], Value[Index]) + elif(unit == 8): + for cnt in range(0x0,int(RemBytes/8)): + Index = cnt*8 + ValueStr = ValueStr + ' 0x%02X%02X%02X%02X%02X%02X%02X%02X ' %(Value[Index+7], Value[Index+6], Value[Index+5], Value[Index+4], Value[Index+3], Value[Index+2], Value[Index+1], Value[Index]) + log.result(f' {(f"0x{CurAddr:X}"):>13} |{ValueStr}') + + +def memread(address, size): + """ + This function reads data from specific memory. + It can be used to read Maximum `8 bytes` of data. + + > This function cannot be used to read Blocks of data. + + :param address: source address from which data to be read + :param size: size of the data to be read + :return: + """ + global cliaccess + _checkCliAccess() + return int(cliaccess.mem_read(address, size)) + + +def memwrite(address, size, value): + """ + This function writes data to specific memory. + It can be used to write Maximum `8 bytes` of data. + + > This function cannot be used to write Blocks of data. + + :param address: source address at which data to be written + :param size: size of the data to be read + :return: + """ + global cliaccess + _checkCliAccess() + return cliaccess.mem_write(address, size, value) + + +def load_data(filename, address): + """ + Loads the given file data to the desired memory address + + :param filename: name of file from which data has to be copied + :param address: address on which data has to be copied + :return: + """ + global cliaccess + _checkCliAccess() + return cliaccess.load_data(filename, address) + + +def readIO(address, size): + """ + Read data from IO ports + + :param address: address of port from which data to be read + :param size: size of data to be read + :return: integer value read from address + """ + global cliaccess + _checkCliAccess() + return int(cliaccess.read_io(address, size)) + + +def writeIO(address, size, value): + """ + Write requested value of data to specified IO port + + :param address: address of IO port where data to be written + :param size: amount of data to be written + :param value: value of data to write on specified address port + :return: + """ + global cliaccess + _checkCliAccess() + return cliaccess.write_io(address, size, value) + + +def triggerSMI(SmiVal): + """ + Triggers the software SMI of desired value. Triggering SMI involves writing + desired value to port 0x72. + Internally writing to port achieved by write io api + + :param SmiVal: Value with which SMI should be triggered + :return: + """ + global cliaccess + _checkCliAccess() + return cliaccess.trigger_smi(SmiVal) + + +def ReadMSR(Ap, MSR_Addr): + global cliaccess + _checkCliAccess() + return int(cliaccess.read_msr(Ap, MSR_Addr)) + + +def WriteMSR(Ap, MSR_Addr, MSR_Val): + global cliaccess + _checkCliAccess() + return cliaccess.write_msr(Ap, MSR_Addr, MSR_Val) + + +def ReadSmbase(): + """ + Reads the SMBASE address value. Objective is achieved by reading value of + MSR 0x171 + + :return: + """ + global cliaccess + _checkCliAccess() + return int(cliaccess.read_sm_base()) + + +def RemoveFile(file_name): + """ + Remove/delete file after checking if it really exists + + :param file_name: name of file to be removed + :return: + """ + if os.path.isfile(file_name): + os.remove(file_name) + + +def RenameFile(file_name, new_file_name): + """ + File to be renamed + If new file name exists then it will be removed + + :param file_name: original file name + :param new_file_name: new file name + :return: + """ + if os.path.isfile(new_file_name): + os.remove(new_file_name) + os.rename(file_name, new_file_name) + + +def readcmos(register_address): + """ + Read CMOS register value + + :param register_address: CMOS register address + :return: + """ + upper_register_val = 0x0 if register_address < 0x80 else 0x2 + writeIO(0x70 + upper_register_val, 1, register_address) + value = readIO(0x71 + upper_register_val, 1) + return value + + +def writecmos(register_address, value): + """ + Write value to CMOS address register + + :param register_address: address of CMOS register + :param value: value to be written on specified CMOS register + :return: + """ + if register_address < 0x80: + writeIO(0x70, 1, register_address) + writeIO(0x71, 1, value) + + if register_address >= 0x80: + writeIO(0x72, 1, register_address) + writeIO(0x73, 1, value) + + +def clearcmos(): + """ + Clear all CMOS locations to 0 and set CMOS BAD flag. + + Writing 0 to CMOS data port and writing register value to CMOS address port, + CMOS clearing is achived + + CMOS are accessed through IO ports 0x70 and 0x71. Each CMOS values are + accessed a byte at a time and each byte is individually accessible. + + :return: + """ + log.warning('Clearing CMOS') + for i in range(0x0, 0x80, 1): + writeIO(0x70, 1, i) + writeIO(0x71, 1, 0) + value = i | 0x80 + if value in (0xF0, 0xF1): + # skip clearing the CMOS register's which hold Dram Shared MB address. + continue + writeIO(0x72, 1, value) + writeIO(0x73, 1, 0) + writeIO(0x70, 1, 0x0E) + writeIO(0x71, 1, 0xC0) # set CMOS BAD flag + + rtc_reg_pci_address = ((1 << 31) + (0 << 16) + (31 << 11) + (0 << 8) + 0xA4) + writeIO(0xCF8, 4, rtc_reg_pci_address) + rtc_value = readIO(0xCFC, 2) + rtc_value = rtc_value | 0x4 + writeIO(0xCF8, 4, rtc_reg_pci_address) + writeIO(0xCFC, 2, rtc_value) # set cmos bad in PCH RTC register + +# read all Cmos locations from 0 to 0xFF +def readallcmos(): + Value = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + log.result('Reading CMOS') + log.result(' |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|') + log.result('Addr|00|01|02|03|04|05|06|07|08|09|0A|0B|0C|0D|0E|0F|') + log.result('----|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|') + for i in range(0x0,0x8,1): + for j in range(0x0,0x10,1): + writeIO(0x70, 1, ((i<<4) + j) ) + Value[j] = readIO(0x71, 1) + log.result( + f' {(i << 4):2X} |{Value[0]:2X} {Value[1]:2X} {Value[2]:2X} {Value[3]:2X} {Value[4]:2X} {Value[5]:2X} {Value[6]:2X} {Value[7]:2X} {Value[8]:2X} {Value[9]:2X} {Value[10]:2X} {Value[11]:2X} {Value[12]:2X} {Value[13]:2X} {Value[14]:2X} {Value[15]:2X}|') + log.result(' ---|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|') + for i in range(0x8,0x10,1): + for j in range(0x0,0x10,1): + writeIO(0x72, 1, ((i<<4) + j) ) + Value[j] = readIO(0x73, 1) + log.result( + f' {(i << 4):2X} |{Value[0]:2X} {Value[1]:2X} {Value[2]:2X} {Value[3]:2X} {Value[4]:2X} {Value[5]:2X} {Value[6]:2X} {Value[7]:2X} {Value[8]:2X} {Value[9]:2X} {Value[10]:2X} {Value[11]:2X} {Value[12]:2X} {Value[13]:2X} {Value[14]:2X} {Value[15]:2X}|') + log.result(' ---|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|') + + +def ReadBuffer(inBuffer, offset, size, inType): + """ + This function reads the desired format of data of specified size + from the given offset of buffer. + + > Input buffer is in big endian ASCII format + + :param inBuffer: buffer from which data to be read + :param offset: start offset from which data to be read + :param size: size to be read from buffer + :param inType: format in which data can be read (ascii or hex) + + :return: buffer read from input + """ + value_buffer = inBuffer[offset:offset+size] + value_string = '' + if len(value_buffer) == 0: + return 0 + if inType == ASCII: + value_string = "".join(chr(value_buffer[i]) for i in range(len(value_buffer))) + return value_string + if inType == HEX: + # value_string = "".join(f"{value_buffer[i]:02x}" for i in range(len(value_buffer))) + for count in range(len(value_buffer)): + value_string = f"{value_buffer[count]:02x}" + value_string + return int(value_string, 16) + return 0 + +def ReadList(inBuffer, offset, size, inType=HEX): + value_buffer = inBuffer[offset:offset+size] + if inType == ASCII: + for count in range(len(value_buffer)): + if value_buffer[count] == 0: + return ''.join(value_buffer[0:count]) + value_buffer[count] = chr(value_buffer[count]) + return ''.join(value_buffer) + for count in range(len(value_buffer)): + value_buffer[count]=hex(value_buffer[count])[2:].zfill(2) + return int(''.join(value_buffer[::-1]), 16) + + +def ListInsertVal(Val): + return Val & 0xFF + +def HexLiFy(String): + return String.encode().hex() + +def UnHexLiFy(Integer): + return binascii.unhexlify((hex(Integer)[2:]).strip('L')).decode() + +def ReadBios(BiosBinListBuff, BinSize, Addr, Size): + if(BiosBinListBuff == 0): # Online mode + return memread(Addr, Size) + else: # Offline mode + return ReadList(BiosBinListBuff, (BinSize-(0x100000000-Addr)), Size) + +def GetCliSpecVersion(DramMbAddr): + global CliSpecRelVersion, CliSpecMajorVersion, CliSpecMinorVersion, CLI_REQ_READY_SIG, CLI_RES_READY_SIG + CliSpecRelVersion = memread((DramMbAddr+CLI_SPEC_VERSION_RELEASE_OFF), 1) & 0xF + CliSpecMajorVersion = memread((DramMbAddr+CLI_SPEC_VERSION_MAJOR_OFF), 2) + CliSpecMinorVersion = memread((DramMbAddr+CLI_SPEC_VERSION_MINOR_OFF), 1) + CLI_REQ_READY_SIG = 0xC001C001 + CLI_RES_READY_SIG = 0xCAFECAFE + if(CliSpecRelVersion == 0): + if(CliSpecMajorVersion >= 7): + CLI_REQ_READY_SIG = 0xD055C001 + CLI_RES_READY_SIG = 0xD055CAFE + else: + LEGACYMB_XML_OFF = 0x50 + CLI_REQ_READY_SIG = 0xD055C001 + CLI_RES_READY_SIG = 0xD055CAFE + return f'{CliSpecRelVersion:d}.{CliSpecMajorVersion:d}.{CliSpecMinorVersion:d}' + +def FixLegXmlOffset(DramMbAddr): + global CliSpecRelVersion, CliSpecMajorVersion, CliSpecMinorVersion, LEGACYMB_XML_OFF + LEGACYMB_XML_OFF = 0x0C + if(CliSpecRelVersion == 0): + if(CliSpecMajorVersion >= 7): + LEGACYMB_XML_OFF = 0x50 + if((CliSpecMajorVersion == 7) and (CliSpecMinorVersion == 0)): + LegMbOffset = memread((DramMbAddr+LEGACYMB_OFF), 4) + if(LegMbOffset < 0xFFFF): + LegMbOffset = DramMbAddr+LegMbOffset + if(memread((LegMbOffset+0x4C), 4) == 0): + LEGACYMB_XML_OFF = 0x50 + else: + LEGACYMB_XML_OFF = 0x4C + else: + LEGACYMB_XML_OFF = 0x50 + +def IsLegMbSigValid(DramMbAddr): + global CliSpecRelVersion, CliSpecMajorVersion, MerlinxXmlCliEnableAddr + SharedMbSig1 = memread((DramMbAddr+SHAREDMB_SIG1_OFF), 4) + SharedMbSig2 = memread((DramMbAddr+SHAREDMB_SIG2_OFF), 4) + if ( (SharedMbSig1 == SHAREDMB_SIG1) and (SharedMbSig2 == SHAREDMB_SIG2) ): + cli_spec_version = GetCliSpecVersion(DramMbAddr) + ShareMbEntry1Sig = memread((DramMbAddr+LEGACYMB_SIG_OFF), 4) + if (ShareMbEntry1Sig == LEGACYMB_SIG): + FixLegXmlOffset(DramMbAddr) + if( (CliSpecRelVersion >=0) and (CliSpecMajorVersion >=8) ): + LegMbOffset = int(memread(DramMbAddr+LEGACYMB_OFF, 4)) + if(LegMbOffset > 0xFFFF): + MerlinxXmlCliEnableAddr = LegMbOffset + MERLINX_XML_CLI_ENABLED_OFF + else: + MerlinxXmlCliEnableAddr = DramMbAddr + LegMbOffset + MERLINX_XML_CLI_ENABLED_OFF + return cli_spec_version + return False + + +def GetDramMbAddr(display_spec=True): + """ + Read DRAM shared Mailbox from CMOS location 0xBB [23:16] & 0xBC [31:24] + + :return: + """ + global gDramSharedMbAddr, InterfaceType, LastErrorSig + LastErrorSig = 0x0000 + InitInterface() + writeIO(0x72, 1, 0xF0) # Write a byte to cmos offset 0xF0 + result0 = int(readIO(0x73, 1) & 0xFF) # Read a byte from cmos offset 0xBB [23:16] + writeIO(0x72, 1, 0xF1) # Write a byte to cmos offset 0xF1 + result1 = int(readIO(0x73, 1) & 0xFF) # Read a byte from cmos offset 0xBC [31:24] + dram_shared_mb_address = int((result1 << 24) | (result0 << 16)) # Get bits [31:24] of the Dram MB address + if IsLegMbSigValid(dram_shared_mb_address): + CloseInterface() + return dram_shared_mb_address + + writeIO(0x70, 1, 0x78) # Write a byte to cmos offset 0x78 + result0 = int(readIO(0x71, 1) & 0xFF) # Read a byte from cmos offset 0xBB [23:16] + writeIO(0x70, 1, 0x79) # Write a byte to cmos offset 0x79 + result1 = int(readIO(0x71, 1) & 0xFF) # Read a byte from cmos offset 0xBC [31:24] + dram_shared_mb_address = int((result1 << 24) | (result0 << 16)) # Get bits [31:24] of the Dram MB address + if IsLegMbSigValid(dram_shared_mb_address): + CloseInterface() + return dram_shared_mb_address + + if gDramSharedMbAddr != 0: + dram_shared_mb_address = int(gDramSharedMbAddr) + if IsLegMbSigValid(dram_shared_mb_address): + CloseInterface() + return dram_shared_mb_address + CloseInterface() + LastErrorSig = 0xD9FD # Dram Shared MailBox Not Found + return 0 + + +def ConfXmlCli(SkipEnable=0): + global LastErrorSig + LastErrorSig = 0x0000 + InitInterface() + DRAM_MbAddr = GetDramMbAddr() # Get DRam MAilbox Address from Cmos. + log.result(f'CLI Spec Version = {GetCliSpecVersion(DRAM_MbAddr)}') + log.debug(f'DRAM_MbAddr = 0x{DRAM_MbAddr:X}') + Status = 0 + if DRAM_MbAddr == 0x0: + if SkipEnable == 0: + log.error('Dram Shared Mailbox not Valid, XmlCli May not be Enabled, Trying to Enable now..') + try: + from .tools.restricted import EnableXmlCli as exc + except (ModuleNotFoundError, ImportError) as e: + from .tools import EnableXmlCli as exc + except ImportError: + log.error(f'Import error on EnableXmlCli, current Python version {sys.version}') + CloseInterface() + LastErrorSig = 0x13E4 # import error + return 0xF + Status = exc.EnableXmlCli() + if Status == 0: + Status = 2 + LastErrorSig = 0xCE4E # XmlCli support was not Enabled, its now Enabled, Reboot Required + else: + log.error('XmlCli support is not Available in Your BIOS, Contact your BIOS Engineer..') + Status = 1 + LastErrorSig = 0xC19A # XmlCli Support not Available in BIOS + else: + log.error('XmlCli support is not Enable at the moment') + Status = 3 + LastErrorSig = 0xC19E # XmlCli Support not Enabled + else: + log.result('XmlCli support is Enabled..') + Status = 0 + CloseInterface() + return Status + + +def TriggerXmlCliEntry(): + global LastErrorSig + LastErrorSig = 0x0000 + status = 0 + try: + from .tools.restricted import EnableXmlCli as exc + except (ModuleNotFoundError, ImportError) as e: + from .tools import EnableXmlCli as exc + except ImportError: + log.error(f'Import error on EnableXmlCli, current Python version {sys.version}') + LastErrorSig = 0x13E4 # import error + return 1 + status = exc.XmlCliApiAuthenticate() + if status: + LastErrorSig = 0xE7CA # Error Triggering XmlCli command, Authentication Failed + return 1 + triggerSMI(0xF6) # trigger S/W SMI for CLI + return status + + +def WaitForCliResponse(CLI_ResBuffAddr, Delay=1, Retries=12, PrintRes=1): + """ + Whenever any command is requested to execute through Command Line Interface; + it needs to be checked if that command is responded or not. + It may take time to respond for a specific command. + For that a certain delay needs to be introduced. This function waits + for a certain delay and checks if given command is executed and + returned Response buffer is returned or not for a certain amount of time + else it returns Error. + + :param CLI_ResBuffAddr: Address of CLI response Buffer + :param Delay: The amount of delay which needs to be introduced + :param Retries: Number of Retries to be attempt + :param PrintRes: If this flag is set then function prints CLI response buffer contents. + :return: + """ + global CliRespFlags, LastErrorSig + CliRespFlags = 0 + LastErrorSig = 0x0000 + ret = 0 + CommandSideEffect = ['NoSideEffect', 'WarmResetRequired', 'PowerGoodResetRequired', 'Reserved'] + + XmlCliRespFlags['Status'] = 0 + XmlCliRespFlags['TimedOut'] = 0 + XmlCliRespFlags['CantExe'] = 0 + XmlCliRespFlags['WrongParam'] = 0 + XmlCliRespFlags['SideEffect'] = 'NoSideEffect' + + for retryCnt in range(0x0, Retries, 1): + if UfsFlag: + time.sleep(Delay) + haltcpu() + else: + haltcpu(delay=Delay) + ResHeaderbuff = memBlock(CLI_ResBuffAddr, CLI_REQ_RES_BUFF_HEADER_SIZE) + ResReadySig = ReadBuffer(ResHeaderbuff, CLI_REQ_RES_READY_SIG_OFF, 4, HEX) + if ResReadySig == CLI_RES_READY_SIG: # Verify if BIOS is done with the request + if PrintRes == 1: + ResCmdId = ReadBuffer(ResHeaderbuff, CLI_REQ_RES_READY_CMD_OFF, 2, HEX) + ResFlags = ReadBuffer(ResHeaderbuff, CLI_REQ_RES_READY_FLAGS_OFF, 2, HEX) + CliRespFlags = ResFlags + ResStatus = ReadBuffer(ResHeaderbuff, CLI_REQ_RES_READY_STATUS_OFF, 4, HEX) + ResParamSize = ReadBuffer(ResHeaderbuff, CLI_REQ_RES_READY_PARAMSZ_OFF, 4, HEX) + XmlCliRespFlags['Status'] = ResStatus + XmlCliRespFlags['CantExe'] = ((ResFlags >> 1) & 0x1) + XmlCliRespFlags['WrongParam'] = (ResFlags & 0x1) + XmlCliRespFlags['SideEffect'] = CommandSideEffect[int((ResFlags >> 2) & 0xF)] + log.info('CLI Response Header:') + log.info(f' CmdID = 0x{ResCmdId:X} (\"{CliCmdDict.get(ResCmdId, "??")}\") ') + log.info( + f' Status = 0x{ResStatus:X}; ParamSize = 0x{ResParamSize:X}; Flags.WrongParam = {XmlCliRespFlags["WrongParam"]:X};') + log.info( + f' Flags.CantExe = {XmlCliRespFlags["CantExe"]:X}; Flags.SideEffects = \"{XmlCliRespFlags["SideEffect"]}\"; ') + if ((ResFlags & 0x3) == 0) and (ResStatus == 0): + log.info('CLI command executed successfully..') + else: + log.error('CLI command executed, but with errors. See Logfile.') + if XmlCliRespFlags['Status'] != 0: + LastErrorSig = 0xC590 # XmlCli Return Status is Non-Zero + elif XmlCliRespFlags['CantExe'] != 0: + LastErrorSig = 0xCA8E # XmlCli Resp. returned Cant Execute + elif XmlCliRespFlags['WrongParam'] != 0: + LastErrorSig = 0xC391 # XmlCli Resp. returned Wring Parameter + ret = 1 + return ret + else: # CLI Response is not Ready yet + if MerlinxXmlCliEnableAddr != 0: + if int(memread(MerlinxXmlCliEnableAddr, 1)) & 0x2 == 0: # if BIT1 is cleared, this means XmlCli Interface was disabled + log.error('XmlCli Interface is Disabled, exiting..') + XmlCliRespFlags['TimedOut'] = 1 + LastErrorSig = 0xC1D1 # XmlCli Interface is Disabled + return 1 + log.info('CLI Response not yet ready, retrying..') + runcpu() + log.error('CLI Response not ready even after retries, exiting..') + XmlCliRespFlags['TimedOut'] = 1 + LastErrorSig = 0xC2E0 # XmlCli Resp. Timed-Out even after retries + return 1 + + +def readxmldetails(dram_shared_mailbox_buffer): + """ + Get XML Base Address & XML size details from the Shared Mailbox temp buffer + + We will retrieve shared mailbox signature 1 and signature 2 through offsets + `SHAREDMB_SIG1_OFF` and `SHAREDMB_SIG2_OFF`. If retrieved data matches with + signatures then we will check for Shared Mailbox entry signature. + If it matches we will collect XML base address and XML size details + from `LEGACYMB_OFF` and `LEGACYMB_XML_OFF`. + + :param dram_shared_mailbox_buffer: Shared Mailbox temporary buffer address + :return: + """ + SharedMbSig1 = ReadBuffer(dram_shared_mailbox_buffer, SHAREDMB_SIG1_OFF, 4, HEX) + SharedMbSig2 = ReadBuffer(dram_shared_mailbox_buffer, SHAREDMB_SIG2_OFF, 4, HEX) + GBT_XML_Addr = 0 + GBT_XML_Size = 0 + if (SharedMbSig1 == SHAREDMB_SIG1) and (SharedMbSig2 == SHAREDMB_SIG2): + ShareMbEntry1Sig = ReadBuffer(dram_shared_mailbox_buffer, LEGACYMB_SIG_OFF, 4, HEX) + if ShareMbEntry1Sig == LEGACYMB_SIG: + LegMbOffset = ReadBuffer(dram_shared_mailbox_buffer, LEGACYMB_OFF, 4, HEX) + if LegMbOffset > 0xFFFF: + GBT_XML_Addr = memread(LegMbOffset + LEGACYMB_XML_OFF, 4) + 4 + else: + GBT_XML_Addr = ReadBuffer(dram_shared_mailbox_buffer, LegMbOffset + LEGACYMB_XML_OFF, 4, HEX) + 4 + GBT_XML_Size = memread(GBT_XML_Addr - 4, 4) + return GBT_XML_Addr, GBT_XML_Size + + +def isxmlvalid(gbt_xml_address, gbt_xml_size): + """ + Check if Target XML is Valid or not + + :param gbt_xml_address: Address of GBT XML + :param gbt_xml_size: Size of GBT XML + :return: + """ + global LastErrorSig + LastErrorSig = 0x0000 + try: + temp_buffer = memBlock(gbt_xml_address, 0x08) # Read/save parameter buffer + SystemStart = ReadBuffer(temp_buffer, 0, 0x08, ASCII) + temp_buffer = memBlock(gbt_xml_address + gbt_xml_size - 0xB, 0x09) # Read/save parameter buffer + SystemEnd = ReadBuffer(temp_buffer, 0, 0x09, ASCII) + if (SystemStart == XML_START) and (SystemEnd == XML_END): + return True + else: + LastErrorSig = 0x8311 # Xml data is in-valid + return False + except Exception as e: + log.error(f'Exception detected when determining if xml is valid.\n {e}') + LastErrorSig = 0xEC09 # Exception detected + return False + + +def readclireqbufAddr(dram_shared_mailbox_buffer): + """ + Reads CLI Request Buffer Address from the Shared Mailbox temp buffer + + Request buffer address is present at offset of SHARED_MB_CLI_REQ_BUFF_ADDR_OFF. + First signature of buffer will be checked with valid signature + SHARED_MB_CLI_REQ_BUFF_SIG; and if it matches CLI request buffer address + will be collected in temporary buffer. + + + :param dram_shared_mailbox_buffer: pointer to dram shared mailbox buffer from + where CLI Request Buffer address can be retrieved + :return: + """ + cli_request_buffer_address = 0 + if ReadBuffer(dram_shared_mailbox_buffer, SHARED_MB_CLI_REQ_BUFF_SIG_OFF, 4, HEX) == SHARED_MB_CLI_REQ_BUFF_SIG: + cli_request_buffer_address = ReadBuffer(dram_shared_mailbox_buffer, SHARED_MB_CLI_REQ_BUFF_ADDR_OFF, 4, HEX) + return cli_request_buffer_address + + +def readclireqbufSize(dram_shared_mailbox_buffer): + """ + Reads CLI Request Buffer Address from the Shared Mailbox temp buffer + + :param dram_shared_mailbox_buffer: pointer to dram shared mailbox buffer from + where CLI Request Buffer to be read + :return: + """ + cli_request_buffer_size = 0 + if ReadBuffer(dram_shared_mailbox_buffer, SHARED_MB_CLI_REQ_BUFF_SIG_OFF, 4, HEX) == SHARED_MB_CLI_REQ_BUFF_SIG: + cli_request_buffer_size = ReadBuffer(dram_shared_mailbox_buffer, SHARED_MB_CLI_REQ_BUFF_SIZE_OFF, 4, HEX) + return cli_request_buffer_size + + +def readcliresbufAddr(dram_shared_mailbox_buffer): + """ + Reads CLI Response Buffer Address from the Shared Mailbox temp buffer + + Response buffer address is present at offset of `SHARED_MB_CLI_RES_BUFF_ADDR_OFF` (0x44). + + First signature check done which received from accessing `dram_shared_mailbox_buffer` with + `SHARED_MB_CLI_RES_BUFF_SIG`; and if it matches CLI response buffer address + will be collected in temporary buffer. + + :param dram_shared_mailbox_buffer: pointer to dram shared mailbox buffer + :return: + """ + cli_response_buffer_address = 0 + if ReadBuffer(dram_shared_mailbox_buffer, SHARED_MB_CLI_RES_BUFF_SIG_OFF, 4, HEX) == SHARED_MB_CLI_RES_BUFF_SIG: + cli_response_buffer_address = ReadBuffer(dram_shared_mailbox_buffer, SHARED_MB_CLI_RES_BUFF_ADDR_OFF, 4, HEX) + return cli_response_buffer_address + + +def readcliresbufSize(dram_shared_mailbox_buffer): + """ + Reads CLI Response Buffer Size from the Shared Mailbox temp buffer + + :param dram_shared_mailbox_buffer: pointer to dram shared mailbox buffer + :return: + """ + cli_response_buffer_size = 0 + if ReadBuffer(dram_shared_mailbox_buffer, SHARED_MB_CLI_RES_BUFF_SIG_OFF, 4, HEX) == SHARED_MB_CLI_RES_BUFF_SIG: + cli_response_buffer_size = ReadBuffer(dram_shared_mailbox_buffer, SHARED_MB_CLI_RES_BUFF_SIZE_OFF, 4, HEX) + return cli_response_buffer_size + + +def readLegMailboxAddrOffset(dram_shared_mailbox_buffer): + """ + Get Legacy DRAM Mailbox Address offset from the Shared Mailbox temporary buffer + + Legacy Mailbox address offset is present at offset of + `SHARED_MB_LEGMB_ADDR_OFF` (0x24). + + First signature check done which received from accessing + `dram_shared_mailbox_buffer` with LEGACYMB_SIG; and if it matches + CLI request buffer address will be collected in temporary buffer. + + :param dram_shared_mailbox_buffer: pointer to dram shared mailbox buffer + :return: + """ + legacy_mailbox_address_offset = 0 + if ReadBuffer(dram_shared_mailbox_buffer, SHARED_MB_LEGMB_SIG_OFF, 4, HEX) == LEGACYMB_SIG: + legacy_mailbox_address_offset = ReadBuffer(dram_shared_mailbox_buffer, SHARED_MB_LEGMB_ADDR_OFF, 4, HEX) + return legacy_mailbox_address_offset + + +def fetchHdrNknob(KnobFilename=None, PlatformXml=None): + """ + Check & store the given XML File (only the Header + Knobs section) + + :param KnobFilename: file name where requested xml details are to store + :param PlatformXml: + :return: + """ + if KnobFilename == None: + KnobFilename = KnobsXmlFile + if PlatformXml == None: + PlatformXml = PlatformConfigXml + if SaveXml(PlatformXml) == 1: # Check and Save the GBT XML knobs section. + log.error('Aborting due to Error!') + return 1 + file_content = "" + with open(PlatformXml, 'r') as file_ptr: + src = file_ptr.read() + src = src.split("\n") + biosKnobStarted = biosKnobEnded = searchbiosKnob = systemDone = platformDone = biosDone = gbtDone = False + for line in src : + if line.find('') >= 0: + file_content += line + systemDone = True + elif line.find('= 0: + file_content += line + platformDone = True + elif (line.find('= 0) or (line.find('= 0) or (line.find('= 0): + file_content += line + biosDone = True + elif line.find('= 0: + file_content += line + gbtDone = True + elif systemDone and platformDone and biosDone and gbtDone: # All the headers are written then start from Bios Knob + break + for line in src: + if line.find('') >= 0: + file_content += line + break + for line in src: + file_content += line + if line.find('') >= 0: + break + for line in src: + if line.find('') >= 0: + file_content += line + break + with open(KnobFilename, 'w') as newFile: + newFile.write(file_content) + + +def PatchXmlData(XmlListBuff, XmlAddr, XmlSize): + XmlPatchDataFound = 0 + NewXmlPatchDataFound = 0 + PacketAddr = ((XmlAddr+XmlSize+0xFFF) & 0xFFFFF000) + for count in range (0, 4): + PacketHdr = int(memread(PacketAddr, 8)) + PacketSize = ((PacketHdr >> 40) & 0xFFFFFF) + if ( ((PacketHdr & 0xFFFFFFFFFF) == 0x4c444B5824) and (PacketSize != 0) ): # cmp with $XKDL + XmlKnobsDeltaBuff = memBlock((PacketAddr+8), PacketSize) + XmlPatchDataFound = 1 + break + if ( ((PacketHdr & 0xFFFFFFFFFF) == 0x54444B5824) and (PacketSize != 0) ): # cmp with $XKDT + XmlKnobsDeltaBuff = memBlock((PacketAddr+8), PacketSize) + NewXmlPatchDataFound = 1 + break + PacketAddr = ((PacketAddr+8+PacketSize+0xFFF) & 0xFFFFF000) + if( (XmlPatchDataFound == 1) or (NewXmlPatchDataFound == 1) ): + offset = 0 + while(1): # read and print the return knobs entry parameters from CLI's response buffer + if (offset >= PacketSize): + break + KnobEntryOffset = ReadBuffer(XmlKnobsDeltaBuff, offset+0, 3, HEX) + Data16 = ReadBuffer(XmlKnobsDeltaBuff, offset+3, 2, HEX) + DataOfst = KnobEntryOffset+(Data16 & 0xFFF) + if(NewXmlPatchDataFound): + DataSize = ReadBuffer(XmlKnobsDeltaBuff, offset+5, 1, HEX) + ValueToReplace = ReadBuffer(XmlKnobsDeltaBuff, offset+6, DataSize, HEX) + else: + DataSize = (Data16 >> 12) & 0xF + ValueToReplace = ReadBuffer(XmlKnobsDeltaBuff, offset+5, DataSize, HEX) + StrValToReplace = hex(ValueToReplace)[2::].strip('L').zfill(DataSize*2).upper() + XmlListBuff[DataOfst:DataOfst+(DataSize*2)] = list(StrValToReplace.encode()) + if(NewXmlPatchDataFound): + offset = offset + 6 + DataSize + else: + offset = offset + 5 + DataSize + log.info(f'Patch buffer data size = {PacketSize:d} bytes') + +InValidXmlChar=['\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\x0B', '\x0C', '\x0E', '\x0F', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', '\x1E', '\x1F', '\x7F', '\x80', '\x81', '\x82', '\x83', '\x84', '\x86', '\x87', '\x88', '\x89', '\x8A', '\x8B', '\x8C', '\x8D', '\x8E', '\x8F', '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97', '\x98', '\x99', '\x9A', '\x9B', '\x9C', '\x9D', '\x9E', '\x9F', '\xAE'] +def SanitizeXml(filename): + try: + MyTree = ET.parse(filename) + log.info('SanitizeXml(): No XML syntax errors found with source XML file.') + except: + with open(filename, 'rb') as TempXML: + XmlListBuff = list(TempXML.read()) + Modified = False + for Index in range(len(XmlListBuff)): + CurrVal = XmlListBuff[Index] + CurrValChr = chr(CurrVal) + if (CurrVal == ListInsertVal(0xB5)): + XmlListBuff[Index] = ListInsertVal(0x75) # 'u' + Modified = True + if (CurrVal == ListInsertVal(0x26)): + XmlListBuff[Index] = ListInsertVal(0x6E) # 'n' + Modified = True + elif (CurrVal == ListInsertVal(0xA0)): + XmlListBuff[Index] = ListInsertVal(0x2E) #'.' + Modified = True + elif (CurrValChr in InValidXmlChar): + XmlListBuff[Index] = ListInsertVal(0x20) # ' ' + Modified = True + if(Modified): + log.info('SanitizeXml(): Fixing XML syntax errors found with source XML file.') + RenameFile (filename, filename+".raw") + with open(filename, 'wb') as NewXmlFile: # opening for writing + NewXmlFile.write(bytearray(XmlListBuff)) + +def IsXmlGenerated(): + global LastErrorSig + LastErrorSig = 0x0000 + Status = 0 + InitInterface() + DRAM_MbAddr = GetDramMbAddr() # Get DRam Mailbox Address from Cmos. + log.result(f'CLI Spec Version = {GetCliSpecVersion(DRAM_MbAddr)}') + log.debug(f'DRAM_MbAddr = 0x{DRAM_MbAddr:X}') + if (DRAM_MbAddr == 0x0): + log.error('Dram Shared Mailbox not Valid, hence exiting') + CloseInterface() + return 1 + DramSharedMBbuf = memBlock(DRAM_MbAddr,0x200) # Read/save parameter buffer + (XmlAddr,XmlSize) = readxmldetails(DramSharedMBbuf) # read GBTG XML address and Size + if (XmlAddr == 0): + log.error('Platform Configuration XML not yet generated, hence exiting') + CloseInterface() + LastErrorSig = 0x8AD0 # Xml Address is Zero + return 1 + if(isxmlvalid(XmlAddr,XmlSize)): + log.result('Xml Is Generated and it is Valid') + else: + log.error(f'XML is not valid or not yet generated XmlAddr = 0x{XmlAddr:X}, XmlSize = 0x{XmlSize:X}') + Status = 1 + CloseInterface() + return Status + +EFI_IFR_ONE_OF_OP = 0x05 +EFI_IFR_CHECKBOX_OP = 0x06 +EFI_IFR_NUMERIC_OP = 0x07 +EFI_IFR_STRING_OP = 0x1C +BIOS_KNOBS_DATA_BIN_HDR_SIZE_OLD = 0x10 +INVALID_KNOB_SIZE = 0xFF +BIOS_KNOBS_DATA_BIN_HDR_SIZE = 0x40 +BIOS_KNOBS_DATA_BIN_HDR_SIZE_V03 = 0x50 +BIOS_KNOB_BIN_REVISION_OFFSET = 0x0F +NVAR_NAME_OFFSET = 0x0E +NVAR_SIZE_OFFSET = 0x10 +BIOS_KNOB_BIN_GUID_OFFSET = 0x12 + +ZeroGuid = [ 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] +SetupTypeHiiDict = { EFI_IFR_ONE_OF_OP:'oneof', EFI_IFR_NUMERIC_OP:'numeric', EFI_IFR_CHECKBOX_OP:'checkbox', EFI_IFR_STRING_OP:'string', 0xF:'ReadOnly' } +SetupTypeBinDict = { 0x5:'oneof', 0x7:'numeric', 0x6:'checkbox', 0x8:'string', 0xF:'ReadOnly'} +SetupTypeBin2ValDict = { 0x5:EFI_IFR_ONE_OF_OP, 0x7:EFI_IFR_NUMERIC_OP, 0x6:EFI_IFR_CHECKBOX_OP, 0x8:EFI_IFR_STRING_OP } +OldBinNvarNameDict = { 0: 'Setup', 1: 'ServerMgmt'} +OldBinNvarNameDictPly = { 0 :'Setup', 1 :'SocketIioConfig', 2 :'SocketCommonRcConfig', 3 :'SocketMpLinkConfig', 4 :'SocketMemoryConfig', 5 :'SocketMiscConfig', 6 :'SocketPowerManagementConfig', 7 :'SocketProcessorCoreConfig', 8 :'SvOtherConfiguration', 9 :'SvPchConfiguration' } + +def GuidStr(GuidList): + GuidString = '{ 0x%08X, 0x%04X, 0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X }}' %(GuidList[0], GuidList[1], GuidList[2], GuidList[3], GuidList[4], GuidList[5], GuidList[6], GuidList[7], GuidList[8], GuidList[9], GuidList[10]) + return GuidString + +def FetchGuid(BufferList, Offset): + GuidList = [] + if (len(BufferList) > (Offset + 0x10)): + GuidList.append(ReadList(BufferList, (Offset+0x0), 4)) + GuidList.append(ReadList(BufferList, (Offset+0x4), 2)) + GuidList.append(ReadList(BufferList, (Offset+0x6), 2)) + GuidList.append(ReadList(BufferList, (Offset+0x8), 1)) + GuidList.append(ReadList(BufferList, (Offset+0x9), 1)) + GuidList.append(ReadList(BufferList, (Offset+0xA), 1)) + GuidList.append(ReadList(BufferList, (Offset+0xB), 1)) + GuidList.append(ReadList(BufferList, (Offset+0xC), 1)) + GuidList.append(ReadList(BufferList, (Offset+0xD), 1)) + GuidList.append(ReadList(BufferList, (Offset+0xE), 1)) + GuidList.append(ReadList(BufferList, (Offset+0xF), 1)) + else: + GuidList = ZeroGuid + return GuidList + +def KnobsDataToXmlFile(OutFile, BiosKnobDict={}): + NoOfVars = len(BiosKnobDict) + if(NoOfVars != 0): + result = '\t\n' + result += '\t\n' + for VarId in BiosKnobDict: + if (BiosKnobDict[VarId]['Status'] != 0): + continue + result += f'\t\t\n' + result += '\t\n\t\n' + for VarId in BiosKnobDict: + if (BiosKnobDict[VarId]['Status'] != 0): + continue + for KnobOfst in BiosKnobDict[VarId]['KnobDict']: + KnobSize = BiosKnobDict[VarId]['KnobDict'][KnobOfst]['KnobSzBin'] + KnobWidth = KnobSize + if(KnobOfst >= BITWISE_KNOB_PREFIX): + KnobOffsetStr = '0x%05X' % KnobOfst + KnobWidth = int((KnobOfst & 0x3FFFF) % 8) + KnobSize + if KnobWidth % 8: + KnobWidth = int(KnobWidth/8) + 1 + else: + KnobWidth = int(KnobWidth/8) + else: + KnobOffsetStr = '0x%04X' %KnobOfst + if('DefVal' in BiosKnobDict[VarId]['KnobDict'][KnobOfst]): + DefVal = BiosKnobDict[VarId]['KnobDict'][KnobOfst]['DefVal'] + CurVal = BiosKnobDict[VarId]['KnobDict'][KnobOfst]['CurVal'] + else: + DefVal = 0 + CurVal = 0 + result += '\t\t\n' %(SetupTypeHiiDict.get(BiosKnobDict[VarId]['KnobDict'][KnobOfst]['SetupTypeBin'], '??'), BiosKnobDict[VarId]['KnobDict'][KnobOfst]['KnobName'], VarId, KnobSize, KnobOffsetStr, BiosKnobDict[VarId]['KnobDict'][KnobOfst]['Depex'].replace('&', '_BitAnd_'), (KnobWidth*2), DefVal, (KnobWidth*2), CurVal) + result += '\t\n' + OutFile.write(result) + +def BiosKnobsDataBinParser(BiosKnobBinFile, BiosIdString='', StartOfst=0x1C, parselite=False): + with open(BiosKnobBinFile, 'rb') as BiosKnobFile: + BiosKnobBinBuff = list(BiosKnobFile.read()) + BiosKnobDict = {} + TmpKnobDict = {} + TmpDupKnobDict = {} + if(StartOfst == 0x1C): + BiosKnobBinEndAddr = ReadList(BiosKnobBinBuff, 0x18, 3) + else: + BiosKnobBinEndAddr = len(BiosKnobBinBuff) + BiosKnobBinPtr = StartOfst + OldBinFileFormat = False + KnobBinRevision = 0 + DataBinHdrSize = BIOS_KNOBS_DATA_BIN_HDR_SIZE_OLD + while(BiosKnobBinPtr < BiosKnobBinEndAddr): + BinHdrSig = ReadList(BiosKnobBinBuff, BiosKnobBinPtr, 5, ASCII) + VarId = ReadList(BiosKnobBinBuff, BiosKnobBinPtr+5, 1) + KnobCount = ReadList(BiosKnobBinBuff, BiosKnobBinPtr+6, 2) + if( ( (BinHdrSig == '$NVAR') or ((parselite == True) and (BinHdrSig == '$NVRO')) )and (KnobCount != 0) ): + DupKnobBufOff = ReadList(BiosKnobBinBuff, BiosKnobBinPtr+8, 3) + NvarPktSize = ReadList(BiosKnobBinBuff, BiosKnobBinPtr+0xB, 3) + NvarSize = ReadList(BiosKnobBinBuff, BiosKnobBinPtr+0xE, 2) + NvarGuid = ZeroGuid + if (NvarSize == 0): + OldBinFileFormat = True + DataBinHdrSize = BIOS_KNOBS_DATA_BIN_HDR_SIZE_OLD + if (BiosIdString[0:3] == 'PLY'): + NvarName = OldBinNvarNameDictPly[VarId] # this is an assumption if we still have old Bin format, so that we are backward compatible + else: + NvarName = OldBinNvarNameDict[VarId] # this is an assumption if we still have old Bin format, so that we are backward compatible + tmpBiosKnobBinPtr = BiosKnobBinPtr + DataBinHdrSize + else: # New Format + OldBinFileFormat = False + KnobBinRevision = ReadList(BiosKnobBinBuff, (BiosKnobBinPtr+BIOS_KNOB_BIN_REVISION_OFFSET), 1) + if(KnobBinRevision >= 2): # revision equal or higher than 0.2? + NvarGuid = FetchGuid(BiosKnobBinBuff, (BiosKnobBinPtr+BIOS_KNOB_BIN_GUID_OFFSET)) + NvarSize = ReadList(BiosKnobBinBuff, BiosKnobBinPtr+NVAR_SIZE_OFFSET, 2) + NvarNameOfst = ReadList(BiosKnobBinBuff, (BiosKnobBinPtr+NVAR_NAME_OFFSET), 1) + NvarName = '' + for VarSizeCount in range (0, 0x30): + Val = ReadList(BiosKnobBinBuff, (BiosKnobBinPtr+NvarNameOfst+VarSizeCount), 1) + if(Val == 0): + break + NvarName = NvarName + chr(Val) + if(KnobBinRevision >= 3): # revision equal or higher than 0.3? + DataBinHdrSize = BIOS_KNOBS_DATA_BIN_HDR_SIZE_V03 + else: + DataBinHdrSize = BIOS_KNOBS_DATA_BIN_HDR_SIZE + tmpBiosKnobBinPtr = BiosKnobBinPtr + DataBinHdrSize + TmpKnobDict = {} + if(parselite): + if( (BinHdrSig != '$NVRO') or (VarId not in BiosKnobDict) ): + KnobNameList = {} + BiosKnobDict[VarId]={'KnobDict':{}, 'KnobNameList':{}, 'NvarName':NvarName, 'NvarGuid':NvarGuid, 'NvarSize':NvarSize, 'NvarAttri':0, 'Status':0, 'KnobCount':KnobCount} + else: + KnobNameList = BiosKnobDict[VarId]['KnobNameList'] + TmpKnobDict = BiosKnobDict[VarId]['KnobDict'] + else: + BiosKnobDict[VarId]={'HiiVarId':0xFF, 'HiiVarSize':0, 'KnobDict':{}, 'DupKnobDict':{}, 'NvarName':NvarName, 'NvarGuid':NvarGuid, 'NvarSize':NvarSize, 'KnobCount':KnobCount} + while( tmpBiosKnobBinPtr < (BiosKnobBinPtr+DupKnobBufOff) ): + KnobOffset = ReadList(BiosKnobBinBuff, tmpBiosKnobBinPtr, 2) + if(OldBinFileFormat): + tmpBiosKnobBinPtr = tmpBiosKnobBinPtr + 2 + KnobSize_bin = INVALID_KNOB_SIZE + SetupTypeBin = INVALID_KNOB_SIZE + else: + KnobInfo = ReadList(BiosKnobBinBuff, tmpBiosKnobBinPtr+2, 1) + tmpBiosKnobBinPtr = tmpBiosKnobBinPtr + 3 + KnobType_bin = ((KnobInfo >> 4) & 0xF) + if(KnobType_bin >= 0x8): + KnobType_bin = 0x8 + KnobSize_bin = (KnobInfo & 0x7F) * 2 + else: + KnobSize_bin = (KnobInfo & 0x0F) + if( (KnobBinRevision >= 3) and (KnobType_bin < 0x4) ): + KnobType_bin = KnobType_bin + 0x4 # This indicates that current Knob entry is part of Depex, Adjust the Type accordingly. + if KnobSize_bin >= 0xC: # this indicates that the given Knob is Bitwise and is of Size mentioned in subsequent fields + BitData = ReadList(BiosKnobBinBuff, tmpBiosKnobBinPtr, 1) # Bitsize[7:3] BitOffset[2:0] + tmpBiosKnobBinPtr = tmpBiosKnobBinPtr + 1 + KnobSize_bin = ((KnobSize_bin & 0x1) << 5) + ((BitData >> 3) & 0x1F) + KnobOffset = BITWISE_KNOB_PREFIX + (KnobOffset*8) + (BitData & 0x7) # Knob Offset will now indicate 20 bit wide Value that represents Bit Offset. + SetupTypeBin = SetupTypeBin2ValDict.get(KnobType_bin, INVALID_KNOB_SIZE) + if(BinHdrSig == '$NVRO'): + SetupTypeBin = 0xF # indicates its "Readonly" Type + StrSize = 0 + while(ReadList(BiosKnobBinBuff, tmpBiosKnobBinPtr+StrSize, 1)): + StrSize = StrSize + 1 + if(StrSize): + KnobName = ReadList(BiosKnobBinBuff, tmpBiosKnobBinPtr, StrSize, ASCII) + else: + KnobName = '' + tmpBiosKnobBinPtr = tmpBiosKnobBinPtr + StrSize + 1 + StrSize = 0 + while(ReadList(BiosKnobBinBuff, tmpBiosKnobBinPtr+StrSize, 1)): + StrSize = StrSize + 1 + if(StrSize): + KnobDepex = ReadList(BiosKnobBinBuff, tmpBiosKnobBinPtr, StrSize, ASCII) + else: + KnobDepex = 'TRUE' + tmpBiosKnobBinPtr = tmpBiosKnobBinPtr + StrSize + 1 + if(parselite): + if(KnobOffset not in TmpKnobDict): + KnobNameList[KnobName] = KnobOffset + TmpKnobDict[KnobOffset] = { 'SetupTypeBin':SetupTypeBin, 'KnobName':KnobName, 'KnobSzBin':KnobSize_bin, 'Depex':KnobDepex, 'DefVal':0, 'CurVal':0 } + else: + TmpKnobDict[KnobOffset] = { 'SetupTypeHii':0, 'SetupTypeBin':SetupTypeBin, 'KnobName':KnobName, 'KnobSzHii':0, 'KnobSzBin':KnobSize_bin, 'HiiDefVal':0, 'Depex':KnobDepex, 'Prompt':0, 'Help':0, 'ParentPromptList': [], 'Min':0, 'Max':0, 'Step':0, 'KnobPrsd':[0, 0, 0xFF], 'OneOfOptionsDict':{} } + BiosKnobDict[VarId]['KnobDict'] = TmpKnobDict + if(parselite): + BiosKnobDict[VarId]['KnobNameList'] = KnobNameList + + tmpBiosKnobBinPtr = (BiosKnobBinPtr+DupKnobBufOff) # Parse Duplicate list + TmpDupKnobDict = {} + DupCount = 0 + while( tmpBiosKnobBinPtr < (BiosKnobBinPtr+NvarPktSize) ): + StrSize = 0 + while(ReadList(BiosKnobBinBuff, tmpBiosKnobBinPtr+StrSize, 1)): + StrSize = StrSize + 1 + if(StrSize): + DupKnobName = ReadList(BiosKnobBinBuff, tmpBiosKnobBinPtr, StrSize, ASCII) + else: + DupKnobName = '' + tmpBiosKnobBinPtr = tmpBiosKnobBinPtr + StrSize + 1 + StrSize = 0 + while(ReadList(BiosKnobBinBuff, (tmpBiosKnobBinPtr+StrSize), 1)): + StrSize = StrSize + 1 + if(StrSize): + DupKnobDepex = ReadList(BiosKnobBinBuff, tmpBiosKnobBinPtr, StrSize, ASCII) + else: + DupKnobDepex = 'TRUE' + tmpBiosKnobBinPtr = tmpBiosKnobBinPtr + StrSize + 1 + TmpDupKnobDict[DupCount] = { 'DupKnobName':DupKnobName, 'DupDepex':DupKnobDepex } + DupCount = DupCount + 1 + BiosKnobDict[VarId]['DupKnobDict'] = TmpDupKnobDict + BiosKnobBinPtr = BiosKnobBinPtr + NvarPktSize + elif(BinHdrSig == '$NVRO'): + NvarPktSize = ReadList(BiosKnobBinBuff, BiosKnobBinPtr+0xB, 3) + BiosKnobBinPtr = BiosKnobBinPtr + NvarPktSize + else: + BiosKnobBinPtr = BiosKnobBinPtr + DataBinHdrSize + return BiosKnobDict + +def LittEndian(HexVal): + NewStr = '' + for count in range(0, len(HexVal), 2): + NewStr = HexVal[count:count+2]+NewStr + return NewStr + +def Str2Int(StrVal): + StrVal = StrVal.strip() + if(len(StrVal) > 2): + if (StrVal[0:2] == '0x'): + return int(StrVal, 16) + return int(StrVal) + +# save XmlLite generated from BiosKnobsData bin to desired file. +def SaveXmlLite(filename=PlatformConfigLiteXml, Operation='savexml', UserKnobsDict={}): + global LastErrorSig + LastErrorSig = 0x0000 + Binfilename = os.path.join(TempFolder, "BiosKnobsData.bin") + RemoveFile(Binfilename) + Status = 0 + InitInterface() + DRAM_MbAddr = GetDramMbAddr() # Get DRam MAilbox Address from Cmos. + if (DRAM_MbAddr == 0x0): + log.error('Dram Shared Mailbox not Valid, hence exiting') + CloseInterface() + return 1 + DramSharedMBbuf = memBlock(DRAM_MbAddr,0x200) # Read/save parameter buffer + (XmlAddr,XmlSize) = readxmldetails(DramSharedMBbuf) # read GBTG XML address and Size + if (XmlAddr == 0): + log.error('Platform Configuration XML not yet generated, hence exiting') + CloseInterface() + LastErrorSig = 0x8AD0 # Xml Address is Zero + return 1 + IndependentLite = False + if(isxmlvalid(XmlAddr,XmlSize)): + if(XmlSize > (0x1000-4)): + IndependentLite = True + else: + XmlSize = 0 + IndependentLite = True + ComprXmlFound = False + PacketAddr = ((XmlAddr+XmlSize+0xFFF) & 0xFFFFF000) + for count in range (0, 2): + PacketHdr = int(memread(PacketAddr, 8)) + PacketSize = ((PacketHdr >> 40) & 0xFFFFFF) + if ( ((PacketHdr & 0xFFFFFFFFFF) == 0x424B4E5424) and (PacketSize != 0) ): # cmp with $TNKB + if Operation == "savexml": + log.info('Found Tiano Compressed BiosKnobsData Bin, Downloading it') + TempInFile = os.path.join(TempFolder, "CmpBiosKnobsData.bin") + memsave(TempInFile, (PacketAddr+8), int(PacketSize)) + try: + utils.system_call(cmd_lis=[TianoCompressUtility, "-d", "-q", TempInFile, "-o", Binfilename]) + RemoveFile(TempInFile) + if os.path.getsize(Binfilename): + ComprXmlFound = True + if Operation == "savexml": + log.info('Tiano Compressed BiosKnobsData Bin Decompressed Successfully') + except: + log.error('Decompression Failed!...') + break + PacketAddr = ((PacketAddr+8+PacketSize+0xFFF) & 0xFFFFF000) + if (ComprXmlFound): + pass + else: + log.error('Compressed Data is not supported, aborting') + CloseInterface() + LastErrorSig = 0x8311 # Xml is invalid + return 1 + + MyKnobsDict = {} + MyKnobsDict = BiosKnobsDataBinParser(Binfilename, BiosIdString='', StartOfst=0, parselite=True) + + if(Operation !='savexml'): + if(len(UserKnobsDict) == 0): + Operation = 'savexml' + log.warning('Input Knob String is empty, just saving the XML for now') + else: + if(Operation =='prog'): + for NvarCount in MyKnobsDict: + MyKnobsDict[NvarCount]['Status'] = 0xFF # initialize initially as Invalid Status + UserNvarDict = {} + for KnobName in UserKnobsDict: + for NvarCount in MyKnobsDict: + if(KnobName in MyKnobsDict[NvarCount]['KnobNameList']): + KnobOfst = MyKnobsDict[NvarCount]['KnobNameList'][KnobName] + KnobType = SetupTypeHiiDict.get(MyKnobsDict[NvarCount]['KnobDict'][KnobOfst]['SetupTypeBin'], '??') + if(KnobType == 'Readonly' or KnobType == '??'): + break # invalid knob Type + ReqVal = Str2Int(UserKnobsDict[KnobName]) + KnobSize = MyKnobsDict[NvarCount]['KnobDict'][KnobOfst]['KnobSzBin'] + if(len(hex(ReqVal)[2:]) <= (KnobSize*2)): + if(NvarCount not in UserNvarDict): + UserNvarDict[NvarCount] = {} + UserNvarDict[NvarCount][KnobName]={'KnobOfst': KnobOfst, 'KnobSize':KnobSize, 'ReqVal': ReqVal} + break + + FinalNvarBuffStr = '' + VarCount = 0 + MyVarList = sorted(MyKnobsDict) + Opcode = 0 + if(Operation =='prog'): + MyVarList = sorted(UserNvarDict) + Opcode = 2 + + for NvarCount in MyVarList: + if (len(MyKnobsDict[NvarCount]['NvarName']) >= 48): + continue + ProgListBuff = '' + VarSize = 0 + if Operation =='prog' and UserNvarDict: + for Knob in UserNvarDict.get(NvarCount, []): + KnobOfst = UserNvarDict[NvarCount][Knob]['KnobOfst'] + KnobSize = UserNvarDict[NvarCount][Knob]['KnobSize'] + KnobWidth = KnobSize + if(KnobOfst >= BITWISE_KNOB_PREFIX): # bitwise knob? + KnobWidth, KnobOfst, BitOfst = get_bitwise_knob_details(KnobSize, KnobOfst) + KnobSize = ((KnobSize & 0x1F) << 3) + (BitOfst & 0x7) + ProgListBuff = ProgListBuff + LittEndian('%04X' %KnobOfst) + '%02X'%KnobSize + LittEndian('%0*X' %((KnobWidth*2), UserNvarDict[NvarCount][Knob]['ReqVal'])) + VarSize = int(len(ProgListBuff)/2) + NvarBuffHeaderStr = LittEndian('%04X' %MyKnobsDict[NvarCount]['NvarGuid'][1]) + LittEndian('%04X' %MyKnobsDict[NvarCount]['NvarGuid'][2]) + '%02X%02X%02X%02X%02X%02X%02X%02X' %(MyKnobsDict[NvarCount]['NvarGuid'][3], MyKnobsDict[NvarCount]['NvarGuid'][4], MyKnobsDict[NvarCount]['NvarGuid'][5], MyKnobsDict[NvarCount]['NvarGuid'][6], MyKnobsDict[NvarCount]['NvarGuid'][7], MyKnobsDict[NvarCount]['NvarGuid'][8], MyKnobsDict[NvarCount]['NvarGuid'][9], MyKnobsDict[NvarCount]['NvarGuid'][10]) + '00'.zfill(8) + FinalNvarBuffStr = FinalNvarBuffStr + LittEndian('%08X' %MyKnobsDict[NvarCount]['NvarGuid'][0]) + NvarBuffHeaderStr + LittEndian('%08X' %VarSize) + '00'.zfill(8) + '%02X'%Opcode + HexLiFy(MyKnobsDict[NvarCount]['NvarName']) + '00'.zfill(2) + ProgListBuff + VarCount = VarCount + 1 + FinalNvarBuffStr = FinalNvarBuffStr + '1D90FADE' + NvarBuffHeaderStr + '00'.zfill(18) + HexLiFy('Def'+MyKnobsDict[NvarCount]['NvarName']) + '00'.zfill(2) + VarCount = VarCount + 1 + if(FinalNvarBuffStr != ''): + binfile = os.path.join(TempFolder, 'NvarReqBuff.bin') + with open(binfile, 'wb') as file_ptr: + file_ptr.write(binascii.unhexlify(FinalNvarBuffStr)) + + DRAM_MbAddr = GetDramMbAddr() # Get DRam Mailbox Address. + dram_shared_mailbox_buffer = memBlock(DRAM_MbAddr,0x200) # Read/save parameter buffer + CLI_ReqBuffAddr = readclireqbufAddr(DramSharedMBbuf) # Get CLI Request Buffer Address + CLI_ResBuffAddr = readcliresbufAddr(DramSharedMBbuf) # Get CLI Response Buffer Address + if Operation != "savexml": + log.result(f'CLI Spec Version = {GetCliSpecVersion(DRAM_MbAddr)}') + log.info(f'CLI Request Buffer Addr = 0x{CLI_ReqBuffAddr:X} CLI Response Buffer Addr = 0x{CLI_ResBuffAddr:X}') + if ( (CLI_ReqBuffAddr == 0) or (CLI_ResBuffAddr == 0) ): + if Operation != "savexml": + log.error('CLI buffers are not valid or not supported, Aborting due to Error!') + CloseInterface() + LastErrorSig = 0xC140 # XmlCli Req or Resp Buffer Address is Zero + return 1 + + binfile = os.path.join(TempFolder, 'NvarReqBuff.bin') + ClearCliBuff(CLI_ReqBuffAddr, CLI_ResBuffAddr) + memwrite( CLI_ReqBuffAddr + CLI_REQ_RES_READY_PARAMSZ_OFF, 4, VarCount) + # log.info('Req Buffer Bin file used is %s' %binfile) + load_data(binfile, CLI_ReqBuffAddr+CLI_REQ_RES_READY_PARAMSZ_OFF+4) + memwrite( CLI_ReqBuffAddr + CLI_REQ_RES_READY_CMD_OFF, 4, GET_SET_VARIABLE_OPCODE) + memwrite( CLI_ReqBuffAddr + CLI_REQ_RES_READY_SIG_OFF, 4, CLI_REQ_READY_SIG ) + if Operation != "savexml": + log.info('CLI Mailbox programmed, issuing S/W SMI to program knobs...') + + Status = TriggerXmlCliEntry() # trigger S/W SMI for CLI Entry + if(Status): + log.error('Error while triggering CLI Entry Point, Aborting....') + CloseInterface() + return 1 + if (WaitForCliResponse(CLI_ResBuffAddr, 2, 3, PrintRes=bool(Operation!="savexml")) != 0): + log.error('CLI Response not ready, Aborting....') + CloseInterface() + return 1 + + CurParamSize = int(memread(CLI_ResBuffAddr + CLI_REQ_RES_READY_PARAMSZ_OFF, 4)) + if(CurParamSize != 0): + CurParambuff = memBlock((CLI_ResBuffAddr + CLI_REQ_RES_BUFF_HEADER_SIZE), CurParamSize) + ResBufFilename = os.path.join(TempFolder, 'NvarRespBuff.bin') + with open(ResBufFilename, 'wb') as out_file: # opening for writing + out_file.write(CurParambuff) + CurParamList = list(CurParambuff) + RespBuffPtr = 0 + for Varcount in range (0, 0x100): + if(RespBuffPtr >= CurParamSize): + break + CurNvarGuid = FetchGuid(CurParamList, RespBuffPtr) + CurNvarAttri = ReadList(CurParamList, RespBuffPtr+0x10, 4) + CurNvarSize = ReadList(CurParamList, RespBuffPtr+0x14, 4) + CurNvarStatus = ReadList(CurParamList, RespBuffPtr+0x18, 4) + if(CurNvarStatus != 0): + CurNvarSize = 0 + CurNvarName = '' + for VarSizeCount in range (0, 0x30): + Val = ReadList(CurParamList, (RespBuffPtr+0x1D+VarSizeCount), 1) + if(Val == 0): + RespBuffPtr = RespBuffPtr + 0x1D + VarSizeCount + 1 + break + CurNvarName = CurNvarName + chr(Val) + for VarId in MyKnobsDict: + if( (CurNvarGuid == MyKnobsDict[VarId]['NvarGuid']) and (CurNvarName == MyKnobsDict[VarId]['NvarName']) ): + MyKnobsDict[VarId]['NvarSize'] = CurNvarSize + MyKnobsDict[VarId]['NvarAttri'] = CurNvarAttri + MyKnobsDict[VarId]['Status'] = CurNvarStatus + if( (CurNvarStatus == 0) and (CurNvarName != '') ): + for KnobOfst in MyKnobsDict[VarId]['KnobDict']: + KnobSize = MyKnobsDict[VarId]['KnobDict'][KnobOfst]['KnobSzBin'] + if KnobOfst >= BITWISE_KNOB_PREFIX: # bitwise knob? + KnobWidth, CurOffset, BitOfst = get_bitwise_knob_details(KnobSize, KnobOfst, padding=0) + MyKnobsDict[VarId]['KnobDict'][KnobOfst]['CurVal'] = (ReadList(CurParamList, (RespBuffPtr+CurOffset), KnobWidth) >> BitOfst) & (and_mask(KnobWidth) >> ((KnobWidth*8) - KnobSize)) + else: + MyKnobsDict[VarId]['KnobDict'][KnobOfst]['CurVal'] = ReadList(CurParamList, (RespBuffPtr+KnobOfst), KnobSize) + MyKnobsDict[VarId]['KnobDict'][KnobOfst]['DefVal'] = MyKnobsDict[VarId]['KnobDict'][KnobOfst]['CurVal'] + break + if( (CurNvarStatus == 0) and (CurNvarName[0:3] == 'Def') ): + for VarId in MyKnobsDict: + DefGuid = copy.deepcopy(MyKnobsDict[VarId]['NvarGuid']) + DefGuid[0] = 0xDEFA901D + if( (CurNvarGuid == DefGuid) and (CurNvarName == ('Def'+MyKnobsDict[VarId]['NvarName'])) and (MyKnobsDict[VarId]['Status'] == 0) ): + for KnobOfst in MyKnobsDict[VarId]['KnobDict']: + KnobSize = MyKnobsDict[VarId]['KnobDict'][KnobOfst]['KnobSzBin'] + if KnobOfst >= BITWISE_KNOB_PREFIX: # bitwise knob? + KnobWidth, CurOffset, BitOfst = get_bitwise_knob_details(KnobSize, KnobOfst, padding=0) + MyKnobsDict[VarId]['KnobDict'][KnobOfst]['DefVal'] = (ReadList(CurParamList, (RespBuffPtr+CurOffset), KnobWidth) >> BitOfst) & (and_mask(KnobWidth) >> ((KnobWidth*8) - KnobSize)) + else: + MyKnobsDict[VarId]['KnobDict'][KnobOfst]['DefVal'] = ReadList(CurParamList, (RespBuffPtr+KnobOfst), KnobSize) + break + RespBuffPtr = RespBuffPtr + CurNvarSize + + if not IndependentLite: + memsave(filename, XmlAddr, (XmlSize-0xB)) + mode = 'w' if IndependentLite else 'a' + with open(filename, mode) as OutFile: + if IndependentLite: + OutFile.write('\n') + KnobsDataToXmlFile(OutFile, BiosKnobDict=MyKnobsDict) + OutFile.write('\n') + + if Operation == 'savexml': + log.info(f'Saved XML Lite Data as {filename}') + CloseInterface() + return Status + + +def SaveXml(filename=None, ITPOptimz=0, MbAddr=0, XmlAddr=0, XmlSize=0): + """ + Save entire/complete Target XML to desired file. + + :param filename: + :param ITPOptimz: + :param MbAddr: + :param XmlAddr: + :param XmlSize: + :return: + """ + global LastErrorSig, LEGACYMB_XML_OFF + LastErrorSig = 0x0000 + if filename == None: + filename = PlatformConfigXml + Status = 0 + InitInterface() + DRAM_MbAddr = 0 + if MbAddr == 0: + DRAM_MbAddr = GetDramMbAddr() # Get DRam MAilbox Address from Cmos. + else: + DRAM_MbAddr = MbAddr + log.result(f'CLI Spec Version = {GetCliSpecVersion(DRAM_MbAddr)}') + log.debug(f'DRAM_MbAddr = 0x{DRAM_MbAddr:X}') + if (DRAM_MbAddr == 0x0): + log.error('Dram Shared Mailbox not Valid, hence exiting') + CloseInterface() + return 1 + DramSharedMBbuf = memBlock(DRAM_MbAddr,0x200) # Read/save parameter buffer + if (filename == SvXml) : + TempXmlOfst = LEGACYMB_XML_OFF + LEGACYMB_XML_OFF = 0xC # Point to SV PC XML offset (On-Demand) + if XmlAddr == 0: + (XmlAddr,XmlSize) = readxmldetails(DramSharedMBbuf) # read GBTG XML address and Size + if (XmlAddr == 0): + log.error('Platform Configuration XML not yet generated, hence exiting') + CloseInterface() + LastErrorSig = 0x8AD0 # Xml Address is Zero + if (filename == SvXml) : + LEGACYMB_XML_OFF = TempXmlOfst # Restore orignal offset value before returning + return 1 + if(isxmlvalid(XmlAddr,XmlSize)): + ComprXmlFound = False + if(_isExeAvailable): + PacketAddr = ((XmlAddr+XmlSize+0xFFF) & 0xFFFFF000) + for count in range (0, 2): + PacketHdr = int(memread(PacketAddr, 8)) + PacketSize = ((PacketHdr >> 40) & 0xFFFFFF) + if ( ((PacketHdr & 0xFFFFFFFFFF) == 0x414d5a4c24) and (PacketSize != 0) ): # cmp with $LZMA + log.result('Found LZMA Compressed XML, Downloading it') + TempInFile = os.path.join(TempFolder, "GbtLzC.bin") + TempOutFile = os.path.join(TempFolder, "GbtPc.xml") + memsave(TempInFile, (PacketAddr+8), int(PacketSize)) + try: + compress.lzma_decompress(TempInFile, TempOutFile) + RemoveFile(TempInFile) + if(os.path.getsize(os.path.join(TempFolder, "GbtPc.xml"))): + log.result('LZMA Compressed XML Decompressed Successfully') + ComprXmlFound = True + break + except: + log.result('Decompression Failed!, falling back to regular XML download.') + ComprXmlFound = False + if ( ((PacketHdr & 0xFFFFFFFFFF) == 0x434F4E5424) and (PacketSize != 0) ): # cmp with $TNOC + log.result('Found Tiano Compressed XML, Downloading it') + TempInFile = os.path.join(TempFolder, "GbtTianoC.bin") + TempOutFile = os.path.join(TempFolder, "GbtPc.xml") + memsave(TempInFile, (PacketAddr+8), int(PacketSize)) + try: + utils.system_call(cmd_lis=[TianoCompressUtility, "-d", "-q", TempInFile, "-o", TempOutFile]) + RemoveFile(TempInFile) + if(os.path.getsize(os.path.join(TempFolder, "GbtPc.xml"))): + log.result('Tiano Compressed XML Decompressed Successfully') + ComprXmlFound = True + break + except: + log.result('Decompression Failed!, falling back to regular XML download.') + ComprXmlFound = False + PacketAddr = ((PacketAddr+8+PacketSize+0xFFF) & 0xFFFFF000) + if (ComprXmlFound): + with open(os.path.join(TempFolder, "GbtPc.xml"), 'rb') as TempXML: + XmlListBuff = list(TempXML.read()) + PatchXmlData(XmlListBuff, XmlAddr,XmlSize) + RemoveFile(os.path.join(TempFolder, "GbtPc.xml")) + with open(filename, 'wb') as NewXmlFile: # opening for writing + NewXmlFile.write(bytearray(XmlListBuff)) + else: + log.result('Compressed XML is not supported, Downloading Regular XML') + if((InterfaceType != 'itpii') and (InterfaceType != 'simics') and (InterfaceType != 'ltb') and (InterfaceType != 'svlegitp')): + ITPOptimz = 0 + if ( (XmlCmp(filename, XmlAddr) == False) or (ITPOptimz == 0) ): + log.result('Host XML did not exist or is different from Target XML, downloading Target XML..') + memsave(filename, XmlAddr, int(XmlSize)) # saves complete xml + else: + log.result('Target XML is same as the one Pointed to, skipping XML download') + log.result(f'Saved XML Data as {filename}') + else: + log.error(f'XML is not valid or not yet generated XmlAddr = 0x{XmlAddr:X}, XmlSize = 0x{XmlSize:X}') + Status = 1 + SanitizeXml(filename) + CloseInterface() + if (filename == SvXml) : + LEGACYMB_XML_OFF = TempXmlOfst # Restore orignal offset value before returning + return Status + + +def XmlCmp(filename, XmlAddr): + """ + Create or Compare and Save Target XML Header to file. + + If given XML is not present in target memory it creates new XML + else if its present then function compares the same + and if it is different XML is overwritten. + + :param filename: given xml file + :param XmlAddr: address from which xml has to be downloaded + :return: + """ + HdrCmpLen = 0x140 + targetbuff = list(memBlock(XmlAddr, HdrCmpLen)) + if (os.path.isfile(filename)) and (os.path.getsize(filename) > 0x800): + log.info('File Exists: comparing target & host XML header') + with open(filename, 'rb') as HostXML: + hbuffer = list(HostXML.read(HdrCmpLen)) + if hbuffer[0:HdrCmpLen - 1] == targetbuff[0:HdrCmpLen - 1]: # compare host & target XML header + return True # indicates Target XML was unchanged + return False # indicates Target XML file was not yet created + +# Extract knob name from given KnobEntry pointer. +def findKnobName(KnobEntryAdd): + KnobEntryBuff = memBlock(KnobEntryAdd, 0x100) # copy first 256 chars in temp buffer + Type = Name = '' + for i in range(0x0,0x100,1): # assuming the name attribute will be found within first 256 chars + Knobname = ReadBuffer(KnobEntryBuff, i, 11, HEX) # read 11 chars from buffer + if (Knobname == 0x223D657079547075746573): # compare with setupType=' + for j in range(0x0,0x80,1): # assuming max knob name size of 128 chars + if (ReadBuffer(KnobEntryBuff, i+11+j, 1, HEX) == 0x22): # save till next ' + Type = ReadBuffer(KnobEntryBuff, i+11, j, ASCII) # return Knob name + break + for i in range(0x0,0x100,1): # assuming the name attribute will be found within first 256 chars + Knobname = ReadBuffer(KnobEntryBuff, i, 0x06, HEX) # read 6 chars from buffer + if (Knobname == 0x223D656D616E): # compare with name=' + for j in range(0x0,0x80,1): # assuming max knob name size of 128 chars + if (ReadBuffer(KnobEntryBuff, i+6+j, 1, HEX) == 0x22): # save till next ' + Name = ReadBuffer(KnobEntryBuff, i+6, j, ASCII) # return Knob name + break + return (Type,Name) + + +def getBiosDetails(): + """ + Extract BIOS Version details from XML. + + Bios details will give detailed description of BIOS populated on platform. + This description involves Platform Name, Bios Name, BIOS Time Stamp. + + Design Description: + Get DRAM Mailbox address from CMOS then Read and save parameters buffer. + After validating xml; first 512 bytes will be copied in temporary buffer + assuming BIOS attributes will be found within first 512 bytes. + + Then respective attributes will be copied in already allocated temporary buffers. + + :return: Tuple of (Platform name, Bios Name, Bios Timestamp) + """ + global LastErrorSig + LastErrorSig = 0x0000 + Platformname = '' + BiosName = '' + BiosTimestamp = '' + InitInterface() + DRAM_MbAddr = GetDramMbAddr() # Get DRam Mailbox Address from Cmos. + log.result(f'CLI Spec Version = {GetCliSpecVersion(DRAM_MbAddr)}') + log.debug(f'DRAM_MbAddr = 0x{DRAM_MbAddr:X}') + if DRAM_MbAddr == 0x0: + log.error('Dram Shared Mailbox not Valid, hence exiting') + CloseInterface() + return Platformname, BiosName, BiosTimestamp # empty strings + DramSharedMBbuf = memBlock(DRAM_MbAddr, 0x200) # Read/save parameter buffer + (XmlAddr, XmlSize) = readxmldetails(DramSharedMBbuf) + if XmlAddr == 0: + log.error('Platform Configuration XML not ready, hence exiting') + LastErrorSig = 0x8AD0 # Xml Address is Zero + runcpu() + CloseInterface() + return Platformname, BiosName, BiosTimestamp # empty Strings + if isxmlvalid(XmlAddr, XmlSize): + XmlEntryBuff = memBlock(XmlAddr, 0x200) # copy first 512 chars in temp buffer + for i in range(0x0, 0x200, 1): # assuming the name attribute will be found within first 512 chars + Platformnametmp = ReadBuffer(XmlEntryBuff, i, 15, ASCII) # read 16 chars from buffer + BiosDetailstmp = ReadBuffer(XmlEntryBuff, i, 10, ASCII) # read 16 chars from buffer + if (Platformnametmp == '>> get_bin_file(access_method="winhwa") # specifies access method and stores result + + Optional parameters can also be used to override default values as below + >>> get_bin_file(access_method="winhwa", max_bios_size=12 * (1024**2)) # overrides bios size to 12 MB and will store only 12 MB chunk ending at memory address + + Multiple optional arguments can also be used to override default parameters + >>> get_bin_file(access_method="winhwa", max_bios_size=12 * (1024**2), bin_file="path/to/store/bin_file.bin") # overrides default location of binary file to store and bios size + """ + max_bios_size = kwargs.get("max_bios_size", 32 * (1024 ** 2)) # default: 32 MB + memory_size = kwargs.get("memory_size", 4 * (1024 ** 3)) # default: 4 GB + bin_file = kwargs.get("output_bin_file", os.path.join(TempFolder, "online_bios.bin")) + if access_method not in utils.VALID_ACCESS_METHODS: + err_msg = "Invalid Access Method: {}".format(access_method) + log.error(err_msg) + raise Exception(err_msg) + else: + _setCliAccess(access_method) + status = InitInterface() + log.debug("Status of XmlCli (init interface..): {}".format(status)) + start = memory_size - max_bios_size # start address of chunk to parse bios region + log.debug("Start of BIOS at memory: 0x{:x}".format(start)) + memsave(bin_file, start, max_bios_size) + if os.path.exists(bin_file): + log.info("Memory dump from 0x{:x} of size 0x{:x} is stored at: {}".format(start, max_bios_size, bin_file)) + CloseInterface() + return bin_file + + +def SearchForSystemTableAddress(): + for Address in range (0x20000000, 0xE0000000, 0x400000): # EFI_SYSTEM_TABLE_POINTER address is 4MB aligned + Signature = memread(Address, 8) + if(Signature == 0x5453595320494249): # EFI System Table Signature = 'IBI SYST' + Address = memread((Address+8), 8) + return Address + return 0 + +def readDramMbAddrFromEFI(): + DramSharedMailBoxGuidLow = 0x4D2C18789D99A394 + DramSharedMailBoxGuidHigh = 0x3379C48E6BC1E998 + log.debug('Searching for Dram Shared Mailbox address from gST EfiConfigTable..') + gST = SearchForSystemTableAddress() + if(gST == 0): + EfiCompatibleTableBase = getEfiCompatibleTableBase() + if(EfiCompatibleTableBase == 0): + return 0 + gST = memread(EfiCompatibleTableBase+0x14, 4) + Signature = memread(gST, 8) + if(Signature != 0x5453595320494249): # EFI System Table Signature = 'IBI SYST' + return 0 + log.debug( + f'EFI SYSTEM TABLE Address = 0x{gST:X} Signature = \"{UnHexLiFy(Signature)[::-1]}\" Revision = {memread(gST + 8, 2):d}.{memread(gST + 0xA, 2):d}') + count = 0 + FirmwarePtr = memread(gST+0x18, 8) + FirmwareRevision = memread(gST+0x20, 4) + BiosStr = '' + while (1): + Value = int(memread(FirmwarePtr+count, 2)) + if (Value == 0): + break + BiosStr = BiosStr + chr((Value & 0xFF)) + count = count + 2 + log.debug(f'Firmware : {BiosStr}') + log.debug(f'Firmware Revision: 0x{FirmwareRevision:X}') + EfiConfigTblEntries = memread(gST+0x68, 8) + EfiConfigTbl = memread(gST+0x70, 8) + log.debug(f'EfiConfigTblEntries = {EfiConfigTblEntries:d} EfiConfigTbl Addr = 0x{EfiConfigTbl:X}') + Offset = 0 + DramMailboxAddr = 0 + for Index in range (0, EfiConfigTblEntries): + GuidLow = memread(EfiConfigTbl+Offset, 8) + GuidHigh = memread(EfiConfigTbl+8+Offset, 8) + if ( (GuidLow == DramSharedMailBoxGuidLow) and (GuidHigh == DramSharedMailBoxGuidHigh) ): + DramMailboxAddr = int(memread(EfiConfigTbl+16+Offset, 8)) + log.info(f'Found Dram Shared MailBox Address = 0x{DramMailboxAddr:X} from EfiConfigTable') + break + Offset = Offset + 0x18 + return DramMailboxAddr + +def PrintE820Table (): + """Legacy function for printing E820 table for memory type identification using + legacy efi compatible table + + EFI ST offset = 0x14 + ACPI table offset = 0x1C + E820 Table offset = 0x22 + E820 table Length = 0x26 + + :return: + """ + Offset = 0 + Index = 0 + E820TableList = {} + EfiCompatibleTableBase = getEfiCompatibleTableBase() + E820Ptr = memread(EfiCompatibleTableBase+0x22, 4) + Size = memread(EfiCompatibleTableBase+0x26, 4) + log.result( ',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,') + log.result( 'E820[no]: Start Block Address ---- End Block Address , Type = Mem Type') + log.result( '``````````````````````````````````````````````````````````````````````') + while (1): + BaseAddr = memread(E820Ptr+Offset, 8) + Length = memread(E820Ptr+Offset+8, 8) + Type = memread(E820Ptr+Offset+16, 4) + log.result(f'E820[{Index:2d}]: 0x{BaseAddr:16X} ---- 0x{(BaseAddr + Length):<16X}, Type = 0X{Type:x} ') + E820TableList[Index] = [BaseAddr, Length, Type] + Index = Index + 1 + Offset = Offset + 20 + if (Offset >= Size): + break + log.result(',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,') + return E820TableList diff --git a/src/xmlcli/XmlIniParser.py b/src/xmlcli/XmlIniParser.py new file mode 100644 index 0000000..4035478 --- /dev/null +++ b/src/xmlcli/XmlIniParser.py @@ -0,0 +1,1001 @@ +#!/usr/bin/env python +""" +To generate BiosKnobs.bin file from BiosKnobs.ini and biosKnobs.xml file +""" +__author__ = ['Amol Shinde', 'Gahan Saraiya'] + +# Built-in Imports +import os +import re +import binascii + + +# Custom Imports +from .common.logger import log +from . import XmlCliLib as clb + +try: + from defusedxml import ElementTree as ET +except ModuleNotFoundError as e: + log.warn("Insecure module import used! Please install all the required dependencies by running `pip install -r requirements.txt`") + from xml.etree import ElementTree as ET + +# Global variable +# ------------------- + +END_OF_BUFFER = 'F4FBD0E9' +XML_TREE = None +mydebug = 1 +SIG_FLAG = 0 +SETUP_FLAG = 0 +SETUP_MAP = {0: {0: 'biosknobs', 1: 'biosknobs'}, 1: {0: 'setupknobs', 1: 'biosknobs'}} +NVAR_MAP = {} +EXIT_ON_UNKNOWN_KNOB = False + +MATH_OPERATIONS = {'and', 'or', 'not', '==', '!=', '<=', '>=', '<', '>', '_LIST_'} +DEPEX_RESULT_MAP = {True : {'Sif': 'Active', 'Gif': 'Active', 'Dif': 'Active', '': 'Active'}, + False: {'Sif': 'Suppressed', 'Gif': 'GrayedOut', 'Dif': 'Disabled', '': 'Unknown'}} +EQUALITY_MAP = {'==': 'in', '!=': 'not in'} + + +# User defined Function +# ----------------------- + +def nstrip(input_string, default=''): + """ + Strip valid input string for spaces. + If not valid string then returned default null string + + :param input_string: valid input string + :param default: default empty string '' + :return: stripped result of input_string or default string + """ + return input_string.strip() if isinstance(input_string, str) else default + + +def populate_nvar_map(file_name='biosKnobs.xml'): + global NVAR_MAP + global XML_TREE + if XML_TREE is None: + XML_TREE = ET.parse(file_name) + re_nvar = re.compile('Nvar_(.*)_Size') + offset = 0x100 + nvar_idx = 0 + for setup_knobs in XML_TREE.iter(tag='biosknobs'): + for knob in setup_knobs: + setup_type = (nstrip(knob.get('setupType'))).upper() + if setup_type == 'STRING': + continue + name = (nstrip(knob.get('name'))) + default = int((nstrip(knob.get('default'))), 16) + x1 = re.search(re_nvar, name) + if setup_type in ['LEGACY']: + if x1 is not None: + nvar_idx = int(x1.group(1)) + NVAR_MAP[nvar_idx] = {'NvarSize': default, 'correction': offset} + offset = offset + NVAR_MAP[nvar_idx]['NvarSize'] + if offset > 0x100: + nvar_idx = nvar_idx + 1 + NVAR_MAP[nvar_idx] = {'NvarSize': 0x00, 'correction': offset} + log.info('Nvar value Corrected') + + +def get_setup_tag(file_name='biosKnobs.xml'): + global XML_TREE + global SETUP_MAP + global SETUP_FLAG + global SIG_FLAG + if XML_TREE is None: + XML_TREE = ET.parse(file_name) + SIG_FLAG = 0xF + SETUP_FLAG = 0xF + for setup_knobs in XML_TREE.iter(tag='biosknobs'): + SIG_FLAG = 0 + SETUP_FLAG = 0 + for knob in setup_knobs: + setup_type = (nstrip(knob.get('setupType'))).upper() + name = (nstrip(knob.get('name'))) + if name in ['Signature']: + SIG_FLAG = 1 + if setup_type in ['LEGACY']: + SETUP_FLAG = 1 + break + + if SIG_FLAG == 0xF and SETUP_FLAG == 0xF: + setup_tag = 'setupknobs' # this means tag was not found in the XML + else: + setup_tag = SETUP_MAP[SIG_FLAG][SETUP_FLAG] + + if SIG_FLAG == 1 and SETUP_FLAG == 1: + log.info('Found XML Knobs in Ganges format') + populate_nvar_map(file_name) # populate dictionary NVAR_MAP from xml + + return setup_tag + + +def get_bios_lookup(file_name='biosKnobs.xml', force_parse_xml=False, build_type=None): + global XML_TREE + if XML_TREE is None or force_parse_xml: + XML_TREE = ET.parse(file_name) + setup_tag = get_setup_tag(file_name) + bios_map = {} + for setup_knobs in XML_TREE.iter(tag=setup_tag): + if setup_knobs.get('BuildType') != build_type: + continue + for knob in setup_knobs: + setup_type = (nstrip(knob.get('setupType'))).upper() + if setup_type in ['CHECKBOX', 'NUMRIC', 'NUMERIC', 'ONEOF', 'STRING']: + bios_map[nstrip(knob.get('name'))] = { + 'size' : nstrip(knob.get('size')), 'offset': nstrip(knob.get('offset')), + 'vstore' : nstrip(knob.get('varstoreIndex', '0xFF')), + 'CurrentVal': nstrip(knob.get('CurrentVal'))} + elif setup_type not in ['LEGACY', 'READONLY']: + log.warning(f'Setup Type is unknown (Need to add this) biosName[{nstrip(knob.get("name"))}] setupType[{setup_type}].') + return bios_map + + +def get_cpu_sv_bios_lookup(file_name='biosKnobs.xml'): + global XML_TREE + if XML_TREE is None: + XML_TREE = ET.parse(file_name) + setup_tag = 'biosknobs' + bios_map = {} + offset_map = {} + for setup_knobs in XML_TREE.iter(tag=setup_tag): + for knob in setup_knobs: + knob_type = (nstrip(knob.get('type'))).upper() + if knob_type in ['SCALAR']: + if nstrip(knob.get('name')) not in bios_map: + bios_map[nstrip(knob.get('name'))] = nstrip(knob.get('offset')) + offset_map[nstrip(knob.get('offset'))] = { + 'name' : nstrip(knob.get('name')), 'size': nstrip(knob.get('size')), + 'offset': nstrip(knob.get('offset')), 'default': nstrip(knob.get('default'))} + else: + log.warning(f' Warning - Duplicate Knobs : {nstrip(knob.get("name"))} ') + log.info(f'Lookup Prepared !! len[{str(len(bios_map))}]') + return bios_map, offset_map + + +def get_bios_ini(ini_file_name): + with open(ini_file_name) as f: + bios_knobs_lis = f.readlines() + knob_map = {} + knob_start = 0 + i = 0 + knob_lis = [] + while i < len(bios_knobs_lis): + line = bios_knobs_lis[i] + if line.strip() == '[BiosKnobs]': + knob_start = 1 + i = i + 1 + continue + elif line.strip() == '[Softstraps]': + knob_start = 0 # to end BiosKnobs section -Added by Cscripts tool + if knob_start == 1: + line = line.split(';')[0] + if line.strip() != '': + knob_name, knob_value = line.split('=') + knob_map[knob_name.strip()] = knob_value.strip() + knob_lis.append(knob_name.strip()) + i = i + 1 + return knob_map, knob_lis + + +def offset_correction(knob_offset_hex, knob_vstore_hex): + knob_offset_hex_format = '0x' + knob_offset_hex + knob_vstore_hex_format = '0x' + knob_vstore_hex + global NVAR_MAP + offset_correction_value = int(knob_offset_hex_format, 16) - NVAR_MAP[int(knob_vstore_hex_format, 16)]['correction'] + offset_correction_format = hex(offset_correction_value)[2:].zfill(4) + return offset_correction_format + + +def create_bin_file(bin_file, bios_map, ini_map, knob_lis): + global SETUP_FLAG, SIG_FLAG, EXIT_ON_UNKNOWN_KNOB + buffer_lis = [] + has_unknown_knob = False + for knob in knob_lis: + if knob in bios_map: + knob_val_hex = '00' + knobSize_int = 0 + knob_offset_hex = '0000' + knob_var_store_hex = '00' + knob_size_hex = '00' + knob_val = ini_map[knob] + knob_size = bios_map[knob]['size'] + knob_offset = bios_map[knob]['offset'] + knob_var_store = bios_map[knob]['vstore'] + a1 = re.search('0x(.*)', knob_val) + a2 = re.search('L"(.*)"', knob_val) + a3 = re.search('"(.*)"', knob_val) + b1 = re.search('0x(.*)', knob_size) + c1 = re.search('0x(.*)', knob_var_store) + d1 = re.search('0x(.*)', knob_offset) + if a1 is not None: + knob_val_hex = a1.group(1) + elif a2 is not None: + j = 0 + data = a2.group(1).strip()[::-1] + total_str = '' + while j < len(data): + each_bit = '00' + clb.HexLiFy(data[j]).zfill(2) + total_str = total_str + each_bit + j = j + 1 + knob_val_hex = total_str + elif a3 is not None: + knob_val_hex = clb.HexLiFy(a3.group(1).strip()[::-1]) + else: + if knob_val.isdigit(): + knob_val_hex = hex(int(knob_val))[2:] + else: + log.warning(f' Knob [{knob}] value [{knob_val}] is not in proper format') + continue + if b1 is not None: + knob_size_hex = b1.group(1).zfill(2) + knob_size_int = int('0x' + knob_size_hex, 16) + else: + knob_size_hex = hex(int(knob_size))[2:].zfill(2) + knob_size_int = int(knob_size) + if c1 is not None: + knob_var_store_hex = c1.group(1).zfill(2) + else: + knob_var_store_hex = hex(int(knob_var_store))[2:].zfill(2) + if d1 is not None: + knob_offset_hex = d1.group(1).zfill(4) + knob_offset_int = int(knob_offset_hex, 16) + else: + knob_offset_int = int(knob_offset) + knob_offset_hex = hex(knob_offset_int)[2:].zfill(4) + + knob_size = knob_size_int + knob_width = knob_size_int + if knob_offset_int >= clb.BITWISE_KNOB_PREFIX: # bitwise knob? + knob_width, knob_offset_int, bit_offset = clb.get_bitwise_knob_details(knob_size_int, knob_offset_int) + knob_size_int = ((knob_size_int & 0x1F) << 3) + (bit_offset & 0x7) + knob_size_hex = hex(knob_size_int)[2:].zfill(2) + knob_offset_hex = hex(knob_offset_int)[2:].zfill(4) + + if SETUP_FLAG == 1 and SIG_FLAG == 1: + if int('0x' + knob_var_store_hex, 16) != 0xFF: + knob_offset_hex = offset_correction(knob_offset_hex, knob_var_store_hex) + if int(knob_width * 2) < len(knob_val_hex): + log.warning(f'Value [{knob_val}] of knob [{knob}] is larger in size compared to maximum size for the knob[{knob_size}] mentioned in xml') + continue + else: + knob_val_hex = knob_val_hex.zfill(knob_width * 2) + else: + log.warning(f'Bios Knob "{knob}" does not currently exist ') + has_unknown_knob = True + continue + value_line = '' + tbl_desc_line = [] + inc = knob_width * 2 + while inc > 0: + tbl_desc_line.append(knob_val_hex[inc - 2:inc]) + inc = inc - 2 + value_line = ''.join(tbl_desc_line) + binline = knob_var_store_hex.strip() + knob_offset_hex[2:].strip() + knob_offset_hex[0:2].strip() + knob_size_hex.strip() + value_line.strip() + binline_ascii = binline + buffer_lis.append(binline_ascii) + + if EXIT_ON_UNKNOWN_KNOB and has_unknown_knob: + log.error('Aborting Since ExitOnAlienKnob was set, see above for details. ') + return '' + + total_entries = hex(len(buffer_lis))[2:].zfill(8) + inc = 8 + entries_line = [] + while inc > 0: + entries_line.append(total_entries[inc - 2:inc]) + inc = inc - 2 + entry_line = ''.join(entries_line) + buffer_str = entry_line + ''.join(buffer_lis) + END_OF_BUFFER + request_buffer = binascii.unhexlify(buffer_str) + with open(bin_file, 'wb') as out_bin: + out_bin.write(request_buffer) + return request_buffer + + +def value_to_hex(val): + val_hex = '' + a1 = re.search('0x(.*)', val) + a2 = re.search('L"(.*)"', val) + a3 = re.search('"(.*)"', val) + if a1 is not None: + val_hex = a1.group(1) + elif a2 is not None: + j = 0 + data = a2.group(1) + total_str = '' + while j < len(data): + each_bit = clb.HexLiFy(data[j]).zfill(4) + ' ' + total_str = total_str + each_bit + j = j + 1 + val_hex = total_str + + elif a3 is not None: + val_hex = clb.HexLiFy(a3.group(1)) + else: + if val.isdigit(): + val_hex = hex(int(val))[2:] + val_hex = '0x' + val_hex + return val_hex + + +def parse_cli_ini_xml(file_name, ini_file, bin_file='bios.bin', build_type=None): + global XML_TREE + XML_TREE = None + bios_map = get_bios_lookup(file_name, build_type=build_type) + ini_map, knob_lis = get_bios_ini(ini_file) + return create_bin_file(bin_file, bios_map, ini_map, knob_lis) + + +def generate_csv(xml_file, por_default_review=False): + global XML_TREE + duplicateKnobs = [] + invalidOption = {} + nullUQI = [] + unknown_setup_type = [] + knobList = {} + XML_TREE = None + if XML_TREE is None: + XML_TREE = ET.parse(xml_file) + + _bios_version = '' + for version in XML_TREE.iter(tag='BIOS'): + _bios_version = version.get('VERSION') + if _bios_version == '': + for version in XML_TREE.iter(tag='SVBIOS'): + _bios_version = version.get('VERSION') + if _bios_version == '': + for version in XML_TREE.iter(tag='CPUSVBIOS'): + _bios_version = version.get('VERSION') + + log.info(f'\nBIOS XML is of VERSION [{_bios_version}]') + csv_data = "" + if por_default_review: + csv_data += 'Name,Description,Grouping,Type,Size(Bytes),Selection [Value],DefaultVal,SetupPagePtr,Depex\n' + else: + csv_data += 'Name,Description,Type,Size(Bytes),Selection [Value],DefaultVal,CurrentVal,SetupPagePtr,Depex\n' + for setup_knobs in XML_TREE.iter(tag='biosknobs'): + for knob in setup_knobs: + sel_str = '\"' + setup_type = (nstrip(knob.get('setupType'))).upper() + if setup_type == 'ONEOF': + for options in knob: + for option in options: + sel_str += f'{nstrip(option.get("text"))} [{nstrip(option.get("value"))}]\n' + if sel_str[len(sel_str) - 1] == '\n': + sel_str = sel_str[0:(len(sel_str) - 1)] + elif setup_type in ['NUMRIC', 'NUMERIC']: + sel_str += f'{"min"} [{nstrip(knob.get("min"))}]\n{"max"} [{nstrip(knob.get("max"))}]' + elif setup_type == 'STRING': + sel_str += f'{"minsize"} [{nstrip(knob.get("minsize"))}]\n{"maxsize"} [{nstrip(knob.get("maxsize"))}]' + elif setup_type in ['CHECKBOX']: + sel_str += f'{"UnChecked"} [{"0"}]\n{"Checked"} [{"1"}]' + else: + log.warning(f'Setup Type is unknown for biosName[{nstrip(knob.get("name"))}] setupType[{setup_type}]. ') + unknown_setup_type.append(setup_type) + sel_str = sel_str + '\"' + if setup_type in ['ONEOF', 'CHECKBOX', 'NUMRIC', 'NUMERIC', 'STRING']: + if por_default_review: + csv_data += f'{nstrip(knob.get("name"))},{nstrip(knob.get("prompt")).replace(",", ";")}: {nstrip(knob.get("description")).replace(",", ";")},{nstrip(knob.get("Nvar"))},{setup_type},{nstrip(knob.get("size"))},{sel_str},{nstrip(knob.get("default"))},{nstrip(knob.get("SetupPgPtr"))},{nstrip(knob.get("depex"))}\n' + else: + csv_data += f'{nstrip(knob.get("name"))},{nstrip(knob.get("prompt")).replace(",", ";")}: {nstrip(knob.get("description")).replace(",", ";")},{setup_type},{nstrip(knob.get("size"))},{sel_str},{nstrip(knob.get("default"))},{nstrip(knob.get("CurrentVal"))},{nstrip(knob.get("SetupPgPtr"))},{nstrip(knob.get("depex"))}\n' + + csv_file_name = f'{_bios_version.replace(".", "_")}_KnobsData.csv' + csv_file = os.path.join(clb.TempFolder, csv_file_name) + with open(csv_file, 'w') as file_ptr: + log.info(f'writing to file : {csv_file}') + file_ptr.write(csv_file) + log.info('Csv File generated !') + + +def generate_bios_knobs_config(xml_file, flexcon_cfg_file, knobs_ini_file, build_type=None): + tree = ET.parse(xml_file) + bios_knobs_map = {} + for setup_knobs in tree.iter(tag='biosknobs'): + if setup_knobs.get('BuildType') != build_type: + continue + for knob in setup_knobs: + setup_type = (nstrip(knob.get('setupType'))).upper() + knob_name = nstrip(knob.get('name')) + bios_knobs_map[knob_name] = {} + bios_knobs_map[knob_name]['$SetUpType'] = setup_type + if setup_type == 'ONEOF': + for options in knob: + for option in options: + bios_knobs_map[knob_name][nstrip(option.get('text'))] = nstrip(option.get('value')) + with open(flexcon_cfg_file, "r") as f: + bios_knobs_lis = f.readlines() + knob_start = 0 + i = 0 + ini_content = ';-------------------------------------------------\n' + '; BIOS contact: xmlcli@intel.com\n' + '; XML Shared MailBox settings for BIOS CLI based setup\n' + '; The name entry here should be identical as the name from the XML file (retain the case)\n' + ';-------------------------------------------------\n' + '[BiosKnobs]\n' + while i < len(bios_knobs_lis): + line = bios_knobs_lis[i].strip() + if (line == '[BIOS Overrides]') or (line == '[BiosKnobs]'): + knob_start = 1 + i = i + 1 + continue + if knob_start == 1: + knob_name = '' + knob_value = '' + line = line.split(';')[0] + if line != '': + if line[0] == '[': + if line[-1] == ']': + break + knob_name = line.split('=')[0].strip() + knob_value = line.split('=')[1].strip() + if knob_name not in bios_knobs_map: + log.warning(f'Bios Knob \"{knob_name}\" does not currently exist ') + i = i + 1 + continue + if bios_knobs_map[knob_name]['$SetUpType'] == 'ONEOF': + if knob_value in ['Enabled', 'Enable']: + try: + ini_content += f'{knob_name} = {bios_knobs_map[knob_name]["Enabled"]} \n' + i = i + 1 + continue + except: + try: + ini_content += f'{knob_name} = {bios_knobs_map[knob_name]["Enable"]} \n' + i = i + 1 + continue + except: + log.warning(f'InCorrect Knob Value for Bios Knob \"{knob_name}\"') + elif knob_value in ['Disabled', 'Disable']: + try: + ini_content += f'{knob_name} = {bios_knobs_map[knob_name]["Disabled"]} \n' + i = i + 1 + continue + except: + try: + ini_content += f'{knob_name} = {bios_knobs_map[knob_name]["Disable"]} \n' + i = i + 1 + continue + except: + log.warning(f'InCorrect Knob Value for Bios Knob \"{knob_name}\"') + else: + try: + ini_content += f'{knob_name} = {bios_knobs_map[knob_name][knob_value]} \n' + except: + log.warning(f'InCorrect Knob Value for Bios Knob \"{knob_name}\"') + if bios_knobs_map[knob_name]['$SetUpType'] == 'CHECKBOX': + if knob_value == 'Checked': + ini_content += f'{knob_name} = {1:d} \n' + if knob_value == 'Unchecked': + ini_content += f'{knob_name} = {0:d} \n' + if (bios_knobs_map[knob_name]['$SetUpType'] == 'NUMRIC') or (bios_knobs_map[knob_name]['$SetUpType'] == 'NUMERIC'): + ini_content += f'{line}\n' + i = i + 1 + with open(knobs_ini_file, 'w') as out_ini: + out_ini.write(ini_content) + + +def generate_bios_config_ini(xml_file, bios_config_file, knobs_ini_file='', mode='genbiosconf', knobs_map={}): + tree = ET.parse(xml_file) + bios_knobs_map = {} + knob_count = 0 + xml_map = {} + KnobComments = {} + knob_start = False + comment = '' + comment_map = {} + for line in open(xml_file, 'r').readlines(): + line = line.strip() + if line == '': + continue + match = re.search(r'\s*\\s*', line) + if match != None: + knob_start = True + match = re.search(r'\s*\<\/biosknobs\>\s*', line) + if match != None: + knob_start = False + if knob_start: + match = re.search(r'\s*\