public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Abdul Lateef Attar via groups.io" <AbdulLateef.Attar=amd.com@groups.io>
To: <devel@edk2.groups.io>
Cc: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>,
	Abner Chang <abner.chang@amd.com>,
	Paul Grimes <paul.grimes@amd.com>
Subject: [edk2-devel] [PATCH 5/5] AmdMinBoardPkg: Implements BoardBdsHookLib library
Date: Fri, 17 May 2024 09:19:13 +0530	[thread overview]
Message-ID: <dd61bee14aae29074834cf0214fd110671f0e14a.1715917637.git.AbdulLateef.Attar@amd.com> (raw)
In-Reply-To: <cover.1715917637.git.AbdulLateef.Attar@amd.com>

Implements BoardBdsHookLib library class for AMD platforms.

Cc: Abner Chang <abner.chang@amd.com>
Cc: Paul Grimes <paul.grimes@amd.com>
Signed-off-by: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
---
 .../AMD/AmdMinBoardPkg/AmdMinBoardPkg.dec     |   10 +
 .../AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc     |    2 +
 .../Include/Library/AmdBoardBdsHookLib.h      |  130 ++
 .../Library/BoardBdsHookLib/BoardBdsHook.h    |  242 +++
 .../Library/BoardBdsHookLib/BoardBdsHookLib.c | 1712 +++++++++++++++++
 .../BoardBdsHookLib/BoardBdsHookLib.inf       |  105 +
 .../Library/BoardBdsHookLib/BoardBootOption.c |  754 ++++++++
 .../Library/BoardBdsHookLib/BoardMemoryTest.c |   83 +
 8 files changed, 3038 insertions(+)
 create mode 100644 Platform/AMD/AmdMinBoardPkg/Include/Library/AmdBoardBdsHookLib.h
 create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h
 create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c
 create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
 create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBootOption.c
 create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardMemoryTest.c

diff --git a/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dec b/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dec
index 03d1d77c34..47ec5b4b56 100644
--- a/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dec
+++ b/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dec
@@ -17,9 +17,19 @@
   PACKAGE_GUID                   = 44F9D761-9ECB-43DD-A5AC-177E5048701B
   PACKAGE_VERSION                = 0.1
 
+[Includes]
+  Include
+
 [Guids]
   gAmdMinBoardPkgTokenSpaceGuid  = {0xd4d23d79, 0x73bf, 0x460a, {0xa1, 0xc7, 0x85, 0xa3, 0xca, 0x71, 0xb9, 0x4c}}
 
+[LibraryClasses]
+  ##  @libraryclass    Provide services to platform BDS hook.
+  BoardBdsHookLib|Include/Library/AmdBoardBdsHookLib.h
+
+[Protocols]
+  gAmdBoardBdsBootOptionPriorityProtocolGuid = { 0x5806db97, 0x5303, 0x409f, { 0x8f, 0x09, 0xab, 0x29, 0xd8, 0x07, 0xa3, 0xf1}}
+
 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   #
   # PCI HotPlug Resource Padding
diff --git a/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc b/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc
index e0afe1e755..e002e78f21 100644
--- a/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc
+++ b/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc
@@ -41,6 +41,7 @@
   BoardInitLib|AmdMinBoardPkg/Library/PeiBoardInitPreMemLib/PeiBoardInitPreMemLib.inf
 
 [LibraryClasses.common.DXE_DRIVER]
+  BoardBdsHookLib|AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
   BoardInitLib|AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.inf
 
 [Components]
@@ -53,4 +54,5 @@
 
 [Components.X64]
   AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.inf
+  AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
   AmdMinBoardPkg/PciHotPlug/PciHotPlugInit.inf
