/** @file
Implementation for PlatformBdsLib library class interfaces.
Copyright (C) 2015, Red Hat, Inc.
Copyright (c) 2014, ARM Ltd. All rights reserved.
Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.
Copyright (c) 2015, Hisilicon Limited. All rights reserved.
Copyright (c) 2015, Linaro Limited. 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.
Based on the files under ArmVirtPkg/Library/PlatformIntelBdsLib/
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "IntelBdsPlatform.h"
GUID gOemBootVaraibleGuid = {0xb7784577, 0x5aaf, 0x4557, {0xa1, 0x99,
0xd4, 0xa4, 0x2f, 0x45, 0x06, 0xf8} };
//3CEF354A-3B7A-4519-AD70-72A134698311
GUID gEblFileGuid = {0x3CEF354A, 0x3B7A, 0x4519, {0xAD, 0x70,
0x72, 0xA1, 0x34, 0x69, 0x83, 0x11} };
// Need to keep the same with FlashStartOs.inf
// 282cae50-940e-11e5-b7b8-774201c0f2d8
GUID gFlashStartOsAppGuid = { 0x282cae50, 0x940e, 0x11e5, {0xb7, 0xb8,
0x77, 0x42, 0x01, 0xc0, 0xf2, 0xd8} };
// Need to keep the same with EslStartOs.inf
// 8880a72c-9411-11e5-b6f0-97310bc151d1
GUID gEslStartOsAppGuid = { 0x8880a72c, 0x9411, 0x11e5, {0xb6, 0xf0,
0x97, 0x31, 0x0b, 0xc1, 0x51, 0xd1} };
EFI_STATUS
BdsDeleteAllInvalidEfiBootOption (
VOID
);
#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
#pragma pack (1)
typedef struct {
VENDOR_DEVICE_PATH SerialDxe;
UART_DEVICE_PATH Uart;
VENDOR_DEFINED_DEVICE_PATH Vt100;
EFI_DEVICE_PATH_PROTOCOL End;
} PLATFORM_SERIAL_CONSOLE;
#pragma pack ()
#define SERIAL_DXE_FILE_GUID { \
0xD3987D4B, 0x971A, 0x435F, \
{ 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \
}
STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {
//
// VENDOR_DEVICE_PATH SerialDxe
//
{
{ HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },
SERIAL_DXE_FILE_GUID
},
//
// UART_DEVICE_PATH Uart
//
{
{ MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) },
0, // Reserved
FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits
FixedPcdGet8 (PcdUartDefaultParity), // Parity
FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits
},
//
// VENDOR_DEFINED_DEVICE_PATH Vt100
//
{
{
MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,
DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)
},
EFI_VT_100_GUID
},
//
// EFI_DEVICE_PATH_PROTOCOL End
//
{
END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
}
};
#pragma pack (1)
typedef struct {
USB_CLASS_DEVICE_PATH Keyboard;
EFI_DEVICE_PATH_PROTOCOL End;
} PLATFORM_USB_KEYBOARD;
#pragma pack ()
STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {
//
// USB_CLASS_DEVICE_PATH Keyboard
//
{
{
MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,
DP_NODE_LEN (USB_CLASS_DEVICE_PATH)
},
0xFFFF, // VendorId: any
0xFFFF, // ProductId: any
3, // DeviceClass: HID
1, // DeviceSubClass: boot
1 // DeviceProtocol: keyboard
},
//
// EFI_DEVICE_PATH_PROTOCOL End
//
{
END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
}
};
STATIC
UINT16
GetBBSTypeFromFileSysPath (
IN CHAR16 *UsbPathTxt,
IN CHAR16 *FileSysPathTxt,
IN EFI_DEVICE_PATH_PROTOCOL *FileSysPath
)
{
EFI_DEVICE_PATH_PROTOCOL *Node;
if (StrnCmp (UsbPathTxt, FileSysPathTxt, StrLen (UsbPathTxt)) == 0) {
Node = FileSysPath;
while (!IsDevicePathEnd (Node)) {
if ((DevicePathType (Node) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType (Node) == MEDIA_CDROM_DP)) {
return BBS_TYPE_CDROM;
}
Node = NextDevicePathNode (Node);
}
}
return BBS_TYPE_UNKNOWN;
}
STATIC
UINT16
GetBBSTypeFromUsbPath (
IN CONST EFI_DEVICE_PATH_PROTOCOL *UsbPath
)
{
EFI_STATUS Status;
EFI_HANDLE *FileSystemHandles;
UINTN NumberFileSystemHandles;
UINTN Index;
EFI_DEVICE_PATH_PROTOCOL *FileSysPath;
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
CHAR16 *UsbPathTxt;
CHAR16 *FileSysPathTxt;
UINT16 Result;
Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **) &DevPathToText);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Locate DevicePathToTextPro %r\n", Status));
return BBS_TYPE_UNKNOWN;
}
Result = BBS_TYPE_UNKNOWN;
UsbPathTxt = DevPathToText->ConvertDevicePathToText (UsbPath, TRUE, TRUE);
if (UsbPathTxt == NULL) {
return Result;
}
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiSimpleFileSystemProtocolGuid,
NULL,
&NumberFileSystemHandles,
&FileSystemHandles
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Locate SimpleFileSystemProtocol error(%r)\n", Status));
FreePool (UsbPathTxt);
return BBS_TYPE_UNKNOWN;
}
for (Index = 0; Index < NumberFileSystemHandles; Index++) {
FileSysPath = DevicePathFromHandle (FileSystemHandles[Index]);
FileSysPathTxt = DevPathToText->ConvertDevicePathToText (FileSysPath, TRUE, TRUE);
if (FileSysPathTxt == NULL) {
continue;
}
Result = GetBBSTypeFromFileSysPath (UsbPathTxt, FileSysPathTxt, FileSysPath);
FreePool (FileSysPathTxt);
if (Result != BBS_TYPE_UNKNOWN) {
break;
}
}
if (NumberFileSystemHandles != 0) {
FreePool (FileSystemHandles);
}
FreePool (UsbPathTxt);
return Result;
}
STATIC
UINT16
GetBBSTypeFromMessagingDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN EFI_DEVICE_PATH_PROTOCOL *Node
)
{
VENDOR_DEVICE_PATH *Vendor;
UINT16 Result;
Result = BBS_TYPE_UNKNOWN;
switch (DevicePathSubType (Node)) {
case MSG_MAC_ADDR_DP:
Result = BBS_TYPE_EMBEDDED_NETWORK;
break;
case MSG_USB_DP:
Result = GetBBSTypeFromUsbPath (DevicePath);
if (Result == BBS_TYPE_UNKNOWN) {
Result = BBS_TYPE_USB;
}
break;
case MSG_SATA_DP:
Result = BBS_TYPE_HARDDRIVE;
break;
case MSG_VENDOR_DP:
Vendor = (VENDOR_DEVICE_PATH *) (Node);
if ((&Vendor->Guid) != NULL) {
if (CompareGuid (&Vendor->Guid, &((EFI_GUID) DEVICE_PATH_MESSAGING_SAS))) {
Result = BBS_TYPE_HARDDRIVE;
}
}
break;
default:
Result = BBS_TYPE_UNKNOWN;
break;
}
return Result;
}
STATIC
UINT16
GetBBSTypeByDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
EFI_DEVICE_PATH_PROTOCOL *Node;
UINT16 Result;
Result = BBS_TYPE_UNKNOWN;
if (DevicePath == NULL) {
return Result;
}
Node = DevicePath;
while (!IsDevicePathEnd (Node)) {
switch (DevicePathType (Node)) {
case MEDIA_DEVICE_PATH:
if (DevicePathSubType (Node) == MEDIA_CDROM_DP) {
Result = BBS_TYPE_CDROM;
}
break;
case MESSAGING_DEVICE_PATH:
Result = GetBBSTypeFromMessagingDevicePath (DevicePath, Node);
break;
default:
Result = BBS_TYPE_UNKNOWN;
break;
}
if (Result != BBS_TYPE_UNKNOWN) {
break;
}
Node = NextDevicePathNode (Node);
}
return Result;
}
STATIC
EFI_STATUS
GetBmcBootOptionsSetting (
OUT IPMI_GET_BOOT_OPTION *BmcBootOpt
)
{
EFI_STATUS Status;
Status = IpmiCmdGetSysBootOptions (BmcBootOpt);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Get iBMC BootOpts %r!\n", Status));
return Status;
}
if (BmcBootOpt->BootFlagsValid != BOOT_OPTION_BOOT_FLAG_VALID) {
return EFI_NOT_FOUND;
}
if (BmcBootOpt->Persistent) {
BmcBootOpt->BootFlagsValid = BOOT_OPTION_BOOT_FLAG_VALID;
} else {
BmcBootOpt->BootFlagsValid = BOOT_OPTION_BOOT_FLAG_INVALID;
}
Status = IpmiCmdSetSysBootOptions (BmcBootOpt);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Set iBMC BootOpts %r!\n", Status));
}
return Status;
}
STATIC
VOID
RestoreBootOrder (
VOID
)
{
EFI_STATUS Status;
UINT16 *BootOrder;
UINTN BootOrderSize;
GetVariable2 (L"BootOrderBackup", &gOemBootVaraibleGuid, (VOID **) &BootOrder, &BootOrderSize);
if (BootOrder == NULL) {
return ;
}
Print (L"Restore BootOrder(%d).\n", BootOrderSize / sizeof (UINT16));
Status = gRT->SetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
BootOrderSize,
BootOrder
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "SetVariable BootOrder %r!\n", Status));
}
Status = gRT->SetVariable (
L"BootOrderBackup",
&gOemBootVaraibleGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
0,
NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "SetVariable BootOrderBackup %r!\n", Status));
}
FreePool (BootOrder);
return;
}
VOID
RestoreBootOrderOnReadyToBoot (
IN EFI_EVENT Event,
IN VOID *Context
)
{
// restore BootOrder variable in normal condition.
RestoreBootOrder ();
}
STATIC
VOID
UpdateBootOrder (
IN UINT16 *NewOrder,
IN UINT16 *BootOrder,
IN UINTN BootOrderSize
)
{
EFI_STATUS Status;
EFI_EVENT Event;
Status = gRT->SetVariable (
L"BootOrderBackup",
&gOemBootVaraibleGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
BootOrderSize,
BootOrder
);
if (EFI_ERROR (Status)) {
return;
}
Status = gRT->SetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
BootOrderSize,
NewOrder
);
if (EFI_ERROR (Status)) {
return;
}
// Register notify function to restore BootOrder variable on ReadyToBoot Event.
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
RestoreBootOrderOnReadyToBoot,
NULL,
&gEfiEventReadyToBootGuid,
&Event
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Create ready to boot event %r!\n", Status));
}
return;
}
STATIC
VOID
SetBootOrder (
IN UINT16 BootType
)
{
UINT16 *NewOrder;
UINT16 *RemainBoots;
UINT16 *BootOrder;
UINTN BootOrderSize;
CHAR16 OptionName[sizeof ("Boot####")];
UINTN Index;
LIST_ENTRY BootOptionList;
BDS_COMMON_OPTION *Option;
UINTN SelectCnt;
UINTN RemainCnt;
InitializeListHead (&BootOptionList);
GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);
if (BootOrder == NULL) {
return ;
}
NewOrder = AllocatePool (BootOrderSize);
RemainBoots = AllocatePool (BootOrderSize);
if ((NewOrder == NULL) || (RemainBoots == NULL)) {
DEBUG ((DEBUG_ERROR, "Out of resources."));
goto Exit;
}
SelectCnt = 0;
RemainCnt = 0;
for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]);
Option = BdsLibVariableToOption (&BootOptionList, OptionName);
if (Option == NULL) {
DEBUG ((DEBUG_ERROR, "Boot%04x is invalid option!\n", BootOrder[Index]));
continue;
}
if (GetBBSTypeByDevicePath (Option->DevicePath) == BootType) {
NewOrder[SelectCnt++] = BootOrder[Index];
} else {
RemainBoots[RemainCnt++] = BootOrder[Index];
}
}
if (SelectCnt != 0) {
// append RemainBoots to NewOrder
for (Index = 0; Index < RemainCnt; Index++) {
NewOrder[SelectCnt + Index] = RemainBoots[Index];
}
if (CompareMem (NewOrder, BootOrder, BootOrderSize) != 0) {
UpdateBootOrder (NewOrder, BootOrder, BootOrderSize);
}
}
Exit:
FreePool (BootOrder);
if (NewOrder != NULL) {
FreePool (NewOrder);
}
if (RemainBoots != NULL) {
FreePool (RemainBoots);
}
return ;
}
STATIC
VOID
HandleBmcBootType (
VOID
)
{
EFI_STATUS Status;
IPMI_GET_BOOT_OPTION BmcBootOpt;
UINT16 BootType;
Status = GetBmcBootOptionsSetting (&BmcBootOpt);
if (EFI_ERROR (Status)) {
return;
}
Print (L"Boot Type from BMC is %x\n", BmcBootOpt.BootDeviceSelector);
switch (BmcBootOpt.BootDeviceSelector) {
case ForcePxe:
BootType = BBS_TYPE_EMBEDDED_NETWORK;
break;
case ForcePrimaryRemovableMedia:
BootType = BBS_TYPE_USB;
break;
case ForceDefaultHardDisk:
BootType = BBS_TYPE_HARDDRIVE;
break;
case ForceDefaultCD:
BootType = BBS_TYPE_CDROM;
break;
default:
return;
}
SetBootOrder (BootType);
}
//
// BDS Platform Functions
//
/**
Platform Bds init. Include the platform firmware vendor, revision
and so crc check.
**/
VOID
EFIAPI
PlatformBdsInit (
VOID
)
{
//Signal EndofDxe Event
EfiEventGroupSignal(&gEfiEndOfDxeEventGroupGuid);
// restore BootOrder variable if previous BMC boot override attempt
// left it in a modified state
RestoreBootOrder ();
}
/**
Check if the handle satisfies a particular condition.
@param[in] Handle The handle to check.
@param[in] ReportText A caller-allocated string passed in for reporting
purposes. It must never be NULL.
@retval TRUE The condition is satisfied.
@retval FALSE Otherwise. This includes the case when the condition could not
be fully evaluated due to an error.
**/
typedef
BOOLEAN
(EFIAPI *FILTER_FUNCTION) (
IN EFI_HANDLE Handle,
IN CONST CHAR16 *ReportText
);
/**
Process a handle.
@param[in] Handle The handle to process.
@param[in] ReportText A caller-allocated string passed in for reporting
purposes. It must never be NULL.
**/
typedef
VOID
(EFIAPI *CALLBACK_FUNCTION) (
IN EFI_HANDLE Handle,
IN CONST CHAR16 *ReportText
);
/**
Locate all handles that carry the specified protocol, filter them with a
callback function, and pass each handle that passes the filter to another
callback.
@param[in] ProtocolGuid The protocol to look for.
@param[in] Filter The filter function to pass each handle to. If this
parameter is NULL, then all handles are processed.
@param[in] Process The callback function to pass each handle to that
clears the filter.
**/
STATIC
VOID
FilterAndProcess (
IN EFI_GUID *ProtocolGuid,
IN FILTER_FUNCTION Filter OPTIONAL,
IN CALLBACK_FUNCTION Process
)
{
EFI_STATUS Status;
EFI_HANDLE *Handles;
UINTN NoHandles;
UINTN Idx;
Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid,
NULL /* SearchKey */, &NoHandles, &Handles);
if (EFI_ERROR (Status)) {
//
// This is not an error, just an informative condition.
//
DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid,
Status));
return;
}
ASSERT (NoHandles > 0);
for (Idx = 0; Idx < NoHandles; ++Idx) {
CHAR16 *DevicePathText;
STATIC CHAR16 Fallback[] = L"";
//
// The ConvertDevicePathToText() function handles NULL input transparently.
//
DevicePathText = ConvertDevicePathToText (
DevicePathFromHandle (Handles[Idx]),
FALSE, // DisplayOnly
FALSE // AllowShortcuts
);
if (DevicePathText == NULL) {
DevicePathText = Fallback;
}
if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) {
Process (Handles[Idx], DevicePathText);
}
if (DevicePathText != Fallback) {
FreePool (DevicePathText);
}
}
gBS->FreePool (Handles);
}
/**
This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
**/
STATIC
BOOLEAN
EFIAPI
IsPciDisplay (
IN EFI_HANDLE Handle,
IN CONST CHAR16 *ReportText
)
{
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
PCI_TYPE00 Pci;
Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid,
(VOID**)&PciIo);
if (EFI_ERROR (Status)) {
//
// This is not an error worth reporting.
//
return FALSE;
}
Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */,
sizeof Pci / sizeof (UINT32), &Pci);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));
return FALSE;
}
return IS_PCI_DISPLAY (&Pci);
}
/**
This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
the matching driver to produce all first-level child handles.
**/
STATIC
VOID
EFIAPI
Connect (
IN EFI_HANDLE Handle,
IN CONST CHAR16 *ReportText
)
{
EFI_STATUS Status;
Status = gBS->ConnectController (
Handle, // ControllerHandle
NULL, // DriverImageHandle
NULL, // RemainingDevicePath -- produce all children
FALSE // Recursive
);
DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n",
__FUNCTION__, ReportText, Status));
}
/**
This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
handle, and adds it to ConOut and ErrOut.
**/
STATIC
VOID
EFIAPI
AddOutput (
IN EFI_HANDLE Handle,
IN CONST CHAR16 *ReportText
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
DevicePath = DevicePathFromHandle (Handle);
if (DevicePath == NULL) {
DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n",
__FUNCTION__, ReportText, Handle));
return;
}
Status = BdsLibUpdateConsoleVariable (L"ConOut", DevicePath, NULL);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__,
ReportText, Status));
return;
}
Status = BdsLibUpdateConsoleVariable (L"ErrOut", DevicePath, NULL);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__,
ReportText, Status));
return;
}
DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__,
ReportText));
}
/**
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;
//
// 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 ();
//
// Add memory test to convert memory above 4GB to be tested
//
Status = BaseMemoryTest (QUICK);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "[%a:%d] - Base memory test failed: %r\n", __FUNCTION__, __LINE__, Status));
}
//
// 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);
// Add Flash Start OS and ESL Start OS boot option
(VOID) HwBdsLibRegisterAppBootOption (BootOptionList, &gFlashStartOsAppGuid, L"Flash Start OS");
(VOID) HwBdsLibRegisterAppBootOption (BootOptionList, &gEslStartOsAppGuid, L"ESL Start OS");
// Add EBL as boot option
(VOID) HwBdsLibRegisterAppBootOption (BootOptionList, &gEblFileGuid, L"Embedded Boot Loader (EBL)");
// Remove EFI Misc Device Boot Options
BdsDeleteAllInvalidEfiBootOption ();
//SetBootOrderFromQemu (BootOptionList);
//
// The BootOrder variable may have changed, reload the in-memory list with
// it.
//
BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
//PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE);
Print (L"Press Enter to boot OS immediately.\n");
Print (L"Press any other key in %d seconds to stop automatical booting...\n", PcdGet16(PcdPlatformBootTimeOut));
PlatformBdsEnterFrontPage (PcdGet16(PcdPlatformBootTimeOut), TRUE);
HandleBmcBootType ();
}
/**
Hook point after a boot attempt succeeds. We don't expect a boot option to
return, so the UEFI 2.0 specification defines that you will default to an
interactive mode and stop processing the BootOrder list in this case. This
is also a platform implementation and can be customized by IBV/OEM.
@param Option Pointer to Boot Option that succeeded to boot.
**/
VOID
EFIAPI
PlatformBdsBootSuccess (
IN BDS_COMMON_OPTION *Option
)
{
}
/**
Hook point after a boot attempt fails.
@param Option Pointer to Boot Option that failed to boot.
@param Status Status returned from failed boot.
@param ExitData Exit data returned from failed boot.
@param ExitDataSize Exit data size returned from failed boot.
**/
VOID
EFIAPI
PlatformBdsBootFail (
IN BDS_COMMON_OPTION *Option,
IN EFI_STATUS Status,
IN CHAR16 *ExitData,
IN UINTN ExitDataSize
)
{
}
/**
This function locks platform flash that is not allowed to be updated during normal boot path.
The flash layout is platform specific.
**/
VOID
EFIAPI
PlatformBdsLockNonUpdatableFlash (
VOID
)
{
return;
}