• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
EnumerateNvmeDevNamespace(IN NVME_CONTROLLER_PRIVATE_DATA * Private,UINT32 NamespaceId)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
DiscoverAllNamespaces(IN NVME_CONTROLLER_PRIVATE_DATA * Private)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
UnregisterNvmeNamespace(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_HANDLE Handle)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
NvmExpressDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
NvmExpressDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
NvmExpressDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)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
NvmExpressUnload(IN EFI_HANDLE ImageHandle)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
NvmExpressDriverEntry(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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