]> git.proxmox.com Git - mirror_edk2.git/blame - PrmPkg/Readme.md
UefiCpuPkg: Fix SMM code hangs when InitPaging
[mirror_edk2.git] / PrmPkg / Readme.md
CommitLineData
d2cb6e67
MK
1# **Platform Runtime Mechanism**\r
2\r
3Platform Runtime Mechanism (PRM) introduces the capability of moving platform-specific code out of SMM and into a\r
4code module that executes within the OS context. Moving this firmware to the OS context provides better transparency\r
5and mitigates the negative system impact currently accompanied with SMM solutions. Futhermore, the PRM code is\r
6packaged into modules with well-defined entry points, each representing a specific PRM functionality.\r
7\r
deea4e58
MK
8For more details on PRM, refer to the [Platform Runtime Mechanism Specification on uefi.org](https://uefi.org/sites/default/files/resources/Platform%20Runtime%20Mechanism%20-%20with%20legal%20notice.pdf).\r
9\r
d2cb6e67
MK
10The `PrmPkg` maintained in this branch provides a single cohesive set of generic PRM functionality that is intended\r
11to be leveraged by platform firmware with minimal overhead to integrate PRM functionality in the firmware.\r
12\r
f8e68587
MK
13> By default, the build makes use of a new ACPI OperationRegion type specifically introduced for PRM called\r
14`PlatformRtMechanism`. Support for this OperationRegion is planned for the next release of the ACPI specification.\r
15However, support for `PlatformRtMechanism` is already included in the iASL Compiler/Disassembler for early prototyping\r
16(i.e. this package). If you would like the default build to work and/or to use PRM handlers that are invoked\r
17through ACPI, iASL compiler [20200528](https://acpica.org/node/181) or greater must be used. If you are only\r
18interested in compiling the code and/or using direct call style PRM handlers, you can simply remove\r
19`PrmSsdtInstallDxe` from `PrmPkg.dsc`.\r
20\r
f3c11224
MK
21The changes in the ACPI Specification include two elements:\r
22\r
231. `BIT20` in Platform-Wide _OSC Capabilities DWORD2 will be used by an OS to indicate support for PRM\r
242. A new Operation Region Address Space Identifier Value is defined as `0xB` for `PlatformRtMechanism`\r
25\r
d2cb6e67 26## How to Build PrmPkg\r
f3c11224 27\r
d2cb6e67
MK
28As noted earlier, resources in `PrmPkg` are intended to be referenced by a platform firmware so it can adopt support\r
29for PRM. In that case, the platform firmware should add the `PrmConfigDxe` and `PrmLoaderDxe` drivers to its DSC and\r
30FDF files so they are built in the platform firmware build and dispatched during its runtime. All that is left is to\r
31add individual PRM modules to the DSC and FDF. These can be built from source or included as binaries into the platform\r
32firmware flash map.\r
33\r
34### PrmPkg Standalone Build\r
d2cb6e67
MK
35\r
36To build `PrmPkg` as a standalone package:\r
f3c11224 37\r
d2cb6e67
MK
381. If new to EDK II, follow the directions in [Getting Started with EDK II](https://github.com/tianocore/tianocore.github.io/wiki/Getting-Started-with-EDK-II)\r
39\r
402. Clone the *master* branch on the edk2 repository locally \\r
41 ``git clone https://github.com/tianocore/edk2.git``\r
42\r
f3c11224 433. Change to the edk2 workspace directory \\r
d2cb6e67
MK
44 ``cd edk2``\r
45\r
f3c11224 464. Run *edksetup* to set local environment variables needed for build\r
d2cb6e67
MK
47 * Windows:\r
48 * ``edksetup.bat``\r
49 * Linux:\r
50 * If you have not already built BaseTools:\r
51 * ``make -C BaseTools``\r
52 * ``. edksetup.sh``\r
53\r
f3c11224 545. Build PrmPkg \\r
1da2012d
JM
55\r
56The PrmPkg can be built targetting the IA32/X64 and AArch64 architectures.\r
57\r
58 - IA32/X64\r
59\r
d2cb6e67 60 ``build -p PrmPkg/PrmPkg.dsc -a IA32 -a X64``\r
f3c11224
MK
61 > ***Note***: Due to the way PRM modules are compiled with exports, **only building on Visual Studio compiler tool\r
62 chains has been tested**.\r
d2cb6e67 63\r
f3c11224 64> ***Note***: \\r
f8e68587
MK
65> This package has been used without modification in several environments including client, server,\r
66> and virtual systems.\r
67>\r
f8e68587
MK
68> You can add your own PRM modules into the build and check them with the `PrmInfo` UEFI application described\r
69> later in this document and dump the PRMT table in the OS to check if your PRM module is represented as expected.\r
70\r
1da2012d
JM
71 - AArch64\r
72 ``build -p PrmPkg/PrmPkg.dsc -a AARCH64 -t GCC5``\r
73\r
74 > ***Note***: Only builds with the GCC5 toolchain have been tested.\r
75 > ***Note***: For builds with the GCC5 toolchain, the PrmModuleExportDescriptor and any other handler entry points symbols, to be listed in the PRMT, must be explicitly preserved by enumerating these in the AARCH64 linker flags. The --require-defined linker flag must be used for each symbol to be preserved.\r
76\r
c040831c 77### PRM Platform GUID\r
c040831c 78\r
f3c11224
MK
79**IMPORTANT** PRM has a concept of a "Platform GUID" which associates a specific platform with a set of PRM modules\r
80built for that platform. This GUID is used to ensure system compatibility for a given collection of PRM modules.\r
4a4aeaa4
MK
81\r
82Therefore, each PRM module must only target a single platform and each platform must have a unique GUID. Even if a\r
83PRM module is unchanged between two different platforms now, there is no guarantee that will remain the case so always\r
84assign a unique Platform GUID for each platform.\r
c040831c 85\r
4a4aeaa4
MK
86The PRM Platform GUID is primarily used during PRM module runtime updates in the OS to ensure that the Platform GUID\r
87in the system's ACPI table (PRMT) matches the Platform GUID of the module requested for update. Even if runtime\r
88updates are not a planned feature for a given platform, still assign a unique Platform GUID for binary module\r
89identification (the Platform GUID is in the module's export descriptor) and to ensure such updates can be seamlessly\r
90supported in the future if needed.\r
c040831c 91\r
4a4aeaa4
MK
92In the `PrmPkg` implementation, the Platform GUID is automatically derived from the PLATFORM_GUID in the DSC file of\r
93the package being built.\r
c040831c 94\r
f3c11224
MK
95### Build Output\r
96\r
97Like a typical EDK II package, the PrmPkg binary build output can be found in the Build directory in the edk2\r
98workspace. The organization in that directory follows the same layout as other EDK II packages.\r
99\r
100For example, that path to PRM module sample binaries for a DEBUG VS2017 X64 build is: \\r
101``edk2/Build/Prm/DEBUG_VS2017/X64/PrmPkg/Samples``\r
102\r
d2cb6e67 103## Overview\r
f3c11224 104\r
d2cb6e67
MK
105At a high-level, PRM can be viewed from three levels of granularity:\r
106\r
f3c11224 1071. `PRM interface` - Encompassing the entirety of firmware functionalities and data provided to OS runtime. Most\r
d2cb6e67 108 information is provided through ACPI tables to be agnostic to a UEFI implementation.\r
f3c11224 1092. `PRM module` - An independently updatable package of PRM handlers. The PRM interface will be composed of multiple\r
d2cb6e67
MK
110 PRM modules. This requirement allows for the separation of OEM and IHV PRM code, each of which can be serviced\r
111 independently.\r
f3c11224 1123. `PRM handler` - The implementation/callback of a single PRM functionality as identified by a GUID.\r
d2cb6e67
MK
113\r
114## Firmware Design\r
f3c11224 115\r
d2cb6e67
MK
116The firmware has three key generic drivers to support PRM:\r
117\r
f3c11224 1181. A `PRM Loader driver` - Functionality is split across three phases:\r
d2cb6e67
MK
119 1. Discover - Find all PRM modules in the firmware image made available by the platform firmware author.\r
120 * This phase includes verifying authenticity/integrity of the image, the image executable type, the export\r
121 table is present and the PRM Export Module Descriptor is present and valid.\r
122 2. Process - Convert PRM handler GUID to name mappings in the PRM Module Export Descriptor to PRM handler Name\r
123 to physical address mappings required to construct the PRM ACPI table.\r
124 3. Publish - Publish the PRM ACPI table using the information from the Process phase.\r
125\r
f3c11224 1262. A `PRM Configuration driver` - A generic driver responsible for processing PRM module configuration information\r
d2cb6e67
MK
127 consumed through a `PRM_CONFIG_PROTOCOL` per PRM module instance. Therefore, the `PRM_CONFIG_PROTOCOL` serves\r
128 as the dynamic interface for this driver to process PRM module resources and prepare the module's data to be\r
129 configured properly for OS runtime.\r
130\r
f3c11224 1313. A `PRM Module` - Not a single driver but a user written PE/COFF image that follows the PRM module authoring process.\r
d2cb6e67
MK
132 A PRM module groups together cohesive sets of PRM functionality into functions referred to as "PRM handlers".\r
133\r
134## PrmPkg Code Organization\r
f3c11224 135\r
d2cb6e67
MK
136The package follows a standard EDK II style package format. The list below contains some notable areas to\r
137explore in the package:\r
138\r
139* [ACPI Table Definitions](PrmPkg/PrmLoaderDxe/PrmAcpiTable.h)\r
140* [Common Interface Definitions](PrmPkg/Include)\r
141* [PRM Config Driver](PrmPkg/PrmConfigDxe)\r
142* [PRM Loader Driver](PrmPkg/PrmLoaderDxe)\r
143* [Sample PRM Modules](PrmPkg/Samples)\r
144\r
145While the package does provide sample PRM modules to be used as a reference, actual PRM modules should not be\r
146maintained in PrmPkg. It is intended to only contain PRM infrastructure code and a few samples of how to use\r
147that infrastructure. The PrmPkg is meant to be used as-is by firmware that supports PRM. Any shortcomings that\r
148prevent the package from being used as-is should be addressed directly in PrmPkg.\r
149\r
4348c72a 150## PRM Information UEFI Application\r
f3c11224
MK
151\r
152A UEFI application is provided in this package called `PrmInfo` that allows a user to display and test PRM\r
4348c72a
MK
153modules on their system.\r
154\r
155[Link to application source code](PrmPkg/Application/PrmInfo).\r
156\r
157This application is intended to be helpful during PRM enabling by allowing the user to:\r
f3c11224 158\r
4348c72a
MK
159 1. Confirm that their firmware port of the PRM infrastructure implemented in this package is functioning correctly.\r
160 2. Quickly get information about what PRM modules and handlers that are present on a given system.\r
161 3. Quickly test PRM handlers without booting into a full operating system.\r
162 4. Develop and exercise PRM handlers prior to the availability of an operating system that is PRM aware.\r
163\r
164Execute the application help command for detailed usage instructions and examples of how to use the application: \\r
165 ``PrmInfo -?``\r
166\r
167*Example Usage:*\r
168\r
f3c11224 169![PrmInfo Usage Example](https://raw.githubusercontent.com/tianocore/edk2-staging/PlatformRuntimeMechanism/PrmPkg/Application/PrmInfo/PrmInfo_Usage_Example.gif)\r
4348c72a 170\r
d2cb6e67
MK
171## PRM Module\r
172\r
f3c11224 173> ***Note***: You can find simple examples of PRM modules in the Samples directory of this package.\r
d10b8dc5
MK
174> [Samples/Readme.md](PrmPkg/Samples/Readme.md) has more information.\r
175\r
d2cb6e67 176By default, the EDK II implementation of UEFI does not allow images with the subsystem type\r
f3c11224 177`IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER` to be built with exports.\r
d2cb6e67 178\r
f3c11224 179```txt\r
d2cb6e67
MK
180ERROR - Linker #1294 from LINK : fatal exports and import libraries are not supported with /SUBSYSTEM:EFI_RUNTIME_DRIVER\r
181```\r
f3c11224 182\r
d2cb6e67
MK
183This can adjusted in the MSVC linker options.\r
184\r
f3c11224
MK
185The subsystem type is changed in the firmware build to allow the export table to be added but the subsystem type in the\r
186final image is still `0xC` (`EFI Runtime Driver`). This is important to allow the DXE dispatcher to use its standard\r
187image verification and loading algorithms to load the image into permanent memory during the DXE execution phase.\r
d2cb6e67 188\r
f3c11224 189All firmware-loaded PRM modules are loaded into a memory buffer of type `EfiRuntimeServicesCode`. This means the\r
d2cb6e67
MK
190operating system must preserve all PRM handler code and the buffer will be reflected in the UEFI memory map. The\r
191execution for invoking PRM handlers is the same as that required for UEFI Runtime Services, notably 4KiB or more of\r
f3c11224 192available stack space must be provided and the stack must be 16-byte aligned.\r
d2cb6e67 193\r
f3c11224 194***Note:*** Long term it is possible to similarly load the modules into a `EfiRuntimeServicesCode` buffer and perform\r
d2cb6e67
MK
195relocation fixups with a new EFI module type for PRM if desired. It was simply not done since it is not essential\r
196for this POC.\r
197\r
198Where possible, PRM module information is stored and generated using industry compiler tool chains. This is a key\r
199motivation behind using PE/COFF export tables to expose PRM module information and using a single PRM module binary\r
200definition consistent between firmware and OS load.\r
201\r
202### PRM Module Exports\r
f3c11224 203\r
a409f4b6
MK
204A PRM module must contain at least two exports: A PRM Module Export Descriptor and at least one PRM handler. Here's\r
205an example of an export table from a PRM module that has a single PRM handler:\r
d2cb6e67 206\r
f3c11224 207```txt\r
a409f4b6
MK
208 0000000000005000: 00 00 00 00 FF FF FF FF 00 00 00 00 3C 50 00 00 ............<P..\r
209 0000000000005010: 01 00 00 00 02 00 00 00 02 00 00 00 28 50 00 00 ............(P..\r
210 0000000000005020: 30 50 00 00 38 50 00 00 78 13 00 00 20 40 00 00 0P..8P..x... @..\r
211 0000000000005030: 5D 50 00 00 7C 50 00 00 00 00 01 00 50 72 6D 53 ]P..|P......PrmS\r
212 0000000000005040: 61 6D 70 6C 65 43 6F 6E 74 65 78 74 42 75 66 66 ampleContextBuff\r
213 0000000000005050: 65 72 4D 6F 64 75 6C 65 2E 64 6C 6C 00 44 75 6D erModule.dll.Dum\r
214 0000000000005060: 70 53 74 61 74 69 63 44 61 74 61 42 75 66 66 65 pStaticDataBuffe\r
215 0000000000005070: 72 50 72 6D 48 61 6E 64 6C 65 72 00 50 72 6D 4D rPrmHandler.PrmM\r
216 0000000000005080: 6F 64 75 6C 65 45 78 70 6F 72 74 44 65 73 63 72 oduleExportDescr\r
217 0000000000005090: 69 70 74 6F 72 00 iptor.\r
d2cb6e67
MK
218\r
219 00000000 characteristics\r
220 FFFFFFFF time date stamp\r
a409f4b6 221 0.00 version\r
d2cb6e67 222 1 ordinal base\r
a409f4b6
MK
223 2 number of functions\r
224 2 number of names\r
d2cb6e67
MK
225\r
226 ordinal hint RVA name\r
a409f4b6 227\r
d2cb6e67 228 1 0 00001378 DumpStaticDataBufferPrmHandler\r
a409f4b6
MK
229 2 1 00004020 PrmModuleExportDescriptor\r
230\r
d2cb6e67 231```\r
f3c11224 232\r
d2cb6e67 233### PRM Image Format\r
f3c11224 234\r
d2cb6e67
MK
235PRM modules are ultimately PE/COFF images. However, when packaged in firmware the PE/COFF image is placed into a\r
236Firmware File System (FFS) file. This is transparent to the operating system but done to better align with the typical\r
237packaging of PE32(+) images managed in the firmware binary image. In the dump of the PRM FV binary image shown earlier,\r
238the FFS sections placed by EDK II build tools ("DXE dependency", "User interface", "Version") that reside alongside the\r
239PE/COFF binary are shown. A PRM module can be placed into a firmware image as a pre-built PE/COFF binary or built\r
240during the firmware build process. In either case, the PE/COFF section is contained in a FFS file as shown in that\r
241image.\r
242\r
243### PRM Module Implementation\r
f3c11224 244\r
d2cb6e67
MK
245To simplify building the PRM Module Export Descriptor, a PRM module implementation can use the following macros to mark\r
246functions as PRM handlers. In this example, a PRM module registers three functions by name as PRM handlers with the\r
247associated GUIDs.\r
248\r
f3c11224 249```c\r
d2cb6e67
MK
250//\r
251// Register the PRM export information for this PRM Module\r
252//\r
253PRM_MODULE_EXPORT (\r
254 PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_1_GUID, PrmHandler1),\r
255 PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_2_GUID, PrmHandler2),\r
256 PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_N_GUID, PrmHandlerN)\r
257 );\r
258```\r
259\r
260`PRM_MODULE_EXPORT` take a variable-length argument list of `PRM_HANDLER_EXPORT_ENTRY` entries that each describe an\r
261individual PRM handler being exported for the module. Ultimately, this information is used to define the structure\r
262necessary to statically allocate the PRM Module Export Descriptor Structure (and its PRM Handler Export Descriptor\r
263substructures) in the image.\r
264\r
265Another required export for PRM modules is automatically provided in `PrmModule.h`, a header file that pulls together\r
266all the includes needed to author a PRM module. This export is `PRM_MODULE_UPDATE_LOCK_EXPORT`. By including,\r
267`PrmModule.h`, a PRM module has the `PRM_MODULE_UPDATE_LOCK_DESCRIPTOR` automatically exported.\r
268\r
269## PRM Handler Constraints\r
f3c11224 270\r
d2cb6e67
MK
271At this time, PRM handlers are restricted to a maximum identifier length of 128 characters. This is checked when using\r
272the `PRM_HANDLER_EXPORT` macro by using a static assert that reports a violation at build-time.\r
273\r
274PRM handlers are **not** allowed to use UEFI Runtime Services and should not rely upon any UEFI constructs. For the\r
275purposes of this POC, this is currently not explicitly enforced but should be in the final changes.\r