X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=EdkUnixPkg%2FDxe%2FPlatformBds%2FGeneric%2FBdsEntry.c;fp=EdkUnixPkg%2FDxe%2FPlatformBds%2FGeneric%2FBdsEntry.c;h=ddd6b4f78e5d8bbb4e78bf8d39c094e97e760fc5;hp=0000000000000000000000000000000000000000;hb=c9093a06e72ef16d2f3bd7ce0a2b9a172e9d048c;hpb=8ba7afaf2e9c682a5d17760e6dd5463b3a2b2d67 diff --git a/EdkUnixPkg/Dxe/PlatformBds/Generic/BdsEntry.c b/EdkUnixPkg/Dxe/PlatformBds/Generic/BdsEntry.c new file mode 100644 index 0000000000..ddd6b4f78e --- /dev/null +++ b/EdkUnixPkg/Dxe/PlatformBds/Generic/BdsEntry.c @@ -0,0 +1,356 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + BdsEntry.c + +Abstract: + + The entry of the bds + +--*/ + +#include "Bds.h" +#include "BdsPlatform.h" +#include "FrontPage.h" + +EFI_BDS_ARCH_PROTOCOL_INSTANCE gBdsInstanceTemplate = { + EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE, + NULL, + BdsEntry, + 0xFFFF, + TRUE, + EXTENSIVE +}; + +UINT16 *mBootNext = NULL; + +EFI_HANDLE mBdsImageHandle; + +EFI_STATUS +EFIAPI +BdsInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Install Boot Device Selection Protocol + +Arguments: + + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + + EFI_SUCEESS - BDS has finished initializing. + Rerun the + dispatcher and recall BDS.Entry + + Other - Return value from EfiLibAllocatePool() + or gBS->InstallProtocolInterface + +--*/ +{ + EFI_STATUS Status; + + mBdsImageHandle = ImageHandle; + + // + // Install protocol interface + // + Status = gBS->InstallProtocolInterface ( + &gBdsInstanceTemplate.Handle, + &gEfiBdsArchProtocolGuid, + EFI_NATIVE_INTERFACE, + &gBdsInstanceTemplate.Bds + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +VOID +BdsBootDeviceSelect ( + VOID + ) +/*++ + +Routine Description: + + In the loop of attempt to boot for the boot order + +Arguments: + + None. + +Returns: + + None. + +--*/ +{ + 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; + + // + // Got the latest boot option + // + BootNextExist = FALSE; + LinkBootNext = NULL; + InitializeListHead (&BootLists); + + // + // First check the boot next option + // + ZeroMem (Buffer, sizeof (Buffer)); + + 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 + // + gRT->SetVariable ( + L"BootNext", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + mBootNext + ); + + // + // Add the boot next boot option + // + UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext); + BootOption = BdsLibVariableToOption (&BootLists, Buffer); + } + // + // Parse the boot order to get boot option + // + BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); + 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) { + // + // 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, becuase 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); + } + // + // All the driver options should have been processed since + // now boot will be performed. + // + PERF_END (0, BDS_TOK, NULL, 0); + Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData); + if (EFI_ERROR (Status)) { + // + // Call platform action to indicate the boot fail + // + PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize); + + // + // Check the next boot option + // + Link = Link->ForwardLink; + + } else { + // + // Call platform action to indicate the boot success + // + PlatformBdsBootSuccess (BootOption); + + // + // Boot success, then stop process the boot order, and + // present the boot manager menu, front page + // + Timeout = 0xffff; + PlatformBdsEnterFrontPage (Timeout, FALSE); + + // + // Rescan the boot option list, avoid pertential 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; + } + } + + return ; + +} + +EFI_STATUS +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ) +/*++ + +Routine Description: + + Service routine for BdsInstance->Entry(). Devices are connected, the + consoles are initialized, and the boot options are tried. + +Arguments: + + This - Protocol Instance structure. + +Returns: + + EFI_SUCEESS - BDS->Entry has finished executing. + +--*/ +{ + EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData; + LIST_ENTRY DriverOptionList; + LIST_ENTRY BootOptionList; + UINTN BootNextSize; + + // + // Insert the performance probe + // + PERF_END (0, DXE_TOK, NULL, 0); + PERF_START (0, BDS_TOK, NULL, 0); + + // + // Initialize the global system boot option and driver option + // + InitializeListHead (&DriverOptionList); + InitializeListHead (&BootOptionList); + + // + // Get the BDS private data + // + PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This); + + // + // Do the platform init, can be customized by OEM/IBV + // + PERF_START (0, "PlatformBds", "BDS", 0); + PlatformBdsInit (PrivateData); + + // + // 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 (PrivateData, &DriverOptionList, &BootOptionList); + PERF_END (0, L"PlatformBds", L"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 EFI_SUCCESS; +}