]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
MdeModulePkg NvmExpressDxe: Add NamespaceId validity check in PassThru
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NvmExpressDxe / NvmExpressPassthru.c
index ec7507e4c29a100cfc109f461fa8aae2b471bd54..96e9d88e5267399f3ea37a1da70464cc02b0b8cc 100644 (file)
@@ -357,27 +357,30 @@ NvmExpressPassThru (
   IN     EFI_EVENT                                   Event OPTIONAL\r
   )\r
 {\r
-  NVME_CONTROLLER_PRIVATE_DATA  *Private;\r
-  EFI_STATUS                    Status;\r
-  EFI_PCI_IO_PROTOCOL           *PciIo;\r
-  NVME_SQ                       *Sq;\r
-  NVME_CQ                       *Cq;\r
-  UINT16                        QueueId;\r
-  UINT32                        Bytes;\r
-  UINT16                        Offset;\r
-  EFI_EVENT                     TimerEvent;\r
-  EFI_PCI_IO_PROTOCOL_OPERATION Flag;\r
-  EFI_PHYSICAL_ADDRESS          PhyAddr;\r
-  VOID                          *MapData;\r
-  VOID                          *MapMeta;\r
-  VOID                          *MapPrpList;\r
-  UINTN                         MapLength;\r
-  UINT64                        *Prp;\r
-  VOID                          *PrpListHost;\r
-  UINTN                         PrpListNo;\r
-  UINT32                        Data;\r
-  NVME_PASS_THRU_ASYNC_REQ      *AsyncRequest;\r
-  EFI_TPL                       OldTpl;\r
+  NVME_CONTROLLER_PRIVATE_DATA   *Private;\r
+  EFI_STATUS                     Status;\r
+  EFI_PCI_IO_PROTOCOL            *PciIo;\r
+  NVME_SQ                        *Sq;\r
+  NVME_CQ                        *Cq;\r
+  UINT16                         QueueId;\r
+  UINT32                         Bytes;\r
+  UINT16                         Offset;\r
+  EFI_EVENT                      TimerEvent;\r
+  EFI_PCI_IO_PROTOCOL_OPERATION  Flag;\r
+  EFI_PHYSICAL_ADDRESS           PhyAddr;\r
+  VOID                           *MapData;\r
+  VOID                           *MapMeta;\r
+  VOID                           *MapPrpList;\r
+  UINTN                          MapLength;\r
+  UINT64                         *Prp;\r
+  VOID                           *PrpListHost;\r
+  UINTN                          PrpListNo;\r
+  UINT32                         Attributes;\r
+  UINT32                         IoAlign;\r
+  UINT32                         MaxTransLen;\r
+  UINT32                         Data;\r
+  NVME_PASS_THRU_ASYNC_REQ       *AsyncRequest;\r
+  EFI_TPL                        OldTpl;\r
 \r
   //\r
   // check the data fields in Packet parameter.\r
@@ -394,7 +397,51 @@ NvmExpressPassThru (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  //\r
+  // 'Attributes' with neither EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL nor\r
+  // EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL set is an illegal\r
+  // configuration.\r
+  //\r
+  Attributes  = This->Mode->Attributes;\r
+  if ((Attributes & (EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |\r
+    EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL)) == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Buffer alignment check for TransferBuffer & MetadataBuffer.\r
+  //\r
+  IoAlign     = This->Mode->IoAlign;\r
+  if (IoAlign > 0 && (((UINTN) Packet->TransferBuffer & (IoAlign - 1)) != 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (IoAlign > 0 && (((UINTN) Packet->MetadataBuffer & (IoAlign - 1)) != 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   Private     = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This);\r
+\r
+  //\r
+  // Check NamespaceId is valid or not.\r
+  //\r
+  if ((NamespaceId > Private->ControllerData->Nn) &&\r
+      (NamespaceId != (UINT32) -1)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Check whether TransferLength exceeds the maximum data transfer size.\r
+  //\r
+  if (Private->ControllerData->Mdts != 0) {\r
+    MaxTransLen = (1 << (Private->ControllerData->Mdts)) *\r
+                  (1 << (Private->Cap.Mpsmin + 12));\r
+    if (Packet->TransferLength > MaxTransLen) {\r
+      Packet->TransferLength = MaxTransLen;\r
+      return EFI_BAD_BUFFER_SIZE;\r
+    }\r
+  }\r
+\r
   PciIo       = Private->PciIo;\r
   MapData     = NULL;\r
   MapMeta     = NULL;\r
@@ -452,6 +499,10 @@ NvmExpressPassThru (
   // processor and a PCI Bus Master. It's caller's responsbility to ensure this.\r
   //\r
   if (((Sq->Opc & (BIT0 | BIT1)) != 0) && (Sq->Opc != NVME_ADMIN_CRIOCQ_CMD) && (Sq->Opc != NVME_ADMIN_CRIOSQ_CMD)) {\r
+    if ((Packet->TransferLength == 0) || (Packet->TransferBuffer == NULL)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
     if ((Sq->Opc & BIT0) != 0) {\r
       Flag = EfiPciIoOperationBusMasterRead;\r
     } else {\r
@@ -474,8 +525,7 @@ NvmExpressPassThru (
     Sq->Prp[0] = PhyAddr;\r
     Sq->Prp[1] = 0;\r
 \r
-    MapLength = Packet->MetadataLength;\r
-    if(Packet->MetadataBuffer != NULL) {\r
+    if((Packet->MetadataLength != 0) && (Packet->MetadataBuffer != NULL)) {\r
       MapLength = Packet->MetadataLength;\r
       Status = PciIo->Map (\r
                         PciIo,\r