How CSMWrap Works - FlyGoat/csmwrap GitHub Wiki
How CSMWrap Works
CSMWrap bridges the gap between a modern UEFI environment and the requirements of a legacy BIOS by performing a series of setup steps before handing control to a legacy operating system.
efi_main
in csmwrap.c
)
1. UEFI Entry Point (- Initialization:
- Sets up basic EFI services (console output via
printf.c
). - Allocates a private data structure (
struct csmwrap_priv
) to store state.
- Sets up basic EFI services (console output via
- Hardware/Firmware Checks & Setup:
- Legacy Region Unlocking (
unlock_region.c
): This is a critical step. The memory range 0xC0000-0xFFFFF (Option ROM and UMA area) must be made writable.- It first attempts to use
EFI_LEGACY_REGION2_PROTOCOL
. - If the protocol is unavailable or fails, it falls back to chipset-specific methods:
- Intel chipsets: Modifies PAM (Programmable Attribute Map) registers via PCI configuration space (e.g., for PIIX4, Q35, Skylake+).
- AMD chipsets: Modifies MTRRs (Memory Type Range Registers) to make the region write-back.
- It first attempts to use
- Video Initialization (
video.c
):- Identifies the active PCI VGA device, often by locating the EFI Graphics Output Protocol (GOP) provider.
- Sets up the
cb_framebuffer
structure (part of the Coreboot table) with information from EFI GOP (resolution, framebuffer address, color depth). This information is used by SeaVGABIOS. - Decides whether to use the embedded SeaVGABIOS or try to load an Option ROM from the GPU.
- ACPI Initialization (
acpi.c
):- Initializes the uACPI library.
- Locates the RSDP (Root System Description Pointer) provided by the UEFI firmware. This RSDP will be passed to the legacy environment.
- SMBIOS Table: The physical address of the SMBIOS table from UEFI is stored and later passed to the CSM.
- E820 Memory Map (
e820.c
):- Calls UEFI
GetMemoryMap()
to get the current memory layout. - Converts UEFI memory types to E820 types.
- Populates an E820 map, reserving space for the low stub, EBDA, and Option ROMs. This map is stored in the low stub area.
- Calls UEFI
- Coreboot Table (
coreboot.c
):- Builds a Coreboot-compatible parameter table in low memory. This table includes:
- Memory ranges.
- Serial port configuration (if any, usually stubbed).
- Framebuffer information (from
video.c
). - ACPI RSDP pointer.
- SMBIOS entry point.
- CBMEM (Coreboot Memory) console (if logging via CBMEM is enabled).
- Builds a Coreboot-compatible parameter table in low memory. This table includes:
- Legacy Region Unlocking (
csmwrap.h
, csmwrap.c
)
2. Low Memory Stub Setup (- A block of conventional memory (below 1MB, typically starting at 0x00000) is allocated or reserved. This "low stub" area is crucial for the 16-bit environment.
- It contains:
- The SeaBIOS CSM binary (
Csm16.bin
fromsrc/bins/Csm16.h
, relocated here). - The SeaBIOS VBIOS binary (
vgabios.bin
fromsrc/bins/vgabios.h
, placed typically at 0xC0000 after shadowing). - The generated E820 memory map.
- The Coreboot table.
- Space for the CSM's BDA (BIOS Data Area) and EBDA (Extended BIOS Data Area).
- A small 16-bit thunking mechanism (
Thunk16.asm*
,x86thunk.c
) to transition between UEFI's protected/long mode and the CSM's 16-bit real mode. - Space for the CSM's runtime stack.
- The SeaBIOS CSM binary (
3. CSM Initialization and Boot Handoff
- Intel Platform Workarounds (
intel_workarounds.c
): Applies specific workarounds, such as disabling the 8254 PIT Programmable Interval Timer's "Gate Enable" (8254CGE) on certain Intel chipsets to prevent conflicts. - Thunking to CSM:
- The
EFI_LEGACY_BIOS_PROTOCOL
equivalent functions are invoked using the 16-bit thunk. - The primary function called is
Compatibility16InitializeYourself
(or its modern equivalent name in SeaBIOS CSM). This function withinCsm16.bin
:- Initializes legacy hardware (PIC, PIT, DMA controllers).
- Sets up interrupt vectors.
- Scans for and initializes Option ROMs (including the VBIOS at 0xC0000).
- Builds the BBS (BIOS Boot Specification) table.
- The
- Video Option ROM / SeaVGABIOS:
- If a GPU Option ROM is used, it's loaded and executed.
- If SeaVGABIOS is used, it's copied to 0xC0000 and initialized. It uses the framebuffer information from the Coreboot table to set up a VBE (VESA BIOS Extensions) compatible display mode.
- Preparing for ExitBootServices:
- ACPI tables are finalized for handoff (
acpi_prepare_exitbs
). - UEFI video output via GOP might be disabled if SeaVGABIOS has taken over.
- ACPI tables are finalized for handoff (
- Exiting Boot Services:
ExitBootServices()
is called. This terminates all UEFI runtime services except for a minimal set (like reset/shutdown, GetTime, SetVariable if persistent).- CSMWrap takes full control of the hardware.
- Final Legacy Setup:
- External interrupts are disabled.
- The 8259 PIC is programmed to its default legacy state.
- The PIT is programmed to its default legacy state.
- Legacy Boot:
- The CSM's
Compatibility16Boot
function (or equivalent) is called via thunk. - This function typically performs an INT 19h (System Bootstrap) to load the boot sector from the highest priority device in the BBS table.
- The CSM's
Key Components and Binaries
Csm16.bin
(from SeaBIOS, embedded insrc/bins/Csm16.h
): The core Compatibility Support Module. It handles most of the legacy BIOS emulation, Option ROM scanning, and boot device management.vgabios.bin
(from SeaBIOS, embedded insrc/bins/vgabios.h
): A VESA-compliant VBIOS. It provides INT 10h video services.Thunk16.asm32
/Thunk16.asm64
andx86thunk.c
: Code responsible for transitioning the CPU between UEFI's native mode (32-bit protected or 64-bit long mode) and the 16-bit real mode required by the CSM.- uACPI (
uACPI/
submodule): A lightweight ACPI library used to parse and manage ACPI tables. - Nyu-EFI (
nyu-efi/
submodule): Provides a minimal C runtime, EFI headers, and the linker script for building UEFI applications.
This steps allows CSMWrap to create an environment where legacy operating systems believe they are running on a traditional BIOS-based machine.