Reviewed-by: Michael Kubacki <michael.a.kuba...@intel.com> > -----Original Message----- > From: Agyeman, Prince <prince.agye...@intel.com> > Sent: Friday, December 13, 2019 5:32 PM > To: devel@edk2.groups.io > Cc: Kubacki, Michael A <michael.a.kuba...@intel.com>; Chiu, Chasel > <chasel.c...@intel.com>; Desimone, Nathaniel L > <nathaniel.l.desim...@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.kuba...@intel.com> > Cc: Chasel Chiu <chasel.c...@intel.com> > Cc: Nate DeSimone <nathaniel.l.desim...@intel.com> > > Signed-off-by: Prince Agyeman <prince.agye...@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
-=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#52466): https://edk2.groups.io/g/devel/message/52466 Mute This Topic: https://groups.io/mt/68590724/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-