]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c
BMP file may has padding data between the bmp header section and the bmp data section...
[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
b5ded3c4 4Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>\r
180a5a35 5This program and the accompanying materials\r
5c08e117 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
a637802c 16#include <IndustryStandard/Bmp.h>\r
17\r
5c08e117 18\r
19/**\r
20 Check if we need to save the EFI variable with "ConVarName" as name\r
21 as NV type\r
775a9b19 22 If ConVarName is NULL, then ASSERT().\r
23 \r
5c08e117 24 @param ConVarName The name of the EFI variable.\r
25\r
26 @retval TRUE Set the EFI variable as NV type.\r
27 @retval FALSE EFI variable as NV type can be set NonNV.\r
28**/\r
29BOOLEAN\r
30IsNvNeed (\r
31 IN CHAR16 *ConVarName\r
32 )\r
33{\r
34 CHAR16 *Ptr;\r
35\r
775a9b19 36 ASSERT (ConVarName != NULL);\r
37 \r
5c08e117 38 Ptr = ConVarName;\r
39\r
40 //\r
41 // If the variable includes "Dev" at last, we consider\r
42 // it does not support NV attribute.\r
43 //\r
44 while (*Ptr != L'\0') {\r
45 Ptr++;\r
46 }\r
47\r
9260b915 48 if (((INTN)((UINTN)Ptr - (UINTN)ConVarName) / sizeof (CHAR16)) <= 3) {\r
f0a3b1a2 49 return TRUE;\r
50 }\r
51 \r
5c08e117 52 if ((*(Ptr - 3) == 'D') && (*(Ptr - 2) == 'e') && (*(Ptr - 1) == 'v')) {\r
53 return FALSE;\r
54 } else {\r
55 return TRUE;\r
56 }\r
57}\r
58\r
dad60833 59/**\r
60 Fill console handle in System Table if there are no valid console handle in.\r
61\r
62 Firstly, check the validation of console handle in System Table. If it is invalid,\r
63 update it by the first console device handle from EFI console variable. \r
64\r
65 @param VarName The name of the EFI console variable.\r
66 @param ConsoleGuid Specified Console protocol GUID.\r
67 @param ConsoleHandle On IN, console handle in System Table to be checked. \r
68 On OUT, new console hanlde in system table.\r
69 @param ProtocolInterface On IN, console protocol on console handle in System Table to be checked. \r
70 On OUT, new console protocol on new console hanlde in system table.\r
406ddad3 71\r
72 @retval TRUE System Table has been updated.\r
73 @retval FALSE System Table hasn't been updated.\r
74\r
dad60833 75**/\r
406ddad3 76BOOLEAN \r
dad60833 77UpdateSystemTableConsole (\r
78 IN CHAR16 *VarName,\r
79 IN EFI_GUID *ConsoleGuid,\r
80 IN OUT EFI_HANDLE *ConsoleHandle,\r
81 IN OUT VOID **ProtocolInterface\r
82 )\r
83{\r
84 EFI_STATUS Status;\r
85 UINTN DevicePathSize;\r
86 EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;\r
87 EFI_DEVICE_PATH_PROTOCOL *VarConsole;\r
88 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
89 VOID *Interface;\r
90 EFI_HANDLE NewHandle;\r
641b4a46 91 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
dad60833 92\r
93 ASSERT (VarName != NULL);\r
94 ASSERT (ConsoleHandle != NULL);\r
95 ASSERT (ConsoleGuid != NULL);\r
96 ASSERT (ProtocolInterface != NULL);\r
97\r
98 if (*ConsoleHandle != NULL) {\r
99 Status = gBS->HandleProtocol (\r
100 *ConsoleHandle,\r
101 ConsoleGuid,\r
102 &Interface\r
103 );\r
104 if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) {\r
105 //\r
106 // If ConsoleHandle is valid and console protocol on this handle also\r
107 // also matched, just return.\r
108 //\r
406ddad3 109 return FALSE;\r
dad60833 110 }\r
111 }\r
112 \r
113 //\r
114 // Get all possible consoles device path from EFI variable\r
115 //\r
116 VarConsole = BdsLibGetVariableAndSize (\r
117 VarName,\r
118 &gEfiGlobalVariableGuid,\r
119 &DevicePathSize\r
120 );\r
121 if (VarConsole == NULL) {\r
122 //\r
123 // If there is no any console device, just return.\r
124 //\r
406ddad3 125 return FALSE;\r
dad60833 126 }\r
127\r
128 FullDevicePath = VarConsole;\r
129\r
130 do {\r
131 //\r
132 // Check every instance of the console variable\r
133 //\r
134 Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);\r
135 if (Instance == NULL) {\r
136 FreePool (FullDevicePath);\r
137 ASSERT (FALSE);\r
138 }\r
139 \r
140 //\r
141 // Find console device handle by device path instance\r
142 //\r
143 Status = gBS->LocateDevicePath (\r
144 ConsoleGuid,\r
145 &Instance,\r
146 &NewHandle\r
147 );\r
148 if (!EFI_ERROR (Status)) {\r
149 //\r
150 // Get the console protocol on this console device handle\r
151 //\r
152 Status = gBS->HandleProtocol (\r
153 NewHandle,\r
154 ConsoleGuid,\r
155 &Interface\r
156 );\r
157 if (!EFI_ERROR (Status)) {\r
158 //\r
159 // Update new console handle in System Table.\r
160 //\r
161 *ConsoleHandle = NewHandle;\r
162 *ProtocolInterface = Interface;\r
641b4a46 163 if (CompareGuid (ConsoleGuid, &gEfiSimpleTextOutProtocolGuid)) {\r
164 //\r
165 // If it is console out device, set console mode 80x25 if current mode is invalid.\r
166 //\r
167 TextOut = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *) Interface;\r
168 if (TextOut->Mode->Mode == -1) {\r
169 TextOut->SetMode (TextOut, 0);\r
170 }\r
171 }\r
406ddad3 172 return TRUE;\r
dad60833 173 }\r
174 }\r
175\r
176 } while (Instance != NULL);\r
177\r
178 //\r
179 // No any available console devcie found.\r
180 //\r
406ddad3 181 return FALSE;\r
dad60833 182}\r
183\r
bc79c731 184/**\r
185 Connect the console device base on the variable ConVarName, if\r
186 device path of the ConVarName is multi-instance device path and\r
187 anyone of the instances is connected success, this function will\r
188 return success. \r
189 Dispatch service is called basing on input when the handle associate\r
190 with one device path node can not be created successfully. Since in\r
191 some cases we assume driver dependency does not exist and do not \r
192 need to call this service.\r
193\r
194 @param ConVarName Console related variable name, ConIn, ConOut,\r
195 ErrOut.\r
196 @param NeedDispatch Whether requires dispatch service during connection \r
197\r
198 @retval EFI_NOT_FOUND There is not any console devices connected\r
199 success\r
200 @retval EFI_SUCCESS Success connect any one instance of the console\r
201 device path base on the variable ConVarName.\r
202\r
203**/\r
204EFI_STATUS\r
205ConnectConsoleVariableInternal (\r
206 IN CHAR16 *ConVarName,\r
207 IN BOOLEAN NeedDispatch\r
208 )\r
209{\r
210 EFI_STATUS Status;\r
211 EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;\r
212 UINTN VariableSize;\r
213 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
214 EFI_DEVICE_PATH_PROTOCOL *Next;\r
215 EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;\r
216 UINTN Size;\r
217 BOOLEAN DeviceExist;\r
218\r
219 Status = EFI_SUCCESS;\r
220 DeviceExist = FALSE;\r
221\r
222 //\r
223 // Check if the console variable exist\r
224 //\r
225 StartDevicePath = BdsLibGetVariableAndSize (\r
226 ConVarName,\r
227 &gEfiGlobalVariableGuid,\r
228 &VariableSize\r
229 );\r
230 if (StartDevicePath == NULL) {\r
231 return EFI_UNSUPPORTED;\r
232 }\r
233\r
234 CopyOfDevicePath = StartDevicePath;\r
235 do {\r
236 //\r
237 // Check every instance of the console variable\r
238 //\r
239 Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);\r
240 if (Instance == NULL) {\r
241 FreePool (StartDevicePath);\r
242 return EFI_UNSUPPORTED;\r
243 }\r
244 \r
245 Next = Instance;\r
246 while (!IsDevicePathEndType (Next)) {\r
247 Next = NextDevicePathNode (Next);\r
248 }\r
249\r
250 SetDevicePathEndNode (Next);\r
251 //\r
252 // Connect the USB console\r
253 // USB console device path is a short-form device path that \r
254 // starts with the first element being a USB WWID\r
255 // or a USB Class device path\r
256 //\r
257 if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&\r
258 ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP)\r
259 || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)\r
260 )) {\r
261 Status = BdsLibConnectUsbDevByShortFormDP (0xFF, Instance);\r
262 if (!EFI_ERROR (Status)) {\r
263 DeviceExist = TRUE;\r
264 }\r
265 } else {\r
266 //\r
267 // Connect the instance device path\r
268 //\r
269 Status = ConnectDevicePathInternal (Instance, NeedDispatch);\r
270\r
271 if (EFI_ERROR (Status)) {\r
272 //\r
273 // Delete the instance from the console varialbe\r
274 //\r
275 BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance);\r
276 } else {\r
277 DeviceExist = TRUE;\r
278 }\r
279 }\r
280 FreePool(Instance);\r
281 } while (CopyOfDevicePath != NULL);\r
282\r
283 FreePool (StartDevicePath);\r
284\r
285 if (!DeviceExist) {\r
286 return EFI_NOT_FOUND;\r
287 }\r
288\r
289 return EFI_SUCCESS;\r
290}\r
291\r
5c08e117 292/**\r
293 This function update console variable based on ConVarName, it can\r
294 add or remove one specific console device path from the variable\r
295\r
296 @param ConVarName Console related variable name, ConIn, ConOut,\r
297 ErrOut.\r
298 @param CustomizedConDevicePath The console device path which will be added to\r
299 the console variable ConVarName, this parameter\r
300 can not be multi-instance.\r
301 @param ExclusiveDevicePath The console device path which will be removed\r
302 from the console variable ConVarName, this\r
303 parameter can not be multi-instance.\r
304\r
305 @retval EFI_UNSUPPORTED The added device path is same to the removed one.\r
306 @retval EFI_SUCCESS Success add or remove the device path from the\r
307 console variable.\r
308\r
309**/\r
310EFI_STATUS\r
311EFIAPI\r
312BdsLibUpdateConsoleVariable (\r
313 IN CHAR16 *ConVarName,\r
314 IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,\r
315 IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath\r
316 )\r
317{\r
63b30616 318 EFI_STATUS Status;\r
5c08e117 319 EFI_DEVICE_PATH_PROTOCOL *VarConsole;\r
320 UINTN DevicePathSize;\r
321 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
322 EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
323 UINT32 Attributes;\r
324\r
325 VarConsole = NULL;\r
326 DevicePathSize = 0;\r
327\r
328 //\r
329 // Notes: check the device path point, here should check\r
330 // with compare memory\r
331 //\r
332 if (CustomizedConDevicePath == ExclusiveDevicePath) {\r
333 return EFI_UNSUPPORTED;\r
334 }\r
335 //\r
336 // Delete the ExclusiveDevicePath from current default console\r
337 //\r
338 VarConsole = BdsLibGetVariableAndSize (\r
339 ConVarName,\r
340 &gEfiGlobalVariableGuid,\r
341 &DevicePathSize\r
342 );\r
343\r
344 //\r
345 // Initialize NewDevicePath\r
346 //\r
347 NewDevicePath = VarConsole;\r
348\r
349 //\r
350 // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.\r
351 // In the end, NewDevicePath is the final device path.\r
352 //\r
353 if (ExclusiveDevicePath != NULL && VarConsole != NULL) {\r
354 NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath);\r
355 }\r
356 //\r
357 // Try to append customized device path to NewDevicePath.\r
358 //\r
359 if (CustomizedConDevicePath != NULL) {\r
360 if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {\r
361 //\r
362 // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.\r
363 //\r
364 NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);\r
365 //\r
366 // In the first check, the default console variable will be _ModuleEntryPoint,\r
367 // just append current customized device path\r
368 //\r
369 TempNewDevicePath = NewDevicePath;\r
370 NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);\r
371 if (TempNewDevicePath != NULL) {\r
372 FreePool(TempNewDevicePath);\r
373 }\r
374 }\r
375 }\r
376\r
377 //\r
378 // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.\r
379 //\r
380 if (IsNvNeed(ConVarName)) {\r
381 //\r
382 // ConVarName has NV attribute.\r
383 //\r
384 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
385 } else {\r
386 //\r
387 // ConVarName does not have NV attribute.\r
388 //\r
389 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
390 }\r
391\r
392 //\r
393 // Finally, Update the variable of the default console by NewDevicePath\r
394 //\r
f6079c70 395 DevicePathSize = GetDevicePathSize (NewDevicePath);\r
63b30616
RN
396 Status = gRT->SetVariable (\r
397 ConVarName,\r
398 &gEfiGlobalVariableGuid,\r
399 Attributes,\r
f6079c70 400 DevicePathSize,\r
63b30616
RN
401 NewDevicePath\r
402 );\r
f6079c70 403 if ((DevicePathSize == 0) && (Status == EFI_NOT_FOUND)) {\r
404 Status = EFI_SUCCESS;\r
405 }\r
63b30616 406 ASSERT_EFI_ERROR (Status);\r
5c08e117 407\r
408 if (VarConsole == NewDevicePath) {\r
409 if (VarConsole != NULL) {\r
410 FreePool(VarConsole);\r
411 }\r
412 } else {\r
413 if (VarConsole != NULL) {\r
414 FreePool(VarConsole);\r
415 }\r
416 if (NewDevicePath != NULL) {\r
417 FreePool(NewDevicePath);\r
418 }\r
419 }\r
420\r
f6079c70 421 return Status;\r
5c08e117 422\r
423}\r
424\r
425\r
426/**\r
427 Connect the console device base on the variable ConVarName, if\r
bc79c731 428 device path of the ConVarName is multi-instance device path and\r
5c08e117 429 anyone of the instances is connected success, then this function\r
430 will return success.\r
bc79c731 431 If the handle associate with one device path node can not\r
432 be created successfully, then still give chance to do the dispatch,\r
433 which load the missing drivers if possible..\r
5c08e117 434\r
435 @param ConVarName Console related variable name, ConIn, ConOut,\r
436 ErrOut.\r
437\r
438 @retval EFI_NOT_FOUND There is not any console devices connected\r
439 success\r
440 @retval EFI_SUCCESS Success connect any one instance of the console\r
441 device path base on the variable ConVarName.\r
442\r
443**/\r
444EFI_STATUS\r
445EFIAPI\r
446BdsLibConnectConsoleVariable (\r
447 IN CHAR16 *ConVarName\r
448 )\r
449{\r
bc79c731 450 return ConnectConsoleVariableInternal(ConVarName, TRUE);\r
451}\r
5c08e117 452\r
bc79c731 453/**\r
454 Connect the console device base on the variable ConVarName, if\r
455 device path of the ConVarName is multi-instance device path and\r
456 anyone of the instances is connected success, then this function\r
457 will return success.\r
458 Dispatch service is not called when the handle associate with one \r
459 device path node can not be created successfully. Here no driver \r
460 dependency is assumed exist, so need not to call this service.\r
5c08e117 461\r
5c08e117 462\r
bc79c731 463 @param ConVarName Console related variable name, ConIn, ConOut,\r
464 ErrOut.\r
5c08e117 465\r
bc79c731 466 @retval EFI_NOT_FOUND There is not any console devices connected\r
467 success\r
468 @retval EFI_SUCCESS Success connect any one instance of the console\r
469 device path base on the variable ConVarName.\r
5c08e117 470\r
bc79c731 471**/\r
472EFI_STATUS\r
473EFIAPI\r
474BdsLibConnectConsoleVariableWithOutDispatch (\r
475 IN CHAR16 *ConVarName\r
476 )\r
477{\r
478 return ConnectConsoleVariableInternal(ConVarName, FALSE);\r
5c08e117 479}\r
480\r
5c08e117 481/**\r
482 This function will search every simpletext device in current system,\r
483 and make every simpletext device as pertantial console device.\r
484\r
485**/\r
486VOID\r
487EFIAPI\r
488BdsLibConnectAllConsoles (\r
489 VOID\r
490 )\r
491{\r
492 UINTN Index;\r
493 EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;\r
494 UINTN HandleCount;\r
495 EFI_HANDLE *HandleBuffer;\r
496\r
497 Index = 0;\r
498 HandleCount = 0;\r
499 HandleBuffer = NULL;\r
500 ConDevicePath = NULL;\r
501\r
502 //\r
503 // Update all the console variables\r
504 //\r
505 gBS->LocateHandleBuffer (\r
506 ByProtocol,\r
507 &gEfiSimpleTextInProtocolGuid,\r
508 NULL,\r
509 &HandleCount,\r
510 &HandleBuffer\r
511 );\r
512\r
513 for (Index = 0; Index < HandleCount; Index++) {\r
514 gBS->HandleProtocol (\r
515 HandleBuffer[Index],\r
516 &gEfiDevicePathProtocolGuid,\r
517 (VOID **) &ConDevicePath\r
518 );\r
519 BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL);\r
520 }\r
521\r
522 if (HandleBuffer != NULL) {\r
523 FreePool(HandleBuffer);\r
524 HandleBuffer = NULL;\r
525 }\r
526\r
527 gBS->LocateHandleBuffer (\r
528 ByProtocol,\r
529 &gEfiSimpleTextOutProtocolGuid,\r
530 NULL,\r
531 &HandleCount,\r
532 &HandleBuffer\r
533 );\r
534 for (Index = 0; Index < HandleCount; Index++) {\r
535 gBS->HandleProtocol (\r
536 HandleBuffer[Index],\r
537 &gEfiDevicePathProtocolGuid,\r
538 (VOID **) &ConDevicePath\r
539 );\r
540 BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL);\r
541 BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL);\r
542 }\r
543\r
544 if (HandleBuffer != NULL) {\r
545 FreePool(HandleBuffer);\r
546 }\r
547\r
548 //\r
549 // Connect all console variables\r
550 //\r
551 BdsLibConnectAllDefaultConsoles ();\r
552\r
553}\r
554\r
555/**\r
556 This function will connect console device base on the console\r
557 device variable ConIn, ConOut and ErrOut.\r
558\r
559 @retval EFI_SUCCESS At least one of the ConIn and ConOut device have\r
560 been connected success.\r
561 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().\r
562\r
563**/\r
564EFI_STATUS\r
565EFIAPI\r
566BdsLibConnectAllDefaultConsoles (\r
567 VOID\r
568 )\r
569{\r
570 EFI_STATUS Status;\r
406ddad3 571 BOOLEAN SystemTableUpdated;\r
5c08e117 572\r
573 //\r
574 // Connect all default console variables\r
575 //\r
576\r
577 //\r
578 // It seems impossible not to have any ConOut device on platform,\r
579 // so we check the status here.\r
580 //\r
581 Status = BdsLibConnectConsoleVariable (L"ConOut");\r
582 if (EFI_ERROR (Status)) {\r
583 return Status;\r
584 }\r
585\r
586 //\r
587 // Insert the performance probe for Console Out\r
588 //\r
589 PERF_START (NULL, "ConOut", "BDS", 1);\r
590 PERF_END (NULL, "ConOut", "BDS", 0);\r
591\r
592 //\r
593 // Because possibly the platform is legacy free, in such case,\r
594 // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,\r
595 // so we need not check the status.\r
596 //\r
597 BdsLibConnectConsoleVariable (L"ConIn");\r
598\r
599 //\r
600 // The _ModuleEntryPoint err out var is legal.\r
601 //\r
602 BdsLibConnectConsoleVariable (L"ErrOut");\r
603\r
406ddad3 604 SystemTableUpdated = FALSE;\r
dad60833 605 //\r
606 // Fill console handles in System Table if no console device assignd.\r
607 //\r
406ddad3 608 if (UpdateSystemTableConsole (L"ConIn", &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **) &gST->ConIn)) {\r
609 SystemTableUpdated = TRUE;\r
610 }\r
611 if (UpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) {\r
612 SystemTableUpdated = TRUE;\r
613 }\r
614 if (UpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) {\r
615 SystemTableUpdated = TRUE;\r
616 }\r
617\r
18cf3950 618 if (SystemTableUpdated) {\r
619 //\r
620 // Update the CRC32 in the EFI System Table header\r
621 //\r
622 gST->Hdr.CRC32 = 0;\r
623 gBS->CalculateCrc32 (\r
624 (UINT8 *) &gST->Hdr,\r
625 gST->Hdr.HeaderSize,\r
626 &gST->Hdr.CRC32\r
627 );\r
628 }\r
629\r
630 return EFI_SUCCESS;\r
631\r
632}\r
633\r
634/**\r
635 This function will connect console device except ConIn base on the console\r
636 device variable ConOut and ErrOut.\r
637\r
638 @retval EFI_SUCCESS At least one of the ConOut device have\r
639 been connected success.\r
640 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().\r
641\r
642**/\r
643EFI_STATUS\r
644EFIAPI\r
645BdsLibConnectAllDefaultConsolesWithOutConIn (\r
646 VOID\r
647 )\r
648{\r
649 EFI_STATUS Status;\r
650 BOOLEAN SystemTableUpdated;\r
651\r
652 //\r
653 // Connect all default console variables except ConIn\r
654 //\r
655\r
656 //\r
657 // It seems impossible not to have any ConOut device on platform,\r
658 // so we check the status here.\r
659 //\r
660 Status = BdsLibConnectConsoleVariable (L"ConOut");\r
661 if (EFI_ERROR (Status)) {\r
662 return Status;\r
663 }\r
664\r
665 //\r
666 // Insert the performance probe for Console Out\r
667 //\r
668 PERF_START (NULL, "ConOut", "BDS", 1);\r
669 PERF_END (NULL, "ConOut", "BDS", 0);\r
670\r
671 //\r
672 // The _ModuleEntryPoint err out var is legal.\r
673 //\r
674 BdsLibConnectConsoleVariable (L"ErrOut");\r
675\r
676 SystemTableUpdated = FALSE;\r
677 //\r
678 // Fill console handles in System Table if no console device assignd.\r
679 //\r
680 if (UpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) {\r
681 SystemTableUpdated = TRUE;\r
682 }\r
683 if (UpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) {\r
684 SystemTableUpdated = TRUE;\r
685 }\r
686\r
406ddad3 687 if (SystemTableUpdated) {\r
688 //\r
689 // Update the CRC32 in the EFI System Table header\r
690 //\r
691 gST->Hdr.CRC32 = 0;\r
692 gBS->CalculateCrc32 (\r
693 (UINT8 *) &gST->Hdr,\r
694 gST->Hdr.HeaderSize,\r
695 &gST->Hdr.CRC32\r
696 );\r
697 }\r
dad60833 698\r
5c08e117 699 return EFI_SUCCESS;\r
700\r
701}\r
702\r
703/**\r
704 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer\r
705 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt\r
706 buffer is passed in it will be used if it is big enough.\r
707\r
708 @param BmpImage Pointer to BMP file\r
709 @param BmpImageSize Number of bytes in BmpImage\r
710 @param GopBlt Buffer containing GOP version of BmpImage.\r
711 @param GopBltSize Size of GopBlt in bytes.\r
712 @param PixelHeight Height of GopBlt/BmpImage in pixels\r
713 @param PixelWidth Width of GopBlt/BmpImage in pixels\r
714\r
715 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.\r
716 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image\r
717 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.\r
718 GopBltSize will contain the required size.\r
719 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.\r
720\r
721**/\r
722EFI_STATUS\r
723ConvertBmpToGopBlt (\r
724 IN VOID *BmpImage,\r
725 IN UINTN BmpImageSize,\r
726 IN OUT VOID **GopBlt,\r
727 IN OUT UINTN *GopBltSize,\r
728 OUT UINTN *PixelHeight,\r
729 OUT UINTN *PixelWidth\r
730 )\r
731{\r
732 UINT8 *Image;\r
733 UINT8 *ImageHeader;\r
734 BMP_IMAGE_HEADER *BmpHeader;\r
735 BMP_COLOR_MAP *BmpColorMap;\r
736 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
737 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
88f2bdb5 738 UINT64 BltBufferSize;\r
5c08e117 739 UINTN Index;\r
740 UINTN Height;\r
741 UINTN Width;\r
742 UINTN ImageIndex;\r
a46c3657 743 UINT32 DataSizePerLine;\r
5c08e117 744 BOOLEAN IsAllocated;\r
a46c3657
ED
745 UINT32 ColorMapNum;\r
746\r
747 if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {\r
748 return EFI_INVALID_PARAMETER;\r
749 }\r
5c08e117 750\r
751 BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;\r
752\r
753 if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {\r
754 return EFI_UNSUPPORTED;\r
755 }\r
756\r
757 //\r
758 // Doesn't support compress.\r
759 //\r
760 if (BmpHeader->CompressionType != 0) {\r
761 return EFI_UNSUPPORTED;\r
762 }\r
763\r
a46c3657
ED
764 //\r
765 // Only support BITMAPINFOHEADER format.\r
766 // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER\r
767 //\r
768 if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {\r
769 return EFI_UNSUPPORTED;\r
770 }\r
771\r
772 //\r
773 // The data size in each line must be 4 byte alignment.\r
774 //\r
775 DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);\r
776 BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);\r
777 if (BltBufferSize > (UINT32) ~0) {\r
778 return EFI_INVALID_PARAMETER;\r
779 }\r
780\r
781 if ((BmpHeader->Size != BmpImageSize) || \r
782 (BmpHeader->Size < BmpHeader->ImageOffset) ||\r
783 (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) {\r
784 return EFI_INVALID_PARAMETER;\r
785 }\r
786\r
5c08e117 787 //\r
788 // Calculate Color Map offset in the image.\r
789 //\r
790 Image = BmpImage;\r
791 BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));\r
a46c3657
ED
792 if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {\r
793 return EFI_INVALID_PARAMETER;\r
794 }\r
795\r
796 if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {\r
797 switch (BmpHeader->BitPerPixel) {\r
798 case 1:\r
799 ColorMapNum = 2;\r
800 break;\r
801 case 4:\r
802 ColorMapNum = 16;\r
803 break;\r
804 case 8:\r
805 ColorMapNum = 256;\r
806 break;\r
807 default:\r
808 ColorMapNum = 0;\r
809 break;\r
810 }\r
b5ded3c4
ED
811 //\r
812 // BMP file may has padding data between the bmp header section and the bmp data section.\r
813 //\r
814 if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {\r
a46c3657
ED
815 return EFI_INVALID_PARAMETER;\r
816 }\r
817 }\r
5c08e117 818\r
819 //\r
820 // Calculate graphics image data address in the image\r
821 //\r
822 Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;\r
823 ImageHeader = Image;\r
824\r
825 //\r
826 // Calculate the BltBuffer needed size.\r
827 //\r
d2eec319 828 BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);\r
829 //\r
830 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow\r
831 //\r
832 if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {\r
a46c3657
ED
833 return EFI_UNSUPPORTED;\r
834 }\r
d2eec319 835 BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
836\r
5c08e117 837 IsAllocated = FALSE;\r
838 if (*GopBlt == NULL) {\r
839 //\r
840 // GopBlt is not allocated by caller.\r
841 //\r
88f2bdb5 842 *GopBltSize = (UINTN) BltBufferSize;\r
5c08e117 843 *GopBlt = AllocatePool (*GopBltSize);\r
844 IsAllocated = TRUE;\r
845 if (*GopBlt == NULL) {\r
846 return EFI_OUT_OF_RESOURCES;\r
847 }\r
848 } else {\r
849 //\r
850 // GopBlt has been allocated by caller.\r
851 //\r
2bf3421a 852 if (*GopBltSize < (UINTN) BltBufferSize) {\r
88f2bdb5 853 *GopBltSize = (UINTN) BltBufferSize;\r
5c08e117 854 return EFI_BUFFER_TOO_SMALL;\r
855 }\r
856 }\r
857\r
858 *PixelWidth = BmpHeader->PixelWidth;\r
859 *PixelHeight = BmpHeader->PixelHeight;\r
860\r
861 //\r
862 // Convert image from BMP to Blt buffer format\r
863 //\r
864 BltBuffer = *GopBlt;\r
865 for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {\r
866 Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];\r
867 for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {\r
868 switch (BmpHeader->BitPerPixel) {\r
869 case 1:\r
870 //\r
871 // Convert 1-bit (2 colors) BMP to 24-bit color\r
872 //\r
873 for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {\r
874 Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;\r
875 Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;\r
876 Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;\r
877 Blt++;\r
878 Width++;\r
879 }\r
880\r
881 Blt--;\r
882 Width--;\r
883 break;\r
884\r
885 case 4:\r
886 //\r
887 // Convert 4-bit (16 colors) BMP Palette to 24-bit color\r
888 //\r
889 Index = (*Image) >> 4;\r
890 Blt->Red = BmpColorMap[Index].Red;\r
891 Blt->Green = BmpColorMap[Index].Green;\r
892 Blt->Blue = BmpColorMap[Index].Blue;\r
893 if (Width < (BmpHeader->PixelWidth - 1)) {\r
894 Blt++;\r
895 Width++;\r
896 Index = (*Image) & 0x0f;\r
897 Blt->Red = BmpColorMap[Index].Red;\r
898 Blt->Green = BmpColorMap[Index].Green;\r
899 Blt->Blue = BmpColorMap[Index].Blue;\r
900 }\r
901 break;\r
902\r
903 case 8:\r
904 //\r
905 // Convert 8-bit (256 colors) BMP Palette to 24-bit color\r
906 //\r
907 Blt->Red = BmpColorMap[*Image].Red;\r
908 Blt->Green = BmpColorMap[*Image].Green;\r
909 Blt->Blue = BmpColorMap[*Image].Blue;\r
910 break;\r
911\r
912 case 24:\r
913 //\r
914 // It is 24-bit BMP.\r
915 //\r
916 Blt->Blue = *Image++;\r
917 Blt->Green = *Image++;\r
918 Blt->Red = *Image;\r
919 break;\r
920\r
921 default:\r
922 //\r
923 // Other bit format BMP is not supported.\r
924 //\r
925 if (IsAllocated) {\r
926 FreePool (*GopBlt);\r
927 *GopBlt = NULL;\r
928 }\r
929 return EFI_UNSUPPORTED;\r
930 break;\r
931 };\r
932\r
933 }\r
934\r
935 ImageIndex = (UINTN) (Image - ImageHeader);\r
936 if ((ImageIndex % 4) != 0) {\r
937 //\r
938 // Bmp Image starts each row on a 32-bit boundary!\r
939 //\r
940 Image = Image + (4 - (ImageIndex % 4));\r
941 }\r
942 }\r
943\r
944 return EFI_SUCCESS;\r
945}\r
946\r
5c08e117 947/**\r
24cdd14e
LG
948 Use SystemTable Conout to stop video based Simple Text Out consoles from going\r
949 to the video device. Put up LogoFile on every video device that is a console.\r
5c08e117 950\r
951 @param[in] LogoFile File name of logo to display on the center of the screen.\r
952\r
953 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.\r
954 @retval EFI_UNSUPPORTED Logo not found\r
955\r
956**/\r
957EFI_STATUS\r
958EFIAPI\r
959EnableQuietBoot (\r
960 IN EFI_GUID *LogoFile\r
961 )\r
962{\r
963 EFI_STATUS Status;\r
5c08e117 964 EFI_OEM_BADGING_PROTOCOL *Badging;\r
965 UINT32 SizeOfX;\r
966 UINT32 SizeOfY;\r
967 INTN DestX;\r
968 INTN DestY;\r
969 UINT8 *ImageData;\r
970 UINTN ImageSize;\r
971 UINTN BltSize;\r
972 UINT32 Instance;\r
973 EFI_BADGING_FORMAT Format;\r
974 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;\r
975 UINTN CoordinateX;\r
976 UINTN CoordinateY;\r
977 UINTN Height;\r
978 UINTN Width;\r
979 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
980 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
981 UINT32 ColorDepth;\r
982 UINT32 RefreshRate;\r
983 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
a637802c 984 EFI_BOOT_LOGO_PROTOCOL *BootLogo;\r
985 UINTN NumberOfLogos;\r
986 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt;\r
987 UINTN LogoDestX;\r
988 UINTN LogoDestY;\r
989 UINTN LogoHeight;\r
990 UINTN LogoWidth;\r
991 UINTN NewDestX;\r
992 UINTN NewDestY;\r
993 UINTN NewHeight;\r
994 UINTN NewWidth;\r
a46c3657 995 UINT64 BufferSize;\r
5c08e117 996\r
5c08e117 997 UgaDraw = NULL;\r
998 //\r
999 // Try to open GOP first\r
1000 //\r
1001 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);\r
1002 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
1003 GraphicsOutput = NULL;\r
1004 //\r
1005 // Open GOP failed, try to open UGA\r
1006 //\r
1007 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);\r
1008 }\r
1009 if (EFI_ERROR (Status)) {\r
1010 return EFI_UNSUPPORTED;\r
1011 }\r
1012\r
a637802c 1013 //\r
1014 // Try to open Boot Logo Protocol.\r
1015 //\r
1016 BootLogo = NULL;\r
1017 gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);\r
1018\r
5c08e117 1019 //\r
5d7c1609 1020 // Erase Cursor from screen\r
5c08e117 1021 //\r
5d7c1609 1022 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
1023\r
1024 Badging = NULL;\r
1025 Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);\r
5c08e117 1026\r
1027 if (GraphicsOutput != NULL) {\r
1028 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
1029 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
1030\r
1031 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
1032 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);\r
1033 if (EFI_ERROR (Status)) {\r
1034 return EFI_UNSUPPORTED;\r
1035 }\r
1036 } else {\r
1037 return EFI_UNSUPPORTED;\r
1038 }\r
1039\r
a637802c 1040 Blt = NULL;\r
1041 NumberOfLogos = 0;\r
1042 LogoDestX = 0;\r
1043 LogoDestY = 0;\r
1044 LogoHeight = 0;\r
1045 LogoWidth = 0;\r
1046 NewDestX = 0;\r
1047 NewDestY = 0;\r
1048 NewHeight = 0;\r
1049 NewWidth = 0;\r
5c08e117 1050 Instance = 0;\r
1051 while (1) {\r
1052 ImageData = NULL;\r
1053 ImageSize = 0;\r
1054\r
1055 if (Badging != NULL) {\r
1056 //\r
1057 // Get image from OEMBadging protocol.\r
1058 //\r
1059 Status = Badging->GetImage (\r
1060 Badging,\r
1061 &Instance,\r
1062 &Format,\r
1063 &ImageData,\r
1064 &ImageSize,\r
1065 &Attribute,\r
1066 &CoordinateX,\r
1067 &CoordinateY\r
1068 );\r
1069 if (EFI_ERROR (Status)) {\r
a637802c 1070 goto Done;\r
5c08e117 1071 }\r
1072\r
1073 //\r
1074 // Currently only support BMP format.\r
1075 //\r
1076 if (Format != EfiBadgingFormatBMP) {\r
1077 if (ImageData != NULL) {\r
1078 FreePool (ImageData);\r
1079 }\r
1080 continue;\r
1081 }\r
1082 } else {\r
1083 //\r
1084 // Get the specified image from FV.\r
1085 //\r
1086 Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);\r
1087 if (EFI_ERROR (Status)) {\r
1088 return EFI_UNSUPPORTED;\r
1089 }\r
1090\r
1091 CoordinateX = 0;\r
1092 CoordinateY = 0;\r
2df686c6 1093 if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {\r
1094 Attribute = EfiBadgingDisplayAttributeCenter;\r
1095 } else {\r
1096 Attribute = EfiBadgingDisplayAttributeCustomized;\r
1097 } \r
5c08e117 1098 }\r
1099\r
a637802c 1100 if (Blt != NULL) {\r
1101 FreePool (Blt);\r
1102 }\r
5c08e117 1103 Blt = NULL;\r
1104 Status = ConvertBmpToGopBlt (\r
1105 ImageData,\r
1106 ImageSize,\r
1107 (VOID **) &Blt,\r
1108 &BltSize,\r
1109 &Height,\r
1110 &Width\r
1111 );\r
1112 if (EFI_ERROR (Status)) {\r
1113 FreePool (ImageData);\r
1114\r
1115 if (Badging == NULL) {\r
1116 return Status;\r
1117 } else {\r
1118 continue;\r
1119 }\r
1120 }\r
1121\r
1122 //\r
1123 // Calculate the display position according to Attribute.\r
1124 //\r
1125 switch (Attribute) {\r
1126 case EfiBadgingDisplayAttributeLeftTop:\r
1127 DestX = CoordinateX;\r
1128 DestY = CoordinateY;\r
1129 break;\r
1130\r
1131 case EfiBadgingDisplayAttributeCenterTop:\r
1132 DestX = (SizeOfX - Width) / 2;\r
1133 DestY = CoordinateY;\r
1134 break;\r
1135\r
1136 case EfiBadgingDisplayAttributeRightTop:\r
1137 DestX = (SizeOfX - Width - CoordinateX);\r
1138 DestY = CoordinateY;;\r
1139 break;\r
1140\r
1141 case EfiBadgingDisplayAttributeCenterRight:\r
1142 DestX = (SizeOfX - Width - CoordinateX);\r
1143 DestY = (SizeOfY - Height) / 2;\r
1144 break;\r
1145\r
1146 case EfiBadgingDisplayAttributeRightBottom:\r
1147 DestX = (SizeOfX - Width - CoordinateX);\r
1148 DestY = (SizeOfY - Height - CoordinateY);\r
1149 break;\r
1150\r
1151 case EfiBadgingDisplayAttributeCenterBottom:\r
1152 DestX = (SizeOfX - Width) / 2;\r
1153 DestY = (SizeOfY - Height - CoordinateY);\r
1154 break;\r
1155\r
1156 case EfiBadgingDisplayAttributeLeftBottom:\r
1157 DestX = CoordinateX;\r
1158 DestY = (SizeOfY - Height - CoordinateY);\r
1159 break;\r
1160\r
1161 case EfiBadgingDisplayAttributeCenterLeft:\r
1162 DestX = CoordinateX;\r
1163 DestY = (SizeOfY - Height) / 2;\r
1164 break;\r
1165\r
1166 case EfiBadgingDisplayAttributeCenter:\r
1167 DestX = (SizeOfX - Width) / 2;\r
1168 DestY = (SizeOfY - Height) / 2;\r
1169 break;\r
1170\r
2df686c6 1171 case EfiBadgingDisplayAttributeCustomized:\r
1172 DestX = (SizeOfX - Width) / 2;\r
1173 DestY = ((SizeOfY * 382) / 1000) - Height / 2;\r
1174 break;\r
1175\r
5c08e117 1176 default:\r
1177 DestX = CoordinateX;\r
1178 DestY = CoordinateY;\r
1179 break;\r
1180 }\r
1181\r
1182 if ((DestX >= 0) && (DestY >= 0)) {\r
1183 if (GraphicsOutput != NULL) {\r
1184 Status = GraphicsOutput->Blt (\r
1185 GraphicsOutput,\r
1186 Blt,\r
1187 EfiBltBufferToVideo,\r
1188 0,\r
1189 0,\r
1190 (UINTN) DestX,\r
1191 (UINTN) DestY,\r
1192 Width,\r
1193 Height,\r
1194 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
1195 );\r
1196 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
1197 Status = UgaDraw->Blt (\r
1198 UgaDraw,\r
1199 (EFI_UGA_PIXEL *) Blt,\r
1200 EfiUgaBltBufferToVideo,\r
1201 0,\r
1202 0,\r
1203 (UINTN) DestX,\r
1204 (UINTN) DestY,\r
1205 Width,\r
1206 Height,\r
1207 Width * sizeof (EFI_UGA_PIXEL)\r
1208 );\r
1209 } else {\r
a637802c 1210 Status = EFI_UNSUPPORTED;\r
1211 }\r
1212\r
1213 //\r
1214 // Report displayed Logo information.\r
1215 //\r
1216 if (!EFI_ERROR (Status)) {\r
1217 NumberOfLogos++;\r
1218\r
1219 if (LogoWidth == 0) {\r
1220 //\r
1221 // The first Logo.\r
1222 //\r
6ba8465f 1223 LogoDestX = (UINTN) DestX;\r
1224 LogoDestY = (UINTN) DestY;\r
a637802c 1225 LogoWidth = Width;\r
1226 LogoHeight = Height;\r
1227 } else {\r
1228 //\r
1229 // Merge new logo with old one.\r
1230 //\r
1231 NewDestX = MIN ((UINTN) DestX, LogoDestX);\r
1232 NewDestY = MIN ((UINTN) DestY, LogoDestY);\r
1233 NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX;\r
1234 NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY;\r
1235\r
1236 LogoDestX = NewDestX;\r
1237 LogoDestY = NewDestY;\r
1238 LogoWidth = NewWidth;\r
1239 LogoHeight = NewHeight;\r
1240 }\r
5c08e117 1241 }\r
1242 }\r
1243\r
1244 FreePool (ImageData);\r
1245\r
a637802c 1246 if (Badging == NULL) {\r
1247 break;\r
1248 }\r
1249 }\r
1250\r
1251Done:\r
1252 if (BootLogo == NULL || NumberOfLogos == 0) {\r
1253 //\r
1254 // No logo displayed.\r
1255 //\r
5c08e117 1256 if (Blt != NULL) {\r
1257 FreePool (Blt);\r
1258 }\r
1259\r
a637802c 1260 return Status;\r
1261 }\r
1262\r
1263 //\r
1264 // Advertise displayed Logo information.\r
1265 //\r
1266 if (NumberOfLogos == 1) {\r
1267 //\r
1268 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.\r
1269 //\r
1270 LogoBlt = Blt;\r
1271 Status = EFI_SUCCESS;\r
1272 } else {\r
1273 //\r
1274 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation. \r
1275 //\r
1276 if (Blt != NULL) {\r
1277 FreePool (Blt);\r
1278 }\r
1279\r
a46c3657
ED
1280 //\r
1281 // Ensure the LogoHeight * LogoWidth doesn't overflow\r
1282 //\r
1283 if (LogoHeight > DivU64x64Remainder ((UINTN) ~0, LogoWidth, NULL)) {\r
1284 return EFI_UNSUPPORTED;\r
1285 }\r
1286 BufferSize = MultU64x64 (LogoWidth, LogoHeight);\r
1287\r
1288 //\r
1289 // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow\r
1290 //\r
1291 if (BufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {\r
1292 return EFI_UNSUPPORTED;\r
1293 }\r
1294\r
1295 LogoBlt = AllocateZeroPool ((UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
a637802c 1296 if (LogoBlt == NULL) {\r
1297 return EFI_OUT_OF_RESOURCES;\r
1298 }\r
1299\r
1300 if (GraphicsOutput != NULL) {\r
1301 Status = GraphicsOutput->Blt (\r
1302 GraphicsOutput,\r
1303 LogoBlt,\r
1304 EfiBltVideoToBltBuffer,\r
1305 LogoDestX,\r
1306 LogoDestY,\r
1307 0,\r
1308 0,\r
1309 LogoWidth,\r
1310 LogoHeight,\r
1311 LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
1312 );\r
1313 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
1314 Status = UgaDraw->Blt (\r
1315 UgaDraw,\r
1316 (EFI_UGA_PIXEL *) LogoBlt,\r
1317 EfiUgaVideoToBltBuffer,\r
1318 LogoDestX,\r
1319 LogoDestY,\r
1320 0,\r
1321 0,\r
1322 LogoWidth,\r
1323 LogoHeight,\r
1324 LogoWidth * sizeof (EFI_UGA_PIXEL)\r
1325 );\r
1326 } else {\r
1327 Status = EFI_UNSUPPORTED;\r
5c08e117 1328 }\r
1329 }\r
1330\r
a637802c 1331 if (!EFI_ERROR (Status)) {\r
1332 BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight);\r
1333 }\r
1334 FreePool (LogoBlt);\r
1335\r
5c08e117 1336 return Status;\r
1337}\r
1338\r
1339/**\r
24cdd14e
LG
1340 Use SystemTable Conout to turn on video based Simple Text Out consoles. The \r
1341 Simple Text Out screens will now be synced up with all non video output devices\r
5c08e117 1342\r
1343 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.\r
1344\r
1345**/\r
1346EFI_STATUS\r
1347EFIAPI\r
1348DisableQuietBoot (\r
1349 VOID\r
1350 )\r
1351{\r
5c08e117 1352\r
1353 //\r
5d7c1609 1354 // Enable Cursor on Screen\r
5c08e117 1355 //\r
5d7c1609 1356 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
1357 return EFI_SUCCESS;\r
5c08e117 1358}\r
1359\r