Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13527 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			494 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			494 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   This module install ACPI Boot Graphics Resource Table (BGRT).
 | |
| 
 | |
|   Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| **/
 | |
| 
 | |
| #include <Uefi.h>
 | |
| 
 | |
| #include <IndustryStandard/Acpi.h>
 | |
| #include <IndustryStandard/Bmp.h>
 | |
| 
 | |
| #include <Protocol/AcpiTable.h>
 | |
| #include <Protocol/GraphicsOutput.h>
 | |
| #include <Protocol/BootLogo.h>
 | |
| 
 | |
| #include <Guid/EventGroup.h>
 | |
| 
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/MemoryAllocationLib.h>
 | |
| #include <Library/UefiBootServicesTableLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| 
 | |
| //
 | |
| // ACPI table information used to initialize tables.
 | |
| //
 | |
| #define EFI_ACPI_OEM_ID           "INTEL"
 | |
| #define EFI_ACPI_OEM_TABLE_ID     0x2020204F4E414954ULL // "TIANO   "
 | |
| #define EFI_ACPI_OEM_REVISION     0x00000001
 | |
| #define EFI_ACPI_CREATOR_ID       0x5446534D            // TBD "MSFT"
 | |
| #define EFI_ACPI_CREATOR_REVISION 0x01000013            // TBD
 | |
| 
 | |
| //
 | |
| // Module globals.
 | |
| //
 | |
| EFI_EVENT  mBootGraphicsReadyToBootEvent;
 | |
| UINTN      mBootGraphicsResourceTableKey = 0;
 | |
| 
 | |
| EFI_HANDLE                     mBootLogoHandle = NULL;
 | |
| BOOLEAN                        mIsLogoValid = FALSE;
 | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *mLogoBltBuffer = NULL;
 | |
| UINTN                          mLogoDestX = 0;
 | |
| UINTN                          mLogoDestY = 0;
 | |
| UINTN                          mLogoWidth = 0;
 | |
| UINTN                          mLogoHeight = 0;
 | |
| 
 | |
| BMP_IMAGE_HEADER  mBmpImageHeaderTemplate = {
 | |
|   'B',    // CharB
 | |
|   'M',    // CharM
 | |
|   0,      // Size will be updated at runtime
 | |
|   {0, 0}, // Reserved
 | |
|   sizeof (BMP_IMAGE_HEADER), // ImageOffset
 | |
|   sizeof (BMP_IMAGE_HEADER) - OFFSET_OF (BMP_IMAGE_HEADER, HeaderSize), // HeaderSize
 | |
|   0,      // PixelWidth will be updated at runtime
 | |
|   0,      // PixelHeight will be updated at runtime
 | |
|   1,      // Planes
 | |
|   24,     // BitPerPixel
 | |
|   0,      // CompressionType
 | |
|   0,      // ImageSize will be updated at runtime
 | |
|   0,      // XPixelsPerMeter
 | |
|   0,      // YPixelsPerMeter
 | |
|   0,      // NumberOfColors
 | |
|   0       // ImportantColors
 | |
| };
 | |
| 
 | |
| BOOLEAN  mAcpiBgrtInstalled = FALSE;
 | |
| BOOLEAN  mAcpiBgrtStatusChanged = FALSE;
 | |
| BOOLEAN  mAcpiBgrtBufferChanged = FALSE;
 | |
| 
 | |
| 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 runtime.
 | |
|     //
 | |
|     EFI_ACPI_OEM_ID,            // OEMID is a 6 bytes long field
 | |
|     EFI_ACPI_OEM_TABLE_ID,      // OEM table identification(8 bytes long)
 | |
|     EFI_ACPI_OEM_REVISION,      // OEM revision number
 | |
|     EFI_ACPI_CREATOR_ID,        // ASL compiler vendor ID
 | |
|     EFI_ACPI_CREATOR_REVISION,  // ASL compiler revision number
 | |
|   },
 | |
|   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
 | |
|   );
 | |
| 
 | |
| EFI_BOOT_LOGO_PROTOCOL  mBootLogoProtocolTemplate = { SetBootLogo };
 | |
| 
 | |
