* [PATCH] PurleyOpenBoardPkg: add platform level fast boot support
@ 2018-09-27 7:42 Zhou, Bowen
0 siblings, 0 replies; only message in thread
From: Zhou, Bowen @ 2018-09-27 7:42 UTC (permalink / raw)
To: edk2-devel@lists.01.org; +Cc: Cao, Rock, Song, Edmund
Introduce initial support for fast boot and related feature flags. This is targeted for fixed hardware configuration systems which care less about BDS phase console and dynamic detection, where a headless-like boot is acceptable.
When fast boot flag is turned ON, some features will be disabled such as IPMI. Users are supposed to tune flags to meet their own requirements.
Cc: Rock Cao <rock.cao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Xiaohu Zhou <bowen.zhou@intel.com>
---
.../BoardMtOlympus/PlatformPkg.dsc | 5 +
.../BoardMtOlympus/PlatformPkgConfig.dsc | 5 +
.../BoardMtOlympus/PlatformPkgPcd.dsc | 4 +
.../DxePlatformBootManagerLib/BdsPlatform.c | 1360 ++++++++++++++++++++
.../DxePlatformBootManagerLib/BdsPlatform.h | 190 +++
.../DxePlatformBootManagerLib.inf | 102 ++
.../Library/DxePlatformBootManagerLib/MemoryTest.c | 91 ++
.../DxePlatformBootManagerLib/PlatformBootOption.c | 565 ++++++++
Platform/Intel/PurleyOpenBoardPkg/PlatPkg.dec | 6 +
9 files changed, 2328 insertions(+)
create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.c
create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.h
create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf
create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/MemoryTest.c
create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/PlatformBootOption.c
diff --git a/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkg.dsc b/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkg.dsc
index 7f9c786b9d..a2dc9b66b6 100644
--- a/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkg.dsc
+++ b/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkg.dsc
@@ -84,7 +84,12 @@
!include $(PCH_PKG)/PchCommonLib.dsc
[LibraryClasses.common]
+!if gPlatformTokenSpaceGuid.PcdFastBoot == FALSE
PlatformBootManagerLib|MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf
+!else
+ PlatformBootManagerLib|$(BOARD_PKG)/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf
+!endif
+
TestPointCheckLib|MinPlatformPkg/Test/Library/TestPointCheckLibNull/TestPointCheckLibNull.inf
CompressLib|MinPlatformPkg/Library/CompressLib/CompressLib.inf
diff --git a/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgConfig.dsc b/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgConfig.dsc
index 39d60df47f..4f9e0a9702 100644
--- a/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgConfig.dsc
+++ b/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgConfig.dsc
@@ -61,3 +61,8 @@
gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosEnable|TRUE
gAdvancedFeaturePkgTokenSpaceGuid.PcdIpmiEnable|TRUE
+ gPlatformTokenSpaceGuid.PcdFastBoot|FALSE
+!if gPlatformTokenSpaceGuid.PcdFastBoot == TRUE
+ gAdvancedFeaturePkgTokenSpaceGuid.PcdIpmiEnable|FALSE
+ gPlatformTokenSpaceGuid.PcdUpdateConsoleInBds|FALSE
+!endif
\ No newline at end of file
diff --git a/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgPcd.dsc b/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgPcd.dsc
index c4fff722ab..bfe32aba1c 100644
--- a/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgPcd.dsc
+++ b/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgPcd.dsc
@@ -279,7 +279,11 @@
gOemSkuTokenSpaceGuid.PcdOemSkuUplinkPortIndex|0x5
[PcdsDynamicExHii.common.DEFAULT]
+!if gPlatformTokenSpaceGuid.PcdFastBoot == FALSE
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|3 # Variable: L"Timeout"
+!else
+ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|0 # Variable: L"Timeout"
+!endif
gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|L"HwErrRecSupport"|gEfiGlobalVariableGuid|0x0|1 # Variable: L"HwErrRecSupport"
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.c b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.c
new file mode 100644
index 0000000000..831d325037
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.c
@@ -0,0 +1,1360 @@
+/** @file
+ This file include all platform action which can be customized by IBV/OEM.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that 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.
+
+**/
+
+#include "BdsPlatform.h"
+#include <Guid/EventGroup.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/PciIo.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Guid/EventGroup.h>
+
+#include <Library/Tcg2PhysicalPresenceLib.h>
+
+#include <Library/HobLib.h>
+#include <Protocol/UsbIo.h>
+
+#include <Library/UefiBootManagerLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_BOOT_MODE gBootMode;
+
+BOOLEAN gPPRequireUIConfirm;
+
+extern UINTN mBootMenuOptionNumber;
+
+GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = {
+ {
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_CLASS_DP,
+ {
+ (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),
+ (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
+ }
+ },
+ 0xffff, // VendorId
+ 0xffff, // ProductId
+ CLASS_HID, // DeviceClass
+ SUBCLASS_BOOT, // DeviceSubClass
+ PROTOCOL_KEYBOARD // DeviceProtocol
+ },
+ gEndEntire
+};
+
+//
+// Internal shell mode
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mShellModeColumn;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mShellModeRow;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mShellHorizontalResolution;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mShellVerticalResolution;
+//
+// BDS Platform Functions
+//
+
+BOOLEAN
+IsMorBitSet (
+ VOID
+ )
+{
+ UINTN MorControl;
+ EFI_STATUS Status;
+ UINTN DataSize;
+
+ //
+ // Check if the MOR bit is set.
+ //
+ DataSize = sizeof (MorControl);
+ Status = gRT->GetVariable (
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+ &gEfiMemoryOverwriteControlDataGuid,
+ NULL,
+ &DataSize,
+ &MorControl
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, " PlatformBootMangerLib: gEfiMemoryOverwriteControlDataGuid doesn't exist!!***\n"));
+ MorControl = 0;
+ } else {
+ DEBUG ((DEBUG_INFO, " PlatformBootMangerLib: Get the gEfiMemoryOverwriteControlDataGuid = %x!!***\n", MorControl));
+ }
+
+ return (BOOLEAN) (MorControl & 0x01);
+}
+
+VOID
+DumpDevicePath (
+ IN CHAR16 *Name,
+ IN EFI_DEVICE_PATH *DevicePath
+ )
+{
+ CHAR16 *Str;
+
+ Str = ConvertDevicePathToText(DevicePath, TRUE, TRUE);
+ DEBUG ((DEBUG_INFO, "%s: %s\n", Name, Str));
+ if (Str != NULL) {
+ FreePool (Str);
+ }
+}
+
+/**
+ An empty function to pass error checking of CreateEventEx ().
+
+ This empty function ensures that EVT_NOTIFY_SIGNAL_ALL is error
+ checked correctly since it is now mapped into CreateEventEx() in UEFI 2.0.
+
+ @param Event Event whose notification function is being invoked.
+ @param Context The pointer to the notification function's context,
+ which is implementation-dependent.
+**/
+VOID
+EFIAPI
+InternalBdsEmptyCallbackFuntion (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ return;
+}
+
+VOID
+ExitPmAuth (
+ VOID
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ EFI_EVENT EndOfDxeEvent;
+
+ DEBUG((DEBUG_INFO,"ExitPmAuth ()- Start\n"));
+ //
+ // Prepare S3 information, this MUST be done before ExitPmAuth/EndOfDxe
+ //
+ //
+ // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ InternalBdsEmptyCallbackFuntion,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+ gBS->SignalEvent (EndOfDxeEvent);
+ gBS->CloseEvent (EndOfDxeEvent);
+ DEBUG((DEBUG_INFO,"All EndOfDxe callbacks have returned successfully\n"));
+
+ //
+ // NOTE: We need install DxeSmmReadyToLock directly here because many boot script is added via ExitPmAuth/EndOfDxe callback.
+ // If we install them at same callback, these boot script will be rejected because BootScript Driver runs first to lock them done.
+ // So we seperate them to be 2 different events, ExitPmAuth is last chance to let platform add boot script. DxeSmmReadyToLock will
+ // make boot script save driver lock down the interface.
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiDxeSmmReadyToLockProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ DEBUG((DEBUG_INFO,"ExitPmAuth ()- End\n"));
+}
+
+VOID
+ConnectRootBridge (
+ BOOLEAN Recursive
+ )
+{
+ UINTN RootBridgeHandleCount;
+ EFI_HANDLE *RootBridgeHandleBuffer;
+ UINTN RootBridgeIndex;
+
+ RootBridgeHandleCount = 0;
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ &RootBridgeHandleCount,
+ &RootBridgeHandleBuffer
+ );
+ for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {
+ gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, Recursive);
+ }
+}
+
+
+/**
+ Return whether the device is trusted console.
+
+ @param Device The device to be tested.
+
+ @retval TRUE The device can be trusted.
+ @retval FALSE The device cannot be trusted.
+**/
+BOOLEAN
+IsTrustedConsole (
+ IN CONSOLE_TYPE ConsoleType,
+ IN EFI_DEVICE_PATH_PROTOCOL *Device
+ )
+{
+ VOID *TrustedConsoleDevicepath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
+ UINTN Size;
+ EFI_DEVICE_PATH_PROTOCOL *ConsoleDevice;
+
+ if (Device == NULL) {
+ return FALSE;
+ }
+
+ ConsoleDevice = DuplicateDevicePath(Device);
+
+ TrustedConsoleDevicepath = NULL;
+
+ switch (ConsoleType) {
+ case ConIn:
+ TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
+ break;
+ case ConOut:
+ //
+ // Check GOP and remove last node
+ //
+ TempDevicePath = ConsoleDevice;
+ while (!IsDevicePathEndType (TempDevicePath)) {
+ if (DevicePathType (TempDevicePath) == ACPI_DEVICE_PATH &&
+ DevicePathSubType (TempDevicePath) == ACPI_ADR_DP) {
+ SetDevicePathEndNode (TempDevicePath);
+ break;
+ }
+ TempDevicePath = NextDevicePathNode (TempDevicePath);
+ }
+
+ TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
+ break;
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
+ TempDevicePath = TrustedConsoleDevicepath;
+ do {
+ Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
+ if (Instance == NULL) {
+ break;
+ }
+
+ if (CompareMem (ConsoleDevice, Instance, Size - END_DEVICE_PATH_LENGTH) == 0) {
+ FreePool (Instance);
+ FreePool (ConsoleDevice);
+ return TRUE;
+ }
+
+ FreePool (Instance);
+ } while (TempDevicePath != NULL);
+
+ FreePool (ConsoleDevice);
+
+ return FALSE;
+}
+
+BOOLEAN
+IsUsbShortForm (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
+ ((DevicePathSubType (DevicePath) == MSG_USB_CLASS_DP) || (DevicePathSubType (DevicePath) == MSG_USB_WWID_DP)) ) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Connect the USB short form device path.
+
+ @param DevicePath USB short form device path
+
+ @retval EFI_SUCCESS Successfully connected the USB device
+ @retval EFI_NOT_FOUND Cannot connect the USB device
+ @retval EFI_INVALID_PARAMETER The device path is invalid.
+**/
+EFI_STATUS
+ConnectUsbShortFormDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *Handles;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Class[3];
+ BOOLEAN AtLeastOneConnected;
+
+ //
+ // Check the passed in parameters
+ //
+ if (DevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsUsbShortForm (DevicePath)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Find the usb host controller firstly, then connect with the remaining device path
+ //
+ AtLeastOneConnected = FALSE;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handles
+ );
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ Handles[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Check whether the Pci device is the wanted usb host controller
+ //
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
+ if (!EFI_ERROR (Status) &&
+ ((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))
+ ) {
+ Status = gBS->ConnectController (
+ Handles[Index],
+ NULL,
+ DevicePath,
+ FALSE
+ );
+ if (!EFI_ERROR(Status)) {
+ AtLeastOneConnected = TRUE;
+ }
+ }
+ }
+ }
+
+ return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;
+}
+
+/**
+ Update the ConIn variable with USB Keyboard device path,if its not already exists in ConIn
+**/
+VOID
+EnumUsbKeyboard (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "[EnumUsbKeyboard]\n"));
+ EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, NULL);
+
+ //
+ // Append Usb Keyboard short form DevicePath into "ConInDev"
+ //
+ EfiBootManagerUpdateConsoleVariable (ConInDev, (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, NULL);
+}
+
+BOOLEAN
+IsVgaHandle (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+ EFI_STATUS Status;
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIo
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (!EFI_ERROR (Status)) {
+ if (IS_PCI_VGA (&Pci) || IS_PCI_OLD_VGA (&Pci)) {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+EFI_HANDLE
+IsVideoController (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_STATUS Status;
+ EFI_HANDLE DeviceHandle;
+
+ DupDevicePath = DuplicateDevicePath (DevicePath);
+ ASSERT (DupDevicePath != NULL);
+ if (DupDevicePath == NULL) {
+ return NULL;
+ }
+
+ TempDevicePath = DupDevicePath;
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &TempDevicePath,
+ &DeviceHandle
+ );
+ FreePool (DupDevicePath);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ if (IsVgaHandle (DeviceHandle)) {
+ return DeviceHandle;
+ } else {
+ return NULL;
+ }
+}
+
+BOOLEAN
+IsGopDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ while (!IsDevicePathEndType (DevicePath)) {
+ if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH &&
+ DevicePathSubType (DevicePath) == ACPI_ADR_DP) {
+ return TRUE;
+ }
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+ return FALSE;
+}
+
+/**
+ Remove all GOP device path instance from DevicePath and add the Gop to the DevicePath.
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+UpdateGopDevicePath (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ EFI_DEVICE_PATH_PROTOCOL *Gop
+ )
+{
+ UINTN Size;
+ UINTN GopSize;
+ EFI_DEVICE_PATH_PROTOCOL *Temp;
+ EFI_DEVICE_PATH_PROTOCOL *Return;
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
+ BOOLEAN Exist;
+
+ Exist = FALSE;
+ Return = NULL;
+ GopSize = GetDevicePathSize (Gop);
+ do {
+ Instance = GetNextDevicePathInstance (&DevicePath, &Size);
+ if (Instance == NULL) {
+ break;
+ }
+ if (!IsGopDevicePath (Instance) ||
+ (Size == GopSize && CompareMem (Instance, Gop, GopSize) == 0)
+ ) {
+ if (Size == GopSize && CompareMem (Instance, Gop, GopSize) == 0) {
+ Exist = TRUE;
+ }
+ Temp = Return;
+ Return = AppendDevicePathInstance (Return, Instance);
+ if (Temp != NULL) {
+ FreePool (Temp);
+ }
+ }
+ FreePool (Instance);
+ } while (DevicePath != NULL);
+
+ if (!Exist) {
+ Temp = Return;
+ Return = AppendDevicePathInstance (Return, Gop);
+ if (Temp != NULL) {
+ FreePool (Temp);
+ }
+ }
+ return Return;
+}
+
+/**
+ Get Graphics Controller Handle.
+
+ @retval GraphicsController Successfully located
+ @retval NULL Failed to locate
+**/
+EFI_HANDLE
+EFIAPI
+GetGraphicsController (
+ IN BOOLEAN NeedTrustedConsole
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_HANDLE *PciHandles;
+ UINTN PciHandlesSize;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &PciHandlesSize,
+ &PciHandles
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ for (Index = 0; Index < PciHandlesSize; Index++) {
+ Status = gBS->HandleProtocol (
+ PciHandles[Index],
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+ if (!IsVgaHandle (PciHandles[Index])) {
+ continue;
+ }
+ if ((NeedTrustedConsole && IsTrustedConsole (ConOut, DevicePath)) ||
+ ((!NeedTrustedConsole) && (!IsTrustedConsole (ConOut, DevicePath)))) {
+ return PciHandles[Index];
+ }
+ }
+
+ return NULL;
+}
+
+VOID
+UpdateGraphicConOut (
+ IN BOOLEAN NeedTrustedConsole
+ )
+{
+ EFI_HANDLE GraphicsControllerHandle;
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *ConOutDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *UpdatedConOutDevicePath;
+
+ //
+ // Update ConOut variable
+ //
+ GraphicsControllerHandle = GetGraphicsController (NeedTrustedConsole);
+ if (GraphicsControllerHandle != NULL) {
+ //
+ // Connect the GOP driver
+ //
+ gBS->ConnectController (GraphicsControllerHandle, NULL, NULL, TRUE);
+
+ //
+ // Get the GOP device path
+ // NOTE: We may get a device path that contains Controller node in it.
+ //
+ GopDevicePath = EfiBootManagerGetGopDevicePath (GraphicsControllerHandle);
+ if (GopDevicePath != NULL) {
+ GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConOutDevicePath, NULL);
+ UpdatedConOutDevicePath = UpdateGopDevicePath (ConOutDevicePath, GopDevicePath);
+ if (ConOutDevicePath != NULL) {
+ FreePool (ConOutDevicePath);
+ }
+ FreePool (GopDevicePath);
+ gRT->SetVariable (
+ L"ConOut",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ GetDevicePathSize (UpdatedConOutDevicePath),
+ UpdatedConOutDevicePath
+ );
+ }
+ }
+}
+
+VOID
+AddConsoleVariable (
+ IN CONSOLE_TYPE ConsoleType,
+ IN EFI_DEVICE_PATH *ConsoleDevicePath
+ )
+{
+ EFI_DEVICE_PATH *TempDevicePath;
+ EFI_DEVICE_PATH *Instance;
+ UINTN Size;
+ EFI_HANDLE GraphicsControllerHandle;
+ EFI_DEVICE_PATH *GopDevicePath;
+
+ TempDevicePath = ConsoleDevicePath;
+ do {
+ Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
+ if (Instance == NULL) {
+ break;
+ }
+
+ switch (ConsoleType) {
+ case ConIn:
+ if (IsUsbShortForm (Instance)) {
+ //
+ // Append Usb Keyboard short form DevicePath into "ConInDev"
+ //
+ EfiBootManagerUpdateConsoleVariable (ConInDev, Instance, NULL);
+ }
+ EfiBootManagerUpdateConsoleVariable (ConsoleType, Instance, NULL);
+ break;
+ case ConOut:
+ GraphicsControllerHandle = IsVideoController (Instance);
+ if (GraphicsControllerHandle == NULL) {
+ EfiBootManagerUpdateConsoleVariable (ConsoleType, Instance, NULL);
+ } else {
+ //
+ // Connect the GOP driver
+ //
+ gBS->ConnectController (GraphicsControllerHandle, NULL, NULL, TRUE);
+ //
+ // Get the GOP device path
+ // NOTE: We may get a device path that contains Controller node in it.
+ //
+ GopDevicePath = EfiBootManagerGetGopDevicePath (GraphicsControllerHandle);
+ if (GopDevicePath != NULL) {
+ EfiBootManagerUpdateConsoleVariable (ConsoleType, GopDevicePath, NULL);
+ }
+ }
+ break;
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
+ FreePool (Instance);
+ } while (TempDevicePath != NULL);
+}
+
+/**
+ The function connects the trusted consoles.
+**/
+VOID
+ConnectTrustedConsole (
+ VOID
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Consoles;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
+ EFI_DEVICE_PATH_PROTOCOL *Next;
+ UINTN Size;
+ UINTN Index;
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ CHAR16 *ConsoleVar[] = {L"ConIn", L"ConOut"};
+ VOID *TrustedConsoleDevicepath;
+
+ TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
+ DumpDevicePath (L"TrustedConsoleIn", TrustedConsoleDevicepath);
+ TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
+ DumpDevicePath (L"TrustedConsoleOut", TrustedConsoleDevicepath);
+
+ for (Index = 0; Index < sizeof (ConsoleVar) / sizeof (ConsoleVar[0]); Index++) {
+
+ GetEfiGlobalVariable2 (ConsoleVar[Index], (VOID **)&Consoles, NULL);
+
+ TempDevicePath = Consoles;
+ do {
+ Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
+ if (Instance == NULL) {
+ break;
+ }
+ if (IsTrustedConsole (Index, Instance)) {
+ if (IsUsbShortForm (Instance)) {
+ ConnectUsbShortFormDevicePath (Instance);
+ } else {
+ for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {
+ if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) {
+ break;
+ } else if (DevicePathType (Next) == HARDWARE_DEVICE_PATH &&
+ DevicePathSubType (Next) == HW_CONTROLLER_DP &&
+ DevicePathType (NextDevicePathNode (Next)) == ACPI_DEVICE_PATH &&
+ DevicePathSubType (NextDevicePathNode (Next)) == ACPI_ADR_DP
+ ) {
+ break;
+ }
+ }
+ if (!IsDevicePathEnd (Next)) {
+ SetDevicePathEndNode (Next);
+ Status = EfiBootManagerConnectDevicePath (Instance, &Handle);
+ if (!EFI_ERROR (Status)) {
+ gBS->ConnectController (Handle, NULL, NULL, TRUE);
+ }
+ } else {
+ EfiBootManagerConnectDevicePath (Instance, NULL);
+ }
+ }
+ }
+ FreePool (Instance);
+ } while (TempDevicePath != NULL);
+
+ if (Consoles != NULL) {
+ FreePool (Consoles);
+ }
+ }
+}
+
+/**
+ The function connects the trusted Storages.
+**/
+VOID
+ConnectTrustedStorage (
+ VOID
+ )
+{
+ VOID *TrustedStorageDevicepath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
+ UINTN Size;
+ EFI_DEVICE_PATH_PROTOCOL *TempStorageDevicePath;
+ EFI_STATUS Status;
+ EFI_HANDLE DeviceHandle;
+
+ TrustedStorageDevicepath = PcdGetPtr (PcdTrustedStorageDevicePath);
+ DumpDevicePath (L"TrustedStorage", TrustedStorageDevicepath);
+
+ TempDevicePath = TrustedStorageDevicepath;
+ do {
+ Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
+ if (Instance == NULL) {
+ break;
+ }
+
+ EfiBootManagerConnectDevicePath (Instance, NULL);
+
+ TempStorageDevicePath = Instance;
+
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &TempStorageDevicePath,
+ &DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->ConnectController (DeviceHandle, NULL, NULL, FALSE);
+ }
+
+ FreePool (Instance);
+ } while (TempDevicePath != NULL);
+}
+
+/**
+ The function connects the trusted consoles and then call the PP processing library interface.
+**/
+VOID
+ProcessTcgPp (
+ VOID
+ )
+{
+ gPPRequireUIConfirm |= Tcg2PhysicalPresenceLibNeedUserConfirm();
+
+ if (gPPRequireUIConfirm) {
+ ConnectTrustedConsole ();
+ }
+
+ Tcg2PhysicalPresenceLibProcessRequest (NULL);
+}
+
+/**
+ The function connects the trusted storage to perform TPerReset.
+**/
+VOID
+ProcessTcgMor (
+ VOID
+ )
+{
+ if (IsMorBitSet ()) {
+ ConnectTrustedConsole();
+ ConnectTrustedStorage();
+ }
+}
+
+/**
+ Check if current BootCurrent variable is internal shell boot option.
+
+ @retval TRUE BootCurrent is internal shell.
+ @retval FALSE BootCurrent is not internal shell.
+**/
+BOOLEAN
+BootCurrentIsInternalShell (
+ VOID
+ )
+{
+ UINTN VarSize;
+ UINT16 BootCurrent;
+ CHAR16 BootOptionName[16];
+ UINT8 *BootOption;
+ UINT8 *Ptr;
+ BOOLEAN Result;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;
+ EFI_GUID *GuidPoint;
+
+ BootOption = NULL;
+ Result = FALSE;
+
+ //
+ // Get BootCurrent variable
+ //
+ VarSize = sizeof (UINT16);
+ Status = gRT->GetVariable (
+ L"BootCurrent",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &VarSize,
+ &BootCurrent
+ );
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ //
+ // Create boot option Bootxxxx from BootCurrent
+ //
+ UnicodeSPrint (BootOptionName, sizeof(BootOptionName), L"Boot%04X", BootCurrent);
+
+ GetEfiGlobalVariable2 (BootOptionName, (VOID **) &BootOption, &VarSize);
+ if (BootOption == NULL || VarSize == 0) {
+ return FALSE;
+ }
+
+ Ptr = BootOption;
+ Ptr += sizeof (UINT32);
+ Ptr += sizeof (UINT16);
+ Ptr += StrSize ((CHAR16 *) Ptr);
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
+ LastDeviceNode = TempDevicePath;
+ while (!IsDevicePathEnd (TempDevicePath)) {
+ LastDeviceNode = TempDevicePath;
+ TempDevicePath = NextDevicePathNode (TempDevicePath);
+ }
+ GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (
+ (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode
+ );
+ if ((GuidPoint != NULL) &&
+ ((CompareGuid (GuidPoint, &gUefiShellFileGuid)))
+ ) {
+ //
+ // if this option is internal shell, return TRUE
+ //
+ Result = TRUE;
+ }
+
+ if (BootOption != NULL) {
+ FreePool (BootOption);
+ BootOption = NULL;
+ }
+
+ return Result;
+}
+
+/**
+ This function will change video resolution and text mode
+ for internl shell when internal shell is launched.
+
+ @param None.
+
+ @retval EFI_SUCCESS Mode is changed successfully.
+ @retval Others Mode failed to changed.
+**/
+EFI_STATUS
+EFIAPI
+ChangeModeForInternalShell (
+ VOID
+ )
+{
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
+ UINTN SizeOfInfo;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ UINT32 MaxGopMode;
+ UINT32 MaxTextMode;
+ UINT32 ModeNumber;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN CurrentColumn;
+ UINTN CurrentRow;
+
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID**)&GraphicsOutput
+ );
+ if (EFI_ERROR (Status)) {
+ GraphicsOutput = NULL;
+ }
+
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiSimpleTextOutProtocolGuid,
+ (VOID**)&SimpleTextOut
+ );
+ if (EFI_ERROR (Status)) {
+ SimpleTextOut = NULL;
+ }
+
+ if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ MaxGopMode = GraphicsOutput->Mode->MaxMode;
+ MaxTextMode = SimpleTextOut->Mode->MaxMode;
+
+ //
+ // 1. If current video resolution is same with new video resolution,
+ // video resolution need not be changed.
+ // 1.1. If current text mode is same with new text mode, text mode need not be change.
+ // 1.2. If current text mode is different with new text mode, text mode need be change to new text mode.
+ // 2. If current video resolution is different with new video resolution, we need restart whole console drivers.
+ //
+ for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {
+ Status = GraphicsOutput->QueryMode (
+ GraphicsOutput,
+ ModeNumber,
+ &SizeOfInfo,
+ &Info
+ );
+ if (!EFI_ERROR (Status)) {
+ if ((Info->HorizontalResolution == mShellHorizontalResolution) &&
+ (Info->VerticalResolution == mShellVerticalResolution)) {
+ if ((GraphicsOutput->Mode->Info->HorizontalResolution == mShellHorizontalResolution) &&
+ (GraphicsOutput->Mode->Info->VerticalResolution == mShellVerticalResolution)) {
+ //
+ // If current video resolution is same with new resolution,
+ // then check if current text mode is same with new text mode.
+ //
+ Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);
+ ASSERT_EFI_ERROR (Status);
+ if (CurrentColumn == mShellModeColumn && CurrentRow == mShellModeRow) {
+ //
+ // Current text mode is same with new text mode, text mode need not be change.
+ //
+ FreePool (Info);
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Current text mode is different with new text mode, text mode need be change to new text mode.
+ //
+ for (Index = 0; Index < MaxTextMode; Index++) {
+ Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);
+ if (!EFI_ERROR(Status)) {
+ if ((CurrentColumn == mShellModeColumn) && (CurrentRow == mShellModeRow)) {
+ //
+ // New text mode is supported, set it.
+ //
+ Status = SimpleTextOut->SetMode (SimpleTextOut, Index);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Update text mode PCD.
+ //
+ Status = PcdSet32S (PcdConOutColumn, mShellModeColumn);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PcdSet32S (PcdConOutRow, mShellModeRow);
+ ASSERT_EFI_ERROR (Status);
+
+ FreePool (Info);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ if (Index == MaxTextMode) {
+ //
+ // If new text mode is not supported, return error.
+ //
+ FreePool (Info);
+ return EFI_UNSUPPORTED;
+ }
+ }
+ } else {
+ FreePool (Info);
+ //
+ // If current video resolution is not same with the new one, set new video resolution.
+ // In this case, the driver which produces simple text out need be restarted.
+ //
+ Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Set PCD to restart GraphicsConsole and Consplitter to change video resolution
+ // and produce new text mode based on new resolution.
+ //
+ Status = PcdSet32S (PcdVideoHorizontalResolution, mShellHorizontalResolution);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PcdSet32S (PcdVideoVerticalResolution, mShellVerticalResolution);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PcdSet32S (PcdConOutColumn, mShellModeColumn);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PcdSet32S (PcdConOutRow, mShellModeRow);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleTextOutProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
+ }
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+ }
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+ break;
+ }
+ }
+ }
+ }
+ FreePool (Info);
+ }
+ }
+
+ if (ModeNumber == MaxGopMode) {
+ //
+ // If the new resolution is not supported, return error.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ ReadyToBoot callback to set video and text mode for internal shell boot.
+ That will not connect USB controller while CSM and FastBoot are disabled, we need to connect them
+ before booting to Shell for showing USB devices in Shell.
+
+ When FastBoot is enabled and Windows Console is the chosen Console behavior, input devices will not be connected
+ by default. Hence, when booting to EFI shell, connecting input consoles are required.
+
+ @param Event Pointer to this event
+ @param Context Event hanlder private data
+
+ @retval None.
+**/
+VOID
+EFIAPI
+OnReadyToBootCallBack (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ DEBUG ((EFI_D_INFO, "OnReadyToBootCallBack\n"));
+
+ if (BootCurrentIsInternalShell ()) {
+
+ ChangeModeForInternalShell ();
+ EfiBootManagerConnectAllDefaultConsoles();
+ gDS->Dispatch ();
+ }
+}
+
+/**
+ Platform Bds init. Incude the platform firmware vendor, revision
+ and so crc check.
+**/
+VOID
+EFIAPI
+PlatformBootManagerBeforeConsole (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *VarConOut;
+ EFI_DEVICE_PATH_PROTOCOL *VarConIn;
+ EFI_EVENT Event;
+
+ DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole\n"));
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Get user defined text mode for internal shell only once.
+ //
+ mShellHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
+ mShellVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution);
+ mShellModeColumn = PcdGet32 (PcdSetupConOutColumn);
+ mShellModeRow = PcdGet32 (PcdSetupConOutRow);
+
+ if (PcdGetBool (PcdUpdateConsoleInBds) == TRUE) {
+ //
+ // Create event to set proper video resolution and text mode for internal shell.
+ //
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ OnReadyToBootCallBack,
+ NULL,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Connect Root Bridge to make PCI BAR resource allocated and all PciIo created
+ //
+ ConnectRootBridge (FALSE);
+
+ //
+ // Fill ConIn/ConOut in Full Configuration boot mode
+ //
+ DEBUG ((DEBUG_INFO, "PlatformBootManagerInit - %x\n", gBootMode));
+
+ if (gBootMode == BOOT_WITH_FULL_CONFIGURATION ||
+ gBootMode == BOOT_WITH_DEFAULT_SETTINGS ||
+ gBootMode == BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS ||
+ gBootMode == BOOT_IN_RECOVERY_MODE) {
+
+ GetEfiGlobalVariable2 (L"ConOut", (VOID **)&VarConOut, NULL); if (VarConOut != NULL) { FreePool (VarConOut); }
+ GetEfiGlobalVariable2 (L"ConIn", (VOID **)&VarConIn, NULL); if (VarConIn != NULL) { FreePool (VarConIn); }
+
+ //
+ // Only fill ConIn/ConOut when ConIn/ConOut is empty because we may drop to Full Configuration boot mode in non-first boot
+ //
+ if (VarConOut == NULL || VarConIn == NULL) {
+ if (PcdGetSize (PcdTrustedConsoleOutputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
+ AddConsoleVariable (ConOut, PcdGetPtr (PcdTrustedConsoleOutputDevicePath));
+ }
+ if (PcdGetSize (PcdTrustedConsoleInputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
+ AddConsoleVariable (ConIn, PcdGetPtr (PcdTrustedConsoleInputDevicePath));
+ }
+ }
+ }
+
+ EnumUsbKeyboard ();
+ //
+ // For trusted console it must be handled here.
+ //
+ UpdateGraphicConOut (TRUE);
+
+ //
+ // Dynamically register hot key: F2/F7/Enter
+ //
+ RegisterDefaultBootOption ();
+ RegisterStaticHotkey ();
+ }
+
+ PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7010);
+ if (PcdGetBool (PcdTpm2Enable)) {
+ ProcessTcgPp ();
+ ProcessTcgMor ();
+ }
+ PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7011);
+
+ //
+ // We should make all UEFI memory and GCD information populated before ExitPmAuth.
+ // SMM may consume these information.
+ //
+ MemoryTest((EXTENDMEM_COVERAGE_LEVEL) PcdGet32 (PcdPlatformMemoryCheckLevel));
+
+ PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7020);
+ ExitPmAuth ();
+ PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7021);
+
+ //
+ // Dispatch the deferred 3rd party images.
+ //
+ EfiBootManagerDispatchDeferredImages ();
+
+ //
+ // For non-trusted console it must be handled here.
+ //
+ if (PcdGetBool (PcdUpdateConsoleInBds) == TRUE) {
+ UpdateGraphicConOut (FALSE);
+ }
+}
+
+
+/**
+ Connect with predeined platform connect sequence,
+ the OEM/IBV can customize with their own connect sequence.
+
+ @param[in] BootMode Boot mode of this boot.
+**/
+VOID
+ConnectSequence (
+ IN EFI_BOOT_MODE BootMode
+ )
+{
+ EfiBootManagerConnectAll ();
+}
+
+/**
+ The function is to consider the boot order which is not in our expectation.
+ In the case that we need to re-sort the boot option.
+
+ @retval TRUE Need to sort Boot Option.
+ @retval FALSE Don't need to sort Boot Option.
+**/
+BOOLEAN
+IsNeedSortBootOption (
+ VOID
+ )
+{
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+
+ BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+
+ //
+ // If setup is the first priority in boot option, we need to sort boot option.
+ //
+ if ((BootOptionCount > 1) &&
+ (((StrnCmp (BootOptions->Description, L"Enter Setup", StrLen (L"Enter Setup"))) == 0) ||
+ ((StrnCmp (BootOptions->Description, L"BootManagerMenuApp", StrLen (L"BootManagerMenuApp"))) == 0))) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ 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.
+
+ @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
+PlatformBootManagerAfterConsole (
+ VOID
+ )
+{
+ EFI_BOOT_MODE LocalBootMode;
+
+ DEBUG ((EFI_D_INFO, "PlatformBootManagerAfterConsole\n"));
+
+ //
+ // Get current Boot Mode
+ //
+ LocalBootMode = gBootMode;
+ DEBUG ((DEBUG_INFO, "Current local bootmode - %x\n", LocalBootMode));
+
+ //
+ // Go the different platform policy with different boot mode
+ // Notes: this part code can be change with the table policy
+ //
+ switch (LocalBootMode) {
+
+ case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
+ case BOOT_WITH_MINIMAL_CONFIGURATION:
+ case BOOT_ON_S4_RESUME:
+ //
+ // Perform some platform specific connect sequence
+ //
+ if (PcdGetBool (PcdFastBoot) == FALSE) {
+ PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7050);
+ ConnectSequence (LocalBootMode);
+ PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7051);
+ }
+
+ break;
+
+ case BOOT_WITH_FULL_CONFIGURATION:
+ case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
+ case BOOT_WITH_DEFAULT_SETTINGS:
+ default:
+ //
+ // Perform some platform specific connect sequence
+ //
+ ConnectSequence (LocalBootMode);
+
+ //
+ // Only in Full Configuration boot mode we do the enumeration of boot device
+ //
+ //
+ // Dispatch all but Storage Oprom explicitly, because we assume Int13Thunk driver is there.
+ //
+ EfiBootManagerRefreshAllBootOption ();
+
+ if (IsNeedSortBootOption()) {
+ EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOption);
+ }
+ //
+ // PXE boot option may appear after boot option enumeration
+ //
+
+ break;
+ }
+
+ if (PcdGetBool (PcdFastBoot) == FALSE) {
+ Print (L"Press F7 for BootMenu!\n");
+
+ EfiBootManagerRefreshAllBootOption ();
+ EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOption);
+ }
+}
+
+/**
+ The function is called when no boot option could be launched,
+ including platform recovery options and options pointing to applications
+ built into firmware volumes.
+
+ If this function returns, BDS attempts to enter an infinite loop.
+**/
+VOID
+EFIAPI
+PlatformBootManagerUnableToBoot (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootDeviceList;
+ CHAR16 OptionName[sizeof ("Boot####")];
+
+ if (mBootMenuOptionNumber == LoadOptionNumberUnassigned) {
+ return;
+ }
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", mBootMenuOptionNumber);
+ Status = EfiBootManagerVariableToLoadOption (OptionName, &BootDeviceList);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ for (;;) {
+ EfiBootManagerBoot (&BootDeviceList);
+ }
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.h b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.h
new file mode 100644
index 0000000000..779ba9a98d
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.h
@@ -0,0 +1,190 @@
+/** @file
+ Header file for BDS Platform specific code
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that 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.
+
+**/
+
+#ifndef _BDS_PLATFORM_H
+#define _BDS_PLATFORM_H
+
+#include <PiDxe.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/CpuIo2.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/DiskInfo.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/UgaDraw.h>
+#include <Protocol/GenericMemoryTest.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include <Guid/CapsuleVendor.h>
+#include <Guid/MemoryTypeInformation.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/MemoryOverwriteControl.h>
+#include <Guid/FileInfo.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PlatformBootManagerLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiLib.h>
+#include <Library/HobLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HiiLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/PerformanceLib.h>
+
+#include <IndustryStandard/Pci30.h>
+#include <IndustryStandard/PciCodeId.h>
+
+///
+/// ConnectType
+///
+#define CONSOLE_OUT 0x00000001
+#define STD_ERROR 0x00000002
+#define CONSOLE_IN 0x00000004
+#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
+
+extern EFI_GUID gUefiShellFileGuid;
+extern EFI_BOOT_MODE gBootMode;
+
+#define gPciRootBridge \
+ { \
+ { \
+ ACPI_DEVICE_PATH, \
+ ACPI_DP, \
+ { \
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
+ }, \
+ }, \
+ EISA_PNP_ID (0x0A03), \
+ 0 \
+ }
+
+#define gEndEntire \
+ { \
+ END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { END_DEVICE_PATH_LENGTH, 0 } \
+ }
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN ConnectType;
+} BDS_CONSOLE_CONNECT_ENTRY;
+
+//
+// Platform Root Bridge
+//
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;
+
+//
+// Below is the platform console device path
+//
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH IsaBridge;
+ ACPI_HID_DEVICE_PATH Keyboard;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_KEYBOARD_DEVICE_PATH;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH PciDevice;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_ONBOARD_CONTROLLER_DEVICE_PATH;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH Pci0Device;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_PEG_ROOT_CONTROLLER_DEVICE_PATH;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH PciBridge;
+ PCI_DEVICE_PATH PciDevice;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_PCI_CONTROLLER_DEVICE_PATH;
+
+//
+// Below is the boot option device path
+//
+
+#define CLASS_HID 3
+#define SUBCLASS_BOOT 1
+#define PROTOCOL_KEYBOARD 1
+
+typedef struct {
+ USB_CLASS_DEVICE_PATH UsbClass;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} USB_CLASS_FORMAT_DEVICE_PATH;
+
+extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath;
+
+//
+// Platform BDS Functions
+//
+
+
+/**
+ Perform the memory test base on the memory test intensive level,
+ and update the memory resource.
+
+ @param Level The memory test intensive level.
+
+ @retval EFI_STATUS Success test all the system memory and update
+ the memory resource
+
+**/
+EFI_STATUS
+MemoryTest (
+ IN EXTENDMEM_COVERAGE_LEVEL Level
+ );
+
+VOID
+ConnectSequence (
+ IN EFI_BOOT_MODE BootMode
+ );
+
+
+INTN
+EFIAPI
+CompareBootOption (
+ CONST VOID *Left,
+ CONST VOID *Right
+ );
+
+
+VOID
+RegisterStaticHotkey (
+ VOID
+ );
+VOID
+RegisterDefaultBootOption (
+ VOID
+ );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf
new file mode 100644
index 0000000000..563c8a25b2
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf
@@ -0,0 +1,102 @@
+### @file
+# Component name for module DxePlatformBootManagerLib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# 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.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = DxePlatformBootManagerLib
+ FILE_GUID = A6BC385D-59E5-4B77-87D7-200ABAA83C15
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_DRIVER
+ UEFI_SPECIFICATION_VERSION = 2.10
+ LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[LibraryClasses]
+ BaseLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ PrintLib
+ DevicePathLib
+ UefiLib
+ HobLib
+ DxeServicesLib
+ DxeServicesTableLib
+ HiiLib
+ UefiBootManagerLib
+ PerformanceLib
+ TimerLib
+ Tcg2PhysicalPresenceLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ PurleyOpenBoardPkg/PlatPkg.dec
+
+[Pcd]
+ gMinPlatformPkgTokenSpaceGuid.PcdTpm2Enable ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut ## PRODUCES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution ## PRODUCES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution ## PRODUCES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow ## PRODUCES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn ## PRODUCES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand ## PRODUCES
+ gMinPlatformPkgTokenSpaceGuid.PcdPlatformMemoryCheckLevel ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleInputDevicePath ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleOutputDevicePath ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdTrustedStorageDevicePath ## CONSUMES
+ gPlatformTokenSpaceGuid.PcdUpdateConsoleInBds ## CONSUMES
+ gPlatformTokenSpaceGuid.PcdFastBoot ## CONSUMES
+
+[Sources]
+ BdsPlatform.c
+ BdsPlatform.h
+ PlatformBootOption.c
+ MemoryTest.c
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
+ gEfiPciIoProtocolGuid ## CONSUMES
+ gEfiCpuIo2ProtocolGuid ## CONSUMES
+ gEfiDxeSmmReadyToLockProtocolGuid ## PRODUCES
+ gEfiGenericMemTestProtocolGuid ## CONSUMES
+ gEfiDiskInfoProtocolGuid ## CONSUMES
+ gEfiDevicePathToTextProtocolGuid ## CONSUMES
+ gEfiSimpleTextInputExProtocolGuid ## CONSUMES
+ gEfiFirmwareVolume2ProtocolGuid ## CONSUMES
+ gEfiFormBrowser2ProtocolGuid ## CONSUMES
+ gEfiGenericMemTestProtocolGuid ## CONSUMES
+
+[Guids]
+ gEfiGlobalVariableGuid ## PRODUCES
+ gEfiMemoryOverwriteControlDataGuid ## PRODUCES
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES
+
+[Depex.common.DXE_DRIVER]
+ gEfiVariableArchProtocolGuid
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/MemoryTest.c b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/MemoryTest.c
new file mode 100644
index 0000000000..6c36e7d28b
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/MemoryTest.c
@@ -0,0 +1,91 @@
+/** @file
+ Perform the platform memory test
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that 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.
+
+**/
+
+#include "BdsPlatform.h"
+#include <Protocol/GenericMemoryTest.h>
+
+/**
+ Perform the memory test base on the memory test intensive level,
+ and update the memory resource.
+
+ @param Level The memory test intensive level.
+
+ @retval EFI_STATUS Success test all the system memory and update
+ the memory resource
+
+**/
+EFI_STATUS
+MemoryTest (
+ IN EXTENDMEM_COVERAGE_LEVEL Level
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN RequireSoftECCInit;
+ EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;
+ UINT64 TestedMemorySize;
+ UINT64 TotalMemorySize;
+ BOOLEAN ErrorOut;
+ BOOLEAN TestAbort;
+
+ TestedMemorySize = 0;
+ TotalMemorySize = 0;
+ ErrorOut = FALSE;
+ TestAbort = FALSE;
+
+ RequireSoftECCInit = FALSE;
+
+ Status = gBS->LocateProtocol (
+ &gEfiGenericMemTestProtocolGuid,
+ NULL,
+ (VOID **) &GenMemoryTest
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ Status = GenMemoryTest->MemoryTestInit (
+ GenMemoryTest,
+ Level,
+ &RequireSoftECCInit
+ );
+ if (Status == EFI_NO_MEDIA) {
+ //
+ // The PEI codes also have the relevant memory test code to check the memory,
+ // it can select to test some range of the memory or all of them. If PEI code
+ // checks all the memory, this BDS memory test will has no not-test memory to
+ // do the test, and then the status of EFI_NO_MEDIA will be returned by
+ // "MemoryTestInit". So it does not need to test memory again, just return.
+ //
+ return EFI_SUCCESS;
+ }
+
+ if (PcdGetBool (PcdFastBoot) == FALSE) {
+ do {
+ Status = GenMemoryTest->PerformMemoryTest (
+ GenMemoryTest,
+ &TestedMemorySize,
+ &TotalMemorySize,
+ &ErrorOut,
+ TestAbort
+ );
+ if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {
+ ASSERT (0);
+ }
+ } while (Status != EFI_NOT_FOUND);
+ }
+
+ Status = GenMemoryTest->Finished (GenMemoryTest);
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/PlatformBootOption.c b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/PlatformBootOption.c
new file mode 100644
index 0000000000..ea30de0540
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/PlatformBootOption.c
@@ -0,0 +1,565 @@
+/** @file
+ Driver for Platform Boot Options support.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that 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.
+
+**/
+
+#include "BdsPlatform.h"
+
+#include <Library/PcdLib.h>
+
+BOOLEAN mContinueBoot = FALSE;
+BOOLEAN mBootMenuBoot = FALSE;
+BOOLEAN mPxeBoot = FALSE;
+BOOLEAN mHotKeypressed = FALSE;
+EFI_EVENT HotKeyEvent = NULL;
+
+UINTN mBootMenuOptionNumber;
+
+EFI_DEVICE_PATH_PROTOCOL *
+BdsCreateShellDevicePath (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function will create a SHELL BootOption to boot.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Shell Device path for booting.
+
+--*/
+{
+ UINTN FvHandleCount;
+ EFI_HANDLE *FvHandleBuffer;
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+ UINTN Size;
+ UINT32 AuthenticationStatus;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ VOID *Buffer;
+
+ DevicePath = NULL;
+ Status = EFI_SUCCESS;
+
+ DEBUG ((DEBUG_INFO, "BdsCreateShellDevicePath\n"));
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &FvHandleCount,
+ &FvHandleBuffer
+ );
+
+ for (Index = 0; Index < FvHandleCount; Index++) {
+ gBS->HandleProtocol (
+ FvHandleBuffer[Index],
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &Fv
+ );
+
+ Buffer = NULL;
+ Size = 0;
+ Status = Fv->ReadSection (
+ Fv,
+ &gUefiShellFileGuid,
+ EFI_SECTION_PE32,
+ 0,
+ &Buffer,
+ &Size,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Skip if no shell file in the FV
+ //
+ continue;
+ } else {
+ //
+ // Found the shell
+ //
+ break;
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // No shell present
+ //
+ if (FvHandleCount) {
+ FreePool (FvHandleBuffer);
+ }
+ return NULL;
+ }
+ //
+ // Build the shell boot option
+ //
+ DevicePath = DevicePathFromHandle (FvHandleBuffer[Index]);
+
+ if (FvHandleCount) {
+ FreePool (FvHandleBuffer);
+ }
+
+ return DevicePath;
+}
+
+
+EFI_STATUS
+CreateFvBootOption (
+ EFI_GUID *FileGuid,
+ CHAR16 *Description,
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOption,
+ UINT32 Attributes,
+ UINT8 *OptionalData, OPTIONAL
+ UINT32 OptionalDataSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+ UINT32 AuthenticationStatus;
+ VOID *Buffer;
+ UINTN Size;
+
+ if ((BootOption == NULL) || (FileGuid == NULL) || (Description == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
+
+ if (!CompareGuid (&gUefiShellFileGuid, FileGuid)) {
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->HandleProtocol (
+ LoadedImage->DeviceHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &Fv
+ );
+ if (!EFI_ERROR (Status)) {
+ Buffer = NULL;
+ Size = 0;
+ Status = Fv->ReadSection (
+ Fv,
+ FileGuid,
+ EFI_SECTION_PE32,
+ 0,
+ &Buffer,
+ &Size,
+ &AuthenticationStatus
+ );
+ if (Buffer != NULL) {
+ FreePool (Buffer);
+ }
+ }
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ DevicePath = AppendDevicePathNode (
+ DevicePathFromHandle (LoadedImage->DeviceHandle),
+ (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+ );
+ } else {
+ DevicePath = AppendDevicePathNode (
+ BdsCreateShellDevicePath (),
+ (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+ );
+ }
+
+ Status = EfiBootManagerInitializeLoadOption (
+ BootOption,
+ LoadOptionNumberUnassigned,
+ LoadOptionTypeBoot,
+ Attributes,
+ Description,
+ DevicePath,
+ OptionalData,
+ OptionalDataSize
+ );
+ FreePool (DevicePath);
+ return Status;
+}
+
+EFI_GUID mUiFile = {
+ 0x462CAA21, 0x7614, 0x4503, { 0x83, 0x6E, 0x8A, 0xB6, 0xF4, 0x66, 0x23, 0x31 }
+};
+EFI_GUID mBootMenuFile = {
+ 0xEEC25BDC, 0x67F2, 0x4D95, { 0xB1, 0xD5, 0xF8, 0x1B, 0x20, 0x39, 0xD1, 0x1D }
+};
+
+
+/**
+ Return the index of the load option in the load option array.
+
+ The function consider two load options are equal when the
+ OptionType, Attributes, Description, FilePath and OptionalData are equal.
+
+ @param Key Pointer to the load option to be found.
+ @param Array Pointer to the array of load options to be found.
+ @param Count Number of entries in the Array.
+
+ @retval -1 Key wasn't found in the Array.
+ @retval 0 ~ Count-1 The index of the Key in the Array.
+**/
+INTN
+PlatformFindLoadOption (
+ IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
+ IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
+ IN UINTN Count
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < Count; Index++) {
+ if ((Key->OptionType == Array[Index].OptionType) &&
+ (Key->Attributes == Array[Index].Attributes) &&
+ (StrCmp (Key->Description, Array[Index].Description) == 0) &&
+ (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
+ (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
+ (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
+ return (INTN) Index;
+ }
+ }
+
+ return -1;
+}
+
+UINTN
+RegisterFvBootOption (
+ EFI_GUID *FileGuid,
+ CHAR16 *Description,
+ UINTN Position,
+ UINT32 Attributes,
+ UINT8 *OptionalData, OPTIONAL
+ UINT32 OptionalDataSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN OptionIndex;
+ EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+
+ NewOption.OptionNumber = LoadOptionNumberUnassigned;
+ Status = CreateFvBootOption (FileGuid, Description, &NewOption, Attributes, OptionalData, OptionalDataSize);
+ if (!EFI_ERROR (Status)) {
+ BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+
+ OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions, BootOptionCount);
+
+ if (OptionIndex == -1) {
+ Status = EfiBootManagerAddLoadOptionVariable (&NewOption, Position);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ NewOption.OptionNumber = BootOptions[OptionIndex].OptionNumber;
+ }
+ EfiBootManagerFreeLoadOption (&NewOption);
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+ }
+
+ return NewOption.OptionNumber;
+}
+
+
+
+VOID
+EFIAPI
+PlatformBootManagerWaitCallback (
+ UINT16 TimeoutRemain
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;
+ EFI_KEY_DATA KeyData;
+ BOOLEAN PausePressed;
+
+ //
+ // Pause on PAUSE key
+ //
+ Status = gBS->HandleProtocol (gST->ConsoleInHandle, &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);
+ ASSERT_EFI_ERROR (Status);
+
+ PausePressed = FALSE;
+
+ while (TRUE) {
+ Status = TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (KeyData.Key.ScanCode == SCAN_PAUSE) {
+ PausePressed = TRUE;
+ break;
+ }
+ }
+
+ //
+ // Loop until non-PAUSE key pressed
+ //
+ while (PausePressed) {
+ Status = TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData);
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_INFO, "[PauseCallback] %x/%x %x/%x\n",
+ KeyData.Key.ScanCode, KeyData.Key.UnicodeChar,
+ KeyData.KeyState.KeyShiftState, KeyData.KeyState.KeyToggleState
+ ));
+ PausePressed = (BOOLEAN) (KeyData.Key.ScanCode == SCAN_PAUSE);
+ }
+ }
+}
+
+
+EFI_GUID gUefiShellFileGuid = { 0x7C04A583, 0x9E3E, 0x4f1c, { 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 } };
+
+#define INTERNAL_UEFI_SHELL_NAME L"Internal UEFI Shell 2.0"
+#define UEFI_HARD_DRIVE_NAME L"UEFI Hard Drive"
+
+VOID
+RegisterDefaultBootOption (
+ VOID
+ )
+{
+#if 0
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+#endif
+ UINT16 *ShellData;
+ UINT32 ShellDataSize;
+
+ ShellData = NULL;
+ ShellDataSize = 0;
+ RegisterFvBootOption (&gUefiShellFileGuid, INTERNAL_UEFI_SHELL_NAME, (UINTN) -1, LOAD_OPTION_ACTIVE, (UINT8 *)ShellData, ShellDataSize);
+
+ //
+ // Boot Menu
+ //
+ mBootMenuOptionNumber = RegisterFvBootOption (&mBootMenuFile, L"Boot Device List", (UINTN) -1, LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDEN, NULL, 0);
+
+ if (mBootMenuOptionNumber == LoadOptionNumberUnassigned) {
+ DEBUG ((DEBUG_INFO, "BootMenuOptionNumber (%d) should not be same to LoadOptionNumberUnassigned(%d).\n", mBootMenuOptionNumber, LoadOptionNumberUnassigned));
+ }
+#if 0
+ //
+ // Boot Manager Menu
+ //
+ EfiInitializeFwVolDevicepathNode (&FileNode, &mUiFile);
+
+ gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage
+ );
+ DevicePath = AppendDevicePathNode (DevicePathFromHandle (LoadedImage->DeviceHandle), (EFI_DEVICE_PATH_PROTOCOL *) &FileNode);
+#endif
+
+}
+
+VOID
+RegisterBootOptionHotkey (
+ UINT16 OptionNumber,
+ EFI_INPUT_KEY *Key,
+ BOOLEAN Add
+ )
+{
+ EFI_STATUS Status;
+
+ if (!Add) {
+ //
+ // No enter hotkey when force to setup or there is no boot option
+ //
+ Status = EfiBootManagerDeleteKeyOptionVariable (NULL, 0, Key, NULL);
+ ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);
+ } else {
+ //
+ // Register enter hotkey for the first boot option
+ //
+ Status = EfiBootManagerAddKeyOptionVariable (NULL, OptionNumber, 0, Key,NULL);
+ ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
+ }
+}
+
+EFI_STATUS
+EFIAPI
+DetectKeypressCallback (
+ IN EFI_KEY_DATA *KeyData
+)
+{
+ mHotKeypressed = TRUE;
+
+ if (HotKeyEvent != NULL) {
+ gBS->SignalEvent(HotKeyEvent);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is called after all the boot options are enumerated and ordered properly.
+**/
+VOID
+RegisterStaticHotkey (
+ VOID
+ )
+{
+
+ EFI_INPUT_KEY Enter;
+ EFI_KEY_DATA F2;
+ EFI_KEY_DATA F7;
+ BOOLEAN EnterSetup;
+ EFI_STATUS Status;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
+
+ EnterSetup = FALSE;
+
+ //
+ // [Enter]
+ //
+ mContinueBoot = !EnterSetup;
+ if (mContinueBoot) {
+ Enter.ScanCode = SCAN_NULL;
+ Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
+ EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
+ }
+
+
+ //
+ // [F2]/[F7]
+ //
+ F2.Key.ScanCode = SCAN_F2;
+ F2.Key.UnicodeChar = CHAR_NULL;
+ F2.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
+ F2.KeyState.KeyToggleState = 0;
+ Status = EfiBootManagerGetBootManagerMenu (&BootOption);
+ ASSERT_EFI_ERROR (Status);
+ RegisterBootOptionHotkey ((UINT16) BootOption.OptionNumber, &F2.Key, TRUE);
+ EfiBootManagerFreeLoadOption (&BootOption);
+
+ F7.Key.ScanCode = SCAN_F7;
+ F7.Key.UnicodeChar = CHAR_NULL;
+ F7.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
+ F7.KeyState.KeyToggleState = 0;
+ mBootMenuBoot = !EnterSetup;
+ RegisterBootOptionHotkey ((UINT16) mBootMenuOptionNumber, &F7.Key, mBootMenuBoot);
+
+}
+
+UINT8
+BootOptionType (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ EFI_DEVICE_PATH_PROTOCOL *NextNode;
+
+ for (Node = DevicePath; !IsDevicePathEndType (Node); Node = NextDevicePathNode (Node)) {
+ if (DevicePathType (Node) == MESSAGING_DEVICE_PATH) {
+ //
+ // Make sure the device path points to the driver device.
+ //
+ NextNode = NextDevicePathNode (Node);
+ if (DevicePathSubType(NextNode) == MSG_DEVICE_LOGICAL_UNIT_DP) {
+ //
+ // if the next node type is Device Logical Unit, which specify the Logical Unit Number (LUN),
+ // skip it
+ //
+ NextNode = NextDevicePathNode (NextNode);
+ }
+ if (IsDevicePathEndType (NextNode)) {
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH)) {
+ return DevicePathSubType (Node);
+ } else {
+ return MSG_SATA_DP;
+ }
+ }
+ }
+ }
+
+ return (UINT8) -1;
+}
+
+/**
+ Returns the priority number.
+ OptionType EFI
+ ------------------------------------
+ PXE 2
+ DVD 4
+ USB 6
+ NVME 7
+ HDD 8
+ EFI Shell 9
+ Others 100
+
+ @param BootOption
+**/
+UINTN
+BootOptionPriority (
+ CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
+ )
+{
+ //
+ // EFI boot options
+ //
+ switch (BootOptionType (BootOption->FilePath)) {
+ case MSG_MAC_ADDR_DP:
+ case MSG_VLAN_DP:
+ case MSG_IPv4_DP:
+ case MSG_IPv6_DP:
+ return 2;
+
+ case MSG_SATA_DP:
+ case MSG_ATAPI_DP:
+ case MSG_UFS_DP:
+ case MSG_NVME_NAMESPACE_DP:
+ return 4;
+
+ case MSG_USB_DP:
+ return 6;
+
+ }
+ if (StrCmp (BootOption->Description, INTERNAL_UEFI_SHELL_NAME) == 0) {
+ if (PcdGetBool (PcdBootToShellOnly)) {
+ return 0;
+ }
+ return 9;
+ }
+ if (StrCmp (BootOption->Description, UEFI_HARD_DRIVE_NAME) == 0) {
+ return 8;
+ }
+ return 100;
+}
+
+INTN
+EFIAPI
+CompareBootOption (
+ CONST VOID *Left,
+ CONST VOID *Right
+ )
+{
+ return BootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *) Left) -
+ BootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *) Right);
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/PlatPkg.dec b/Platform/Intel/PurleyOpenBoardPkg/PlatPkg.dec
index 221269e1f4..c203716029 100644
--- a/Platform/Intel/PurleyOpenBoardPkg/PlatPkg.dec
+++ b/Platform/Intel/PurleyOpenBoardPkg/PlatPkg.dec
@@ -26,6 +26,7 @@
gCpPlatFlashTokenSpaceGuid = { 0xc9c39664, 0x96dd, 0x4c5c, { 0xaf, 0xd7, 0xcd, 0x65, 0x76, 0x29, 0xcf, 0xb0 } }
gOemSkuTokenSpaceGuid = { 0x9e37d253, 0xabf8, 0x4985, { 0x8e, 0x23, 0xba, 0xca, 0x10, 0x39, 0x56, 0x13 } }
gEfiIpmiPkgTokenSpaceGuid = { 0xe96431d, 0xc68e, 0x4212, { 0xa1, 0x70, 0x16, 0xa6, 0x8, 0x55, 0x12, 0xc6 } }
+ gPlatformTokenSpaceGuid = { 0x07dfa0d2, 0x2ac5, 0x4cab, { 0xac, 0x14, 0x30, 0x5c, 0x62, 0x48, 0x87, 0xe4 } }
[Ppis]
gEfiPeiSystemBoardPpiGuid = { 0xc8d85e8c, 0xdc1c, 0x4f8c, { 0xad, 0xa7, 0x58, 0xc1, 0xd1, 0x07, 0xa3, 0x04 } }
@@ -43,6 +44,11 @@
# 0 - Disable; 1 - Minimum; 2 - Normal; 3 - Max
gPlatformTokenSpaceGuid.PcdSerialDbgLvlAtBadCmos|0x1|UINT8|0x30000033
+[PcdsFeatureFlag]
+ gPlatformTokenSpaceGuid.PcdFastBoot|FALSE|BOOLEAN|0x30000034
+
+ gPlatformTokenSpaceGuid.PcdUpdateConsoleInBds|TRUE|BOOLEAN|0x30000035
+
[PcdsDynamicEx]
gPlatformTokenSpaceGuid.PcdDfxAdvDebugJumper|FALSE|BOOLEAN|0x6000001D
--
2.14.3.windows.1
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2018-09-27 7:42 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-09-27 7:42 [PATCH] PurleyOpenBoardPkg: add platform level fast boot support Zhou, Bowen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox