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 variabel as NV type.
24 @retval FALSE EFI variabel 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 Add or remove the same device path.
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_UNSUPPORTED Request console variable does not exist.
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
);
231 while (!IsDevicePathEndType (Next
)) {
232 Next
= NextDevicePathNode (Next
);
235 SetDevicePathEndNode (Next
);
237 // Check USB1.1 console
239 if ((DevicePathType (Instance
) == MESSAGING_DEVICE_PATH
) &&
240 ((DevicePathSubType (Instance
) == MSG_USB_CLASS_DP
)
241 || (DevicePathSubType (Instance
) == MSG_USB_WWID_DP
)
244 // Check the Usb console in Usb2.0 bus firstly, then Usb1.1 bus
246 Status
= BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_EHCI
, Instance
);
247 if (!EFI_ERROR (Status
)) {
251 Status
= BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_UHCI
, Instance
);
252 if (!EFI_ERROR (Status
)) {
257 // Connect the instance device path
259 Status
= BdsLibConnectDevicePath (Instance
);
260 if (EFI_ERROR (Status
)) {
262 // Delete the instance from the console varialbe
264 BdsLibUpdateConsoleVariable (ConVarName
, NULL
, Instance
);
270 } while (CopyOfDevicePath
!= NULL
);
272 FreePool (StartDevicePath
);
275 return EFI_NOT_FOUND
;
283 This function will search every simpletxt devive in current system,
284 and make every simpletxt device as pertantial console device.
289 BdsLibConnectAllConsoles (
294 EFI_DEVICE_PATH_PROTOCOL
*ConDevicePath
;
296 EFI_HANDLE
*HandleBuffer
;
301 ConDevicePath
= NULL
;
304 // Update all the console varables
306 gBS
->LocateHandleBuffer (
308 &gEfiSimpleTextInProtocolGuid
,
314 for (Index
= 0; Index
< HandleCount
; Index
++) {
315 gBS
->HandleProtocol (
317 &gEfiDevicePathProtocolGuid
,
318 (VOID
**) &ConDevicePath
320 BdsLibUpdateConsoleVariable (L
"ConIn", ConDevicePath
, NULL
);
323 if (HandleBuffer
!= NULL
) {
324 FreePool(HandleBuffer
);
328 gBS
->LocateHandleBuffer (
330 &gEfiSimpleTextOutProtocolGuid
,
335 for (Index
= 0; Index
< HandleCount
; Index
++) {
336 gBS
->HandleProtocol (
338 &gEfiDevicePathProtocolGuid
,
339 (VOID
**) &ConDevicePath
341 BdsLibUpdateConsoleVariable (L
"ConOut", ConDevicePath
, NULL
);
342 BdsLibUpdateConsoleVariable (L
"ErrOut", ConDevicePath
, NULL
);
345 if (HandleBuffer
!= NULL
) {
346 FreePool(HandleBuffer
);
350 // Connect all console variables
352 BdsLibConnectAllDefaultConsoles ();
357 This function will connect console device base on the console
358 device variable ConIn, ConOut and ErrOut.
360 @retval EFI_SUCCESS At least one of the ConIn and ConOut device have
361 been connected success.
362 @retval EFI_STATUS Return the status of
363 BdsLibConnectConsoleVariable ().
368 BdsLibConnectAllDefaultConsoles (
375 // Connect all default console variables
379 // It seems impossible not to have any ConOut device on platform,
380 // so we check the status here.
382 Status
= BdsLibConnectConsoleVariable (L
"ConOut");
383 if (EFI_ERROR (Status
)) {
388 // Insert the performance probe for Console Out
390 PERF_START (NULL
, "ConOut", "BDS", 1);
391 PERF_END (NULL
, "ConOut", "BDS", 0);
394 // Because possibly the platform is legacy free, in such case,
395 // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,
396 // so we need not check the status.
398 BdsLibConnectConsoleVariable (L
"ConIn");
401 // The _ModuleEntryPoint err out var is legal.
403 BdsLibConnectConsoleVariable (L
"ErrOut");
410 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
411 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
412 buffer is passed in it will be used if it is big enough.
414 @param BmpImage Pointer to BMP file
415 @param BmpImageSize Number of bytes in BmpImage
416 @param GopBlt Buffer containing GOP version of BmpImage.
417 @param GopBltSize Size of GopBlt in bytes.
418 @param PixelHeight Height of GopBlt/BmpImage in pixels
419 @param PixelWidth Width of GopBlt/BmpImage in pixels
421 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
422 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
423 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
424 GopBltSize will contain the required size.
425 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
431 IN UINTN BmpImageSize
,
432 IN OUT VOID
**GopBlt
,
433 IN OUT UINTN
*GopBltSize
,
434 OUT UINTN
*PixelHeight
,
435 OUT UINTN
*PixelWidth
440 BMP_IMAGE_HEADER
*BmpHeader
;
441 BMP_COLOR_MAP
*BmpColorMap
;
442 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
443 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
451 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
453 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
454 return EFI_UNSUPPORTED
;
458 // Doesn't support compress.
460 if (BmpHeader
->CompressionType
!= 0) {
461 return EFI_UNSUPPORTED
;
465 // Calculate Color Map offset in the image.
468 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
471 // Calculate graphics image data address in the image
473 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
477 // Calculate the BltBuffer needed size.
479 BltBufferSize
= BmpHeader
->PixelWidth
* BmpHeader
->PixelHeight
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
481 if (*GopBlt
== NULL
) {
483 // GopBlt is not allocated by caller.
485 *GopBltSize
= BltBufferSize
;
486 *GopBlt
= AllocatePool (*GopBltSize
);
488 if (*GopBlt
== NULL
) {
489 return EFI_OUT_OF_RESOURCES
;
493 // GopBlt has been allocated by caller.
495 if (*GopBltSize
< BltBufferSize
) {
496 *GopBltSize
= BltBufferSize
;
497 return EFI_BUFFER_TOO_SMALL
;
501 *PixelWidth
= BmpHeader
->PixelWidth
;
502 *PixelHeight
= BmpHeader
->PixelHeight
;
505 // Convert image from BMP to Blt buffer format
508 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
509 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
510 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
511 switch (BmpHeader
->BitPerPixel
) {
514 // Convert 1-bit (2 colors) BMP to 24-bit color
516 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
517 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
518 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
519 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
530 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
532 Index
= (*Image
) >> 4;
533 Blt
->Red
= BmpColorMap
[Index
].Red
;
534 Blt
->Green
= BmpColorMap
[Index
].Green
;
535 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
536 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
539 Index
= (*Image
) & 0x0f;
540 Blt
->Red
= BmpColorMap
[Index
].Red
;
541 Blt
->Green
= BmpColorMap
[Index
].Green
;
542 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
548 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
550 Blt
->Red
= BmpColorMap
[*Image
].Red
;
551 Blt
->Green
= BmpColorMap
[*Image
].Green
;
552 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
559 Blt
->Blue
= *Image
++;
560 Blt
->Green
= *Image
++;
566 // Other bit format BMP is not supported.
572 return EFI_UNSUPPORTED
;
578 ImageIndex
= (UINTN
) (Image
- ImageHeader
);
579 if ((ImageIndex
% 4) != 0) {
581 // Bmp Image starts each row on a 32-bit boundary!
583 Image
= Image
+ (4 - (ImageIndex
% 4));
592 Use Console Control Protocol to lock the Console In Spliter virtual handle.
593 This is the ConInHandle and ConIn handle in the EFI system table. All key
594 presses will be ignored until the Password is typed in. The only way to
595 disable the password is to type it in to a ConIn device.
597 @param Password Password used to lock ConIn device.
599 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
600 @retval EFI_UNSUPPORTED Password not found.
610 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
612 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
613 if (EFI_ERROR (Status
)) {
614 return EFI_UNSUPPORTED
;
617 Status
= ConsoleControl
->LockStdIn (ConsoleControl
, Password
);
623 Use Console Control to turn off UGA based Simple Text Out consoles from going
624 to the UGA device. Put up LogoFile on every UGA device that is a console.
626 @param LogoFile File name of logo to display on the center of the screen.
628 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
629 @retval EFI_UNSUPPORTED Logo not found.
630 Fail to locate ConsoleControl protocol.
631 Fail to get UgaDraw or Gop handle.
632 Fail to switch grahic mode.
638 IN EFI_GUID
*LogoFile OPTIONAL
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
;
699 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
700 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
701 if (EFI_ERROR (Status
)) {
702 return EFI_UNSUPPORTED
;
705 return EFI_UNSUPPORTED
;
713 if (Badging
!= NULL
) {
715 // Get image from OEMBadging protocol.
717 Status
= Badging
->GetImage (
727 if (EFI_ERROR (Status
)) {
732 // Currently only support BMP format.
734 if (Format
!= EfiBadgingFormatBMP
) {
735 if (ImageData
!= NULL
) {
736 FreePool (ImageData
);
742 // Get the specified image from FV.
744 Status
= GetSectionFromAnyFv (LogoFile
, EFI_SECTION_RAW
, 0, (VOID
**) &ImageData
, &ImageSize
);
745 if (EFI_ERROR (Status
)) {
746 return EFI_UNSUPPORTED
;
751 Attribute
= EfiBadgingDisplayAttributeCenter
;
755 Status
= ConvertBmpToGopBlt (
763 if (EFI_ERROR (Status
)) {
764 if (ImageData
!= NULL
) {
765 FreePool (ImageData
);
767 if (Badging
== NULL
) {
775 // Caculate 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 (FeaturePcdGet (PcdUgaConsumeSupport
)) {
844 Status
= UgaDraw
->Blt (
846 (EFI_UGA_PIXEL
*) Blt
,
847 EfiUgaBltBufferToVideo
,
854 Width
* sizeof (EFI_UGA_PIXEL
)
857 Status
= EFI_UNSUPPORTED
;
861 if (ImageData
!= NULL
) {
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.
881 @retval EFI_UNSUPPORTED Fail to locate ConsoleControl Protocol.
891 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
893 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
894 if (EFI_ERROR (Status
)) {
895 return EFI_UNSUPPORTED
;
899 // Set console control to text mode.
901 return ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);