# LegacyRegion2 DXE Driver

## Overview

The `LegacyRegion2` DXE driver manages read/write/execute permissions for the
legacy memory region (0xC0000 - 0xFFFFF) on Intel Purley/Purley Refresh
platforms.  It controls PAM (Programmable Attribute Map) registers in the
chipset's PCI-to-LPC bridge to enable or disable decode of legacy VGA BIOS
and option ROM regions.

This driver is the **LegacyRegion2** protocol producer.  It consumes the
**LegacyRegion** protocol (from the CSM / Legacy Platform Driver) to access
the low-level PAM I/O ports, and publishes the **LegacyRegion2** protocol
with enhanced locking semantics over the original LegacyRegion interface.

## File Information

| Property       | Value                                           |
|----------------|--------------------------------------------------|
| Module         | `LegacyRegion2.efi` (0322)                       |
| Source         | `PurleyPlatPkg\Legacy\Dxe\LegacyRegion\LegacyRegion.c` |
| PDB            | `LegacyRegion2.pdb`                              |
| Arch           | x86-64                                           |
| Image Size     | 0x12A0 (4768 bytes)                              |
| Entry Point    | `0x350`                                          |
| Build Env      | VS2015 DEBUG, HR6N0XMLK platform                 |
| SHA-256        | `84f4964291f0d5788882eb7801452ff5fe6b58a5a50cd1e481917127e615d800` |

## Memory Layout

| Segment    | Start    | End      | Size   | Permissions | Contents                              |
|------------|----------|----------|--------|-------------|---------------------------------------|
| HEADER     | 0x0000   | 0x0280   | 0x0280 | ---         | PE/COFF header                        |
| .text      | 0x0280   | 0x0C40   | 0x09C0 | rx          | Executable code                       |
| .rdata     | 0x0C40   | 0x1000   | 0x03C0 | r           | Strings, debug info                   |
| .data      | 0x1000   | 0x1180   | 0x0180 | rw          | GUIDs, globals, region descriptor tbl |
| seg004     | 0x1180   | 0x1220   | 0x00A0 | r           | BSS (zeroed)                          |
| .xdata     | 0x1220   | 0x12A0   | 0x0080 | r           | Exception handler data                |

## GUIDs Discovered

| Address  | GUID                                  | Purpose                                  |
|----------|---------------------------------------|------------------------------------------|
| 0x1000   | `{36232936-0E76-31C8-A13A-3AF2FC1C3932}` | Custom HOB data GUID (in HOB library)  |
| 0x1010   | `{0067835F-9A50-433A-8CBB-852078197814}` | Vendor GUID (sub-protocol)              |
| 0x1020   | `{A7CED760-C71C-4E1A-ACB1-89604D5216CB}` | **EFI_LEGACY_REGION2_PROTOCOL**        |
| 0x1030   | `{AF1E1070-0085-440C-B356-8EE36FEF24F0}` | Protocol GUID for installed interface   |
| 0x1040   | `{7739F24C-93D7-11D4-9A3A-0090273FC14D}` | **HOB List GUID** (in System Config Table) |

## Region Descriptor Table

The PAM attribute map divides the 0xC0000-0xFFFFF range into 13 sub-regions:

