Newer
Older
AMI-Aptio-BIOS-Reversed / PiSmmCpuDxeSmm / PiSmmCpuDxeSmm.md
@Ajax Dong Ajax Dong 2 days ago 7 KB Init

PiSmmCpuDxeSmm

Function Table

Address Name Description
_ModuleEntryPoint
SmmInit
SmiHandlerDispatch
SmmRestoreCpu
InitMp
ProgramRegisterTable
InitPaging
DebugPrint
AssertBreak
PciExpressAddress
AcquireSpinLock
ReleaseSpinLock
SmiHandlerFeatureMsr
SendSmiIpi
StartupAP
GetCpuIndex
IsCpuSandyBridge
IsCpuKnightsLanding
IsCpuIvyTown
CpuDeadLoop
Global data initialized at module entry
EFI_HANDLE gImageHandle = NULL; // 0x108F0
0x10698 - SystemTable alias
0x108E8 UINT64 gSmst = NULL; // 0x10900 - SMM System Table (gSmst)
0x10908 UINT64 gPciExpressBase = 0; // 0x10910 - PCIe config base address
0x10920 //
SMM S3 Resume State - pointer to S3 resume structure in SMRAM
Checked by SmmRestoreCpu() at 0x1C3C for:
Signature "SMM_S_32" (0x32335F33534D4D53) -> use AsmDisablePaging64
Signature "SMM_S_64" (0x34365F33534D4D53) -> use SwitchStack
SMM_S3_RESUME_STATE *mSmmS3ResumeState = NULL; // 0x10690
CPU configuration
UINT32 mNumberOfCpus = 0; // 0x118A4
0x118A0 UINT32 mCpusExiting = 0; // 0x11870 - APs remaining to finish init
0x118C8 UINT64 mStartupRoutine = 0; // 0x11880
0x11878 UINT64 mGdtBuffer = 0; // 0x11898
0x118A8 UINT64 mGdtrProfile = 0; // 0x11888
0x11890 UINT64 mPreSmmInitRegisterTable = 0; // 0x118B0
0x118B8 UINT64 mGdtForAp = 0; // 0x118C0
0x11910 UINT8 mApStartPhase = 0; // 0x11918
UINT64 mGdtForApAlloc = 0; // 0x10890
0x10898 UINT64 mExcptHandlerAlloc = 0; // 0x108A0
MSR Spin Locks
UINT64 mMsrSpinLocks = 0; // 0x108A8 - base address
0x108B0 UINT64 mMsrSpinLockMax = 0; // 0x105F0
CPU enabling bitmap
UINT64 mCpuEnabledBitmap = 0; // 0x108B8
State flags
UINT8 mGdtIdtReady = 0; // 0x10888
0x10889 UINT8 mSmrrConfigured = 0; // 0x118E9
Exception handler base/length
UINT64 mExceptionHandlerBase = 0; // 0x10970
SMM CPU private data array (off_10378 at 0x10378)
An 11-entry array of pointers to per-CPU SMM data:
volatile UINT64 gSmmCpuPrivate = (volatile UINT64 )0x10378;
0xB90 SmmEntryPointSaveHandles(ImageHandle); // sub_C4C
qword_10788 = 0x8000000000000001
Lock acquired - we are the first to init
sub_2390 **if (gStatus >= 0 gStatus < 0) { // always true after init**
preserve status
Debug asserts for build info
0x2390 - Entry
Extensive initialization sequence spanning SmmFeatures.c
Step 1: Initialize SMM protocol interfaces
Locate SMM System Table (gSmst) at qword_10900
Register communication handler
Set up SMI entry/exit
Step 2: CPU detection
CPUID to determine CPU family (SNB/HSW/SKX/KNL/IVT)
Step 3: Page table initialization
Step 4: Long mode setup
Step 5: MP data initialization
Step 6: SMM features initialization
Registers SmiHandlerDispatch() as SwSmiHandler
Registers SmiHandlerFeatureMsr() for feature MSR access
Step 7: MP wake and startup
Start APs with StartupRoutine
Each AP calls ProgramRegisterTable() for its register table entries
Wait for all APs via mCpusExiting counter
0x3BD0 UINT64 MsrValue;
Check CPU model and dispatch to correct MSR handling
Not SNB/HSW/SKX - try other models
sub_A0DC if (ReadWrite == 0) {
Read 0x4107C
Write to 0x41050/0x41054
IVT MSR handling at 0x4115x - 0x4117x range
0x1C3C SMM_S3_RESUME_STATE *S3State;
qword_10690 if (S3State == NULL) {
Save IDT, set up page tables, init exception handler
sub_B45C if (EFI_ERROR(Status)) {
Initialize interrupt state for APs
sub_524C LaunchS3Resume(); // sub_1A90
Program register table for BSP
sub_4F70 // Set up return state
Set return function
GDT pointer
Return function
Start APs with SIPI
Determine resume method based on signature
sub_8384 }
0x2110 ACPI_CPU_DATA *AcpiCpuData;
Get ACPI CPU data via protocol
sub_8AA8 // Allocate and copy MTRR table
sub_9C8C CopyMem(mMtrrTable, *(AcpiCpuData->MtrrTable), 608);
Allocate and copy GDTR profile
Allocate and copy IDTR profile
Allocate and copy PreSmmInitRegisterTable (24 bytes per CPU)
Allocate and copy RegisterTable (24 bytes per CPU)
Allocate combined GDT/IDT/Exception handler region
0x4F70 // Entry processing:
Count == 1: BitField read -> modify -> write
Read MSR, mask StartBit..StartBit+BitsLength-1, write Value
Uses BitFieldRead64/Write64 then CR writes (sub_410=cr0, sub_420=cr3, etc.)
Count == 3: Cache maintain (wbinvd or just clean)
Count == 0 && BitsLength < 0x40:
Look up MSR in mMsrSpinLocks, acquire lock, read/modify/write MSR, release
Count == 0: direct write via __writemsr()
0x314C // 1. Get SMM Access2 Protocol
0x9AA4 // 1. Check if Format is NULL -> ASSERT
0x9B78 // AsciiSPrint("ASSERT [%a] %a(%d): %a\n", ...)
Then break via SerialPortWrite
0x9BCC if ((Address & ~0xFFFFFFF) != 0) {
0xA0DC // Check if already acquired via IsSpinLockAcquired
If not:
StartTime = ReadTsc()
Timeout = 10000000 * gTimerPeriod / 0xF4240
while not acquired:
if (elapsed >= Timeout) ASSERT
0xA20C // ASSERT(SpinLock != NULL)
0x4344 // Same dispatch pattern as SmiHandlerDispatch but
specifically handles MSR read/write at:
0x41058 (KNL read)
0x4107C (KNL status)
0xA598 // if (GetApicMode() == xAPIC) {
Save eflags, cli
Write APIC ICR register via memory-mapped APIC
Wait for ICR to be accepted
x2APIC mode: use MSR 0x830
0xA78C // ASSERT(StartupRoutine < 0x100000)
Send INIT IPI (0xC4500 = delivery + INIT)
Delay 10ms
Send SIPI with startup page
Delay 200us
Send SIPI again
0xA6C4 // if (GetApicMode() != 1) {
return GetApicId(); // x2APIC: APIC ID == CPU index
CPUID leaf 0xB: get x2APIC ID
If leaf 0xB available:
CPU Feature Checks
0x3694 INT32 CpuVersion;
sub_470 CpuVersion &= 0xFFF0FF0;

Generated by HR650X BIOS Decompilation Project