# PiSmmCore Module

## Overview
UEFI SMM Core driver -- the SMM equivalent of the DXE Core. Provides the
EFI_SMM_SYSTEM_TABLE2 (SMST) protocol services consumed by all other SMM
drivers. Responsible for SMI dispatch, SMM driver loading/resolution via
DEPEX, SMRAM pool/page allocation, and the SMM protocol handle database.
AMI additions include platform-specific SMI hooks, communication buffer
validation, and PCH RAS policy integration.

## Address Range
0x2C0 - 0xB900 (46,208 bytes .text, 167 functions)
Source files compiled into this module:
- MdeModulePkg/Core/PiSmmCore/: PiSmmCore.c, Dispatcher.c, Handle.c, Smi.c,
  Page.c, Pool.c, Notify.c, Locate.c, MemoryAttributesTable.c
- AmiModulePkg/Library/SmmCoreAmiBufferValidationLib/
- PurleyPlatPkg/Override/MdeModulePkg/Library/SmmCorePlatformHookLib/
- MdeModulePkg/Library/SmmCorePerformanceLib/
- MdePkg/Library/: BaseLib, BasePrintLib, BaseMemoryLibRepStr,
  BaseDebugLibSerialPort, BasePeCoffLib, BaseCacheMaintenanceLib,
  SmmPciExpressLib
- MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/

## Key Functions