\ No newline at end of file
diff --git a/Platform/AMD/AmdMinBoardPkg/Include/Library/AmdBoardBdsHookLib.h b/Platform/AMD/AmdMinBoardPkg/Include/Library/AmdBoardBdsHookLib.h
new file mode 100644
index 0000000000..6bfa4747e0
--- /dev/null
+++ b/Platform/AMD/AmdMinBoardPkg/Include/Library/AmdBoardBdsHookLib.h
@@ -0,0 +1,130 @@
+/** @file
+  Header file for BDS Hook Library
+
+  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef AMD_BOARD_BDS_HOOK_LIB_H_
+#define AMD_BOARD_BDS_HOOK_LIB_H_
+
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PlatformBootManagerLib.h>
+#include <Library/SortLib.h>
+
+#define AMD_BOARD_BDS_BOOT_OPTION_PRIORITY_PROTOCOL_GUID    \
+  { 0x5806db97, 0x5303, 0x409f,                         \
+    { 0x8f, 0x09, 0xab, 0x29, 0xd8, 0x07, 0xa3, 0xf1 }}
+
+/*
+  This protocol is introduced so the platform can give certain boot options
+  a custom priority value. Useful in boot overrides, or when IPMI doesn't inherently
+  support a specific boot override needed by the platform.
+*/
+struct _AMD_BOARD_BDS_BOOT_OPTION_PRIORITY_PROTOCOL {
+  UINT8           IpmiBootDeviceSelectorType;
+  SORT_COMPARE    Compare;
+};
+
+typedef struct _AMD_BOARD_BDS_BOOT_OPTION_PRIORITY_PROTOCOL AMD_BOARD_BDS_BOOT_OPTION_PRIORITY_PROTOCOL;
+
+extern EFI_GUID  gAmdBoardBdsBootOptionPriorityProtocolGuid;
+
+/**
+  Returns the boot option type of a device
+
+  @param[in] DevicePath         The path of device whose boot option type
+                                should be returned
+  @retval -1                    Device type not found
+  @retval > -1                  Device type found
+**/
+UINT8
+BootOptionType (
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  );
+
+/**
+  This is the callback function for Bds Ready To Boot event.
+
+  @param[in]  Event   Pointer to this event
+  @param[in]  Context Event handler private data
+
+  @retval None.
+**/
+VOID
+EFIAPI
+BdsReadyToBootCallback (
+  IN  EFI_EVENT  Event,
+  IN  VOID       *Context
+  );
+
+/**
+  This is the callback function for Smm Ready To Lock event.
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsSmmReadyToLockCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+/**
+  This is the callback function for PCI ENUMERATION COMPLETE.
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsPciEnumCompleteCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+/**
+  Before console after trusted console event callback
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsBeforeConsoleAfterTrustedConsoleCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+/**
+  Before console before end of DXE event callback
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsBeforeConsoleBeforeEndOfDxeGuidCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+/**
+  After console ready before boot option event callback
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsAfterConsoleReadyBeforeBootOptionCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+#endif
diff --git a/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h
new file mode 100644
index 0000000000..5c950c4866
--- /dev/null
+++ b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h
@@ -0,0 +1,242 @@
+/** @file
+  Header file for BDS Hook Library
+
+  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef BOARD_BDS_HOOK_H_
+#define BOARD_BDS_HOOK_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>
+#include <Protocol/PciEnumerationComplete.h>
+
+///
+/// For boot order override.
+///
+#define IPMI_BOOT_OVERRIDE_VAR_NAME  L"IpmiBootOverride"
+#define IS_FIRST_BOOT_VAR_NAME       L"IsFirstBoot"
+#define UEFI_HARD_DRIVE_NAME         L"UEFI Hard Drive"
+
+///
+/// ConnectType
+///
+#define CONSOLE_OUT  0x00000001
+#define STD_ERROR    0x00000002
+#define CONSOLE_IN   0x00000004
+#define CONSOLE_ALL  (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
+#define END_ENTIRE_DEVICE_PATH \
+  { \
+    END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { END_DEVICE_PATH_LENGTH, 0 } \
+  }
+
+extern EFI_GUID       gUefiShellFileGuid;
+extern EFI_BOOT_MODE  gBootMode;
+
+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[in]  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
+  );
+
+/**
+  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
+  );
+
+/**
+   Compares boot priorities of two boot options
+
+  @param[in] Left       The left boot option
+  @param[in] Right      The right boot option
+
+  @return           The difference between the Left and Right
+                    boot options
+ **/
+INTN
+EFIAPI
+CompareBootOption (
+  IN CONST VOID  *Left,
+  IN CONST VOID  *Right
+  );
+
+/**
+   Compares boot priorities of two boot options, while giving PXE the highest priority
+
+  @param[in] Left       The left boot option
+  @param[in] Right      The right boot option
+
+  @return           The difference between the Left and Right
+                    boot options
+**/
+INTN
+EFIAPI
+CompareBootOptionPxePriority (
+  IN CONST VOID  *Left,
+  IN CONST VOID  *Right
+  );
+
+/**
+   Compares boot priorities of two boot options, while giving HDD the highest priority
+
+  @param[in] Left       The left boot option
+  @param[in] Right      The right boot option
+
+  @return           The difference between the Left and Right
+                    boot options
+**/
+INTN
+EFIAPI
+CompareBootOptionHddPriority (
+  IN CONST VOID  *Left,
+  IN CONST VOID  *Right
+  );
+
+/**
+  This function is called after all the boot options are enumerated and ordered properly.
+**/
+VOID
+RegisterStaticHotkey (
+  VOID
+  );
+
+/**
+  Registers/Unregisters boot option hotkey
+**/
+VOID
+RegisterDefaultBootOption (
+  VOID
+  );
+
+/**
+  Add console variable device paths
+
+  @param[in] ConsoleType         ConIn or ConOut
+  @param[in] ConsoleDevicePath   Device path to be added
+**/
+VOID
+AddConsoleVariable (
+  IN CONSOLE_TYPE     ConsoleType,
+  IN EFI_DEVICE_PATH  *ConsoleDevicePath
+  );
+
+#endif //BOARD_BDS_HOOK_H_
diff --git a/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c
new file mode 100644
index 0000000000..3d7c0c2bf7
--- /dev/null
+++ b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c
@@ -0,0 +1,1712 @@
+/** @file
+  This library registers Bds callbacks. It is a default library
+  implementation instance of the BDS hook library
+
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+  Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Guid/EventGroup.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+#include <Library/IpmiBaseLib.h>
+#include <Library/IpmiCommandLib.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/UsbIo.h>
+#include <Protocol/PciEnumerationComplete.h>
+#include <IndustryStandard/Ipmi.h>
+#include <Library/AmdBoardBdsHookLib.h>
+#include "BoardBdsHook.h"
+
+#ifdef INTERNAL_IDS
+  #include <Register/Amd/Msr.h>
+#endif
+
+CHAR16                                       *mConsoleVar[] = { L"ConIn", L"ConOut" };
+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
+  },
+  END_ENTIRE_DEVICE_PATH
+};
+
+#ifdef INTERNAL_IDS
+EFI_STATUS
+PrintSocOpnInfo (
+  IN  VOID
+  );
+
+#endif
+
+//
+// BDS Platform Functions
+//
+
+/**
+  Checks if Mor bit is set.
+  @retval TRUE    The MOR bit is set
+  @retval FALSE   The MOR bit is not set
+**/
+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, " gEfiMemoryOverwriteControlDataGuid doesn't exist!!***\n"));
+    MorControl = 0;
+  } else {
+    DEBUG ((DEBUG_INFO, " Get the gEfiMemoryOverwriteControlDataGuid = %x!!***\n", MorControl));
+  }
+
+  return (BOOLEAN)(MorControl & 0x01);
+}
+
+/**
+  Prints device paths.
+  @param[in] Name           The device name.
+  @param[in] DevicePath     The device path to be printed
+**/
+VOID
+EFIAPI
+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);
+  }
+}
+
+/**
+  Return whether the device is trusted console.
+
+  @param[in]  ConsoleType  The console type.
+  @param[in]  Device       The device path 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 = DuplicateDevicePath (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 = DuplicateDevicePath (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);
+      if (TempDevicePath != NULL) {
+        FreePool (TempDevicePath);
+      }
+
+      return TRUE;
+    }
+
+    FreePool (Instance);
+  } while (TempDevicePath != NULL);
+
+  FreePool (ConsoleDevice);
+  if (TempDevicePath != NULL) {
+    FreePool (TempDevicePath);
+  }
+
+  return FALSE;
+}
+
+/**
+  Return whether the USB device path is in a short form.
+
+  @param[in] DevicePath  The device path to be tested.
+
+  @retval TRUE   The device path is in short form.
+  @retval FALSE  The device path is not in short form.
+**/
+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[in] 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;
+}
+
+/**
+  Return whether the Handle is a vga handle.
+
+  @param[in] Handle  The handle to be tested.
+
+  @retval TRUE   The handle is a vga handle.
+  @retval FALSE  The handle is not a vga handle..
+**/
+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;
+}
+
+/**
+  Return whether the device path points to a video controller.
+
+  @param[in] DevicePath  The device path to be tested.
+
+  @retval TRUE   The device path points to a video controller.
+  @retval FALSE  The device path does not point to a video controller.
+**/
+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;
+  }
+}
+
+/**
+  Return whether the device path is a GOP device path.
+
+  @param[in] DevicePath  The device path to be tested.
+
+  @retval TRUE   The device path is a GOP device path.
+  @retval FALSE  The device on the device path is not a GOP device path.
+**/
+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.
+
+  @param[in] DevicePath  The device path to be removed
+  @param[in] Gop         The device path to be added.
+
+  @retval Return     The updated device path.
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+UpdateGopDevicePath (
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
+  IN 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. VgaDevices needs to be freed by caller.
+
+  @param[in] NeedTrustedConsole     The flag to determine if trusted console
+                                    or non trusted console should be returned
+  @param[out] VgaDevices            Array of handles corresponding to
+                                    valid VGA devices
+  @param[out] VgaDevicesCount       Number of VGA devices found and placed in
+                                    VgaDevices
+
+  @retval EFI ERROR                 No VGA capable devices found
+  @retval EFI_SUCCESS               At least one VGA device found
+**/
+EFI_STATUS
+EFIAPI
+GetGraphicsController (
+  IN  BOOLEAN     NeedTrustedConsole,
+  OUT EFI_HANDLE  **VgaDevices,
+  OUT UINTN       *VgaDevicesCount
+  )
+{
+  EFI_STATUS                Status;
+  UINTN                     Index;
+  EFI_HANDLE                *PciHandles;
+  UINTN                     PciHandlesSize;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  UINT32                    NumDevices;
+
+  if ((VgaDevicesCount == NULL) || (VgaDevices == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  NumDevices = 0;
+  Status     = gBS->LocateHandleBuffer (
+                      ByProtocol,
+                      &gEfiPciIoProtocolGuid,
+                      NULL,
+                      &PciHandlesSize,
+                      &PciHandles
+                      );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *VgaDevices = AllocateZeroPool (sizeof (EFI_HANDLE) * PciHandlesSize);
+  if (VgaDevices == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  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))))
+    {
+      VgaDevices[0][NumDevices] = PciHandles[Index];
+      NumDevices++;
+    }
+  }
+
+  *VgaDevicesCount = NumDevices;
+  if (NumDevices > 0) {
+    return EFI_SUCCESS;
+  } else {
+    return EFI_NOT_FOUND;
+  }
+}
+
+/**
+  Updates Graphic ConOut variable. This function searches for all VGA capable output devices and
+  adds them to the ConOut variable.
+
+  @param[in] NeedTrustedConsole    The flag that determines if trusted console
+  or non trusted console should be returned
+**/
+VOID
+UpdateGraphicConOut (
+  IN BOOLEAN  NeedTrustedConsole
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *ConOutDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *UpdatedConOutDevicePath;
+  EFI_HANDLE                *VgaDevices;
+  UINTN                     VgaDevicesCount;
+  UINTN                     Count;
+  EFI_STATUS                Status;
+
+  Count           = 0;
+  VgaDevicesCount = 0;
+
+  //
+  // Update ConOut variable
+  //
+  Status = GetGraphicsController (NeedTrustedConsole, &VgaDevices, &VgaDevicesCount);
+  if (Status == EFI_SUCCESS) {
+    GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConOutDevicePath, NULL);
+    if (ConOutDevicePath != NULL) {
+      DumpDevicePath (L"Original ConOut variable", ConOutDevicePath);
+      FreePool (ConOutDevicePath);
+    }
+
+    // Add VGA devices to ConOut
+    for (Count = 0; Count < VgaDevicesCount; Count++) {
+      //
+      // Connect the GOP driver
+      //
+      gBS->ConnectController (VgaDevices[Count], NULL, NULL, TRUE);
+      //
+      // Get the GOP device path
+      // NOTE: We may get a device path that contains Controller node in it.
+      //
+      GopDevicePath = EfiBootManagerGetGopDevicePath (VgaDevices[Count]);
+      if (GopDevicePath != NULL) {
+        GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConOutDevicePath, NULL);
+        if (ConOutDevicePath != NULL) {
+          UpdatedConOutDevicePath = UpdateGopDevicePath (ConOutDevicePath, GopDevicePath);
+          if (UpdatedConOutDevicePath != NULL) {
+            gRT->SetVariable (
+                   L"ConOut",
+                   &gEfiGlobalVariableGuid,
+                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                   GetDevicePathSize (UpdatedConOutDevicePath),
+                   UpdatedConOutDevicePath
+                   );
+            FreePool (UpdatedConOutDevicePath);
+          }
+
+          FreePool (ConOutDevicePath);
+        }
+
+        FreePool (GopDevicePath);
+      }
+    }
+
+    FreePool (VgaDevices);
+  }
+
+  GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConOutDevicePath, NULL);
+  if (ConOutDevicePath != NULL) {
+    DumpDevicePath (L"Final ConOut variable", ConOutDevicePath);
+    FreePool (ConOutDevicePath);
+  }
+}
+
+/**
+  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;
+  VOID                      *TrustedConsoleDevicepath;
+
+  TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
+  DumpDevicePath (L"TrustedConsoleIn", TrustedConsoleDevicepath);
+  TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
+  DumpDevicePath (L"TrustedConsoleOut", TrustedConsoleDevicepath);
+
+  for (Index = 0; Index < sizeof (mConsoleVar) / sizeof (mConsoleVar[0]); Index++) {
+    GetEfiGlobalVariable2 (mConsoleVar[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 = DuplicateDevicePath (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);
+
+  if (TempDevicePath != NULL) {
+    FreePool (TempDevicePath);
+  }
+}
+
+/**
+  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 internal 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;
+
+  //
+  // Internal shell mode
+  //
+  UINT32  mShellModeColumn;
+  UINT32  mShellModeRow;
+  UINT32  mShellHorizontalResolution;
+  UINT32  mShellVerticalResolution;
+
+  //
+  // Get user defined text mode for internal shell only once.
+  //
+  mShellHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
+  mShellVerticalResolution   = PcdGet32 (PcdSetupVideoVerticalResolution);
+  mShellModeColumn           = PcdGet32 (PcdSetupConOutColumn);
+  mShellModeRow              = PcdGet32 (PcdSetupConOutRow);
+
+  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;
+}
+
+/**
+  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 ();
+  }
+}
+
+/**
+  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);
+}
+
+/**
+  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 ();
+}
+
+/**
+  Connects Root Bridge.
+
+  @param[in] Recursive  Recursively connect controllers if TRUE
+ **/
+VOID
+ConnectRootBridge (
+  IN 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);
+  }
+}
+
+/**
+  Add console variable device paths.
+
+  @param[in] ConsoleType         ConIn or ConOut
+  @param[in] ConsoleDevicePath   Device path to be added
+**/
+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 = DuplicateDevicePath (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);
+
+  if (TempDevicePath != NULL) {
+    FreePool (TempDevicePath);
+  }
+}
+
+/**
+  This is the callback function for PCI ENUMERATION COMPLETE.
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsPciEnumCompleteCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  EFI_STATUS                Status;
+  VOID                      *ProtocolPointer;
+  EFI_DEVICE_PATH_PROTOCOL  *VarConOut;
+  EFI_DEVICE_PATH_PROTOCOL  *VarConIn;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
+  // if it is, we will skip it until real event is triggered
+  //
+  Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **)&ProtocolPointer);
+  if (EFI_SUCCESS != Status) {
+    return;
+  }
+
+  // gBS->CloseEvent (Event);
+
+  DEBUG ((DEBUG_INFO, "Event BdsPciEnumCompleteCallback callback starts\n"));
+
+  gBootMode = GetBootModeHob ();
+
+  //
+  // 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));
+      }
+    }
+  }
+
+  //
+  // Enumerate USB keyboard
+  //
+  EnumUsbKeyboard ();
+
+  //
+  // For trusted console it must be handled here.
+  //
+  UpdateGraphicConOut (TRUE);
+
+  //
+  // Register Boot Options
+  //
+  RegisterDefaultBootOption ();
+
+  //
+  // Register Static Hot keys
+  //
+  RegisterStaticHotkey ();
+
+  //
+  // Process Physical Preo
+  //
+  PERF_START_EX (NULL, "EventRec", NULL, AsmReadTsc (), 0x7010);
+  if (PcdGetBool (PcdTpm2Enable)) {
+    ProcessTcgPp ();
+    ProcessTcgMor ();
+  }
+
+  PERF_END_EX (NULL, "EventRec", NULL, AsmReadTsc (), 0x7011);
+
+  //
+  // Perform memory test
+  // We should make all UEFI memory and GCD information populated before ExitPmAuth.
+  // SMM may consume these information.
+  //
+  MemoryTest ((EXTENDMEM_COVERAGE_LEVEL)PcdGet32 (PcdPlatformMemoryCheckLevel));
+}
+
+/**
+  This is the callback function for Smm Ready To Lock.
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsSmmReadyToLockCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  VOID        *ProtocolPointer;
+  EFI_STATUS  Status;
+
+  //
+  // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
+  // if it is, we will skip it until real event is triggered
+  //
+  Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, (VOID **)&ProtocolPointer);
+  if (EFI_SUCCESS != Status) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO, "Event gEfiDxeSmmReadyToLockProtocolGuid callback starts\n"));
+
+  //
+  // Dispatch the deferred 3rd party images.
+  //
+  EfiBootManagerDispatchDeferredImages ();
+
+  //
+  // For non-trusted console it must be handled here.
+  //
+  UpdateGraphicConOut (FALSE);
+}
+
+/**
+  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[in]  Event   Pointer to this event
+  @param[in]  Context Event handler private data
+**/
+VOID
+EFIAPI
+BdsReadyToBootCallback (
+  IN  EFI_EVENT  Event,
+  IN  VOID       *Context
+  )
+{
+  DEBUG ((DEBUG_INFO, "BdsReadyToBootCallback\n"));
+
+  if (BootCurrentIsInternalShell ()) {
+    ChangeModeForInternalShell ();
+    EfiBootManagerConnectAllDefaultConsoles ();
+    gDS->Dispatch ();
+  }
+}
+
+/**
+  Before console after trusted console event callback
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsBeforeConsoleAfterTrustedConsoleCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  DEBUG ((DEBUG_INFO, "Event gBdsEventBeforeConsoleBeforeEndOfDxeGuid callback starts\n"));
+
+  //
+  // Connect Root Bridge to make PCI BAR resource allocated and all PciIo created
+  //
+  ConnectRootBridge (FALSE);
+}
+
+/**
+  Before console before end of DXE event callback
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsBeforeConsoleBeforeEndOfDxeGuidCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  DEBUG ((DEBUG_INFO, "Event gBdsBeforeConsoleBeforeEndOfDxeGuid callback starts\n"));
+}
+
+/**
+  Handles possible IPMI boot overrides by modifying the LoadOptions variable.
+  Uses sorting function installed in BootOptionPriorityProtocol if the protocol
+  is installed and a valid IPMI override is detected.
+
+  @retval  EFI_SUCCESS    Boot override successful, or not necessary.
+  @retval  EFI_NOT_FOUND  Attempted to override boot to an unsupported boot option.
+**/
+EFI_STATUS
+HandleIpmiBootOverride (
+  VOID
+  )
+{
+  UINT8                                        NvIpmiBootOverride;
+  UINT8                                        Index;
+  UINT8                                        CurrentIpmiBootOverride;
+  UINT8                                        *GetBootOptionsBuffer;
+  UINT8                                        *SetBootOptionsBuffer;
+  UINTN                                        BootOptionCount;
+  UINTN                                        DataSize;
+  IPMI_GET_BOOT_OPTIONS_REQUEST                BootOptionsRequest;
+  IPMI_GET_BOOT_OPTIONS_RESPONSE               *BootOptionsResponse;
+  IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5       *BootOptionsParameterData;
+  IPMI_SET_BOOT_OPTIONS_REQUEST                *SetBootOptionsRequest;
+  IPMI_SET_BOOT_OPTIONS_RESPONSE               SetBootOptionsResponse;
+  IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5       *SetBootOptionsParameterData;
+  EFI_BOOT_MANAGER_LOAD_OPTION                 *LoadOptionToManipulate;
+  EFI_BOOT_MANAGER_LOAD_OPTION                 *BootOptions;
+  EFI_STATUS                                   Status;
+  AMD_BOARD_BDS_BOOT_OPTION_PRIORITY_PROTOCOL  *BootOptionPriorityProtocol;
+  EFI_HANDLE                                   *BootPriorityHandles;
+  UINTN                                        BootPriorityCount;
+  UINTN                                        BootPriorityIndex;
+  BOOLEAN                                      ValidBootPriorityOverride;
+
+  ZeroMem (&BootOptionsRequest, sizeof (IPMI_GET_BOOT_OPTIONS_REQUEST));
+  ZeroMem (&SetBootOptionsResponse, sizeof (IPMI_SET_BOOT_OPTIONS_RESPONSE));
+
+  LoadOptionToManipulate    = NULL;
+  Status                    = EFI_SUCCESS;
+  ValidBootPriorityOverride = FALSE;
+  // setup buffers
+  GetBootOptionsBuffer = (UINT8 *)AllocateZeroPool (sizeof (BootOptionsResponse) + sizeof (IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5));
+  SetBootOptionsBuffer = (UINT8 *)AllocateZeroPool (sizeof (SetBootOptionsRequest) + sizeof (IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5));
+
+  // setup parameter data
+  BootOptionsRequest.ParameterSelector.Bits.ParameterSelector = IPMI_BOOT_OPTIONS_PARAMETER_BOOT_FLAGS;
+  BootOptionsResponse                                         = (IPMI_GET_BOOT_OPTIONS_RESPONSE *)&GetBootOptionsBuffer[0];
+  Status                                                      = IpmiGetSystemBootOptions (&BootOptionsRequest, BootOptionsResponse);
+  BootOptionsParameterData                                    = (IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5 *)BootOptionsResponse->ParameterData;
+
+  if (EFI_ERROR (Status)) {
+    Status = EFI_UNSUPPORTED;
+    goto end;
+  }
+
+  // setup SetBootOptions parameter data
+  SetBootOptionsRequest       = (IPMI_SET_BOOT_OPTIONS_REQUEST *)&SetBootOptionsBuffer[0];
+  SetBootOptionsParameterData = (IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5 *)SetBootOptionsRequest->ParameterData;
+
+  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+
+  // if received valid IPMI data, then override boot option
+  if (!BootOptionsResponse->ParameterValid.Bits.ParameterValid && BootOptionsParameterData->Data1.Bits.BootFlagValid) {
+    // get non volatile IpmiBootOverride variable
+    DataSize = sizeof (UINT8);
+    Status   = gRT->GetVariable (
+                      IPMI_BOOT_OVERRIDE_VAR_NAME,
+                      &gEfiCallerIdGuid,
+                      NULL,
+                      &DataSize,
+                      &NvIpmiBootOverride
+                      );
+    if (EFI_ERROR (Status)) {
+      NvIpmiBootOverride = IPMI_BOOT_DEVICE_SELECTOR_NO_OVERRIDE;
+    }
+
+    CurrentIpmiBootOverride = BootOptionsParameterData->Data2.Bits.BootDeviceSelector;
+
+    // Handle platform specific boot priority override
+    Status = gBS->LocateHandleBuffer (
+                    ByProtocol,
+                    &gAmdBoardBdsBootOptionPriorityProtocolGuid,
+                    NULL,
+                    &BootPriorityCount,
+                    &BootPriorityHandles
+                    );
+
+    if (!EFI_ERROR (Status)) {
+      for (BootPriorityIndex = 0; BootPriorityIndex < BootPriorityCount; BootPriorityIndex++) {
+        Status = gBS->HandleProtocol (
+                        BootPriorityHandles[BootPriorityIndex],
+                        &gAmdBoardBdsBootOptionPriorityProtocolGuid,
+                        (VOID **)&BootOptionPriorityProtocol
+                        );
+        if (!EFI_ERROR (Status) &&
+            (BootOptionPriorityProtocol->IpmiBootDeviceSelectorType == CurrentIpmiBootOverride))
+        {
+          DEBUG ((DEBUG_INFO, "Valid BootOptionPriority Override detected\n"));
+          ValidBootPriorityOverride = TRUE;
+          break;
+        }
+      }
+    }
+
+    if (CurrentIpmiBootOverride == IPMI_BOOT_DEVICE_SELECTOR_BIOS_SETUP) {
+      DEBUG ((DEBUG_INFO, "[Bds]BiosSetup option override detected via IPMI\n"));
+      // need to find boot option corresponding to BiosSetup
+      for (Index = 0; Index < BootOptionCount; Index++) {
+        if ((StrCmp (BootOptions[Index].Description, L"Enter Setup") == 0) && (BootOptions[Index].Attributes == (LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDEN))) {
+          LoadOptionToManipulate = &BootOptions[Index];
+        } else if (StrCmp (BootOptions[Index].Description, L"Enter Setup") == 0) {
+          // delete duplicate BiosSetup Menu option
+          EfiBootManagerDeleteLoadOptionVariable (BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
+        }
+      }
+
+      if (LoadOptionToManipulate == NULL) {
+        Status = EFI_UNSUPPORTED;
+        goto end;
+      }
+
+      // have Load option for bios setup, now update loadoptions
+      Status                              = EfiBootManagerDeleteLoadOptionVariable (LoadOptionToManipulate->OptionNumber, LoadOptionTypeBoot);
+      LoadOptionToManipulate->Attributes &= LOAD_OPTION_CATEGORY_BOOT;
+      LoadOptionToManipulate->Attributes |= (LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDEN);
+      Status                              = EfiBootManagerAddLoadOptionVariable (LoadOptionToManipulate, 0); // add back in loadoptions in 0th index (first option)
+    } else if (CurrentIpmiBootOverride == IPMI_BOOT_DEVICE_SELECTOR_PXE) {
+      DEBUG ((DEBUG_INFO, "[Bds]PXE option override detected via IPMI\n"));
+
+      if (ValidBootPriorityOverride) {
+        EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, BootOptionPriorityProtocol->Compare);
+      } else {
+        EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOptionPxePriority);
+      }
+    } else if (CurrentIpmiBootOverride == IPMI_BOOT_DEVICE_SELECTOR_HARDDRIVE) {
+      DEBUG ((DEBUG_INFO, "[Bds]HDD option override detected via IPMI\n"));
+      if (ValidBootPriorityOverride) {
+        EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, BootOptionPriorityProtocol->Compare);
+      } else {
+        EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOptionHddPriority);
+      }
+    } else if ((CurrentIpmiBootOverride == IPMI_BOOT_DEVICE_SELECTOR_NO_OVERRIDE) && (CurrentIpmiBootOverride != NvIpmiBootOverride)) {
+      // delete BiosSetup option corresponding to the override
+      Status = EfiBootManagerDeleteLoadOptionVariable (BootOptions[0].OptionNumber, LoadOptionTypeBoot);
+      // re sort boot options
+      EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOption);
+    }
+
+    // if Ipmi override not persistent, reset boot option to None and persistent to true
+    if (!BootOptionsParameterData->Data1.Bits.PersistentOptions) {
+      SetBootOptionsRequest->ParameterValid.Bits.ParameterSelector = IPMI_BOOT_OPTIONS_PARAMETER_BOOT_FLAGS;
+      CopyMem (SetBootOptionsParameterData, BootOptionsParameterData, sizeof (IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5));
+      SetBootOptionsParameterData->Data1.Bits.PersistentOptions  = 1;                                     // persistent
+      SetBootOptionsParameterData->Data2.Bits.BootDeviceSelector = IPMI_BOOT_DEVICE_SELECTOR_NO_OVERRIDE; // revert to no override
+      Status                                                     = IpmiSetSystemBootOptions (SetBootOptionsRequest, &SetBootOptionsResponse);
+    }
+
+    Status = gRT->SetVariable (
+                    IPMI_BOOT_OVERRIDE_VAR_NAME,
+                    &gEfiCallerIdGuid,
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                    sizeof (UINT8),
+                    &CurrentIpmiBootOverride
+                    );
+  }
+
+end:
+  // Free buffers
+  FreePool (GetBootOptionsBuffer);
+  FreePool (SetBootOptionsBuffer);
+  return Status;
+}
+
+/**
+  After console ready before boot option event callback.
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsAfterConsoleReadyBeforeBootOptionCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  EFI_BOOT_MODE  LocalBootMode;
+  EFI_STATUS     Status;
+  BOOLEAN        IsFirstBoot;
+  UINTN          DataSize;
+
+  DEBUG ((DEBUG_INFO, "Event gBdsAfterConsoleReadyBeforeBootOptionEvent callback starts\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
+      //
+      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.
+      //
+
+      //
+      // PXE boot option may appear after boot option enumeration
+      //
+
+      EfiBootManagerRefreshAllBootOption ();
+      DataSize = sizeof (BOOLEAN);
+      Status   = gRT->GetVariable (
+                        IS_FIRST_BOOT_VAR_NAME,
+                        &gEfiCallerIdGuid,
+                        NULL,
+                        &DataSize,
+                        &IsFirstBoot
+                        );
+      if (EFI_ERROR (Status)) {
+        //
+        // If can't find the variable, see it as the first boot
+        //
+        IsFirstBoot = TRUE;
+      }
+
+      if (IsFirstBoot) {
+        //
+        // In the first boot, sort the boot option
+        //
+        EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOption);
+        IsFirstBoot = FALSE;
+        Status      = gRT->SetVariable (
+                             IS_FIRST_BOOT_VAR_NAME,
+                             &gEfiCallerIdGuid,
+                             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                             sizeof (BOOLEAN),
+                             &IsFirstBoot
+                             );
+      }
+
+      break;
+  }
+
+  HandleIpmiBootOverride ();
+
+  Print (L"Press F2 for Setup, or F7 for BootMenu!\n");
+
+ #ifdef INTERNAL_IDS
+  PrintSocOpnInfo ();
+ #endif
+}
+
+#ifdef INTERNAL_IDS
+
+/**
+  Display CPU OPN on Splash screen After console ready.
+  @retval EFI_SUCCESS
+**/
+EFI_STATUS
+PrintSocOpnInfo (
+  IN  VOID
+  )
+{
+  CHAR16  OpnChar[(sizeof (UINT64) / sizeof (UINT8)) * (MSR_CPUID_NAME_STRING5 - MSR_CPUID_NAME_STRING0 + 1) + 1];
+  UINT32  Msr;
+  UINT64  Value;
+  UINTN   CharIndex;
+  UINTN   ByteIndex;
+
+  CharIndex = 0;
+  for (Msr = MSR_CPUID_NAME_STRING0; Msr <= MSR_CPUID_NAME_STRING5; Msr++) {
+    Value = AsmReadMsr64 (Msr);
+    for (ByteIndex = 0; ByteIndex < (sizeof (UINT64) / sizeof (UINT8)); ByteIndex++) {
+      OpnChar[CharIndex] = (Value & 0xFF);
+      CharIndex++;
+      Value = RShiftU64 (Value, 8);
+    }
+  }
+
+  OpnChar[CharIndex] = L'\0';
+
+  DEBUG ((DEBUG_INFO, "\nProcessor OPN: "));
+  DEBUG ((DEBUG_INFO, "%s\n", OpnChar));
+
+  Print (L"Processor OPN: ");
+  Print (OpnChar);
+  Print (L"\n\r");
+
+  return EFI_SUCCESS;
+}
+
+#endif
diff --git a/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
new file mode 100644
index 0000000000..23e834e332
--- /dev/null
+++ b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
@@ -0,0 +1,105 @@
+### @file
+# Module Information file for the Bds Hook Library.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (C) 2023- 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = BoardBdsHookLib
+  FILE_GUID                      = A500CFFB-26DA-4CB1-B214-EC16524C9733
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = DXE_DRIVER
+  LIBRARY_CLASS                  = BoardBdsHookLib|DXE_DRIVER
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  DevicePathLib
+  DxeServicesLib
+  DxeServicesTableLib
+  HiiLib
+  HobLib
+  IpmiCommandLib
+  IpmiLib
+  MemoryAllocationLib
+  PcdLib
+  PerformanceLib
+  PrintLib
+  SortLib
+  Tcg2PhysicalPresenceLib
+  TimerLib
+  UefiBootManagerLib
+  UefiBootServicesTableLib
+  UefiLib
+  UefiRuntimeServicesTableLib
+
+[Packages]
+  AmdMinBoardPkg/AmdMinBoardPkg.dec
+  BoardModulePkg/BoardModulePkg.dec
+  IpmiFeaturePkg/IpmiFeaturePkg.dec
+  ManageabilityPkg/ManageabilityPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  MinPlatformPkg/MinPlatformPkg.dec
+  SecurityPkg/SecurityPkg.dec
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand            ## PRODUCES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn                    ## PRODUCES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow                       ## PRODUCES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn               ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow                  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution    ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution       ## PRODUCES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution         ## PRODUCES
+  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut                   ## PRODUCES
+  gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly                  ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdPlatformMemoryCheckLevel         ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdShellFile                        ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdShellFileDesc                    ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdTpm2Enable                       ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleInputDevicePath    ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleOutputDevicePath   ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdTrustedStorageDevicePath         ## CONSUMES
+
+[Sources]
+  BoardBdsHook.h
+  BoardBdsHookLib.c
+  BoardBootOption.c
+  BoardMemoryTest.c
+
+[Protocols]
+  gAmdBoardBdsBootOptionPriorityProtocolGuid    ## CONSUMES
+  gEfiCpuIo2ProtocolGuid                        ## CONSUMES
+  gEfiDevicePathToTextProtocolGuid              ## CONSUMES
+  gEfiDiskInfoProtocolGuid                      ## CONSUMES
+  gEfiDxeSmmReadyToLockProtocolGuid
+  gEfiDxeSmmReadyToLockProtocolGuid             ## PRODUCES
+  gEfiFirmwareVolume2ProtocolGuid               ## CONSUMES
+  gEfiFormBrowser2ProtocolGuid                  ## CONSUMES
+  gEfiGenericMemTestProtocolGuid                ## CONSUMES
+  gEfiGenericMemTestProtocolGuid                ## CONSUMES
+  gEfiPciIoProtocolGuid                         ## CONSUMES
+  gEfiPciRootBridgeIoProtocolGuid               ## CONSUMES
+  gEfiSimpleTextInputExProtocolGuid             ## CONSUMES
+
+[Guids]
+  gBdsEventAfterConsoleReadyBeforeBootOptionGuid
+  gBdsEventBeforeConsoleAfterTrustedConsoleGuid
+  gBdsEventBeforeConsoleBeforeEndOfDxeGuid
+  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES
+  gEfiGlobalVariableGuid                        ## PRODUCES
+  gEfiMemoryOverwriteControlDataGuid            ## PRODUCES
+
+[Depex.common.DXE_DRIVER]
+  gEfiVariableArchProtocolGuid
+
+[Depex]
+  TRUE
diff --git a/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBootOption.c b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBootOption.c
new file mode 100644
index 0000000000..16a47c2f82
--- /dev/null
+++ b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBootOption.c
@@ -0,0 +1,754 @@
+/** @file
+  Driver for Platform Boot Options support.
+
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+  Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BoardBdsHook.h"
+
+EFI_GUID  gUefiShellFileGuid = { 0 };
+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 }
+};
+
+BOOLEAN    mContinueBoot  = FALSE;
+BOOLEAN    mBootMenuBoot  = FALSE;
+BOOLEAN    mPxeBoot       = FALSE;
+BOOLEAN    mHotKeypressed = FALSE;
+EFI_EVENT  HotKeyEvent    = NULL;
+
+UINTN  mBootMenuOptionNumber;
+UINTN  mSetupOptionNumber;
+
+/**
+  This function will create a SHELL BootOption to boot.
+
+  @return Shell Device path for booting.
+**/
+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_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;
+}
+
+/**
+  Create Boot option for passed Firmware Volume.
+
+  @param[in] FileGuid         FV file name to use in FvDevicePathNode
+  @param[in] Description      Description of the load option.
+  @param[in, out] BootOption  Pointer to the load option to be initialized.
+  @param[in] Attributes       Attributes of the load option.
+  @param[in] OptionalData     Optional data of the load option.
+  @param[in] OptionalDataSize Size of the optional data of the load option.
+
+  @retval EFI_SUCCESS           The load option was initialized successfully.
+  @retval EFI_INVALID_PARAMETER BootOption, Description or FileGuid is NULL.
+**/
+EFI_STATUS
+CreateFvBootOption (
+  IN EFI_GUID *FileGuid,
+  IN CHAR16 *Description,
+  IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *BootOption,
+  IN UINT32 Attributes,
+  IN UINT8 *OptionalData, OPTIONAL IN 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[in] Key    Pointer to the load option to be found.
+  @param[in] Array  Pointer to the array of load options to be found.
+  @param[in] 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;
+}
+
+/**
+  Registers a boot option.
+
+  @param[in] FileGuid               Boot file GUID
+  @param[in] Description            Boot option description
+  @param[in] Position               Position of the new load option to put in the ****Order variable.
+  @param[in] Attributes             Boot option attributes
+  @param[in] OptionalData           Optional data of the boot option.
+  @param[in] OptionalDataSize       Size of the optional data of the boot option
+
+  @return boot option number
+**/
+UINTN
+RegisterFvBootOption (
+  IN EFI_GUID *FileGuid,
+  IN CHAR16 *Description,
+  IN UINTN Position,
+  IN UINT32 Attributes,
+  IN UINT8 *OptionalData, OPTIONAL IN 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;
+}
+
+/**
+  Boot manager wait callback.
+
+  @param[in] TimeoutRemain The remaining timeout period
+**/
+VOID
+EFIAPI
+PlatformBootManagerWaitCallback (
+  IN 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);
+    }
+  }
+}
+
+/**
+   Registers default boot option.
+**/
+VOID
+RegisterDefaultBootOption (
+  VOID
+  )
+{
+  UINT16  *ShellData;
+  UINT32  ShellDataSize;
+
+  ShellData     = NULL;
+  ShellDataSize = 0;
+  CopyMem (&gUefiShellFileGuid, PcdGetPtr (PcdShellFile), sizeof (GUID));
+  RegisterFvBootOption (&gUefiShellFileGuid, (CHAR16 *)PcdGetPtr (PcdShellFileDesc), (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));
+  }
+
+  //
+  // Boot Manager Menu
+  //
+  mSetupOptionNumber = RegisterFvBootOption (&mUiFile, L"Enter Setup", (UINTN)-1, LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDEN, NULL, 0);
+}
+
+/**
+  Registers/Unregisters boot option hotkey.
+
+  @param[in] OptionNumber  The boot option number for the key option.
+  @param[in] Key           The key input
+  @param[in] Add           Flag to indicate to add or remove a key
+**/
+VOID
+RegisterBootOptionHotkey (
+  IN UINT16         OptionNumber,
+  IN EFI_INPUT_KEY  *Key,
+  IN 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);
+  }
+}
+
+/**
+  Detect key press callback.
+
+  @param[in] KeyData  The key data
+
+  @retval   EFI_SUCCESS
+**/
+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;
+
+  EnterSetup = FALSE;
+
+  //
+  // [Enter]
+  //
+  mContinueBoot = !EnterSetup;
+  if (mContinueBoot) {
+    Enter.ScanCode    = SCAN_NULL;
+    Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
+    EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
+  }
+
+  //
+  // [F2]
+  //
+  if (mSetupOptionNumber != LoadOptionNumberUnassigned) {
+    F2.Key.ScanCode            = SCAN_F2;
+    F2.Key.UnicodeChar         = CHAR_NULL;
+    F2.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;
+    F2.KeyState.KeyToggleState = 0;
+    RegisterBootOptionHotkey ((UINT16)mSetupOptionNumber, &F2.Key, TRUE);
+  }
+
+  //
+  // Register [F7] only when the mBootMenuOptionNumber is valid
+  //
+  if (mBootMenuOptionNumber != LoadOptionNumberUnassigned) {
+    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);
+  }
+}
+
+/**
+  Returns the boot option type of a device.
+
+  @param[in] DevicePath         The DevicePath whose boot option type is
+                                to be returned
+  @retval -1                    Device type not found
+  @retval > -1                  Device type found
+**/
+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.
+
+  @param[in] BootOption     Load option to get the priority value for
+  @retval
+    OptionType                 EFI
+    ------------------------------------
+    PXE                         2
+    DVD                         4
+    USB                         6
+    NVME                        7
+    HDD                         8
+    EFI Shell                   9
+    Others                      100
+
+**/
+UINTN
+BootOptionPriority (
+  IN 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, (CHAR16 *)PcdGetPtr (PcdShellFileDesc)) == 0) {
+    if (PcdGetBool (PcdBootToShellOnly)) {
+      return 0;
+    }
+
+    return 9;
+  }
+
+  if (StrCmp (BootOption->Description, UEFI_HARD_DRIVE_NAME) == 0) {
+    return 8;
+  }
+
+  return 100;
+}
+
+/**
+  Returns the priority number while giving PXE highest
+  priority.
+
+  @param[in] BootOption   Load option to get the priority value for
+  @retval
+    OptionType                 EFI
+    ------------------------------------
+    PXE                         2
+    DVD                         4
+    USB                         6
+    NVME                        7
+    HDD                         8
+    EFI Shell                   9
+    Others                      100
+**/
+UINTN
+PxeBootOptionPriority (
+  IN 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, (CHAR16 *)PcdGetPtr (PcdShellFileDesc)) == 0) {
+    if (PcdGetBool (PcdBootToShellOnly)) {
+      return 0;
+    }
+
+    return 9;
+  }
+
+  if (StrCmp (BootOption->Description, UEFI_HARD_DRIVE_NAME) == 0) {
+    return 8;
+  }
+
+  return 100;
+}
+
+/**
+  Returns the priority number while giving HDD, DVD, and NVME highest priority.
+
+  @param[in] BootOption Load option to get the priority value for
+  @retval
+    OptionType                 EFI
+    ------------------------------------
+    NVME, DVD, HDD              2
+    PXE                         4
+    USB                         6
+    HDD                         8
+    EFI Shell                   9
+    Others                      100
+**/
+UINTN
+HddBootOptionPriority (
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption
+  )
+{
+  //
+  // EFI boot options
+  //
+  switch (BootOptionType (BootOption->FilePath)) {
+    case MSG_SATA_DP:
+    case MSG_UFS_DP:
+    case MSG_NVME_NAMESPACE_DP:
+      return 2;
+
+    case MSG_ATAPI_DP:
+      return 3;
+
+    case MSG_MAC_ADDR_DP:
+    case MSG_VLAN_DP:
+    case MSG_IPv4_DP:
+    case MSG_IPv6_DP:
+      return 4;
+
+    case MSG_USB_DP:
+      return 6;
+  }
+
+  if (StrCmp (BootOption->Description, (CHAR16 *)PcdGetPtr (PcdShellFileDesc)) == 0) {
+    if (PcdGetBool (PcdBootToShellOnly)) {
+      return 0;
+    }
+
+    return 9;
+  }
+
+  if (StrCmp (BootOption->Description, UEFI_HARD_DRIVE_NAME) == 0) {
+    return 2;
+  }
+
+  return 100;
+}
+
+/**
+  Compares boot priorities of two boot options.
+
+  @param[in] Left       The left boot option
+  @param[in] Right      The right boot option
+
+  @retval           The difference between the Left and Right
+                    boot options
+ **/
+INTN
+EFIAPI
+CompareBootOption (
+  IN CONST VOID  *Left,
+  IN CONST VOID  *Right
+  )
+{
+  return BootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *)Left) -
+         BootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *)Right);
+}
+
+/**
+   Compares boot priorities of two boot options, while giving PXE the highest priority.
+
+  @param[in] Left       The left boot option
+  @param[in] Right      The right boot option
+
+  @retval           The difference between the Left and Right
+                    boot options
+ **/
+INTN
+EFIAPI
+CompareBootOptionPxePriority (
+  IN CONST VOID  *Left,
+  IN CONST VOID  *Right
+  )
+{
+  return PxeBootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *)Left) -
+         PxeBootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *)Right);
+}
+
+/**
+   Compares boot priorities of two boot options, while giving HDD the highest priority.
+
+  @param[in] Left       The left boot option
+  @param[in] Right      The right boot option
+
+  @retval           The difference between the Left and Right
+                    boot options
+ **/
+INTN
+EFIAPI
+CompareBootOptionHddPriority (
+  IN CONST VOID  *Left,
+  IN CONST VOID  *Right
+  )
+{
+  return HddBootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *)Left) -
+         HddBootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *)Right);
+}
diff --git a/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardMemoryTest.c b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardMemoryTest.c
new file mode 100644
index 0000000000..fff0ef2993
--- /dev/null
+++ b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardMemoryTest.c
@@ -0,0 +1,83 @@
+/** @file
+  Perform the platform memory test
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "BoardBdsHook.h"
+#include <Protocol/GenericMemoryTest.h>
+
+/**
+  Perform the memory test base on the memory test intensive level,
+  and update the memory resource.
+
+  @param[in]  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;
+  }
+
+  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;
+}
-- 
2.34.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118979): https://edk2.groups.io/g/devel/message/118979
Mute This Topic: https://groups.io/mt/106148095/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  parent reply	other threads:[~2024-05-17  3:49 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-17  3:49 [edk2-devel] [PATCH 0/5] AmdMinBoardPkg: AMD board specific modules Abdul Lateef Attar via groups.io
2024-05-17  3:49 ` [edk2-devel] [PATCH 1/5] AmdMinBoardPkg: Uncrustify PciHotPlug module Abdul Lateef Attar via groups.io
2024-05-17  3:49 ` [edk2-devel] [PATCH 2/5] AmdMinBoardPkg/Library: Uncrustify the Library module Abdul Lateef Attar via groups.io
2024-05-17  3:49 ` [edk2-devel] [PATCH 3/5] AmdMinBoardPkg: Implement BoardInitLib for PEI phase Abdul Lateef Attar via groups.io
2024-05-17  3:49 ` [edk2-devel] [PATCH 4/5] AmdMinBoardPkg: Implement BoardInitLib for DXE phase Abdul Lateef Attar via groups.io
2024-05-17  3:49 ` Abdul Lateef Attar via groups.io [this message]
2024-05-17  5:53 ` [edk2-devel] [PATCH 0/5] AmdMinBoardPkg: AMD board specific modules Chang, Abner via groups.io

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=dd61bee14aae29074834cf0214fd110671f0e14a.1715917637.git.AbdulLateef.Attar@amd.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox