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