# LegacySmmSredir Module

## Overview

This is a UEFI SMM (System Management Mode) driver for legacy serial redirection, sourced from AmiModulePkg/LegacySerialRedirection. It installs a protocol notification callback that intercepts SMM communication via a structured buffer (a serial redirection command/response I/O protocol), validates the buffer address against SMM allowed regions using AmiBufferValidationLib, then performs 8/16/32-bit indexed memory reads, writes, or block-fill operations on behalf of the caller. The module has no DXE-to-SMM protocol dependencies (0 imports); it resolves all dependencies at runtime via the SMM Services Table (gSmst) protocol database.

## Address Range

0x2A0 - 0x1320 (20 functions, 0x1080 bytes .text segment)

## Key Functions

| Address | Name | Purpose |
|---------|------|---------|
| 0x420 | _ModuleEntryPoint / ModuleEntryPoint alias | Standard UEFI SMM driver entry; calls init then dispatch |
| 0x44C | LegacySmmSredirAutoGenInit (`sub_44C`) | AutoGen library init: saves ImageHandle, SystemTable, BootServices, RuntimeServices; locates SmmBase2 protocol and SMM buffer validation protocol |
| 0x618 | LegacySmmSredirDriverEntry (`sub_618`) | Driver main entry: checks if board supports legacy serial redirect (sub_2A0/setjmp), then dispatches to main logic (sub_C58) and cleans up |
| 0xC58 | sub_C58 | Primary dispatch: locates SmmBase2 protocol, opens SMM subsystem interface, initializes globals, calls sub_9E8 for registration |
| 0x9E8 | sub_9E8 | Registration function: opens SMM Internal protocol, registers SMM communicate handler (sub_6CC) with EFI_SMM_COMMUNICATE_HEADER protocol, registers notification handlers and SW dispatch |
| 0x6CC | sub_6CC | Core SMM communicate handler: receives structured commands (read/1, write/2, fill/3) targeting an I/O base; validates buffer via AmiBufferValidationLib; performs typed 8/16/32-bit indexed I/O access |
| 0x93C | sub_93C | Disable handler: sets byte_19F9 = 1 to globally disable the communicate handler |
| 0x944 | sub_944 | Notification registration: registers sub_93C as a notification handler on two SMM protocol GUIDs |
| 0x9C0 | sub_9C0 | Notification callback: captures the communicate buffer pointer and invokes SMM-appropriate completion callback |
| 0x2A0 | sub_2A0 | SetJump context save: saves all GPRs (rbx, rbp, rdi, rsi, r12-r15, return address), MXCSR, and XMM6-XMM15 into a 248-byte jump buffer |
| 0x340 | sub_340 | LongJump context restore: restores MXCSR and jumps through saved return address |
| 0xD78 | sub_D78 | SetJump buffer validation: asserts non-null and 8-byte alignment |
| 0xDC0 | sub_DC0 | Locate DebugLib protocol lazily via gSmst |
| 0xE10 | sub_E10 | Debug print with level check: prints via DebugLib protocol if error level matches |
| 0xE58 | sub_E58 | Debug ASSERT message: ASSERT-style formatted output via DebugLib protocol |
| 0xE98 | sub_E98 | Locate SMM or DXE I/O protocol based on phase (byte_1A50) |
| 0xF20 | sub_F20 | Locate DebugLib protocol for SMM or DXE phase based on byte_1A50 |
| 0x1004 | sub_1004 | Find runtime services pointer: traverses SMM protocol database entries, filtering by sub_1074 match check |
| 0x1074 | sub_1074 | Memory comparison against unk_19E0 pattern (memcmp variant with alignment handling) |
| 0x10F0 | sub_10F0 | SMM buffer security validation wrapper: calls AmiBufferValidationLib to validate an address/size region |
| 0x115C | sub_115C | CMOS-based platform detection: reads CMOS offset 0x4C (RTC register 0x4C), checks for platform-specific serial redirection support; returns EFI_SUCCESS or EFI_UNSUPPORTED based on CMOS byte |

## Entry Points (Public API)

- **0x420** `_ModuleEntryPoint`: The sole standard entry point called by the SMM driver framework. Calls sub_44C (library init) then sub_618 (driver entry).

## Internal Call Flow

1. `_ModuleEntryPoint` (0x420)
2. `sub_44C` (0x44C) -- saves UEFI handles, locates SmmBase2 and AmiBufferValidationLib protocols
3. `sub_618` (0x618) -- calls sub_2A0/setjmp to check if board is supported (CMOS check); dispatches to sub_C58
4. `sub_C58` (0xC58) -- locates SMM subsystem, initializes I/O protocol, calls sub_9E8
5. `sub_9E8` (0x9E8) -- registers sub_6CC as SMM communicate handler (65 = EFI_SMM_COMMUNICATE_HEADER) + notification callbacks
6. `sub_6CC` (0x6CC) -- the actual communicate handler servicing read/write/fill commands from the caller

## State Management

Global variables in .data segment:

