UEFI SMM (System Management Mode) driver for AHCI (Advanced Host Controller Interface) controller management. This module provides SMI-based AHCI port configuration, command execution, error handling, and device presence detection within the SMM environment. It is compiled from AmiModulePkg/AHCI/AhciSmm/AhciSmm.c and resides in the DXE_SMM_DRIVER dispatch phase. The driver manages AHCI ports via MMIO register access, SATA FIS (Frame Information Structure) processing, port multiplier support, and generates SMI callbacks for ATA command execution in SMM.
0x2A0 - 0x2830 (41 functions)
| Address | Name | Purpose |
|---|---|---|
| 0x470 | _ModuleEntryPoint | UEFI/SMM driver entry point |
| 0x49C | AhciSmmPreInit | UEFI boot/run-time services table initialization |
| 0x5DC | AhciSmmRegisterSmiHandlers | Main driver dispatch: lock, init, register SMI handler |
| 0x2150 | AhciSmmInitialize | SMM driver initialization: locate protocols, init H/W, install SMI handlers |
| 0x1F0C | AhciSmmRegisterCallback | SMI handler registration: allocate buffers, register SMI callback via SMM base2 |
| 0x13F4 | AhciGenerateSoftReset | Soft reset generation for AHCI port |
| 0x1F04 | AhciPortSoftResetThunk | Thunk to sub_13F4 (soft reset) |
| 0x19FC | AhciCommandCompleteType : DetectAtaDeviceType | ATA command completions: read FIS, detect PMP/SATA/ATAPI device type |
| 0x1BB8 | AhciNonDataCommandHandler | ATA non-data command execution (identify device, etc.) |
| 0x1648 | AhciPioDataInCommand | ATA PIO data-in command execution |
| 0x17C0 | AhciDmaDataCommand | ATA DMA command execution |
| 0x1914 | AhciSoftwareResetCommand | ATA software reset execution |
| 0x1D60 | AhciControllerInit | AHCI controller initialization (HBA reset, port config) |
| 0x1EBC | AhciFisReceiveHandler | Port FIS receive / command completion dispatch |
| 0xC0C | AhciPortCommandComplete | Port command completion handler (FIS receive + SDB notify) |
| 0xE30 | AhciPortStartStop | AHCI port start/stop (command list activation, PxCMD.PxRUN) |
| 0x1014 | AhciCheckDevicePresenceAndRecover | Port PMP status check and error recovery via sub_C0C |
| 0x1274 | AhciPmpRegisterAccess | Port multiplier register access (PMP SATA register read/write) |
| 0x9D0 | AhciPortResetSequence | Port reset sequence (wait for device ready, signature, PxSIG) |
| 0x91C | AhciIssuePortCommand | Command issue helper: write PxCMD, clear SError, trigger port start |
| 0x11BC | AhciBuildCommandFis | Command list entry setup (FIS frame format into PRDT) |
| 0x111C | AhciBuildPrdt | Command scatter-gather list construction (PRDT entries) |
| 0x10C8 | AhciCopyReceivedFis | FIS shadow area copy (16 bytes from command table to RFIS) |
| 0x107C | AhciInitCommandHeader | Command header initialization (clear PRD region, set PxISA) |
| 0x7D0 | AhciPollForCommandCompletion | Polling loop for command completion / error (PxIS, PxSERR, timeout) |
| 0x75C | AhciWaitForBitClear | MMIO register bit wait loop (poll for bit clear with timeout) |
| 0x6E4 | AhciWaitForBitMatch | MMIO register bit match polling (poll for specific bit pattern) |
| 0x9D0 | AhciGetPortSignature | Port signature read (poll PxSIG for device type detection) |
| 0x690 | AhciUsDelay | Microsecond delay based on ACPI PM timer (port 0x508) |
| 0x2720 | AhciMemset | memset implementation (aligned dword fill with residual) |
| 0x2780 | AhciMemmove | memmove implementation (overlap-aware, aligned copy) |
| 0x2314 | AhciDebugPrint | Debug logging (vprintf to SMM debug output) |
| 0x235C | AhciDebugAssert | ASSERT implementation (conditional via debug protocol) |
| 0x22C4 | AhciLocateDebugProtocol | SMM debug protocol locator (locate gEfiSmmDebug2ProtocolGuid) |
| 0x239C | AhciLocatePcdProtocol | PCD protocol locator (DxePcdLib, locate mMdePkgPcd) |
| 0x2428 | AhciInstallChildProtocol | SMM child protocol installation (SmmBase2 vs BootServices LocateProtocol) |
| 0x24B0 | AhciInstallSmiHandlerProtocol | SMI handler protocol installation (SmmBase2 or standalone) |
| 0x2594 | AhciResolveRuntimeServices | Runtime services pointer resolution via SMM system table |
| 0x2604 | AhciMemcmpPattern | memcmp implementation (byte compare against fixed pattern) |
| 0x2680 | AhciReadDebugLevelFromCmos | CMOS/CMOS register read for platform debug level detection |
| 0x2A0 | AhciSetJump | SetJump wrapper (save non-volatile register context) |
| 0x340 | AhciLongJump | LongJump wrapper (restore context via saved frame) |
| 0x227C | AhciValidateJumpFrame | Jump buffer validation (alignment check for SetJump) |
0x470 _ModuleEntryPoint: Standard UEFI SMM driver entry point. Calls AhciSmmPreInit (sub_49C) to initialize UEFI boot/runtime services globals, then calls AhciSmmRegisterSmiHandlers (sub_5DC) which handles the SMM dispatch table registration.
0x2150 AhciSmmInitialize (sub_2150): SMM driver initialization. Locates gEfiSmmCpuIo2ProtocolGuid protocol at GUID unk_2E30, probes presence via call into qword_2EB0+8, resolves runtime services via AhciResolveRuntimeServices (sub_2594), installs child protocols via AhciInstallChildProtocol (sub_2428) and AhciInstallSmiHandlerProtocol (sub_24B0), then calls AhciSmmRegisterCallback (sub_1F0C) to register the SMI handler.
0x1D60 AhciControllerInit (sub_1D60): AHCI controller HBA-level initialization. Programs port registers (PxCMD start, PxIE interrupt enable, PxSERR clear, PxCFG), sets command list/FIS base addresses via qword_3018. Called via function pointer stored at pAhciPortInitHandler (0x3070).
AHCI Low-Level MMIO:
0x75C AhciWaitForBitClear (sub_75C): Polls an AHCI port MMIO register, waiting for a bitmask to clear with configurable timeout. Base register = a1 + ((a2 + 2) << 7) where a2 is port number.0x6E4 AhciWaitForBitMatch (sub_6E4): Polls an AHCI port MMIO register, waiting for (reg_value & mask) == match_value. Used for status transitions.0x690 AhciUsDelay (sub_690): Microsecond delay using ACPI PM timer I/O port 0x508. Calculates delay based on timer ticks.0x1274 AhciPmpRegisterAccess (sub_1274): SATA port multiplier register access. Builds a PMP register read/write FIS, sends it via command list, waits for completion, reads result from RFIS buffer.Command Processing Pipeline:
0x11BC AhciBuildCommandFis (sub_11BC): Builds a command list entry (49 bytes FIS frame starting at a4+0). Sets command FIS type, port multiplier, ATA registers (features, sector count, LBA, command). Sets CFL=5 and W=1 bits in PxCMD.0x111C AhciBuildPrdt (sub_111C): Constructs PRDT (Physical Region Descriptor Table) entries. Walks the data buffer scatter-gather list, setting DBA/DBC/DI bits per 4MB-aligned region. Last entry gets EOF flag.0x107C AhciInitCommandHeader (sub_107C): Initializes a command header slot. Zeroes PRD region. Sets PxISA (port multiplier) bits. Sets PRDTL (PRD table length).0x10C8 AhciCopyReceivedFis (sub_10C8): Copies 16 bytes from command FIS to received FIS (RFIS) area in the command table. Handles overlap-safe copy.ATA Command Execution:
0x1648 AhciPioDataInCommand (sub_1648): ATA PIO data-in command (READ SECTOR(S), IDENTIFY, etc.). Calls AhciPortStartStop (sub_E30) (port start), AhciCheckDevicePresenceAndRecover (sub_1014) (PMP check), builds FIS, issues command, polls completion via AhciPollForCommandCompletion (sub_7D0).0x17C0 AhciDmaDataCommand (sub_17C0): ATA DMA command (READ DMA, WRITE DMA). Similar flow to PIO but for DMA transfers.0x1914 AhciSoftwareResetCommand (sub_1914): ATA software reset command. Sends SRST via command list, polls completion.0x1EBC AhciFisReceiveHandler (sub_1EBC): Port FIS receive handler. Extracts port number and PMP status from register, dispatches to AhciPortCommandComplete (sub_C0C) for command completion processing.0x1BB8 AhciNonDataCommandHandler (sub_1BB8): ATA non-data command execution. Used for IDENTIFY DEVICE, SET FEATURES, etc. Builds FIS, issues command, polls completion. On error with specific conditions, retries via AhciCommandCompleteType (sub_19FC).AHCI Port Management:
0xE30 AhciPortStartStop (sub_E30): Port start/stop. Saves/restores command list and FIS base addresses (stored in qword_3010/qword_3018). Stops PxCMD.PxRUN, clears PxCMD.ST, calls AhciPortCommandComplete (sub_C0C) for error recovery if needed, restores base registers.0x91C AhciIssuePortCommand (sub_91C): Port command issue. Clears PxSERR, sets PxIE, starts port via PxCMD.PxRUN, waits for PxCMD.PxGO. Clears command slot and receiver buffers.0x7D0 AhciPollForCommandCompletion (sub_7D0): Command completion polling. Monitors PxIS (interrupt status) and PxSERR (error status) with timeout. Returns error on BSY/DRQ bits or timeout.0x1014 AhciCheckDevicePresenceAndRecover (sub_1014): Checks port multiplier status (PxSSTS.DET). If device not present, returns success. If error, calls AhciPortCommandComplete (sub_C0C) for recovery.Debug and Error Handling:
0x2314 AhciDebugPrint (sub_2314): Debug/log message printf. Calls AhciLocateDebugProtocol (sub_22C4) to get SMM debug2 protocol, checks debug mask from AhciReadDebugLevelFromCmos (sub_2680), and prints via protocol's vprintf.0x235C AhciDebugAssert (sub_235C): ASSERT implementation. Calls AhciLocateDebugProtocol (sub_22C4) for debug protocol, then calls the protocol's assert handler with file/line/message.0x22C4 AhciLocateDebugProtocol (sub_22C4): Locates gEfiSmmDebug2ProtocolGuid via SMM system table. Caches in qword_2E98.0x2680 AhciReadDebugLevelFromCmos (sub_2680): Reads CMOS register 0x4C to determine platform debug level. Returns EFI debug masks (0x8000000C or 0x80000006) based on value.0x2604 AhciMemcmpPattern (sub_2604): memcmp against a fixed pattern at unk_2E40 (16 bytes). Used for runtime services table scanning.0x2594 AhciResolveRuntimeServices (sub_2594): Resolves EFI runtime services pointer by scanning SMM system table's SMM runtime services table for a non-NULL entry.Port Reset:
0x9D0 AhciPortResetSequence (sub_9D0): Complete port reset sequence. Polls PxSIG for device signature (ATA, ATAPI, PMP), waits for PxCMD.PxGO and BSY clear, checks PxSERR error bits. Returns status based on device detection.0x13F4 AhciGenerateSoftReset (sub_13F4): Soft reset. Stops port, sends SRST FIS, waits for completion, starts port, checks signature.0xC0C AhciPortCommandComplete (sub_C0C): Port command completion handler. Called by AhciFisReceiveHandler (sub_1EBC). Programs the command list base, clears PxSERR, sends SDB (Set Device Bits) FIS notification, triggers port reset via AhciPortResetSequence (sub_9D0) if needed. Works with port multipliers.Library Functions:
0x2720 AhciMemset (sub_2720): memset - aligned dword fill with residual byte fill.0x2780 AhciMemmove (sub_2780): memmove - overlap-safe memory copy. Checks src/dst overlap direction (forward/backward), uses aligned qword copy for large blocks.0x2A0 AhciSetJump (sub_2A0): SetJump - saves all non-volatile registers (rbx, rbp, rdi, rsi, r12-r15), MXCSR, and XMM6-XMM15. Stores at offset 0x72 for return address.0x340 AhciLongJump (sub_340): LongJump - restores MXCSR from saved frame, jumps to saved return address.SMM Protocol Cache (initialized in AhciSmmPreInit/AhciSmmInitialize):
qword_2E80 (0x2E80): gImageHandle (cached)qword_2E70 (0x2E70): gST (SystemTable)qword_2E78 (0x2E78): gBS (BootServices)qword_2E88 (0x2E88): gRT (RuntimeServices)qword_2E90 (0x2E90): gSmst (SMM System Table)qword_2EA0 (0x2EA0): mPcd (PCD protocol, resolved lazily)SMM Driver Globals (initialized in AhciSmmInitialize):
qword_2EB0 (0x2EB0): SMM CPU I/O2 protocol instancebyte_2EB8 (0x2EB8): SMM mode flag (1 = SMM, 0 = DXE)qword_2EE8 (0x2EE8): SmmServicesTableBase2 protocolqword_2EC0 (0x2EC0): SMM child protocol (in SMM)qword_2ED8 (0x2ED8): Protocol in DXE (BootServices)qword_2ED0 (0x2ED0): SMI handler protocol (in SMM)qword_2EF0 (0x2EF0): SMI handler protocol (in DXE)byte_2EC8 (0x2EC8): Protocol ready flagAHCI Hardware State:
qword_3010 (0x3010): Saved PxCLB (command list base address) during port stopqword_3018 (0x3018): Saved PxFB (FIS base address) during port stopqword_3008 (0x3008): Driver return statusbyte_2E60 (0x2E60): Reentry guard for sub_C0C (port complete handler)byte_2E61 (0x2E61): Reentry guard for sub_13F4 (soft reset)dword_3020 (0x3020): SMI callback registration handleSMI Handler Function Pointers (at 0x3070-0x30A0):
pAhciPortInitHandler (0x3070): AhciControllerInit (HBA initialization handler)pAhciDmaCommandHandler (0x3078): AhciDmaDataCommand (ATA DMA command handler)pAhciPioDataInHandler (0x3080): AhciPioDataInCommand (ATA PIO data-in command handler)pAhciSoftwareResetHandler (0x3088): AhciSoftwareResetCommand (ATA software reset handler)pAhciNonDataCommandHandler (0x3090): AhciNonDataCommandHandler (ATA non-data command handler)pAhciFisReceiveHandler (0x3098): AhciFisReceiveHandler (FIS receive / command completion handler)pAhciSoftResetHandler (0x30A0): AhciPortSoftResetThunk (ATA soft reset port-level handler)Buffers (allocated in AhciSmmRegisterCallback / sub_1F0C):
buf at qword_2E68 (0x2E68): 256-byte buffer for command response dataqword_3038 (0x3038): 256-byte command list for SMMqword_3030 (0x3030): 1024-byte AHCI receive areaqword_3028 (0x3028): 1152-byte AHCI command tableAHCI Port Context (a1 pointer, at least 40 bytes):
Offset | Size | Field | Description |
--------|------|-------|-------------|
+0 | 4 | HBA_BASE | AHCI controller MMIO base address |
+4 | 4 | RESERVED | Padding |
+8 | 8 | RFIS_BUF_NEXT | Received FIS buffer physical address (next slot) |
+16 | 8 | CMD_LIST | Command list physical address |
+24 | 4 | CMD_TBL_SIZE | Command table size (upper 32 bits of RFIS address) |
+28 | 4 | port_status | Port status / register value |
+32 | 1 | port | Port number |
+33 | 1 | port_mult | Port multiplier (0xFF = none) |
+34 | 2 | RESERVED | Padding |
+36 | 4 | timeout | Timeout value in milliseconds |
AHCI Port Register Layout (per port, 128 bytes each, base + (port+2) << 7):
Offset | Register | Description |
--------|----------|-------------|
+0 | PxCLB | Command list base address (lower 32 bits) |
+4 | PxCLBU | Command list base address (upper 32 bits) |
+8 | PxFB | FIS base address (lower 32 bits) |
+12 | PxFBU | FIS base address (upper 32 bits) |
+16 | PxIS | Interrupt status register |
+20 | PxIE | Interrupt enable register |
+24 | PxCMD | Command and status register |
+28 | RESERVED | - |
+32 | PxSSTS | Serial ATA status (SCR0) |
+36 | PxSCTL | Serial ATA control (SCR2) |
+40 | PxSERR | Serial ATA error (SCR1) |
+44 | PxSACT | Serial ATA active (SCR3) |
+48 | PxCI | Command issue register |
+52 | PxSNTF | Serial ATA notification (SCR4) |
+56 | PxFBS | FIS-based switching |
FIS Frame Structure (49 bytes, built by sub_11BC):
Offset | Size | Field |
--------|------|-------|
+0 | 1 | FIS type (0x27 = register H2D) |
+1 | 1 | PM port (lower nibble) + C=1 bit |
+2 | 1 | Command (CFL in upper nibble) |
+3 | 1 | Features |
+4 | 1 | Sector count (byte 0) |
+8 | 1 | Sector count (byte 1) |
+12 | 1 | LBA low (byte 0) |
+13 | 1 | LBA low (byte 1) |
+14 | 1 | LBA mid (byte 0) |
+15 | 1 | LBA mid (byte 1) |
+16 | 1 | LBA high (byte 0) |
+17 | 1 | LBA high (byte 1) |
+18 | 1 | Device register |
+19 | 1 | Command register |
+20 | 1 | Reserved |
+21 | 1 | Reserved |
+22 | 1 | Control (0xA0 = device reset) |
+23 | 1 | Reserved (low bit = PM port valid) |
Jump Buffer Structure (248+ bytes, managed by sub_2A0/sub_340):
Offset | Register |
--------|----------|
+0 | rbx |
+8 | Return address (from retaddr) |
+16 | rbp |
+24 | rdi |
+32 | rsi |
+40 | r12 |
+48 | r13 |
+56 | r14 |
+64 | r15 |
+72 | Function pointer (return target) |
+80 | MXCSR |
+88 | xmm6 |
+104 | xmm7 |
+120 | xmm8 |
+136 | xmm9 |
+152 | xmm10 |
+168 | xmm11 |
+184 | xmm12 |
+200 | xmm13 |
+216 | xmm14 |
+232 | xmm15 |
Driver Entry and Initialization:_ModuleEntryPoint -> AhciSmmPreInit (sub_49C) (init UEFI globals) -> AhciSmmRegisterSmiHandlers (sub_5DC) (main dispatch)
SMM Driver Registration (AhciSmmRegisterSmiHandlers flow):AhciSmmRegisterSmiHandlers (sub_5DC) -> AhciSetJump (sub_2A0) (SetJump/lock) -> AhciSmmInitialize (sub_2150) (init SMM) -> AhciValidateJumpFrame (sub_227C) (validate) -> AhciLongJump (sub_340) (LongJump/unlock)
SMM Initialization Chain (AhciSmmInitialize):AhciSmmInitialize (sub_2150) -> AhciLocatePcdProtocol (sub_239C) (PCD) -> LocateProtocol(SmmCpuIo2) -> Probe -> AhciResolveRuntimeServices (sub_2594) (Runtime) -> AhciInstallChildProtocol (sub_2428) (child proto) -> AhciInstallSmiHandlerProtocol (sub_24B0) (SMI handler) -> AhciSmmRegisterCallback (sub_1F0C) (register callback)
SMI Handler Registration (AhciSmmRegisterCallback):
Allocate buffer -> zero -> AhciMemset (sub_2720) -> Set function pointers -> Locate SMM base2 -> Register SmiHandler with GUID unk_2DF0 -> Return
ATA Command Execution Flow:AhciPioDataInCommand/AhciDmaDataCommand/AhciSoftwareResetCommand/AhciNonDataCommandHandler:
AhciPortStartStop (sub_E30) (start port, arg=1)AhciCheckDevicePresenceAndRecover (sub_1014) (PMP check)AhciInitCommandHeader (sub_107C) (init cmd header)AhciBuildCommandFis (sub_11BC) (write FIS to command list)AhciIssuePortCommand (sub_91C) (issue command / start DMA)AhciPollForCommandCompletion (sub_7D0) (poll for completion)AhciPortStartStop (sub_E30) (stop port, arg=0)Command Completion Path:AhciFisReceiveHandler (sub_1EBC) -> AhciPortCommandComplete (sub_C0C) -> AhciPortResetSequence (sub_9D0) (port reset if error)
Debug Logging:AhciDebugPrint (sub_2314) -> AhciLocateDebugProtocol (sub_22C4) (locate debug protocol) -> AhciReadDebugLevelFromCmos (sub_2680) (check CMOS debug level) -> protocol vprintf
Soft Reset Flow:AhciGenerateSoftReset (sub_13F4) (or thunked via AhciPortSoftResetThunk (sub_1F04)):
byte_2E61)AhciPortStartStop (sub_E30) (start port)sub_107C + sub_11BC (build SRST FIS)AhciIssuePortCommand (sub_91C) (issue)AhciUsDelay (sub_690) (100us delay)AhciPollForCommandCompletion (sub_7D0) (poll command completion with 30s timeout)AhciPortStartStop (sub_E30) (stop port)AhciSmm.h stores recovered symbol declarations, global state mapping, and protocol/function dispatch aliases.AhciSmm.c stores recovered runtime scaffolding and stubbed entrypoint implementations used to anchor symbol recovery.sub_22C4 locates at unk_2DE0 (gEfiSmmDebug2ProtocolGuid), used for assert/debug printsub_2150 locates at unk_2E30, used for SMM I/O operationssub_239C locates at unk_2DD0 (gEfiPcdProtocolGuid)sub_690sub_2680sub_2594 for EFI runtime services pointer_ModuleEntryPoint as standard SMM driver entry pointsub_1F0C) is invoked by the SMM core when the AHCI SMI is triggeredbyte_2EB8. In DXE mode, it uses BootServices directly; in SMM mode, it uses SmmServicesTableBase2.port_mult == 0xFF meaning no PMP, otherwise 0-15.base + ((port + 2) << 7) for 128-byte port register blocks.