microsoft/mu_tiano_platforms
Publicmirrored fromhttps://github.com/microsoft/mu_tiano_platformsAvailable
docs/TPM/TpmQemuQ35.md
420lines · modecode
| 1 | # TPM on QEMU Q35 |
| 2 | |
| 3 | This document describes the TPM 2.0 architecture for the QEMU Q35 platform. Q35 uses a |
| 4 | direct CRB/FIFO path between firmware and the TPM device. |
| 5 | |
| 6 | ## Table of Contents |
| 7 | |
| 8 | - [Requirements](#requirements) |
| 9 | - [Build Configuration](#build-configuration) |
| 10 | - [Platform Memory Layout](#platform-memory-layout) |
| 11 | - [Architecture Overview](#architecture-overview) |
| 12 | - [TPM Device Library Stack](#tpm-device-library-stack) |
| 13 | - [Hash Library Architecture](#hash-library-architecture) |
| 14 | - [Physical Presence Interface](#physical-presence-interface) |
| 15 | - [swtpm Setup](#swtpm-setup) |
| 16 | - [Communication Flow](#communication-flow) |
| 17 | - [PCDs Reference](#pcds-reference) |
| 18 | |
| 19 | ## Requirements |
| 20 | |
| 21 | | Requirement | Notes | |
| 22 | | ------------- | ------- | |
| 23 | | **Host OS** | Linux (native) or **WSL** on Windows. Native Windows is not supported. | |
| 24 | | **swtpm** | TPM 2.0 emulator. Install via your distro's package manager (e.g. `apt install swtpm swtpm-tools`). | |
| 25 | | **QEMU** | Built with `tpm-tis` device support (standard upstream QEMU includes this). | |
| 26 | | **Build host** | Same Linux/WSL environment used to run `stuart_build` and launch QEMU. | |
| 27 | |
| 28 | See [swtpm Setup](#swtpm-setup) for the full setup commands. |
| 29 | |
| 30 | ## Build Configuration |
| 31 | |
| 32 | The TPM is disabled by default. To enable it, set `BLD_*_TPM_ENABLE=TRUE` on the command line or in a |
| 33 | BuildConfig.conf file placed at the root level of the repo: |
| 34 | |
| 35 | ```bash |
| 36 | stuart_build -c Platforms/QemuQ35Pkg/PlatformBuild.py --FlashRom \ |
| 37 | BLD_*_TPM_ENABLE=TRUE \ |
| 38 | ``` |
| 39 | |
| 40 | The following defines control TPM behavior in `QemuQ35Pkg.dsc`: |
| 41 | |
| 42 | | Define | Default | Purpose | |
| 43 | | -------- | --------- | --------- | |
| 44 | | `TPM_ENABLE` | `FALSE` | Master switch. Guards all TPM drivers, libraries, and PCDs. | |
| 45 | | `TPM_CONFIG_ENABLE` | `FALSE` | Enables `Tcg2ConfigDxe` HII configuration UI. | |
| 46 | | `TPM_REPLAY_ENABLED` | `FALSE` | Enables TPM Replay overrides (uses `TpmTestingPkg` variants of Tcg2Dxe and DxeTpm2MeasureBootLib). | |
| 47 | |
| 48 | ## Platform Memory Layout |
| 49 | |
| 50 | Q35 uses the standard x86 TPM memory-mapped I/O region: |
| 51 | |
| 52 | | Region | Address | Size | Interface | |
| 53 | | -------- | --------- | ------ | ----------- | |
| 54 | | TPM TIS/CRB | `0xFED40000` | 0x5000 (20 KiB) | CRB or TIS (auto-detected) | |
| 55 | |
| 56 | The firmware communicates directly with the TPM device via MMIO, and QEMU forwards the |
| 57 | I/O to swtpm over a Unix socket. |
| 58 | |
| 59 | The base address comes from the SecurityPkg package declaration default |
| 60 | (`PcdTpmBaseAddress = 0xFED40000`). The Q35 DSC does not override it explicitly. The |
| 61 | `Tcg2ConfigPei` driver detects the TPM at this address during PEI. |
| 62 | |
| 63 | ## Architecture Overview |
| 64 | |
| 65 | ```text |
| 66 | ┌──────────────────────────────────────────────────────────────────────────────────┐ |
| 67 | │ UEFI Firmware (x86_64) │ |
| 68 | │ │ |
| 69 | │ ┌─── PEI Phase ──────────────────────────────────────────────────────────────┐ │ |
| 70 | │ │ │ │ |
| 71 | │ │ Tcg2ConfigPei │ │ |
| 72 | │ │ │ 1. Detect TPM 1.2 vs 2.0 at 0xFED40000 │ │ |
| 73 | │ │ │ 2. Set PcdTpmInstanceGuid │ │ |
| 74 | │ │ ▼ │ │ |
| 75 | │ │ HashLibBaseCryptoRouterPei + HashInstanceLib* │ │ |
| 76 | │ │ │ 1. Constructors register each enabled hash algorithm │ │ |
| 77 | │ │ │ 2. Filtered by PcdTpm2HashMask → PcdTcg2HashAlgorithmBitmap │ │ |
| 78 | │ │ ▼ │ │ |
| 79 | │ │ Tcg2Pei │ │ |
| 80 | │ │ │ 1. Tpm2RequestUseTpm() │ │ |
| 81 | │ │ │ 2. Tpm2Startup(TPM_SU_CLEAR) │ │ |
| 82 | │ │ │ 3. SyncPcrAllocationsAndPcrMask() │ │ |
| 83 | │ │ │ 4. Tpm2SelfTest() │ │ |
| 84 | │ │ │ 5. Measure firmware volumes (CRTM) into PCR[0-7] │ │ |
| 85 | │ │ │ 6. Install TpmInitializedPpi │ │ |
| 86 | │ └────┼───────────────────────────────────────────────────────────────────────┘ │ |
| 87 | │ ▼ │ |
| 88 | │ ┌─── DXE Phase ──────────────────────────────────────────────────────────────┐ │ |
| 89 | │ │ │ │ |
| 90 | │ │ HashLibBaseCryptoRouterDxe + HashInstanceLib* │ │ |
| 91 | │ │ │ 1. Constructors register each enabled hash algorithm │ │ |
| 92 | │ │ │ 2. Filtered by PcdTpm2HashMask → PcdTcg2HashAlgorithmBitmap │ │ |
| 93 | │ │ ▼ │ │ |
| 94 | │ │ Tcg2Dxe │ │ |
| 95 | │ │ │ 1. Verify PcdTpmInstanceGuid is TPM 2.0 │ │ |
| 96 | │ │ │ 2. Verify no TpmErrorHob is present │ │ |
| 97 | │ │ │ 3. Tpm2RequestUseTpm() │ │ |
| 98 | │ │ │ 4. Query TPM capabilities │ │ |
| 99 | │ │ │ ├── Manufacturer │ │ |
| 100 | │ │ │ ├── Firmware version │ │ |
| 101 | │ │ │ └── Max cmd/resp size │ │ |
| 102 | │ │ │ 5. Get supported/active PCR banks filtered by → HashAlgorithmBitmap │ │ |
| 103 | │ │ │ 6. Decide SupportedEventLogs (TCG_1_2 only if SHA1 active) │ │ |
| 104 | │ │ │ 7. SetupEventLog │ │ |
| 105 | │ │ │ ├── Allocate log area(s) │ │ |
| 106 | │ │ │ └── Acquire and log pre-DXE HOB(s) │ │ |
| 107 | │ │ │ 8. Register events │ │ |
| 108 | │ │ │ ├── ReadyToBoot │ │ |
| 109 | │ │ │ ├── ExitBootServices │ │ |
| 110 | │ │ │ └── ExitBootServices Failed │ │ |
| 111 | │ │ │ 9. Register protocol notifies │ │ |
| 112 | │ │ │ ├── VariableWriteArch (SecureBoot) │ │ |
| 113 | │ │ │ └── ResetNotification (TPM shutdown) │ │ |
| 114 | │ │ │ 10. Install Tcg2Protocol │ │ |
| 115 | │ └────┼───────────────────────────────────────────────────────────────────────┘ │ |
| 116 | │ ▼ │ |
| 117 | │ ┌─── BDS Phase ──────────────────────────────────────────────────────────────┐ │ |
| 118 | │ │ │ │ |
| 119 | │ │ DeviceBootManagerAfterConsole │ │ |
| 120 | │ │ │ 1. Tcg2PhysicalPresenceLibProcessRequest (NULL) │ │ |
| 121 | │ │ │ 2. Process any pending PP request before shell launch │ │ |
| 122 | │ │ │ 3. Create TCG2_PHYSICAL_PRESENCE_VARIABLE if it doesn't exist │ │ |
| 123 | │ └────┼───────────────────────────────────────────────────────────────────────┘ │ |
| 124 | │ ▼ │ |
| 125 | │ ┌─── UEFI Shell ─────────────────────────────────────────────────────────────┐ │ |
| 126 | │ │ │ │ |
| 127 | │ │ UEFI Shell / OS / TpmShellApp │ │ |
| 128 | │ │ │ 1. gBS->LocateProtocol(&gEfiTcg2ProtocolGuid) │ │ |
| 129 | │ │ │ 2. Tcg2Protocol->GetCapability / SetActivePcrBanks / etc. │ │ |
| 130 | │ └────┼───────────────────────────────────────────────────────────────────────┘ │ |
| 131 | │ ▼ │ |
| 132 | │ Tpm2DeviceLibDTpm ─ direct MMIO reads/writes to 0xFED40000 │ |
| 133 | │ │ │ |
| 134 | ├───────┼──────────────────────────────────────────────────────────────────────────┤ |
| 135 | │ ▼ │ |
| 136 | │ QEMU TPM TIS device (-device tpm-tis,tpmdev=tpm0) │ |
| 137 | │ │ │ |
| 138 | │ ▼ │ |
| 139 | │ Unix socket ─ swtpm process (--tpm2) │ |
| 140 | └──────────────────────────────────────────────────────────────────────────────────┘ |
| 141 | ``` |
| 142 | |
| 143 | ## TPM Device Library Stack |
| 144 | |
| 145 | Q35 uses two different patterns for accessing the TPM, depending on the firmware phase: |
| 146 | |
| 147 | ### PEI Phase: Direct MMIO (`Tpm2DeviceLibDTpm`) |
| 148 | |
| 149 | ```text |
| 150 | Tcg2Pei |
| 151 | │ Tpm2SubmitCommand() |
| 152 | ▼ |
| 153 | Tpm2DeviceLibDTpm |
| 154 | │ Auto-detects CRB vs TIS vs FIFO via InterfaceId register |
| 155 | │ DTpm2SubmitCommand() dispatches: |
| 156 | │ CRB → PtpCrbTpmCommand() |
| 157 | │ FIFO → Tpm2TisTpmCommand() |
| 158 | │ TIS → Tpm2TisTpmCommand() |
| 159 | ▼ |
| 160 | Direct MMIO to 0xFED40000 |
| 161 | ``` |
| 162 | |
| 163 | `Tpm2DeviceLibDTpm` reads the `InterfaceId` register at `PcdTpmBaseAddress + 0x30` to |
| 164 | determine the interface type. QEMU's `tpm-tis` device presents a TIS/FIFO interface. |
| 165 | |
| 166 | ### DXE Phase: Router Pattern (`Tpm2DeviceLibRouter`) |
| 167 | |
| 168 | ```text |
| 169 | Tcg2Dxe |
| 170 | │ Tpm2SubmitCommand() |
| 171 | ▼ |
| 172 | Tpm2DeviceLibRouterDxe |
| 173 | │ Delegates to registered TPM2_DEVICE_INTERFACE |
| 174 | ▼ |
| 175 | Tpm2InstanceLibDTpm (constructor registers with router) |
| 176 | │ DTpm2SubmitCommand() — same dispatch as PEI |
| 177 | ▼ |
| 178 | Direct MMIO to 0xFED40000 |
| 179 | ``` |
| 180 | |
| 181 | The router pattern exists to support future scenarios where multiple TPM device types |
| 182 | could coexist. The router accepts only the instance whose `ProviderGuid` matches |
| 183 | `PcdTpmInstanceGuid`. |
| 184 | |
| 185 | ### Other DXE Drivers: TCG2 Protocol (`Tpm2DeviceLibTcg2`) |
| 186 | |
| 187 | Most DXE drivers that need TPM access use `Tpm2DeviceLibTcg2`, which goes through the |
| 188 | TCG2 Protocol rather than direct MMIO. Only Tcg2Dxe itself uses `Tpm2DeviceLibRouter` |
| 189 | with direct MMIO. |
| 190 | |
| 191 | ### CRB Register Layout |
| 192 | |
| 193 | If the TPM presents a CRB interface (as opposed to TIS/FIFO), the register layout is |
| 194 | defined by the TCG PC Client Platform TPM Profile (PTP) specification. See: |
| 195 | |
| 196 | - [TCG PC Client Platform TPM Profile (PTP) Specification][ptp-spec] — |
| 197 | *Section 6 "Command Response Buffer Interface"* describes `LocalityState`, |
| 198 | `LocalityControl`, `InterfaceId`, `CrbControlRequest`, `CrbControlStart`, |
| 199 | `CrbControlCommand*`/`CrbControlResponse*`, and the shared `CrbDataBuffer`. |
| 200 | |
| 201 | The key register for this platform is `InterfaceId` at `PcdTpmBaseAddress + 0x30`, which |
| 202 | `Tpm2DeviceLibDTpm` reads to decide between CRB and TIS/FIFO dispatch paths. |
| 203 | |
| 204 | ### TIS Register Layout |
| 205 | |
| 206 | QEMU's `tpm-tis` device presents a TIS (TPM Interface Specification) / FIFO interface. |
| 207 | The register layout is defined by: |
| 208 | |
| 209 | - [TCG PC Client Specific TPM Interface Specification (TIS)][tis-spec] — |
| 210 | defines `Access`, `IntEnable`/`IntVector`, `STS` (with `commandReady`, `tpmGo`, |
| 211 | `dataAvail`, `burstCount`), `DataFifo`, and the `Vid`/`Did`/`Rid` identification |
| 212 | registers. |
| 213 | |
| 214 | The TIS flow uses `BurstCount` from the STS register to pace reads and writes through |
| 215 | the `DataFifo` register, one burst at a time. |
| 216 | |
| 217 | [ptp-spec]: https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/ |
| 218 | [tis-spec]: https://trustedcomputinggroup.org/resource/pc-client-work-group-pc-client-specific-tpm-interface-specification-tis/ |
| 219 | |
| 220 | ## Hash Library Architecture |
| 221 | |
| 222 | Tcg2Dxe uses `HashLibBaseCryptoRouterDxe` while Tcg2Pei uses `HashLibBaseCryptoRouterPei` |
| 223 | with all hash instance libraries included. |
| 224 | |
| 225 | ### Registration Flow |
| 226 | |
| 227 | 1. `HashLibBaseCryptoRouterConstructor` resets `PcdTcg2HashAlgorithmBitmap` to 0. |
| 228 | 2. Each `HashInstanceLib` constructor calls `RegisterHashInterfaceLib()`. |
| 229 | 3. `RegisterHashInterfaceLib()` checks the algorithm against `PcdTpm2HashMask` (`0x02` = |
| 230 | SHA256 only). Algorithms not in the mask return `EFI_UNSUPPORTED`. |
| 231 | |
| 232 | ### Hash Algorithm Bitmask Values |
| 233 | |
| 234 | The bit positions used in `PcdTpm2HashMask`, `PcdTcg2HashAlgorithmBitmap`, and the |
| 235 | `EFI_TCG2_BOOT_SERVICE_CAPABILITY.HashAlgorithmBitmap` field are defined by the EFI |
| 236 | TCG2 protocol and the TCG algorithm registry: |
| 237 | |
| 238 | - [UEFI TCG2 Protocol Specification][tcg2-proto] — see `EFI_TCG2_BOOT_HASH_ALG_*` |
| 239 | (`SHA1` = BIT0, `SHA256` = BIT1, `SHA384` = BIT2, `SHA512` = BIT3, `SM3_256` = BIT4). |
| 240 | - [TCG Algorithm Registry][tcg-algreg] — canonical list of TPM hash algorithm IDs. |
| 241 | |
| 242 | For this platform, `PcdTpm2HashMask = 0x02` enables SHA256 only. |
| 243 | |
| 244 | [tcg2-proto]: https://trustedcomputinggroup.org/resource/tcg-efi-protocol-specification/ |
| 245 | [tcg-algreg]: https://trustedcomputinggroup.org/resource/tcg-algorithm-registry/ |
| 246 | |
| 247 | ### Filtering Chain |
| 248 | |
| 249 | ```text |
| 250 | PcdTpm2HashMask (0x02) |
| 251 | │ |
| 252 | ▼ |
| 253 | RegisterHashInterfaceLib() ── gates which HashInstanceLibs register |
| 254 | │ |
| 255 | ▼ |
| 256 | PcdTcg2HashAlgorithmBitmap ── result of all successful registrations |
| 257 | │ |
| 258 | ▼ |
| 259 | Tcg2Dxe intersects with TPM-reported capabilities |
| 260 | │ |
| 261 | ▼ |
| 262 | Final ActivePcrBanks / HashAlgorithmBitmap in EFI_TCG2_BOOT_SERVICE_CAPABILITY |
| 263 | ``` |
| 264 | |
| 265 | ## Physical Presence Interface |
| 266 | |
| 267 | ### Library Selection |
| 268 | |
| 269 | | `TPM_ENABLE` | Library | Behavior | |
| 270 | | -------------- | --------- | ---------- | |
| 271 | | `FALSE` | `Tcg2PhysicalPresenceLibNull` | All functions stubbed | |
| 272 | | `TRUE` | `DxeTcg2PhysicalPresenceMinimumLib` | Auto-confirms Clear; rejects all other operations | |
| 273 | |
| 274 | The MinimumLib implementation: |
| 275 | |
| 276 | - **Auto-confirms** TPM Clear operations without user prompting. |
| 277 | - **Rejects** SET_PCR_BANKS, LOG_ALL_DIGESTS, and other operations with |
| 278 | `TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE`. |
| 279 | - Does **not** create or use `TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE`. |
| 280 | |
| 281 | ### ProcessRequest in BDS |
| 282 | |
| 283 | `Tcg2PhysicalPresenceLibProcessRequest()` is invoked from the platform's |
| 284 | `DeviceBootManagerLib` during `DeviceBootManagerAfterConsole()`, before the shell |
| 285 | launches. It: |
| 286 | |
| 287 | 1. Reads the `Tcg2PhysicalPresence` NV variable (creates it if missing). |
| 288 | 2. Executes any pending PP request stored in the variable. |
| 289 | 3. Stores the result back for `ReturnOperationResponseToOsFunction()` to report. |
| 290 | |
| 291 | ## swtpm Setup |
| 292 | |
| 293 | ### Installation |
| 294 | |
| 295 | swtpm requires Unix sockets, so it must run in a Linux environment. On Windows, |
| 296 | use [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) (Windows |
| 297 | Subsystem for Linux). |
| 298 | |
| 299 | ```bash |
| 300 | # Windows (from a WSL terminal) |
| 301 | wsl --install # if WSL is not yet enabled |
| 302 | wsl # enter the WSL environment |
| 303 | |
| 304 | # Ubuntu/Debian (native or WSL) |
| 305 | sudo apt install swtpm swtpm-tools |
| 306 | |
| 307 | # Fedora |
| 308 | sudo dnf install swtpm swtpm-tools |
| 309 | ``` |
| 310 | |
| 311 | ### Manual Setup |
| 312 | |
| 313 | Create the TPM state directory and start swtpm before launching QEMU: |
| 314 | |
| 315 | ```bash |
| 316 | mkdir -p /tmp/mytpm1 |
| 317 | swtpm socket \ |
| 318 | --tpmstate dir=/tmp/mytpm1 \ |
| 319 | --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ |
| 320 | --tpm2 \ |
| 321 | --log level=20 |
| 322 | ``` |
| 323 | |
| 324 | ### Automatic Setup (QemuRunner) |
| 325 | |
| 326 | When `SWTPM_ENABLE=TRUE`, `QemuRunner.py` automatically starts swtpm in a background thread |
| 327 | before launching QEMU. The swtpm state directory is set to `BUILD_OUTPUT_BASE` and the |
| 328 | Unix socket is placed at `{BUILD_OUTPUT_BASE}/swtpm-sock`: |
| 329 | |
| 330 | ```python |
| 331 | # Platforms/QemuQ35Pkg/Plugins/QemuRunner/QemuRunner.py |
| 332 | @staticmethod |
| 333 | def RunSwTpmThread(tpm_dir, tpm_sock): |
| 334 | """Runs TPM in a separate thread""" |
| 335 | tpm_cmd = "swtpm" |
| 336 | tpm_args = f"socket --tpmstate dir={tpm_dir} --ctrl type=unixio,path={tpm_sock} --tpm2 --log level=1" |
| 337 | ``` |
| 338 | |
| 339 | The thread is launched before QEMU starts and joined after QEMU exits. Note that the SWTPM |
| 340 | is enabled by default. You can disable it by setting `SWTPM_ENABLE=FALSE` from the command |
| 341 | line or in the BuildConfig.conf file. |
| 342 | |
| 343 | ### QEMU Arguments |
| 344 | |
| 345 | When `SWTPM_ENABLE=TRUE`, `QemuRunner.py` adds the following to the QEMU command line |
| 346 | (with the socket path under `BUILD_OUTPUT_BASE`): |
| 347 | |
| 348 | ```text |
| 349 | -chardev socket,id=chrtpm,path={BUILD_OUTPUT_BASE}/swtpm-sock |
| 350 | -tpmdev emulator,id=tpm0,chardev=chrtpm |
| 351 | -device tpm-tis,tpmdev=tpm0 |
| 352 | ``` |
| 353 | |
| 354 | The `-device tpm-tis` argument is Q35-specific — it attaches a TIS-compatible TPM device |
| 355 | to the Q35 chipset at the standard address `0xFED40000`. |
| 356 | |
| 357 | ## Communication Flow |
| 358 | |
| 359 | Complete path from a shell application to swtpm: |
| 360 | |
| 361 | ```text |
| 362 | TpmShellApp (UEFI Shell) |
| 363 | │ gBS->LocateProtocol(&gEfiTcg2ProtocolGuid) |
| 364 | │ Tcg2Protocol->SetActivePcrBanks(0x02) |
| 365 | ▼ |
| 366 | Tcg2Dxe (EFI_TCG2_PROTOCOL) |
| 367 | │ Validates bank mask against HashAlgorithmBitmap |
| 368 | │ Calls Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction() |
| 369 | │ ├── MinimumLib: rejects SET_PCR_BANKS → returns EFI_UNSUPPORTED |
| 370 | │ └── MinimumLib: NO_ACTION (already-active) → writes NV variable → EFI_SUCCESS |
| 371 | ▼ |
| 372 | Tpm2CommandLib (for direct TPM commands like GetCapability) |
| 373 | │ Serializes TPM2 command structure into byte buffer |
| 374 | │ Calls Tpm2SubmitCommand(cmdBuffer, cmdSize, rspBuffer, &rspSize) |
| 375 | ▼ |
| 376 | Tpm2DeviceLibRouter → Tpm2InstanceLibDTpm |
| 377 | │ DTpm2SubmitCommand() — detects interface type (TIS on QEMU) |
| 378 | ▼ |
| 379 | Tpm2TisTpmCommand (Tpm2Tis.c) |
| 380 | │ 1. TisPcPrepareCommand: set TIS_PC_STS_COMMAND_READY |
| 381 | │ 2. Write command bytes to DataFifo (paced by BurstCount) |
| 382 | │ 3. Set TIS_PC_STS_GO to start execution |
| 383 | │ 4. Poll STS for DataAvail (90 second timeout) |
| 384 | │ 5. Read response header from DataFifo |
| 385 | │ 6. Read remaining response bytes (paced by BurstCount) |
| 386 | │ 7. Set TIS_PC_STS_READY (return to idle) |
| 387 | ▼ |
| 388 | MMIO to 0xFED40000 (QEMU TIS device) |
| 389 | │ |
| 390 | ▼ |
| 391 | QEMU tpm-tis device ──── Unix socket ──── swtpm process |
| 392 | ``` |
| 393 | |
| 394 | ## PCDs Reference |
| 395 | |
| 396 | ### Required PCDs (set when TPM_ENABLE=TRUE) |
| 397 | |
| 398 | | PCD | Value | Type | Purpose | |
| 399 | | ----- | ------- | ------ | --------- | |
| 400 | | `PcdTpmBaseAddress` | `0xFED40000` (package default) | DynamicDefault | TPM TIS/CRB MMIO base address | |
| 401 | | `PcdTpm2HashMask` | `0x02` | DynamicDefault | Hash algorithm filter (SHA256 only) | |
| 402 | | `PcdTpmInstanceGuid` | `gEfiTpmDeviceInstanceTpm20DtpmGuid` | DynamicDefault | Selects discrete TPM 2.0 device type (set by Tcg2ConfigPei at runtime) | |
| 403 | | `PcdTpm2AcpiTableRev` | `4` | DynamicHii | ACPI TPM2 table revision | |
| 404 | | `PcdUserPhysicalPresence` | `FALSE` | FixedAtBuild | No physical user presence assertion | |
| 405 | |
| 406 | ### Memory Type PCDs |
| 407 | |
| 408 | | PCD | Value (pages) | Purpose | |
| 409 | | ----- | --------------- | --------- | |
| 410 | | `PcdMemoryTypeEfiACPIReclaimMemory` | `0x2B` (43) | Includes TPM ACPI tables | |
| 411 | | `PcdMemoryTypeEfiACPIMemoryNVS` | `0x80` (128) | ACPI NVS memory | |
| 412 | | `PcdMemoryTypeEfiReservedMemoryType` | `0x510` | Reserved memory | |
| 413 | | `PcdMemoryTypeEfiRuntimeServicesCode` | `0x100` | Runtime code | |
| 414 | | `PcdMemoryTypeEfiRuntimeServicesData` | `0x700` | Runtime data | |
| 415 | |
| 416 | ### Conditional PCDs (TPM_CONFIG_ENABLE=TRUE) |
| 417 | |
| 418 | | PCD | Value | Purpose | |
| 419 | | ----- | ------- | --------- | |
| 420 | | `PcdTcgPhysicalPresenceInterfaceVer` | `"1.3"` | TCG PPI specification version reported to OS | |
| 421 | |