microsoft/mu_tiano_platforms

Public

mirrored fromhttps://github.com/microsoft/mu_tiano_platformsAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
main

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

docs/TPM/TpmQemuQ35.md

420lines · modecode

1# TPM on QEMU Q35
2
3This document describes the TPM 2.0 architecture for the QEMU Q35 platform. Q35 uses a
4direct 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
28See [swtpm Setup](#swtpm-setup) for the full setup commands.
29
30## Build Configuration
31
32The TPM is disabled by default. To enable it, set `BLD_*_TPM_ENABLE=TRUE` on the command line or in a
33BuildConfig.conf file placed at the root level of the repo:
34
35```bash
36stuart_build -c Platforms/QemuQ35Pkg/PlatformBuild.py --FlashRom \
37 BLD_*_TPM_ENABLE=TRUE \
38```
39
40The 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
50Q35 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
56The firmware communicates directly with the TPM device via MMIO, and QEMU forwards the
57I/O to swtpm over a Unix socket.
58
59The 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
145Q35 uses two different patterns for accessing the TPM, depending on the firmware phase:
146
147### PEI Phase: Direct MMIO (`Tpm2DeviceLibDTpm`)
148
149```text
150Tcg2Pei
151 │ Tpm2SubmitCommand()
152
153Tpm2DeviceLibDTpm
154 │ Auto-detects CRB vs TIS vs FIFO via InterfaceId register
155 │ DTpm2SubmitCommand() dispatches:
156 │ CRB → PtpCrbTpmCommand()
157 │ FIFO → Tpm2TisTpmCommand()
158 │ TIS → Tpm2TisTpmCommand()
159
160Direct MMIO to 0xFED40000
161```
162
163`Tpm2DeviceLibDTpm` reads the `InterfaceId` register at `PcdTpmBaseAddress + 0x30` to
164determine the interface type. QEMU's `tpm-tis` device presents a TIS/FIFO interface.
165
166### DXE Phase: Router Pattern (`Tpm2DeviceLibRouter`)
167
168```text
169Tcg2Dxe
170 │ Tpm2SubmitCommand()
171
172Tpm2DeviceLibRouterDxe
173 │ Delegates to registered TPM2_DEVICE_INTERFACE
174
175Tpm2InstanceLibDTpm (constructor registers with router)
176 │ DTpm2SubmitCommand() — same dispatch as PEI
177
178Direct MMIO to 0xFED40000
179```
180
181The router pattern exists to support future scenarios where multiple TPM device types
182could coexist. The router accepts only the instance whose `ProviderGuid` matches
183`PcdTpmInstanceGuid`.
184
185### Other DXE Drivers: TCG2 Protocol (`Tpm2DeviceLibTcg2`)
186
187Most DXE drivers that need TPM access use `Tpm2DeviceLibTcg2`, which goes through the
188TCG2 Protocol rather than direct MMIO. Only Tcg2Dxe itself uses `Tpm2DeviceLibRouter`
189with direct MMIO.
190
191### CRB Register Layout
192
193If the TPM presents a CRB interface (as opposed to TIS/FIFO), the register layout is
194defined 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
201The 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
206QEMU's `tpm-tis` device presents a TIS (TPM Interface Specification) / FIFO interface.
207The 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
214The TIS flow uses `BurstCount` from the STS register to pace reads and writes through
215the `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
222Tcg2Dxe uses `HashLibBaseCryptoRouterDxe` while Tcg2Pei uses `HashLibBaseCryptoRouterPei`
223with all hash instance libraries included.
224
225### Registration Flow
226
2271. `HashLibBaseCryptoRouterConstructor` resets `PcdTcg2HashAlgorithmBitmap` to 0.
2282. Each `HashInstanceLib` constructor calls `RegisterHashInterfaceLib()`.
2293. `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
234The bit positions used in `PcdTpm2HashMask`, `PcdTcg2HashAlgorithmBitmap`, and the
235`EFI_TCG2_BOOT_SERVICE_CAPABILITY.HashAlgorithmBitmap` field are defined by the EFI
236TCG2 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
242For 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
250PcdTpm2HashMask (0x02)
251
252
253RegisterHashInterfaceLib() ── gates which HashInstanceLibs register
254
255
256PcdTcg2HashAlgorithmBitmap ── result of all successful registrations
257
258
259Tcg2Dxe intersects with TPM-reported capabilities
260
261
262Final 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
274The 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
285launches. It:
286
2871. Reads the `Tcg2PhysicalPresence` NV variable (creates it if missing).
2882. Executes any pending PP request stored in the variable.
2893. Stores the result back for `ReturnOperationResponseToOsFunction()` to report.
290
291## swtpm Setup
292
293### Installation
294
295swtpm requires Unix sockets, so it must run in a Linux environment. On Windows,
296use [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) (Windows
297Subsystem for Linux).
298
299```bash
300# Windows (from a WSL terminal)
301wsl --install # if WSL is not yet enabled
302wsl # enter the WSL environment
303
304# Ubuntu/Debian (native or WSL)
305sudo apt install swtpm swtpm-tools
306
307# Fedora
308sudo dnf install swtpm swtpm-tools
309```
310
311### Manual Setup
312
313Create the TPM state directory and start swtpm before launching QEMU:
314
315```bash
316mkdir -p /tmp/mytpm1
317swtpm 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
326When `SWTPM_ENABLE=TRUE`, `QemuRunner.py` automatically starts swtpm in a background thread
327before launching QEMU. The swtpm state directory is set to `BUILD_OUTPUT_BASE` and the
328Unix socket is placed at `{BUILD_OUTPUT_BASE}/swtpm-sock`:
329
330```python
331# Platforms/QemuQ35Pkg/Plugins/QemuRunner/QemuRunner.py
332@staticmethod
333def 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
339The thread is launched before QEMU starts and joined after QEMU exits. Note that the SWTPM
340is enabled by default. You can disable it by setting `SWTPM_ENABLE=FALSE` from the command
341line or in the BuildConfig.conf file.
342
343### QEMU Arguments
344
345When `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
354The `-device tpm-tis` argument is Q35-specific — it attaches a TIS-compatible TPM device
355to the Q35 chipset at the standard address `0xFED40000`.
356
357## Communication Flow
358
359Complete path from a shell application to swtpm:
360
361```text
362TpmShellApp (UEFI Shell)
363 │ gBS->LocateProtocol(&gEfiTcg2ProtocolGuid)
364 │ Tcg2Protocol->SetActivePcrBanks(0x02)
365
366Tcg2Dxe (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
372Tpm2CommandLib (for direct TPM commands like GetCapability)
373 │ Serializes TPM2 command structure into byte buffer
374 │ Calls Tpm2SubmitCommand(cmdBuffer, cmdSize, rspBuffer, &rspSize)
375
376Tpm2DeviceLibRouter → Tpm2InstanceLibDTpm
377 │ DTpm2SubmitCommand() — detects interface type (TIS on QEMU)
378
379Tpm2TisTpmCommand (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
388MMIO to 0xFED40000 (QEMU TIS device)
389
390
391QEMU 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