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