2 BDS Lib functions which contain all the code to connect console device
4 Copyright (c) 2004 - 2008, Intel Corporation. <BR>
5 All rights reserved. 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"
19 Check if we need to save the EFI variable with "ConVarName" as name
22 @param ConVarName The name of the EFI variable.
24 @retval TRUE Set the EFI variable as NV type.
25 @retval FALSE EFI variable as NV type can be set NonNV.
37 // If the variable includes "Dev" at last, we consider
38 // it does not support NV attribute.
40 while (*Ptr
!= L
'\0') {
44 if ((*(Ptr
- 3) == 'D') && (*(Ptr
- 2) == 'e') && (*(Ptr
- 1) == 'v')) {
52 This function update console variable based on ConVarName, it can
53 add or remove one specific console device path from the variable
55 @param ConVarName Console related variable name, ConIn, ConOut,
57 @param CustomizedConDevicePath The console device path which will be added to
58 the console variable ConVarName, this parameter
59 can not be multi-instance.
60 @param ExclusiveDevicePath The console device path which will be removed
61 from the console variable ConVarName, this
62 parameter can not be multi-instance.
64 @retval EFI_UNSUPPORTED The added device path is same to the removed one.
65 @retval EFI_SUCCESS Success add or remove the device path from the
71 BdsLibUpdateConsoleVariable (
72 IN CHAR16
*ConVarName
,
73 IN EFI_DEVICE_PATH_PROTOCOL
*CustomizedConDevicePath
,
74 IN EFI_DEVICE_PATH_PROTOCOL
*ExclusiveDevicePath
77 EFI_DEVICE_PATH_PROTOCOL
*VarConsole
;
79 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
80 EFI_DEVICE_PATH_PROTOCOL
*TempNewDevicePath
;
87 // Notes: check the device path point, here should check
88 // with compare memory
90 if (CustomizedConDevicePath
== ExclusiveDevicePath
) {
91 return EFI_UNSUPPORTED
;
94 // Delete the ExclusiveDevicePath from current default console
96 VarConsole
= BdsLibGetVariableAndSize (
98 &gEfiGlobalVariableGuid
,
103 // Initialize NewDevicePath
105 NewDevicePath
= VarConsole
;
108 // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.
109 // In the end, NewDevicePath is the final device path.
111 if (ExclusiveDevicePath
!= NULL
&& VarConsole
!= NULL
) {
112 NewDevicePath
= BdsLibDelPartMatchInstance (VarConsole
, ExclusiveDevicePath
);
115 // Try to append customized device path to NewDevicePath.
117 if (CustomizedConDevicePath
!= NULL
) {
118 if (!BdsLibMatchDevicePaths (NewDevicePath
, CustomizedConDevicePath
)) {
120 // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.
122 NewDevicePath
= BdsLibDelPartMatchInstance (NewDevicePath
, CustomizedConDevicePath
);
124 // In the first check, the default console variable will be _ModuleEntryPoint,
125 // just append current customized device path
127 TempNewDevicePath
= NewDevicePath
;
128 NewDevicePath
= AppendDevicePathInstance (NewDevicePath
, CustomizedConDevicePath
);
129 if (TempNewDevicePath
!= NULL
) {
130 FreePool(TempNewDevicePath
);
136 // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.
138 if (IsNvNeed(ConVarName
)) {
140 // ConVarName has NV attribute.
142 Attributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
145 // ConVarName does not have NV attribute.
147 Attributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
;
151 // Finally, Update the variable of the default console by NewDevicePath
155 &gEfiGlobalVariableGuid
,
157 GetDevicePathSize (NewDevicePath
),
161 if (VarConsole
== NewDevicePath
) {
162 if (VarConsole
!= NULL
) {
163 FreePool(VarConsole
);
166 if (VarConsole
!= NULL
) {
167 FreePool(VarConsole
);
169 if (NewDevicePath
!= NULL
) {
170 FreePool(NewDevicePath
);
180 Connect the console device base on the variable ConVarName, if
181 device path of the ConVarName is multi-instance device path, if
182 anyone of the instances is connected success, then this function
185 @param ConVarName Console related variable name, ConIn, ConOut,
188 @retval EFI_NOT_FOUND There is not any console devices connected
190 @retval EFI_SUCCESS Success connect any one instance of the console
191 device path base on the variable ConVarName.
196 BdsLibConnectConsoleVariable (
197 IN CHAR16
*ConVarName
201 EFI_DEVICE_PATH_PROTOCOL
*StartDevicePath
;
203 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
204 EFI_DEVICE_PATH_PROTOCOL
*Next
;
205 EFI_DEVICE_PATH_PROTOCOL
*CopyOfDevicePath
;
209 Status
= EFI_SUCCESS
;
213 // Check if the console variable exist
215 StartDevicePath
= BdsLibGetVariableAndSize (
217 &gEfiGlobalVariableGuid
,
220 if (StartDevicePath
== NULL
) {
221 return EFI_UNSUPPORTED
;
224 CopyOfDevicePath
= StartDevicePath
;
227 // Check every instance of the console variable
229 Instance
= GetNextDevicePathInstance (&CopyOfDevicePath
, &Size
);
230 if (Instance
== NULL
) {
231 FreePool (StartDevicePath
);
232 return EFI_UNSUPPORTED
;
236 while (!IsDevicePathEndType (Next
)) {
237 Next
= NextDevicePathNode (Next
);
240 SetDevicePathEndNode (Next
);
242 // Check USB1.1 console
244 if ((DevicePathType (Instance
) == MESSAGING_DEVICE_PATH
) &&
245 ((DevicePathSubType (Instance
) == MSG_USB_CLASS_DP
)
246 || (DevicePathSubType (Instance
) == MSG_USB_WWID_DP
)
249 // Check the Usb console in Usb2.0 bus firstly, then Usb1.1 bus
251 Status
= BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_EHCI
, Instance
);
252 if (!EFI_ERROR (Status
)) {
256 Status
= BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_UHCI
, Instance
);
257 if (!EFI_ERROR (Status
)) {
262 // Connect the instance device path
264 Status
= BdsLibConnectDevicePath (Instance
);
265 if (EFI_ERROR (Status
)) {
267 // Delete the instance from the console varialbe
269 BdsLibUpdateConsoleVariable (ConVarName
, NULL
, Instance
);
275 } while (CopyOfDevicePath
!= NULL
);
277 FreePool (StartDevicePath
);
280 return EFI_NOT_FOUND
;
288 This function will search every simpletext device in current system,
289 and make every simpletext device as pertantial console device.
294 BdsLibConnectAllConsoles (
299 EFI_DEVICE_PATH_PROTOCOL
*ConDevicePath
;
301 EFI_HANDLE
*HandleBuffer
;
306 ConDevicePath
= NULL
;
309 // Update all the console variables
311 gBS
->LocateHandleBuffer (
313 &gEfiSimpleTextInProtocolGuid
,
319 for (Index
= 0; Index
< HandleCount
; Index
++) {
320 gBS
->HandleProtocol (
322 &gEfiDevicePathProtocolGuid
,
323 (VOID
**) &ConDevicePath
325 BdsLibUpdateConsoleVariable (L
"ConIn", ConDevicePath
, NULL
);
328 if (HandleBuffer
!= NULL
) {
329 FreePool(HandleBuffer
);
333 gBS
->LocateHandleBuffer (
335 &gEfiSimpleTextOutProtocolGuid
,
340 for (Index
= 0; Index
< HandleCount
; Index
++) {
341 gBS
->HandleProtocol (
343 &gEfiDevicePathProtocolGuid
,
344 (VOID
**) &ConDevicePath
346 BdsLibUpdateConsoleVariable (L
"ConOut", ConDevicePath
, NULL
);
347 BdsLibUpdateConsoleVariable (L
"ErrOut", ConDevicePath
, NULL
);
350 if (HandleBuffer
!= NULL
) {
351 FreePool(HandleBuffer
);
355 // Connect all console variables
357 BdsLibConnectAllDefaultConsoles ();
362 This function will connect console device base on the console
363 device variable ConIn, ConOut and ErrOut.
365 @retval EFI_SUCCESS At least one of the ConIn and ConOut device have
366 been connected success.
367 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().
372 BdsLibConnectAllDefaultConsoles (
379 // Connect all default console variables
383 // It seems impossible not to have any ConOut device on platform,
384 // so we check the status here.
386 Status
= BdsLibConnectConsoleVariable (L
"ConOut");
387 if (EFI_ERROR (Status
)) {
392 // Insert the performance probe for Console Out
394 PERF_START (NULL
, "ConOut", "BDS", 1);
395 PERF_END (NULL
, "ConOut", "BDS", 0);
398 // Because possibly the platform is legacy free, in such case,
399 // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,
400 // so we need not check the status.
402 BdsLibConnectConsoleVariable (L
"ConIn");
405 // The _ModuleEntryPoint err out var is legal.
407 BdsLibConnectConsoleVariable (L
"ErrOut");
414 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
415 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
416 buffer is passed in it will be used if it is big enough.
418 @param BmpImage Pointer to BMP file
419 @param BmpImageSize Number of bytes in BmpImage
420 @param GopBlt Buffer containing GOP version of BmpImage.
421 @param GopBltSize Size of GopBlt in bytes.
422 @param PixelHeight Height of GopBlt/BmpImage in pixels
423 @param PixelWidth Width of GopBlt/BmpImage in pixels
425 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
426 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
427 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
428 GopBltSize will contain the required size.
429 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
435 IN UINTN BmpImageSize
,
436 IN OUT VOID
**GopBlt
,
437 IN OUT UINTN
*GopBltSize
,
438 OUT UINTN
*PixelHeight
,
439 OUT UINTN
*PixelWidth
444 BMP_IMAGE_HEADER
*BmpHeader
;
445 BMP_COLOR_MAP
*BmpColorMap
;
446 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
447 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
455 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
457 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
458 return EFI_UNSUPPORTED
;
462 // Doesn't support compress.
464 if (BmpHeader
->CompressionType
!= 0) {
465 return EFI_UNSUPPORTED
;
469 // Calculate Color Map offset in the image.
472 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
475 // Calculate graphics image data address in the image
477 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
481 // Calculate the BltBuffer needed size.
483 BltBufferSize
= BmpHeader
->PixelWidth
* BmpHeader
->PixelHeight
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
485 if (*GopBlt
== NULL
) {
487 // GopBlt is not allocated by caller.
489 *GopBltSize
= BltBufferSize
;
490 *GopBlt
= AllocatePool (*GopBltSize
);
492 if (*GopBlt
== NULL
) {
493 return EFI_OUT_OF_RESOURCES
;
497 // GopBlt has been allocated by caller.
499 if (*GopBltSize
< BltBufferSize
) {
500 *GopBltSize
= BltBufferSize
;
501 return EFI_BUFFER_TOO_SMALL
;
505 *PixelWidth
= BmpHeader
->PixelWidth
;
506 *PixelHeight
= BmpHeader
->PixelHeight
;
509 // Convert image from BMP to Blt buffer format
512 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
513 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
514 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
515 switch (BmpHeader
->BitPerPixel
) {
518 // Convert 1-bit (2 colors) BMP to 24-bit color
520 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
521 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
522 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
523 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
534 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
536 Index
= (*Image
) >> 4;
537 Blt
->Red
= BmpColorMap
[Index
].Red
;
538 Blt
->Green
= BmpColorMap
[Index
].Green
;
539 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
540 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
543 Index
= (*Image
) & 0x0f;
544 Blt
->Red
= BmpColorMap
[Index
].Red
;
545 Blt
->Green
= BmpColorMap
[Index
].Green
;
546 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
552 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
554 Blt
->Red
= BmpColorMap
[*Image
].Red
;
555 Blt
->Green
= BmpColorMap
[*Image
].Green
;
556 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
563 Blt
->Blue
= *Image
++;
564 Blt
->Green
= *Image
++;
570 // Other bit format BMP is not supported.
576 return EFI_UNSUPPORTED
;
582 ImageIndex
= (UINTN
) (Image
- ImageHeader
);
583 if ((ImageIndex
% 4) != 0) {
585 // Bmp Image starts each row on a 32-bit boundary!
587 Image
= Image
+ (4 - (ImageIndex
% 4));
596 Use Console Control Protocol to lock the Console In Spliter virtual handle.
597 This is the ConInHandle and ConIn handle in the EFI system table. All key
598 presses will be ignored until the Password is typed in. The only way to
599 disable the password is to type it in to a ConIn device.
601 @param Password Password used to lock ConIn device.
603 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
604 @retval EFI_UNSUPPORTED Password not found
614 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
616 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
617 if (EFI_ERROR (Status
)) {
618 return EFI_UNSUPPORTED
;
621 Status
= ConsoleControl
->LockStdIn (ConsoleControl
, Password
);
627 Use Console Control to turn off UGA based Simple Text Out consoles from going
628 to the UGA device. Put up LogoFile on every UGA device that is a console
630 @param[in] LogoFile File name of logo to display on the center of the screen.
632 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
633 @retval EFI_UNSUPPORTED Logo not found
639 IN EFI_GUID
*LogoFile
643 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
644 EFI_OEM_BADGING_PROTOCOL
*Badging
;
653 EFI_BADGING_FORMAT Format
;
654 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute
;
659 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
660 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
663 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
665 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
666 if (EFI_ERROR (Status
)) {
667 return EFI_UNSUPPORTED
;
672 // Try to open GOP first
674 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
675 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
676 GraphicsOutput
= NULL
;
678 // Open GOP failed, try to open UGA
680 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
682 if (EFI_ERROR (Status
)) {
683 return EFI_UNSUPPORTED
;
687 Status
= gBS
->LocateProtocol (&gEfiOEMBadgingProtocolGuid
, NULL
, (VOID
**) &Badging
);
690 // Set console control to graphics mode.
692 Status
= ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenGraphics
);
693 if (EFI_ERROR (Status
)) {
694 return EFI_UNSUPPORTED
;
697 if (GraphicsOutput
!= NULL
) {
698 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
699 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
701 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
702 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
703 if (EFI_ERROR (Status
)) {
704 return EFI_UNSUPPORTED
;
707 return EFI_UNSUPPORTED
;
715 if (Badging
!= NULL
) {
717 // Get image from OEMBadging protocol.
719 Status
= Badging
->GetImage (
729 if (EFI_ERROR (Status
)) {
734 // Currently only support BMP format.
736 if (Format
!= EfiBadgingFormatBMP
) {
737 if (ImageData
!= NULL
) {
738 FreePool (ImageData
);
744 // Get the specified image from FV.
746 Status
= GetSectionFromAnyFv (LogoFile
, EFI_SECTION_RAW
, 0, (VOID
**) &ImageData
, &ImageSize
);
747 if (EFI_ERROR (Status
)) {
748 return EFI_UNSUPPORTED
;
753 Attribute
= EfiBadgingDisplayAttributeCenter
;
757 Status
= ConvertBmpToGopBlt (
765 if (EFI_ERROR (Status
)) {
766 FreePool (ImageData
);
768 if (Badging
== NULL
) {
776 // Calculate the display position according to Attribute.
779 case EfiBadgingDisplayAttributeLeftTop
:
784 case EfiBadgingDisplayAttributeCenterTop
:
785 DestX
= (SizeOfX
- Width
) / 2;
789 case EfiBadgingDisplayAttributeRightTop
:
790 DestX
= (SizeOfX
- Width
- CoordinateX
);
791 DestY
= CoordinateY
;;
794 case EfiBadgingDisplayAttributeCenterRight
:
795 DestX
= (SizeOfX
- Width
- CoordinateX
);
796 DestY
= (SizeOfY
- Height
) / 2;
799 case EfiBadgingDisplayAttributeRightBottom
:
800 DestX
= (SizeOfX
- Width
- CoordinateX
);
801 DestY
= (SizeOfY
- Height
- CoordinateY
);
804 case EfiBadgingDisplayAttributeCenterBottom
:
805 DestX
= (SizeOfX
- Width
) / 2;
806 DestY
= (SizeOfY
- Height
- CoordinateY
);
809 case EfiBadgingDisplayAttributeLeftBottom
:
811 DestY
= (SizeOfY
- Height
- CoordinateY
);
814 case EfiBadgingDisplayAttributeCenterLeft
:
816 DestY
= (SizeOfY
- Height
) / 2;
819 case EfiBadgingDisplayAttributeCenter
:
820 DestX
= (SizeOfX
- Width
) / 2;
821 DestY
= (SizeOfY
- Height
) / 2;
830 if ((DestX
>= 0) && (DestY
>= 0)) {
831 if (GraphicsOutput
!= NULL
) {
832 Status
= GraphicsOutput
->Blt (
842 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
844 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
845 Status
= UgaDraw
->Blt (
847 (EFI_UGA_PIXEL
*) Blt
,
848 EfiUgaBltBufferToVideo
,
855 Width
* sizeof (EFI_UGA_PIXEL
)
858 Status
= EFI_UNSUPPORTED
;
862 FreePool (ImageData
);
868 if (Badging
== NULL
) {
877 Use Console Control to turn on UGA based Simple Text Out consoles. The UGA
878 Simple Text Out screens will now be synced up with all non UGA output devices
880 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
890 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
892 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
893 if (EFI_ERROR (Status
)) {
894 return EFI_UNSUPPORTED
;
898 // Set console control to text mode.
900 return ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);