# CpuMpDxe

## Function Table

| Address | Name | Description |
|---------|------|-------------|
|  | **CpuMpAssertInternal** |  |
|  | **GetPcdValue** |  |
|  | **IoRead8** |  |
|  | **IoWrite8** |  |
|  | **CpuMpMicroSecondDelay** |  |
|  | **CpuMpQueryTimer** |  |
|  | **BitFieldRead32** |  |
|  | **CpuMpDebugPrint** |  |
|  | **CpuMpAssert** |  |
|  | **DetectUartBaudRate** |  |
|  | **DetectCmosPage** |  |
|  | **WaitUartReady** |  |
|  | **InitializeDriverServices** |  |
|  | **ProcessorConfigInit** |  |
|  | **SelectCpuFeatures** |  |
|  | **InitDataCollection** |  |
|  | **CpuMpDxeInit** |  |
|  | **StartAllCpus** |  |
|  | **StartCpu** |  |
|  | **SaveS3BootScript** |  |
|  | **CpuMpDxeUnload** |  |
|  | **CpuMpDxeDriverEntry** |  |
|  | **ModuleEntryPoint** |  |
| Global | **UEFI table pointers** |  |
| EFI_HANDLE | **gImageHandle        = NULL;** |  |
| CpuConfigLib | **runtime context (allocated per-cpu config buffer)** |  |
| VOID | ***mCpuConfigLibConfigContextBuffer = NULL;** |  |
| MP | **System Data globals** |  |
| UINT64 | **mMpNumberOfCpus          = 0;   ///< qword_28340** |  |
| MACHINE_CHECK_ATTRIBUTE | ***mMachineCheckAttribute   = NULL; ///< qword_282E8** |  |
| Boot | **performance measurement** |  |
| UINT64 | **mBootTimeTimer = 0;               ///< qword_17F58** |  |
| CPUID | **feature bitmasks (AND-reduced across all CPUs)** |  |
| UINT32 | **mCpuFeatureEdx     = 0xFFFFFFFF;  ///< dword_18280** |  |
| Driver | **binding handle and processor configuration** |  |
| EFI_HANDLE | **mDriverBindingHandle  = NULL;     ///< qword_17DD0** |  |
| MP | **System Data (the aggregate mMPSystemData structure)** |  |
| MP_SYSTEM_DATA | **mMPSystemData;** |  |
| Offset | **32 = Get64** |  |
| Offset | **48 = Set64** |  |
| The | **decompiled code shows 8254 PIT-based delay via IO port 0x43/0x40.** |  |
| This | **is a simplified implementation.** |  |
| UINT64 | **Start;** |  |
| Timestamp | **counter** |  |
| ASSERT | **from BaseLib: EndBit < 32, StartBit <= EndBit** |  |
| if | **(EndBit >= 32) {** |  |
| BaseMemoryLibRepStr | **CopyMemWrapper.c asserts:** |  |
| if | **((Length - 1) > ~(UINTN)Destination) {** |  |
| Read | **CMOS debug level from offset 0x4B.** |  |
| CMOS | **index 0x70 bit 7 preserves NMI; offset 0x4B = BIOS debug level.** |  |
| CmosIndex | **= __inbyte (0x70);** |  |
| Serial | **port debug output via DebugPort protocol.** |  |
| VSPrint | **(Buffer, sizeof (Buffer), Format, Args);** |  |
| Output | **via serial port (I/O 0x3F8).** |  |
| for | **(CHAR8 *Ch = Buffer; *Ch != '\0'; Ch++) {** |  |
| Read | **CMOS index 0x5C for the base baud rate selector, then index 0x6C** |  |
| for | **the extended byte.** |  |
| IoWrite8 | **(0x72, 0x5C);** |  |
| unk_1C200 | **case 0xA6:  BaudRate = 57600;  break;** |  |
| Compute | **the actual baud rate divisor.** |  |
| Reference | **clock = 0x1C200 = 115200 (standard UART clock).** |  |
| return | **0x1C200 / BaudRate;** |  |
| LSR | **port (COM1 + 5 = 0x3FD for standard, or dynamic)** |  |
| Poll | **LSR until bits 5 and 6 are both set.** |  |
| do | **{** |  |
| Locate | **the DXE Services Table.  This is the standard library constructor** |  |
| that | **the DxeServicesTableLib performs at module startup.** |  |
| Status | **= gDS->Dispatch ();** |  |
| ASSERT | **on failure.** |  |
| if | **(EFI_ERROR (Status)) {** |  |
| Locate | **the MM PCI Base protocol (DxeMmPciBaseLib).** |  |
| This | **provides the MmPciBase (mPciUsra) for memory-mapped PCI config access.** |  |
| if | **(mPciUsra == NULL) {** |  |
| GUID | **from CpRcPkg** |  |
| Initialize | **per-CPU context blocks (zero-initialized from allocation).** |  |
| The | **C code also initializes lists at unk_17C80 and unk_17D00.** |  |
| for | **(Index = 0; Index < NumberOfCpus; Index++) {** |  |
| Allocate | **a 4KB config buffer (one physical page) for processor config I/O.** |  |
| This | **is used for communicating configuration data between BSP and APs.** |  |
| ConfigPagesAddress | **= 0xFFFFFFFFFFFFFFFFULL;** |  |
| 1 | **page = 4KB** |  |
| Initialize | **the config buffer header.** |  |
| CpuListHeads | **= (UINT64 *)(UINTN)ConfigPagesAddress;** |  |
| Buffer | **size (32K)** |  |
| Mark | **CPUs in the config buffer.** |  |
| The | **original code writes 1 to the marker dword.** |  |
| for | **(BufferIndex = 0; BufferIndex < NumberOfCpus; BufferIndex++) {** |  |
| Allocate | **per-CPU data array (1088 bytes each) - qword_28350** |  |
| mMpCpuList | **= (UINT64 *)CpuMpAllocatePool ((UINTN)(1088 * NumberOfCpus));** |  |
| Allocate | **linked list heads (16 bytes each) - qword_28358** |  |
| Initialize | **each as an empty doubly-linked list.** |  |
| LinkedListHeads | **= (UINT64 *)CpuMpAllocatePool ((UINTN)(16 * NumberOfCpus));** |  |
| Allocate | **per-CPU flags array (32 bytes each) - qword_28368** |  |
| mMpPerCpuData | **= (UINT64)CpuMpAllocatePool ((UINTN)(32 * NumberOfCpus));** |  |
| Allocate | **per-CPU flags shadow array (32 bytes each) - qword_28360** |  |
| CPU | **index array: initialize with sequential indices - qword_28370** |  |
| mMpCpuIndexArray | **= (UINT64)CpuMpAllocatePool ((UINTN)(24 * NumberOfCpus));** |  |
| Report | **CPU count to CpuConfigLib via PCD 151.** |  |
| This | **connects the config context to the library's internal tracking.** |  |
| Status | **= SetPcdValue (151, NumberOfCpus);** |  |
| Allocate | **per-CPU feature arrays** |  |
| mMachineCheckAttribute | **= 128 bytes per CPU (qword_282E8)** |  |
| 16 | **UINT64 per CPU** |  |
| mThermalMgmtCapability | **= 1 byte per CPU (qword_282B8)** |  |
| mMaxCStateValue | **= 8 bytes per CPU (qword_18260)** |  |
| mMicrocodeInfo | **= 24 bytes per CPU (qword_28300)** |  |
| mLtSupported | **= 1 byte per CPU (qword_282F0)** |  |
| mMsrValue | **= 8 bytes per CPU (qword_282F8)** |  |
| Connect | **the global config context buffer pointer for CpuConfigLib.** |  |
| This | **pointer is stored in qword_17FC8 and is used by multiple library functions.** |  |
| mCpuConfigLibConfigContextBuffer | **= (VOID *)mMpCpuList;** |  |
| Read | **PCD 155 for platform type and store it.** |  |
| Initialize | **feature masks to all-ones (all features assumed present** |  |
| until | **a CPU clears a bit).** |  |
| mCpuFeatureEdx | **= 0xFFFFFFFF;** |  |
| Read | **CPUID leaf 0x1 from CpuConfigLib.** |  |
| CpuidRegisters | **= (CPUID_REGISTERS *)CpuConfigLibGetCpuid (** |  |
| Read | **CPUID leaf 0x80000001 for extended features.** |  |
| mCpuFeatureExtEdx | **&= CpuidRegisters->Edx;** |  |
| Read | **PCD 146 (CPU data collection enable flag) and set bit 1.** |  |
| Check | **PCD 147 for a specific feature enable flag (bit 1).** |  |
| Enable | **the feature in PCD 145.** |  |
| PcdValue | **= GetPcdValue (145);** |  |
| Step | **1: Read platform type from CpuConfigLib (PCD 155).** |  |
| This | **determines which feature set to enable.** |  |
| PlatformType | **= GetPcdValue (155);** |  |
| Step | **2: Initialize data collection subsystem.** |  |
| InitDataCollection | **();** |  |
| Step | **3: Initialize per-CPU feature subsystems.** |  |
| These | **correspond to the source files in the CpuMpDxe directory.** |  |
| Step | **4: Allocate processor configuration structure (104 bytes).** |  |
| mProcessorConfig | **= (PROCESSOR_CONFIG_DATA *)CpuMpAllocatePool (sizeof (PROCESSOR_CONFIG_DATA));** |  |
| Fill | **in processor configuration structure.** |  |
| Get | **the config buffer from the pages allocated during ProcessorConfigInit.** |  |
| The | **base is stored at qword_18268 + 8.** |  |
| CpuListHeads | **= (UINT64 *)(UINTN)1;  // Placeholder: real address set in ProcessorConfigInit** |  |
| Report | **configuration to CpuConfigLib via PCD 156.** |  |
| Status | **= SetPcdValue (156, (UINT64)mProcessorConfig);** |  |
| Step | **5: Install the MP Services protocol or other protocols.** |  |
| The | **decompile shows InstallMultipleProtocolInterfaces with GUID at 0x186A0.** |  |
| NewHandle | **= mDriverBindingHandle;** |  |
| Replace | **with actual GUID at 0x186A0** |  |
| Step | **6: Register for callback on a specific protocol notification.** |  |
| The | **original calls sub_F7A0 with unk_17790 as the protocol GUID and** |  |
| sub_5104 | **as the notification function.** |  |
| Detect | **CMOS page and baud rate (serial init).** |  |
| Program | **UART divisor.** |  |
| Lcr | **= IoRead8 ((UINT16)(CmosPage + 3));** |  |
| Clear | **DLAB, set FIFO.** |  |
| IoWrite8 | **((UINT16)(CmosPage + 2), 0);** |  |
| Check | **for the speedstep flag from sub_780().** |  |
| Read | **and validate the RTC timer.** |  |
| TSC | **//** |  |
| Wait | **for the timeout window.** |  |
| The | **original uses a 357-CPU-index-based timeout comparison.** |  |
| Wait | **loop with timeout check** |  |
| Perform | **speedstep-specific delay compensation.** |  |
| Set | **divisor to 1** |  |
| Start | **each AP.** |  |
| for | **(CpuIndex = 0; CpuIndex < (UINTN)mMpNumberOfCpus; CpuIndex++) {** |  |
| Skip | **BSP** |  |
| Get | **the APIC ID for this processor.** |  |
| ApicId | **= (UINT32)GetPcdValue (ProcessorNumber);  // Placeholder: read from CPU map** |  |
| Send | **INIT IPI.** |  |
| __writemsr | **(0x8B, 0);                             // Clear ICR** |  |
| INIT | **IPI (fixed, edge, assert)** |  |
| Microsecond | **delay (10ms per spec).** |  |
| CpuMpMicroSecondDelay | **(10000);** |  |
| Send | **first SIPI.** |  |
| StartupAddress | **= 0x10000 >> 12;                   // Reset vector page** |  |
| Microsecond | **delay (200us per spec).** |  |
| CpuMpMicroSecondDelay | **(200);** |  |
| Send | **second SIPI.** |  |
| __writemsr | **(0x8B, (ApicId << 32) | 0x600 | StartupAddress);** |  |
| Wait | **for AP to report in.** |  |
| CpuMpMicroSecondDelay | **(100);** |  |
| Locate | **the S3 boot script protocol.** |  |
| Status | **= gBS->LocateProtocol (** |  |
| Write | **IO write boot script entries for each MSR programmed during init.** |  |
| return | **EFI_SUCCESS;** |  |
| Save | **globals.** |  |
| gImageHandle | **= ImageHandle;** |  |
| Initialize | **DXE services and locate MM PCI base protocol.** |  |
| Locate | **HII protocols.** |  |
| Detect | **and configure the serial port baud rate and CMOS wait state.** |  |
| Check | **if the UART is already configured for this baud rate.** |  |
| If | **the divisor doesn't match, reprogram it.** |  |
| if | **(CurrentDivisor != (UINT16)Divisor) {** |  |
| Check | **for CPU 0 stepping/workaround via CMOS page.** |  |
| Read | **PCD 1024068 (byte) and PCD 1024064 (base address) to check** |  |
| for | **specific CPU stepping workaround.** |  |
| If | **the byte at PCD 1024068 is >= 0 (signed), then perform a workaround** |  |
| by | **setting bit 7 of the byte at PCD 1024064 + 1280.** |  |
| INT8 | **Stepping;** |  |
| Query | **CPU count from PCD 151.** |  |
| NumberOfCpus | **= GetPcdValue (151);** |  |
| Allocate | **and initialize MP system data structures.** |  |
| Status | **= ProcessorConfigInit (NumberOfCpus);** |  |
| Measure | **the boot TSC.** |  |
| Check | **speedstep flag.** |  |
| SpeedstepFlags | **= IoRead8 (0x780);        // Simplified: actual call to sub_780()** |  |
| Read | **TSC for timing** |  |
| Perform | **timeout-adjusted delay loop using PCD 1288.** |  |
| Wait | **with timeout using the CPU index-based check.** |  |
| TimerCurrent | **= GetPcdValue (1288);** |  |
| The | **original algorithm compares timer values with a wraparound** |  |
| if | **(((TimerStart + 357 - NewTimer) & 0x800000) != 0) {** |  |
| Set | **the final timer measurement.** |  |
| Speedstep | **workaround: restore UART speed.** |  |
| COM1 | **+ 1 = IER** |  |
| COM1 | **+ 0 = DLL** |  |
| Set | **DLAB + LCR** |  |
| COM1 | **+ 3 = LCR** |  |
| Normal | **path: no speedstep compensation needed.** |  |
| Invoke | **the main initialization dispatcher.** |  |
| Status | **= CpuMpDxeInit ();** |  |

---
*Generated by HR650X BIOS Decompilation Project*