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