# McBankErrorInjection Module (index 0225)

## Overview

SMM driver that injects Machine Check Bank (MCBANK) error records into the UEFI
variable store for RAS (Reliability, Availability, Serviceability) testing on
Intel Purley platforms.  On each boot, it checks an OEM policy variable to
decide whether to inject a pre-built error injection record (SMI handler
registration with INTEL vendor GUID).  This is a debug/test driver -- it
generates test error records that platform RAS firmware (e.g. the BIOS error
record handler) can consume.

## Address Range

0x280 - 0x1020 (18 functions)

## File Metadata

- Image: McBankErrorInjection.efi
- Image size: 0x1ca0
- Architecture: X64
- Source branch: PurleyPlatPkg\Ras\Smm\McBankErrorInjection
- MD5: f4eb9888b50f0dbe3add207008acadaa
- SHA256: 739a991d6999aadd74d79b23ceb4866fa0a2b8ebd608c71a01c460aa17aee35c

## Entry Points (Public API)

| Address | Name | Purpose |
|---------|------|---------|
| 0x464 | `_ModuleEntryPoint` | UEFI driver entry point. Initializes module, calls OEM policy check, registers SMI error injection handler. |

## Driver Flow

```
_ModuleEntryPoint (0x464)
  |
  +-- sub_510()          -- Init UEFI Boot/SMM services, SMRAM ranges
  |
  +-- sub_280(&unk_1A30) -- SetJump/save context (for LongJump on error)
  |
  +-- sub_8F0()          -- MAIN: OEM policy check + error injection
  |     |
  |     +-- Get SMM CPU I/O protocol (0x17C0) to check MSR
  |     +-- Read OEM policy variable (via SMM Variable protocol 0x17E0)
  |     +-- If OEM policy allows:
  |     |     +-- sub_754() -- Build INTEL error injection descriptor
  |     |     |     |
  |     |     |     +-- Allocate 0x140-byte buffer
  |     |     |     +-- Fill structure: Type=3, fields zeroed
  |     |     |     +-- Build "INTEL " vendor signature (6+8 bytes)
  |     |     |     +-- Register SMI handler via SMM SW Dispatch (0x17B0)
  |     |     |     +-- Locate INTEL SMI handler via unk_17F0 GUID
  |     |     |
  |     |     +-- Get SMM Variable protocol (0x19C0)
  |     |     +-- Write 159-byte error injection record via variable
  |     |
  |     +-- Return status
  |
  +-- sub_C54(&unk_1A30) -- Validate jump buffer alignment
  +-- sub_320(&unk_1A30) -- LongJump (restore context, never reached on success)
  +-- AutoGen DEBUG() cleanups
  |
  +-- sub_FB8() -- Free SMRAM buffer on failure
```

## Key Functions

### Application-Level Logic

| Address | Name | Type | Purpose |
|---------|------|------|---------|
| 0x8F0 | `sub_8F0` | Dispatcher | Main OEM policy check + error injection. Uses SMM Variable protocol to check OEM enable flag. If enabled, calls sub_754 to build and register the injection handler, then writes 159-byte record via SMM Variable protocol. |
| 0x754 | `sub_754` | Complex | Builds an INTEL MC Bank error injection SMI handler. Allocates 320-byte buffer, fills structure header (Type=3), creates "INTEL " vendor signature (6+8 chars), registers via SMM SW Dispatch, and invokes INTEL SMI handler with unk_17F0 GUID. |

### Library / Support Functions

| Address | Name | Type | Purpose |
|---------|------|------|---------|
| 0x510 | `sub_510` | Dispatcher | UEFI Boot/SMM services initialization. Locates SMM Base2 protocol, gets SmmServicesTable, allocates SMRAM. Also initializes PCD protocol and SMM CPU IO. |
| 0xC9C | `sub_C9C` | Wrapper | Singleton lookup of gEfiPcdProtocolGuid (0x1790). Cached in qword_1A10. |
| 0xE2C | `sub_E2C` | Wrapper | Singleton lookup of SmmCpuIo protocol (0x17A0). Cached in qword_1A18. Used for I/O port access in ASSERT handler. |
| 0xF44 | `sub_F44` | Helper | Checks if an address is within SMRAM ranges. Walks qword_1B38 (SMRAM descriptors). Used by sub_FB8. |
| 0xF88 | `sub_F88` | Wrapper | Allocates SMRAM via SmmServicesTable->SmramAllocatePages (function index 10 = offset 80 from gSmst). |
| 0xFB8 | `sub_FB8` | Cleanup | Frees SMRAM buffer on error. Calls sub_F44 to check SMRAM ownership, then FreePages. |

### Debug / Assert