| Entry | Base     | Size     | End      | Type | Description          |
|-------|----------|----------|----------|------|----------------------|
| 0     | 0xF0000  | 0x10000  | 0xFFFFF  | 0    | BIOS segment F (64K) |
| 1     | 0xC0000  | 0x4000   | 0xC3FFF  | 1    | VGA BIOS segment 0   |
| 2     | 0xC4000  | 0x4000   | 0xC7FFF  | 2    | VGA BIOS segment 1   |
| 3     | 0xC8000  | 0x4000   | 0xCBFFF  | 3    | VGA BIOS segment 2   |
| 4     | 0xCC000  | 0x4000   | 0xCFFFF  | 4    | VGA BIOS segment 3   |
| 5     | 0xD0000  | 0x4000   | 0xD3FFF  | 5    | VGA BIOS segment 4   |
| 6     | 0xD4000  | 0x4000   | 0xD7FFF  | 6    | VGA BIOS segment 5   |
| 7     | 0xD8000  | 0x4000   | 0xDBFFF  | 7    | VGA BIOS segment 6   |
| 8     | 0xDC000  | 0x4000   | 0xDFFFF  | 8    | VGA BIOS segment 7   |
| 9     | 0xE0000  | 0x4000   | 0xE3FFF  | 9    | VGA BIOS segment 8   |
| 10    | 0xE4000  | 0x4000   | 0xE7FFF  | 10   | VGA BIOS segment 9   |
| 11    | 0xE8000  | 0x4000   | 0xEBFFF  | 11   | VGA BIOS segment 10  |
| 12    | 0xEC000  | 0x4000   | 0xEFFFF  | 12   | VGA BIOS segment 11  |

Type values map to PAM register bit positions (each 2-bit field = read-enable + write-enable).

## PAM Attribute Bit Layout

Each PAM register packs 4 region attributes (types N..N+3) into a 32-bit value:

```
Bit      31 30  29 28  27 26  25 24  ...  7 6  5 4  3 2  1 0
Field    [A3]    [A2]    [A1]    [A0]
         2 bits  2 bits  2 bits  2 bits
```

Each 2-bit field:
- Bit 0: Read Enable
- Bit 1: Write Enable

Types 0-6: attributes in the "read port" PAM register (I/O 0x30000C0).
Types 7-12: attributes in the "write port" PAM register (I/O 0x30000C4).

## Protocol Flow

```
ModuleEntryPoint (0x350)
  |
  +-> Save gImageHandle, gST, gBS, gRT (lib constructors)
  |
  +-> GetHobList (0xAC4)
  |     +-> Scan gST->ConfigurationTable for HOB_LIST_GUID
  |     +-> Return cached HOB list pointer
  |
  +-> WheaSupportEntry (0x408)
        +-> gBS->LocateProtocol(LEGACY_REGION_PROTOCOL)
        +-> gBS->LocateProtocol(LEGACY_REGION2_PROTOCOL)
        +-> Read gPamCapabilities
        +-> InstallMultipleProtocolInterfaces(LEGACY_REGION2_PROTOCOL)
```

## Function Map (Original to Renamed)

| Address | Size | Original   | Renamed Name               | Purpose                              |
|---------|------|------------|----------------------------|--------------------------------------|
| 0x0350  | 184  | sub_350    | `ModuleEntryPoint`         | DXE driver entry point               |
| 0x0408  | 383  | sub_408    | `WheaSupportEntry`         | Main init: locate protocols + install|
| 0x0588  | 11   | sub_588    | `LegacyRegion2GetMaxSize`  | Return 0 max size (stub)             |
| 0x0594  | 771  | sub_594    | `ProgramPamRegisters`      | Core PAM register programming        |
| 0x0898  | 36   | sub_898    | `LegacyRegion2Decode`      | Validate region range                |
| 0x08BC  | 114  | sub_8BC    | `LegacyRegion2Program`     | Program region attributes            |
| 0x0930  | 73   | sub_930    | `LegacyRegion2ProgramLock` | Program with lock override           |
| 0x097C  | 127  | sub_97C    | `GetHobListCache`          | Return cached HOB list               |
| 0x09FC  | 136  | sub_9FC    | `DebugAssertPrint`         | Debug assertion print (DebugLib)     |
| 0x0A84  | 62   | sub_A84    | `DebugAssert`              | Debug assertion handler (DebugLib)   |
| 0x0AC4  | 214  | sub_AC4    | `GetHobList`               | Find HOB list via config table       |
| 0x0B9C  | 110  | sub_B9C    | `IsHobListConfigEntry`     | Compare config table entry GUID      |
| 0x0C0C  | 47   | sub_C0C    | `ReadUnaligned64`          | Unaligned 64-bit read (BaseLib)      |

