/** This function invokes Boot Manager. If all devices have not a chance to be connected, the connect all will be triggered. It then enumerate all boot options. If a boot option from the Boot Manager page is selected, Boot Manager will boot from this boot option. **/ VOID CallBootManager ( VOID ) { EFI_STATUS Status; BDS_COMMON_OPTION *Option; LIST_ENTRY *Link; CHAR16 *ExitData; UINTN ExitDataSize; EFI_STRING_ID Token; EFI_INPUT_KEY Key; CHAR16 *HelpString; UINTN HelpSize; EFI_STRING_ID HelpToken; UINT16 *TempStr; EFI_HII_HANDLE HiiHandle; EFI_BROWSER_ACTION_REQUEST ActionRequest; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; UINT16 DeviceType; BOOLEAN IsLegacyOption; BOOLEAN NeedEndOp; DeviceType = (UINT16) -1; gOption = NULL; InitializeListHead (&mBootOptionsList); // // Connect all prior to entering the platform setup menu. // if (!gConnectAllHappened) { BdsLibConnectAllDriversToAllControllers (); gConnectAllHappened = TRUE; } BdsLibEnumerateAllBootOption (&mBootOptionsList); // // Group the legacy boot options for the same device type // GroupMultipleLegacyBootOption4SameType (); InitializeListHead (&mBootOptionsList); BdsLibBuildOptionFromVar (&mBootOptionsList, L"BootOrder"); HiiHandle = gBootManagerPrivate.HiiHandle; // // Allocate space for creation of UpdateData Buffer // StartOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (StartOpCodeHandle != NULL); EndOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (EndOpCodeHandle != NULL); // // Create Hii Extend Label OpCode as the start opcode // StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; StartLabel->Number = LABEL_BOOT_OPTION; // // Create Hii Extend Label OpCode as the end opcode // EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; EndLabel->Number = LABEL_BOOT_OPTION_END; mKeyInput = 0; NeedEndOp = FALSE; for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) { Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); // // At this stage we are creating a menu entry, thus the Keys are reproduceable // mKeyInput++; // // Don't display the hidden/inactive boot option // if (((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) || ((Option->Attribute & LOAD_OPTION_ACTIVE) == 0)) { continue; } // // Group the legacy boot option in the sub title created dynamically // IsLegacyOption = (BOOLEAN) ( (DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) && (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP) ); if (!IsLegacyOption && NeedEndOp) { NeedEndOp = FALSE; HiiCreateEndOpCode (StartOpCodeHandle); } if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType) { if (NeedEndOp) { HiiCreateEndOpCode (StartOpCodeHandle); } DeviceType = ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType; Token = HiiSetString ( HiiHandle, 0, mDeviceTypeStr[ MIN (DeviceType & 0xF, ARRAY_SIZE (mDeviceTypeStr) - 1) ], NULL ); HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1); NeedEndOp = TRUE; } ASSERT (Option->Description != NULL); Token = HiiSetString (HiiHandle, 0, Option->Description, NULL); TempStr = DevicePathToStr (Option->DevicePath); HelpSize = StrSize (TempStr) + StrSize (L"Device Path : "); HelpString = AllocateZeroPool (HelpSize); ASSERT (HelpString != NULL); StrCatS (HelpString, HelpSize / sizeof (CHAR16), L"Device Path : "); StrCatS (HelpString, HelpSize / sizeof (CHAR16), TempStr); HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL); HiiCreateActionOpCode ( StartOpCodeHandle, mKeyInput, Token, HelpToken, EFI_IFR_FLAG_CALLBACK, 0 ); } if (NeedEndOp) { HiiCreateEndOpCode (StartOpCodeHandle); } HiiUpdateForm ( HiiHandle, &gBootManagerFormSetGuid, BOOT_MANAGER_FORM_ID, StartOpCodeHandle, EndOpCodeHandle ); HiiFreeOpCodeHandle (StartOpCodeHandle); HiiFreeOpCodeHandle (EndOpCodeHandle); ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; Status = gFormBrowser2->SendForm ( gFormBrowser2, &HiiHandle, 1, &gBootManagerFormSetGuid, 0, NULL, &ActionRequest ); if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { EnableResetRequired (); } if (gOption == NULL) { return ; } // // Will leave browser, check any reset required change is applied? if yes, reset system // SetupResetReminder (); // // Restore to original mode before launching boot option. // BdsSetConsoleMode (FALSE); // // parse the selected option // Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData); if (!EFI_ERROR (Status)) { gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); PlatformBdsBootSuccess (gOption); } else { gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize); gST->ConOut->OutputString ( gST->ConOut, GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE)) ); gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); } }
VOID EFIAPI PlatformBdsPolicyBehavior ( IN OUT LIST_ENTRY *DriverOptionList, IN OUT LIST_ENTRY *BootOptionList, IN PROCESS_CAPSULES ProcessCapsules, IN BASEM_MEMORY_TEST BaseMemoryTest ) /*++ Routine Description: The function will excute with as the platform policy, current policy is driven by boot mode. IBV/OEM can customize this code for their specific policy action. Arguments: DriverOptionList - The header of the driver option link list BootOptionList - The header of the boot option link list ProcessCapsules - A pointer to ProcessCapsules() BaseMemoryTest - A pointer to BaseMemoryTest() Returns: None. --*/ { EFI_STATUS Status; UINT16 Timeout; EFI_EVENT UserInputDurationTime; LIST_ENTRY *Link; BDS_COMMON_OPTION *BootOption; UINTN Index; EFI_INPUT_KEY Key; EFI_TPL OldTpl; EFI_BOOT_MODE BootMode; VBoxLogFlowFuncEnter(); ConnectRootBridge (); if (PcdGetBool (PcdOvmfFlashVariablesEnable)) { DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars " "from disk since flash variables appear to be supported.\n")); } else { // // Try to restore variables from the hard disk early so // they can be used for the other BDS connect operations. // PlatformBdsRestoreNvVarsFromHardDisk (); } // // Init the time out value // Timeout = PcdGet16 (PcdPlatformBootTimeOut); // // Load the driver option as the driver option list // PlatformBdsGetDriverOption (DriverOptionList); // // Get current Boot Mode // Status = BdsLibGetBootMode (&BootMode); DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode)); // // Go the different platform policy with different boot mode // Notes: this part code can be change with the table policy // ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION); // // Connect platform console // Status = PlatformBdsConnectConsole (gPlatformConsole); if (EFI_ERROR (Status)) { // // Here OEM/IBV can customize with defined action // PlatformBdsNoConsoleAction (); } // // Create a 300ms duration event to ensure user has enough input time to enter Setup // Status = gBS->CreateEvent ( EVT_TIMER, 0, NULL, NULL, &UserInputDurationTime ); ASSERT (Status == EFI_SUCCESS); Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000); ASSERT (Status == EFI_SUCCESS); // // Memory test and Logo show // PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest); // // Perform some platform specific connect sequence // PlatformBdsConnectSequence (); // // Process QEMU's -kernel command line option // TryRunningQemuKernel (); // // Give one chance to enter the setup if we // have the time out // if (Timeout != 0) { //PlatformBdsEnterFrontPage (Timeout, FALSE); } DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n")); BdsLibConnectAll (); #ifdef VBOX { UINTN cFileSystem = 0; EFI_HANDLE *phFileSystem = NULL; BDS_COMMON_OPTION *BootOption0080 = NULL; EFI_STATUS rc = EFI_SUCCESS; DEBUG ((EFI_D_INFO, "------------------ VBox Platform Specific Initialization Start -----------------------\n")); BootOption0080 = BdsLibVariableToOption(BootOptionList, L"Boot0080"); if (!BootOption0080) { rc = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &cFileSystem, &phFileSystem); VBoxLogFlowFuncMarkRC(rc); VBoxLogFlowFuncMarkVar(cFileSystem, "%d"); if ( rc == EFI_SUCCESS && cFileSystem > 0) { EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFSVolume; EFI_FILE_HANDLE hFSRoot; EFI_FILE_HANDLE hBootEfiFile; UINTN iFileSystem = 0; /* Ok, we've found several simple file system handles * 1. we should find if '\\System\\Library\\CoreServices\\boot.efi' present * 2. Alter 'BootOrder' to include this file in boot sequence. */ for (iFileSystem = 0; iFileSystem < cFileSystem; ++iFileSystem) { EFI_DEVICE_PATH_PROTOCOL *pDevicePath = NULL; /* mount and look up the boot.efi */ rc = gBS->HandleProtocol (phFileSystem[iFileSystem], &gEfiSimpleFileSystemProtocolGuid, (VOID *) &pFSVolume); VBoxLogFlowFuncMarkVar(iFileSystem, "%d"); VBoxLogFlowFuncMarkRC(rc); if (EFI_ERROR(rc)) continue; rc = pFSVolume->OpenVolume(pFSVolume, &hFSRoot); VBoxLogFlowFuncMarkRC(rc); if (EFI_ERROR(rc)) continue; rc = hFSRoot->Open(hFSRoot, &hBootEfiFile, L"\\System\\Library\\CoreServices\\boot.efi", EFI_FILE_MODE_READ, 0); VBoxLogFlowFuncMarkRC(rc); if (EFI_ERROR(rc)) continue; /* nice file is found and we have to register it */ pDevicePath = FileDevicePath(phFileSystem[iFileSystem], L"\\System\\Library\\CoreServices\\boot.efi"); VBoxLogFlowFuncMarkVar(pDevicePath,"%p"); if (!pDevicePath) continue; rc = BdsLibRegisterNewOption (BootOptionList, pDevicePath, L"Mac Boot", L"BootOrder"); VBoxLogFlowFuncMarkRC(rc); } } } else { VBoxLogFlowFuncMarkVar(BootOption0080->LoadOptionsSize, "%d"); if (BootOption0080->LoadOptionsSize) VBoxLogFlowFuncMarkVar(BootOption0080->LoadOptions, "%s"); #if 0 /* Boot0080 option is found */ UINT16 *BootOrder; UINTN BootOrderSize; UINTN Index = 0; CHAR16 *BootOptionName; ASSERT(BootOption0080->Signature == BDS_LOAD_OPTION_SIGNATURE); BootOrder = BdsLibGetVariableAndSize ( L"BootOrder", &gEfiGlobalVariableGuid, &BootOrderSize); ASSERT(BootOrder); BootOptionName = AllocateRuntimePool(256 * sizeof(UINT16)); UnicodeSPrint(BootOptionName, 256 * sizeof(UINT16), L"Boot%04x", BootOrder[Index]); BootOption0080->OptionName = BootOptionName; rc = gRT->SetVariable(BootOptionName, &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof(BDS_COMMON_OPTION), BootOption0080); LogFlowFuncMarkRC(rc); #if 0 rc = BdsLibRegisterNewOption (BootOptionList, BootOption0080->DevicePath, L"Mac Boot Temp", L"BootOrder"); #endif LogFlowFuncMarkRC(rc); #endif } DEBUG ((EFI_D_INFO, "------------------ VBox Platform Specific Initialization End -----------------------\n")); } #endif BdsLibEnumerateAllBootOption (BootOptionList); SetBootOrderFromQemu (BootOptionList); // // The BootOrder variable may have changed, reload the in-memory list with // it. // BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); // // To give the User a chance to enter Setup here, if user set TimeOut is 0. // BDS should still give user a chance to enter Setup // // Connect first boot option, and then check user input before exit // for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) { BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) { // // skip the header of the link list, becuase it has no boot option // continue; } else { // // Make sure the boot option device path connected, but ignore the BBS device path // if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) { BdsLibConnectDevicePath (BootOption->DevicePath); } break; } } // // Check whether the user input after the duration time has expired // OldTpl = EfiGetCurrentTpl(); gBS->RestoreTPL (TPL_APPLICATION); gBS->WaitForEvent (1, &UserInputDurationTime, &Index); gBS->CloseEvent (UserInputDurationTime); Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); gBS->RaiseTPL (OldTpl); if (!EFI_ERROR (Status)) { // // Enter Setup if user input // Timeout = 0xffff; PlatformBdsEnterFrontPage (Timeout, FALSE); } VBoxLogFlowFuncLeave(); return ; }
/** The function will execute with as the platform policy, current policy is driven by boot mode. IBV/OEM can customize this code for their specific policy action. @param DriverOptionList The header of the driver option link list @param BootOptionList The header of the boot option link list @param ProcessCapsules A pointer to ProcessCapsules() @param BaseMemoryTest A pointer to BaseMemoryTest() **/ VOID EFIAPI PlatformBdsPolicyBehavior ( IN LIST_ENTRY *DriverOptionList, IN LIST_ENTRY *BootOptionList, IN PROCESS_CAPSULES ProcessCapsules, IN BASEM_MEMORY_TEST BaseMemoryTest ) { // // Locate the PCI root bridges and make the PCI bus driver connect each, // non-recursively. This will produce a number of child handles with PciIo on // them. // FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect); // // Find all display class PCI devices (using the handles from the previous // step), and connect them non-recursively. This should produce a number of // child handles with GOPs on them. // FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect); // // Now add the device path of all handles with GOP on them to ConOut and // ErrOut. // FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput); // // Add the hardcoded short-form USB keyboard device path to ConIn. // BdsLibUpdateConsoleVariable (L"ConIn", (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL); // // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut. // BdsLibUpdateConsoleVariable (L"ConIn", (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); BdsLibUpdateConsoleVariable (L"ConOut", (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); BdsLibUpdateConsoleVariable (L"ErrOut", (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); // // Connect the consoles based on the above variables. // BdsLibConnectAllDefaultConsoles (); // // Show the splash screen. // EnableQuietBoot (PcdGetPtr (PcdLogoFile)); // // Connect the rest of the devices. // BdsLibConnectAll (); // // Process QEMU's -kernel command line option. Note that the kernel booted // this way should receive ACPI tables, which is why we connect all devices // first (see above) -- PCI enumeration blocks ACPI table installation, if // there is a PCI host. // TryRunningQemuKernel (); BdsLibEnumerateAllBootOption (BootOptionList); SetBootOrderFromQemu (BootOptionList); // // The BootOrder variable may have changed, reload the in-memory list with // it. // BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE); }
/** The function will execute with as the platform policy, current policy is driven by boot mode. IBV/OEM can customize this code for their specific policy action. @param DriverOptionList The header of the driver option link list @param BootOptionList The header of the boot option link list @param ProcessCapsules A pointer to ProcessCapsules() @param BaseMemoryTest A pointer to BaseMemoryTest() **/ VOID EFIAPI PlatformBdsPolicyBehavior ( IN LIST_ENTRY *DriverOptionList, IN LIST_ENTRY *BootOptionList, IN PROCESS_CAPSULES ProcessCapsules, IN BASEM_MEMORY_TEST BaseMemoryTest ) { EFI_STATUS Status; UINT16 Timeout; EFI_EVENT UserInputDurationTime; LIST_ENTRY *Link; BDS_COMMON_OPTION *BootOption; UINTN Index; EFI_INPUT_KEY Key; EFI_TPL OldTpl; EFI_BOOT_MODE BootMode; DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n")); ConnectRootBridge (); // // Init the time out value // Timeout = PcdGet16 (PcdPlatformBootTimeOut); // // Load the driver option as the driver option list // PlatformBdsGetDriverOption (DriverOptionList); // // Get current Boot Mode // Status = BdsLibGetBootMode (&BootMode); DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode)); // // Go the different platform policy with different boot mode // Notes: this part code can be change with the table policy // ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION); // // Connect platform console // Status = PlatformBdsConnectConsole (gPlatformConsole); if (EFI_ERROR (Status)) { // // Here OEM/IBV can customize with defined action // PlatformBdsNoConsoleAction (); } // // Create a 300ms duration event to ensure user has enough input time to enter Setup // Status = gBS->CreateEvent ( EVT_TIMER, 0, NULL, NULL, &UserInputDurationTime ); ASSERT (Status == EFI_SUCCESS); Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000); ASSERT (Status == EFI_SUCCESS); // // Memory test and Logo show // PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest); // // Perform some platform specific connect sequence // PlatformBdsConnectSequence (); // // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device // and do enumerate all the default boot options. But in development system board, the boot mode // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot. // Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); if (EFI_ERROR(Status)) { // // If cannot find "BootOrder" variable, it may be first boot. // Try to connect all devices and enumerate all boot options here. // BdsLibConnectAll (); BdsLibEnumerateAllBootOption (BootOptionList); } // // To give the User a chance to enter Setup here, if user set TimeOut is 0. // BDS should still give user a chance to enter Setup // // Connect first boot option, and then check user input before exit // for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) { BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) { // // skip the header of the link list, becuase it has no boot option // continue; } else { // // Make sure the boot option device path connected, but ignore the BBS device path // if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) { BdsLibConnectDevicePath (BootOption->DevicePath); } break; } } // // Check whether the user input after the duration time has expired // OldTpl = EfiGetCurrentTpl(); gBS->RestoreTPL (TPL_APPLICATION); gBS->WaitForEvent (1, &UserInputDurationTime, &Index); gBS->CloseEvent (UserInputDurationTime); Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); gBS->RaiseTPL (OldTpl); if (!EFI_ERROR (Status)) { // // Enter Setup if user input // Timeout = 0xffff; PlatformBdsEnterFrontPage (Timeout, FALSE); } }
/** This function attempts to boot for the boot order specified by platform policy. **/ VOID BdsBootDeviceSelect ( VOID ) { EFI_STATUS Status; LIST_ENTRY *Link; BDS_COMMON_OPTION *BootOption; UINTN ExitDataSize; CHAR16 *ExitData; UINT16 Timeout; LIST_ENTRY BootLists; CHAR16 Buffer[20]; BOOLEAN BootNextExist; LIST_ENTRY *LinkBootNext; EFI_EVENT ConnectConInEvent; // // Got the latest boot option // BootNextExist = FALSE; LinkBootNext = NULL; ConnectConInEvent = NULL; InitializeListHead (&BootLists); // // First check the boot next option // ZeroMem (Buffer, sizeof (Buffer)); // // Create Event to signal ConIn connection request // if (PcdGetBool (PcdConInConnectOnDemand)) { Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, BdsEmptyCallbackFunction, NULL, &gConnectConInEventGuid, &ConnectConInEvent ); if (EFI_ERROR(Status)) { ConnectConInEvent = NULL; } } if (mBootNext != NULL) { // // Indicate we have the boot next variable, so this time // boot will always have this boot option // BootNextExist = TRUE; // // Clear the this variable so it's only exist in this time boot // Status = gRT->SetVariable ( L"BootNext", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, 0, NULL ); // // Deleting variable with current variable implementation shouldn't fail. // ASSERT_EFI_ERROR (Status); // // Add the boot next boot option // UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext); BootOption = BdsLibVariableToOption (&BootLists, Buffer); // // If fail to get boot option from variable, just return and do nothing. // if (BootOption == NULL) { return; } BootOption->BootCurrent = *mBootNext; } // // Parse the boot order to get boot option // BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); // // When we didn't have chance to build boot option variables in the first // full configuration boot (e.g.: Reset in the first page or in Device Manager), // we have no boot options in the following mini configuration boot. // Give the last chance to enumerate the boot options. // if (IsListEmpty (&BootLists)) { BdsLibEnumerateAllBootOption (&BootLists); } Link = BootLists.ForwardLink; // // Parameter check, make sure the loop will be valid // if (Link == NULL) { return ; } // // Here we make the boot in a loop, every boot success will // return to the front page // for (;;) { // // Check the boot option list first // if (Link == &BootLists) { // // When LazyConIn enabled, signal connect ConIn event before enter UI // if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) { gBS->SignalEvent (ConnectConInEvent); } // // There are two ways to enter here: // 1. There is no active boot option, give user chance to // add new boot option // 2. All the active boot option processed, and there is no // one is success to boot, then we back here to allow user // add new active boot option // Timeout = 0xffff; PlatformBdsEnterFrontPage (Timeout, FALSE); InitializeListHead (&BootLists); BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); Link = BootLists.ForwardLink; continue; } // // Get the boot option from the link list // BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); // // According to EFI Specification, if a load option is not marked // as LOAD_OPTION_ACTIVE, the boot manager will not automatically // load the option. // if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) { // // skip the header of the link list, because it has no boot option // Link = Link->ForwardLink; continue; } // // Make sure the boot option device path connected, // but ignore the BBS device path // if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) { // // Notes: the internal shell can not been connected with device path // so we do not check the status here // BdsLibConnectDevicePath (BootOption->DevicePath); } // // Restore to original mode before launching boot option. // BdsSetConsoleMode (FALSE); // // All the driver options should have been processed since // now boot will be performed. // Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData); if (Status != EFI_SUCCESS) { // // Call platform action to indicate the boot fail // BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize); // // Check the next boot option // Link = Link->ForwardLink; } else { // // Call platform action to indicate the boot success // BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); PlatformBdsBootSuccess (BootOption); // // Boot success, then stop process the boot order, and // present the boot manager menu, front page // // // When LazyConIn enabled, signal connect ConIn Event before enter UI // if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) { gBS->SignalEvent (ConnectConInEvent); } Timeout = 0xffff; PlatformBdsEnterFrontPage (Timeout, FALSE); // // Rescan the boot option list, avoid potential risk of the boot // option change in front page // if (BootNextExist) { LinkBootNext = BootLists.ForwardLink; } InitializeListHead (&BootLists); if (LinkBootNext != NULL) { // // Reserve the boot next option // InsertTailList (&BootLists, LinkBootNext); } BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); Link = BootLists.ForwardLink; } } }
/** Service routine for BdsInstance->Entry(). Devices are connected, the consoles are initialized, and the boot options are tried. @param This Protocol Instance structure. **/ VOID EFIAPI BdsEntry ( IN EFI_BDS_ARCH_PROTOCOL *This ) { LIST_ENTRY DriverOptionList; LIST_ENTRY BootOptionList; UINTN BootNextSize; CHAR16 *FirmwareVendor; EFI_STATUS Status; UINT16 BootTimeOut; UINTN Index; EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; // // Insert the performance probe // PERF_END (NULL, "DXE", NULL, 0); PERF_START (NULL, "BDS", NULL, 0); // // Initialize the global system boot option and driver option // InitializeListHead (&DriverOptionList); InitializeListHead (&BootOptionList); // // Initialize hotkey service // InitializeHotkeyService (); // // Fill in FirmwareVendor and FirmwareRevision from PCDs // FirmwareVendor = (CHAR16 *)PcdGetPtr (PcdFirmwareVendor); gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor); ASSERT (gST->FirmwareVendor != NULL); gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision); // // Fixup Tasble CRC after we updated Firmware Vendor and Revision // gST->Hdr.CRC32 = 0; gBS->CalculateCrc32 ((VOID *)gST, sizeof(EFI_SYSTEM_TABLE), &gST->Hdr.CRC32); // // Validate Variable. // BdsFormalizeEfiGlobalVariable(); // // Mark the read-only variables if the Variable Lock protocol exists // Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock); DEBUG ((EFI_D_INFO, "[BdsDxe] Locate Variable Lock protocol - %r\n", Status)); if (!EFI_ERROR (Status)) { for (Index = 0; Index < ARRAY_SIZE (mReadOnlyVariables); Index++) { Status = VariableLock->RequestToLock (VariableLock, mReadOnlyVariables[Index], &gEfiGlobalVariableGuid); ASSERT_EFI_ERROR (Status); } } // // Report Status Code to indicate connecting drivers will happen // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS) ); InitializeHwErrRecSupport(); // // Initialize L"Timeout" EFI global variable. // BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); if (BootTimeOut != 0xFFFF) { // // If time out value equal 0xFFFF, no need set to 0xFFFF to variable area because UEFI specification // define same behavior between no value or 0xFFFF value for L"Timeout". // BdsDxeSetVariableAndReportStatusCodeOnError ( L"Timeout", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, sizeof (UINT16), &BootTimeOut ); } // // bugbug: platform specific code // Initialize the platform specific string and language // InitializeStringSupport (); InitializeLanguage (TRUE); InitializeFrontPage (TRUE); // // Do the platform init, can be customized by OEM/IBV // PERF_START (NULL, "PlatformBds", "BDS", 0); PlatformBdsInit (); // // Set up the device list based on EFI 1.1 variables // process Driver#### and Load the driver's in the // driver option list // BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder"); if (!IsListEmpty (&DriverOptionList)) { BdsLibLoadDrivers (&DriverOptionList); } // // Check if we have the boot next option // mBootNext = BdsLibGetVariableAndSize ( L"BootNext", &gEfiGlobalVariableGuid, &BootNextSize ); // // Setup some platform policy here // PlatformBdsPolicyBehavior (&DriverOptionList, &BootOptionList, BdsProcessCapsules, BdsMemoryTest); PERF_END (NULL, "PlatformBds", "BDS", 0); // // BDS select the boot device to load OS // BdsBootDeviceSelect (); // // Only assert here since this is the right behavior, we should never // return back to DxeCore. // ASSERT (FALSE); return ; }
/** Service routine for BdsInstance->Entry(). Devices are connected, the consoles are initialized, and the boot options are tried. @param This Protocol Instance structure. **/ VOID EFIAPI BdsEntry ( IN EFI_BDS_ARCH_PROTOCOL *This ) { LIST_ENTRY DriverOptionList; LIST_ENTRY BootOptionList; UINTN BootNextSize; CHAR16 *FirmwareVendor; // // Insert the performance probe // PERF_END (NULL, "DXE", NULL, 0); PERF_START (NULL, "BDS", NULL, 0); // // Initialize the global system boot option and driver option // InitializeListHead (&DriverOptionList); InitializeListHead (&BootOptionList); // // Initialize hotkey service // InitializeHotkeyService (); // // Fill in FirmwareVendor and FirmwareRevision from PCDs // FirmwareVendor = (CHAR16 *)PcdGetPtr (PcdFirmwareVendor); gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor); ASSERT (gST->FirmwareVendor != NULL); gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision); // // Fixup Tasble CRC after we updated Firmware Vendor and Revision // gBS->CalculateCrc32 ((VOID *)gST, sizeof(EFI_SYSTEM_TABLE), &gST->Hdr.CRC32); // // Validate Variable. // BdsFormalizeEfiGlobalVariable(); // // Do the platform init, can be customized by OEM/IBV // PERF_START (NULL, "PlatformBds", "BDS", 0); PlatformBdsInit (); InitializeHwErrRecSupport(); // // bugbug: platform specific code // Initialize the platform specific string and language // InitializeStringSupport (); InitializeLanguage (TRUE); InitializeFrontPage (TRUE); // // Set up the device list based on EFI 1.1 variables // process Driver#### and Load the driver's in the // driver option list // BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder"); if (!IsListEmpty (&DriverOptionList)) { BdsLibLoadDrivers (&DriverOptionList); } // // Check if we have the boot next option // mBootNext = BdsLibGetVariableAndSize ( L"BootNext", &gEfiGlobalVariableGuid, &BootNextSize ); // // Setup some platform policy here // PlatformBdsPolicyBehavior (&DriverOptionList, &BootOptionList, BdsProcessCapsules, BdsMemoryTest); PERF_END (NULL, "PlatformBds", "BDS", 0); // // BDS select the boot device to load OS // BdsBootDeviceSelect (); // // Only assert here since this is the right behavior, we should never // return back to DxeCore. // ASSERT (FALSE); return ; }