mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-05 04:44:25 +02:00
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.wang@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Hao Wu <hao.a.wu@intel.com> Reviewed-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
This commit is contained in:
parent
2e15b750c4
commit
05fd2a9268
@ -88,6 +88,59 @@ NextDevicePathNode (
|
|||||||
return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength(Node));
|
return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength(Node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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 the validity of the device path of a NVM Express host controller.
|
Check the validity of the device path of a NVM Express host controller.
|
||||||
|
|
||||||
|
@ -213,6 +213,7 @@ NvmExpressPeimEntry (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
|
EFI_BOOT_MODE BootMode;
|
||||||
EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi;
|
EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi;
|
||||||
UINT8 Controller;
|
UINT8 Controller;
|
||||||
UINTN MmioBase;
|
UINTN MmioBase;
|
||||||
@ -223,6 +224,15 @@ NvmExpressPeimEntry (
|
|||||||
|
|
||||||
DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
|
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
|
// Locate the NVME host controller PPI
|
||||||
//
|
//
|
||||||
@ -279,6 +289,22 @@ NvmExpressPeimEntry (
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// For S3 resume performance consideration, not all NVM Express controllers
|
||||||
|
// will be initialized. The driver consumes the content within
|
||||||
|
// S3StorageDeviceInitList LockBox to see if a controller will be skipped
|
||||||
|
// during S3 resume.
|
||||||
|
//
|
||||||
|
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
|
// Memory allocation for controller private data
|
||||||
//
|
//
|
||||||
|
@ -266,6 +266,26 @@ NvmePeimEndOfPei (
|
|||||||
IN VOID *Ppi
|
IN VOID *Ppi
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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.
|
Check the validity of the device path of a NVM Express host controller.
|
||||||
|
|
||||||
@ -309,4 +329,20 @@ NvmeBuildDevicePath (
|
|||||||
OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
|
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
|
#endif
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
NvmExpressPeiHci.h
|
NvmExpressPeiHci.h
|
||||||
NvmExpressPeiPassThru.c
|
NvmExpressPeiPassThru.c
|
||||||
NvmExpressPeiPassThru.h
|
NvmExpressPeiPassThru.h
|
||||||
|
NvmExpressPeiS3.c
|
||||||
NvmExpressPeiStorageSecurity.c
|
NvmExpressPeiStorageSecurity.c
|
||||||
NvmExpressPeiStorageSecurity.h
|
NvmExpressPeiStorageSecurity.h
|
||||||
|
|
||||||
@ -54,6 +55,7 @@
|
|||||||
BaseMemoryLib
|
BaseMemoryLib
|
||||||
IoLib
|
IoLib
|
||||||
TimerLib
|
TimerLib
|
||||||
|
LockBoxLib
|
||||||
PeimEntryPoint
|
PeimEntryPoint
|
||||||
|
|
||||||
[Ppis]
|
[Ppis]
|
||||||
@ -64,9 +66,13 @@
|
|||||||
gEfiPeiVirtualBlockIo2PpiGuid ## SOMETIMES_PRODUCES
|
gEfiPeiVirtualBlockIo2PpiGuid ## SOMETIMES_PRODUCES
|
||||||
gEdkiiPeiStorageSecurityCommandPpiGuid ## SOMETIMES_PRODUCES
|
gEdkiiPeiStorageSecurityCommandPpiGuid ## SOMETIMES_PRODUCES
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gS3StorageDeviceInitListGuid ## SOMETIMES_CONSUMES ## UNDEFINED
|
||||||
|
|
||||||
[Depex]
|
[Depex]
|
||||||
gEfiPeiMemoryDiscoveredPpiGuid AND
|
gEfiPeiMemoryDiscoveredPpiGuid AND
|
||||||
gEdkiiPeiNvmExpressHostControllerPpiGuid
|
gEdkiiPeiNvmExpressHostControllerPpiGuid AND
|
||||||
|
gEfiPeiMasterBootModePpiGuid
|
||||||
|
|
||||||
[UserExtensions.TianoCore."ExtraFiles"]
|
[UserExtensions.TianoCore."ExtraFiles"]
|
||||||
NvmExpressPeiExtra.uni
|
NvmExpressPeiExtra.uni
|
||||||
|
114
MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiS3.c
Normal file
114
MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiS3.c
Normal file
@ -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;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user