From: Maggie Chu Date: Mon, 17 Jun 2019 02:11:26 +0000 (+0800) Subject: MdeModulePkg/NvmExpressPei: Produce NVM Express PassThru PPI X-Git-Tag: edk2-stable201908~369 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=ba3aa1c4e727feef36cdaa28ea1c49f7a9f3d081 MdeModulePkg/NvmExpressPei: Produce NVM Express PassThru PPI https://bugzilla.tianocore.org/show_bug.cgi?id=1879 This commit will add codes to produce the NVM Express PassThru PPI. Signed-off-by: Maggie Chu Reviewed-by: Hao A Wu Cc: Jian J Wang Cc: Ray Ni Cc: Star Zeng --- diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c index 0e79b29f82..987eed420e 100644 --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c @@ -28,6 +28,12 @@ EFI_PEI_PPI_DESCRIPTOR mNvmeStorageSecurityPpiListTemplate = { NULL }; +EFI_PEI_PPI_DESCRIPTOR mNvmePassThruPpiListTemplate = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEdkiiPeiNvmExpressPassThruPpiGuid, + NULL +}; + EFI_PEI_NOTIFY_DESCRIPTOR mNvmeEndOfPeiNotifyListTemplate = { (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), &gEfiEndOfPeiSignalPpiGuid, @@ -392,6 +398,26 @@ NvmExpressPeimEntry ( Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi; PeiServicesInstallPpi (&Private->BlkIoPpiList); + // + // 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); + // // Check if the NVME controller supports the Security Receive/Send commands // diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h index 6b2e2f0326..8cd905191b 100644 --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -74,6 +75,8 @@ struct _PEI_NVME_NAMESPACE_INFO { PEI_NVME_CONTROLLER_PRIVATE_DATA *Controller; }; +#define NVME_CONTROLLER_NSID 0 + // // Unique signature for private data structure. // @@ -85,15 +88,18 @@ struct _PEI_NVME_NAMESPACE_INFO { struct _PEI_NVME_CONTROLLER_PRIVATE_DATA { UINT32 Signature; UINTN MmioBase; + EFI_NVM_EXPRESS_PASS_THRU_MODE PassThruMode; UINTN DevicePathLength; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_PEI_RECOVERY_BLOCK_IO_PPI BlkIoPpi; EFI_PEI_RECOVERY_BLOCK_IO2_PPI BlkIo2Ppi; EDKII_PEI_STORAGE_SECURITY_CMD_PPI StorageSecurityPpi; + EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI NvmePassThruPpi; EFI_PEI_PPI_DESCRIPTOR BlkIoPpiList; EFI_PEI_PPI_DESCRIPTOR BlkIo2PpiList; EFI_PEI_PPI_DESCRIPTOR StorageSecurityPpiList; + EFI_PEI_PPI_DESCRIPTOR NvmePassThruPpiList; EFI_PEI_NOTIFY_DESCRIPTOR EndOfPeiNotifyList; // @@ -145,6 +151,8 @@ struct _PEI_NVME_CONTROLLER_PRIVATE_DATA { CR (a, PEI_NVME_CONTROLLER_PRIVATE_DATA, BlkIo2Ppi, NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE) #define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY(a) \ CR (a, PEI_NVME_CONTROLLER_PRIVATE_DATA, StorageSecurityPpi, NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE) +#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NVME_PASSTHRU(a) \ + CR (a, PEI_NVME_CONTROLLER_PRIVATE_DATA, NvmePassThruPpi, NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE) #define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY(a) \ CR (a, PEI_NVME_CONTROLLER_PRIVATE_DATA, EndOfPeiNotifyList, NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE) diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf index a8e4808e6b..4dd6c5704f 100644 --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf @@ -56,6 +56,7 @@ gEdkiiPeiNvmExpressHostControllerPpiGuid ## CONSUMES gEdkiiIoMmuPpiGuid ## CONSUMES gEfiEndOfPeiSignalPpiGuid ## CONSUMES + gEdkiiPeiNvmExpressPassThruPpiGuid ## SOMETIMES_PRODUCES gEfiPeiVirtualBlockIoPpiGuid ## SOMETIMES_PRODUCES gEfiPeiVirtualBlockIo2PpiGuid ## SOMETIMES_PRODUCES gEdkiiPeiStorageSecurityCommandPpiGuid ## SOMETIMES_PRODUCES diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiBlockIo.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiBlockIo.c index 94cdd05f33..a9bf4f8190 100644 --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiBlockIo.c +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiBlockIo.c @@ -2,7 +2,7 @@ The NvmExpressPei driver is used to manage non-volatile memory subsystem which follows NVM Express specification at PEI phase. - Copyright (c) 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -34,17 +34,19 @@ ReadSectors ( UINT32 BlockSize; PEI_NVME_CONTROLLER_PRIVATE_DATA *Private; UINT32 Bytes; - EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EDKII_PEI_NVM_EXPRESS_COMMAND Command; - EDKII_PEI_NVM_EXPRESS_COMPLETION Completion; + EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; + EFI_NVM_EXPRESS_COMMAND Command; + EFI_NVM_EXPRESS_COMPLETION Completion; + EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI *NvmePassThru; Private = NamespaceInfo->Controller; + NvmePassThru = &Private->NvmePassThruPpi; BlockSize = NamespaceInfo->Media.BlockSize; Bytes = Blocks * BlockSize; - ZeroMem (&CommandPacket, sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); - ZeroMem (&Command, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND)); - ZeroMem (&Completion, sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION)); + ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); + ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND)); + ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION)); CommandPacket.NvmeCmd = &Command; CommandPacket.NvmeCompletion = &Completion; @@ -63,11 +65,12 @@ ReadSectors ( CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID; - Status = NvmePassThru ( - Private, - NamespaceInfo->NamespaceId, - &CommandPacket - ); + Status = NvmePassThru->PassThru ( + NvmePassThru, + NamespaceInfo->NamespaceId, + &CommandPacket + ); + return Status; } diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.c index c290f5b56f..1d7e3d26e0 100644 --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.c +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.c @@ -320,14 +320,14 @@ NvmeIdentifyController ( IN VOID *Buffer ) { - EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EDKII_PEI_NVM_EXPRESS_COMMAND Command; - EDKII_PEI_NVM_EXPRESS_COMPLETION Completion; - EFI_STATUS Status; + EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; + EFI_NVM_EXPRESS_COMMAND Command; + EFI_NVM_EXPRESS_COMPLETION Completion; + EFI_STATUS Status; - ZeroMem (&CommandPacket, sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); - ZeroMem (&Command, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND)); - ZeroMem (&Completion, sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION)); + ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); + ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND)); + ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION)); Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD; // @@ -348,7 +348,7 @@ NvmeIdentifyController ( CommandPacket.NvmeCmd->Cdw10 = 1; CommandPacket.NvmeCmd->Flags = CDW10_VALID; - Status = NvmePassThru ( + Status = NvmePassThruExecute ( Private, NVME_CONTROLLER_NSID, &CommandPacket @@ -374,14 +374,14 @@ NvmeIdentifyNamespace ( IN VOID *Buffer ) { - EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EDKII_PEI_NVM_EXPRESS_COMMAND Command; - EDKII_PEI_NVM_EXPRESS_COMPLETION Completion; - EFI_STATUS Status; + EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; + EFI_NVM_EXPRESS_COMMAND Command; + EFI_NVM_EXPRESS_COMPLETION Completion; + EFI_STATUS Status; - ZeroMem (&CommandPacket, sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); - ZeroMem (&Command, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND)); - ZeroMem (&Completion, sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION)); + ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); + ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND)); + ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION)); Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD; Command.Nsid = NamespaceId; @@ -398,7 +398,7 @@ NvmeIdentifyNamespace ( CommandPacket.NvmeCmd->Cdw10 = 0; CommandPacket.NvmeCmd->Flags = CDW10_VALID; - Status = NvmePassThru ( + Status = NvmePassThruExecute ( Private, NamespaceId, &CommandPacket @@ -454,22 +454,21 @@ NvmeCreateIoCompletionQueue ( IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private ) { - EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EDKII_PEI_NVM_EXPRESS_COMMAND Command; - EDKII_PEI_NVM_EXPRESS_COMPLETION Completion; - EFI_STATUS Status; - NVME_ADMIN_CRIOCQ CrIoCq; - - ZeroMem (&CommandPacket, sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); - ZeroMem (&Command, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND)); - ZeroMem (&Completion, sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION)); + EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; + EFI_NVM_EXPRESS_COMMAND Command; + EFI_NVM_EXPRESS_COMPLETION Completion; + EFI_STATUS Status; + NVME_ADMIN_CRIOCQ CrIoCq; + + ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); + ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND)); + ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION)); ZeroMem (&CrIoCq, sizeof(NVME_ADMIN_CRIOCQ)); CommandPacket.NvmeCmd = &Command; CommandPacket.NvmeCompletion = &Completion; Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_CMD; - Command.Cdw0.Cid = Private->Cid[NVME_ADMIN_QUEUE]++; CommandPacket.TransferBuffer = Private->CqBuffer[NVME_IO_QUEUE]; CommandPacket.TransferLength = EFI_PAGE_SIZE; CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT; @@ -481,7 +480,7 @@ NvmeCreateIoCompletionQueue ( CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof (NVME_ADMIN_CRIOCQ)); CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID; - Status = NvmePassThru ( + Status = NvmePassThruExecute ( Private, NVME_CONTROLLER_NSID, &CommandPacket @@ -503,22 +502,21 @@ NvmeCreateIoSubmissionQueue ( IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private ) { - EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EDKII_PEI_NVM_EXPRESS_COMMAND Command; - EDKII_PEI_NVM_EXPRESS_COMPLETION Completion; - EFI_STATUS Status; - NVME_ADMIN_CRIOSQ CrIoSq; - - ZeroMem (&CommandPacket, sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); - ZeroMem (&Command, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND)); - ZeroMem (&Completion, sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION)); + EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; + EFI_NVM_EXPRESS_COMMAND Command; + EFI_NVM_EXPRESS_COMPLETION Completion; + EFI_STATUS Status; + NVME_ADMIN_CRIOSQ CrIoSq; + + ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); + ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND)); + ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION)); ZeroMem (&CrIoSq, sizeof(NVME_ADMIN_CRIOSQ)); CommandPacket.NvmeCmd = &Command; CommandPacket.NvmeCompletion = &Completion; Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_CMD; - Command.Cdw0.Cid = Private->Cid[NVME_ADMIN_QUEUE]++; CommandPacket.TransferBuffer = Private->SqBuffer[NVME_IO_QUEUE]; CommandPacket.TransferLength = EFI_PAGE_SIZE; CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT; @@ -532,7 +530,7 @@ NvmeCreateIoSubmissionQueue ( CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof (NVME_ADMIN_CRIOSQ)); CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID; - Status = NvmePassThru ( + Status = NvmePassThruExecute ( Private, NVME_CONTROLLER_NSID, &CommandPacket diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiPassThru.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiPassThru.c index a33f5a872e..370a54e5a2 100644 --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiPassThru.c +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiPassThru.c @@ -2,7 +2,7 @@ The NvmExpressPei driver is used to manage non-volatile memory subsystem which follows NVM Express specification at PEI phase. - Copyright (c) 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -332,10 +332,10 @@ NvmeCheckCqStatus ( **/ EFI_STATUS -NvmePassThru ( +NvmePassThruExecute ( IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private, IN UINT32 NamespaceId, - IN OUT EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet + IN OUT EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet ) { EFI_STATUS Status; @@ -411,9 +411,9 @@ NvmePassThru ( } ZeroMem (Sq, sizeof (NVME_SQ)); - Sq->Opc = Packet->NvmeCmd->Cdw0.Opcode; - Sq->Fuse = Packet->NvmeCmd->Cdw0.FusedOperation; - Sq->Cid = Packet->NvmeCmd->Cdw0.Cid; + Sq->Opc = (UINT8)Packet->NvmeCmd->Cdw0.Opcode; + Sq->Fuse = (UINT8)Packet->NvmeCmd->Cdw0.FusedOperation; + Sq->Cid = Private->Cid[QueueId]++;; Sq->Nsid = Packet->NvmeCmd->Nsid; // @@ -603,7 +603,7 @@ NvmePassThru ( // // Copy the Respose Queue entry for this command to the callers response buffer // - CopyMem (Packet->NvmeCompletion, Cq, sizeof (EDKII_PEI_NVM_EXPRESS_COMPLETION)); + CopyMem (Packet->NvmeCompletion, Cq, sizeof (EFI_NVM_EXPRESS_COMPLETION)); // // Check the NVMe cmd execution result @@ -622,3 +622,207 @@ Exit: return Status; } + +/** + Gets the device path information of the underlying NVM Express host controller. + + @param[in] This The PPI instance pointer. + @param[out] DevicePathLength The length of the device path in bytes specified + by DevicePath. + @param[out] DevicePath The device path of the underlying NVM Express + host controller. + This field re-uses EFI Device Path Protocol as + defined by Section 10.2 EFI Device Path Protocol + of UEFI 2.7 Specification. + + @retval EFI_SUCCESS The operation succeeds. + @retval EFI_INVALID_PARAMETER DevicePathLength or DevicePath is NULL. + @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources. + +**/ +EFI_STATUS +EFIAPI +NvmePassThruGetDevicePath ( + IN EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI *This, + OUT UINTN *DevicePathLength, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + PEI_NVME_CONTROLLER_PRIVATE_DATA *Private; + + if (This == NULL || DevicePathLength == NULL || DevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NVME_PASSTHRU (This); + + *DevicePathLength = Private->DevicePathLength; + *DevicePath = AllocateCopyPool (Private->DevicePathLength, Private->DevicePath); + if (*DevicePath == NULL) { + *DevicePathLength = 0; + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +/** + Used to retrieve the next namespace ID for this NVM Express controller. + + If on input the value pointed to by NamespaceId is 0xFFFFFFFF, then the first + valid namespace ID defined on the NVM Express controller is returned in the + location pointed to by NamespaceId and a status of EFI_SUCCESS is returned. + + If on input the value pointed to by NamespaceId is an invalid namespace ID + other than 0xFFFFFFFF, then EFI_INVALID_PARAMETER is returned. + + If on input the value pointed to by NamespaceId is a valid namespace ID, then + the next valid namespace ID on the NVM Express controller is returned in the + location pointed to by NamespaceId, and EFI_SUCCESS is returned. + + If the value pointed to by NamespaceId is the namespace ID of the last + namespace on the NVM Express controller, then EFI_NOT_FOUND is returned. + + @param[in] This The PPI instance pointer. + @param[in,out] NamespaceId On input, a pointer to a legal NamespaceId + for an NVM Express namespace present on the + NVM Express controller. On output, a pointer + to the next NamespaceId of an NVM Express + namespace on an NVM Express controller. An + input value of 0xFFFFFFFF retrieves the + first NamespaceId for an NVM Express + namespace present on an NVM Express + controller. + + @retval EFI_SUCCESS The Namespace ID of the next Namespace was + returned. + @retval EFI_NOT_FOUND There are no more namespaces defined on this + controller. + @retval EFI_INVALID_PARAMETER NamespaceId is an invalid value other than + 0xFFFFFFFF. + +**/ +EFI_STATUS +EFIAPI +NvmePassThruGetNextNameSpace ( + IN EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI *This, + IN OUT UINT32 *NamespaceId + ) +{ + PEI_NVME_CONTROLLER_PRIVATE_DATA *Private; + UINT32 DeviceIndex; + EFI_STATUS Status; + + if (This == NULL || NamespaceId == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NVME_PASSTHRU (This); + + Status = EFI_NOT_FOUND; + + // + // If active namespace number is 0, then valid namespace ID is unavailable + // + if (Private->ActiveNamespaceNum == 0) { + return EFI_NOT_FOUND; + } + + // + // If the NamespaceId input value is 0xFFFFFFFF, then get the first valid namespace ID + // + if (*NamespaceId == 0xFFFFFFFF) { + // + // Start with the first namespace ID + // + *NamespaceId = Private->NamespaceInfo[0].NamespaceId; + Status = EFI_SUCCESS; + } else { + if (*NamespaceId > Private->ControllerData->Nn) { + return EFI_INVALID_PARAMETER; + } + + if ((*NamespaceId + 1) > Private->ControllerData->Nn) { + return EFI_NOT_FOUND; + } + + for (DeviceIndex = 0; DeviceIndex < Private->ActiveNamespaceNum; DeviceIndex++) { + if (*NamespaceId == Private->NamespaceInfo[DeviceIndex].NamespaceId) { + if ((DeviceIndex + 1) < Private->ActiveNamespaceNum) { + *NamespaceId = Private->NamespaceInfo[DeviceIndex + 1].NamespaceId; + Status = EFI_SUCCESS; + } + break; + } + } + } + + return Status; + +} + +/** + Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function only + supports blocking execution of the command. + + @param[in] This The PPI instance pointer. + @param[in] NamespaceId Is a 32 bit Namespace ID to which the Nvm Express command packet will + be sent. + A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in + the namespace ID specifies that the command packet should be sent to all + valid namespaces. + @param[in,out] Packet A pointer to the EDKII PEI NVM Express PassThru Command Packet to send + to the NVMe namespace specified by NamespaceId. + + @retval EFI_SUCCESS The EDKII PEI NVM Express Command Packet was sent by the host. + TransferLength bytes were transferred to, or from DataBuffer. + @retval EFI_NOT_READY The EDKII PEI NVM Express Command Packet could not be sent because + the controller is not ready. The caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the EDKII PEI NVM + Express Command Packet. + @retval EFI_INVALID_PARAMETER Namespace, or the contents of EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET + are invalid. + The EDKII PEI NVM Express Command Packet was not sent, so no + additional status information is available. + @retval EFI_UNSUPPORTED The command described by the EDKII PEI NVM Express Command Packet + is not supported by the host adapter. + The EDKII PEI NVM Express Command Packet was not sent, so no + additional status information is available. + @retval EFI_TIMEOUT A timeout occurred while waiting for the EDKII PEI NVM Express Command + Packet to execute. + +**/ +EFI_STATUS +EFIAPI +NvmePassThru ( + IN EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI *This, + IN UINT32 NamespaceId, + IN OUT EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet + ) +{ + PEI_NVME_CONTROLLER_PRIVATE_DATA *Private; + EFI_STATUS Status; + + if (This == NULL || Packet == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NVME_PASSTHRU (This); + // + // Check NamespaceId is valid or not. + // + if ((NamespaceId > Private->ControllerData->Nn) && + (NamespaceId != (UINT32) -1)) { + return EFI_INVALID_PARAMETER; + } + + Status = NvmePassThruExecute ( + Private, + NamespaceId, + Packet + ); + + return Status; + +} + diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiPassThru.h b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiPassThru.h index 81066bbd54..00e8f0abda 100644 --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiPassThru.h +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiPassThru.h @@ -2,7 +2,7 @@ The NvmExpressPei driver is used to manage non-volatile memory subsystem which follows NVM Express specification at PEI phase. - Copyright (c) 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -11,52 +11,6 @@ #ifndef _NVM_EXPRESS_PEI_PASSTHRU_H_ #define _NVM_EXPRESS_PEI_PASSTHRU_H_ -#define NVME_CONTROLLER_NSID 0 - -typedef struct { - UINT8 Opcode; - UINT8 FusedOperation; - #define NORMAL_CMD 0x00 - #define FUSED_FIRST_CMD 0x01 - #define FUSED_SECOND_CMD 0x02 - UINT16 Cid; -} NVME_CDW0; - -typedef struct { - NVME_CDW0 Cdw0; - UINT8 Flags; - #define CDW10_VALID 0x01 - #define CDW11_VALID 0x02 - #define CDW12_VALID 0x04 - #define CDW13_VALID 0x08 - #define CDW14_VALID 0x10 - #define CDW15_VALID 0x20 - UINT32 Nsid; - UINT32 Cdw10; - UINT32 Cdw11; - UINT32 Cdw12; - UINT32 Cdw13; - UINT32 Cdw14; - UINT32 Cdw15; -} EDKII_PEI_NVM_EXPRESS_COMMAND; - -typedef struct { - UINT32 Cdw0; - UINT32 Cdw1; - UINT32 Cdw2; - UINT32 Cdw3; -} EDKII_PEI_NVM_EXPRESS_COMPLETION; - -typedef struct { - UINT64 CommandTimeout; - VOID *TransferBuffer; - UINT32 TransferLength; - VOID *MetadataBuffer; - UINT32 MetadataLength; - UINT8 QueueType; - EDKII_PEI_NVM_EXPRESS_COMMAND *NvmeCmd; - EDKII_PEI_NVM_EXPRESS_COMPLETION *NvmeCompletion; -} EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET; /** @@ -91,10 +45,117 @@ typedef struct { **/ EFI_STATUS -NvmePassThru ( +NvmePassThruExecute ( IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private, IN UINT32 NamespaceId, - IN OUT EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet + IN OUT EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet + ); + +/** + Gets the device path information of the underlying NVM Express host controller. + + @param[in] This The PPI instance pointer. + @param[out] DevicePathLength The length of the device path in bytes specified + by DevicePath. + @param[out] DevicePath The device path of the underlying NVM Express + host controller. + This field re-uses EFI Device Path Protocol as + defined by Section 10.2 EFI Device Path Protocol + of UEFI 2.7 Specification. + + @retval EFI_SUCCESS The operation succeeds. + @retval EFI_INVALID_PARAMETER DevicePathLength or DevicePath is NULL. + @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources. + +**/ +EFI_STATUS +EFIAPI +NvmePassThruGetDevicePath ( + IN EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI *This, + OUT UINTN *DevicePathLength, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +/** + Used to retrieve the next namespace ID for this NVM Express controller. + + If on input the value pointed to by NamespaceId is 0xFFFFFFFF, then the first + valid namespace ID defined on the NVM Express controller is returned in the + location pointed to by NamespaceId and a status of EFI_SUCCESS is returned. + + If on input the value pointed to by NamespaceId is an invalid namespace ID + other than 0xFFFFFFFF, then EFI_INVALID_PARAMETER is returned. + + If on input the value pointed to by NamespaceId is a valid namespace ID, then + the next valid namespace ID on the NVM Express controller is returned in the + location pointed to by NamespaceId, and EFI_SUCCESS is returned. + + If the value pointed to by NamespaceId is the namespace ID of the last + namespace on the NVM Express controller, then EFI_NOT_FOUND is returned. + + @param[in] This The PPI instance pointer. + @param[in,out] NamespaceId On input, a pointer to a legal NamespaceId + for an NVM Express namespace present on the + NVM Express controller. On output, a pointer + to the next NamespaceId of an NVM Express + namespace on an NVM Express controller. An + input value of 0xFFFFFFFF retrieves the + first NamespaceId for an NVM Express + namespace present on an NVM Express + controller. + + @retval EFI_SUCCESS The Namespace ID of the next Namespace was + returned. + @retval EFI_NOT_FOUND There are no more namespaces defined on this + controller. + @retval EFI_INVALID_PARAMETER NamespaceId is an invalid value other than + 0xFFFFFFFF. + +**/ +EFI_STATUS +EFIAPI +NvmePassThruGetNextNameSpace ( + IN EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI *This, + IN OUT UINT32 *NamespaceId + ); + +/** + Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function only + supports blocking execution of the command. + + @param[in] This The PPI instance pointer. + @param[in] NamespaceId Is a 32 bit Namespace ID to which the Nvm Express command packet will + be sent. + A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in + the namespace ID specifies that the command packet should be sent to all + valid namespaces. + @param[in,out] Packet A pointer to the EDKII PEI NVM Express PassThru Command Packet to send + to the NVMe namespace specified by NamespaceId. + + @retval EFI_SUCCESS The EDKII PEI NVM Express Command Packet was sent by the host. + TransferLength bytes were transferred to, or from DataBuffer. + @retval EFI_NOT_READY The EDKII PEI NVM Express Command Packet could not be sent because + the controller is not ready. The caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the EDKII PEI NVM + Express Command Packet. + @retval EFI_INVALID_PARAMETER Namespace, or the contents of EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET + are invalid. + The EDKII PEI NVM Express Command Packet was not sent, so no + additional status information is available. + @retval EFI_UNSUPPORTED The command described by the EDKII PEI NVM Express Command Packet + is not supported by the host adapter. + The EDKII PEI NVM Express Command Packet was not sent, so no + additional status information is available. + @retval EFI_TIMEOUT A timeout occurred while waiting for the EDKII PEI NVM Express Command + Packet to execute. + +**/ +EFI_STATUS +EFIAPI +NvmePassThru ( + IN EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI *This, + IN UINT32 NamespaceId, + IN OUT EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet ); #endif diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.c index dda69988b1..094d61bb8a 100644 --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.c +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.c @@ -57,15 +57,17 @@ TrustTransferNvmeDevice ( OUT UINTN *TransferLengthOut ) { - EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EDKII_PEI_NVM_EXPRESS_COMMAND Command; - EDKII_PEI_NVM_EXPRESS_COMPLETION Completion; + EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; + EFI_NVM_EXPRESS_COMMAND Command; + EFI_NVM_EXPRESS_COMPLETION Completion; EFI_STATUS Status; UINT16 SpecificData; + EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI *NvmePassThru; - ZeroMem (&CommandPacket, sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); - ZeroMem (&Command, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND)); - ZeroMem (&Completion, sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION)); + NvmePassThru = &Private->NvmePassThruPpi; + ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); + ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND)); + ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION)); CommandPacket.NvmeCmd = &Command; CommandPacket.NvmeCompletion = &Completion; @@ -94,11 +96,11 @@ TrustTransferNvmeDevice ( CommandPacket.CommandTimeout = Timeout; CommandPacket.QueueType = NVME_ADMIN_QUEUE; - Status = NvmePassThru ( - Private, - NVME_CONTROLLER_NSID, - &CommandPacket - ); + Status = NvmePassThru->PassThru ( + NvmePassThru, + NVME_CONTROLLER_NSID, + &CommandPacket + ); if (!IsTrustSend) { if (EFI_ERROR (Status)) {