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