From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.24; helo=mga09.intel.com; envelope-from=bowen.zhou@intel.com; receiver=edk2-devel@lists.01.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id BC64621B02822 for ; Thu, 27 Sep 2018 00:42:28 -0700 (PDT) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Sep 2018 00:42:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,309,1534834800"; d="scan'208";a="76311809" Received: from fmsmsx106.amr.corp.intel.com ([10.18.124.204]) by orsmga007.jf.intel.com with ESMTP; 27 Sep 2018 00:42:13 -0700 Received: from fmsmsx120.amr.corp.intel.com (10.18.124.208) by FMSMSX106.amr.corp.intel.com (10.18.124.204) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 27 Sep 2018 00:42:13 -0700 Received: from shsmsx103.ccr.corp.intel.com (10.239.4.69) by fmsmsx120.amr.corp.intel.com (10.18.124.208) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 27 Sep 2018 00:42:12 -0700 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.220]) by SHSMSX103.ccr.corp.intel.com ([169.254.4.245]) with mapi id 14.03.0319.002; Thu, 27 Sep 2018 15:42:10 +0800 From: "Zhou, Bowen" To: "edk2-devel@lists.01.org" CC: "Cao, Rock" , "Song, Edmund" Thread-Topic: [edk2] [PATCH] PurleyOpenBoardPkg: add platform level fast boot support Thread-Index: AdRWNTIo225cmzYBT+63RBE+Aa1cPg== Date: Thu, 27 Sep 2018 07:42:09 +0000 Message-ID: <477DBD36544FF849A8AD024E912EEC0F58FFDFBF@SHSMSX101.ccr.corp.intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: [PATCH] PurleyOpenBoardPkg: add platform level fast boot support X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 Sep 2018 07:42:28 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Introduce initial support for fast boot and related feature flags. This is = targeted for fixed hardware configuration systems which care less about BDS= phase console and dynamic detection, where a headless-like boot is accepta= ble. When fast boot flag is turned ON, some features will be disabled such as IP= MI. Users are supposed to tune flags to meet their own requirements. Cc: Rock Cao Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Xiaohu Zhou --- .../BoardMtOlympus/PlatformPkg.dsc | 5 + .../BoardMtOlympus/PlatformPkgConfig.dsc | 5 + .../BoardMtOlympus/PlatformPkgPcd.dsc | 4 + .../DxePlatformBootManagerLib/BdsPlatform.c | 1360 ++++++++++++++++= ++++ .../DxePlatformBootManagerLib/BdsPlatform.h | 190 +++ .../DxePlatformBootManagerLib.inf | 102 ++ .../Library/DxePlatformBootManagerLib/MemoryTest.c | 91 ++ .../DxePlatformBootManagerLib/PlatformBootOption.c | 565 ++++++++ Platform/Intel/PurleyOpenBoardPkg/PlatPkg.dec | 6 + 9 files changed, 2328 insertions(+) create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Int= el/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Int= el/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Int= el/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootMana= gerLib.inf create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Int= el/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/MemoryTest.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Int= el/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/PlatformBootOption.= c diff --git a/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkg.d= sc b/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkg.dsc index 7f9c786b9d..a2dc9b66b6 100644 --- a/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkg.dsc +++ b/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkg.dsc @@ -84,7 +84,12 @@ !include $(PCH_PKG)/PchCommonLib.dsc =20 [LibraryClasses.common] +!if gPlatformTokenSpaceGuid.PcdFastBoot =3D=3D FALSE PlatformBootManagerLib|MinPlatformPkg/Bds/Library/DxePlatformBootManager= Lib/DxePlatformBootManagerLib.inf +!else + PlatformBootManagerLib|$(BOARD_PKG)/Override/Platform/Intel/MinPlatformP= kg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf +!endif + TestPointCheckLib|MinPlatformPkg/Test/Library/TestPointCheckLibNull/Test= PointCheckLibNull.inf =20 CompressLib|MinPlatformPkg/Library/CompressLib/CompressLib.inf diff --git a/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgCo= nfig.dsc b/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgConf= ig.dsc index 39d60df47f..4f9e0a9702 100644 --- a/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgConfig.ds= c +++ b/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgConfig.ds= c @@ -61,3 +61,8 @@ gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosEnable|TRUE gAdvancedFeaturePkgTokenSpaceGuid.PcdIpmiEnable|TRUE =20 + gPlatformTokenSpaceGuid.PcdFastBoot|FALSE +!if gPlatformTokenSpaceGuid.PcdFastBoot =3D=3D TRUE + gAdvancedFeaturePkgTokenSpaceGuid.PcdIpmiEnable|FALSE + gPlatformTokenSpaceGuid.PcdUpdateConsoleInBds|FALSE +!endif \ No newline at end of file diff --git a/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgPc= d.dsc b/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgPcd.dsc index c4fff722ab..bfe32aba1c 100644 --- a/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgPcd.dsc +++ b/Platform/Intel/PurleyOpenBoardPkg/BoardMtOlympus/PlatformPkgPcd.dsc @@ -279,7 +279,11 @@ gOemSkuTokenSpaceGuid.PcdOemSkuUplinkPortIndex|0x5 =20 [PcdsDynamicExHii.common.DEFAULT] +!if gPlatformTokenSpaceGuid.PcdFastBoot =3D=3D FALSE gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVar= iableGuid|0x0|3 # Variable: L"Timeout" +!else + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVar= iableGuid|0x0|0 # Variable: L"Timeout" +!endif gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|L"HwErrRecSupport"|= gEfiGlobalVariableGuid|0x0|1 # Variable: L"HwErrRecSupport" =20 =20 diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinP= latformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.c b/Platform/I= ntel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/= DxePlatformBootManagerLib/BdsPlatform.c new file mode 100644 index 0000000000..831d325037 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatform= Pkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.c @@ -0,0 +1,1360 @@ +/** @file + This file include all platform action which can be customized by IBV/OEM= . + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made availabl= e under +the terms and conditions of the BSD License that accompanies this distribu= tion. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#include "BdsPlatform.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_BOOT_MODE gBootMode; + +BOOLEAN gPPRequireUIConfirm; + +extern UINTN mBootMenuOptionNumber; + +GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboa= rdDevicePath =3D { + { + { + 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 +}; + +// +// Internal shell mode +// +GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mShellModeColumn; +GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mShellModeRow; +GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mShellHorizontalResolution; +GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mShellVerticalResolution; +// +// BDS Platform Functions +// + +BOOLEAN +IsMorBitSet ( + VOID + ) +{ + UINTN MorControl; + EFI_STATUS Status; + UINTN DataSize; + + // + // Check if the MOR bit is set. + // + DataSize =3D sizeof (MorControl); + Status =3D gRT->GetVariable ( + MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, + &gEfiMemoryOverwriteControlDataGuid, + NULL, + &DataSize, + &MorControl + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, " PlatformBootMangerLib: gEfiMemoryOverwriteContro= lDataGuid doesn't exist!!***\n")); + MorControl =3D 0; + } else { + DEBUG ((DEBUG_INFO, " PlatformBootMangerLib: Get the gEfiMemoryOverwri= teControlDataGuid =3D %x!!***\n", MorControl)); + } + + return (BOOLEAN) (MorControl & 0x01); +} + +VOID +DumpDevicePath ( + IN CHAR16 *Name, + IN EFI_DEVICE_PATH *DevicePath + ) +{ + CHAR16 *Str; + + Str =3D ConvertDevicePathToText(DevicePath, TRUE, TRUE); + DEBUG ((DEBUG_INFO, "%s: %s\n", Name, Str)); + if (Str !=3D NULL) { + FreePool (Str); + } +} + +/** + An empty function to pass error checking of CreateEventEx (). + + This empty function ensures that EVT_NOTIFY_SIGNAL_ALL is error + checked correctly since it is now mapped into CreateEventEx() in UEFI 2.= 0. + + @param Event Event whose notification function is being= invoked. + @param Context The pointer to the notification function's= context, + which is implementation-dependent. +**/ +VOID +EFIAPI +InternalBdsEmptyCallbackFuntion ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + return; +} + +VOID +ExitPmAuth ( + VOID + ) +{ + EFI_HANDLE Handle; + EFI_STATUS Status; + EFI_EVENT EndOfDxeEvent; + + DEBUG((DEBUG_INFO,"ExitPmAuth ()- Start\n")); + // + // Prepare S3 information, this MUST be done before ExitPmAuth/EndOfDxe + // + // + // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + InternalBdsEmptyCallbackFuntion, + NULL, + &gEfiEndOfDxeEventGroupGuid, + &EndOfDxeEvent + ); + ASSERT_EFI_ERROR (Status); + gBS->SignalEvent (EndOfDxeEvent); + gBS->CloseEvent (EndOfDxeEvent); + DEBUG((DEBUG_INFO,"All EndOfDxe callbacks have returned successfully\n")= ); + + // + // NOTE: We need install DxeSmmReadyToLock directly here because many bo= ot script is added via ExitPmAuth/EndOfDxe callback. + // If we install them at same callback, these boot script will be reject= ed because BootScript Driver runs first to lock them done. + // So we seperate them to be 2 different events, ExitPmAuth is last chan= ce to let platform add boot script. DxeSmmReadyToLock will + // make boot script save driver lock down the interface. + // + Handle =3D NULL; + Status =3D gBS->InstallProtocolInterface ( + &Handle, + &gEfiDxeSmmReadyToLockProtocolGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + ASSERT_EFI_ERROR (Status); + DEBUG((DEBUG_INFO,"ExitPmAuth ()- End\n")); +} + +VOID +ConnectRootBridge ( + BOOLEAN Recursive + ) +{ + UINTN RootBridgeHandleCount; + EFI_HANDLE *RootBridgeHandleBuffer; + UINTN RootBridgeIndex; + + RootBridgeHandleCount =3D 0; + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &RootBridgeHandleCount, + &RootBridgeHandleBuffer + ); + for (RootBridgeIndex =3D 0; RootBridgeIndex < RootBridgeHandleCount; Roo= tBridgeIndex++) { + gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL,= NULL, Recursive); + } +} + + +/** + 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 =3D=3D NULL) { + return FALSE; + } + + ConsoleDevice =3D DuplicateDevicePath(Device); + + TrustedConsoleDevicepath =3D NULL; + + switch (ConsoleType) { + case ConIn: + TrustedConsoleDevicepath =3D PcdGetPtr (PcdTrustedConsoleInputDevicePa= th); + break; + case ConOut: + // + // Check GOP and remove last node + // + TempDevicePath =3D ConsoleDevice; + while (!IsDevicePathEndType (TempDevicePath)) { + if (DevicePathType (TempDevicePath) =3D=3D ACPI_DEVICE_PATH && + DevicePathSubType (TempDevicePath) =3D=3D ACPI_ADR_DP) { + SetDevicePathEndNode (TempDevicePath); + break; + } + TempDevicePath =3D NextDevicePathNode (TempDevicePath); + } + + TrustedConsoleDevicepath =3D PcdGetPtr (PcdTrustedConsoleOutputDeviceP= ath); + break; + default: + ASSERT(FALSE); + break; + } + + TempDevicePath =3D TrustedConsoleDevicepath; + do { + Instance =3D GetNextDevicePathInstance (&TempDevicePath, &Size); + if (Instance =3D=3D NULL) { + break; + } + + if (CompareMem (ConsoleDevice, Instance, Size - END_DEVICE_PATH_LENGTH= ) =3D=3D 0) { + FreePool (Instance); + FreePool (ConsoleDevice); + return TRUE; + } + + FreePool (Instance); + } while (TempDevicePath !=3D NULL); + + FreePool (ConsoleDevice); + + return FALSE; +} + +BOOLEAN +IsUsbShortForm ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + if ((DevicePathType (DevicePath) =3D=3D MESSAGING_DEVICE_PATH) && + ((DevicePathSubType (DevicePath) =3D=3D MSG_USB_CLASS_DP) || (Device= PathSubType (DevicePath) =3D=3D 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 =3D=3D 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 =3D FALSE; + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol ( + Handles[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (!EFI_ERROR (Status)) { + // + // Check whether the Pci device is the wanted usb host controller + // + Status =3D PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Cla= ss); + if (!EFI_ERROR (Status) && + ((PCI_CLASS_SERIAL =3D=3D Class[2]) && (PCI_CLASS_SERIAL_USB =3D= =3D Class[1])) + ) { + Status =3D gBS->ConnectController ( + Handles[Index], + NULL, + DevicePath, + FALSE + ); + if (!EFI_ERROR(Status)) { + AtLeastOneConnected =3D TRUE; + } + } + } + } + + return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND; +} + +/** + Update the ConIn variable with USB Keyboard device path,if its not alrea= dy exists in ConIn +**/ +VOID +EnumUsbKeyboard ( + VOID + ) +{ + DEBUG ((DEBUG_INFO, "[EnumUsbKeyboard]\n")); + EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL *)= &gUsbClassKeyboardDevicePath, NULL); + =20 + // + // Append Usb Keyboard short form DevicePath into "ConInDev" + // + EfiBootManagerUpdateConsoleVariable (ConInDev, (EFI_DEVICE_PATH_PROTOCOL= *) &gUsbClassKeyboardDevicePath, NULL); +} + +BOOLEAN +IsVgaHandle ( + IN EFI_HANDLE Handle + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + EFI_STATUS Status; + + Status =3D gBS->HandleProtocol ( + Handle, + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo + ); + if (!EFI_ERROR (Status)) { + Status =3D 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; +} + +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 =3D DuplicateDevicePath (DevicePath); + ASSERT (DupDevicePath !=3D NULL); + if (DupDevicePath =3D=3D NULL) { + return NULL; + } + + TempDevicePath =3D DupDevicePath; + Status =3D gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &TempDevicePath, + &DeviceHandle + ); + FreePool (DupDevicePath); + if (EFI_ERROR (Status)) { + return NULL; + } + + if (IsVgaHandle (DeviceHandle)) { + return DeviceHandle; + } else { + return NULL; + } +} + +BOOLEAN +IsGopDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + while (!IsDevicePathEndType (DevicePath)) { + if (DevicePathType (DevicePath) =3D=3D ACPI_DEVICE_PATH && + DevicePathSubType (DevicePath) =3D=3D ACPI_ADR_DP) { + return TRUE; + } + DevicePath =3D NextDevicePathNode (DevicePath); + } + return FALSE; +} + +/** + Remove all GOP device path instance from DevicePath and add the Gop to t= he DevicePath. +**/ +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 =3D FALSE; + Return =3D NULL; + GopSize =3D GetDevicePathSize (Gop); + do { + Instance =3D GetNextDevicePathInstance (&DevicePath, &Size); + if (Instance =3D=3D NULL) { + break; + } + if (!IsGopDevicePath (Instance) || + (Size =3D=3D GopSize && CompareMem (Instance, Gop, GopSize) =3D=3D= 0) + ) { + if (Size =3D=3D GopSize && CompareMem (Instance, Gop, GopSize) =3D= =3D 0) { + Exist =3D TRUE; + } + Temp =3D Return; + Return =3D AppendDevicePathInstance (Return, Instance); + if (Temp !=3D NULL) { + FreePool (Temp); + } + } + FreePool (Instance); + } while (DevicePath !=3D NULL); + + if (!Exist) { + Temp =3D Return; + Return =3D AppendDevicePathInstance (Return, Gop); + if (Temp !=3D NULL) { + FreePool (Temp); + } + } + return Return; +} + +/** + Get Graphics Controller Handle. + + @retval GraphicsController Successfully located + @retval NULL Failed to locate +**/ +EFI_HANDLE +EFIAPI +GetGraphicsController ( + IN BOOLEAN NeedTrustedConsole + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_HANDLE *PciHandles; + UINTN PciHandlesSize; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &PciHandlesSize, + &PciHandles + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + for (Index =3D 0; Index < PciHandlesSize; Index++) { + Status =3D 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; +} + +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 =3D GetGraphicsController (NeedTrustedConsole); + if (GraphicsControllerHandle !=3D 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 =3D EfiBootManagerGetGopDevicePath (GraphicsControllerHa= ndle); + if (GopDevicePath !=3D NULL) { + GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConOutDevicePath, NULL); + UpdatedConOutDevicePath =3D UpdateGopDevicePath (ConOutDevicePath, G= opDevicePath); + if (ConOutDevicePath !=3D NULL) { + FreePool (ConOutDevicePath); + } + FreePool (GopDevicePath); + gRT->SetVariable ( + L"ConOut", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACC= ESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, + GetDevicePathSize (UpdatedConOutDevicePath), + UpdatedConOutDevicePath + ); + } + } +} + +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 =3D ConsoleDevicePath; + do { + Instance =3D GetNextDevicePathInstance (&TempDevicePath, &Size); + if (Instance =3D=3D NULL) { + break; + } + =20 + 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 =3D IsVideoController (Instance); + if (GraphicsControllerHandle =3D=3D 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 =3D EfiBootManagerGetGopDevicePath (GraphicsControll= erHandle); + if (GopDevicePath !=3D NULL) { + EfiBootManagerUpdateConsoleVariable (ConsoleType, GopDevicePath,= NULL); + } + } + break; + default: + ASSERT(FALSE); + break; + } + + FreePool (Instance); + } while (TempDevicePath !=3D NULL); +} + +/** + 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[] =3D {L"ConIn", L"ConOut"}; + VOID *TrustedConsoleDevicepath; + + TrustedConsoleDevicepath =3D PcdGetPtr (PcdTrustedConsoleInputDevicePath= ); + DumpDevicePath (L"TrustedConsoleIn", TrustedConsoleDevicepath); + TrustedConsoleDevicepath =3D PcdGetPtr (PcdTrustedConsoleOutputDevicePat= h); + DumpDevicePath (L"TrustedConsoleOut", TrustedConsoleDevicepath); + + for (Index =3D 0; Index < sizeof (ConsoleVar) / sizeof (ConsoleVar[0]); = Index++) { + + GetEfiGlobalVariable2 (ConsoleVar[Index], (VOID **)&Consoles, NULL); + + TempDevicePath =3D Consoles; + do { + Instance =3D GetNextDevicePathInstance (&TempDevicePath, &Size); + if (Instance =3D=3D NULL) { + break; + } + if (IsTrustedConsole (Index, Instance)) { + if (IsUsbShortForm (Instance)) { + ConnectUsbShortFormDevicePath (Instance); + } else { + for (Next =3D Instance; !IsDevicePathEnd (Next); Next =3D NextDe= vicePathNode (Next)) { + if (DevicePathType (Next) =3D=3D ACPI_DEVICE_PATH && DevicePat= hSubType (Next) =3D=3D ACPI_ADR_DP) { + break; + } else if (DevicePathType (Next) =3D=3D HARDWARE_DEVICE_PATH &= & + DevicePathSubType (Next) =3D=3D HW_CONTROLLER_DP && + DevicePathType (NextDevicePathNode (Next)) =3D=3D A= CPI_DEVICE_PATH && + DevicePathSubType (NextDevicePathNode (Next)) =3D= =3D ACPI_ADR_DP + ) { + break; + } + } + if (!IsDevicePathEnd (Next)) { + SetDevicePathEndNode (Next); + Status =3D EfiBootManagerConnectDevicePath (Instance, &Handle)= ; + if (!EFI_ERROR (Status)) { + gBS->ConnectController (Handle, NULL, NULL, TRUE); + } + } else { + EfiBootManagerConnectDevicePath (Instance, NULL); + } + } + } + FreePool (Instance); + } while (TempDevicePath !=3D NULL); + + if (Consoles !=3D 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 =3D PcdGetPtr (PcdTrustedStorageDevicePath); + DumpDevicePath (L"TrustedStorage", TrustedStorageDevicepath); + + TempDevicePath =3D TrustedStorageDevicepath; + do { + Instance =3D GetNextDevicePathInstance (&TempDevicePath, &Size); + if (Instance =3D=3D NULL) { + break; + } + + EfiBootManagerConnectDevicePath (Instance, NULL); + + TempStorageDevicePath =3D Instance; + + Status =3D gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &TempStorageDevicePath, + &DeviceHandle + ); + if (!EFI_ERROR (Status)) { + gBS->ConnectController (DeviceHandle, NULL, NULL, FALSE); + } + + FreePool (Instance); + } while (TempDevicePath !=3D NULL); +} + +/** + The function connects the trusted consoles and then call the PP processi= ng library interface. +**/ +VOID +ProcessTcgPp ( + VOID + ) +{ + gPPRequireUIConfirm |=3D Tcg2PhysicalPresenceLibNeedUserConfirm(); + + if (gPPRequireUIConfirm) { + ConnectTrustedConsole (); + } + + Tcg2PhysicalPresenceLibProcessRequest (NULL); +} + +/** + The function connects the trusted storage to perform TPerReset. +**/ +VOID +ProcessTcgMor ( + VOID + ) +{ + if (IsMorBitSet ()) { + ConnectTrustedConsole(); + ConnectTrustedStorage(); + } +} + +/** + 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 =3D NULL; + Result =3D FALSE; + + // + // Get BootCurrent variable + // + VarSize =3D sizeof (UINT16); + Status =3D 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", Boot= Current); + + GetEfiGlobalVariable2 (BootOptionName, (VOID **) &BootOption, &VarSize); + if (BootOption =3D=3D NULL || VarSize =3D=3D 0) { + return FALSE; + } + + Ptr =3D BootOption; + Ptr +=3D sizeof (UINT32); + Ptr +=3D sizeof (UINT16); + Ptr +=3D StrSize ((CHAR16 *) Ptr); + TempDevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + LastDeviceNode =3D TempDevicePath; + while (!IsDevicePathEnd (TempDevicePath)) { + LastDeviceNode =3D TempDevicePath; + TempDevicePath =3D NextDevicePathNode (TempDevicePath); + } + GuidPoint =3D EfiGetNameGuidFromFwVolDevicePathNode ( + (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode + ); + if ((GuidPoint !=3D NULL) && + ((CompareGuid (GuidPoint, &gUefiShellFileGuid))) + ) { + // + // if this option is internal shell, return TRUE + // + Result =3D TRUE; + } + + if (BootOption !=3D NULL) { + FreePool (BootOption); + BootOption =3D 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; + + Status =3D gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID**)&GraphicsOutput + ); + if (EFI_ERROR (Status)) { + GraphicsOutput =3D NULL; + } + + Status =3D gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID**)&SimpleTextOut + ); + if (EFI_ERROR (Status)) { + SimpleTextOut =3D NULL; + } + + if ((GraphicsOutput =3D=3D NULL) || (SimpleTextOut =3D=3D NULL)) { + return EFI_UNSUPPORTED; + } + + MaxGopMode =3D GraphicsOutput->Mode->MaxMode; + MaxTextMode =3D 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 ne= ed not be change. + // 1.2. If current text mode is different with new text mode, text mo= de 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 =3D 0; ModeNumber < MaxGopMode; ModeNumber++) { + Status =3D GraphicsOutput->QueryMode ( + GraphicsOutput, + ModeNumber, + &SizeOfInfo, + &Info + ); + if (!EFI_ERROR (Status)) { + if ((Info->HorizontalResolution =3D=3D mShellHorizontalResolution) &= & + (Info->VerticalResolution =3D=3D mShellVerticalResolution)) { + if ((GraphicsOutput->Mode->Info->HorizontalResolution =3D=3D mShel= lHorizontalResolution) && + (GraphicsOutput->Mode->Info->VerticalResolution =3D=3D mShellV= erticalResolution)) { + // + // If current video resolution is same with new resolution, + // then check if current text mode is same with new text mode. + // + Status =3D SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOu= t->Mode->Mode, &CurrentColumn, &CurrentRow); + ASSERT_EFI_ERROR (Status); + if (CurrentColumn =3D=3D mShellModeColumn && CurrentRow =3D=3D m= ShellModeRow) { + // + // Current text mode is same with new text mode, text mode nee= d not be change. + // + FreePool (Info); + return EFI_SUCCESS; + } else { + // + // Current text mode is different with new text mode, text mod= e need be change to new text mode. + // + for (Index =3D 0; Index < MaxTextMode; Index++) { + Status =3D SimpleTextOut->QueryMode (SimpleTextOut, Index, &= CurrentColumn, &CurrentRow); + if (!EFI_ERROR(Status)) { + if ((CurrentColumn =3D=3D mShellModeColumn) && (CurrentRow= =3D=3D mShellModeRow)) { + // + // New text mode is supported, set it. + // + Status =3D SimpleTextOut->SetMode (SimpleTextOut, Index)= ; + ASSERT_EFI_ERROR (Status); + // + // Update text mode PCD. + // + Status =3D PcdSet32S (PcdConOutColumn, mShellModeColumn)= ; + ASSERT_EFI_ERROR (Status); + + Status =3D PcdSet32S (PcdConOutRow, mShellModeRow); + ASSERT_EFI_ERROR (Status); + + FreePool (Info); + return EFI_SUCCESS; + } + } + } + if (Index =3D=3D 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 =3D GraphicsOutput->SetMode (GraphicsOutput, ModeNumber); + if (!EFI_ERROR (Status)) { + // + // Set PCD to restart GraphicsConsole and Consplitter to chang= e video resolution + // and produce new text mode based on new resolution. + // + Status =3D PcdSet32S (PcdVideoHorizontalResolution, mShellHori= zontalResolution); + ASSERT_EFI_ERROR (Status); + + Status =3D PcdSet32S (PcdVideoVerticalResolution, mShellVertic= alResolution); + ASSERT_EFI_ERROR (Status); + + Status =3D PcdSet32S (PcdConOutColumn, mShellModeColumn); + ASSERT_EFI_ERROR (Status); + + Status =3D PcdSet32S (PcdConOutRow, mShellModeRow); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleTextOutProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (!EFI_ERROR (Status)) { + for (Index =3D 0; Index < HandleCount; Index++) { + gBS->DisconnectController (HandleBuffer[Index], NULL, NULL= ); + } + for (Index =3D 0; Index < HandleCount; Index++) { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, T= RUE); + } + if (HandleBuffer !=3D NULL) { + FreePool (HandleBuffer); + } + break; + } + } + } + } + FreePool (Info); + } + } + + if (ModeNumber =3D=3D MaxGopMode) { + // + // If the new resolution is not supported, return error. + // + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + 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 behav= ior, input devices will not be connected + by default. Hence, when booting to EFI shell, connecting input consoles = are required. + + @param Event Pointer to this event + @param Context Event hanlder private data + + @retval None. +**/ +VOID +EFIAPI +OnReadyToBootCallBack ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + DEBUG ((EFI_D_INFO, "OnReadyToBootCallBack\n")); + + if (BootCurrentIsInternalShell ()) { + + ChangeModeForInternalShell (); + EfiBootManagerConnectAllDefaultConsoles(); + gDS->Dispatch (); + } +} + +/** + Platform Bds init. Incude the platform firmware vendor, revision + and so crc check. +**/ +VOID +EFIAPI +PlatformBootManagerBeforeConsole ( + VOID + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *VarConOut; + EFI_DEVICE_PATH_PROTOCOL *VarConIn; + EFI_EVENT Event; + + DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole\n")); + + Status =3D EFI_SUCCESS; + + // + // Get user defined text mode for internal shell only once. + // + mShellHorizontalResolution =3D PcdGet32 (PcdSetupVideoHorizontalResoluti= on); + mShellVerticalResolution =3D PcdGet32 (PcdSetupVideoVerticalResolution= ); + mShellModeColumn =3D PcdGet32 (PcdSetupConOutColumn); + mShellModeRow =3D PcdGet32 (PcdSetupConOutRow); + + if (PcdGetBool (PcdUpdateConsoleInBds) =3D=3D TRUE) { + // + // Create event to set proper video resolution and text mode for inter= nal shell. + // + Status =3D EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + OnReadyToBootCallBack, + NULL, + &Event + ); + ASSERT_EFI_ERROR (Status); + + // + // Connect Root Bridge to make PCI BAR resource allocated and all PciI= o created + // + ConnectRootBridge (FALSE); + + // + // Fill ConIn/ConOut in Full Configuration boot mode + // + DEBUG ((DEBUG_INFO, "PlatformBootManagerInit - %x\n", gBootMode)); + + if (gBootMode =3D=3D BOOT_WITH_FULL_CONFIGURATION || + gBootMode =3D=3D BOOT_WITH_DEFAULT_SETTINGS || + gBootMode =3D=3D BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS || + gBootMode =3D=3D BOOT_IN_RECOVERY_MODE) { + + GetEfiGlobalVariable2 (L"ConOut", (VOID **)&VarConOut, NULL); if (= VarConOut !=3D NULL) { FreePool (VarConOut); } + GetEfiGlobalVariable2 (L"ConIn", (VOID **)&VarConIn, NULL); if (V= arConIn !=3D 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 =3D=3D NULL || VarConIn =3D=3D NULL) { + if (PcdGetSize (PcdTrustedConsoleOutputDevicePath) >=3D sizeof(EFI= _DEVICE_PATH_PROTOCOL)) { + AddConsoleVariable (ConOut, PcdGetPtr (PcdTrustedConsoleOutputDe= vicePath)); + } + if (PcdGetSize (PcdTrustedConsoleInputDevicePath) >=3D sizeof(EFI_= DEVICE_PATH_PROTOCOL)) { + AddConsoleVariable (ConIn, PcdGetPtr (PcdTrustedConsoleInputDevi= cePath)); + } + } + } + + EnumUsbKeyboard (); + // + // For trusted console it must be handled here. + // + UpdateGraphicConOut (TRUE); + + // + // Dynamically register hot key: F2/F7/Enter + // + RegisterDefaultBootOption (); + RegisterStaticHotkey (); + } + =20 + PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7010); + if (PcdGetBool (PcdTpm2Enable)) { + ProcessTcgPp (); + ProcessTcgMor (); + } + PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7011); + + // + // We should make all UEFI memory and GCD information populated before E= xitPmAuth. + // SMM may consume these information. + // + MemoryTest((EXTENDMEM_COVERAGE_LEVEL) PcdGet32 (PcdPlatformMemoryCheckLe= vel)); + + PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7020); + ExitPmAuth (); + PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7021); + + // + // Dispatch the deferred 3rd party images. + // + EfiBootManagerDispatchDeferredImages (); + + // + // For non-trusted console it must be handled here. + // + if (PcdGetBool (PcdUpdateConsoleInBds) =3D=3D TRUE) { + UpdateGraphicConOut (FALSE); + } +} + + +/** + 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 expectati= on. + 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 =3D EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOpti= onTypeBoot); + + // + // If setup is the first priority in boot option, we need to sort boot o= ption. + // + if ((BootOptionCount > 1) && + (((StrnCmp (BootOptions->Description, L"Enter Setup", StrLen (L"Ente= r Setup"))) =3D=3D 0) || + ((StrnCmp (BootOptions->Description, L"BootManagerMenuApp", StrLen = (L"BootManagerMenuApp"))) =3D=3D 0))) { + return TRUE; + } + + return FALSE; +} + +/** + The function will excute with as the platform policy, current policy + is driven by boot mode. IBV/OEM can customize this code for their specif= ic + policy action. + + @param DriverOptionList - The header of the driver option link list + @param BootOptionList - The header of the boot option link list + @param ProcessCapsules - A pointer to ProcessCapsules() + @param BaseMemoryTest - A pointer to BaseMemoryTest() +**/ +VOID +EFIAPI +PlatformBootManagerAfterConsole ( + VOID + ) +{ + EFI_BOOT_MODE LocalBootMode; + + DEBUG ((EFI_D_INFO, "PlatformBootManagerAfterConsole\n")); + + // + // Get current Boot Mode + // + LocalBootMode =3D 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 + // + if (PcdGetBool (PcdFastBoot) =3D=3D FALSE) { + 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 Int13T= hunk driver is there. + // + EfiBootManagerRefreshAllBootOption (); + + if (IsNeedSortBootOption()) { + EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBoo= tOption); + } + // + // PXE boot option may appear after boot option enumeration + // + + break; + } + + if (PcdGetBool (PcdFastBoot) =3D=3D FALSE) { + Print (L"Press F7 for BootMenu!\n"); + + EfiBootManagerRefreshAllBootOption (); + EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootO= ption); + } +} + +/** + The function is called when no boot option could be launched, + including platform recovery options and options pointing to applications + built into firmware volumes. + + If this function returns, BDS attempts to enter an infinite loop. +**/ +VOID +EFIAPI +PlatformBootManagerUnableToBoot ( + VOID + ) +{ + EFI_STATUS Status; + EFI_BOOT_MANAGER_LOAD_OPTION BootDeviceList; + CHAR16 OptionName[sizeof ("Boot####")]; + + if (mBootMenuOptionNumber =3D=3D LoadOptionNumberUnassigned) { + return; + } + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", mBootMenuOp= tionNumber); + Status =3D EfiBootManagerVariableToLoadOption (OptionName, &BootDeviceLi= st); + if (EFI_ERROR (Status)) { + return; + } + for (;;) { + EfiBootManagerBoot (&BootDeviceList); + } +} diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinP= latformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.h b/Platform/I= ntel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/= DxePlatformBootManagerLib/BdsPlatform.h new file mode 100644 index 0000000000..779ba9a98d --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatform= Pkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.h @@ -0,0 +1,190 @@ +/** @file + Header file for BDS Platform specific code + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made availabl= e under +the terms and conditions of the BSD License that accompanies this distribu= tion. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#ifndef _BDS_PLATFORM_H +#define _BDS_PLATFORM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/// +/// 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_PAT= H_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 gUsbClassKeyboardDevicePa= th; + +// +// 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 + ); + +VOID +ConnectSequence ( + IN EFI_BOOT_MODE BootMode + ); + + +INTN +EFIAPI +CompareBootOption ( + CONST VOID *Left, + CONST VOID *Right + ); + + +VOID +RegisterStaticHotkey ( + VOID + ); +VOID +RegisterDefaultBootOption ( + VOID + ); + +#endif diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinP= latformPkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.= inf b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatform= Pkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf new file mode 100644 index 0000000000..563c8a25b2 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatform= Pkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf @@ -0,0 +1,102 @@ +### @file +# Component name for module DxePlatformBootManagerLib +# +# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble under +# the terms and conditions of the BSD License which accompanies this distr= ibution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# +### + +[Defines] + INF_VERSION =3D 0x00010017 + BASE_NAME =3D DxePlatformBootManagerLib + FILE_GUID =3D A6BC385D-59E5-4B77-87D7-200ABAA83C15 + VERSION_STRING =3D 1.0 + MODULE_TYPE =3D DXE_DRIVER + UEFI_SPECIFICATION_VERSION =3D 2.10 + LIBRARY_CLASS =3D PlatformBootManagerLib|DXE_DRIVER +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 EBC +# + +[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 + PurleyOpenBoardPkg/PlatPkg.dec + +[Pcd] + gMinPlatformPkgTokenSpaceGuid.PcdTpm2Enable ## CONSUM= ES + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut ## PRO= DUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution ## PRO= DUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution ## PRO= DUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow ## PRO= DUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn ## PRO= DUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn ## CON= SUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow ## CON= SUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution ## CON= SUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution ## CON= SUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand ## PRO= DUCES + gMinPlatformPkgTokenSpaceGuid.PcdPlatformMemoryCheckLevel ## CONSUM= ES + gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly ## CONSUM= ES + gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleInputDevicePath ## CONSU= MES + gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleOutputDevicePath ## CONSU= MES + gMinPlatformPkgTokenSpaceGuid.PcdTrustedStorageDevicePath ## CONSU= MES + gPlatformTokenSpaceGuid.PcdUpdateConsoleInBds ## CONSU= MES + gPlatformTokenSpaceGuid.PcdFastBoot ## CONSU= MES + +[Sources] + BdsPlatform.c + BdsPlatform.h + PlatformBootOption.c + MemoryTest.c + +[Protocols] + gEfiPciRootBridgeIoProtocolGuid ## CONSUMES + gEfiPciIoProtocolGuid ## CONSUMES + gEfiCpuIo2ProtocolGuid ## CONSUMES + gEfiDxeSmmReadyToLockProtocolGuid ## PRODUCES + gEfiGenericMemTestProtocolGuid ## CONSUMES + gEfiDiskInfoProtocolGuid ## CONSUMES + gEfiDevicePathToTextProtocolGuid ## CONSUMES + gEfiSimpleTextInputExProtocolGuid ## CONSUMES + gEfiFirmwareVolume2ProtocolGuid ## CONSUMES + gEfiFormBrowser2ProtocolGuid ## CONSUMES + gEfiGenericMemTestProtocolGuid ## CONSUMES + +[Guids] + gEfiGlobalVariableGuid ## PRODUCES + gEfiMemoryOverwriteControlDataGuid ## PRODUCES + gEfiEndOfDxeEventGroupGuid ## CONSUMES + +[Depex.common.DXE_DRIVER] + gEfiVariableArchProtocolGuid diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinP= latformPkg/Bds/Library/DxePlatformBootManagerLib/MemoryTest.c b/Platform/In= tel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/D= xePlatformBootManagerLib/MemoryTest.c new file mode 100644 index 0000000000..6c36e7d28b --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatform= Pkg/Bds/Library/DxePlatformBootManagerLib/MemoryTest.c @@ -0,0 +1,91 @@ +/** @file + Perform the platform memory test + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made availabl= e under +the terms and conditions of the BSD License that accompanies this distribu= tion. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#include "BdsPlatform.h" +#include + +/** + 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 =3D 0; + TotalMemorySize =3D 0; + ErrorOut =3D FALSE; + TestAbort =3D FALSE; + + RequireSoftECCInit =3D FALSE; + + Status =3D gBS->LocateProtocol ( + &gEfiGenericMemTestProtocolGuid, + NULL, + (VOID **) &GenMemoryTest + ); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + Status =3D GenMemoryTest->MemoryTestInit ( + GenMemoryTest, + Level, + &RequireSoftECCInit + ); + if (Status =3D=3D 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 P= EI code + // checks all the memory, this BDS memory test will has no not-test me= mory to + // do the test, and then the status of EFI_NO_MEDIA will be returned b= y + // "MemoryTestInit". So it does not need to test memory again, just re= turn. + // + return EFI_SUCCESS; + } + + if (PcdGetBool (PcdFastBoot) =3D=3D FALSE) { + do { + Status =3D GenMemoryTest->PerformMemoryTest ( + GenMemoryTest, + &TestedMemorySize, + &TotalMemorySize, + &ErrorOut, + TestAbort + ); + if (ErrorOut && (Status =3D=3D EFI_DEVICE_ERROR)) { + ASSERT (0); + } + } while (Status !=3D EFI_NOT_FOUND); + } + + Status =3D GenMemoryTest->Finished (GenMemoryTest); + + return EFI_SUCCESS; +} diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinP= latformPkg/Bds/Library/DxePlatformBootManagerLib/PlatformBootOption.c b/Pla= tform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/L= ibrary/DxePlatformBootManagerLib/PlatformBootOption.c new file mode 100644 index 0000000000..ea30de0540 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatform= Pkg/Bds/Library/DxePlatformBootManagerLib/PlatformBootOption.c @@ -0,0 +1,565 @@ +/** @file + Driver for Platform Boot Options support. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made availabl= e under +the terms and conditions of the BSD License that accompanies this distribu= tion. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#include "BdsPlatform.h" + +#include + +BOOLEAN mContinueBoot =3D FALSE; +BOOLEAN mBootMenuBoot =3D FALSE; +BOOLEAN mPxeBoot =3D FALSE; +BOOLEAN mHotKeypressed =3D FALSE; +EFI_EVENT HotKeyEvent =3D NULL; + +UINTN mBootMenuOptionNumber; + +EFI_DEVICE_PATH_PROTOCOL * +BdsCreateShellDevicePath ( + VOID + ) +/*++ + +Routine Description: + + This function will create a SHELL BootOption to boot. + +Arguments: + + None. + +Returns: + + Shell Device path for booting. + +--*/ +{ + 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 =3D NULL; + Status =3D EFI_SUCCESS; + + DEBUG ((DEBUG_INFO, "BdsCreateShellDevicePath\n")); + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &FvHandleCount, + &FvHandleBuffer + ); + + for (Index =3D 0; Index < FvHandleCount; Index++) { + gBS->HandleProtocol ( + FvHandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + + Buffer =3D NULL; + Size =3D 0; + Status =3D 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 =3D 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 =3D=3D NULL) || (FileGuid =3D=3D NULL) || (Description = =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + + if (!CompareGuid (&gUefiShellFileGuid, FileGuid)) { + Status =3D gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + if (!EFI_ERROR (Status)) { + Status =3D gBS->HandleProtocol ( + LoadedImage->DeviceHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + if (!EFI_ERROR (Status)) { + Buffer =3D NULL; + Size =3D 0; + Status =3D Fv->ReadSection ( + Fv, + FileGuid, + EFI_SECTION_PE32, + 0, + &Buffer, + &Size, + &AuthenticationStatus + ); + if (Buffer !=3D NULL) { + FreePool (Buffer); + } + } + } + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + DevicePath =3D AppendDevicePathNode ( + DevicePathFromHandle (LoadedImage->DeviceHandle), + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); + } else { + DevicePath =3D AppendDevicePathNode ( + BdsCreateShellDevicePath (), + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); + } + + Status =3D EfiBootManagerInitializeLoadOption ( + BootOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + Attributes, + Description, + DevicePath, + OptionalData, + OptionalDataSize + ); + FreePool (DevicePath); + return Status; +} + +EFI_GUID mUiFile =3D { + 0x462CAA21, 0x7614, 0x4503, { 0x83, 0x6E, 0x8A, 0xB6, 0xF4, 0x66, 0x23, = 0x31 } +}; +EFI_GUID mBootMenuFile =3D { + 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 =3D 0; Index < Count; Index++) { + if ((Key->OptionType =3D=3D Array[Index].OptionType) && + (Key->Attributes =3D=3D Array[Index].Attributes) && + (StrCmp (Key->Description, Array[Index].Description) =3D=3D 0) && + (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSi= ze (Key->FilePath)) =3D=3D 0) && + (Key->OptionalDataSize =3D=3D Array[Index].OptionalDataSize) && + (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->Op= tionalDataSize) =3D=3D 0)) { + return (INTN) Index; + } + } + + return -1; +} + +UINTN +RegisterFvBootOption ( + EFI_GUID *FileGuid, + CHAR16 *Description, + UINTN Position, + UINT32 Attributes, + UINT8 *OptionalData, OPTIONAL + UINT32 OptionalDataSize + ) +{ + EFI_STATUS Status; + UINTN OptionIndex; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + + NewOption.OptionNumber =3D LoadOptionNumberUnassigned; + Status =3D CreateFvBootOption (FileGuid, Description, &NewOption, Attrib= utes, OptionalData, OptionalDataSize); + if (!EFI_ERROR (Status)) { + BootOptions =3D EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOp= tionTypeBoot); + + OptionIndex =3D PlatformFindLoadOption (&NewOption, BootOptions, BootO= ptionCount); + + if (OptionIndex =3D=3D -1) { + Status =3D EfiBootManagerAddLoadOptionVariable (&NewOption, Position= ); + ASSERT_EFI_ERROR (Status); + } else { + NewOption.OptionNumber =3D BootOptions[OptionIndex].OptionNumber; + } + EfiBootManagerFreeLoadOption (&NewOption); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); + } + + return NewOption.OptionNumber; +} + + + +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 =3D gBS->HandleProtocol (gST->ConsoleInHandle, &gEfiSimpleTextInp= utExProtocolGuid, (VOID **) &TxtInEx); + ASSERT_EFI_ERROR (Status); + + PausePressed =3D FALSE; + + while (TRUE) { + Status =3D TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData); + if (EFI_ERROR (Status)) { + break; + } + + if (KeyData.Key.ScanCode =3D=3D SCAN_PAUSE) { + PausePressed =3D TRUE; + break; + } + } + + // + // Loop until non-PAUSE key pressed + // + while (PausePressed) { + Status =3D 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 =3D (BOOLEAN) (KeyData.Key.ScanCode =3D=3D SCAN_PAUSE); + } + } +} + + +EFI_GUID gUefiShellFileGuid =3D { 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" + +VOID +RegisterDefaultBootOption ( + VOID + ) +{ +#if 0 + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; +#endif + UINT16 *ShellData; + UINT32 ShellDataSize; + + ShellData =3D NULL; + ShellDataSize =3D 0; + RegisterFvBootOption (&gUefiShellFileGuid, INTERNAL_UEFI_SHELL_NA= ME, (UINTN) -1, LOAD_OPTION_ACTIVE, (UINT8 *)ShellData, ShellDataSize); + + // + // Boot Menu + // + mBootMenuOptionNumber =3D RegisterFvBootOption (&mBootMenuFile, L"Boot D= evice List", (UINTN) -1, LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | = LOAD_OPTION_HIDDEN, NULL, 0); + + if (mBootMenuOptionNumber =3D=3D LoadOptionNumberUnassigned) { + DEBUG ((DEBUG_INFO, "BootMenuOptionNumber (%d) should not be same to L= oadOptionNumberUnassigned(%d).\n", mBootMenuOptionNumber, LoadOptionNumberU= nassigned)); + } +#if 0 + // + // Boot Manager Menu + // + EfiInitializeFwVolDevicepathNode (&FileNode, &mUiFile); + + gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + DevicePath =3D AppendDevicePathNode (DevicePathFromHandle (LoadedImage->= DeviceHandle), (EFI_DEVICE_PATH_PROTOCOL *) &FileNode); +#endif + +} + +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 =3D EfiBootManagerDeleteKeyOptionVariable (NULL, 0, Key, NULL); + ASSERT (Status =3D=3D EFI_SUCCESS || Status =3D=3D EFI_NOT_FOUND); + } else { + // + // Register enter hotkey for the first boot option + // + Status =3D EfiBootManagerAddKeyOptionVariable (NULL, OptionNumber, 0, = Key,NULL); + ASSERT (Status =3D=3D EFI_SUCCESS || Status =3D=3D EFI_ALREADY_STARTED= ); + } +} + +EFI_STATUS +EFIAPI +DetectKeypressCallback ( + IN EFI_KEY_DATA *KeyData +) +{ + mHotKeypressed =3D TRUE; + + if (HotKeyEvent !=3D NULL) { + gBS->SignalEvent(HotKeyEvent); + } + + return EFI_SUCCESS; +} + +/** + This function is called after all the boot options are enumerated and or= dered 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 =3D FALSE; + + // + // [Enter] + // + mContinueBoot =3D !EnterSetup; + if (mContinueBoot) { + Enter.ScanCode =3D SCAN_NULL; + Enter.UnicodeChar =3D CHAR_CARRIAGE_RETURN; + EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); + } + + + // + // [F2]/[F7] + // + F2.Key.ScanCode =3D SCAN_F2; + F2.Key.UnicodeChar =3D CHAR_NULL; + F2.KeyState.KeyShiftState =3D EFI_SHIFT_STATE_VALID; + F2.KeyState.KeyToggleState =3D 0; + Status =3D EfiBootManagerGetBootManagerMenu (&BootOption); + ASSERT_EFI_ERROR (Status); + RegisterBootOptionHotkey ((UINT16) BootOption.OptionNumber, &F2.Key, TRU= E); + EfiBootManagerFreeLoadOption (&BootOption); + + F7.Key.ScanCode =3D SCAN_F7; + F7.Key.UnicodeChar =3D CHAR_NULL; + F7.KeyState.KeyShiftState =3D EFI_SHIFT_STATE_VALID; + F7.KeyState.KeyToggleState =3D 0; + mBootMenuBoot =3D !EnterSetup; + RegisterBootOptionHotkey ((UINT16) mBootMenuOptionNumber, &F7.Key, mBoot= MenuBoot); + +} + +UINT8 +BootOptionType ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *NextNode; + + for (Node =3D DevicePath; !IsDevicePathEndType (Node); Node =3D NextDevi= cePathNode (Node)) { + if (DevicePathType (Node) =3D=3D MESSAGING_DEVICE_PATH) { + // + // Make sure the device path points to the driver device. + // + NextNode =3D NextDevicePathNode (Node); + if (DevicePathSubType(NextNode) =3D=3D MSG_DEVICE_LOGICAL_UNIT_DP) { + // + // if the next node type is Device Logical Unit, which specify the= Logical Unit Number (LUN), + // skip it + // + NextNode =3D NextDevicePathNode (NextNode); + } + if (IsDevicePathEndType (NextNode)) { + if ((DevicePathType (Node) =3D=3D 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) =3D=3D = 0) { + if (PcdGetBool (PcdBootToShellOnly)) { + return 0; + } + return 9; + } + if (StrCmp (BootOption->Description, UEFI_HARD_DRIVE_NAME) =3D=3D 0) { + return 8; + } + return 100; +} + +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/PurleyOpenBoardPkg/PlatPkg.dec b/Platform/Intel= /PurleyOpenBoardPkg/PlatPkg.dec index 221269e1f4..c203716029 100644 --- a/Platform/Intel/PurleyOpenBoardPkg/PlatPkg.dec +++ b/Platform/Intel/PurleyOpenBoardPkg/PlatPkg.dec @@ -26,6 +26,7 @@ gCpPlatFlashTokenSpaceGuid =3D { 0xc9c39664, 0x= 96dd, 0x4c5c, { 0xaf, 0xd7, 0xcd, 0x65, 0x76, 0x29, 0xcf, 0xb0 } } gOemSkuTokenSpaceGuid =3D { 0x9e37d253, 0x= abf8, 0x4985, { 0x8e, 0x23, 0xba, 0xca, 0x10, 0x39, 0x56, 0x13 } } gEfiIpmiPkgTokenSpaceGuid =3D { 0xe96431d, 0xc= 68e, 0x4212, { 0xa1, 0x70, 0x16, 0xa6, 0x8, 0x55, 0x12, 0xc6 } } + gPlatformTokenSpaceGuid =3D { 0x07dfa0d2, 0x= 2ac5, 0x4cab, { 0xac, 0x14, 0x30, 0x5c, 0x62, 0x48, 0x87, 0xe4 } } =20 [Ppis] gEfiPeiSystemBoardPpiGuid =3D { 0xc8d85e8c, 0x= dc1c, 0x4f8c, { 0xad, 0xa7, 0x58, 0xc1, 0xd1, 0x07, 0xa3, 0x04 } } @@ -43,6 +44,11 @@ # 0 - Disable; 1 - Minimum; 2 - Normal; 3 - Max gPlatformTokenSpaceGuid.PcdSerialDbgLvlAtBadCmos|0x1|UINT8|0x30000033 =20 +[PcdsFeatureFlag] + gPlatformTokenSpaceGuid.PcdFastBoot|FALSE|BOOLEAN|0x30000034 + + gPlatformTokenSpaceGuid.PcdUpdateConsoleInBds|TRUE|BOOLEAN|0x30000035 + [PcdsDynamicEx] gPlatformTokenSpaceGuid.PcdDfxAdvDebugJumper|FALSE|BOOLEAN|0x6000001D =20 --=20 2.14.3.windows.1