* [PATCH v2 0/1] Use PCI_DEVICE_PPI to manage Nvme device
@ 2022-08-30 5:46 chenxia1
2022-08-30 5:46 ` [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: " chenxia1
0 siblings, 1 reply; 4+ messages in thread
From: chenxia1 @ 2022-08-30 5:46 UTC (permalink / raw)
To: devel; +Cc: Xiao X Chen
This change modifies NvmExpressPei library to allow usage EDKII_PCI_DEVICE_PPI to manage Nvme device.
For now, the part that performs the enumeration and creates EDKII_PCI_DEVICE_PPI will be implemented in the silicon code.
Sample code can be seen here: https://github.com/mczaj/edk2-platforms/commit/d443062e58f9fba228869b54f2546d9735b3b506
unit test:
- verified the origin EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI flow in platform project,
Nvme controller can successful initialize.
- merged https://github.com/mczaj/edk2-platforms/commit/d443062e58f9fba228869b54f2546d9735b3b506 to platform project
to enumerate pcie device and create the EDKII_PCI_DEVICE_PPI for Nvme,
Nvme controller also can successful initialize by EDKII_PCI_DEVICE_PPI.
v1: https://edk2.groups.io/g/devel/topic/93340344
v2 changes:
- add the unit test information for cover letter
- refine the BAR type check for no.1 commit
Xiao X Chen (1):
MdeModulePkg/NvmExpressPei: Use PCI_DEVICE_PPI to manage Nvme device
.../Bus/Pci/NvmExpressPei/DevicePath.c | 44 --
.../Bus/Pci/NvmExpressPei/NvmExpressPei.c | 639 ++++++++++++------
.../Bus/Pci/NvmExpressPei/NvmExpressPei.h | 54 ++
.../Bus/Pci/NvmExpressPei/NvmExpressPei.inf | 3 +-
4 files changed, 488 insertions(+), 252 deletions(-)
--
2.37.0.windows.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: Use PCI_DEVICE_PPI to manage Nvme device
2022-08-30 5:46 [PATCH v2 0/1] Use PCI_DEVICE_PPI to manage Nvme device chenxia1
@ 2022-08-30 5:46 ` chenxia1
2022-08-30 6:27 ` Wu, Hao A
0 siblings, 1 reply; 4+ messages in thread
From: chenxia1 @ 2022-08-30 5:46 UTC (permalink / raw)
To: devel; +Cc: Xiao X Chen, Hao A Wu, Ray Ni
https://bugzilla.tianocore.org/show_bug.cgi?id=4017
This change modifies NvmExpressPei library
to allow usage both EDKII_PCI_DEVICE_PPI and
EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI to manage Nvme device.
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Signed-off-by: Xiao X Chen <xiao.x.chen@intel.com>
---
.../Bus/Pci/NvmExpressPei/DevicePath.c | 44 --
.../Bus/Pci/NvmExpressPei/NvmExpressPei.c | 639 ++++++++++++------
.../Bus/Pci/NvmExpressPei/NvmExpressPei.h | 54 ++
.../Bus/Pci/NvmExpressPei/NvmExpressPei.inf | 3 +-
4 files changed, 488 insertions(+), 252 deletions(-)
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
index 9b454a7dd8f4..307045be70ea 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
@@ -37,50 +37,6 @@ EFI_DEVICE_PATH_PROTOCOL mNvmeEndDevicePathNodeTemplate = {
}
};
-/**
- Returns the 16-bit Length field of a device path node.
-
- Returns the 16-bit Length field of the device path node specified by Node.
- Node is not required to be aligned on a 16-bit boundary, so it is recommended
- that a function such as ReadUnaligned16() be used to extract the contents of
- the Length field.
-
- If Node is NULL, then ASSERT().
-
- @param Node A pointer to a device path node data structure.
-
- @return The 16-bit Length field of the device path node specified by Node.
-
-**/
-UINTN
-DevicePathNodeLength (
- IN CONST VOID *Node
- )
-{
- ASSERT (Node != NULL);
- return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]);
-}
-
-/**
- Returns a pointer to the next node in a device path.
-
- If Node is NULL, then ASSERT().
-
- @param Node A pointer to a device path node data structure.
-
- @return a pointer to the device path node that follows the device path node
- specified by Node.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-NextDevicePathNode (
- IN CONST VOID *Node
- )
-{
- ASSERT (Node != NULL);
- return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength (Node));
-}
-
/**
Get the size of the current device path instance.
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
index 2d6a79028fcd..0d02c2785da7 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
@@ -40,6 +40,18 @@ EFI_PEI_NOTIFY_DESCRIPTOR mNvmeEndOfPeiNotifyListTemplate = {
NvmePeimEndOfPei
};
+EFI_PEI_NOTIFY_DESCRIPTOR mNvmeHostControllerNotify = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEdkiiPeiNvmExpressHostControllerPpiGuid,
+ NvmeHostControllerPpiInstallationCallback
+};
+
+EFI_PEI_NOTIFY_DESCRIPTOR mPciDevicePpiNotify = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEdkiiPeiPciDevicePpiGuid,
+ NvmePciDevicePpiInstallationCallback
+};
+
/**
Check if the specified Nvm Express device namespace is active, and then get the Identify
Namespace data.
@@ -212,30 +224,27 @@ NvmePeimEndOfPei (
}
/**
- Entry point of the PEIM.
+ Initialize and install PrivateData PPIs.
- @param[in] FileHandle Handle of the file being invoked.
- @param[in] PeiServices Describes the list of possible PEI Services.
-
- @retval EFI_SUCCESS PPI successfully installed.
+ @param[in] MmioBase MMIO base address of specific Nvme controller
+ @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
+ structure.
+ @param[in] DevicePathLength Length of the device path.
+ @retval EFI_SUCCESS Nvme controller initialized and PPIs installed
+ @retval others Failed to initialize Nvme controller
**/
EFI_STATUS
-EFIAPI
-NvmExpressPeimEntry (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN CONST EFI_PEI_SERVICES **PeiServices
+NvmeInitPrivateData (
+ IN UINTN MmioBase,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN UINTN DevicePathLength
)
{
- EFI_STATUS Status;
- EFI_BOOT_MODE BootMode;
- EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi;
- UINT8 Controller;
- UINTN MmioBase;
- UINTN DevicePathLength;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;
- EFI_PHYSICAL_ADDRESS DeviceAddress;
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
@@ -249,19 +258,358 @@ NvmExpressPeimEntry (
}
//
- // Locate the NVME host controller PPI
+ // Check validity of the device path of the NVM Express controller.
//
- Status = PeiServicesLocatePpi (
- &gEdkiiPeiNvmExpressHostControllerPpiGuid,
- 0,
- NULL,
- (VOID **)&NvmeHcPpi
+ Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: The device path is invalid for Controller %d.\n",
+ __FUNCTION__
+ ));
+ return Status;
+ }
+
+ //
+ // 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: skipped during S3.\n",
+ __FUNCTION__
+ ));
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Memory allocation for controller private data
+ //
+ Private = AllocateZeroPool (sizeof (PEI_NVME_CONTROLLER_PRIVATE_DATA));
+ if (Private == NULL) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Fail to allocate private data.\n",
+ __FUNCTION__
+ ));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Memory allocation for transfer-related data
+ //
+ Status = IoMmuAllocateBuffer (
+ NVME_MEM_MAX_PAGES,
+ &Private->Buffer,
+ &DeviceAddress,
+ &Private->BufferMapping
);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: Fail to locate NvmeHostControllerPpi.\n", __FUNCTION__));
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Fail to allocate DMA buffers.\n",
+ __FUNCTION__
+ ));
+ return Status;
+ }
+
+ ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)Private->Buffer));
+ DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n", __FUNCTION__, Private->Buffer));
+
+ //
+ // Initialize controller private data
+ //
+ Private->Signature = NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
+ Private->MmioBase = MmioBase;
+ Private->DevicePathLength = DevicePathLength;
+ Private->DevicePath = DevicePath;
+
+ //
+ // Initialize the NVME controller
+ //
+ Status = NvmeControllerInit (Private);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Controller initialization fail with Status - %r.\n",
+ __FUNCTION__,
+ Status
+ ));
+ NvmeFreeDmaResource (Private);
+ return Status;
+ }
+
+ //
+ // Enumerate the NVME namespaces on the controller
+ //
+ Status = NvmeDiscoverNamespaces (Private);
+ if (EFI_ERROR (Status)) {
+ //
+ // No active namespace was found on the controller
+ //
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Namespaces discovery fail with Status - %r.\n",
+ __FUNCTION__,
+ Status
+ ));
+ NvmeFreeDmaResource (Private);
+ return Status;
+ }
+
+ //
+ // Nvm Express Pass Thru PPI
+ //
+ Private->PassThruMode.Attributes = EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
+ EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL |
+ EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
+ Private->PassThruMode.IoAlign = sizeof (UINTN);
+ Private->PassThruMode.NvmeVersion = EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
+ Private->NvmePassThruPpi.Mode = &Private->PassThruMode;
+ Private->NvmePassThruPpi.GetDevicePath = NvmePassThruGetDevicePath;
+ Private->NvmePassThruPpi.GetNextNameSpace = NvmePassThruGetNextNameSpace;
+ Private->NvmePassThruPpi.PassThru = NvmePassThru;
+ CopyMem (
+ &Private->NvmePassThruPpiList,
+ &mNvmePassThruPpiListTemplate,
+ sizeof (EFI_PEI_PPI_DESCRIPTOR)
+ );
+ Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
+ PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
+
+ //
+ // Block Io PPI
+ //
+ Private->BlkIoPpi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo;
+ Private->BlkIoPpi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo;
+ Private->BlkIoPpi.ReadBlocks = NvmeBlockIoPeimReadBlocks;
+ CopyMem (
+ &Private->BlkIoPpiList,
+ &mNvmeBlkIoPpiListTemplate,
+ sizeof (EFI_PEI_PPI_DESCRIPTOR)
+ );
+ Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
+
+ Private->BlkIo2Ppi.Revision = EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
+ Private->BlkIo2Ppi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo2;
+ Private->BlkIo2Ppi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo2;
+ Private->BlkIo2Ppi.ReadBlocks = NvmeBlockIoPeimReadBlocks2;
+ CopyMem (
+ &Private->BlkIo2PpiList,
+ &mNvmeBlkIo2PpiListTemplate,
+ sizeof (EFI_PEI_PPI_DESCRIPTOR)
+ );
+ Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
+ PeiServicesInstallPpi (&Private->BlkIoPpiList);
+
+ //
+ // Check if the NVME controller supports the Security Receive/Send commands
+ //
+ if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Security Security Command PPI will be produced.\n",
+ __FUNCTION__
+ ));
+ Private->StorageSecurityPpi.Revision = EDKII_STORAGE_SECURITY_PPI_REVISION;
+ Private->StorageSecurityPpi.GetNumberofDevices = NvmeStorageSecurityGetDeviceNo;
+ Private->StorageSecurityPpi.GetDevicePath = NvmeStorageSecurityGetDevicePath;
+ Private->StorageSecurityPpi.ReceiveData = NvmeStorageSecurityReceiveData;
+ Private->StorageSecurityPpi.SendData = NvmeStorageSecuritySendData;
+ CopyMem (
+ &Private->StorageSecurityPpiList,
+ &mNvmeStorageSecurityPpiListTemplate,
+ sizeof (EFI_PEI_PPI_DESCRIPTOR)
+ );
+ Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
+ PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
+ }
+
+ CopyMem (
+ &Private->EndOfPeiNotifyList,
+ &mNvmeEndOfPeiNotifyListTemplate,
+ sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
+ );
+ PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize Nvme controller from fiven PCI_DEVICE_PPI.
+
+ @param[in] PciDevice Pointer to the PCI Device PPI instance.
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval Others Cannot initialize Nvme controller for given device
+**/
+EFI_STATUS
+NvmeInitControllerDataFromPciDevice (
+ EDKII_PCI_DEVICE_PPI *PciDevice
+ )
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 PciData;
+ UINTN MmioBase;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN DevicePathLength;
+ UINT64 EnabledPciAttributes;
+ UINT32 MmioBaseH;
+
+ //
+ // Now further check the PCI header: Base Class (offset 0x0B), Sub Class (offset 0x0A) and
+ // Programming Interface (offset 0x09). This controller should be an Nvme controller
+ //
+ Status = PciDevice->PciIo.Pci.Read (
+ &PciDevice->PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (PciData.Hdr.ClassCode),
+ PciData.Hdr.ClassCode
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (!IS_PCI_NVMHCI (&PciData)) {
return EFI_UNSUPPORTED;
}
+ Status = PciDevice->PciIo.Attributes (
+ &PciDevice->PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &EnabledPciAttributes
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ } else {
+ EnabledPciAttributes &= (UINT64)EFI_PCI_DEVICE_ENABLE;
+ Status = PciDevice->PciIo.Attributes (
+ &PciDevice->PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EnabledPciAttributes,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ Status = PciDevice->PciIo.Pci.Read (
+ &PciDevice->PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BASE_ADDRESSREG_OFFSET,
+ 1,
+ &MmioBase
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ switch (MmioBase & 0x07) {
+ case 0x0:
+ //
+ // Memory space for 32 bit bar address
+ //
+ MmioBase = MmioBase & 0xFFFFFFF0;
+ break;
+ case 0x4:
+ //
+ // For 64 bit bar address, read the high 32bits of this 64 bit bar
+ //
+ Status = PciDevice->PciIo.Pci.Read (
+ &PciDevice->PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BASE_ADDRESSREG_OFFSET + 4,
+ 1,
+ &MmioBaseH
+ );
+ //
+ // For 32 bit environment, high 32bits of the bar should be zero.
+ //
+ if ( EFI_ERROR (Status)
+ || ((MmioBaseH != 0) && (sizeof (UINTN) == sizeof (UINT32))))
+ {
+ return EFI_UNSUPPORTED;
+ }
+
+ MmioBase = MmioBase & 0xFFFFFFF0;
+ MmioBase |= LShiftU64 ((UINT64)MmioBaseH, 32);
+ break;
+ default:
+ //
+ // Unknown bar type
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ DevicePathLength = GetDevicePathSize (PciDevice->DevicePath);
+ DevicePath = PciDevice->DevicePath;
+
+ Status = NvmeInitPrivateData (MmioBase, DevicePath, DevicePathLength);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Failed to init controller, with Status - %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Callback for EDKII_PCI_DEVICE_PPI installation.
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDescriptor Pointer to the descriptor for the Notification
+ event that caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval Others Cannot initialize Nvme controller from given PCI_DEVICE_PPI
+
+**/
+EFI_STATUS
+EFIAPI
+NvmePciDevicePpiInstallationCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EDKII_PCI_DEVICE_PPI *PciDevice;
+
+ PciDevice = (EDKII_PCI_DEVICE_PPI *)Ppi;
+
+ return NvmeInitControllerDataFromPciDevice (PciDevice);
+}
+
+/**
+ Initialize Nvme controller from EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI instance.
+
+ @param[in] NvmeHcPpi Pointer to the Nvme Host Controller PPI instance.
+
+ @retval EFI_SUCCESS PPI successfully installed.
+**/
+EFI_STATUS
+NvmeInitControllerFromHostControllerPpi (
+ IN EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi
+ )
+{
+ UINT8 Controller;
+ UINTN MmioBase;
+ UINTN DevicePathLength;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_STATUS Status;
+
Controller = 0;
MmioBase = 0;
while (TRUE) {
@@ -293,88 +641,7 @@ NvmExpressPeimEntry (
return Status;
}
- //
- // Check validity of the device path of the NVM Express controller.
- //
- Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: The device path is invalid for Controller %d.\n",
- __FUNCTION__,
- Controller
- ));
- Controller++;
- 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
- //
- Private = AllocateZeroPool (sizeof (PEI_NVME_CONTROLLER_PRIVATE_DATA));
- if (Private == NULL) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: Fail to allocate private data for Controller %d.\n",
- __FUNCTION__,
- Controller
- ));
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Memory allocation for transfer-related data
- //
- Status = IoMmuAllocateBuffer (
- NVME_MEM_MAX_PAGES,
- &Private->Buffer,
- &DeviceAddress,
- &Private->BufferMapping
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: Fail to allocate DMA buffers for Controller %d.\n",
- __FUNCTION__,
- Controller
- ));
- return Status;
- }
-
- ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)Private->Buffer));
- DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n", __FUNCTION__, Private->Buffer));
-
- //
- // Initialize controller private data
- //
- Private->Signature = NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
- Private->MmioBase = MmioBase;
- Private->DevicePathLength = DevicePathLength;
- Private->DevicePath = DevicePath;
-
- //
- // Initialize the NVME controller
- //
- Status = NvmeControllerInit (Private);
+ Status = NvmeInitPrivateData (MmioBase, DevicePath, DevicePathLength);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
@@ -383,115 +650,73 @@ NvmExpressPeimEntry (
Controller,
Status
));
- NvmeFreeDmaResource (Private);
- Controller++;
- continue;
- }
-
- //
- // Enumerate the NVME namespaces on the controller
- //
- Status = NvmeDiscoverNamespaces (Private);
- if (EFI_ERROR (Status)) {
- //
- // No active namespace was found on the controller
- //
- DEBUG ((
- DEBUG_ERROR,
- "%a: Namespaces discovery fail for Controller %d with Status - %r.\n",
- __FUNCTION__,
- Controller,
- Status
- ));
- NvmeFreeDmaResource (Private);
- Controller++;
- continue;
- }
-
- //
- // Nvm Express Pass Thru PPI
- //
- Private->PassThruMode.Attributes = EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
- EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL |
- EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
- Private->PassThruMode.IoAlign = sizeof (UINTN);
- Private->PassThruMode.NvmeVersion = EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
- Private->NvmePassThruPpi.Mode = &Private->PassThruMode;
- Private->NvmePassThruPpi.GetDevicePath = NvmePassThruGetDevicePath;
- Private->NvmePassThruPpi.GetNextNameSpace = NvmePassThruGetNextNameSpace;
- Private->NvmePassThruPpi.PassThru = NvmePassThru;
- CopyMem (
- &Private->NvmePassThruPpiList,
- &mNvmePassThruPpiListTemplate,
- sizeof (EFI_PEI_PPI_DESCRIPTOR)
- );
- Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
- PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
-
- //
- // Block Io PPI
- //
- Private->BlkIoPpi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo;
- Private->BlkIoPpi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo;
- Private->BlkIoPpi.ReadBlocks = NvmeBlockIoPeimReadBlocks;
- CopyMem (
- &Private->BlkIoPpiList,
- &mNvmeBlkIoPpiListTemplate,
- sizeof (EFI_PEI_PPI_DESCRIPTOR)
- );
- Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
-
- Private->BlkIo2Ppi.Revision = EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
- Private->BlkIo2Ppi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo2;
- Private->BlkIo2Ppi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo2;
- Private->BlkIo2Ppi.ReadBlocks = NvmeBlockIoPeimReadBlocks2;
- CopyMem (
- &Private->BlkIo2PpiList,
- &mNvmeBlkIo2PpiListTemplate,
- sizeof (EFI_PEI_PPI_DESCRIPTOR)
- );
- Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
- PeiServicesInstallPpi (&Private->BlkIoPpiList);
-
- //
- // Check if the NVME controller supports the Security Receive/Send commands
- //
- if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
+ } else {
DEBUG ((
DEBUG_INFO,
- "%a: Security Security Command PPI will be produced for Controller %d.\n",
+ "%a: Controller %d has been successfully initialized.\n",
__FUNCTION__,
Controller
));
- Private->StorageSecurityPpi.Revision = EDKII_STORAGE_SECURITY_PPI_REVISION;
- Private->StorageSecurityPpi.GetNumberofDevices = NvmeStorageSecurityGetDeviceNo;
- Private->StorageSecurityPpi.GetDevicePath = NvmeStorageSecurityGetDevicePath;
- Private->StorageSecurityPpi.ReceiveData = NvmeStorageSecurityReceiveData;
- Private->StorageSecurityPpi.SendData = NvmeStorageSecuritySendData;
- CopyMem (
- &Private->StorageSecurityPpiList,
- &mNvmeStorageSecurityPpiListTemplate,
- sizeof (EFI_PEI_PPI_DESCRIPTOR)
- );
- Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
- PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
}
- CopyMem (
- &Private->EndOfPeiNotifyList,
- &mNvmeEndOfPeiNotifyListTemplate,
- sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
- );
- PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
-
- DEBUG ((
- DEBUG_INFO,
- "%a: Controller %d has been successfully initialized.\n",
- __FUNCTION__,
- Controller
- ));
Controller++;
}
return EFI_SUCCESS;
}
+
+/**
+ Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDescriptor Pointer to the descriptor for the Notification
+ event that caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval Others Cannot initialize Nvme controller from given EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeHostControllerPpiInstallationCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi;
+
+ if (Ppi == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NvmeHcPpi = (EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *)Ppi;
+
+ return NvmeInitControllerFromHostControllerPpi (NvmeHcPpi);
+}
+
+/**
+ Entry point of the PEIM.
+
+ @param[in] FileHandle Handle of the file being invoked.
+ @param[in] PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS PPI successfully installed.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressPeimEntry (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
+
+ PeiServicesNotifyPpi (&mNvmeHostControllerNotify);
+
+ PeiServicesNotifyPpi (&mPciDevicePpiNotify);
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
index 78a6b7016503..12a7624099c0 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
@@ -14,6 +14,7 @@
#include <PiPei.h>
#include <IndustryStandard/Nvme.h>
+#include <IndustryStandard/Pci.h>
#include <Ppi/NvmExpressHostController.h>
#include <Ppi/BlockIo.h>
@@ -22,6 +23,7 @@
#include <Ppi/NvmExpressPassThru.h>
#include <Ppi/IoMmu.h>
#include <Ppi/EndOfPeiPhase.h>
+#include <Ppi/PciDevice.h>
#include <Library/DebugLib.h>
#include <Library/PeiServicesLib.h>
@@ -29,6 +31,7 @@
#include <Library/BaseMemoryLib.h>
#include <Library/IoLib.h>
#include <Library/TimerLib.h>
+#include <Library/DevicePathLib.h>
//
// Structure forward declarations
@@ -36,6 +39,17 @@
typedef struct _PEI_NVME_NAMESPACE_INFO PEI_NVME_NAMESPACE_INFO;
typedef struct _PEI_NVME_CONTROLLER_PRIVATE_DATA PEI_NVME_CONTROLLER_PRIVATE_DATA;
+/**
+ Macro that checks whether device is a NVMHCI Interface.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is a NVMHCI Interface.
+ @retval FALSE Device is not a NVMHCI Interface.
+
+**/
+#define IS_PCI_NVMHCI(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_SOLID_STATE, PCI_IF_MASS_STORAGE_SOLID_STATE_ENTERPRISE_NVMHCI)
+
#include "NvmExpressPeiHci.h"
#include "NvmExpressPeiPassThru.h"
#include "NvmExpressPeiBlockIo.h"
@@ -345,4 +359,44 @@ NvmeS3SkipThisController (
IN UINTN HcDevicePathLength
);
+/**
+ Callback for EDKII_PCI_DEVICE_PPI installation.
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDescriptor Pointer to the descriptor for the Notification
+ event that caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval Others Cannot initialize Nvme controller from given PCI_DEVICE_PPI
+
+**/
+EFI_STATUS
+EFIAPI
+NvmePciDevicePpiInstallationCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+/**
+ Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDescriptor Pointer to the descriptor for the Notification
+ event that caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval Others Cannot initialize Nvme controller from given EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeHostControllerPpiInstallationCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
#endif
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
index 4dd6c5704fa3..ba6f1afbf168 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
@@ -44,6 +44,7 @@
[LibraryClasses]
DebugLib
+ DevicePathLib
PeiServicesLib
MemoryAllocationLib
BaseMemoryLib
@@ -56,6 +57,7 @@
gEdkiiPeiNvmExpressHostControllerPpiGuid ## CONSUMES
gEdkiiIoMmuPpiGuid ## CONSUMES
gEfiEndOfPeiSignalPpiGuid ## CONSUMES
+ gEdkiiPeiPciDevicePpiGuid ## CONSUMES
gEdkiiPeiNvmExpressPassThruPpiGuid ## SOMETIMES_PRODUCES
gEfiPeiVirtualBlockIoPpiGuid ## SOMETIMES_PRODUCES
gEfiPeiVirtualBlockIo2PpiGuid ## SOMETIMES_PRODUCES
@@ -66,7 +68,6 @@
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid AND
- gEdkiiPeiNvmExpressHostControllerPpiGuid AND
gEfiPeiMasterBootModePpiGuid
[UserExtensions.TianoCore."ExtraFiles"]
--
2.37.0.windows.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: Use PCI_DEVICE_PPI to manage Nvme device
2022-08-30 5:46 ` [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: " chenxia1
@ 2022-08-30 6:27 ` Wu, Hao A
2022-09-01 5:33 ` [edk2-devel] " Wu, Hao A
0 siblings, 1 reply; 4+ messages in thread
From: Wu, Hao A @ 2022-08-30 6:27 UTC (permalink / raw)
To: Chen, Xiao X, devel@edk2.groups.io; +Cc: Ni, Ray
Thanks.
Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
Will wait a couple of days before merging to see if comments from other reviewers.
Best Regards,
Hao Wu
> -----Original Message-----
> From: Chen, Xiao X <xiao.x.chen@intel.com>
> Sent: Tuesday, August 30, 2022 1:47 PM
> To: devel@edk2.groups.io
> Cc: Chen, Xiao X <xiao.x.chen@intel.com>; Wu, Hao A
> <hao.a.wu@intel.com>; Ni, Ray <ray.ni@intel.com>
> Subject: [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: Use
> PCI_DEVICE_PPI to manage Nvme device
>
> https://bugzilla.tianocore.org/show_bug.cgi?id=4017
>
> This change modifies NvmExpressPei library to allow usage both
> EDKII_PCI_DEVICE_PPI and EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
> to manage Nvme device.
>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Signed-off-by: Xiao X Chen <xiao.x.chen@intel.com>
> ---
> .../Bus/Pci/NvmExpressPei/DevicePath.c | 44 --
> .../Bus/Pci/NvmExpressPei/NvmExpressPei.c | 639 ++++++++++++------
> .../Bus/Pci/NvmExpressPei/NvmExpressPei.h | 54 ++
> .../Bus/Pci/NvmExpressPei/NvmExpressPei.inf | 3 +-
> 4 files changed, 488 insertions(+), 252 deletions(-)
>
> diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> index 9b454a7dd8f4..307045be70ea 100644
> --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> @@ -37,50 +37,6 @@ EFI_DEVICE_PATH_PROTOCOL
> mNvmeEndDevicePathNodeTemplate = {
> }
> };
>
> -/**
> - Returns the 16-bit Length field of a device path node.
> -
> - Returns the 16-bit Length field of the device path node specified by Node.
> - Node is not required to be aligned on a 16-bit boundary, so it is
> recommended
> - that a function such as ReadUnaligned16() be used to extract the contents
> of
> - the Length field.
> -
> - If Node is NULL, then ASSERT().
> -
> - @param Node A pointer to a device path node data structure.
> -
> - @return The 16-bit Length field of the device path node specified by Node.
> -
> -**/
> -UINTN
> -DevicePathNodeLength (
> - IN CONST VOID *Node
> - )
> -{
> - ASSERT (Node != NULL);
> - return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL
> *)(Node))->Length[0]); -}
> -
> -/**
> - Returns a pointer to the next node in a device path.
> -
> - If Node is NULL, then ASSERT().
> -
> - @param Node A pointer to a device path node data structure.
> -
> - @return a pointer to the device path node that follows the device path
> node
> - specified by Node.
> -
> -**/
> -EFI_DEVICE_PATH_PROTOCOL *
> -NextDevicePathNode (
> - IN CONST VOID *Node
> - )
> -{
> - ASSERT (Node != NULL);
> - return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) +
> DevicePathNodeLength (Node)); -}
> -
> /**
> Get the size of the current device path instance.
>
> diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> index 2d6a79028fcd..0d02c2785da7 100644
> --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> @@ -40,6 +40,18 @@ EFI_PEI_NOTIFY_DESCRIPTOR
> mNvmeEndOfPeiNotifyListTemplate = {
> NvmePeimEndOfPei
> };
>
> +EFI_PEI_NOTIFY_DESCRIPTOR mNvmeHostControllerNotify = {
> + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> +EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> + &gEdkiiPeiNvmExpressHostControllerPpiGuid,
> + NvmeHostControllerPpiInstallationCallback
> +};
> +
> +EFI_PEI_NOTIFY_DESCRIPTOR mPciDevicePpiNotify = {
> + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> +EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> + &gEdkiiPeiPciDevicePpiGuid,
> + NvmePciDevicePpiInstallationCallback
> +};
> +
> /**
> Check if the specified Nvm Express device namespace is active, and then
> get the Identify
> Namespace data.
> @@ -212,30 +224,27 @@ NvmePeimEndOfPei ( }
>
> /**
> - Entry point of the PEIM.
> + Initialize and install PrivateData PPIs.
>
> - @param[in] FileHandle Handle of the file being invoked.
> - @param[in] PeiServices Describes the list of possible PEI Services.
> -
> - @retval EFI_SUCCESS PPI successfully installed.
> + @param[in] MmioBase MMIO base address of specific Nvme
> controller
> + @param[in] DevicePath A pointer to the
> EFI_DEVICE_PATH_PROTOCOL
> + structure.
> + @param[in] DevicePathLength Length of the device path.
>
> + @retval EFI_SUCCESS Nvme controller initialized and PPIs installed
> + @retval others Failed to initialize Nvme controller
> **/
> EFI_STATUS
> -EFIAPI
> -NvmExpressPeimEntry (
> - IN EFI_PEI_FILE_HANDLE FileHandle,
> - IN CONST EFI_PEI_SERVICES **PeiServices
> +NvmeInitPrivateData (
> + IN UINTN MmioBase,
> + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
> + IN UINTN DevicePathLength
> )
> {
> - EFI_STATUS Status;
> - EFI_BOOT_MODE BootMode;
> - EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi;
> - UINT8 Controller;
> - UINTN MmioBase;
> - UINTN DevicePathLength;
> - EFI_DEVICE_PATH_PROTOCOL *DevicePath;
> - PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;
> - EFI_PHYSICAL_ADDRESS DeviceAddress;
> + EFI_STATUS Status;
> + EFI_BOOT_MODE BootMode;
> + PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;
> + EFI_PHYSICAL_ADDRESS DeviceAddress;
>
> DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
>
> @@ -249,19 +258,358 @@ NvmExpressPeimEntry (
> }
>
> //
> - // Locate the NVME host controller PPI
> + // Check validity of the device path of the NVM Express controller.
> //
> - Status = PeiServicesLocatePpi (
> - &gEdkiiPeiNvmExpressHostControllerPpiGuid,
> - 0,
> - NULL,
> - (VOID **)&NvmeHcPpi
> + Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength); if
> + (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "%a: The device path is invalid for Controller %d.\n",
> + __FUNCTION__
> + ));
> + return Status;
> + }
> +
> + //
> + // 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: skipped during S3.\n",
> + __FUNCTION__
> + ));
> + return EFI_SUCCESS;
> + }
> +
> + //
> + // Memory allocation for controller private data // Private =
> + AllocateZeroPool (sizeof (PEI_NVME_CONTROLLER_PRIVATE_DATA));
> + if (Private == NULL) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "%a: Fail to allocate private data.\n",
> + __FUNCTION__
> + ));
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + //
> + // Memory allocation for transfer-related data // Status =
> + IoMmuAllocateBuffer (
> + NVME_MEM_MAX_PAGES,
> + &Private->Buffer,
> + &DeviceAddress,
> + &Private->BufferMapping
> );
> if (EFI_ERROR (Status)) {
> - DEBUG ((DEBUG_ERROR, "%a: Fail to locate NvmeHostControllerPpi.\n",
> __FUNCTION__));
> + DEBUG ((
> + DEBUG_ERROR,
> + "%a: Fail to allocate DMA buffers.\n",
> + __FUNCTION__
> + ));
> + return Status;
> + }
> +
> + ASSERT (DeviceAddress ==
> + ((EFI_PHYSICAL_ADDRESS)(UINTN)Private->Buffer));
> + DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n",
> __FUNCTION__,
> + Private->Buffer));
> +
> + //
> + // Initialize controller private data //
> + Private->Signature =
> NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
> + Private->MmioBase = MmioBase;
> + Private->DevicePathLength = DevicePathLength;
> + Private->DevicePath = DevicePath;
> +
> + //
> + // Initialize the NVME controller
> + //
> + Status = NvmeControllerInit (Private); if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "%a: Controller initialization fail with Status - %r.\n",
> + __FUNCTION__,
> + Status
> + ));
> + NvmeFreeDmaResource (Private);
> + return Status;
> + }
> +
> + //
> + // Enumerate the NVME namespaces on the controller // Status =
> + NvmeDiscoverNamespaces (Private); if (EFI_ERROR (Status)) {
> + //
> + // No active namespace was found on the controller
> + //
> + DEBUG ((
> + DEBUG_ERROR,
> + "%a: Namespaces discovery fail with Status - %r.\n",
> + __FUNCTION__,
> + Status
> + ));
> + NvmeFreeDmaResource (Private);
> + return Status;
> + }
> +
> + //
> + // Nvm Express Pass Thru PPI
> + //
> + Private->PassThruMode.Attributes =
> EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
> + EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL
> |
> +
> EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
> + Private->PassThruMode.IoAlign = sizeof (UINTN);
> + Private->PassThruMode.NvmeVersion =
> EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
> + Private->NvmePassThruPpi.Mode = &Private->PassThruMode;
> + Private->NvmePassThruPpi.GetDevicePath =
> NvmePassThruGetDevicePath;
> + Private->NvmePassThruPpi.GetNextNameSpace =
> NvmePassThruGetNextNameSpace;
> + Private->NvmePassThruPpi.PassThru = NvmePassThru;
> + CopyMem (
> + &Private->NvmePassThruPpiList,
> + &mNvmePassThruPpiListTemplate,
> + sizeof (EFI_PEI_PPI_DESCRIPTOR)
> + );
> + Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
> + PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
> +
> + //
> + // Block Io PPI
> + //
> + Private->BlkIoPpi.GetNumberOfBlockDevices =
> + NvmeBlockIoPeimGetDeviceNo; Private-
> >BlkIoPpi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo;
> + Private->BlkIoPpi.ReadBlocks = NvmeBlockIoPeimReadBlocks;
> + CopyMem (
> + &Private->BlkIoPpiList,
> + &mNvmeBlkIoPpiListTemplate,
> + sizeof (EFI_PEI_PPI_DESCRIPTOR)
> + );
> + Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
> +
> + Private->BlkIo2Ppi.Revision =
> EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
> + Private->BlkIo2Ppi.GetNumberOfBlockDevices =
> + NvmeBlockIoPeimGetDeviceNo2; Private-
> >BlkIo2Ppi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo2;
> + Private->BlkIo2Ppi.ReadBlocks = NvmeBlockIoPeimReadBlocks2;
> + CopyMem (
> + &Private->BlkIo2PpiList,
> + &mNvmeBlkIo2PpiListTemplate,
> + sizeof (EFI_PEI_PPI_DESCRIPTOR)
> + );
> + Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
> + PeiServicesInstallPpi (&Private->BlkIoPpiList);
> +
> + //
> + // Check if the NVME controller supports the Security Receive/Send
> + commands // if ((Private->ControllerData->Oacs &
> + SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: Security Security Command PPI will be produced.\n",
> + __FUNCTION__
> + ));
> + Private->StorageSecurityPpi.Revision =
> EDKII_STORAGE_SECURITY_PPI_REVISION;
> + Private->StorageSecurityPpi.GetNumberofDevices =
> NvmeStorageSecurityGetDeviceNo;
> + Private->StorageSecurityPpi.GetDevicePath =
> NvmeStorageSecurityGetDevicePath;
> + Private->StorageSecurityPpi.ReceiveData =
> NvmeStorageSecurityReceiveData;
> + Private->StorageSecurityPpi.SendData =
> NvmeStorageSecuritySendData;
> + CopyMem (
> + &Private->StorageSecurityPpiList,
> + &mNvmeStorageSecurityPpiListTemplate,
> + sizeof (EFI_PEI_PPI_DESCRIPTOR)
> + );
> + Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
> + PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
> + }
> +
> + CopyMem (
> + &Private->EndOfPeiNotifyList,
> + &mNvmeEndOfPeiNotifyListTemplate,
> + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
> + );
> + PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Initialize Nvme controller from fiven PCI_DEVICE_PPI.
> +
> + @param[in] PciDevice Pointer to the PCI Device PPI instance.
> +
> + @retval EFI_SUCCESS The function completes successfully
> + @retval Others Cannot initialize Nvme controller for given device
> +**/
> +EFI_STATUS
> +NvmeInitControllerDataFromPciDevice (
> + EDKII_PCI_DEVICE_PPI *PciDevice
> + )
> +{
> + EFI_STATUS Status;
> + PCI_TYPE00 PciData;
> + UINTN MmioBase;
> + EFI_DEVICE_PATH_PROTOCOL *DevicePath;
> + UINTN DevicePathLength;
> + UINT64 EnabledPciAttributes;
> + UINT32 MmioBaseH;
> +
> + //
> + // Now further check the PCI header: Base Class (offset 0x0B), Sub
> + Class (offset 0x0A) and // Programming Interface (offset 0x09). This
> + controller should be an Nvme controller // Status =
> + PciDevice->PciIo.Pci.Read (
> + &PciDevice->PciIo,
> + EfiPciIoWidthUint8,
> + PCI_CLASSCODE_OFFSET,
> + sizeof (PciData.Hdr.ClassCode),
> + PciData.Hdr.ClassCode
> + );
> + if (EFI_ERROR (Status)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + if (!IS_PCI_NVMHCI (&PciData)) {
> return EFI_UNSUPPORTED;
> }
>
> + Status = PciDevice->PciIo.Attributes (
> + &PciDevice->PciIo,
> + EfiPciIoAttributeOperationSupported,
> + 0,
> + &EnabledPciAttributes
> + );
> + if (EFI_ERROR (Status)) {
> + return EFI_UNSUPPORTED;
> + } else {
> + EnabledPciAttributes &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> + Status = PciDevice->PciIo.Attributes (
> + &PciDevice->PciIo,
> + EfiPciIoAttributeOperationEnable,
> + EnabledPciAttributes,
> + NULL
> + );
> + if (EFI_ERROR (Status)) {
> + return EFI_UNSUPPORTED;
> + }
> + }
> +
> + Status = PciDevice->PciIo.Pci.Read (
> + &PciDevice->PciIo,
> + EfiPciIoWidthUint32,
> + PCI_BASE_ADDRESSREG_OFFSET,
> + 1,
> + &MmioBase
> + );
> + if (EFI_ERROR (Status)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + switch (MmioBase & 0x07) {
> + case 0x0:
> + //
> + // Memory space for 32 bit bar address
> + //
> + MmioBase = MmioBase & 0xFFFFFFF0;
> + break;
> + case 0x4:
> + //
> + // For 64 bit bar address, read the high 32bits of this 64 bit bar
> + //
> + Status = PciDevice->PciIo.Pci.Read (
> + &PciDevice->PciIo,
> + EfiPciIoWidthUint32,
> + PCI_BASE_ADDRESSREG_OFFSET + 4,
> + 1,
> + &MmioBaseH
> + );
> + //
> + // For 32 bit environment, high 32bits of the bar should be zero.
> + //
> + if ( EFI_ERROR (Status)
> + || ((MmioBaseH != 0) && (sizeof (UINTN) == sizeof (UINT32))))
> + {
> + return EFI_UNSUPPORTED;
> + }
> +
> + MmioBase = MmioBase & 0xFFFFFFF0;
> + MmioBase |= LShiftU64 ((UINT64)MmioBaseH, 32);
> + break;
> + default:
> + //
> + // Unknown bar type
> + //
> + return EFI_UNSUPPORTED;
> + }
> +
> + DevicePathLength = GetDevicePathSize (PciDevice->DevicePath);
> + DevicePath = PciDevice->DevicePath;
> +
> + Status = NvmeInitPrivateData (MmioBase, DevicePath,
> + DevicePathLength); if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: Failed to init controller, with Status - %r\n",
> + __FUNCTION__,
> + Status
> + ));
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Callback for EDKII_PCI_DEVICE_PPI installation.
> +
> + @param[in] PeiServices Pointer to PEI Services Table.
> + @param[in] NotifyDescriptor Pointer to the descriptor for the
> Notification
> + event that caused this function to execute.
> + @param[in] Ppi Pointer to the PPI data associated with this
> function.
> +
> + @retval EFI_SUCCESS The function completes successfully
> + @retval Others Cannot initialize Nvme controller from given
> PCI_DEVICE_PPI
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmePciDevicePpiInstallationCallback (
> + IN EFI_PEI_SERVICES **PeiServices,
> + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
> + IN VOID *Ppi
> + )
> +{
> + EDKII_PCI_DEVICE_PPI *PciDevice;
> +
> + PciDevice = (EDKII_PCI_DEVICE_PPI *)Ppi;
> +
> + return NvmeInitControllerDataFromPciDevice (PciDevice); }
> +
> +/**
> + Initialize Nvme controller from
> EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI instance.
> +
> + @param[in] NvmeHcPpi Pointer to the Nvme Host Controller PPI instance.
> +
> + @retval EFI_SUCCESS PPI successfully installed.
> +**/
> +EFI_STATUS
> +NvmeInitControllerFromHostControllerPpi (
> + IN EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi
> + )
> +{
> + UINT8 Controller;
> + UINTN MmioBase;
> + UINTN DevicePathLength;
> + EFI_DEVICE_PATH_PROTOCOL *DevicePath;
> + EFI_STATUS Status;
> +
> Controller = 0;
> MmioBase = 0;
> while (TRUE) {
> @@ -293,88 +641,7 @@ NvmExpressPeimEntry (
> return Status;
> }
>
> - //
> - // Check validity of the device path of the NVM Express controller.
> - //
> - Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((
> - DEBUG_ERROR,
> - "%a: The device path is invalid for Controller %d.\n",
> - __FUNCTION__,
> - Controller
> - ));
> - Controller++;
> - 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
> - //
> - Private = AllocateZeroPool (sizeof
> (PEI_NVME_CONTROLLER_PRIVATE_DATA));
> - if (Private == NULL) {
> - DEBUG ((
> - DEBUG_ERROR,
> - "%a: Fail to allocate private data for Controller %d.\n",
> - __FUNCTION__,
> - Controller
> - ));
> - return EFI_OUT_OF_RESOURCES;
> - }
> -
> - //
> - // Memory allocation for transfer-related data
> - //
> - Status = IoMmuAllocateBuffer (
> - NVME_MEM_MAX_PAGES,
> - &Private->Buffer,
> - &DeviceAddress,
> - &Private->BufferMapping
> - );
> - if (EFI_ERROR (Status)) {
> - DEBUG ((
> - DEBUG_ERROR,
> - "%a: Fail to allocate DMA buffers for Controller %d.\n",
> - __FUNCTION__,
> - Controller
> - ));
> - return Status;
> - }
> -
> - ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)Private-
> >Buffer));
> - DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n",
> __FUNCTION__, Private->Buffer));
> -
> - //
> - // Initialize controller private data
> - //
> - Private->Signature =
> NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
> - Private->MmioBase = MmioBase;
> - Private->DevicePathLength = DevicePathLength;
> - Private->DevicePath = DevicePath;
> -
> - //
> - // Initialize the NVME controller
> - //
> - Status = NvmeControllerInit (Private);
> + Status = NvmeInitPrivateData (MmioBase, DevicePath,
> + DevicePathLength);
> if (EFI_ERROR (Status)) {
> DEBUG ((
> DEBUG_ERROR,
> @@ -383,115 +650,73 @@ NvmExpressPeimEntry (
> Controller,
> Status
> ));
> - NvmeFreeDmaResource (Private);
> - Controller++;
> - continue;
> - }
> -
> - //
> - // Enumerate the NVME namespaces on the controller
> - //
> - Status = NvmeDiscoverNamespaces (Private);
> - if (EFI_ERROR (Status)) {
> - //
> - // No active namespace was found on the controller
> - //
> - DEBUG ((
> - DEBUG_ERROR,
> - "%a: Namespaces discovery fail for Controller %d with Status - %r.\n",
> - __FUNCTION__,
> - Controller,
> - Status
> - ));
> - NvmeFreeDmaResource (Private);
> - Controller++;
> - continue;
> - }
> -
> - //
> - // Nvm Express Pass Thru PPI
> - //
> - Private->PassThruMode.Attributes =
> EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
> - EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL
> |
> -
> EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
> - Private->PassThruMode.IoAlign = sizeof (UINTN);
> - Private->PassThruMode.NvmeVersion =
> EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
> - Private->NvmePassThruPpi.Mode = &Private->PassThruMode;
> - Private->NvmePassThruPpi.GetDevicePath =
> NvmePassThruGetDevicePath;
> - Private->NvmePassThruPpi.GetNextNameSpace =
> NvmePassThruGetNextNameSpace;
> - Private->NvmePassThruPpi.PassThru = NvmePassThru;
> - CopyMem (
> - &Private->NvmePassThruPpiList,
> - &mNvmePassThruPpiListTemplate,
> - sizeof (EFI_PEI_PPI_DESCRIPTOR)
> - );
> - Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
> - PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
> -
> - //
> - // Block Io PPI
> - //
> - Private->BlkIoPpi.GetNumberOfBlockDevices =
> NvmeBlockIoPeimGetDeviceNo;
> - Private->BlkIoPpi.GetBlockDeviceMediaInfo =
> NvmeBlockIoPeimGetMediaInfo;
> - Private->BlkIoPpi.ReadBlocks = NvmeBlockIoPeimReadBlocks;
> - CopyMem (
> - &Private->BlkIoPpiList,
> - &mNvmeBlkIoPpiListTemplate,
> - sizeof (EFI_PEI_PPI_DESCRIPTOR)
> - );
> - Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
> -
> - Private->BlkIo2Ppi.Revision =
> EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
> - Private->BlkIo2Ppi.GetNumberOfBlockDevices =
> NvmeBlockIoPeimGetDeviceNo2;
> - Private->BlkIo2Ppi.GetBlockDeviceMediaInfo =
> NvmeBlockIoPeimGetMediaInfo2;
> - Private->BlkIo2Ppi.ReadBlocks = NvmeBlockIoPeimReadBlocks2;
> - CopyMem (
> - &Private->BlkIo2PpiList,
> - &mNvmeBlkIo2PpiListTemplate,
> - sizeof (EFI_PEI_PPI_DESCRIPTOR)
> - );
> - Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
> - PeiServicesInstallPpi (&Private->BlkIoPpiList);
> -
> - //
> - // Check if the NVME controller supports the Security Receive/Send
> commands
> - //
> - if ((Private->ControllerData->Oacs &
> SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
> + } else {
> DEBUG ((
> DEBUG_INFO,
> - "%a: Security Security Command PPI will be produced for
> Controller %d.\n",
> + "%a: Controller %d has been successfully initialized.\n",
> __FUNCTION__,
> Controller
> ));
> - Private->StorageSecurityPpi.Revision =
> EDKII_STORAGE_SECURITY_PPI_REVISION;
> - Private->StorageSecurityPpi.GetNumberofDevices =
> NvmeStorageSecurityGetDeviceNo;
> - Private->StorageSecurityPpi.GetDevicePath =
> NvmeStorageSecurityGetDevicePath;
> - Private->StorageSecurityPpi.ReceiveData =
> NvmeStorageSecurityReceiveData;
> - Private->StorageSecurityPpi.SendData =
> NvmeStorageSecuritySendData;
> - CopyMem (
> - &Private->StorageSecurityPpiList,
> - &mNvmeStorageSecurityPpiListTemplate,
> - sizeof (EFI_PEI_PPI_DESCRIPTOR)
> - );
> - Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
> - PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
> }
>
> - CopyMem (
> - &Private->EndOfPeiNotifyList,
> - &mNvmeEndOfPeiNotifyListTemplate,
> - sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
> - );
> - PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
> -
> - DEBUG ((
> - DEBUG_INFO,
> - "%a: Controller %d has been successfully initialized.\n",
> - __FUNCTION__,
> - Controller
> - ));
> Controller++;
> }
>
> return EFI_SUCCESS;
> }
> +
> +/**
> + Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
> +
> + @param[in] PeiServices Pointer to PEI Services Table.
> + @param[in] NotifyDescriptor Pointer to the descriptor for the
> Notification
> + event that caused this function to execute.
> + @param[in] Ppi Pointer to the PPI data associated with this
> function.
> +
> + @retval EFI_SUCCESS The function completes successfully
> + @retval Others Cannot initialize Nvme controller from given
> EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmeHostControllerPpiInstallationCallback (
> + IN EFI_PEI_SERVICES **PeiServices,
> + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
> + IN VOID *Ppi
> + )
> +{
> + EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi;
> +
> + if (Ppi == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + NvmeHcPpi = (EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *)Ppi;
> +
> + return NvmeInitControllerFromHostControllerPpi (NvmeHcPpi); }
> +
> +/**
> + Entry point of the PEIM.
> +
> + @param[in] FileHandle Handle of the file being invoked.
> + @param[in] PeiServices Describes the list of possible PEI Services.
> +
> + @retval EFI_SUCCESS PPI successfully installed.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmExpressPeimEntry (
> + IN EFI_PEI_FILE_HANDLE FileHandle,
> + IN CONST EFI_PEI_SERVICES **PeiServices
> + )
> +{
> + DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
> +
> + PeiServicesNotifyPpi (&mNvmeHostControllerNotify);
> +
> + PeiServicesNotifyPpi (&mPciDevicePpiNotify);
> +
> + return EFI_SUCCESS;
> +}
> diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> index 78a6b7016503..12a7624099c0 100644
> --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> @@ -14,6 +14,7 @@
> #include <PiPei.h>
>
> #include <IndustryStandard/Nvme.h>
> +#include <IndustryStandard/Pci.h>
>
> #include <Ppi/NvmExpressHostController.h> #include <Ppi/BlockIo.h> @@
> -22,6 +23,7 @@ #include <Ppi/NvmExpressPassThru.h> #include
> <Ppi/IoMmu.h> #include <Ppi/EndOfPeiPhase.h>
> +#include <Ppi/PciDevice.h>
>
> #include <Library/DebugLib.h>
> #include <Library/PeiServicesLib.h>
> @@ -29,6 +31,7 @@
> #include <Library/BaseMemoryLib.h>
> #include <Library/IoLib.h>
> #include <Library/TimerLib.h>
> +#include <Library/DevicePathLib.h>
>
> //
> // Structure forward declarations
> @@ -36,6 +39,17 @@
> typedef struct _PEI_NVME_NAMESPACE_INFO
> PEI_NVME_NAMESPACE_INFO;
> typedef struct _PEI_NVME_CONTROLLER_PRIVATE_DATA
> PEI_NVME_CONTROLLER_PRIVATE_DATA;
>
> +/**
> + Macro that checks whether device is a NVMHCI Interface.
> +
> + @param _p Specified device.
> +
> + @retval TRUE Device is a NVMHCI Interface.
> + @retval FALSE Device is not a NVMHCI Interface.
> +
> +**/
> +#define IS_PCI_NVMHCI(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE,
> +PCI_CLASS_MASS_STORAGE_SOLID_STATE,
> +PCI_IF_MASS_STORAGE_SOLID_STATE_ENTERPRISE_NVMHCI)
> +
> #include "NvmExpressPeiHci.h"
> #include "NvmExpressPeiPassThru.h"
> #include "NvmExpressPeiBlockIo.h"
> @@ -345,4 +359,44 @@ NvmeS3SkipThisController (
> IN UINTN HcDevicePathLength
> );
>
> +/**
> + Callback for EDKII_PCI_DEVICE_PPI installation.
> +
> + @param[in] PeiServices Pointer to PEI Services Table.
> + @param[in] NotifyDescriptor Pointer to the descriptor for the
> Notification
> + event that caused this function to execute.
> + @param[in] Ppi Pointer to the PPI data associated with this
> function.
> +
> + @retval EFI_SUCCESS The function completes successfully
> + @retval Others Cannot initialize Nvme controller from given
> PCI_DEVICE_PPI
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmePciDevicePpiInstallationCallback (
> + IN EFI_PEI_SERVICES **PeiServices,
> + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
> + IN VOID *Ppi
> + );
> +
> +/**
> + Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
> +
> + @param[in] PeiServices Pointer to PEI Services Table.
> + @param[in] NotifyDescriptor Pointer to the descriptor for the
> Notification
> + event that caused this function to execute.
> + @param[in] Ppi Pointer to the PPI data associated with this
> function.
> +
> + @retval EFI_SUCCESS The function completes successfully
> + @retval Others Cannot initialize Nvme controller from given
> EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmeHostControllerPpiInstallationCallback (
> + IN EFI_PEI_SERVICES **PeiServices,
> + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
> + IN VOID *Ppi
> + );
> +
> #endif
> diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> index 4dd6c5704fa3..ba6f1afbf168 100644
> --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> @@ -44,6 +44,7 @@
>
> [LibraryClasses]
> DebugLib
> + DevicePathLib
> PeiServicesLib
> MemoryAllocationLib
> BaseMemoryLib
> @@ -56,6 +57,7 @@
> gEdkiiPeiNvmExpressHostControllerPpiGuid ## CONSUMES
> gEdkiiIoMmuPpiGuid ## CONSUMES
> gEfiEndOfPeiSignalPpiGuid ## CONSUMES
> + gEdkiiPeiPciDevicePpiGuid ## CONSUMES
> gEdkiiPeiNvmExpressPassThruPpiGuid ## SOMETIMES_PRODUCES
> gEfiPeiVirtualBlockIoPpiGuid ## SOMETIMES_PRODUCES
> gEfiPeiVirtualBlockIo2PpiGuid ## SOMETIMES_PRODUCES
> @@ -66,7 +68,6 @@
>
> [Depex]
> gEfiPeiMemoryDiscoveredPpiGuid AND
> - gEdkiiPeiNvmExpressHostControllerPpiGuid AND
> gEfiPeiMasterBootModePpiGuid
>
> [UserExtensions.TianoCore."ExtraFiles"]
> --
> 2.37.0.windows.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [edk2-devel] [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: Use PCI_DEVICE_PPI to manage Nvme device
2022-08-30 6:27 ` Wu, Hao A
@ 2022-09-01 5:33 ` Wu, Hao A
0 siblings, 0 replies; 4+ messages in thread
From: Wu, Hao A @ 2022-09-01 5:33 UTC (permalink / raw)
To: devel@edk2.groups.io, Wu, Hao A, Chen, Xiao X; +Cc: Ni, Ray
Patch merged via:
PR - https://github.com/tianocore/edk2/pull/3267
Commit - https://github.com/tianocore/edk2/commit/9ca7ece8b3b1743b6ee76f5f20f2c5eeed001d72
Best Regards,
Hao Wu
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Wu, Hao
> A
> Sent: Tuesday, August 30, 2022 2:27 PM
> To: Chen, Xiao X <xiao.x.chen@intel.com>; devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>
> Subject: Re: [edk2-devel] [PATCH v2 1/1] MdeModulePkg/NvmExpressPei:
> Use PCI_DEVICE_PPI to manage Nvme device
>
> Thanks.
> Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
>
> Will wait a couple of days before merging to see if comments from other
> reviewers.
>
> Best Regards,
> Hao Wu
>
> > -----Original Message-----
> > From: Chen, Xiao X <xiao.x.chen@intel.com>
> > Sent: Tuesday, August 30, 2022 1:47 PM
> > To: devel@edk2.groups.io
> > Cc: Chen, Xiao X <xiao.x.chen@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>; Ni, Ray <ray.ni@intel.com>
> > Subject: [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: Use
> PCI_DEVICE_PPI
> > to manage Nvme device
> >
> > https://bugzilla.tianocore.org/show_bug.cgi?id=4017
> >
> > This change modifies NvmExpressPei library to allow usage both
> > EDKII_PCI_DEVICE_PPI and EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
> > to manage Nvme device.
> >
> > Cc: Hao A Wu <hao.a.wu@intel.com>
> > Cc: Ray Ni <ray.ni@intel.com>
> > Signed-off-by: Xiao X Chen <xiao.x.chen@intel.com>
> > ---
> > .../Bus/Pci/NvmExpressPei/DevicePath.c | 44 --
> > .../Bus/Pci/NvmExpressPei/NvmExpressPei.c | 639 ++++++++++++------
> > .../Bus/Pci/NvmExpressPei/NvmExpressPei.h | 54 ++
> > .../Bus/Pci/NvmExpressPei/NvmExpressPei.inf | 3 +-
> > 4 files changed, 488 insertions(+), 252 deletions(-)
> >
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> > index 9b454a7dd8f4..307045be70ea 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> > @@ -37,50 +37,6 @@ EFI_DEVICE_PATH_PROTOCOL
> > mNvmeEndDevicePathNodeTemplate = {
> > }
> > };
> >
> > -/**
> > - Returns the 16-bit Length field of a device path node.
> > -
> > - Returns the 16-bit Length field of the device path node specified by Node.
> > - Node is not required to be aligned on a 16-bit boundary, so it is
> > recommended
> > - that a function such as ReadUnaligned16() be used to extract the
> > contents of
> > - the Length field.
> > -
> > - If Node is NULL, then ASSERT().
> > -
> > - @param Node A pointer to a device path node data structure.
> > -
> > - @return The 16-bit Length field of the device path node specified by
> Node.
> > -
> > -**/
> > -UINTN
> > -DevicePathNodeLength (
> > - IN CONST VOID *Node
> > - )
> > -{
> > - ASSERT (Node != NULL);
> > - return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL
> > *)(Node))->Length[0]); -}
> > -
> > -/**
> > - Returns a pointer to the next node in a device path.
> > -
> > - If Node is NULL, then ASSERT().
> > -
> > - @param Node A pointer to a device path node data structure.
> > -
> > - @return a pointer to the device path node that follows the device
> > path node
> > - specified by Node.
> > -
> > -**/
> > -EFI_DEVICE_PATH_PROTOCOL *
> > -NextDevicePathNode (
> > - IN CONST VOID *Node
> > - )
> > -{
> > - ASSERT (Node != NULL);
> > - return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) +
> > DevicePathNodeLength (Node)); -}
> > -
> > /**
> > Get the size of the current device path instance.
> >
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> > index 2d6a79028fcd..0d02c2785da7 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> > @@ -40,6 +40,18 @@ EFI_PEI_NOTIFY_DESCRIPTOR
> > mNvmeEndOfPeiNotifyListTemplate = {
> > NvmePeimEndOfPei
> > };
> >
> > +EFI_PEI_NOTIFY_DESCRIPTOR mNvmeHostControllerNotify = {
> > + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> > +EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> > + &gEdkiiPeiNvmExpressHostControllerPpiGuid,
> > + NvmeHostControllerPpiInstallationCallback
> > +};
> > +
> > +EFI_PEI_NOTIFY_DESCRIPTOR mPciDevicePpiNotify = {
> > + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> > +EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> > + &gEdkiiPeiPciDevicePpiGuid,
> > + NvmePciDevicePpiInstallationCallback
> > +};
> > +
> > /**
> > Check if the specified Nvm Express device namespace is active, and
> > then get the Identify
> > Namespace data.
> > @@ -212,30 +224,27 @@ NvmePeimEndOfPei ( }
> >
> > /**
> > - Entry point of the PEIM.
> > + Initialize and install PrivateData PPIs.
> >
> > - @param[in] FileHandle Handle of the file being invoked.
> > - @param[in] PeiServices Describes the list of possible PEI Services.
> > -
> > - @retval EFI_SUCCESS PPI successfully installed.
> > + @param[in] MmioBase MMIO base address of specific Nvme
> > controller
> > + @param[in] DevicePath A pointer to the
> > EFI_DEVICE_PATH_PROTOCOL
> > + structure.
> > + @param[in] DevicePathLength Length of the device path.
> >
> > + @retval EFI_SUCCESS Nvme controller initialized and PPIs installed
> > + @retval others Failed to initialize Nvme controller
> > **/
> > EFI_STATUS
> > -EFIAPI
> > -NvmExpressPeimEntry (
> > - IN EFI_PEI_FILE_HANDLE FileHandle,
> > - IN CONST EFI_PEI_SERVICES **PeiServices
> > +NvmeInitPrivateData (
> > + IN UINTN MmioBase,
> > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
> > + IN UINTN DevicePathLength
> > )
> > {
> > - EFI_STATUS Status;
> > - EFI_BOOT_MODE BootMode;
> > - EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi;
> > - UINT8 Controller;
> > - UINTN MmioBase;
> > - UINTN DevicePathLength;
> > - EFI_DEVICE_PATH_PROTOCOL *DevicePath;
> > - PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;
> > - EFI_PHYSICAL_ADDRESS DeviceAddress;
> > + EFI_STATUS Status;
> > + EFI_BOOT_MODE BootMode;
> > + PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;
> > + EFI_PHYSICAL_ADDRESS DeviceAddress;
> >
> > DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
> >
> > @@ -249,19 +258,358 @@ NvmExpressPeimEntry (
> > }
> >
> > //
> > - // Locate the NVME host controller PPI
> > + // Check validity of the device path of the NVM Express controller.
> > //
> > - Status = PeiServicesLocatePpi (
> > - &gEdkiiPeiNvmExpressHostControllerPpiGuid,
> > - 0,
> > - NULL,
> > - (VOID **)&NvmeHcPpi
> > + Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
> > + if (EFI_ERROR (Status)) {
> > + DEBUG ((
> > + DEBUG_ERROR,
> > + "%a: The device path is invalid for Controller %d.\n",
> > + __FUNCTION__
> > + ));
> > + return Status;
> > + }
> > +
> > + //
> > + // 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: skipped during S3.\n",
> > + __FUNCTION__
> > + ));
> > + return EFI_SUCCESS;
> > + }
> > +
> > + //
> > + // Memory allocation for controller private data // Private =
> > + AllocateZeroPool (sizeof (PEI_NVME_CONTROLLER_PRIVATE_DATA));
> > + if (Private == NULL) {
> > + DEBUG ((
> > + DEBUG_ERROR,
> > + "%a: Fail to allocate private data.\n",
> > + __FUNCTION__
> > + ));
> > + return EFI_OUT_OF_RESOURCES;
> > + }
> > +
> > + //
> > + // Memory allocation for transfer-related data // Status =
> > + IoMmuAllocateBuffer (
> > + NVME_MEM_MAX_PAGES,
> > + &Private->Buffer,
> > + &DeviceAddress,
> > + &Private->BufferMapping
> > );
> > if (EFI_ERROR (Status)) {
> > - DEBUG ((DEBUG_ERROR, "%a: Fail to locate NvmeHostControllerPpi.\n",
> > __FUNCTION__));
> > + DEBUG ((
> > + DEBUG_ERROR,
> > + "%a: Fail to allocate DMA buffers.\n",
> > + __FUNCTION__
> > + ));
> > + return Status;
> > + }
> > +
> > + ASSERT (DeviceAddress ==
> > + ((EFI_PHYSICAL_ADDRESS)(UINTN)Private->Buffer));
> > + DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n",
> > __FUNCTION__,
> > + Private->Buffer));
> > +
> > + //
> > + // Initialize controller private data //
> > + Private->Signature =
> > NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
> > + Private->MmioBase = MmioBase;
> > + Private->DevicePathLength = DevicePathLength;
> > + Private->DevicePath = DevicePath;
> > +
> > + //
> > + // Initialize the NVME controller
> > + //
> > + Status = NvmeControllerInit (Private); if (EFI_ERROR (Status)) {
> > + DEBUG ((
> > + DEBUG_ERROR,
> > + "%a: Controller initialization fail with Status - %r.\n",
> > + __FUNCTION__,
> > + Status
> > + ));
> > + NvmeFreeDmaResource (Private);
> > + return Status;
> > + }
> > +
> > + //
> > + // Enumerate the NVME namespaces on the controller // Status =
> > + NvmeDiscoverNamespaces (Private); if (EFI_ERROR (Status)) {
> > + //
> > + // No active namespace was found on the controller
> > + //
> > + DEBUG ((
> > + DEBUG_ERROR,
> > + "%a: Namespaces discovery fail with Status - %r.\n",
> > + __FUNCTION__,
> > + Status
> > + ));
> > + NvmeFreeDmaResource (Private);
> > + return Status;
> > + }
> > +
> > + //
> > + // Nvm Express Pass Thru PPI
> > + //
> > + Private->PassThruMode.Attributes =
> > EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
> > +
> > + EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL
> > |
> > +
> > EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
> > + Private->PassThruMode.IoAlign = sizeof (UINTN);
> > + Private->PassThruMode.NvmeVersion =
> > EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
> > + Private->NvmePassThruPpi.Mode = &Private->PassThruMode;
> > + Private->NvmePassThruPpi.GetDevicePath =
> > NvmePassThruGetDevicePath;
> > + Private->NvmePassThruPpi.GetNextNameSpace =
> > NvmePassThruGetNextNameSpace;
> > + Private->NvmePassThruPpi.PassThru = NvmePassThru;
> > + CopyMem (
> > + &Private->NvmePassThruPpiList,
> > + &mNvmePassThruPpiListTemplate,
> > + sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > + );
> > + Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
> > + PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
> > +
> > + //
> > + // Block Io PPI
> > + //
> > + Private->BlkIoPpi.GetNumberOfBlockDevices =
> > + NvmeBlockIoPeimGetDeviceNo; Private-
> > >BlkIoPpi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo;
> > + Private->BlkIoPpi.ReadBlocks = NvmeBlockIoPeimReadBlocks;
> > + CopyMem (
> > + &Private->BlkIoPpiList,
> > + &mNvmeBlkIoPpiListTemplate,
> > + sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > + );
> > + Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
> > +
> > + Private->BlkIo2Ppi.Revision =
> > EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
> > + Private->BlkIo2Ppi.GetNumberOfBlockDevices =
> > + NvmeBlockIoPeimGetDeviceNo2; Private-
> > >BlkIo2Ppi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo2;
> > + Private->BlkIo2Ppi.ReadBlocks = NvmeBlockIoPeimReadBlocks2;
> > + CopyMem (
> > + &Private->BlkIo2PpiList,
> > + &mNvmeBlkIo2PpiListTemplate,
> > + sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > + );
> > + Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
> > + PeiServicesInstallPpi (&Private->BlkIoPpiList);
> > +
> > + //
> > + // Check if the NVME controller supports the Security Receive/Send
> > + commands // if ((Private->ControllerData->Oacs &
> > + SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
> > + DEBUG ((
> > + DEBUG_INFO,
> > + "%a: Security Security Command PPI will be produced.\n",
> > + __FUNCTION__
> > + ));
> > + Private->StorageSecurityPpi.Revision =
> > EDKII_STORAGE_SECURITY_PPI_REVISION;
> > + Private->StorageSecurityPpi.GetNumberofDevices =
> > NvmeStorageSecurityGetDeviceNo;
> > + Private->StorageSecurityPpi.GetDevicePath =
> > NvmeStorageSecurityGetDevicePath;
> > + Private->StorageSecurityPpi.ReceiveData =
> > NvmeStorageSecurityReceiveData;
> > + Private->StorageSecurityPpi.SendData =
> > NvmeStorageSecuritySendData;
> > + CopyMem (
> > + &Private->StorageSecurityPpiList,
> > + &mNvmeStorageSecurityPpiListTemplate,
> > + sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > + );
> > + Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
> > + PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
> > + }
> > +
> > + CopyMem (
> > + &Private->EndOfPeiNotifyList,
> > + &mNvmeEndOfPeiNotifyListTemplate,
> > + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
> > + );
> > + PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > + Initialize Nvme controller from fiven PCI_DEVICE_PPI.
> > +
> > + @param[in] PciDevice Pointer to the PCI Device PPI instance.
> > +
> > + @retval EFI_SUCCESS The function completes successfully
> > + @retval Others Cannot initialize Nvme controller for given device
> > +**/
> > +EFI_STATUS
> > +NvmeInitControllerDataFromPciDevice (
> > + EDKII_PCI_DEVICE_PPI *PciDevice
> > + )
> > +{
> > + EFI_STATUS Status;
> > + PCI_TYPE00 PciData;
> > + UINTN MmioBase;
> > + EFI_DEVICE_PATH_PROTOCOL *DevicePath;
> > + UINTN DevicePathLength;
> > + UINT64 EnabledPciAttributes;
> > + UINT32 MmioBaseH;
> > +
> > + //
> > + // Now further check the PCI header: Base Class (offset 0x0B), Sub
> > + Class (offset 0x0A) and // Programming Interface (offset 0x09).
> > + This controller should be an Nvme controller // Status =
> > + PciDevice->PciIo.Pci.Read (
> > + &PciDevice->PciIo,
> > + EfiPciIoWidthUint8,
> > + PCI_CLASSCODE_OFFSET,
> > + sizeof (PciData.Hdr.ClassCode),
> > + PciData.Hdr.ClassCode
> > + );
> > + if (EFI_ERROR (Status)) {
> > + return EFI_UNSUPPORTED;
> > + }
> > +
> > + if (!IS_PCI_NVMHCI (&PciData)) {
> > return EFI_UNSUPPORTED;
> > }
> >
> > + Status = PciDevice->PciIo.Attributes (
> > + &PciDevice->PciIo,
> > + EfiPciIoAttributeOperationSupported,
> > + 0,
> > + &EnabledPciAttributes
> > + );
> > + if (EFI_ERROR (Status)) {
> > + return EFI_UNSUPPORTED;
> > + } else {
> > + EnabledPciAttributes &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > + Status = PciDevice->PciIo.Attributes (
> > + &PciDevice->PciIo,
> > + EfiPciIoAttributeOperationEnable,
> > + EnabledPciAttributes,
> > + NULL
> > + );
> > + if (EFI_ERROR (Status)) {
> > + return EFI_UNSUPPORTED;
> > + }
> > + }
> > +
> > + Status = PciDevice->PciIo.Pci.Read (
> > + &PciDevice->PciIo,
> > + EfiPciIoWidthUint32,
> > + PCI_BASE_ADDRESSREG_OFFSET,
> > + 1,
> > + &MmioBase
> > + );
> > + if (EFI_ERROR (Status)) {
> > + return EFI_UNSUPPORTED;
> > + }
> > +
> > + switch (MmioBase & 0x07) {
> > + case 0x0:
> > + //
> > + // Memory space for 32 bit bar address
> > + //
> > + MmioBase = MmioBase & 0xFFFFFFF0;
> > + break;
> > + case 0x4:
> > + //
> > + // For 64 bit bar address, read the high 32bits of this 64 bit bar
> > + //
> > + Status = PciDevice->PciIo.Pci.Read (
> > + &PciDevice->PciIo,
> > + EfiPciIoWidthUint32,
> > + PCI_BASE_ADDRESSREG_OFFSET + 4,
> > + 1,
> > + &MmioBaseH
> > + );
> > + //
> > + // For 32 bit environment, high 32bits of the bar should be zero.
> > + //
> > + if ( EFI_ERROR (Status)
> > + || ((MmioBaseH != 0) && (sizeof (UINTN) == sizeof (UINT32))))
> > + {
> > + return EFI_UNSUPPORTED;
> > + }
> > +
> > + MmioBase = MmioBase & 0xFFFFFFF0;
> > + MmioBase |= LShiftU64 ((UINT64)MmioBaseH, 32);
> > + break;
> > + default:
> > + //
> > + // Unknown bar type
> > + //
> > + return EFI_UNSUPPORTED;
> > + }
> > +
> > + DevicePathLength = GetDevicePathSize (PciDevice->DevicePath);
> > + DevicePath = PciDevice->DevicePath;
> > +
> > + Status = NvmeInitPrivateData (MmioBase, DevicePath,
> > + DevicePathLength); if (EFI_ERROR (Status)) {
> > + DEBUG ((
> > + DEBUG_INFO,
> > + "%a: Failed to init controller, with Status - %r\n",
> > + __FUNCTION__,
> > + Status
> > + ));
> > + }
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > + Callback for EDKII_PCI_DEVICE_PPI installation.
> > +
> > + @param[in] PeiServices Pointer to PEI Services Table.
> > + @param[in] NotifyDescriptor Pointer to the descriptor for the
> > Notification
> > + event that caused this function to execute.
> > + @param[in] Ppi Pointer to the PPI data associated with this
> > function.
> > +
> > + @retval EFI_SUCCESS The function completes successfully
> > + @retval Others Cannot initialize Nvme controller from given
> > PCI_DEVICE_PPI
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmePciDevicePpiInstallationCallback (
> > + IN EFI_PEI_SERVICES **PeiServices,
> > + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
> > + IN VOID *Ppi
> > + )
> > +{
> > + EDKII_PCI_DEVICE_PPI *PciDevice;
> > +
> > + PciDevice = (EDKII_PCI_DEVICE_PPI *)Ppi;
> > +
> > + return NvmeInitControllerDataFromPciDevice (PciDevice); }
> > +
> > +/**
> > + Initialize Nvme controller from
> > EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI instance.
> > +
> > + @param[in] NvmeHcPpi Pointer to the Nvme Host Controller PPI
> instance.
> > +
> > + @retval EFI_SUCCESS PPI successfully installed.
> > +**/
> > +EFI_STATUS
> > +NvmeInitControllerFromHostControllerPpi (
> > + IN EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi
> > + )
> > +{
> > + UINT8 Controller;
> > + UINTN MmioBase;
> > + UINTN DevicePathLength;
> > + EFI_DEVICE_PATH_PROTOCOL *DevicePath;
> > + EFI_STATUS Status;
> > +
> > Controller = 0;
> > MmioBase = 0;
> > while (TRUE) {
> > @@ -293,88 +641,7 @@ NvmExpressPeimEntry (
> > return Status;
> > }
> >
> > - //
> > - // Check validity of the device path of the NVM Express controller.
> > - //
> > - Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
> > - if (EFI_ERROR (Status)) {
> > - DEBUG ((
> > - DEBUG_ERROR,
> > - "%a: The device path is invalid for Controller %d.\n",
> > - __FUNCTION__,
> > - Controller
> > - ));
> > - Controller++;
> > - 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
> > - //
> > - Private = AllocateZeroPool (sizeof
> > (PEI_NVME_CONTROLLER_PRIVATE_DATA));
> > - if (Private == NULL) {
> > - DEBUG ((
> > - DEBUG_ERROR,
> > - "%a: Fail to allocate private data for Controller %d.\n",
> > - __FUNCTION__,
> > - Controller
> > - ));
> > - return EFI_OUT_OF_RESOURCES;
> > - }
> > -
> > - //
> > - // Memory allocation for transfer-related data
> > - //
> > - Status = IoMmuAllocateBuffer (
> > - NVME_MEM_MAX_PAGES,
> > - &Private->Buffer,
> > - &DeviceAddress,
> > - &Private->BufferMapping
> > - );
> > - if (EFI_ERROR (Status)) {
> > - DEBUG ((
> > - DEBUG_ERROR,
> > - "%a: Fail to allocate DMA buffers for Controller %d.\n",
> > - __FUNCTION__,
> > - Controller
> > - ));
> > - return Status;
> > - }
> > -
> > - ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)Private-
> > >Buffer));
> > - DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n",
> > __FUNCTION__, Private->Buffer));
> > -
> > - //
> > - // Initialize controller private data
> > - //
> > - Private->Signature =
> > NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
> > - Private->MmioBase = MmioBase;
> > - Private->DevicePathLength = DevicePathLength;
> > - Private->DevicePath = DevicePath;
> > -
> > - //
> > - // Initialize the NVME controller
> > - //
> > - Status = NvmeControllerInit (Private);
> > + Status = NvmeInitPrivateData (MmioBase, DevicePath,
> > + DevicePathLength);
> > if (EFI_ERROR (Status)) {
> > DEBUG ((
> > DEBUG_ERROR,
> > @@ -383,115 +650,73 @@ NvmExpressPeimEntry (
> > Controller,
> > Status
> > ));
> > - NvmeFreeDmaResource (Private);
> > - Controller++;
> > - continue;
> > - }
> > -
> > - //
> > - // Enumerate the NVME namespaces on the controller
> > - //
> > - Status = NvmeDiscoverNamespaces (Private);
> > - if (EFI_ERROR (Status)) {
> > - //
> > - // No active namespace was found on the controller
> > - //
> > - DEBUG ((
> > - DEBUG_ERROR,
> > - "%a: Namespaces discovery fail for Controller %d with Status - %r.\n",
> > - __FUNCTION__,
> > - Controller,
> > - Status
> > - ));
> > - NvmeFreeDmaResource (Private);
> > - Controller++;
> > - continue;
> > - }
> > -
> > - //
> > - // Nvm Express Pass Thru PPI
> > - //
> > - Private->PassThruMode.Attributes =
> > EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
> > -
> EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL
> > |
> > -
> > EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
> > - Private->PassThruMode.IoAlign = sizeof (UINTN);
> > - Private->PassThruMode.NvmeVersion =
> > EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
> > - Private->NvmePassThruPpi.Mode = &Private->PassThruMode;
> > - Private->NvmePassThruPpi.GetDevicePath =
> > NvmePassThruGetDevicePath;
> > - Private->NvmePassThruPpi.GetNextNameSpace =
> > NvmePassThruGetNextNameSpace;
> > - Private->NvmePassThruPpi.PassThru = NvmePassThru;
> > - CopyMem (
> > - &Private->NvmePassThruPpiList,
> > - &mNvmePassThruPpiListTemplate,
> > - sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > - );
> > - Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
> > - PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
> > -
> > - //
> > - // Block Io PPI
> > - //
> > - Private->BlkIoPpi.GetNumberOfBlockDevices =
> > NvmeBlockIoPeimGetDeviceNo;
> > - Private->BlkIoPpi.GetBlockDeviceMediaInfo =
> > NvmeBlockIoPeimGetMediaInfo;
> > - Private->BlkIoPpi.ReadBlocks = NvmeBlockIoPeimReadBlocks;
> > - CopyMem (
> > - &Private->BlkIoPpiList,
> > - &mNvmeBlkIoPpiListTemplate,
> > - sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > - );
> > - Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
> > -
> > - Private->BlkIo2Ppi.Revision =
> > EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
> > - Private->BlkIo2Ppi.GetNumberOfBlockDevices =
> > NvmeBlockIoPeimGetDeviceNo2;
> > - Private->BlkIo2Ppi.GetBlockDeviceMediaInfo =
> > NvmeBlockIoPeimGetMediaInfo2;
> > - Private->BlkIo2Ppi.ReadBlocks = NvmeBlockIoPeimReadBlocks2;
> > - CopyMem (
> > - &Private->BlkIo2PpiList,
> > - &mNvmeBlkIo2PpiListTemplate,
> > - sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > - );
> > - Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
> > - PeiServicesInstallPpi (&Private->BlkIoPpiList);
> > -
> > - //
> > - // Check if the NVME controller supports the Security Receive/Send
> > commands
> > - //
> > - if ((Private->ControllerData->Oacs &
> > SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
> > + } else {
> > DEBUG ((
> > DEBUG_INFO,
> > - "%a: Security Security Command PPI will be produced for
> > Controller %d.\n",
> > + "%a: Controller %d has been successfully initialized.\n",
> > __FUNCTION__,
> > Controller
> > ));
> > - Private->StorageSecurityPpi.Revision =
> > EDKII_STORAGE_SECURITY_PPI_REVISION;
> > - Private->StorageSecurityPpi.GetNumberofDevices =
> > NvmeStorageSecurityGetDeviceNo;
> > - Private->StorageSecurityPpi.GetDevicePath =
> > NvmeStorageSecurityGetDevicePath;
> > - Private->StorageSecurityPpi.ReceiveData =
> > NvmeStorageSecurityReceiveData;
> > - Private->StorageSecurityPpi.SendData =
> > NvmeStorageSecuritySendData;
> > - CopyMem (
> > - &Private->StorageSecurityPpiList,
> > - &mNvmeStorageSecurityPpiListTemplate,
> > - sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > - );
> > - Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
> > - PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
> > }
> >
> > - CopyMem (
> > - &Private->EndOfPeiNotifyList,
> > - &mNvmeEndOfPeiNotifyListTemplate,
> > - sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
> > - );
> > - PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
> > -
> > - DEBUG ((
> > - DEBUG_INFO,
> > - "%a: Controller %d has been successfully initialized.\n",
> > - __FUNCTION__,
> > - Controller
> > - ));
> > Controller++;
> > }
> >
> > return EFI_SUCCESS;
> > }
> > +
> > +/**
> > + Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
> > +
> > + @param[in] PeiServices Pointer to PEI Services Table.
> > + @param[in] NotifyDescriptor Pointer to the descriptor for the
> > Notification
> > + event that caused this function to execute.
> > + @param[in] Ppi Pointer to the PPI data associated with this
> > function.
> > +
> > + @retval EFI_SUCCESS The function completes successfully
> > + @retval Others Cannot initialize Nvme controller from given
> > EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmeHostControllerPpiInstallationCallback (
> > + IN EFI_PEI_SERVICES **PeiServices,
> > + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
> > + IN VOID *Ppi
> > + )
> > +{
> > + EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi;
> > +
> > + if (Ppi == NULL) {
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + NvmeHcPpi = (EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *)Ppi;
> > +
> > + return NvmeInitControllerFromHostControllerPpi (NvmeHcPpi); }
> > +
> > +/**
> > + Entry point of the PEIM.
> > +
> > + @param[in] FileHandle Handle of the file being invoked.
> > + @param[in] PeiServices Describes the list of possible PEI Services.
> > +
> > + @retval EFI_SUCCESS PPI successfully installed.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmExpressPeimEntry (
> > + IN EFI_PEI_FILE_HANDLE FileHandle,
> > + IN CONST EFI_PEI_SERVICES **PeiServices
> > + )
> > +{
> > + DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
> > +
> > + PeiServicesNotifyPpi (&mNvmeHostControllerNotify);
> > +
> > + PeiServicesNotifyPpi (&mPciDevicePpiNotify);
> > +
> > + return EFI_SUCCESS;
> > +}
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> > index 78a6b7016503..12a7624099c0 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> > @@ -14,6 +14,7 @@
> > #include <PiPei.h>
> >
> > #include <IndustryStandard/Nvme.h>
> > +#include <IndustryStandard/Pci.h>
> >
> > #include <Ppi/NvmExpressHostController.h> #include <Ppi/BlockIo.h>
> > @@
> > -22,6 +23,7 @@ #include <Ppi/NvmExpressPassThru.h> #include
> > <Ppi/IoMmu.h> #include <Ppi/EndOfPeiPhase.h>
> > +#include <Ppi/PciDevice.h>
> >
> > #include <Library/DebugLib.h>
> > #include <Library/PeiServicesLib.h>
> > @@ -29,6 +31,7 @@
> > #include <Library/BaseMemoryLib.h>
> > #include <Library/IoLib.h>
> > #include <Library/TimerLib.h>
> > +#include <Library/DevicePathLib.h>
> >
> > //
> > // Structure forward declarations
> > @@ -36,6 +39,17 @@
> > typedef struct _PEI_NVME_NAMESPACE_INFO
> PEI_NVME_NAMESPACE_INFO;
> > typedef struct _PEI_NVME_CONTROLLER_PRIVATE_DATA
> > PEI_NVME_CONTROLLER_PRIVATE_DATA;
> >
> > +/**
> > + Macro that checks whether device is a NVMHCI Interface.
> > +
> > + @param _p Specified device.
> > +
> > + @retval TRUE Device is a NVMHCI Interface.
> > + @retval FALSE Device is not a NVMHCI Interface.
> > +
> > +**/
> > +#define IS_PCI_NVMHCI(_p) IS_CLASS3 (_p,
> PCI_CLASS_MASS_STORAGE,
> > +PCI_CLASS_MASS_STORAGE_SOLID_STATE,
> > +PCI_IF_MASS_STORAGE_SOLID_STATE_ENTERPRISE_NVMHCI)
> > +
> > #include "NvmExpressPeiHci.h"
> > #include "NvmExpressPeiPassThru.h"
> > #include "NvmExpressPeiBlockIo.h"
> > @@ -345,4 +359,44 @@ NvmeS3SkipThisController (
> > IN UINTN HcDevicePathLength
> > );
> >
> > +/**
> > + Callback for EDKII_PCI_DEVICE_PPI installation.
> > +
> > + @param[in] PeiServices Pointer to PEI Services Table.
> > + @param[in] NotifyDescriptor Pointer to the descriptor for the
> > Notification
> > + event that caused this function to execute.
> > + @param[in] Ppi Pointer to the PPI data associated with this
> > function.
> > +
> > + @retval EFI_SUCCESS The function completes successfully
> > + @retval Others Cannot initialize Nvme controller from given
> > PCI_DEVICE_PPI
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmePciDevicePpiInstallationCallback (
> > + IN EFI_PEI_SERVICES **PeiServices,
> > + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
> > + IN VOID *Ppi
> > + );
> > +
> > +/**
> > + Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
> > +
> > + @param[in] PeiServices Pointer to PEI Services Table.
> > + @param[in] NotifyDescriptor Pointer to the descriptor for the
> > Notification
> > + event that caused this function to execute.
> > + @param[in] Ppi Pointer to the PPI data associated with this
> > function.
> > +
> > + @retval EFI_SUCCESS The function completes successfully
> > + @retval Others Cannot initialize Nvme controller from given
> > EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmeHostControllerPpiInstallationCallback (
> > + IN EFI_PEI_SERVICES **PeiServices,
> > + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
> > + IN VOID *Ppi
> > + );
> > +
> > #endif
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> > index 4dd6c5704fa3..ba6f1afbf168 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> > @@ -44,6 +44,7 @@
> >
> > [LibraryClasses]
> > DebugLib
> > + DevicePathLib
> > PeiServicesLib
> > MemoryAllocationLib
> > BaseMemoryLib
> > @@ -56,6 +57,7 @@
> > gEdkiiPeiNvmExpressHostControllerPpiGuid ## CONSUMES
> > gEdkiiIoMmuPpiGuid ## CONSUMES
> > gEfiEndOfPeiSignalPpiGuid ## CONSUMES
> > + gEdkiiPeiPciDevicePpiGuid ## CONSUMES
> > gEdkiiPeiNvmExpressPassThruPpiGuid ## SOMETIMES_PRODUCES
> > gEfiPeiVirtualBlockIoPpiGuid ## SOMETIMES_PRODUCES
> > gEfiPeiVirtualBlockIo2PpiGuid ## SOMETIMES_PRODUCES
> > @@ -66,7 +68,6 @@
> >
> > [Depex]
> > gEfiPeiMemoryDiscoveredPpiGuid AND
> > - gEdkiiPeiNvmExpressHostControllerPpiGuid AND
> > gEfiPeiMasterBootModePpiGuid
> >
> > [UserExtensions.TianoCore."ExtraFiles"]
> > --
> > 2.37.0.windows.1
>
>
>
>
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-09-01 5:33 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-08-30 5:46 [PATCH v2 0/1] Use PCI_DEVICE_PPI to manage Nvme device chenxia1
2022-08-30 5:46 ` [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: " chenxia1
2022-08-30 6:27 ` Wu, Hao A
2022-09-01 5:33 ` [edk2-devel] " Wu, Hao A
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox