Home | History | Annotate | Download | only in NvmExpressDxe
      1 /** @file
      2   NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
      3   NVM Express specification.
      4 
      5   Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "NvmExpress.h"
     17 
     18 //
     19 // NVM Express Driver Binding Protocol Instance
     20 //
     21 EFI_DRIVER_BINDING_PROTOCOL gNvmExpressDriverBinding = {
     22   NvmExpressDriverBindingSupported,
     23   NvmExpressDriverBindingStart,
     24   NvmExpressDriverBindingStop,
     25   0x10,
     26   NULL,
     27   NULL
     28 };
     29 
     30 //
     31 // NVM Express EFI Driver Supported EFI Version Protocol Instance
     32 //
     33 EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiVersion = {
     34   sizeof (EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL), // Size of Protocol structure.
     35   0                                                   // Version number to be filled at start up.
     36 };
     37 
     38 //
     39 // Template for NVM Express Pass Thru Mode data structure.
     40 //
     41 GLOBAL_REMOVE_IF_UNREFERENCED EFI_NVM_EXPRESS_PASS_THRU_MODE gEfiNvmExpressPassThruMode = {
     42   EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL | EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM,
     43   sizeof (UINTN),
     44   0x10100
     45 };
     46 
     47 /**
     48   Check if the specified Nvm Express device namespace is active, and create child handles
     49   for them with BlockIo and DiskInfo protocol instances.
     50 
     51   @param[in] Private         The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
     52   @param[in] NamespaceId     The NVM Express namespace ID  for which a device path node is to be
     53                              allocated and built. Caller must set the NamespaceId to zero if the
     54                              device path node will contain a valid UUID.
     55 
     56   @retval EFI_SUCCESS        All the namespaces in the device are successfully enumerated.
     57   @return Others             Some error occurs when enumerating the namespaces.
     58 
     59 **/
     60 EFI_STATUS
     61 EnumerateNvmeDevNamespace (
     62   IN NVME_CONTROLLER_PRIVATE_DATA       *Private,
     63   UINT32                                NamespaceId
     64   )
     65 {
     66   NVME_ADMIN_NAMESPACE_DATA             *NamespaceData;
     67   EFI_DEVICE_PATH_PROTOCOL              *NewDevicePathNode;
     68   EFI_DEVICE_PATH_PROTOCOL              *DevicePath;
     69   EFI_HANDLE                            DeviceHandle;
     70   EFI_DEVICE_PATH_PROTOCOL              *ParentDevicePath;
     71   EFI_DEVICE_PATH_PROTOCOL              *RemainingDevicePath;
     72   NVME_DEVICE_PRIVATE_DATA              *Device;
     73   EFI_STATUS                            Status;
     74   UINT32                                Lbads;
     75   UINT32                                Flbas;
     76   UINT32                                LbaFmtIdx;
     77 
     78   NewDevicePathNode = NULL;
     79   DevicePath        = NULL;
     80   Device            = NULL;
     81 
     82   //
     83   // Allocate a buffer for Identify Namespace data
     84   //
     85   NamespaceData = AllocateZeroPool(sizeof (NVME_ADMIN_NAMESPACE_DATA));
     86   if(NamespaceData == NULL) {
     87     return EFI_OUT_OF_RESOURCES;
     88   }
     89 
     90   ParentDevicePath = Private->ParentDevicePath;
     91   //
     92   // Identify Namespace
     93   //
     94   Status = NvmeIdentifyNamespace (
     95              Private,
     96              NamespaceId,
     97              (VOID *)NamespaceData
     98              );
     99   if (EFI_ERROR(Status)) {
    100     goto Exit;
    101   }
    102   //
    103   // Validate Namespace
    104   //
    105   if (NamespaceData->Ncap == 0) {
    106     Status = EFI_DEVICE_ERROR;
    107   } else {
    108     //
    109     // allocate device private data for each discovered namespace
    110     //
    111     Device = AllocateZeroPool(sizeof(NVME_DEVICE_PRIVATE_DATA));
    112     if (Device == NULL) {
    113       Status = EFI_OUT_OF_RESOURCES;
    114       goto Exit;
    115     }
    116 
    117     //
    118     // Initialize SSD namespace instance data
    119     //
    120     Device->Signature           = NVME_DEVICE_PRIVATE_DATA_SIGNATURE;
    121     Device->NamespaceId         = NamespaceId;
    122     Device->NamespaceUuid       = NamespaceData->Eui64;
    123 
    124     Device->ControllerHandle    = Private->ControllerHandle;
    125     Device->DriverBindingHandle = Private->DriverBindingHandle;
    126     Device->Controller          = Private;
    127 
    128     //
    129     // Build BlockIo media structure
    130     //
    131     Device->Media.MediaId        = 0;
    132     Device->Media.RemovableMedia = FALSE;
    133     Device->Media.MediaPresent   = TRUE;
    134     Device->Media.LogicalPartition = FALSE;
    135     Device->Media.ReadOnly       = FALSE;
    136     Device->Media.WriteCaching   = FALSE;
    137 
    138     Flbas     = NamespaceData->Flbas;
    139     LbaFmtIdx = Flbas & 0xF;
    140     Lbads     = NamespaceData->LbaFormat[LbaFmtIdx].Lbads;
    141     Device->Media.BlockSize = (UINT32)1 << Lbads;
    142 
    143     Device->Media.LastBlock                     = NamespaceData->Nsze - 1;
    144     Device->Media.LogicalBlocksPerPhysicalBlock = 1;
    145     Device->Media.LowestAlignedLba              = 1;
    146 
    147     //
    148     // Create BlockIo Protocol instance
    149     //
    150     Device->BlockIo.Revision     = EFI_BLOCK_IO_PROTOCOL_REVISION2;
    151     Device->BlockIo.Media        = &Device->Media;
    152     Device->BlockIo.Reset        = NvmeBlockIoReset;
    153     Device->BlockIo.ReadBlocks   = NvmeBlockIoReadBlocks;
    154     Device->BlockIo.WriteBlocks  = NvmeBlockIoWriteBlocks;
    155     Device->BlockIo.FlushBlocks  = NvmeBlockIoFlushBlocks;
    156 
    157     //
    158     // Create StorageSecurityProtocol Instance
    159     //
    160     Device->StorageSecurity.ReceiveData = NvmeStorageSecurityReceiveData;
    161     Device->StorageSecurity.SendData    = NvmeStorageSecuritySendData;
    162 
    163     //
    164     // Create DiskInfo Protocol instance
    165     //
    166     InitializeDiskInfo (Device);
    167 
    168     //
    169     // Create a Nvm Express Namespace Device Path Node
    170     //
    171     Status = Private->Passthru.BuildDevicePath (
    172                                  &Private->Passthru,
    173                                  Device->NamespaceId,
    174                                  &NewDevicePathNode
    175                                  );
    176 
    177     if (EFI_ERROR(Status)) {
    178       goto Exit;
    179     }
    180 
    181     //
    182     // Append the SSD node to the controller's device path
    183     //
    184     DevicePath = AppendDevicePathNode (ParentDevicePath, NewDevicePathNode);
    185     if (DevicePath == NULL) {
    186       Status = EFI_OUT_OF_RESOURCES;
    187       goto Exit;
    188     }
    189 
    190     DeviceHandle = NULL;
    191     RemainingDevicePath = DevicePath;
    192     Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);
    193     if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {
    194       Status = EFI_ALREADY_STARTED;
    195       FreePool (DevicePath);
    196       goto Exit;
    197     }
    198 
    199     Device->DevicePath = DevicePath;
    200 
    201     //
    202     // Make sure the handle is NULL so we create a new handle
    203     //
    204     Device->DeviceHandle = NULL;
    205 
    206     Status = gBS->InstallMultipleProtocolInterfaces (
    207                     &Device->DeviceHandle,
    208                     &gEfiDevicePathProtocolGuid,
    209                     Device->DevicePath,
    210                     &gEfiBlockIoProtocolGuid,
    211                     &Device->BlockIo,
    212                     &gEfiDiskInfoProtocolGuid,
    213                     &Device->DiskInfo,
    214                     NULL
    215                     );
    216 
    217     if(EFI_ERROR(Status)) {
    218       goto Exit;
    219     }
    220 
    221     //
    222     // Check if the NVMe controller supports the Security Send and Security Receive commands
    223     //
    224     if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
    225       Status = gBS->InstallProtocolInterface (
    226                       &Device->DeviceHandle,
    227                       &gEfiStorageSecurityCommandProtocolGuid,
    228                       EFI_NATIVE_INTERFACE,
    229                       &Device->StorageSecurity
    230                       );
    231       if(EFI_ERROR(Status)) {
    232         gBS->UninstallMultipleProtocolInterfaces (
    233                &Device->DeviceHandle,
    234                &gEfiDevicePathProtocolGuid,
    235                Device->DevicePath,
    236                &gEfiBlockIoProtocolGuid,
    237                &Device->BlockIo,
    238                &gEfiDiskInfoProtocolGuid,
    239                &Device->DiskInfo,
    240                NULL
    241                );
    242         goto Exit;
    243       }
    244     }
    245 
    246     gBS->OpenProtocol (
    247            Private->ControllerHandle,
    248            &gEfiNvmExpressPassThruProtocolGuid,
    249            (VOID **) &Private->Passthru,
    250            Private->DriverBindingHandle,
    251            Device->DeviceHandle,
    252            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    253            );
    254 
    255     //
    256     // Dump NvmExpress Identify Namespace Data
    257     //
    258     DEBUG ((EFI_D_INFO, " == NVME IDENTIFY NAMESPACE [%d] DATA ==\n", NamespaceId));
    259     DEBUG ((EFI_D_INFO, "    NSZE        : 0x%x\n", NamespaceData->Nsze));
    260     DEBUG ((EFI_D_INFO, "    NCAP        : 0x%x\n", NamespaceData->Ncap));
    261     DEBUG ((EFI_D_INFO, "    NUSE        : 0x%x\n", NamespaceData->Nuse));
    262     DEBUG ((EFI_D_INFO, "    LBAF0.LBADS : 0x%x\n", (NamespaceData->LbaFormat[0].Lbads)));
    263 
    264     //
    265     // Build controller name for Component Name (2) protocol.
    266     //
    267     UnicodeSPrintAsciiFormat (Device->ModelName, sizeof (Device->ModelName), "%a-%a-%x", Private->ControllerData->Sn, Private->ControllerData->Mn, NamespaceData->Eui64);
    268 
    269     AddUnicodeString2 (
    270       "eng",
    271       gNvmExpressComponentName.SupportedLanguages,
    272       &Device->ControllerNameTable,
    273       Device->ModelName,
    274       TRUE
    275       );
    276 
    277     AddUnicodeString2 (
    278       "en",
    279       gNvmExpressComponentName2.SupportedLanguages,
    280       &Device->ControllerNameTable,
    281       Device->ModelName,
    282       FALSE
    283       );
    284   }
    285 
    286 Exit:
    287   if(NamespaceData != NULL) {
    288     FreePool (NamespaceData);
    289   }
    290 
    291   if (NewDevicePathNode != NULL) {
    292     FreePool (NewDevicePathNode);
    293   }
    294 
    295   if(EFI_ERROR(Status) && (Device != NULL) && (Device->DevicePath != NULL)) {
    296     FreePool (Device->DevicePath);
    297   }
    298   if(EFI_ERROR(Status) && (Device != NULL)) {
    299     FreePool (Device);
    300   }
    301   return Status;
    302 }
    303 
    304 /**
    305   Discover all Nvm Express device namespaces, and create child handles for them with BlockIo
    306   and DiskInfo protocol instances.
    307 
    308   @param[in] Private         The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
    309 
    310   @retval EFI_SUCCESS        All the namespaces in the device are successfully enumerated.
    311   @return Others             Some error occurs when enumerating the namespaces.
    312 
    313 **/
    314 EFI_STATUS
    315 DiscoverAllNamespaces (
    316   IN NVME_CONTROLLER_PRIVATE_DATA       *Private
    317   )
    318 {
    319   EFI_STATUS                            Status;
    320   UINT32                                NamespaceId;
    321   EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL    *Passthru;
    322 
    323   NamespaceId   = 0xFFFFFFFF;
    324   Passthru      = &Private->Passthru;
    325 
    326   while (TRUE) {
    327     Status = Passthru->GetNextNamespace (
    328                          Passthru,
    329                          (UINT32 *)&NamespaceId
    330                          );
    331 
    332     if (EFI_ERROR (Status)) {
    333       break;
    334     }
    335 
    336     Status = EnumerateNvmeDevNamespace (
    337                Private,
    338                NamespaceId
    339                );
    340 
    341     if (EFI_ERROR(Status)) {
    342       continue;
    343     }
    344   }
    345 
    346   return EFI_SUCCESS;
    347 }
    348 
    349 /**
    350   Unregisters a Nvm Express device namespace.
    351 
    352   This function removes the protocols installed on the controller handle and
    353   frees the resources allocated for the namespace.
    354 
    355   @param  This                  The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
    356   @param  Controller            The controller handle of the namespace.
    357   @param  Handle                The child handle.
    358 
    359   @retval EFI_SUCCESS           The namespace is successfully unregistered.
    360   @return Others                Some error occurs when unregistering the namespace.
    361 
    362 **/
    363 EFI_STATUS
    364 UnregisterNvmeNamespace (
    365   IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
    366   IN  EFI_HANDLE                     Controller,
    367   IN  EFI_HANDLE                     Handle
    368   )
    369 {
    370   EFI_STATUS                               Status;
    371   EFI_BLOCK_IO_PROTOCOL                    *BlockIo;
    372   NVME_DEVICE_PRIVATE_DATA                 *Device;
    373   NVME_CONTROLLER_PRIVATE_DATA             *Private;
    374   EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *StorageSecurity;
    375 
    376   BlockIo = NULL;
    377 
    378   Status = gBS->OpenProtocol (
    379                   Handle,
    380                   &gEfiBlockIoProtocolGuid,
    381                   (VOID **) &BlockIo,
    382                   This->DriverBindingHandle,
    383                   Controller,
    384                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    385                   );
    386   if (EFI_ERROR (Status)) {
    387     return Status;
    388   }
    389 
    390   Device  = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo);
    391   Private = Device->Controller;
    392 
    393   //
    394   // Close the child handle
    395   //
    396   gBS->CloseProtocol (
    397          Controller,
    398          &gEfiNvmExpressPassThruProtocolGuid,
    399          This->DriverBindingHandle,
    400          Handle
    401          );
    402 
    403   //
    404   // The Nvm Express driver installs the BlockIo and DiskInfo in the DriverBindingStart().
    405   // Here should uninstall both of them.
    406   //
    407   Status = gBS->UninstallMultipleProtocolInterfaces (
    408                   Handle,
    409                   &gEfiDevicePathProtocolGuid,
    410                   Device->DevicePath,
    411                   &gEfiBlockIoProtocolGuid,
    412                   &Device->BlockIo,
    413                   &gEfiDiskInfoProtocolGuid,
    414                   &Device->DiskInfo,
    415                   NULL
    416                   );
    417 
    418   if (EFI_ERROR (Status)) {
    419     gBS->OpenProtocol (
    420            Controller,
    421            &gEfiNvmExpressPassThruProtocolGuid,
    422            (VOID **) &Private->Passthru,
    423            This->DriverBindingHandle,
    424            Handle,
    425            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    426            );
    427     return Status;
    428   }
    429 
    430   //
    431   // If Storage Security Command Protocol is installed, then uninstall this protocol.
    432   //
    433   Status = gBS->OpenProtocol (
    434                   Handle,
    435                   &gEfiStorageSecurityCommandProtocolGuid,
    436                   (VOID **) &StorageSecurity,
    437                   This->DriverBindingHandle,
    438                   Controller,
    439                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    440                   );
    441 
    442   if (!EFI_ERROR (Status)) {
    443     Status = gBS->UninstallProtocolInterface (
    444                     Handle,
    445                     &gEfiStorageSecurityCommandProtocolGuid,
    446                     &Device->StorageSecurity
    447                     );
    448     if (EFI_ERROR (Status)) {
    449       gBS->OpenProtocol (
    450         Controller,
    451         &gEfiNvmExpressPassThruProtocolGuid,
    452         (VOID **) &Private->Passthru,
    453         This->DriverBindingHandle,
    454         Handle,
    455         EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    456         );
    457       return Status;
    458     }
    459   }
    460 
    461   if(Device->DevicePath != NULL) {
    462     FreePool (Device->DevicePath);
    463   }
    464 
    465   if (Device->ControllerNameTable != NULL) {
    466     FreeUnicodeStringTable (Device->ControllerNameTable);
    467   }
    468 
    469   FreePool (Device);
    470 
    471   return EFI_SUCCESS;
    472 }
    473 
    474 /**
    475   Tests to see if this driver supports a given controller. If a child device is provided,
    476   it further tests to see if this driver supports creating a handle for the specified child device.
    477 
    478   This function checks to see if the driver specified by This supports the device specified by
    479   ControllerHandle. Drivers will typically use the device path attached to
    480   ControllerHandle and/or the services from the bus I/O abstraction attached to
    481   ControllerHandle to determine if the driver supports ControllerHandle. This function
    482   may be called many times during platform initialization. In order to reduce boot times, the tests
    483   performed by this function must be very small, and take as little time as possible to execute. This
    484   function must not change the state of any hardware devices, and this function must be aware that the
    485   device specified by ControllerHandle may already be managed by the same driver or a
    486   different driver. This function must match its calls to AllocatePages() with FreePages(),
    487   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
    488   Since ControllerHandle may have been previously started by the same driver, if a protocol is
    489   already in the opened state, then it must not be closed with CloseProtocol(). This is required
    490   to guarantee the state of ControllerHandle is not modified by this function.
    491 
    492   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    493   @param[in]  ControllerHandle     The handle of the controller to test. This handle
    494                                    must support a protocol interface that supplies
    495                                    an I/O abstraction to the driver.
    496   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    497                                    parameter is ignored by device drivers, and is optional for bus
    498                                    drivers. For bus drivers, if this parameter is not NULL, then
    499                                    the bus driver must determine if the bus controller specified
    500                                    by ControllerHandle and the child controller specified
    501                                    by RemainingDevicePath are both supported by this
    502                                    bus driver.
    503 
    504   @retval EFI_SUCCESS              The device specified by ControllerHandle and
    505                                    RemainingDevicePath is supported by the driver specified by This.
    506   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
    507                                    RemainingDevicePath is already being managed by the driver
    508                                    specified by This.
    509   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
    510                                    RemainingDevicePath is already being managed by a different
    511                                    driver or an application that requires exclusive access.
    512                                    Currently not implemented.
    513   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
    514                                    RemainingDevicePath is not supported by the driver specified by This.
    515 **/
    516 EFI_STATUS
    517 EFIAPI
    518 NvmExpressDriverBindingSupported (
    519   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    520   IN EFI_HANDLE                   Controller,
    521   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    522   )
    523 {
    524   EFI_STATUS                Status;
    525   EFI_DEV_PATH_PTR          DevicePathNode;
    526   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
    527   EFI_PCI_IO_PROTOCOL       *PciIo;
    528   UINT8                     ClassCode[3];
    529 
    530   //
    531   // Check whether device path is valid
    532   //
    533   if (RemainingDevicePath != NULL) {
    534     //
    535     // Check if RemainingDevicePath is the End of Device Path Node,
    536     // if yes, go on checking other conditions
    537     //
    538     if (!IsDevicePathEnd (RemainingDevicePath)) {
    539       //
    540       // If RemainingDevicePath isn't the End of Device Path Node,
    541       // check its validation
    542       //
    543       DevicePathNode.DevPath = RemainingDevicePath;
    544 
    545       if ((DevicePathNode.DevPath->Type    != MESSAGING_DEVICE_PATH) ||
    546           (DevicePathNode.DevPath->SubType != MSG_NVME_NAMESPACE_DP) ||
    547           (DevicePathNodeLength(DevicePathNode.DevPath) != sizeof(NVME_NAMESPACE_DEVICE_PATH))) {
    548          return EFI_UNSUPPORTED;
    549       }
    550     }
    551   }
    552 
    553   //
    554   // Open the EFI Device Path protocol needed to perform the supported test
    555   //
    556   Status = gBS->OpenProtocol (
    557                   Controller,
    558                   &gEfiDevicePathProtocolGuid,
    559                   (VOID **) &ParentDevicePath,
    560                   This->DriverBindingHandle,
    561                   Controller,
    562                   EFI_OPEN_PROTOCOL_BY_DRIVER
    563                   );
    564   if (Status == EFI_ALREADY_STARTED) {
    565     return EFI_SUCCESS;
    566   }
    567 
    568   if (EFI_ERROR (Status)) {
    569     return Status;
    570   }
    571 
    572   //
    573   // Close protocol, don't use device path protocol in the Support() function
    574   //
    575   gBS->CloseProtocol (
    576          Controller,
    577          &gEfiDevicePathProtocolGuid,
    578          This->DriverBindingHandle,
    579          Controller
    580          );
    581 
    582   //
    583   // Attempt to Open PCI I/O Protocol
    584   //
    585   Status = gBS->OpenProtocol (
    586                   Controller,
    587                   &gEfiPciIoProtocolGuid,
    588                   (VOID **) &PciIo,
    589                   This->DriverBindingHandle,
    590                   Controller,
    591                   EFI_OPEN_PROTOCOL_BY_DRIVER
    592                   );
    593   if (Status == EFI_ALREADY_STARTED) {
    594     return EFI_SUCCESS;
    595   }
    596 
    597   if (EFI_ERROR (Status)) {
    598     return Status;
    599   }
    600 
    601   //
    602   // Now further check the PCI header: Base class (offset 0x0B) and Sub Class (offset 0x0A).
    603   // This controller should be a Nvm Express controller.
    604   //
    605   Status = PciIo->Pci.Read (
    606                         PciIo,
    607                         EfiPciIoWidthUint8,
    608                         PCI_CLASSCODE_OFFSET,
    609                         sizeof (ClassCode),
    610                         ClassCode
    611                         );
    612   if (EFI_ERROR (Status)) {
    613     goto Done;
    614   }
    615 
    616   //
    617   // Examine Nvm Express controller PCI Configuration table fields
    618   //
    619   if ((ClassCode[0] != PCI_IF_NVMHCI) || (ClassCode[1] != PCI_CLASS_MASS_STORAGE_NVM) || (ClassCode[2] != PCI_CLASS_MASS_STORAGE)) {
    620     Status = EFI_UNSUPPORTED;
    621   }
    622 
    623 Done:
    624   gBS->CloseProtocol (
    625          Controller,
    626          &gEfiPciIoProtocolGuid,
    627          This->DriverBindingHandle,
    628          Controller
    629          );
    630 
    631   return Status;
    632 }
    633 
    634 
    635 /**
    636   Starts a device controller or a bus controller.
    637 
    638   The Start() function is designed to be invoked from the EFI boot service ConnectController().
    639   As a result, much of the error checking on the parameters to Start() has been moved into this
    640   common boot service. It is legal to call Start() from other locations,
    641   but the following calling restrictions must be followed or the system behavior will not be deterministic.
    642   1. ControllerHandle must be a valid EFI_HANDLE.
    643   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
    644      EFI_DEVICE_PATH_PROTOCOL.
    645   3. Prior to calling Start(), the Supported() function for the driver specified by This must
    646      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
    647 
    648   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    649   @param[in]  ControllerHandle     The handle of the controller to start. This handle
    650                                    must support a protocol interface that supplies
    651                                    an I/O abstraction to the driver.
    652   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    653                                    parameter is ignored by device drivers, and is optional for bus
    654                                    drivers. For a bus driver, if this parameter is NULL, then handles
    655                                    for all the children of Controller are created by this driver.
    656                                    If this parameter is not NULL and the first Device Path Node is
    657                                    not the End of Device Path Node, then only the handle for the
    658                                    child device specified by the first Device Path Node of
    659                                    RemainingDevicePath is created by this driver.
    660                                    If the first Device Path Node of RemainingDevicePath is
    661                                    the End of Device Path Node, no child handle is created by this
    662                                    driver.
    663 
    664   @retval EFI_SUCCESS              The device was started.
    665   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
    666   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
    667   @retval Others                   The driver failded to start the device.
    668 
    669 **/
    670 EFI_STATUS
    671 EFIAPI
    672 NvmExpressDriverBindingStart (
    673   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    674   IN EFI_HANDLE                   Controller,
    675   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    676   )
    677 {
    678   EFI_STATUS                          Status;
    679   EFI_PCI_IO_PROTOCOL                 *PciIo;
    680   NVME_CONTROLLER_PRIVATE_DATA        *Private;
    681   EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
    682   UINT32                              NamespaceId;
    683   EFI_PHYSICAL_ADDRESS                MappedAddr;
    684   UINTN                               Bytes;
    685   EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL  *Passthru;
    686 
    687   DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: start\n"));
    688 
    689   Private          = NULL;
    690   Passthru         = NULL;
    691   ParentDevicePath = NULL;
    692 
    693   Status = gBS->OpenProtocol (
    694                   Controller,
    695                   &gEfiDevicePathProtocolGuid,
    696                   (VOID **) &ParentDevicePath,
    697                   This->DriverBindingHandle,
    698                   Controller,
    699                   EFI_OPEN_PROTOCOL_BY_DRIVER
    700                   );
    701   if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
    702     return Status;
    703   }
    704 
    705   Status = gBS->OpenProtocol (
    706                   Controller,
    707                   &gEfiPciIoProtocolGuid,
    708                   (VOID **) &PciIo,
    709                   This->DriverBindingHandle,
    710                   Controller,
    711                   EFI_OPEN_PROTOCOL_BY_DRIVER
    712                   );
    713 
    714   if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
    715     return Status;
    716   }
    717 
    718   //
    719   // Check EFI_ALREADY_STARTED to reuse the original NVME_CONTROLLER_PRIVATE_DATA.
    720   //
    721   if (Status != EFI_ALREADY_STARTED) {
    722     Private = AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA));
    723 
    724     if (Private == NULL) {
    725       DEBUG ((EFI_D_ERROR, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n"));
    726       Status = EFI_OUT_OF_RESOURCES;
    727       goto Exit;
    728     }
    729 
    730     //
    731     // 4 x 4kB aligned buffers will be carved out of this buffer.
    732     // 1st 4kB boundary is the start of the admin submission queue.
    733     // 2nd 4kB boundary is the start of the admin completion queue.
    734     // 3rd 4kB boundary is the start of I/O submission queue #1.
    735     // 4th 4kB boundary is the start of I/O completion queue #1.
    736     //
    737     // Allocate 4 pages of memory, then map it for bus master read and write.
    738     //
    739     Status = PciIo->AllocateBuffer (
    740                       PciIo,
    741                       AllocateAnyPages,
    742                       EfiBootServicesData,
    743                       4,
    744                       (VOID**)&Private->Buffer,
    745                       0
    746                       );
    747     if (EFI_ERROR (Status)) {
    748       goto Exit;
    749     }
    750 
    751     Bytes = EFI_PAGES_TO_SIZE (4);
    752     Status = PciIo->Map (
    753                       PciIo,
    754                       EfiPciIoOperationBusMasterCommonBuffer,
    755                       Private->Buffer,
    756                       &Bytes,
    757                       &MappedAddr,
    758                       &Private->Mapping
    759                       );
    760 
    761     if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (4))) {
    762       goto Exit;
    763     }
    764 
    765     Private->BufferPciAddr = (UINT8 *)(UINTN)MappedAddr;
    766     ZeroMem (Private->Buffer, EFI_PAGES_TO_SIZE (4));
    767 
    768     Private->Signature = NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE;
    769     Private->ControllerHandle          = Controller;
    770     Private->ImageHandle               = This->DriverBindingHandle;
    771     Private->DriverBindingHandle       = This->DriverBindingHandle;
    772     Private->PciIo                     = PciIo;
    773     Private->ParentDevicePath          = ParentDevicePath;
    774     Private->Passthru.Mode             = &Private->PassThruMode;
    775     Private->Passthru.PassThru         = NvmExpressPassThru;
    776     Private->Passthru.GetNextNamespace = NvmExpressGetNextNamespace;
    777     Private->Passthru.BuildDevicePath  = NvmExpressBuildDevicePath;
    778     Private->Passthru.GetNamespace     = NvmExpressGetNamespace;
    779     CopyMem (&Private->PassThruMode, &gEfiNvmExpressPassThruMode, sizeof (EFI_NVM_EXPRESS_PASS_THRU_MODE));
    780 
    781     Status = NvmeControllerInit (Private);
    782     if (EFI_ERROR(Status)) {
    783       goto Exit;
    784     }
    785 
    786     Status = gBS->InstallMultipleProtocolInterfaces (
    787                     &Controller,
    788                     &gEfiNvmExpressPassThruProtocolGuid,
    789                     &Private->Passthru,
    790                     NULL
    791                     );
    792     if (EFI_ERROR (Status)) {
    793       goto Exit;
    794     }
    795   } else {
    796     Status = gBS->OpenProtocol (
    797                     Controller,
    798                     &gEfiNvmExpressPassThruProtocolGuid,
    799                     (VOID **) &Passthru,
    800                     This->DriverBindingHandle,
    801                     Controller,
    802                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
    803                     );
    804     if (EFI_ERROR (Status)) {
    805       goto Exit;
    806     }
    807 
    808     Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (Passthru);
    809   }
    810 
    811   if (RemainingDevicePath == NULL) {
    812     //
    813     // Enumerate all NVME namespaces in the controller
    814     //
    815     Status = DiscoverAllNamespaces (
    816                Private
    817                );
    818 
    819   } else if (!IsDevicePathEnd (RemainingDevicePath)) {
    820     //
    821     // Enumerate the specified NVME namespace
    822     //
    823     Status = Private->Passthru.GetNamespace (
    824                                  &Private->Passthru,
    825                                  RemainingDevicePath,
    826                                  &NamespaceId
    827                                  );
    828 
    829     if (!EFI_ERROR (Status)) {
    830       Status = EnumerateNvmeDevNamespace (
    831                  Private,
    832                  NamespaceId
    833                  );
    834     }
    835   }
    836 
    837   DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: end successfully\n"));
    838   return EFI_SUCCESS;
    839 
    840 Exit:
    841   if ((Private != NULL) && (Private->Mapping != NULL)) {
    842     PciIo->Unmap (PciIo, Private->Mapping);
    843   }
    844 
    845   if ((Private != NULL) && (Private->Buffer != NULL)) {
    846     PciIo->FreeBuffer (PciIo, 4, Private->Buffer);
    847   }
    848 
    849   if (Private != NULL) {
    850     FreePool (Private);
    851   }
    852 
    853   gBS->CloseProtocol (
    854          Controller,
    855          &gEfiPciIoProtocolGuid,
    856          This->DriverBindingHandle,
    857          Controller
    858          );
    859 
    860   gBS->CloseProtocol (
    861          Controller,
    862          &gEfiDevicePathProtocolGuid,
    863          This->DriverBindingHandle,
    864          Controller
    865          );
    866 
    867   DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: end with %r\n", Status));
    868 
    869   return Status;
    870 }
    871 
    872 
    873 /**
    874   Stops a device controller or a bus controller.
    875 
    876   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
    877   As a result, much of the error checking on the parameters to Stop() has been moved
    878   into this common boot service. It is legal to call Stop() from other locations,
    879   but the following calling restrictions must be followed or the system behavior will not be deterministic.
    880   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
    881      same driver's Start() function.
    882   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
    883      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
    884      Start() function, and the Start() function must have called OpenProtocol() on
    885      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    886 
    887   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    888   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
    889                                 support a bus specific I/O protocol for the driver
    890                                 to use to stop the device.
    891   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
    892   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
    893                                 if NumberOfChildren is 0.
    894 
    895   @retval EFI_SUCCESS           The device was stopped.
    896   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
    897 
    898 **/
    899 EFI_STATUS
    900 EFIAPI
    901 NvmExpressDriverBindingStop (
    902   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
    903   IN  EFI_HANDLE                      Controller,
    904   IN  UINTN                           NumberOfChildren,
    905   IN  EFI_HANDLE                      *ChildHandleBuffer
    906   )
    907 {
    908   EFI_STATUS                          Status;
    909   BOOLEAN                             AllChildrenStopped;
    910   UINTN                               Index;
    911   NVME_CONTROLLER_PRIVATE_DATA        *Private;
    912   EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL  *PassThru;
    913 
    914   if (NumberOfChildren == 0) {
    915     Status = gBS->OpenProtocol (
    916                     Controller,
    917                     &gEfiNvmExpressPassThruProtocolGuid,
    918                     (VOID **) &PassThru,
    919                     This->DriverBindingHandle,
    920                     Controller,
    921                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
    922                     );
    923 
    924     if (!EFI_ERROR (Status)) {
    925       Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (PassThru);
    926       gBS->UninstallMultipleProtocolInterfaces (
    927             Controller,
    928             &gEfiNvmExpressPassThruProtocolGuid,
    929             PassThru,
    930             NULL
    931             );
    932 
    933       if (Private->Mapping != NULL) {
    934         Private->PciIo->Unmap (Private->PciIo, Private->Mapping);
    935       }
    936 
    937       if (Private->Buffer != NULL) {
    938         Private->PciIo->FreeBuffer (Private->PciIo, 4, Private->Buffer);
    939       }
    940 
    941       FreePool (Private->ControllerData);
    942       FreePool (Private);
    943     }
    944 
    945     gBS->CloseProtocol (
    946           Controller,
    947           &gEfiPciIoProtocolGuid,
    948           This->DriverBindingHandle,
    949           Controller
    950           );
    951     gBS->CloseProtocol (
    952           Controller,
    953           &gEfiDevicePathProtocolGuid,
    954           This->DriverBindingHandle,
    955           Controller
    956           );
    957     return EFI_SUCCESS;
    958   }
    959 
    960   AllChildrenStopped = TRUE;
    961 
    962   for (Index = 0; Index < NumberOfChildren; Index++) {
    963     Status = UnregisterNvmeNamespace (This, Controller, ChildHandleBuffer[Index]);
    964     if (EFI_ERROR (Status)) {
    965       AllChildrenStopped = FALSE;
    966     }
    967   }
    968 
    969   if (!AllChildrenStopped) {
    970     return EFI_DEVICE_ERROR;
    971   }
    972 
    973   return EFI_SUCCESS;
    974 }
    975 
    976 /**
    977   This is the unload handle for the NVM Express driver.
    978 
    979   Disconnect the driver specified by ImageHandle from the NVMe device in the handle database.
    980   Uninstall all the protocols installed in the driver.
    981 
    982   @param[in]  ImageHandle       The drivers' driver image.
    983 
    984   @retval EFI_SUCCESS           The image is unloaded.
    985   @retval Others                Failed to unload the image.
    986 
    987 **/
    988 EFI_STATUS
    989 EFIAPI
    990 NvmExpressUnload (
    991   IN EFI_HANDLE             ImageHandle
    992   )
    993 {
    994   EFI_STATUS                        Status;
    995   EFI_HANDLE                        *DeviceHandleBuffer;
    996   UINTN                             DeviceHandleCount;
    997   UINTN                             Index;
    998   EFI_COMPONENT_NAME_PROTOCOL       *ComponentName;
    999   EFI_COMPONENT_NAME2_PROTOCOL      *ComponentName2;
   1000 
   1001   //
   1002   // Get the list of the device handles managed by this driver.
   1003   // If there is an error getting the list, then means the driver
   1004   // doesn't manage any device. At this way, we would only close
   1005   // those protocols installed at image handle.
   1006   //
   1007   DeviceHandleBuffer = NULL;
   1008   Status = gBS->LocateHandleBuffer (
   1009                   ByProtocol,
   1010                   &gEfiNvmExpressPassThruProtocolGuid,
   1011                   NULL,
   1012                   &DeviceHandleCount,
   1013                   &DeviceHandleBuffer
   1014                   );
   1015 
   1016   if (!EFI_ERROR (Status)) {
   1017     //
   1018     // Disconnect the driver specified by ImageHandle from all
   1019     // the devices in the handle database.
   1020     //
   1021     for (Index = 0; Index < DeviceHandleCount; Index++) {
   1022       Status = gBS->DisconnectController (
   1023                       DeviceHandleBuffer[Index],
   1024                       ImageHandle,
   1025                       NULL
   1026                       );
   1027       if (EFI_ERROR (Status)) {
   1028         goto EXIT;
   1029       }
   1030     }
   1031   }
   1032 
   1033   //
   1034   // Uninstall all the protocols installed in the driver entry point
   1035   //
   1036   Status = gBS->UninstallMultipleProtocolInterfaces (
   1037                   ImageHandle,
   1038                   &gEfiDriverBindingProtocolGuid,
   1039                   &gNvmExpressDriverBinding,
   1040                   &gEfiDriverSupportedEfiVersionProtocolGuid,
   1041                   &gNvmExpressDriverSupportedEfiVersion,
   1042                   NULL
   1043                   );
   1044 
   1045   if (EFI_ERROR (Status)) {
   1046     goto EXIT;
   1047   }
   1048 
   1049   //
   1050   // Note we have to one by one uninstall the following protocols.
   1051   // It's because some of them are optionally installed based on
   1052   // the following PCD settings.
   1053   //   gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
   1054   //   gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable
   1055   //   gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable
   1056   //   gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable
   1057   //
   1058   Status = gBS->HandleProtocol (
   1059                   ImageHandle,
   1060                   &gEfiComponentNameProtocolGuid,
   1061                   (VOID **) &ComponentName
   1062                   );
   1063   if (!EFI_ERROR (Status)) {
   1064     gBS->UninstallProtocolInterface (
   1065            ImageHandle,
   1066            &gEfiComponentNameProtocolGuid,
   1067            ComponentName
   1068            );
   1069   }
   1070 
   1071   Status = gBS->HandleProtocol (
   1072                   ImageHandle,
   1073                   &gEfiComponentName2ProtocolGuid,
   1074                   (VOID **) &ComponentName2
   1075                   );
   1076   if (!EFI_ERROR (Status)) {
   1077     gBS->UninstallProtocolInterface (
   1078            ImageHandle,
   1079            &gEfiComponentName2ProtocolGuid,
   1080            ComponentName2
   1081            );
   1082   }
   1083 
   1084   Status = EFI_SUCCESS;
   1085 
   1086 EXIT:
   1087   //
   1088   // Free the buffer containing the list of handles from the handle database
   1089   //
   1090   if (DeviceHandleBuffer != NULL) {
   1091     gBS->FreePool (DeviceHandleBuffer);
   1092   }
   1093   return Status;
   1094 }
   1095 
   1096 /**
   1097   The entry point for Nvm Express driver, used to install Nvm Express driver on the ImageHandle.
   1098 
   1099   @param  ImageHandle   The firmware allocated handle for this driver image.
   1100   @param  SystemTable   Pointer to the EFI system table.
   1101 
   1102   @retval EFI_SUCCESS   Driver loaded.
   1103   @retval other         Driver not loaded.
   1104 
   1105 **/
   1106 EFI_STATUS
   1107 EFIAPI
   1108 NvmExpressDriverEntry (
   1109   IN EFI_HANDLE        ImageHandle,
   1110   IN EFI_SYSTEM_TABLE  *SystemTable
   1111   )
   1112 {
   1113   EFI_STATUS              Status;
   1114 
   1115   Status = EfiLibInstallDriverBindingComponentName2 (
   1116              ImageHandle,
   1117              SystemTable,
   1118              &gNvmExpressDriverBinding,
   1119              ImageHandle,
   1120              &gNvmExpressComponentName,
   1121              &gNvmExpressComponentName2
   1122              );
   1123   ASSERT_EFI_ERROR (Status);
   1124 
   1125   //
   1126   // Install EFI Driver Supported EFI Version Protocol required for
   1127   // EFI drivers that are on PCI and other plug in cards.
   1128   //
   1129   gNvmExpressDriverSupportedEfiVersion.FirmwareVersion = 0x00020028;
   1130   Status = gBS->InstallMultipleProtocolInterfaces (
   1131                   &ImageHandle,
   1132                   &gEfiDriverSupportedEfiVersionProtocolGuid,
   1133                   &gNvmExpressDriverSupportedEfiVersion,
   1134                   NULL
   1135                   );
   1136   ASSERT_EFI_ERROR (Status);
   1137   return Status;
   1138 }
   1139