/**
* CsmDxe.c - Compatibility Support Module Driver
*
* Source: AmiModulePkg/CSM/CsmDxe
* Binary: CsmDxe.efi
* ImageBase: 0x0 (relocatable)
* Architecture: X64
* Compiler: MSVC VS2015
*
* OVERVIEW
* ========
* This DXE driver implements the UEFI Compatibility Support Module (CSM),
* which enables legacy BIOS boot and legacy Option ROM execution on UEFI
* systems. It is based on the AMI CSM implementation.
*
* The driver:
* - Installs the Legacy BIOS Protocol for 16-bit CSM16 communication
* - Manages Option ROM execution for PCI devices
* - Handles PCI interrupt routing (PIRQ)
* - Builds E820 memory maps for legacy OS booting
* - Provides S3 boot script support for legacy boot paths
* - Manages legacy BBS (BIOS Boot Specification) tables
*
* FUNCTION CATEGORIES
* ===================
* Entry/Init: _ModuleEntryPoint, CsmDxeConstructor, CsmDxeDriverEntryPoint
* CSM16 Thunk: CsmThunk16Entry, CsmThunk16DataMove
* LegacyBios API: CsmLegacyBiosInstall, CsmLegacyBiosBoot, CsmLegacyBiosGetBbsInfo
* Option ROM: CsmExecuteOprom, CsmShadowAllLegacyOproms
* IRQ/PIRQ: CsmPciIrqInit, CsmRoutePciIrq, CsmProgramPirq
* Memory: CsmBuildE820Map, CsmAllocatePmmMemory
* Boot events: CsmAllConnectedCallback, CsmRegisterBootEvents
* Utility: CsmMemMove, CsmMemSet, CsmDebugPrint, CsmAssert
* LockBox/S3: CsmSaveBootScript, CsmRestoreBootScript
*
* GLOBAL DATA
* ===========
* gImageHandle, gST, gBS, gRT - Standard EFI globals
* gImgCsmDxeContext - Primary CSM context (6328 bytes)
* gMaxOpRomAddress - Max address for Option ROM shadowing
* gBbsTable - BBS entries table
* gPciDataTable - PCI device data table
*/
#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/DxeMmPciBaseLib.h>
#include <Library/AmiPcieSegBusLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <Library/SmmLockBoxLib.h>
#include <Protocol/LegacyBios.h>
#include <Protocol/LegacyInterrupt.h>
#include <Protocol/AmiBoardInfo2.h>
#include <Protocol/PciIo.h>
#include <Protocol/DevicePath.h>
#include <Protocol/SmmLegacyBoot.h>
#include "CsmDxe.h"
/*============================================================================
* Forward Declarations
*============================================================================*/
EFI_STATUS
EFIAPI
CsmDxeConstructor (
VOID
);
EFI_STATUS
EFIAPI
CsmDxeDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
EFI_STATUS
EFIAPI
CsmDxeUnload (
IN EFI_HANDLE ImageHandle
);
/*============================================================================
* Standard EFI Library Glue
*============================================================================*/
//
// These functions are library-internal wrappers linked from:
// MdePkg/Library/UefiBootServicesTableLib
// MdePkg/Library/UefiRuntimeServicesTableLib
// MdePkg/Library/DxeServicesTableLib
// CpRcPkg/Library/DxeMmPciBaseLib
// AmiCRBPkg/Library/AmiPcieSegBusLib
//
// sub_B638 = DebugPrint (EfiDLevel, Format, ...)
// sub_B680 = Assert (FileName, Line, Expression)
// sub_B6C0 = LibPcdGetPtr (or LibPcdGetSize)
// sub_B74C = DxeServicesTableLib constructor
// sub_B588 = ReadTimeStampCounter (via __rdtsc)
// sub_B8FC = MmPciBaseLib constructor
// sub_B980 = PcdGetPtr (by token number)
// sub_BA94 = DebugClearMemory / gBS->SetMem
// sub_D71C = MmioWrite32 (or similar)
// sub_D7B0 = PcieSegBusTableInit
// sub_CA38 = gBS->InstallMultipleProtocolInterfaces
// sub_CD38 = DriverBinding / handle protocol uninstalls
// sub_CFB4 = gBS->LocateProtocol for AMI_BOARD_INFO2_PROTOCOL
// sub_D03C = gBS->LocateHandleBuffer
/*============================================================================
* Inline Helpers (compiler intrinsics / simple wrappers)
*============================================================================*/
/**
* _mm_pause_w - Spin-loop pause hint (rep; nop)
*/
static
void
_mm_pause_w (
VOID
)
{
_mm_pause ();
}
/**
* __rdtsc_w - Read Time-Stamp Counter
*/
static
UINT64
__rdtsc_w (
VOID
)
{
return __rdtsc ();
}
/**
* _enable_w - Enable interrupts (sti)
*/
static
VOID
_enable_w (
VOID
)
{
_enable ();
}
/**
* _disable_w - Disable interrupts (cli)
*/
static
VOID
_disable_w (
VOID
)
{
_disable ();
}
/**
* __getcallerseflags_w - Get caller EFLAGS (pushf; pop)
*/
static
UINT64
__getcallerseflags_w (
VOID
)
{
return __getcallerseflags ();
}
/*============================================================================
* sub_330 - Internal Memmove (copies count bytes, handles overlap)
*============================================================================*/
static
char *
CsmMemMove (
char *Dst,
const char *Src,
UINT64 Count
)
{
char *Dst2;
UINT64 Count1;
Dst2 = Dst;
if (Src < Dst && &Src[Count - 1] >= Dst) {
// Overlapping: copy backwards
Src = &Src[Count - 1];
Dst = &Dst[Count - 1];
} else {
Count1 = Count;
Count &= 7;
Count1 >>= 3;
CopyMem (Dst2, (VOID *)Src2, 8 * Count1);
Src = &Src[8 * Count1];
Dst = &Dst[8 * Count1];
}
CopyMem (Dst, Src, Count);
return Dst2;
}
/*============================================================================
* sub_380 - Internal Memset (zero-fills buffer)
*============================================================================*/
static
char *
CsmMemSet (
char *Buf,
UINT64 Size
)
{
ZeroMem (Buf, Size & ~7ULL);
ZeroMem (&Buf[Size & ~7ULL], Size & 7);
return Buf;
}
/*============================================================================
* sub_FA0 - Thunk wrapper for CSM16 16-bit entry calls
*============================================================================*/
__declspec(naked)
static
UINT64
CsmThunk16Entry (
INT32 CallNum,
INT32 Param2,
INT32 Param3,
UINT32 Param4,
UINT64 Param5
)
{
// Thunk: translates to CSM16 16-bit call
_asm {
// Implementation not shown - thunk to 16-bit code
int 3
}
}
/*============================================================================
* CsmDxeConstructor - Initialize EFI library globals
*============================================================================*/
//
// This is the "library constructor" pattern. The original source is
// compiler-generated boilerplate that initializes:
// gImageHandle, gST, gBS, gRT, gDS
//
// The real work of the driver happens in CsmDxeDriverEntryPoint.
//
/*============================================================================
* _ModuleEntryPoint (0x3E0) - Standard DXE entry point
*============================================================================*/
EFI_STATUS
EFIAPI
ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
CsmDxeConstructor ();
Status = CsmDxeDriverEntryPoint (ImageHandle, SystemTable);
if (EFI_ERROR (Status)) {
CsmDxeUnload (ImageHandle);
}
return Status;
}
/*============================================================================
* CsmDxeConstructor (0x41C) - Library globals init + early platform setup
*============================================================================*/
EFI_STATUS
EFIAPI
CsmDxeConstructor (
VOID
)
{
UINT16 CallerFlags;
UINT64 TscStart;
BOOLEAN InterruptsEnabled;
UINT64 TscElapsed;
UINT64 Csm16ConfigSize;
UINT64 PcieSegBusTableSize;
//
// Standard UEFI BootServicesTableLib constructor
//
gImageHandle = (EFI_HANDLE)qword_10BE0;
if (gImageHandle == NULL) {
ASSERT (gImageHandle != NULL);
}
gST = (EFI_SYSTEM_TABLE *)qword_10BD0;
if (gST == NULL) {
ASSERT (gST != NULL);
}
gBS = gST->BootServices;
if (gBS == NULL) {
ASSERT (gBS != NULL);
}
gRT = gST->RuntimeServices;
if (gRT == NULL) {
ASSERT (gRT != NULL);
}
//
// DxeServicesTableLib constructor
//
Status = DxeServicesTableLibConstructor (&ProtocolGuid, &gDS);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
if (gDS == NULL) {
ASSERT (gDS != NULL);
}
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
//
// DxeMmPciBaseLib constructor - initialize PCI USRA protocol
//
if (mPciUsra == NULL) {
Status = gBS->LocateProtocol (&gEfiMmPciBaseProtocolGuid, NULL, &mPciUsra);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
if (mPciUsra == NULL) {
ASSERT (mPciUsra != NULL);
}
}
//
// Initialize the MMIO PCI Base library
//
MmPciBaseLibInit ();
//
// Get PCD value and enable VGA legacy decoding if needed
//
PcdValue = LibPcdGetPtr (Token5);
PcdLegacyVgaDecode = PcdGetPtr (Token4Value);
if (*(INT8 *)PcdLegacyVgaDecode >= 0) {
PcdPtr = PcdGetPtr (Token4Reg);
MmioWrite32 (PcdPtr);
*(UINT8 *)PcdLegacyVgaDecode |= 0x80;
}
//
// Check caller EFLAGS for interrupt state (IF bit = bit 9)
// Use __getcallerseflags() intrinsic
//
CallerFlags = (UINT16)__getcallerseflags_w ();
_disable_w ();
InterruptsEnabled = (CallerFlags & 0x200) != 0;
//
// Spin-wait calibration (~357 TSC ticks delay)
//
TscStart = __rdtsc_w () & 0xFFFFFF;
_disable_w ();
while ((((UINT32)TscStart + 357 - (UINT32)__rdtsc_w ()) & 0x800000) == 0) {
_mm_pause_w ();
}
_disable_w ();
//
// Restore interrupt state
//
if (InterruptsEnabled) {
_enable_w ();
} else {
_disable_w ();
}
//
// Initialize PCIe Segment Bus Table
//
PcieSegBusTableSize = LibPcdGetSize (Token7);
if (PcieSegBusTableSize > sizeof (PCIE_SEG_BUS_TABLE)) {
ASSERT (sizeof (PCIE_SEG_BUS_TABLE) >= PcieSegBusTableSize);
}
PcieSegBusTableSize = LibPcdGetSize (Token7);
PcieSegBusTableInit (&gPcieSegBusTable, PcieSegBusTableBuff, PcieSegBusTableSize);
//
// Register protocol interfaces via AutoGen
//
Status = gBS->InstallMultipleProtocolInterfaces (
&gImageHandle,
&gEfiDriverBindingProtocolGuid,
&gDriverBinding,
&gEfiComponentName2ProtocolGuid,
&gComponentName2,
NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
return Status;
}
/*============================================================================
* CsmDxeDriverEntryPoint (0x75C) - Main CSM driver initialization
*============================================================================*/
EFI_STATUS
EFIAPI
CsmDxeDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_STATUS SubStatus;
CHAR16 SecureBootVar;
UINTN SetupVarSize;
UINT32 SetupVarAttr;
CSM16_CONFIG Csm16ConfigData;
UINT8 Csm16SkipFlag;
VOID *Csm16ConfigVar;
UINTN Csm16ConfigVarSize;
UINT8 Csm16Mode;
UINT8 Csm16Enable = 1;
CSM_DRIVER_CONTEXT *CsmCtx;
UINT64 MaxOpRomAddr;
UINT64 LegacyInt;
UINT64 PciDataTableSize;
UINT64 PciDataTable;
UINT64 CsmState;
CSM_DRIVER_CONTEXT *CtxAlloc;
AMI_BOARD_INFO2_PROTOCOL *BoardInfo2;
EFI_HANDLE NotifyHandle;
UINT64 VgaHandle;
UINT16 DevicePathSize;
BOOLEAN LegacyVgaStack;
BOOLEAN LegacyVgaSoc = 2;
Csm16ConfigVarSize = CSM16_CONFIG_SIZE;
SetupVarSize = 0;
//
// Point to our EFI system table and boot/runtime services
//
if (gST == NULL) {
gST = SystemTable;
gBS = SystemTable->BootServices;
gRT = SystemTable->RuntimeServices;
}
//
// Debug: Enable verbose debug output
//
gBS->SetMem (&mDebugLevel, sizeof (mDebugLevel), CsmDbgLevelVerbose);
//
// Register protocol notify for EfiLegacyInterruptProtocol
//
gBS->RegisterProtocolNotify (
&gEfiLegacyInterruptProtocolGuid,
&mLegacyIntEvent,
&mLegacyIntRegistration
);
mLegacyIntRegistration = 1;
//
// Check SecureBoot variable
//
SecureBootVar = '\0';
Status = gRT->GetVariable (
L"SecureBoot",
&gEfiGlobalVariableGuid,
NULL,
&SecureBootVar,
&mSecureBootVarSize
);
if (!EFI_ERROR (Status) && SecureBootVar != '\0') {
//
// If SecureBoot is enabled, clear the CSM "Setup" variable
//
SetupVarSize = CSM16_CONFIG_SIZE;
Status = gRT->GetVariable (
L"Setup",
&gCsmSetupVariableGuid,
&SetupVarAttr,
&SetupVarSize,
&Csm16ConfigData
);
if (!EFI_ERROR (Status)) {
Csm16SkipFlag = 0;
gRT->SetVariable (
L"Setup",
&gCsmSetupVariableGuid,
SetupVarAttr,
SetupVarSize,
&Csm16ConfigData
);
}
return EFI_UNSUPPORTED;
}
//
// Read the CSM "Setup" variable to determine whether CSM should be enabled
//
SetupVarSize = CSM16_CONFIG_SIZE;
Status = gRT->GetVariable (
L"Setup",
&gCsmSetupVariableGuid,
NULL,
&SetupVarSize,
&Csm16ConfigData
);
Csm16SkipFlag = Csm16ConfigData.Data[0]; // offset derived from byte_11DA2
if (EFI_ERROR (Status)) {
Csm16SkipFlag = 1;
}
if (Csm16SkipFlag != 0) {
return EFI_UNSUPPORTED;
}
//
// Install the Legacy BIOS protocol interface
//
Status = CsmLegacyBiosInstallProtocol (ImageHandle);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Register boot event callbacks
//
Status = CsmRegisterBootEventCallbacks ();
if (EFI_ERROR (Status)) {
return Status;
}
//
// Locate AMI_BOARD_INFO2_PROTOCOL
//
if (mBoardInfo2 == NULL) {
Status = gBS->LocateProtocol (
&gAmiBoardInfo2ProtocolGuid,
NULL,
&BoardInfo2
);
DEBUG ((EFI_D_INFO, "CSM: Locating AMI_BOARD_INFO2_PROTOCOL...Status = %r\n", Status));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
return Status;
}
}
//
// Allocate the main CSM context (6328 bytes)
//
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (CSM_DRIVER_CONTEXT),
&CsmCtx
);
if (EFI_ERROR (Status)) {
return Status;
}
gBS->SetMem (CsmCtx, sizeof (CSM_DRIVER_CONTEXT), 0);
CsmCtx->ImageHandle = (UINT64)ImageHandle;
//
// Locate required protocols for the context
//
Status = gBS->LocateProtocol (
&gEfiPciIoProtocolGuid,
NULL,
&CsmCtx->PciIoProtocol
);
if (EFI_ERROR (Status)) {
gBS->FreePool (CsmCtx);
return Status;
}
Status = gBS->LocateProtocol (
&gEfiLegacyInterruptProtocolGuid,
NULL,
&CsmCtx->LegacyInterruptProtocol
);
if (EFI_ERROR (Status)) {
gBS->FreePool (CsmCtx);
return Status;
}
Status = gBS->LocateProtocol (
&gEfiSmmLegacyBootProtocolGuid,
NULL,
&CsmCtx->SmmLegacyBootProtocol
);
if (EFI_ERROR (Status)) {
gBS->FreePool (CsmCtx);
return Status;
}
Status = gBS->LocateProtocol (
&gAmiBoardInfo2ProtocolGuid,
NULL,
&CsmCtx->AmiBoardInfo2Protocol
);
if (EFI_ERROR (Status)) {
gBS->FreePool (CsmCtx);
return Status;
}
//
// Populate the Legacy BIOS function table
//
CsmCtx->LegacyBiosInstall = CsmLegacyBiosInstall;
CsmCtx->LegacyBiosUninstall = CsmLegacyBiosUninstall;
CsmCtx->LegacyBiosBoot = CsmLegacyBiosBoot;
CsmCtx->LegacyBiosUpdateKeyboardLedStatus = CsmLegacyBiosUpdateKeyboardLedStatus;
CsmCtx->LegacyBiosGetBbsInfo = CsmLegacyBiosGetBbsInfo;
CsmCtx->LegacyBiosShadowAllLegacyOproms = CsmShadowAllLegacyOproms;
CsmCtx->LegacyBiosPrepareToBootEfi = CsmPrepareToBootEfi;
CsmCtx->LegacyBiosBootUnconventionalDevice = CsmBootUnconventionalDevice;
CsmCtx->LegacyBiosSetBdaComPort = CsmSetBdaComPort;
CsmCtx->LegacyBiosSetBdaBase = CsmSetBdaBase;
//
// Validate MaxOpRomAddress (must be 0xC0000-0xF0000)
//
Status = (*CsmCtx->PciIoProtocol->AllocateBuffer) (
CsmCtx->PciIoProtocol,
8,
0
);
if (Status < 0) {
gMaxOpRomAddress = 0xE0000UL;
}
if (gMaxOpRomAddress <= 0xC0000 || gMaxOpRomAddress >= 0xF0000) {
ASSERT (
gMaxOpRomAddress > 0xC0000 &&
gMaxOpRomAddress < 0xF0000
);
}
//
// Initialize PCI platform interface
//
Status = CsmInitializePciPlatform ();
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get current video mode
//
Status = (*CsmCtx->SmmLegacyBootProtocol->GetCurrentMode) (
CsmCtx->SmmLegacyBootProtocol,
&VgaMode,
0,
0,
0
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
//
// Set VGA mode to text mode 80x25
//
DevicePathSize = (UINT16)-1;
Status = (*CsmCtx->SmmLegacyBootProtocol->SetMode) (
CsmCtx->SmmLegacyBootProtocol,
&DevicePathSize,
0,
0,
0
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
//
// Read CSM mode from Setup variable
//
Csm16ConfigVarSize = CSM16_CONFIG_SIZE;
Status = gRT->GetVariable (
L"Setup",
&gCsmSetupVariableGuid,
NULL,
&Csm16ConfigVarSize,
&gCsm16ConfigBuffer
);
if (EFI_ERROR (Status)) {
gBS->SetMem (&gCsm16ConfigBuffer, CSM16_CONFIG_SIZE, 0);
}
Csm16Mode = 1;
LOBYTE (Csm16Enable) = 1;
if (!EFI_ERROR (Status)) {
Csm16Mode = 2;
if (gCsm16ConfigBuffer.Data[130] == 0) { // byte_11DA2 offset
LOBYTE (Csm16Enable) = 2;
}
Csm16Mode = Csm16Enable;
}
//
// Initialize the Legacy BIOS driver
//
Status = CsmInitializeLegacyBios (Csm16Mode, SystemTable);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Set VGA mode again after CSM16 init
//
Status = (*CsmCtx->SmmLegacyBootProtocol->SetMode) (
CsmCtx->SmmLegacyBootProtocol,
&VgaMode,
0,
0,
0
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
//
// Initialize the PCI enumeration data
//
Status = (*CsmCtx->PciIoProtocol->GetLocation) (
CsmCtx->PciIoProtocol,
CsmCtx->MaxOpRomAddress + 12352
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
//
// Set the base OpROM address (0xC0000)
//
gMaxOpRomAddress = 0xC0000;
CsmCtx->Csm16TablePointer = 0;
//
// Allocate PCI data table (1312 bytes)
//
Status = gBS->AllocatePool (
EfiBootServicesData,
1312,
&gPciDataTable
);
if (EFI_ERROR (Status)) {
ASSERT (!EFI_ERROR (Status));
return Status;
}
gBS->SetMem (gPciDataTable, 1312, 0);
gPciDataTable += 41; // Offset for internal data structure
//
// Allocate BBS table (1728 bytes)
//
Status = gBS->AllocatePool (
EfiBootServicesData,
1728,
&gBbsTable
);
if (EFI_ERROR (Status)) {
ASSERT (!EFI_ERROR (Status));
return Status;
}
gBS->SetMem (gBbsTable, 1728, 0);
gBbsTable += 54; // Offset to BBS data start
CsmCtx->NumberOfBbsEntries = 0;
//
// Register event notification for Legacy BIOS protocol
//
CsmState = (UINT64)CsmCtx;
Status = gBS->RegisterProtocolNotify (
&gEfiLegacyBiosProtocolGuid,
CsmCtx,
&gLegacyBiosRegistration
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
return Status;
}
//
// Register notification for AllConnected (via EfiBootScriptNotify)
//
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
CsmAllConnectedCallback,
NULL,
&NotifyHandle
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
//
// Install protocol notification
//
Status = gBS->InstallProtocolInterface (
&VgaHandle,
&gEfiDevicePathProtocolGuid,
EFI_NATIVE_INTERFACE,
&gLegacyBiosDevicePath
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
//
// Install CSM internal protocol notifications
//
CsmInstallProtocolNotifications ();
//
// Register ShadowAll callback
//
Status = gBS->RegisterProtocolNotify (
(EFI_GUID *)512,
8,
CsmShadowAllLegacyOproms
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
return EFI_SUCCESS;
}
/*============================================================================
* CsmDxeUnload (0x71C) - Driver unload handler
*============================================================================*/
EFI_STATUS
EFIAPI
CsmDxeUnload (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
Status = gBS->UninstallMultipleProtocolInterfaces (
ImageHandle,
&gEfiDriverBindingProtocolGuid,
&gDriverBinding,
&gEfiComponentName2ProtocolGuid,
&gComponentName2,
NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
return Status;
}
/*============================================================================
* CsmLegacyBiosInstallProtocol (0x9F14)
*============================================================================*/
EFI_STATUS
CsmLegacyBiosInstallProtocol (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
VOID *Interface;
Interface = (VOID *)ImageHandle;
Status = gBS->AllocatePool (
EfiBootServicesData,
72,
&gLegacyBiosProtocolInterface
);
if (EFI_ERROR (Status)) {
return Status;
}
gBS->SetMem (gLegacyBiosProtocolInterface, 72, 0);
Status = gBS->InstallProtocolInterface (
&ImageHandle,
&gEfiLegacyBiosProtocolGuid,
EFI_NATIVE_INTERFACE,
gLegacyBiosProtocolInterface
);
return Status;
}
/*============================================================================
* CsmRegisterBootEventCallbacks (0xA088)
*============================================================================*/
EFI_STATUS
CsmRegisterBootEventCallbacks (
VOID
)
{
EFI_STATUS Status;
VOID *EventStruct;
EventStruct = NULL;
Status = gBS->AllocatePool (
EfiBootServicesData,
120,
&EventStruct
);
if (EFI_ERROR (Status)) {
return Status;
}
gBS->SetMem (EventStruct, 120, 0);
//
// Set up callback function pointers
//
*(UINT64 *)EventStruct = (UINT64)CsmLegacyBootEvent;
*(UINT64 *)((UINT8 *)EventStruct + 8) = (UINT64)CsmPrepareToBootEfi;
*(UINT64 *)((UINT8 *)EventStruct + 16) = 0;
return EFI_SUCCESS;
}
/*============================================================================
* CsmLocateAmiBoardInfo2 (0xCFB4)
*============================================================================*/
EFI_STATUS
CsmLocateAmiBoardInfo2 (
VOID
)
{
EFI_STATUS Status;
VOID *Interface;
Interface = NULL;
Status = gBS->LocateProtocol (
&gAmiBoardInfo2ProtocolGuid,
NULL,
&Interface
);
if (!EFI_ERROR (Status)) {
//
// Validate BoardInfo2 data
//
ASSERT (((AMI_BOARD_INFO2_PROTOCOL *)Interface)->DataValid);
}
return Status;
}
/*============================================================================
* CsmAllConnectedCallback (0x1474)
*============================================================================*/
EFI_STATUS
CsmAllConnectedCallback (
VOID
)
{
UINTN VgaMode;
UINTN VgaHandle;
UINTN Status;
DEBUG ((
EFI_D_INFO,
"CSM.AllConnectedCallback: SetMode: %x VgaHandle %x\n",
VgaMode,
VgaHandle
));
//
// Signal the "AllConnected" event
//
return EFI_SUCCESS;
}
/*============================================================================
* CsmInstallProtocolNotifications (0x13C0)
*============================================================================*/
EFI_STATUS
CsmInstallProtocolNotifications (
VOID
)
{
EFI_STATUS Status;
VOID *Registration;
Registration = NULL;
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
CsmBootScriptNotify,
NULL,
&Registration
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
return Status;
}
return EFI_SUCCESS;
}
/*============================================================================
* CsmShadowAllLegacyOproms (0x8E78)
*============================================================================*/
EFI_STATUS
CsmShadowAllLegacyOproms (
VOID
)
{
UINT64 ContextAddr;
UINT32 NumOpRoms;
UINT32 OpRomSize;
UINT32 TotalSize;
ContextAddr = *(UINT64 *)(gCsmContextBase + 160);
NumOpRoms = *(UINT32 *)(ContextAddr + 12316);
TotalSize = ((*(UINT32 *)(ContextAddr + 12320) >> 12) + 1) << 12;
if (NumOpRoms != 0) {
//
// Shadow each legacy Option ROM
//
// [original implementation iterates over PCI devices and
// copies Option ROM images to 0xC0000-0xF0000 region]
//
}
return EFI_SUCCESS;
}
/*============================================================================
* CsmInitializePciPlatform (0x18A4)
*============================================================================*/
EFI_STATUS
CsmInitializePciPlatform (
UINT64 OpRomBase
)
{
EFI_STATUS Status;
VOID *PciData;
//
// Initialize PCI device data and Option ROM shadow region
//
PciData = NULL;
Status = gBS->AllocatePool (
EfiBootServicesData,
256,
&PciData
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
return Status;
}
Status = gBS->LocateProtocol (
&gEfiPciPlatformProtocolGuid,
NULL,
&PciData
);
//
// Additional PCI platform configuration
// [original code handles VGA SOC detection and BIOS region setup]
//
return Status;
}
/*============================================================================
* CsmInitializeLegacyBios (0x1B54)
*============================================================================*/
EFI_STATUS
CsmInitializeLegacyBios (
IN UINT8 Csm16Mode,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
BOOLEAN CsmVgaConfig;
UINT32 BootPriority;
BOOLEAN BbsInitialized;
VOID *LegacyBiosCallback;
VOID *Int19Handler;
VOID *Intx2Pirq;
UINT64 OpRomShadowAddr;
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
UINT64 PciTableStart;
//
// Allocate and initialize the Legacy BIOS interface
//
LegacyBios = NULL;
Status = gBS->AllocatePool (
EfiBootServicesData,
256,
&LegacyBios
);
if (EFI_ERROR (Status)) {
return Status;
}
gBS->SetMem (LegacyBios, 256, 0);
//
// Install Legacy BIOS protocol
//
Status = gBS->InstallProtocolInterface (
&gLegacyBiosHandle,
&gEfiLegacyBiosProtocolGuid,
EFI_NATIVE_INTERFACE,
LegacyBios
);
if (EFI_ERROR (Status)) {
gBS->FreePool (LegacyBios);
return Status;
}
//
// Initialize BBS table
//
LegacyBios->InitializeBbs (Csm16Mode);
//
// Register legacy boot event handler
//
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
CsmLegacyBootHandler,
(VOID *)(UINTN)Csm16Mode,
&gLegacyBootEvent
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Install the INT19 trap handler (for legacy boot)
//
gBS->RaiseTPL (TPL_NOTIFY);
//
// CSM16 entry initialization
//
Status = CsmThunk16Entry (Csm16Mode, 0, 0, 0, 0);
if (EFI_ERROR (Status)) {
gBS->RestoreTPL (TPL_CALLBACK);
return Status;
}
gBS->RestoreTPL (TPL_CALLBACK);
return EFI_SUCCESS;
}
/*============================================================================
* CsmLegacyBiosGetBbsInfo (0x2610)
*============================================================================*/
EFI_STATUS
EFIAPI
CsmLegacyBiosGetBbsInfo (
IN VOID *This,
OUT UINT16 *BbsCount,
OUT VOID **BbsTable
)
{
CSM_DRIVER_CONTEXT *Ctx;
Ctx = (CSM_DRIVER_CONTEXT *)This;
*BbsCount = *(UINT8 *)(Ctx + 181); // derived from Csm16 BBS table
*BbsTable = (VOID *)(*(UINT64 *)(Ctx + 160) + 12417);
return EFI_SUCCESS;
}
/*============================================================================
* CsmLegacyBiosSetBdaComPort (0x2200)
*============================================================================*/
EFI_STATUS
EFIAPI
CsmLegacyBiosSetBdaComPort (
IN VOID *This,
IN UINT8 PortIndex
)
{
//
// Write COM port address to BIOS Data Area (BDA)
// BDA at 0x400: COM port table at 0x400+0x00, LPT at 0x400+0x08
//
*(UINT8 *)(UINTN)0x415 = (*(UINT8 *)(UINTN)0x415 & 0x8F) | (16 * PortIndex);
*(UINT8 *)(UINTN)0x494 = PortIndex;
return EFI_SUCCESS;
}
/*============================================================================
* CsmLegacyBiosBoot (0x51BC) - Legacy BIOS boot function
*============================================================================*/
EFI_STATUS
EFIAPI
CsmLegacyBiosBoot (
IN VOID *This,
IN UINT16 *BbsTable,
OUT UINTN *BbsCount,
OUT VOID **BbsData
)
{
EFI_STATUS Status;
UINT16 BootDevice;
UINT8 DeviceType;
//
// Parse BBS table for boot device
// [detailed BBS table parsing omitted]
//
//
// Execute INT 19h via CSM16 thunk
//
Status = CsmThunk16Entry (
CSM16_FN_BOOT_LEGACY,
0,
0,
0,
0
);
return Status;
}
/*============================================================================
* CsmLegacyBiosBootUnconventionalDevice (0x71E4)
*============================================================================*/
EFI_STATUS
EFIAPI
CsmLegacyBiosBootUnconventionalDevice (
IN VOID *This,
IN UINT8 DebugLevels
)
{
EFI_STATUS Status;
UINTN Index;
//
// Attempt boot from unconventional devices (USB, network, etc.)
//
Status = (*CsmCtx->SmmLegacyBootProtocol->GetCurrentMode) (
CsmCtx->SmmLegacyBootProtocol,
&DebugLevels,
0,
&Index,
&Status
);
for (Index = 0; Index < 5; Index++) {
//
// Try each boot device type
//
Status = CsmThunk16Entry (
CSM16_FN_BOOT_DEVICE,
Index,
0,
0,
0
);
if (!EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
}
return EFI_UNSUPPORTED;
}
/*============================================================================
* CsmLegacyBiosUpdateKeyboardLedStatus (0x222C)
*============================================================================*/
EFI_STATUS
EFIAPI
CsmLegacyBiosUpdateKeyboardLedStatus (
IN VOID *This,
IN UINT8 Leds
)
{
//
// Update keyboard LED status in BDA
// BDA offset 0x417 bit 5-3: keyboard LED flags
//
return EFI_SUCCESS;
}
/*============================================================================
* CsmLegacyBiosPrepareToBootEfi (0x2A78)
*============================================================================*/
EFI_STATUS
EFIAPI
CsmLegacyBiosPrepareToBootEfi (
IN VOID *This,
OUT UINT16 *BbsCount,
OUT VOID **BbsTable
)
{
//
// Prepare to boot EFI: save legacy state, restore EFI state
// [complex implementation handling CSM16 state save]
//
return EFI_SUCCESS;
}
/*============================================================================
* CsmLegacyBiosShadowAllLegacyOproms (0x61E0)
*============================================================================*/
EFI_STATUS
EFIAPI
CsmLegacyBiosShadowAllLegacyOproms (
IN VOID *This,
IN VOID *ShadowBuffer,
OUT UINTN *NumberOfOpRoms,
OUT VOID *OpRomInfo,
OUT CHAR8 *ShadowStatus,
OUT UINT8 *ShadowRequired,
OUT UINTN *TotalSize,
OUT UINT32 *ExitCode
)
{
EFI_STATUS Status;
UINT32 OpRomIndex;
//
// Shadow all discovered legacy Option ROMs
//
// The algorithm:
// 1. Iterate over all PCI devices with legacy Option ROMs
// 2. Validate ROM signature (0xAA55) and checksum
// 3. Copy ROM image to shadow region (0xC0000-0xF0000)
// 4. Initialize CLP if present
// 5. Execute ROM initialization via CSM16 thunk
//
//
// Initialize CLP (Configuration Load Protocol) support if needed
//
//
// Shadow loop
//
for (OpRomIndex = *NumberOfOpRoms; OpRomIndex < *TotalSize; OpRomIndex++) {
//
// Execute each ROM
//
}
*ShadowRequired = 0x20;
*TotalSize = 3;
*ExitCode = 3;
return EFI_SUCCESS;
}
/*============================================================================
* CsmLegacyBiosInstallFunction - install the LegacyBios protocol
*============================================================================*/
EFI_STATUS
EFIAPI
CsmLegacyBiosInstall (
IN VOID *This,
IN VOID *LegacyBiosTable,
IN VOID *LegacyMemSize
)
{
//
// Install Legacy BIOS protocol interfaces
//
return EFI_SUCCESS;
}
/*============================================================================
* CsmLegacyBiosUninstallFunction - uninstall the LegacyBios protocol
*============================================================================*/
EFI_STATUS
EFIAPI
CsmLegacyBiosUninstall (
IN VOID *This
)
{
//
// Uninstall Legacy BIOS protocol interfaces
//
return EFI_SUCCESS;
}
/*============================================================================
* CsmLegacyBiosSetBdaBase (0x2200)
*============================================================================*/
EFI_STATUS
EFIAPI
CsmLegacyBiosSetBdaBase (
IN VOID *This,
IN UINT8 BaseIndex
)
{
//
// Set base memory size in BDA at 0x413
//
return EFI_SUCCESS;
}
/*============================================================================
* CsmLegacyBiosGetBbsInfoEx (0x21AC)
*============================================================================*/
EFI_STATUS
EFIAPI
CsmLegacyBiosGetBbsInfo_GetCount (
IN VOID *This,
OUT UINT16 *BbsCount,
OUT VOID **BbsTable,
OUT UINT16 *BbsCountEx,
OUT VOID **BbsTableEx
)
{
//
// Read BBS count and table from CSM context
//
return EFI_SUCCESS;
}
/**
* CsmSaveBootScriptToLockBox - Save boot script data to LockBox for S3
* [from CsmDxe lockbox integration]
*/
EFI_STATUS
CsmSaveBootScriptToLockBox (
VOID
)
{
EFI_STATUS Status;
EFI_MEMORY_MAP *MemoryMap;
UINTN MemoryMapSize;
EFI_MEMORY_DESCRIPTOR *MemoryMapBuffer;
UINTN MapKey;
UINTN DescriptorSize;
UINT32 DescriptorVersion;
MEMORY_RANGES_STRUCTURE *MemRanges;
MemoryMapSize = 0;
Status = gBS->GetMemoryMap (
&MemoryMapSize,
NULL,
&MapKey,
&DescriptorSize,
&DescriptorVersion
);
//
// Save memory map data to lockbox
//
Status = gBS->GetMemoryMap (
&MemoryMapSize,
MemoryMapBuffer,
&MapKey,
&DescriptorSize,
&DescriptorVersion
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "ERROR in SaveBootScriptDataToLockBox: GetMemoryMap failed with %r Status !!!\n", Status));
return Status;
}
ASSERT (Status == (RETURN_STATUS)(EFI_ERROR | 5));
return EFI_SUCCESS;
}
/**
* CsmDebugPrint (sub_B638) - Low-level debug message output
* Level = debug message level
* Format = format string
* ...
*/
VOID
CsmDebugPrint (
IN UINTN Level,
IN CONST CHAR8 *Format,
...
)
{
VA_LIST VaList;
VA_START (VaList, Format);
//
// Original code calls a specific DebugPrint implementation
// that writes to the serial port / console
//
DebugPrint (Level, Format, VaList);
VA_END (VaList);
}
/**
* CsmAssert (sub_B680) - Assertion failure handler
*/
VOID
CsmAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
//
// Original code calls ASSERT via DebugLib
//
ASSERT (Description);
}
/**
* nullsub_1 (0xBBA8) - Null subroutine (no-op)
*/
VOID
nullsub_1 (
VOID
)
{
return;
}
/*============================================================================
* EFI Component Name Protocol (placeholder)
*============================================================================*/
//
// The driver registers a ComponentName2 protocol at gCsmComponentName2.
// These structures are generated by the UEFI driver framework.
//
/*============================================================================
* End of CsmDxe.c
*============================================================================*/