EFI_STATUS EnableQuietBootEx ( IN EFI_GUID *LogoFile, IN EFI_HANDLE ImageHandle ) /*++ Routine Description: Use Console Control to turn off GOP/UGA based Simple Text Out consoles from going to the GOP/UGA device. Put up LogoFile on every GOP/UGA device that is a console Arguments: LogoFile - File name of logo to display on the center of the screen. ImageHandle - The driver image handle of the caller. The parameter is used to optimize the loading of the logo file so that the FV from which the driver image is loaded will be tried first. Returns: EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo displayed. EFI_UNSUPPORTED - Logo not found --*/ { EFI_STATUS Status; EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl; EFI_OEM_BADGING_PROTOCOL *Badging; UINT32 SizeOfX; UINT32 SizeOfY; INTN DestX; INTN DestY; UINT8 *ImageData; UINTN ImageSize; UINTN BltSize; UINT32 Instance; EFI_BADGING_FORMAT Format; EFI_BADGING_DISPLAY_ATTRIBUTE Attribute; UINTN CoordinateX; UINTN CoordinateY; UINTN Height; UINTN Width; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; EFI_UGA_DRAW_PROTOCOL *UgaDraw; UINT32 ColorDepth; UINT32 RefreshRate; EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID**)&ConsoleControl); 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)) { GraphicsOutput = NULL; // // Open GOP failed, try to open UGA // Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID**)&UgaDraw); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } } Badging = NULL; Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID**)&Badging); ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics); if (GraphicsOutput != NULL) { SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution; SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution; } else { Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } } Instance = 0; while (1) { ImageData = NULL; ImageSize = 0; if (Badging != NULL) { Status = Badging->GetImage ( Badging, &Instance, &Format, &ImageData, &ImageSize, &Attribute, &CoordinateX, &CoordinateY ); if (EFI_ERROR (Status)) { return Status; } // // Currently only support BMP format // if (Format != EfiBadgingFormatBMP) { gBS->FreePool (ImageData); continue; } } else { Status = GetGraphicsBitMapFromFVEx (ImageHandle, LogoFile, (VOID **) &ImageData, &ImageSize); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } CoordinateX = 0; CoordinateY = 0; Attribute = EfiBadgingDisplayAttributeCenter; } Blt = NULL; Status = ConvertBmpToGopBlt ( ImageData, ImageSize, (VOID**)&Blt, &BltSize, &Height, &Width ); if (EFI_ERROR (Status)) { gBS->FreePool (ImageData); if (Badging == NULL) { return Status; } else { continue; } } switch (Attribute) { case EfiBadgingDisplayAttributeLeftTop: DestX = CoordinateX; DestY = CoordinateY; break; case EfiBadgingDisplayAttributeCenterTop: DestX = (SizeOfX - Width) / 2; DestY = CoordinateY; break; case EfiBadgingDisplayAttributeRightTop: DestX = (SizeOfX - Width - CoordinateX); DestY = CoordinateY;; break; case EfiBadgingDisplayAttributeCenterRight: DestX = (SizeOfX - Width - CoordinateX); DestY = (SizeOfY - Height) / 2; break; case EfiBadgingDisplayAttributeRightBottom: DestX = (SizeOfX - Width - CoordinateX); DestY = (SizeOfY - Height - CoordinateY); break; case EfiBadgingDisplayAttributeCenterBottom: DestX = (SizeOfX - Width) / 2; DestY = (SizeOfY - Height - CoordinateY); break; case EfiBadgingDisplayAttributeLeftBottom: DestX = CoordinateX; DestY = (SizeOfY - Height - CoordinateY); break; case EfiBadgingDisplayAttributeCenterLeft: DestX = CoordinateX; DestY = (SizeOfY - Height) / 2; break; case EfiBadgingDisplayAttributeCenter: DestX = (SizeOfX - Width) / 2; DestY = (SizeOfY - Height) / 2; break; default: DestX = CoordinateX; DestY = CoordinateY; break; } if ((DestX >= 0) && (DestY >= 0)) { if (GraphicsOutput != NULL) { Status = GraphicsOutput->Blt ( GraphicsOutput, Blt, EfiBltBufferToVideo, 0, 0, (UINTN) DestX, (UINTN) DestY, Width, Height, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); } else { Status = UgaDraw->Blt ( UgaDraw, (EFI_UGA_PIXEL *) Blt, EfiUgaBltBufferToVideo, 0, 0, (UINTN) DestX, (UINTN) DestY, Width, Height, Width * sizeof (EFI_UGA_PIXEL) ); } } gBS->FreePool (ImageData); gBS->FreePool (Blt); if (Badging == NULL) { break; } } return Status; }
/** Use SystemTable Conout to stop video based Simple Text Out consoles from going to the video device. Put up LogoFile on every video device that is a console. @param[in] LogoFile File name of logo to display on the center of the screen. @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed. @retval EFI_UNSUPPORTED Logo not found **/ EFI_STATUS EFIAPI EnableQuietBoot ( IN EFI_GUID *LogoFile ) { EFI_STATUS Status; EFI_OEM_BADGING_PROTOCOL *Badging; UINT32 SizeOfX; UINT32 SizeOfY; INTN DestX; INTN DestY; UINT8 *ImageData; UINTN ImageSize; UINTN BltSize; UINT32 Instance; EFI_BADGING_FORMAT Format; EFI_BADGING_DISPLAY_ATTRIBUTE Attribute; UINTN CoordinateX; UINTN CoordinateY; UINTN Height; UINTN Width; 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; UINTN NumberOfLogos; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt; UINTN LogoDestX; UINTN LogoDestY; UINTN LogoHeight; UINTN LogoWidth; UINTN NewDestX; UINTN NewDestY; UINTN NewHeight; UINTN NewWidth; UINT64 BufferSize; 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)) { return EFI_UNSUPPORTED; } // // Try to open Boot Logo Protocol. // BootLogo = NULL; gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo); // // Erase Cursor from screen // gST->ConOut->EnableCursor (gST->ConOut, FALSE); Badging = NULL; Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging); if (GraphicsOutput != NULL) { SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution; SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution; } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) { Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } } else { return EFI_UNSUPPORTED; } Blt = NULL; NumberOfLogos = 0; LogoDestX = 0; LogoDestY = 0; LogoHeight = 0; LogoWidth = 0; NewDestX = 0; NewDestY = 0; NewHeight = 0; NewWidth = 0; Instance = 0; while (1) { ImageData = NULL; ImageSize = 0; if (Badging != NULL) { // // Get image from OEMBadging protocol. // Status = Badging->GetImage ( Badging, &Instance, &Format, &ImageData, &ImageSize, &Attribute, &CoordinateX, &CoordinateY ); if (EFI_ERROR (Status)) { goto Done; } // // Currently only support BMP format. // if (Format != EfiBadgingFormatBMP) { if (ImageData != NULL) { FreePool (ImageData); } continue; } } else { // // Get the specified image from FV. // Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } CoordinateX = 0; CoordinateY = 0; if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { Attribute = EfiBadgingDisplayAttributeCenter; } else { Attribute = EfiBadgingDisplayAttributeCustomized; } } if (Blt != NULL) { FreePool (Blt); } Blt = NULL; Status = TranslateBmpToGopBlt ( ImageData, ImageSize, &Blt, &BltSize, &Height, &Width ); if (EFI_ERROR (Status)) { FreePool (ImageData); if (Badging == NULL) { return Status; } else { continue; } } // // Calculate the display position according to Attribute. // switch (Attribute) { case EfiBadgingDisplayAttributeLeftTop: DestX = CoordinateX; DestY = CoordinateY; break; case EfiBadgingDisplayAttributeCenterTop: DestX = (SizeOfX - Width) / 2; DestY = CoordinateY; break; case EfiBadgingDisplayAttributeRightTop: DestX = (SizeOfX - Width - CoordinateX); DestY = CoordinateY;; break; case EfiBadgingDisplayAttributeCenterRight: DestX = (SizeOfX - Width - CoordinateX); DestY = (SizeOfY - Height) / 2; break; case EfiBadgingDisplayAttributeRightBottom: DestX = (SizeOfX - Width - CoordinateX); DestY = (SizeOfY - Height - CoordinateY); break; case EfiBadgingDisplayAttributeCenterBottom: DestX = (SizeOfX - Width) / 2; DestY = (SizeOfY - Height - CoordinateY); break; case EfiBadgingDisplayAttributeLeftBottom: DestX = CoordinateX; DestY = (SizeOfY - Height - CoordinateY); break; case EfiBadgingDisplayAttributeCenterLeft: DestX = CoordinateX; DestY = (SizeOfY - Height) / 2; break; case EfiBadgingDisplayAttributeCenter: DestX = (SizeOfX - Width) / 2; DestY = (SizeOfY - Height) / 2; break; case EfiBadgingDisplayAttributeCustomized: DestX = (SizeOfX - Width) / 2; DestY = ((SizeOfY * 382) / 1000) - Height / 2; break; default: DestX = CoordinateX; DestY = CoordinateY; break; } if ((DestX >= 0) && (DestY >= 0)) { if (GraphicsOutput != NULL) { Status = GraphicsOutput->Blt ( GraphicsOutput, Blt, EfiBltBufferToVideo, 0, 0, (UINTN) DestX, (UINTN) DestY, Width, Height, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) { Status = UgaDraw->Blt ( UgaDraw, (EFI_UGA_PIXEL *) Blt, EfiUgaBltBufferToVideo, 0, 0, (UINTN) DestX, (UINTN) DestY, Width, Height, Width * sizeof (EFI_UGA_PIXEL) ); } else { Status = EFI_UNSUPPORTED; } // // Report displayed Logo information. // if (!EFI_ERROR (Status)) { NumberOfLogos++; if (LogoWidth == 0) { // // The first Logo. // LogoDestX = (UINTN) DestX; LogoDestY = (UINTN) DestY; LogoWidth = Width; LogoHeight = Height; } else { // // Merge new logo with old one. // NewDestX = MIN ((UINTN) DestX, LogoDestX); NewDestY = MIN ((UINTN) DestY, LogoDestY); NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX; NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY; LogoDestX = NewDestX; LogoDestY = NewDestY; LogoWidth = NewWidth; LogoHeight = NewHeight; } } } FreePool (ImageData); if (Badging == NULL) { break; } } Done: if (BootLogo == 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 doesn't overflow // if (LogoHeight > DivU64x64Remainder ((UINTN) ~0, LogoWidth, NULL)) { return EFI_UNSUPPORTED; } BufferSize = MultU64x64 (LogoWidth, LogoHeight); // // 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; } LogoBlt = AllocateZeroPool ((UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); 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 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) { Status = UgaDraw->Blt ( UgaDraw, (EFI_UGA_PIXEL *) LogoBlt, EfiUgaVideoToBltBuffer, LogoDestX, LogoDestY, 0, 0, LogoWidth, LogoHeight, LogoWidth * sizeof (EFI_UGA_PIXEL) ); } else { Status = EFI_UNSUPPORTED; } } if (!EFI_ERROR (Status)) { BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight); } FreePool (LogoBlt); return Status; }