MdeModulePkg NvmExpressDxe: Add buffer alignment check in PassThru API

According to the UEFI spec, the 'TransferBuffer' and 'MetadataBuffer' used
in a data transfer should be aligned on the boundary specified by the
IoAlign field in the EFI_NVM_EXPRESS_PASS_THRU_MODE structure.

This commit adds this check to follow the spec.

Cc: Feng Tian <feng.tian@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
index ec7507e..6b29260 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
@@ -357,27 +357,28 @@
   IN     EFI_EVENT                                   Event OPTIONAL

   )

 {

-  NVME_CONTROLLER_PRIVATE_DATA  *Private;

-  EFI_STATUS                    Status;

-  EFI_PCI_IO_PROTOCOL           *PciIo;

-  NVME_SQ                       *Sq;

-  NVME_CQ                       *Cq;

-  UINT16                        QueueId;

-  UINT32                        Bytes;

-  UINT16                        Offset;

-  EFI_EVENT                     TimerEvent;

-  EFI_PCI_IO_PROTOCOL_OPERATION Flag;

-  EFI_PHYSICAL_ADDRESS          PhyAddr;

-  VOID                          *MapData;

-  VOID                          *MapMeta;

-  VOID                          *MapPrpList;

-  UINTN                         MapLength;

-  UINT64                        *Prp;

-  VOID                          *PrpListHost;

-  UINTN                         PrpListNo;

-  UINT32                        Data;

-  NVME_PASS_THRU_ASYNC_REQ      *AsyncRequest;

-  EFI_TPL                       OldTpl;

+  NVME_CONTROLLER_PRIVATE_DATA   *Private;

+  EFI_STATUS                     Status;

+  EFI_PCI_IO_PROTOCOL            *PciIo;

+  NVME_SQ                        *Sq;

+  NVME_CQ                        *Cq;

+  UINT16                         QueueId;

+  UINT32                         Bytes;

+  UINT16                         Offset;

+  EFI_EVENT                      TimerEvent;

+  EFI_PCI_IO_PROTOCOL_OPERATION  Flag;

+  EFI_PHYSICAL_ADDRESS           PhyAddr;

+  VOID                           *MapData;

+  VOID                           *MapMeta;

+  VOID                           *MapPrpList;

+  UINTN                          MapLength;

+  UINT64                         *Prp;

+  VOID                           *PrpListHost;

+  UINTN                          PrpListNo;

+  UINT32                         IoAlign;

+  UINT32                         Data;

+  NVME_PASS_THRU_ASYNC_REQ       *AsyncRequest;

+  EFI_TPL                        OldTpl;

 

   //

   // check the data fields in Packet parameter.

@@ -394,6 +395,18 @@
     return EFI_INVALID_PARAMETER;

   }

 

+  //

+  // Buffer alignment check for TransferBuffer & MetadataBuffer.

+  //

+  IoAlign = This->Mode->IoAlign;

+  if (IoAlign > 0 && (((UINTN) Packet->TransferBuffer & (IoAlign - 1)) != 0)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (IoAlign > 0 && (((UINTN) Packet->MetadataBuffer & (IoAlign - 1)) != 0)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

   Private     = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This);

   PciIo       = Private->PciIo;

   MapData     = NULL;