summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzwei4 <david.wei@intel.com>2018-03-22 13:29:43 +0800
committerzwei4 <david.wei@intel.com>2018-03-22 13:33:06 +0800
commit191c87cbb5ae6a93d9d7c1b874d93849dea77675 (patch)
tree5b7a3e33f752841ad4fbfdfdd7fddc35715af736
parent8af4cb8bbceaeb08837d8f653df5a7dd66ec417f (diff)
downloadedk2-platforms-191c87cbb5ae6a93d9d7c1b874d93849dea77675.tar.xz
Platform Boot Manager Library.
Add library instance of PlatformBootManagerLib. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: zwei4 <david.wei@intel.com>
-rw-r--r--Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootManager.c1052
-rw-r--r--Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootManager.h226
-rw-r--r--Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf109
-rw-r--r--Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootOption.c738
-rw-r--r--Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformData.c179
5 files changed, 2304 insertions, 0 deletions
diff --git a/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootManager.c b/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootManager.c
new file mode 100644
index 0000000000..3dffe72636
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootManager.c
@@ -0,0 +1,1052 @@
+/** @file
+ This file include all platform action at BDS stage which can be customized by IBV/OEM.
+
+ Copyright (c) 2006 - 2018, 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.
+
+**/
+
+#include "PlatformBootManager.h"
+#include <Guid/EventGroup.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/AcpiS3Save.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/ExitPmAuth.h>
+#include <Protocol/UsbIo.h>
+#include <Protocol/VariableLock.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/TcgPhysicalPresenceLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+#include <Library/HobLib.h>
+#include <Guid/EventGroup.h>
+#include <Guid/ImageAuthentication.h>
+#include <Guid/Tcg2PhysicalPresenceData.h>
+#include <Guid/PhysicalPresenceData.h>
+#include <Guid/TpmInstance.h>
+#include <Guid/PttPTPInstanceGuid.h>
+
+#pragma optimize("g", off)
+
+#define TIMEOUT_COMMAND 100000
+#define BIOS_COLOR_CODING_BAR_HEIGHT 40
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_HII_HANDLE gPlatformBdsLibStringPackHandle;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_BOOT_MODE mBootMode;
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID *mLibTerminalType[] = {
+ &gEfiPcAnsiGuid,
+ &gEfiVT100Guid,
+ &gEfiVT100PlusGuid,
+ &gEfiVTUTF8Guid
+};
+
+//
+// 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;
+
+CHAR16 *mConsoleVar[] = {L"ConIn", L"ConOut"};
+
+extern USB_CLASS_FORMAT_DEVICE_PATH mUsbClassKeyboardDevicePath;
+extern BOOLEAN mAnyKeypressed;
+
+/**
+ The handle on the path we get might be not the display device.
+ We must check it.
+
+ @todo fix the parameters
+
+ @retval TRUE PCI class type is VGA.
+ @retval FALSE PCI class type isn't VGA.
+**/
+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)) {
+ DEBUG ((DEBUG_ERROR, " PCI CLASS CODE = 0x%x\n", Pci.Hdr.ClassCode [2]));
+ DEBUG ((DEBUG_ERROR, " PCI SUBCLASS CODE = 0x%x\n", Pci.Hdr.ClassCode [1]));
+
+ if (IS_PCI_VGA (&Pci) || IS_PCI_OLD_VGA (&Pci)) {
+ DEBUG ((DEBUG_ERROR, " \nPCI VGA Device Found\n"));
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/**
+ This function converts an input device structure to a Unicode string.
+
+ @param DevPath A pointer to the device path structure.
+
+ @return A new allocated Unicode string that represents the device path.
+**/
+CHAR16 *
+DevicePathToStr (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *ToText;
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
+
+ if (DevPath == NULL) {
+ return NULL;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiDevicePathToTextProtocolGuid,
+ NULL,
+ (VOID **) &DevPathToText
+ );
+ ASSERT_EFI_ERROR (Status);
+ ToText = DevPathToText->ConvertDevicePathToText (
+ DevPath,
+ FALSE,
+ TRUE
+ );
+ ASSERT (ToText != NULL);
+ return ToText;
+}
+
+/**
+ 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_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;
+ EFI_EVENT EndOfDxeEvent;
+
+ DEBUG((DEBUG_INFO,"ExitPmAuth ()- Start\n"));
+
+ //
+ // Inform the SMM infrastructure that we're entering BDS and may run 3rd party code hereafter
+ // We can NOT put it to PlatformBdsInit, because many boot script touch PCI BAR.
+ // We have to connect PCI root bridge, allocate resource, then ExitPmAuth().
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gExitPmAuthProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // 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"));
+
+ //
+ // Prepare S3 information, this MUST be done before ExitPmAuth/EndOfDxe.
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid, NULL, (VOID **)&AcpiS3Save);
+ if (!EFI_ERROR (Status)) {
+ AcpiS3Save->S3Save (AcpiS3Save, NULL);
+ }
+
+ //
+ // 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);
+ }
+}
+
+
+BOOLEAN
+IsGopDevicePath (
+ 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;
+}
+
+/**
+ 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 ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||
+ ((DevicePathSubType (DevicePath) != MSG_USB_CLASS_DP) && (DevicePathSubType (DevicePath) != MSG_USB_WWID_DP))
+ ) {
+ 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 if Ps2 keyboard is connected.
+**/
+VOID
+EnumPs2Keyboard (
+ VOID
+ )
+{
+ UINTN DevicePathSize;
+ EFI_DEVICE_PATH_PROTOCOL *VarConIn;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance;
+ EFI_DEVICE_PATH_PROTOCOL *Next;
+ BOOLEAN Ps2Keyboard;
+
+ Ps2Keyboard = FALSE;
+ GetEfiGlobalVariable2 (L"ConIn", (VOID **) &VarConIn, NULL);
+
+ //
+ // If ConIn variable is empty, need to enumerate PS/2 keyboard device path.
+ //
+ do {
+ DevicePathInstance = GetNextDevicePathInstance (
+ &VarConIn,
+ &DevicePathSize
+ );
+
+ if (DevicePathInstance == NULL) {
+ //
+ // The instance is NULL, it means the VarConIn is null, escape the DO loop,
+ // and need to add PS/2 keyboard dev path.
+ //
+ break;
+ }
+
+ Next = DevicePathInstance;
+ while (!IsDevicePathEndType(Next)) {
+ //
+ // Checking the device path to see the PS/2 keyboard existance.
+ //
+ if ((Next->Type == ACPI_DEVICE_PATH) &&
+ (Next->SubType == ACPI_DP ) &&
+ (((ACPI_HID_DEVICE_PATH *) Next)->HID == EISA_PNP_ID (0x0303))) {
+ //
+ // PS/2 keyboard already exists.
+ //
+ DEBUG ((DEBUG_INFO, "[EnumPs2Keyboard] PS2 keyboard path exists\n"));
+ Ps2Keyboard = TRUE;
+ break;
+ }
+ Next = NextDevicePathNode (Next);
+ }
+
+ if (DevicePathInstance != NULL) {
+ FreePool (DevicePathInstance);
+ }
+ } while (VarConIn != NULL);
+
+ //
+ // PS/2 keyboard device path does not exist, so try detecting ps2 keyboard
+ // and add-in its device path.
+ //
+ if (!Ps2Keyboard) {
+ DEBUG ((DEBUG_INFO, "[EnumPs2Keyboard] Adding detected PS2 keyboard to ConIn.\n"));
+ }
+
+ if (VarConIn != NULL) {
+ FreePool (VarConIn);
+ }
+}
+
+/**
+ Update the ConIn variable with USB Keyboard device path,if its not already exists in ConIn.
+**/
+VOID
+EnumUsbKeyboard (
+ VOID
+ )
+{
+ UINTN DevicePathSize;
+ EFI_DEVICE_PATH_PROTOCOL *VarConIn;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance;
+ EFI_DEVICE_PATH_PROTOCOL *Next;
+ BOOLEAN UsbKeyboard;
+
+ UsbKeyboard = FALSE;
+ GetEfiGlobalVariable2 (L"ConIn", (VOID **)&VarConIn, NULL);
+
+ //
+ // If ConIn variable is empty, need to enumerate USB keyboard device path.
+ //
+ do {
+ DevicePathInstance = GetNextDevicePathInstance (
+ &VarConIn,
+ &DevicePathSize
+ );
+
+ if (DevicePathInstance == NULL) {
+ //
+ // The instance is NULL, it means the VarConIn is null, escape the DO loop,
+ // and need to add USB keyboard dev path.
+ //
+ break;
+ }
+
+ Next = DevicePathInstance;
+ while (!IsDevicePathEndType(Next)) {
+ //
+ // Checking the device path to see the USB keyboard existance.
+ //
+ if ((Next->Type == MESSAGING_DEVICE_PATH) &&
+ (Next->SubType == MSG_USB_CLASS_DP) &&
+ (((USB_CLASS_DEVICE_PATH *) Next)->DeviceClass == CLASS_HID) &&
+ (((USB_CLASS_DEVICE_PATH *) Next)->DeviceSubClass == SUBCLASS_BOOT) &&
+ (((USB_CLASS_DEVICE_PATH *) Next)->DeviceProtocol == PROTOCOL_KEYBOARD)) {
+
+ DEBUG ((DEBUG_INFO, "[EnumUsbKeyboard] USB keyboard path exists\n"));
+ UsbKeyboard = TRUE;
+
+ break;
+ }
+ Next = NextDevicePathNode (Next);
+ }
+
+ if (DevicePathInstance != NULL) {
+ FreePool (DevicePathInstance);
+ }
+ } while (VarConIn != NULL);
+
+ //
+ // USB keyboard device path does not exist, So add it to the ConIn.
+ //
+ if (!UsbKeyboard) {
+ DEBUG ((DEBUG_INFO, "[EnumUsbKeyboard] Adding USB keyboard device path to ConIn.\n"));
+ EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL *) &mUsbClassKeyboardDevicePath, NULL);
+ }
+
+ if (VarConIn != NULL) {
+ FreePool (VarConIn);
+ }
+}
+
+/**
+ 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 (
+ EFI_DEVICE_PATH_PROTOCOL *Device
+ )
+{
+ if (IsGopDevicePath (Device)) {
+ return TRUE;
+ }
+
+ if (CompareMem (Device, &mKeyboardDevicePath, GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mKeyboardDevicePath) - END_DEVICE_PATH_LENGTH) == 0) {
+ return TRUE;
+ }
+
+ if (CompareMem (Device, &mUsbClassKeyboardDevicePath, GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mUsbClassKeyboardDevicePath) - END_DEVICE_PATH_LENGTH) == 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+VOID
+ProcessTcgPp (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Tcg2PpDataSize;
+ EFI_TCG2_PHYSICAL_PRESENCE Tcg2PpData;
+ EFI_PHYSICAL_PRESENCE TcgPpData;
+ UINTN TcgPpDataSize;
+
+ //
+ // Initialize physical presence variable.
+ //
+ if (CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid) ||
+ CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gTpmDeviceInstanceTpm20PttPtpGuid)) {
+ Tcg2PpDataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+ Status = gRT->GetVariable (
+ TCG2_PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiTcg2PhysicalPresenceGuid,
+ NULL,
+ &Tcg2PpDataSize,
+ &Tcg2PpData
+ );
+
+ if (EFI_ERROR (Status)) {
+ ZeroMem ((VOID *) &Tcg2PpData, sizeof (Tcg2PpData));
+ Tcg2PpDataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+ Status = gRT->SetVariable (
+ TCG2_PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiTcg2PhysicalPresenceGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Tcg2PpDataSize,
+ &Tcg2PpData
+ );
+ }
+ } else if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)) {
+ TcgPpDataSize = sizeof (EFI_PHYSICAL_PRESENCE);
+ Status = gRT->GetVariable (
+ PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiPhysicalPresenceGuid,
+ NULL,
+ &TcgPpDataSize,
+ &TcgPpData
+ );
+
+ if (EFI_ERROR (Status)) {
+ ZeroMem ((VOID *) &TcgPpData, sizeof (TcgPpData));
+ TcgPpDataSize = sizeof (EFI_PHYSICAL_PRESENCE);
+ Status = gRT->SetVariable (
+ PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiPhysicalPresenceGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ TcgPpDataSize,
+ &TcgPpData
+ );
+ }
+ }
+
+ if (!EFI_ERROR (Status) && ((Tcg2PpData.PPRequest != TCG2_PHYSICAL_PRESENCE_NO_ACTION) || (TcgPpData.PPRequest != TCG_PHYSICAL_PRESENCE_NO_ACTION))) {
+ //
+ // If it requests any action on TCG, need to connect console to display information.
+ //
+ EfiBootManagerConnectAllDefaultConsoles();
+ }
+
+ if (CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid) ||
+ CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gTpmDeviceInstanceTpm20PttPtpGuid)) {
+ Tcg2PhysicalPresenceLibProcessRequest (NULL);
+ } else if (CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)) {
+ TcgPhysicalPresenceLibProcessRequest ();
+ }
+}
+
+/**
+ Remove all GOP device path instance from DevicePath and add the Gop to the DevicePath.
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+UpdateDevicePath (
+ 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);
+ gBS->FreePool (Temp);
+ }
+ return Return;
+}
+
+#pragma optimize("g", off)
+
+/**
+ 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;
+ EFI_DEVICE_PATH_PROTOCOL *BootDevicePath;
+ BOOLEAN Result;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;
+ EFI_GUID *GuidPoint;
+
+ BootOption = NULL;
+ BootDevicePath = 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;
+}
+
+/**
+ 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 ()) {
+
+ }
+}
+
+/**
+ Platform Bds init. Incude the platform firmware vendor, revision
+ and so crc check.
+**/
+VOID
+EFIAPI
+PlatformBootManagerBeforeConsole (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *VarConOut;
+ EFI_DEVICE_PATH_PROTOCOL *VarConIn;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *ConsoleOut;
+ EFI_DEVICE_PATH_PROTOCOL *Temp;
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
+ EFI_DEVICE_PATH_PROTOCOL *Next;
+ EFI_HANDLE Handle;
+ EFI_EVENT Event;
+ EFI_GUID *TerminalGuid;
+ UINT8 TerminalType;
+ UINTN InstanceSize;
+
+ DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole\n"));
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Append Usb Keyboard short form DevicePath into "ConInDev".
+ //
+ EfiBootManagerUpdateConsoleVariable (
+ ConInDev,
+ (EFI_DEVICE_PATH_PROTOCOL *) &mUsbClassKeyboardDevicePath,
+ NULL
+ );
+
+ //
+ // Get user defined text mode for internal shell only once.
+ //
+ mShellHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
+ mShellVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution);
+ mShellModeColumn = PcdGet32 (PcdSetupConOutColumn);
+ mShellModeRow = PcdGet32 (PcdSetupConOutRow);
+
+ //
+ // 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);
+
+ //
+ // Update ConOut variable accordign to the PrimaryDisplay setting.
+ //
+ GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConsoleOut, NULL);
+
+ //
+ // Add IGD to ConOut.
+ //
+ Handle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &mPlatformIGDDevice;
+ Status = gBS->LocateDevicePath (&gEfiPciIoProtocolGuid, &TempDevicePath, &Handle);
+ if (!EFI_ERROR (Status) &&
+ IsDevicePathEnd (TempDevicePath) &&
+ IsVgaHandle (Handle)) {
+ }
+ DEBUG ((EFI_D_INFO, "GOP Device Handle - 0x%x\n", Handle));
+
+ if (Handle != NULL) {
+ //
+ // Connect the GOP driver.
+ //
+ gBS->ConnectController (Handle, NULL, NULL, TRUE);
+
+ //
+ // Get the GOP device path.
+ // NOTE: We may get a device path that contains Controller node in it.
+ //
+ TempDevicePath = EfiBootManagerGetGopDevicePath (Handle);
+ DEBUG ((EFI_D_INFO, "GOP device path - 0x%x\n", TempDevicePath));
+ if (TempDevicePath != NULL) {
+ DEBUG ((EFI_D_INFO, "GOP device string - %S\n", DevicePathToStr ((EFI_DEVICE_PATH_PROTOCOL*)TempDevicePath) ));
+ Temp = ConsoleOut;
+ ConsoleOut = UpdateDevicePath (ConsoleOut, TempDevicePath);
+ if (Temp != NULL) {
+ FreePool (Temp);
+ }
+ FreePool (TempDevicePath);
+ Status = gRT->SetVariable (
+ L"ConOut",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ GetDevicePathSize (ConsoleOut),
+ ConsoleOut
+ );
+ }
+ }
+
+ gBS->FreePool (ConsoleOut);
+
+ //
+ // Fill ConIn/ConOut in Full Configuration boot mode.
+ //
+ DEBUG ((DEBUG_ERROR, "PlatformBootManagerInit - %x\n", mBootMode));
+ if (mBootMode == BOOT_WITH_FULL_CONFIGURATION ||
+ mBootMode == BOOT_WITH_DEFAULT_SETTINGS ||
+ mBootMode == BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS ||
+ mBootMode == 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); }
+
+ if (VarConOut == NULL || VarConIn == NULL) {
+ //
+ // Only fill ConIn/ConOut when ConIn/ConOut is empty because we may drop to Full Configuration boot mode in non-first boot.
+ // Update ConOutDevicePath (just in case it is wrong at build phase).
+ // To be enabled later.
+ //
+ for (Index = 0; mPlatformConsole[Index].DevicePath != NULL; Index++) {
+ //
+ // Update the console variable with the connect type.
+ //
+ if ((mPlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
+ EfiBootManagerUpdateConsoleVariable (ConIn, mPlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((mPlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
+ EfiBootManagerUpdateConsoleVariable (ConOut, mPlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((mPlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
+ EfiBootManagerUpdateConsoleVariable (ErrOut, mPlatformConsole[Index].DevicePath, NULL);
+ }
+ }
+ } else {
+ if (mBootMode == BOOT_WITH_DEFAULT_SETTINGS) {
+ //
+ // Get default Terminal Type.
+ //
+ TerminalGuid = &gEfiPcAnsiGuid;
+ TerminalType = PcdGet8 (PcdDefaultTerminalType);
+ if (TerminalType < 4) {
+ TerminalGuid = mLibTerminalType[TerminalType];
+ }
+
+ GetEfiGlobalVariable2 (L"ConIn", (VOID **)&VarConIn, NULL);
+ Instance = GetNextDevicePathInstance (&VarConIn, &InstanceSize);
+ InstanceSize -= END_DEVICE_PATH_LENGTH;
+
+ while (Instance != NULL) {
+ Next = Instance;
+ while (!IsDevicePathEndType (Next)) {
+ Next = NextDevicePathNode (Next);
+ if (DevicePathType (Next) == MESSAGING_DEVICE_PATH && DevicePathSubType (Next) == MSG_VENDOR_DP) {
+ //
+ // Restoring default serial device path.
+ //
+ EfiBootManagerUpdateConsoleVariable (ConIn, NULL, Instance);
+ EfiBootManagerUpdateConsoleVariable (ConOut, NULL, Instance);
+ }
+ }
+ FreePool(Instance);
+ Instance = GetNextDevicePathInstance (&VarConIn, &InstanceSize);
+ InstanceSize -= END_DEVICE_PATH_LENGTH;
+ }
+ }
+ }
+ }
+
+ EnumPs2Keyboard ();
+ EnumUsbKeyboard ();
+
+ //
+ // Dynamically register hot key: F2/F7/Enter.
+ //
+ RegisterDefaultBootOption ();
+ RegisterStaticHotkey ();
+
+ //
+ // Connect Root Bridge to make PCI BAR resource allocated.
+ // Then exit PM auth before Legacy OPROM run.
+ //
+ ConnectRootBridge (FALSE);
+
+ ProcessTcgPp ();
+
+ ExitPmAuth ();
+}
+
+/**
+ 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 = mBootMode;
+ DEBUG ((DEBUG_ERROR, "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.
+ //
+ ConnectSequence (LocalBootMode);
+
+ 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.
+ //
+ EfiBootManagerRefreshAllBootOption ();
+
+ break;
+ }
+
+ if (IsNeedSortBootOption()) {
+ EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOption);
+ }
+}
diff --git a/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootManager.h b/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootManager.h
new file mode 100644
index 0000000000..5ed9a4b37d
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootManager.h
@@ -0,0 +1,226 @@
+/** @file
+ Header file of Platform Boot Manager Lib.
+
+ Copyright (c) 2006 - 2018, 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.
+
+**/
+
+#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 <IndustryStandard/Pci30.h>
+#include <IndustryStandard/PciCodeId.h>
+
+#define CONSOLE_OUT 0x00000001
+#define STD_ERROR 0x00000002
+#define CONSOLE_IN 0x00000004
+#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
+#define CLASS_HID 3
+#define SUBCLASS_BOOT 1
+#define PROTOCOL_KEYBOARD 1
+
+#define mPciRootBridge \
+ { \
+ ACPI_DEVICE_PATH, ACPI_DP, (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), (UINT8) \
+ ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8), EISA_PNP_ID (0x0A03), 0 \
+ }
+
+#define mEndEntire \
+ { \
+ 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 IsaBridge;
+ ACPI_HID_DEVICE_PATH IsaSerial;
+ UART_DEVICE_PATH Uart;
+ VENDOR_DEVICE_PATH TerminalType;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_ISA_SERIAL_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;
+
+typedef struct {
+ USB_CLASS_DEVICE_PATH UsbClass;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} USB_CLASS_FORMAT_DEVICE_PATH;
+
+typedef
+VOID
+(*PROCESS_VARIABLE) (
+ VOID **Variable,
+ UINTN *VariableSize
+ );
+
+/**
+ Generic function to update the console variable.
+ Please refer to FastBootSupport.c for how to use it.
+
+ @param VariableName - The name of the variable to be updated
+ @param AgentGuid - The Agent GUID
+ @param ProcessVariable - The function pointer to update the variable
+ NULL means to restore to the original value
+**/
+VOID
+UpdateEfiGlobalVariable (
+ CHAR16 *VariableName,
+ EFI_GUID *AgentGuid,
+ PROCESS_VARIABLE ProcessVariable
+ );
+
+VOID
+ConnectSequence (
+ IN EFI_BOOT_MODE BootMode
+ );
+
+INTN
+EFIAPI
+CompareBootOption (
+ CONST EFI_BOOT_MANAGER_LOAD_OPTION *Left,
+ CONST EFI_BOOT_MANAGER_LOAD_OPTION *Right
+ );
+
+VOID
+PrintBootPrompt (
+ VOID
+ );
+
+VOID
+RegisterStaticHotkey (
+ VOID
+ );
+
+VOID
+RegisterDynamicHotkey (
+ VOID
+ );
+
+VOID
+RegisterDefaultBootOption (
+ VOID
+ );
+
+VOID
+BootUi (
+ VOID
+ );
+
+EFI_STATUS
+AutomaticFirmwareUpdateHandler (
+ CHAR16 *FileName
+ );
+
+EFI_STATUS
+EFIAPI
+EfiPlatformBootManagerProcessCapsules (
+ VOID
+ );
+
+VOID
+PlatformBootManagerAttemptUsbBoot (
+ VOID
+ );
+
+EFI_STATUS
+SetMorControl (
+ VOID
+ );
+
+extern PLATFORM_ISA_SERIAL_DEVICE_PATH mSerialDevicePath;
+extern EFI_DEVICE_PATH_PROTOCOL *mPlatformRootBridges[];
+extern BDS_CONSOLE_CONNECT_ENTRY mPlatformConsole[];
+extern PLATFORM_ONBOARD_CONTROLLER_DEVICE_PATH mPlatformIGDDevice;
+extern PLATFORM_KEYBOARD_DEVICE_PATH mKeyboardDevicePath;
+extern USB_CLASS_FORMAT_DEVICE_PATH mUsbClassKeyboardDevicePath;
+extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassMassStorageDevice;
+extern EFI_GUID gUefiShellFileGuid;
+extern EFI_HII_HANDLE mPlatformBdsLibStringPackHandle;
+extern BDS_CONSOLE_CONNECT_ENTRY mPlatformConsole [];
+extern EFI_BOOT_MODE mBootMode;
+
+#endif
diff --git a/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
new file mode 100644
index 0000000000..8e429fbf9f
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
@@ -0,0 +1,109 @@
+## @file
+# Component INF for module PlatformBootManagerLib.
+#
+# Copyright (c) 2008 - 2018, 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
+ #
+
+[Sources]
+ PlatformBootManager.c
+ PlatformData.c
+ PlatformBootOption.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ BroxtonPlatformPkg/PlatformPkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand
+ gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid
+
+ [LibraryClasses]
+ BaseLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ PrintLib
+ DevicePathLib
+ UefiLib
+ HobLib
+ DxeServicesLib
+ DxeServicesTableLib
+ HiiLib
+ UefiBootManagerLib
+ PerformanceLib
+ TimerLib
+ PciLib
+ Tcg2PhysicalPresenceLib
+ TcgPhysicalPresenceLib
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEfiCpuIo2ProtocolGuid
+ gEfiDxeSmmReadyToLockProtocolGuid
+ gEfiGenericMemTestProtocolGuid
+ gEfiDiskInfoProtocolGuid
+ gEfiAcpiS3SaveProtocolGuid
+ gEfiDevicePathToTextProtocolGuid
+ gEfiSimpleTextInputExProtocolGuid
+ gEfiFirmwareVolume2ProtocolGuid
+ gEfiFormBrowser2ProtocolGuid
+ gExitPmAuthProtocolGuid
+ gEfiGraphicsOutputProtocolGuid
+
+[Guids]
+ gEfiGlobalVariableGuid
+ gEfiEndOfDxeEventGroupGuid
+ gEfiVTUTF8Guid
+ gEfiVT100Guid
+ gEfiVT100PlusGuid
+ gEfiPcAnsiGuid
+ gEfiTpmDeviceInstanceTpm20DtpmGuid
+ gTpmDeviceInstanceTpm20PttPtpGuid
+ gEfiTcg2PhysicalPresenceGuid
+ gEfiTpmDeviceInstanceTpm12Guid
+
+[Depex.common.DXE_DRIVER]
+ gEfiVariableArchProtocolGuid
diff --git a/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootOption.c b/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootOption.c
new file mode 100644
index 0000000000..bed512a462
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformBootOption.c
@@ -0,0 +1,738 @@
+/** @file
+ This file include all platform action which can be customized by IBV/OEM.
+
+ Copyright (c) 2006 - 2018, 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.
+
+**/
+
+#include "PlatformBootManager.h"
+
+BOOLEAN mContinueBoot = FALSE;
+BOOLEAN mUiAppBoot = FALSE;
+BOOLEAN mPxeBoot = FALSE;
+BOOLEAN mAnyKeypressed = FALSE;
+BOOLEAN mHotKeypressed = FALSE;
+EFI_EVENT HotKeyEvent = NULL;
+UINTN mUiAppOptionNumber;
+CHAR16 *TmpStr = L"Press [F2] key to enter BIOS Setup";
+
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+
+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 }};
+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"
+#define UEFI_NVME_DRIVE_NAME L"UEFI NVMe Storage"
+
+/**
+ Show progress bar with title above it. It only works in Graphics mode.
+
+ @param TitleForeground Foreground color for Title.
+ @param TitleBackground Background color for Title.
+ @param Title Title above progress bar.
+ @param ProgressColor Progress bar color.
+ @param Progress Progress (0-100)
+ @param PreviousValue The previous value of the progress.
+
+ @retval EFI_STATUS Success update the progress bar.
+
+**/
+EFI_STATUS
+PlatformBdsShowProgress (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
+ IN CHAR16 *Title,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
+ IN UINTN Progress,
+ IN UINTN PreviousValue
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ UINT32 SizeOfX;
+ UINT32 SizeOfY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ UINTN BlockHeight;
+ UINTN BlockWidth;
+ UINTN BlockNum;
+ UINTN PosX;
+ UINTN PosY;
+ UINTN Index;
+
+ if (Progress > 100) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **) &GraphicsOutput
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ SizeOfX = 0;
+ SizeOfY = 0;
+ if (GraphicsOutput != NULL) {
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ BlockWidth = SizeOfX / 100;
+ BlockHeight = SizeOfY / 50;
+
+ BlockNum = Progress;
+
+ PosX = 0;
+ PosY = SizeOfY * 48 / 50;
+
+ if (BlockNum == 0) {
+ //
+ // Clear progress area
+ //
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &Color,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ 0,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ SizeOfX,
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
+ SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ //
+ // Show progress by drawing blocks.
+ //
+ for (Index = PreviousValue; Index < BlockNum; Index++) {
+ PosX = Index * BlockWidth;
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &ProgressColor,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ PosX,
+ PosY,
+ BlockWidth - 1,
+ BlockHeight,
+ (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ PrintXY (
+ (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ &TitleForeground,
+ &TitleBackground,
+ Title
+ );
+
+ return EFI_SUCCESS;
+}
+
+/*++
+
+This function will create a SHELL BootOption to boot.
+
+ @param void
+
+ @retval EFI_STATUS
+
+--*/
+EFI_DEVICE_PATH_PROTOCOL *
+BdsCreateShellDevicePath (
+ VOID
+ )
+
+{
+ 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_ERROR, "[FVMAIN2] 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;
+}
+
+/**
+ 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
+BootUi (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
+
+ Status = EfiBootManagerGetBootManagerMenu (&BootOption);
+ if (!EFI_ERROR (Status)) {
+ EfiBootManagerBoot (&BootOption);
+ EfiBootManagerFreeLoadOption (&BootOption);
+ }
+}
+
+VOID
+EFIAPI
+PlatformBootManagerWaitCallback (
+ UINT16 TimeoutRemain
+ )
+{
+ UINT16 TimeoutDefault;
+ EFI_STATUS Status;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;
+ EFI_KEY_DATA KeyData;
+ BOOLEAN PausePressed;
+
+ TimeoutDefault = PcdGet16 (PcdPlatformBootTimeOut);
+ if (TimeoutDefault == TimeoutRemain) {
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+ }
+
+ PlatformBdsShowProgress (
+ Foreground,
+ Background,
+ TmpStr,
+ Color,
+ ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),
+ 0
+ );
+
+ //
+ // 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);
+ }
+ }
+}
+
+/**
+ Check if the boot option is a EFI network boot option.
+
+ @param Option The boot option need to be processed.
+
+ @retval TRUE It is a EFI network boot option.
+ @retval FALSE It is not a EFI network boot option.
+
+**/
+BOOLEAN
+IsEfiNetWorkBootOption (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *Option
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+
+ for (Node = Option->FilePath; !IsDevicePathEndType (Node); Node = NextDevicePathNode (Node)) {
+ if (DevicePathType (Node) == MESSAGING_DEVICE_PATH) {
+ switch (DevicePathSubType (Node)) {
+ case MSG_MAC_ADDR_DP:
+ case MSG_VLAN_DP:
+ case MSG_IPv4_DP:
+ case MSG_IPv6_DP:
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+VOID
+RegisterDefaultBootOption (
+ VOID
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+ UINT16 *ShellData;
+ UINT32 ShellDataSize;
+
+ //
+ // Shell.
+ //
+ if (1) {
+ ShellData = NULL;
+ ShellDataSize = 0;
+ RegisterFvBootOption (&gUefiShellFileGuid, INTERNAL_UEFI_SHELL_NAME, (UINTN) -1, LOAD_OPTION_ACTIVE, (UINT8 *)ShellData, ShellDataSize);
+ }
+
+ //
+ // UiApp.
+ //
+ mUiAppOptionNumber = RegisterFvBootOption (&mUiFile, L"Enter Setup", (UINTN) -1, (LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDEN), NULL, 0);
+
+ if (mUiAppOptionNumber == LoadOptionNumberUnassigned) {
+ DEBUG ((DEBUG_ERROR, "UiAppOptionNumber (%d) should not be same to LoadOptionNumberUnassigned(%d).\n", mUiAppOptionNumber, LoadOptionNumberUnassigned));
+ }
+
+ //
+ // Boot Manager Menu.
+ //
+ EfiInitializeFwVolDevicepathNode (&FileNode, &mBootMenuFile);
+
+ gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage
+ );
+ DevicePath = AppendDevicePathNode (DevicePathFromHandle (LoadedImage->DeviceHandle), (EFI_DEVICE_PATH_PROTOCOL *) &FileNode);
+
+}
+
+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].
+ //
+
+ F7.Key.ScanCode = SCAN_F7;
+ F7.Key.UnicodeChar = CHAR_NULL;
+ F7.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
+ F7.KeyState.KeyToggleState = 0;
+ Status = EfiBootManagerGetBootManagerMenu (&BootOption);
+ ASSERT_EFI_ERROR (Status);
+ //
+ RegisterBootOptionHotkey ((UINT16) BootOption.OptionNumber, &F7.Key, TRUE);
+ EfiBootManagerFreeLoadOption (&BootOption);
+
+ F2.Key.ScanCode = SCAN_F2;
+ F2.Key.UnicodeChar = CHAR_NULL;
+ F2.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
+ F2.KeyState.KeyToggleState = 0;
+ mUiAppBoot = !EnterSetup;
+ RegisterBootOptionHotkey ((UINT16) mUiAppOptionNumber, &F2.Key, mUiAppBoot);
+}
+
+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 Default Priority
+ ------------------------------------
+ PXE 5
+ DVD 2
+ USB 1
+ NVME 4
+ HDD 3
+ EFI Shell 6
+ 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 5;
+ case MSG_SATA_DP:
+ case MSG_ATAPI_DP:
+ return 2;
+ case MSG_USB_DP:
+ return 1;
+ }
+
+ if (StrCmp (BootOption->Description, INTERNAL_UEFI_SHELL_NAME) == 0) {
+ return 6;
+ }
+ if (StrCmp (BootOption->Description, UEFI_HARD_DRIVE_NAME) == 0) {
+ return 3;
+ }
+ if (StrCmp (BootOption->Description, UEFI_NVME_DRIVE_NAME) == 0) {
+ return 4;
+ }
+
+ return 100;
+}
+
+INTN
+EFIAPI
+CompareBootOption (
+ CONST EFI_BOOT_MANAGER_LOAD_OPTION *Left,
+ CONST EFI_BOOT_MANAGER_LOAD_OPTION *Right
+ )
+{
+ return BootOptionPriority (Left) - BootOptionPriority (Right);
+}
diff --git a/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformData.c b/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformData.c
new file mode 100644
index 0000000000..90b05334dd
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Library/PlatformBootManagerLib/PlatformData.c
@@ -0,0 +1,179 @@
+/** @file
+ This file include all platform action which can be customized by IBV/OEM.
+
+ Copyright (c) 2006 - 2018, 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.
+
+**/
+
+#include "PlatformBootManager.h"
+
+#define PCI_DEVICE_NUMBER_PCH_LPC 31
+#define PCI_FUNCTION_NUMBER_PCH_LPC 0
+
+#define SA_IGD_DEV 0x02
+#define SA_IGD_FUN 0x00
+
+//
+// Predefined platform root bridge.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 = {
+ mPciRootBridge,
+ mEndEntire
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_PROTOCOL *mPlatformRootBridges[] = {
+ (EFI_DEVICE_PATH_PROTOCOL *) &gPlatformRootBridge0,
+ NULL
+};
+
+//
+// Platform specific keyboard device path.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PLATFORM_KEYBOARD_DEVICE_PATH mKeyboardDevicePath = {
+ mPciRootBridge,
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_PCI_DP,
+ (UINT8) (sizeof (PCI_DEVICE_PATH)),
+ (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8),
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ PCI_DEVICE_NUMBER_PCH_LPC
+ },
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8),
+ EISA_PNP_ID(0x0303),
+ 0
+ },
+ mEndEntire
+};
+
+//
+// Platform specific serial device path.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PLATFORM_ISA_SERIAL_DEVICE_PATH mSerialDevicePath = {
+ mPciRootBridge,
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_PCI_DP,
+ (UINT8) (sizeof (PCI_DEVICE_PATH)),
+ (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8),
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ PCI_DEVICE_NUMBER_PCH_LPC
+ },
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8),
+ EISA_PNP_ID(0x0501),
+ 0
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_UART_DP,
+ (UINT8) (sizeof (UART_DEVICE_PATH)),
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8),
+ 0,
+ 115200,
+ 8,
+ 1,
+ 1
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP,
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8),
+ DEVICE_PATH_MESSAGING_PC_ANSI
+ },
+ mEndEntire
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH mUsbClassKeyboardDevicePath = {
+ {
+ {
+ 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
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+};
+
+//
+// Onboard VGA controller device path.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PLATFORM_ONBOARD_CONTROLLER_DEVICE_PATH mPlatformIGDDevice = {
+ mPciRootBridge,
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_PCI_DP,
+ (UINT8) (sizeof (PCI_DEVICE_PATH)),
+ (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8),
+ SA_IGD_FUN,
+ SA_IGD_DEV
+ },
+ mEndEntire
+};
+
+//
+// Predefined platform default console device path.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED BDS_CONSOLE_CONNECT_ENTRY mPlatformConsole[] = {
+ {
+ (EFI_DEVICE_PATH_PROTOCOL *) &mSerialDevicePath,
+ (CONSOLE_OUT | CONSOLE_IN)
+ },
+ {
+ (EFI_DEVICE_PATH_PROTOCOL *) &mKeyboardDevicePath,
+ CONSOLE_IN
+ },
+ {
+ (EFI_DEVICE_PATH_PROTOCOL *) &mUsbClassKeyboardDevicePath,
+ CONSOLE_IN
+ },
+ {
+ NULL,
+ 0
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH gUsbClassMassStorageDevice = {
+ {
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_CLASS_DP,
+ (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),
+ (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
+ },
+ 0xffff, // VendorId
+ 0xffff, // ProductId
+ 0x08, // DeviceClass - USB Mass Storage Class
+ 0x06, // DeviceSubClass - SCSI Transparent Command Set
+ 0xff // DeviceProtocol - Match any Device Protocol
+ },
+ mEndEntire
+};