]> git.proxmox.com Git - mirror_edk2.git/blob - Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c
2fffd9e4bcfa7038afdf00a8bdbf3a277e08dc80
[mirror_edk2.git] / Vlv2TbltDevicePkg / Override / 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 //
566 // If any component set PcdTestKeyUsed to TRUE because use of a test key
567 // was detected, then display a warning message on the debug log and the console
568 //
569 if (PcdGetBool (PcdTestKeyUsed) == TRUE) {
570 DEBUG ((DEBUG_ERROR, "**********************************\n"));
571 DEBUG ((DEBUG_ERROR, "** WARNING: Test Key is used. **\n"));
572 DEBUG ((DEBUG_ERROR, "**********************************\n"));
573 Print (L"** WARNING: Test Key is used. **\n");
574 }
575
576 return EFI_SUCCESS;
577
578 }
579
580 /**
581 This function will connect console device except ConIn base on the console
582 device variable ConOut and ErrOut.
583
584 @retval EFI_SUCCESS At least one of the ConOut device have
585 been connected success.
586 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().
587
588 **/
589 EFI_STATUS
590 EFIAPI
591 BdsLibConnectAllDefaultConsolesWithOutConIn (
592 VOID
593 )
594 {
595 EFI_STATUS Status;
596 BOOLEAN SystemTableUpdated;
597
598 //
599 // Connect all default console variables except ConIn
600 //
601
602 //
603 // It seems impossible not to have any ConOut device on platform,
604 // so we check the status here.
605 //
606 Status = BdsLibConnectConsoleVariable (L"ConOut");
607 if (EFI_ERROR (Status)) {
608 return Status;
609 }
610
611 //
612 // Insert the performance probe for Console Out
613 //
614 PERF_START (NULL, "ConOut", "BDS", 1);
615 PERF_END (NULL, "ConOut", "BDS", 0);
616
617 //
618 // The _ModuleEntryPoint err out var is legal.
619 //
620 BdsLibConnectConsoleVariable (L"ErrOut");
621
622 SystemTableUpdated = FALSE;
623 //
624 // Fill console handles in System Table if no console device assignd.
625 //
626 if (UpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) {
627 SystemTableUpdated = TRUE;
628 }
629 if (UpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) {
630 SystemTableUpdated = TRUE;
631 }
632
633 if (SystemTableUpdated) {
634 //
635 // Update the CRC32 in the EFI System Table header
636 //
637 gST->Hdr.CRC32 = 0;
638 gBS->CalculateCrc32 (
639 (UINT8 *) &gST->Hdr,
640 gST->Hdr.HeaderSize,
641 &gST->Hdr.CRC32
642 );
643 }
644
645 return EFI_SUCCESS;
646
647 }
648
649 /**
650 Use SystemTable Conout to stop video based Simple Text Out consoles from going
651 to the video device. Put up LogoFile on every video device that is a console.
652
653 @param[in] LogoFile File name of logo to display on the center of the screen.
654
655 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
656 @retval EFI_UNSUPPORTED Logo not found
657
658 **/
659 EFI_STATUS
660 EFIAPI
661 EnableQuietBoot (
662 IN EFI_GUID *LogoFile
663 )
664 {
665 EFI_STATUS Status;
666 EFI_OEM_BADGING_PROTOCOL *Badging;
667 UINT32 SizeOfX;
668 UINT32 SizeOfY;
669 INTN DestX;
670 INTN DestY;
671 UINT8 *ImageData;
672 UINTN ImageSize;
673 UINTN BltSize;
674 UINT32 Instance;
675 EFI_BADGING_FORMAT Format;
676 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
677 UINTN CoordinateX;
678 UINTN CoordinateY;
679 UINTN Height;
680 UINTN Width;
681 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
682 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
683 UINT32 ColorDepth;
684 UINT32 RefreshRate;
685 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
686 EFI_BOOT_LOGO_PROTOCOL *BootLogo;
687 UINTN NumberOfLogos;
688 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt;
689 UINTN LogoDestX;
690 UINTN LogoDestY;
691 UINTN LogoHeight;
692 UINTN LogoWidth;
693 UINTN NewDestX;
694 UINTN NewDestY;
695 UINTN NewHeight;
696 UINTN NewWidth;
697 UINT64 BufferSize;
698
699 UgaDraw = NULL;
700 //
701 // Try to open GOP first
702 //
703 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
704 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
705 GraphicsOutput = NULL;
706 //
707 // Open GOP failed, try to open UGA
708 //
709 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
710 }
711 if (EFI_ERROR (Status)) {
712 return EFI_UNSUPPORTED;
713 }
714
715 //
716 // Try to open Boot Logo Protocol.
717 //
718 BootLogo = NULL;
719 gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
720
721 //
722 // Erase Cursor from screen
723 //
724 gST->ConOut->EnableCursor (gST->ConOut, FALSE);
725
726 Badging = NULL;
727 Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);
728
729 if (GraphicsOutput != NULL) {
730 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
731 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
732
733 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
734 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
735 if (EFI_ERROR (Status)) {
736 return EFI_UNSUPPORTED;
737 }
738 } else {
739 return EFI_UNSUPPORTED;
740 }
741
742 Blt = NULL;
743 NumberOfLogos = 0;
744 LogoDestX = 0;
745 LogoDestY = 0;
746 LogoHeight = 0;
747 LogoWidth = 0;
748 NewDestX = 0;
749 NewDestY = 0;
750 NewHeight = 0;
751 NewWidth = 0;
752 Instance = 0;
753 while (1) {
754 ImageData = NULL;
755 ImageSize = 0;
756
757 if (Badging != NULL) {
758 //
759 // Get image from OEMBadging protocol.
760 //
761 Status = Badging->GetImage (
762 Badging,
763 &Instance,
764 &Format,
765 &ImageData,
766 &ImageSize,
767 &Attribute,
768 &CoordinateX,
769 &CoordinateY
770 );
771 if (EFI_ERROR (Status)) {
772 goto Done;
773 }
774
775 //
776 // Currently only support BMP format.
777 //
778 if (Format != EfiBadgingFormatBMP) {
779 if (ImageData != NULL) {
780 FreePool (ImageData);
781 }
782 continue;
783 }
784 } else {
785 //
786 // Get the specified image from FV.
787 //
788 Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);
789 if (EFI_ERROR (Status)) {
790 return EFI_UNSUPPORTED;
791 }
792
793 CoordinateX = 0;
794 CoordinateY = 0;
795 if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {
796 Attribute = EfiBadgingDisplayAttributeCenter;
797 } else {
798 Attribute = EfiBadgingDisplayAttributeCustomized;
799 }
800 }
801
802 if (Blt != NULL) {
803 FreePool (Blt);
804 }
805 Blt = NULL;
806 Status = TranslateBmpToGopBlt (
807 ImageData,
808 ImageSize,
809 &Blt,
810 &BltSize,
811 &Height,
812 &Width
813 );
814 if (EFI_ERROR (Status)) {
815 FreePool (ImageData);
816
817 if (Badging == NULL) {
818 return Status;
819 } else {
820 continue;
821 }
822 }
823
824 //
825 // Calculate the display position according to Attribute.
826 //
827 switch (Attribute) {
828 case EfiBadgingDisplayAttributeLeftTop:
829 DestX = CoordinateX;
830 DestY = CoordinateY;
831 break;
832
833 case EfiBadgingDisplayAttributeCenterTop:
834 DestX = (SizeOfX - Width) / 2;
835 DestY = CoordinateY;
836 break;
837
838 case EfiBadgingDisplayAttributeRightTop:
839 DestX = (SizeOfX - Width - CoordinateX);
840 DestY = CoordinateY;;
841 break;
842
843 case EfiBadgingDisplayAttributeCenterRight:
844 DestX = (SizeOfX - Width - CoordinateX);
845 DestY = (SizeOfY - Height) / 2;
846 break;
847
848 case EfiBadgingDisplayAttributeRightBottom:
849 DestX = (SizeOfX - Width - CoordinateX);
850 DestY = (SizeOfY - Height - CoordinateY);
851 break;
852
853 case EfiBadgingDisplayAttributeCenterBottom:
854 DestX = (SizeOfX - Width) / 2;
855 DestY = (SizeOfY - Height - CoordinateY);
856 break;
857
858 case EfiBadgingDisplayAttributeLeftBottom:
859 DestX = CoordinateX;
860 DestY = (SizeOfY - Height - CoordinateY);
861 break;
862
863 case EfiBadgingDisplayAttributeCenterLeft:
864 DestX = CoordinateX;
865 DestY = (SizeOfY - Height) / 2;
866 break;
867
868 case EfiBadgingDisplayAttributeCenter:
869 DestX = (SizeOfX - Width) / 2;
870 DestY = (SizeOfY - Height) / 2;
871 break;
872
873 case EfiBadgingDisplayAttributeCustomized:
874 DestX = (SizeOfX - Width) / 2;
875 DestY = ((SizeOfY * 382) / 1000) - Height / 2;
876 break;
877
878 default:
879 DestX = CoordinateX;
880 DestY = CoordinateY;
881 break;
882 }
883
884 if ((DestX >= 0) && (DestY >= 0)) {
885 if (GraphicsOutput != NULL) {
886 Status = GraphicsOutput->Blt (
887 GraphicsOutput,
888 Blt,
889 EfiBltBufferToVideo,
890 0,
891 0,
892 (UINTN) DestX,
893 (UINTN) DestY,
894 Width,
895 Height,
896 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
897 );
898 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
899 Status = UgaDraw->Blt (
900 UgaDraw,
901 (EFI_UGA_PIXEL *) Blt,
902 EfiUgaBltBufferToVideo,
903 0,
904 0,
905 (UINTN) DestX,
906 (UINTN) DestY,
907 Width,
908 Height,
909 Width * sizeof (EFI_UGA_PIXEL)
910 );
911 } else {
912 Status = EFI_UNSUPPORTED;
913 }
914
915 //
916 // Report displayed Logo information.
917 //
918 if (!EFI_ERROR (Status)) {
919 NumberOfLogos++;
920
921 if (LogoWidth == 0) {
922 //
923 // The first Logo.
924 //
925 LogoDestX = (UINTN) DestX;
926 LogoDestY = (UINTN) DestY;
927 LogoWidth = Width;
928 LogoHeight = Height;
929 } else {
930 //
931 // Merge new logo with old one.
932 //
933 NewDestX = MIN ((UINTN) DestX, LogoDestX);
934 NewDestY = MIN ((UINTN) DestY, LogoDestY);
935 NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX;
936 NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY;
937
938 LogoDestX = NewDestX;
939 LogoDestY = NewDestY;
940 LogoWidth = NewWidth;
941 LogoHeight = NewHeight;
942 }
943 }
944 }
945
946 FreePool (ImageData);
947
948 if (Badging == NULL) {
949 break;
950 }
951 }
952
953 Done:
954 if (BootLogo == NULL || NumberOfLogos == 0) {
955 //
956 // No logo displayed.
957 //
958 if (Blt != NULL) {
959 FreePool (Blt);
960 }
961
962 return Status;
963 }
964
965 //
966 // Advertise displayed Logo information.
967 //
968 if (NumberOfLogos == 1) {
969 //
970 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.
971 //
972 LogoBlt = Blt;
973 Status = EFI_SUCCESS;
974 } else {
975 //
976 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.
977 //
978 if (Blt != NULL) {
979 FreePool (Blt);
980 }
981
982 //
983 // Ensure the LogoHeight * LogoWidth doesn't overflow
984 //
985 if (LogoHeight > DivU64x64Remainder ((UINTN) ~0, LogoWidth, NULL)) {
986 return EFI_UNSUPPORTED;
987 }
988 BufferSize = MultU64x64 (LogoWidth, LogoHeight);
989
990 //
991 // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
992 //
993 if (BufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
994 return EFI_UNSUPPORTED;
995 }
996
997 LogoBlt = AllocateZeroPool ((UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
998 if (LogoBlt == NULL) {
999 return EFI_OUT_OF_RESOURCES;
1000 }
1001
1002 if (GraphicsOutput != NULL) {
1003 Status = GraphicsOutput->Blt (
1004 GraphicsOutput,
1005 LogoBlt,
1006 EfiBltVideoToBltBuffer,
1007 LogoDestX,
1008 LogoDestY,
1009 0,
1010 0,
1011 LogoWidth,
1012 LogoHeight,
1013 LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1014 );
1015 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
1016 Status = UgaDraw->Blt (
1017 UgaDraw,
1018 (EFI_UGA_PIXEL *) LogoBlt,
1019 EfiUgaVideoToBltBuffer,
1020 LogoDestX,
1021 LogoDestY,
1022 0,
1023 0,
1024 LogoWidth,
1025 LogoHeight,
1026 LogoWidth * sizeof (EFI_UGA_PIXEL)
1027 );
1028 } else {
1029 Status = EFI_UNSUPPORTED;
1030 }
1031 }
1032
1033 if (!EFI_ERROR (Status)) {
1034 BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight);
1035 }
1036 FreePool (LogoBlt);
1037
1038 return Status;
1039 }
1040
1041 /**
1042 Use SystemTable Conout to turn on video based Simple Text Out consoles. The
1043 Simple Text Out screens will now be synced up with all non video output devices
1044
1045 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
1046
1047 **/
1048 EFI_STATUS
1049 EFIAPI
1050 DisableQuietBoot (
1051 VOID
1052 )
1053 {
1054
1055 //
1056 // Enable Cursor on Screen
1057 //
1058 gST->ConOut->EnableCursor (gST->ConOut, TRUE);
1059 return EFI_SUCCESS;
1060 }
1061