| Address | Name in Source | Size | Callees | Callers | Purpose |
|---------|----------------|------|---------|---------|---------|
| 0x454 | _ModuleEntryPoint | 0x2C | 4 | 0 | PE/COFF entry point |
| 0x480 | SmmCoreEntry | 0x4B5 | 17 | 1 | Early init: BS/RT/SMST locate, SMRAM discovery, lib inits |
| 0x9D0 | SmmMain | 0x16D | 4 | 1 | Main init: SMST setup, SMI handler registration, MAT callback reg |
| 0x938 | SmmCoreUnload | 0x98 | 5 | 1 | Error/unload cleanup: free SMRAM, unregister protocols |
| 0xE4C | SmmEntryPoint | 0x30A | 10 | 1 | Per-SMI entry: AMI hooks, save CommBuffer, SMI dispatch |
| 0x1158 | SmmInstallConfigurationTable | 0x2C6 | 11 | 1 | Install SMST + gEfiSmmConfigurationProtocol |
| 0x1E38 | SmmInsertImageRecord | 0x3C4 | 12 | 4 | Record loaded image code sections for MAT |
| 0x2474 | SmmUpdateMemoryAttributesTable | 0x1A9 | 7 | 1 | Scan loaded images, build memory protection table |
| 0x2620 | SmmMemoryAttributesTableCallback | 0xE6 | 4 | 1 | EndOfDxe callback: dump images, set memory attributes |
| 0x2708 | SmmLoadImage | 0x5D4 | 20 | 1 | PE32+ loading: DEPEX eval, FV read, PeCoff load, image rec |
| 0x2D94 | SmmDispatcher | 0x556 | 12 | 2 | Main dispatcher loop |
| 0x34C0 | SmmEntryPointWrapper | 0x59A | 22 | 1 | Root SMI handler: save state, call SmiManage, restore |
| 0x3A5C | SmiManage | 0xD5 | 4 | 2 | Core SMI dispatch: walk SMI handler list by GUID |
| 0x3B34 | SmiHandlerInvoke | 0x162 | 5 | 2 | Invoke registered SMI handlers, process return codes |
| 0x3C98 | SmiHandlerRegister | 0xD5 | 4 | 5 | Register a SMI handler for a GUID key |
| 0x4068 | SmmFindProtocolEntry | 0x222 | 7 | 6 | Find/create PROTOCOL_ENTRY by GUID |
| 0x41F4 | SmmInstallProtocolInterface | 0x26E | 17 | 3 | Install protocol interface on handle |
| 0x48F0 | SmmHandleProtocol | 0x193 | 4 | 0 | Locate protocol interface on a handle |
| 0x4A84 | SmmRegisterProtocolNotify | 0x1FC | 7 | 3 | Register notify for protocol installation |
| 0x4C68 | SmmLocateHandle | 0x1FA | 2 | 3 | Locate handles by search type |
| 0x4F80 | SmmAllocatePool | 0x175 | 5 | 10 | Pool allocation (internal) |
| 0x5100 | SmmFreePool | 0x157 | 2 | 3 | Pool free (internal) |
| 0x5818 | InternalFreePages | 0x14A | 3 | 6 | Free page-aligned SMRAM |
| 0x59E8 | SmmFreePages | 0x101 | 2 | 4 | Page free with cache maintenance |
| 0x5DF0 | SmmEvaluateDepex | 0x342 | 8 | 3 | DEPEX expression evaluator |
| 0x6134 | CopyMem | 0x99 | 1 | 36 | Memory copy |
| 0x61D0 | ZeroMem | 0x63 | 1 | 9 | Memory zero |
| 0x627C | GuidEqual | 0x67 | 3 | 8 | Compare 16-byte GUIDs |
| 0x6234 | CopyGuid | 0x2C | 4 | 6 | Copy 16-byte GUID |
| 0x6350 | InitializeListHead | 0x36 | 1 | 14 | Linked list init |
| 0x63D8 | InsertTailList | 0x51 | 2 | 14 | Linked list tail insert |
| 0x6388 | InsertHeadList | 0x50 | 1 | 2 | Linked list head insert |
| 0x6464 | RemoveEntryList | 0x48 | 2 | 7 | Linked list entry remove |
| 0x7834 | DebugPrint | 0xD3 | 4 | 35 | SMM debug via serial port (CMOS 0x4C/0x70/0x71) |
| 0x7908 | Assert | 0x52 | 3 | 203 | SMM assertion handler |
| 0x79A0 | InternalAllocatePool | 0x2F | 1 | 22 | Raw pool allocation wrapper |
| 0x79D0 | AllocateZeroPool | 0x24 | 2 | 4 | Allocate + zero pool |
| 0x7A74 | InternalFreePool | 0x5D | 4 | 6 | Raw pool free wrapper |
| 0x7CC0 | StrnLenS | 0x62 | 4 | 6 | String length / data size |
| 0x8234 | PciExpressRead | 0x3A | 1 | 12 | PCI Express config read (SMM-safe) |
| 0x8414 | SmmIsBufferOutsideSmmValid | 0x12A | 5 | 2 | Validate buffer not in SMRAM |
| 0x853C | SmmAmiValidateCommBuffer | 0x55 | 2 | 3 | AMI CommBuffer validation |
| 0x8594 | SmmAmiIsBufferValid | 0xA2 | 1 | 2 | AMI buffer range validation |
| 0x8980 | SmmAmiBufferValidationLibInit | 0x3B0 | 6 | 1 | Init AMI buffer validation: query MMIO ranges, allocate |
| 0x8BE8 | SmmAmiCommBufferLock | 0x2D0 | 5 | 1 | Lock/unlock SMM communication buffer |
| 0x8F44 | SmmAmiBufferValidationLibConstructor | 0x16E | 8 | 1 | Constructor: locate protocol, allocate mailbox, register handler |
| 0x9464 | SmmCorePerformanceLog | 0x1F4 | 2 | 3 | Performance measurement logging |
| 0x9598 | SmmCorePerformanceEndMeasure | 0x310 | 2 | 3 | End performance measurement |
| 0x98B8 | SmmPerformanceHandler | 0x212 | 4 | 1 | SMI handler for performance data queries |
| 0x9A18 | SmmCorePerformanceLibInit | 0x258 | 6 | 1 | Performance library init |
| 0xAE00 | PeCoffReadWrapper | 0x9D | 1 | 3 | PE/COFF read callback |
| 0xB158 | SmmCorePlatformHookLibInit | 0xEA | 4 | 1 | Platform hook init: locate RAS policy protocol |
| 0xB6A4 | SerialPortWrite | 0xB8 | 0 | 2 | Serial port putc (polled I/O) |

## Entry Points (Public API)

The following are called from outside the module (SMST function dispatch table):