| /**
 | |
|   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
 | |
|   )
 | |
| {
 | |
|   UINT64                        BufferSize;
 | |
| 
 | |
|   if (BltBuffer == NULL) {
 | |
|     mIsLogoValid = FALSE;
 | |
|     mAcpiBgrtStatusChanged = TRUE;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (Width == 0 || Height == 0) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   
 | |
|   mAcpiBgrtBufferChanged = TRUE;
 | |
|   if (mLogoBltBuffer != NULL) {
 | |
|     FreePool (mLogoBltBuffer);
 | |
|     mLogoBltBuffer = NULL;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Ensure the Height * Width doesn't overflow
 | |
|   //
 | |
|   if (Height > DivU64x64Remainder ((UINTN) ~0, Width, NULL)) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
|   BufferSize = MultU64x64 (Width, Height);
 | |
|   
 | |
|   //
 | |
|   // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
 | |
|   //
 | |
|   if (BufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   mLogoBltBuffer = AllocateCopyPool (
 | |
|                      (UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),
 | |
|                      BltBuffer
 | |
|                      );
 | |
|   if (mLogoBltBuffer == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   mLogoDestX = DestinationX;
 | |
|   mLogoDestY = DestinationY;
 | |
|   mLogoWidth = Width;
 | |
|   mLogoHeight = Height;
 | |
|   mIsLogoValid = TRUE;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function calculates and updates an UINT8 checksum.
 | |
| 
 | |
|   @param[in]  Buffer          Pointer to buffer to checksum.
 | |
|   @param[in]  Size            Number of bytes to checksum.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| BgrtAcpiTableChecksum (
 | |
|   IN UINT8      *Buffer,
 | |
|   IN UINTN      Size
 | |
|   )
 | |
| {
 | |
|   UINTN ChecksumOffset;
 | |
| 
 | |
|   ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
 | |
| 
 | |
|   //
 | |
|   // Set checksum to 0 first.
 | |
|   //
 | |
|   Buffer[ChecksumOffset] = 0;
 | |
| 
 | |
|   //
 | |
|   // Update checksum value.
 | |
|   //
 | |
|   Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Size);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Allocate EfiReservedMemoryType below 4G memory address.
 | |
| 
 | |
|   This function allocates EfiReservedMemoryType below 4G memory address.
 | |
| 
 | |
|   @param[in]  Size   Size of memory to allocate.
 | |
| 
 | |
|   @return Allocated address for output.
 | |
| 
 | |
| **/
 | |
| VOID *
 | |
| BgrtAllocateReservedMemoryBelow4G (
 | |
|   IN UINTN       Size
 | |
|   )
 | |
