2 BDS Lib functions which contain all the code to connect console device
4 Copyright (c) 2004 - 2014, 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
;
877 ImageIndex
= (UINTN
) (Image
- ImageHeader
);
878 if ((ImageIndex
% 4) != 0) {
880 // Bmp Image starts each row on a 32-bit boundary!
882 Image
= Image
+ (4 - (ImageIndex
% 4));
890 Use SystemTable Conout to stop video based Simple Text Out consoles from going
891 to the video device. Put up LogoFile on every video device that is a console.
893 @param[in] LogoFile File name of logo to display on the center of the screen.
895 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
896 @retval EFI_UNSUPPORTED Logo not found
902 IN EFI_GUID
*LogoFile
906 EFI_OEM_BADGING_PROTOCOL
*Badging
;
915 EFI_BADGING_FORMAT Format
;
916 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute
;
921 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
922 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
925 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
926 EFI_BOOT_LOGO_PROTOCOL
*BootLogo
;
928 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LogoBlt
;
941 // Try to open GOP first
943 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
944 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
945 GraphicsOutput
= NULL
;
947 // Open GOP failed, try to open UGA
949 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
951 if (EFI_ERROR (Status
)) {
952 return EFI_UNSUPPORTED
;
956 // Try to open Boot Logo Protocol.
959 gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**) &BootLogo
);
962 // Erase Cursor from screen
964 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
967 Status
= gBS
->LocateProtocol (&gEfiOEMBadgingProtocolGuid
, NULL
, (VOID
**) &Badging
);
969 if (GraphicsOutput
!= NULL
) {
970 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
971 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
973 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
974 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
975 if (EFI_ERROR (Status
)) {
976 return EFI_UNSUPPORTED
;
979 return EFI_UNSUPPORTED
;
997 if (Badging
!= NULL
) {
999 // Get image from OEMBadging protocol.
1001 Status
= Badging
->GetImage (
1011 if (EFI_ERROR (Status
)) {
1016 // Currently only support BMP format.
1018 if (Format
!= EfiBadgingFormatBMP
) {
1019 if (ImageData
!= NULL
) {
1020 FreePool (ImageData
);
1026 // Get the specified image from FV.
1028 Status
= GetSectionFromAnyFv (LogoFile
, EFI_SECTION_RAW
, 0, (VOID
**) &ImageData
, &ImageSize
);
1029 if (EFI_ERROR (Status
)) {
1030 return EFI_UNSUPPORTED
;
1035 if (!FeaturePcdGet(PcdBootlogoOnlyEnable
)) {
1036 Attribute
= EfiBadgingDisplayAttributeCenter
;
1038 Attribute
= EfiBadgingDisplayAttributeCustomized
;
1046 Status
= ConvertBmpToGopBlt (
1054 if (EFI_ERROR (Status
)) {
1055 FreePool (ImageData
);
1057 if (Badging
== NULL
) {
1065 // Calculate the display position according to Attribute.
1067 switch (Attribute
) {
1068 case EfiBadgingDisplayAttributeLeftTop
:
1069 DestX
= CoordinateX
;
1070 DestY
= CoordinateY
;
1073 case EfiBadgingDisplayAttributeCenterTop
:
1074 DestX
= (SizeOfX
- Width
) / 2;
1075 DestY
= CoordinateY
;
1078 case EfiBadgingDisplayAttributeRightTop
:
1079 DestX
= (SizeOfX
- Width
- CoordinateX
);
1080 DestY
= CoordinateY
;;
1083 case EfiBadgingDisplayAttributeCenterRight
:
1084 DestX
= (SizeOfX
- Width
- CoordinateX
);
1085 DestY
= (SizeOfY
- Height
) / 2;
1088 case EfiBadgingDisplayAttributeRightBottom
:
1089 DestX
= (SizeOfX
- Width
- CoordinateX
);
1090 DestY
= (SizeOfY
- Height
- CoordinateY
);
1093 case EfiBadgingDisplayAttributeCenterBottom
:
1094 DestX
= (SizeOfX
- Width
) / 2;
1095 DestY
= (SizeOfY
- Height
- CoordinateY
);
1098 case EfiBadgingDisplayAttributeLeftBottom
:
1099 DestX
= CoordinateX
;
1100 DestY
= (SizeOfY
- Height
- CoordinateY
);
1103 case EfiBadgingDisplayAttributeCenterLeft
:
1104 DestX
= CoordinateX
;
1105 DestY
= (SizeOfY
- Height
) / 2;
1108 case EfiBadgingDisplayAttributeCenter
:
1109 DestX
= (SizeOfX
- Width
) / 2;
1110 DestY
= (SizeOfY
- Height
) / 2;
1113 case EfiBadgingDisplayAttributeCustomized
:
1114 DestX
= (SizeOfX
- Width
) / 2;
1115 DestY
= ((SizeOfY
* 382) / 1000) - Height
/ 2;
1119 DestX
= CoordinateX
;
1120 DestY
= CoordinateY
;
1124 if ((DestX
>= 0) && (DestY
>= 0)) {
1125 if (GraphicsOutput
!= NULL
) {
1126 Status
= GraphicsOutput
->Blt (
1129 EfiBltBufferToVideo
,
1136 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1138 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1139 Status
= UgaDraw
->Blt (
1141 (EFI_UGA_PIXEL
*) Blt
,
1142 EfiUgaBltBufferToVideo
,
1149 Width
* sizeof (EFI_UGA_PIXEL
)
1152 Status
= EFI_UNSUPPORTED
;
1156 // Report displayed Logo information.
1158 if (!EFI_ERROR (Status
)) {
1161 if (LogoWidth
== 0) {
1165 LogoDestX
= (UINTN
) DestX
;
1166 LogoDestY
= (UINTN
) DestY
;
1168 LogoHeight
= Height
;
1171 // Merge new logo with old one.
1173 NewDestX
= MIN ((UINTN
) DestX
, LogoDestX
);
1174 NewDestY
= MIN ((UINTN
) DestY
, LogoDestY
);
1175 NewWidth
= MAX ((UINTN
) DestX
+ Width
, LogoDestX
+ LogoWidth
) - NewDestX
;
1176 NewHeight
= MAX ((UINTN
) DestY
+ Height
, LogoDestY
+ LogoHeight
) - NewDestY
;
1178 LogoDestX
= NewDestX
;
1179 LogoDestY
= NewDestY
;
1180 LogoWidth
= NewWidth
;
1181 LogoHeight
= NewHeight
;
1186 FreePool (ImageData
);
1188 if (Badging
== NULL
) {
1194 if (BootLogo
== NULL
|| NumberOfLogos
== 0) {
1196 // No logo displayed.
1206 // Advertise displayed Logo information.
1208 if (NumberOfLogos
== 1) {
1210 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.
1213 Status
= EFI_SUCCESS
;
1216 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.
1223 // Ensure the LogoHeight * LogoWidth doesn't overflow
1225 if (LogoHeight
> DivU64x64Remainder ((UINTN
) ~0, LogoWidth
, NULL
)) {
1226 return EFI_UNSUPPORTED
;
1228 BufferSize
= MultU64x64 (LogoWidth
, LogoHeight
);
1231 // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
1233 if (BufferSize
> DivU64x32 ((UINTN
) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))) {
1234 return EFI_UNSUPPORTED
;
1237 LogoBlt
= AllocateZeroPool ((UINTN
)BufferSize
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1238 if (LogoBlt
== NULL
) {
1239 return EFI_OUT_OF_RESOURCES
;
1242 if (GraphicsOutput
!= NULL
) {
1243 Status
= GraphicsOutput
->Blt (
1246 EfiBltVideoToBltBuffer
,
1253 LogoWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1255 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1256 Status
= UgaDraw
->Blt (
1258 (EFI_UGA_PIXEL
*) LogoBlt
,
1259 EfiUgaVideoToBltBuffer
,
1266 LogoWidth
* sizeof (EFI_UGA_PIXEL
)
1269 Status
= EFI_UNSUPPORTED
;
1273 if (!EFI_ERROR (Status
)) {
1274 BootLogo
->SetBootLogo (BootLogo
, LogoBlt
, LogoDestX
, LogoDestY
, LogoWidth
, LogoHeight
);
1282 Use SystemTable Conout to turn on video based Simple Text Out consoles. The
1283 Simple Text Out screens will now be synced up with all non video output devices
1285 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
1296 // Enable Cursor on Screen
1298 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);