]> git.proxmox.com Git - mirror_edk2.git/blame - PrmPkg/Readme.md
PrmPkg: Add PlatformGuid
[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
8The `PrmPkg` maintained in this branch provides a single cohesive set of generic PRM functionality that is intended\r
9to be leveraged by platform firmware with minimal overhead to integrate PRM functionality in the firmware.\r
10\r
11## **IMPORTANT NOTE**\r
d10b8dc5 12> The code provided in this package and branch are for proof-of-concept purposes only. The code does not represent a\r
d2cb6e67
MK
13formal design and is not validated at product quality. The development of this feature is shared in the edk2-staging\r
14branch to simplify collaboration by allowing direct code contributions and early feedback throughout its development.\r
15\r
16## How to Build PrmPkg\r
17As noted earlier, resources in `PrmPkg` are intended to be referenced by a platform firmware so it can adopt support\r
18for PRM. In that case, the platform firmware should add the `PrmConfigDxe` and `PrmLoaderDxe` drivers to its DSC and\r
19FDF files so they are built in the platform firmware build and dispatched during its runtime. All that is left is to\r
20add individual PRM modules to the DSC and FDF. These can be built from source or included as binaries into the platform\r
21firmware flash map.\r
22\r
23### PrmPkg Standalone Build\r
24**All changes to `PrmPkg` must not regress the standalone package build**. Any time a change is made to `PrmPkg`, the\r
25package build must be tested. Since this is a forward looking package, to ease potential integration into the edk2\r
26project in the future, the build is tested against the tip of the master branch in the [edk2](https://github.com/tianocore/edk2)\r
27repository.\r
28\r
29To build `PrmPkg` as a standalone package:\r
301. 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
31\r
322. Clone the *master* branch on the edk2 repository locally \\r
33 ``git clone https://github.com/tianocore/edk2.git``\r
34\r
353. Clone the *PlatformRuntimeMechanism* branch on the edk2-staging repository locally \\r
36 ``git clone -b PlatformRuntimeMechanism --single-branch https://github.com/tianocore/edk2-staging.git``\r
37 > __*Note*__: The *--single-branch* argument is recommended since edk2-staging hosts many branches for completely\r
38 unrelated features. If you are just interested in PRM, this will avoid fetching all of the other branches.\r
39\r
404. Change to the edk2 workspace directory \\r
41 ``cd edk2``\r
42\r
435. Run *edksetup* to set local environment variables needed for build\r
44 * Windows:\r
45 * ``edksetup.bat``\r
46 * Linux:\r
47 * If you have not already built BaseTools:\r
48 * ``make -C BaseTools``\r
49 * ``. edksetup.sh``\r
50\r
516. Set the PACKAGES_PATH environment variable to include the directory path that contains `PrmPkg`\r
52 * Windows example:\r
53 * ``set PACKAGES_PATH=c:\src\edk2-staging``\r
54\r
557. Change to the edk2-staging workspace directory\r
56 * Example: ``cd ../edk2-staging``\r
57\r
588. Build PrmPkg \\r
59 ``build -p PrmPkg/PrmPkg.dsc -a IA32 -a X64``\r
60 > __*Note*__: Due to the way PRM modules are compiled with exports, **only building on Visual Studio compiler tool\r
61 chains is currently supported**.\r
62\r
63### Build Flags\r
64As PRM is a new feature at a proof-of-concept (POC) level of maturity, there's some changes to the normal build\r
65available as build flags. By default, if no flags are specified, the build is done with the currently expected plan of\r
66record (POR) configuration.\r
67\r
68The following list are the currently defined build flags (if any) that may be passed to the `build` command\r
69(e.g. -D FLAG=VALUE).\r
70\r
0797989c 71* NONE - No build flags are currently used.\r
e8467976
MK
72\r
73 Additional detail: The context buffer structure is defined in [PrmContextBuffer.h](PrmPkg/Include/PrmContextBuffer.h).\r
0797989c
MK
74 This structure is passed as the context buffer to PRM handlers. The structure actually passed to PRM handlers is\r
75 allocated and populated by the OS where it gets all the information to populate the context buffer from other structures.\r
e8467976 76\r
c040831c
MK
77### PRM Platform GUID\r
78**IMPORTANT**\r
79\r
80A configuration item that requires user attention is the PRM platform GUID. Each platform that uses PRM must be\r
81uniquely identifiable so that various instances of a PRM module can target the correct platform in PRM module updates.\r
82\r
83To apply a unique platform GUID set the following PCD to a unique value in your platform DSC file.\r
84 ``gPrmPkgTokenSpaceGuid.PcdPrmPlatformGuid``\r
85\r
86The default value assigned in [PrmPkg.dec](PrmPkg/PrmPkg.dec) is zero. By design, this is an invalid value that will\r
87cause an ASSERT if it is not updated.\r
88\r
d2cb6e67
MK
89## Overview\r
90At a high-level, PRM can be viewed from three levels of granularity:\r
91\r
921. PRM interface - Encompassing the entirety of firmware functionalities and data provided to OS runtime. Most\r
93 information is provided through ACPI tables to be agnostic to a UEFI implementation.\r
942. PRM module - An independently updatable package of PRM handlers. The PRM interface will be composed of multiple\r
95 PRM modules. This requirement allows for the separation of OEM and IHV PRM code, each of which can be serviced\r
96 independently.\r
973. PRM handler - The implementation/callback of a single PRM functionality as identified by a GUID.\r
98\r
99## Firmware Design\r
100The firmware has three key generic drivers to support PRM:\r
101\r
1021. A PRM Loader driver - Functionality is split across three phases:\r
103 1. Discover - Find all PRM modules in the firmware image made available by the platform firmware author.\r
104 * This phase includes verifying authenticity/integrity of the image, the image executable type, the export\r
105 table is present and the PRM Export Module Descriptor is present and valid.\r
106 2. Process - Convert PRM handler GUID to name mappings in the PRM Module Export Descriptor to PRM handler Name\r
107 to physical address mappings required to construct the PRM ACPI table.\r
108 3. Publish - Publish the PRM ACPI table using the information from the Process phase.\r
109\r
1102. A PRM Configuration driver - A generic driver responsible for processing PRM module configuration information\r
111 consumed through a `PRM_CONFIG_PROTOCOL` per PRM module instance. Therefore, the `PRM_CONFIG_PROTOCOL` serves\r
112 as the dynamic interface for this driver to process PRM module resources and prepare the module's data to be\r
113 configured properly for OS runtime.\r
114\r
1153. A PRM Module - Not a single driver but a user written PE/COFF image that follows the PRM module authoring process.\r
116 A PRM module groups together cohesive sets of PRM functionality into functions referred to as "PRM handlers".\r
117\r
118## PrmPkg Code Organization\r
119The package follows a standard EDK II style package format. The list below contains some notable areas to\r
120explore in the package:\r
121\r
122* [ACPI Table Definitions](PrmPkg/PrmLoaderDxe/PrmAcpiTable.h)\r
123* [Common Interface Definitions](PrmPkg/Include)\r
124* [PRM Config Driver](PrmPkg/PrmConfigDxe)\r
125* [PRM Loader Driver](PrmPkg/PrmLoaderDxe)\r
126* [Sample PRM Modules](PrmPkg/Samples)\r
127\r
128While the package does provide sample PRM modules to be used as a reference, actual PRM modules should not be\r
129maintained in PrmPkg. It is intended to only contain PRM infrastructure code and a few samples of how to use\r
130that infrastructure. The PrmPkg is meant to be used as-is by firmware that supports PRM. Any shortcomings that\r
131prevent the package from being used as-is should be addressed directly in PrmPkg.\r
132\r
4348c72a
MK
133## PRM Information UEFI Application\r
134A UEFI application is provided in this package called "PrmInfo" that allows a user to display and test PRM\r
135modules on their system.\r
136\r
137[Link to application source code](PrmPkg/Application/PrmInfo).\r
138\r
139This application is intended to be helpful during PRM enabling by allowing the user to:\r
140 1. Confirm that their firmware port of the PRM infrastructure implemented in this package is functioning correctly.\r
141 2. Quickly get information about what PRM modules and handlers that are present on a given system.\r
142 3. Quickly test PRM handlers without booting into a full operating system.\r
143 4. Develop and exercise PRM handlers prior to the availability of an operating system that is PRM aware.\r
144\r
145Execute the application help command for detailed usage instructions and examples of how to use the application: \\r
146 ``PrmInfo -?``\r
147\r
148*Example Usage:*\r
149\r
150![](PrmPkg/Application/PrmInfo/PrmInfo_Usage_Example.gif)\r
151\r
d2cb6e67
MK
152## PRM Module\r
153\r
d10b8dc5
MK
154> __*Note*__: You can find simple examples of PRM modules in the Samples directory of this package.\r
155> [Samples/Readme.md](PrmPkg/Samples/Readme.md) has more information.\r
156\r
d2cb6e67
MK
157By default, the EDK II implementation of UEFI does not allow images with the subsystem type\r
158IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER to be built with exports. \r
159\r
160```\r
161ERROR - Linker #1294 from LINK : fatal exports and import libraries are not supported with /SUBSYSTEM:EFI_RUNTIME_DRIVER\r
162```\r
163This can adjusted in the MSVC linker options.\r
164\r
165__For the purposes of this POC__, the subsystem type is changed in the firmware build to allow the export table to be\r
166added but the subsystem type in the final image is still 0xC (EFI Runtime Driver). This is important to allow the DXE\r
167dispatcher to use its standard image verification and loading algorithms to load the image into permanent memory during\r
168the DXE execution phase.\r
169\r
170All firmware-loaded PRM modules are loaded into a memory buffer of type EfiRuntimeServicesCode. This means the\r
171operating system must preserve all PRM handler code and the buffer will be reflected in the UEFI memory map. The\r
172execution for invoking PRM handlers is the same as that required for UEFI Runtime Services, notably 4KiB or more of\r
173available stack space must be provided and the stack must be 16-byte aligned. \r
174\r
175__*Note:*__ Long term it is possible to similarly load the modules into a EfiRuntimeServicesCode buffer and perform\r
176relocation fixups with a new EFI module type for PRM if desired. It was simply not done since it is not essential\r
177for this POC.\r
178\r
179Where possible, PRM module information is stored and generated using industry compiler tool chains. This is a key\r
180motivation behind using PE/COFF export tables to expose PRM module information and using a single PRM module binary\r
181definition consistent between firmware and OS load.\r
182\r
183### PRM Module Exports\r
a409f4b6
MK
184A PRM module must contain at least two exports: A PRM Module Export Descriptor and at least one PRM handler. Here's\r
185an example of an export table from a PRM module that has a single PRM handler:\r
d2cb6e67
MK
186\r
187```\r
a409f4b6
MK
188 0000000000005000: 00 00 00 00 FF FF FF FF 00 00 00 00 3C 50 00 00 ............<P..\r
189 0000000000005010: 01 00 00 00 02 00 00 00 02 00 00 00 28 50 00 00 ............(P..\r
190 0000000000005020: 30 50 00 00 38 50 00 00 78 13 00 00 20 40 00 00 0P..8P..x... @..\r
191 0000000000005030: 5D 50 00 00 7C 50 00 00 00 00 01 00 50 72 6D 53 ]P..|P......PrmS\r
192 0000000000005040: 61 6D 70 6C 65 43 6F 6E 74 65 78 74 42 75 66 66 ampleContextBuff\r
193 0000000000005050: 65 72 4D 6F 64 75 6C 65 2E 64 6C 6C 00 44 75 6D erModule.dll.Dum\r
194 0000000000005060: 70 53 74 61 74 69 63 44 61 74 61 42 75 66 66 65 pStaticDataBuffe\r
195 0000000000005070: 72 50 72 6D 48 61 6E 64 6C 65 72 00 50 72 6D 4D rPrmHandler.PrmM\r
196 0000000000005080: 6F 64 75 6C 65 45 78 70 6F 72 74 44 65 73 63 72 oduleExportDescr\r
197 0000000000005090: 69 70 74 6F 72 00 iptor.\r
d2cb6e67
MK
198\r
199 00000000 characteristics\r
200 FFFFFFFF time date stamp\r
a409f4b6 201 0.00 version\r
d2cb6e67 202 1 ordinal base\r
a409f4b6
MK
203 2 number of functions\r
204 2 number of names\r
d2cb6e67
MK
205\r
206 ordinal hint RVA name\r
a409f4b6 207\r
d2cb6e67 208 1 0 00001378 DumpStaticDataBufferPrmHandler\r
a409f4b6
MK
209 2 1 00004020 PrmModuleExportDescriptor\r
210\r
d2cb6e67
MK
211```\r
212### PRM Image Format\r
213PRM modules are ultimately PE/COFF images. However, when packaged in firmware the PE/COFF image is placed into a\r
214Firmware File System (FFS) file. This is transparent to the operating system but done to better align with the typical\r
215packaging of PE32(+) images managed in the firmware binary image. In the dump of the PRM FV binary image shown earlier,\r
216the FFS sections placed by EDK II build tools ("DXE dependency", "User interface", "Version") that reside alongside the\r
217PE/COFF binary are shown. A PRM module can be placed into a firmware image as a pre-built PE/COFF binary or built\r
218during the firmware build process. In either case, the PE/COFF section is contained in a FFS file as shown in that\r
219image.\r
220\r
221### PRM Module Implementation\r
222To simplify building the PRM Module Export Descriptor, a PRM module implementation can use the following macros to mark\r
223functions as PRM handlers. In this example, a PRM module registers three functions by name as PRM handlers with the\r
224associated GUIDs.\r
225\r
226```\r
227//\r
228// Register the PRM export information for this PRM Module\r
229//\r
230PRM_MODULE_EXPORT (\r
231 PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_1_GUID, PrmHandler1),\r
232 PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_2_GUID, PrmHandler2),\r
233 PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_N_GUID, PrmHandlerN)\r
234 );\r
235```\r
236\r
237`PRM_MODULE_EXPORT` take a variable-length argument list of `PRM_HANDLER_EXPORT_ENTRY` entries that each describe an\r
238individual PRM handler being exported for the module. Ultimately, this information is used to define the structure\r
239necessary to statically allocate the PRM Module Export Descriptor Structure (and its PRM Handler Export Descriptor\r
240substructures) in the image.\r
241\r
242Another required export for PRM modules is automatically provided in `PrmModule.h`, a header file that pulls together\r
243all the includes needed to author a PRM module. This export is `PRM_MODULE_UPDATE_LOCK_EXPORT`. By including,\r
244`PrmModule.h`, a PRM module has the `PRM_MODULE_UPDATE_LOCK_DESCRIPTOR` automatically exported.\r
245\r
246## PRM Handler Constraints\r
247At this time, PRM handlers are restricted to a maximum identifier length of 128 characters. This is checked when using\r
248the `PRM_HANDLER_EXPORT` macro by using a static assert that reports a violation at build-time.\r
249\r
250PRM handlers are **not** allowed to use UEFI Runtime Services and should not rely upon any UEFI constructs. For the\r
251purposes of this POC, this is currently not explicitly enforced but should be in the final changes.\r