]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
MdeModulePkg/NvmExpress: Fix mem leak in error handling of Start()
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NvmExpressDxe / NvmExpress.c
index ee40ba05c9151f2a038a80fc9c4649f8c07ff08f..54d637e7d03b13f74351a13eabb07171ea3e5501 100644 (file)
@@ -2,7 +2,7 @@
   NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows\r
   NVM Express specification.\r
 \r
-  Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -35,6 +35,15 @@ EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiVersion =
   0                                                   // Version number to be filled at start up.\r
 };\r
 \r
+//\r
+// Template for NVM Express Pass Thru Mode data structure.\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_NVM_EXPRESS_PASS_THRU_MODE gEfiNvmExpressPassThruMode = {\r
+  EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL | EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM,\r
+  sizeof (UINTN),\r
+  0x10100\r
+};\r
+\r
 /**\r
   Check if the specified Nvm Express device namespace is active, and create child handles\r
   for them with BlockIo and DiskInfo protocol instances.\r
@@ -43,8 +52,6 @@ EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiVersion =
   @param[in] NamespaceId     The NVM Express namespace ID  for which a device path node is to be\r
                              allocated and built. Caller must set the NamespaceId to zero if the\r
                              device path node will contain a valid UUID.\r
-  @param[in] NamespaceUuid   The NVM Express namespace UUID for which a device path node is to be\r
-                             allocated and built. UUID will only be valid of the Namespace ID is zero.\r
 \r
   @retval EFI_SUCCESS        All the namespaces in the device are successfully enumerated.\r
   @return Others             Some error occurs when enumerating the namespaces.\r
@@ -53,8 +60,7 @@ EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiVersion =
 EFI_STATUS\r
 EnumerateNvmeDevNamespace (\r
   IN NVME_CONTROLLER_PRIVATE_DATA       *Private,\r
-  UINT32                                NamespaceId,\r
-  UINT64                                NamespaceUuid\r
+  UINT32                                NamespaceId\r
   )\r
 {\r
   NVME_ADMIN_NAMESPACE_DATA             *NamespaceData;\r
@@ -104,6 +110,7 @@ EnumerateNvmeDevNamespace (
     //\r
     Device = AllocateZeroPool(sizeof(NVME_DEVICE_PRIVATE_DATA));\r
     if (Device == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
       goto Exit;\r
     }\r
 \r
@@ -147,9 +154,16 @@ EnumerateNvmeDevNamespace (
     Device->BlockIo.WriteBlocks  = NvmeBlockIoWriteBlocks;\r
     Device->BlockIo.FlushBlocks  = NvmeBlockIoFlushBlocks;\r
 \r
+    //\r
+    // Create StorageSecurityProtocol Instance\r
+    //\r
+    Device->StorageSecurity.ReceiveData = NvmeStorageSecurityReceiveData;\r
+    Device->StorageSecurity.SendData    = NvmeStorageSecuritySendData;\r
+\r
     //\r
     // Create DiskInfo Protocol instance\r
     //\r
+    CopyMem (&Device->NamespaceData, NamespaceData, sizeof (NVME_ADMIN_NAMESPACE_DATA));\r
     InitializeDiskInfo (Device);\r
 \r
     //\r
@@ -158,7 +172,6 @@ EnumerateNvmeDevNamespace (
     Status = Private->Passthru.BuildDevicePath (\r
                                  &Private->Passthru,\r
                                  Device->NamespaceId,\r
-                                 Device->NamespaceUuid,\r
                                  &NewDevicePathNode\r
                                  );\r
 \r
@@ -205,10 +218,36 @@ EnumerateNvmeDevNamespace (
     if(EFI_ERROR(Status)) {\r
       goto Exit;\r
     }\r
+\r
+    //\r
+    // Check if the NVMe controller supports the Security Send and Security Receive commands\r
+    //\r
+    if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {\r
+      Status = gBS->InstallProtocolInterface (\r
+                      &Device->DeviceHandle,\r
+                      &gEfiStorageSecurityCommandProtocolGuid,\r
+                      EFI_NATIVE_INTERFACE,\r
+                      &Device->StorageSecurity\r
+                      );\r
+      if(EFI_ERROR(Status)) {\r
+        gBS->UninstallMultipleProtocolInterfaces (\r
+               &Device->DeviceHandle,\r
+               &gEfiDevicePathProtocolGuid,\r
+               Device->DevicePath,\r
+               &gEfiBlockIoProtocolGuid,\r
+               &Device->BlockIo,\r
+               &gEfiDiskInfoProtocolGuid,\r
+               &Device->DiskInfo,\r
+               NULL\r
+               );\r
+        goto Exit;\r
+      }\r
+    }\r
+\r
     gBS->OpenProtocol (\r
            Private->ControllerHandle,\r
-           &gEfiPciIoProtocolGuid,\r
-           (VOID **) &Private->PciIo,\r
+           &gEfiNvmExpressPassThruProtocolGuid,\r
+           (VOID **) &Private->Passthru,\r
            Private->DriverBindingHandle,\r
            Device->DeviceHandle,\r
            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
@@ -250,6 +289,10 @@ Exit:
     FreePool (NamespaceData);\r
   }\r
 \r
+  if (NewDevicePathNode != NULL) {\r
+    FreePool (NewDevicePathNode);\r
+  }\r
+\r
   if(EFI_ERROR(Status) && (Device != NULL) && (Device->DevicePath != NULL)) {\r
     FreePool (Device->DevicePath);\r
   }\r
@@ -276,18 +319,15 @@ DiscoverAllNamespaces (
 {\r
   EFI_STATUS                            Status;\r
   UINT32                                NamespaceId;\r
-  UINT64                                NamespaceUuid;\r
-  NVM_EXPRESS_PASS_THRU_PROTOCOL        *Passthru;\r
+  EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL    *Passthru;\r
 \r
   NamespaceId   = 0xFFFFFFFF;\r
-  NamespaceUuid = 0;\r
   Passthru      = &Private->Passthru;\r
 \r
   while (TRUE) {\r
     Status = Passthru->GetNextNamespace (\r
                          Passthru,\r
-                         (UINT32 *)&NamespaceId,\r
-                         (UINT64 *)&NamespaceUuid\r
+                         (UINT32 *)&NamespaceId\r
                          );\r
 \r
     if (EFI_ERROR (Status)) {\r
@@ -296,8 +336,7 @@ DiscoverAllNamespaces (
 \r
     Status = EnumerateNvmeDevNamespace (\r
                Private,\r
-               NamespaceId,\r
-               NamespaceUuid\r
+               NamespaceId\r
                );\r
 \r
     if (EFI_ERROR(Status)) {\r
@@ -330,9 +369,10 @@ UnregisterNvmeNamespace (
   )\r
 {\r
   EFI_STATUS                               Status;\r
-  EFI_PCI_IO_PROTOCOL                      *PciIo;\r
   EFI_BLOCK_IO_PROTOCOL                    *BlockIo;\r
   NVME_DEVICE_PRIVATE_DATA                 *Device;\r
+  NVME_CONTROLLER_PRIVATE_DATA             *Private;\r
+  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *StorageSecurity;\r
 \r
   BlockIo = NULL;\r
 \r
@@ -348,14 +388,15 @@ UnregisterNvmeNamespace (
     return Status;\r
   }\r
 \r
-  Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo);\r
+  Device  = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo);\r
+  Private = Device->Controller;\r
 \r
   //\r
   // Close the child handle\r
   //\r
   gBS->CloseProtocol (\r
          Controller,\r
-         &gEfiPciIoProtocolGuid,\r
+         &gEfiNvmExpressPassThruProtocolGuid,\r
          This->DriverBindingHandle,\r
          Handle\r
          );\r
@@ -378,8 +419,8 @@ UnregisterNvmeNamespace (
   if (EFI_ERROR (Status)) {\r
     gBS->OpenProtocol (\r
            Controller,\r
-           &gEfiPciIoProtocolGuid,\r
-           (VOID **) &PciIo,\r
+           &gEfiNvmExpressPassThruProtocolGuid,\r
+           (VOID **) &Private->Passthru,\r
            This->DriverBindingHandle,\r
            Handle,\r
            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
@@ -387,6 +428,37 @@ UnregisterNvmeNamespace (
     return Status;\r
   }\r
 \r
+  //\r
+  // If Storage Security Command Protocol is installed, then uninstall this protocol.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Handle,\r
+                  &gEfiStorageSecurityCommandProtocolGuid,\r
+                  (VOID **) &StorageSecurity,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->UninstallProtocolInterface (\r
+                    Handle,\r
+                    &gEfiStorageSecurityCommandProtocolGuid,\r
+                    &Device->StorageSecurity\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->OpenProtocol (\r
+        Controller,\r
+        &gEfiNvmExpressPassThruProtocolGuid,\r
+        (VOID **) &Private->Passthru,\r
+        This->DriverBindingHandle,\r
+        Handle,\r
+        EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+        );\r
+      return Status;\r
+    }\r
+  }\r
+\r
   if(Device->DevicePath != NULL) {\r
     FreePool (Device->DevicePath);\r
   }\r
@@ -395,6 +467,8 @@ UnregisterNvmeNamespace (
     FreeUnicodeStringTable (Device->ControllerNameTable);\r
   }\r
 \r
+  FreePool (Device);\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -471,8 +545,8 @@ NvmExpressDriverBindingSupported (
 \r
       if ((DevicePathNode.DevPath->Type    != MESSAGING_DEVICE_PATH) ||\r
           (DevicePathNode.DevPath->SubType != MSG_NVME_NAMESPACE_DP) ||\r
-           DevicePathNodeLength(DevicePathNode.DevPath) != sizeof(NVME_NAMESPACE_DEVICE_PATH)) {\r
-        return EFI_UNSUPPORTED;\r
+          (DevicePathNodeLength(DevicePathNode.DevPath) != sizeof(NVME_NAMESPACE_DEVICE_PATH))) {\r
+         return EFI_UNSUPPORTED;\r
       }\r
     }\r
   }\r
@@ -602,18 +676,19 @@ NvmExpressDriverBindingStart (
   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
   )\r
 {\r
-  EFI_STATUS                        Status;\r
-  EFI_PCI_IO_PROTOCOL               *PciIo;\r
-  NVME_CONTROLLER_PRIVATE_DATA      *Private;\r
-  EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;\r
-  UINT32                            NamespaceId;\r
-  UINT64                            NamespaceUuid;\r
-  EFI_PHYSICAL_ADDRESS              MappedAddr;\r
-  UINTN                             Bytes;\r
+  EFI_STATUS                          Status;\r
+  EFI_PCI_IO_PROTOCOL                 *PciIo;\r
+  NVME_CONTROLLER_PRIVATE_DATA        *Private;\r
+  EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;\r
+  UINT32                              NamespaceId;\r
+  EFI_PHYSICAL_ADDRESS                MappedAddr;\r
+  UINTN                               Bytes;\r
+  EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL  *Passthru;\r
 \r
   DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: start\n"));\r
 \r
-  Private = NULL;\r
+  Private          = NULL;\r
+  Passthru         = NULL;\r
   ParentDevicePath = NULL;\r
 \r
   Status = gBS->OpenProtocol (\r
@@ -650,7 +725,7 @@ NvmExpressDriverBindingStart (
     if (Private == NULL) {\r
       DEBUG ((EFI_D_ERROR, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n"));\r
       Status = EFI_OUT_OF_RESOURCES;\r
-      goto Exit2;\r
+      goto Exit;\r
     }\r
 \r
     //\r
@@ -671,7 +746,7 @@ NvmExpressDriverBindingStart (
                       0\r
                       );\r
     if (EFI_ERROR (Status)) {\r
-      goto Exit2;\r
+      goto Exit;\r
     }\r
 \r
     Bytes = EFI_PAGES_TO_SIZE (4);\r
@@ -685,7 +760,7 @@ NvmExpressDriverBindingStart (
                       );\r
 \r
     if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (4))) {\r
-      goto Exit2;\r
+      goto Exit;\r
     }\r
 \r
     Private->BufferPciAddr = (UINT8 *)(UINTN)MappedAddr;\r
@@ -702,36 +777,36 @@ NvmExpressDriverBindingStart (
     Private->Passthru.GetNextNamespace = NvmExpressGetNextNamespace;\r
     Private->Passthru.BuildDevicePath  = NvmExpressBuildDevicePath;\r
     Private->Passthru.GetNamespace     = NvmExpressGetNamespace;\r
-    Private->PassThruMode.Attributes   = NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL;\r
+    CopyMem (&Private->PassThruMode, &gEfiNvmExpressPassThruMode, sizeof (EFI_NVM_EXPRESS_PASS_THRU_MODE));\r
 \r
     Status = NvmeControllerInit (Private);\r
-\r
     if (EFI_ERROR(Status)) {\r
-      goto Exit2;\r
+      goto Exit;\r
     }\r
 \r
     Status = gBS->InstallMultipleProtocolInterfaces (\r
                     &Controller,\r
-                    &gEfiCallerIdGuid,\r
-                    Private,\r
+                    &gEfiNvmExpressPassThruProtocolGuid,\r
+                    &Private->Passthru,\r
                     NULL\r
                     );\r
     if (EFI_ERROR (Status)) {\r
-      goto Exit2;\r
+      goto Exit;\r
     }\r
   } else {\r
     Status = gBS->OpenProtocol (\r
                     Controller,\r
-                    &gEfiCallerIdGuid,\r
-                    (VOID **) &Private,\r
+                    &gEfiNvmExpressPassThruProtocolGuid,\r
+                    (VOID **) &Passthru,\r
                     This->DriverBindingHandle,\r
                     Controller,\r
                     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                     );\r
     if (EFI_ERROR (Status)) {\r
-      Private = NULL;\r
-      goto Exit1;\r
+      goto Exit;\r
     }\r
+\r
+    Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (Passthru);\r
   }\r
 \r
   if (RemainingDevicePath == NULL) {\r
@@ -749,30 +824,21 @@ NvmExpressDriverBindingStart (
     Status = Private->Passthru.GetNamespace (\r
                                  &Private->Passthru,\r
                                  RemainingDevicePath,\r
-                                 &NamespaceId,\r
-                                 &NamespaceUuid\r
+                                 &NamespaceId\r
                                  );\r
 \r
     if (!EFI_ERROR (Status)) {\r
-        Status = EnumerateNvmeDevNamespace (\r
-                   Private,\r
-                   NamespaceId,\r
-                   NamespaceUuid\r
-                   );\r
+      Status = EnumerateNvmeDevNamespace (\r
+                 Private,\r
+                 NamespaceId\r
+                 );\r
     }\r
   }\r
 \r
   DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: end successfully\n"));\r
   return EFI_SUCCESS;\r
 \r
-Exit1:\r
-  gBS->UninstallMultipleProtocolInterfaces (\r
-         Controller,\r
-         &gEfiCallerIdGuid,\r
-         Private,\r
-         NULL\r
-         );\r
-Exit2:\r
+Exit:\r
   if ((Private != NULL) && (Private->Mapping != NULL)) {\r
     PciIo->Unmap (PciIo, Private->Mapping);\r
   }\r
@@ -781,6 +847,10 @@ Exit2:
     PciIo->FreeBuffer (PciIo, 4, Private->Buffer);\r
   }\r
 \r
+  if ((Private != NULL) && (Private->ControllerData != NULL)) {\r
+    FreePool (Private->ControllerData);\r
+  }\r
+\r
   if (Private != NULL) {\r
     FreePool (Private);\r
   }\r
@@ -844,22 +914,24 @@ NvmExpressDriverBindingStop (
   BOOLEAN                             AllChildrenStopped;\r
   UINTN                               Index;\r
   NVME_CONTROLLER_PRIVATE_DATA        *Private;\r
+  EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL  *PassThru;\r
 \r
   if (NumberOfChildren == 0) {\r
     Status = gBS->OpenProtocol (\r
                     Controller,\r
-                    &gEfiCallerIdGuid,\r
-                    (VOID **) &Private,\r
+                    &gEfiNvmExpressPassThruProtocolGuid,\r
+                    (VOID **) &PassThru,\r
                     This->DriverBindingHandle,\r
                     Controller,\r
                     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                     );\r
 \r
     if (!EFI_ERROR (Status)) {\r
+      Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (PassThru);\r
       gBS->UninstallMultipleProtocolInterfaces (\r
             Controller,\r
-            &gEfiCallerIdGuid,\r
-            Private,\r
+            &gEfiNvmExpressPassThruProtocolGuid,\r
+            PassThru,\r
             NULL\r
             );\r
 \r
@@ -940,7 +1012,7 @@ NvmExpressUnload (
   DeviceHandleBuffer = NULL;\r
   Status = gBS->LocateHandleBuffer (\r
                   ByProtocol,\r
-                  &gEfiCallerIdGuid,\r
+                  &gEfiNvmExpressPassThruProtocolGuid,\r
                   NULL,\r
                   &DeviceHandleCount,\r
                   &DeviceHandleBuffer\r