]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c
Add return status check for SetVariable.
[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 - 2011, Intel Corporation. All rights reserved.<BR>
5 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 If ConVarName is NULL, then ASSERT().
22
23 @param ConVarName The name of the EFI variable.
24
25 @retval TRUE Set the EFI variable as NV type.
26 @retval FALSE EFI variable as NV type can be set NonNV.
27 **/
28 BOOLEAN
29 IsNvNeed (
30 IN CHAR16 *ConVarName
31 )
32 {
33 CHAR16 *Ptr;
34
35 ASSERT (ConVarName != NULL);
36
37 Ptr = ConVarName;
38
39 //
40 // If the variable includes "Dev" at last, we consider
41 // it does not support NV attribute.
42 //
43 while (*Ptr != L'\0') {
44 Ptr++;
45 }
46
47 if (((INTN)((UINTN)Ptr - (UINTN)ConVarName) / sizeof (CHAR16)) <= 3) {
48 return TRUE;
49 }
50
51 if ((*(Ptr - 3) == 'D') && (*(Ptr - 2) == 'e') && (*(Ptr - 1) == 'v')) {
52 return FALSE;
53 } else {
54 return TRUE;
55 }
56 }
57
58 /**
59 Fill console handle in System Table if there are no valid console handle in.
60
61 Firstly, check the validation of console handle in System Table. If it is invalid,
62 update it by the first console device handle from EFI console variable.
63
64 @param VarName The name of the EFI console variable.
65 @param ConsoleGuid Specified Console protocol GUID.
66 @param ConsoleHandle On IN, console handle in System Table to be checked.
67 On OUT, new console hanlde in system table.
68 @param ProtocolInterface On IN, console protocol on console handle in System Table to be checked.
69 On OUT, new console protocol on new console hanlde in system table.
70
71 @retval TRUE System Table has been updated.
72 @retval FALSE System Table hasn't been updated.
73
74 **/
75 BOOLEAN
76 UpdateSystemTableConsole (
77 IN CHAR16 *VarName,
78 IN EFI_GUID *ConsoleGuid,
79 IN OUT EFI_HANDLE *ConsoleHandle,
80 IN OUT VOID **ProtocolInterface
81 )
82 {
83 EFI_STATUS Status;
84 UINTN DevicePathSize;
85 EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;
86 EFI_DEVICE_PATH_PROTOCOL *VarConsole;
87 EFI_DEVICE_PATH_PROTOCOL *Instance;
88 VOID *Interface;
89 EFI_HANDLE NewHandle;
90
91 ASSERT (VarName != NULL);
92 ASSERT (ConsoleHandle != NULL);
93 ASSERT (ConsoleGuid != NULL);
94 ASSERT (ProtocolInterface != NULL);
95
96 if (*ConsoleHandle != NULL) {
97 Status = gBS->HandleProtocol (
98 *ConsoleHandle,
99 ConsoleGuid,
100 &Interface
101 );
102 if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) {
103 //
104 // If ConsoleHandle is valid and console protocol on this handle also
105 // also matched, just return.
106 //
107 return FALSE;
108 }
109 }
110
111 //
112 // Get all possible consoles device path from EFI variable
113 //
114 VarConsole = BdsLibGetVariableAndSize (
115 VarName,
116 &gEfiGlobalVariableGuid,
117 &DevicePathSize
118 );
119 if (VarConsole == NULL) {
120 //
121 // If there is no any console device, just return.
122 //
123 return FALSE;
124 }
125
126 FullDevicePath = VarConsole;
127
128 do {
129 //
130 // Check every instance of the console variable
131 //
132 Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);
133 if (Instance == NULL) {
134 FreePool (FullDevicePath);
135 ASSERT (FALSE);
136 }
137
138 //
139 // Find console device handle by device path instance
140 //
141 Status = gBS->LocateDevicePath (
142 ConsoleGuid,
143 &Instance,
144 &NewHandle
145 );
146 if (!EFI_ERROR (Status)) {
147 //
148 // Get the console protocol on this console device handle
149 //
150 Status = gBS->HandleProtocol (
151 NewHandle,
152 ConsoleGuid,
153 &Interface
154 );
155 if (!EFI_ERROR (Status)) {
156 //
157 // Update new console handle in System Table.
158 //
159 *ConsoleHandle = NewHandle;
160 *ProtocolInterface = Interface;
161 return TRUE;
162 }
163 }
164
165 } while (Instance != NULL);
166
167 //
168 // No any available console devcie found.
169 //
170 return FALSE;
171 }
172
173 /**
174 This function update console variable based on ConVarName, it can
175 add or remove one specific console device path from the variable
176
177 @param ConVarName Console related variable name, ConIn, ConOut,
178 ErrOut.
179 @param CustomizedConDevicePath The console device path which will be added to
180 the console variable ConVarName, this parameter
181 can not be multi-instance.
182 @param ExclusiveDevicePath The console device path which will be removed
183 from the console variable ConVarName, this
184 parameter can not be multi-instance.
185
186 @retval EFI_UNSUPPORTED The added device path is same to the removed one.
187 @retval EFI_SUCCESS Success add or remove the device path from the
188 console variable.
189
190 **/
191 EFI_STATUS
192 EFIAPI
193 BdsLibUpdateConsoleVariable (
194 IN CHAR16 *ConVarName,
195 IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,
196 IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath
197 )
198 {
199 EFI_STATUS Status;
200 EFI_DEVICE_PATH_PROTOCOL *VarConsole;
201 UINTN DevicePathSize;
202 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
203 EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
204 UINT32 Attributes;
205
206 VarConsole = NULL;
207 DevicePathSize = 0;
208
209 //
210 // Notes: check the device path point, here should check
211 // with compare memory
212 //
213 if (CustomizedConDevicePath == ExclusiveDevicePath) {
214 return EFI_UNSUPPORTED;
215 }
216 //
217 // Delete the ExclusiveDevicePath from current default console
218 //
219 VarConsole = BdsLibGetVariableAndSize (
220 ConVarName,
221 &gEfiGlobalVariableGuid,
222 &DevicePathSize
223 );
224
225 //
226 // Initialize NewDevicePath
227 //
228 NewDevicePath = VarConsole;
229
230 //
231 // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.
232 // In the end, NewDevicePath is the final device path.
233 //
234 if (ExclusiveDevicePath != NULL && VarConsole != NULL) {
235 NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath);
236 }
237 //
238 // Try to append customized device path to NewDevicePath.
239 //
240 if (CustomizedConDevicePath != NULL) {
241 if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {
242 //
243 // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.
244 //
245 NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);
246 //
247 // In the first check, the default console variable will be _ModuleEntryPoint,
248 // just append current customized device path
249 //
250 TempNewDevicePath = NewDevicePath;
251 NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);
252 if (TempNewDevicePath != NULL) {
253 FreePool(TempNewDevicePath);
254 }
255 }
256 }
257
258 //
259 // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.
260 //
261 if (IsNvNeed(ConVarName)) {
262 //
263 // ConVarName has NV attribute.
264 //
265 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
266 } else {
267 //
268 // ConVarName does not have NV attribute.
269 //
270 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
271 }
272
273 //
274 // Finally, Update the variable of the default console by NewDevicePath
275 //
276 Status = gRT->SetVariable (
277 ConVarName,
278 &gEfiGlobalVariableGuid,
279 Attributes,
280 GetDevicePathSize (NewDevicePath),
281 NewDevicePath
282 );
283 ASSERT_EFI_ERROR (Status);
284
285 if (VarConsole == NewDevicePath) {
286 if (VarConsole != NULL) {
287 FreePool(VarConsole);
288 }
289 } else {
290 if (VarConsole != NULL) {
291 FreePool(VarConsole);
292 }
293 if (NewDevicePath != NULL) {
294 FreePool(NewDevicePath);
295 }
296 }
297
298 return EFI_SUCCESS;
299
300 }
301
302
303 /**
304 Connect the console device base on the variable ConVarName, if
305 device path of the ConVarName is multi-instance device path, if
306 anyone of the instances is connected success, then this function
307 will return success.
308
309 @param ConVarName Console related variable name, ConIn, ConOut,
310 ErrOut.
311
312 @retval EFI_NOT_FOUND There is not any console devices connected
313 success
314 @retval EFI_SUCCESS Success connect any one instance of the console
315 device path base on the variable ConVarName.
316
317 **/
318 EFI_STATUS
319 EFIAPI
320 BdsLibConnectConsoleVariable (
321 IN CHAR16 *ConVarName
322 )
323 {
324 EFI_STATUS Status;
325 EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;
326 UINTN VariableSize;
327 EFI_DEVICE_PATH_PROTOCOL *Instance;
328 EFI_DEVICE_PATH_PROTOCOL *Next;
329 EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;
330 UINTN Size;
331 BOOLEAN DeviceExist;
332
333 Status = EFI_SUCCESS;
334 DeviceExist = FALSE;
335
336 //
337 // Check if the console variable exist
338 //
339 StartDevicePath = BdsLibGetVariableAndSize (
340 ConVarName,
341 &gEfiGlobalVariableGuid,
342 &VariableSize
343 );
344 if (StartDevicePath == NULL) {
345 return EFI_UNSUPPORTED;
346 }
347
348 CopyOfDevicePath = StartDevicePath;
349 do {
350 //
351 // Check every instance of the console variable
352 //
353 Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);
354 if (Instance == NULL) {
355 FreePool (StartDevicePath);
356 return EFI_UNSUPPORTED;
357 }
358
359 Next = Instance;
360 while (!IsDevicePathEndType (Next)) {
361 Next = NextDevicePathNode (Next);
362 }
363
364 SetDevicePathEndNode (Next);
365 //
366 // Connect the USB console
367 // USB console device path is a short-form device path that
368 // starts with the first element being a USB WWID
369 // or a USB Class device path
370 //
371 if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&
372 ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP)
373 || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)
374 )) {
375 Status = BdsLibConnectUsbDevByShortFormDP (0xFF, 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 = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
630 //
631 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
632 //
633 if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
634 return EFI_UNSUPPORTED;
635 }
636 BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
637
638 IsAllocated = FALSE;
639 if (*GopBlt == NULL) {
640 //
641 // GopBlt is not allocated by caller.
642 //
643 *GopBltSize = (UINTN) BltBufferSize;
644 *GopBlt = AllocatePool (*GopBltSize);
645 IsAllocated = TRUE;
646 if (*GopBlt == NULL) {
647 return EFI_OUT_OF_RESOURCES;
648 }
649 } else {
650 //
651 // GopBlt has been allocated by caller.
652 //
653 if (*GopBltSize < (UINTN) BltBufferSize) {
654 *GopBltSize = (UINTN) BltBufferSize;
655 return EFI_BUFFER_TOO_SMALL;
656 }
657 }
658
659 *PixelWidth = BmpHeader->PixelWidth;
660 *PixelHeight = BmpHeader->PixelHeight;
661
662 //
663 // Convert image from BMP to Blt buffer format
664 //
665 BltBuffer = *GopBlt;
666 for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
667 Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
668 for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
669 switch (BmpHeader->BitPerPixel) {
670 case 1:
671 //
672 // Convert 1-bit (2 colors) BMP to 24-bit color
673 //
674 for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
675 Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
676 Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
677 Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
678 Blt++;
679 Width++;
680 }
681
682 Blt--;
683 Width--;
684 break;
685
686 case 4:
687 //
688 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
689 //
690 Index = (*Image) >> 4;
691 Blt->Red = BmpColorMap[Index].Red;
692 Blt->Green = BmpColorMap[Index].Green;
693 Blt->Blue = BmpColorMap[Index].Blue;
694 if (Width < (BmpHeader->PixelWidth - 1)) {
695 Blt++;
696 Width++;
697 Index = (*Image) & 0x0f;
698 Blt->Red = BmpColorMap[Index].Red;
699 Blt->Green = BmpColorMap[Index].Green;
700 Blt->Blue = BmpColorMap[Index].Blue;
701 }
702 break;
703
704 case 8:
705 //
706 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
707 //
708 Blt->Red = BmpColorMap[*Image].Red;
709 Blt->Green = BmpColorMap[*Image].Green;
710 Blt->Blue = BmpColorMap[*Image].Blue;
711 break;
712
713 case 24:
714 //
715 // It is 24-bit BMP.
716 //
717 Blt->Blue = *Image++;
718 Blt->Green = *Image++;
719 Blt->Red = *Image;
720 break;
721
722 default:
723 //
724 // Other bit format BMP is not supported.
725 //
726 if (IsAllocated) {
727 FreePool (*GopBlt);
728 *GopBlt = NULL;
729 }
730 return EFI_UNSUPPORTED;
731 break;
732 };
733
734 }
735
736 ImageIndex = (UINTN) (Image - ImageHeader);
737 if ((ImageIndex % 4) != 0) {
738 //
739 // Bmp Image starts each row on a 32-bit boundary!
740 //
741 Image = Image + (4 - (ImageIndex % 4));
742 }
743 }
744
745 return EFI_SUCCESS;
746 }
747
748 /**
749 Use SystemTable Conout to stop video based Simple Text Out consoles from going
750 to the video device. Put up LogoFile on every video device that is a console.
751
752 @param[in] LogoFile File name of logo to display on the center of the screen.
753
754 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
755 @retval EFI_UNSUPPORTED Logo not found
756
757 **/
758 EFI_STATUS
759 EFIAPI
760 EnableQuietBoot (
761 IN EFI_GUID *LogoFile
762 )
763 {
764 EFI_STATUS Status;
765 EFI_OEM_BADGING_PROTOCOL *Badging;
766 UINT32 SizeOfX;
767 UINT32 SizeOfY;
768 INTN DestX;
769 INTN DestY;
770 UINT8 *ImageData;
771 UINTN ImageSize;
772 UINTN BltSize;
773 UINT32 Instance;
774 EFI_BADGING_FORMAT Format;
775 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
776 UINTN CoordinateX;
777 UINTN CoordinateY;
778 UINTN Height;
779 UINTN Width;
780 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
781 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
782 UINT32 ColorDepth;
783 UINT32 RefreshRate;
784 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
785
786 UgaDraw = NULL;
787 //
788 // Try to open GOP first
789 //
790 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
791 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
792 GraphicsOutput = NULL;
793 //
794 // Open GOP failed, try to open UGA
795 //
796 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
797 }
798 if (EFI_ERROR (Status)) {
799 return EFI_UNSUPPORTED;
800 }
801
802 //
803 // Erase Cursor from screen
804 //
805 gST->ConOut->EnableCursor (gST->ConOut, FALSE);
806
807 Badging = NULL;
808 Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);
809
810 if (GraphicsOutput != NULL) {
811 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
812 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
813
814 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
815 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
816 if (EFI_ERROR (Status)) {
817 return EFI_UNSUPPORTED;
818 }
819 } else {
820 return EFI_UNSUPPORTED;
821 }
822
823 Instance = 0;
824 while (1) {
825 ImageData = NULL;
826 ImageSize = 0;
827
828 if (Badging != NULL) {
829 //
830 // Get image from OEMBadging protocol.
831 //
832 Status = Badging->GetImage (
833 Badging,
834 &Instance,
835 &Format,
836 &ImageData,
837 &ImageSize,
838 &Attribute,
839 &CoordinateX,
840 &CoordinateY
841 );
842 if (EFI_ERROR (Status)) {
843 return Status;
844 }
845
846 //
847 // Currently only support BMP format.
848 //
849 if (Format != EfiBadgingFormatBMP) {
850 if (ImageData != NULL) {
851 FreePool (ImageData);
852 }
853 continue;
854 }
855 } else {
856 //
857 // Get the specified image from FV.
858 //
859 Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);
860 if (EFI_ERROR (Status)) {
861 return EFI_UNSUPPORTED;
862 }
863
864 CoordinateX = 0;
865 CoordinateY = 0;
866 Attribute = EfiBadgingDisplayAttributeCenter;
867 }
868
869 Blt = NULL;
870 Status = ConvertBmpToGopBlt (
871 ImageData,
872 ImageSize,
873 (VOID **) &Blt,
874 &BltSize,
875 &Height,
876 &Width
877 );
878 if (EFI_ERROR (Status)) {
879 FreePool (ImageData);
880
881 if (Badging == NULL) {
882 return Status;
883 } else {
884 continue;
885 }
886 }
887
888 //
889 // Calculate the display position according to Attribute.
890 //
891 switch (Attribute) {
892 case EfiBadgingDisplayAttributeLeftTop:
893 DestX = CoordinateX;
894 DestY = CoordinateY;
895 break;
896
897 case EfiBadgingDisplayAttributeCenterTop:
898 DestX = (SizeOfX - Width) / 2;
899 DestY = CoordinateY;
900 break;
901
902 case EfiBadgingDisplayAttributeRightTop:
903 DestX = (SizeOfX - Width - CoordinateX);
904 DestY = CoordinateY;;
905 break;
906
907 case EfiBadgingDisplayAttributeCenterRight:
908 DestX = (SizeOfX - Width - CoordinateX);
909 DestY = (SizeOfY - Height) / 2;
910 break;
911
912 case EfiBadgingDisplayAttributeRightBottom:
913 DestX = (SizeOfX - Width - CoordinateX);
914 DestY = (SizeOfY - Height - CoordinateY);
915 break;
916
917 case EfiBadgingDisplayAttributeCenterBottom:
918 DestX = (SizeOfX - Width) / 2;
919 DestY = (SizeOfY - Height - CoordinateY);
920 break;
921
922 case EfiBadgingDisplayAttributeLeftBottom:
923 DestX = CoordinateX;
924 DestY = (SizeOfY - Height - CoordinateY);
925 break;
926
927 case EfiBadgingDisplayAttributeCenterLeft:
928 DestX = CoordinateX;
929 DestY = (SizeOfY - Height) / 2;
930 break;
931
932 case EfiBadgingDisplayAttributeCenter:
933 DestX = (SizeOfX - Width) / 2;
934 DestY = (SizeOfY - Height) / 2;
935 break;
936
937 default:
938 DestX = CoordinateX;
939 DestY = CoordinateY;
940 break;
941 }
942
943 if ((DestX >= 0) && (DestY >= 0)) {
944 if (GraphicsOutput != NULL) {
945 Status = GraphicsOutput->Blt (
946 GraphicsOutput,
947 Blt,
948 EfiBltBufferToVideo,
949 0,
950 0,
951 (UINTN) DestX,
952 (UINTN) DestY,
953 Width,
954 Height,
955 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
956 );
957 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
958 Status = UgaDraw->Blt (
959 UgaDraw,
960 (EFI_UGA_PIXEL *) Blt,
961 EfiUgaBltBufferToVideo,
962 0,
963 0,
964 (UINTN) DestX,
965 (UINTN) DestY,
966 Width,
967 Height,
968 Width * sizeof (EFI_UGA_PIXEL)
969 );
970 } else {
971 Status = EFI_UNSUPPORTED;
972 }
973 }
974
975 FreePool (ImageData);
976
977 if (Blt != NULL) {
978 FreePool (Blt);
979 }
980
981 if (Badging == NULL) {
982 break;
983 }
984 }
985
986 return Status;
987 }
988
989 /**
990 Use SystemTable Conout to turn on video based Simple Text Out consoles. The
991 Simple Text Out screens will now be synced up with all non video output devices
992
993 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
994
995 **/
996 EFI_STATUS
997 EFIAPI
998 DisableQuietBoot (
999 VOID
1000 )
1001 {
1002
1003 //
1004 // Enable Cursor on Screen
1005 //
1006 gST->ConOut->EnableCursor (gST->ConOut, TRUE);
1007 return EFI_SUCCESS;
1008 }
1009