2 NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3 NVM Express specification.
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.
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.
16 #include "NvmExpress.h"
19 // NVM Express Driver Binding Protocol Instance
21 EFI_DRIVER_BINDING_PROTOCOL gNvmExpressDriverBinding
= {
22 NvmExpressDriverBindingSupported
,
23 NvmExpressDriverBindingStart
,
24 NvmExpressDriverBindingStop
,
31 // NVM Express EFI Driver Supported EFI Version Protocol Instance
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.
39 Check if the specified Nvm Express device namespace is active, and create child handles
40 for them with BlockIo and DiskInfo protocol instances.
42 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
43 @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
44 allocated and built. Caller must set the NamespaceId to zero if the
45 device path node will contain a valid UUID.
46 @param[in] NamespaceUuid The NVM Express namespace UUID for which a device path node is to be
47 allocated and built. UUID will only be valid of the Namespace ID is zero.
49 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
50 @return Others Some error occurs when enumerating the namespaces.
54 EnumerateNvmeDevNamespace (
55 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
60 NVME_ADMIN_NAMESPACE_DATA
*NamespaceData
;
61 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePathNode
;
62 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
63 EFI_HANDLE DeviceHandle
;
64 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
65 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
66 NVME_DEVICE_PRIVATE_DATA
*Device
;
72 NewDevicePathNode
= NULL
;
77 // Allocate a buffer for Identify Namespace data
79 NamespaceData
= AllocateZeroPool(sizeof (NVME_ADMIN_NAMESPACE_DATA
));
80 if(NamespaceData
== NULL
) {
81 return EFI_OUT_OF_RESOURCES
;
84 ParentDevicePath
= Private
->ParentDevicePath
;
88 Status
= NvmeIdentifyNamespace (
93 if (EFI_ERROR(Status
)) {
99 if (NamespaceData
->Ncap
== 0) {
100 Status
= EFI_DEVICE_ERROR
;
103 // allocate device private data for each discovered namespace
105 Device
= AllocateZeroPool(sizeof(NVME_DEVICE_PRIVATE_DATA
));
106 if (Device
== NULL
) {
107 Status
= EFI_OUT_OF_RESOURCES
;
112 // Initialize SSD namespace instance data
114 Device
->Signature
= NVME_DEVICE_PRIVATE_DATA_SIGNATURE
;
115 Device
->NamespaceId
= NamespaceId
;
116 Device
->NamespaceUuid
= NamespaceData
->Eui64
;
118 Device
->ControllerHandle
= Private
->ControllerHandle
;
119 Device
->DriverBindingHandle
= Private
->DriverBindingHandle
;
120 Device
->Controller
= Private
;
123 // Build BlockIo media structure
125 Device
->Media
.MediaId
= 0;
126 Device
->Media
.RemovableMedia
= FALSE
;
127 Device
->Media
.MediaPresent
= TRUE
;
128 Device
->Media
.LogicalPartition
= FALSE
;
129 Device
->Media
.ReadOnly
= FALSE
;
130 Device
->Media
.WriteCaching
= FALSE
;
132 Flbas
= NamespaceData
->Flbas
;
133 LbaFmtIdx
= Flbas
& 0xF;
134 Lbads
= NamespaceData
->LbaFormat
[LbaFmtIdx
].Lbads
;
135 Device
->Media
.BlockSize
= (UINT32
)1 << Lbads
;
137 Device
->Media
.LastBlock
= NamespaceData
->Nsze
- 1;
138 Device
->Media
.LogicalBlocksPerPhysicalBlock
= 1;
139 Device
->Media
.LowestAlignedLba
= 1;
142 // Create BlockIo Protocol instance
144 Device
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION2
;
145 Device
->BlockIo
.Media
= &Device
->Media
;
146 Device
->BlockIo
.Reset
= NvmeBlockIoReset
;
147 Device
->BlockIo
.ReadBlocks
= NvmeBlockIoReadBlocks
;
148 Device
->BlockIo
.WriteBlocks
= NvmeBlockIoWriteBlocks
;
149 Device
->BlockIo
.FlushBlocks
= NvmeBlockIoFlushBlocks
;
152 // Create DiskInfo Protocol instance
154 InitializeDiskInfo (Device
);
157 // Create a Nvm Express Namespace Device Path Node
159 Status
= Private
->Passthru
.BuildDevicePath (
162 Device
->NamespaceUuid
,
166 if (EFI_ERROR(Status
)) {
171 // Append the SSD node to the controller's device path
173 DevicePath
= AppendDevicePathNode (ParentDevicePath
, NewDevicePathNode
);
174 if (DevicePath
== NULL
) {
175 Status
= EFI_OUT_OF_RESOURCES
;
180 RemainingDevicePath
= DevicePath
;
181 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &DeviceHandle
);
182 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd(RemainingDevicePath
)) {
183 Status
= EFI_ALREADY_STARTED
;
184 FreePool (DevicePath
);
188 Device
->DevicePath
= DevicePath
;
191 // Make sure the handle is NULL so we create a new handle
193 Device
->DeviceHandle
= NULL
;
195 Status
= gBS
->InstallMultipleProtocolInterfaces (
196 &Device
->DeviceHandle
,
197 &gEfiDevicePathProtocolGuid
,
199 &gEfiBlockIoProtocolGuid
,
201 &gEfiDiskInfoProtocolGuid
,
206 if(EFI_ERROR(Status
)) {
210 Private
->ControllerHandle
,
211 &gEfiPciIoProtocolGuid
,
212 (VOID
**) &Private
->PciIo
,
213 Private
->DriverBindingHandle
,
214 Device
->DeviceHandle
,
215 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
219 // Dump NvmExpress Identify Namespace Data
221 DEBUG ((EFI_D_INFO
, " == NVME IDENTIFY NAMESPACE [%d] DATA ==\n", NamespaceId
));
222 DEBUG ((EFI_D_INFO
, " NSZE : 0x%x\n", NamespaceData
->Nsze
));
223 DEBUG ((EFI_D_INFO
, " NCAP : 0x%x\n", NamespaceData
->Ncap
));
224 DEBUG ((EFI_D_INFO
, " NUSE : 0x%x\n", NamespaceData
->Nuse
));
225 DEBUG ((EFI_D_INFO
, " LBAF0.LBADS : 0x%x\n", (NamespaceData
->LbaFormat
[0].Lbads
)));
228 // Build controller name for Component Name (2) protocol.
230 UnicodeSPrintAsciiFormat (Device
->ModelName
, sizeof (Device
->ModelName
), "%a-%a-%x", Private
->ControllerData
->Sn
, Private
->ControllerData
->Mn
, NamespaceData
->Eui64
);
234 gNvmExpressComponentName
.SupportedLanguages
,
235 &Device
->ControllerNameTable
,
242 gNvmExpressComponentName2
.SupportedLanguages
,
243 &Device
->ControllerNameTable
,
250 if(NamespaceData
!= NULL
) {
251 FreePool (NamespaceData
);
254 if (NewDevicePathNode
!= NULL
) {
255 FreePool (NewDevicePathNode
);
258 if(EFI_ERROR(Status
) && (Device
!= NULL
) && (Device
->DevicePath
!= NULL
)) {
259 FreePool (Device
->DevicePath
);
261 if(EFI_ERROR(Status
) && (Device
!= NULL
)) {
268 Discover all Nvm Express device namespaces, and create child handles for them with BlockIo
269 and DiskInfo protocol instances.
271 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
273 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
274 @return Others Some error occurs when enumerating the namespaces.
278 DiscoverAllNamespaces (
279 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
284 UINT64 NamespaceUuid
;
285 NVM_EXPRESS_PASS_THRU_PROTOCOL
*Passthru
;
287 NamespaceId
= 0xFFFFFFFF;
289 Passthru
= &Private
->Passthru
;
292 Status
= Passthru
->GetNextNamespace (
294 (UINT32
*)&NamespaceId
,
295 (UINT64
*)&NamespaceUuid
298 if (EFI_ERROR (Status
)) {
302 Status
= EnumerateNvmeDevNamespace (
308 if (EFI_ERROR(Status
)) {
317 Unregisters a Nvm Express device namespace.
319 This function removes the protocols installed on the controller handle and
320 frees the resources allocated for the namespace.
322 @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
323 @param Controller The controller handle of the namespace.
324 @param Handle The child handle.
326 @retval EFI_SUCCESS The namespace is successfully unregistered.
327 @return Others Some error occurs when unregistering the namespace.
331 UnregisterNvmeNamespace (
332 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
333 IN EFI_HANDLE Controller
,
338 EFI_PCI_IO_PROTOCOL
*PciIo
;
339 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
340 NVME_DEVICE_PRIVATE_DATA
*Device
;
344 Status
= gBS
->OpenProtocol (
346 &gEfiBlockIoProtocolGuid
,
348 This
->DriverBindingHandle
,
350 EFI_OPEN_PROTOCOL_GET_PROTOCOL
352 if (EFI_ERROR (Status
)) {
356 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo
);
359 // Close the child handle
363 &gEfiPciIoProtocolGuid
,
364 This
->DriverBindingHandle
,
369 // The Nvm Express driver installs the BlockIo and DiskInfo in the DriverBindingStart().
370 // Here should uninstall both of them.
372 Status
= gBS
->UninstallMultipleProtocolInterfaces (
374 &gEfiDevicePathProtocolGuid
,
376 &gEfiBlockIoProtocolGuid
,
378 &gEfiDiskInfoProtocolGuid
,
383 if (EFI_ERROR (Status
)) {
386 &gEfiPciIoProtocolGuid
,
388 This
->DriverBindingHandle
,
390 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
395 if(Device
->DevicePath
!= NULL
) {
396 FreePool (Device
->DevicePath
);
399 if (Device
->ControllerNameTable
!= NULL
) {
400 FreeUnicodeStringTable (Device
->ControllerNameTable
);
409 Tests to see if this driver supports a given controller. If a child device is provided,
410 it further tests to see if this driver supports creating a handle for the specified child device.
412 This function checks to see if the driver specified by This supports the device specified by
413 ControllerHandle. Drivers will typically use the device path attached to
414 ControllerHandle and/or the services from the bus I/O abstraction attached to
415 ControllerHandle to determine if the driver supports ControllerHandle. This function
416 may be called many times during platform initialization. In order to reduce boot times, the tests
417 performed by this function must be very small, and take as little time as possible to execute. This
418 function must not change the state of any hardware devices, and this function must be aware that the
419 device specified by ControllerHandle may already be managed by the same driver or a
420 different driver. This function must match its calls to AllocatePages() with FreePages(),
421 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
422 Since ControllerHandle may have been previously started by the same driver, if a protocol is
423 already in the opened state, then it must not be closed with CloseProtocol(). This is required
424 to guarantee the state of ControllerHandle is not modified by this function.
426 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
427 @param[in] ControllerHandle The handle of the controller to test. This handle
428 must support a protocol interface that supplies
429 an I/O abstraction to the driver.
430 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
431 parameter is ignored by device drivers, and is optional for bus
432 drivers. For bus drivers, if this parameter is not NULL, then
433 the bus driver must determine if the bus controller specified
434 by ControllerHandle and the child controller specified
435 by RemainingDevicePath are both supported by this
438 @retval EFI_SUCCESS The device specified by ControllerHandle and
439 RemainingDevicePath is supported by the driver specified by This.
440 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
441 RemainingDevicePath is already being managed by the driver
443 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
444 RemainingDevicePath is already being managed by a different
445 driver or an application that requires exclusive access.
446 Currently not implemented.
447 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
448 RemainingDevicePath is not supported by the driver specified by This.
452 NvmExpressDriverBindingSupported (
453 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
454 IN EFI_HANDLE Controller
,
455 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
459 EFI_DEV_PATH_PTR DevicePathNode
;
460 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
461 EFI_PCI_IO_PROTOCOL
*PciIo
;
465 // Check whether device path is valid
467 if (RemainingDevicePath
!= NULL
) {
469 // Check if RemainingDevicePath is the End of Device Path Node,
470 // if yes, go on checking other conditions
472 if (!IsDevicePathEnd (RemainingDevicePath
)) {
474 // If RemainingDevicePath isn't the End of Device Path Node,
475 // check its validation
477 DevicePathNode
.DevPath
= RemainingDevicePath
;
479 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
480 (DevicePathNode
.DevPath
->SubType
!= MSG_NVME_NAMESPACE_DP
) ||
481 DevicePathNodeLength(DevicePathNode
.DevPath
) != sizeof(NVME_NAMESPACE_DEVICE_PATH
)) {
482 return EFI_UNSUPPORTED
;
488 // Open the EFI Device Path protocol needed to perform the supported test
490 Status
= gBS
->OpenProtocol (
492 &gEfiDevicePathProtocolGuid
,
493 (VOID
**) &ParentDevicePath
,
494 This
->DriverBindingHandle
,
496 EFI_OPEN_PROTOCOL_BY_DRIVER
498 if (Status
== EFI_ALREADY_STARTED
) {
502 if (EFI_ERROR (Status
)) {
507 // Close protocol, don't use device path protocol in the Support() function
511 &gEfiDevicePathProtocolGuid
,
512 This
->DriverBindingHandle
,
517 // Attempt to Open PCI I/O Protocol
519 Status
= gBS
->OpenProtocol (
521 &gEfiPciIoProtocolGuid
,
523 This
->DriverBindingHandle
,
525 EFI_OPEN_PROTOCOL_BY_DRIVER
527 if (Status
== EFI_ALREADY_STARTED
) {
531 if (EFI_ERROR (Status
)) {
536 // Now further check the PCI header: Base class (offset 0x0B) and Sub Class (offset 0x0A).
537 // This controller should be a Nvm Express controller.
539 Status
= PciIo
->Pci
.Read (
542 PCI_CLASSCODE_OFFSET
,
546 if (EFI_ERROR (Status
)) {
551 // Examine Nvm Express controller PCI Configuration table fields
553 if ((ClassCode
[0] != PCI_IF_NVMHCI
) || (ClassCode
[1] != PCI_CLASS_MASS_STORAGE_NVM
) || (ClassCode
[2] != PCI_CLASS_MASS_STORAGE
)) {
554 Status
= EFI_UNSUPPORTED
;
560 &gEfiPciIoProtocolGuid
,
561 This
->DriverBindingHandle
,
570 Starts a device controller or a bus controller.
572 The Start() function is designed to be invoked from the EFI boot service ConnectController().
573 As a result, much of the error checking on the parameters to Start() has been moved into this
574 common boot service. It is legal to call Start() from other locations,
575 but the following calling restrictions must be followed or the system behavior will not be deterministic.
576 1. ControllerHandle must be a valid EFI_HANDLE.
577 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
578 EFI_DEVICE_PATH_PROTOCOL.
579 3. Prior to calling Start(), the Supported() function for the driver specified by This must
580 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
582 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
583 @param[in] ControllerHandle The handle of the controller to start. This handle
584 must support a protocol interface that supplies
585 an I/O abstraction to the driver.
586 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
587 parameter is ignored by device drivers, and is optional for bus
588 drivers. For a bus driver, if this parameter is NULL, then handles
589 for all the children of Controller are created by this driver.
590 If this parameter is not NULL and the first Device Path Node is
591 not the End of Device Path Node, then only the handle for the
592 child device specified by the first Device Path Node of
593 RemainingDevicePath is created by this driver.
594 If the first Device Path Node of RemainingDevicePath is
595 the End of Device Path Node, no child handle is created by this
598 @retval EFI_SUCCESS The device was started.
599 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
600 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
601 @retval Others The driver failded to start the device.
606 NvmExpressDriverBindingStart (
607 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
608 IN EFI_HANDLE Controller
,
609 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
613 EFI_PCI_IO_PROTOCOL
*PciIo
;
614 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
615 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
617 UINT64 NamespaceUuid
;
618 EFI_PHYSICAL_ADDRESS MappedAddr
;
621 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: start\n"));
624 ParentDevicePath
= NULL
;
626 Status
= gBS
->OpenProtocol (
628 &gEfiDevicePathProtocolGuid
,
629 (VOID
**) &ParentDevicePath
,
630 This
->DriverBindingHandle
,
632 EFI_OPEN_PROTOCOL_BY_DRIVER
634 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
638 Status
= gBS
->OpenProtocol (
640 &gEfiPciIoProtocolGuid
,
642 This
->DriverBindingHandle
,
644 EFI_OPEN_PROTOCOL_BY_DRIVER
647 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
652 // Check EFI_ALREADY_STARTED to reuse the original NVME_CONTROLLER_PRIVATE_DATA.
654 if (Status
!= EFI_ALREADY_STARTED
) {
655 Private
= AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA
));
657 if (Private
== NULL
) {
658 DEBUG ((EFI_D_ERROR
, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n"));
659 Status
= EFI_OUT_OF_RESOURCES
;
664 // 4 x 4kB aligned buffers will be carved out of this buffer.
665 // 1st 4kB boundary is the start of the admin submission queue.
666 // 2nd 4kB boundary is the start of the admin completion queue.
667 // 3rd 4kB boundary is the start of I/O submission queue #1.
668 // 4th 4kB boundary is the start of I/O completion queue #1.
670 // Allocate 4 pages of memory, then map it for bus master read and write.
672 Status
= PciIo
->AllocateBuffer (
677 (VOID
**)&Private
->Buffer
,
680 if (EFI_ERROR (Status
)) {
684 Bytes
= EFI_PAGES_TO_SIZE (4);
685 Status
= PciIo
->Map (
687 EfiPciIoOperationBusMasterCommonBuffer
,
694 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (4))) {
698 Private
->BufferPciAddr
= (UINT8
*)(UINTN
)MappedAddr
;
699 ZeroMem (Private
->Buffer
, EFI_PAGES_TO_SIZE (4));
701 Private
->Signature
= NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE
;
702 Private
->ControllerHandle
= Controller
;
703 Private
->ImageHandle
= This
->DriverBindingHandle
;
704 Private
->DriverBindingHandle
= This
->DriverBindingHandle
;
705 Private
->PciIo
= PciIo
;
706 Private
->ParentDevicePath
= ParentDevicePath
;
707 Private
->Passthru
.Mode
= &Private
->PassThruMode
;
708 Private
->Passthru
.PassThru
= NvmExpressPassThru
;
709 Private
->Passthru
.GetNextNamespace
= NvmExpressGetNextNamespace
;
710 Private
->Passthru
.BuildDevicePath
= NvmExpressBuildDevicePath
;
711 Private
->Passthru
.GetNamespace
= NvmExpressGetNamespace
;
712 Private
->PassThruMode
.Attributes
= NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL
;
714 Status
= NvmeControllerInit (Private
);
716 if (EFI_ERROR(Status
)) {
720 Status
= gBS
->InstallMultipleProtocolInterfaces (
726 if (EFI_ERROR (Status
)) {
730 Status
= gBS
->OpenProtocol (
734 This
->DriverBindingHandle
,
736 EFI_OPEN_PROTOCOL_GET_PROTOCOL
738 if (EFI_ERROR (Status
)) {
744 if (RemainingDevicePath
== NULL
) {
746 // Enumerate all NVME namespaces in the controller
748 Status
= DiscoverAllNamespaces (
752 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
754 // Enumerate the specified NVME namespace
756 Status
= Private
->Passthru
.GetNamespace (
763 if (!EFI_ERROR (Status
)) {
764 Status
= EnumerateNvmeDevNamespace (
772 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: end successfully\n"));
776 gBS
->UninstallMultipleProtocolInterfaces (
783 if ((Private
!= NULL
) && (Private
->Mapping
!= NULL
)) {
784 PciIo
->Unmap (PciIo
, Private
->Mapping
);
787 if ((Private
!= NULL
) && (Private
->Buffer
!= NULL
)) {
788 PciIo
->FreeBuffer (PciIo
, 4, Private
->Buffer
);
791 if (Private
!= NULL
) {
797 &gEfiPciIoProtocolGuid
,
798 This
->DriverBindingHandle
,
804 &gEfiDevicePathProtocolGuid
,
805 This
->DriverBindingHandle
,
809 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: end with %r\n", Status
));
816 Stops a device controller or a bus controller.
818 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
819 As a result, much of the error checking on the parameters to Stop() has been moved
820 into this common boot service. It is legal to call Stop() from other locations,
821 but the following calling restrictions must be followed or the system behavior will not be deterministic.
822 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
823 same driver's Start() function.
824 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
825 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
826 Start() function, and the Start() function must have called OpenProtocol() on
827 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
829 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
830 @param[in] ControllerHandle A handle to the device being stopped. The handle must
831 support a bus specific I/O protocol for the driver
832 to use to stop the device.
833 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
834 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
835 if NumberOfChildren is 0.
837 @retval EFI_SUCCESS The device was stopped.
838 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
843 NvmExpressDriverBindingStop (
844 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
845 IN EFI_HANDLE Controller
,
846 IN UINTN NumberOfChildren
,
847 IN EFI_HANDLE
*ChildHandleBuffer
851 BOOLEAN AllChildrenStopped
;
853 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
855 if (NumberOfChildren
== 0) {
856 Status
= gBS
->OpenProtocol (
860 This
->DriverBindingHandle
,
862 EFI_OPEN_PROTOCOL_GET_PROTOCOL
865 if (!EFI_ERROR (Status
)) {
866 gBS
->UninstallMultipleProtocolInterfaces (
873 if (Private
->Mapping
!= NULL
) {
874 Private
->PciIo
->Unmap (Private
->PciIo
, Private
->Mapping
);
877 if (Private
->Buffer
!= NULL
) {
878 Private
->PciIo
->FreeBuffer (Private
->PciIo
, 4, Private
->Buffer
);
881 FreePool (Private
->ControllerData
);
887 &gEfiPciIoProtocolGuid
,
888 This
->DriverBindingHandle
,
893 &gEfiDevicePathProtocolGuid
,
894 This
->DriverBindingHandle
,
900 AllChildrenStopped
= TRUE
;
902 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
903 Status
= UnregisterNvmeNamespace (This
, Controller
, ChildHandleBuffer
[Index
]);
904 if (EFI_ERROR (Status
)) {
905 AllChildrenStopped
= FALSE
;
909 if (!AllChildrenStopped
) {
910 return EFI_DEVICE_ERROR
;
917 This is the unload handle for the NVM Express driver.
919 Disconnect the driver specified by ImageHandle from the NVMe device in the handle database.
920 Uninstall all the protocols installed in the driver.
922 @param[in] ImageHandle The drivers' driver image.
924 @retval EFI_SUCCESS The image is unloaded.
925 @retval Others Failed to unload the image.
931 IN EFI_HANDLE ImageHandle
935 EFI_HANDLE
*DeviceHandleBuffer
;
936 UINTN DeviceHandleCount
;
938 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
939 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
942 // Get the list of the device handles managed by this driver.
943 // If there is an error getting the list, then means the driver
944 // doesn't manage any device. At this way, we would only close
945 // those protocols installed at image handle.
947 DeviceHandleBuffer
= NULL
;
948 Status
= gBS
->LocateHandleBuffer (
956 if (!EFI_ERROR (Status
)) {
958 // Disconnect the driver specified by ImageHandle from all
959 // the devices in the handle database.
961 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
962 Status
= gBS
->DisconnectController (
963 DeviceHandleBuffer
[Index
],
967 if (EFI_ERROR (Status
)) {
974 // Uninstall all the protocols installed in the driver entry point
976 Status
= gBS
->UninstallMultipleProtocolInterfaces (
978 &gEfiDriverBindingProtocolGuid
,
979 &gNvmExpressDriverBinding
,
980 &gEfiDriverSupportedEfiVersionProtocolGuid
,
981 &gNvmExpressDriverSupportedEfiVersion
,
985 if (EFI_ERROR (Status
)) {
990 // Note we have to one by one uninstall the following protocols.
991 // It's because some of them are optionally installed based on
992 // the following PCD settings.
993 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
994 // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable
995 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable
996 // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable
998 Status
= gBS
->HandleProtocol (
1000 &gEfiComponentNameProtocolGuid
,
1001 (VOID
**) &ComponentName
1003 if (!EFI_ERROR (Status
)) {
1004 gBS
->UninstallProtocolInterface (
1006 &gEfiComponentNameProtocolGuid
,
1011 Status
= gBS
->HandleProtocol (
1013 &gEfiComponentName2ProtocolGuid
,
1014 (VOID
**) &ComponentName2
1016 if (!EFI_ERROR (Status
)) {
1017 gBS
->UninstallProtocolInterface (
1019 &gEfiComponentName2ProtocolGuid
,
1024 Status
= EFI_SUCCESS
;
1028 // Free the buffer containing the list of handles from the handle database
1030 if (DeviceHandleBuffer
!= NULL
) {
1031 gBS
->FreePool (DeviceHandleBuffer
);
1037 The entry point for Nvm Express driver, used to install Nvm Express driver on the ImageHandle.
1039 @param ImageHandle The firmware allocated handle for this driver image.
1040 @param SystemTable Pointer to the EFI system table.
1042 @retval EFI_SUCCESS Driver loaded.
1043 @retval other Driver not loaded.
1048 NvmExpressDriverEntry (
1049 IN EFI_HANDLE ImageHandle
,
1050 IN EFI_SYSTEM_TABLE
*SystemTable
1055 Status
= EfiLibInstallDriverBindingComponentName2 (
1058 &gNvmExpressDriverBinding
,
1060 &gNvmExpressComponentName
,
1061 &gNvmExpressComponentName2
1063 ASSERT_EFI_ERROR (Status
);
1066 // Install EFI Driver Supported EFI Version Protocol required for
1067 // EFI drivers that are on PCI and other plug in cards.
1069 gNvmExpressDriverSupportedEfiVersion
.FirmwareVersion
= 0x00020028;
1070 Status
= gBS
->InstallMultipleProtocolInterfaces (
1072 &gEfiDriverSupportedEfiVersionProtocolGuid
,
1073 &gNvmExpressDriverSupportedEfiVersion
,
1076 ASSERT_EFI_ERROR (Status
);