2 NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3 NVM Express specification.
5 Copyright (c) 2013, 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
) {
111 // Initialize SSD namespace instance data
113 Device
->Signature
= NVME_DEVICE_PRIVATE_DATA_SIGNATURE
;
114 Device
->NamespaceId
= NamespaceId
;
115 Device
->NamespaceUuid
= NamespaceData
->Eui64
;
117 Device
->ControllerHandle
= Private
->ControllerHandle
;
118 Device
->DriverBindingHandle
= Private
->DriverBindingHandle
;
119 Device
->Controller
= Private
;
122 // Build BlockIo media structure
124 Device
->Media
.MediaId
= 0;
125 Device
->Media
.RemovableMedia
= FALSE
;
126 Device
->Media
.MediaPresent
= TRUE
;
127 Device
->Media
.LogicalPartition
= FALSE
;
128 Device
->Media
.ReadOnly
= FALSE
;
129 Device
->Media
.WriteCaching
= FALSE
;
131 Flbas
= NamespaceData
->Flbas
;
132 LbaFmtIdx
= Flbas
& 3;
133 Lbads
= NamespaceData
->LbaFormat
[LbaFmtIdx
].Lbads
;
134 Device
->Media
.BlockSize
= (UINT32
)1 << Lbads
;
136 Device
->Media
.LastBlock
= NamespaceData
->Nsze
- 1;
137 Device
->Media
.LogicalBlocksPerPhysicalBlock
= 1;
138 Device
->Media
.LowestAlignedLba
= 1;
141 // Create BlockIo Protocol instance
143 Device
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION2
;
144 Device
->BlockIo
.Media
= &Device
->Media
;
145 Device
->BlockIo
.Reset
= NvmeBlockIoReset
;
146 Device
->BlockIo
.ReadBlocks
= NvmeBlockIoReadBlocks
;
147 Device
->BlockIo
.WriteBlocks
= NvmeBlockIoWriteBlocks
;
148 Device
->BlockIo
.FlushBlocks
= NvmeBlockIoFlushBlocks
;
151 // Create DiskInfo Protocol instance
153 InitializeDiskInfo (Device
);
156 // Create a Nvm Express Namespace Device Path Node
158 Status
= Private
->Passthru
.BuildDevicePath (
161 Device
->NamespaceUuid
,
165 if (EFI_ERROR(Status
)) {
170 // Append the SSD node to the controller's device path
172 DevicePath
= AppendDevicePathNode (ParentDevicePath
, NewDevicePathNode
);
173 if (DevicePath
== NULL
) {
174 Status
= EFI_OUT_OF_RESOURCES
;
179 RemainingDevicePath
= DevicePath
;
180 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &DeviceHandle
);
181 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd(RemainingDevicePath
)) {
182 Status
= EFI_ALREADY_STARTED
;
183 FreePool (DevicePath
);
187 Device
->DevicePath
= DevicePath
;
190 // Make sure the handle is NULL so we create a new handle
192 Device
->DeviceHandle
= NULL
;
194 Status
= gBS
->InstallMultipleProtocolInterfaces (
195 &Device
->DeviceHandle
,
196 &gEfiDevicePathProtocolGuid
,
198 &gEfiBlockIoProtocolGuid
,
200 &gEfiDiskInfoProtocolGuid
,
205 if(EFI_ERROR(Status
)) {
209 Private
->ControllerHandle
,
210 &gEfiPciIoProtocolGuid
,
211 (VOID
**) &Private
->PciIo
,
212 Private
->DriverBindingHandle
,
213 Device
->DeviceHandle
,
214 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
218 // Dump NvmExpress Identify Namespace Data
220 DEBUG ((EFI_D_INFO
, " == NVME IDENTIFY NAMESPACE [%d] DATA ==\n", NamespaceId
));
221 DEBUG ((EFI_D_INFO
, " NSZE : 0x%x\n", NamespaceData
->Nsze
));
222 DEBUG ((EFI_D_INFO
, " NCAP : 0x%x\n", NamespaceData
->Ncap
));
223 DEBUG ((EFI_D_INFO
, " NUSE : 0x%x\n", NamespaceData
->Nuse
));
224 DEBUG ((EFI_D_INFO
, " LBAF0.LBADS : 0x%x\n", (NamespaceData
->LbaFormat
[0].Lbads
)));
227 // Build controller name for Component Name (2) protocol.
229 UnicodeSPrintAsciiFormat (Device
->ModelName
, sizeof (Device
->ModelName
), "%a-%a-%x", Private
->ControllerData
->Sn
, Private
->ControllerData
->Mn
, NamespaceData
->Eui64
);
233 gNvmExpressComponentName
.SupportedLanguages
,
234 &Device
->ControllerNameTable
,
241 gNvmExpressComponentName2
.SupportedLanguages
,
242 &Device
->ControllerNameTable
,
249 if(NamespaceData
!= NULL
) {
250 FreePool (NamespaceData
);
253 if(EFI_ERROR(Status
) && (Device
!= NULL
) && (Device
->DevicePath
!= NULL
)) {
254 FreePool (Device
->DevicePath
);
256 if(EFI_ERROR(Status
) && (Device
!= NULL
)) {
263 Discover all Nvm Express device namespaces, and create child handles for them with BlockIo
264 and DiskInfo protocol instances.
266 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
268 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
269 @return Others Some error occurs when enumerating the namespaces.
273 DiscoverAllNamespaces (
274 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
279 UINT64 NamespaceUuid
;
280 NVM_EXPRESS_PASS_THRU_PROTOCOL
*Passthru
;
282 NamespaceId
= 0xFFFFFFFF;
284 Passthru
= &Private
->Passthru
;
287 Status
= Passthru
->GetNextNamespace (
289 (UINT32
*)&NamespaceId
,
290 (UINT64
*)&NamespaceUuid
293 if (EFI_ERROR (Status
)) {
297 Status
= EnumerateNvmeDevNamespace (
303 if (EFI_ERROR(Status
)) {
312 Unregisters a Nvm Express device namespace.
314 This function removes the protocols installed on the controller handle and
315 frees the resources allocated for the namespace.
317 @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
318 @param Controller The controller handle of the namespace.
319 @param Handle The child handle.
321 @retval EFI_SUCCESS The namespace is successfully unregistered.
322 @return Others Some error occurs when unregistering the namespace.
326 UnregisterNvmeNamespace (
327 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
328 IN EFI_HANDLE Controller
,
333 EFI_PCI_IO_PROTOCOL
*PciIo
;
334 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
335 NVME_DEVICE_PRIVATE_DATA
*Device
;
339 Status
= gBS
->OpenProtocol (
341 &gEfiBlockIoProtocolGuid
,
343 This
->DriverBindingHandle
,
345 EFI_OPEN_PROTOCOL_GET_PROTOCOL
347 if (EFI_ERROR (Status
)) {
351 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo
);
354 // Close the child handle
358 &gEfiPciIoProtocolGuid
,
359 This
->DriverBindingHandle
,
364 // The Nvm Express driver installs the BlockIo and DiskInfo in the DriverBindingStart().
365 // Here should uninstall both of them.
367 Status
= gBS
->UninstallMultipleProtocolInterfaces (
369 &gEfiDevicePathProtocolGuid
,
371 &gEfiBlockIoProtocolGuid
,
373 &gEfiDiskInfoProtocolGuid
,
378 if (EFI_ERROR (Status
)) {
381 &gEfiPciIoProtocolGuid
,
383 This
->DriverBindingHandle
,
385 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
390 if(Device
->DevicePath
!= NULL
) {
391 FreePool (Device
->DevicePath
);
394 if (Device
->ControllerNameTable
!= NULL
) {
395 FreeUnicodeStringTable (Device
->ControllerNameTable
);
402 Tests to see if this driver supports a given controller. If a child device is provided,
403 it further tests to see if this driver supports creating a handle for the specified child device.
405 This function checks to see if the driver specified by This supports the device specified by
406 ControllerHandle. Drivers will typically use the device path attached to
407 ControllerHandle and/or the services from the bus I/O abstraction attached to
408 ControllerHandle to determine if the driver supports ControllerHandle. This function
409 may be called many times during platform initialization. In order to reduce boot times, the tests
410 performed by this function must be very small, and take as little time as possible to execute. This
411 function must not change the state of any hardware devices, and this function must be aware that the
412 device specified by ControllerHandle may already be managed by the same driver or a
413 different driver. This function must match its calls to AllocatePages() with FreePages(),
414 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
415 Since ControllerHandle may have been previously started by the same driver, if a protocol is
416 already in the opened state, then it must not be closed with CloseProtocol(). This is required
417 to guarantee the state of ControllerHandle is not modified by this function.
419 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
420 @param[in] ControllerHandle The handle of the controller to test. This handle
421 must support a protocol interface that supplies
422 an I/O abstraction to the driver.
423 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
424 parameter is ignored by device drivers, and is optional for bus
425 drivers. For bus drivers, if this parameter is not NULL, then
426 the bus driver must determine if the bus controller specified
427 by ControllerHandle and the child controller specified
428 by RemainingDevicePath are both supported by this
431 @retval EFI_SUCCESS The device specified by ControllerHandle and
432 RemainingDevicePath is supported by the driver specified by This.
433 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
434 RemainingDevicePath is already being managed by the driver
436 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
437 RemainingDevicePath is already being managed by a different
438 driver or an application that requires exclusive access.
439 Currently not implemented.
440 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
441 RemainingDevicePath is not supported by the driver specified by This.
445 NvmExpressDriverBindingSupported (
446 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
447 IN EFI_HANDLE Controller
,
448 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
452 EFI_DEV_PATH_PTR DevicePathNode
;
453 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
454 EFI_PCI_IO_PROTOCOL
*PciIo
;
458 // Check whether device path is valid
460 if (RemainingDevicePath
!= NULL
) {
462 // Check if RemainingDevicePath is the End of Device Path Node,
463 // if yes, go on checking other conditions
465 if (!IsDevicePathEnd (RemainingDevicePath
)) {
467 // If RemainingDevicePath isn't the End of Device Path Node,
468 // check its validation
470 DevicePathNode
.DevPath
= RemainingDevicePath
;
472 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
473 (DevicePathNode
.DevPath
->SubType
!= MSG_NVME_NAMESPACE_DP
) ||
474 DevicePathNodeLength(DevicePathNode
.DevPath
) != sizeof(NVME_NAMESPACE_DEVICE_PATH
)) {
475 return EFI_UNSUPPORTED
;
481 // Open the EFI Device Path protocol needed to perform the supported test
483 Status
= gBS
->OpenProtocol (
485 &gEfiDevicePathProtocolGuid
,
486 (VOID
**) &ParentDevicePath
,
487 This
->DriverBindingHandle
,
489 EFI_OPEN_PROTOCOL_BY_DRIVER
491 if (Status
== EFI_ALREADY_STARTED
) {
495 if (EFI_ERROR (Status
)) {
500 // Close protocol, don't use device path protocol in the Support() function
504 &gEfiDevicePathProtocolGuid
,
505 This
->DriverBindingHandle
,
510 // Attempt to Open PCI I/O Protocol
512 Status
= gBS
->OpenProtocol (
514 &gEfiPciIoProtocolGuid
,
516 This
->DriverBindingHandle
,
518 EFI_OPEN_PROTOCOL_BY_DRIVER
520 if (Status
== EFI_ALREADY_STARTED
) {
524 if (EFI_ERROR (Status
)) {
529 // Now further check the PCI header: Base class (offset 0x0B) and Sub Class (offset 0x0A).
530 // This controller should be a Nvm Express controller.
532 Status
= PciIo
->Pci
.Read (
535 PCI_CLASSCODE_OFFSET
,
539 if (EFI_ERROR (Status
)) {
544 // Examine Nvm Express controller PCI Configuration table fields
546 if ((ClassCode
[0] != PCI_IF_NVMHCI
) || (ClassCode
[1] != PCI_CLASS_MASS_STORAGE_NVM
) || (ClassCode
[2] != PCI_CLASS_MASS_STORAGE
)) {
547 Status
= EFI_UNSUPPORTED
;
553 &gEfiPciIoProtocolGuid
,
554 This
->DriverBindingHandle
,
563 Starts a device controller or a bus controller.
565 The Start() function is designed to be invoked from the EFI boot service ConnectController().
566 As a result, much of the error checking on the parameters to Start() has been moved into this
567 common boot service. It is legal to call Start() from other locations,
568 but the following calling restrictions must be followed or the system behavior will not be deterministic.
569 1. ControllerHandle must be a valid EFI_HANDLE.
570 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
571 EFI_DEVICE_PATH_PROTOCOL.
572 3. Prior to calling Start(), the Supported() function for the driver specified by This must
573 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
575 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
576 @param[in] ControllerHandle The handle of the controller to start. This handle
577 must support a protocol interface that supplies
578 an I/O abstraction to the driver.
579 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
580 parameter is ignored by device drivers, and is optional for bus
581 drivers. For a bus driver, if this parameter is NULL, then handles
582 for all the children of Controller are created by this driver.
583 If this parameter is not NULL and the first Device Path Node is
584 not the End of Device Path Node, then only the handle for the
585 child device specified by the first Device Path Node of
586 RemainingDevicePath is created by this driver.
587 If the first Device Path Node of RemainingDevicePath is
588 the End of Device Path Node, no child handle is created by this
591 @retval EFI_SUCCESS The device was started.
592 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
593 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
594 @retval Others The driver failded to start the device.
599 NvmExpressDriverBindingStart (
600 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
601 IN EFI_HANDLE Controller
,
602 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
606 EFI_PCI_IO_PROTOCOL
*PciIo
;
607 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
608 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
610 UINT64 NamespaceUuid
;
611 EFI_PHYSICAL_ADDRESS MappedAddr
;
614 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: start\n"));
617 ParentDevicePath
= NULL
;
619 Status
= gBS
->OpenProtocol (
621 &gEfiDevicePathProtocolGuid
,
622 (VOID
**) &ParentDevicePath
,
623 This
->DriverBindingHandle
,
625 EFI_OPEN_PROTOCOL_BY_DRIVER
627 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
631 Status
= gBS
->OpenProtocol (
633 &gEfiPciIoProtocolGuid
,
635 This
->DriverBindingHandle
,
637 EFI_OPEN_PROTOCOL_BY_DRIVER
640 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
645 // Check EFI_ALREADY_STARTED to reuse the original NVME_CONTROLLER_PRIVATE_DATA.
647 if (Status
!= EFI_ALREADY_STARTED
) {
648 Private
= AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA
));
650 if (Private
== NULL
) {
651 DEBUG ((EFI_D_ERROR
, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n"));
652 Status
= EFI_OUT_OF_RESOURCES
;
657 // 4 x 4kB aligned buffers will be carved out of this buffer.
658 // 1st 4kB boundary is the start of the admin submission queue.
659 // 2nd 4kB boundary is the start of the admin completion queue.
660 // 3rd 4kB boundary is the start of I/O submission queue #1.
661 // 4th 4kB boundary is the start of I/O completion queue #1.
663 // Allocate 4 pages of memory, then map it for bus master read and write.
665 Status
= PciIo
->AllocateBuffer (
670 (VOID
**)&Private
->Buffer
,
673 if (EFI_ERROR (Status
)) {
677 Bytes
= EFI_PAGES_TO_SIZE (4);
678 Status
= PciIo
->Map (
680 EfiPciIoOperationBusMasterCommonBuffer
,
687 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (4))) {
691 Private
->BufferPciAddr
= (UINT8
*)(UINTN
)MappedAddr
;
692 ZeroMem (Private
->Buffer
, EFI_PAGES_TO_SIZE (4));
694 Private
->Signature
= NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE
;
695 Private
->ControllerHandle
= Controller
;
696 Private
->ImageHandle
= This
->DriverBindingHandle
;
697 Private
->DriverBindingHandle
= This
->DriverBindingHandle
;
698 Private
->PciIo
= PciIo
;
699 Private
->ParentDevicePath
= ParentDevicePath
;
700 Private
->Passthru
.Mode
= &Private
->PassThruMode
;
701 Private
->Passthru
.PassThru
= NvmExpressPassThru
;
702 Private
->Passthru
.GetNextNamespace
= NvmExpressGetNextNamespace
;
703 Private
->Passthru
.BuildDevicePath
= NvmExpressBuildDevicePath
;
704 Private
->Passthru
.GetNamespace
= NvmExpressGetNamespace
;
705 Private
->PassThruMode
.Attributes
= NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL
;
707 Status
= NvmeControllerInit (Private
);
709 if (EFI_ERROR(Status
)) {
713 Status
= gBS
->InstallMultipleProtocolInterfaces (
719 if (EFI_ERROR (Status
)) {
723 Status
= gBS
->OpenProtocol (
727 This
->DriverBindingHandle
,
729 EFI_OPEN_PROTOCOL_GET_PROTOCOL
731 if (EFI_ERROR (Status
)) {
737 if (RemainingDevicePath
== NULL
) {
739 // Enumerate all NVME namespaces in the controller
741 Status
= DiscoverAllNamespaces (
745 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
747 // Enumerate the specified NVME namespace
749 Status
= Private
->Passthru
.GetNamespace (
756 if (!EFI_ERROR (Status
)) {
757 Status
= EnumerateNvmeDevNamespace (
765 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: end successfully\n"));
769 gBS
->UninstallMultipleProtocolInterfaces (
776 if ((Private
!= NULL
) && (Private
->Mapping
!= NULL
)) {
777 PciIo
->Unmap (PciIo
, Private
->Mapping
);
780 if ((Private
!= NULL
) && (Private
->Buffer
!= NULL
)) {
781 PciIo
->FreeBuffer (PciIo
, 4, Private
->Buffer
);
784 if (Private
!= NULL
) {
790 &gEfiPciIoProtocolGuid
,
791 This
->DriverBindingHandle
,
797 &gEfiDevicePathProtocolGuid
,
798 This
->DriverBindingHandle
,
802 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: end with %r\n", Status
));
809 Stops a device controller or a bus controller.
811 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
812 As a result, much of the error checking on the parameters to Stop() has been moved
813 into this common boot service. It is legal to call Stop() from other locations,
814 but the following calling restrictions must be followed or the system behavior will not be deterministic.
815 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
816 same driver's Start() function.
817 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
818 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
819 Start() function, and the Start() function must have called OpenProtocol() on
820 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
822 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
823 @param[in] ControllerHandle A handle to the device being stopped. The handle must
824 support a bus specific I/O protocol for the driver
825 to use to stop the device.
826 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
827 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
828 if NumberOfChildren is 0.
830 @retval EFI_SUCCESS The device was stopped.
831 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
836 NvmExpressDriverBindingStop (
837 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
838 IN EFI_HANDLE Controller
,
839 IN UINTN NumberOfChildren
,
840 IN EFI_HANDLE
*ChildHandleBuffer
844 BOOLEAN AllChildrenStopped
;
846 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
848 if (NumberOfChildren
== 0) {
849 Status
= gBS
->OpenProtocol (
853 This
->DriverBindingHandle
,
855 EFI_OPEN_PROTOCOL_GET_PROTOCOL
858 if (!EFI_ERROR (Status
)) {
859 gBS
->UninstallMultipleProtocolInterfaces (
866 if (Private
->Mapping
!= NULL
) {
867 Private
->PciIo
->Unmap (Private
->PciIo
, Private
->Mapping
);
870 if (Private
->Buffer
!= NULL
) {
871 Private
->PciIo
->FreeBuffer (Private
->PciIo
, 4, Private
->Buffer
);
874 FreePool (Private
->ControllerData
);
880 &gEfiPciIoProtocolGuid
,
881 This
->DriverBindingHandle
,
886 &gEfiDevicePathProtocolGuid
,
887 This
->DriverBindingHandle
,
893 AllChildrenStopped
= TRUE
;
895 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
896 Status
= UnregisterNvmeNamespace (This
, Controller
, ChildHandleBuffer
[Index
]);
897 if (EFI_ERROR (Status
)) {
898 AllChildrenStopped
= FALSE
;
902 if (!AllChildrenStopped
) {
903 return EFI_DEVICE_ERROR
;
910 This is the unload handle for the NVM Express driver.
912 Disconnect the driver specified by ImageHandle from the NVMe device in the handle database.
913 Uninstall all the protocols installed in the driver.
915 @param[in] ImageHandle The drivers' driver image.
917 @retval EFI_SUCCESS The image is unloaded.
918 @retval Others Failed to unload the image.
924 IN EFI_HANDLE ImageHandle
928 EFI_HANDLE
*DeviceHandleBuffer
;
929 UINTN DeviceHandleCount
;
931 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
932 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
933 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
936 // Get the list of all the handles in the handle database.
937 // If there is an error getting the list, then the unload
940 Status
= gBS
->LocateHandleBuffer (
948 if (EFI_ERROR (Status
)) {
953 // Disconnect the driver specified by ImageHandle from all
954 // the devices in the handle database.
956 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
957 Status
= gBS
->DisconnectController (
958 DeviceHandleBuffer
[Index
],
965 // Uninstall all the protocols installed in the driver entry point
967 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
968 Status
= gBS
->HandleProtocol (
969 DeviceHandleBuffer
[Index
],
970 &gEfiDriverBindingProtocolGuid
,
971 (VOID
**) &DriverBinding
974 if (EFI_ERROR (Status
)) {
978 if (DriverBinding
->ImageHandle
!= ImageHandle
) {
982 gBS
->UninstallProtocolInterface (
984 &gEfiDriverBindingProtocolGuid
,
988 Status
= gBS
->HandleProtocol (
989 DeviceHandleBuffer
[Index
],
990 &gEfiComponentNameProtocolGuid
,
991 (VOID
**) &ComponentName
993 if (!EFI_ERROR (Status
)) {
994 gBS
->UninstallProtocolInterface (
996 &gEfiComponentNameProtocolGuid
,
1001 Status
= gBS
->HandleProtocol (
1002 DeviceHandleBuffer
[Index
],
1003 &gEfiComponentName2ProtocolGuid
,
1004 (VOID
**) &ComponentName2
1006 if (!EFI_ERROR (Status
)) {
1007 gBS
->UninstallProtocolInterface (
1009 &gEfiComponentName2ProtocolGuid
,
1016 // Free the buffer containing the list of handles from the handle database
1018 if (DeviceHandleBuffer
!= NULL
) {
1019 gBS
->FreePool (DeviceHandleBuffer
);
1025 The entry point for Nvm Express driver, used to install Nvm Express driver on the ImageHandle.
1027 @param ImageHandle The firmware allocated handle for this driver image.
1028 @param SystemTable Pointer to the EFI system table.
1030 @retval EFI_SUCCESS Driver loaded.
1031 @retval other Driver not loaded.
1036 NvmExpressDriverEntry (
1037 IN EFI_HANDLE ImageHandle
,
1038 IN EFI_SYSTEM_TABLE
*SystemTable
1043 Status
= EfiLibInstallDriverBindingComponentName2 (
1046 &gNvmExpressDriverBinding
,
1048 &gNvmExpressComponentName
,
1049 &gNvmExpressComponentName2
1051 ASSERT_EFI_ERROR (Status
);
1054 // Install EFI Driver Supported EFI Version Protocol required for
1055 // EFI drivers that are on PCI and other plug in cards.
1057 gNvmExpressDriverSupportedEfiVersion
.FirmwareVersion
= 0x00020028;
1058 Status
= gBS
->InstallMultipleProtocolInterfaces (
1060 &gEfiDriverSupportedEfiVersionProtocolGuid
,
1061 &gNvmExpressDriverSupportedEfiVersion
,
1064 ASSERT_EFI_ERROR (Status
);