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"
18 Check if we need to save the EFI variable with "ConVarName" as name
21 @param ConVarName The name of the EFI variable.
23 @retval TRUE Set the EFI variable as NV type.
24 @retval FALSE EFI variable as NV type can be set NonNV.
36 // If the variable includes "Dev" at last, we consider
37 // it does not support NV attribute.
39 while (*Ptr
!= L
'\0') {
43 if ((*(Ptr
- 3) == 'D') && (*(Ptr
- 2) == 'e') && (*(Ptr
- 1) == 'v')) {
51 This function update console variable based on ConVarName, it can
52 add or remove one specific console device path from the variable
54 @param ConVarName Console related variable name, ConIn, ConOut,
56 @param CustomizedConDevicePath The console device path which will be added to
57 the console variable ConVarName, this parameter
58 can not be multi-instance.
59 @param ExclusiveDevicePath The console device path which will be removed
60 from the console variable ConVarName, this
61 parameter can not be multi-instance.
63 @retval EFI_UNSUPPORTED The added device path is same to the removed one.
64 @retval EFI_SUCCESS Success add or remove the device path from the
70 BdsLibUpdateConsoleVariable (
71 IN CHAR16
*ConVarName
,
72 IN EFI_DEVICE_PATH_PROTOCOL
*CustomizedConDevicePath
,
73 IN EFI_DEVICE_PATH_PROTOCOL
*ExclusiveDevicePath
76 EFI_DEVICE_PATH_PROTOCOL
*VarConsole
;
78 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
79 EFI_DEVICE_PATH_PROTOCOL
*TempNewDevicePath
;
86 // Notes: check the device path point, here should check
87 // with compare memory
89 if (CustomizedConDevicePath
== ExclusiveDevicePath
) {
90 return EFI_UNSUPPORTED
;
93 // Delete the ExclusiveDevicePath from current default console
95 VarConsole
= BdsLibGetVariableAndSize (
97 &gEfiGlobalVariableGuid
,
102 // Initialize NewDevicePath
104 NewDevicePath
= VarConsole
;
107 // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.
108 // In the end, NewDevicePath is the final device path.
110 if (ExclusiveDevicePath
!= NULL
&& VarConsole
!= NULL
) {
111 NewDevicePath
= BdsLibDelPartMatchInstance (VarConsole
, ExclusiveDevicePath
);
114 // Try to append customized device path to NewDevicePath.
116 if (CustomizedConDevicePath
!= NULL
) {
117 if (!BdsLibMatchDevicePaths (NewDevicePath
, CustomizedConDevicePath
)) {
119 // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.
121 NewDevicePath
= BdsLibDelPartMatchInstance (NewDevicePath
, CustomizedConDevicePath
);
123 // In the first check, the default console variable will be _ModuleEntryPoint,
124 // just append current customized device path
126 TempNewDevicePath
= NewDevicePath
;
127 NewDevicePath
= AppendDevicePathInstance (NewDevicePath
, CustomizedConDevicePath
);
128 if (TempNewDevicePath
!= NULL
) {
129 FreePool(TempNewDevicePath
);
135 // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.
137 if (IsNvNeed(ConVarName
)) {
139 // ConVarName has NV attribute.
141 Attributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
144 // ConVarName does not have NV attribute.
146 Attributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
;
150 // Finally, Update the variable of the default console by NewDevicePath
154 &gEfiGlobalVariableGuid
,
156 GetDevicePathSize (NewDevicePath
),
160 if (VarConsole
== NewDevicePath
) {
161 if (VarConsole
!= NULL
) {
162 FreePool(VarConsole
);
165 if (VarConsole
!= NULL
) {
166 FreePool(VarConsole
);
168 if (NewDevicePath
!= NULL
) {
169 FreePool(NewDevicePath
);
179 Connect the console device base on the variable ConVarName, if
180 device path of the ConVarName is multi-instance device path, if
181 anyone of the instances is connected success, then this function
184 @param ConVarName Console related variable name, ConIn, ConOut,
187 @retval EFI_NOT_FOUND There is not any console devices connected
189 @retval EFI_SUCCESS Success connect any one instance of the console
190 device path base on the variable ConVarName.
195 BdsLibConnectConsoleVariable (
196 IN CHAR16
*ConVarName
200 EFI_DEVICE_PATH_PROTOCOL
*StartDevicePath
;
202 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
203 EFI_DEVICE_PATH_PROTOCOL
*Next
;
204 EFI_DEVICE_PATH_PROTOCOL
*CopyOfDevicePath
;
208 Status
= EFI_SUCCESS
;
212 // Check if the console variable exist
214 StartDevicePath
= BdsLibGetVariableAndSize (
216 &gEfiGlobalVariableGuid
,
219 if (StartDevicePath
== NULL
) {
220 return EFI_UNSUPPORTED
;
223 CopyOfDevicePath
= StartDevicePath
;
226 // Check every instance of the console variable
228 Instance
= GetNextDevicePathInstance (&CopyOfDevicePath
, &Size
);
229 if (Instance
== NULL
) {
230 FreePool (StartDevicePath
);
231 return EFI_UNSUPPORTED
;
235 while (!IsDevicePathEndType (Next
)) {
236 Next
= NextDevicePathNode (Next
);
239 SetDevicePathEndNode (Next
);
241 // Check USB1.1 console
243 if ((DevicePathType (Instance
) == MESSAGING_DEVICE_PATH
) &&
244 ((DevicePathSubType (Instance
) == MSG_USB_CLASS_DP
)
245 || (DevicePathSubType (Instance
) == MSG_USB_WWID_DP
)
248 // Check the Usb console in Usb2.0 bus firstly, then Usb1.1 bus
250 Status
= BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_EHCI
, Instance
);
251 if (!EFI_ERROR (Status
)) {
255 Status
= BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_UHCI
, Instance
);
256 if (!EFI_ERROR (Status
)) {
261 // Connect the instance device path
263 Status
= BdsLibConnectDevicePath (Instance
);
264 if (EFI_ERROR (Status
)) {
266 // Delete the instance from the console varialbe
268 BdsLibUpdateConsoleVariable (ConVarName
, NULL
, Instance
);
274 } while (CopyOfDevicePath
!= NULL
);
276 FreePool (StartDevicePath
);
279 return EFI_NOT_FOUND
;
287 This function will search every simpletext device in current system,
288 and make every simpletext device as pertantial console device.
293 BdsLibConnectAllConsoles (
298 EFI_DEVICE_PATH_PROTOCOL
*ConDevicePath
;
300 EFI_HANDLE
*HandleBuffer
;
305 ConDevicePath
= NULL
;
308 // Update all the console variables
310 gBS
->LocateHandleBuffer (
312 &gEfiSimpleTextInProtocolGuid
,
318 for (Index
= 0; Index
< HandleCount
; Index
++) {
319 gBS
->HandleProtocol (
321 &gEfiDevicePathProtocolGuid
,
322 (VOID
**) &ConDevicePath
324 BdsLibUpdateConsoleVariable (L
"ConIn", ConDevicePath
, NULL
);
327 if (HandleBuffer
!= NULL
) {
328 FreePool(HandleBuffer
);
332 gBS
->LocateHandleBuffer (
334 &gEfiSimpleTextOutProtocolGuid
,
339 for (Index
= 0; Index
< HandleCount
; Index
++) {
340 gBS
->HandleProtocol (
342 &gEfiDevicePathProtocolGuid
,
343 (VOID
**) &ConDevicePath
345 BdsLibUpdateConsoleVariable (L
"ConOut", ConDevicePath
, NULL
);
346 BdsLibUpdateConsoleVariable (L
"ErrOut", ConDevicePath
, NULL
);
349 if (HandleBuffer
!= NULL
) {
350 FreePool(HandleBuffer
);
354 // Connect all console variables
356 BdsLibConnectAllDefaultConsoles ();
361 This function will connect console device base on the console
362 device variable ConIn, ConOut and ErrOut.
364 @retval EFI_SUCCESS At least one of the ConIn and ConOut device have
365 been connected success.
366 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().
371 BdsLibConnectAllDefaultConsoles (
378 // Connect all default console variables
382 // It seems impossible not to have any ConOut device on platform,
383 // so we check the status here.
385 Status
= BdsLibConnectConsoleVariable (L
"ConOut");
386 if (EFI_ERROR (Status
)) {
391 // Insert the performance probe for Console Out
393 PERF_START (NULL
, "ConOut", "BDS", 1);
394 PERF_END (NULL
, "ConOut", "BDS", 0);
397 // Because possibly the platform is legacy free, in such case,
398 // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,
399 // so we need not check the status.
401 BdsLibConnectConsoleVariable (L
"ConIn");
404 // The _ModuleEntryPoint err out var is legal.
406 BdsLibConnectConsoleVariable (L
"ErrOut");
413 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
414 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
415 buffer is passed in it will be used if it is big enough.
417 @param BmpImage Pointer to BMP file
418 @param BmpImageSize Number of bytes in BmpImage
419 @param GopBlt Buffer containing GOP version of BmpImage.
420 @param GopBltSize Size of GopBlt in bytes.
421 @param PixelHeight Height of GopBlt/BmpImage in pixels
422 @param PixelWidth Width of GopBlt/BmpImage in pixels
424 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
425 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
426 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
427 GopBltSize will contain the required size.
428 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
434 IN UINTN BmpImageSize
,
435 IN OUT VOID
**GopBlt
,
436 IN OUT UINTN
*GopBltSize
,
437 OUT UINTN
*PixelHeight
,
438 OUT UINTN
*PixelWidth
443 BMP_IMAGE_HEADER
*BmpHeader
;
444 BMP_COLOR_MAP
*BmpColorMap
;
445 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
446 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
454 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
456 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
457 return EFI_UNSUPPORTED
;
461 // Doesn't support compress.
463 if (BmpHeader
->CompressionType
!= 0) {
464 return EFI_UNSUPPORTED
;
468 // Calculate Color Map offset in the image.
471 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
474 // Calculate graphics image data address in the image
476 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
480 // Calculate the BltBuffer needed size.
482 BltBufferSize
= BmpHeader
->PixelWidth
* BmpHeader
->PixelHeight
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
484 if (*GopBlt
== NULL
) {
486 // GopBlt is not allocated by caller.
488 *GopBltSize
= BltBufferSize
;
489 *GopBlt
= AllocatePool (*GopBltSize
);
491 if (*GopBlt
== NULL
) {
492 return EFI_OUT_OF_RESOURCES
;
496 // GopBlt has been allocated by caller.
498 if (*GopBltSize
< BltBufferSize
) {
499 *GopBltSize
= BltBufferSize
;
500 return EFI_BUFFER_TOO_SMALL
;
504 *PixelWidth
= BmpHeader
->PixelWidth
;
505 *PixelHeight
= BmpHeader
->PixelHeight
;
508 // Convert image from BMP to Blt buffer format
511 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
512 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
513 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
514 switch (BmpHeader
->BitPerPixel
) {
517 // Convert 1-bit (2 colors) BMP to 24-bit color
519 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
520 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
521 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
522 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
533 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
535 Index
= (*Image
) >> 4;
536 Blt
->Red
= BmpColorMap
[Index
].Red
;
537 Blt
->Green
= BmpColorMap
[Index
].Green
;
538 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
539 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
542 Index
= (*Image
) & 0x0f;
543 Blt
->Red
= BmpColorMap
[Index
].Red
;
544 Blt
->Green
= BmpColorMap
[Index
].Green
;
545 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
551 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
553 Blt
->Red
= BmpColorMap
[*Image
].Red
;
554 Blt
->Green
= BmpColorMap
[*Image
].Green
;
555 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
562 Blt
->Blue
= *Image
++;
563 Blt
->Green
= *Image
++;
569 // Other bit format BMP is not supported.
575 return EFI_UNSUPPORTED
;
581 ImageIndex
= (UINTN
) (Image
- ImageHeader
);
582 if ((ImageIndex
% 4) != 0) {
584 // Bmp Image starts each row on a 32-bit boundary!
586 Image
= Image
+ (4 - (ImageIndex
% 4));
595 Use Console Control Protocol to lock the Console In Spliter virtual handle.
596 This is the ConInHandle and ConIn handle in the EFI system table. All key
597 presses will be ignored until the Password is typed in. The only way to
598 disable the password is to type it in to a ConIn device.
600 @param Password Password used to lock ConIn device.
602 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
603 @retval EFI_UNSUPPORTED Password not found
613 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
615 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
616 if (EFI_ERROR (Status
)) {
617 return EFI_UNSUPPORTED
;
620 Status
= ConsoleControl
->LockStdIn (ConsoleControl
, Password
);
626 Use Console Control to turn off UGA based Simple Text Out consoles from going
627 to the UGA device. Put up LogoFile on every UGA device that is a console
629 @param[in] LogoFile File name of logo to display on the center of the screen.
631 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
632 @retval EFI_UNSUPPORTED Logo not found
638 IN EFI_GUID
*LogoFile
642 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
643 EFI_OEM_BADGING_PROTOCOL
*Badging
;
652 EFI_BADGING_FORMAT Format
;
653 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute
;
658 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
659 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
662 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
664 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
665 if (EFI_ERROR (Status
)) {
666 return EFI_UNSUPPORTED
;
671 // Try to open GOP first
673 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
674 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
675 GraphicsOutput
= NULL
;
677 // Open GOP failed, try to open UGA
679 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
681 if (EFI_ERROR (Status
)) {
682 return EFI_UNSUPPORTED
;
686 Status
= gBS
->LocateProtocol (&gEfiOEMBadgingProtocolGuid
, NULL
, (VOID
**) &Badging
);
689 // Set console control to graphics mode.
691 Status
= ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenGraphics
);
692 if (EFI_ERROR (Status
)) {
693 return EFI_UNSUPPORTED
;
696 if (GraphicsOutput
!= NULL
) {
697 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
698 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
700 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
701 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
702 if (EFI_ERROR (Status
)) {
703 return EFI_UNSUPPORTED
;
706 return EFI_UNSUPPORTED
;
714 if (Badging
!= NULL
) {
716 // Get image from OEMBadging protocol.
718 Status
= Badging
->GetImage (
728 if (EFI_ERROR (Status
)) {
733 // Currently only support BMP format.
735 if (Format
!= EfiBadgingFormatBMP
) {
736 if (ImageData
!= NULL
) {
737 FreePool (ImageData
);
743 // Get the specified image from FV.
745 Status
= GetSectionFromAnyFv (LogoFile
, EFI_SECTION_RAW
, 0, (VOID
**) &ImageData
, &ImageSize
);
746 if (EFI_ERROR (Status
)) {
747 return EFI_UNSUPPORTED
;
752 Attribute
= EfiBadgingDisplayAttributeCenter
;
756 Status
= ConvertBmpToGopBlt (
764 if (EFI_ERROR (Status
)) {
765 FreePool (ImageData
);
767 if (Badging
== NULL
) {
775 // Calculate the display position according to Attribute.
778 case EfiBadgingDisplayAttributeLeftTop
:
783 case EfiBadgingDisplayAttributeCenterTop
:
784 DestX
= (SizeOfX
- Width
) / 2;
788 case EfiBadgingDisplayAttributeRightTop
:
789 DestX
= (SizeOfX
- Width
- CoordinateX
);
790 DestY
= CoordinateY
;;
793 case EfiBadgingDisplayAttributeCenterRight
:
794 DestX
= (SizeOfX
- Width
- CoordinateX
);
795 DestY
= (SizeOfY
- Height
) / 2;
798 case EfiBadgingDisplayAttributeRightBottom
:
799 DestX
= (SizeOfX
- Width
- CoordinateX
);
800 DestY
= (SizeOfY
- Height
- CoordinateY
);
803 case EfiBadgingDisplayAttributeCenterBottom
:
804 DestX
= (SizeOfX
- Width
) / 2;
805 DestY
= (SizeOfY
- Height
- CoordinateY
);
808 case EfiBadgingDisplayAttributeLeftBottom
:
810 DestY
= (SizeOfY
- Height
- CoordinateY
);
813 case EfiBadgingDisplayAttributeCenterLeft
:
815 DestY
= (SizeOfY
- Height
) / 2;
818 case EfiBadgingDisplayAttributeCenter
:
819 DestX
= (SizeOfX
- Width
) / 2;
820 DestY
= (SizeOfY
- Height
) / 2;
829 if ((DestX
>= 0) && (DestY
>= 0)) {
830 if (GraphicsOutput
!= NULL
) {
831 Status
= GraphicsOutput
->Blt (
841 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
843 } else if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
844 Status
= UgaDraw
->Blt (
846 (EFI_UGA_PIXEL
*) Blt
,
847 EfiUgaBltBufferToVideo
,
854 Width
* sizeof (EFI_UGA_PIXEL
)
857 Status
= EFI_UNSUPPORTED
;
861 FreePool (ImageData
);
867 if (Badging
== NULL
) {
876 Use Console Control to turn on UGA based Simple Text Out consoles. The UGA
877 Simple Text Out screens will now be synced up with all non UGA output devices
879 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
889 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
891 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
892 if (EFI_ERROR (Status
)) {
893 return EFI_UNSUPPORTED
;
897 // Set console control to text mode.
899 return ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);