From: "Kubacki, Michael A" <michael.a.kubacki@intel.com>
To: "Agyeman, Prince" <prince.agyeman@intel.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Chiu, Chasel" <chasel.chiu@intel.com>,
"Desimone, Nathaniel L" <nathaniel.l.desimone@intel.com>
Subject: Re: [edk2-platforms] [PATCH 02/11] BoardModulePkg: Add BDS Hook Library
Date: Sat, 21 Dec 2019 02:36:25 +0000 [thread overview]
Message-ID: <BY5PR11MB448481E7BCFA6C2D48FCD8DAB52C0@BY5PR11MB4484.namprd11.prod.outlook.com> (raw)
In-Reply-To: <6db8d0100389024cf00c0d1e260ce48cca179d53.1576282834.git.prince.agyeman@intel.com>
Reviewed-by: Michael Kubacki <michael.a.kubacki@intel.com>
> -----Original Message-----
> From: Agyeman, Prince <prince.agyeman@intel.com>
> Sent: Friday, December 13, 2019 5:32 PM
> To: devel@edk2.groups.io
> Cc: Kubacki, Michael A <michael.a.kubacki@intel.com>; Chiu, Chasel
> <chasel.chiu@intel.com>; Desimone, Nathaniel L
> <nathaniel.l.desimone@intel.com>
> Subject: [edk2-platforms] [PATCH 02/11] BoardModulePkg: Add BDS Hook
> Library
>
> 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@intel.com>
> Cc: Chasel Chiu <chasel.chiu@intel.com>
> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
>
> Signed-off-by: Prince Agyeman <prince.agyeman@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/BoardBdsHookLi
> b.c
> create mode 100644
> Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHookLi
> b.inf
> create mode 100644
> Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBootOptio
> n.c
> create mode 100644
> Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardMemoryTe
> st.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_
> +
> +#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_
> +
> +#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/BoardBdsHook
> Lib.c
> b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHook
> Lib.c
> new file mode 100644
> index 0000000000..9d42a8c27f
> --- /dev/null
> +++
> b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHook
> Lib.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/BoardBdsHook
> Lib.inf
> b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHook
> Lib.inf
> new file mode 100644
> index 0000000000..69f3fcb552
> --- /dev/null
> +++
> b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBdsHook
> Lib.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/BoardBootOpti
> on.c
> b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBootOpti
> on.c
> new file mode 100644
> index 0000000000..87138bdd79
> --- /dev/null
> +++
> b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardBootOpti
> on.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/BoardMemory
> Test.c
> b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardMemory
> Test.c
> new file mode 100644
> index 0000000000..e3650721fe
> --- /dev/null
> +++
> b/Platform/Intel/BoardModulePkg/Library/BoardBdsHookLib/BoardMemory
> Test.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
next prev parent reply other threads:[~2019-12-21 2:36 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-14 1:32 [edk2-platforms] [PATCH 00/11] Add BDS Hook Points Agyeman, Prince
2019-12-14 1:32 ` [edk2-platforms] [PATCH 01/11] MinPlatformPkg: Add BDS Hook Point Guids Agyeman, Prince
2019-12-16 1:31 ` Chiu, Chasel
2019-12-16 8:50 ` [edk2-devel] " Ni, Ray
2019-12-17 23:58 ` Kubacki, Michael A
2019-12-18 0:11 ` Ni, Ray
2019-12-18 1:31 ` Nate DeSimone
2019-12-21 2:36 ` Kubacki, Michael A
2019-12-14 1:32 ` [edk2-platforms] [PATCH 02/11] BoardModulePkg: Add BDS Hook Library Agyeman, Prince
2019-12-18 1:19 ` Nate DeSimone
2019-12-21 2:36 ` Kubacki, Michael A [this message]
2019-12-14 1:32 ` [edk2-platforms] [PATCH 03/11] BoardModulePkg: Add BDS Hook DXE Driver Agyeman, Prince
2019-12-18 1:32 ` Nate DeSimone
2019-12-21 2:36 ` Kubacki, Michael A
2019-12-14 1:32 ` [edk2-platforms] [PATCH 04/11] MinPlatformPkg: Add BDS Board Boot Manager library Agyeman, Prince
2019-12-17 4:24 ` Chiu, Chasel
2019-12-18 1:33 ` Nate DeSimone
2019-12-21 2:36 ` Kubacki, Michael A
2019-12-14 1:32 ` [edk2-platforms] [PATCH 05/11] MinPlatformPkg: Add BDS Hook Points Agyeman, Prince
2019-12-17 5:44 ` Chiu, Chasel
2019-12-18 1:33 ` Nate DeSimone
2019-12-21 2:36 ` Kubacki, Michael A
2019-12-14 1:32 ` [edk2-platforms] [PATCH 06/11] BoardModulePkg: Add Generic BoardBootManagerLib Agyeman, Prince
2019-12-18 1:34 ` Nate DeSimone
2019-12-21 2:36 ` Kubacki, Michael A
2019-12-14 1:32 ` [edk2-platforms] [PATCH 07/11] KabylakeOpenBoardPkg: Add BDS Hook Dxe Driver Agyeman, Prince
2019-12-17 5:44 ` Chiu, Chasel
2019-12-18 1:35 ` Nate DeSimone
2019-12-21 2:36 ` Kubacki, Michael A
2019-12-14 1:32 ` [edk2-platforms] [PATCH 08/11] WhiskeylakeOpenBoardPkg: " Agyeman, Prince
2019-12-17 5:45 ` Chiu, Chasel
2019-12-18 1:35 ` Nate DeSimone
2019-12-21 2:36 ` Kubacki, Michael A
2019-12-14 1:32 ` [edk2-platforms] [PATCH 09/11] SimicsOpenBoardPkg: Add Bds Hook Library Agyeman, Prince
2019-12-18 1:29 ` Nate DeSimone
2019-12-21 2:37 ` Kubacki, Michael A
2019-12-14 1:32 ` [edk2-platforms] [PATCH 10/11] SimicsOpenBoardPkg: Add BDS Board Boot Manager library Agyeman, Prince
2019-12-18 1:35 ` Nate DeSimone
2019-12-21 2:37 ` Kubacki, Michael A
2019-12-14 1:32 ` [edk2-platforms] [PATCH 11/11] SimicsOpenBoardPkg: Add Bds Hook Points Agyeman, Prince
2019-12-18 1:36 ` Nate DeSimone
2019-12-21 2:37 ` Kubacki, Michael A
2020-04-21 20:37 ` [edk2-devel] [edk2-platforms] [PATCH 00/11] Add BDS " Nate DeSimone
2020-04-22 10:31 ` Leif Lindholm
2020-04-22 22:13 ` Nate DeSimone
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=BY5PR11MB448481E7BCFA6C2D48FCD8DAB52C0@BY5PR11MB4484.namprd11.prod.outlook.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