| Address | Name | Purpose |
|---------|------|---------|
| 0x1A08 | qword_1A08 | gST (SystemTable) saved pointer |
| 0x1A10 | qword_1A10 | gBS (BootServices) saved pointer |
| 0x1A18 | qword_1A18 | gImageHandle saved pointer |
| 0x1A20 | qword_1A20 | gRT (RuntimeServices) saved pointer |
| 0x1A28 | qword_1A28 | gSmst (SMM Services Table) saved pointer |
| 0x1A30 | qword_1A30 | DebugLib protocol pointer (lazily resolved) |
| 0x1A38 | qword_1A38 | BootServices (local copy) |
| 0x1A40 | qword_1A40 | SMM Internal protocol interface |
| 0x1A48 | qword_1A48 | SmmBase2 protocol interface |
| 0x1A50 | byte_1A50 | Phase flag (1 = SMM, 0 = DXE) |
| 0x1A58 | qword_1A58 | SMM I/O protocol |
| 0x1A60 | byte_1A60 | Phase marker for protocol initialization |
| 0x1A68 | qword_1A68 | SMM DebugLib protocol |
| 0x1A70 | qword_1A70 | DXE I/O protocol |
| 0x1A78 | qword_1A78 | RuntimeServices (local copy) |
| 0x1A80 | qword_1A80 | DXE DebugLib protocol |
| 0x1A88 | qword_1A88 | SystemTable (local copy) |
| 0x1A90 | qword_1A90 | AmiBufferValidationLib protocol |
| 0x1A98 | byte_1A98 | CMOS register value scratch |
| 0x1B98 | qword_1B98 | Driver status (return value) |
| 0x1BA0 | qword_1BA0 | SmmCommunication protocol (resolved from gSmst) |
| 0x19F0 | qword_19F0 | SMM Communicate protocol interface |
| 0x19F8 | byte_19F8 | Data width field (1/2/4 bytes) |
| 0x19F9 | byte_19F9 | Disable flag (set by sub_93C) |
| 0x1A00 | qword_1A00 | Communicate buffer pointer (set by sub_9C0) |

## Recovered Naming Notes

- `qword_*`/`byte_*` entries in this table are documented with recovered semantic names in `LegacySmmSredir.c/.h`:
  `gST`, `gBS`, `gImageHandle`, `gRT`, `gSmst`, `gSmmMode`, `gSmmIoProtocol`,
  `gDataWidth`, `gCommunicateDisabled`, `gSmmCommunicateBuffer`, etc.

## Data Structures

- **Jump Buffer** at struct pointed to by sub_2A0 (0x2A0): 248 bytes = 8 GPRs (0x00-0x3F), return addr (0x40-0x47), call-thunk ptr (0x48), MXCSR (0x50), 10 XMM regs (0x58-0xE8)
- **SMM Communicate Buffer**: structured with command byte at +0 (1=read, 2=write, 3=fill), index at +2, data at +3, count at +4 (for fill), pointer at +5 (for fill source)
- **CMOS Register 0x4C**: byte at CMOS I/O ports 0x70/0x71; bit 0 determines legacy serial redirect support

## Command Protocol (sub_6CC handler)

The communicate handler at 0x6CC decodes commands from the buffer:

- **Case 1 (Read)**: Reads 8/16/32-bit value from `qword_1A00 + (index * width)` based on width field at +9; stores result at buffer+3
- **Case 2 (Write)**: Writes buffer+3 value to `qword_1A00 + (index * width)`
- **Case 3 (Block Fill)**: Repeatedly writes N bytes from source pointer (buffer+5) to indexed locations, count = buffer+4

Width (data element size) is determined by byte at +9: 1=byte, 2=word, 4=dword. All I/O is relative to the I/O base pointer stored in qword_1A00.

## Dependencies

### Consumed (this module calls SMM services)

- **SmmBase2 Protocol** (GUID at unk_19D0): entry point into SMM, provides SmmCommunicate
- **gSmst (SMM Services Table)** (offset 0x1A28): provides AllocatePool, LocateProtocol, InstallProtocolInterface, etc.
- **DebugLib Protocol** (GUID at unk_1940): provides DEBUG print and ASSERT support
- **AmiBufferValidationLib** (GUID at unk_1950): validates buffer addresses against GCD-allowed MMIO regions
- **SMM Internal Protocol** (GUID at unk_1960): provides SMM core internal services
- **I/O Protocol** (GUIDs at unk_19B0/unk_19C0): provides SMM or DXE I/O access
- **SMM Communicate Protocol** (GUID at unk_1930): for registering communicate handlers
- **SMM SW Dispatch Protocol** (GUID at unk_1970): for SMM software interrupt dispatch registration
- **SMM Notification protocols** (GUIDs at unk_1980/unk_19A0): for protocol notification callbacks
- **Hardware**: CMOS RTC ports 0x70/0x71, fixed memory address 0xFDAF0490 (hardwired platform config)

### Consumed By (other modules call this)

None directly -- this is a leaf SMM driver that installs protocols and handlers consumed by the SMM framework through its communicate handler registration.
