Hi Hao, > -----Original Message----- > From: Wu, Hao A > Sent: Friday, February 15, 2019 2:24 PM > To: edk2-devel@lists.01.org > Cc: Wu, Hao A <hao.a...@intel.com>; Wang, Jian J <jian.j.w...@intel.com>; > Ni, Ray <ray...@intel.com>; Dong, Eric <eric.d...@intel.com> > Subject: [PATCH v5 07/13] MdeModulePkg/NvmExpressPei: Consume > S3StorageDeviceInitList LockBox > > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1409 > > For the NvmExpressPei driver, this commit will update the driver to consume > the S3StorageDeviceInitList LockBox in S3 phase. The purpose is to perform > an on-demand (partial) NVM Express device enumeration/initialization to > benefit the S3 resume performance. > > Cc: Jian J Wang <jian.j.w...@intel.com> > Cc: Ray Ni <ray...@intel.com> > Cc: Eric Dong <eric.d...@intel.com> > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Hao Wu <hao.a...@intel.com> > --- > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf | 8 +- > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h | 36 +++++++ > MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c | 53 +++++++++ > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c | 20 ++++ > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiS3.c | 114 > ++++++++++++++++++++ > 5 files changed, 230 insertions(+), 1 deletion(-) > > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf > index 0666e5892b..22b703e971 100644 > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf > @@ -40,6 +40,7 @@ > NvmExpressPeiHci.h > NvmExpressPeiPassThru.c > NvmExpressPeiPassThru.h > + NvmExpressPeiS3.c > NvmExpressPeiStorageSecurity.c > NvmExpressPeiStorageSecurity.h > > @@ -54,6 +55,7 @@ > BaseMemoryLib > IoLib > TimerLib > + LockBoxLib > PeimEntryPoint > > [Ppis] > @@ -64,9 +66,13 @@ > gEfiPeiVirtualBlockIo2PpiGuid ## SOMETIMES_PRODUCES > gEdkiiPeiStorageSecurityCommandPpiGuid ## SOMETIMES_PRODUCES > > +[Guids] > + gS3StorageDeviceInitListGuid ## SOMETIMES_CONSUMES ## > UNDEFINED > + > [Depex] > gEfiPeiMemoryDiscoveredPpiGuid AND > - gEdkiiPeiNvmExpressHostControllerPpiGuid > + gEdkiiPeiNvmExpressHostControllerPpiGuid AND > + gEfiPeiMasterBootModePpiGuid > > [UserExtensions.TianoCore."ExtraFiles"] > NvmExpressPeiExtra.uni > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h > index 92c3854c6e..e2a693abe8 100644 > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h > @@ -267,6 +267,26 @@ NvmePeimEndOfPei ( > ); > > /** > + Get the size of the current device path instance. > + > + @param[in] DevicePath A pointer to the > EFI_DEVICE_PATH_PROTOCOL > + structure. > + @param[out] InstanceSize The size of the current device path > instance. > + @param[out] EntireDevicePathEnd Indicate whether the instance is the > last > + one in the device path strucure. > + > + @retval EFI_SUCCESS The size of the current device path instance is > fetched. > + @retval Others Fails to get the size of the current device path > instance. > + > +**/ > +EFI_STATUS > +GetDevicePathInstanceSize ( > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, > + OUT UINTN *InstanceSize, > + OUT BOOLEAN *EntireDevicePathEnd > + ); > + > +/** > Check the validity of the device path of a NVM Express host controller. > > @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL > @@ -309,4 +329,20 @@ NvmeBuildDevicePath ( > OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath > ); > > +/** > + Determine if a specific NVM Express controller can be skipped for S3 phase. > + > + @param[in] HcDevicePath Device path of the controller. > + @param[in] HcDevicePathLength Length of the device path specified by > + HcDevicePath. > + > + @retval The number of ports that need to be enumerated. > + > +**/ > +BOOLEAN > +NvmeS3SkipThisController ( > + IN EFI_DEVICE_PATH_PROTOCOL *HcDevicePath, > + IN UINTN HcDevicePathLength > + ); > + > #endif > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c > b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c > index 5dab447f09..ed05d7a2be 100644 > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c > @@ -89,6 +89,59 @@ NextDevicePathNode ( > } > > /** > + Get the size of the current device path instance. > + > + @param[in] DevicePath A pointer to the > EFI_DEVICE_PATH_PROTOCOL > + structure. > + @param[out] InstanceSize The size of the current device path > instance. > + @param[out] EntireDevicePathEnd Indicate whether the instance is the > last > + one in the device path strucure. > + > + @retval EFI_SUCCESS The size of the current device path instance is > fetched. > + @retval Others Fails to get the size of the current device path > instance. > + > +**/ > +EFI_STATUS > +GetDevicePathInstanceSize ( > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, > + OUT UINTN *InstanceSize, > + OUT BOOLEAN *EntireDevicePathEnd > + ) > +{ > + EFI_DEVICE_PATH_PROTOCOL *Walker; > + > + if (DevicePath == NULL || InstanceSize == NULL || EntireDevicePathEnd == > NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Find the end of the device path instance // Walker = DevicePath; > + while (Walker->Type != END_DEVICE_PATH_TYPE) { > + Walker = NextDevicePathNode (Walker); } > + > + // > + // Check if 'Walker' points to the end of an entire device path // > + if (Walker->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE) { > + *EntireDevicePathEnd = TRUE; > + } else if (Walker->SubType == END_INSTANCE_DEVICE_PATH_SUBTYPE) { > + *EntireDevicePathEnd = FALSE; > + } else { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Compute the size of the device path instance // *InstanceSize = > + ((UINTN) Walker - (UINTN) (DevicePath)) + sizeof > + (EFI_DEVICE_PATH_PROTOCOL); > + > + return EFI_SUCCESS; > +}
Check whether can leverage UefiDevicePathLib API. Thanks, Eric > + > +/** > Check the validity of the device path of a NVM Express host controller. > > @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c > index 96622e6fd5..43b2dfc3e7 100644 > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c > @@ -213,6 +213,7 @@ NvmExpressPeimEntry ( > ) > { > EFI_STATUS Status; > + EFI_BOOT_MODE BootMode; > EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi; > UINT8 Controller; > UINTN MmioBase; > @@ -224,6 +225,15 @@ NvmExpressPeimEntry ( > DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__)); > > // > + // Get the current boot mode. > + // > + Status = PeiServicesGetBootMode (&BootMode); if (EFI_ERROR (Status)) > + { > + DEBUG ((DEBUG_ERROR, "%a: Fail to get the current boot mode.\n", > __FUNCTION__)); > + return Status; > + } > + > + // > // Locate the NVME host controller PPI > // > Status = PeiServicesLocatePpi ( > @@ -279,6 +289,16 @@ NvmExpressPeimEntry ( > continue; > } > > + if ((BootMode == BOOT_ON_S3_RESUME) && > + (NvmeS3SkipThisController (DevicePath, DevicePathLength))) { > + DEBUG (( > + DEBUG_ERROR, "%a: Controller %d is skipped during S3.\n", > + __FUNCTION__, Controller > + )); > + Controller++; > + continue; > + } > + > // > // Memory allocation for controller private data > // > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiS3.c > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiS3.c > new file mode 100644 > index 0000000000..eb3af75b89 > --- /dev/null > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiS3.c > @@ -0,0 +1,114 @@ > +/** @file > + The NvmExpressPei driver is used to manage non-volatile memory > +subsystem > + which follows NVM Express specification at PEI phase. > + > + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> > + > + This program and the accompanying materials are licensed and made > + available under the terms and conditions of the BSD License which > + accompanies this distribution. 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 IMPLIED. > + > +**/ > + > +#include "NvmExpressPei.h" > + > +#include <Guid/S3StorageDeviceInitList.h> > + > +#include <Library/LockBoxLib.h> > + > +/** > + Determine if a specific NVM Express controller can be skipped for S3 phase. > + > + @param[in] HcDevicePath Device path of the controller. > + @param[in] HcDevicePathLength Length of the device path specified by > + HcDevicePath. > + > + @retval The number of ports that need to be enumerated. > + > +**/ > +BOOLEAN > +NvmeS3SkipThisController ( > + IN EFI_DEVICE_PATH_PROTOCOL *HcDevicePath, > + IN UINTN HcDevicePathLength > + ) > +{ > + EFI_STATUS Status; > + UINT8 DummyData; > + UINTN S3InitDevicesLength; > + EFI_DEVICE_PATH_PROTOCOL *S3InitDevices; > + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; > + UINTN DevicePathInstLength; > + BOOLEAN EntireEnd; > + BOOLEAN Skip; > + > + // > + // From the LockBox, get the list of device paths for devices need to > + be // initialized in S3. > + // > + S3InitDevices = NULL; > + S3InitDevicesLength = sizeof (DummyData); > + EntireEnd = FALSE; > + Skip = TRUE; > + Status = RestoreLockBox (&gS3StorageDeviceInitListGuid, &DummyData, > + &S3InitDevicesLength); if (Status != EFI_BUFFER_TOO_SMALL) { > + return Skip; > + } else { > + S3InitDevices = AllocatePool (S3InitDevicesLength); > + if (S3InitDevices == NULL) { > + return Skip; > + } > + > + Status = RestoreLockBox (&gS3StorageDeviceInitListGuid, S3InitDevices, > &S3InitDevicesLength); > + if (EFI_ERROR (Status)) { > + return Skip; > + } > + } > + > + if (S3InitDevices == NULL) { > + return Skip; > + } > + > + // > + // Only need to initialize the controllers that exist in the device list. > + // > + do { > + // > + // Fetch the size of current device path instance. > + // > + Status = GetDevicePathInstanceSize ( > + S3InitDevices, > + &DevicePathInstLength, > + &EntireEnd > + ); > + if (EFI_ERROR (Status)) { > + break; > + } > + > + DevicePathInst = S3InitDevices; > + S3InitDevices = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN) S3InitDevices > + + DevicePathInstLength); > + > + if (HcDevicePathLength >= DevicePathInstLength) { > + continue; > + } > + > + // > + // Compare the device paths to determine if the device is managed by > this > + // controller. > + // > + if (CompareMem ( > + DevicePathInst, > + HcDevicePath, > + HcDevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL) > + ) == 0) { > + Skip = FALSE; > + break; > + } > + } while (!EntireEnd); > + > + return Skip; > +} > -- > 2.12.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel