/** @file
This file Multiboot specification (implementation).
Copyright (c) 2014 - 2023, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "MultibootLibInternal.h"
#define SUPPORTED_FEATURES (MULTIBOOT_HEADER_MODS_ALIGNED | MULTIBOOT_HEADER_WANT_MEMORY | MULTIBOOT_HEADER_HAS_VBE)
UINT8 mLoaderName[] = "Slim BootLoader\0";
VOID DumpMbHeader (CONST MULTIBOOT_HEADER *Mh);
/**
Get multiboot header address
Get multiboot header following Multboot spec 0.6.98.
@param[in] ImageAddr Memory address of an image
@retval MultibootHeader Pointer to Multiboot header if found.
@retval NULL No valid Multiboot header found or requesting
features not support.
**/
CONST MULTIBOOT_HEADER *
EFIAPI
GetMultibootHeader (
IN VOID *ImageAddr
)
{
UINT32 AlignedAddress;
MULTIBOOT_HEADER *MbHeader;
UINT32 Offset;
// Multiboot header must be 32-bit aligned.
AlignedAddress = ((UINT32)(UINTN)ImageAddr + 3) & ~0x3;
// Multiboot header must completely within the first 8192 bytes of the image.
for (Offset = 0; Offset < 8192 - sizeof (MULTIBOOT_HEADER); Offset += 4) {
MbHeader = (MULTIBOOT_HEADER *)(UINTN)(AlignedAddress + Offset);
if ((MbHeader->Magic == MULTIBOOT_HEADER_MAGIC) &&
(MbHeader->Magic + MbHeader->Flags + MbHeader->Checksum == 0)) {
if ((MbHeader->Flags & (~SUPPORTED_FEATURES & 0xffff)) != 0) {
// Some Multiboot features are not supported yet.
DEBUG ((DEBUG_INFO, "Not supported Multiboot, flags=0x%x\n", MbHeader->Flags));
return NULL;
}
return (CONST MULTIBOOT_HEADER *) MbHeader;
}
}
return NULL;
}
/**
Check if it is Multiboot image
@param[in] ImageAddr Memory address of an image
@retval TRUE Image is Multiboot 0.6.98 compliant image
@retval FALSE Not multiboot image
**/
BOOLEAN
EFIAPI
IsMultiboot (
IN VOID *ImageAddr
)
{
CONST MULTIBOOT_HEADER *MbHeader;
MbHeader = GetMultibootHeader (ImageAddr);
if (MbHeader != NULL) {
DumpMbHeader (MbHeader);
return TRUE;
}
return FALSE;
}
/**
Get memory map information.
@retval Memory Map Info pointer
**/
STATIC
MEMORY_MAP_INFO *
EFIAPI
GetMemoryMapInfo (
VOID
)
{
EFI_HOB_GUID_TYPE *GuidHob;
GuidHob = GetNextGuidHob (&gLoaderMemoryMapInfoGuid, GetHobList());
if (GuidHob == NULL) {
ASSERT (GuidHob);
return NULL;
}
return (MEMORY_MAP_INFO *)GET_GUID_HOB_DATA (GuidHob);
}
/**
Init Multiboot memory map.
@param[out] MbMmap Multiboot memmap buffer
@param[in] MemoryMapInfo Memmap buffer from boot loader
**/
VOID
InitMultibootMmap (
OUT MULTIBOOT_MMAP *MbMmap,
IN MEMORY_MAP_INFO *MemoryMapInfo
)
{
UINT32 Index;
MEMORY_MAP_ENTRY *MmapEntry;
MmapEntry = &MemoryMapInfo->Entry[0];
for (Index = 0; Index < MemoryMapInfo->Count; Index++) {
MbMmap[Index].Size = sizeof (MULTIBOOT_MMAP) - sizeof (MbMmap[Index].Size);
MbMmap[Index].BaseAddr = MmapEntry[Index].Base;
MbMmap[Index].Length = MmapEntry[Index].Size;
MbMmap[Index].Type = MmapEntry[Index].Type;
}
}
/**
Setup the Multiboot info for boot usage.
@param[in,out] MultiBoot Point to loaded Multiboot image structure
**/
VOID
EFIAPI
SetupMultibootInfo (
IN OUT MULTIBOOT_IMAGE *MultiBoot
)
{
UINT32 MmapCount;
MULTIBOOT_MMAP *MbMmap;
MEMORY_MAP_INFO *MemoryMapInfo;
MULTIBOOT_INFO *MbInfo;
EFI_HOB_GUID_TYPE *GuidHob;
EFI_PEI_GRAPHICS_INFO_HOB *GfxInfoHob;
MbInfo = &MultiBoot->MbInfo;
MemoryMapInfo = GetMemoryMapInfo();
MmapCount = MemoryMapInfo->Count;
if (MmapCount > 0) {
MbMmap = (MULTIBOOT_MMAP *) AllocatePool (sizeof (MULTIBOOT_MMAP) * MmapCount);
if (MbMmap == NULL) {
DEBUG ((DEBUG_INFO, "Multiboot MMap allocation Error\n"));
ASSERT (MbMmap);
}
InitMultibootMmap (MbMmap, MemoryMapInfo);
MbInfo->MmapAddr = (UINT32 *) MbMmap;
MbInfo->MmapLength = MmapCount * sizeof (MULTIBOOT_MMAP);
MbInfo->Flags |= MULTIBOOT_INFO_HAS_MMAP;
// The amount of lower and upper memory size (in KB) will be updated
// later since current memmap is not the final memmap.
}
// boot device [MULTIBOOT_INFO_HAS_BOOT_DEVICE]: not supported.
if (MultiBoot->CmdFile.Size != 0) {
MbInfo->Cmdline = MultiBoot->CmdFile.Addr;
MbInfo->Flags |= MULTIBOOT_INFO_HAS_CMDLINE;
}
// modules [MULTIBOOT_INFO_HAS_MODS]
if (MultiBoot->MbModuleNumber > 0) {
MbInfo->ModsAddr = (V_ADDR)&MultiBoot->MbModule;
MbInfo->ModsCount = MultiBoot->MbModuleNumber;
MbInfo->Flags |= MULTIBOOT_INFO_HAS_MODS;
}
// a.out symbol table [MULTIBOOT_INFO_HAS_AOUT_SYMS]: provided by a.out loader
// ELF symbol table [MULTIBOOT_INFO_HAS_ELF_SYMS]: not supported,
// if required, ElfLib and MultibootLib should implement additional APIs.
// BIOS drive info [MULTIBOOT_INFO_HAS_DRIVES]: not supported
// BIOS ROM configuration table [MULTIBOOT_INFO_HAS_CONFIG_TABLE]: not supported.
// boot loader name:
MbInfo->LoaderName = (UINT8 *) &mLoaderName;
MbInfo->Flags |= MULTIBOOT_INFO_HAS_LOADER_NAME;
// BIOS APM table [MULTIBOOT_INFO_HAS_APM_TABLE]: not supported
// BIOS VBE video mode information [MULTIBOOT_INFO_HAS_VBE]: not supported
// BIOS FB framebuffer information [MULTIBOOT_INFO_HAS_FB]
GuidHob = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid);
if (GuidHob != NULL) {
GfxInfoHob = (EFI_PEI_GRAPHICS_INFO_HOB *)GET_GUID_HOB_DATA (GuidHob);
MbInfo = &MultiBoot->MbInfo;
MbInfo->FramebufferAddr = (UINT64)(UINTN)GfxInfoHob->FrameBufferBase;
MbInfo->FramebufferPitch = GfxInfoHob->GraphicsMode.PixelsPerScanLine * 4;
MbInfo->FramebufferWidth = GfxInfoHob->GraphicsMode.HorizontalResolution;
MbInfo->FramebufferHeight = GfxInfoHob->GraphicsMode.VerticalResolution;
MbInfo->FramebufferBpp = 32;
MbInfo->FramebufferType = 1;
MbInfo->FramebufferRedFieldPosition = 0x10;
MbInfo->FramebufferRedMaskSize = 8;
MbInfo->FramebufferGreenFieldPosition = 0x08;
MbInfo->FramebufferGreenMaskSize = 8;
MbInfo->FramebufferBlueFieldPosition = 0x00;
MbInfo->FramebufferBlueMaskSize = 8;
MbInfo->Flags |= MULTIBOOT_INFO_HAS_FB;
}
// Arrange for passing this data to the image.
MultiBoot->BootState.Eax = MULTIBOOT_INFO_MAGIC;
MultiBoot->BootState.Ebx = (UINT32)(UINTN)MbInfo;
}
/**
Load Multiboot module string
@param[in,out] MultiBoot Point to loaded Multiboot image structure
@param[in] ModuleIndex Module index to load
@param[in] File Source image file
@retval EFI_SUCCESS Load Multiboot module image successfully
@retval Others There is error when setup image
**/
EFI_STATUS
EFIAPI
LoadMultibootModString (
IN OUT MULTIBOOT_IMAGE *MultiBoot,
IN UINT16 ModuleIndex,
IN IMAGE_DATA *File
)
{
EFI_STATUS Status;
UINT32 Index;
IMAGE_DATA *CmdFile;
UINT8 *NewCmdBuffer;
UINT32 NewSize;
if ((MultiBoot == NULL) || (File == NULL) || (ModuleIndex >= MAX_MULTIBOOT_MODULE_NUMBER)) {
return EFI_INVALID_PARAMETER;
}
CmdFile = &MultiBoot->MbModuleData[ModuleIndex].CmdFile;
CopyMem (CmdFile, File, sizeof (IMAGE_DATA));
Status = EFI_SUCCESS;
if (CmdFile->Addr == NULL || CmdFile->Size == 0) {
goto done;
}
// multiboot spec requires a mod string be a zero-terminated ASCII string
// fast check: 1st char is zero or zero-terminated
if (((UINT8 *)CmdFile->Addr)[0] == '\0') {
goto done;
}
for (Index = (CmdFile->Size-1); Index > 0; Index--) {
if (((UINT8 *)CmdFile->Addr)[Index] == '\0') {
goto done;
}
}
// if the mod string is not zero-terminated, allocate a new buffer to append zero char
NewCmdBuffer = (UINT8 *) AllocatePages (EFI_SIZE_TO_PAGES (CMDLINE_LENGTH_MAX));
if (NewCmdBuffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto done;
}
// no ASCII check here for performance
NewSize = (CmdFile->Size > (CMDLINE_LENGTH_MAX -1)) ? CMDLINE_LENGTH_MAX: (CmdFile->Size + 1);
CopyMem (NewCmdBuffer, CmdFile->Addr, NewSize - 1);
NewCmdBuffer[NewSize - 1] = '\0';
// Free Allocated Memory earlier first
FreeImageData (CmdFile);
// Assign new one
CmdFile->Addr = NewCmdBuffer;
CmdFile->Size = NewSize;
CmdFile->AllocType = ImageAllocateTypePage;
done:
if (Status == EFI_SUCCESS) {
MultiBoot->MbModule[ModuleIndex].String = (UINT8 *) MultiBoot->MbModuleData[ModuleIndex].CmdFile.Addr;
}
return Status;
}
/**
Align multiboot modules if required by spec.
@param[in,out] MultiBoot Point to loaded Multiboot image structure
@retval RETURN_SUCCESS Align modules successfully
@retval Others There is error when align image
**/
EFI_STATUS
EFIAPI
AlignMultibootModules (
IN OUT MULTIBOOT_IMAGE *MultiBoot
)
{
MULTIBOOT_MODULE *MbModule;
VOID *AlignedAddr;
UINT32 ModuleSize;
UINT32 Index;
for (Index = 0; Index < MultiBoot->MbModuleNumber; Index++) {
MbModule = &MultiBoot->MbModule[Index];
ModuleSize = MbModule->End - MbModule->Start;
if ((MbModule->Start & EFI_PAGE_MASK) != 0) {
AlignedAddr = AllocatePages (EFI_SIZE_TO_PAGES (ModuleSize));
if (AlignedAddr == NULL) {
return RETURN_OUT_OF_RESOURCES;
}
DEBUG ((DEBUG_INFO, "Align Module[%d] from 0x%x to 0x%p\n",
Index, MbModule->Start, AlignedAddr));
CopyMem (AlignedAddr, (CONST VOID *)(UINTN)MbModule->Start, (UINTN)ModuleSize);
MbModule->Start = (UINT32)(UINTN)AlignedAddr;
MbModule->End = MbModule->Start + ModuleSize;
}
}
return RETURN_SUCCESS;
}
/**
Align multiboot modules if requested by header.
@param[in,out] MultiBoot Point to loaded Multiboot image structure
@retval RETURN_SUCCESS Align modules successfully
@retval Others There is error when align image
**/
EFI_STATUS
EFIAPI
CheckAndAlignMultibootModules (
IN OUT MULTIBOOT_IMAGE *MultiBoot
)
{
EFI_STATUS Status;
CONST MULTIBOOT_HEADER *MbHeader;
if (MultiBoot == NULL) {
return RETURN_INVALID_PARAMETER;
}
MbHeader = GetMultibootHeader (MultiBoot->BootFile.Addr);
if (MbHeader == NULL) {
return RETURN_LOAD_ERROR;
}
if ((MbHeader->Flags & MULTIBOOT_HEADER_MODS_ALIGNED) != 0) {
// Modules should be page (4KB) aligned
Status = AlignMultibootModules (MultiBoot);
if (EFI_ERROR (Status)) {
return Status;
}
}
return EFI_SUCCESS;
}
/**
Setup Multiboot image and its boot info.
@param[in,out] MultiBoot Point to loaded Multiboot image structure
@retval RETURN_SUCCESS Setup Multiboot image successfully
@retval Others There is error when setup image
**/
EFI_STATUS
EFIAPI
SetupMultibootImage (
IN OUT MULTIBOOT_IMAGE *MultiBoot
)
{
EFI_STATUS Status;
UINT8 *HeaderAddr;
UINT8 *LoadAddr;
UINT8 *LoadEnd;
UINT8 *BssEnd;
CONST MULTIBOOT_HEADER *MbHeader;
UINT8 *CopyStart;
UINT32 ImgOffset;
UINT32 ImgLength;
if (MultiBoot == NULL) {
return RETURN_INVALID_PARAMETER;
}
MbHeader = GetMultibootHeader (MultiBoot->BootFile.Addr);
if (MbHeader == NULL) {
return RETURN_LOAD_ERROR;
}
if ((MbHeader->Flags & MULTIBOOT_HEADER_HAS_ADDR) == 0) {
return RETURN_UNSUPPORTED;
}
if ((MbHeader->Flags & MULTIBOOT_HEADER_HAS_VBE) != 0) {
// Just print the preferred graphics mode.
DEBUG ((DEBUG_INFO, "Mb: ModeType=0x%x, Width=0x%x , Height=0x%x, Depth=0x%x\n", MbHeader->ModeType, MbHeader->Width, MbHeader->Height, MbHeader->Depth));
}
if ((MbHeader->Flags & MULTIBOOT_HEADER_MODS_ALIGNED) != 0) {
// Other modules should be page (4KB) aligned
Status = AlignMultibootModules (MultiBoot);
if (EFI_ERROR (Status)) {
return Status;
}
}
HeaderAddr = MbHeader->HeaderAddr;
LoadAddr = MbHeader->LoadAddr;
LoadEnd = MbHeader->LoadEndAddr;
BssEnd = MbHeader->BssEndAddr;
ImgOffset = (UINT32)((UINT8 *)MbHeader - (UINT8 *)MultiBoot->BootFile.Addr - (HeaderAddr - LoadAddr));
ImgLength = (UINT32)((LoadEnd == NULL) ? MultiBoot->BootFile.Size - ImgOffset : LoadEnd - LoadAddr);
if ((ImgOffset >= MultiBoot->BootFile.Size) || (ImgOffset + ImgLength > MultiBoot->BootFile.Size)) {
return RETURN_LOAD_ERROR;
}
DEBUG ((DEBUG_INFO, "Mb: LoadAddr=0x%p, LoadEnd=0x%p , BssEnd=0x%p, Size=0x%x\n", LoadAddr, LoadEnd, BssEnd, ImgLength));
CopyStart = (UINT8 *)MultiBoot->BootFile.Addr + ImgOffset;
CopyMem (LoadAddr, CopyStart, ImgLength);
if ((BssEnd != NULL) && (LoadEnd != NULL)) {
if (BssEnd > LoadEnd) {
ZeroMem ((VOID *) LoadEnd, BssEnd - LoadEnd);
}
}
SetupMultibootInfo (MultiBoot);
MultiBoot->BootState.EntryPoint = (UINT32)(UINTN)MbHeader->EntryAddr;
return EFI_SUCCESS;
}
/**
Print out the Multiboot header.
@param[in] Mh The Multiboot header to be printed.
**/
VOID
DumpMbHeader (CONST MULTIBOOT_HEADER *Mh)
{
DEBUG ((DEBUG_INFO, "\nDump MB header @%p:\n", Mh));
DEBUG ((DEBUG_INFO, "- Magic: %8x\n", Mh->Magic));
DEBUG ((DEBUG_INFO, "- Flags: %8x\n", Mh->Flags));
DEBUG ((DEBUG_INFO, "- Checksum: %8x\n", Mh->Checksum));
/* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_ADDR. */
DEBUG ((DEBUG_INFO, "- HeaderAddr: %8x\n", Mh->HeaderAddr));
DEBUG ((DEBUG_INFO, "- LoadAddr: %8x\n", Mh->LoadAddr));
DEBUG ((DEBUG_INFO, "- LoadEndAddr: %8x\n", Mh->LoadEndAddr));
DEBUG ((DEBUG_INFO, "- BssEndAddr: %8x\n", Mh->BssEndAddr));
DEBUG ((DEBUG_INFO, "- EntryAddr: %8x\n", Mh->EntryAddr));
/* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE. */
DEBUG ((DEBUG_INFO, "- ModeType: %8x\n", Mh->ModeType));
DEBUG ((DEBUG_INFO, "- Width: %8x\n", Mh->Width));
DEBUG ((DEBUG_INFO, "- Height: %8x\n", Mh->Height));
DEBUG ((DEBUG_INFO, "- Depth: %8x\n", Mh->Depth));
}
/**
Print out the Multiboot information block.
@param[in] Mi The Multiboot information block to be printed.
**/
VOID
DumpMbInfo (
IN CONST MULTIBOOT_INFO *Mi
)
{
UINT32 Index;
MULTIBOOT_MODULE *Mod;
CONST MULTIBOOT_MMAP *Map;
UINT32 Offs;
DEBUG ((DEBUG_INFO, "\nDump MB info @%p:\n", Mi));
if (Mi == NULL) {
return;
}
DEBUG ((DEBUG_INFO, "- Flags: %8x\n", Mi->Flags));
// Valid if mi_flags sets MULTIBOOT_INFO_HAS_MEMORY.
DEBUG ((DEBUG_INFO, "- MemLower: %8x (%dK)\n", Mi->MemLower, Mi->MemLower));
DEBUG ((DEBUG_INFO, "- MemUpper: %8x (%dK)\n", Mi->MemUpper, Mi->MemUpper));
// Valid if mi_flags sets MULTIBOOT_INFO_HAS_BOOT_DEVICE.
DEBUG ((DEBUG_INFO, "- BootDevicePart3: %8x\n", Mi->BootDevicePart3));
DEBUG ((DEBUG_INFO, "- BootDevicePart2: %8x\n", Mi->BootDevicePart2));
DEBUG ((DEBUG_INFO, "- BootDevicePart1: %8x\n", Mi->BootDevicePart1));
DEBUG ((DEBUG_INFO, "- BootDeviceDrive: %8x\n", Mi->BootDeviceDrive));
// Valid if mi_flags sets MULTIBOOT_INFO_HAS_CMDLINE.
DEBUG ((DEBUG_INFO, "- Cmdline addr: %8p\n", Mi->Cmdline));
if ((Mi->Flags & MULTIBOOT_INFO_HAS_CMDLINE) && Mi->Cmdline) {
DEBUG ((DEBUG_INFO, "cmd = '%a'\n", Mi->Cmdline));
}
// Valid if mi_flags sets MULTIBOOT_INFO_HAS_MODS.
DEBUG ((DEBUG_INFO, "- ModsCount: %8x\n", Mi->ModsCount));
DEBUG ((DEBUG_INFO, "- ModsAddr: %8x\n", Mi->ModsAddr));
if ((Mi->Flags & MULTIBOOT_INFO_HAS_MODS) && Mi->ModsCount > 0) {
Mod = (MULTIBOOT_MODULE *)Mi->ModsAddr;
for (Index = 0; Index < Mi->ModsCount; Index++) {
DEBUG ((DEBUG_INFO, "- Mod[%d].Start: %08x\n", Index, Mod[Index].Start));
DEBUG ((DEBUG_INFO, "- Mod[%d].End: %08x\n", Index, Mod[Index].End));
DEBUG ((DEBUG_INFO, "- Mod[%d].String: %08x\n", Index, (UINT32)(UINTN)Mod[Index].String));
DEBUG ((DEBUG_INFO, " string = '%a'\n", Mod[Index].String));
}
}
// Valid if mi_flags sets MULTIBOOT_INFO_HAS_{AOUT,ELF}_SYMS.
DEBUG ((DEBUG_INFO, "- ElfshdrNum: %8x\n", Mi->ElfshdrNum));
DEBUG ((DEBUG_INFO, "- ElfshdrSize: %8x\n", Mi->ElfshdrSize));
DEBUG ((DEBUG_INFO, "- ElfshdrAddr: %8x\n", Mi->ElfshdrAddr));
DEBUG ((DEBUG_INFO, "- ElfshdrShndx: %8x\n", Mi->ElfshdrShndx));
// Valid if mi_flags sets MULTIBOOT_INFO_HAS_MMAP.
DEBUG ((DEBUG_INFO, "- MmapLength: %8x\n", Mi->MmapLength));
DEBUG ((DEBUG_INFO, "- MmapAddr: %8x\n", Mi->MmapAddr));
if ((Mi->Flags & MULTIBOOT_INFO_HAS_MMAP)) {
for (Offs = 0; Offs < Mi->MmapLength; Offs += Map->Size + sizeof (Map->Size)) {
Map = (VOID *)((UINTN)Mi->MmapAddr + Offs);
DEBUG ((DEBUG_INFO, "%3x: ", Offs));
DEBUG ((DEBUG_INFO, "%016lX", Map->BaseAddr));
DEBUG ((DEBUG_INFO, "--%016lX", Map->Length));
DEBUG ((DEBUG_INFO, " %d\n", Map->Type));
}
}
// Valid if mi_flags sets MULTIBOOT_INFO_HAS_DRIVES.
DEBUG ((DEBUG_INFO, "- DrivesLength: %8x\n", Mi->DrivesLength));
DEBUG ((DEBUG_INFO, "- DrivesAddr: %8x\n", Mi->DrivesAddr));
// Valid if mi_flags sets MULTIBOOT_INFO_HAS_CONFIG_TABLE.
DEBUG ((DEBUG_INFO, "- ConfigTable: %8p\n", Mi->UnusedConfigTable));
// Valid if mi_flags sets MULTIBOOT_INFO_HAS_LOADER_NAME.
DEBUG ((DEBUG_INFO, "- LoaderName: %8p\n", Mi->LoaderName));
if ((Mi->Flags & MULTIBOOT_INFO_HAS_LOADER_NAME) && Mi->LoaderName) {
DEBUG ((DEBUG_INFO, " '%a'\n", Mi->LoaderName));
}
// Valid if mi_flags sets MULTIBOOT_INFO_HAS_APM.
DEBUG ((DEBUG_INFO, "- ApmTable: %8p\n", Mi->UnusedApmTable));
// Valid if mi_flags sets MULTIBOOT_INFO_HAS_VBE.
DEBUG ((DEBUG_INFO, "- VbeControlInfo: %8p\n", Mi->UnusedVbeControlInfo));
DEBUG ((DEBUG_INFO, "- VbeModeInfo: %8p\n", Mi->UnusedVbeModeInfo));
DEBUG ((DEBUG_INFO, "- VbeInterfaceSeg: %8x\n", Mi->UnusedVbeInterfaceSeg));
DEBUG ((DEBUG_INFO, "- VbeInterfaceOff: %8x\n", Mi->UnusedVbeInterfaceOff));
DEBUG ((DEBUG_INFO, "- VbeInterfaceLen: %8x\n\n", Mi->UnusedVbeInterfaceLen));
}
/**
Print out the Multiboot boot state.
@param[in] BootState The Multiboot boot state pointer.
**/
VOID
DumpMbBootState (
IN CONST IA32_BOOT_STATE *BootState
)
{
DEBUG ((DEBUG_INFO, "Dump multiboot boot state:\n"));
DEBUG ((DEBUG_INFO, "- EntryPoint: %4x\n", BootState->EntryPoint));
DEBUG ((DEBUG_INFO, "- Eax: %4x\n", BootState->Eax));
DEBUG ((DEBUG_INFO, "- Ebx: %4x\n", BootState->Ebx));
DEBUG ((DEBUG_INFO, "- Esi: %4x\n", BootState->Esi));
DEBUG ((DEBUG_INFO, "- Edi: %4x\n\n", BootState->Edi));
}