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