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