summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg
diff options
context:
space:
mode:
authorChen, Xiao X <xiao.x.chen@intel.com>2022-08-30 13:46:48 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2022-09-01 05:32:08 +0000
commit9ca7ece8b3b1743b6ee76f5f20f2c5eeed001d72 (patch)
tree71ee55dbc3e6d09f445d6591dbadb793bd09595f /MdeModulePkg
parent31a94f7fba2a2c1244fc35b6f631e235e267715b (diff)
downloadedk2-9ca7ece8b3b1743b6ee76f5f20f2c5eeed001d72.tar.gz
edk2-9ca7ece8b3b1743b6ee76f5f20f2c5eeed001d72.tar.bz2
edk2-9ca7ece8b3b1743b6ee76f5f20f2c5eeed001d72.zip
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> Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c44
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c629
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h54
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf3
4 files changed, 483 insertions, 247 deletions
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
index 9b454a7dd8..307045be70 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
@@ -38,50 +38,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.
@param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
index 2d6a79028f..0d02c2785d 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,205 +641,82 @@ NvmExpressPeimEntry (
return Status;
}
- //
- // Check validity of the device path of the NVM Express controller.
- //
- Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
+ Status = NvmeInitPrivateData (MmioBase, DevicePath, DevicePathLength);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
- "%a: The device path is invalid for Controller %d.\n",
+ "%a: Controller initialization fail for Controller %d with Status - %r.\n",
__FUNCTION__,
- Controller
+ Controller,
+ Status
));
- 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)))
- {
+ } else {
DEBUG ((
- DEBUG_ERROR,
- "%a: Controller %d is skipped during S3.\n",
+ DEBUG_INFO,
+ "%a: Controller %d has been successfully initialized.\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;
- }
+ Controller++;
+ }
- //
- // 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;
- }
+ return EFI_SUCCESS;
+}
- ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)Private->Buffer));
- DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n", __FUNCTION__, Private->Buffer));
+/**
+ Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
- //
- // Initialize controller private data
- //
- Private->Signature = NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
- Private->MmioBase = MmioBase;
- Private->DevicePathLength = DevicePathLength;
- Private->DevicePath = DevicePath;
+ @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.
- //
- // Initialize the NVME controller
- //
- Status = NvmeControllerInit (Private);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: Controller initialization fail for Controller %d with Status - %r.\n",
- __FUNCTION__,
- Controller,
- Status
- ));
- NvmeFreeDmaResource (Private);
- Controller++;
- continue;
- }
+ @retval EFI_SUCCESS The function completes successfully
+ @retval Others Cannot initialize Nvme controller from given EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
- //
- // 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;
- }
+**/
+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;
- //
- // 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);
+ if (Ppi == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
- //
- // 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;
+ NvmeHcPpi = (EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *)Ppi;
- 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);
+ return NvmeInitControllerFromHostControllerPpi (NvmeHcPpi);
+}
- //
- // 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 for Controller %d.\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);
- }
+/**
+ Entry point of the PEIM.
- CopyMem (
- &Private->EndOfPeiNotifyList,
- &mNvmeEndOfPeiNotifyListTemplate,
- sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
- );
- PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
+ @param[in] FileHandle Handle of the file being invoked.
+ @param[in] PeiServices Describes the list of possible PEI Services.
- DEBUG ((
- DEBUG_INFO,
- "%a: Controller %d has been successfully initialized.\n",
- __FUNCTION__,
- Controller
- ));
- Controller++;
- }
+ @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 78a6b70165..12a7624099 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 4dd6c5704f..ba6f1afbf1 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"]