IntelFrameworkModulePkg: add BGRT table
Add support for adding a BGRT table for Windows 8/8.1/10 bootlogo.
This commit is contained in:
272
IntelFrameworkModulePkg/Universal/BdsDxe/AddBGRT.c
Normal file
272
IntelFrameworkModulePkg/Universal/BdsDxe/AddBGRT.c
Normal file
@ -0,0 +1,272 @@
|
||||
#include "Bds.h"
|
||||
#include "FrontPage.h"
|
||||
#include <IndustryStandard/Acpi.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(){
|
||||
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"));
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user