| Address | Name | Type | Purpose |
|---------|------|------|---------|
| 0xE7C | `sub_E7C` | Complex | Debug assertion handler. Reads CMOS via I/O port 0x70/0x71 to determine debug level. If error mask matches, calls DebugPrint. |
| 0xF04 | `sub_F04` | Wrapper | DEBUG_ASSERT wrapper. Calls sub_E2C to get DebugLib protocol, then invokes DebugAssert (vtable+8). |

### SetJump / LongJump

| Address | Name | Type | Purpose |
|---------|------|------|---------|
| 0x280 | `sub_280` | Wrapper | SetJump implementation. Saves all general-purpose registers, XMM registers, and MXCSR to the jump buffer at unk_1A30. Returns via the continuation function pointer. |
| 0x320 | `sub_320` | Leaf | LongJump implementation. Restores MXCSR from jump buffer, then jumps to the saved continuation. |
| 0xC54 | `sub_C54` | Leaf | Validates jump buffer alignment (must be 8-byte aligned, non-null). |

### Memory Operations

| Address | Name | Type | Purpose |
|---------|------|------|---------|
| 0x3A0 | `sub_3A0` | Leaf | Memcpy with overlap handling. Uses qmemcpy for aligned 8-byte chunks, then byte copy for remainder. |
| 0x3F0 | `sub_3F0` | Leaf | Memset (zero-fill). Handles 8-byte aligned chunks via memset, remainder via byte memset. |
| 0xD28 | `sub_D28` | Wrapper | CopyMem with bounds checking. Delegates to sub_3A0. |
| 0xDC8 | `sub_DC8` | Wrapper | ZeroMem with bounds checking. Delegates to sub_3F0. |

## Protocol Interfaces

### Consumed (this module calls)

| Address | GUID | Protocol | Used By |
|---------|------|----------|---------|
| 0x1780 | `86B091ED-1463-43B5-82A1-2C8B83CB8917` | gEfiSmmBase2ProtocolGuid | sub_510 - get SmmServicesTable |
| 0x1790 | `11B34006-D85B-4D0A-A290-D5A571310EF7` | gEfiPcdProtocolGuid | sub_C9C - PCD access |
| 0x17A0 | `441FFA18-8714-421E-8C95-587080796FEE` | SmmCpuIo (debug) | sub_E2C - CMOS I/O for debug level |
| 0x17B0 | `FFE06BDD-6107-46A6-7BB2-5A9C7EC5275C` | gEfiSmmSwDispatch2ProtocolGuid | sub_754 - register SMI handler |
| 0x17C0 | `F4CCBFB7-F6E0-47FD-9DD4-10A8F150C191` | SmmCpuIo2 (MSR read) | sub_8F0 - CPU MSR access for policy check |
| 0x17D0 | `C2702B74-800C-4131-8746-8FB5B89CE4AC` | SMM Memory Allocation protocol | sub_510 - get SMRAM ranges |
| 0x17E0 | `18A3C6DC-5EEA-48C8-A1C1-B53389F98999` | gEfiSmmVariableProtocolGuid | sub_8F0 - read/write OEM policy variable |

### INTEL Vendor SMI Handler (0x17F0)

The block at 0x17F0 is the INTEL vendor descriptor:
- dword_17F0 = 0x4A45434D ("MCEJ" = Machine Check Error Injection)
- dword_17F4 = 0x00000130 (size/version descriptor, 0x130 = 304 bytes)
- 0x17FA: "INTEL " vendor signature (6 bytes)

This identifies the error injection descriptor as an INTEL-vendor-specific SMI
handler record, matching the Purley platform's RAS error injection mechanism.

## Global Variables

### Initialized .data (0x1780 - 0x1B60)

| Address | Name | Size | Purpose |
|---------|------|------|---------|
| 0x17FA | `aIntel` | 7 | "INTEL " vendor signature string |
| 0x1828 | `qword_1828` | 8 | Buffer field offset (buf+40) - error injection descriptor field |
| 0x1848 | `qword_1848` | 8 | Buffer field offset (buf+16) - error injection descriptor field |
| 0x1868 | `buf_0` | 8 | Error injection descriptor pointer |
| 0x1888 | `qword_1888` | 8 | Buffer field offset (buf+8) |
| 0x18C8 | `qword_18C8` | 8 | Buffer field offset (buf+40) |
| 0x18E8 | `qword_18E8` | 8 | Buffer field offset (buf+32) |
| 0x1908 | `qword_1908` | 8 | Buffer field offset (buf+24) |
| 0x1920 | `src` | 144 | Temp buffer for "INTEL " vendor string assembly |
| 0x19B0 | `byte_19B0` | 1 | OEM policy enable flag (0 or 1) |
| 0x19B8 | `buf` | 8 | SMM SW Dispatch interface pointer |
| 0x19C0 | `qword_19C0` | 8 | SMM Variable protocol interface (from sub_8F0) |
| 0x19C8 | `qword_19C8` | 8 | SMM Variable protocol pointer |
| 0x19D0 | `qword_19D0` | 8 | INTEL SMI handler protocol pointer |
| 0x19D8 | `qword_19D8` | 8 | Error injection buffer secondary pointer |
| 0x19E0 | `qword_19E0` | 8 | SMM CPU I/O protocol pointer |
| 0x19E8 | `SystemTable` | 8 | gST - UEFI System Table |
| 0x19F0 | `BootServices` | 8 | gBS - UEFI Boot Services |
| 0x19F8 | `ImageHandle` | 8 | gImageHandle |
| 0x1A00 | `RuntimeServices` | 8 | gRT - UEFI Runtime Services |

