]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c
1. retried PrimaryConsoleInDeviceGuid, PrimaryConsoleOutDeviceGuid and PrimaryStandar...
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / GenericBdsLib / BdsConsole.c
1 /** @file
2 BDS Lib functions which contain all the code to connect console device
3
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
9
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.
12
13 **/
14
15 #include "InternalBdsLib.h"
16 #include "Bmp.h"
17
18 /**
19 Check if we need to save the EFI variable with "ConVarName" as name
20 as NV type
21
22 @param ConVarName The name of the EFI variable.
23
24 @retval TRUE Set the EFI variable as NV type.
25 @retval FALSE EFI variable as NV type can be set NonNV.
26 **/
27 BOOLEAN
28 IsNvNeed (
29 IN CHAR16 *ConVarName
30 )
31 {
32 CHAR16 *Ptr;
33
34 Ptr = ConVarName;
35
36 //
37 // If the variable includes "Dev" at last, we consider
38 // it does not support NV attribute.
39 //
40 while (*Ptr != L'\0') {
41 Ptr++;
42 }
43
44 if ((*(Ptr - 3) == 'D') && (*(Ptr - 2) == 'e') && (*(Ptr - 1) == 'v')) {
45 return FALSE;
46 } else {
47 return TRUE;
48 }
49 }
50
51 /**
52 Fill console handle in System Table if there are no valid console handle in.
53
54 Firstly, check the validation of console handle in System Table. If it is invalid,
55 update it by the first console device handle from EFI console variable.
56
57 @param VarName The name of the EFI console variable.
58 @param ConsoleGuid Specified Console protocol GUID.
59 @param ConsoleHandle On IN, console handle in System Table to be checked.
60 On OUT, new console hanlde in system table.
61 @param ProtocolInterface On IN, console protocol on console handle in System Table to be checked.
62 On OUT, new console protocol on new console hanlde in system table.
63 **/
64 VOID
65 UpdateSystemTableConsole (
66 IN CHAR16 *VarName,
67 IN EFI_GUID *ConsoleGuid,
68 IN OUT EFI_HANDLE *ConsoleHandle,
69 IN OUT VOID **ProtocolInterface
70 )
71 {
72 EFI_STATUS Status;
73 UINTN DevicePathSize;
74 EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;
75 EFI_DEVICE_PATH_PROTOCOL *VarConsole;
76 EFI_DEVICE_PATH_PROTOCOL *Instance;
77 VOID *Interface;
78 EFI_HANDLE NewHandle;
79
80 ASSERT (VarName != NULL);
81 ASSERT (ConsoleHandle != NULL);
82 ASSERT (ConsoleGuid != NULL);
83 ASSERT (ProtocolInterface != NULL);
84
85 if (*ConsoleHandle != NULL) {
86 Status = gBS->HandleProtocol (
87 *ConsoleHandle,
88 ConsoleGuid,
89 &Interface
90 );
91 if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) {
92 //
93 // If ConsoleHandle is valid and console protocol on this handle also
94 // also matched, just return.
95 //
96 return;
97 }
98 }
99
100 //
101 // Get all possible consoles device path from EFI variable
102 //
103 VarConsole = BdsLibGetVariableAndSize (
104 VarName,
105 &gEfiGlobalVariableGuid,
106 &DevicePathSize
107 );
108 if (VarConsole == NULL) {
109 //
110 // If there is no any console device, just return.
111 //
112 return ;
113 }
114
115 FullDevicePath = VarConsole;
116
117 do {
118 //
119 // Check every instance of the console variable
120 //
121 Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);
122 if (Instance == NULL) {
123 FreePool (FullDevicePath);
124 ASSERT (FALSE);
125 }
126
127 //
128 // Find console device handle by device path instance
129 //
130 Status = gBS->LocateDevicePath (
131 ConsoleGuid,
132 &Instance,
133 &NewHandle
134 );
135 if (!EFI_ERROR (Status)) {
136 //
137 // Get the console protocol on this console device handle
138 //
139 Status = gBS->HandleProtocol (
140 NewHandle,
141 ConsoleGuid,
142 &Interface
143 );
144 if (!EFI_ERROR (Status)) {
145 //
146 // Update new console handle in System Table.
147 //
148 *ConsoleHandle = NewHandle;
149 *ProtocolInterface = Interface;
150 return ;
151 }
152 }
153
154 } while (Instance != NULL);
155
156 //
157 // No any available console devcie found.
158 //
159 ASSERT (FALSE);
160 }
161
162 /**
163 This function update console variable based on ConVarName, it can
164 add or remove one specific console device path from the variable
165
166 @param ConVarName Console related variable name, ConIn, ConOut,
167 ErrOut.
168 @param CustomizedConDevicePath The console device path which will be added to
169 the console variable ConVarName, this parameter
170 can not be multi-instance.
171 @param ExclusiveDevicePath The console device path which will be removed
172 from the console variable ConVarName, this
173 parameter can not be multi-instance.
174
175 @retval EFI_UNSUPPORTED The added device path is same to the removed one.
176 @retval EFI_SUCCESS Success add or remove the device path from the
177 console variable.
178
179 **/
180 EFI_STATUS
181 EFIAPI
182 BdsLibUpdateConsoleVariable (
183 IN CHAR16 *ConVarName,
184 IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,
185 IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath
186 )
187 {
188 EFI_DEVICE_PATH_PROTOCOL *VarConsole;
189 UINTN DevicePathSize;
190 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
191 EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
192 UINT32 Attributes;
193
194 VarConsole = NULL;
195 DevicePathSize = 0;
196
197 //
198 // Notes: check the device path point, here should check
199 // with compare memory
200 //
201 if (CustomizedConDevicePath == ExclusiveDevicePath) {
202 return EFI_UNSUPPORTED;
203 }
204 //
205 // Delete the ExclusiveDevicePath from current default console
206 //
207 VarConsole = BdsLibGetVariableAndSize (
208 ConVarName,
209 &gEfiGlobalVariableGuid,
210 &DevicePathSize
211 );
212
213 //
214 // Initialize NewDevicePath
215 //
216 NewDevicePath = VarConsole;
217
218 //
219 // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.
220 // In the end, NewDevicePath is the final device path.
221 //
222 if (ExclusiveDevicePath != NULL && VarConsole != NULL) {
223 NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath);
224 }
225 //
226 // Try to append customized device path to NewDevicePath.
227 //
228 if (CustomizedConDevicePath != NULL) {
229 if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {
230 //
231 // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.
232 //
233 NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);
234 //
235 // In the first check, the default console variable will be _ModuleEntryPoint,
236 // just append current customized device path
237 //
238 TempNewDevicePath = NewDevicePath;
239 NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);
240 if (TempNewDevicePath != NULL) {
241 FreePool(TempNewDevicePath);
242 }
243 }
244 }
245
246 //
247 // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.
248 //
249 if (IsNvNeed(ConVarName)) {
250 //
251 // ConVarName has NV attribute.
252 //
253 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
254 } else {
255 //
256 // ConVarName does not have NV attribute.
257 //
258 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
259 }
260
261 //
262 // Finally, Update the variable of the default console by NewDevicePath
263 //
264 gRT->SetVariable (
265 ConVarName,
266 &gEfiGlobalVariableGuid,
267 Attributes,
268 GetDevicePathSize (NewDevicePath),
269 NewDevicePath
270 );
271
272 if (VarConsole == NewDevicePath) {
273 if (VarConsole != NULL) {
274 FreePool(VarConsole);
275 }
276 } else {
277 if (VarConsole != NULL) {
278 FreePool(VarConsole);
279 }
280 if (NewDevicePath != NULL) {
281 FreePool(NewDevicePath);
282 }
283 }
284
285 return EFI_SUCCESS;
286
287 }
288
289
290 /**
291 Connect the console device base on the variable ConVarName, if
292 device path of the ConVarName is multi-instance device path, if
293 anyone of the instances is connected success, then this function
294 will return success.
295
296 @param ConVarName Console related variable name, ConIn, ConOut,
297 ErrOut.
298
299 @retval EFI_NOT_FOUND There is not any console devices connected
300 success
301 @retval EFI_SUCCESS Success connect any one instance of the console
302 device path base on the variable ConVarName.
303
304 **/
305 EFI_STATUS
306 EFIAPI
307 BdsLibConnectConsoleVariable (
308 IN CHAR16 *ConVarName
309 )
310 {
311 EFI_STATUS Status;
312 EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;
313 UINTN VariableSize;
314 EFI_DEVICE_PATH_PROTOCOL *Instance;
315 EFI_DEVICE_PATH_PROTOCOL *Next;
316 EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;
317 UINTN Size;
318 BOOLEAN DeviceExist;
319
320 Status = EFI_SUCCESS;
321 DeviceExist = FALSE;
322
323 //
324 // Check if the console variable exist
325 //
326 StartDevicePath = BdsLibGetVariableAndSize (
327 ConVarName,
328 &gEfiGlobalVariableGuid,
329 &VariableSize
330 );
331 if (StartDevicePath == NULL) {
332 return EFI_UNSUPPORTED;
333 }
334
335 CopyOfDevicePath = StartDevicePath;
336 do {
337 //
338 // Check every instance of the console variable
339 //
340 Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);
341 if (Instance == NULL) {
342 FreePool (StartDevicePath);
343 return EFI_UNSUPPORTED;
344 }
345
346 Next = Instance;
347 while (!IsDevicePathEndType (Next)) {
348 Next = NextDevicePathNode (Next);
349 }
350
351 SetDevicePathEndNode (Next);
352 //
353 // Check USB1.1 console
354 //
355 if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&
356 ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP)
357 || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)
358 )) {
359 //
360 // Check the Usb console in Usb2.0 bus firstly, then Usb1.1 bus
361 //
362 Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_EHCI, Instance);
363 if (!EFI_ERROR (Status)) {
364 DeviceExist = TRUE;
365 }
366
367 Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_UHCI, Instance);
368 if (!EFI_ERROR (Status)) {
369 DeviceExist = TRUE;
370 }
371 } else {
372 //
373 // Connect the instance device path
374 //
375 Status = BdsLibConnectDevicePath (Instance);
376 if (EFI_ERROR (Status)) {
377 //
378 // Delete the instance from the console varialbe
379 //
380 BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance);
381 } else {
382 DeviceExist = TRUE;
383 }
384 }
385 FreePool(Instance);
386 } while (CopyOfDevicePath != NULL);
387
388 FreePool (StartDevicePath);
389
390 if (!DeviceExist) {
391 return EFI_NOT_FOUND;
392 }
393
394 return EFI_SUCCESS;
395 }
396
397
398 /**
399 This function will search every simpletext device in current system,
400 and make every simpletext device as pertantial console device.
401
402 **/
403 VOID
404 EFIAPI
405 BdsLibConnectAllConsoles (
406 VOID
407 )
408 {
409 UINTN Index;
410 EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
411 UINTN HandleCount;
412 EFI_HANDLE *HandleBuffer;
413
414 Index = 0;
415 HandleCount = 0;
416 HandleBuffer = NULL;
417 ConDevicePath = NULL;
418
419 //
420 // Update all the console variables
421 //
422 gBS->LocateHandleBuffer (
423 ByProtocol,
424 &gEfiSimpleTextInProtocolGuid,
425 NULL,
426 &HandleCount,
427 &HandleBuffer
428 );
429
430 for (Index = 0; Index < HandleCount; Index++) {
431 gBS->HandleProtocol (
432 HandleBuffer[Index],
433 &gEfiDevicePathProtocolGuid,
434 (VOID **) &ConDevicePath
435 );
436 BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL);
437 }
438
439 if (HandleBuffer != NULL) {
440 FreePool(HandleBuffer);
441 HandleBuffer = NULL;
442 }
443
444 gBS->LocateHandleBuffer (
445 ByProtocol,
446 &gEfiSimpleTextOutProtocolGuid,
447 NULL,
448 &HandleCount,
449 &HandleBuffer
450 );
451 for (Index = 0; Index < HandleCount; Index++) {
452 gBS->HandleProtocol (
453 HandleBuffer[Index],
454 &gEfiDevicePathProtocolGuid,
455 (VOID **) &ConDevicePath
456 );
457 BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL);
458 BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL);
459 }
460
461 if (HandleBuffer != NULL) {
462 FreePool(HandleBuffer);
463 }
464
465 //
466 // Connect all console variables
467 //
468 BdsLibConnectAllDefaultConsoles ();
469
470 }
471
472 /**
473 This function will connect console device base on the console
474 device variable ConIn, ConOut and ErrOut.
475
476 @retval EFI_SUCCESS At least one of the ConIn and ConOut device have
477 been connected success.
478 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().
479
480 **/
481 EFI_STATUS
482 EFIAPI
483 BdsLibConnectAllDefaultConsoles (
484 VOID
485 )
486 {
487 EFI_STATUS Status;
488
489 //
490 // Connect all default console variables
491 //
492
493 //
494 // It seems impossible not to have any ConOut device on platform,
495 // so we check the status here.
496 //
497 Status = BdsLibConnectConsoleVariable (L"ConOut");
498 if (EFI_ERROR (Status)) {
499 return Status;
500 }
501
502 //
503 // Insert the performance probe for Console Out
504 //
505 PERF_START (NULL, "ConOut", "BDS", 1);
506 PERF_END (NULL, "ConOut", "BDS", 0);
507
508 //
509 // Because possibly the platform is legacy free, in such case,
510 // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,
511 // so we need not check the status.
512 //
513 BdsLibConnectConsoleVariable (L"ConIn");
514
515 //
516 // The _ModuleEntryPoint err out var is legal.
517 //
518 BdsLibConnectConsoleVariable (L"ErrOut");
519
520 //
521 // Fill console handles in System Table if no console device assignd.
522 //
523 UpdateSystemTableConsole (L"ConIn", &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **) &gST->ConIn);
524 UpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut);
525 UpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr);
526
527 return EFI_SUCCESS;
528
529 }
530
531 /**
532 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
533 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
534 buffer is passed in it will be used if it is big enough.
535
536 @param BmpImage Pointer to BMP file
537 @param BmpImageSize Number of bytes in BmpImage
538 @param GopBlt Buffer containing GOP version of BmpImage.
539 @param GopBltSize Size of GopBlt in bytes.
540 @param PixelHeight Height of GopBlt/BmpImage in pixels
541 @param PixelWidth Width of GopBlt/BmpImage in pixels
542
543 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
544 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
545 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
546 GopBltSize will contain the required size.
547 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
548
549 **/
550 EFI_STATUS
551 ConvertBmpToGopBlt (
552 IN VOID *BmpImage,
553 IN UINTN BmpImageSize,
554 IN OUT VOID **GopBlt,
555 IN OUT UINTN *GopBltSize,
556 OUT UINTN *PixelHeight,
557 OUT UINTN *PixelWidth
558 )
559 {
560 UINT8 *Image;
561 UINT8 *ImageHeader;
562 BMP_IMAGE_HEADER *BmpHeader;
563 BMP_COLOR_MAP *BmpColorMap;
564 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
565 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
566 UINTN BltBufferSize;
567 UINTN Index;
568 UINTN Height;
569 UINTN Width;
570 UINTN ImageIndex;
571 BOOLEAN IsAllocated;
572
573 BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
574
575 if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
576 return EFI_UNSUPPORTED;
577 }
578
579 //
580 // Doesn't support compress.
581 //
582 if (BmpHeader->CompressionType != 0) {
583 return EFI_UNSUPPORTED;
584 }
585
586 //
587 // Calculate Color Map offset in the image.
588 //
589 Image = BmpImage;
590 BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
591
592 //
593 // Calculate graphics image data address in the image
594 //
595 Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
596 ImageHeader = Image;
597
598 //
599 // Calculate the BltBuffer needed size.
600 //
601 BltBufferSize = BmpHeader->PixelWidth * BmpHeader->PixelHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
602 IsAllocated = FALSE;
603 if (*GopBlt == NULL) {
604 //
605 // GopBlt is not allocated by caller.
606 //
607 *GopBltSize = BltBufferSize;
608 *GopBlt = AllocatePool (*GopBltSize);
609 IsAllocated = TRUE;
610 if (*GopBlt == NULL) {
611 return EFI_OUT_OF_RESOURCES;
612 }
613 } else {
614 //
615 // GopBlt has been allocated by caller.
616 //
617 if (*GopBltSize < BltBufferSize) {
618 *GopBltSize = BltBufferSize;
619 return EFI_BUFFER_TOO_SMALL;
620 }
621 }
622
623 *PixelWidth = BmpHeader->PixelWidth;
624 *PixelHeight = BmpHeader->PixelHeight;
625
626 //
627 // Convert image from BMP to Blt buffer format
628 //
629 BltBuffer = *GopBlt;
630 for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
631 Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
632 for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
633 switch (BmpHeader->BitPerPixel) {
634 case 1:
635 //
636 // Convert 1-bit (2 colors) BMP to 24-bit color
637 //
638 for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
639 Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
640 Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
641 Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
642 Blt++;
643 Width++;
644 }
645
646 Blt--;
647 Width--;
648 break;
649
650 case 4:
651 //
652 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
653 //
654 Index = (*Image) >> 4;
655 Blt->Red = BmpColorMap[Index].Red;
656 Blt->Green = BmpColorMap[Index].Green;
657 Blt->Blue = BmpColorMap[Index].Blue;
658 if (Width < (BmpHeader->PixelWidth - 1)) {
659 Blt++;
660 Width++;
661 Index = (*Image) & 0x0f;
662 Blt->Red = BmpColorMap[Index].Red;
663 Blt->Green = BmpColorMap[Index].Green;
664 Blt->Blue = BmpColorMap[Index].Blue;
665 }
666 break;
667
668 case 8:
669 //
670 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
671 //
672 Blt->Red = BmpColorMap[*Image].Red;
673 Blt->Green = BmpColorMap[*Image].Green;
674 Blt->Blue = BmpColorMap[*Image].Blue;
675 break;
676
677 case 24:
678 //
679 // It is 24-bit BMP.
680 //
681 Blt->Blue = *Image++;
682 Blt->Green = *Image++;
683 Blt->Red = *Image;
684 break;
685
686 default:
687 //
688 // Other bit format BMP is not supported.
689 //
690 if (IsAllocated) {
691 FreePool (*GopBlt);
692 *GopBlt = NULL;
693 }
694 return EFI_UNSUPPORTED;
695 break;
696 };
697
698 }
699
700 ImageIndex = (UINTN) (Image - ImageHeader);
701 if ((ImageIndex % 4) != 0) {
702 //
703 // Bmp Image starts each row on a 32-bit boundary!
704 //
705 Image = Image + (4 - (ImageIndex % 4));
706 }
707 }
708
709 return EFI_SUCCESS;
710 }
711
712
713 /**
714 Use Console Control Protocol to lock the Console In Spliter virtual handle.
715 This is the ConInHandle and ConIn handle in the EFI system table. All key
716 presses will be ignored until the Password is typed in. The only way to
717 disable the password is to type it in to a ConIn device.
718
719 @param Password Password used to lock ConIn device.
720
721 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
722 @retval EFI_UNSUPPORTED Password not found
723
724 **/
725 EFI_STATUS
726 EFIAPI
727 LockKeyboards (
728 IN CHAR16 *Password
729 )
730 {
731 EFI_STATUS Status;
732 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
733
734 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
735 if (EFI_ERROR (Status)) {
736 return EFI_UNSUPPORTED;
737 }
738
739 Status = ConsoleControl->LockStdIn (ConsoleControl, Password);
740 return Status;
741 }
742
743
744 /**
745 Use Console Control to turn off UGA based Simple Text Out consoles from going
746 to the UGA device. Put up LogoFile on every UGA device that is a console
747
748 @param[in] LogoFile File name of logo to display on the center of the screen.
749
750 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
751 @retval EFI_UNSUPPORTED Logo not found
752
753 **/
754 EFI_STATUS
755 EFIAPI
756 EnableQuietBoot (
757 IN EFI_GUID *LogoFile
758 )
759 {
760 EFI_STATUS Status;
761 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
762 EFI_OEM_BADGING_PROTOCOL *Badging;
763 UINT32 SizeOfX;
764 UINT32 SizeOfY;
765 INTN DestX;
766 INTN DestY;
767 UINT8 *ImageData;
768 UINTN ImageSize;
769 UINTN BltSize;
770 UINT32 Instance;
771 EFI_BADGING_FORMAT Format;
772 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
773 UINTN CoordinateX;
774 UINTN CoordinateY;
775 UINTN Height;
776 UINTN Width;
777 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
778 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
779 UINT32 ColorDepth;
780 UINT32 RefreshRate;
781 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
782
783 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
784 if (EFI_ERROR (Status)) {
785 return EFI_UNSUPPORTED;
786 }
787
788 UgaDraw = NULL;
789 //
790 // Try to open GOP first
791 //
792 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
793 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
794 GraphicsOutput = NULL;
795 //
796 // Open GOP failed, try to open UGA
797 //
798 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
799 }
800 if (EFI_ERROR (Status)) {
801 return EFI_UNSUPPORTED;
802 }
803
804 Badging = NULL;
805 Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);
806
807 //
808 // Set console control to graphics mode.
809 //
810 Status = ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);
811 if (EFI_ERROR (Status)) {
812 return EFI_UNSUPPORTED;
813 }
814
815 if (GraphicsOutput != NULL) {
816 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
817 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
818
819 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
820 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
821 if (EFI_ERROR (Status)) {
822 return EFI_UNSUPPORTED;
823 }
824 } else {
825 return EFI_UNSUPPORTED;
826 }
827
828 Instance = 0;
829 while (1) {
830 ImageData = NULL;
831 ImageSize = 0;
832
833 if (Badging != NULL) {
834 //
835 // Get image from OEMBadging protocol.
836 //
837 Status = Badging->GetImage (
838 Badging,
839 &Instance,
840 &Format,
841 &ImageData,
842 &ImageSize,
843 &Attribute,
844 &CoordinateX,
845 &CoordinateY
846 );
847 if (EFI_ERROR (Status)) {
848 return Status;
849 }
850
851 //
852 // Currently only support BMP format.
853 //
854 if (Format != EfiBadgingFormatBMP) {
855 if (ImageData != NULL) {
856 FreePool (ImageData);
857 }
858 continue;
859 }
860 } else {
861 //
862 // Get the specified image from FV.
863 //
864 Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);
865 if (EFI_ERROR (Status)) {
866 return EFI_UNSUPPORTED;
867 }
868
869 CoordinateX = 0;
870 CoordinateY = 0;
871 Attribute = EfiBadgingDisplayAttributeCenter;
872 }
873
874 Blt = NULL;
875 Status = ConvertBmpToGopBlt (
876 ImageData,
877 ImageSize,
878 (VOID **) &Blt,
879 &BltSize,
880 &Height,
881 &Width
882 );
883 if (EFI_ERROR (Status)) {
884 FreePool (ImageData);
885
886 if (Badging == NULL) {
887 return Status;
888 } else {
889 continue;
890 }
891 }
892
893 //
894 // Calculate the display position according to Attribute.
895 //
896 switch (Attribute) {
897 case EfiBadgingDisplayAttributeLeftTop:
898 DestX = CoordinateX;
899 DestY = CoordinateY;
900 break;
901
902 case EfiBadgingDisplayAttributeCenterTop:
903 DestX = (SizeOfX - Width) / 2;
904 DestY = CoordinateY;
905 break;
906
907 case EfiBadgingDisplayAttributeRightTop:
908 DestX = (SizeOfX - Width - CoordinateX);
909 DestY = CoordinateY;;
910 break;
911
912 case EfiBadgingDisplayAttributeCenterRight:
913 DestX = (SizeOfX - Width - CoordinateX);
914 DestY = (SizeOfY - Height) / 2;
915 break;
916
917 case EfiBadgingDisplayAttributeRightBottom:
918 DestX = (SizeOfX - Width - CoordinateX);
919 DestY = (SizeOfY - Height - CoordinateY);
920 break;
921
922 case EfiBadgingDisplayAttributeCenterBottom:
923 DestX = (SizeOfX - Width) / 2;
924 DestY = (SizeOfY - Height - CoordinateY);
925 break;
926
927 case EfiBadgingDisplayAttributeLeftBottom:
928 DestX = CoordinateX;
929 DestY = (SizeOfY - Height - CoordinateY);
930 break;
931
932 case EfiBadgingDisplayAttributeCenterLeft:
933 DestX = CoordinateX;
934 DestY = (SizeOfY - Height) / 2;
935 break;
936
937 case EfiBadgingDisplayAttributeCenter:
938 DestX = (SizeOfX - Width) / 2;
939 DestY = (SizeOfY - Height) / 2;
940 break;
941
942 default:
943 DestX = CoordinateX;
944 DestY = CoordinateY;
945 break;
946 }
947
948 if ((DestX >= 0) && (DestY >= 0)) {
949 if (GraphicsOutput != NULL) {
950 Status = GraphicsOutput->Blt (
951 GraphicsOutput,
952 Blt,
953 EfiBltBufferToVideo,
954 0,
955 0,
956 (UINTN) DestX,
957 (UINTN) DestY,
958 Width,
959 Height,
960 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
961 );
962 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
963 Status = UgaDraw->Blt (
964 UgaDraw,
965 (EFI_UGA_PIXEL *) Blt,
966 EfiUgaBltBufferToVideo,
967 0,
968 0,
969 (UINTN) DestX,
970 (UINTN) DestY,
971 Width,
972 Height,
973 Width * sizeof (EFI_UGA_PIXEL)
974 );
975 } else {
976 Status = EFI_UNSUPPORTED;
977 }
978 }
979
980 FreePool (ImageData);
981
982 if (Blt != NULL) {
983 FreePool (Blt);
984 }
985
986 if (Badging == NULL) {
987 break;
988 }
989 }
990
991 return Status;
992 }
993
994 /**
995 Use Console Control to turn on UGA based Simple Text Out consoles. The UGA
996 Simple Text Out screens will now be synced up with all non UGA output devices
997
998 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
999
1000 **/
1001 EFI_STATUS
1002 EFIAPI
1003 DisableQuietBoot (
1004 VOID
1005 )
1006 {
1007 EFI_STATUS Status;
1008 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
1009
1010 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
1011 if (EFI_ERROR (Status)) {
1012 return EFI_UNSUPPORTED;
1013 }
1014
1015 //
1016 // Set console control to text mode.
1017 //
1018 return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
1019 }
1020