- **0x3C98** `SmiHandlerRegister`: Register a handler for a SMI GUID
- **0x3B34** `SmiHandlerInvoke`: Invoke handlers for a SMI GUID (walk linked list)
- **0x41F4** `SmmInstallProtocolInterface`: Install protocol on a handle
- **0x48F0** `SmmHandleProtocol`: Get protocol interface from a handle
- **0x4A84** `SmmRegisterProtocolNotify`: Register for protocol install notification
- **0x4C68** `SmmLocateHandle`: Find handles supporting a protocol
- **0x4F80** `SmmAllocatePool`: Allocate from SMRAM pool
- **0x5100** `SmmFreePool`: Free SMRAM pool allocation
- **0x5818** `InternalFreePages`: Free page-aligned SMRAM

The following are internal entry points:

- **0x454** `_ModuleEntryPoint` (PE/COFF entry, called by DXE IPL)
- **0x34C0** `SmmEntryPointWrapper` (registered as root SMI handler in SMST)
- **0x2620** `SmmMemoryAttributesTableCallback` (registered as EndOfDxe SMI handler)
- **0x90B4** `SmmAmiBufferValidationLibInit` (called from SmmMain)

## Internal Helpers

- **0x79A0** `InternalAllocatePool`: Allocates pool memory with POOL_HEADER/POOL_TAIL management.
  Small (<=0x800 bytes): uses pool free list buckets (power-of-2 indexed).
  Large (>0x800 bytes): calls page allocator, creates page header.
- **0x3A5C** `SmiManage`: Core SMI dispatch. Walks SMI handler list at
  `gSmiHandlerList` (0x11508). Uses `sub_627C` for 16-byte GUID comparison.
  Iterates per-GUID handler chains for SmiHandlerInvoke.
- **0x6350** `InitializeListHead`: Internal linked list head init for SMHC,
  PRTI, SHND, IMGR, COSE structures.
- **0x9464** `SmmCorePerformanceLog`: Performance measurement entry.
- **0x9598** `SmmCorePerformanceEndMeasure`: Performance measurement exit.

## State Management

### Critical Global Variables (.data segment 0x11000-0x144A0)

| Address | Name | Type | Purpose |
|---------|------|------|---------|
| 0x14078 | SystemTable | ptr | EFI_SYSTEM_TABLE pointer (from entry point) |
| 0x14080 | BootServices | ptr | gBS (BootServices table) |
| 0x14098 | SMST | ptr | gSmst (EFI_SMM_SYSTEM_TABLE2) |
| 0x140A0 | mSmmCoreSmmramRanges | ptr | Active SMRAM descriptor array (memory alloc lib) |
| 0x140A8 | mSmmCoreSmmramRangeCount | u64 | Count of active SMRAM descriptors |
| 0x140B8 | gPciExpressBase | u64 | PCI Express MMIO base address |
| 0x140C0 | gCpuIo | ptr | CPU I/O protocol for MMIO access |
| 0x140E8 | byte_140E8 | u8 | MMIO ranges initialized flag |
| 0x140F0 | qword_140F0 | ptr | AMI buffer validation comm buffer page |
| 0x140F8 | qword_140F8 | u64 | Number of MMIO ranges for buffer validation |
| 0x14108 | qword_14108 | ptr | AMI buffer validation protocol interface |
| 0x14110 | qword_14110 | ptr | SMM memory allocation table (alloc lib) |
| 0x14118 | qword_14118 | ptr | AMI mailbox for comm buffer locking |
| 0x14120 | qword_14120 | ptr | SMM image handle (for unload) |
| 0x14128 | dword_14128 | u32 | Max supported comm buffer size |
| 0x14138 | dword_14138 | u32 | AMI mailbox session counter |
| 0x14140 | qword_14140 | ptr | SMM memory allocation table range list |
| 0x14148 | byte_14148 | u8 | AMI buffer validation initialized flag |
| 0x14158 | byte_14158 | u8 | Comm buffer locked flag |
| 0x14160 | qword_14160 | ptr | AMI MMIO range array |
| 0x141C8 | qword_141C8 | ptr | AMI platform RAS policy protocol |
| 0x14208 | qword_14208 | ptr | AMI platform PCH data |
| 0x14210 | qword_14210 | ptr | AMI platform PCH method table (vtable) |
| 0x14218 | qword_14218 | ptr | AMI platform PCH flags |
| 0x14220 | qword_14220 | ptr | SMM Core performance data buffer |
| 0x14228 | byte_14228 | u8 | Performance enable flag |
| 0x14478 | mFullSmramRanges | ptr | Full SMRAM descriptor array (from DXE handoff) |
| 0x14488 | mFullSmramRangeCount | u64 | Count of full SMRAM descriptors |
| 0x14498 | gImageHandle | ptr | SMM Core's own image handle |
| 0x14490 | qword_14490 | ptr | SMST configuration protocol buffer |
| 0x14480 | qword_14480 | ptr | SMST protocol structure buffer |
| 0x11470 | qword_11470 | u64 | Memory protection attribute (bit 0 = NX enable) |
| 0x11480 | qword_11480 | u64 | Image record count |
| 0x11488 | qword_11488 | u64 | Max code sections across all image records |
| 0x14020 | byte_14020 | u8 | Non-zero if in legacy boot |
| 0x11490 | off_11490 | LIST_ENTRY | Image record list head |
| 0x11508 | off_11508 | LIST_ENTRY | SMI handler protocol list head |
| 0x11518 | off_11518 | LIST_ENTRY | Protocol database list head |
| 0x13F60 | off_13F60 | LIST_ENTRY | Handle database list head |
| 0x13F70 | off_13F70 | LIST_ENTRY | Page allocation pool list head |
| 0x10BA0 | off_10BA0 | funcptr[] | Pre-SMI-entry callback table |
| 0x10BA8 | off_10BA8 | funcptr[] | Post-SMI-entry callback table (reverse order) |

