From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../MdeModulePkg/Library/BootLogoLib/BootLogoLib.c | 551 +++++++++++++++++++++ 1 file changed, 551 insertions(+) create mode 100644 src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c (limited to 'src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c') diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c new file mode 100644 index 00000000..ab4e58a2 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c @@ -0,0 +1,551 @@ +/** @file + This library is only intended to be used by PlatformBootManagerLib + to show progress bar and LOGO. + +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 + +/** + Show LOGO returned from Edkii Platform Logo protocol on all consoles. + + @retval EFI_SUCCESS Logo was displayed. + @retval EFI_UNSUPPORTED Logo was not found or cannot be displayed. +**/ +EFI_STATUS +EFIAPI +BootLogoEnableLogo ( + VOID + ) +{ + EFI_STATUS Status; + EDKII_PLATFORM_LOGO_PROTOCOL *PlatformLogo; + EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE Attribute; + INTN OffsetX; + INTN OffsetY; + UINT32 SizeOfX; + UINT32 SizeOfY; + INTN DestX; + INTN DestY; + UINT32 Instance; + EFI_IMAGE_INPUT Image; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + UINT32 ColorDepth; + UINT32 RefreshRate; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_BOOT_LOGO_PROTOCOL *BootLogo; + EDKII_BOOT_LOGO2_PROTOCOL *BootLogo2; + UINTN NumberOfLogos; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt; + UINTN LogoDestX; + UINTN LogoDestY; + UINTN LogoHeight; + UINTN LogoWidth; + UINTN NewDestX; + UINTN NewDestY; + UINTN BufferSize; + + Status = gBS->LocateProtocol (&gEdkiiPlatformLogoProtocolGuid, NULL, (VOID **) &PlatformLogo); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + UgaDraw = NULL; + // + // Try to open GOP first + // + Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput); + if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) { + GraphicsOutput = NULL; + // + // Open GOP failed, try to open UGA + // + Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw); + if (EFI_ERROR (Status)) { + UgaDraw = NULL; + } + } + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Try to open Boot Logo Protocol. + // + Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo); + if (EFI_ERROR (Status)) { + BootLogo = NULL; + } + + // + // Try to open Boot Logo 2 Protocol. + // + Status = gBS->LocateProtocol (&gEdkiiBootLogo2ProtocolGuid, NULL, (VOID **) &BootLogo2); + if (EFI_ERROR (Status)) { + BootLogo2 = NULL; + } + + // + // Erase Cursor from screen + // + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + if (GraphicsOutput != NULL) { + SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution; + SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution; + + } else { + ASSERT (UgaDraw != NULL); + Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + } + + Blt = NULL; + NumberOfLogos = 0; + LogoDestX = 0; + LogoDestY = 0; + LogoHeight = 0; + LogoWidth = 0; + NewDestX = 0; + NewDestY = 0; + Instance = 0; + DestX = 0; + DestY = 0; + while (TRUE) { + // + // Get image from PlatformLogo protocol. + // + Status = PlatformLogo->GetImage ( + PlatformLogo, + &Instance, + &Image, + &Attribute, + &OffsetX, + &OffsetY + ); + if (EFI_ERROR (Status)) { + break; + } + + if (Blt != NULL) { + FreePool (Blt); + } + Blt = Image.Bitmap; + + // + // Calculate the display position according to Attribute. + // + switch (Attribute) { + case EdkiiPlatformLogoDisplayAttributeLeftTop: + DestX = 0; + DestY = 0; + break; + case EdkiiPlatformLogoDisplayAttributeCenterTop: + DestX = (SizeOfX - Image.Width) / 2; + DestY = 0; + break; + case EdkiiPlatformLogoDisplayAttributeRightTop: + DestX = SizeOfX - Image.Width; + DestY = 0; + break; + + case EdkiiPlatformLogoDisplayAttributeCenterLeft: + DestX = 0; + DestY = (SizeOfY - Image.Height) / 2; + break; + case EdkiiPlatformLogoDisplayAttributeCenter: + DestX = (SizeOfX - Image.Width) / 2; + DestY = (SizeOfY - Image.Height) / 2; + break; + case EdkiiPlatformLogoDisplayAttributeCenterRight: + DestX = SizeOfX - Image.Width; + DestY = (SizeOfY - Image.Height) / 2; + break; + + case EdkiiPlatformLogoDisplayAttributeLeftBottom: + DestX = 0; + DestY = SizeOfY - Image.Height; + break; + case EdkiiPlatformLogoDisplayAttributeCenterBottom: + DestX = (SizeOfX - Image.Width) / 2; + DestY = SizeOfY - Image.Height; + break; + case EdkiiPlatformLogoDisplayAttributeRightBottom: + DestX = SizeOfX - Image.Width; + DestY = SizeOfY - Image.Height; + break; + + default: + ASSERT (FALSE); + continue; + break; + } + + DestX += OffsetX; + DestY += OffsetY; + + if ((DestX >= 0) && (DestY >= 0)) { + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + Blt, + EfiBltBufferToVideo, + 0, + 0, + (UINTN) DestX, + (UINTN) DestY, + Image.Width, + Image.Height, + Image.Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else { + ASSERT (UgaDraw != NULL); + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) Blt, + EfiUgaBltBufferToVideo, + 0, + 0, + (UINTN) DestX, + (UINTN) DestY, + Image.Width, + Image.Height, + Image.Width * sizeof (EFI_UGA_PIXEL) + ); + } + + // + // Report displayed Logo information. + // + if (!EFI_ERROR (Status)) { + NumberOfLogos++; + + if (NumberOfLogos == 1) { + // + // The first Logo. + // + LogoDestX = (UINTN) DestX; + LogoDestY = (UINTN) DestY; + LogoWidth = Image.Width; + LogoHeight = Image.Height; + } else { + // + // Merge new logo with old one. + // + NewDestX = MIN ((UINTN) DestX, LogoDestX); + NewDestY = MIN ((UINTN) DestY, LogoDestY); + LogoWidth = MAX ((UINTN) DestX + Image.Width, LogoDestX + LogoWidth) - NewDestX; + LogoHeight = MAX ((UINTN) DestY + Image.Height, LogoDestY + LogoHeight) - NewDestY; + + LogoDestX = NewDestX; + LogoDestY = NewDestY; + } + } + } + } + + if ((BootLogo == NULL && BootLogo2 == NULL) || NumberOfLogos == 0) { + // + // No logo displayed. + // + if (Blt != NULL) { + FreePool (Blt); + } + + return Status; + } + + // + // Advertise displayed Logo information. + // + if (NumberOfLogos == 1) { + // + // Only one logo displayed, use its Blt buffer directly for BootLogo protocol. + // + LogoBlt = Blt; + Status = EFI_SUCCESS; + } else { + // + // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation. + // + if (Blt != NULL) { + FreePool (Blt); + } + + // + // Ensure the LogoHeight * LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow + // + if (LogoHeight > MAX_UINTN / LogoWidth / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) { + return EFI_UNSUPPORTED; + } + BufferSize = LogoWidth * LogoHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + + LogoBlt = AllocatePool (BufferSize); + if (LogoBlt == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + LogoBlt, + EfiBltVideoToBltBuffer, + LogoDestX, + LogoDestY, + 0, + 0, + LogoWidth, + LogoHeight, + LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else { + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) LogoBlt, + EfiUgaVideoToBltBuffer, + LogoDestX, + LogoDestY, + 0, + 0, + LogoWidth, + LogoHeight, + LogoWidth * sizeof (EFI_UGA_PIXEL) + ); + } + } + + if (!EFI_ERROR (Status)) { + // + // Attempt to register logo with Boot Logo 2 Protocol first + // + if (BootLogo2 != NULL) { + Status = BootLogo2->SetBootLogo (BootLogo2, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight); + } + // + // If Boot Logo 2 Protocol is not available or registration with Boot Logo 2 + // Protocol failed, then attempt to register logo with Boot Logo Protocol + // + if (EFI_ERROR (Status) && BootLogo != NULL) { + Status = BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight); + } + // + // Status of this function is EFI_SUCCESS even if registration with Boot + // Logo 2 Protocol or Boot Logo Protocol fails. + // + Status = EFI_SUCCESS; + } + FreePool (LogoBlt); + + return Status; +} + +/** + Use SystemTable Conout to turn on video based Simple Text Out consoles. The + Simple Text Out screens will now be synced up with all non video output devices + + @retval EFI_SUCCESS UGA devices are back in text mode and synced up. + +**/ +EFI_STATUS +EFIAPI +BootLogoDisableLogo ( + VOID + ) +{ + + // + // Enable Cursor on Screen + // + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + return EFI_SUCCESS; +} + + +/** + + Update progress bar with title above it. It only works in Graphics mode. + + @param TitleForeground Foreground color for Title. + @param TitleBackground Background color for Title. + @param Title Title above progress bar. + @param ProgressColor Progress bar color. + @param Progress Progress (0-100) + @param PreviousValue The previous value of the progress. + + @retval EFI_STATUS Success update the progress bar + +**/ +EFI_STATUS +EFIAPI +BootLogoUpdateProgress ( + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground, + IN CHAR16 *Title, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor, + IN UINTN Progress, + IN UINTN PreviousValue + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + UINT32 SizeOfX; + UINT32 SizeOfY; + UINT32 ColorDepth; + UINT32 RefreshRate; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; + UINTN BlockHeight; + UINTN BlockWidth; + UINTN BlockNum; + UINTN PosX; + UINTN PosY; + UINTN Index; + + if (Progress > 100) { + return EFI_INVALID_PARAMETER; + } + + UgaDraw = NULL; + Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput); + if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) { + GraphicsOutput = NULL; + + Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw); + if (EFI_ERROR (Status)) { + UgaDraw = NULL; + } + } + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + SizeOfX = 0; + SizeOfY = 0; + if (GraphicsOutput != NULL) { + SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution; + SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution; + } else if (UgaDraw != NULL) { + Status = UgaDraw->GetMode ( + UgaDraw, + &SizeOfX, + &SizeOfY, + &ColorDepth, + &RefreshRate + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + } else { + return EFI_UNSUPPORTED; + } + + BlockWidth = SizeOfX / 100; + BlockHeight = SizeOfY / 50; + + BlockNum = Progress; + + PosX = 0; + PosY = SizeOfY * 48 / 50; + + if (BlockNum == 0) { + // + // Clear progress area + // + SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); + + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + &Color, + EfiBltVideoFill, + 0, + 0, + 0, + PosY - EFI_GLYPH_HEIGHT - 1, + SizeOfX, + SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1), + SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else if (FeaturePcdGet (PcdUgaConsumeSupport)) { + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) &Color, + EfiUgaVideoFill, + 0, + 0, + 0, + PosY - EFI_GLYPH_HEIGHT - 1, + SizeOfX, + SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1), + SizeOfX * sizeof (EFI_UGA_PIXEL) + ); + } else { + return EFI_UNSUPPORTED; + } + } + // + // Show progress by drawing blocks + // + for (Index = PreviousValue; Index < BlockNum; Index++) { + PosX = Index * BlockWidth; + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + &ProgressColor, + EfiBltVideoFill, + 0, + 0, + PosX, + PosY, + BlockWidth - 1, + BlockHeight, + (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else if (FeaturePcdGet (PcdUgaConsumeSupport)) { + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) &ProgressColor, + EfiUgaVideoFill, + 0, + 0, + PosX, + PosY, + BlockWidth - 1, + BlockHeight, + (BlockWidth) * sizeof (EFI_UGA_PIXEL) + ); + } else { + return EFI_UNSUPPORTED; + } + } + + PrintXY ( + (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2, + PosY - EFI_GLYPH_HEIGHT - 1, + &TitleForeground, + &TitleBackground, + Title + ); + + return EFI_SUCCESS; +} -- cgit v1.2.3