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