### SMI Handler Registration Table at 0x11280

This table contains an array of 32-byte entries:

```
struct {
    UINT64  GuidPtr;      // Pointer to EFI_GUID data (embedded in code segment)
    UINT64  HandlerFunc;  // SMI handler callback function
    UINT64  NotifyFlag;   // Registration flags (non-zero = fire notification on install)
};
```

Empty entry (all zeros) terminates the table. Each entry calls
`SmiHandlerRegister(GuidPtr, HandlerFunc, &NotifyFlag)` during SmmMain.

## Data Structures

### SMI Handler Structure (SMHC, 48 bytes, alloc 64)
```
Offset  Size  Field
0x00    4     Signature ("SMHC")
0x08    16    LIST_ENTRY Link (Flink/Blink)
0x18    8     Key (GUID pointer)
0x20    8     Handler (callback function)
0x28    8     Name (string, e.g. "smie")
```

### Protocol Entry Structure (SMHP, 56 bytes)
```
Offset  Size  Field
0x00    4     Signature ("SMHP")
0x08    16    LIST_ENTRY (global protocol list)
0x18    8     ProtocolID (GUID pointer)
0x20    16    LIST_ENTRY (per-protocol interface list: PRTI entries)
0x30    16    LIST_ENTRY (notification list: NOTIFY entries)
```

### Protocol Interface (PRTI, 64 bytes)
```
Offset  Size  Field
0x00    4     Signature ("PRTI")
0x08    16    LIST_ENTRY (link on handle's protocol list)
0x18    8     Handle (backpointer to SHND_ENTRY)
0x20    8     ProtocolEntry (backpointer to PROTOCOL_ENTRY)
0x30    8     Interface (protocol interface pointer)
```

### Image Record (IMGR, 64 bytes)
```
Offset  Size  Field
0x00    4     Signature ("IMGR")
0x08    16    LIST_ENTRY (global image record list)
0x18    8     ImageBase (source base address)
0x20    8     ImageSize (byte count)
0x28    8     CodeSegmentCount
0x30    16    LIST_ENTRY (code section list)
```

### Code Section (COSE, 40 bytes)
```
Offset  Size  Field
0x00    4     Signature ("COSE")
0x08    16    LIST_ENTRY (link on image's code list)
0x18    8     CodeBase (virtual address)
0x20    8     CodeSize (raw data size)
```

### Pool Header (24 bytes)
```
Offset  Size  Field
0x00    4     Signature ("phd0"=allocated, "phf0"=free)
0x04    1     Available (0=in use, 1=free)
0x05    1     Type (5=EfiRuntimeServicesCode, 6=EfiRuntimeServicesData)
0x08    4     Size (total allocation size, must == POOL_TAIL.Size)
0x10    8     LIST_ENTRY link on pool free list
```

### Pool Tail (16 bytes)
```
Offset  Size  Field
0x00    4     Signature ("ptal")
0x08    8     Size (must match POOL_HEADER.Size)
```

