2 NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3 NVM Express specification.
5 Copyright (c) 2013 - 2016, 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 // Template for NVM Express Pass Thru Mode data structure.
41 GLOBAL_REMOVE_IF_UNREFERENCED EFI_NVM_EXPRESS_PASS_THRU_MODE gEfiNvmExpressPassThruMode
= {
42 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL
|
43 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL
|
44 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_NONBLOCKIO
|
45 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM
,
51 Check if the specified Nvm Express device namespace is active, and create child handles
52 for them with BlockIo and DiskInfo protocol instances.
54 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
55 @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
56 allocated and built. Caller must set the NamespaceId to zero if the
57 device path node will contain a valid UUID.
59 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
60 @return Others Some error occurs when enumerating the namespaces.
64 EnumerateNvmeDevNamespace (
65 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
69 NVME_ADMIN_NAMESPACE_DATA
*NamespaceData
;
70 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePathNode
;
71 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
72 EFI_HANDLE DeviceHandle
;
73 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
74 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
75 NVME_DEVICE_PRIVATE_DATA
*Device
;
84 NewDevicePathNode
= NULL
;
89 // Allocate a buffer for Identify Namespace data
91 NamespaceData
= AllocateZeroPool(sizeof (NVME_ADMIN_NAMESPACE_DATA
));
92 if(NamespaceData
== NULL
) {
93 return EFI_OUT_OF_RESOURCES
;
96 ParentDevicePath
= Private
->ParentDevicePath
;
100 Status
= NvmeIdentifyNamespace (
103 (VOID
*)NamespaceData
105 if (EFI_ERROR(Status
)) {
109 // Validate Namespace
111 if (NamespaceData
->Ncap
== 0) {
112 Status
= EFI_DEVICE_ERROR
;
115 // allocate device private data for each discovered namespace
117 Device
= AllocateZeroPool(sizeof(NVME_DEVICE_PRIVATE_DATA
));
118 if (Device
== NULL
) {
119 Status
= EFI_OUT_OF_RESOURCES
;
124 // Initialize SSD namespace instance data
126 Device
->Signature
= NVME_DEVICE_PRIVATE_DATA_SIGNATURE
;
127 Device
->NamespaceId
= NamespaceId
;
128 Device
->NamespaceUuid
= NamespaceData
->Eui64
;
130 Device
->ControllerHandle
= Private
->ControllerHandle
;
131 Device
->DriverBindingHandle
= Private
->DriverBindingHandle
;
132 Device
->Controller
= Private
;
135 // Build BlockIo media structure
137 Device
->Media
.MediaId
= 0;
138 Device
->Media
.RemovableMedia
= FALSE
;
139 Device
->Media
.MediaPresent
= TRUE
;
140 Device
->Media
.LogicalPartition
= FALSE
;
141 Device
->Media
.ReadOnly
= FALSE
;
142 Device
->Media
.WriteCaching
= FALSE
;
143 Device
->Media
.IoAlign
= Private
->PassThruMode
.IoAlign
;
145 Flbas
= NamespaceData
->Flbas
;
146 LbaFmtIdx
= Flbas
& 0xF;
147 Lbads
= NamespaceData
->LbaFormat
[LbaFmtIdx
].Lbads
;
148 Device
->Media
.BlockSize
= (UINT32
)1 << Lbads
;
150 Device
->Media
.LastBlock
= NamespaceData
->Nsze
- 1;
151 Device
->Media
.LogicalBlocksPerPhysicalBlock
= 1;
152 Device
->Media
.LowestAlignedLba
= 1;
155 // Create BlockIo Protocol instance
157 Device
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION2
;
158 Device
->BlockIo
.Media
= &Device
->Media
;
159 Device
->BlockIo
.Reset
= NvmeBlockIoReset
;
160 Device
->BlockIo
.ReadBlocks
= NvmeBlockIoReadBlocks
;
161 Device
->BlockIo
.WriteBlocks
= NvmeBlockIoWriteBlocks
;
162 Device
->BlockIo
.FlushBlocks
= NvmeBlockIoFlushBlocks
;
165 // Create BlockIo2 Protocol instance
167 Device
->BlockIo2
.Media
= &Device
->Media
;
168 Device
->BlockIo2
.Reset
= NvmeBlockIoResetEx
;
169 Device
->BlockIo2
.ReadBlocksEx
= NvmeBlockIoReadBlocksEx
;
170 Device
->BlockIo2
.WriteBlocksEx
= NvmeBlockIoWriteBlocksEx
;
171 Device
->BlockIo2
.FlushBlocksEx
= NvmeBlockIoFlushBlocksEx
;
172 InitializeListHead (&Device
->AsyncQueue
);
175 // Create StorageSecurityProtocol Instance
177 Device
->StorageSecurity
.ReceiveData
= NvmeStorageSecurityReceiveData
;
178 Device
->StorageSecurity
.SendData
= NvmeStorageSecuritySendData
;
181 // Create DiskInfo Protocol instance
183 CopyMem (&Device
->NamespaceData
, NamespaceData
, sizeof (NVME_ADMIN_NAMESPACE_DATA
));
184 InitializeDiskInfo (Device
);
187 // Create a Nvm Express Namespace Device Path Node
189 Status
= Private
->Passthru
.BuildDevicePath (
195 if (EFI_ERROR(Status
)) {
200 // Append the SSD node to the controller's device path
202 DevicePath
= AppendDevicePathNode (ParentDevicePath
, NewDevicePathNode
);
203 if (DevicePath
== NULL
) {
204 Status
= EFI_OUT_OF_RESOURCES
;
209 RemainingDevicePath
= DevicePath
;
210 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &DeviceHandle
);
211 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd(RemainingDevicePath
)) {
212 Status
= EFI_ALREADY_STARTED
;
213 FreePool (DevicePath
);
217 Device
->DevicePath
= DevicePath
;
220 // Make sure the handle is NULL so we create a new handle
222 Device
->DeviceHandle
= NULL
;
224 Status
= gBS
->InstallMultipleProtocolInterfaces (
225 &Device
->DeviceHandle
,
226 &gEfiDevicePathProtocolGuid
,
228 &gEfiBlockIoProtocolGuid
,
230 &gEfiBlockIo2ProtocolGuid
,
232 &gEfiDiskInfoProtocolGuid
,
237 if(EFI_ERROR(Status
)) {
242 // Check if the NVMe controller supports the Security Send and Security Receive commands
244 if ((Private
->ControllerData
->Oacs
& SECURITY_SEND_RECEIVE_SUPPORTED
) != 0) {
245 Status
= gBS
->InstallProtocolInterface (
246 &Device
->DeviceHandle
,
247 &gEfiStorageSecurityCommandProtocolGuid
,
248 EFI_NATIVE_INTERFACE
,
249 &Device
->StorageSecurity
251 if(EFI_ERROR(Status
)) {
252 gBS
->UninstallMultipleProtocolInterfaces (
253 &Device
->DeviceHandle
,
254 &gEfiDevicePathProtocolGuid
,
256 &gEfiBlockIoProtocolGuid
,
258 &gEfiBlockIo2ProtocolGuid
,
260 &gEfiDiskInfoProtocolGuid
,
269 Private
->ControllerHandle
,
270 &gEfiNvmExpressPassThruProtocolGuid
,
271 (VOID
**) &DummyInterface
,
272 Private
->DriverBindingHandle
,
273 Device
->DeviceHandle
,
274 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
278 // Dump NvmExpress Identify Namespace Data
280 DEBUG ((EFI_D_INFO
, " == NVME IDENTIFY NAMESPACE [%d] DATA ==\n", NamespaceId
));
281 DEBUG ((EFI_D_INFO
, " NSZE : 0x%x\n", NamespaceData
->Nsze
));
282 DEBUG ((EFI_D_INFO
, " NCAP : 0x%x\n", NamespaceData
->Ncap
));
283 DEBUG ((EFI_D_INFO
, " NUSE : 0x%x\n", NamespaceData
->Nuse
));
284 DEBUG ((EFI_D_INFO
, " LBAF0.LBADS : 0x%x\n", (NamespaceData
->LbaFormat
[0].Lbads
)));
287 // Build controller name for Component Name (2) protocol.
289 CopyMem (Sn
, Private
->ControllerData
->Sn
, sizeof (Private
->ControllerData
->Sn
));
291 CopyMem (Mn
, Private
->ControllerData
->Mn
, sizeof (Private
->ControllerData
->Mn
));
293 UnicodeSPrintAsciiFormat (Device
->ModelName
, sizeof (Device
->ModelName
), "%a-%a-%x", Sn
, Mn
, NamespaceData
->Eui64
);
297 gNvmExpressComponentName
.SupportedLanguages
,
298 &Device
->ControllerNameTable
,
305 gNvmExpressComponentName2
.SupportedLanguages
,
306 &Device
->ControllerNameTable
,
313 if(NamespaceData
!= NULL
) {
314 FreePool (NamespaceData
);
317 if (NewDevicePathNode
!= NULL
) {
318 FreePool (NewDevicePathNode
);
321 if(EFI_ERROR(Status
) && (Device
!= NULL
) && (Device
->DevicePath
!= NULL
)) {
322 FreePool (Device
->DevicePath
);
324 if(EFI_ERROR(Status
) && (Device
!= NULL
)) {
331 Discover all Nvm Express device namespaces, and create child handles for them with BlockIo
332 and DiskInfo protocol instances.
334 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
336 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
337 @return Others Some error occurs when enumerating the namespaces.
341 DiscoverAllNamespaces (
342 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
347 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*Passthru
;
349 NamespaceId
= 0xFFFFFFFF;
350 Passthru
= &Private
->Passthru
;
353 Status
= Passthru
->GetNextNamespace (
355 (UINT32
*)&NamespaceId
358 if (EFI_ERROR (Status
)) {
362 Status
= EnumerateNvmeDevNamespace (
367 if (EFI_ERROR(Status
)) {
376 Unregisters a Nvm Express device namespace.
378 This function removes the protocols installed on the controller handle and
379 frees the resources allocated for the namespace.
381 @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
382 @param Controller The controller handle of the namespace.
383 @param Handle The child handle.
385 @retval EFI_SUCCESS The namespace is successfully unregistered.
386 @return Others Some error occurs when unregistering the namespace.
390 UnregisterNvmeNamespace (
391 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
392 IN EFI_HANDLE Controller
,
397 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
398 NVME_DEVICE_PRIVATE_DATA
*Device
;
399 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*StorageSecurity
;
402 VOID
*DummyInterface
;
406 Status
= gBS
->OpenProtocol (
408 &gEfiBlockIoProtocolGuid
,
410 This
->DriverBindingHandle
,
412 EFI_OPEN_PROTOCOL_GET_PROTOCOL
414 if (EFI_ERROR (Status
)) {
418 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo
);
421 // Wait for the device's asynchronous I/O queue to become empty.
424 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
425 IsEmpty
= IsListEmpty (&Device
->AsyncQueue
);
426 gBS
->RestoreTPL (OldTpl
);
436 // Close the child handle
440 &gEfiNvmExpressPassThruProtocolGuid
,
441 This
->DriverBindingHandle
,
446 // The Nvm Express driver installs the BlockIo and DiskInfo in the DriverBindingStart().
447 // Here should uninstall both of them.
449 Status
= gBS
->UninstallMultipleProtocolInterfaces (
451 &gEfiDevicePathProtocolGuid
,
453 &gEfiBlockIoProtocolGuid
,
455 &gEfiBlockIo2ProtocolGuid
,
457 &gEfiDiskInfoProtocolGuid
,
462 if (EFI_ERROR (Status
)) {
465 &gEfiNvmExpressPassThruProtocolGuid
,
466 (VOID
**) &DummyInterface
,
467 This
->DriverBindingHandle
,
469 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
475 // If Storage Security Command Protocol is installed, then uninstall this protocol.
477 Status
= gBS
->OpenProtocol (
479 &gEfiStorageSecurityCommandProtocolGuid
,
480 (VOID
**) &StorageSecurity
,
481 This
->DriverBindingHandle
,
483 EFI_OPEN_PROTOCOL_GET_PROTOCOL
486 if (!EFI_ERROR (Status
)) {
487 Status
= gBS
->UninstallProtocolInterface (
489 &gEfiStorageSecurityCommandProtocolGuid
,
490 &Device
->StorageSecurity
492 if (EFI_ERROR (Status
)) {
495 &gEfiNvmExpressPassThruProtocolGuid
,
496 (VOID
**) &DummyInterface
,
497 This
->DriverBindingHandle
,
499 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
505 if(Device
->DevicePath
!= NULL
) {
506 FreePool (Device
->DevicePath
);
509 if (Device
->ControllerNameTable
!= NULL
) {
510 FreeUnicodeStringTable (Device
->ControllerNameTable
);
519 Call back function when the timer event is signaled.
521 @param[in] Event The Event this notify function registered to.
522 @param[in] Context Pointer to the context data registered to the
528 ProcessAsyncTaskList (
533 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
534 EFI_PCI_IO_PROTOCOL
*PciIo
;
539 LIST_ENTRY
*NextLink
;
540 NVME_PASS_THRU_ASYNC_REQ
*AsyncRequest
;
541 NVME_BLKIO2_SUBTASK
*Subtask
;
542 NVME_BLKIO2_REQUEST
*BlkIo2Request
;
543 EFI_BLOCK_IO2_TOKEN
*Token
;
547 Private
= (NVME_CONTROLLER_PRIVATE_DATA
*)Context
;
549 Cq
= Private
->CqBuffer
[QueueId
] + Private
->CqHdbl
[QueueId
].Cqh
;
553 // Submit asynchronous subtasks to the NVMe Submission Queue
555 for (Link
= GetFirstNode (&Private
->UnsubmittedSubtasks
);
556 !IsNull (&Private
->UnsubmittedSubtasks
, Link
);
558 NextLink
= GetNextNode (&Private
->UnsubmittedSubtasks
, Link
);
559 Subtask
= NVME_BLKIO2_SUBTASK_FROM_LINK (Link
);
560 BlkIo2Request
= Subtask
->BlockIo2Request
;
561 Token
= BlkIo2Request
->Token
;
562 RemoveEntryList (Link
);
563 BlkIo2Request
->UnsubmittedSubtaskNum
--;
566 // If any previous subtask fails, do not process subsequent ones.
568 if (Token
->TransactionStatus
!= EFI_SUCCESS
) {
569 if (IsListEmpty (&BlkIo2Request
->SubtasksQueue
) &&
570 BlkIo2Request
->LastSubtaskSubmitted
&&
571 (BlkIo2Request
->UnsubmittedSubtaskNum
== 0)) {
573 // Remove the BlockIo2 request from the device asynchronous queue.
575 RemoveEntryList (&BlkIo2Request
->Link
);
576 FreePool (BlkIo2Request
);
577 gBS
->SignalEvent (Token
->Event
);
580 FreePool (Subtask
->CommandPacket
->NvmeCmd
);
581 FreePool (Subtask
->CommandPacket
->NvmeCompletion
);
582 FreePool (Subtask
->CommandPacket
);
588 Status
= Private
->Passthru
.PassThru (
590 Subtask
->NamespaceId
,
591 Subtask
->CommandPacket
,
594 if (Status
== EFI_NOT_READY
) {
595 InsertHeadList (&Private
->UnsubmittedSubtasks
, Link
);
596 BlkIo2Request
->UnsubmittedSubtaskNum
++;
598 } else if (EFI_ERROR (Status
)) {
599 Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
601 if (IsListEmpty (&BlkIo2Request
->SubtasksQueue
) &&
604 // Remove the BlockIo2 request from the device asynchronous queue.
606 RemoveEntryList (&BlkIo2Request
->Link
);
607 FreePool (BlkIo2Request
);
608 gBS
->SignalEvent (Token
->Event
);
611 FreePool (Subtask
->CommandPacket
->NvmeCmd
);
612 FreePool (Subtask
->CommandPacket
->NvmeCompletion
);
613 FreePool (Subtask
->CommandPacket
);
616 InsertTailList (&BlkIo2Request
->SubtasksQueue
, Link
);
617 if (Subtask
->IsLast
) {
618 BlkIo2Request
->LastSubtaskSubmitted
= TRUE
;
623 while (Cq
->Pt
!= Private
->Pt
[QueueId
]) {
624 ASSERT (Cq
->Sqid
== QueueId
);
629 // Find the command with given Command Id.
631 for (Link
= GetFirstNode (&Private
->AsyncPassThruQueue
);
632 !IsNull (&Private
->AsyncPassThruQueue
, Link
);
634 NextLink
= GetNextNode (&Private
->AsyncPassThruQueue
, Link
);
635 AsyncRequest
= NVME_PASS_THRU_ASYNC_REQ_FROM_THIS (Link
);
636 if (AsyncRequest
->CommandId
== Cq
->Cid
) {
638 // Copy the Respose Queue entry for this command to the callers
642 AsyncRequest
->Packet
->NvmeCompletion
,
644 sizeof(EFI_NVM_EXPRESS_COMPLETION
)
647 RemoveEntryList (Link
);
648 gBS
->SignalEvent (AsyncRequest
->CallerEvent
);
649 FreePool (AsyncRequest
);
652 // Update submission queue head.
654 Private
->AsyncSqHead
= Cq
->Sqhd
;
659 Private
->CqHdbl
[QueueId
].Cqh
++;
660 if (Private
->CqHdbl
[QueueId
].Cqh
> NVME_ASYNC_CCQ_SIZE
) {
661 Private
->CqHdbl
[QueueId
].Cqh
= 0;
662 Private
->Pt
[QueueId
] ^= 1;
665 Cq
= Private
->CqBuffer
[QueueId
] + Private
->CqHdbl
[QueueId
].Cqh
;
669 PciIo
= Private
->PciIo
;
670 Data
= ReadUnaligned32 ((UINT32
*)&Private
->CqHdbl
[QueueId
]);
675 NVME_CQHDBL_OFFSET(QueueId
, Private
->Cap
.Dstrd
),
683 Tests to see if this driver supports a given controller. If a child device is provided,
684 it further tests to see if this driver supports creating a handle for the specified child device.
686 This function checks to see if the driver specified by This supports the device specified by
687 ControllerHandle. Drivers will typically use the device path attached to
688 ControllerHandle and/or the services from the bus I/O abstraction attached to
689 ControllerHandle to determine if the driver supports ControllerHandle. This function
690 may be called many times during platform initialization. In order to reduce boot times, the tests
691 performed by this function must be very small, and take as little time as possible to execute. This
692 function must not change the state of any hardware devices, and this function must be aware that the
693 device specified by ControllerHandle may already be managed by the same driver or a
694 different driver. This function must match its calls to AllocatePages() with FreePages(),
695 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
696 Since ControllerHandle may have been previously started by the same driver, if a protocol is
697 already in the opened state, then it must not be closed with CloseProtocol(). This is required
698 to guarantee the state of ControllerHandle is not modified by this function.
700 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
701 @param[in] ControllerHandle The handle of the controller to test. This handle
702 must support a protocol interface that supplies
703 an I/O abstraction to the driver.
704 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
705 parameter is ignored by device drivers, and is optional for bus
706 drivers. For bus drivers, if this parameter is not NULL, then
707 the bus driver must determine if the bus controller specified
708 by ControllerHandle and the child controller specified
709 by RemainingDevicePath are both supported by this
712 @retval EFI_SUCCESS The device specified by ControllerHandle and
713 RemainingDevicePath is supported by the driver specified by This.
714 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
715 RemainingDevicePath is already being managed by the driver
717 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
718 RemainingDevicePath is already being managed by a different
719 driver or an application that requires exclusive access.
720 Currently not implemented.
721 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
722 RemainingDevicePath is not supported by the driver specified by This.
726 NvmExpressDriverBindingSupported (
727 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
728 IN EFI_HANDLE Controller
,
729 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
733 EFI_DEV_PATH_PTR DevicePathNode
;
734 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
735 EFI_PCI_IO_PROTOCOL
*PciIo
;
739 // Check whether device path is valid
741 if (RemainingDevicePath
!= NULL
) {
743 // Check if RemainingDevicePath is the End of Device Path Node,
744 // if yes, go on checking other conditions
746 if (!IsDevicePathEnd (RemainingDevicePath
)) {
748 // If RemainingDevicePath isn't the End of Device Path Node,
749 // check its validation
751 DevicePathNode
.DevPath
= RemainingDevicePath
;
753 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
754 (DevicePathNode
.DevPath
->SubType
!= MSG_NVME_NAMESPACE_DP
) ||
755 (DevicePathNodeLength(DevicePathNode
.DevPath
) != sizeof(NVME_NAMESPACE_DEVICE_PATH
))) {
756 return EFI_UNSUPPORTED
;
762 // Open the EFI Device Path protocol needed to perform the supported test
764 Status
= gBS
->OpenProtocol (
766 &gEfiDevicePathProtocolGuid
,
767 (VOID
**) &ParentDevicePath
,
768 This
->DriverBindingHandle
,
770 EFI_OPEN_PROTOCOL_BY_DRIVER
772 if (Status
== EFI_ALREADY_STARTED
) {
776 if (EFI_ERROR (Status
)) {
781 // Close protocol, don't use device path protocol in the Support() function
785 &gEfiDevicePathProtocolGuid
,
786 This
->DriverBindingHandle
,
791 // Attempt to Open PCI I/O Protocol
793 Status
= gBS
->OpenProtocol (
795 &gEfiPciIoProtocolGuid
,
797 This
->DriverBindingHandle
,
799 EFI_OPEN_PROTOCOL_BY_DRIVER
801 if (Status
== EFI_ALREADY_STARTED
) {
805 if (EFI_ERROR (Status
)) {
810 // Now further check the PCI header: Base class (offset 0x0B) and Sub Class (offset 0x0A).
811 // This controller should be a Nvm Express controller.
813 Status
= PciIo
->Pci
.Read (
816 PCI_CLASSCODE_OFFSET
,
820 if (EFI_ERROR (Status
)) {
825 // Examine Nvm Express controller PCI Configuration table fields
827 if ((ClassCode
[0] != PCI_IF_NVMHCI
) || (ClassCode
[1] != PCI_CLASS_MASS_STORAGE_NVM
) || (ClassCode
[2] != PCI_CLASS_MASS_STORAGE
)) {
828 Status
= EFI_UNSUPPORTED
;
834 &gEfiPciIoProtocolGuid
,
835 This
->DriverBindingHandle
,
844 Starts a device controller or a bus controller.
846 The Start() function is designed to be invoked from the EFI boot service ConnectController().
847 As a result, much of the error checking on the parameters to Start() has been moved into this
848 common boot service. It is legal to call Start() from other locations,
849 but the following calling restrictions must be followed or the system behavior will not be deterministic.
850 1. ControllerHandle must be a valid EFI_HANDLE.
851 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
852 EFI_DEVICE_PATH_PROTOCOL.
853 3. Prior to calling Start(), the Supported() function for the driver specified by This must
854 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
856 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
857 @param[in] ControllerHandle The handle of the controller to start. This handle
858 must support a protocol interface that supplies
859 an I/O abstraction to the driver.
860 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
861 parameter is ignored by device drivers, and is optional for bus
862 drivers. For a bus driver, if this parameter is NULL, then handles
863 for all the children of Controller are created by this driver.
864 If this parameter is not NULL and the first Device Path Node is
865 not the End of Device Path Node, then only the handle for the
866 child device specified by the first Device Path Node of
867 RemainingDevicePath is created by this driver.
868 If the first Device Path Node of RemainingDevicePath is
869 the End of Device Path Node, no child handle is created by this
872 @retval EFI_SUCCESS The device was started.
873 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
874 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
875 @retval Others The driver failded to start the device.
880 NvmExpressDriverBindingStart (
881 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
882 IN EFI_HANDLE Controller
,
883 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
887 EFI_PCI_IO_PROTOCOL
*PciIo
;
888 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
889 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
891 EFI_PHYSICAL_ADDRESS MappedAddr
;
893 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*Passthru
;
895 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: start\n"));
899 ParentDevicePath
= NULL
;
901 Status
= gBS
->OpenProtocol (
903 &gEfiDevicePathProtocolGuid
,
904 (VOID
**) &ParentDevicePath
,
905 This
->DriverBindingHandle
,
907 EFI_OPEN_PROTOCOL_BY_DRIVER
909 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
913 Status
= gBS
->OpenProtocol (
915 &gEfiPciIoProtocolGuid
,
917 This
->DriverBindingHandle
,
919 EFI_OPEN_PROTOCOL_BY_DRIVER
922 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
927 // Check EFI_ALREADY_STARTED to reuse the original NVME_CONTROLLER_PRIVATE_DATA.
929 if (Status
!= EFI_ALREADY_STARTED
) {
930 Private
= AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA
));
932 if (Private
== NULL
) {
933 DEBUG ((EFI_D_ERROR
, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n"));
934 Status
= EFI_OUT_OF_RESOURCES
;
939 // 6 x 4kB aligned buffers will be carved out of this buffer.
940 // 1st 4kB boundary is the start of the admin submission queue.
941 // 2nd 4kB boundary is the start of the admin completion queue.
942 // 3rd 4kB boundary is the start of I/O submission queue #1.
943 // 4th 4kB boundary is the start of I/O completion queue #1.
944 // 5th 4kB boundary is the start of I/O submission queue #2.
945 // 6th 4kB boundary is the start of I/O completion queue #2.
947 // Allocate 6 pages of memory, then map it for bus master read and write.
949 Status
= PciIo
->AllocateBuffer (
954 (VOID
**)&Private
->Buffer
,
957 if (EFI_ERROR (Status
)) {
961 Bytes
= EFI_PAGES_TO_SIZE (6);
962 Status
= PciIo
->Map (
964 EfiPciIoOperationBusMasterCommonBuffer
,
971 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (6))) {
975 Private
->BufferPciAddr
= (UINT8
*)(UINTN
)MappedAddr
;
977 Private
->Signature
= NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE
;
978 Private
->ControllerHandle
= Controller
;
979 Private
->ImageHandle
= This
->DriverBindingHandle
;
980 Private
->DriverBindingHandle
= This
->DriverBindingHandle
;
981 Private
->PciIo
= PciIo
;
982 Private
->ParentDevicePath
= ParentDevicePath
;
983 Private
->Passthru
.Mode
= &Private
->PassThruMode
;
984 Private
->Passthru
.PassThru
= NvmExpressPassThru
;
985 Private
->Passthru
.GetNextNamespace
= NvmExpressGetNextNamespace
;
986 Private
->Passthru
.BuildDevicePath
= NvmExpressBuildDevicePath
;
987 Private
->Passthru
.GetNamespace
= NvmExpressGetNamespace
;
988 CopyMem (&Private
->PassThruMode
, &gEfiNvmExpressPassThruMode
, sizeof (EFI_NVM_EXPRESS_PASS_THRU_MODE
));
989 InitializeListHead (&Private
->AsyncPassThruQueue
);
990 InitializeListHead (&Private
->UnsubmittedSubtasks
);
992 Status
= NvmeControllerInit (Private
);
993 if (EFI_ERROR(Status
)) {
998 // Start the asynchronous I/O completion monitor
1000 Status
= gBS
->CreateEvent (
1001 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1003 ProcessAsyncTaskList
,
1005 &Private
->TimerEvent
1007 if (EFI_ERROR (Status
)) {
1011 Status
= gBS
->SetTimer (
1012 Private
->TimerEvent
,
1016 if (EFI_ERROR (Status
)) {
1020 Status
= gBS
->InstallMultipleProtocolInterfaces (
1022 &gEfiNvmExpressPassThruProtocolGuid
,
1026 if (EFI_ERROR (Status
)) {
1030 Status
= gBS
->OpenProtocol (
1032 &gEfiNvmExpressPassThruProtocolGuid
,
1033 (VOID
**) &Passthru
,
1034 This
->DriverBindingHandle
,
1036 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1038 if (EFI_ERROR (Status
)) {
1042 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (Passthru
);
1045 if (RemainingDevicePath
== NULL
) {
1047 // Enumerate all NVME namespaces in the controller
1049 Status
= DiscoverAllNamespaces (
1053 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
1055 // Enumerate the specified NVME namespace
1057 Status
= Private
->Passthru
.GetNamespace (
1059 RemainingDevicePath
,
1063 if (!EFI_ERROR (Status
)) {
1064 Status
= EnumerateNvmeDevNamespace (
1071 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: end successfully\n"));
1075 if ((Private
!= NULL
) && (Private
->Mapping
!= NULL
)) {
1076 PciIo
->Unmap (PciIo
, Private
->Mapping
);
1079 if ((Private
!= NULL
) && (Private
->Buffer
!= NULL
)) {
1080 PciIo
->FreeBuffer (PciIo
, 6, Private
->Buffer
);
1083 if ((Private
!= NULL
) && (Private
->ControllerData
!= NULL
)) {
1084 FreePool (Private
->ControllerData
);
1087 if (Private
!= NULL
) {
1088 if (Private
->TimerEvent
!= NULL
) {
1089 gBS
->CloseEvent (Private
->TimerEvent
);
1095 gBS
->CloseProtocol (
1097 &gEfiPciIoProtocolGuid
,
1098 This
->DriverBindingHandle
,
1102 gBS
->CloseProtocol (
1104 &gEfiDevicePathProtocolGuid
,
1105 This
->DriverBindingHandle
,
1109 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: end with %r\n", Status
));
1116 Stops a device controller or a bus controller.
1118 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1119 As a result, much of the error checking on the parameters to Stop() has been moved
1120 into this common boot service. It is legal to call Stop() from other locations,
1121 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1122 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1123 same driver's Start() function.
1124 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1125 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1126 Start() function, and the Start() function must have called OpenProtocol() on
1127 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1129 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1130 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1131 support a bus specific I/O protocol for the driver
1132 to use to stop the device.
1133 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1134 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1135 if NumberOfChildren is 0.
1137 @retval EFI_SUCCESS The device was stopped.
1138 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1143 NvmExpressDriverBindingStop (
1144 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1145 IN EFI_HANDLE Controller
,
1146 IN UINTN NumberOfChildren
,
1147 IN EFI_HANDLE
*ChildHandleBuffer
1151 BOOLEAN AllChildrenStopped
;
1153 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
1154 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*PassThru
;
1158 if (NumberOfChildren
== 0) {
1159 Status
= gBS
->OpenProtocol (
1161 &gEfiNvmExpressPassThruProtocolGuid
,
1162 (VOID
**) &PassThru
,
1163 This
->DriverBindingHandle
,
1165 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1168 if (!EFI_ERROR (Status
)) {
1169 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (PassThru
);
1172 // Wait for the asynchronous PassThru queue to become empty.
1175 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1176 IsEmpty
= IsListEmpty (&Private
->AsyncPassThruQueue
) &&
1177 IsListEmpty (&Private
->UnsubmittedSubtasks
);
1178 gBS
->RestoreTPL (OldTpl
);
1187 gBS
->UninstallMultipleProtocolInterfaces (
1189 &gEfiNvmExpressPassThruProtocolGuid
,
1194 if (Private
->TimerEvent
!= NULL
) {
1195 gBS
->CloseEvent (Private
->TimerEvent
);
1198 if (Private
->Mapping
!= NULL
) {
1199 Private
->PciIo
->Unmap (Private
->PciIo
, Private
->Mapping
);
1202 if (Private
->Buffer
!= NULL
) {
1203 Private
->PciIo
->FreeBuffer (Private
->PciIo
, 6, Private
->Buffer
);
1206 FreePool (Private
->ControllerData
);
1210 gBS
->CloseProtocol (
1212 &gEfiPciIoProtocolGuid
,
1213 This
->DriverBindingHandle
,
1216 gBS
->CloseProtocol (
1218 &gEfiDevicePathProtocolGuid
,
1219 This
->DriverBindingHandle
,
1225 AllChildrenStopped
= TRUE
;
1227 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1228 Status
= UnregisterNvmeNamespace (This
, Controller
, ChildHandleBuffer
[Index
]);
1229 if (EFI_ERROR (Status
)) {
1230 AllChildrenStopped
= FALSE
;
1234 if (!AllChildrenStopped
) {
1235 return EFI_DEVICE_ERROR
;
1242 This is the unload handle for the NVM Express driver.
1244 Disconnect the driver specified by ImageHandle from the NVMe device in the handle database.
1245 Uninstall all the protocols installed in the driver.
1247 @param[in] ImageHandle The drivers' driver image.
1249 @retval EFI_SUCCESS The image is unloaded.
1250 @retval Others Failed to unload the image.
1256 IN EFI_HANDLE ImageHandle
1260 EFI_HANDLE
*DeviceHandleBuffer
;
1261 UINTN DeviceHandleCount
;
1263 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1264 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
1267 // Get the list of the device handles managed by this driver.
1268 // If there is an error getting the list, then means the driver
1269 // doesn't manage any device. At this way, we would only close
1270 // those protocols installed at image handle.
1272 DeviceHandleBuffer
= NULL
;
1273 Status
= gBS
->LocateHandleBuffer (
1275 &gEfiNvmExpressPassThruProtocolGuid
,
1281 if (!EFI_ERROR (Status
)) {
1283 // Disconnect the driver specified by ImageHandle from all
1284 // the devices in the handle database.
1286 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1287 Status
= gBS
->DisconnectController (
1288 DeviceHandleBuffer
[Index
],
1292 if (EFI_ERROR (Status
)) {
1299 // Uninstall all the protocols installed in the driver entry point
1301 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1303 &gEfiDriverBindingProtocolGuid
,
1304 &gNvmExpressDriverBinding
,
1305 &gEfiDriverSupportedEfiVersionProtocolGuid
,
1306 &gNvmExpressDriverSupportedEfiVersion
,
1310 if (EFI_ERROR (Status
)) {
1315 // Note we have to one by one uninstall the following protocols.
1316 // It's because some of them are optionally installed based on
1317 // the following PCD settings.
1318 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
1319 // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable
1320 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable
1321 // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable
1323 Status
= gBS
->HandleProtocol (
1325 &gEfiComponentNameProtocolGuid
,
1326 (VOID
**) &ComponentName
1328 if (!EFI_ERROR (Status
)) {
1329 gBS
->UninstallProtocolInterface (
1331 &gEfiComponentNameProtocolGuid
,
1336 Status
= gBS
->HandleProtocol (
1338 &gEfiComponentName2ProtocolGuid
,
1339 (VOID
**) &ComponentName2
1341 if (!EFI_ERROR (Status
)) {
1342 gBS
->UninstallProtocolInterface (
1344 &gEfiComponentName2ProtocolGuid
,
1349 Status
= EFI_SUCCESS
;
1353 // Free the buffer containing the list of handles from the handle database
1355 if (DeviceHandleBuffer
!= NULL
) {
1356 gBS
->FreePool (DeviceHandleBuffer
);
1362 The entry point for Nvm Express driver, used to install Nvm Express driver on the ImageHandle.
1364 @param ImageHandle The firmware allocated handle for this driver image.
1365 @param SystemTable Pointer to the EFI system table.
1367 @retval EFI_SUCCESS Driver loaded.
1368 @retval other Driver not loaded.
1373 NvmExpressDriverEntry (
1374 IN EFI_HANDLE ImageHandle
,
1375 IN EFI_SYSTEM_TABLE
*SystemTable
1380 Status
= EfiLibInstallDriverBindingComponentName2 (
1383 &gNvmExpressDriverBinding
,
1385 &gNvmExpressComponentName
,
1386 &gNvmExpressComponentName2
1388 ASSERT_EFI_ERROR (Status
);
1391 // Install EFI Driver Supported EFI Version Protocol required for
1392 // EFI drivers that are on PCI and other plug in cards.
1394 gNvmExpressDriverSupportedEfiVersion
.FirmwareVersion
= 0x00020028;
1395 Status
= gBS
->InstallMultipleProtocolInterfaces (
1397 &gEfiDriverSupportedEfiVersionProtocolGuid
,
1398 &gNvmExpressDriverSupportedEfiVersion
,
1401 ASSERT_EFI_ERROR (Status
);