[edk2-devel] [edk2-platforms] [PATCH 02/11] BoardModulePkg: Add BDS Hook Library

Nate DeSimone nathaniel.l.desimone at intel.com
Wed Dec 18 01:19:31 UTC 2019


Hi Prince,

Feedback inline.

Sat, Dec 14, 2019 at 01:32:28AM +0000, Agyeman, Prince wrote:
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2336
> 
> Added a generic board BDS hook library that implements
> BDS hook points as defined in the Minimum platform specification.
> 
> This library implements callbacks for the three MinPlatformPkg
> BDS event groups, namely gBdsEventBeforeConsoleAfterTrustedConsoleGuid,
> gBdsEventBeforeConsoleBeforeEndOfDxeGuid and
> gBdsEventAfterConsoleReadyBeforeBootOptionGuid.
> 
> This Library also implements callbacks for pre-existing event groups:
> gEfiEndOfDxeEventGroupGuid, gEfiPciEnumerationCompleteProtocolGuid,
> gEfiDxeSmmReadyToLockProtocolGuid.
> 
> These callbacks can be registered to their respective event groups,
> through other libraries or DXE drivers
> 
> Cc: Michael Kubacki <michael.a.kubacki at intel.com>
> Cc: Chasel Chiu <chasel.chiu at intel.com>
> Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>
> 
> Signed-off-by: Prince Agyeman <prince.agyeman at intel.com>
> ---
>  .../Include/Library/BoardBdsHookLib.h         |  100 ++
>  .../Library/BoardBdsHookLib/BoardBdsHook.h    |  211 +++
>  .../Library/BoardBdsHookLib/BoardBdsHookLib.c | 1390 +++++++++++++++++
>  .../BoardBdsHookLib/BoardBdsHookLib.inf       |   95 ++
>  .../Library/BoardBdsHookLib/BoardBootOption.c |  598 +++++++
>  .../Library/BoardBdsHookLib/BoardMemoryTest.c |   83 +
>  6 files changed, 2477 insertions(+)
>  create mode 100644 Platform/Intel/BoardModulePkg/Include/Library/BoardBdsHookLib.h
>  create mode 100644 Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHook.h
>  create mode 100644 Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHookLib.c
>  create mode 100644 Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
>  create mode 100644 Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBootOption.c
>  create mode 100644 Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardMemoryTest.c
> 
> diff --git a/Platform/Intel/BoardModulePkg/Include/Library/BoardBdsHookLib.h b/Platform/Intel/BoardModulePkg/Include/Library/BoardBdsHookLib.h
> new file mode 100644
> index 0000000000..ba351b7bf4
> --- /dev/null
> +++ b/Platform/Intel/BoardModulePkg/Include/Library/BoardBdsHookLib.h
> @@ -0,0 +1,100 @@
> +/** @file
> +Header file for BDS Hook Library
> +
> +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _BDS_HOOK_LIB_H_
> +#define _BDS_HOOK_LIB_H_

Please make the macros match the file name: _BOARD_BDS_HOOK_LIB_H_

> +
> +#include <Library/UefiLib.h>
> +
> +
> +/**
> +  This is the callback function for Bds Ready To Boot event.
> +
> +  @param  Event   Pointer to this event
> +  @param  Context Event hanlder 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/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHook.h b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHook.h
> new file mode 100644
> index 0000000000..748385499b
> --- /dev/null
> +++ b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHook.h
> @@ -0,0 +1,211 @@
> +/** @file
> +  Header file for BDS Hook Library
> +
> +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _BDS_HOOK_H_
> +#define _BDS_HOOK_H_

Please use the same macro name as the file name: _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>
> +
> +///
> +/// ConnectType
> +///
> +#define CONSOLE_OUT 0x00000001
> +#define STD_ERROR   0x00000002
> +#define CONSOLE_IN  0x00000004
> +#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
> +
> +extern EFI_GUID                  gUefiShellFileGuid;
> +extern EFI_BOOT_MODE             gBootMode;
> +
> +#define gPciRootBridge \
> +  { \
> +    { \
> +      ACPI_DEVICE_PATH, \
> +      ACPI_DP, \
> +      { \
> +        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
> +        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
> +      }, \
> +    }, \
> +    EISA_PNP_ID (0x0A03), \
> +    0 \
> +  }
> +
> +#define gEndEntire \
> +  { \
> +    END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { END_DEVICE_PATH_LENGTH, 0 } \
> +  }
> +
> +typedef struct {
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  UINTN                     ConnectType;
> +} BDS_CONSOLE_CONNECT_ENTRY;
> +
> +//
> +// Platform Root Bridge
> +//
> +typedef struct {
> +  ACPI_HID_DEVICE_PATH      PciRootBridge;
> +  EFI_DEVICE_PATH_PROTOCOL  End;
> +} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;
> +
> +//
> +// Below is the platform console device path
> +//
> +typedef struct {
> +  ACPI_HID_DEVICE_PATH      PciRootBridge;
> +  PCI_DEVICE_PATH           IsaBridge;
> +  ACPI_HID_DEVICE_PATH      Keyboard;
> +  EFI_DEVICE_PATH_PROTOCOL  End;
> +} PLATFORM_KEYBOARD_DEVICE_PATH;
> +
> +typedef struct {
> +  ACPI_HID_DEVICE_PATH      PciRootBridge;
> +  PCI_DEVICE_PATH           PciDevice;
> +  EFI_DEVICE_PATH_PROTOCOL  End;
> +} PLATFORM_ONBOARD_CONTROLLER_DEVICE_PATH;
> +
> +typedef struct {
> +  ACPI_HID_DEVICE_PATH      PciRootBridge;
> +  PCI_DEVICE_PATH           Pci0Device;
> +  EFI_DEVICE_PATH_PROTOCOL  End;
> +} PLATFORM_PEG_ROOT_CONTROLLER_DEVICE_PATH;
> +
> +typedef struct {
> +  ACPI_HID_DEVICE_PATH      PciRootBridge;
> +  PCI_DEVICE_PATH           PciBridge;
> +  PCI_DEVICE_PATH           PciDevice;
> +  EFI_DEVICE_PATH_PROTOCOL  End;
> +} PLATFORM_PCI_CONTROLLER_DEVICE_PATH;
> +
> +//
> +// Below is the boot option device path
> +//
> +
> +#define CLASS_HID           3
> +#define SUBCLASS_BOOT       1
> +#define PROTOCOL_KEYBOARD   1
> +
> +typedef struct {
> +  USB_CLASS_DEVICE_PATH           UsbClass;
> +  EFI_DEVICE_PATH_PROTOCOL        End;
> +} USB_CLASS_FORMAT_DEVICE_PATH;
> +
> +extern USB_CLASS_FORMAT_DEVICE_PATH              gUsbClassKeyboardDevicePath;
> +
> +//
> +// Platform BDS Functions
> +//
> +
> +
> +/**
> +  Perform the memory test base on the memory test intensive level,
> +  and update the memory resource.
> +
> +  @param  Level         The memory test intensive level.
> +
> +  @retval EFI_STATUS    Success test all the system memory and update
> +                        the memory resource
> +
> +**/
> +EFI_STATUS
> +MemoryTest (
> +  IN EXTENDMEM_COVERAGE_LEVEL Level
> +  );
> +
> +/**
> +  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 Left       The left boot option
> +  @param Right      The right boot option
> +
> +  @return           The difference between the Left and Right
> +                    boot options
> + **/
> +INTN
> +EFIAPI
> +CompareBootOption (
> +  CONST VOID  *Left,
> +  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
> +
> +  @param OptionNumber  The boot option number for the key option.
> +  @param Key           The the key input
> +  @param Add           Flag to indicate to add or remove a key
> +**/
> +VOID
> +RegisterDefaultBootOption (
> +  VOID
> +  );
> +
> +#endif
> diff --git a/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHookLib.c b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHookLib.c
> new file mode 100644
> index 0000000000..9d42a8c27f
> --- /dev/null
> +++ b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHookLib.c
> @@ -0,0 +1,1390 @@
> +/** @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>
> +  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 <Protocol/BlockIo.h>
> +#include <Protocol/UsbIo.h>
> +#include <Protocol/PciEnumerationComplete.h>
> +
> +#include "BoardBdsHook.h"
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_BOOT_MODE    gBootMode;
> +BOOLEAN                                        gPPRequireUIConfirm;
> +extern UINTN                                   mBootMenuOptionNumber;
> +
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = {
> +  {
> +    {
> +      MESSAGING_DEVICE_PATH,
> +      MSG_USB_CLASS_DP,
> +      {
> +        (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),
> +        (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
> +      }
> +    },
> +    0xffff,           // VendorId
> +    0xffff,           // ProductId
> +    CLASS_HID,        // DeviceClass
> +    SUBCLASS_BOOT,    // DeviceSubClass
> +    PROTOCOL_KEYBOARD // DeviceProtocol
> +  },
> +  gEndEntire
> +};
> +
> +
> +//
> +// BDS Platform Functions
> +//
> +BOOLEAN
> +IsMorBitSet (
> +  VOID
> +  )
> +{
> +  UINTN                     MorControl;
> +  EFI_STATUS                Status;
> +  UINTN                     DataSize;
> +
> +  //
> +  // Check if the MOR bit is set.
> +  //
> +  DataSize = sizeof (MorControl);
> +  Status = gRT->GetVariable (
> +                  MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
> +                  &gEfiMemoryOverwriteControlDataGuid,
> +                  NULL,
> +                  &DataSize,
> +                  &MorControl
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_INFO, " 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 Name           The device name.
> +  @param 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 Device  The device to be tested.
> +
> +  @retval TRUE   The device can be trusted.
> +  @retval FALSE  The device cannot be trusted.
> +**/
> +BOOLEAN
> +IsTrustedConsole (
> +  IN CONSOLE_TYPE              ConsoleType,
> +  IN EFI_DEVICE_PATH_PROTOCOL  *Device
> +  )
> +{
> +  VOID                      *TrustedConsoleDevicepath;
> +  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL  *Instance;
> +  UINTN                     Size;
> +  EFI_DEVICE_PATH_PROTOCOL  *ConsoleDevice;
> +
> +  if (Device == NULL) {
> +    return FALSE;
> +  }
> +
> +  ConsoleDevice = DuplicateDevicePath (Device);
> +
> +  TrustedConsoleDevicepath = NULL;
> +
> +  switch (ConsoleType) {
> +    case ConIn:
> +      TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
> +      break;
> +    case ConOut:
> +      //
> +      // Check GOP and remove last node
> +      //
> +      TempDevicePath = ConsoleDevice;
> +      while (!IsDevicePathEndType (TempDevicePath)) {
> +        if (DevicePathType (TempDevicePath) == ACPI_DEVICE_PATH &&
> +          DevicePathSubType (TempDevicePath) == ACPI_ADR_DP) {
> +          SetDevicePathEndNode (TempDevicePath);
> +          break;
> +        }
> +        TempDevicePath = NextDevicePathNode (TempDevicePath);
> +      }
> +
> +      TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
> +      break;
> +    default:
> +      ASSERT (FALSE);
> +      break;
> +  }
> +
> +  TempDevicePath = TrustedConsoleDevicepath;
> +  do {
> +    Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
> +    if (Instance == NULL) {
> +      break;
> +    }
> +
> +    if (CompareMem (ConsoleDevice, Instance, Size - END_DEVICE_PATH_LENGTH) == 0) {
> +      FreePool (Instance);
> +      FreePool (ConsoleDevice);
> +      return TRUE;
> +    }
> +
> +    FreePool (Instance);
> +  } while (TempDevicePath != NULL);
> +
> +  FreePool (ConsoleDevice);
> +
> +  return FALSE;
> +}
> +
> +
> +/**
> +  Return whether the USB device path is in a short form.
> +
> +  @param 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 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 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 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 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 DevicePath  The device path to be removed
> +  @param Gop         The device path to be added.
> +
> +  @retval Return     The updated device path.
> +**/
> +EFI_DEVICE_PATH_PROTOCOL *
> +UpdateGopDevicePath (
> +  EFI_DEVICE_PATH_PROTOCOL *DevicePath,
> +  EFI_DEVICE_PATH_PROTOCOL *Gop
> +  )
> +{
> +  UINTN                    Size;
> +  UINTN                    GopSize;
> +  EFI_DEVICE_PATH_PROTOCOL *Temp;
> +  EFI_DEVICE_PATH_PROTOCOL *Return;
> +  EFI_DEVICE_PATH_PROTOCOL *Instance;
> +  BOOLEAN                  Exist;
> +
> +  Exist = FALSE;
> +  Return = NULL;
> +  GopSize = GetDevicePathSize (Gop);
> +  do {
> +    Instance = GetNextDevicePathInstance (&DevicePath, &Size);
> +    if (Instance == NULL) {
> +      break;
> +    }
> +    if (!IsGopDevicePath (Instance) ||
> +        (Size == GopSize && CompareMem (Instance, Gop, GopSize) == 0)
> +       ) {
> +      if (Size == GopSize && CompareMem (Instance, Gop, GopSize) == 0) {
> +        Exist = TRUE;
> +      }
> +      Temp = Return;
> +      Return = AppendDevicePathInstance (Return, Instance);
> +      if (Temp != NULL) {
> +        FreePool (Temp);
> +      }
> +    }
> +    FreePool (Instance);
> +  } while (DevicePath != NULL);
> +
> +  if (!Exist) {
> +    Temp = Return;
> +    Return = AppendDevicePathInstance (Return, Gop);
> +    if (Temp != NULL) {
> +      FreePool (Temp);
> +    }
> +  }
> +  return Return;
> +}
> +
> +
> +/**
> +  Get Graphics Controller Handle.
> +
> +  @param NeedTrustedConsole    The flag to determine if trusted console
> +  or non trusted console should be returned
> +
> +  @retval NULL                  Console not found
> +  @retval PciHandles            Successfully located
> +**/
> +EFI_HANDLE
> +EFIAPI
> +GetGraphicsController (
> +  IN BOOLEAN    NeedTrustedConsole
> +  )
> +{
> +  EFI_STATUS                Status;
> +  UINTN                     Index;
> +  EFI_HANDLE                *PciHandles;
> +  UINTN                     PciHandlesSize;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiPciIoProtocolGuid,
> +                  NULL,
> +                  &PciHandlesSize,
> +                  &PciHandles
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return NULL;
> +  }
> +
> +  for (Index = 0; Index < PciHandlesSize; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    PciHandles[Index],
> +                    &gEfiDevicePathProtocolGuid,
> +                    (VOID **) &DevicePath
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +    if (!IsVgaHandle (PciHandles[Index])) {
> +      continue;
> +    }
> +    if ((NeedTrustedConsole && IsTrustedConsole (ConOut, DevicePath)) ||
> +        ((!NeedTrustedConsole) && (!IsTrustedConsole (ConOut, DevicePath)))) {
> +      return PciHandles[Index];
> +    }
> +  }
> +
> +  return NULL;
> +}
> +
> +
> +/**
> +  Updates Graphic ConOut variable.
> +
> +  @param NeedTrustedConsole    The flag that determines if trusted console
> +  or non trusted console should be returned
> +**/
> +VOID
> +UpdateGraphicConOut (
> +  IN BOOLEAN    NeedTrustedConsole
> +  )
> +{
> +  EFI_HANDLE                          GraphicsControllerHandle;
> +  EFI_DEVICE_PATH_PROTOCOL            *GopDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL            *ConOutDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL            *UpdatedConOutDevicePath;
> +
> +  //
> +  // Update ConOut variable
> +  //
> +  GraphicsControllerHandle = GetGraphicsController (NeedTrustedConsole);
> +  if (GraphicsControllerHandle != NULL) {
> +    //
> +    // Connect the GOP driver
> +    //
> +    gBS->ConnectController (GraphicsControllerHandle, NULL, NULL, TRUE);
> +
> +    //
> +    // Get the GOP device path
> +    // NOTE: We may get a device path that contains Controller node in it.
> +    //
> +    GopDevicePath = EfiBootManagerGetGopDevicePath (GraphicsControllerHandle);
> +    if (GopDevicePath != NULL) {
> +      GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConOutDevicePath, NULL);
> +      UpdatedConOutDevicePath = UpdateGopDevicePath (ConOutDevicePath, GopDevicePath);
> +      if (ConOutDevicePath != NULL) {
> +        FreePool (ConOutDevicePath);
> +      }
> +      FreePool (GopDevicePath);
> +      gRT->SetVariable (
> +                      L"ConOut",
> +                      &gEfiGlobalVariableGuid,
> +                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                      GetDevicePathSize (UpdatedConOutDevicePath),
> +                      UpdatedConOutDevicePath
> +                      );
> +    }
> +  }
> +}
> +
> +
> +/**
> +  The function connects the trusted consoles.
> +**/
> +VOID
> +ConnectTrustedConsole (
> +  VOID
> +  )
> +{
> +  EFI_DEVICE_PATH_PROTOCOL     *Consoles;
> +  EFI_DEVICE_PATH_PROTOCOL     *TempDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL     *Instance;
> +  EFI_DEVICE_PATH_PROTOCOL     *Next;
> +  UINTN                        Size;
> +  UINTN                        Index;
> +  EFI_HANDLE                   Handle;
> +  EFI_STATUS                   Status;
> +  CHAR16                       *ConsoleVar[] = {L"ConIn", L"ConOut"};
> +  VOID                         *TrustedConsoleDevicepath;
> +
> +  TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
> +  DumpDevicePath (L"TrustedConsoleIn", TrustedConsoleDevicepath);
> +  TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
> +  DumpDevicePath (L"TrustedConsoleOut", TrustedConsoleDevicepath);
> +
> +  for (Index = 0; Index < sizeof (ConsoleVar) / sizeof (ConsoleVar[0]); Index++) {
> +
> +    GetEfiGlobalVariable2 (ConsoleVar[Index], (VOID **)&Consoles, NULL);
> +
> +    TempDevicePath = Consoles;
> +    do {
> +      Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
> +      if (Instance == NULL) {
> +        break;
> +      }
> +      if (IsTrustedConsole (Index, Instance)) {
> +        if (IsUsbShortForm (Instance)) {
> +          ConnectUsbShortFormDevicePath (Instance);
> +        } else {
> +          for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {
> +            if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) {
> +              break;
> +            } else if (DevicePathType (Next) == HARDWARE_DEVICE_PATH &&
> +                       DevicePathSubType (Next) == HW_CONTROLLER_DP &&
> +                       DevicePathType (NextDevicePathNode (Next)) == ACPI_DEVICE_PATH &&
> +                       DevicePathSubType (NextDevicePathNode (Next)) == ACPI_ADR_DP
> +                       ) {
> +              break;
> +            }
> +          }
> +          if (!IsDevicePathEnd (Next)) {
> +            SetDevicePathEndNode (Next);
> +            Status = EfiBootManagerConnectDevicePath (Instance, &Handle);
> +            if (!EFI_ERROR (Status)) {
> +              gBS->ConnectController (Handle, NULL, NULL, TRUE);
> +            }
> +          } else {
> +            EfiBootManagerConnectDevicePath (Instance, NULL);
> +          }
> +        }
> +      }
> +      FreePool (Instance);
> +    } while (TempDevicePath != NULL);
> +
> +    if (Consoles != NULL) {
> +      FreePool (Consoles);
> +    }
> +  }
> +}
> +
> +
> +/**
> +  The function connects the trusted Storages.
> +**/
> +VOID
> +ConnectTrustedStorage (
> +  VOID
> +  )
> +{
> +  VOID                      *TrustedStorageDevicepath;
> +  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL  *Instance;
> +  UINTN                     Size;
> +  EFI_DEVICE_PATH_PROTOCOL  *TempStorageDevicePath;
> +  EFI_STATUS                Status;
> +  EFI_HANDLE                DeviceHandle;
> +
> +  TrustedStorageDevicepath = PcdGetPtr (PcdTrustedStorageDevicePath);
> +  DumpDevicePath (L"TrustedStorage", TrustedStorageDevicepath);
> +
> +  TempDevicePath = TrustedStorageDevicepath;
> +  do {
> +    Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
> +    if (Instance == NULL) {
> +      break;
> +    }
> +
> +    EfiBootManagerConnectDevicePath (Instance, NULL);
> +
> +    TempStorageDevicePath = Instance;
> +
> +    Status = gBS->LocateDevicePath (
> +                    &gEfiDevicePathProtocolGuid,
> +                    &TempStorageDevicePath,
> +                    &DeviceHandle
> +                    );
> +    if (!EFI_ERROR (Status)) {
> +      gBS->ConnectController (DeviceHandle, NULL, NULL, FALSE);
> +    }
> +
> +    FreePool (Instance);
> +  } while (TempDevicePath != NULL);
> +}
> +
> +
> +/**
> +  Check if current BootCurrent variable is internal shell boot option.
> +
> +  @retval  TRUE         BootCurrent is internal shell.
> +  @retval  FALSE        BootCurrent is not internal shell.
> +**/
> +BOOLEAN
> +BootCurrentIsInternalShell (
> +  VOID
> +  )
> +{
> +  UINTN                         VarSize;
> +  UINT16                        BootCurrent;
> +  CHAR16                        BootOptionName[16];
> +  UINT8                         *BootOption;
> +  UINT8                         *Ptr;
> +  BOOLEAN                       Result;
> +  EFI_STATUS                    Status;
> +  EFI_DEVICE_PATH_PROTOCOL      *TempDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL      *LastDeviceNode;
> +  EFI_GUID                      *GuidPoint;
> +
> +  BootOption = NULL;
> +  Result     = FALSE;
> +
> +  //
> +  // Get BootCurrent variable
> +  //
> +  VarSize = sizeof (UINT16);
> +  Status = gRT->GetVariable (
> +                  L"BootCurrent",
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &VarSize,
> +                  &BootCurrent
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Create boot option Bootxxxx from BootCurrent
> +  //
> +  UnicodeSPrint (BootOptionName, sizeof(BootOptionName), L"Boot%04X", BootCurrent);
> +
> +  GetEfiGlobalVariable2 (BootOptionName, (VOID **) &BootOption, &VarSize);
> +  if (BootOption == NULL || VarSize == 0) {
> +    return FALSE;
> +  }
> +
> +  Ptr = BootOption;
> +  Ptr += sizeof (UINT32);
> +  Ptr += sizeof (UINT16);
> +  Ptr += StrSize ((CHAR16 *) Ptr);
> +  TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
> +  LastDeviceNode = TempDevicePath;
> +  while (!IsDevicePathEnd (TempDevicePath)) {
> +    LastDeviceNode = TempDevicePath;
> +    TempDevicePath = NextDevicePathNode (TempDevicePath);
> +  }
> +  GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (
> +                (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode
> +                );
> +  if ((GuidPoint != NULL) &&
> +    ((CompareGuid (GuidPoint, &gUefiShellFileGuid)))) {
> +    //
> +    // if this option is internal shell, return TRUE
> +    //
> +    Result = TRUE;
> +  }
> +
> +  if (BootOption != NULL) {
> +    FreePool (BootOption);
> +    BootOption = NULL;
> +  }
> +
> +  return Result;
> +}
> +
> +/**
> +  This function will change video resolution and text mode
> +  for internl shell when internal shell is launched.
> +
> +  @param   None.
> +
> +  @retval  EFI_SUCCESS  Mode is changed successfully.
> +  @retval  Others       Mode failed to changed.
> +**/
> +EFI_STATUS
> +EFIAPI
> +ChangeModeForInternalShell (
> +  VOID
> +  )
> +{
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL          *GraphicsOutput;
> +  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL       *SimpleTextOut;
> +  UINTN                                 SizeOfInfo;
> +  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
> +  UINT32                                MaxGopMode;
> +  UINT32                                MaxTextMode;
> +  UINT32                                ModeNumber;
> +  UINTN                                 HandleCount;
> +  EFI_HANDLE                            *HandleBuffer;
> +  EFI_STATUS                            Status;
> +  UINTN                                 Index;
> +  UINTN                                 CurrentColumn;
> +  UINTN                                 CurrentRow;
> +
> +  //
> +  // 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 ();
> +}
> +
> +
> +/**
> +  The function is to consider the boot order which is not in our expectation.
> +  In the case that we need to re-sort the boot option.
> +
> +  @retval  TRUE         Need to sort Boot Option.
> +  @retval  FALSE        Don't need to sort Boot Option.
> +**/
> +BOOLEAN
> +IsNeedSortBootOption (
> +  VOID
> +  )
> +{
> +  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions;
> +  UINTN                         BootOptionCount;
> +
> +  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
> +
> +  //
> +  // If setup is the first priority in boot option, we need to sort boot option.
> +  //
> +  if ((BootOptionCount > 1) &&
> +    (((StrnCmp (BootOptions->Description, L"Enter Setup", StrLen (L"Enter Setup"))) == 0) ||
> +    ((StrnCmp (BootOptions->Description, L"BootManagerMenuApp", StrLen (L"BootManagerMenuApp"))) == 0))) {
> +    return TRUE;
> +  }
> +
> +  return FALSE;
> +}
> +
> +
> +/**
> +  Connects Root Bridge
> + **/
> +VOID
> +ConnectRootBridge (
> +  BOOLEAN Recursive
> +  )
> +{
> +  UINTN                            RootBridgeHandleCount;
> +  EFI_HANDLE                       *RootBridgeHandleBuffer;
> +  UINTN                            RootBridgeIndex;
> +
> +  RootBridgeHandleCount = 0;
> +  gBS->LocateHandleBuffer (
> +         ByProtocol,
> +         &gEfiPciRootBridgeIoProtocolGuid,
> +         NULL,
> +         &RootBridgeHandleCount,
> +         &RootBridgeHandleBuffer
> +         );
> +  for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {
> +    gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, Recursive);
> +  }
> +}
> +
> +VOID
> +AddConsoleVariable (
> +  IN CONSOLE_TYPE              ConsoleType,
> +  IN EFI_DEVICE_PATH           *ConsoleDevicePath
> +  )
> +{
> +  EFI_DEVICE_PATH           *TempDevicePath;
> +  EFI_DEVICE_PATH           *Instance;
> +  UINTN                     Size;
> +  EFI_HANDLE                GraphicsControllerHandle;
> +  EFI_DEVICE_PATH           *GopDevicePath;
> +
> +  TempDevicePath = ConsoleDevicePath;
> +  do {
> +    Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
> +    if (Instance == NULL) {
> +      break;
> +    }
> +
> +    switch (ConsoleType) {
> +      case ConIn:
> +        if (IsUsbShortForm (Instance)) {
> +          //
> +          // Append Usb Keyboard short form DevicePath into "ConInDev"
> +          //
> +          EfiBootManagerUpdateConsoleVariable (ConInDev, Instance, NULL);
> +        }
> +        EfiBootManagerUpdateConsoleVariable (ConsoleType, Instance, NULL);
> +        break;
> +      case ConOut:
> +        GraphicsControllerHandle = IsVideoController (Instance);
> +        if (GraphicsControllerHandle == NULL) {
> +          EfiBootManagerUpdateConsoleVariable (ConsoleType, Instance, NULL);
> +        } else {
> +          //
> +          // Connect the GOP driver
> +          //
> +          gBS->ConnectController (GraphicsControllerHandle, NULL, NULL, TRUE);
> +          //
> +          // Get the GOP device path
> +          // NOTE: We may get a device path that contains Controller node in it.
> +          //
> +          GopDevicePath = EfiBootManagerGetGopDevicePath (GraphicsControllerHandle);
> +          if (GopDevicePath != NULL) {
> +            EfiBootManagerUpdateConsoleVariable (ConsoleType, GopDevicePath, NULL);
> +          }
> +        }
> +        break;
> +      default:
> +        ASSERT(FALSE);
> +        break;
> +    }
> +
> +    FreePool (Instance);
> +  } while (TempDevicePath != NULL);
> +}
> +
> +
> +/**
> +  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 ();
> +
> +  //
> +  // Connect Root Bridge to make PCI BAR resource allocated and all PciIo created
> +  //
> +  ConnectRootBridge (FALSE);
> +
> +  //
> +  // Fill ConIn/ConOut in Full Configuration boot mode
> +  //
> +  DEBUG ((DEBUG_INFO, "PlatformBootManagerInit - %x\n", gBootMode));
> +
> +
> +  if (gBootMode == BOOT_WITH_FULL_CONFIGURATION ||
> +      gBootMode == BOOT_WITH_DEFAULT_SETTINGS ||
> +      gBootMode == BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS ||
> +      gBootMode == BOOT_IN_RECOVERY_MODE) {
> +
> +    GetEfiGlobalVariable2 (L"ConOut", (VOID **)&VarConOut, NULL);
> +    if (VarConOut != NULL) {
> +      FreePool (VarConOut);
> +    }
> +
> +    GetEfiGlobalVariable2 (L"ConIn", (VOID **)&VarConIn, NULL);
> +    if (VarConIn  != NULL) {
> +      FreePool (VarConIn);
> +    }
> +
> +    //
> +    // Only fill ConIn/ConOut when ConIn/ConOut is empty because we may drop to Full Configuration boot mode in non-first boot
> +    //
> +    if (VarConOut == NULL || VarConIn == NULL) {
> +      if (PcdGetSize (PcdTrustedConsoleOutputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
> +        AddConsoleVariable (ConOut, PcdGetPtr (PcdTrustedConsoleOutputDevicePath));
> +      }
> +      if (PcdGetSize (PcdTrustedConsoleInputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
> +        AddConsoleVariable (ConIn, PcdGetPtr (PcdTrustedConsoleInputDevicePath));
> +      }
> +    }
> +  }
> +
> +}
> +
> +/**
> +  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  Event   Pointer to this event
> +  @param  Context Event hanlder private data
> +
> +  @retval None.
> +**/
> +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
> +BdsBeforeConsoleAfterTrustedConsoleCallback (
> +  IN EFI_EVENT          Event,
> +  IN VOID               *Context
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "Event gBdsEventBeforeConsoleBeforeEndOfDxeGuid callback starts\n"));
> +
> +  //
> +  // 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));
> +}
> +
> +
> +/**
> +  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
> +BdsBeforeConsoleBeforeEndOfDxeGuidCallback (
> +  IN EFI_EVENT          Event,
> +  IN VOID               *Context
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "Event gBdsBeforeConsoleBeforeEndOfDxeGuid callback starts\n"));
> +
> +}
> +
> +
> +/**
> +  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
> +BdsAfterConsoleReadyBeforeBootOptionCallback (
> +  IN EFI_EVENT          Event,
> +  IN VOID               *Context
> +  )
> +{
> +  EFI_BOOT_MODE                 LocalBootMode;
> +
> +  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
> +      //
> +      break;
> +  }
> +
> +  Print (L"Press F7 for BootMenu!\n");
> +
> +  EfiBootManagerRefreshAllBootOption ();
> +
> +  if (IsNeedSortBootOption()) {
> +    EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOption);
> +  }
> +}
> diff --git a/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
> new file mode 100644
> index 0000000000..69f3fcb552
> --- /dev/null
> +++ b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
> @@ -0,0 +1,95 @@
> +### @file
> +# Module Information file for the Bds Hook Library.
> +#
> +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +###
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010017
> +  BASE_NAME                      = BoardBdsHookLib
> +  FILE_GUID                      = 649A7502-7301-4E3A-A99B-EA91AD6DD7A8
> +  VERSION_STRING                 = 1.0
> +  MODULE_TYPE                    = DXE_DRIVER
> +  LIBRARY_CLASS                  = BoardBdsHookLib|DXE_DRIVER
> +
> +[LibraryClasses]
> +  BaseLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  BaseMemoryLib
> +  DebugLib
> +  PcdLib
> +  PrintLib
> +  DevicePathLib
> +  UefiLib
> +  HobLib
> +  DxeServicesLib
> +  DxeServicesTableLib
> +  HiiLib
> +  UefiBootManagerLib
> +  PerformanceLib
> +  TimerLib
> +  Tcg2PhysicalPresenceLib
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  SecurityPkg/SecurityPkg.dec
> +  MinPlatformPkg/MinPlatformPkg.dec
> +  BoardModulePkg/BoardModulePkg.dec
> +
> +[Pcd]
> +  gMinPlatformPkgTokenSpaceGuid.PcdTpm2Enable                       ## CONSUMES
> +  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut                   ## PRODUCES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution       ## PRODUCES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution         ## PRODUCES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow                       ## PRODUCES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn                    ## PRODUCES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn               ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow                  ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution  ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution    ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand            ## PRODUCES
> +  gMinPlatformPkgTokenSpaceGuid.PcdPlatformMemoryCheckLevel         ## CONSUMES
> +  gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly                  ## CONSUMES
> +  gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleInputDevicePath    ## CONSUMES
> +  gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleOutputDevicePath   ## CONSUMES
> +  gMinPlatformPkgTokenSpaceGuid.PcdTrustedStorageDevicePath         ## CONSUMES
> +
> +[Sources]
> +  BoardBdsHook.h
> +  BoardBdsHookLib.c
> +  BoardMemoryTest.c
> +  BoardBootOption.c
> +
> +[Protocols]
> +  gEfiPciRootBridgeIoProtocolGuid               ## CONSUMES
> +  gEfiPciIoProtocolGuid                         ## CONSUMES
> +  gEfiCpuIo2ProtocolGuid                        ## CONSUMES
> +  gEfiDxeSmmReadyToLockProtocolGuid             ## PRODUCES
> +  gEfiGenericMemTestProtocolGuid                ## CONSUMES
> +  gEfiDiskInfoProtocolGuid                      ## CONSUMES
> +  gEfiDevicePathToTextProtocolGuid              ## CONSUMES
> +  gEfiSimpleTextInputExProtocolGuid             ## CONSUMES
> +  gEfiFirmwareVolume2ProtocolGuid               ## CONSUMES
> +  gEfiFormBrowser2ProtocolGuid                  ## CONSUMES
> +  gEfiGenericMemTestProtocolGuid                ## CONSUMES
> +  gEfiDxeSmmReadyToLockProtocolGuid
> +
> +[Guids]
> +  gEfiGlobalVariableGuid                        ## PRODUCES
> +  gEfiMemoryOverwriteControlDataGuid            ## PRODUCES
> +  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES
> +  gBdsEventBeforeConsoleAfterTrustedConsoleGuid
> +  gBdsEventBeforeConsoleBeforeEndOfDxeGuid
> +  gBdsEventAfterConsoleReadyBeforeBootOptionGuid
> +
> +[Depex.common.DXE_DRIVER]
> +  gEfiVariableArchProtocolGuid
> +
> +[Depex]
> +  TRUE
> diff --git a/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBootOption.c b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBootOption.c
> new file mode 100644
> index 0000000000..87138bdd79
> --- /dev/null
> +++ b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBootOption.c
> @@ -0,0 +1,598 @@
> +/** @file
> +  Driver for Platform Boot Options support.
> +
> +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "BoardBdsHook.h"
> +
> +BOOLEAN    mContinueBoot  = FALSE;
> +BOOLEAN    mBootMenuBoot  = FALSE;
> +BOOLEAN    mPxeBoot       = FALSE;
> +BOOLEAN    mHotKeypressed = FALSE;
> +EFI_EVENT  HotKeyEvent    = NULL;
> +
> +UINTN      mBootMenuOptionNumber;
> +
> +
> +/**
> +  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;
> +}
> +
> +
> +EFI_STATUS
> +CreateFvBootOption (
> +  EFI_GUID                     *FileGuid,
> +  CHAR16                       *Description,
> +  EFI_BOOT_MANAGER_LOAD_OPTION *BootOption,
> +  UINT32                       Attributes,
> +  UINT8                        *OptionalData,    OPTIONAL
> +  UINT32                       OptionalDataSize
> +  )
> +{
> +  EFI_STATUS                         Status;
> +  EFI_DEVICE_PATH_PROTOCOL           *DevicePath;
> +  EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;
> +  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;
> +  EFI_FIRMWARE_VOLUME2_PROTOCOL      *Fv;
> +  UINT32                             AuthenticationStatus;
> +  VOID                               *Buffer;
> +  UINTN                              Size;
> +
> +  if ((BootOption == NULL) || (FileGuid == NULL) || (Description == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
> +
> +  if (!CompareGuid (&gUefiShellFileGuid, FileGuid)) {
> +    Status = gBS->HandleProtocol (
> +                    gImageHandle,
> +                    &gEfiLoadedImageProtocolGuid,
> +                    (VOID **) &LoadedImage
> +                    );
> +    if (!EFI_ERROR (Status)) {
> +      Status = gBS->HandleProtocol (
> +                      LoadedImage->DeviceHandle,
> +                      &gEfiFirmwareVolume2ProtocolGuid,
> +                      (VOID **) &Fv
> +                      );
> +      if (!EFI_ERROR (Status)) {
> +        Buffer  = NULL;
> +        Size    = 0;
> +        Status  = Fv->ReadSection (
> +                        Fv,
> +                        FileGuid,
> +                        EFI_SECTION_PE32,
> +                        0,
> +                        &Buffer,
> +                        &Size,
> +                        &AuthenticationStatus
> +                        );
> +        if (Buffer != NULL) {
> +          FreePool (Buffer);
> +        }
> +      }
> +    }
> +    if (EFI_ERROR (Status)) {
> +      return EFI_NOT_FOUND;
> +    }
> +
> +    DevicePath = AppendDevicePathNode (
> +                   DevicePathFromHandle (LoadedImage->DeviceHandle),
> +                   (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
> +                   );
> +  } else {
> +    DevicePath = AppendDevicePathNode (
> +                   BdsCreateShellDevicePath (),
> +                   (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
> +                   );
> +  }
> +
> +  Status = EfiBootManagerInitializeLoadOption (
> +             BootOption,
> +             LoadOptionNumberUnassigned,
> +             LoadOptionTypeBoot,
> +             Attributes,
> +             Description,
> +             DevicePath,
> +             OptionalData,
> +             OptionalDataSize
> +             );
> +  FreePool (DevicePath);
> +  return Status;
> +}
> +
> +EFI_GUID mUiFile = {
> +  0x462CAA21, 0x7614, 0x4503, { 0x83, 0x6E, 0x8A, 0xB6, 0xF4, 0x66, 0x23, 0x31 }
> +};
> +EFI_GUID mBootMenuFile = {
> +  0xEEC25BDC, 0x67F2, 0x4D95, { 0xB1, 0xD5, 0xF8, 0x1B, 0x20, 0x39, 0xD1, 0x1D }
> +};
> +
> +
> +/**
> +  Return the index of the load option in the load option array.
> +
> +  The function consider two load options are equal when the
> +  OptionType, Attributes, Description, FilePath and OptionalData are equal.
> +
> +  @param Key    Pointer to the load option to be found.
> +  @param Array  Pointer to the array of load options to be found.
> +  @param Count  Number of entries in the Array.
> +
> +  @retval -1          Key wasn't found in the Array.
> +  @retval 0 ~ Count-1 The index of the Key in the Array.
> +**/
> +INTN
> +PlatformFindLoadOption (
> +  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
> +  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
> +  IN UINTN                              Count
> +  )
> +{
> +  UINTN                             Index;
> +
> +  for (Index = 0; Index < Count; Index++) {
> +    if ((Key->OptionType == Array[Index].OptionType) &&
> +        (Key->Attributes == Array[Index].Attributes) &&
> +        (StrCmp (Key->Description, Array[Index].Description) == 0) &&
> +        (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
> +        (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
> +        (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
> +      return (INTN) Index;
> +    }
> +  }
> +
> +  return -1;
> +}
> +
> +
> +/**
> +  Registers a boot option
> +
> +  @param FileGuid               Boot file GUID
> +  @param Description            Boot option discription
> +  @param Position               Position of the new load option to put in the ****Order variable.
> +  @param Attributes             Boot option attributes
> +  @param OptionalData           Optional data of the boot option.
> +  @param OptionalDataSize       Size of the optional data of the boot option
> +
> +  @return boot option number
> +**/
> +UINTN
> +RegisterFvBootOption (
> +  EFI_GUID                         *FileGuid,
> +  CHAR16                           *Description,
> +  UINTN                            Position,
> +  UINT32                           Attributes,
> +  UINT8                            *OptionalData,    OPTIONAL
> +  UINT32                           OptionalDataSize
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  UINTN                            OptionIndex;
> +  EFI_BOOT_MANAGER_LOAD_OPTION     NewOption;
> +  EFI_BOOT_MANAGER_LOAD_OPTION     *BootOptions;
> +  UINTN                            BootOptionCount;
> +
> +  NewOption.OptionNumber = LoadOptionNumberUnassigned;
> +  Status = CreateFvBootOption (FileGuid, Description, &NewOption, Attributes, OptionalData, OptionalDataSize);
> +  if (!EFI_ERROR (Status)) {
> +    BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
> +
> +    OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions, BootOptionCount);
> +
> +    if (OptionIndex == -1) {
> +      Status = EfiBootManagerAddLoadOptionVariable (&NewOption, Position);
> +      ASSERT_EFI_ERROR (Status);
> +    } else {
> +      NewOption.OptionNumber = BootOptions[OptionIndex].OptionNumber;
> +    }
> +    EfiBootManagerFreeLoadOption (&NewOption);
> +    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
> +  }
> +
> +  return NewOption.OptionNumber;
> +}
> +
> +
> +/**
> +  Boot manager wait callback
> +
> +  @param TimeoutRemain The remaingin timeout period
> +**/
> +VOID
> +EFIAPI
> +PlatformBootManagerWaitCallback (
> +  UINT16          TimeoutRemain
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *TxtInEx;
> +  EFI_KEY_DATA                  KeyData;
> +  BOOLEAN                       PausePressed;
> +
> +  //
> +  // Pause on PAUSE key
> +  //
> +  Status = gBS->HandleProtocol (gST->ConsoleInHandle, &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  PausePressed = FALSE;
> +
> +  while (TRUE) {
> +    Status = TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData);
> +    if (EFI_ERROR (Status)) {
> +      break;
> +    }
> +
> +    if (KeyData.Key.ScanCode == SCAN_PAUSE) {
> +      PausePressed = TRUE;
> +      break;
> +    }
> +  }
> +
> +  //
> +  // Loop until non-PAUSE key pressed
> +  //
> +  while (PausePressed) {
> +    Status = TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData);
> +    if (!EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_INFO, "[PauseCallback] %x/%x %x/%x\n",
> +        KeyData.Key.ScanCode, KeyData.Key.UnicodeChar,
> +        KeyData.KeyState.KeyShiftState, KeyData.KeyState.KeyToggleState
> +        ));
> +      PausePressed = (BOOLEAN) (KeyData.Key.ScanCode == SCAN_PAUSE);
> +    }
> +  }
> +}
> +
> +
> +EFI_GUID gUefiShellFileGuid = { 0x7C04A583, 0x9E3E, 0x4f1c, { 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 } };
> +
> +#define INTERNAL_UEFI_SHELL_NAME      L"Internal UEFI Shell 2.0"
> +#define UEFI_HARD_DRIVE_NAME          L"UEFI Hard Drive"
> +
> +/**
> +   Registers default boot option
> +**/
> +
> +VOID
> +RegisterDefaultBootOption (
> +  VOID
> +  )
> +{
> +  UINT16                             *ShellData;
> +  UINT32                             ShellDataSize;
> +
> +    ShellData = NULL;
> +    ShellDataSize = 0;
> +    RegisterFvBootOption (&gUefiShellFileGuid,      INTERNAL_UEFI_SHELL_NAME, (UINTN) -1, LOAD_OPTION_ACTIVE, (UINT8 *)ShellData, ShellDataSize);
> +
> +  //
> +  // Boot Menu
> +  //
> +  mBootMenuOptionNumber = RegisterFvBootOption (&mBootMenuFile, L"Boot Device List",   (UINTN) -1, LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDEN, NULL, 0);
> +
> +  if (mBootMenuOptionNumber == LoadOptionNumberUnassigned) {
> +    DEBUG ((DEBUG_INFO, "BootMenuOptionNumber (%d) should not be same to LoadOptionNumberUnassigned(%d).\n", mBootMenuOptionNumber, LoadOptionNumberUnassigned));
> +  }
> +#if 0
> +  //
> +  // Boot Manager Menu
> +  //
> +  EfiInitializeFwVolDevicepathNode (&FileNode, &mUiFile);
> +
> +  gBS->HandleProtocol (
> +         gImageHandle,
> +         &gEfiLoadedImageProtocolGuid,
> +         (VOID **) &LoadedImage
> +         );
> +  DevicePath = AppendDevicePathNode (DevicePathFromHandle (LoadedImage->DeviceHandle), (EFI_DEVICE_PATH_PROTOCOL *) &FileNode);
> +#endif
> +
> +}
> +
> +/**
> +  Registers/Unregisters boot option hotkey
> +
> +  @param OptionNumber  The boot option number for the key option.
> +  @param Key           The the key input
> +  @param Add           Flag to indicate to add or remove a key
> +**/
> +VOID
> +RegisterBootOptionHotkey (
> +  UINT16                       OptionNumber,
> +  EFI_INPUT_KEY                *Key,
> +  BOOLEAN                      Add
> +  )
> +{
> +  EFI_STATUS                   Status;
> +
> +  if (!Add) {
> +    //
> +    // No enter hotkey when force to setup or there is no boot option
> +    //
> +    Status = EfiBootManagerDeleteKeyOptionVariable (NULL, 0, Key, NULL);
> +    ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);
> +  } else {
> +    //
> +    // Register enter hotkey for the first boot option
> +    //
> +    Status = EfiBootManagerAddKeyOptionVariable (NULL, OptionNumber, 0, Key,NULL);
> +    ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
> +  }
> +}
> +
> +
> +/**
> +  Detect key press callback
> +
> +  @param    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;
> +  EFI_STATUS                    Status;
> +  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;
> +
> +  EnterSetup = FALSE;
> +
> +  //
> +  // [Enter]
> +  //
> +  mContinueBoot = !EnterSetup;
> +  if (mContinueBoot) {
> +    Enter.ScanCode    = SCAN_NULL;
> +    Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
> +    EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
> +  }
> +
> +
> +  //
> +  // [F2]/[F7]
> +  //
> +  F2.Key.ScanCode    = SCAN_F2;
> +  F2.Key.UnicodeChar = CHAR_NULL;
> +  F2.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
> +  F2.KeyState.KeyToggleState = 0;
> +  Status = EfiBootManagerGetBootManagerMenu (&BootOption);
> +  ASSERT_EFI_ERROR (Status);
> +  RegisterBootOptionHotkey ((UINT16) BootOption.OptionNumber, &F2.Key, TRUE);
> +  EfiBootManagerFreeLoadOption (&BootOption);
> +
> +  F7.Key.ScanCode    = SCAN_F7;
> +  F7.Key.UnicodeChar = CHAR_NULL;
> +  F7.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
> +  F7.KeyState.KeyToggleState = 0;
> +  mBootMenuBoot  = !EnterSetup;
> +  RegisterBootOptionHotkey ((UINT16) mBootMenuOptionNumber, &F7.Key, mBootMenuBoot);
> +
> +}
> +
> +
> +
> +/**
> +  Returns the boot option type of a device
> +
> +  @param DevicePath             The path of device whose boot option type
> +                                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.
> +  OptionType                 EFI
> +  ------------------------------------
> +  PXE                         2
> +  DVD                         4
> +  USB                         6
> +  NVME                        7
> +  HDD                         8
> +  EFI Shell                   9
> +  Others                      100
> +
> +  @param BootOption
> +**/
> +UINTN
> +BootOptionPriority (
> +  CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
> +  )
> +{
> +    //
> +    // EFI boot options
> +    //
> +    switch (BootOptionType (BootOption->FilePath)) {
> +    case MSG_MAC_ADDR_DP:
> +    case MSG_VLAN_DP:
> +    case MSG_IPv4_DP:
> +    case MSG_IPv6_DP:
> +      return 2;
> +
> +    case MSG_SATA_DP:
> +    case MSG_ATAPI_DP:
> +    case MSG_UFS_DP:
> +    case MSG_NVME_NAMESPACE_DP:
> +      return 4;
> +
> +    case MSG_USB_DP:
> +      return 6;
> +
> +    }
> +    if (StrCmp (BootOption->Description, INTERNAL_UEFI_SHELL_NAME) == 0) {
> +      if (PcdGetBool (PcdBootToShellOnly)) {
> +        return 0;
> +      }
> +      return 9;
> +    }
> +    if (StrCmp (BootOption->Description, UEFI_HARD_DRIVE_NAME) == 0) {
> +      return 8;
> +    }
> +    return 100;
> +}
> +
> +/**
> +   Compares boot priorities of two boot options
> +
> +  @param Left       The left boot option
> +  @param Right      The right boot option
> +
> +  @return           The difference between the Left and Right
> +                    boot options
> + **/
> +INTN
> +EFIAPI
> +CompareBootOption (
> +  CONST VOID  *Left,
> +  CONST VOID  *Right
> +  )
> +{
> +  return BootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *) Left) -
> +         BootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *) Right);
> +}
> +
> diff --git a/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardMemoryTest.c b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardMemoryTest.c
> new file mode 100644
> index 0000000000..e3650721fe
> --- /dev/null
> +++ b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardMemoryTest.c
> @@ -0,0 +1,83 @@
> +/** @file
> +  Perform the platform memory test
> +
> +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  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.19.1.windows.1
> 

Thanks,
Nate
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#52301): https://edk2.groups.io/g/devel/message/52301
Mute This Topic: https://groups.io/mt/68590724/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list