Matt DeVillier has uploaded this change for review. ( https://review.coreboot.org/c/edk2/+/58786 )
Change subject: MdeModulePkg: load boot logo into BGRT table ......................................................................
MdeModulePkg: load boot logo into BGRT table
This is a shoehorned-in implementation of an ACPI BGRT table, ported pretty much directly from the version used under CorebootPayloadPkg, which itself was adapted from an older version of HackBGRT[1].
EDK2 provides a facility to do this already, but it assumes the ACPI tables already exist as EFI structures, so would need to write code to populate those using the tables already in RAM created by coreboot. This seemed like the easier option ATM.
[1] https://github.com/Metabolix/HackBGRT
Signed-off-by: Matt DeVillier matt.devillier@gmail.com Change-Id: I726fd7a9deb9ba5f8e351ce24834fc627acc4542 --- M MdeModulePkg/Include/Library/BootLogoLib.h A MdeModulePkg/Library/BootLogoLib/Bgrt.c M MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf M MdeModulePkg/MdeModulePkg.dec M UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c M UefiPayloadPkg/UefiPayloadPkg.fdf 6 files changed, 313 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/edk2 refs/changes/86/58786/1
diff --git a/MdeModulePkg/Include/Library/BootLogoLib.h b/MdeModulePkg/Include/Library/BootLogoLib.h index afd895b..1b6b12a 100644 --- a/MdeModulePkg/Include/Library/BootLogoLib.h +++ b/MdeModulePkg/Include/Library/BootLogoLib.h @@ -61,4 +61,14 @@ IN UINTN PreviousValue );
+/** + + Install Boot Logo into BGRT table + +**/ +VOID +AddBGRT ( + VOID + ); + #endif diff --git a/MdeModulePkg/Library/BootLogoLib/Bgrt.c b/MdeModulePkg/Library/BootLogoLib/Bgrt.c new file mode 100644 index 0000000..5b97ce0 --- /dev/null +++ b/MdeModulePkg/Library/BootLogoLib/Bgrt.c @@ -0,0 +1,283 @@ +#include <IndustryStandard/Acpi.h> +#include <IndustryStandard/Bmp.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/BootLogoLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Protocol/FirmwareVolume2.h> +#include <Protocol/SimpleFileSystem.h> + +/** RSDP (Root System Description Pointer) */ +typedef struct { + CHAR8 signature[8]; + UINT8 checksum; + CHAR8 oem_id[6]; + UINT8 revision; + UINT32 rsdt_address; + UINT32 length; + UINT64 xsdt_address; + UINT8 extended_checksum; + UINT8 reserved[3]; +} ACPI_20_RSDP; + +/** SDT (System Description Table) entry header */ +typedef struct { + CHAR8 signature[4]; + UINT32 length; + UINT8 revision; + UINT8 checksum; + CHAR8 oem_id[6]; + CHAR8 oem_table_id[8]; + UINT32 oem_revision; + UINT32 asl_compiler_id; + UINT32 asl_compiler_revision; +} ACPI_SDT_HEADER; + +/** BGRT structure */ +typedef struct { + ACPI_SDT_HEADER header; + UINT16 version; + UINT8 status; + UINT8 image_type; + UINT64 image_address; + UINT32 image_offset_x; + UINT32 image_offset_y; +} ACPI_BGRT; + +EFI_STATUS +EFIAPI +LoadBmp( + OUT EFI_PHYSICAL_ADDRESS *BmpAddress, + OUT UINT32 *BmpSize +) +{ + EFI_STATUS Status; + UINTN FvProtocolCount; + EFI_HANDLE *FvHandles; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINTN Index; + UINT32 AuthenticationStatus; + + UINT8 *Buffer; + UINTN BmpBufferSize; + + Buffer = 0; + FvHandles = NULL; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &FvProtocolCount, + &FvHandles + ); + + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < FvProtocolCount; Index++) { + Status = gBS->HandleProtocol ( + FvHandles[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + BmpBufferSize = 0; + Status = Fv->ReadSection ( + Fv, + (EFI_GUID *)PcdGetPtr(PcdLogoFile), + EFI_SECTION_RAW, + 0, + (void **)&Buffer, + &BmpBufferSize, + &AuthenticationStatus + ); + + if (!EFI_ERROR (Status)) { + *BmpAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + *BmpSize = (UINT32)BmpBufferSize; + Status = EFI_SUCCESS; + break; + } + } + } else { + Status = EFI_NOT_FOUND; + } + + if (FvHandles != NULL) { + gBS->FreePool (FvHandles); + FvHandles = NULL; + } + + return Status; +} + +UINT8 SumBytes(const UINT8* arr, UINTN size) { + UINT8 sum = 0; + UINTN i; + for (i = 0; i < size; ++i) { + sum += arr[i]; + } + return sum; +} + +int VerifyAcpiRsdp2Checksums(const void* data) { + const UINT8* arr = data; + UINTN size = *(const UINT32*)&arr[20]; + return SumBytes(arr, 20) == 0 && SumBytes(arr, size) == 0; +} + +void SetAcpiRsdp2Checksums(void* data) { + UINT8* arr = data; + UINTN size = *(const UINT32*)&arr[20]; + arr[9] = 0; + arr[32] = 0; + arr[9] = -SumBytes(arr, 20); + arr[32] = -SumBytes(arr, size); +} + +int VerifyAcpiSdtChecksum(const void* data) { + const UINT8* arr = data; + UINTN size = *(const UINT32*)&arr[4]; + return SumBytes(arr, size) == 0; +} + +void SetAcpiSdtChecksum(void* data) { + UINT8* arr = data; + UINTN size = *(const UINT32*)&arr[4]; + arr[9] = 0; + arr[9] = -SumBytes(arr, size); +} + +const CHAR16* TmpStr(CHAR8 *src, int length) { + static CHAR16 arr[4][16]; + static int j; + CHAR16* dest = arr[j = (j+1) % 4]; + int i; + for (i = 0; i < length && i < 16-1 && src[i]; ++i) { + dest[i] = src[i]; + } + dest[i] = 0; + return dest; +} + +static UINT32 min(UINT32 first, UINT32 second){ + if (first < second) + return first; + return second; +} + +ACPI_SDT_HEADER* CreateXsdt(ACPI_SDT_HEADER* xsdt0, UINTN entries) { + ACPI_SDT_HEADER* xsdt = 0; + UINT32 xsdt_len = (UINT32)(sizeof(ACPI_SDT_HEADER) + entries * sizeof(UINT64)); + gBS->AllocatePool(EfiACPIReclaimMemory, xsdt_len, (void**)&xsdt); + if (!xsdt) { + DEBUG ((EFI_D_INFO, "HackBGRT: Failed to allocate memory for XSDT.\n")); + return 0; + } + ZeroMem(xsdt, xsdt_len); + CopyMem(xsdt, xsdt0, min(xsdt0->length, xsdt_len)); + xsdt->length = xsdt_len; + SetAcpiSdtChecksum(xsdt); + return xsdt; +} + +static ACPI_BGRT* HandleAcpiTables(ACPI_BGRT* bgrt) { + int i; + + for (i = 0; i < gST->NumberOfTableEntries; i++) { + EFI_GUID* vendor_guid = &gST->ConfigurationTable[i].VendorGuid; + ACPI_20_RSDP *rsdp; + ACPI_SDT_HEADER *xsdt; + UINT64 *entry_arr; + UINT32 entry_arr_length; + + if (!CompareGuid(vendor_guid, &gEfiAcpiTableGuid) && !CompareGuid(vendor_guid, &gEfiAcpi20TableGuid)) { + continue; + } + rsdp = (ACPI_20_RSDP *) gST->ConfigurationTable[i].VendorTable; + if (CompareMem(rsdp->signature, "RSD PTR ", 8) != 0 || rsdp->revision < 2 || !VerifyAcpiRsdp2Checksums(rsdp)) { + continue; + } + DEBUG ((EFI_D_INFO, "RSDP: revision = %d, OEM ID = %s\n", rsdp->revision, TmpStr(rsdp->oem_id, 6))); + + xsdt = (ACPI_SDT_HEADER *) (UINTN) rsdp->xsdt_address; + if (!xsdt || CompareMem(xsdt->signature, "XSDT", 4) != 0 || !VerifyAcpiSdtChecksum(xsdt)) { + DEBUG ((EFI_D_INFO, "* XSDT: missing or invalid\n")); + continue; + } + entry_arr = (UINT64*)&xsdt[1]; + entry_arr_length = (xsdt->length - sizeof(*xsdt)) / sizeof(UINT64); + + DEBUG ((EFI_D_INFO, "* XSDT: OEM ID = %s, entry count = %d\n", TmpStr(xsdt->oem_id, 6), entry_arr_length)); + + if (bgrt) { + DEBUG ((EFI_D_INFO, " - Adding missing BGRT.\n")); + xsdt = CreateXsdt(xsdt, entry_arr_length + 1); + entry_arr = (UINT64*)&xsdt[1]; + entry_arr[entry_arr_length++] = (UINTN) bgrt; + rsdp->xsdt_address = (UINTN) xsdt; + SetAcpiRsdp2Checksums(rsdp); + } + SetAcpiSdtChecksum(xsdt); + } + return bgrt; +} + +VOID +AddBGRT ( + VOID + ) +{ + EFI_STATUS Status; + ACPI_BGRT *bgrt; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_PHYSICAL_ADDRESS BmpAddress; + UINT32 BmpSize; + BMP_IMAGE_HEADER *BmpHeader; + const char data[0x38] = + "BGRT" "\x38\x00\x00\x00" "\x00" "\xd6" "INTEL " " EDK2" + "\x20\x17\x00\x00" "PTL " "\x02\x00\x00\x00" + "\x01\x00" "\x00" "\x00"; + + BmpAddress = 0; + + DEBUG ((EFI_D_INFO, "HackBGRT Start\n")); + + Status = gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID**)&GraphicsOutput + ); + + // Replace missing = allocate new. + gBS->AllocatePool(EfiACPIReclaimMemory, sizeof(*bgrt), (void**)&bgrt); + if (!bgrt) { + DEBUG ((EFI_D_INFO, "HackBGRT MEM ERR\n")); + return; + } + + DEBUG ((EFI_D_INFO, "HackBGRT Load Bmp\n")); + Status = LoadBmp(&BmpAddress, &BmpSize); + if (EFI_ERROR(Status)){ + DEBUG ((EFI_D_INFO, "HackBGRT BMP Load ERR\n")); + return; + } + + DEBUG ((EFI_D_INFO, "HackBGRT Set Table; BMP Size: %d\n", BmpSize)); + // Clear the BGRT. + CopyMem(bgrt, data, sizeof(data)); + + if (GraphicsOutput != NULL && GraphicsOutput->Mode != NULL && GraphicsOutput->Mode->Info != NULL) + { + BmpHeader = (BMP_IMAGE_HEADER *)BmpAddress; + bgrt->image_address = (UINTN)BmpAddress; + bgrt->image_offset_x = (GraphicsOutput->Mode->Info->HorizontalResolution - BmpHeader->PixelWidth) / 2; + bgrt->image_offset_y = ((GraphicsOutput->Mode->Info->VerticalResolution * 382) / 1000) - + (BmpHeader->PixelHeight / 2); + DEBUG ((EFI_D_INFO, "HackBGRT Set checksum\n")); + SetAcpiSdtChecksum(bgrt); + DEBUG ((EFI_D_INFO, "HackBGRT Add Table\n")); + HandleAcpiTables(bgrt); + } else { + DEBUG ((EFI_D_INFO, "HackBGRT no display connected, skip adding table\n")); + } +} diff --git a/MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf b/MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf index 7d50f2d..aa4bd7f 100644 --- a/MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf +++ b/MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf @@ -24,6 +24,7 @@ #
[Sources] + Bgrt.c BootLogoLib.c
[Packages] @@ -48,5 +49,12 @@ gEfiUserManagerProtocolGuid ## CONSUMES gEdkiiPlatformLogoProtocolGuid ## CONSUMES
+[Guids] + gEfiAcpiTableGuid ## CONSUMES ## GUID + gEfiAcpi20TableGuid ## CONSUMES ## GUID + [FeaturePcd] gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdLogoFile ## CONSUMES diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 133e04e..81b302b 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -2159,3 +2159,8 @@
[UserExtensions.TianoCore."ExtraFiles"] MdeModulePkgExtra.uni + +[PcdsFixedAtBuild, PcdsPatchableInModule] + ## FFS filename to find the default BMP Logo file. + # @Prompt FFS Name of Boot Logo File + gEfiMdeModulePkgTokenSpaceGuid.PcdLogoFile |{ 0x99, 0x8b, 0xB2, 0x7B, 0xBB, 0x61, 0xD5, 0x11, 0x9A, 0x5D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }|VOID*|0x40000003 diff --git a/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c b/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c index 1c4952a..a15536e 100644 --- a/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c +++ b/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c @@ -238,6 +238,9 @@ 0, 0 ); + + // Inject boot logo into BGRT table + AddBGRT(); }
/** diff --git a/UefiPayloadPkg/UefiPayloadPkg.fdf b/UefiPayloadPkg/UefiPayloadPkg.fdf index cd69247..57e3b32 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.fdf +++ b/UefiPayloadPkg/UefiPayloadPkg.fdf @@ -129,6 +129,10 @@ INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf INF MdeModulePkg/Logo/LogoDxe.inf
+FILE FREEFORM = PCD(gEfiMdeModulePkgTokenSpaceGuid.PcdLogoFile) { + SECTION RAW = MdeModulePkg/Logo/Logo.bmp +} + # # PCI Support #