mirror of https://github.com/acidanthera/audk.git
405 lines
15 KiB
Markdown
405 lines
15 KiB
Markdown
# Dynamic Tables Framework
|
|
|
|
Dynamic Tables Framework provides mechanisms to reduce the amount
|
|
of effort required in porting firmware to new platforms. The aim is
|
|
to provide an implementation capable of generating the firmware
|
|
tables from an external source. This is potentially a management
|
|
node, either local or remote, or, where suitable, a file that might
|
|
be generated from the system construction. This initial release
|
|
does not fully implement that - the configuration is held in local
|
|
UEFI modules.
|
|
|
|
# Feature Summary
|
|
|
|
The dynamic tables framework is designed to generate standardised
|
|
firmware tables that describe the hardware information at
|
|
run-time. A goal of standardised firmware is to have a common
|
|
firmware for a platform capable of booting both Windows and Linux
|
|
operating systems.
|
|
|
|
Traditionally the firmware tables are handcrafted using ACPI
|
|
Source Language (ASL), Table Definition Language (TDL) and
|
|
C-code. This approach can be error prone and involves time
|
|
consuming debugging. In addition, it may be desirable to configure
|
|
platform hardware at runtime such as: configuring the number of
|
|
cores available for use by the OS, or turning SoC features ON or
|
|
OFF.
|
|
|
|
The dynamic tables framework simplifies this by providing a set
|
|
of standard table generators, that are implemented as libraries.
|
|
These generators query a platform specific component, the
|
|
'Configuration Manager', to collate the information required
|
|
for generating the tables at run-time.
|
|
|
|
The framework also provides the ability to implement custom/OEM
|
|
generators; thereby facilitating support for custom tables. The
|
|
custom generators can also utilize the existing standard generators
|
|
and override any functionality if needed.
|
|
|
|
The framework currently implements a set of standard ACPI table
|
|
generators for ARM architecture, that can generate Server Base Boot
|
|
Requirement (SBBR) compliant tables. Although, the set of standard
|
|
generators implement the functionality required for ARM architecture;
|
|
the framework is extensible, and support for other architectures can
|
|
be added easily.
|
|
|
|
The framework currently supports the following table generators for ARM:
|
|
* DBG2 - Debug Port Table 2
|
|
* DSDT - Differentiated system description table. This is essentially
|
|
a RAW table generator.
|
|
* FADT - Fixed ACPI Description Table
|
|
* GTDT - Generic Timer Description Table
|
|
* IORT - IO Remapping Table
|
|
* MADT - Multiple APIC Description Table
|
|
* MCFG - PCI Express memory mapped configuration space base address
|
|
Description Table
|
|
* PCCT - Platform Communications Channel Table
|
|
* PPTT - Processor Properties Topology Table
|
|
* SPCR - Serial Port Console Redirection Table
|
|
* SRAT - System Resource Affinity Table
|
|
* SSDT - Secondary System Description Table. This is essentially
|
|
a RAW table generator.
|
|
|
|
## Dynamic AML
|
|
|
|
ACPI Definition block (e.g. DSDT or SSDT) tables are used to describe system
|
|
devices along with other control and power management information. These tables
|
|
are written using ACPI Source Language (ASL). The ASL code is compiled using an
|
|
ASL compiler (e.g. Intel iASL compiler) to generate ACPI Machine Language (AML)
|
|
bytecode.
|
|
|
|
Since, definition blocks are represented using AML grammar, run-time generation
|
|
of definition blocks is complex. Dynamic AML is a feature of Dynamic Tables
|
|
framework that provides a solution for dynamic generation of ACPI Definition
|
|
block tables.
|
|
|
|
Dynamic AML introduces the following techniques:
|
|
* AML Fixup
|
|
* AML Codegen
|
|
* AML Fixup + Codegen
|
|
|
|
### AML Fixup
|
|
AML fixup is a technique that involves compiling an ASL template file to
|
|
generate AML bytecode. This template AML bytecode can be parsed at run-time
|
|
and a fixup code can update the required fields in the AML template.
|
|
|
|
To simplify AML Fixup, the Dynamic Tables Framework provides an *AmlLib*
|
|
library with a rich set of APIs that can be used to fixup the AML code.
|
|
|
|
### AML Codegen
|
|
AML Codegen employs generating small segments of AML code. The *AmlLib*
|
|
library provides AML Codegen APIs that generate the AML code segments.
|
|
|
|
Example: The following table depicts the AML Codegen APIs and the
|
|
corresponding ASL code that would be generated.
|
|
|
|
| AML Codegen API | ASL Code |
|
|
|--------------------------------|--------------------------------|
|
|
| AmlCodeGenDefinitionBlock ( | DefinitionBlock ( |
|
|
| .., | ... |
|
|
| &RootNode); | ) { |
|
|
| AmlCodeGenScope ( | Scope (_SB) { |
|
|
| "\_SB", | |
|
|
| RootNode, | |
|
|
| &ScopeNode); | |
|
|
| AmlCodeGenDevice ( | Device (CPU0) { |
|
|
| "CPU0", | |
|
|
| ScopeNode, | |
|
|
| &CpuNode); | |
|
|
| AmlCodeGenNameString ( | Name (_HID, "ACPI0007") |
|
|
| "_HID", | |
|
|
| "ACPI0007", | |
|
|
| CpuNode, | |
|
|
| &HidNode); | |
|
|
| AmlCodeGenNameInteger ( | Name (_UID, Zero) |
|
|
| "_UID", | |
|
|
| 0, | |
|
|
| CpuNode, | |
|
|
| &UidNode); | |
|
|
| | } // Device |
|
|
| | } // Scope |
|
|
| | } // DefinitionBlock |
|
|
|
|
### AML Fixup + Codegen
|
|
A combination of AML Fixup and AML Codegen could be used for generating
|
|
Definition Blocks. For example the AML Fixup could be used to fixup certain
|
|
parts of the AML template while the AML Codegen APIs could be used to inserted
|
|
small fragments of AML code in the AML template.
|
|
|
|
### AmlLib Library
|
|
Since, AML bytecode represents complex AML grammar, an **AmlLib** library is
|
|
introduced to assist parsing and traversing of the AML bytecode at run-time.
|
|
|
|
The AmlLib library parses a definition block and represents it as an AML
|
|
tree. This tree representation is based on the AML grammar defined by the
|
|
ACPI 6.3 specification, section - 20 'ACPI Machine Language (AML)
|
|
Specification'.
|
|
|
|
AML objects, methods and data are represented as tree nodes. Since the AML
|
|
data is represented as tree nodes, it is possible to traverse the tree, locate
|
|
a node and modify the node data. The tree can then be serialized to a buffer
|
|
(that represents the definition block). This definition block containing
|
|
the fixed up AML code can then be installed as an ACPI table (DSDT/SSDT).
|
|
|
|
AmlLib provides a rich API to operate on AML data. For example it provides
|
|
APIs to update a device's name, the value of a "_UID" object, and the memory
|
|
and interrupt number stored in a "_CRS" node.
|
|
|
|
Although the AmlLib performs checks to a reasonable extent while modifying a
|
|
definition block, these checks may not cover all aspects due to the complexity
|
|
of the ASL/AML language. It is therefore recommended to review any operation
|
|
performed, and validate the generated output.
|
|
|
|
Example: The serialized AML code could be validated by
|
|
- Saving the generated AML to a file and comparing with
|
|
a reference output.
|
|
or
|
|
- Disassemble the generated AML using the iASL compiler
|
|
and verifying the output.
|
|
|
|
### Bespoke ACPI tables
|
|
|
|
The Dynamic Tables framework supports the creation of several tables using
|
|
standard generators, see Feature Summary Section for a list of such tables.
|
|
|
|
The supported platforms already contain several tables.
|
|
If a table is not present for the platform, two alternative processes can be followed:
|
|
|
|
- define the table in using ASL,
|
|
- define the table in packed C structures (also known as RAW).
|
|
|
|
The two approaches are detailed below.
|
|
|
|
#### Adding an ASL table for which the Dynamic Tables Framework does not provide a standard generator
|
|
|
|
This method creates the SSDT table from the ASL source, using a standard generator.
|
|
Perform the following steps:
|
|
|
|
1. Create the table source file, placing it within the ConfigurationManager source tree, e.g.:
|
|
|
|
Create a file Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/AslTables/NewTableSource.asl
|
|
with the following contents:
|
|
|
|
```
|
|
DefinitionBlock ("", "SSDT", 2, "XXXXXX", "XXXXXXXX", 1) {
|
|
Scope(_SB) {
|
|
Device(FLA0) {
|
|
Name(_HID, "XXXX0000")
|
|
Name(_UID, 0)
|
|
|
|
// _DSM - Device Specific Method
|
|
Function(_DSM,{IntObj,BuffObj},{BuffObj, IntObj, IntObj, PkgObj})
|
|
{
|
|
W0 = 0x1
|
|
return (W0)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
2. Reference the table source file in ConfigurationMangerDxe.inf
|
|
|
|
```
|
|
[Sources]
|
|
AslTables/NewTableSource.asl
|
|
```
|
|
|
|
3. Update the ConfigurationManager.h file
|
|
Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.h
|
|
|
|
Add an array to hold the AML code:
|
|
```
|
|
extern CHAR8 newtablesource_aml_code[];
|
|
```
|
|
|
|
Note: the array name is composed of the ASL source file name all in lower case, followed by the _aml_code postfix.
|
|
|
|
4. Increment the macro PLAT_ACPI_TABLE_COUNT
|
|
|
|
5. Add a new CM_STD_OBJ_ACPI_TABLE_INFO structure entry and initialise.
|
|
|
|
- the entry contains:
|
|
- the table signature,
|
|
- the table revision (unused in this case),
|
|
- the ID of the standard generator to be used (the SSDT generator in this case).
|
|
- a pointer to the AML code,
|
|
|
|
```
|
|
// Table defined in the NewTableSource.asl file
|
|
{
|
|
EFI_ACPI_6_4_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
|
|
0, // Unused
|
|
CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdt),
|
|
(EFI_ACPI_DESCRIPTION_HEADER*)newtablesource_aml_code
|
|
},
|
|
```
|
|
|
|
#### Add a RAW table for which there is no standard generator
|
|
|
|
An ACPI table can be defined as a packed C struct in the C source code. This is referred to as the "raw" table format.
|
|
The steps to create a table in raw format are detailed below:
|
|
|
|
1. Define the table in a C source file and populate the ACPI table structure field with the required values.
|
|
|
|
For example, create the file Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/RawTable.c
|
|
|
|
```
|
|
// Example creating the HMAT in raw format
|
|
EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE Hmat = {
|
|
...
|
|
};
|
|
```
|
|
|
|
2. Reference the table source file in ConfigurationMangerDxe.inf
|
|
|
|
```
|
|
[Sources]
|
|
RawTable.c
|
|
```
|
|
|
|
2. Increment the macro PLAT_ACPI_TABLE_COUNT
|
|
|
|
3. Add a new CM_STD_OBJ_ACPI_TABLE_INFO structure entry and initialise.
|
|
|
|
- the entry contains:
|
|
- the table signature,
|
|
- the table revision,
|
|
- the RAW generator ID.
|
|
- a pointer to the C packed struct that defines the table,
|
|
|
|
```
|
|
{
|
|
EFI_ACPI_6_3_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_SIGNATURE,
|
|
EFI_ACPI_6_3_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_REVISION,
|
|
CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdRaw),
|
|
(EFI_ACPI_DESCRIPTION_HEADER*)&Hmat
|
|
},
|
|
```
|
|
|
|
# Roadmap
|
|
|
|
The current implementation of the Configuration Manager populates the
|
|
platform information statically as a C structure. Further enhancements
|
|
to introduce runtime loading of platform information from a platform
|
|
information file is planned.
|
|
|
|
Also support for generating SMBIOS tables is planned and will be added
|
|
subsequently.
|
|
|
|
# Supported Platforms
|
|
|
|
1. Juno
|
|
2. FVP Models
|
|
|
|
# Build Instructions
|
|
|
|
1. Set path for the iASL compiler with support for generating a C header
|
|
file as output.
|
|
|
|
2. Set PACKAGES_PATH to point to the locations of the following repositories:
|
|
|
|
Example:
|
|
|
|
> set PACKAGES_PATH=%CD%\edk2;%CD%\edk2-platforms;
|
|
|
|
or
|
|
|
|
> export PACKAGES_PATH=$PWD/edk2:$PWD/edk2-platforms
|
|
|
|
3. To enable Dynamic tables framework the *'DYNAMIC_TABLES_FRAMEWORK'*
|
|
option must be defined. This can be passed as a command line
|
|
parameter to the edk2 build system.
|
|
|
|
Example:
|
|
|
|
>build -a AARCH64 -p Platform\ARM\JunoPkg\ArmJuno.dsc
|
|
-t GCC5 **-D DYNAMIC_TABLES_FRAMEWORK**
|
|
|
|
or
|
|
|
|
>build -a AARCH64 -p Platform\ARM\VExpressPkg\ArmVExpress-FVP-AArch64.dsc
|
|
-t GCC5 **-D DYNAMIC_TABLES_FRAMEWORK**
|
|
|
|
# Prerequisites
|
|
|
|
Ensure that the latest ACPICA iASL compiler is used for building *Dynamic Tables Framework*.
|
|
*Dynamic Tables Framework* has been tested using the following iASL compiler version:
|
|
[Version 20200717](https://www.acpica.org/node/183), dated 17 July, 2020.
|
|
|
|
|
|
#Running CI builds locally
|
|
|
|
The TianoCore EDKII project has introduced Core CI infrastructure using TianoCore EDKII Tools PIP modules:
|
|
|
|
- *[edk2-pytool-library](https://pypi.org/project/edk2-pytool-library)*
|
|
|
|
- *[edk2-pytool-extensions](https://pypi.org/project/edk2-pytool-extensions)*
|
|
|
|
|
|
The instructions to setup the CI environment are in *'edk2\\.pytool\\Readme.md'*
|
|
|
|
## Building DynamicTablesPkg with Pytools
|
|
|
|
1. [Optional] Create a Python Virtual Environment - generally once per workspace
|
|
|
|
```
|
|
python -m venv <name of virtual environment>
|
|
|
|
e.g. python -m venv edk2-ci
|
|
```
|
|
|
|
2. [Optional] Activate Virtual Environment - each time new shell/command window is opened
|
|
|
|
```
|
|
<name of virtual environment>/Scripts/activate
|
|
|
|
e.g. On a windows host PC run:
|
|
edk2-ci\Scripts\activate.bat
|
|
```
|
|
3. Install Pytools - generally once per virtual env or whenever pip-requirements.txt changes
|
|
|
|
```
|
|
pip install --upgrade -r pip-requirements.txt
|
|
```
|
|
|
|
4. Initialize & Update Submodules - only when submodules updated
|
|
|
|
```
|
|
stuart_setup -c .pytool/CISettings.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH>
|
|
|
|
e.g. stuart_setup -c .pytool/CISettings.py TOOL_CHAIN_TAG=GCC5
|
|
```
|
|
|
|
5. Initialize & Update Dependencies - only as needed when ext_deps change
|
|
|
|
```
|
|
stuart_update -c .pytool/CISettings.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH>
|
|
|
|
e.g. stuart_update -c .pytool/CISettings.py TOOL_CHAIN_TAG=GCC5
|
|
```
|
|
|
|
6. Compile the basetools if necessary - only when basetools C source files change
|
|
|
|
```
|
|
python BaseTools/Edk2ToolsBuild.py -t <ToolChainTag>
|
|
```
|
|
|
|
7. Compile DynamicTablesPkg
|
|
|
|
```
|
|
stuart_build-c .pytool/CISettings.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH>
|
|
|
|
e.g. stuart_ci_build -c .pytool/CISettings.py TOOL_CHAIN_TAG=GCC5 -p DynamicTablesPkg -a AARCH64 --verbose
|
|
```
|
|
|
|
- use `stuart_build -c .pytool/CISettings.py -h` option to see help on additional options.
|
|
|
|
|
|
# Documentation
|
|
|
|
Refer to the following presentation from *UEFI Plugfest Seattle 2018*:
|
|
|
|
[Dynamic Tables Framework: A Step Towards Automatic Generation of Advanced Configuration and Power Interface (ACPI) & System Management BIOS (SMBIOS) Tables](http://www.uefi.org/sites/default/files/resources/Arm_Dynamic%20Tables%20Framework%20A%20Step%20Towards%20Automatic%20Generation%20of%20Advanced%20Configuration%20and%20Power%20Interface%20%28ACPI%29%20%26%20System%20Management%20BIOS%20%28SMBIOS%29%20Tables%20_0.pdf)
|
|
|