1 /** @file 2 This file include all platform action which can be customized by IBV/OEM. 3 4 Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "BdsPlatform.h" 16 17 // 18 // Global data 19 // 20 BOOLEAN mDetectVgaOnly; 21 22 23 // 24 // Type definitions 25 // 26 27 typedef 28 EFI_STATUS 29 (EFIAPI *PROTOCOL_INSTANCE_CALLBACK)( 30 IN EFI_HANDLE Handle, 31 IN VOID *Instance, 32 IN VOID *Context 33 ); 34 35 /** 36 @param[in] Handle - Handle of PCI device instance 37 @param[in] PciIo - PCI IO protocol instance 38 @param[in] Pci - PCI Header register block 39 **/ 40 typedef 41 EFI_STATUS 42 (EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)( 43 IN EFI_HANDLE Handle, 44 IN EFI_PCI_IO_PROTOCOL *PciIo, 45 IN PCI_TYPE00 *Pci 46 ); 47 48 49 // 50 // Function prototypes 51 // 52 53 EFI_STATUS 54 VisitAllInstancesOfProtocol ( 55 IN EFI_GUID *Id, 56 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction, 57 IN VOID *Context 58 ); 59 60 EFI_STATUS 61 VisitAllPciInstancesOfProtocol ( 62 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction 63 ); 64 65 66 // 67 // BDS Platform Functions 68 // 69 70 /** 71 Platform Bds init. Include the platform firmware vendor, revision 72 and so crc check. 73 74 **/ 75 VOID 76 EFIAPI 77 PlatformBdsInit ( 78 VOID 79 ) 80 { 81 } 82 83 84 EFI_STATUS 85 PrepareLpcBridgeDevicePath ( 86 IN EFI_HANDLE DeviceHandle 87 ) 88 /*++ 89 90 Routine Description: 91 92 Add IsaKeyboard to ConIn, 93 add IsaSerial to ConOut, ConIn, ErrOut. 94 LPC Bridge: 06 01 00 95 96 Arguments: 97 98 DeviceHandle - Handle of PCIIO protocol. 99 100 Returns: 101 102 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut. 103 EFI_STATUS - No LPC bridge is added. 104 105 --*/ 106 { 107 EFI_STATUS Status; 108 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 109 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; 110 CHAR16 *DevPathStr; 111 112 DevicePath = NULL; 113 Status = gBS->HandleProtocol ( 114 DeviceHandle, 115 &gEfiDevicePathProtocolGuid, 116 (VOID*)&DevicePath 117 ); 118 if (EFI_ERROR (Status)) { 119 return Status; 120 } 121 TempDevicePath = DevicePath; 122 123 // 124 // Register COM1 125 // 126 DevicePath = AppendDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *)NULL, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceVenderNode); 127 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); 128 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); 129 130 // 131 // Print Device Path 132 // 133 DevPathStr = DevicePathToStr(DevicePath); 134 DEBUG(( 135 EFI_D_INFO, 136 "BdsPlatform.c+%d: COM%d DevPath: %s\n", 137 __LINE__, 138 gPnp16550ComPortDeviceNode.UID + 1, 139 DevPathStr 140 )); 141 FreePool(DevPathStr); 142 143 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); 144 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); 145 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL); 146 147 return EFI_SUCCESS; 148 } 149 150 EFI_STATUS 151 GetGopDevicePath ( 152 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath, 153 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath 154 ) 155 { 156 UINTN Index; 157 EFI_STATUS Status; 158 EFI_HANDLE PciDeviceHandle; 159 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; 160 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath; 161 UINTN GopHandleCount; 162 EFI_HANDLE *GopHandleBuffer; 163 164 if (PciDevicePath == NULL || GopDevicePath == NULL) { 165 return EFI_INVALID_PARAMETER; 166 } 167 168 // 169 // Initialize the GopDevicePath to be PciDevicePath 170 // 171 *GopDevicePath = PciDevicePath; 172 TempPciDevicePath = PciDevicePath; 173 174 Status = gBS->LocateDevicePath ( 175 &gEfiDevicePathProtocolGuid, 176 &TempPciDevicePath, 177 &PciDeviceHandle 178 ); 179 if (EFI_ERROR (Status)) { 180 return Status; 181 } 182 183 // 184 // Try to connect this handle, so that GOP dirver could start on this 185 // device and create child handles with GraphicsOutput Protocol installed 186 // on them, then we get device paths of these child handles and select 187 // them as possible console device. 188 // 189 #if 0 190 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE); 191 #else 192 { 193 ACPI_ADR_DEVICE_PATH AcpiAdr; 194 EFI_DEVICE_PATH_PROTOCOL *MyDevicePath = NULL; 195 196 AcpiAdr.Header.Type = ACPI_DEVICE_PATH; 197 AcpiAdr.Header.SubType = ACPI_ADR_DP; 198 //AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 6, 0); //on bayleybay, CRT Device 199 AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, 8, 0); ; // on rambi, eDP C 200 201 SetDevicePathNodeLength (&AcpiAdr.Header, sizeof (ACPI_ADR_DEVICE_PATH)); 202 203 MyDevicePath = AppendDevicePathNode(MyDevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&AcpiAdr); 204 205 gBS->ConnectController (PciDeviceHandle, NULL, MyDevicePath, FALSE); 206 207 FreePool(MyDevicePath); 208 } 209 #endif 210 211 Status = gBS->LocateHandleBuffer ( 212 ByProtocol, 213 &gEfiGraphicsOutputProtocolGuid, 214 NULL, 215 &GopHandleCount, 216 &GopHandleBuffer 217 ); 218 if (!EFI_ERROR (Status)) { 219 // 220 // Add all the child handles as possible Console Device 221 // 222 for (Index = 0; Index < GopHandleCount; Index++) { 223 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath); 224 if (EFI_ERROR (Status)) { 225 continue; 226 } 227 if (CompareMem ( 228 PciDevicePath, 229 TempDevicePath, 230 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH 231 ) == 0) { 232 // 233 // In current implementation, we only enable one of the child handles 234 // as console device, i.e. sotre one of the child handle's device 235 // path to variable "ConOut" 236 // In futhure, we could select all child handles to be console device 237 // 238 239 *GopDevicePath = TempDevicePath; 240 241 // 242 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath() 243 // Add the integrity GOP device path. 244 // 245 BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath); 246 BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL); 247 } 248 } 249 gBS->FreePool (GopHandleBuffer); 250 } 251 252 return EFI_SUCCESS; 253 } 254 255 EFI_STATUS 256 PreparePciVgaDevicePath ( 257 IN EFI_HANDLE DeviceHandle 258 ) 259 /*++ 260 261 Routine Description: 262 263 Add PCI VGA to ConOut. 264 PCI VGA: 03 00 00 265 266 Arguments: 267 268 DeviceHandle - Handle of PCIIO protocol. 269 270 Returns: 271 272 EFI_SUCCESS - PCI VGA is added to ConOut. 273 EFI_STATUS - No PCI VGA device is added. 274 275 --*/ 276 { 277 EFI_STATUS Status; 278 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 279 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; 280 281 DevicePath = NULL; 282 Status = gBS->HandleProtocol ( 283 DeviceHandle, 284 &gEfiDevicePathProtocolGuid, 285 (VOID*)&DevicePath 286 ); 287 if (EFI_ERROR (Status)) { 288 return Status; 289 } 290 291 GetGopDevicePath (DevicePath, &GopDevicePath); 292 DevicePath = GopDevicePath; 293 294 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); 295 296 return EFI_SUCCESS; 297 } 298 299 EFI_STATUS 300 PreparePciSerialDevicePath ( 301 IN EFI_HANDLE DeviceHandle 302 ) 303 /*++ 304 305 Routine Description: 306 307 Add PCI Serial to ConOut, ConIn, ErrOut. 308 PCI Serial: 07 00 02 309 310 Arguments: 311 312 DeviceHandle - Handle of PCIIO protocol. 313 314 Returns: 315 316 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut. 317 EFI_STATUS - No PCI Serial device is added. 318 319 --*/ 320 { 321 EFI_STATUS Status; 322 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 323 324 DevicePath = NULL; 325 Status = gBS->HandleProtocol ( 326 DeviceHandle, 327 &gEfiDevicePathProtocolGuid, 328 (VOID*)&DevicePath 329 ); 330 if (EFI_ERROR (Status)) { 331 return Status; 332 } 333 334 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); 335 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); 336 337 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); 338 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); 339 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL); 340 341 return EFI_SUCCESS; 342 } 343 344 EFI_STATUS 345 VisitAllInstancesOfProtocol ( 346 IN EFI_GUID *Id, 347 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction, 348 IN VOID *Context 349 ) 350 { 351 EFI_STATUS Status; 352 UINTN HandleCount; 353 EFI_HANDLE *HandleBuffer; 354 UINTN Index; 355 VOID *Instance; 356 357 // 358 // Start to check all the PciIo to find all possible device 359 // 360 HandleCount = 0; 361 HandleBuffer = NULL; 362 Status = gBS->LocateHandleBuffer ( 363 ByProtocol, 364 Id, 365 NULL, 366 &HandleCount, 367 &HandleBuffer 368 ); 369 if (EFI_ERROR (Status)) { 370 return Status; 371 } 372 373 for (Index = 0; Index < HandleCount; Index++) { 374 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance); 375 if (EFI_ERROR (Status)) { 376 continue; 377 } 378 379 Status = (*CallBackFunction) ( 380 HandleBuffer[Index], 381 Instance, 382 Context 383 ); 384 } 385 386 gBS->FreePool (HandleBuffer); 387 388 return EFI_SUCCESS; 389 } 390 391 392 EFI_STATUS 393 EFIAPI 394 VisitingAPciInstance ( 395 IN EFI_HANDLE Handle, 396 IN VOID *Instance, 397 IN VOID *Context 398 ) 399 { 400 EFI_STATUS Status; 401 EFI_PCI_IO_PROTOCOL *PciIo; 402 PCI_TYPE00 Pci; 403 404 PciIo = (EFI_PCI_IO_PROTOCOL*) Instance; 405 406 // 407 // Check for all PCI device 408 // 409 Status = PciIo->Pci.Read ( 410 PciIo, 411 EfiPciIoWidthUint32, 412 0, 413 sizeof (Pci) / sizeof (UINT32), 414 &Pci 415 ); 416 if (EFI_ERROR (Status)) { 417 return Status; 418 } 419 420 return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) ( 421 Handle, 422 PciIo, 423 &Pci 424 ); 425 426 } 427 428 429 430 EFI_STATUS 431 VisitAllPciInstances ( 432 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction 433 ) 434 { 435 return VisitAllInstancesOfProtocol ( 436 &gEfiPciIoProtocolGuid, 437 VisitingAPciInstance, 438 (VOID*)(UINTN) CallBackFunction 439 ); 440 } 441 442 443 /** 444 Do platform specific PCI Device check and add them to 445 ConOut, ConIn, ErrOut. 446 447 @param[in] Handle - Handle of PCI device instance 448 @param[in] PciIo - PCI IO protocol instance 449 @param[in] Pci - PCI Header register block 450 451 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully. 452 @retval EFI_STATUS - PCI Device check or Console variable update fail. 453 454 **/ 455 EFI_STATUS 456 EFIAPI 457 DetectAndPreparePlatformPciDevicePath ( 458 IN EFI_HANDLE Handle, 459 IN EFI_PCI_IO_PROTOCOL *PciIo, 460 IN PCI_TYPE00 *Pci 461 ) 462 { 463 EFI_STATUS Status; 464 465 Status = PciIo->Attributes ( 466 PciIo, 467 EfiPciIoAttributeOperationEnable, 468 EFI_PCI_DEVICE_ENABLE, 469 NULL 470 ); 471 ASSERT_EFI_ERROR (Status); 472 473 if (!mDetectVgaOnly) { 474 // 475 // Here we decide whether it is LPC Bridge 476 // 477 if ((IS_PCI_LPC (Pci)) || 478 ((IS_PCI_ISA_PDECODE (Pci)) && 479 (Pci->Hdr.VendorId == 0x8086) 480 ) 481 ) { 482 // 483 // Add IsaKeyboard to ConIn, 484 // add IsaSerial to ConOut, ConIn, ErrOut 485 // 486 DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n")); 487 PrepareLpcBridgeDevicePath (Handle); 488 return EFI_SUCCESS; 489 } 490 // 491 // Here we decide which Serial device to enable in PCI bus 492 // 493 if (IS_PCI_16550SERIAL (Pci)) { 494 // 495 // Add them to ConOut, ConIn, ErrOut. 496 // 497 DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n")); 498 PreparePciSerialDevicePath (Handle); 499 return EFI_SUCCESS; 500 } 501 } 502 503 // 504 // Here we decide which VGA device to enable in PCI bus 505 // 506 if (IS_PCI_VGA (Pci)) { 507 // 508 // Add them to ConOut. 509 // 510 DEBUG ((EFI_D_INFO, "Found PCI VGA device\n")); 511 PreparePciVgaDevicePath (Handle); 512 return EFI_SUCCESS; 513 } 514 515 return Status; 516 } 517 518 519 /** 520 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut 521 522 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE. 523 524 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully. 525 @retval EFI_STATUS - PCI Device check or Console variable update fail. 526 527 **/ 528 EFI_STATUS 529 DetectAndPreparePlatformPciDevicePaths ( 530 BOOLEAN DetectVgaOnly 531 ) 532 { 533 mDetectVgaOnly = DetectVgaOnly; 534 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath); 535 } 536 537 /** 538 Connect the predefined platform default console device. Always try to find 539 and enable the vga device if have. 540 541 @param PlatformConsole Predefined platform default console device array. 542 543 @retval EFI_SUCCESS Success connect at least one ConIn and ConOut 544 device, there must have one ConOut device is 545 active vga device. 546 @return Return the status of BdsLibConnectAllDefaultConsoles () 547 548 **/ 549 EFI_STATUS 550 PlatformBdsConnectConsole ( 551 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole 552 ) 553 { 554 EFI_STATUS Status; 555 UINTN Index; 556 EFI_DEVICE_PATH_PROTOCOL *VarConout; 557 EFI_DEVICE_PATH_PROTOCOL *VarConin; 558 UINTN DevicePathSize; 559 560 // 561 // Connect RootBridge 562 // 563 VarConout = BdsLibGetVariableAndSize ( 564 VarConsoleOut, 565 &gEfiGlobalVariableGuid, 566 &DevicePathSize 567 ); 568 VarConin = BdsLibGetVariableAndSize ( 569 VarConsoleInp, 570 &gEfiGlobalVariableGuid, 571 &DevicePathSize 572 ); 573 574 if (VarConout == NULL || VarConin == NULL) { 575 // 576 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut 577 // 578 DetectAndPreparePlatformPciDevicePaths (FALSE); 579 580 // 581 // Have chance to connect the platform default console, 582 // the platform default console is the minimue device group 583 // the platform should support 584 // 585 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) { 586 // 587 // Update the console variable with the connect type 588 // 589 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { 590 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL); 591 } 592 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { 593 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL); 594 } 595 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { 596 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL); 597 } 598 } 599 } else { 600 // 601 // Only detect VGA device and add them to ConOut 602 // 603 DetectAndPreparePlatformPciDevicePaths (TRUE); 604 } 605 606 // 607 // Connect the all the default console with current cosole variable 608 // 609 Status = BdsLibConnectAllDefaultConsoles (); 610 if (EFI_ERROR (Status)) { 611 return Status; 612 } 613 614 return EFI_SUCCESS; 615 } 616 617 /** 618 Connect with predefined platform connect sequence, 619 the OEM/IBV can customize with their own connect sequence. 620 **/ 621 VOID 622 PlatformBdsConnectSequence ( 623 VOID 624 ) 625 { 626 UINTN Index; 627 628 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n")); 629 Index = 0; 630 631 // 632 // Here we can get the customized platform connect sequence 633 // Notes: we can connect with new variable which record the 634 // last time boots connect device path sequence 635 // 636 while (gPlatformConnectSequence[Index] != NULL) { 637 // 638 // Build the platform boot option 639 // 640 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]); 641 Index++; 642 } 643 } 644 645 /** 646 Load the predefined driver option, OEM/IBV can customize this 647 to load their own drivers 648 649 @param BdsDriverLists - The header of the driver option link list. 650 651 **/ 652 VOID 653 PlatformBdsGetDriverOption ( 654 IN OUT LIST_ENTRY *BdsDriverLists 655 ) 656 { 657 UINTN Index; 658 659 Index = 0; 660 661 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n")); 662 663 664 // 665 // Here we can get the customized platform driver option 666 // 667 while (gPlatformDriverOption[Index] != NULL) { 668 669 // 670 // Build the platform boot option 671 // 672 BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder"); 673 Index ++; 674 } 675 } 676 677 /** 678 Perform the platform diagnostic, such like test memory. OEM/IBV also 679 can customize this function to support specific platform diagnostic. 680 681 @param MemoryTestLevel The memory test intensive level 682 @param QuietBoot Indicate if need to enable the quiet boot 683 @param BaseMemoryTest A pointer to BdsMemoryTest() 684 685 **/ 686 VOID 687 PlatformBdsDiagnostics ( 688 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel, 689 IN BOOLEAN QuietBoot, 690 IN BASEM_MEMORY_TEST BaseMemoryTest 691 ) 692 { 693 EFI_STATUS Status; 694 695 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n")); 696 // 697 // Here we can decide if we need to show 698 // the diagnostics screen 699 // Notes: this quiet boot code should be remove 700 // from the graphic lib 701 // 702 if (QuietBoot) { 703 EnableQuietBoot (PcdGetPtr(PcdLogoFile)); 704 705 // 706 // Perform system diagnostic 707 // 708 Status = BaseMemoryTest (MemoryTestLevel); 709 if (EFI_ERROR (Status)) { 710 DisableQuietBoot (); 711 } 712 713 return; 714 } 715 716 // 717 // Perform system diagnostic 718 // 719 Status = BaseMemoryTest (MemoryTestLevel); 720 } 721 722 723 /** 724 The function will connect root bridge 725 726 @return EFI_SUCCESS Connect RootBridge successfully. 727 728 **/ 729 EFI_STATUS 730 ConnectRootBridge ( 731 VOID 732 ) 733 { 734 EFI_STATUS Status; 735 EFI_HANDLE RootHandle; 736 737 // 738 // Make all the PCI_IO protocols on PCI Seg 0 show up 739 // 740 BdsLibConnectDevicePath (gPlatformRootBridges[0]); 741 742 Status = gBS->LocateDevicePath ( 743 &gEfiDevicePathProtocolGuid, 744 &gPlatformRootBridges[0], 745 &RootHandle 746 ); 747 if (EFI_ERROR (Status)) { 748 return Status; 749 } 750 751 Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE); 752 if (EFI_ERROR (Status)) { 753 return Status; 754 } 755 756 return EFI_SUCCESS; 757 } 758 759 /** 760 The function will execute with as the platform policy, current policy 761 is driven by boot mode. IBV/OEM can customize this code for their specific 762 policy action. 763 764 @param DriverOptionList The header of the driver option link list 765 @param BootOptionList The header of the boot option link list 766 @param ProcessCapsules A pointer to ProcessCapsules() 767 @param BaseMemoryTest A pointer to BaseMemoryTest() 768 769 **/ 770 VOID 771 EFIAPI 772 PlatformBdsPolicyBehavior ( 773 IN LIST_ENTRY *DriverOptionList, 774 IN LIST_ENTRY *BootOptionList, 775 IN PROCESS_CAPSULES ProcessCapsules, 776 IN BASEM_MEMORY_TEST BaseMemoryTest 777 ) 778 { 779 EFI_STATUS Status; 780 UINT16 Timeout; 781 EFI_EVENT UserInputDurationTime; 782 LIST_ENTRY *Link; 783 BDS_COMMON_OPTION *BootOption; 784 UINTN Index; 785 EFI_INPUT_KEY Key; 786 EFI_TPL OldTpl; 787 EFI_BOOT_MODE BootMode; 788 789 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n")); 790 791 ConnectRootBridge (); 792 793 // 794 // Init the time out value 795 // 796 Timeout = PcdGet16 (PcdPlatformBootTimeOut); 797 798 // 799 // Load the driver option as the driver option list 800 // 801 PlatformBdsGetDriverOption (DriverOptionList); 802 803 // 804 // Get current Boot Mode 805 // 806 Status = BdsLibGetBootMode (&BootMode); 807 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode)); 808 809 // 810 // Go the different platform policy with different boot mode 811 // Notes: this part code can be change with the table policy 812 // 813 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION); 814 // 815 // Connect platform console 816 // 817 Status = PlatformBdsConnectConsole (gPlatformConsole); 818 if (EFI_ERROR (Status)) { 819 // 820 // Here OEM/IBV can customize with defined action 821 // 822 PlatformBdsNoConsoleAction (); 823 } 824 // 825 // Create a 300ms duration event to ensure user has enough input time to enter Setup 826 // 827 Status = gBS->CreateEvent ( 828 EVT_TIMER, 829 0, 830 NULL, 831 NULL, 832 &UserInputDurationTime 833 ); 834 ASSERT (Status == EFI_SUCCESS); 835 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000); 836 ASSERT (Status == EFI_SUCCESS); 837 // 838 // Memory test and Logo show 839 // 840 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest); 841 842 // 843 // Perform some platform specific connect sequence 844 // 845 PlatformBdsConnectSequence (); 846 847 // 848 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device 849 // and do enumerate all the default boot options. But in development system board, the boot mode 850 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box 851 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot. 852 // 853 Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); 854 if (EFI_ERROR(Status)) { 855 // 856 // If cannot find "BootOrder" variable, it may be first boot. 857 // Try to connect all devices and enumerate all boot options here. 858 // 859 BdsLibConnectAll (); 860 BdsLibEnumerateAllBootOption (BootOptionList); 861 } 862 863 // 864 // To give the User a chance to enter Setup here, if user set TimeOut is 0. 865 // BDS should still give user a chance to enter Setup 866 // 867 // Connect first boot option, and then check user input before exit 868 // 869 for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) { 870 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); 871 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) { 872 // 873 // skip the header of the link list, becuase it has no boot option 874 // 875 continue; 876 } else { 877 // 878 // Make sure the boot option device path connected, but ignore the BBS device path 879 // 880 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) { 881 BdsLibConnectDevicePath (BootOption->DevicePath); 882 } 883 break; 884 } 885 } 886 887 // 888 // Check whether the user input after the duration time has expired 889 // 890 OldTpl = EfiGetCurrentTpl(); 891 gBS->RestoreTPL (TPL_APPLICATION); 892 gBS->WaitForEvent (1, &UserInputDurationTime, &Index); 893 gBS->CloseEvent (UserInputDurationTime); 894 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); 895 gBS->RaiseTPL (OldTpl); 896 897 if (!EFI_ERROR (Status)) { 898 // 899 // Enter Setup if user input 900 // 901 Timeout = 0xffff; 902 PlatformBdsEnterFrontPage (Timeout, FALSE); 903 } 904 } 905 906 /** 907 Hook point after a boot attempt succeeds. We don't expect a boot option to 908 return, so the UEFI 2.0 specification defines that you will default to an 909 interactive mode and stop processing the BootOrder list in this case. This 910 is also a platform implementation and can be customized by IBV/OEM. 911 912 @param Option Pointer to Boot Option that succeeded to boot. 913 914 **/ 915 VOID 916 EFIAPI 917 PlatformBdsBootSuccess ( 918 IN BDS_COMMON_OPTION *Option 919 ) 920 { 921 CHAR16 *TmpStr; 922 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n")); 923 924 // 925 // If Boot returned with EFI_SUCCESS and there is not in the boot device 926 // select loop then we need to pop up a UI and wait for user input. 927 // 928 TmpStr = Option->StatusString; 929 if (TmpStr != NULL) { 930 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); 931 FreePool (TmpStr); 932 } 933 } 934 935 /** 936 Hook point after a boot attempt fails. 937 938 @param Option Pointer to Boot Option that failed to boot. 939 @param Status Status returned from failed boot. 940 @param ExitData Exit data returned from failed boot. 941 @param ExitDataSize Exit data size returned from failed boot. 942 943 **/ 944 VOID 945 EFIAPI 946 PlatformBdsBootFail ( 947 IN BDS_COMMON_OPTION *Option, 948 IN EFI_STATUS Status, 949 IN CHAR16 *ExitData, 950 IN UINTN ExitDataSize 951 ) 952 { 953 CHAR16 *TmpStr; 954 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n")); 955 956 // 957 // If Boot returned with failed status then we need to pop up a UI and wait 958 // for user input. 959 // 960 TmpStr = Option->StatusString; 961 if (TmpStr != NULL) { 962 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); 963 FreePool (TmpStr); 964 } 965 } 966 967 /** 968 This function is remained for IBV/OEM to do some platform action, 969 if there no console device can be connected. 970 971 @return EFI_SUCCESS Direct return success now. 972 973 **/ 974 EFI_STATUS 975 PlatformBdsNoConsoleAction ( 976 VOID 977 ) 978 { 979 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n")); 980 return EFI_SUCCESS; 981 } 982 983 /** 984 This function locks platform flash that is not allowed to be updated during normal boot path. 985 The flash layout is platform specific. 986 **/ 987 VOID 988 EFIAPI 989 PlatformBdsLockNonUpdatableFlash ( 990 VOID 991 ) 992 { 993 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n")); 994 return ; 995 } 996 997 998 /** 999 Lock the ConsoleIn device in system table. All key 1000 presses will be ignored until the Password is typed in. The only way to 1001 disable the password is to type it in to a ConIn device. 1002 1003 @param Password Password used to lock ConIn device. 1004 1005 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully. 1006 @retval EFI_UNSUPPORTED Password not found 1007 1008 **/ 1009 EFI_STATUS 1010 EFIAPI 1011 LockKeyboards ( 1012 IN CHAR16 *Password 1013 ) 1014 { 1015 return EFI_UNSUPPORTED; 1016 } 1017