Newer
Older
AMI-Aptio-BIOS-Reversed / LenovoServerPkg / GetCpuInfo / GetCpuInfo.md
@Ajax Dong Ajax Dong 2 days ago 6 KB Full restructure

GetCpuInfo

Function Table

Address Name Description
GetCpuInfoEntryPoint
CpuInfoDriverEntry
CpuInfoCollection
CpuInfoDisplayForm
CpuInfoDelayMicro
GetPlatformLanguage
CpuIdEx
AsmReadMsr64
AsmWriteMsr64
CpuInfoReadAll
CpuInfoLocatePcdProtocol
CpuInfoGetProcessorCountFromHob
CpuInfoFreeAllBuffers
HiiFreeOpCodeHandle
GLOBAL VARIABLES (.data section, 0x3D30 - 0x3DF0)
EFI_HANDLE gImageHandle; ///< 0x3D40
GUID DEFINITIONS (.rdata section)
The GUIDs are defined externally in the PE/COFF .rdata section:
unk_3B00 = EFI_CPU_ARCH_PROTOCOL_GUID
unk_3B10 = gEfiRuntimeServicesTableGuid
unk_3B30 = HII package list GUID for VFR
unk_3B40 = gEfiPcdProtocolGuid
unk_3B50 = PackageListGuid for HII string packages
unk_3C08 = gEfiHiiStringProtocolGuid
unk_3C18 = gEfiHiiConfigRoutingProtocolGuid
unk_3C28 = gEfiHiiPackageListProtocolGuid
unk_3C38 = gEfiHiiDatabaseProtocolGuid
unk_3C48 = gEfiHobListGuid
unk_3C58 = gEfiHiiConfigAccessProtocolGuid
unk_3C68 = CPU Info formset GUID
unk_3C80 = CPU Info form GUID (VFR binary data)
FORWARD DECLARATIONS
EFI_STATUS EFIAPI
CPUID / MSR / I/O HELPERS (inlined wrappers)
MODULE ENTRY POINT
Call the actual driver entry
return CpuInfoDriverEntry (ImageHandle, SystemTable);
Step 1: Save UEFI handles
gImageHandle = ImageHandle;
Step 2: Initialize HOB list
GetHobList ();
Step 3: Get PCD for PCI Express base address (lazy init via PCD protocol)
Step 4: Locate HII protocols
Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, &gHiiDatabase);
Step 5: Check and enable platform language via PCI config
PcdAddress = 1024068; // Offset 0xF4244 from PciExpressBaseAddress
Write to IO port to enable
CpuInfoEnablePlatformLanguage (PcdAddress - 4); // 0xF4240
Step 6: Read platform type from IO port 0x80
PlatformType = IoRead32 (IO_PORT_0x80);
Step 7: Wait for IO completion by polling port 0x508
do {
Small delay via IO port read
Step 8: Return based on setup mode
if (SetupMode) {
CPU INFORMATION COLLECTION
Step 1: PCD enable check
if (!PcdGetBool (PcdCpuInfoDisplayEnable)) {
Step 2: Locate CPU Architecture Protocol
CpuProtocol = CpuInfoLocateCpuProtocol ();
Step 3: Get number of processors from HOB
ProcessorNumber = CpuInfoGetProcessorCountFromHob ();
Step 4: Allocate per-processor string buffers
gAllCpuInfoString = AllocateZeroPool (CPU_INFO_STRING_SIZE * ProcessorNumber);
Step 5: Build header string "Total CPU Number: %d\n"
UnicodeSPrint (
Step 6: Initialize per-processor label strings
for (Index = 0; Index < ProcessorNumber; Index++) {
Step 7: Collect actual CPU data from all processors
Step 8: Register callback for form update
Step 9: Create and display HII form
HiiHandle = CpuInfoRegisterPackageList (
Step 10: Free buffers
Max width for number formatting
UnicodeValueToString (Buffer, 0, Index, 4);
AsmCpuid (CPUID_VERSION_INFO, &Eax, &Ebx, &Ecx, &Edx);
Stepping (EAX[3:0])
CPUID (EAX full, printed as hex)
PlatformIdMsr = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);
then read MSR 0x8B[63:32].
AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
MSR_PLATFORM_INFO (0xCE) byte 1 is the Maximum Efficiency Ratio.
Core frequency = ratio * 100 MHz (bus frequency).
MaxEfficiencyRatio = AsmReadMsr64 (MSR_PLATFORM_INFO);
Uses the MPERF (MSR 0xE7) and APERF (MSR 0xE8) ratio method:
if (gMaxTurboRatio == 0) {
freq = (ratio CoreFreq 100) / 10000
MeasuredRatio = DivU64xU64 (MultU64xU64 (AperfValue, 100), gMaxTurboRatio);
actual MHz = (ratio MaxEfficiencyRatio 100) / 100
ActualFrequency = DivU64xU64 (
Format and append
UnicodeValueToString (Buffer, 0, ActualFrequency / 100, 8);
UTILITY FUNCTIONS
These magic values represent GUID comparison data
They are precomputed from the CPU-info HOB GUID
Walk through HOBs looking for CPU info
while (GuidHob != NULL) {
Compare GUID to the expected CPU-info HOB GUID
if (CompareGuid (HobDataGuid, (EFI_GUID *)MagicCheck)) {
Found CPU info HOB extract processor count
CpuCount = (UINT32 )((UINT8 *)GuidHob + sizeof (EFI_HOB_GUID_TYPE));
Move to next HOB
GuidHob = GetNextGuidHob (
Wait for previous I/O to complete by polling port 0x508
while (((AddressRemainder + (IoRead32 (IO_PORT_0x508) & 0xFFFFFF)
Delay via IO read
After first iteration, always use max remainder for remaining
shifted counts
AddressRemainder = 0x400000;
Status = gRT->GetVariable (
HII FORM DISPLAY
Allocate op-code handles
StartOpCodeHandle = HiiAllocateOpCodeHandle ();
Create form header and end markers
HiiCreateFormOpCode (StartOpCodeHandle, FORM_CPU_INFO_ID, 0);
Add "Total CPU Number" header text
Add per-processor data lines (7 fields each)
for (Index = 0; Index < gNumberOfProcessors; Index++) {
Update the form via HII Database
Status = ((EFI_HII_DATABASE_PROTOCOL *)gHiiDatabase)->UpdateForm (
Clean up
HiiFreeOpCodeHandle (StartOpCodeHandle);
Calculate total size of all packages
Package = VA_ARG (Args, VOID *);
Build the package list header
CopyGuid (&PackageListHeader->PackageListGuid, PackageListGuid);
Register with HII Database
Status = ((EFI_HII_PACKAGE_LIST_PROTOCOL *)gHiiPackageList)->NewPackageList (

Generated by HR650X BIOS Decompilation Project