]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/PlatformBootManagerLib/PlatformBm.c
ArmPkg/PlatformBootManagerLib: use static assertion for console type
[mirror_edk2.git] / ArmPkg / Library / PlatformBootManagerLib / PlatformBm.c
CommitLineData
c976f9cb
AB
1/** @file\r
2 Implementation for PlatformBootManagerLib library class interfaces.\r
3\r
4 Copyright (C) 2015-2016, Red Hat, Inc.\r
0f9395d7 5 Copyright (c) 2014 - 2019, ARM Ltd. All rights reserved.<BR>\r
eea668c9 6 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
c976f9cb
AB
7 Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>\r
8\r
4059386c 9 SPDX-License-Identifier: BSD-2-Clause-Patent\r
c976f9cb
AB
10\r
11**/\r
12\r
13#include <IndustryStandard/Pci22.h>\r
a43d75e1 14#include <Library/BootLogoLib.h>\r
4bbcc285 15#include <Library/CapsuleLib.h>\r
c976f9cb 16#include <Library/DevicePathLib.h>\r
4bbcc285 17#include <Library/HobLib.h>\r
c976f9cb
AB
18#include <Library/PcdLib.h>\r
19#include <Library/UefiBootManagerLib.h>\r
20#include <Library/UefiLib.h>\r
cae82316 21#include <Library/UefiRuntimeServicesTableLib.h>\r
c976f9cb 22#include <Protocol/DevicePath.h>\r
13ca0abb 23#include <Protocol/EsrtManagement.h>\r
c976f9cb
AB
24#include <Protocol/GraphicsOutput.h>\r
25#include <Protocol/LoadedImage.h>\r
26#include <Protocol/PciIo.h>\r
27#include <Protocol/PciRootBridgeIo.h>\r
1b6e7633 28#include <Protocol/PlatformBootManager.h>\r
c976f9cb
AB
29#include <Guid/EventGroup.h>\r
30#include <Guid/TtyTerm.h>\r
6631c096 31#include <Guid/SerialPortLibVendor.h>\r
c976f9cb
AB
32\r
33#include "PlatformBm.h"\r
34\r
35#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }\r
36\r
c976f9cb
AB
37#pragma pack (1)\r
38typedef struct {\r
39 VENDOR_DEVICE_PATH SerialDxe;\r
40 UART_DEVICE_PATH Uart;\r
41 VENDOR_DEFINED_DEVICE_PATH TermType;\r
42 EFI_DEVICE_PATH_PROTOCOL End;\r
43} PLATFORM_SERIAL_CONSOLE;\r
44#pragma pack ()\r
45\r
c976f9cb
AB
46STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {\r
47 //\r
48 // VENDOR_DEVICE_PATH SerialDxe\r
49 //\r
50 {\r
51 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },\r
6631c096 52 EDKII_SERIAL_PORT_LIB_VENDOR_GUID\r
c976f9cb
AB
53 },\r
54\r
55 //\r
56 // UART_DEVICE_PATH Uart\r
57 //\r
58 {\r
59 { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) },\r
60 0, // Reserved\r
61 FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate\r
62 FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits\r
63 FixedPcdGet8 (PcdUartDefaultParity), // Parity\r
64 FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits\r
65 },\r
66\r
67 //\r
68 // VENDOR_DEFINED_DEVICE_PATH TermType\r
69 //\r
70 {\r
71 {\r
72 MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,\r
73 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)\r
74 }\r
75 //\r
76 // Guid to be filled in dynamically\r
77 //\r
78 },\r
79\r
80 //\r
81 // EFI_DEVICE_PATH_PROTOCOL End\r
82 //\r
83 {\r
84 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
85 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
86 }\r
87};\r
88\r
89\r
90#pragma pack (1)\r
91typedef struct {\r
92 USB_CLASS_DEVICE_PATH Keyboard;\r
93 EFI_DEVICE_PATH_PROTOCOL End;\r
94} PLATFORM_USB_KEYBOARD;\r
95#pragma pack ()\r
96\r
97STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {\r
98 //\r
99 // USB_CLASS_DEVICE_PATH Keyboard\r
100 //\r
101 {\r
102 {\r
103 MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,\r
104 DP_NODE_LEN (USB_CLASS_DEVICE_PATH)\r
105 },\r
106 0xFFFF, // VendorId: any\r
107 0xFFFF, // ProductId: any\r
108 3, // DeviceClass: HID\r
109 1, // DeviceSubClass: boot\r
110 1 // DeviceProtocol: keyboard\r
111 },\r
112\r
113 //\r
114 // EFI_DEVICE_PATH_PROTOCOL End\r
115 //\r
116 {\r
117 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
118 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
119 }\r
120};\r
121\r
122\r
123/**\r
124 Check if the handle satisfies a particular condition.\r
125\r
126 @param[in] Handle The handle to check.\r
127 @param[in] ReportText A caller-allocated string passed in for reporting\r
128 purposes. It must never be NULL.\r
129\r
130 @retval TRUE The condition is satisfied.\r
131 @retval FALSE Otherwise. This includes the case when the condition could not\r
132 be fully evaluated due to an error.\r
133**/\r
134typedef\r
135BOOLEAN\r
136(EFIAPI *FILTER_FUNCTION) (\r
137 IN EFI_HANDLE Handle,\r
138 IN CONST CHAR16 *ReportText\r
139 );\r
140\r
141\r
142/**\r
143 Process a handle.\r
144\r
145 @param[in] Handle The handle to process.\r
146 @param[in] ReportText A caller-allocated string passed in for reporting\r
147 purposes. It must never be NULL.\r
148**/\r
149typedef\r
150VOID\r
151(EFIAPI *CALLBACK_FUNCTION) (\r
152 IN EFI_HANDLE Handle,\r
153 IN CONST CHAR16 *ReportText\r
154 );\r
155\r
156/**\r
157 Locate all handles that carry the specified protocol, filter them with a\r
158 callback function, and pass each handle that passes the filter to another\r
159 callback.\r
160\r
161 @param[in] ProtocolGuid The protocol to look for.\r
162\r
163 @param[in] Filter The filter function to pass each handle to. If this\r
164 parameter is NULL, then all handles are processed.\r
165\r
166 @param[in] Process The callback function to pass each handle to that\r
167 clears the filter.\r
168**/\r
169STATIC\r
170VOID\r
171FilterAndProcess (\r
172 IN EFI_GUID *ProtocolGuid,\r
173 IN FILTER_FUNCTION Filter OPTIONAL,\r
174 IN CALLBACK_FUNCTION Process\r
175 )\r
176{\r
177 EFI_STATUS Status;\r
178 EFI_HANDLE *Handles;\r
179 UINTN NoHandles;\r
180 UINTN Idx;\r
181\r
182 Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid,\r
183 NULL /* SearchKey */, &NoHandles, &Handles);\r
184 if (EFI_ERROR (Status)) {\r
185 //\r
186 // This is not an error, just an informative condition.\r
187 //\r
188 DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid,\r
189 Status));\r
190 return;\r
191 }\r
192\r
193 ASSERT (NoHandles > 0);\r
194 for (Idx = 0; Idx < NoHandles; ++Idx) {\r
195 CHAR16 *DevicePathText;\r
196 STATIC CHAR16 Fallback[] = L"<device path unavailable>";\r
197\r
198 //\r
199 // The ConvertDevicePathToText() function handles NULL input transparently.\r
200 //\r
201 DevicePathText = ConvertDevicePathToText (\r
202 DevicePathFromHandle (Handles[Idx]),\r
203 FALSE, // DisplayOnly\r
204 FALSE // AllowShortcuts\r
205 );\r
206 if (DevicePathText == NULL) {\r
207 DevicePathText = Fallback;\r
208 }\r
209\r
210 if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) {\r
211 Process (Handles[Idx], DevicePathText);\r
212 }\r
213\r
214 if (DevicePathText != Fallback) {\r
215 FreePool (DevicePathText);\r
216 }\r
217 }\r
218 gBS->FreePool (Handles);\r
219}\r
220\r
221\r
222/**\r
223 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.\r
224**/\r
225STATIC\r
226BOOLEAN\r
227EFIAPI\r
228IsPciDisplay (\r
229 IN EFI_HANDLE Handle,\r
230 IN CONST CHAR16 *ReportText\r
231 )\r
232{\r
233 EFI_STATUS Status;\r
234 EFI_PCI_IO_PROTOCOL *PciIo;\r
235 PCI_TYPE00 Pci;\r
236\r
237 Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid,\r
238 (VOID**)&PciIo);\r
239 if (EFI_ERROR (Status)) {\r
240 //\r
241 // This is not an error worth reporting.\r
242 //\r
243 return FALSE;\r
244 }\r
245\r
246 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */,\r
247 sizeof Pci / sizeof (UINT32), &Pci);\r
248 if (EFI_ERROR (Status)) {\r
249 DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));\r
250 return FALSE;\r
251 }\r
252\r
253 return IS_PCI_DISPLAY (&Pci);\r
254}\r
255\r
256\r
257/**\r
258 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking\r
259 the matching driver to produce all first-level child handles.\r
260**/\r
261STATIC\r
262VOID\r
263EFIAPI\r
264Connect (\r
265 IN EFI_HANDLE Handle,\r
266 IN CONST CHAR16 *ReportText\r
267 )\r
268{\r
269 EFI_STATUS Status;\r
270\r
271 Status = gBS->ConnectController (\r
272 Handle, // ControllerHandle\r
273 NULL, // DriverImageHandle\r
274 NULL, // RemainingDevicePath -- produce all children\r
275 FALSE // Recursive\r
276 );\r
277 DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n",\r
278 __FUNCTION__, ReportText, Status));\r
279}\r
280\r
281\r
282/**\r
283 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the\r
284 handle, and adds it to ConOut and ErrOut.\r
285**/\r
286STATIC\r
287VOID\r
288EFIAPI\r
289AddOutput (\r
290 IN EFI_HANDLE Handle,\r
291 IN CONST CHAR16 *ReportText\r
292 )\r
293{\r
294 EFI_STATUS Status;\r
295 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
296\r
297 DevicePath = DevicePathFromHandle (Handle);\r
298 if (DevicePath == NULL) {\r
299 DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n",\r
300 __FUNCTION__, ReportText, Handle));\r
301 return;\r
302 }\r
303\r
304 Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
305 if (EFI_ERROR (Status)) {\r
306 DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__,\r
307 ReportText, Status));\r
308 return;\r
309 }\r
310\r
311 Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
312 if (EFI_ERROR (Status)) {\r
313 DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__,\r
314 ReportText, Status));\r
315 return;\r
316 }\r
317\r
318 DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__,\r
319 ReportText));\r
320}\r
321\r
322STATIC\r
323VOID\r
324PlatformRegisterFvBootOption (\r
07548e17 325 CONST EFI_GUID *FileGuid,\r
c976f9cb
AB
326 CHAR16 *Description,\r
327 UINT32 Attributes\r
328 )\r
329{\r
330 EFI_STATUS Status;\r
331 INTN OptionIndex;\r
332 EFI_BOOT_MANAGER_LOAD_OPTION NewOption;\r
333 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
334 UINTN BootOptionCount;\r
335 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;\r
336 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
337 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
338\r
339 Status = gBS->HandleProtocol (\r
340 gImageHandle,\r
341 &gEfiLoadedImageProtocolGuid,\r
342 (VOID **) &LoadedImage\r
343 );\r
344 ASSERT_EFI_ERROR (Status);\r
345\r
346 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);\r
347 DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);\r
348 ASSERT (DevicePath != NULL);\r
349 DevicePath = AppendDevicePathNode (\r
350 DevicePath,\r
351 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
352 );\r
353 ASSERT (DevicePath != NULL);\r
354\r
355 Status = EfiBootManagerInitializeLoadOption (\r
356 &NewOption,\r
357 LoadOptionNumberUnassigned,\r
358 LoadOptionTypeBoot,\r
359 Attributes,\r
360 Description,\r
361 DevicePath,\r
362 NULL,\r
363 0\r
364 );\r
365 ASSERT_EFI_ERROR (Status);\r
366 FreePool (DevicePath);\r
367\r
368 BootOptions = EfiBootManagerGetLoadOptions (\r
369 &BootOptionCount, LoadOptionTypeBoot\r
370 );\r
371\r
372 OptionIndex = EfiBootManagerFindLoadOption (\r
373 &NewOption, BootOptions, BootOptionCount\r
374 );\r
375\r
376 if (OptionIndex == -1) {\r
377 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);\r
378 ASSERT_EFI_ERROR (Status);\r
379 }\r
380 EfiBootManagerFreeLoadOption (&NewOption);\r
381 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
382}\r
383\r
384\r
1b6e7633
HZ
385STATIC\r
386VOID\r
387GetPlatformOptions (\r
388 VOID\r
389 )\r
390{\r
391 EFI_STATUS Status;\r
392 EFI_BOOT_MANAGER_LOAD_OPTION *CurrentBootOptions;\r
393 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
394 EFI_INPUT_KEY *BootKeys;\r
395 PLATFORM_BOOT_MANAGER_PROTOCOL *PlatformBootManager;\r
396 UINTN CurrentBootOptionCount;\r
397 UINTN Index;\r
398 UINTN BootCount;\r
399\r
400 Status = gBS->LocateProtocol (&gPlatformBootManagerProtocolGuid, NULL,\r
401 (VOID **)&PlatformBootManager);\r
402 if (EFI_ERROR (Status)) {\r
403 return;\r
404 }\r
405 Status = PlatformBootManager->GetPlatformBootOptionsAndKeys (\r
406 &BootCount,\r
407 &BootOptions,\r
408 &BootKeys\r
409 );\r
410 if (EFI_ERROR (Status)) {\r
411 return;\r
412 }\r
413 //\r
414 // Fetch the existent boot options. If there are none, CurrentBootCount\r
415 // will be zeroed.\r
416 //\r
417 CurrentBootOptions = EfiBootManagerGetLoadOptions (\r
418 &CurrentBootOptionCount,\r
419 LoadOptionTypeBoot\r
420 );\r
421 //\r
422 // Process the platform boot options.\r
423 //\r
424 for (Index = 0; Index < BootCount; Index++) {\r
425 INTN Match;\r
426 UINTN BootOptionNumber;\r
427\r
428 //\r
429 // If there are any preexistent boot options, and the subject platform boot\r
430 // option is already among them, then don't try to add it. Just get its\r
431 // assigned boot option number so we can associate a hotkey with it. Note\r
432 // that EfiBootManagerFindLoadOption() deals fine with (CurrentBootOptions\r
433 // == NULL) if (CurrentBootCount == 0).\r
434 //\r
435 Match = EfiBootManagerFindLoadOption (\r
436 &BootOptions[Index],\r
437 CurrentBootOptions,\r
438 CurrentBootOptionCount\r
439 );\r
440 if (Match >= 0) {\r
441 BootOptionNumber = CurrentBootOptions[Match].OptionNumber;\r
442 } else {\r
443 //\r
444 // Add the platform boot options as a new one, at the end of the boot\r
445 // order. Note that if the platform provided this boot option with an\r
446 // unassigned option number, then the below function call will assign a\r
447 // number.\r
448 //\r
449 Status = EfiBootManagerAddLoadOptionVariable (\r
450 &BootOptions[Index],\r
451 MAX_UINTN\r
452 );\r
453 if (EFI_ERROR (Status)) {\r
454 DEBUG ((DEBUG_ERROR, "%a: failed to register \"%s\": %r\n",\r
455 __FUNCTION__, BootOptions[Index].Description, Status));\r
456 continue;\r
457 }\r
458 BootOptionNumber = BootOptions[Index].OptionNumber;\r
459 }\r
460\r
461 //\r
462 // Register a hotkey with the boot option, if requested.\r
463 //\r
464 if (BootKeys[Index].UnicodeChar == L'\0') {\r
465 continue;\r
466 }\r
467\r
468 Status = EfiBootManagerAddKeyOptionVariable (\r
469 NULL,\r
470 BootOptionNumber,\r
471 0,\r
2b2959dd 472 &BootKeys[Index],\r
1b6e7633
HZ
473 NULL\r
474 );\r
475 if (EFI_ERROR (Status)) {\r
476 DEBUG ((DEBUG_ERROR, "%a: failed to register hotkey for \"%s\": %r\n",\r
477 __FUNCTION__, BootOptions[Index].Description, Status));\r
478 }\r
479 }\r
480 EfiBootManagerFreeLoadOptions (CurrentBootOptions, CurrentBootOptionCount);\r
481 EfiBootManagerFreeLoadOptions (BootOptions, BootCount);\r
482 FreePool (BootKeys);\r
483}\r
484\r
c976f9cb
AB
485STATIC\r
486VOID\r
487PlatformRegisterOptionsAndKeys (\r
488 VOID\r
489 )\r
490{\r
491 EFI_STATUS Status;\r
492 EFI_INPUT_KEY Enter;\r
493 EFI_INPUT_KEY F2;\r
494 EFI_INPUT_KEY Esc;\r
495 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
496\r
1b6e7633
HZ
497 GetPlatformOptions ();\r
498\r
c976f9cb
AB
499 //\r
500 // Register ENTER as CONTINUE key\r
501 //\r
502 Enter.ScanCode = SCAN_NULL;\r
503 Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
504 Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);\r
505 ASSERT_EFI_ERROR (Status);\r
506\r
507 //\r
508 // Map F2 and ESC to Boot Manager Menu\r
509 //\r
510 F2.ScanCode = SCAN_F2;\r
511 F2.UnicodeChar = CHAR_NULL;\r
512 Esc.ScanCode = SCAN_ESC;\r
513 Esc.UnicodeChar = CHAR_NULL;\r
514 Status = EfiBootManagerGetBootManagerMenu (&BootOption);\r
515 ASSERT_EFI_ERROR (Status);\r
516 Status = EfiBootManagerAddKeyOptionVariable (\r
517 NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL\r
518 );\r
519 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
520 Status = EfiBootManagerAddKeyOptionVariable (\r
521 NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL\r
522 );\r
523 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
524}\r
525\r
526\r
527//\r
528// BDS Platform Functions\r
529//\r
530/**\r
531 Do the platform init, can be customized by OEM/IBV\r
532 Possible things that can be done in PlatformBootManagerBeforeConsole:\r
533 > Update console variable: 1. include hot-plug devices;\r
534 > 2. Clear ConIn and add SOL for AMT\r
535 > Register new Driver#### or Boot####\r
536 > Register new Key####: e.g.: F12\r
537 > Signal ReadyToLock event\r
538 > Authentication action: 1. connect Auth devices;\r
539 > 2. Identify auto logon user.\r
540**/\r
541VOID\r
542EFIAPI\r
543PlatformBootManagerBeforeConsole (\r
544 VOID\r
545 )\r
546{\r
547 //\r
548 // Signal EndOfDxe PI Event\r
549 //\r
550 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
551\r
0f9395d7
SM
552 //\r
553 // Dispatch deferred images after EndOfDxe event.\r
554 //\r
555 EfiBootManagerDispatchDeferredImages ();\r
556\r
c976f9cb
AB
557 //\r
558 // Locate the PCI root bridges and make the PCI bus driver connect each,\r
559 // non-recursively. This will produce a number of child handles with PciIo on\r
560 // them.\r
561 //\r
562 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);\r
563\r
564 //\r
565 // Find all display class PCI devices (using the handles from the previous\r
566 // step), and connect them non-recursively. This should produce a number of\r
567 // child handles with GOPs on them.\r
568 //\r
569 FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);\r
570\r
571 //\r
572 // Now add the device path of all handles with GOP on them to ConOut and\r
573 // ErrOut.\r
574 //\r
575 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);\r
576\r
577 //\r
578 // Add the hardcoded short-form USB keyboard device path to ConIn.\r
579 //\r
580 EfiBootManagerUpdateConsoleVariable (ConIn,\r
581 (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL);\r
582\r
583 //\r
584 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.\r
585 //\r
b1d3895f
AB
586 STATIC_ASSERT (FixedPcdGet8 (PcdDefaultTerminalType) == 4,\r
587 "PcdDefaultTerminalType must be TTYTERM");\r
588\r
c976f9cb
AB
589 CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid);\r
590\r
591 EfiBootManagerUpdateConsoleVariable (ConIn,\r
592 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
593 EfiBootManagerUpdateConsoleVariable (ConOut,\r
594 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
595 EfiBootManagerUpdateConsoleVariable (ErrOut,\r
596 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
597\r
598 //\r
599 // Register platform-specific boot options and keyboard shortcuts.\r
600 //\r
601 PlatformRegisterOptionsAndKeys ();\r
602}\r
603\r
cae82316
AB
604STATIC\r
605VOID\r
606HandleCapsules (\r
607 VOID\r
608 )\r
609{\r
610 ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;\r
611 EFI_PEI_HOB_POINTERS HobPointer;\r
612 EFI_CAPSULE_HEADER *CapsuleHeader;\r
613 BOOLEAN NeedReset;\r
614 EFI_STATUS Status;\r
615\r
616 DEBUG ((DEBUG_INFO, "%a: processing capsules ...\n", __FUNCTION__));\r
617\r
618 Status = gBS->LocateProtocol (&gEsrtManagementProtocolGuid, NULL,\r
619 (VOID **)&EsrtManagement);\r
620 if (!EFI_ERROR (Status)) {\r
621 EsrtManagement->SyncEsrtFmp ();\r
622 }\r
623\r
624 //\r
625 // Find all capsule images from hob\r
626 //\r
627 HobPointer.Raw = GetHobList ();\r
628 NeedReset = FALSE;\r
629 while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE,\r
630 HobPointer.Raw)) != NULL) {\r
631 CapsuleHeader = (VOID *)(UINTN)HobPointer.Capsule->BaseAddress;\r
632\r
633 Status = ProcessCapsuleImage (CapsuleHeader);\r
634 if (EFI_ERROR (Status)) {\r
635 DEBUG ((DEBUG_ERROR, "%a: failed to process capsule %p - %r\n",\r
636 __FUNCTION__, CapsuleHeader, Status));\r
637 return;\r
638 }\r
639\r
640 NeedReset = TRUE;\r
641 HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
642 }\r
643\r
644 if (NeedReset) {\r
645 DEBUG ((DEBUG_WARN, "%a: capsule update successful, resetting ...\n",\r
646 __FUNCTION__));\r
647\r
648 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
649 CpuDeadLoop();\r
650 }\r
651}\r
652\r
653\r
6c4194c9
AB
654#define VERSION_STRING_PREFIX L"Tianocore/EDK2 firmware version "\r
655\r
c976f9cb
AB
656/**\r
657 Do the platform specific action after the console is ready\r
658 Possible things that can be done in PlatformBootManagerAfterConsole:\r
659 > Console post action:\r
ff5fef14 660 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario\r
c976f9cb
AB
661 > Signal console ready platform customized event\r
662 > Run diagnostics like memory testing\r
663 > Connect certain devices\r
ff5fef14 664 > Dispatch additional option roms\r
c976f9cb
AB
665 > Special boot: e.g.: USB boot, enter UI\r
666**/\r
667VOID\r
668EFIAPI\r
669PlatformBootManagerAfterConsole (\r
670 VOID\r
671 )\r
672{\r
13ca0abb 673 EFI_STATUS Status;\r
6c4194c9
AB
674 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
675 UINTN FirmwareVerLength;\r
676 UINTN PosX;\r
677 UINTN PosY;\r
678\r
679 FirmwareVerLength = StrLen (PcdGetPtr (PcdFirmwareVersionString));\r
c976f9cb
AB
680\r
681 //\r
682 // Show the splash screen.\r
683 //\r
a43d75e1
AB
684 Status = BootLogoEnableLogo ();\r
685 if (EFI_ERROR (Status)) {\r
6c4194c9 686 if (FirmwareVerLength > 0) {\r
26b99f3b 687 Print (VERSION_STRING_PREFIX L"%s\n",\r
6c4194c9
AB
688 PcdGetPtr (PcdFirmwareVersionString));\r
689 }\r
a43d75e1 690 Print (L"Press ESCAPE for boot options ");\r
6c4194c9
AB
691 } else if (FirmwareVerLength > 0) {\r
692 Status = gBS->HandleProtocol (gST->ConsoleOutHandle,\r
693 &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);\r
694 if (!EFI_ERROR (Status)) {\r
695 PosX = (GraphicsOutput->Mode->Info->HorizontalResolution -\r
696 (StrLen (VERSION_STRING_PREFIX) + FirmwareVerLength) *\r
697 EFI_GLYPH_WIDTH) / 2;\r
698 PosY = 0;\r
699\r
700 PrintXY (PosX, PosY, NULL, NULL, VERSION_STRING_PREFIX L"%s",\r
701 PcdGetPtr (PcdFirmwareVersionString));\r
702 }\r
a43d75e1 703 }\r
6c4194c9 704\r
c976f9cb
AB
705 //\r
706 // Connect the rest of the devices.\r
707 //\r
708 EfiBootManagerConnectAll ();\r
709\r
cae82316
AB
710 //\r
711 // On ARM, there is currently no reason to use the phased capsule\r
712 // update approach where some capsules are dispatched before EndOfDxe\r
713 // and some are dispatched after. So just handle all capsules here,\r
714 // when the console is up and we can actually give the user some\r
715 // feedback about what is going on.\r
716 //\r
717 HandleCapsules ();\r
4bbcc285 718\r
c976f9cb
AB
719 //\r
720 // Enumerate all possible boot options.\r
721 //\r
722 EfiBootManagerRefreshAllBootOption ();\r
723\r
724 //\r
725 // Register UEFI Shell\r
726 //\r
727 PlatformRegisterFvBootOption (\r
07548e17 728 &gUefiShellFileGuid, L"UEFI Shell", LOAD_OPTION_ACTIVE\r
c976f9cb
AB
729 );\r
730}\r
731\r
732/**\r
733 This function is called each second during the boot manager waits the\r
734 timeout.\r
735\r
736 @param TimeoutRemain The remaining timeout.\r
737**/\r
738VOID\r
739EFIAPI\r
740PlatformBootManagerWaitCallback (\r
741 UINT16 TimeoutRemain\r
742 )\r
743{\r
a43d75e1
AB
744 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;\r
745 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;\r
746 UINT16 Timeout;\r
747 EFI_STATUS Status;\r
748\r
749 Timeout = PcdGet16 (PcdPlatformBootTimeOut);\r
750\r
751 Black.Raw = 0x00000000;\r
752 White.Raw = 0x00FFFFFF;\r
753\r
754 Status = BootLogoUpdateProgress (\r
755 White.Pixel,\r
756 Black.Pixel,\r
757 L"Press ESCAPE for boot options",\r
758 White.Pixel,\r
759 (Timeout - TimeoutRemain) * 100 / Timeout,\r
760 0\r
761 );\r
762 if (EFI_ERROR (Status)) {\r
763 Print (L".");\r
764 }\r
c976f9cb 765}\r
eea668c9
RN
766\r
767/**\r
768 The function is called when no boot option could be launched,\r
769 including platform recovery options and options pointing to applications\r
770 built into firmware volumes.\r
771\r
772 If this function returns, BDS attempts to enter an infinite loop.\r
773**/\r
774VOID\r
775EFIAPI\r
776PlatformBootManagerUnableToBoot (\r
777 VOID\r
778 )\r
779{\r
780 return;\r
781}\r