## Key Functions Detail

### WheaSupportEntry (0x408)
Driver initialisation.  Locates LegacyRegion and LegacyRegion2 protocols,
reads PAM capabilities from the LegacyRegion2 protocol's internal state,
builds the protocol function table, and installs it.

### ProgramPamRegisters (0x594)
The core PAM programming routine.  Iterates the 13-entry region descriptor
table, detects overlaps with the requested range, reads current PAM register
values via the LegacyRegion protocol's I/O abstractions, modifies the 2-bit
attribute fields, and writes them back.  Handles both "low" (types 0-6) and
"high" (types 7-12) PAM registers with bit position mapping.

### LegacyRegion2Decode (0x898)
Validates that [StartAddress, StartAddress+Length) falls within 0xC0000-0xFFFFF.
Returns EFI_INVALID_PARAMETER if the range extends beyond these boundaries.

### LegacyRegion2Program (0x8BC)
Programs PAM attributes for the given range.  Checks LegacyRegion2 internal
write-disable state (at offsets +0x06F4 and +0x06F1) to decide whether to
force write-enable.  Delegates to ProgramPamRegisters.

### LegacyRegion2ProgramLock (0x930)
Like Program but always passes LegacyDecode=2 (override).  Checks the same
write-disable state before calling ProgramPamRegisters.

### GetHobList (0xAC4)
Scans the System Table's Configuration Table for an entry whose VendorGuid
matches {7739F24C-93D7-11D4-9A3A-0090273FC14D}.  Returns the associated
VendorTable pointer, which is the HOB list used by DxeHobLib.

### ReadUnaligned64 (0xC0C)
BaseLib helper: reads 8 bytes from any address (may be unaligned).

### DebugAssert / DebugAssertPrint (0xA84, 0x9FC)
Debug library wrappers.  DebugAssertPrint checks CMOS register 0x4B for
platform type and routes to the appropriate debug output.

## Global Variables

| Address | Size | Name                    | Description                                 |
|---------|------|-------------------------|---------------------------------------------|
| 0x10E0  | 8    | `gST`                   | EFI System Table pointer                    |
| 0x10E8  | 8    | `gBS`                   | EFI Boot Services table pointer             |
| 0x10F0  | 8    | `gImageHandle`          | Image handle (from entry)                   |
| 0x10F8  | 8    | `gRT`                   | EFI Runtime Services table pointer          |
| 0x1100  | 8    | _unused_                | Debug library internal                      |
| 0x1108  | 8    | `gHobList`              | Cached HOB list pointer                     |
| 0x1120  | 4    | `gLegacyRegion2Signature` | Signature 'INIT' (0x4E495449)              |
| 0x1128  | 8    | `gLegacyRegion2ProtocolHandle` | Protocol handle for installed interface|
| 0x1130  | 8    | `gLegacyRegion2Protocol.Decode`     | Function pointer: Decode          |
| 0x1138  | 8    | `gLegacyRegion2Protocol.Program`    | Function pointer: Program         |
| 0x1140  | 8    | `gLegacyRegion2Protocol.ProgramLock`| Function pointer: ProgramLock     |
| 0x1148  | 8    | `gLegacyRegion2Protocol.GetMaxSize` | Function pointer: GetMaxSize     |
| 0x1150  | 8    | `gLegacyRegion2Protocol.GetMaxSize2`| Duplicate GetMaxSize (unused)    |
| 0x1158  | 8    | `gImageHandleSaved`     | Saved ImageHandle for init                 |
| 0x1160  | 4    | `gPamCapabilities`      | PAM capabilities bitmask                   |
| 0x1168  | 8    | `gLegacyRegion2`        | Located LegacyRegion2 protocol              |
| 0x1170  | 8    | `gLegacyRegion`         | Located LegacyRegion protocol               |

## Strings Referenced

All strings reside in .rdata:

| Address | String                                               |
|---------|------------------------------------------------------|
| 0xC40   | `\nASSERT_EFI_ERROR (Status = %r)\n` (format string) |
| 0xC68   | `!EFI_ERROR (Status)`                                |
| 0xC80   | `e:\hs\PurleyPlatPkg\Legacy\Dxe\LegacyRegion\LegacyRegion.c` |
| 0xCC0   | `gImageHandle != ((void *) 0)`                       |
| 0xCE0   | `e:\hs\MdePkg\Library\UefiBootServicesTableLib\UefiBootServicesTableLib.c` |
| 0xD30   | `gST != ((void *) 0)`                                |
| 0xD48   | `gBS != ((void *) 0)`                                |
| 0xD60   | `gRT != ((void *) 0)`                                |
| 0xD80   | `e:\hs\MdePkg\Library\UefiRuntimeServicesTableLib\UefiRuntimeServicesTableLib.c` |
| 0xDD0   | `Buffer != ((void *) 0)`                             |
| 0xDE8   | `e:\hs\MdePkg\Library\DxeHobLib\HobLib.c`            |
| 0xE10   | `mHobList != ((void *) 0)`                           |
| 0xE30   | `e:\hs\MdePkg\Library\BaseLib\Unaligned.c`           |

## Call Graph

```
ModuleEntryPoint (0x350)
  |
  +-> DebugAssert (0xA84)  [called for each NULL check]
  |     +-> GetHobListCache (0x97C) [lazy init]
  |
  +-> GetHobList (0xAC4)
  |     +-> IsHobListConfigEntry (0xB9C)
  |     |     +-> ReadUnaligned64 (0xC0C) [x4]
  |     +-> DebugAssertPrint (0x9FC)
  |     +-> DebugAssert (0xA84)
  |
  +-> WheaSupportEntry (0x408)
        +-> DebugAssertPrint (0x9FC)
        |     +-> GetHobListCache (0x97C)
        +-> DebugAssert (0xA84)
        +-> gBS->LocateProtocol (x2)
        +-> gBS->InstallMultipleProtocolInterfaces
```

## Import Table (IAT)

| Ordinal | Function             | Library                |
|---------|----------------------|------------------------|
| 320     | `LocateProtocol`     | gBS                    |
| 128     | `InstallMultipleProtocolInterfaces` | gBS   |
| 24      | `GetNextMonotonicCount` | gBS                 |
| 32      | `Stall`              | gBS                    |

## Dependencies

- **EFI_LEGACY_REGION_PROTOCOL** -- provided by CSM/LegacyPlatform driver
- **EFI_LEGACY_REGION2_PROTOCOL** -- provided by SMM/other driver (for capabilities)
- **UefiBootServicesTableLib** -- gImageHandle, gST, gBS globals
- **UefiRuntimeServicesTableLib** -- gRT global
- **DxeHobLib** -- HOB list access via configuration table
- **BaseLib** -- ReadUnaligned64

## Notes

1. The HOB list GUID {7739F24C-93D7-11D4-9A3A-0090273FC14D} is not a standard
   UEFI specification GUID (standard is gEfiDxeServicesTableGuid).  This is a
   platform-specific GUID published by the DXE firmware during boot.

2. The driver contains embedded CmosDebugLib logic that reads CMOS register
   0x4B through I/O ports 0x70/0x71 to determine platform type (IPMI/BMC mode)
   before routing debug output.

3. PAM register ports 0x30000C0 and 0x30000C4 are chipset-specific PCIe
   configuration space registers in the P2SB (Primary-to-Sideband) bridge.

4. The original source file path indicates this is from
   `PurleyPlatPkg\Legacy\Dxe\LegacyRegion\LegacyRegion.c` -- the single source
   file builds both the LegacyRegion (SMM) and LegacyRegion2 (DXE) drivers
   via compile-time flags.

5. All assertion strings reference EDK2 MdePkg library paths, confirming
   this uses standard EDK2 DebugLib, BaseLib, and HobLib implementations
   with PurleyPlatPkg-specific platform overrides.