2 NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3 NVM Express specification.
5 Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "NvmExpress.h"
13 // NVM Express Driver Binding Protocol Instance
15 EFI_DRIVER_BINDING_PROTOCOL gNvmExpressDriverBinding
= {
16 NvmExpressDriverBindingSupported
,
17 NvmExpressDriverBindingStart
,
18 NvmExpressDriverBindingStop
,
25 // NVM Express EFI Driver Supported EFI Version Protocol Instance
27 EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiVersion
= {
28 sizeof (EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL
), // Size of Protocol structure.
29 0 // Version number to be filled at start up.
33 // Template for NVM Express Pass Thru Mode data structure.
35 GLOBAL_REMOVE_IF_UNREFERENCED EFI_NVM_EXPRESS_PASS_THRU_MODE gEfiNvmExpressPassThruMode
= {
36 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL
|
37 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL
|
38 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_NONBLOCKIO
|
39 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM
,
45 Check if the specified Nvm Express device namespace is active, and create child handles
46 for them with BlockIo and DiskInfo protocol instances.
48 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
49 @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
50 allocated and built. Caller must set the NamespaceId to zero if the
51 device path node will contain a valid UUID.
53 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
54 @return Others Some error occurs when enumerating the namespaces.
58 EnumerateNvmeDevNamespace (
59 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
63 NVME_ADMIN_NAMESPACE_DATA
*NamespaceData
;
64 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePathNode
;
65 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
66 EFI_HANDLE DeviceHandle
;
67 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
68 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
69 NVME_DEVICE_PRIVATE_DATA
*Device
;
78 NewDevicePathNode
= NULL
;
83 // Allocate a buffer for Identify Namespace data
85 NamespaceData
= AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA
));
86 if (NamespaceData
== NULL
) {
87 return EFI_OUT_OF_RESOURCES
;
90 ParentDevicePath
= Private
->ParentDevicePath
;
94 Status
= NvmeIdentifyNamespace (
99 if (EFI_ERROR (Status
)) {
104 // Validate Namespace
106 if (NamespaceData
->Ncap
== 0) {
107 Status
= EFI_DEVICE_ERROR
;
110 // allocate device private data for each discovered namespace
112 Device
= AllocateZeroPool (sizeof (NVME_DEVICE_PRIVATE_DATA
));
113 if (Device
== NULL
) {
114 Status
= EFI_OUT_OF_RESOURCES
;
119 // Initialize SSD namespace instance data
121 Device
->Signature
= NVME_DEVICE_PRIVATE_DATA_SIGNATURE
;
122 Device
->NamespaceId
= NamespaceId
;
123 Device
->NamespaceUuid
= NamespaceData
->Eui64
;
125 Device
->ControllerHandle
= Private
->ControllerHandle
;
126 Device
->DriverBindingHandle
= Private
->DriverBindingHandle
;
127 Device
->Controller
= Private
;
130 // Build BlockIo media structure
132 Device
->Media
.MediaId
= 0;
133 Device
->Media
.RemovableMedia
= FALSE
;
134 Device
->Media
.MediaPresent
= TRUE
;
135 Device
->Media
.LogicalPartition
= FALSE
;
136 Device
->Media
.ReadOnly
= FALSE
;
137 Device
->Media
.WriteCaching
= FALSE
;
138 Device
->Media
.IoAlign
= Private
->PassThruMode
.IoAlign
;
140 Flbas
= NamespaceData
->Flbas
;
141 LbaFmtIdx
= Flbas
& 0xF;
144 // Currently this NVME driver only suport Metadata Size == 0
146 if (NamespaceData
->LbaFormat
[LbaFmtIdx
].Ms
!= 0) {
149 "NVME IDENTIFY NAMESPACE [%d] Ms(%d) is not supported.\n",
151 NamespaceData
->LbaFormat
[LbaFmtIdx
].Ms
153 Status
= EFI_UNSUPPORTED
;
157 Lbads
= NamespaceData
->LbaFormat
[LbaFmtIdx
].Lbads
;
158 Device
->Media
.BlockSize
= (UINT32
)1 << Lbads
;
160 Device
->Media
.LastBlock
= NamespaceData
->Nsze
- 1;
161 Device
->Media
.LogicalBlocksPerPhysicalBlock
= 1;
162 Device
->Media
.LowestAlignedLba
= 1;
165 // Create BlockIo Protocol instance
167 Device
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION2
;
168 Device
->BlockIo
.Media
= &Device
->Media
;
169 Device
->BlockIo
.Reset
= NvmeBlockIoReset
;
170 Device
->BlockIo
.ReadBlocks
= NvmeBlockIoReadBlocks
;
171 Device
->BlockIo
.WriteBlocks
= NvmeBlockIoWriteBlocks
;
172 Device
->BlockIo
.FlushBlocks
= NvmeBlockIoFlushBlocks
;
175 // Create BlockIo2 Protocol instance
177 Device
->BlockIo2
.Media
= &Device
->Media
;
178 Device
->BlockIo2
.Reset
= NvmeBlockIoResetEx
;
179 Device
->BlockIo2
.ReadBlocksEx
= NvmeBlockIoReadBlocksEx
;
180 Device
->BlockIo2
.WriteBlocksEx
= NvmeBlockIoWriteBlocksEx
;
181 Device
->BlockIo2
.FlushBlocksEx
= NvmeBlockIoFlushBlocksEx
;
182 InitializeListHead (&Device
->AsyncQueue
);
185 // Create StorageSecurityProtocol Instance
187 Device
->StorageSecurity
.ReceiveData
= NvmeStorageSecurityReceiveData
;
188 Device
->StorageSecurity
.SendData
= NvmeStorageSecuritySendData
;
191 // Create DiskInfo Protocol instance
193 CopyMem (&Device
->NamespaceData
, NamespaceData
, sizeof (NVME_ADMIN_NAMESPACE_DATA
));
194 InitializeDiskInfo (Device
);
197 // Create a Nvm Express Namespace Device Path Node
199 Status
= Private
->Passthru
.BuildDevicePath (
205 if (EFI_ERROR (Status
)) {
210 // Append the SSD node to the controller's device path
212 DevicePath
= AppendDevicePathNode (ParentDevicePath
, NewDevicePathNode
);
213 if (DevicePath
== NULL
) {
214 Status
= EFI_OUT_OF_RESOURCES
;
219 RemainingDevicePath
= DevicePath
;
220 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &DeviceHandle
);
221 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd (RemainingDevicePath
)) {
222 Status
= EFI_ALREADY_STARTED
;
223 FreePool (DevicePath
);
227 Device
->DevicePath
= DevicePath
;
230 // Make sure the handle is NULL so we create a new handle
232 Device
->DeviceHandle
= NULL
;
234 Status
= gBS
->InstallMultipleProtocolInterfaces (
235 &Device
->DeviceHandle
,
236 &gEfiDevicePathProtocolGuid
,
238 &gEfiBlockIoProtocolGuid
,
240 &gEfiBlockIo2ProtocolGuid
,
242 &gEfiDiskInfoProtocolGuid
,
247 if (EFI_ERROR (Status
)) {
252 // Check if the NVMe controller supports the Security Send and Security Receive commands
254 if ((Private
->ControllerData
->Oacs
& SECURITY_SEND_RECEIVE_SUPPORTED
) != 0) {
255 Status
= gBS
->InstallProtocolInterface (
256 &Device
->DeviceHandle
,
257 &gEfiStorageSecurityCommandProtocolGuid
,
258 EFI_NATIVE_INTERFACE
,
259 &Device
->StorageSecurity
261 if (EFI_ERROR (Status
)) {
262 gBS
->UninstallMultipleProtocolInterfaces (
263 Device
->DeviceHandle
,
264 &gEfiDevicePathProtocolGuid
,
266 &gEfiBlockIoProtocolGuid
,
268 &gEfiBlockIo2ProtocolGuid
,
270 &gEfiDiskInfoProtocolGuid
,
279 Private
->ControllerHandle
,
280 &gEfiNvmExpressPassThruProtocolGuid
,
281 (VOID
**)&DummyInterface
,
282 Private
->DriverBindingHandle
,
283 Device
->DeviceHandle
,
284 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
288 // Dump NvmExpress Identify Namespace Data
290 DEBUG ((DEBUG_INFO
, " == NVME IDENTIFY NAMESPACE [%d] DATA ==\n", NamespaceId
));
291 DEBUG ((DEBUG_INFO
, " NSZE : 0x%x\n", NamespaceData
->Nsze
));
292 DEBUG ((DEBUG_INFO
, " NCAP : 0x%x\n", NamespaceData
->Ncap
));
293 DEBUG ((DEBUG_INFO
, " NUSE : 0x%x\n", NamespaceData
->Nuse
));
294 DEBUG ((DEBUG_INFO
, " LBAF0.LBADS : 0x%x\n", (NamespaceData
->LbaFormat
[0].Lbads
)));
297 // Build controller name for Component Name (2) protocol.
299 CopyMem (Sn
, Private
->ControllerData
->Sn
, sizeof (Private
->ControllerData
->Sn
));
301 CopyMem (Mn
, Private
->ControllerData
->Mn
, sizeof (Private
->ControllerData
->Mn
));
303 UnicodeSPrintAsciiFormat (Device
->ModelName
, sizeof (Device
->ModelName
), "%a-%a-%x", Sn
, Mn
, NamespaceData
->Eui64
);
307 gNvmExpressComponentName
.SupportedLanguages
,
308 &Device
->ControllerNameTable
,
315 gNvmExpressComponentName2
.SupportedLanguages
,
316 &Device
->ControllerNameTable
,
323 if (NamespaceData
!= NULL
) {
324 FreePool (NamespaceData
);
327 if (NewDevicePathNode
!= NULL
) {
328 FreePool (NewDevicePathNode
);
331 if (EFI_ERROR (Status
) && (Device
!= NULL
) && (Device
->DevicePath
!= NULL
)) {
332 FreePool (Device
->DevicePath
);
335 if (EFI_ERROR (Status
) && (Device
!= NULL
)) {
343 Discover all Nvm Express device namespaces, and create child handles for them with BlockIo
344 and DiskInfo protocol instances.
346 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
348 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
349 @return Others Some error occurs when enumerating the namespaces.
353 DiscoverAllNamespaces (
354 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
359 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*Passthru
;
361 NamespaceId
= 0xFFFFFFFF;
362 Passthru
= &Private
->Passthru
;
365 Status
= Passthru
->GetNextNamespace (
367 (UINT32
*)&NamespaceId
370 if (EFI_ERROR (Status
)) {
374 Status
= EnumerateNvmeDevNamespace (
379 if (EFI_ERROR (Status
)) {
388 Unregisters a Nvm Express device namespace.
390 This function removes the protocols installed on the controller handle and
391 frees the resources allocated for the namespace.
393 @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
394 @param Controller The controller handle of the namespace.
395 @param Handle The child handle.
397 @retval EFI_SUCCESS The namespace is successfully unregistered.
398 @return Others Some error occurs when unregistering the namespace.
402 UnregisterNvmeNamespace (
403 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
404 IN EFI_HANDLE Controller
,
409 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
410 NVME_DEVICE_PRIVATE_DATA
*Device
;
411 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*StorageSecurity
;
414 VOID
*DummyInterface
;
418 Status
= gBS
->OpenProtocol (
420 &gEfiBlockIoProtocolGuid
,
422 This
->DriverBindingHandle
,
424 EFI_OPEN_PROTOCOL_GET_PROTOCOL
426 if (EFI_ERROR (Status
)) {
430 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo
);
433 // Wait for the device's asynchronous I/O queue to become empty.
436 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
437 IsEmpty
= IsListEmpty (&Device
->AsyncQueue
);
438 gBS
->RestoreTPL (OldTpl
);
448 // Close the child handle
452 &gEfiNvmExpressPassThruProtocolGuid
,
453 This
->DriverBindingHandle
,
458 // The Nvm Express driver installs the BlockIo and DiskInfo in the DriverBindingStart().
459 // Here should uninstall both of them.
461 Status
= gBS
->UninstallMultipleProtocolInterfaces (
463 &gEfiDevicePathProtocolGuid
,
465 &gEfiBlockIoProtocolGuid
,
467 &gEfiBlockIo2ProtocolGuid
,
469 &gEfiDiskInfoProtocolGuid
,
474 if (EFI_ERROR (Status
)) {
477 &gEfiNvmExpressPassThruProtocolGuid
,
478 (VOID
**)&DummyInterface
,
479 This
->DriverBindingHandle
,
481 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
487 // If Storage Security Command Protocol is installed, then uninstall this protocol.
489 Status
= gBS
->OpenProtocol (
491 &gEfiStorageSecurityCommandProtocolGuid
,
492 (VOID
**)&StorageSecurity
,
493 This
->DriverBindingHandle
,
495 EFI_OPEN_PROTOCOL_GET_PROTOCOL
498 if (!EFI_ERROR (Status
)) {
499 Status
= gBS
->UninstallProtocolInterface (
501 &gEfiStorageSecurityCommandProtocolGuid
,
502 &Device
->StorageSecurity
504 if (EFI_ERROR (Status
)) {
507 &gEfiNvmExpressPassThruProtocolGuid
,
508 (VOID
**)&DummyInterface
,
509 This
->DriverBindingHandle
,
511 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
517 if (Device
->DevicePath
!= NULL
) {
518 FreePool (Device
->DevicePath
);
521 if (Device
->ControllerNameTable
!= NULL
) {
522 FreeUnicodeStringTable (Device
->ControllerNameTable
);
531 Call back function when the timer event is signaled.
533 @param[in] Event The Event this notify function registered to.
534 @param[in] Context Pointer to the context data registered to the
540 ProcessAsyncTaskList (
545 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
546 EFI_PCI_IO_PROTOCOL
*PciIo
;
551 LIST_ENTRY
*NextLink
;
552 NVME_PASS_THRU_ASYNC_REQ
*AsyncRequest
;
553 NVME_BLKIO2_SUBTASK
*Subtask
;
554 NVME_BLKIO2_REQUEST
*BlkIo2Request
;
555 EFI_BLOCK_IO2_TOKEN
*Token
;
559 Private
= (NVME_CONTROLLER_PRIVATE_DATA
*)Context
;
561 Cq
= Private
->CqBuffer
[QueueId
] + Private
->CqHdbl
[QueueId
].Cqh
;
563 PciIo
= Private
->PciIo
;
566 // Submit asynchronous subtasks to the NVMe Submission Queue
568 for (Link
= GetFirstNode (&Private
->UnsubmittedSubtasks
);
569 !IsNull (&Private
->UnsubmittedSubtasks
, Link
);
572 NextLink
= GetNextNode (&Private
->UnsubmittedSubtasks
, Link
);
573 Subtask
= NVME_BLKIO2_SUBTASK_FROM_LINK (Link
);
574 BlkIo2Request
= Subtask
->BlockIo2Request
;
575 Token
= BlkIo2Request
->Token
;
576 RemoveEntryList (Link
);
577 BlkIo2Request
->UnsubmittedSubtaskNum
--;
580 // If any previous subtask fails, do not process subsequent ones.
582 if (Token
->TransactionStatus
!= EFI_SUCCESS
) {
583 if (IsListEmpty (&BlkIo2Request
->SubtasksQueue
) &&
584 BlkIo2Request
->LastSubtaskSubmitted
&&
585 (BlkIo2Request
->UnsubmittedSubtaskNum
== 0))
588 // Remove the BlockIo2 request from the device asynchronous queue.
590 RemoveEntryList (&BlkIo2Request
->Link
);
591 FreePool (BlkIo2Request
);
592 gBS
->SignalEvent (Token
->Event
);
595 FreePool (Subtask
->CommandPacket
->NvmeCmd
);
596 FreePool (Subtask
->CommandPacket
->NvmeCompletion
);
597 FreePool (Subtask
->CommandPacket
);
603 Status
= Private
->Passthru
.PassThru (
605 Subtask
->NamespaceId
,
606 Subtask
->CommandPacket
,
609 if (Status
== EFI_NOT_READY
) {
610 InsertHeadList (&Private
->UnsubmittedSubtasks
, Link
);
611 BlkIo2Request
->UnsubmittedSubtaskNum
++;
613 } else if (EFI_ERROR (Status
)) {
614 Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
616 if (IsListEmpty (&BlkIo2Request
->SubtasksQueue
) &&
620 // Remove the BlockIo2 request from the device asynchronous queue.
622 RemoveEntryList (&BlkIo2Request
->Link
);
623 FreePool (BlkIo2Request
);
624 gBS
->SignalEvent (Token
->Event
);
627 FreePool (Subtask
->CommandPacket
->NvmeCmd
);
628 FreePool (Subtask
->CommandPacket
->NvmeCompletion
);
629 FreePool (Subtask
->CommandPacket
);
632 InsertTailList (&BlkIo2Request
->SubtasksQueue
, Link
);
633 if (Subtask
->IsLast
) {
634 BlkIo2Request
->LastSubtaskSubmitted
= TRUE
;
639 while (Cq
->Pt
!= Private
->Pt
[QueueId
]) {
640 ASSERT (Cq
->Sqid
== QueueId
);
645 // Find the command with given Command Id.
647 for (Link
= GetFirstNode (&Private
->AsyncPassThruQueue
);
648 !IsNull (&Private
->AsyncPassThruQueue
, Link
);
651 NextLink
= GetNextNode (&Private
->AsyncPassThruQueue
, Link
);
652 AsyncRequest
= NVME_PASS_THRU_ASYNC_REQ_FROM_THIS (Link
);
653 if (AsyncRequest
->CommandId
== Cq
->Cid
) {
655 // Copy the Respose Queue entry for this command to the callers
659 AsyncRequest
->Packet
->NvmeCompletion
,
661 sizeof (EFI_NVM_EXPRESS_COMPLETION
)
665 // Free the resources allocated before cmd submission
667 if (AsyncRequest
->MapData
!= NULL
) {
668 PciIo
->Unmap (PciIo
, AsyncRequest
->MapData
);
671 if (AsyncRequest
->MapMeta
!= NULL
) {
672 PciIo
->Unmap (PciIo
, AsyncRequest
->MapMeta
);
675 if (AsyncRequest
->MapPrpList
!= NULL
) {
676 PciIo
->Unmap (PciIo
, AsyncRequest
->MapPrpList
);
679 if (AsyncRequest
->PrpListHost
!= NULL
) {
682 AsyncRequest
->PrpListNo
,
683 AsyncRequest
->PrpListHost
687 RemoveEntryList (Link
);
688 gBS
->SignalEvent (AsyncRequest
->CallerEvent
);
689 FreePool (AsyncRequest
);
692 // Update submission queue head.
694 Private
->AsyncSqHead
= Cq
->Sqhd
;
699 Private
->CqHdbl
[QueueId
].Cqh
++;
700 if (Private
->CqHdbl
[QueueId
].Cqh
> MIN (NVME_ASYNC_CCQ_SIZE
, Private
->Cap
.Mqes
)) {
701 Private
->CqHdbl
[QueueId
].Cqh
= 0;
702 Private
->Pt
[QueueId
] ^= 1;
705 Cq
= Private
->CqBuffer
[QueueId
] + Private
->CqHdbl
[QueueId
].Cqh
;
709 Data
= ReadUnaligned32 ((UINT32
*)&Private
->CqHdbl
[QueueId
]);
714 NVME_CQHDBL_OFFSET (QueueId
, Private
->Cap
.Dstrd
),
722 Tests to see if this driver supports a given controller. If a child device is provided,
723 it further tests to see if this driver supports creating a handle for the specified child device.
725 This function checks to see if the driver specified by This supports the device specified by
726 ControllerHandle. Drivers will typically use the device path attached to
727 ControllerHandle and/or the services from the bus I/O abstraction attached to
728 ControllerHandle to determine if the driver supports ControllerHandle. This function
729 may be called many times during platform initialization. In order to reduce boot times, the tests
730 performed by this function must be very small, and take as little time as possible to execute. This
731 function must not change the state of any hardware devices, and this function must be aware that the
732 device specified by ControllerHandle may already be managed by the same driver or a
733 different driver. This function must match its calls to AllocatePages() with FreePages(),
734 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
735 Since ControllerHandle may have been previously started by the same driver, if a protocol is
736 already in the opened state, then it must not be closed with CloseProtocol(). This is required
737 to guarantee the state of ControllerHandle is not modified by this function.
739 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
740 @param[in] ControllerHandle The handle of the controller to test. This handle
741 must support a protocol interface that supplies
742 an I/O abstraction to the driver.
743 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
744 parameter is ignored by device drivers, and is optional for bus
745 drivers. For bus drivers, if this parameter is not NULL, then
746 the bus driver must determine if the bus controller specified
747 by ControllerHandle and the child controller specified
748 by RemainingDevicePath are both supported by this
751 @retval EFI_SUCCESS The device specified by ControllerHandle and
752 RemainingDevicePath is supported by the driver specified by This.
753 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
754 RemainingDevicePath is already being managed by the driver
756 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
757 RemainingDevicePath is already being managed by a different
758 driver or an application that requires exclusive access.
759 Currently not implemented.
760 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
761 RemainingDevicePath is not supported by the driver specified by This.
765 NvmExpressDriverBindingSupported (
766 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
767 IN EFI_HANDLE Controller
,
768 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
772 EFI_DEV_PATH_PTR DevicePathNode
;
773 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
774 EFI_PCI_IO_PROTOCOL
*PciIo
;
778 // Check whether device path is valid
780 if (RemainingDevicePath
!= NULL
) {
782 // Check if RemainingDevicePath is the End of Device Path Node,
783 // if yes, go on checking other conditions
785 if (!IsDevicePathEnd (RemainingDevicePath
)) {
787 // If RemainingDevicePath isn't the End of Device Path Node,
788 // check its validation
790 DevicePathNode
.DevPath
= RemainingDevicePath
;
792 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
793 (DevicePathNode
.DevPath
->SubType
!= MSG_NVME_NAMESPACE_DP
) ||
794 (DevicePathNodeLength (DevicePathNode
.DevPath
) != sizeof (NVME_NAMESPACE_DEVICE_PATH
)))
796 return EFI_UNSUPPORTED
;
802 // Open the EFI Device Path protocol needed to perform the supported test
804 Status
= gBS
->OpenProtocol (
806 &gEfiDevicePathProtocolGuid
,
807 (VOID
**)&ParentDevicePath
,
808 This
->DriverBindingHandle
,
810 EFI_OPEN_PROTOCOL_BY_DRIVER
812 if (Status
== EFI_ALREADY_STARTED
) {
816 if (EFI_ERROR (Status
)) {
821 // Close protocol, don't use device path protocol in the Support() function
825 &gEfiDevicePathProtocolGuid
,
826 This
->DriverBindingHandle
,
831 // Attempt to Open PCI I/O Protocol
833 Status
= gBS
->OpenProtocol (
835 &gEfiPciIoProtocolGuid
,
837 This
->DriverBindingHandle
,
839 EFI_OPEN_PROTOCOL_BY_DRIVER
841 if (Status
== EFI_ALREADY_STARTED
) {
845 if (EFI_ERROR (Status
)) {
850 // Now further check the PCI header: Base class (offset 0x0B) and Sub Class (offset 0x0A).
851 // This controller should be a Nvm Express controller.
853 Status
= PciIo
->Pci
.Read (
856 PCI_CLASSCODE_OFFSET
,
860 if (EFI_ERROR (Status
)) {
865 // Examine Nvm Express controller PCI Configuration table fields
867 if ((ClassCode
[0] != PCI_IF_NVMHCI
) || (ClassCode
[1] != PCI_CLASS_MASS_STORAGE_NVM
) || (ClassCode
[2] != PCI_CLASS_MASS_STORAGE
)) {
868 Status
= EFI_UNSUPPORTED
;
874 &gEfiPciIoProtocolGuid
,
875 This
->DriverBindingHandle
,
883 Starts a device controller or a bus controller.
885 The Start() function is designed to be invoked from the EFI boot service ConnectController().
886 As a result, much of the error checking on the parameters to Start() has been moved into this
887 common boot service. It is legal to call Start() from other locations,
888 but the following calling restrictions must be followed or the system behavior will not be deterministic.
889 1. ControllerHandle must be a valid EFI_HANDLE.
890 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
891 EFI_DEVICE_PATH_PROTOCOL.
892 3. Prior to calling Start(), the Supported() function for the driver specified by This must
893 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
895 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
896 @param[in] ControllerHandle The handle of the controller to start. This handle
897 must support a protocol interface that supplies
898 an I/O abstraction to the driver.
899 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
900 parameter is ignored by device drivers, and is optional for bus
901 drivers. For a bus driver, if this parameter is NULL, then handles
902 for all the children of Controller are created by this driver.
903 If this parameter is not NULL and the first Device Path Node is
904 not the End of Device Path Node, then only the handle for the
905 child device specified by the first Device Path Node of
906 RemainingDevicePath is created by this driver.
907 If the first Device Path Node of RemainingDevicePath is
908 the End of Device Path Node, no child handle is created by this
911 @retval EFI_SUCCESS The device was started.
912 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
913 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
914 @retval Others The driver failded to start the device.
919 NvmExpressDriverBindingStart (
920 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
921 IN EFI_HANDLE Controller
,
922 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
926 EFI_PCI_IO_PROTOCOL
*PciIo
;
927 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
928 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
930 EFI_PHYSICAL_ADDRESS MappedAddr
;
932 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*Passthru
;
934 DEBUG ((DEBUG_INFO
, "NvmExpressDriverBindingStart: start\n"));
938 ParentDevicePath
= NULL
;
940 Status
= gBS
->OpenProtocol (
942 &gEfiDevicePathProtocolGuid
,
943 (VOID
**)&ParentDevicePath
,
944 This
->DriverBindingHandle
,
946 EFI_OPEN_PROTOCOL_BY_DRIVER
948 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
952 Status
= gBS
->OpenProtocol (
954 &gEfiPciIoProtocolGuid
,
956 This
->DriverBindingHandle
,
958 EFI_OPEN_PROTOCOL_BY_DRIVER
961 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
966 // Check EFI_ALREADY_STARTED to reuse the original NVME_CONTROLLER_PRIVATE_DATA.
968 if (Status
!= EFI_ALREADY_STARTED
) {
969 Private
= AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA
));
971 if (Private
== NULL
) {
972 DEBUG ((DEBUG_ERROR
, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n"));
973 Status
= EFI_OUT_OF_RESOURCES
;
978 // Save original PCI attributes
980 Status
= PciIo
->Attributes (
982 EfiPciIoAttributeOperationGet
,
984 &Private
->PciAttributes
987 if (EFI_ERROR (Status
)) {
992 // Enable 64-bit DMA support in the PCI layer.
994 Status
= PciIo
->Attributes (
996 EfiPciIoAttributeOperationEnable
,
997 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
,
1000 if (EFI_ERROR (Status
)) {
1001 DEBUG ((DEBUG_WARN
, "NvmExpressDriverBindingStart: failed to enable 64-bit DMA (%r)\n", Status
));
1005 // 6 x 4kB aligned buffers will be carved out of this buffer.
1006 // 1st 4kB boundary is the start of the admin submission queue.
1007 // 2nd 4kB boundary is the start of the admin completion queue.
1008 // 3rd 4kB boundary is the start of I/O submission queue #1.
1009 // 4th 4kB boundary is the start of I/O completion queue #1.
1010 // 5th 4kB boundary is the start of I/O submission queue #2.
1011 // 6th 4kB boundary is the start of I/O completion queue #2.
1013 // Allocate 6 pages of memory, then map it for bus master read and write.
1015 Status
= PciIo
->AllocateBuffer (
1018 EfiBootServicesData
,
1020 (VOID
**)&Private
->Buffer
,
1023 if (EFI_ERROR (Status
)) {
1027 Bytes
= EFI_PAGES_TO_SIZE (6);
1028 Status
= PciIo
->Map (
1030 EfiPciIoOperationBusMasterCommonBuffer
,
1037 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (6))) {
1041 Private
->BufferPciAddr
= (UINT8
*)(UINTN
)MappedAddr
;
1043 Private
->Signature
= NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE
;
1044 Private
->ControllerHandle
= Controller
;
1045 Private
->ImageHandle
= This
->DriverBindingHandle
;
1046 Private
->DriverBindingHandle
= This
->DriverBindingHandle
;
1047 Private
->PciIo
= PciIo
;
1048 Private
->ParentDevicePath
= ParentDevicePath
;
1049 Private
->Passthru
.Mode
= &Private
->PassThruMode
;
1050 Private
->Passthru
.PassThru
= NvmExpressPassThru
;
1051 Private
->Passthru
.GetNextNamespace
= NvmExpressGetNextNamespace
;
1052 Private
->Passthru
.BuildDevicePath
= NvmExpressBuildDevicePath
;
1053 Private
->Passthru
.GetNamespace
= NvmExpressGetNamespace
;
1054 CopyMem (&Private
->PassThruMode
, &gEfiNvmExpressPassThruMode
, sizeof (EFI_NVM_EXPRESS_PASS_THRU_MODE
));
1055 InitializeListHead (&Private
->AsyncPassThruQueue
);
1056 InitializeListHead (&Private
->UnsubmittedSubtasks
);
1058 Status
= NvmeControllerInit (Private
);
1059 if (EFI_ERROR (Status
)) {
1064 // Start the asynchronous I/O completion monitor
1066 Status
= gBS
->CreateEvent (
1067 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1069 ProcessAsyncTaskList
,
1071 &Private
->TimerEvent
1073 if (EFI_ERROR (Status
)) {
1077 Status
= gBS
->SetTimer (
1078 Private
->TimerEvent
,
1082 if (EFI_ERROR (Status
)) {
1086 Status
= gBS
->InstallMultipleProtocolInterfaces (
1088 &gEfiNvmExpressPassThruProtocolGuid
,
1092 if (EFI_ERROR (Status
)) {
1096 NvmeRegisterShutdownNotification ();
1098 Status
= gBS
->OpenProtocol (
1100 &gEfiNvmExpressPassThruProtocolGuid
,
1102 This
->DriverBindingHandle
,
1104 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1106 if (EFI_ERROR (Status
)) {
1110 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (Passthru
);
1113 if (RemainingDevicePath
== NULL
) {
1115 // Enumerate all NVME namespaces in the controller
1117 Status
= DiscoverAllNamespaces (
1120 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
1122 // Enumerate the specified NVME namespace
1124 Status
= Private
->Passthru
.GetNamespace (
1126 RemainingDevicePath
,
1130 if (!EFI_ERROR (Status
)) {
1131 Status
= EnumerateNvmeDevNamespace (
1138 DEBUG ((DEBUG_INFO
, "NvmExpressDriverBindingStart: end successfully\n"));
1142 if ((Private
!= NULL
) && (Private
->Mapping
!= NULL
)) {
1143 PciIo
->Unmap (PciIo
, Private
->Mapping
);
1146 if ((Private
!= NULL
) && (Private
->Buffer
!= NULL
)) {
1147 PciIo
->FreeBuffer (PciIo
, 6, Private
->Buffer
);
1150 if ((Private
!= NULL
) && (Private
->ControllerData
!= NULL
)) {
1151 FreePool (Private
->ControllerData
);
1154 if (Private
!= NULL
) {
1155 if (Private
->TimerEvent
!= NULL
) {
1156 gBS
->CloseEvent (Private
->TimerEvent
);
1162 gBS
->CloseProtocol (
1164 &gEfiPciIoProtocolGuid
,
1165 This
->DriverBindingHandle
,
1169 gBS
->CloseProtocol (
1171 &gEfiDevicePathProtocolGuid
,
1172 This
->DriverBindingHandle
,
1176 DEBUG ((DEBUG_INFO
, "NvmExpressDriverBindingStart: end with %r\n", Status
));
1182 Stops a device controller or a bus controller.
1184 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1185 As a result, much of the error checking on the parameters to Stop() has been moved
1186 into this common boot service. It is legal to call Stop() from other locations,
1187 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1188 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1189 same driver's Start() function.
1190 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1191 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1192 Start() function, and the Start() function must have called OpenProtocol() on
1193 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1195 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1196 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1197 support a bus specific I/O protocol for the driver
1198 to use to stop the device.
1199 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1200 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1201 if NumberOfChildren is 0.
1203 @retval EFI_SUCCESS The device was stopped.
1204 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1209 NvmExpressDriverBindingStop (
1210 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1211 IN EFI_HANDLE Controller
,
1212 IN UINTN NumberOfChildren
,
1213 IN EFI_HANDLE
*ChildHandleBuffer
1217 BOOLEAN AllChildrenStopped
;
1219 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
1220 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*PassThru
;
1224 if (NumberOfChildren
== 0) {
1225 Status
= gBS
->OpenProtocol (
1227 &gEfiNvmExpressPassThruProtocolGuid
,
1229 This
->DriverBindingHandle
,
1231 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1234 if (!EFI_ERROR (Status
)) {
1235 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (PassThru
);
1238 // Wait for the asynchronous PassThru queue to become empty.
1241 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1242 IsEmpty
= IsListEmpty (&Private
->AsyncPassThruQueue
) &&
1243 IsListEmpty (&Private
->UnsubmittedSubtasks
);
1244 gBS
->RestoreTPL (OldTpl
);
1253 gBS
->UninstallMultipleProtocolInterfaces (
1255 &gEfiNvmExpressPassThruProtocolGuid
,
1260 if (Private
->TimerEvent
!= NULL
) {
1261 gBS
->CloseEvent (Private
->TimerEvent
);
1264 if (Private
->Mapping
!= NULL
) {
1265 Private
->PciIo
->Unmap (Private
->PciIo
, Private
->Mapping
);
1268 if (Private
->Buffer
!= NULL
) {
1269 Private
->PciIo
->FreeBuffer (Private
->PciIo
, 6, Private
->Buffer
);
1272 FreePool (Private
->ControllerData
);
1276 gBS
->CloseProtocol (
1278 &gEfiPciIoProtocolGuid
,
1279 This
->DriverBindingHandle
,
1282 gBS
->CloseProtocol (
1284 &gEfiDevicePathProtocolGuid
,
1285 This
->DriverBindingHandle
,
1289 NvmeUnregisterShutdownNotification ();
1294 AllChildrenStopped
= TRUE
;
1296 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1297 Status
= UnregisterNvmeNamespace (This
, Controller
, ChildHandleBuffer
[Index
]);
1298 if (EFI_ERROR (Status
)) {
1299 AllChildrenStopped
= FALSE
;
1303 if (!AllChildrenStopped
) {
1304 return EFI_DEVICE_ERROR
;
1311 This is the unload handle for the NVM Express driver.
1313 Disconnect the driver specified by ImageHandle from the NVMe device in the handle database.
1314 Uninstall all the protocols installed in the driver.
1316 @param[in] ImageHandle The drivers' driver image.
1318 @retval EFI_SUCCESS The image is unloaded.
1319 @retval Others Failed to unload the image.
1325 IN EFI_HANDLE ImageHandle
1329 EFI_HANDLE
*DeviceHandleBuffer
;
1330 UINTN DeviceHandleCount
;
1332 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1333 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
1336 // Get the list of the device handles managed by this driver.
1337 // If there is an error getting the list, then means the driver
1338 // doesn't manage any device. At this way, we would only close
1339 // those protocols installed at image handle.
1341 DeviceHandleBuffer
= NULL
;
1342 Status
= gBS
->LocateHandleBuffer (
1344 &gEfiNvmExpressPassThruProtocolGuid
,
1350 if (!EFI_ERROR (Status
)) {
1352 // Disconnect the driver specified by ImageHandle from all
1353 // the devices in the handle database.
1355 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1356 Status
= gBS
->DisconnectController (
1357 DeviceHandleBuffer
[Index
],
1361 if (EFI_ERROR (Status
)) {
1368 // Uninstall all the protocols installed in the driver entry point
1370 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1372 &gEfiDriverBindingProtocolGuid
,
1373 &gNvmExpressDriverBinding
,
1374 &gEfiDriverSupportedEfiVersionProtocolGuid
,
1375 &gNvmExpressDriverSupportedEfiVersion
,
1379 if (EFI_ERROR (Status
)) {
1384 // Note we have to one by one uninstall the following protocols.
1385 // It's because some of them are optionally installed based on
1386 // the following PCD settings.
1387 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
1388 // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable
1389 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable
1390 // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable
1392 Status
= gBS
->HandleProtocol (
1394 &gEfiComponentNameProtocolGuid
,
1395 (VOID
**)&ComponentName
1397 if (!EFI_ERROR (Status
)) {
1398 gBS
->UninstallProtocolInterface (
1400 &gEfiComponentNameProtocolGuid
,
1405 Status
= gBS
->HandleProtocol (
1407 &gEfiComponentName2ProtocolGuid
,
1408 (VOID
**)&ComponentName2
1410 if (!EFI_ERROR (Status
)) {
1411 gBS
->UninstallProtocolInterface (
1413 &gEfiComponentName2ProtocolGuid
,
1418 Status
= EFI_SUCCESS
;
1422 // Free the buffer containing the list of handles from the handle database
1424 if (DeviceHandleBuffer
!= NULL
) {
1425 gBS
->FreePool (DeviceHandleBuffer
);
1432 The entry point for Nvm Express driver, used to install Nvm Express driver on the ImageHandle.
1434 @param ImageHandle The firmware allocated handle for this driver image.
1435 @param SystemTable Pointer to the EFI system table.
1437 @retval EFI_SUCCESS Driver loaded.
1438 @retval other Driver not loaded.
1443 NvmExpressDriverEntry (
1444 IN EFI_HANDLE ImageHandle
,
1445 IN EFI_SYSTEM_TABLE
*SystemTable
1450 Status
= EfiLibInstallDriverBindingComponentName2 (
1453 &gNvmExpressDriverBinding
,
1455 &gNvmExpressComponentName
,
1456 &gNvmExpressComponentName2
1458 ASSERT_EFI_ERROR (Status
);
1461 // Install EFI Driver Supported EFI Version Protocol required for
1462 // EFI drivers that are on PCI and other plug in cards.
1464 gNvmExpressDriverSupportedEfiVersion
.FirmwareVersion
= 0x00020028;
1465 Status
= gBS
->InstallMultipleProtocolInterfaces (
1467 &gEfiDriverSupportedEfiVersionProtocolGuid
,
1468 &gNvmExpressDriverSupportedEfiVersion
,
1471 ASSERT_EFI_ERROR (Status
);