/** @file This module install ACPI Boot Graphics Resource Table (BGRT). Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
Copyright (c) 2016, Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** Update information of logo image drawn on screen. @param[in] This The pointer to the Boot Logo protocol 2 instance. @param[in] BltBuffer The BLT buffer for logo drawn on screen. If BltBuffer is set to NULL, it indicates that logo image is no longer on the screen. @param[in] DestinationX X coordinate of destination for the BltBuffer. @param[in] DestinationY Y coordinate of destination for the BltBuffer. @param[in] Width Width of rectangle in BltBuffer in pixels. @param[in] Height Hight of rectangle in BltBuffer in pixels. @retval EFI_SUCCESS The boot logo information was updated. @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. @retval EFI_OUT_OF_RESOURCES The logo information was not updated due to insufficient memory resources. **/ EFI_STATUS EFIAPI SetBootLogo ( IN EFI_BOOT_LOGO_PROTOCOL *This, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height ); /** Update information of logo image drawn on screen. @param[in] This The pointer to the Boot Logo protocol 2 instance. @param[in] BltBuffer The BLT buffer for logo drawn on screen. If BltBuffer is set to NULL, it indicates that logo image is no longer on the screen. @param[in] DestinationX X coordinate of destination for the BltBuffer. @param[in] DestinationY Y coordinate of destination for the BltBuffer. @param[in] Width Width of rectangle in BltBuffer in pixels. @param[in] Height Hight of rectangle in BltBuffer in pixels. @retval EFI_SUCCESS The boot logo information was updated. @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. @retval EFI_OUT_OF_RESOURCES The logo information was not updated due to insufficient memory resources. **/ EFI_STATUS EFIAPI SetBootLogo2 ( IN EDKII_BOOT_LOGO2_PROTOCOL *This, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height ); /** Get the location of the boot logo on the screen. @param[in] This The pointer to the Boot Logo Protocol 2 instance @param[out] BltBuffer Returns pointer to the GOP BLT buffer that was previously registered with SetBootLogo2(). The buffer returned must not be modified or freed. @param[out] DestinationX Returns the X start position of the GOP BLT buffer that was previously registered with SetBootLogo2(). @param[out] DestinationY Returns the Y start position of the GOP BLT buffer that was previously registered with SetBootLogo2(). @param[out] Width Returns the width of the GOP BLT buffer that was previously registered with SetBootLogo2(). @param[out] Height Returns the height of the GOP BLT buffer that was previously registered with SetBootLogo2(). @retval EFI_SUCCESS The location of the boot logo was returned. @retval EFI_NOT_READY The boot logo has not been set. @retval EFI_INVALID_PARAMETER BltBuffer is NULL. @retval EFI_INVALID_PARAMETER DestinationX is NULL. @retval EFI_INVALID_PARAMETER DestinationY is NULL. @retval EFI_INVALID_PARAMETER Width is NULL. @retval EFI_INVALID_PARAMETER Height is NULL. **/ EFI_STATUS EFIAPI GetBootLogo2 ( IN EDKII_BOOT_LOGO2_PROTOCOL *This, OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltBuffer, OUT UINTN *DestinationX, OUT UINTN *DestinationY, OUT UINTN *Width, OUT UINTN *Height ); // // Boot Logo Protocol Handle // EFI_HANDLE mBootLogoHandle = NULL; // // Boot Logo Protocol Instance // EFI_BOOT_LOGO_PROTOCOL mBootLogoProtocolTemplate = { SetBootLogo }; /// /// Boot Logo 2 Protocol instance /// EDKII_BOOT_LOGO2_PROTOCOL mBootLogo2ProtocolTemplate = { SetBootLogo2, GetBootLogo2 }; EFI_EVENT mBootGraphicsReadyToBootEvent; UINTN mBootGraphicsResourceTableKey = 0; BOOLEAN mIsLogoValid = FALSE; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *mLogoBltBuffer = NULL; UINTN mLogoDestX = 0; UINTN mLogoDestY = 0; UINTN mLogoWidth = 0; UINTN mLogoHeight = 0; BOOLEAN mAcpiBgrtInstalled = FALSE; BOOLEAN mAcpiBgrtStatusChanged = FALSE; BOOLEAN mAcpiBgrtBufferChanged = FALSE; // // ACPI Boot Graphics Resource Table template // EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE mBootGraphicsResourceTableTemplate = { { EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE, sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE), EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_REVISION, // Revision 0x00, // Checksum will be updated at runtime // // It is expected that these values will be updated at EntryPoint. // {0x00}, // OEM ID is a 6 bytes long field 0x00, // OEM Table ID(8 bytes long) 0x00, // OEM Revision 0x00, // Creator ID 0x00, // Creator Revision }, EFI_ACPI_5_0_BGRT_VERSION, // Version EFI_ACPI_5_0_BGRT_STATUS_VALID, // Status EFI_ACPI_5_0_BGRT_IMAGE_TYPE_BMP, // Image Type 0, // Image Address 0, // Image Offset X 0 // Image Offset Y }; /** Update information of logo image drawn on screen. @param This The pointer to the Boot Logo protocol instance. @param BltBuffer The BLT buffer for logo drawn on screen. If BltBuffer is set to NULL, it indicates that logo image is no longer on the screen. @param DestinationX X coordinate of destination for the BltBuffer. @param DestinationY Y coordinate of destination for the BltBuffer. @param Width Width of rectangle in BltBuffer in pixels. @param Height Hight of rectangle in BltBuffer in pixels. @retval EFI_SUCCESS The boot logo information was updated. @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. @retval EFI_OUT_OF_RESOURCES The logo information was not updated due to insufficient memory resources. **/ EFI_STATUS EFIAPI SetBootLogo ( IN EFI_BOOT_LOGO_PROTOCOL *This, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height ) { // // Call same service in Boot Logo 2 Protocol // return SetBootLogo2 ( &mBootLogo2ProtocolTemplate, BltBuffer, DestinationX, DestinationY, Width, Height ); } /** Update information of logo image drawn on screen. @param[in] This The pointer to the Boot Logo protocol 2 instance. @param[in] BltBuffer The BLT buffer for logo drawn on screen. If BltBuffer is set to NULL, it indicates that logo image is no longer on the screen. @param[in] DestinationX X coordinate of destination for the BltBuffer. @param[in] DestinationY Y coordinate of destination for the BltBuffer. @param[in] Width Width of rectangle in BltBuffer in pixels. @param[in] Height Hight of rectangle in BltBuffer in pixels. @retval EFI_SUCCESS The boot logo information was updated. @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. @retval EFI_OUT_OF_RESOURCES The logo information was not updated due to insufficient memory resources. **/ EFI_STATUS EFIAPI SetBootLogo2 ( IN EDKII_BOOT_LOGO2_PROTOCOL *This, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height ) { EFI_STATUS Status; UINTN BufferSize; UINT32 Result32; if (BltBuffer == NULL) { mIsLogoValid = FALSE; mAcpiBgrtStatusChanged = TRUE; return EFI_SUCCESS; } // // Width and height are not allowed to be zero. // if (Width == 0 || Height == 0) { return EFI_INVALID_PARAMETER; } // // Verify destination, width, and height do not overflow 32-bit values. // The Boot Graphics Resource Table only has 32-bit fields for these values. // Status = SafeUintnToUint32 (DestinationX, &Result32); if (EFI_ERROR(Status)) { return EFI_INVALID_PARAMETER; } Status = SafeUintnToUint32 (DestinationY, &Result32); if (EFI_ERROR(Status)) { return EFI_INVALID_PARAMETER; } Status = SafeUintnToUint32 (Width, &Result32); if (EFI_ERROR(Status)) { return EFI_INVALID_PARAMETER; } Status = SafeUintnToUint32 (Height, &Result32); if (EFI_ERROR(Status)) { return EFI_INVALID_PARAMETER; } // // Ensure the Height * Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) does // not overflow UINTN // Status = SafeUintnMult ( Width, Height, &BufferSize ); if (EFI_ERROR(Status)) { return EFI_UNSUPPORTED; } Status = SafeUintnMult ( BufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), &BufferSize ); if (EFI_ERROR(Status)) { return EFI_UNSUPPORTED; } // // Update state // mAcpiBgrtBufferChanged = TRUE; // // Free old logo buffer // if (mLogoBltBuffer != NULL) { FreePool(mLogoBltBuffer); mLogoBltBuffer = NULL; } // // Allocate new logo buffer // mLogoBltBuffer = AllocateCopyPool(BufferSize, BltBuffer); if (mLogoBltBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } mLogoDestX = DestinationX; mLogoDestY = DestinationY; mLogoWidth = Width; mLogoHeight = Height; mIsLogoValid = TRUE; return EFI_SUCCESS; } /** Get the location of the boot logo on the screen. @param[in] This The pointer to the Boot Logo Protocol 2 instance @param[out] BltBuffer Returns pointer to the GOP BLT buffer that was previously registered with SetBootLogo2(). The buffer returned must not be modified or freed. @param[out] DestinationX Returns the X start position of the GOP BLT buffer that was previously registered with SetBootLogo2(). @param[out] DestinationY Returns the Y start position of the GOP BLT buffer that was previously registered with SetBootLogo2(). @param[out] Width Returns the width of the GOP BLT buffer that was previously registered with SetBootLogo2(). @param[out] Height Returns the height of the GOP BLT buffer that was previously registered with SetBootLogo2(). @retval EFI_SUCCESS The location of the boot logo was returned. @retval EFI_NOT_READY The boot logo has not been set. @retval EFI_INVALID_PARAMETER BltBuffer is NULL. @retval EFI_INVALID_PARAMETER DestinationX is NULL. @retval EFI_INVALID_PARAMETER DestinationY is NULL. @retval EFI_INVALID_PARAMETER Width is NULL. @retval EFI_INVALID_PARAMETER Height is NULL. **/ EFI_STATUS EFIAPI GetBootLogo2 ( IN EDKII_BOOT_LOGO2_PROTOCOL *This, OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltBuffer, OUT UINTN *DestinationX, OUT UINTN *DestinationY, OUT UINTN *Width, OUT UINTN *Height ) { // // If the boot logo has not been set with SetBootLogo() or SetBootLogo() was // called with a NULL BltBuffer then the boot logo is not valid and // EFI_NOT_READY is returned. // if (mLogoBltBuffer == NULL) { DEBUG ((DEBUG_ERROR, "Request to get boot logo location before boot logo has been set.\n")); return EFI_NOT_READY; } // // Make sure none of the boot logo location parameters are NULL. // if (BltBuffer == NULL || DestinationX == NULL || DestinationY == NULL || Width == NULL || Height == NULL) { return EFI_INVALID_PARAMETER; } // // Boot logo is valid. Return values from module globals. // *BltBuffer = mLogoBltBuffer; *DestinationX = mLogoDestX; *DestinationY = mLogoDestY; *Width = mLogoWidth; *Height = mLogoHeight; return EFI_SUCCESS; } /** Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to install the Boot Graphics Resource Table. @param[in] Event The Event that is being processed. @param[in] Context The Event Context. **/ VOID EFIAPI BgrtReadyToBootEventNotify ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; VOID *ImageBuffer; UINT32 BmpSize; // // Get ACPI Table protocol. // Status = gBS->LocateProtocol ( &gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol ); if (EFI_ERROR(Status)) { return; } // // Check whether Boot Graphics Resource Table is already installed. // if (mAcpiBgrtInstalled) { if (!mAcpiBgrtStatusChanged && !mAcpiBgrtBufferChanged) { // // Nothing has changed // return; } else { // // If BGRT data change happens, then uninstall orignal AcpiTable first // Status = AcpiTableProtocol->UninstallAcpiTable ( AcpiTableProtocol, mBootGraphicsResourceTableKey ); if (EFI_ERROR(Status)) { return; } } } else { // // Check whether Logo exists // if (mLogoBltBuffer == NULL) { return; } } if (mAcpiBgrtBufferChanged) { // // Free the old BMP image buffer // ImageBuffer = (UINT8 *)(UINTN)mBootGraphicsResourceTableTemplate.ImageAddress; if (ImageBuffer != NULL) { FreePool(ImageBuffer); } // // Convert GOP Blt buffer to BMP image. Pass in ImageBuffer set to NULL // so the BMP image is allocated by TranslateGopBltToBmp(). // ImageBuffer = NULL; Status = TranslateGopBltToBmp ( mLogoBltBuffer, (UINT32)mLogoHeight, (UINT32)mLogoWidth, &ImageBuffer, &BmpSize ); if (EFI_ERROR(Status)) { return; } // // Free the logo buffer // FreePool(mLogoBltBuffer); mLogoBltBuffer = NULL; // // Update BMP image fields of the Boot Graphics Resource Table // mBootGraphicsResourceTableTemplate.ImageAddress = (UINT64)(UINTN)ImageBuffer; mBootGraphicsResourceTableTemplate.ImageOffsetX = (UINT32)mLogoDestX; mBootGraphicsResourceTableTemplate.ImageOffsetY = (UINT32)mLogoDestY; } // // Update Status field of Boot Graphics Resource Table // if (mIsLogoValid) { mBootGraphicsResourceTableTemplate.Status = EFI_ACPI_5_0_BGRT_STATUS_VALID; } else { mBootGraphicsResourceTableTemplate.Status = EFI_ACPI_5_0_BGRT_STATUS_INVALID; } // // Update Checksum of Boot Graphics Resource Table // mBootGraphicsResourceTableTemplate.Header.Checksum = 0; mBootGraphicsResourceTableTemplate.Header.Checksum = CalculateCheckSum8 ( (UINT8 *)&mBootGraphicsResourceTableTemplate, sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE) ); // // Publish Boot Graphics Resource Table. // Status = AcpiTableProtocol->InstallAcpiTable ( AcpiTableProtocol, &mBootGraphicsResourceTableTemplate, sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE), &mBootGraphicsResourceTableKey ); if (EFI_ERROR(Status)) { return; } mAcpiBgrtInstalled = TRUE; mAcpiBgrtStatusChanged = FALSE; mAcpiBgrtBufferChanged = FALSE; } /** The module Entry Point of the Boot Graphics Resource Table DXE driver. @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval Other Some error occurs when executing this entry point. **/ EFI_STATUS EFIAPI BootGraphicsDxeEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_ACPI_DESCRIPTION_HEADER *Header; // // Update Header fields of Boot Graphics Resource Table from PCDs // Header = &mBootGraphicsResourceTableTemplate.Header; ZeroMem (Header->OemId, sizeof (Header->OemId)); CopyMem( Header->OemId, PcdGetPtr (PcdAcpiDefaultOemId), MIN (PcdGetSize (PcdAcpiDefaultOemId), sizeof (Header->OemId)) ); WriteUnaligned64 (&Header->OemTableId, PcdGet64 (PcdAcpiDefaultOemTableId)); Header->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); Header->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); Header->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); // // Install Boot Logo and Boot Logo 2 Protocols. // Status = gBS->InstallMultipleProtocolInterfaces ( &mBootLogoHandle, &gEfiBootLogoProtocolGuid, &mBootLogoProtocolTemplate, &gEdkiiBootLogo2ProtocolGuid, &mBootLogo2ProtocolTemplate, NULL ); ASSERT_EFI_ERROR(Status); // // Register notify function to install BGRT on ReadyToBoot Event. // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, BgrtReadyToBootEventNotify, NULL, &gEfiEventReadyToBootGuid, &mBootGraphicsReadyToBootEvent ); ASSERT_EFI_ERROR(Status); return Status; }