diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/AddBGRT.c b/IntelFrameworkModulePkg/Universal/BdsDxe/AddBGRT.c new file mode 100644 index 0000000000..3deb80ef90 --- /dev/null +++ b/IntelFrameworkModulePkg/Universal/BdsDxe/AddBGRT.c @@ -0,0 +1,272 @@ +#include "Bds.h" +#include "FrontPage.h" +#include +#include +#include + +/** 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(){ + EFI_STATUS status; + ACPI_BGRT *bgrt; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_PHYSICAL_ADDRESS BmpAddress; + UINT32 BmpSize; + 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) + { + bgrt->image_address = (UINTN)BmpAddress; + bgrt->image_offset_x = (GraphicsOutput->Mode->Info->HorizontalResolution - 200)/2; + bgrt->image_offset_y = (GraphicsOutput->Mode->Info->VerticalResolution * 2/3 - 161)/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")); + } +} \ No newline at end of file diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf b/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf index 7fec0c9fe3..eaa93aa435 100644 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf +++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf @@ -84,7 +84,7 @@ FrontPageStrings.uni FrontPage.c BdsEntry.c - + AddBGRT.c [Packages] MdePkg/MdePkg.dec @@ -136,6 +136,8 @@ ## SOMETIMES_CONSUMES ## Variable:L"ConOutDev" # The device path of console out device ## SOMETIMES_CONSUMES ## Variable:L"ErrOutDev" # The device path of error out device ## SOMETIMES_PRODUCES ## Variable:L"BootNext" # The number of next boot option + gEfiAcpiTableGuid + gEfiAcpi20TableGuid gEfiGlobalVariableGuid gEfiFileSystemVolumeLabelInfoIdGuid ## SOMETIMES_CONSUMES ## UNDEFINED # Indicate the information type is volume gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## UNDEFINED # Indicate the information type is file @@ -215,6 +217,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile [Depex] TRUE diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c index f8a54d5c14..debb7008bc 100644 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c +++ b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c @@ -74,6 +74,8 @@ HII_VENDOR_DEVICE_PATH mFrontPageHiiVendorDevicePath = { } }; +void AddBGRT(); + /** This function allows a caller to extract the current configuration for one or more named elements from the target driver. @@ -1234,6 +1236,7 @@ PlatformBdsEnterFrontPage ( mModeInitialized = TRUE; } + AddBGRT(); // // goto FrontPage directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set