]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c
IntelFrameworkModulePkg: Clean up source files
[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
53473721 4Copyright (c) 2004 - 2018, 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\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
0a6f4824 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
0a6f4824 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
0a6f4824 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
0a6f4824 62 update it by the first console device handle from EFI console variable.\r
dad60833 63\r
64 @param VarName The name of the EFI console variable.\r
65 @param ConsoleGuid Specified Console protocol GUID.\r
0a6f4824 66 @param ConsoleHandle On IN, console handle in System Table to be checked.\r
f95e6f6b 67 On OUT, new console handle in system table.\r
0a6f4824 68 @param ProtocolInterface On IN, console protocol on console handle in System Table to be checked.\r
f95e6f6b 69 On OUT, new console protocol on new console handle 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
0a6f4824 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
641b4a46 90 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
dad60833 91\r
92 ASSERT (VarName != NULL);\r
93 ASSERT (ConsoleHandle != NULL);\r
94 ASSERT (ConsoleGuid != NULL);\r
95 ASSERT (ProtocolInterface != NULL);\r
96\r
97 if (*ConsoleHandle != NULL) {\r
98 Status = gBS->HandleProtocol (\r
99 *ConsoleHandle,\r
100 ConsoleGuid,\r
101 &Interface\r
102 );\r
103 if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) {\r
104 //\r
105 // If ConsoleHandle is valid and console protocol on this handle also\r
106 // also matched, just return.\r
107 //\r
406ddad3 108 return FALSE;\r
dad60833 109 }\r
110 }\r
0a6f4824 111\r
dad60833 112 //\r
113 // Get all possible consoles device path from EFI variable\r
114 //\r
115 VarConsole = BdsLibGetVariableAndSize (\r
116 VarName,\r
117 &gEfiGlobalVariableGuid,\r
118 &DevicePathSize\r
119 );\r
120 if (VarConsole == NULL) {\r
121 //\r
122 // If there is no any console device, just return.\r
123 //\r
406ddad3 124 return FALSE;\r
dad60833 125 }\r
126\r
127 FullDevicePath = VarConsole;\r
128\r
129 do {\r
130 //\r
131 // Check every instance of the console variable\r
132 //\r
133 Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);\r
134 if (Instance == NULL) {\r
135 FreePool (FullDevicePath);\r
136 ASSERT (FALSE);\r
137 }\r
0a6f4824 138\r
dad60833 139 //\r
140 // Find console device handle by device path instance\r
141 //\r
142 Status = gBS->LocateDevicePath (\r
143 ConsoleGuid,\r
144 &Instance,\r
145 &NewHandle\r
146 );\r
147 if (!EFI_ERROR (Status)) {\r
148 //\r
149 // Get the console protocol on this console device handle\r
150 //\r
151 Status = gBS->HandleProtocol (\r
152 NewHandle,\r
153 ConsoleGuid,\r
154 &Interface\r
155 );\r
156 if (!EFI_ERROR (Status)) {\r
157 //\r
158 // Update new console handle in System Table.\r
159 //\r
160 *ConsoleHandle = NewHandle;\r
161 *ProtocolInterface = Interface;\r
641b4a46 162 if (CompareGuid (ConsoleGuid, &gEfiSimpleTextOutProtocolGuid)) {\r
163 //\r
164 // If it is console out device, set console mode 80x25 if current mode is invalid.\r
165 //\r
166 TextOut = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *) Interface;\r
167 if (TextOut->Mode->Mode == -1) {\r
168 TextOut->SetMode (TextOut, 0);\r
169 }\r
170 }\r
406ddad3 171 return TRUE;\r
dad60833 172 }\r
173 }\r
174\r
175 } while (Instance != NULL);\r
176\r
177 //\r
178 // No any available console devcie found.\r
179 //\r
406ddad3 180 return FALSE;\r
dad60833 181}\r
182\r
5c08e117 183/**\r
184 This function update console variable based on ConVarName, it can\r
185 add or remove one specific console device path from the variable\r
186\r
187 @param ConVarName Console related variable name, ConIn, ConOut,\r
188 ErrOut.\r
189 @param CustomizedConDevicePath The console device path which will be added to\r
190 the console variable ConVarName, this parameter\r
191 can not be multi-instance.\r
192 @param ExclusiveDevicePath The console device path which will be removed\r
193 from the console variable ConVarName, this\r
194 parameter can not be multi-instance.\r
195\r
196 @retval EFI_UNSUPPORTED The added device path is same to the removed one.\r
197 @retval EFI_SUCCESS Success add or remove the device path from the\r
198 console variable.\r
199\r
200**/\r
201EFI_STATUS\r
202EFIAPI\r
203BdsLibUpdateConsoleVariable (\r
204 IN CHAR16 *ConVarName,\r
205 IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,\r
206 IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath\r
207 )\r
208{\r
63b30616 209 EFI_STATUS Status;\r
5c08e117 210 EFI_DEVICE_PATH_PROTOCOL *VarConsole;\r
211 UINTN DevicePathSize;\r
212 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
213 EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
214 UINT32 Attributes;\r
215\r
216 VarConsole = NULL;\r
217 DevicePathSize = 0;\r
218\r
219 //\r
220 // Notes: check the device path point, here should check\r
221 // with compare memory\r
222 //\r
223 if (CustomizedConDevicePath == ExclusiveDevicePath) {\r
224 return EFI_UNSUPPORTED;\r
225 }\r
226 //\r
227 // Delete the ExclusiveDevicePath from current default console\r
228 //\r
229 VarConsole = BdsLibGetVariableAndSize (\r
230 ConVarName,\r
231 &gEfiGlobalVariableGuid,\r
232 &DevicePathSize\r
233 );\r
234\r
235 //\r
236 // Initialize NewDevicePath\r
237 //\r
238 NewDevicePath = VarConsole;\r
239\r
240 //\r
241 // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.\r
242 // In the end, NewDevicePath is the final device path.\r
243 //\r
244 if (ExclusiveDevicePath != NULL && VarConsole != NULL) {\r
245 NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath);\r
246 }\r
247 //\r
248 // Try to append customized device path to NewDevicePath.\r
249 //\r
250 if (CustomizedConDevicePath != NULL) {\r
251 if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {\r
252 //\r
253 // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.\r
254 //\r
255 NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);\r
256 //\r
257 // In the first check, the default console variable will be _ModuleEntryPoint,\r
258 // just append current customized device path\r
259 //\r
260 TempNewDevicePath = NewDevicePath;\r
261 NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);\r
262 if (TempNewDevicePath != NULL) {\r
263 FreePool(TempNewDevicePath);\r
264 }\r
265 }\r
266 }\r
267\r
268 //\r
269 // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.\r
270 //\r
271 if (IsNvNeed(ConVarName)) {\r
272 //\r
273 // ConVarName has NV attribute.\r
274 //\r
275 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
276 } else {\r
277 //\r
278 // ConVarName does not have NV attribute.\r
279 //\r
280 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
281 }\r
282\r
283 //\r
284 // Finally, Update the variable of the default console by NewDevicePath\r
285 //\r
f6079c70 286 DevicePathSize = GetDevicePathSize (NewDevicePath);\r
69fc8f08
RN
287 Status = SetVariableAndReportStatusCodeOnError (\r
288 ConVarName,\r
289 &gEfiGlobalVariableGuid,\r
290 Attributes,\r
291 DevicePathSize,\r
292 NewDevicePath\r
293 );\r
f6079c70 294 if ((DevicePathSize == 0) && (Status == EFI_NOT_FOUND)) {\r
295 Status = EFI_SUCCESS;\r
296 }\r
5c08e117 297\r
298 if (VarConsole == NewDevicePath) {\r
299 if (VarConsole != NULL) {\r
300 FreePool(VarConsole);\r
301 }\r
302 } else {\r
303 if (VarConsole != NULL) {\r
304 FreePool(VarConsole);\r
305 }\r
306 if (NewDevicePath != NULL) {\r
307 FreePool(NewDevicePath);\r
308 }\r
309 }\r
310\r
f6079c70 311 return Status;\r
5c08e117 312\r
313}\r
314\r
315\r
316/**\r
317 Connect the console device base on the variable ConVarName, if\r
bc79c731 318 device path of the ConVarName is multi-instance device path and\r
5c08e117 319 anyone of the instances is connected success, then this function\r
320 will return success.\r
bc79c731 321 If the handle associate with one device path node can not\r
322 be created successfully, then still give chance to do the dispatch,\r
323 which load the missing drivers if possible..\r
5c08e117 324\r
325 @param ConVarName Console related variable name, ConIn, ConOut,\r
326 ErrOut.\r
327\r
328 @retval EFI_NOT_FOUND There is not any console devices connected\r
329 success\r
330 @retval EFI_SUCCESS Success connect any one instance of the console\r
331 device path base on the variable ConVarName.\r
332\r
333**/\r
334EFI_STATUS\r
335EFIAPI\r
336BdsLibConnectConsoleVariable (\r
337 IN CHAR16 *ConVarName\r
338 )\r
339{\r
37406c34
RN
340 EFI_STATUS Status;\r
341 EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;\r
342 UINTN VariableSize;\r
343 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
344 EFI_DEVICE_PATH_PROTOCOL *Next;\r
345 EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;\r
346 UINTN Size;\r
347 BOOLEAN DeviceExist;\r
5c08e117 348\r
37406c34
RN
349 Status = EFI_SUCCESS;\r
350 DeviceExist = FALSE;\r
5c08e117 351\r
37406c34
RN
352 //\r
353 // Check if the console variable exist\r
354 //\r
355 StartDevicePath = BdsLibGetVariableAndSize (\r
356 ConVarName,\r
357 &gEfiGlobalVariableGuid,\r
358 &VariableSize\r
359 );\r
360 if (StartDevicePath == NULL) {\r
361 return EFI_UNSUPPORTED;\r
362 }\r
5c08e117 363\r
37406c34
RN
364 CopyOfDevicePath = StartDevicePath;\r
365 do {\r
366 //\r
367 // Check every instance of the console variable\r
368 //\r
369 Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);\r
370 if (Instance == NULL) {\r
371 FreePool (StartDevicePath);\r
372 return EFI_UNSUPPORTED;\r
373 }\r
0a6f4824 374\r
37406c34
RN
375 Next = Instance;\r
376 while (!IsDevicePathEndType (Next)) {\r
377 Next = NextDevicePathNode (Next);\r
378 }\r
5c08e117 379\r
37406c34
RN
380 SetDevicePathEndNode (Next);\r
381 //\r
382 // Connect the USB console\r
0a6f4824 383 // USB console device path is a short-form device path that\r
37406c34
RN
384 // starts with the first element being a USB WWID\r
385 // or a USB Class device path\r
386 //\r
387 if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&\r
388 ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP)\r
389 || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)\r
390 )) {\r
391 Status = BdsLibConnectUsbDevByShortFormDP (0xFF, Instance);\r
392 if (!EFI_ERROR (Status)) {\r
393 DeviceExist = TRUE;\r
394 }\r
395 } else {\r
396 //\r
397 // Connect the instance device path\r
398 //\r
399 Status = BdsLibConnectDevicePath (Instance);\r
5c08e117 400\r
37406c34
RN
401 if (EFI_ERROR (Status)) {\r
402 //\r
403 // Delete the instance from the console varialbe\r
404 //\r
405 BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance);\r
406 } else {\r
407 DeviceExist = TRUE;\r
408 }\r
409 }\r
410 FreePool(Instance);\r
411 } while (CopyOfDevicePath != NULL);\r
412\r
413 FreePool (StartDevicePath);\r
414\r
415 if (!DeviceExist) {\r
416 return EFI_NOT_FOUND;\r
417 }\r
418\r
419 return EFI_SUCCESS;\r
5c08e117 420}\r
421\r
5c08e117 422/**\r
423 This function will search every simpletext device in current system,\r
424 and make every simpletext device as pertantial console device.\r
425\r
426**/\r
427VOID\r
428EFIAPI\r
429BdsLibConnectAllConsoles (\r
430 VOID\r
431 )\r
432{\r
433 UINTN Index;\r
434 EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;\r
435 UINTN HandleCount;\r
436 EFI_HANDLE *HandleBuffer;\r
437\r
438 Index = 0;\r
439 HandleCount = 0;\r
440 HandleBuffer = NULL;\r
441 ConDevicePath = NULL;\r
442\r
443 //\r
444 // Update all the console variables\r
445 //\r
446 gBS->LocateHandleBuffer (\r
447 ByProtocol,\r
448 &gEfiSimpleTextInProtocolGuid,\r
449 NULL,\r
450 &HandleCount,\r
451 &HandleBuffer\r
452 );\r
453\r
454 for (Index = 0; Index < HandleCount; Index++) {\r
455 gBS->HandleProtocol (\r
456 HandleBuffer[Index],\r
457 &gEfiDevicePathProtocolGuid,\r
458 (VOID **) &ConDevicePath\r
459 );\r
460 BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL);\r
461 }\r
462\r
463 if (HandleBuffer != NULL) {\r
464 FreePool(HandleBuffer);\r
465 HandleBuffer = NULL;\r
466 }\r
467\r
468 gBS->LocateHandleBuffer (\r
469 ByProtocol,\r
470 &gEfiSimpleTextOutProtocolGuid,\r
471 NULL,\r
472 &HandleCount,\r
473 &HandleBuffer\r
474 );\r
475 for (Index = 0; Index < HandleCount; Index++) {\r
476 gBS->HandleProtocol (\r
477 HandleBuffer[Index],\r
478 &gEfiDevicePathProtocolGuid,\r
479 (VOID **) &ConDevicePath\r
480 );\r
481 BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL);\r
482 BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL);\r
483 }\r
484\r
485 if (HandleBuffer != NULL) {\r
486 FreePool(HandleBuffer);\r
487 }\r
488\r
489 //\r
490 // Connect all console variables\r
491 //\r
492 BdsLibConnectAllDefaultConsoles ();\r
493\r
494}\r
495\r
496/**\r
497 This function will connect console device base on the console\r
498 device variable ConIn, ConOut and ErrOut.\r
499\r
500 @retval EFI_SUCCESS At least one of the ConIn and ConOut device have\r
501 been connected success.\r
502 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().\r
503\r
504**/\r
505EFI_STATUS\r
506EFIAPI\r
507BdsLibConnectAllDefaultConsoles (\r
508 VOID\r
509 )\r
510{\r
511 EFI_STATUS Status;\r
406ddad3 512 BOOLEAN SystemTableUpdated;\r
5c08e117 513\r
514 //\r
515 // Connect all default console variables\r
516 //\r
517\r
518 //\r
519 // It seems impossible not to have any ConOut device on platform,\r
520 // so we check the status here.\r
521 //\r
522 Status = BdsLibConnectConsoleVariable (L"ConOut");\r
523 if (EFI_ERROR (Status)) {\r
524 return Status;\r
525 }\r
526\r
527 //\r
528 // Insert the performance probe for Console Out\r
529 //\r
530 PERF_START (NULL, "ConOut", "BDS", 1);\r
531 PERF_END (NULL, "ConOut", "BDS", 0);\r
532\r
533 //\r
534 // Because possibly the platform is legacy free, in such case,\r
535 // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,\r
536 // so we need not check the status.\r
537 //\r
538 BdsLibConnectConsoleVariable (L"ConIn");\r
539\r
540 //\r
541 // The _ModuleEntryPoint err out var is legal.\r
542 //\r
543 BdsLibConnectConsoleVariable (L"ErrOut");\r
544\r
406ddad3 545 SystemTableUpdated = FALSE;\r
dad60833 546 //\r
547 // Fill console handles in System Table if no console device assignd.\r
548 //\r
406ddad3 549 if (UpdateSystemTableConsole (L"ConIn", &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **) &gST->ConIn)) {\r
550 SystemTableUpdated = TRUE;\r
551 }\r
552 if (UpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) {\r
553 SystemTableUpdated = TRUE;\r
554 }\r
555 if (UpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) {\r
556 SystemTableUpdated = TRUE;\r
557 }\r
558\r
18cf3950 559 if (SystemTableUpdated) {\r
560 //\r
561 // Update the CRC32 in the EFI System Table header\r
562 //\r
563 gST->Hdr.CRC32 = 0;\r
564 gBS->CalculateCrc32 (\r
565 (UINT8 *) &gST->Hdr,\r
566 gST->Hdr.HeaderSize,\r
567 &gST->Hdr.CRC32\r
568 );\r
569 }\r
570\r
571 return EFI_SUCCESS;\r
572\r
573}\r
574\r
575/**\r
576 This function will connect console device except ConIn base on the console\r
577 device variable ConOut and ErrOut.\r
578\r
579 @retval EFI_SUCCESS At least one of the ConOut device have\r
580 been connected success.\r
581 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().\r
582\r
583**/\r
584EFI_STATUS\r
585EFIAPI\r
586BdsLibConnectAllDefaultConsolesWithOutConIn (\r
587 VOID\r
588 )\r
589{\r
590 EFI_STATUS Status;\r
591 BOOLEAN SystemTableUpdated;\r
592\r
593 //\r
594 // Connect all default console variables except ConIn\r
595 //\r
596\r
597 //\r
598 // It seems impossible not to have any ConOut device on platform,\r
599 // so we check the status here.\r
600 //\r
601 Status = BdsLibConnectConsoleVariable (L"ConOut");\r
602 if (EFI_ERROR (Status)) {\r
603 return Status;\r
604 }\r
605\r
606 //\r
607 // Insert the performance probe for Console Out\r
608 //\r
609 PERF_START (NULL, "ConOut", "BDS", 1);\r
610 PERF_END (NULL, "ConOut", "BDS", 0);\r
611\r
612 //\r
613 // The _ModuleEntryPoint err out var is legal.\r
614 //\r
615 BdsLibConnectConsoleVariable (L"ErrOut");\r
616\r
617 SystemTableUpdated = FALSE;\r
618 //\r
619 // Fill console handles in System Table if no console device assignd.\r
620 //\r
621 if (UpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) {\r
622 SystemTableUpdated = TRUE;\r
623 }\r
624 if (UpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) {\r
625 SystemTableUpdated = TRUE;\r
626 }\r
627\r
406ddad3 628 if (SystemTableUpdated) {\r
629 //\r
630 // Update the CRC32 in the EFI System Table header\r
631 //\r
632 gST->Hdr.CRC32 = 0;\r
633 gBS->CalculateCrc32 (\r
634 (UINT8 *) &gST->Hdr,\r
635 gST->Hdr.HeaderSize,\r
636 &gST->Hdr.CRC32\r
637 );\r
638 }\r
dad60833 639\r
5c08e117 640 return EFI_SUCCESS;\r
641\r
642}\r
643\r
5c08e117 644/**\r
24cdd14e
LG
645 Use SystemTable Conout to stop video based Simple Text Out consoles from going\r
646 to the video device. Put up LogoFile on every video device that is a console.\r
5c08e117 647\r
648 @param[in] LogoFile File name of logo to display on the center of the screen.\r
649\r
650 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.\r
651 @retval EFI_UNSUPPORTED Logo not found\r
652\r
653**/\r
654EFI_STATUS\r
655EFIAPI\r
656EnableQuietBoot (\r
657 IN EFI_GUID *LogoFile\r
658 )\r
659{\r
660 EFI_STATUS Status;\r
5c08e117 661 EFI_OEM_BADGING_PROTOCOL *Badging;\r
662 UINT32 SizeOfX;\r
663 UINT32 SizeOfY;\r
664 INTN DestX;\r
665 INTN DestY;\r
666 UINT8 *ImageData;\r
667 UINTN ImageSize;\r
668 UINTN BltSize;\r
669 UINT32 Instance;\r
670 EFI_BADGING_FORMAT Format;\r
671 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;\r
672 UINTN CoordinateX;\r
673 UINTN CoordinateY;\r
674 UINTN Height;\r
675 UINTN Width;\r
676 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
677 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
678 UINT32 ColorDepth;\r
679 UINT32 RefreshRate;\r
680 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
a637802c 681 EFI_BOOT_LOGO_PROTOCOL *BootLogo;\r
682 UINTN NumberOfLogos;\r
683 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt;\r
684 UINTN LogoDestX;\r
685 UINTN LogoDestY;\r
686 UINTN LogoHeight;\r
687 UINTN LogoWidth;\r
688 UINTN NewDestX;\r
689 UINTN NewDestY;\r
690 UINTN NewHeight;\r
691 UINTN NewWidth;\r
a46c3657 692 UINT64 BufferSize;\r
5c08e117 693\r
5c08e117 694 UgaDraw = NULL;\r
695 //\r
696 // Try to open GOP first\r
697 //\r
698 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);\r
699 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
700 GraphicsOutput = NULL;\r
701 //\r
702 // Open GOP failed, try to open UGA\r
703 //\r
704 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);\r
705 }\r
706 if (EFI_ERROR (Status)) {\r
707 return EFI_UNSUPPORTED;\r
708 }\r
709\r
a637802c 710 //\r
711 // Try to open Boot Logo Protocol.\r
712 //\r
713 BootLogo = NULL;\r
714 gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);\r
715\r
5c08e117 716 //\r
5d7c1609 717 // Erase Cursor from screen\r
5c08e117 718 //\r
5d7c1609 719 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
720\r
721 Badging = NULL;\r
722 Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);\r
5c08e117 723\r
724 if (GraphicsOutput != NULL) {\r
725 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
726 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
727\r
728 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
729 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);\r
730 if (EFI_ERROR (Status)) {\r
731 return EFI_UNSUPPORTED;\r
732 }\r
733 } else {\r
734 return EFI_UNSUPPORTED;\r
735 }\r
736\r
a637802c 737 Blt = NULL;\r
738 NumberOfLogos = 0;\r
739 LogoDestX = 0;\r
740 LogoDestY = 0;\r
741 LogoHeight = 0;\r
742 LogoWidth = 0;\r
743 NewDestX = 0;\r
744 NewDestY = 0;\r
745 NewHeight = 0;\r
746 NewWidth = 0;\r
5c08e117 747 Instance = 0;\r
748 while (1) {\r
749 ImageData = NULL;\r
750 ImageSize = 0;\r
751\r
752 if (Badging != NULL) {\r
753 //\r
754 // Get image from OEMBadging protocol.\r
755 //\r
756 Status = Badging->GetImage (\r
757 Badging,\r
758 &Instance,\r
759 &Format,\r
760 &ImageData,\r
761 &ImageSize,\r
762 &Attribute,\r
763 &CoordinateX,\r
764 &CoordinateY\r
765 );\r
766 if (EFI_ERROR (Status)) {\r
a637802c 767 goto Done;\r
5c08e117 768 }\r
769\r
770 //\r
771 // Currently only support BMP format.\r
772 //\r
773 if (Format != EfiBadgingFormatBMP) {\r
774 if (ImageData != NULL) {\r
775 FreePool (ImageData);\r
776 }\r
777 continue;\r
778 }\r
779 } else {\r
780 //\r
781 // Get the specified image from FV.\r
782 //\r
783 Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);\r
784 if (EFI_ERROR (Status)) {\r
785 return EFI_UNSUPPORTED;\r
786 }\r
787\r
788 CoordinateX = 0;\r
789 CoordinateY = 0;\r
2df686c6 790 if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {\r
791 Attribute = EfiBadgingDisplayAttributeCenter;\r
792 } else {\r
793 Attribute = EfiBadgingDisplayAttributeCustomized;\r
0a6f4824 794 }\r
5c08e117 795 }\r
796\r
a637802c 797 if (Blt != NULL) {\r
798 FreePool (Blt);\r
799 }\r
5c08e117 800 Blt = NULL;\r
53473721 801 Status = TranslateBmpToGopBlt (\r
5c08e117 802 ImageData,\r
803 ImageSize,\r
53473721 804 &Blt,\r
5c08e117 805 &BltSize,\r
806 &Height,\r
807 &Width\r
808 );\r
809 if (EFI_ERROR (Status)) {\r
810 FreePool (ImageData);\r
811\r
812 if (Badging == NULL) {\r
813 return Status;\r
814 } else {\r
815 continue;\r
816 }\r
817 }\r
818\r
819 //\r
820 // Calculate the display position according to Attribute.\r
821 //\r
822 switch (Attribute) {\r
823 case EfiBadgingDisplayAttributeLeftTop:\r
824 DestX = CoordinateX;\r
825 DestY = CoordinateY;\r
826 break;\r
827\r
828 case EfiBadgingDisplayAttributeCenterTop:\r
829 DestX = (SizeOfX - Width) / 2;\r
830 DestY = CoordinateY;\r
831 break;\r
832\r
833 case EfiBadgingDisplayAttributeRightTop:\r
834 DestX = (SizeOfX - Width - CoordinateX);\r
835 DestY = CoordinateY;;\r
836 break;\r
837\r
838 case EfiBadgingDisplayAttributeCenterRight:\r
839 DestX = (SizeOfX - Width - CoordinateX);\r
840 DestY = (SizeOfY - Height) / 2;\r
841 break;\r
842\r
843 case EfiBadgingDisplayAttributeRightBottom:\r
844 DestX = (SizeOfX - Width - CoordinateX);\r
845 DestY = (SizeOfY - Height - CoordinateY);\r
846 break;\r
847\r
848 case EfiBadgingDisplayAttributeCenterBottom:\r
849 DestX = (SizeOfX - Width) / 2;\r
850 DestY = (SizeOfY - Height - CoordinateY);\r
851 break;\r
852\r
853 case EfiBadgingDisplayAttributeLeftBottom:\r
854 DestX = CoordinateX;\r
855 DestY = (SizeOfY - Height - CoordinateY);\r
856 break;\r
857\r
858 case EfiBadgingDisplayAttributeCenterLeft:\r
859 DestX = CoordinateX;\r
860 DestY = (SizeOfY - Height) / 2;\r
861 break;\r
862\r
863 case EfiBadgingDisplayAttributeCenter:\r
864 DestX = (SizeOfX - Width) / 2;\r
865 DestY = (SizeOfY - Height) / 2;\r
866 break;\r
867\r
2df686c6 868 case EfiBadgingDisplayAttributeCustomized:\r
869 DestX = (SizeOfX - Width) / 2;\r
870 DestY = ((SizeOfY * 382) / 1000) - Height / 2;\r
871 break;\r
872\r
5c08e117 873 default:\r
874 DestX = CoordinateX;\r
875 DestY = CoordinateY;\r
876 break;\r
877 }\r
878\r
879 if ((DestX >= 0) && (DestY >= 0)) {\r
880 if (GraphicsOutput != NULL) {\r
881 Status = GraphicsOutput->Blt (\r
882 GraphicsOutput,\r
883 Blt,\r
884 EfiBltBufferToVideo,\r
885 0,\r
886 0,\r
887 (UINTN) DestX,\r
888 (UINTN) DestY,\r
889 Width,\r
890 Height,\r
891 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
892 );\r
893 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
894 Status = UgaDraw->Blt (\r
895 UgaDraw,\r
896 (EFI_UGA_PIXEL *) Blt,\r
897 EfiUgaBltBufferToVideo,\r
898 0,\r
899 0,\r
900 (UINTN) DestX,\r
901 (UINTN) DestY,\r
902 Width,\r
903 Height,\r
904 Width * sizeof (EFI_UGA_PIXEL)\r
905 );\r
906 } else {\r
a637802c 907 Status = EFI_UNSUPPORTED;\r
908 }\r
909\r
910 //\r
911 // Report displayed Logo information.\r
912 //\r
913 if (!EFI_ERROR (Status)) {\r
914 NumberOfLogos++;\r
915\r
916 if (LogoWidth == 0) {\r
917 //\r
918 // The first Logo.\r
919 //\r
6ba8465f 920 LogoDestX = (UINTN) DestX;\r
921 LogoDestY = (UINTN) DestY;\r
a637802c 922 LogoWidth = Width;\r
923 LogoHeight = Height;\r
924 } else {\r
925 //\r
926 // Merge new logo with old one.\r
927 //\r
928 NewDestX = MIN ((UINTN) DestX, LogoDestX);\r
929 NewDestY = MIN ((UINTN) DestY, LogoDestY);\r
930 NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX;\r
931 NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY;\r
932\r
933 LogoDestX = NewDestX;\r
934 LogoDestY = NewDestY;\r
935 LogoWidth = NewWidth;\r
936 LogoHeight = NewHeight;\r
937 }\r
5c08e117 938 }\r
939 }\r
940\r
941 FreePool (ImageData);\r
942\r
a637802c 943 if (Badging == NULL) {\r
944 break;\r
945 }\r
946 }\r
947\r
948Done:\r
949 if (BootLogo == NULL || NumberOfLogos == 0) {\r
950 //\r
951 // No logo displayed.\r
952 //\r
5c08e117 953 if (Blt != NULL) {\r
954 FreePool (Blt);\r
955 }\r
956\r
a637802c 957 return Status;\r
958 }\r
959\r
960 //\r
961 // Advertise displayed Logo information.\r
962 //\r
963 if (NumberOfLogos == 1) {\r
964 //\r
965 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.\r
966 //\r
967 LogoBlt = Blt;\r
968 Status = EFI_SUCCESS;\r
969 } else {\r
970 //\r
0a6f4824 971 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.\r
a637802c 972 //\r
973 if (Blt != NULL) {\r
974 FreePool (Blt);\r
975 }\r
976\r
a46c3657
ED
977 //\r
978 // Ensure the LogoHeight * LogoWidth doesn't overflow\r
979 //\r
980 if (LogoHeight > DivU64x64Remainder ((UINTN) ~0, LogoWidth, NULL)) {\r
981 return EFI_UNSUPPORTED;\r
982 }\r
983 BufferSize = MultU64x64 (LogoWidth, LogoHeight);\r
984\r
985 //\r
986 // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow\r
987 //\r
988 if (BufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {\r
989 return EFI_UNSUPPORTED;\r
990 }\r
991\r
992 LogoBlt = AllocateZeroPool ((UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
a637802c 993 if (LogoBlt == NULL) {\r
994 return EFI_OUT_OF_RESOURCES;\r
995 }\r
996\r
997 if (GraphicsOutput != NULL) {\r
998 Status = GraphicsOutput->Blt (\r
999 GraphicsOutput,\r
1000 LogoBlt,\r
1001 EfiBltVideoToBltBuffer,\r
1002 LogoDestX,\r
1003 LogoDestY,\r
1004 0,\r
1005 0,\r
1006 LogoWidth,\r
1007 LogoHeight,\r
1008 LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
1009 );\r
1010 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
1011 Status = UgaDraw->Blt (\r
1012 UgaDraw,\r
1013 (EFI_UGA_PIXEL *) LogoBlt,\r
1014 EfiUgaVideoToBltBuffer,\r
1015 LogoDestX,\r
1016 LogoDestY,\r
1017 0,\r
1018 0,\r
1019 LogoWidth,\r
1020 LogoHeight,\r
1021 LogoWidth * sizeof (EFI_UGA_PIXEL)\r
1022 );\r
1023 } else {\r
1024 Status = EFI_UNSUPPORTED;\r
5c08e117 1025 }\r
1026 }\r
1027\r
a637802c 1028 if (!EFI_ERROR (Status)) {\r
1029 BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight);\r
1030 }\r
1031 FreePool (LogoBlt);\r
1032\r
5c08e117 1033 return Status;\r
1034}\r
1035\r
1036/**\r
0a6f4824 1037 Use SystemTable Conout to turn on video based Simple Text Out consoles. The\r
24cdd14e 1038 Simple Text Out screens will now be synced up with all non video output devices\r
5c08e117 1039\r
1040 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.\r
1041\r
1042**/\r
1043EFI_STATUS\r
1044EFIAPI\r
1045DisableQuietBoot (\r
1046 VOID\r
1047 )\r
1048{\r
5c08e117 1049\r
1050 //\r
5d7c1609 1051 // Enable Cursor on Screen\r
5c08e117 1052 //\r
5d7c1609 1053 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
1054 return EFI_SUCCESS;\r
5c08e117 1055}\r
1056\r