### AMI Comm Buffer Mailbox (24 bytes)
```
Offset  Size  Field
0x00    8     Command (1 = lock)
0x08    8     Identifier (matches comm buffer identifier)
0x10    4     Sequence number (monotonically increasing)
0x14    4     Session ID
0x18    4     Status
```

## Calling Patterns

### 1. SMI Dispatch Path
```
DXE writes CommBuffer -> triggers SMI (via GPE/APMC/ASMII)
  -> SmmEntryPointWrapper(0x34C0)
    -> Save CommBuffer/Size to gSmmCommBufferBase/Size (0x113F0/0x113F8)
    -> Set gInSmmEntryPoint flag (0x14022)
    -> Execute pre-callbacks from off_10BA0 table
    -> If AMI platform hooks present:
       -> RAS policy check (SMM communication buffer management)
       -> PCH-specific SMI dispatch (per-socket/core/memory channel)
    -> SmiManage(0x3A5C, guid=0, context)
       -> Walk gSmiHandlerList (0x11508) matching GUIDs
       -> For each match: SmiHandlerInvoke(0x3B34)
          -> Call handler function
          -> Process return codes:
             SUCCESS -> done (if GUID-specific)
             INTERRUPT_PENDING -> continue iterating
             NOT_HANDLED_0xA -> abort dispatch chain
    -> Execute post-callbacks from off_10BA8 (reverse order)
    -> Clear gInSmmEntryPoint flag
    -> DebugPrint "SmmEntryPoint Exit"
```

### 2. SMM Driver Loading (Dispatcher Path)
```
SmmDispatcher(0x2D94) loop:
  For each FV:
    -> Locate FV protocol
    -> Locate security/SEC2 protocol
    -> For each firmware file:
       -> Read DEPEX from FV
       -> Evaluate DEPEX (0x5DF0 - Dependency.c)
       -> If satisfied:
          -> SmmLoadImage(0x2708):
             -> Read PE32+ headers via PeCoffLoader
             -> Allocate SMRAM pages via page allocator
             -> Load sections, apply relocations
             -> LoadImage/StartImage boot services call
             -> Initialize SMM driver context (image info, section data)
          -> SmmInsertImageRecord(0x1E38):
             -> Allocate IMAGE_RECORD (64 bytes)
             -> Parse PE section headers
             -> Create CODE_SECTION entries for executable sections
             -> Link into gImageRecordList (0x11490)
             -> Update gImageRecordCount (0x11480)
             -> Update gMaxImageRecordSections (0x11488)
          -> Call driver entry point
          -> Install SMM protocols via SmmInstallProtocolInterface
```

### 3. Memory Allocation Path
```
SmmAllocatePool(PoolType, Size) -> 0x4F80:
  If Size+40 <= 0x800 (small allocation):
    -> Compute bucket index (power-of-2, min 32-byte slots)
    -> Walk pool free list for matching bucket
    -> Carve from existing free page or allocate new page
    -> Create POOL_HEADER ("phd0") at allocation start
    -> Create POOL_TAIL ("ptal") at allocation end
    -> Return pointer after header (offset +24)
  Else (large allocation):
    -> Compute page count: (Size+40 + 0xFFF) >> 12
    -> Walk page allocation pool (off_13F70 list)
    -> Allocate contiguous pages
    -> Create page header with type/size info
    -> Set tail signature at end of allocation
    -> Return pointer after header (offset +24)
```

## Dependencies

### Consumed (this module calls)

- **UefiBootServicesTableLib** (gBS): AllocatePool (BS+64), FreePool (BS+72),
  LocateProtocol (BS+320), InstallProtocolInterface (BS+328),
  LocateHandleBuffer (BS+184), HandleProtocol (BS+152),
  OpenProtocol (BS+320), LocateDevicePath (BS+312),
  LocateImage (BS+208)
- **BaseMemoryLibRepStr** (0x2C0): CopyMem, ZeroMem
- **BaseLib** (0x6134, 0x61D0, 0x6234, 0x627C, 0x6350, 0x63D8, 0x6388,
  0x6464, 0x642C, 0x62E4): linked list, memory ops, GUID cmp
