2 BDS Lib functions which contain all the code to connect console device
4 Copyright (c) 2004 - 2012, 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 hanlde 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 hanlde 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 Connect the console device base on the variable ConVarName, if
186 device path of the ConVarName is multi-instance device path and
187 anyone of the instances is connected success, this function will
189 Dispatch service is called basing on input when the handle associate
190 with one device path node can not be created successfully. Since in
191 some cases we assume driver dependency does not exist and do not
192 need to call this service.
194 @param ConVarName Console related variable name, ConIn, ConOut,
196 @param NeedDispatch Whether requires dispatch service during connection
198 @retval EFI_NOT_FOUND There is not any console devices connected
200 @retval EFI_SUCCESS Success connect any one instance of the console
201 device path base on the variable ConVarName.
205 ConnectConsoleVariableInternal (
206 IN CHAR16
*ConVarName
,
207 IN BOOLEAN NeedDispatch
211 EFI_DEVICE_PATH_PROTOCOL
*StartDevicePath
;
213 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
214 EFI_DEVICE_PATH_PROTOCOL
*Next
;
215 EFI_DEVICE_PATH_PROTOCOL
*CopyOfDevicePath
;
219 Status
= EFI_SUCCESS
;
223 // Check if the console variable exist
225 StartDevicePath
= BdsLibGetVariableAndSize (
227 &gEfiGlobalVariableGuid
,
230 if (StartDevicePath
== NULL
) {
231 return EFI_UNSUPPORTED
;
234 CopyOfDevicePath
= StartDevicePath
;
237 // Check every instance of the console variable
239 Instance
= GetNextDevicePathInstance (&CopyOfDevicePath
, &Size
);
240 if (Instance
== NULL
) {
241 FreePool (StartDevicePath
);
242 return EFI_UNSUPPORTED
;
246 while (!IsDevicePathEndType (Next
)) {
247 Next
= NextDevicePathNode (Next
);
250 SetDevicePathEndNode (Next
);
252 // Connect the USB console
253 // USB console device path is a short-form device path that
254 // starts with the first element being a USB WWID
255 // or a USB Class device path
257 if ((DevicePathType (Instance
) == MESSAGING_DEVICE_PATH
) &&
258 ((DevicePathSubType (Instance
) == MSG_USB_CLASS_DP
)
259 || (DevicePathSubType (Instance
) == MSG_USB_WWID_DP
)
261 Status
= BdsLibConnectUsbDevByShortFormDP (0xFF, Instance
);
262 if (!EFI_ERROR (Status
)) {
267 // Connect the instance device path
269 Status
= ConnectDevicePathInternal (Instance
, NeedDispatch
);
271 if (EFI_ERROR (Status
)) {
273 // Delete the instance from the console varialbe
275 BdsLibUpdateConsoleVariable (ConVarName
, NULL
, Instance
);
281 } while (CopyOfDevicePath
!= NULL
);
283 FreePool (StartDevicePath
);
286 return EFI_NOT_FOUND
;
293 This function update console variable based on ConVarName, it can
294 add or remove one specific console device path from the variable
296 @param ConVarName Console related variable name, ConIn, ConOut,
298 @param CustomizedConDevicePath The console device path which will be added to
299 the console variable ConVarName, this parameter
300 can not be multi-instance.
301 @param ExclusiveDevicePath The console device path which will be removed
302 from the console variable ConVarName, this
303 parameter can not be multi-instance.
305 @retval EFI_UNSUPPORTED The added device path is same to the removed one.
306 @retval EFI_SUCCESS Success add or remove the device path from the
312 BdsLibUpdateConsoleVariable (
313 IN CHAR16
*ConVarName
,
314 IN EFI_DEVICE_PATH_PROTOCOL
*CustomizedConDevicePath
,
315 IN EFI_DEVICE_PATH_PROTOCOL
*ExclusiveDevicePath
319 EFI_DEVICE_PATH_PROTOCOL
*VarConsole
;
320 UINTN DevicePathSize
;
321 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
322 EFI_DEVICE_PATH_PROTOCOL
*TempNewDevicePath
;
329 // Notes: check the device path point, here should check
330 // with compare memory
332 if (CustomizedConDevicePath
== ExclusiveDevicePath
) {
333 return EFI_UNSUPPORTED
;
336 // Delete the ExclusiveDevicePath from current default console
338 VarConsole
= BdsLibGetVariableAndSize (
340 &gEfiGlobalVariableGuid
,
345 // Initialize NewDevicePath
347 NewDevicePath
= VarConsole
;
350 // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.
351 // In the end, NewDevicePath is the final device path.
353 if (ExclusiveDevicePath
!= NULL
&& VarConsole
!= NULL
) {
354 NewDevicePath
= BdsLibDelPartMatchInstance (VarConsole
, ExclusiveDevicePath
);
357 // Try to append customized device path to NewDevicePath.
359 if (CustomizedConDevicePath
!= NULL
) {
360 if (!BdsLibMatchDevicePaths (NewDevicePath
, CustomizedConDevicePath
)) {
362 // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.
364 NewDevicePath
= BdsLibDelPartMatchInstance (NewDevicePath
, CustomizedConDevicePath
);
366 // In the first check, the default console variable will be _ModuleEntryPoint,
367 // just append current customized device path
369 TempNewDevicePath
= NewDevicePath
;
370 NewDevicePath
= AppendDevicePathInstance (NewDevicePath
, CustomizedConDevicePath
);
371 if (TempNewDevicePath
!= NULL
) {
372 FreePool(TempNewDevicePath
);
378 // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.
380 if (IsNvNeed(ConVarName
)) {
382 // ConVarName has NV attribute.
384 Attributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
387 // ConVarName does not have NV attribute.
389 Attributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
;
393 // Finally, Update the variable of the default console by NewDevicePath
395 DevicePathSize
= GetDevicePathSize (NewDevicePath
);
396 Status
= gRT
->SetVariable (
398 &gEfiGlobalVariableGuid
,
403 if ((DevicePathSize
== 0) && (Status
== EFI_NOT_FOUND
)) {
404 Status
= EFI_SUCCESS
;
406 ASSERT_EFI_ERROR (Status
);
408 if (VarConsole
== NewDevicePath
) {
409 if (VarConsole
!= NULL
) {
410 FreePool(VarConsole
);
413 if (VarConsole
!= NULL
) {
414 FreePool(VarConsole
);
416 if (NewDevicePath
!= NULL
) {
417 FreePool(NewDevicePath
);
427 Connect the console device base on the variable ConVarName, if
428 device path of the ConVarName is multi-instance device path and
429 anyone of the instances is connected success, then this function
431 If the handle associate with one device path node can not
432 be created successfully, then still give chance to do the dispatch,
433 which load the missing drivers if possible..
435 @param ConVarName Console related variable name, ConIn, ConOut,
438 @retval EFI_NOT_FOUND There is not any console devices connected
440 @retval EFI_SUCCESS Success connect any one instance of the console
441 device path base on the variable ConVarName.
446 BdsLibConnectConsoleVariable (
447 IN CHAR16
*ConVarName
450 return ConnectConsoleVariableInternal(ConVarName
, TRUE
);
454 Connect the console device base on the variable ConVarName, if
455 device path of the ConVarName is multi-instance device path and
456 anyone of the instances is connected success, then this function
458 Dispatch service is not called when the handle associate with one
459 device path node can not be created successfully. Here no driver
460 dependency is assumed exist, so need not to call this service.
463 @param ConVarName Console related variable name, ConIn, ConOut,
466 @retval EFI_NOT_FOUND There is not any console devices connected
468 @retval EFI_SUCCESS Success connect any one instance of the console
469 device path base on the variable ConVarName.
474 BdsLibConnectConsoleVariableWithOutDispatch (
475 IN CHAR16
*ConVarName
478 return ConnectConsoleVariableInternal(ConVarName
, FALSE
);
482 This function will search every simpletext device in current system,
483 and make every simpletext device as pertantial console device.
488 BdsLibConnectAllConsoles (
493 EFI_DEVICE_PATH_PROTOCOL
*ConDevicePath
;
495 EFI_HANDLE
*HandleBuffer
;
500 ConDevicePath
= NULL
;
503 // Update all the console variables
505 gBS
->LocateHandleBuffer (
507 &gEfiSimpleTextInProtocolGuid
,
513 for (Index
= 0; Index
< HandleCount
; Index
++) {
514 gBS
->HandleProtocol (
516 &gEfiDevicePathProtocolGuid
,
517 (VOID
**) &ConDevicePath
519 BdsLibUpdateConsoleVariable (L
"ConIn", ConDevicePath
, NULL
);
522 if (HandleBuffer
!= NULL
) {
523 FreePool(HandleBuffer
);
527 gBS
->LocateHandleBuffer (
529 &gEfiSimpleTextOutProtocolGuid
,
534 for (Index
= 0; Index
< HandleCount
; Index
++) {
535 gBS
->HandleProtocol (
537 &gEfiDevicePathProtocolGuid
,
538 (VOID
**) &ConDevicePath
540 BdsLibUpdateConsoleVariable (L
"ConOut", ConDevicePath
, NULL
);
541 BdsLibUpdateConsoleVariable (L
"ErrOut", ConDevicePath
, NULL
);
544 if (HandleBuffer
!= NULL
) {
545 FreePool(HandleBuffer
);
549 // Connect all console variables
551 BdsLibConnectAllDefaultConsoles ();
556 This function will connect console device base on the console
557 device variable ConIn, ConOut and ErrOut.
559 @retval EFI_SUCCESS At least one of the ConIn and ConOut device have
560 been connected success.
561 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().
566 BdsLibConnectAllDefaultConsoles (
571 BOOLEAN SystemTableUpdated
;
574 // Connect all default console variables
578 // It seems impossible not to have any ConOut device on platform,
579 // so we check the status here.
581 Status
= BdsLibConnectConsoleVariable (L
"ConOut");
582 if (EFI_ERROR (Status
)) {
587 // Insert the performance probe for Console Out
589 PERF_START (NULL
, "ConOut", "BDS", 1);
590 PERF_END (NULL
, "ConOut", "BDS", 0);
593 // Because possibly the platform is legacy free, in such case,
594 // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,
595 // so we need not check the status.
597 BdsLibConnectConsoleVariable (L
"ConIn");
600 // The _ModuleEntryPoint err out var is legal.
602 BdsLibConnectConsoleVariable (L
"ErrOut");
604 SystemTableUpdated
= FALSE
;
606 // Fill console handles in System Table if no console device assignd.
608 if (UpdateSystemTableConsole (L
"ConIn", &gEfiSimpleTextInProtocolGuid
, &gST
->ConsoleInHandle
, (VOID
**) &gST
->ConIn
)) {
609 SystemTableUpdated
= TRUE
;
611 if (UpdateSystemTableConsole (L
"ConOut", &gEfiSimpleTextOutProtocolGuid
, &gST
->ConsoleOutHandle
, (VOID
**) &gST
->ConOut
)) {
612 SystemTableUpdated
= TRUE
;
614 if (UpdateSystemTableConsole (L
"ErrOut", &gEfiSimpleTextOutProtocolGuid
, &gST
->StandardErrorHandle
, (VOID
**) &gST
->StdErr
)) {
615 SystemTableUpdated
= TRUE
;
618 if (SystemTableUpdated
) {
620 // Update the CRC32 in the EFI System Table header
623 gBS
->CalculateCrc32 (
635 This function will connect console device except ConIn base on the console
636 device variable ConOut and ErrOut.
638 @retval EFI_SUCCESS At least one of the ConOut device have
639 been connected success.
640 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().
645 BdsLibConnectAllDefaultConsolesWithOutConIn (
650 BOOLEAN SystemTableUpdated
;
653 // Connect all default console variables except ConIn
657 // It seems impossible not to have any ConOut device on platform,
658 // so we check the status here.
660 Status
= BdsLibConnectConsoleVariable (L
"ConOut");
661 if (EFI_ERROR (Status
)) {
666 // Insert the performance probe for Console Out
668 PERF_START (NULL
, "ConOut", "BDS", 1);
669 PERF_END (NULL
, "ConOut", "BDS", 0);
672 // The _ModuleEntryPoint err out var is legal.
674 BdsLibConnectConsoleVariable (L
"ErrOut");
676 SystemTableUpdated
= FALSE
;
678 // Fill console handles in System Table if no console device assignd.
680 if (UpdateSystemTableConsole (L
"ConOut", &gEfiSimpleTextOutProtocolGuid
, &gST
->ConsoleOutHandle
, (VOID
**) &gST
->ConOut
)) {
681 SystemTableUpdated
= TRUE
;
683 if (UpdateSystemTableConsole (L
"ErrOut", &gEfiSimpleTextOutProtocolGuid
, &gST
->StandardErrorHandle
, (VOID
**) &gST
->StdErr
)) {
684 SystemTableUpdated
= TRUE
;
687 if (SystemTableUpdated
) {
689 // Update the CRC32 in the EFI System Table header
692 gBS
->CalculateCrc32 (
704 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
705 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
706 buffer is passed in it will be used if it is big enough.
708 @param BmpImage Pointer to BMP file
709 @param BmpImageSize Number of bytes in BmpImage
710 @param GopBlt Buffer containing GOP version of BmpImage.
711 @param GopBltSize Size of GopBlt in bytes.
712 @param PixelHeight Height of GopBlt/BmpImage in pixels
713 @param PixelWidth Width of GopBlt/BmpImage in pixels
715 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
716 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
717 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
718 GopBltSize will contain the required size.
719 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
725 IN UINTN BmpImageSize
,
726 IN OUT VOID
**GopBlt
,
727 IN OUT UINTN
*GopBltSize
,
728 OUT UINTN
*PixelHeight
,
729 OUT UINTN
*PixelWidth
734 BMP_IMAGE_HEADER
*BmpHeader
;
735 BMP_COLOR_MAP
*BmpColorMap
;
736 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
737 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
738 UINT64 BltBufferSize
;
743 UINT32 DataSizePerLine
;
747 if (sizeof (BMP_IMAGE_HEADER
) > BmpImageSize
) {
748 return EFI_INVALID_PARAMETER
;
751 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
753 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
754 return EFI_UNSUPPORTED
;
758 // Doesn't support compress.
760 if (BmpHeader
->CompressionType
!= 0) {
761 return EFI_UNSUPPORTED
;
765 // Only support BITMAPINFOHEADER format.
766 // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
768 if (BmpHeader
->HeaderSize
!= sizeof (BMP_IMAGE_HEADER
) - OFFSET_OF(BMP_IMAGE_HEADER
, HeaderSize
)) {
769 return EFI_UNSUPPORTED
;
773 // The data size in each line must be 4 byte alignment.
775 DataSizePerLine
= ((BmpHeader
->PixelWidth
* BmpHeader
->BitPerPixel
+ 31) >> 3) & (~0x3);
776 BltBufferSize
= MultU64x32 (DataSizePerLine
, BmpHeader
->PixelHeight
);
777 if (BltBufferSize
> (UINT32
) ~0) {
778 return EFI_INVALID_PARAMETER
;
781 if ((BmpHeader
->Size
!= BmpImageSize
) ||
782 (BmpHeader
->Size
< BmpHeader
->ImageOffset
) ||
783 (BmpHeader
->Size
- BmpHeader
->ImageOffset
!= BmpHeader
->PixelHeight
* DataSizePerLine
)) {
784 return EFI_INVALID_PARAMETER
;
788 // Calculate Color Map offset in the image.
791 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
792 if (BmpHeader
->ImageOffset
< sizeof (BMP_IMAGE_HEADER
)) {
793 return EFI_INVALID_PARAMETER
;
796 if (BmpHeader
->ImageOffset
> sizeof (BMP_IMAGE_HEADER
)) {
797 switch (BmpHeader
->BitPerPixel
) {
811 if (BmpHeader
->ImageOffset
- sizeof (BMP_IMAGE_HEADER
) != sizeof (BMP_COLOR_MAP
) * ColorMapNum
) {
812 return EFI_INVALID_PARAMETER
;
817 // Calculate graphics image data address in the image
819 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
823 // Calculate the BltBuffer needed size.
825 BltBufferSize
= MultU64x32 ((UINT64
) BmpHeader
->PixelWidth
, BmpHeader
->PixelHeight
);
827 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
829 if (BltBufferSize
> DivU64x32 ((UINTN
) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))) {
830 return EFI_UNSUPPORTED
;
832 BltBufferSize
= MultU64x32 (BltBufferSize
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
835 if (*GopBlt
== NULL
) {
837 // GopBlt is not allocated by caller.
839 *GopBltSize
= (UINTN
) BltBufferSize
;
840 *GopBlt
= AllocatePool (*GopBltSize
);
842 if (*GopBlt
== NULL
) {
843 return EFI_OUT_OF_RESOURCES
;
847 // GopBlt has been allocated by caller.
849 if (*GopBltSize
< (UINTN
) BltBufferSize
) {
850 *GopBltSize
= (UINTN
) BltBufferSize
;
851 return EFI_BUFFER_TOO_SMALL
;
855 *PixelWidth
= BmpHeader
->PixelWidth
;
856 *PixelHeight
= BmpHeader
->PixelHeight
;
859 // Convert image from BMP to Blt buffer format
862 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
863 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
864 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
865 switch (BmpHeader
->BitPerPixel
) {
868 // Convert 1-bit (2 colors) BMP to 24-bit color
870 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
871 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
872 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
873 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
884 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
886 Index
= (*Image
) >> 4;
887 Blt
->Red
= BmpColorMap
[Index
].Red
;
888 Blt
->Green
= BmpColorMap
[Index
].Green
;
889 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
890 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
893 Index
= (*Image
) & 0x0f;
894 Blt
->Red
= BmpColorMap
[Index
].Red
;
895 Blt
->Green
= BmpColorMap
[Index
].Green
;
896 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
902 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
904 Blt
->Red
= BmpColorMap
[*Image
].Red
;
905 Blt
->Green
= BmpColorMap
[*Image
].Green
;
906 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
913 Blt
->Blue
= *Image
++;
914 Blt
->Green
= *Image
++;
920 // Other bit format BMP is not supported.
926 return EFI_UNSUPPORTED
;
932 ImageIndex
= (UINTN
) (Image
- ImageHeader
);
933 if ((ImageIndex
% 4) != 0) {
935 // Bmp Image starts each row on a 32-bit boundary!
937 Image
= Image
+ (4 - (ImageIndex
% 4));
945 Use SystemTable Conout to stop video based Simple Text Out consoles from going
946 to the video device. Put up LogoFile on every video device that is a console.
948 @param[in] LogoFile File name of logo to display on the center of the screen.
950 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
951 @retval EFI_UNSUPPORTED Logo not found
957 IN EFI_GUID
*LogoFile
961 EFI_OEM_BADGING_PROTOCOL
*Badging
;
970 EFI_BADGING_FORMAT Format
;
971 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute
;
976 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
977 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
980 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
981 EFI_BOOT_LOGO_PROTOCOL
*BootLogo
;
983 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LogoBlt
;
996 // Try to open GOP first
998 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
999 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
1000 GraphicsOutput
= NULL
;
1002 // Open GOP failed, try to open UGA
1004 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
1006 if (EFI_ERROR (Status
)) {
1007 return EFI_UNSUPPORTED
;
1011 // Try to open Boot Logo Protocol.
1014 gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**) &BootLogo
);
1017 // Erase Cursor from screen
1019 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
1022 Status
= gBS
->LocateProtocol (&gEfiOEMBadgingProtocolGuid
, NULL
, (VOID
**) &Badging
);
1024 if (GraphicsOutput
!= NULL
) {
1025 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
1026 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
1028 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1029 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
1030 if (EFI_ERROR (Status
)) {
1031 return EFI_UNSUPPORTED
;
1034 return EFI_UNSUPPORTED
;
1052 if (Badging
!= NULL
) {
1054 // Get image from OEMBadging protocol.
1056 Status
= Badging
->GetImage (
1066 if (EFI_ERROR (Status
)) {
1071 // Currently only support BMP format.
1073 if (Format
!= EfiBadgingFormatBMP
) {
1074 if (ImageData
!= NULL
) {
1075 FreePool (ImageData
);
1081 // Get the specified image from FV.
1083 Status
= GetSectionFromAnyFv (LogoFile
, EFI_SECTION_RAW
, 0, (VOID
**) &ImageData
, &ImageSize
);
1084 if (EFI_ERROR (Status
)) {
1085 return EFI_UNSUPPORTED
;
1090 if (!FeaturePcdGet(PcdBootlogoOnlyEnable
)) {
1091 Attribute
= EfiBadgingDisplayAttributeCenter
;
1093 Attribute
= EfiBadgingDisplayAttributeCustomized
;
1101 Status
= ConvertBmpToGopBlt (
1109 if (EFI_ERROR (Status
)) {
1110 FreePool (ImageData
);
1112 if (Badging
== NULL
) {
1120 // Calculate the display position according to Attribute.
1122 switch (Attribute
) {
1123 case EfiBadgingDisplayAttributeLeftTop
:
1124 DestX
= CoordinateX
;
1125 DestY
= CoordinateY
;
1128 case EfiBadgingDisplayAttributeCenterTop
:
1129 DestX
= (SizeOfX
- Width
) / 2;
1130 DestY
= CoordinateY
;
1133 case EfiBadgingDisplayAttributeRightTop
:
1134 DestX
= (SizeOfX
- Width
- CoordinateX
);
1135 DestY
= CoordinateY
;;
1138 case EfiBadgingDisplayAttributeCenterRight
:
1139 DestX
= (SizeOfX
- Width
- CoordinateX
);
1140 DestY
= (SizeOfY
- Height
) / 2;
1143 case EfiBadgingDisplayAttributeRightBottom
:
1144 DestX
= (SizeOfX
- Width
- CoordinateX
);
1145 DestY
= (SizeOfY
- Height
- CoordinateY
);
1148 case EfiBadgingDisplayAttributeCenterBottom
:
1149 DestX
= (SizeOfX
- Width
) / 2;
1150 DestY
= (SizeOfY
- Height
- CoordinateY
);
1153 case EfiBadgingDisplayAttributeLeftBottom
:
1154 DestX
= CoordinateX
;
1155 DestY
= (SizeOfY
- Height
- CoordinateY
);
1158 case EfiBadgingDisplayAttributeCenterLeft
:
1159 DestX
= CoordinateX
;
1160 DestY
= (SizeOfY
- Height
) / 2;
1163 case EfiBadgingDisplayAttributeCenter
:
1164 DestX
= (SizeOfX
- Width
) / 2;
1165 DestY
= (SizeOfY
- Height
) / 2;
1168 case EfiBadgingDisplayAttributeCustomized
:
1169 DestX
= (SizeOfX
- Width
) / 2;
1170 DestY
= ((SizeOfY
* 382) / 1000) - Height
/ 2;
1174 DestX
= CoordinateX
;
1175 DestY
= CoordinateY
;
1179 if ((DestX
>= 0) && (DestY
>= 0)) {
1180 if (GraphicsOutput
!= NULL
) {
1181 Status
= GraphicsOutput
->Blt (
1184 EfiBltBufferToVideo
,
1191 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1193 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1194 Status
= UgaDraw
->Blt (
1196 (EFI_UGA_PIXEL
*) Blt
,
1197 EfiUgaBltBufferToVideo
,
1204 Width
* sizeof (EFI_UGA_PIXEL
)
1207 Status
= EFI_UNSUPPORTED
;
1211 // Report displayed Logo information.
1213 if (!EFI_ERROR (Status
)) {
1216 if (LogoWidth
== 0) {
1220 LogoDestX
= (UINTN
) DestX
;
1221 LogoDestY
= (UINTN
) DestY
;
1223 LogoHeight
= Height
;
1226 // Merge new logo with old one.
1228 NewDestX
= MIN ((UINTN
) DestX
, LogoDestX
);
1229 NewDestY
= MIN ((UINTN
) DestY
, LogoDestY
);
1230 NewWidth
= MAX ((UINTN
) DestX
+ Width
, LogoDestX
+ LogoWidth
) - NewDestX
;
1231 NewHeight
= MAX ((UINTN
) DestY
+ Height
, LogoDestY
+ LogoHeight
) - NewDestY
;
1233 LogoDestX
= NewDestX
;
1234 LogoDestY
= NewDestY
;
1235 LogoWidth
= NewWidth
;
1236 LogoHeight
= NewHeight
;
1241 FreePool (ImageData
);
1243 if (Badging
== NULL
) {
1249 if (BootLogo
== NULL
|| NumberOfLogos
== 0) {
1251 // No logo displayed.
1261 // Advertise displayed Logo information.
1263 if (NumberOfLogos
== 1) {
1265 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.
1268 Status
= EFI_SUCCESS
;
1271 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.
1278 // Ensure the LogoHeight * LogoWidth doesn't overflow
1280 if (LogoHeight
> DivU64x64Remainder ((UINTN
) ~0, LogoWidth
, NULL
)) {
1281 return EFI_UNSUPPORTED
;
1283 BufferSize
= MultU64x64 (LogoWidth
, LogoHeight
);
1286 // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
1288 if (BufferSize
> DivU64x32 ((UINTN
) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))) {
1289 return EFI_UNSUPPORTED
;
1292 LogoBlt
= AllocateZeroPool ((UINTN
)BufferSize
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1293 if (LogoBlt
== NULL
) {
1294 return EFI_OUT_OF_RESOURCES
;
1297 if (GraphicsOutput
!= NULL
) {
1298 Status
= GraphicsOutput
->Blt (
1301 EfiBltVideoToBltBuffer
,
1308 LogoWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1310 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1311 Status
= UgaDraw
->Blt (
1313 (EFI_UGA_PIXEL
*) LogoBlt
,
1314 EfiUgaVideoToBltBuffer
,
1321 LogoWidth
* sizeof (EFI_UGA_PIXEL
)
1324 Status
= EFI_UNSUPPORTED
;
1328 if (!EFI_ERROR (Status
)) {
1329 BootLogo
->SetBootLogo (BootLogo
, LogoBlt
, LogoDestX
, LogoDestY
, LogoWidth
, LogoHeight
);
1337 Use SystemTable Conout to turn on video based Simple Text Out consoles. The
1338 Simple Text Out screens will now be synced up with all non video output devices
1340 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
1351 // Enable Cursor on Screen
1353 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);