1 /** @file 2 Implementation for PlatformBootManagerLib library class interfaces. 3 4 Copyright (C) 2015-2016, Red Hat, Inc. 5 Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> 6 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR> 7 Copyright (c) 2016-2017, Linaro Ltd. All rights reserved.<BR> 8 9 This program and the accompanying materials are licensed and made available 10 under the terms and conditions of the BSD License which accompanies this 11 distribution. The full text of the license may be found at 12 http://opensource.org/licenses/bsd-license.php 13 14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT 15 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 16 17 **/ 18 19 #include <Library/DevicePathLib.h> 20 #include <Library/PcdLib.h> 21 #include <Library/UefiBootManagerLib.h> 22 #include <Library/UefiLib.h> 23 #include <Protocol/BlockIo.h> 24 #include <Protocol/DevicePath.h> 25 #include <Protocol/DevicePathFromText.h> 26 #include <Protocol/DevicePathToText.h> 27 #include <Protocol/GraphicsOutput.h> 28 #include <Protocol/LoadedImage.h> 29 #include <Guid/EventGroup.h> 30 #include <Guid/TtyTerm.h> 31 32 #include "PlatformBm.h" 33 34 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) } 35 36 #define GRUB_FILE_NAME L"\\EFI\\BOOT\\GRUBAA64.EFI" 37 #define SD_FILE_NAME L"\\EFI\\BOOT\\BOOTAA64.EFI" 38 39 40 #pragma pack (1) 41 typedef struct { 42 VENDOR_DEVICE_PATH SerialDxe; 43 UART_DEVICE_PATH Uart; 44 VENDOR_DEFINED_DEVICE_PATH TermType; 45 EFI_DEVICE_PATH_PROTOCOL End; 46 } PLATFORM_SERIAL_CONSOLE; 47 #pragma pack () 48 49 #define SERIAL_DXE_FILE_GUID { \ 50 0xD3987D4B, 0x971A, 0x435F, \ 51 { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \ 52 } 53 54 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = { 55 // 56 // VENDOR_DEVICE_PATH SerialDxe 57 // 58 { 59 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, 60 SERIAL_DXE_FILE_GUID 61 }, 62 63 // 64 // UART_DEVICE_PATH Uart 65 // 66 { 67 { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) }, 68 0, // Reserved 69 FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate 70 FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits 71 FixedPcdGet8 (PcdUartDefaultParity), // Parity 72 FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits 73 }, 74 75 // 76 // VENDOR_DEFINED_DEVICE_PATH TermType 77 // 78 { 79 { 80 MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, 81 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH) 82 } 83 // 84 // Guid to be filled in dynamically 85 // 86 }, 87 88 // 89 // EFI_DEVICE_PATH_PROTOCOL End 90 // 91 { 92 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, 93 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) 94 } 95 }; 96 97 98 #pragma pack (1) 99 typedef struct { 100 USB_CLASS_DEVICE_PATH Keyboard; 101 EFI_DEVICE_PATH_PROTOCOL End; 102 } PLATFORM_USB_KEYBOARD; 103 #pragma pack () 104 105 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = { 106 // 107 // USB_CLASS_DEVICE_PATH Keyboard 108 // 109 { 110 { 111 MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP, 112 DP_NODE_LEN (USB_CLASS_DEVICE_PATH) 113 }, 114 0xFFFF, // VendorId: any 115 0xFFFF, // ProductId: any 116 3, // DeviceClass: HID 117 1, // DeviceSubClass: boot 118 1 // DeviceProtocol: keyboard 119 }, 120 121 // 122 // EFI_DEVICE_PATH_PROTOCOL End 123 // 124 { 125 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, 126 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) 127 } 128 }; 129 130 131 /** 132 Check if the handle satisfies a particular condition. 133 134 @param[in] Handle The handle to check. 135 @param[in] ReportText A caller-allocated string passed in for reporting 136 purposes. It must never be NULL. 137 138 @retval TRUE The condition is satisfied. 139 @retval FALSE Otherwise. This includes the case when the condition could not 140 be fully evaluated due to an error. 141 **/ 142 typedef 143 BOOLEAN 144 (EFIAPI *FILTER_FUNCTION) ( 145 IN EFI_HANDLE Handle, 146 IN CONST CHAR16 *ReportText 147 ); 148 149 150 /** 151 Process a handle. 152 153 @param[in] Handle The handle to process. 154 @param[in] ReportText A caller-allocated string passed in for reporting 155 purposes. It must never be NULL. 156 **/ 157 typedef 158 VOID 159 (EFIAPI *CALLBACK_FUNCTION) ( 160 IN EFI_HANDLE Handle, 161 IN CONST CHAR16 *ReportText 162 ); 163 164 /** 165 Locate all handles that carry the specified protocol, filter them with a 166 callback function, and pass each handle that passes the filter to another 167 callback. 168 169 @param[in] ProtocolGuid The protocol to look for. 170 171 @param[in] Filter The filter function to pass each handle to. If this 172 parameter is NULL, then all handles are processed. 173 174 @param[in] Process The callback function to pass each handle to that 175 clears the filter. 176 **/ 177 STATIC 178 VOID 179 FilterAndProcess ( 180 IN EFI_GUID *ProtocolGuid, 181 IN FILTER_FUNCTION Filter OPTIONAL, 182 IN CALLBACK_FUNCTION Process 183 ) 184 { 185 EFI_STATUS Status; 186 EFI_HANDLE *Handles; 187 UINTN NoHandles; 188 UINTN Idx; 189 190 Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid, 191 NULL /* SearchKey */, &NoHandles, &Handles); 192 if (EFI_ERROR (Status)) { 193 // 194 // This is not an error, just an informative condition. 195 // 196 DEBUG ((DEBUG_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid, 197 Status)); 198 return; 199 } 200 201 ASSERT (NoHandles > 0); 202 for (Idx = 0; Idx < NoHandles; ++Idx) { 203 CHAR16 *DevicePathText; 204 STATIC CHAR16 Fallback[] = L"<device path unavailable>"; 205 206 // 207 // The ConvertDevicePathToText() function handles NULL input transparently. 208 // 209 DevicePathText = ConvertDevicePathToText ( 210 DevicePathFromHandle (Handles[Idx]), 211 FALSE, // DisplayOnly 212 FALSE // AllowShortcuts 213 ); 214 if (DevicePathText == NULL) { 215 DevicePathText = Fallback; 216 } 217 218 if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) { 219 Process (Handles[Idx], DevicePathText); 220 } 221 222 if (DevicePathText != Fallback) { 223 FreePool (DevicePathText); 224 } 225 } 226 gBS->FreePool (Handles); 227 } 228 229 230 /** 231 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the 232 handle, and adds it to ConOut and ErrOut. 233 **/ 234 STATIC 235 VOID 236 EFIAPI 237 AddOutput ( 238 IN EFI_HANDLE Handle, 239 IN CONST CHAR16 *ReportText 240 ) 241 { 242 EFI_STATUS Status; 243 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 244 245 DevicePath = DevicePathFromHandle (Handle); 246 if (DevicePath == NULL) { 247 DEBUG ((DEBUG_ERROR, "%a: %s: handle %p: device path not found\n", 248 __FUNCTION__, ReportText, Handle)); 249 return; 250 } 251 252 Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); 253 if (EFI_ERROR (Status)) { 254 DEBUG ((DEBUG_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__, 255 ReportText, Status)); 256 return; 257 } 258 259 Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); 260 if (EFI_ERROR (Status)) { 261 DEBUG ((DEBUG_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__, 262 ReportText, Status)); 263 return; 264 } 265 266 DEBUG ((DEBUG_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__, 267 ReportText)); 268 } 269 270 STATIC 271 VOID 272 PlatformRegisterFvBootOption ( 273 EFI_GUID *FileGuid, 274 CHAR16 *Description, 275 UINT32 Attributes 276 ) 277 { 278 EFI_STATUS Status; 279 INTN OptionIndex; 280 EFI_BOOT_MANAGER_LOAD_OPTION NewOption; 281 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; 282 UINTN BootOptionCount; 283 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; 284 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; 285 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 286 287 Status = gBS->HandleProtocol ( 288 gImageHandle, 289 &gEfiLoadedImageProtocolGuid, 290 (VOID **) &LoadedImage 291 ); 292 ASSERT_EFI_ERROR (Status); 293 294 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); 295 DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle); 296 ASSERT (DevicePath != NULL); 297 DevicePath = AppendDevicePathNode ( 298 DevicePath, 299 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode 300 ); 301 ASSERT (DevicePath != NULL); 302 303 Status = EfiBootManagerInitializeLoadOption ( 304 &NewOption, 305 LoadOptionNumberUnassigned, 306 LoadOptionTypeBoot, 307 Attributes, 308 Description, 309 DevicePath, 310 NULL, 311 0 312 ); 313 ASSERT_EFI_ERROR (Status); 314 FreePool (DevicePath); 315 316 BootOptions = EfiBootManagerGetLoadOptions ( 317 &BootOptionCount, LoadOptionTypeBoot 318 ); 319 320 OptionIndex = EfiBootManagerFindLoadOption ( 321 &NewOption, BootOptions, BootOptionCount 322 ); 323 324 if (OptionIndex == -1) { 325 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN); 326 ASSERT_EFI_ERROR (Status); 327 } 328 329 EfiBootManagerFreeLoadOption (&NewOption); 330 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); 331 } 332 333 334 STATIC 335 VOID 336 PlatformRegisterBootSd ( 337 VOID 338 ) 339 { 340 EFI_STATUS Status; 341 CHAR16 *BootPathStr; 342 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; 343 EFI_DEVICE_PATH *DevicePath; 344 EFI_DEVICE_PATH *FileDevicePath; 345 FILEPATH_DEVICE_PATH *FilePath; 346 UINTN Size; 347 EFI_BOOT_MANAGER_LOAD_OPTION NewOption; 348 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; 349 UINTN BootOptionCount; 350 INTN OptionIndex; 351 352 // 353 // Get PcdSdBootDevicePath 354 // 355 BootPathStr = (CHAR16 *)PcdGetPtr (PcdSdBootDevicePath); 356 ASSERT (BootPathStr != NULL); 357 Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); 358 ASSERT_EFI_ERROR(Status); 359 DevicePath = (EFI_DEVICE_PATH *)EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (BootPathStr); 360 ASSERT (DevicePath != NULL); 361 362 Size = StrSize (SD_FILE_NAME); 363 FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH); 364 if (FileDevicePath != NULL) { 365 FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath; 366 FilePath->Header.Type = MEDIA_DEVICE_PATH; 367 FilePath->Header.SubType = MEDIA_FILEPATH_DP; 368 CopyMem (&FilePath->PathName, SD_FILE_NAME, Size); 369 SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); 370 SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header)); 371 372 DevicePath = AppendDevicePath (DevicePath, FileDevicePath); 373 FreePool (FileDevicePath); 374 } 375 Status = EfiBootManagerInitializeLoadOption ( 376 &NewOption, 377 LoadOptionNumberUnassigned, 378 LoadOptionTypeBoot, 379 LOAD_OPTION_ACTIVE, 380 L"Boot from SD", 381 DevicePath, 382 NULL, 383 0 384 ); 385 ASSERT_EFI_ERROR (Status); 386 FreePool (DevicePath); 387 388 BootOptions = EfiBootManagerGetLoadOptions ( 389 &BootOptionCount, LoadOptionTypeBoot 390 ); 391 392 OptionIndex = EfiBootManagerFindLoadOption ( 393 &NewOption, BootOptions, BootOptionCount 394 ); 395 396 if (OptionIndex == -1) { 397 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN); 398 ASSERT_EFI_ERROR (Status); 399 } 400 401 EfiBootManagerFreeLoadOption (&NewOption); 402 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); 403 } 404 405 STATIC 406 VOID 407 PlatformRegisterBootGrub ( 408 VOID 409 ) 410 { 411 EFI_STATUS Status; 412 CHAR16 *BootPathStr; 413 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; 414 EFI_DEVICE_PATH *DevicePath; 415 EFI_DEVICE_PATH *FileDevicePath; 416 FILEPATH_DEVICE_PATH *FilePath; 417 UINTN Size; 418 EFI_BOOT_MANAGER_LOAD_OPTION NewOption; 419 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; 420 UINTN BootOptionCount; 421 INTN OptionIndex; 422 423 // 424 // Get PcdAndroidBootDevicePath 425 // 426 BootPathStr = (CHAR16 *)PcdGetPtr (PcdAndroidBootDevicePath); 427 ASSERT (BootPathStr != NULL); 428 Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); 429 ASSERT_EFI_ERROR(Status); 430 DevicePath = (EFI_DEVICE_PATH *)EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (BootPathStr); 431 ASSERT (DevicePath != NULL); 432 433 Size = StrSize (GRUB_FILE_NAME); 434 FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH); 435 if (FileDevicePath != NULL) { 436 FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath; 437 FilePath->Header.Type = MEDIA_DEVICE_PATH; 438 FilePath->Header.SubType = MEDIA_FILEPATH_DP; 439 CopyMem (&FilePath->PathName, GRUB_FILE_NAME, Size); 440 SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); 441 SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header)); 442 443 DevicePath = AppendDevicePath (DevicePath, FileDevicePath); 444 FreePool (FileDevicePath); 445 } 446 Status = EfiBootManagerInitializeLoadOption ( 447 &NewOption, 448 LoadOptionNumberUnassigned, 449 LoadOptionTypeBoot, 450 LOAD_OPTION_ACTIVE, 451 L"Grub", 452 DevicePath, 453 NULL, 454 0 455 ); 456 ASSERT_EFI_ERROR (Status); 457 FreePool (DevicePath); 458 459 BootOptions = EfiBootManagerGetLoadOptions ( 460 &BootOptionCount, LoadOptionTypeBoot 461 ); 462 463 OptionIndex = EfiBootManagerFindLoadOption ( 464 &NewOption, BootOptions, BootOptionCount 465 ); 466 467 if (OptionIndex == -1) { 468 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN); 469 ASSERT_EFI_ERROR (Status); 470 } 471 472 EfiBootManagerFreeLoadOption (&NewOption); 473 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); 474 475 } 476 477 STATIC 478 VOID 479 PlatformRegisterOptionsAndKeys ( 480 VOID 481 ) 482 { 483 EFI_STATUS Status; 484 EFI_INPUT_KEY Enter; 485 EFI_INPUT_KEY Esc; 486 EFI_INPUT_KEY KeyF; 487 EFI_BOOT_MANAGER_LOAD_OPTION BootOption; 488 489 // 490 // Register Boot on SD. OptionNumber is 1. 491 // 492 PlatformRegisterBootSd (); 493 494 // 495 // Register Boot. OptionNumber is 2. 496 // 497 PlatformRegisterBootGrub (); 498 499 // 500 // Register Android Boot. OptionNumber is 3. 501 // 502 PlatformRegisterFvBootOption ( 503 PcdGetPtr (PcdAndroidBootFile), L"Android Boot", LOAD_OPTION_ACTIVE 504 ); 505 506 // 507 // Register Android Fastboot. OptionNumber is 4. 508 // 509 PlatformRegisterFvBootOption ( 510 PcdGetPtr (PcdAndroidFastbootFile), L"Android Fastboot", LOAD_OPTION_ACTIVE 511 ); 512 513 // 514 // Register ENTER as CONTINUE key 515 // 516 Enter.ScanCode = SCAN_NULL; 517 Enter.UnicodeChar = CHAR_CARRIAGE_RETURN; 518 Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); 519 ASSERT_EFI_ERROR (Status); 520 521 // 522 // Map ESC to Boot Manager Menu 523 // 524 Esc.ScanCode = SCAN_ESC; 525 Esc.UnicodeChar = CHAR_NULL; 526 Status = EfiBootManagerGetBootManagerMenu (&BootOption); 527 ASSERT_EFI_ERROR (Status); 528 Status = EfiBootManagerAddKeyOptionVariable ( 529 NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL 530 ); 531 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); 532 533 // 534 // Map KeyF to Android Fastboot 535 // 536 KeyF.ScanCode = SCAN_NULL; 537 KeyF.UnicodeChar = 'f'; 538 Status = EfiBootManagerAddKeyOptionVariable ( 539 NULL, 4, 0, &KeyF, NULL 540 ); 541 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); 542 } 543 544 545 // 546 // BDS Platform Functions 547 // 548 /** 549 Do the platform init, can be customized by OEM/IBV 550 Possible things that can be done in PlatformBootManagerBeforeConsole: 551 > Update console variable: 1. include hot-plug devices; 552 > 2. Clear ConIn and add SOL for AMT 553 > Register new Driver#### or Boot#### 554 > Register new Key####: e.g.: F12 555 > Signal ReadyToLock event 556 > Authentication action: 1. connect Auth devices; 557 > 2. Identify auto logon user. 558 **/ 559 VOID 560 EFIAPI 561 PlatformBootManagerBeforeConsole ( 562 VOID 563 ) 564 { 565 // 566 // Signal EndOfDxe PI Event 567 // 568 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); 569 570 // 571 // Now add the device path of all handles with GOP on them to ConOut and 572 // ErrOut. 573 // 574 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput); 575 576 // 577 // Add the hardcoded short-form USB keyboard device path to ConIn. 578 // 579 EfiBootManagerUpdateConsoleVariable (ConIn, 580 (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL); 581 582 // 583 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut. 584 // 585 ASSERT (FixedPcdGet8 (PcdDefaultTerminalType) == 4); 586 CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid); 587 588 EfiBootManagerUpdateConsoleVariable (ConIn, 589 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); 590 EfiBootManagerUpdateConsoleVariable (ConOut, 591 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); 592 EfiBootManagerUpdateConsoleVariable (ErrOut, 593 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); 594 595 // 596 // Register platform-specific boot options and keyboard shortcuts. 597 // 598 PlatformRegisterOptionsAndKeys (); 599 } 600 601 /** 602 Do the platform specific action after the console is ready 603 Possible things that can be done in PlatformBootManagerAfterConsole: 604 > Console post action: 605 > Dynamically switch output mode from 100x31 to 80x25 for certain senarino 606 > Signal console ready platform customized event 607 > Run diagnostics like memory testing 608 > Connect certain devices 609 > Dispatch aditional option roms 610 > Special boot: e.g.: USB boot, enter UI 611 **/ 612 VOID 613 EFIAPI 614 PlatformBootManagerAfterConsole ( 615 VOID 616 ) 617 { 618 Print (L"Press ESCAPE for boot options "); 619 620 // 621 // Show the splash screen. 622 // 623 EnableQuietBoot (PcdGetPtr (PcdLogoFile)); 624 625 // 626 // Connect the rest of the devices. 627 // 628 EfiBootManagerConnectAll (); 629 630 // 631 // Enumerate all possible boot options. 632 // 633 EfiBootManagerRefreshAllBootOption (); 634 635 // 636 // Register UEFI Shell 637 // 638 PlatformRegisterFvBootOption ( 639 PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_ACTIVE 640 ); 641 } 642 643 /** 644 This function is called each second during the boot manager waits the 645 timeout. 646 647 @param TimeoutRemain The remaining timeout. 648 **/ 649 VOID 650 EFIAPI 651 PlatformBootManagerWaitCallback ( 652 UINT16 TimeoutRemain 653 ) 654 { 655 Print (L"."); 656 } 657