- **BasePrintLib** (0x689C, 0x6970): AsciiSPrint, UnicodeSPrint
- **BaseDebugLibSerialPort** (0x7834, 0x7908, 0xB6A4): DEBUG/ASSERT via
  serial port (CMOS 0x4C, I/O ports 0x70/0x71, serial data 0x3F8 or 0x2F8)
- **BasePeCoffLib** (0x9C2C, 0xA170, 0xA4E4, 0xA804, 0xAE00):
  PeCoffLoaderGetPeHeader, PeCoffLoaderGetImageInfo,
  PeCoffLoaderLoadImage, PeCoffLoaderCheckImageType
- **SmmPciExpressLib** (0x8234): register-style PCIe config access
- **AmiSmmCoreBufferValidationLib** (0x8980, 0x8BE8, 0x8F44, 0x853C):
  SMM CommBuffer lock/unlock, MMIO range validation, buffer boundary check
- **SmmCorePlatformHookLib** (0xB158): PCH RAS policy protocol, per-socket
  SMI dispatch for memory/PCIe error handling
- **BaseCacheMaintenanceLib**: cache flush for loaded SMM images
- **SmmCorePerformanceLib** (0x9A18, 0x9464, 0x9598):
  SMM performance measurement data gathering

### Consumed By (other modules call this)

- **All SMM Drivers**: Through EFI_SMM_SYSTEM_TABLE2 (SMST) services:
  SmmAllocatePool, SmmFreePool, SmmAllocatePages, SmmFreePages,
  SmmInstallProtocolInterface, SmmHandleProtocol, SmmLocateProtocol,
  SmmRegisterProtocolNotify, SmiHandlerRegister, SmiHandlerUnRegister,
  SmmStartupThisAp
- **DXE Runtime / SMM Communication**: DXE writes CommBuffer to SMRAM and
  triggers SMI; SmmEntryPoint dispatches to registered SMI handlers
- **PI_SMM Driver Dispatch**: The Dispatcher loads SMM drivers after DEPEX
  evaluation; drivers register their protocols/handlers via SmmMain

## Notes

### Build Configuration
- Debug build with full ASSERT and DEBUG enabled
- Source paths: `e:\hs\MdeModulePkg\...`, `e:\hs\AmiModulePkg\...`,
  `e:\hs\PurleyPlatPkg\...`, `e:\hs\MdePkg\...`
- Toolchain: VS2015 x64

### Structure Signatures Summary
| Hex Value | ASCII | Structure | Source File |
|-----------|-------|-----------|-------------|
| 0x68634D53 | "SMHC" | SMI Handler Context | Smi.c |
| 0x70684D53 | "SMHP" | Protocol Entry | Handle.c |
| 0x444E4853 | "SHND" | SMM Handle | Handle.c |
| 0x49545250 | "PRTI" | Protocol Interface | Handle.c |
| 0x52474D49 | "IMGR" | Image Record | MemoryAttributesTable.c |
| 0x45534F43 | "COSE" | Code Section | MemoryAttributesTable.c |
| 0x30646870 | "phd0" | Pool Allocated | Pool.c |
| 0x30666870 | "phf0" | Pool Free | Pool.c |
| 0x6C617470 | "ptal" | Pool Tail | Pool.c |
| 0x65696D73 | "smie" | SMI name string | Smi.c |

### Debug Output
- Uses CMOS register 0x4C for debug level check
- I/O ports 0x70/0x71 for CMOS access
- Serial port at I/O address determined by CMOS 0x5C (0x3F8 if 0x33, else
  0x2F8)
- Debug output format: "ASSERT [%a] %a(%d): %a\n" for assertions,
  "SmmEntryPoint Entry/Exit\n" for SMI entry tracing

### AMI Extensions Specific to HR650X
- **SmmCoreAmiBufferValidationLib**: Two-phase SMM communication buffer
  locking. Uses a mailbox protocol in a pre-allocated SMRAM page to
  coordinate lock/unlock state between DXE and SMM. Protects against
  re-entrant/buffer-overrun attacks.
- **SmmCorePlatformHookLib**: Integrates with Purley platform RAS policy
  protocol for per-socket/core/channel SMI dispatch. Used by
  SmmEntryPoint to dispatch SMI to platform-specific error handlers.
- The SMI handler table at 0x11280 can contain up to 7+ entries (32 bytes
  each, zero-terminated), registered at SmmMain by GUID + handler function.