| {
 | |
|   UINTN                 Pages;
 | |
|   EFI_PHYSICAL_ADDRESS  Address;
 | |
|   EFI_STATUS            Status;
 | |
|   VOID                  *Buffer;
 | |
| 
 | |
|   Pages   = EFI_SIZE_TO_PAGES (Size);
 | |
|   Address = 0xffffffff;
 | |
| 
 | |
|   Status = gBS->AllocatePages (
 | |
|                   AllocateMaxAddress,
 | |
|                   EfiReservedMemoryType,
 | |
|                   Pages,
 | |
|                   &Address
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   Buffer = (VOID *) (UINTN) Address;
 | |
|   ZeroMem (Buffer, Size);
 | |
| 
 | |
|   return Buffer;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Install Boot Graphics Resource Table to ACPI table.
 | |
| 
 | |
|   @return Status code.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| InstallBootGraphicsResourceTable (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_ACPI_TABLE_PROTOCOL       *AcpiTableProtocol;
 | |
|   UINT8                         *ImageBuffer;
 | |
|   UINTN                         PaddingSize;
 | |
|   UINTN                         BmpSize;
 | |
|   UINTN                         OrigBmpSize;
 | |
|   UINT8                         *Image;
 | |
|   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPixel;
 | |
|   UINTN                         Col;
 | |
|   UINTN                         Row;
 | |
| 
 | |
|   //
 | |
|   // Get ACPI Table protocol.
 | |
|   //
 | |
|   Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check whether Boot Graphics Resource Table is already installed.
 | |
|   //
 | |
|   if (mAcpiBgrtInstalled) {
 | |
|     if (!mAcpiBgrtStatusChanged && !mAcpiBgrtBufferChanged) {
 | |
|       //
 | |
|       // Nothing has changed
 | |
|       //
 | |
|       return EFI_SUCCESS;
 | |
|     } else {
 | |
|       //
 | |
|       // If BGRT data change happens. Uninstall Orignal AcpiTable first
 | |
|       //
 | |
|       Status = AcpiTableProtocol->UninstallAcpiTable (
 | |
|                                     AcpiTableProtocol,
 | |
|                                     mBootGraphicsResourceTableKey
 | |
|                                     );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         return Status;
 | |
|       } 
 | |
|     }
 | |
|   } else {
 | |
|     //
 | |
|     // Check whether Logo exist.
 | |
|     //
 | |
|     if ( mLogoBltBuffer == NULL) {
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (mAcpiBgrtBufferChanged) {
 | |
|     //
 | |
|     // reserve original BGRT buffer size
 | |
|     //
 | |
|     OrigBmpSize = mBmpImageHeaderTemplate.ImageSize + sizeof (BMP_IMAGE_HEADER);
 | |
|     //
 | |
|     // Free orignal BMP memory 
 | |
|     // 
 | |
|     if (mBootGraphicsResourceTableTemplate.ImageAddress) {
 | |
|       gBS->FreePages(mBootGraphicsResourceTableTemplate.ImageAddress, EFI_SIZE_TO_PAGES(OrigBmpSize));
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Allocate memory for BMP file.
 | |
|     //
 | |
|     PaddingSize = mLogoWidth & 0x3;
 | |
| 
 | |
|     //
 | |
|     // First check mLogoWidth * 3 + PaddingSize doesn't overflow
 | |
|     //
 | |
|     if (mLogoWidth > (((UINT32) ~0) - PaddingSize) / 3 ) {
 | |
|       return EFI_UNSUPPORTED;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Second check (mLogoWidth * 3 + PaddingSize) * mLogoHeight + sizeof (BMP_IMAGE_HEADER) doesn't overflow
 | |
|     //
 | |
|     if (mLogoHeight > (((UINT32) ~0) - sizeof (BMP_IMAGE_HEADER)) / (mLogoWidth * 3 + PaddingSize)) {
 | |
|       return EFI_UNSUPPORTED;
 | |
|     }
 | |
|     
 | |
|     BmpSize = (mLogoWidth * 3 + PaddingSize) * mLogoHeight + sizeof (BMP_IMAGE_HEADER);
 | |
|     ImageBuffer = BgrtAllocateReservedMemoryBelow4G (BmpSize);
 | |
|     if (ImageBuffer == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     mBmpImageHeaderTemplate.Size = (UINT32) BmpSize;
 | |
|     mBmpImageHeaderTemplate.ImageSize = (UINT32) BmpSize - sizeof (BMP_IMAGE_HEADER);
 | |
|     mBmpImageHeaderTemplate.PixelWidth = (UINT32) mLogoWidth;
 | |
|     mBmpImageHeaderTemplate.PixelHeight = (UINT32) mLogoHeight;
 | |
|     CopyMem (ImageBuffer, &mBmpImageHeaderTemplate, sizeof (BMP_IMAGE_HEADER));
 | |
|     
 | |
|     //
 | |
|     // Convert BLT buffer to BMP file.
 | |
|     //
 | |
|     Image = ImageBuffer + sizeof (BMP_IMAGE_HEADER);
 | |
|     for (Row = 0; Row < mLogoHeight; Row++) {
 | |
|     BltPixel = &mLogoBltBuffer[(mLogoHeight - Row - 1) * mLogoWidth];
 | |
| 
 | |
|     for (Col = 0; Col < mLogoWidth; Col++) {
 | |
|       *Image++ = BltPixel->Blue;
 | |
|       *Image++ = BltPixel->Green;
 | |
|       *Image++ = BltPixel->Red;
 | |
|       BltPixel++;
 | |
|     }
 | |
| 
 | |
|       //
 | |
|       // Padding for 4 byte alignment.
 | |
|       //
 | |
|       Image += PaddingSize;
 | |
|     }
 | |
|     FreePool (mLogoBltBuffer);
 | |
|     mLogoBltBuffer = NULL;
 | |
| 
 | |
|     mBootGraphicsResourceTableTemplate.ImageAddress = (UINT64) (UINTN) ImageBuffer;
 | |
|     mBootGraphicsResourceTableTemplate.ImageOffsetX = (UINT32) mLogoDestX;
 | |
|     mBootGraphicsResourceTableTemplate.ImageOffsetY = (UINT32) mLogoDestY;
 | |
|   }
 | |
| 
 | |
|   mBootGraphicsResourceTableTemplate.Status = (UINT8) (mIsLogoValid ? EFI_ACPI_5_0_BGRT_STATUS_VALID : EFI_ACPI_5_0_BGRT_STATUS_INVALID);
 | |
| 
 | |
|   //
 | |
|   // Update Checksum.
 | |
|   //
 | |
|   BgrtAcpiTableChecksum ((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 Status;
 | |
|   }
 | |
| 
 | |
|   mAcpiBgrtInstalled = TRUE;
 | |
|   mAcpiBgrtStatusChanged = FALSE;
 | |
|   mAcpiBgrtBufferChanged = FALSE;
 | |
|   
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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
 | |
|   )
 | |
| {
 | |
|   InstallBootGraphicsResourceTable ();
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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;
 | |
| 
 | |
|   //
 | |
|   // Install Boot Logo protocol.
 | |
|   //
 | |
|   Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                   &mBootLogoHandle,
 | |
|                   &gEfiBootLogoProtocolGuid,
 | |
|                   &mBootLogoProtocolTemplate,
 | |
|                   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;
 | |
| }
 |