2 BDS Lib functions which contain all the code to connect console device
4 Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "InternalBdsLib.h"
16 #include <IndustryStandard/Bmp.h>
20 Check if we need to save the EFI variable with "ConVarName" as name
22 If ConVarName is NULL, then ASSERT().
24 @param ConVarName The name of the EFI variable.
26 @retval TRUE Set the EFI variable as NV type.
27 @retval FALSE EFI variable as NV type can be set NonNV.
36 ASSERT (ConVarName
!= NULL
);
41 // If the variable includes "Dev" at last, we consider
42 // it does not support NV attribute.
44 while (*Ptr
!= L
'\0') {
48 if (((INTN
)((UINTN
)Ptr
- (UINTN
)ConVarName
) / sizeof (CHAR16
)) <= 3) {
52 if ((*(Ptr
- 3) == 'D') && (*(Ptr
- 2) == 'e') && (*(Ptr
- 1) == 'v')) {
60 Fill console handle in System Table if there are no valid console handle in.
62 Firstly, check the validation of console handle in System Table. If it is invalid,
63 update it by the first console device handle from EFI console variable.
65 @param VarName The name of the EFI console variable.
66 @param ConsoleGuid Specified Console protocol GUID.
67 @param ConsoleHandle On IN, console handle in System Table to be checked.
68 On OUT, new console handle in system table.
69 @param ProtocolInterface On IN, console protocol on console handle in System Table to be checked.
70 On OUT, new console protocol on new console handle in system table.
72 @retval TRUE System Table has been updated.
73 @retval FALSE System Table hasn't been updated.
77 UpdateSystemTableConsole (
79 IN EFI_GUID
*ConsoleGuid
,
80 IN OUT EFI_HANDLE
*ConsoleHandle
,
81 IN OUT VOID
**ProtocolInterface
86 EFI_DEVICE_PATH_PROTOCOL
*FullDevicePath
;
87 EFI_DEVICE_PATH_PROTOCOL
*VarConsole
;
88 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
91 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
93 ASSERT (VarName
!= NULL
);
94 ASSERT (ConsoleHandle
!= NULL
);
95 ASSERT (ConsoleGuid
!= NULL
);
96 ASSERT (ProtocolInterface
!= NULL
);
98 if (*ConsoleHandle
!= NULL
) {
99 Status
= gBS
->HandleProtocol (
104 if (Status
== EFI_SUCCESS
&& Interface
== *ProtocolInterface
) {
106 // If ConsoleHandle is valid and console protocol on this handle also
107 // also matched, just return.
114 // Get all possible consoles device path from EFI variable
116 VarConsole
= BdsLibGetVariableAndSize (
118 &gEfiGlobalVariableGuid
,
121 if (VarConsole
== NULL
) {
123 // If there is no any console device, just return.
128 FullDevicePath
= VarConsole
;
132 // Check every instance of the console variable
134 Instance
= GetNextDevicePathInstance (&VarConsole
, &DevicePathSize
);
135 if (Instance
== NULL
) {
136 FreePool (FullDevicePath
);
141 // Find console device handle by device path instance
143 Status
= gBS
->LocateDevicePath (
148 if (!EFI_ERROR (Status
)) {
150 // Get the console protocol on this console device handle
152 Status
= gBS
->HandleProtocol (
157 if (!EFI_ERROR (Status
)) {
159 // Update new console handle in System Table.
161 *ConsoleHandle
= NewHandle
;
162 *ProtocolInterface
= Interface
;
163 if (CompareGuid (ConsoleGuid
, &gEfiSimpleTextOutProtocolGuid
)) {
165 // If it is console out device, set console mode 80x25 if current mode is invalid.
167 TextOut
= (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*) Interface
;
168 if (TextOut
->Mode
->Mode
== -1) {
169 TextOut
->SetMode (TextOut
, 0);
176 } while (Instance
!= NULL
);
179 // No any available console devcie found.
185 This function update console variable based on ConVarName, it can
186 add or remove one specific console device path from the variable
188 @param ConVarName Console related variable name, ConIn, ConOut,
190 @param CustomizedConDevicePath The console device path which will be added to
191 the console variable ConVarName, this parameter
192 can not be multi-instance.
193 @param ExclusiveDevicePath The console device path which will be removed
194 from the console variable ConVarName, this
195 parameter can not be multi-instance.
197 @retval EFI_UNSUPPORTED The added device path is same to the removed one.
198 @retval EFI_SUCCESS Success add or remove the device path from the
204 BdsLibUpdateConsoleVariable (
205 IN CHAR16
*ConVarName
,
206 IN EFI_DEVICE_PATH_PROTOCOL
*CustomizedConDevicePath
,
207 IN EFI_DEVICE_PATH_PROTOCOL
*ExclusiveDevicePath
211 EFI_DEVICE_PATH_PROTOCOL
*VarConsole
;
212 UINTN DevicePathSize
;
213 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
214 EFI_DEVICE_PATH_PROTOCOL
*TempNewDevicePath
;
221 // Notes: check the device path point, here should check
222 // with compare memory
224 if (CustomizedConDevicePath
== ExclusiveDevicePath
) {
225 return EFI_UNSUPPORTED
;
228 // Delete the ExclusiveDevicePath from current default console
230 VarConsole
= BdsLibGetVariableAndSize (
232 &gEfiGlobalVariableGuid
,
237 // Initialize NewDevicePath
239 NewDevicePath
= VarConsole
;
242 // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.
243 // In the end, NewDevicePath is the final device path.
245 if (ExclusiveDevicePath
!= NULL
&& VarConsole
!= NULL
) {
246 NewDevicePath
= BdsLibDelPartMatchInstance (VarConsole
, ExclusiveDevicePath
);
249 // Try to append customized device path to NewDevicePath.
251 if (CustomizedConDevicePath
!= NULL
) {
252 if (!BdsLibMatchDevicePaths (NewDevicePath
, CustomizedConDevicePath
)) {
254 // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.
256 NewDevicePath
= BdsLibDelPartMatchInstance (NewDevicePath
, CustomizedConDevicePath
);
258 // In the first check, the default console variable will be _ModuleEntryPoint,
259 // just append current customized device path
261 TempNewDevicePath
= NewDevicePath
;
262 NewDevicePath
= AppendDevicePathInstance (NewDevicePath
, CustomizedConDevicePath
);
263 if (TempNewDevicePath
!= NULL
) {
264 FreePool(TempNewDevicePath
);
270 // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.
272 if (IsNvNeed(ConVarName
)) {
274 // ConVarName has NV attribute.
276 Attributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
279 // ConVarName does not have NV attribute.
281 Attributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
;
285 // Finally, Update the variable of the default console by NewDevicePath
287 DevicePathSize
= GetDevicePathSize (NewDevicePath
);
288 Status
= SetVariableAndReportStatusCodeOnError (
290 &gEfiGlobalVariableGuid
,
295 if ((DevicePathSize
== 0) && (Status
== EFI_NOT_FOUND
)) {
296 Status
= EFI_SUCCESS
;
299 if (VarConsole
== NewDevicePath
) {
300 if (VarConsole
!= NULL
) {
301 FreePool(VarConsole
);
304 if (VarConsole
!= NULL
) {
305 FreePool(VarConsole
);
307 if (NewDevicePath
!= NULL
) {
308 FreePool(NewDevicePath
);
318 Connect the console device base on the variable ConVarName, if
319 device path of the ConVarName is multi-instance device path and
320 anyone of the instances is connected success, then this function
322 If the handle associate with one device path node can not
323 be created successfully, then still give chance to do the dispatch,
324 which load the missing drivers if possible..
326 @param ConVarName Console related variable name, ConIn, ConOut,
329 @retval EFI_NOT_FOUND There is not any console devices connected
331 @retval EFI_SUCCESS Success connect any one instance of the console
332 device path base on the variable ConVarName.
337 BdsLibConnectConsoleVariable (
338 IN CHAR16
*ConVarName
342 EFI_DEVICE_PATH_PROTOCOL
*StartDevicePath
;
344 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
345 EFI_DEVICE_PATH_PROTOCOL
*Next
;
346 EFI_DEVICE_PATH_PROTOCOL
*CopyOfDevicePath
;
350 Status
= EFI_SUCCESS
;
354 // Check if the console variable exist
356 StartDevicePath
= BdsLibGetVariableAndSize (
358 &gEfiGlobalVariableGuid
,
361 if (StartDevicePath
== NULL
) {
362 return EFI_UNSUPPORTED
;
365 CopyOfDevicePath
= StartDevicePath
;
368 // Check every instance of the console variable
370 Instance
= GetNextDevicePathInstance (&CopyOfDevicePath
, &Size
);
371 if (Instance
== NULL
) {
372 FreePool (StartDevicePath
);
373 return EFI_UNSUPPORTED
;
377 while (!IsDevicePathEndType (Next
)) {
378 Next
= NextDevicePathNode (Next
);
381 SetDevicePathEndNode (Next
);
383 // Connect the USB console
384 // USB console device path is a short-form device path that
385 // starts with the first element being a USB WWID
386 // or a USB Class device path
388 if ((DevicePathType (Instance
) == MESSAGING_DEVICE_PATH
) &&
389 ((DevicePathSubType (Instance
) == MSG_USB_CLASS_DP
)
390 || (DevicePathSubType (Instance
) == MSG_USB_WWID_DP
)
392 Status
= BdsLibConnectUsbDevByShortFormDP (0xFF, Instance
);
393 if (!EFI_ERROR (Status
)) {
398 // Connect the instance device path
400 Status
= BdsLibConnectDevicePath (Instance
);
402 if (EFI_ERROR (Status
)) {
404 // Delete the instance from the console varialbe
406 BdsLibUpdateConsoleVariable (ConVarName
, NULL
, Instance
);
412 } while (CopyOfDevicePath
!= NULL
);
414 FreePool (StartDevicePath
);
417 return EFI_NOT_FOUND
;
424 This function will search every simpletext device in current system,
425 and make every simpletext device as pertantial console device.
430 BdsLibConnectAllConsoles (
435 EFI_DEVICE_PATH_PROTOCOL
*ConDevicePath
;
437 EFI_HANDLE
*HandleBuffer
;
442 ConDevicePath
= NULL
;
445 // Update all the console variables
447 gBS
->LocateHandleBuffer (
449 &gEfiSimpleTextInProtocolGuid
,
455 for (Index
= 0; Index
< HandleCount
; Index
++) {
456 gBS
->HandleProtocol (
458 &gEfiDevicePathProtocolGuid
,
459 (VOID
**) &ConDevicePath
461 BdsLibUpdateConsoleVariable (L
"ConIn", ConDevicePath
, NULL
);
464 if (HandleBuffer
!= NULL
) {
465 FreePool(HandleBuffer
);
469 gBS
->LocateHandleBuffer (
471 &gEfiSimpleTextOutProtocolGuid
,
476 for (Index
= 0; Index
< HandleCount
; Index
++) {
477 gBS
->HandleProtocol (
479 &gEfiDevicePathProtocolGuid
,
480 (VOID
**) &ConDevicePath
482 BdsLibUpdateConsoleVariable (L
"ConOut", ConDevicePath
, NULL
);
483 BdsLibUpdateConsoleVariable (L
"ErrOut", ConDevicePath
, NULL
);
486 if (HandleBuffer
!= NULL
) {
487 FreePool(HandleBuffer
);
491 // Connect all console variables
493 BdsLibConnectAllDefaultConsoles ();
498 This function will connect console device base on the console
499 device variable ConIn, ConOut and ErrOut.
501 @retval EFI_SUCCESS At least one of the ConIn and ConOut device have
502 been connected success.
503 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().
508 BdsLibConnectAllDefaultConsoles (
513 BOOLEAN SystemTableUpdated
;
516 // Connect all default console variables
520 // It seems impossible not to have any ConOut device on platform,
521 // so we check the status here.
523 Status
= BdsLibConnectConsoleVariable (L
"ConOut");
524 if (EFI_ERROR (Status
)) {
529 // Insert the performance probe for Console Out
531 PERF_START (NULL
, "ConOut", "BDS", 1);
532 PERF_END (NULL
, "ConOut", "BDS", 0);
535 // Because possibly the platform is legacy free, in such case,
536 // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,
537 // so we need not check the status.
539 BdsLibConnectConsoleVariable (L
"ConIn");
542 // The _ModuleEntryPoint err out var is legal.
544 BdsLibConnectConsoleVariable (L
"ErrOut");
546 SystemTableUpdated
= FALSE
;
548 // Fill console handles in System Table if no console device assignd.
550 if (UpdateSystemTableConsole (L
"ConIn", &gEfiSimpleTextInProtocolGuid
, &gST
->ConsoleInHandle
, (VOID
**) &gST
->ConIn
)) {
551 SystemTableUpdated
= TRUE
;
553 if (UpdateSystemTableConsole (L
"ConOut", &gEfiSimpleTextOutProtocolGuid
, &gST
->ConsoleOutHandle
, (VOID
**) &gST
->ConOut
)) {
554 SystemTableUpdated
= TRUE
;
556 if (UpdateSystemTableConsole (L
"ErrOut", &gEfiSimpleTextOutProtocolGuid
, &gST
->StandardErrorHandle
, (VOID
**) &gST
->StdErr
)) {
557 SystemTableUpdated
= TRUE
;
560 if (SystemTableUpdated
) {
562 // Update the CRC32 in the EFI System Table header
565 gBS
->CalculateCrc32 (
577 This function will connect console device except ConIn base on the console
578 device variable ConOut and ErrOut.
580 @retval EFI_SUCCESS At least one of the ConOut device have
581 been connected success.
582 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().
587 BdsLibConnectAllDefaultConsolesWithOutConIn (
592 BOOLEAN SystemTableUpdated
;
595 // Connect all default console variables except ConIn
599 // It seems impossible not to have any ConOut device on platform,
600 // so we check the status here.
602 Status
= BdsLibConnectConsoleVariable (L
"ConOut");
603 if (EFI_ERROR (Status
)) {
608 // Insert the performance probe for Console Out
610 PERF_START (NULL
, "ConOut", "BDS", 1);
611 PERF_END (NULL
, "ConOut", "BDS", 0);
614 // The _ModuleEntryPoint err out var is legal.
616 BdsLibConnectConsoleVariable (L
"ErrOut");
618 SystemTableUpdated
= FALSE
;
620 // Fill console handles in System Table if no console device assignd.
622 if (UpdateSystemTableConsole (L
"ConOut", &gEfiSimpleTextOutProtocolGuid
, &gST
->ConsoleOutHandle
, (VOID
**) &gST
->ConOut
)) {
623 SystemTableUpdated
= TRUE
;
625 if (UpdateSystemTableConsole (L
"ErrOut", &gEfiSimpleTextOutProtocolGuid
, &gST
->StandardErrorHandle
, (VOID
**) &gST
->StdErr
)) {
626 SystemTableUpdated
= TRUE
;
629 if (SystemTableUpdated
) {
631 // Update the CRC32 in the EFI System Table header
634 gBS
->CalculateCrc32 (
646 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
647 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
648 buffer is passed in it will be used if it is big enough.
650 @param BmpImage Pointer to BMP file
651 @param BmpImageSize Number of bytes in BmpImage
652 @param GopBlt Buffer containing GOP version of BmpImage.
653 @param GopBltSize Size of GopBlt in bytes.
654 @param PixelHeight Height of GopBlt/BmpImage in pixels
655 @param PixelWidth Width of GopBlt/BmpImage in pixels
657 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
658 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
659 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
660 GopBltSize will contain the required size.
661 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
667 IN UINTN BmpImageSize
,
668 IN OUT VOID
**GopBlt
,
669 IN OUT UINTN
*GopBltSize
,
670 OUT UINTN
*PixelHeight
,
671 OUT UINTN
*PixelWidth
676 BMP_IMAGE_HEADER
*BmpHeader
;
677 BMP_COLOR_MAP
*BmpColorMap
;
678 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
679 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
680 UINT64 BltBufferSize
;
685 UINT32 DataSizePerLine
;
689 if (sizeof (BMP_IMAGE_HEADER
) > BmpImageSize
) {
690 return EFI_INVALID_PARAMETER
;
693 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
695 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
696 return EFI_UNSUPPORTED
;
700 // Doesn't support compress.
702 if (BmpHeader
->CompressionType
!= 0) {
703 return EFI_UNSUPPORTED
;
707 // Only support BITMAPINFOHEADER format.
708 // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
710 if (BmpHeader
->HeaderSize
!= sizeof (BMP_IMAGE_HEADER
) - OFFSET_OF(BMP_IMAGE_HEADER
, HeaderSize
)) {
711 return EFI_UNSUPPORTED
;
715 // The data size in each line must be 4 byte alignment.
717 DataSizePerLine
= ((BmpHeader
->PixelWidth
* BmpHeader
->BitPerPixel
+ 31) >> 3) & (~0x3);
718 BltBufferSize
= MultU64x32 (DataSizePerLine
, BmpHeader
->PixelHeight
);
719 if (BltBufferSize
> (UINT32
) ~0) {
720 return EFI_INVALID_PARAMETER
;
723 if ((BmpHeader
->Size
!= BmpImageSize
) ||
724 (BmpHeader
->Size
< BmpHeader
->ImageOffset
) ||
725 (BmpHeader
->Size
- BmpHeader
->ImageOffset
!= BmpHeader
->PixelHeight
* DataSizePerLine
)) {
726 return EFI_INVALID_PARAMETER
;
730 // Calculate Color Map offset in the image.
733 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
734 if (BmpHeader
->ImageOffset
< sizeof (BMP_IMAGE_HEADER
)) {
735 return EFI_INVALID_PARAMETER
;
738 if (BmpHeader
->ImageOffset
> sizeof (BMP_IMAGE_HEADER
)) {
739 switch (BmpHeader
->BitPerPixel
) {
754 // BMP file may has padding data between the bmp header section and the bmp data section.
756 if (BmpHeader
->ImageOffset
- sizeof (BMP_IMAGE_HEADER
) < sizeof (BMP_COLOR_MAP
) * ColorMapNum
) {
757 return EFI_INVALID_PARAMETER
;
762 // Calculate graphics image data address in the image
764 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
768 // Calculate the BltBuffer needed size.
770 BltBufferSize
= MultU64x32 ((UINT64
) BmpHeader
->PixelWidth
, BmpHeader
->PixelHeight
);
772 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
774 if (BltBufferSize
> DivU64x32 ((UINTN
) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))) {
775 return EFI_UNSUPPORTED
;
777 BltBufferSize
= MultU64x32 (BltBufferSize
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
780 if (*GopBlt
== NULL
) {
782 // GopBlt is not allocated by caller.
784 *GopBltSize
= (UINTN
) BltBufferSize
;
785 *GopBlt
= AllocatePool (*GopBltSize
);
787 if (*GopBlt
== NULL
) {
788 return EFI_OUT_OF_RESOURCES
;
792 // GopBlt has been allocated by caller.
794 if (*GopBltSize
< (UINTN
) BltBufferSize
) {
795 *GopBltSize
= (UINTN
) BltBufferSize
;
796 return EFI_BUFFER_TOO_SMALL
;
800 *PixelWidth
= BmpHeader
->PixelWidth
;
801 *PixelHeight
= BmpHeader
->PixelHeight
;
804 // Convert image from BMP to Blt buffer format
807 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
808 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
809 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
810 switch (BmpHeader
->BitPerPixel
) {
813 // Convert 1-bit (2 colors) BMP to 24-bit color
815 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
816 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
817 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
818 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
829 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
831 Index
= (*Image
) >> 4;
832 Blt
->Red
= BmpColorMap
[Index
].Red
;
833 Blt
->Green
= BmpColorMap
[Index
].Green
;
834 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
835 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
838 Index
= (*Image
) & 0x0f;
839 Blt
->Red
= BmpColorMap
[Index
].Red
;
840 Blt
->Green
= BmpColorMap
[Index
].Green
;
841 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
847 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
849 Blt
->Red
= BmpColorMap
[*Image
].Red
;
850 Blt
->Green
= BmpColorMap
[*Image
].Green
;
851 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
858 Blt
->Blue
= *Image
++;
859 Blt
->Green
= *Image
++;
865 // Other bit format BMP is not supported.
871 return EFI_UNSUPPORTED
;
876 ImageIndex
= (UINTN
)Image
- (UINTN
)ImageHeader
;
877 if ((ImageIndex
% 4) != 0) {
879 // Bmp Image starts each row on a 32-bit boundary!
881 Image
= Image
+ (4 - (ImageIndex
% 4));
889 Use SystemTable Conout to stop video based Simple Text Out consoles from going
890 to the video device. Put up LogoFile on every video device that is a console.
892 @param[in] LogoFile File name of logo to display on the center of the screen.
894 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
895 @retval EFI_UNSUPPORTED Logo not found
901 IN EFI_GUID
*LogoFile
905 EFI_OEM_BADGING_PROTOCOL
*Badging
;
914 EFI_BADGING_FORMAT Format
;
915 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute
;
920 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
921 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
924 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
925 EFI_BOOT_LOGO_PROTOCOL
*BootLogo
;
927 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LogoBlt
;
940 // Try to open GOP first
942 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
943 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
944 GraphicsOutput
= NULL
;
946 // Open GOP failed, try to open UGA
948 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
950 if (EFI_ERROR (Status
)) {
951 return EFI_UNSUPPORTED
;
955 // Try to open Boot Logo Protocol.
958 gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**) &BootLogo
);
961 // Erase Cursor from screen
963 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
966 Status
= gBS
->LocateProtocol (&gEfiOEMBadgingProtocolGuid
, NULL
, (VOID
**) &Badging
);
968 if (GraphicsOutput
!= NULL
) {
969 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
970 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
972 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
973 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
974 if (EFI_ERROR (Status
)) {
975 return EFI_UNSUPPORTED
;
978 return EFI_UNSUPPORTED
;
996 if (Badging
!= NULL
) {
998 // Get image from OEMBadging protocol.
1000 Status
= Badging
->GetImage (
1010 if (EFI_ERROR (Status
)) {
1015 // Currently only support BMP format.
1017 if (Format
!= EfiBadgingFormatBMP
) {
1018 if (ImageData
!= NULL
) {
1019 FreePool (ImageData
);
1025 // Get the specified image from FV.
1027 Status
= GetSectionFromAnyFv (LogoFile
, EFI_SECTION_RAW
, 0, (VOID
**) &ImageData
, &ImageSize
);
1028 if (EFI_ERROR (Status
)) {
1029 return EFI_UNSUPPORTED
;
1034 if (!FeaturePcdGet(PcdBootlogoOnlyEnable
)) {
1035 Attribute
= EfiBadgingDisplayAttributeCenter
;
1037 Attribute
= EfiBadgingDisplayAttributeCustomized
;
1045 Status
= ConvertBmpToGopBlt (
1053 if (EFI_ERROR (Status
)) {
1054 FreePool (ImageData
);
1056 if (Badging
== NULL
) {
1064 // Calculate the display position according to Attribute.
1066 switch (Attribute
) {
1067 case EfiBadgingDisplayAttributeLeftTop
:
1068 DestX
= CoordinateX
;
1069 DestY
= CoordinateY
;
1072 case EfiBadgingDisplayAttributeCenterTop
:
1073 DestX
= (SizeOfX
- Width
) / 2;
1074 DestY
= CoordinateY
;
1077 case EfiBadgingDisplayAttributeRightTop
:
1078 DestX
= (SizeOfX
- Width
- CoordinateX
);
1079 DestY
= CoordinateY
;;
1082 case EfiBadgingDisplayAttributeCenterRight
:
1083 DestX
= (SizeOfX
- Width
- CoordinateX
);
1084 DestY
= (SizeOfY
- Height
) / 2;
1087 case EfiBadgingDisplayAttributeRightBottom
:
1088 DestX
= (SizeOfX
- Width
- CoordinateX
);
1089 DestY
= (SizeOfY
- Height
- CoordinateY
);
1092 case EfiBadgingDisplayAttributeCenterBottom
:
1093 DestX
= (SizeOfX
- Width
) / 2;
1094 DestY
= (SizeOfY
- Height
- CoordinateY
);
1097 case EfiBadgingDisplayAttributeLeftBottom
:
1098 DestX
= CoordinateX
;
1099 DestY
= (SizeOfY
- Height
- CoordinateY
);
1102 case EfiBadgingDisplayAttributeCenterLeft
:
1103 DestX
= CoordinateX
;
1104 DestY
= (SizeOfY
- Height
) / 2;
1107 case EfiBadgingDisplayAttributeCenter
:
1108 DestX
= (SizeOfX
- Width
) / 2;
1109 DestY
= (SizeOfY
- Height
) / 2;
1112 case EfiBadgingDisplayAttributeCustomized
:
1113 DestX
= (SizeOfX
- Width
) / 2;
1114 DestY
= ((SizeOfY
* 382) / 1000) - Height
/ 2;
1118 DestX
= CoordinateX
;
1119 DestY
= CoordinateY
;
1123 if ((DestX
>= 0) && (DestY
>= 0)) {
1124 if (GraphicsOutput
!= NULL
) {
1125 Status
= GraphicsOutput
->Blt (
1128 EfiBltBufferToVideo
,
1135 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1137 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1138 Status
= UgaDraw
->Blt (
1140 (EFI_UGA_PIXEL
*) Blt
,
1141 EfiUgaBltBufferToVideo
,
1148 Width
* sizeof (EFI_UGA_PIXEL
)
1151 Status
= EFI_UNSUPPORTED
;
1155 // Report displayed Logo information.
1157 if (!EFI_ERROR (Status
)) {
1160 if (LogoWidth
== 0) {
1164 LogoDestX
= (UINTN
) DestX
;
1165 LogoDestY
= (UINTN
) DestY
;
1167 LogoHeight
= Height
;
1170 // Merge new logo with old one.
1172 NewDestX
= MIN ((UINTN
) DestX
, LogoDestX
);
1173 NewDestY
= MIN ((UINTN
) DestY
, LogoDestY
);
1174 NewWidth
= MAX ((UINTN
) DestX
+ Width
, LogoDestX
+ LogoWidth
) - NewDestX
;
1175 NewHeight
= MAX ((UINTN
) DestY
+ Height
, LogoDestY
+ LogoHeight
) - NewDestY
;
1177 LogoDestX
= NewDestX
;
1178 LogoDestY
= NewDestY
;
1179 LogoWidth
= NewWidth
;
1180 LogoHeight
= NewHeight
;
1185 FreePool (ImageData
);
1187 if (Badging
== NULL
) {
1193 if (BootLogo
== NULL
|| NumberOfLogos
== 0) {
1195 // No logo displayed.
1205 // Advertise displayed Logo information.
1207 if (NumberOfLogos
== 1) {
1209 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.
1212 Status
= EFI_SUCCESS
;
1215 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.
1222 // Ensure the LogoHeight * LogoWidth doesn't overflow
1224 if (LogoHeight
> DivU64x64Remainder ((UINTN
) ~0, LogoWidth
, NULL
)) {
1225 return EFI_UNSUPPORTED
;
1227 BufferSize
= MultU64x64 (LogoWidth
, LogoHeight
);
1230 // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
1232 if (BufferSize
> DivU64x32 ((UINTN
) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))) {
1233 return EFI_UNSUPPORTED
;
1236 LogoBlt
= AllocateZeroPool ((UINTN
)BufferSize
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1237 if (LogoBlt
== NULL
) {
1238 return EFI_OUT_OF_RESOURCES
;
1241 if (GraphicsOutput
!= NULL
) {
1242 Status
= GraphicsOutput
->Blt (
1245 EfiBltVideoToBltBuffer
,
1252 LogoWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1254 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1255 Status
= UgaDraw
->Blt (
1257 (EFI_UGA_PIXEL
*) LogoBlt
,
1258 EfiUgaVideoToBltBuffer
,
1265 LogoWidth
* sizeof (EFI_UGA_PIXEL
)
1268 Status
= EFI_UNSUPPORTED
;
1272 if (!EFI_ERROR (Status
)) {
1273 BootLogo
->SetBootLogo (BootLogo
, LogoBlt
, LogoDestX
, LogoDestY
, LogoWidth
, LogoHeight
);
1281 Use SystemTable Conout to turn on video based Simple Text Out consoles. The
1282 Simple Text Out screens will now be synced up with all non video output devices
1284 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
1295 // Enable Cursor on Screen
1297 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);