* [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