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