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