### Zero-initialized BSS (0x1A08 - 0x1B38)

| Address | Name | Purpose |
|---------|------|---------|
| 0x1A08 | `qword_1A08` | gSmst - SMM System Table |
| 0x1A10 | `qword_1A10` | PCD protocol singleton cache |
| 0x1A18 | `qword_1A18` | SmmCpuIo protocol singleton cache |
| 0x1A30 | `unk_1A30` | SetJump/LongJump buffer (248 bytes) |
| 0x1B28 | `qword_1B28` | Module return status |
| 0x1B30 | `qword_1B30` | Number of SMRAM descriptors |
| 0x1B38 | `qword_1B38` | SMRAM ranges array pointer |

## Data Structures

### Error Injection Descriptor (at allocated buffer, 0x140 = 320 bytes)

```
Offset  Size  Field
------  ----  -----
+0x00     8   Type (always 3)
+0x08     8   Field (initially 0)
+0x10     8   Field (initially 0)
+0x18     8   Field (initially 0)
+0x20     8   Field (initially 0)
+0x28     8   Field (initially 0)
+0x30     ...  INTEL vendor signature region (6+8 bytes "INTEL ")
+0x40     0x90  Extended descriptor data (144 bytes copied via CopyMem)
```

The descriptor follows the Purley INTEL MCEJ (Machine Check Error Injection)
format. Type=3 indicates the error record type.

## Calling Patterns

1. **Boot flow**: `_ModuleEntryPoint` -> `sub_510` (init) -> `sub_280` (SetJump) -> `sub_8F0` (OEM check + inject) -> `sub_C54`/`sub_320` (LongJump cleanup) -> return status

2. **OEM policy check**: `sub_8F0` gets SMM CPU I/O protocol, checks MSR via `SmmCpuIo2`, reads SMM Variable for OEM policy bit (byte_19B0), checks OEM field at offset +24 via `qword_19C8`.

3. **Error injection**: `sub_754` allocates 320-byte buffer, fills INTEL error injection descriptor, registers SMI handler via `gEfiSmmSwDispatch2ProtocolGuid`, then calls the INTEL SMI handler protocol.

## Dependencies

### Consumed (this module calls)

| Module | Functions |
|--------|-----------|
| SMM Core | gEfiSmmBase2ProtocolGuid, gEfiSmmSwDispatch2ProtocolGuid, gEfiSmmVariableProtocolGuid |
| PCD Infrastructure | gEfiPcdProtocolGuid |
| SMM CPU I/O | SmmCpuIo protocol (0x17A0), SmmCpuIo2 protocol (0x17C0) |
| INTEL RAS | INTEL MCEJ SMI handler protocol (0x17F0) |
| UEFI Boot Services | gBS, gST, gRT |

### Consumed By (other modules call this)

This module is an SMM driver with no registered protocols -- it is called by
the SMM core via ModuleEntryPoint on SMM driver load. No other module
consumes its services.

## OEM Extension Point

The module references `McBankErrorInjectionOem.c` (at 0x1140), indicating an
OEM-customizable portion of the policy check. The OEM file would define the
SMM Variable GUID and field offset at +24 for the enable/disable flag.

## Notes

- This is a **debug/test driver** -- the AutoGen.c ASSERT lines at lines 307
  and 322 confirm this module is only built in DEBUG_VS2015 configuration.
- The module is SMM-only and does not install any UEFI protocols itself.
- The error injection descriptor is 320 bytes, with Type=3 indicating the
  INTEL MC Bank error format.
- The "INTEL " vendor signature (0x17FA) is used to match against the INTEL
  SMI handler protocol registered by platform firmware.
- CMOS port 0x70/0x71 access in sub_E7C is used to determine debug level for
  ASSERT output filtering.