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
)) {
103 // Validate Namespace
105 if (NamespaceData
->Ncap
== 0) {
106 Status
= EFI_DEVICE_ERROR
;
109 // allocate device private data for each discovered namespace
111 Device
= AllocateZeroPool(sizeof(NVME_DEVICE_PRIVATE_DATA
));
112 if (Device
== NULL
) {
113 Status
= EFI_OUT_OF_RESOURCES
;
118 // Initialize SSD namespace instance data
120 Device
->Signature
= NVME_DEVICE_PRIVATE_DATA_SIGNATURE
;
121 Device
->NamespaceId
= NamespaceId
;
122 Device
->NamespaceUuid
= NamespaceData
->Eui64
;
124 Device
->ControllerHandle
= Private
->ControllerHandle
;
125 Device
->DriverBindingHandle
= Private
->DriverBindingHandle
;
126 Device
->Controller
= Private
;
129 // Build BlockIo media structure
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 Device
->Media
.IoAlign
= Private
->PassThruMode
.IoAlign
;
139 Flbas
= NamespaceData
->Flbas
;
140 LbaFmtIdx
= Flbas
& 0xF;
141 Lbads
= NamespaceData
->LbaFormat
[LbaFmtIdx
].Lbads
;
142 Device
->Media
.BlockSize
= (UINT32
)1 << Lbads
;
144 Device
->Media
.LastBlock
= NamespaceData
->Nsze
- 1;
145 Device
->Media
.LogicalBlocksPerPhysicalBlock
= 1;
146 Device
->Media
.LowestAlignedLba
= 1;
149 // Create BlockIo Protocol instance
151 Device
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION2
;
152 Device
->BlockIo
.Media
= &Device
->Media
;
153 Device
->BlockIo
.Reset
= NvmeBlockIoReset
;
154 Device
->BlockIo
.ReadBlocks
= NvmeBlockIoReadBlocks
;
155 Device
->BlockIo
.WriteBlocks
= NvmeBlockIoWriteBlocks
;
156 Device
->BlockIo
.FlushBlocks
= NvmeBlockIoFlushBlocks
;
159 // Create BlockIo2 Protocol instance
161 Device
->BlockIo2
.Media
= &Device
->Media
;
162 Device
->BlockIo2
.Reset
= NvmeBlockIoResetEx
;
163 Device
->BlockIo2
.ReadBlocksEx
= NvmeBlockIoReadBlocksEx
;
164 Device
->BlockIo2
.WriteBlocksEx
= NvmeBlockIoWriteBlocksEx
;
165 Device
->BlockIo2
.FlushBlocksEx
= NvmeBlockIoFlushBlocksEx
;
166 InitializeListHead (&Device
->AsyncQueue
);
169 // Create StorageSecurityProtocol Instance
171 Device
->StorageSecurity
.ReceiveData
= NvmeStorageSecurityReceiveData
;
172 Device
->StorageSecurity
.SendData
= NvmeStorageSecuritySendData
;
175 // Create DiskInfo Protocol instance
177 CopyMem (&Device
->NamespaceData
, NamespaceData
, sizeof (NVME_ADMIN_NAMESPACE_DATA
));
178 InitializeDiskInfo (Device
);
181 // Create a Nvm Express Namespace Device Path Node
183 Status
= Private
->Passthru
.BuildDevicePath (
189 if (EFI_ERROR(Status
)) {
194 // Append the SSD node to the controller's device path
196 DevicePath
= AppendDevicePathNode (ParentDevicePath
, NewDevicePathNode
);
197 if (DevicePath
== NULL
) {
198 Status
= EFI_OUT_OF_RESOURCES
;
203 RemainingDevicePath
= DevicePath
;
204 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &DeviceHandle
);
205 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd(RemainingDevicePath
)) {
206 Status
= EFI_ALREADY_STARTED
;
207 FreePool (DevicePath
);
211 Device
->DevicePath
= DevicePath
;
214 // Make sure the handle is NULL so we create a new handle
216 Device
->DeviceHandle
= NULL
;
218 Status
= gBS
->InstallMultipleProtocolInterfaces (
219 &Device
->DeviceHandle
,
220 &gEfiDevicePathProtocolGuid
,
222 &gEfiBlockIoProtocolGuid
,
224 &gEfiBlockIo2ProtocolGuid
,
226 &gEfiDiskInfoProtocolGuid
,
231 if(EFI_ERROR(Status
)) {
236 // Check if the NVMe controller supports the Security Send and Security Receive commands
238 if ((Private
->ControllerData
->Oacs
& SECURITY_SEND_RECEIVE_SUPPORTED
) != 0) {
239 Status
= gBS
->InstallProtocolInterface (
240 &Device
->DeviceHandle
,
241 &gEfiStorageSecurityCommandProtocolGuid
,
242 EFI_NATIVE_INTERFACE
,
243 &Device
->StorageSecurity
245 if(EFI_ERROR(Status
)) {
246 gBS
->UninstallMultipleProtocolInterfaces (
247 &Device
->DeviceHandle
,
248 &gEfiDevicePathProtocolGuid
,
250 &gEfiBlockIoProtocolGuid
,
252 &gEfiBlockIo2ProtocolGuid
,
254 &gEfiDiskInfoProtocolGuid
,
263 Private
->ControllerHandle
,
264 &gEfiNvmExpressPassThruProtocolGuid
,
265 (VOID
**) &DummyInterface
,
266 Private
->DriverBindingHandle
,
267 Device
->DeviceHandle
,
268 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
272 // Dump NvmExpress Identify Namespace Data
274 DEBUG ((EFI_D_INFO
, " == NVME IDENTIFY NAMESPACE [%d] DATA ==\n", NamespaceId
));
275 DEBUG ((EFI_D_INFO
, " NSZE : 0x%x\n", NamespaceData
->Nsze
));
276 DEBUG ((EFI_D_INFO
, " NCAP : 0x%x\n", NamespaceData
->Ncap
));
277 DEBUG ((EFI_D_INFO
, " NUSE : 0x%x\n", NamespaceData
->Nuse
));
278 DEBUG ((EFI_D_INFO
, " LBAF0.LBADS : 0x%x\n", (NamespaceData
->LbaFormat
[0].Lbads
)));
281 // Build controller name for Component Name (2) protocol.
283 CopyMem (Sn
, Private
->ControllerData
->Sn
, sizeof (Private
->ControllerData
->Sn
));
285 CopyMem (Mn
, Private
->ControllerData
->Mn
, sizeof (Private
->ControllerData
->Mn
));
287 UnicodeSPrintAsciiFormat (Device
->ModelName
, sizeof (Device
->ModelName
), "%a-%a-%x", Sn
, Mn
, NamespaceData
->Eui64
);
291 gNvmExpressComponentName
.SupportedLanguages
,
292 &Device
->ControllerNameTable
,
299 gNvmExpressComponentName2
.SupportedLanguages
,
300 &Device
->ControllerNameTable
,
307 if(NamespaceData
!= NULL
) {
308 FreePool (NamespaceData
);
311 if (NewDevicePathNode
!= NULL
) {
312 FreePool (NewDevicePathNode
);
315 if(EFI_ERROR(Status
) && (Device
!= NULL
) && (Device
->DevicePath
!= NULL
)) {
316 FreePool (Device
->DevicePath
);
318 if(EFI_ERROR(Status
) && (Device
!= NULL
)) {
325 Discover all Nvm Express device namespaces, and create child handles for them with BlockIo
326 and DiskInfo protocol instances.
328 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
330 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
331 @return Others Some error occurs when enumerating the namespaces.
335 DiscoverAllNamespaces (
336 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
341 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*Passthru
;
343 NamespaceId
= 0xFFFFFFFF;
344 Passthru
= &Private
->Passthru
;
347 Status
= Passthru
->GetNextNamespace (
349 (UINT32
*)&NamespaceId
352 if (EFI_ERROR (Status
)) {
356 Status
= EnumerateNvmeDevNamespace (
361 if (EFI_ERROR(Status
)) {
370 Unregisters a Nvm Express device namespace.
372 This function removes the protocols installed on the controller handle and
373 frees the resources allocated for the namespace.
375 @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
376 @param Controller The controller handle of the namespace.
377 @param Handle The child handle.
379 @retval EFI_SUCCESS The namespace is successfully unregistered.
380 @return Others Some error occurs when unregistering the namespace.
384 UnregisterNvmeNamespace (
385 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
386 IN EFI_HANDLE Controller
,
391 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
392 NVME_DEVICE_PRIVATE_DATA
*Device
;
393 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*StorageSecurity
;
396 VOID
*DummyInterface
;
400 Status
= gBS
->OpenProtocol (
402 &gEfiBlockIoProtocolGuid
,
404 This
->DriverBindingHandle
,
406 EFI_OPEN_PROTOCOL_GET_PROTOCOL
408 if (EFI_ERROR (Status
)) {
412 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo
);
415 // Wait for the device's asynchronous I/O queue to become empty.
418 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
419 IsEmpty
= IsListEmpty (&Device
->AsyncQueue
);
420 gBS
->RestoreTPL (OldTpl
);
430 // Close the child handle
434 &gEfiNvmExpressPassThruProtocolGuid
,
435 This
->DriverBindingHandle
,
440 // The Nvm Express driver installs the BlockIo and DiskInfo in the DriverBindingStart().
441 // Here should uninstall both of them.
443 Status
= gBS
->UninstallMultipleProtocolInterfaces (
445 &gEfiDevicePathProtocolGuid
,
447 &gEfiBlockIoProtocolGuid
,
449 &gEfiBlockIo2ProtocolGuid
,
451 &gEfiDiskInfoProtocolGuid
,
456 if (EFI_ERROR (Status
)) {
459 &gEfiNvmExpressPassThruProtocolGuid
,
460 (VOID
**) &DummyInterface
,
461 This
->DriverBindingHandle
,
463 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
469 // If Storage Security Command Protocol is installed, then uninstall this protocol.
471 Status
= gBS
->OpenProtocol (
473 &gEfiStorageSecurityCommandProtocolGuid
,
474 (VOID
**) &StorageSecurity
,
475 This
->DriverBindingHandle
,
477 EFI_OPEN_PROTOCOL_GET_PROTOCOL
480 if (!EFI_ERROR (Status
)) {
481 Status
= gBS
->UninstallProtocolInterface (
483 &gEfiStorageSecurityCommandProtocolGuid
,
484 &Device
->StorageSecurity
486 if (EFI_ERROR (Status
)) {
489 &gEfiNvmExpressPassThruProtocolGuid
,
490 (VOID
**) &DummyInterface
,
491 This
->DriverBindingHandle
,
493 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
499 if(Device
->DevicePath
!= NULL
) {
500 FreePool (Device
->DevicePath
);
503 if (Device
->ControllerNameTable
!= NULL
) {
504 FreeUnicodeStringTable (Device
->ControllerNameTable
);
513 Call back function when the timer event is signaled.
515 @param[in] Event The Event this notify function registered to.
516 @param[in] Context Pointer to the context data registered to the
522 ProcessAsyncTaskList (
527 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
528 EFI_PCI_IO_PROTOCOL
*PciIo
;
533 LIST_ENTRY
*NextLink
;
534 NVME_PASS_THRU_ASYNC_REQ
*AsyncRequest
;
535 NVME_BLKIO2_SUBTASK
*Subtask
;
536 NVME_BLKIO2_REQUEST
*BlkIo2Request
;
537 EFI_BLOCK_IO2_TOKEN
*Token
;
541 Private
= (NVME_CONTROLLER_PRIVATE_DATA
*)Context
;
543 Cq
= Private
->CqBuffer
[QueueId
] + Private
->CqHdbl
[QueueId
].Cqh
;
545 PciIo
= Private
->PciIo
;
548 // Submit asynchronous subtasks to the NVMe Submission Queue
550 for (Link
= GetFirstNode (&Private
->UnsubmittedSubtasks
);
551 !IsNull (&Private
->UnsubmittedSubtasks
, Link
);
553 NextLink
= GetNextNode (&Private
->UnsubmittedSubtasks
, Link
);
554 Subtask
= NVME_BLKIO2_SUBTASK_FROM_LINK (Link
);
555 BlkIo2Request
= Subtask
->BlockIo2Request
;
556 Token
= BlkIo2Request
->Token
;
557 RemoveEntryList (Link
);
558 BlkIo2Request
->UnsubmittedSubtaskNum
--;
561 // If any previous subtask fails, do not process subsequent ones.
563 if (Token
->TransactionStatus
!= EFI_SUCCESS
) {
564 if (IsListEmpty (&BlkIo2Request
->SubtasksQueue
) &&
565 BlkIo2Request
->LastSubtaskSubmitted
&&
566 (BlkIo2Request
->UnsubmittedSubtaskNum
== 0)) {
568 // Remove the BlockIo2 request from the device asynchronous queue.
570 RemoveEntryList (&BlkIo2Request
->Link
);
571 FreePool (BlkIo2Request
);
572 gBS
->SignalEvent (Token
->Event
);
575 FreePool (Subtask
->CommandPacket
->NvmeCmd
);
576 FreePool (Subtask
->CommandPacket
->NvmeCompletion
);
577 FreePool (Subtask
->CommandPacket
);
583 Status
= Private
->Passthru
.PassThru (
585 Subtask
->NamespaceId
,
586 Subtask
->CommandPacket
,
589 if (Status
== EFI_NOT_READY
) {
590 InsertHeadList (&Private
->UnsubmittedSubtasks
, Link
);
591 BlkIo2Request
->UnsubmittedSubtaskNum
++;
593 } else if (EFI_ERROR (Status
)) {
594 Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
596 if (IsListEmpty (&BlkIo2Request
->SubtasksQueue
) &&
599 // Remove the BlockIo2 request from the device asynchronous queue.
601 RemoveEntryList (&BlkIo2Request
->Link
);
602 FreePool (BlkIo2Request
);
603 gBS
->SignalEvent (Token
->Event
);
606 FreePool (Subtask
->CommandPacket
->NvmeCmd
);
607 FreePool (Subtask
->CommandPacket
->NvmeCompletion
);
608 FreePool (Subtask
->CommandPacket
);
611 InsertTailList (&BlkIo2Request
->SubtasksQueue
, Link
);
612 if (Subtask
->IsLast
) {
613 BlkIo2Request
->LastSubtaskSubmitted
= TRUE
;
618 while (Cq
->Pt
!= Private
->Pt
[QueueId
]) {
619 ASSERT (Cq
->Sqid
== QueueId
);
624 // Find the command with given Command Id.
626 for (Link
= GetFirstNode (&Private
->AsyncPassThruQueue
);
627 !IsNull (&Private
->AsyncPassThruQueue
, Link
);
629 NextLink
= GetNextNode (&Private
->AsyncPassThruQueue
, Link
);
630 AsyncRequest
= NVME_PASS_THRU_ASYNC_REQ_FROM_THIS (Link
);
631 if (AsyncRequest
->CommandId
== Cq
->Cid
) {
633 // Copy the Respose Queue entry for this command to the callers
637 AsyncRequest
->Packet
->NvmeCompletion
,
639 sizeof(EFI_NVM_EXPRESS_COMPLETION
)
643 // Free the resources allocated before cmd submission
645 if (AsyncRequest
->MapData
!= NULL
) {
646 PciIo
->Unmap (PciIo
, AsyncRequest
->MapData
);
648 if (AsyncRequest
->MapMeta
!= NULL
) {
649 PciIo
->Unmap (PciIo
, AsyncRequest
->MapMeta
);
651 if (AsyncRequest
->MapPrpList
!= NULL
) {
652 PciIo
->Unmap (PciIo
, AsyncRequest
->MapPrpList
);
654 if (AsyncRequest
->PrpListHost
!= NULL
) {
657 AsyncRequest
->PrpListNo
,
658 AsyncRequest
->PrpListHost
662 RemoveEntryList (Link
);
663 gBS
->SignalEvent (AsyncRequest
->CallerEvent
);
664 FreePool (AsyncRequest
);
667 // Update submission queue head.
669 Private
->AsyncSqHead
= Cq
->Sqhd
;
674 Private
->CqHdbl
[QueueId
].Cqh
++;
675 if (Private
->CqHdbl
[QueueId
].Cqh
> NVME_ASYNC_CCQ_SIZE
) {
676 Private
->CqHdbl
[QueueId
].Cqh
= 0;
677 Private
->Pt
[QueueId
] ^= 1;
680 Cq
= Private
->CqBuffer
[QueueId
] + Private
->CqHdbl
[QueueId
].Cqh
;
684 Data
= ReadUnaligned32 ((UINT32
*)&Private
->CqHdbl
[QueueId
]);
689 NVME_CQHDBL_OFFSET(QueueId
, Private
->Cap
.Dstrd
),
697 Tests to see if this driver supports a given controller. If a child device is provided,
698 it further tests to see if this driver supports creating a handle for the specified child device.
700 This function checks to see if the driver specified by This supports the device specified by
701 ControllerHandle. Drivers will typically use the device path attached to
702 ControllerHandle and/or the services from the bus I/O abstraction attached to
703 ControllerHandle to determine if the driver supports ControllerHandle. This function
704 may be called many times during platform initialization. In order to reduce boot times, the tests
705 performed by this function must be very small, and take as little time as possible to execute. This
706 function must not change the state of any hardware devices, and this function must be aware that the
707 device specified by ControllerHandle may already be managed by the same driver or a
708 different driver. This function must match its calls to AllocatePages() with FreePages(),
709 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
710 Since ControllerHandle may have been previously started by the same driver, if a protocol is
711 already in the opened state, then it must not be closed with CloseProtocol(). This is required
712 to guarantee the state of ControllerHandle is not modified by this function.
714 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
715 @param[in] ControllerHandle The handle of the controller to test. This handle
716 must support a protocol interface that supplies
717 an I/O abstraction to the driver.
718 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
719 parameter is ignored by device drivers, and is optional for bus
720 drivers. For bus drivers, if this parameter is not NULL, then
721 the bus driver must determine if the bus controller specified
722 by ControllerHandle and the child controller specified
723 by RemainingDevicePath are both supported by this
726 @retval EFI_SUCCESS The device specified by ControllerHandle and
727 RemainingDevicePath is supported by the driver specified by This.
728 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
729 RemainingDevicePath is already being managed by the driver
731 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
732 RemainingDevicePath is already being managed by a different
733 driver or an application that requires exclusive access.
734 Currently not implemented.
735 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
736 RemainingDevicePath is not supported by the driver specified by This.
740 NvmExpressDriverBindingSupported (
741 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
742 IN EFI_HANDLE Controller
,
743 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
747 EFI_DEV_PATH_PTR DevicePathNode
;
748 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
749 EFI_PCI_IO_PROTOCOL
*PciIo
;
753 // Check whether device path is valid
755 if (RemainingDevicePath
!= NULL
) {
757 // Check if RemainingDevicePath is the End of Device Path Node,
758 // if yes, go on checking other conditions
760 if (!IsDevicePathEnd (RemainingDevicePath
)) {
762 // If RemainingDevicePath isn't the End of Device Path Node,
763 // check its validation
765 DevicePathNode
.DevPath
= RemainingDevicePath
;
767 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
768 (DevicePathNode
.DevPath
->SubType
!= MSG_NVME_NAMESPACE_DP
) ||
769 (DevicePathNodeLength(DevicePathNode
.DevPath
) != sizeof(NVME_NAMESPACE_DEVICE_PATH
))) {
770 return EFI_UNSUPPORTED
;
776 // Open the EFI Device Path protocol needed to perform the supported test
778 Status
= gBS
->OpenProtocol (
780 &gEfiDevicePathProtocolGuid
,
781 (VOID
**) &ParentDevicePath
,
782 This
->DriverBindingHandle
,
784 EFI_OPEN_PROTOCOL_BY_DRIVER
786 if (Status
== EFI_ALREADY_STARTED
) {
790 if (EFI_ERROR (Status
)) {
795 // Close protocol, don't use device path protocol in the Support() function
799 &gEfiDevicePathProtocolGuid
,
800 This
->DriverBindingHandle
,
805 // Attempt to Open PCI I/O Protocol
807 Status
= gBS
->OpenProtocol (
809 &gEfiPciIoProtocolGuid
,
811 This
->DriverBindingHandle
,
813 EFI_OPEN_PROTOCOL_BY_DRIVER
815 if (Status
== EFI_ALREADY_STARTED
) {
819 if (EFI_ERROR (Status
)) {
824 // Now further check the PCI header: Base class (offset 0x0B) and Sub Class (offset 0x0A).
825 // This controller should be a Nvm Express controller.
827 Status
= PciIo
->Pci
.Read (
830 PCI_CLASSCODE_OFFSET
,
834 if (EFI_ERROR (Status
)) {
839 // Examine Nvm Express controller PCI Configuration table fields
841 if ((ClassCode
[0] != PCI_IF_NVMHCI
) || (ClassCode
[1] != PCI_CLASS_MASS_STORAGE_NVM
) || (ClassCode
[2] != PCI_CLASS_MASS_STORAGE
)) {
842 Status
= EFI_UNSUPPORTED
;
848 &gEfiPciIoProtocolGuid
,
849 This
->DriverBindingHandle
,
858 Starts a device controller or a bus controller.
860 The Start() function is designed to be invoked from the EFI boot service ConnectController().
861 As a result, much of the error checking on the parameters to Start() has been moved into this
862 common boot service. It is legal to call Start() from other locations,
863 but the following calling restrictions must be followed or the system behavior will not be deterministic.
864 1. ControllerHandle must be a valid EFI_HANDLE.
865 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
866 EFI_DEVICE_PATH_PROTOCOL.
867 3. Prior to calling Start(), the Supported() function for the driver specified by This must
868 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
870 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
871 @param[in] ControllerHandle The handle of the controller to start. This handle
872 must support a protocol interface that supplies
873 an I/O abstraction to the driver.
874 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
875 parameter is ignored by device drivers, and is optional for bus
876 drivers. For a bus driver, if this parameter is NULL, then handles
877 for all the children of Controller are created by this driver.
878 If this parameter is not NULL and the first Device Path Node is
879 not the End of Device Path Node, then only the handle for the
880 child device specified by the first Device Path Node of
881 RemainingDevicePath is created by this driver.
882 If the first Device Path Node of RemainingDevicePath is
883 the End of Device Path Node, no child handle is created by this
886 @retval EFI_SUCCESS The device was started.
887 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
888 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
889 @retval Others The driver failded to start the device.
894 NvmExpressDriverBindingStart (
895 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
896 IN EFI_HANDLE Controller
,
897 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
901 EFI_PCI_IO_PROTOCOL
*PciIo
;
902 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
903 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
905 EFI_PHYSICAL_ADDRESS MappedAddr
;
907 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*Passthru
;
909 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: start\n"));
913 ParentDevicePath
= NULL
;
915 Status
= gBS
->OpenProtocol (
917 &gEfiDevicePathProtocolGuid
,
918 (VOID
**) &ParentDevicePath
,
919 This
->DriverBindingHandle
,
921 EFI_OPEN_PROTOCOL_BY_DRIVER
923 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
927 Status
= gBS
->OpenProtocol (
929 &gEfiPciIoProtocolGuid
,
931 This
->DriverBindingHandle
,
933 EFI_OPEN_PROTOCOL_BY_DRIVER
936 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
941 // Check EFI_ALREADY_STARTED to reuse the original NVME_CONTROLLER_PRIVATE_DATA.
943 if (Status
!= EFI_ALREADY_STARTED
) {
944 Private
= AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA
));
946 if (Private
== NULL
) {
947 DEBUG ((EFI_D_ERROR
, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n"));
948 Status
= EFI_OUT_OF_RESOURCES
;
953 // 6 x 4kB aligned buffers will be carved out of this buffer.
954 // 1st 4kB boundary is the start of the admin submission queue.
955 // 2nd 4kB boundary is the start of the admin completion queue.
956 // 3rd 4kB boundary is the start of I/O submission queue #1.
957 // 4th 4kB boundary is the start of I/O completion queue #1.
958 // 5th 4kB boundary is the start of I/O submission queue #2.
959 // 6th 4kB boundary is the start of I/O completion queue #2.
961 // Allocate 6 pages of memory, then map it for bus master read and write.
963 Status
= PciIo
->AllocateBuffer (
968 (VOID
**)&Private
->Buffer
,
971 if (EFI_ERROR (Status
)) {
975 Bytes
= EFI_PAGES_TO_SIZE (6);
976 Status
= PciIo
->Map (
978 EfiPciIoOperationBusMasterCommonBuffer
,
985 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (6))) {
989 Private
->BufferPciAddr
= (UINT8
*)(UINTN
)MappedAddr
;
991 Private
->Signature
= NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE
;
992 Private
->ControllerHandle
= Controller
;
993 Private
->ImageHandle
= This
->DriverBindingHandle
;
994 Private
->DriverBindingHandle
= This
->DriverBindingHandle
;
995 Private
->PciIo
= PciIo
;
996 Private
->ParentDevicePath
= ParentDevicePath
;
997 Private
->Passthru
.Mode
= &Private
->PassThruMode
;
998 Private
->Passthru
.PassThru
= NvmExpressPassThru
;
999 Private
->Passthru
.GetNextNamespace
= NvmExpressGetNextNamespace
;
1000 Private
->Passthru
.BuildDevicePath
= NvmExpressBuildDevicePath
;
1001 Private
->Passthru
.GetNamespace
= NvmExpressGetNamespace
;
1002 CopyMem (&Private
->PassThruMode
, &gEfiNvmExpressPassThruMode
, sizeof (EFI_NVM_EXPRESS_PASS_THRU_MODE
));
1003 InitializeListHead (&Private
->AsyncPassThruQueue
);
1004 InitializeListHead (&Private
->UnsubmittedSubtasks
);
1006 Status
= NvmeControllerInit (Private
);
1007 if (EFI_ERROR(Status
)) {
1012 // Start the asynchronous I/O completion monitor
1014 Status
= gBS
->CreateEvent (
1015 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1017 ProcessAsyncTaskList
,
1019 &Private
->TimerEvent
1021 if (EFI_ERROR (Status
)) {
1025 Status
= gBS
->SetTimer (
1026 Private
->TimerEvent
,
1030 if (EFI_ERROR (Status
)) {
1034 Status
= gBS
->InstallMultipleProtocolInterfaces (
1036 &gEfiNvmExpressPassThruProtocolGuid
,
1040 if (EFI_ERROR (Status
)) {
1044 NvmeRegisterShutdownNotification ();
1046 Status
= gBS
->OpenProtocol (
1048 &gEfiNvmExpressPassThruProtocolGuid
,
1049 (VOID
**) &Passthru
,
1050 This
->DriverBindingHandle
,
1052 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1054 if (EFI_ERROR (Status
)) {
1058 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (Passthru
);
1061 if (RemainingDevicePath
== NULL
) {
1063 // Enumerate all NVME namespaces in the controller
1065 Status
= DiscoverAllNamespaces (
1069 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
1071 // Enumerate the specified NVME namespace
1073 Status
= Private
->Passthru
.GetNamespace (
1075 RemainingDevicePath
,
1079 if (!EFI_ERROR (Status
)) {
1080 Status
= EnumerateNvmeDevNamespace (
1087 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: end successfully\n"));
1091 if ((Private
!= NULL
) && (Private
->Mapping
!= NULL
)) {
1092 PciIo
->Unmap (PciIo
, Private
->Mapping
);
1095 if ((Private
!= NULL
) && (Private
->Buffer
!= NULL
)) {
1096 PciIo
->FreeBuffer (PciIo
, 6, Private
->Buffer
);
1099 if ((Private
!= NULL
) && (Private
->ControllerData
!= NULL
)) {
1100 FreePool (Private
->ControllerData
);
1103 if (Private
!= NULL
) {
1104 if (Private
->TimerEvent
!= NULL
) {
1105 gBS
->CloseEvent (Private
->TimerEvent
);
1111 gBS
->CloseProtocol (
1113 &gEfiPciIoProtocolGuid
,
1114 This
->DriverBindingHandle
,
1118 gBS
->CloseProtocol (
1120 &gEfiDevicePathProtocolGuid
,
1121 This
->DriverBindingHandle
,
1125 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: end with %r\n", Status
));
1132 Stops a device controller or a bus controller.
1134 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1135 As a result, much of the error checking on the parameters to Stop() has been moved
1136 into this common boot service. It is legal to call Stop() from other locations,
1137 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1138 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1139 same driver's Start() function.
1140 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1141 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1142 Start() function, and the Start() function must have called OpenProtocol() on
1143 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1145 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1146 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1147 support a bus specific I/O protocol for the driver
1148 to use to stop the device.
1149 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1150 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1151 if NumberOfChildren is 0.
1153 @retval EFI_SUCCESS The device was stopped.
1154 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1159 NvmExpressDriverBindingStop (
1160 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1161 IN EFI_HANDLE Controller
,
1162 IN UINTN NumberOfChildren
,
1163 IN EFI_HANDLE
*ChildHandleBuffer
1167 BOOLEAN AllChildrenStopped
;
1169 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
1170 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*PassThru
;
1174 if (NumberOfChildren
== 0) {
1175 Status
= gBS
->OpenProtocol (
1177 &gEfiNvmExpressPassThruProtocolGuid
,
1178 (VOID
**) &PassThru
,
1179 This
->DriverBindingHandle
,
1181 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1184 if (!EFI_ERROR (Status
)) {
1185 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (PassThru
);
1188 // Wait for the asynchronous PassThru queue to become empty.
1191 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1192 IsEmpty
= IsListEmpty (&Private
->AsyncPassThruQueue
) &&
1193 IsListEmpty (&Private
->UnsubmittedSubtasks
);
1194 gBS
->RestoreTPL (OldTpl
);
1203 gBS
->UninstallMultipleProtocolInterfaces (
1205 &gEfiNvmExpressPassThruProtocolGuid
,
1210 if (Private
->TimerEvent
!= NULL
) {
1211 gBS
->CloseEvent (Private
->TimerEvent
);
1214 if (Private
->Mapping
!= NULL
) {
1215 Private
->PciIo
->Unmap (Private
->PciIo
, Private
->Mapping
);
1218 if (Private
->Buffer
!= NULL
) {
1219 Private
->PciIo
->FreeBuffer (Private
->PciIo
, 6, Private
->Buffer
);
1222 FreePool (Private
->ControllerData
);
1226 gBS
->CloseProtocol (
1228 &gEfiPciIoProtocolGuid
,
1229 This
->DriverBindingHandle
,
1232 gBS
->CloseProtocol (
1234 &gEfiDevicePathProtocolGuid
,
1235 This
->DriverBindingHandle
,
1239 NvmeUnregisterShutdownNotification ();
1244 AllChildrenStopped
= TRUE
;
1246 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1247 Status
= UnregisterNvmeNamespace (This
, Controller
, ChildHandleBuffer
[Index
]);
1248 if (EFI_ERROR (Status
)) {
1249 AllChildrenStopped
= FALSE
;
1253 if (!AllChildrenStopped
) {
1254 return EFI_DEVICE_ERROR
;
1261 This is the unload handle for the NVM Express driver.
1263 Disconnect the driver specified by ImageHandle from the NVMe device in the handle database.
1264 Uninstall all the protocols installed in the driver.
1266 @param[in] ImageHandle The drivers' driver image.
1268 @retval EFI_SUCCESS The image is unloaded.
1269 @retval Others Failed to unload the image.
1275 IN EFI_HANDLE ImageHandle
1279 EFI_HANDLE
*DeviceHandleBuffer
;
1280 UINTN DeviceHandleCount
;
1282 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1283 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
1286 // Get the list of the device handles managed by this driver.
1287 // If there is an error getting the list, then means the driver
1288 // doesn't manage any device. At this way, we would only close
1289 // those protocols installed at image handle.
1291 DeviceHandleBuffer
= NULL
;
1292 Status
= gBS
->LocateHandleBuffer (
1294 &gEfiNvmExpressPassThruProtocolGuid
,
1300 if (!EFI_ERROR (Status
)) {
1302 // Disconnect the driver specified by ImageHandle from all
1303 // the devices in the handle database.
1305 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1306 Status
= gBS
->DisconnectController (
1307 DeviceHandleBuffer
[Index
],
1311 if (EFI_ERROR (Status
)) {
1318 // Uninstall all the protocols installed in the driver entry point
1320 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1322 &gEfiDriverBindingProtocolGuid
,
1323 &gNvmExpressDriverBinding
,
1324 &gEfiDriverSupportedEfiVersionProtocolGuid
,
1325 &gNvmExpressDriverSupportedEfiVersion
,
1329 if (EFI_ERROR (Status
)) {
1334 // Note we have to one by one uninstall the following protocols.
1335 // It's because some of them are optionally installed based on
1336 // the following PCD settings.
1337 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
1338 // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable
1339 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable
1340 // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable
1342 Status
= gBS
->HandleProtocol (
1344 &gEfiComponentNameProtocolGuid
,
1345 (VOID
**) &ComponentName
1347 if (!EFI_ERROR (Status
)) {
1348 gBS
->UninstallProtocolInterface (
1350 &gEfiComponentNameProtocolGuid
,
1355 Status
= gBS
->HandleProtocol (
1357 &gEfiComponentName2ProtocolGuid
,
1358 (VOID
**) &ComponentName2
1360 if (!EFI_ERROR (Status
)) {
1361 gBS
->UninstallProtocolInterface (
1363 &gEfiComponentName2ProtocolGuid
,
1368 Status
= EFI_SUCCESS
;
1372 // Free the buffer containing the list of handles from the handle database
1374 if (DeviceHandleBuffer
!= NULL
) {
1375 gBS
->FreePool (DeviceHandleBuffer
);
1381 The entry point for Nvm Express driver, used to install Nvm Express driver on the ImageHandle.
1383 @param ImageHandle The firmware allocated handle for this driver image.
1384 @param SystemTable Pointer to the EFI system table.
1386 @retval EFI_SUCCESS Driver loaded.
1387 @retval other Driver not loaded.
1392 NvmExpressDriverEntry (
1393 IN EFI_HANDLE ImageHandle
,
1394 IN EFI_SYSTEM_TABLE
*SystemTable
1399 Status
= EfiLibInstallDriverBindingComponentName2 (
1402 &gNvmExpressDriverBinding
,
1404 &gNvmExpressComponentName
,
1405 &gNvmExpressComponentName2
1407 ASSERT_EFI_ERROR (Status
);
1410 // Install EFI Driver Supported EFI Version Protocol required for
1411 // EFI drivers that are on PCI and other plug in cards.
1413 gNvmExpressDriverSupportedEfiVersion
.FirmwareVersion
= 0x00020028;
1414 Status
= gBS
->InstallMultipleProtocolInterfaces (
1416 &gEfiDriverSupportedEfiVersionProtocolGuid
,
1417 &gNvmExpressDriverSupportedEfiVersion
,
1420 ASSERT_EFI_ERROR (Status
);