Newer
Older
AMI-Aptio-BIOS-Reversed / AmiModulePkg / LegacySerialRedirection / LegacySmmSredir / LegacySmmSredir.md
@Ajax Dong Ajax Dong 2 days ago 7 KB Full restructure

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 Standard UEFI SMM driver entry; calls init then dispatch
0x44C sub_44C AutoGen library init: saves ImageHandle, SystemTable, BootServices, RuntimeServices; locates SmmBase2 protocol and SMM buffer validation protocol
0x618 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)

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.