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
| EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL
| EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM
,
48 Check if the specified Nvm Express device namespace is active, and create child handles
49 for them with BlockIo and DiskInfo protocol instances.
51 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
52 @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
53 allocated and built. Caller must set the NamespaceId to zero if the
54 device path node will contain a valid UUID.
56 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
57 @return Others Some error occurs when enumerating the namespaces.
61 EnumerateNvmeDevNamespace (
62 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
66 NVME_ADMIN_NAMESPACE_DATA
*NamespaceData
;
67 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePathNode
;
68 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
69 EFI_HANDLE DeviceHandle
;
70 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
71 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
72 NVME_DEVICE_PRIVATE_DATA
*Device
;
80 NewDevicePathNode
= NULL
;
85 // Allocate a buffer for Identify Namespace data
87 NamespaceData
= AllocateZeroPool(sizeof (NVME_ADMIN_NAMESPACE_DATA
));
88 if(NamespaceData
== NULL
) {
89 return EFI_OUT_OF_RESOURCES
;
92 ParentDevicePath
= Private
->ParentDevicePath
;
96 Status
= NvmeIdentifyNamespace (
101 if (EFI_ERROR(Status
)) {
105 // Validate Namespace
107 if (NamespaceData
->Ncap
== 0) {
108 Status
= EFI_DEVICE_ERROR
;
111 // allocate device private data for each discovered namespace
113 Device
= AllocateZeroPool(sizeof(NVME_DEVICE_PRIVATE_DATA
));
114 if (Device
== NULL
) {
115 Status
= EFI_OUT_OF_RESOURCES
;
120 // Initialize SSD namespace instance data
122 Device
->Signature
= NVME_DEVICE_PRIVATE_DATA_SIGNATURE
;
123 Device
->NamespaceId
= NamespaceId
;
124 Device
->NamespaceUuid
= NamespaceData
->Eui64
;
126 Device
->ControllerHandle
= Private
->ControllerHandle
;
127 Device
->DriverBindingHandle
= Private
->DriverBindingHandle
;
128 Device
->Controller
= Private
;
131 // Build BlockIo media structure
133 Device
->Media
.MediaId
= 0;
134 Device
->Media
.RemovableMedia
= FALSE
;
135 Device
->Media
.MediaPresent
= TRUE
;
136 Device
->Media
.LogicalPartition
= FALSE
;
137 Device
->Media
.ReadOnly
= FALSE
;
138 Device
->Media
.WriteCaching
= FALSE
;
140 Flbas
= NamespaceData
->Flbas
;
141 LbaFmtIdx
= Flbas
& 0xF;
142 Lbads
= NamespaceData
->LbaFormat
[LbaFmtIdx
].Lbads
;
143 Device
->Media
.BlockSize
= (UINT32
)1 << Lbads
;
145 Device
->Media
.LastBlock
= NamespaceData
->Nsze
- 1;
146 Device
->Media
.LogicalBlocksPerPhysicalBlock
= 1;
147 Device
->Media
.LowestAlignedLba
= 1;
150 // Create BlockIo Protocol instance
152 Device
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION2
;
153 Device
->BlockIo
.Media
= &Device
->Media
;
154 Device
->BlockIo
.Reset
= NvmeBlockIoReset
;
155 Device
->BlockIo
.ReadBlocks
= NvmeBlockIoReadBlocks
;
156 Device
->BlockIo
.WriteBlocks
= NvmeBlockIoWriteBlocks
;
157 Device
->BlockIo
.FlushBlocks
= NvmeBlockIoFlushBlocks
;
160 // Create StorageSecurityProtocol Instance
162 Device
->StorageSecurity
.ReceiveData
= NvmeStorageSecurityReceiveData
;
163 Device
->StorageSecurity
.SendData
= NvmeStorageSecuritySendData
;
166 // Create DiskInfo Protocol instance
168 CopyMem (&Device
->NamespaceData
, NamespaceData
, sizeof (NVME_ADMIN_NAMESPACE_DATA
));
169 InitializeDiskInfo (Device
);
172 // Create a Nvm Express Namespace Device Path Node
174 Status
= Private
->Passthru
.BuildDevicePath (
180 if (EFI_ERROR(Status
)) {
185 // Append the SSD node to the controller's device path
187 DevicePath
= AppendDevicePathNode (ParentDevicePath
, NewDevicePathNode
);
188 if (DevicePath
== NULL
) {
189 Status
= EFI_OUT_OF_RESOURCES
;
194 RemainingDevicePath
= DevicePath
;
195 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &DeviceHandle
);
196 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd(RemainingDevicePath
)) {
197 Status
= EFI_ALREADY_STARTED
;
198 FreePool (DevicePath
);
202 Device
->DevicePath
= DevicePath
;
205 // Make sure the handle is NULL so we create a new handle
207 Device
->DeviceHandle
= NULL
;
209 Status
= gBS
->InstallMultipleProtocolInterfaces (
210 &Device
->DeviceHandle
,
211 &gEfiDevicePathProtocolGuid
,
213 &gEfiBlockIoProtocolGuid
,
215 &gEfiDiskInfoProtocolGuid
,
220 if(EFI_ERROR(Status
)) {
225 // Check if the NVMe controller supports the Security Send and Security Receive commands
227 if ((Private
->ControllerData
->Oacs
& SECURITY_SEND_RECEIVE_SUPPORTED
) != 0) {
228 Status
= gBS
->InstallProtocolInterface (
229 &Device
->DeviceHandle
,
230 &gEfiStorageSecurityCommandProtocolGuid
,
231 EFI_NATIVE_INTERFACE
,
232 &Device
->StorageSecurity
234 if(EFI_ERROR(Status
)) {
235 gBS
->UninstallMultipleProtocolInterfaces (
236 &Device
->DeviceHandle
,
237 &gEfiDevicePathProtocolGuid
,
239 &gEfiBlockIoProtocolGuid
,
241 &gEfiDiskInfoProtocolGuid
,
250 Private
->ControllerHandle
,
251 &gEfiNvmExpressPassThruProtocolGuid
,
252 (VOID
**) &Private
->Passthru
,
253 Private
->DriverBindingHandle
,
254 Device
->DeviceHandle
,
255 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
259 // Dump NvmExpress Identify Namespace Data
261 DEBUG ((EFI_D_INFO
, " == NVME IDENTIFY NAMESPACE [%d] DATA ==\n", NamespaceId
));
262 DEBUG ((EFI_D_INFO
, " NSZE : 0x%x\n", NamespaceData
->Nsze
));
263 DEBUG ((EFI_D_INFO
, " NCAP : 0x%x\n", NamespaceData
->Ncap
));
264 DEBUG ((EFI_D_INFO
, " NUSE : 0x%x\n", NamespaceData
->Nuse
));
265 DEBUG ((EFI_D_INFO
, " LBAF0.LBADS : 0x%x\n", (NamespaceData
->LbaFormat
[0].Lbads
)));
268 // Build controller name for Component Name (2) protocol.
270 CopyMem (Sn
, Private
->ControllerData
->Sn
, sizeof (Private
->ControllerData
->Sn
));
272 CopyMem (Mn
, Private
->ControllerData
->Mn
, sizeof (Private
->ControllerData
->Mn
));
274 UnicodeSPrintAsciiFormat (Device
->ModelName
, sizeof (Device
->ModelName
), "%a-%a-%x", Sn
, Mn
, NamespaceData
->Eui64
);
278 gNvmExpressComponentName
.SupportedLanguages
,
279 &Device
->ControllerNameTable
,
286 gNvmExpressComponentName2
.SupportedLanguages
,
287 &Device
->ControllerNameTable
,
294 if(NamespaceData
!= NULL
) {
295 FreePool (NamespaceData
);
298 if (NewDevicePathNode
!= NULL
) {
299 FreePool (NewDevicePathNode
);
302 if(EFI_ERROR(Status
) && (Device
!= NULL
) && (Device
->DevicePath
!= NULL
)) {
303 FreePool (Device
->DevicePath
);
305 if(EFI_ERROR(Status
) && (Device
!= NULL
)) {
312 Discover all Nvm Express device namespaces, and create child handles for them with BlockIo
313 and DiskInfo protocol instances.
315 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
317 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
318 @return Others Some error occurs when enumerating the namespaces.
322 DiscoverAllNamespaces (
323 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
328 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*Passthru
;
330 NamespaceId
= 0xFFFFFFFF;
331 Passthru
= &Private
->Passthru
;
334 Status
= Passthru
->GetNextNamespace (
336 (UINT32
*)&NamespaceId
339 if (EFI_ERROR (Status
)) {
343 Status
= EnumerateNvmeDevNamespace (
348 if (EFI_ERROR(Status
)) {
357 Unregisters a Nvm Express device namespace.
359 This function removes the protocols installed on the controller handle and
360 frees the resources allocated for the namespace.
362 @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
363 @param Controller The controller handle of the namespace.
364 @param Handle The child handle.
366 @retval EFI_SUCCESS The namespace is successfully unregistered.
367 @return Others Some error occurs when unregistering the namespace.
371 UnregisterNvmeNamespace (
372 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
373 IN EFI_HANDLE Controller
,
378 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
379 NVME_DEVICE_PRIVATE_DATA
*Device
;
380 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
381 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*StorageSecurity
;
385 Status
= gBS
->OpenProtocol (
387 &gEfiBlockIoProtocolGuid
,
389 This
->DriverBindingHandle
,
391 EFI_OPEN_PROTOCOL_GET_PROTOCOL
393 if (EFI_ERROR (Status
)) {
397 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo
);
398 Private
= Device
->Controller
;
401 // Close the child handle
405 &gEfiNvmExpressPassThruProtocolGuid
,
406 This
->DriverBindingHandle
,
411 // The Nvm Express driver installs the BlockIo and DiskInfo in the DriverBindingStart().
412 // Here should uninstall both of them.
414 Status
= gBS
->UninstallMultipleProtocolInterfaces (
416 &gEfiDevicePathProtocolGuid
,
418 &gEfiBlockIoProtocolGuid
,
420 &gEfiDiskInfoProtocolGuid
,
425 if (EFI_ERROR (Status
)) {
428 &gEfiNvmExpressPassThruProtocolGuid
,
429 (VOID
**) &Private
->Passthru
,
430 This
->DriverBindingHandle
,
432 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
438 // If Storage Security Command Protocol is installed, then uninstall this protocol.
440 Status
= gBS
->OpenProtocol (
442 &gEfiStorageSecurityCommandProtocolGuid
,
443 (VOID
**) &StorageSecurity
,
444 This
->DriverBindingHandle
,
446 EFI_OPEN_PROTOCOL_GET_PROTOCOL
449 if (!EFI_ERROR (Status
)) {
450 Status
= gBS
->UninstallProtocolInterface (
452 &gEfiStorageSecurityCommandProtocolGuid
,
453 &Device
->StorageSecurity
455 if (EFI_ERROR (Status
)) {
458 &gEfiNvmExpressPassThruProtocolGuid
,
459 (VOID
**) &Private
->Passthru
,
460 This
->DriverBindingHandle
,
462 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
468 if(Device
->DevicePath
!= NULL
) {
469 FreePool (Device
->DevicePath
);
472 if (Device
->ControllerNameTable
!= NULL
) {
473 FreeUnicodeStringTable (Device
->ControllerNameTable
);
482 Tests to see if this driver supports a given controller. If a child device is provided,
483 it further tests to see if this driver supports creating a handle for the specified child device.
485 This function checks to see if the driver specified by This supports the device specified by
486 ControllerHandle. Drivers will typically use the device path attached to
487 ControllerHandle and/or the services from the bus I/O abstraction attached to
488 ControllerHandle to determine if the driver supports ControllerHandle. This function
489 may be called many times during platform initialization. In order to reduce boot times, the tests
490 performed by this function must be very small, and take as little time as possible to execute. This
491 function must not change the state of any hardware devices, and this function must be aware that the
492 device specified by ControllerHandle may already be managed by the same driver or a
493 different driver. This function must match its calls to AllocatePages() with FreePages(),
494 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
495 Since ControllerHandle may have been previously started by the same driver, if a protocol is
496 already in the opened state, then it must not be closed with CloseProtocol(). This is required
497 to guarantee the state of ControllerHandle is not modified by this function.
499 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
500 @param[in] ControllerHandle The handle of the controller to test. This handle
501 must support a protocol interface that supplies
502 an I/O abstraction to the driver.
503 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
504 parameter is ignored by device drivers, and is optional for bus
505 drivers. For bus drivers, if this parameter is not NULL, then
506 the bus driver must determine if the bus controller specified
507 by ControllerHandle and the child controller specified
508 by RemainingDevicePath are both supported by this
511 @retval EFI_SUCCESS The device specified by ControllerHandle and
512 RemainingDevicePath is supported by the driver specified by This.
513 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
514 RemainingDevicePath is already being managed by the driver
516 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
517 RemainingDevicePath is already being managed by a different
518 driver or an application that requires exclusive access.
519 Currently not implemented.
520 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
521 RemainingDevicePath is not supported by the driver specified by This.
525 NvmExpressDriverBindingSupported (
526 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
527 IN EFI_HANDLE Controller
,
528 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
532 EFI_DEV_PATH_PTR DevicePathNode
;
533 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
534 EFI_PCI_IO_PROTOCOL
*PciIo
;
538 // Check whether device path is valid
540 if (RemainingDevicePath
!= NULL
) {
542 // Check if RemainingDevicePath is the End of Device Path Node,
543 // if yes, go on checking other conditions
545 if (!IsDevicePathEnd (RemainingDevicePath
)) {
547 // If RemainingDevicePath isn't the End of Device Path Node,
548 // check its validation
550 DevicePathNode
.DevPath
= RemainingDevicePath
;
552 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
553 (DevicePathNode
.DevPath
->SubType
!= MSG_NVME_NAMESPACE_DP
) ||
554 (DevicePathNodeLength(DevicePathNode
.DevPath
) != sizeof(NVME_NAMESPACE_DEVICE_PATH
))) {
555 return EFI_UNSUPPORTED
;
561 // Open the EFI Device Path protocol needed to perform the supported test
563 Status
= gBS
->OpenProtocol (
565 &gEfiDevicePathProtocolGuid
,
566 (VOID
**) &ParentDevicePath
,
567 This
->DriverBindingHandle
,
569 EFI_OPEN_PROTOCOL_BY_DRIVER
571 if (Status
== EFI_ALREADY_STARTED
) {
575 if (EFI_ERROR (Status
)) {
580 // Close protocol, don't use device path protocol in the Support() function
584 &gEfiDevicePathProtocolGuid
,
585 This
->DriverBindingHandle
,
590 // Attempt to Open PCI I/O Protocol
592 Status
= gBS
->OpenProtocol (
594 &gEfiPciIoProtocolGuid
,
596 This
->DriverBindingHandle
,
598 EFI_OPEN_PROTOCOL_BY_DRIVER
600 if (Status
== EFI_ALREADY_STARTED
) {
604 if (EFI_ERROR (Status
)) {
609 // Now further check the PCI header: Base class (offset 0x0B) and Sub Class (offset 0x0A).
610 // This controller should be a Nvm Express controller.
612 Status
= PciIo
->Pci
.Read (
615 PCI_CLASSCODE_OFFSET
,
619 if (EFI_ERROR (Status
)) {
624 // Examine Nvm Express controller PCI Configuration table fields
626 if ((ClassCode
[0] != PCI_IF_NVMHCI
) || (ClassCode
[1] != PCI_CLASS_MASS_STORAGE_NVM
) || (ClassCode
[2] != PCI_CLASS_MASS_STORAGE
)) {
627 Status
= EFI_UNSUPPORTED
;
633 &gEfiPciIoProtocolGuid
,
634 This
->DriverBindingHandle
,
643 Starts a device controller or a bus controller.
645 The Start() function is designed to be invoked from the EFI boot service ConnectController().
646 As a result, much of the error checking on the parameters to Start() has been moved into this
647 common boot service. It is legal to call Start() from other locations,
648 but the following calling restrictions must be followed or the system behavior will not be deterministic.
649 1. ControllerHandle must be a valid EFI_HANDLE.
650 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
651 EFI_DEVICE_PATH_PROTOCOL.
652 3. Prior to calling Start(), the Supported() function for the driver specified by This must
653 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
655 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
656 @param[in] ControllerHandle The handle of the controller to start. This handle
657 must support a protocol interface that supplies
658 an I/O abstraction to the driver.
659 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
660 parameter is ignored by device drivers, and is optional for bus
661 drivers. For a bus driver, if this parameter is NULL, then handles
662 for all the children of Controller are created by this driver.
663 If this parameter is not NULL and the first Device Path Node is
664 not the End of Device Path Node, then only the handle for the
665 child device specified by the first Device Path Node of
666 RemainingDevicePath is created by this driver.
667 If the first Device Path Node of RemainingDevicePath is
668 the End of Device Path Node, no child handle is created by this
671 @retval EFI_SUCCESS The device was started.
672 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
673 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
674 @retval Others The driver failded to start the device.
679 NvmExpressDriverBindingStart (
680 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
681 IN EFI_HANDLE Controller
,
682 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
686 EFI_PCI_IO_PROTOCOL
*PciIo
;
687 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
688 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
690 EFI_PHYSICAL_ADDRESS MappedAddr
;
692 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*Passthru
;
694 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: start\n"));
698 ParentDevicePath
= NULL
;
700 Status
= gBS
->OpenProtocol (
702 &gEfiDevicePathProtocolGuid
,
703 (VOID
**) &ParentDevicePath
,
704 This
->DriverBindingHandle
,
706 EFI_OPEN_PROTOCOL_BY_DRIVER
708 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
712 Status
= gBS
->OpenProtocol (
714 &gEfiPciIoProtocolGuid
,
716 This
->DriverBindingHandle
,
718 EFI_OPEN_PROTOCOL_BY_DRIVER
721 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
726 // Check EFI_ALREADY_STARTED to reuse the original NVME_CONTROLLER_PRIVATE_DATA.
728 if (Status
!= EFI_ALREADY_STARTED
) {
729 Private
= AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA
));
731 if (Private
== NULL
) {
732 DEBUG ((EFI_D_ERROR
, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n"));
733 Status
= EFI_OUT_OF_RESOURCES
;
738 // 4 x 4kB aligned buffers will be carved out of this buffer.
739 // 1st 4kB boundary is the start of the admin submission queue.
740 // 2nd 4kB boundary is the start of the admin completion queue.
741 // 3rd 4kB boundary is the start of I/O submission queue #1.
742 // 4th 4kB boundary is the start of I/O completion queue #1.
744 // Allocate 4 pages of memory, then map it for bus master read and write.
746 Status
= PciIo
->AllocateBuffer (
751 (VOID
**)&Private
->Buffer
,
754 if (EFI_ERROR (Status
)) {
758 Bytes
= EFI_PAGES_TO_SIZE (4);
759 Status
= PciIo
->Map (
761 EfiPciIoOperationBusMasterCommonBuffer
,
768 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (4))) {
772 Private
->BufferPciAddr
= (UINT8
*)(UINTN
)MappedAddr
;
773 ZeroMem (Private
->Buffer
, EFI_PAGES_TO_SIZE (4));
775 Private
->Signature
= NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE
;
776 Private
->ControllerHandle
= Controller
;
777 Private
->ImageHandle
= This
->DriverBindingHandle
;
778 Private
->DriverBindingHandle
= This
->DriverBindingHandle
;
779 Private
->PciIo
= PciIo
;
780 Private
->ParentDevicePath
= ParentDevicePath
;
781 Private
->Passthru
.Mode
= &Private
->PassThruMode
;
782 Private
->Passthru
.PassThru
= NvmExpressPassThru
;
783 Private
->Passthru
.GetNextNamespace
= NvmExpressGetNextNamespace
;
784 Private
->Passthru
.BuildDevicePath
= NvmExpressBuildDevicePath
;
785 Private
->Passthru
.GetNamespace
= NvmExpressGetNamespace
;
786 CopyMem (&Private
->PassThruMode
, &gEfiNvmExpressPassThruMode
, sizeof (EFI_NVM_EXPRESS_PASS_THRU_MODE
));
788 Status
= NvmeControllerInit (Private
);
789 if (EFI_ERROR(Status
)) {
793 Status
= gBS
->InstallMultipleProtocolInterfaces (
795 &gEfiNvmExpressPassThruProtocolGuid
,
799 if (EFI_ERROR (Status
)) {
803 Status
= gBS
->OpenProtocol (
805 &gEfiNvmExpressPassThruProtocolGuid
,
807 This
->DriverBindingHandle
,
809 EFI_OPEN_PROTOCOL_GET_PROTOCOL
811 if (EFI_ERROR (Status
)) {
815 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (Passthru
);
818 if (RemainingDevicePath
== NULL
) {
820 // Enumerate all NVME namespaces in the controller
822 Status
= DiscoverAllNamespaces (
826 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
828 // Enumerate the specified NVME namespace
830 Status
= Private
->Passthru
.GetNamespace (
836 if (!EFI_ERROR (Status
)) {
837 Status
= EnumerateNvmeDevNamespace (
844 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: end successfully\n"));
848 if ((Private
!= NULL
) && (Private
->Mapping
!= NULL
)) {
849 PciIo
->Unmap (PciIo
, Private
->Mapping
);
852 if ((Private
!= NULL
) && (Private
->Buffer
!= NULL
)) {
853 PciIo
->FreeBuffer (PciIo
, 4, Private
->Buffer
);
856 if ((Private
!= NULL
) && (Private
->ControllerData
!= NULL
)) {
857 FreePool (Private
->ControllerData
);
860 if (Private
!= NULL
) {
866 &gEfiPciIoProtocolGuid
,
867 This
->DriverBindingHandle
,
873 &gEfiDevicePathProtocolGuid
,
874 This
->DriverBindingHandle
,
878 DEBUG ((EFI_D_INFO
, "NvmExpressDriverBindingStart: end with %r\n", Status
));
885 Stops a device controller or a bus controller.
887 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
888 As a result, much of the error checking on the parameters to Stop() has been moved
889 into this common boot service. It is legal to call Stop() from other locations,
890 but the following calling restrictions must be followed or the system behavior will not be deterministic.
891 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
892 same driver's Start() function.
893 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
894 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
895 Start() function, and the Start() function must have called OpenProtocol() on
896 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
898 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
899 @param[in] ControllerHandle A handle to the device being stopped. The handle must
900 support a bus specific I/O protocol for the driver
901 to use to stop the device.
902 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
903 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
904 if NumberOfChildren is 0.
906 @retval EFI_SUCCESS The device was stopped.
907 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
912 NvmExpressDriverBindingStop (
913 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
914 IN EFI_HANDLE Controller
,
915 IN UINTN NumberOfChildren
,
916 IN EFI_HANDLE
*ChildHandleBuffer
920 BOOLEAN AllChildrenStopped
;
922 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
923 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*PassThru
;
925 if (NumberOfChildren
== 0) {
926 Status
= gBS
->OpenProtocol (
928 &gEfiNvmExpressPassThruProtocolGuid
,
930 This
->DriverBindingHandle
,
932 EFI_OPEN_PROTOCOL_GET_PROTOCOL
935 if (!EFI_ERROR (Status
)) {
936 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (PassThru
);
937 gBS
->UninstallMultipleProtocolInterfaces (
939 &gEfiNvmExpressPassThruProtocolGuid
,
944 if (Private
->Mapping
!= NULL
) {
945 Private
->PciIo
->Unmap (Private
->PciIo
, Private
->Mapping
);
948 if (Private
->Buffer
!= NULL
) {
949 Private
->PciIo
->FreeBuffer (Private
->PciIo
, 4, Private
->Buffer
);
952 FreePool (Private
->ControllerData
);
958 &gEfiPciIoProtocolGuid
,
959 This
->DriverBindingHandle
,
964 &gEfiDevicePathProtocolGuid
,
965 This
->DriverBindingHandle
,
971 AllChildrenStopped
= TRUE
;
973 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
974 Status
= UnregisterNvmeNamespace (This
, Controller
, ChildHandleBuffer
[Index
]);
975 if (EFI_ERROR (Status
)) {
976 AllChildrenStopped
= FALSE
;
980 if (!AllChildrenStopped
) {
981 return EFI_DEVICE_ERROR
;
988 This is the unload handle for the NVM Express driver.
990 Disconnect the driver specified by ImageHandle from the NVMe device in the handle database.
991 Uninstall all the protocols installed in the driver.
993 @param[in] ImageHandle The drivers' driver image.
995 @retval EFI_SUCCESS The image is unloaded.
996 @retval Others Failed to unload the image.
1002 IN EFI_HANDLE ImageHandle
1006 EFI_HANDLE
*DeviceHandleBuffer
;
1007 UINTN DeviceHandleCount
;
1009 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1010 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
1013 // Get the list of the device handles managed by this driver.
1014 // If there is an error getting the list, then means the driver
1015 // doesn't manage any device. At this way, we would only close
1016 // those protocols installed at image handle.
1018 DeviceHandleBuffer
= NULL
;
1019 Status
= gBS
->LocateHandleBuffer (
1021 &gEfiNvmExpressPassThruProtocolGuid
,
1027 if (!EFI_ERROR (Status
)) {
1029 // Disconnect the driver specified by ImageHandle from all
1030 // the devices in the handle database.
1032 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1033 Status
= gBS
->DisconnectController (
1034 DeviceHandleBuffer
[Index
],
1038 if (EFI_ERROR (Status
)) {
1045 // Uninstall all the protocols installed in the driver entry point
1047 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1049 &gEfiDriverBindingProtocolGuid
,
1050 &gNvmExpressDriverBinding
,
1051 &gEfiDriverSupportedEfiVersionProtocolGuid
,
1052 &gNvmExpressDriverSupportedEfiVersion
,
1056 if (EFI_ERROR (Status
)) {
1061 // Note we have to one by one uninstall the following protocols.
1062 // It's because some of them are optionally installed based on
1063 // the following PCD settings.
1064 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
1065 // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable
1066 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable
1067 // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable
1069 Status
= gBS
->HandleProtocol (
1071 &gEfiComponentNameProtocolGuid
,
1072 (VOID
**) &ComponentName
1074 if (!EFI_ERROR (Status
)) {
1075 gBS
->UninstallProtocolInterface (
1077 &gEfiComponentNameProtocolGuid
,
1082 Status
= gBS
->HandleProtocol (
1084 &gEfiComponentName2ProtocolGuid
,
1085 (VOID
**) &ComponentName2
1087 if (!EFI_ERROR (Status
)) {
1088 gBS
->UninstallProtocolInterface (
1090 &gEfiComponentName2ProtocolGuid
,
1095 Status
= EFI_SUCCESS
;
1099 // Free the buffer containing the list of handles from the handle database
1101 if (DeviceHandleBuffer
!= NULL
) {
1102 gBS
->FreePool (DeviceHandleBuffer
);
1108 The entry point for Nvm Express driver, used to install Nvm Express driver on the ImageHandle.
1110 @param ImageHandle The firmware allocated handle for this driver image.
1111 @param SystemTable Pointer to the EFI system table.
1113 @retval EFI_SUCCESS Driver loaded.
1114 @retval other Driver not loaded.
1119 NvmExpressDriverEntry (
1120 IN EFI_HANDLE ImageHandle
,
1121 IN EFI_SYSTEM_TABLE
*SystemTable
1126 Status
= EfiLibInstallDriverBindingComponentName2 (
1129 &gNvmExpressDriverBinding
,
1131 &gNvmExpressComponentName
,
1132 &gNvmExpressComponentName2
1134 ASSERT_EFI_ERROR (Status
);
1137 // Install EFI Driver Supported EFI Version Protocol required for
1138 // EFI drivers that are on PCI and other plug in cards.
1140 gNvmExpressDriverSupportedEfiVersion
.FirmwareVersion
= 0x00020028;
1141 Status
= gBS
->InstallMultipleProtocolInterfaces (
1143 &gEfiDriverSupportedEfiVersionProtocolGuid
,
1144 &gNvmExpressDriverSupportedEfiVersion
,
1147 ASSERT_EFI_ERROR (Status
);