NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows\r
NVM Express specification.\r
\r
- Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
0 // Version number to be filled at start up.\r
};\r
\r
+//\r
+// Template for NVM Express Pass Thru Mode data structure.\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_NVM_EXPRESS_PASS_THRU_MODE gEfiNvmExpressPassThruMode = {\r
+ EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL | EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM,\r
+ sizeof (UINTN),\r
+ 0x10100\r
+};\r
+\r
/**\r
Check if the specified Nvm Express device namespace is active, and create child handles\r
for them with BlockIo and DiskInfo protocol instances.\r
@param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be\r
allocated and built. Caller must set the NamespaceId to zero if the\r
device path node will contain a valid UUID.\r
- @param[in] NamespaceUuid The NVM Express namespace UUID for which a device path node is to be\r
- allocated and built. UUID will only be valid of the Namespace ID is zero.\r
\r
@retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.\r
@return Others Some error occurs when enumerating the namespaces.\r
EFI_STATUS\r
EnumerateNvmeDevNamespace (\r
IN NVME_CONTROLLER_PRIVATE_DATA *Private,\r
- UINT32 NamespaceId,\r
- UINT64 NamespaceUuid\r
+ UINT32 NamespaceId\r
)\r
{\r
NVME_ADMIN_NAMESPACE_DATA *NamespaceData;\r
//\r
Device = AllocateZeroPool(sizeof(NVME_DEVICE_PRIVATE_DATA));\r
if (Device == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
goto Exit;\r
}\r
\r
Device->Media.WriteCaching = FALSE;\r
\r
Flbas = NamespaceData->Flbas;\r
- LbaFmtIdx = Flbas & 3;\r
+ LbaFmtIdx = Flbas & 0xF;\r
Lbads = NamespaceData->LbaFormat[LbaFmtIdx].Lbads;\r
Device->Media.BlockSize = (UINT32)1 << Lbads;\r
\r
Device->BlockIo.WriteBlocks = NvmeBlockIoWriteBlocks;\r
Device->BlockIo.FlushBlocks = NvmeBlockIoFlushBlocks;\r
\r
+ //\r
+ // Create StorageSecurityProtocol Instance\r
+ //\r
+ Device->StorageSecurity.ReceiveData = NvmeStorageSecurityReceiveData;\r
+ Device->StorageSecurity.SendData = NvmeStorageSecuritySendData;\r
+\r
//\r
// Create DiskInfo Protocol instance\r
//\r
+ CopyMem (&Device->NamespaceData, NamespaceData, sizeof (NVME_ADMIN_NAMESPACE_DATA));\r
InitializeDiskInfo (Device);\r
\r
//\r
Status = Private->Passthru.BuildDevicePath (\r
&Private->Passthru,\r
Device->NamespaceId,\r
- Device->NamespaceUuid,\r
&NewDevicePathNode\r
);\r
\r
if(EFI_ERROR(Status)) {\r
goto Exit;\r
}\r
+\r
+ //\r
+ // Check if the NVMe controller supports the Security Send and Security Receive commands\r
+ //\r
+ if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {\r
+ Status = gBS->InstallProtocolInterface (\r
+ &Device->DeviceHandle,\r
+ &gEfiStorageSecurityCommandProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &Device->StorageSecurity\r
+ );\r
+ if(EFI_ERROR(Status)) {\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ &Device->DeviceHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ Device->DevicePath,\r
+ &gEfiBlockIoProtocolGuid,\r
+ &Device->BlockIo,\r
+ &gEfiDiskInfoProtocolGuid,\r
+ &Device->DiskInfo,\r
+ NULL\r
+ );\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
gBS->OpenProtocol (\r
Private->ControllerHandle,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &Private->PciIo,\r
+ &gEfiNvmExpressPassThruProtocolGuid,\r
+ (VOID **) &Private->Passthru,\r
Private->DriverBindingHandle,\r
Device->DeviceHandle,\r
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
FreePool (NamespaceData);\r
}\r
\r
+ if (NewDevicePathNode != NULL) {\r
+ FreePool (NewDevicePathNode);\r
+ }\r
+\r
if(EFI_ERROR(Status) && (Device != NULL) && (Device->DevicePath != NULL)) {\r
FreePool (Device->DevicePath);\r
}\r
{\r
EFI_STATUS Status;\r
UINT32 NamespaceId;\r
- UINT64 NamespaceUuid;\r
- NVM_EXPRESS_PASS_THRU_PROTOCOL *Passthru;\r
+ EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *Passthru;\r
\r
NamespaceId = 0xFFFFFFFF;\r
- NamespaceUuid = 0;\r
Passthru = &Private->Passthru;\r
\r
while (TRUE) {\r
Status = Passthru->GetNextNamespace (\r
Passthru,\r
- (UINT32 *)&NamespaceId,\r
- (UINT64 *)&NamespaceUuid\r
+ (UINT32 *)&NamespaceId\r
);\r
\r
if (EFI_ERROR (Status)) {\r
\r
Status = EnumerateNvmeDevNamespace (\r
Private,\r
- NamespaceId,\r
- NamespaceUuid\r
+ NamespaceId\r
);\r
\r
if (EFI_ERROR(Status)) {\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
NVME_DEVICE_PRIVATE_DATA *Device;\r
+ NVME_CONTROLLER_PRIVATE_DATA *Private;\r
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity;\r
\r
BlockIo = NULL;\r
\r
return Status;\r
}\r
\r
- Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo);\r
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo);\r
+ Private = Device->Controller;\r
\r
//\r
// Close the child handle\r
//\r
gBS->CloseProtocol (\r
Controller,\r
- &gEfiPciIoProtocolGuid,\r
+ &gEfiNvmExpressPassThruProtocolGuid,\r
This->DriverBindingHandle,\r
Handle\r
);\r
if (EFI_ERROR (Status)) {\r
gBS->OpenProtocol (\r
Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo,\r
+ &gEfiNvmExpressPassThruProtocolGuid,\r
+ (VOID **) &Private->Passthru,\r
This->DriverBindingHandle,\r
Handle,\r
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
return Status;\r
}\r
\r
+ //\r
+ // If Storage Security Command Protocol is installed, then uninstall this protocol.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiStorageSecurityCommandProtocolGuid,\r
+ (VOID **) &StorageSecurity,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->UninstallProtocolInterface (\r
+ Handle,\r
+ &gEfiStorageSecurityCommandProtocolGuid,\r
+ &Device->StorageSecurity\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiNvmExpressPassThruProtocolGuid,\r
+ (VOID **) &Private->Passthru,\r
+ This->DriverBindingHandle,\r
+ Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ return Status;\r
+ }\r
+ }\r
+\r
if(Device->DevicePath != NULL) {\r
FreePool (Device->DevicePath);\r
}\r
FreeUnicodeStringTable (Device->ControllerNameTable);\r
}\r
\r
+ FreePool (Device);\r
+\r
return EFI_SUCCESS;\r
}\r
\r
\r
if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||\r
(DevicePathNode.DevPath->SubType != MSG_NVME_NAMESPACE_DP) ||\r
- DevicePathNodeLength(DevicePathNode.DevPath) != sizeof(NVME_NAMESPACE_DEVICE_PATH)) {\r
- return EFI_UNSUPPORTED;\r
+ (DevicePathNodeLength(DevicePathNode.DevPath) != sizeof(NVME_NAMESPACE_DEVICE_PATH))) {\r
+ return EFI_UNSUPPORTED;\r
}\r
}\r
}\r
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- NVME_CONTROLLER_PRIVATE_DATA *Private;\r
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
- UINT32 NamespaceId;\r
- UINT64 NamespaceUuid;\r
- EFI_PHYSICAL_ADDRESS MappedAddr;\r
- UINTN Bytes;\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ NVME_CONTROLLER_PRIVATE_DATA *Private;\r
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
+ UINT32 NamespaceId;\r
+ EFI_PHYSICAL_ADDRESS MappedAddr;\r
+ UINTN Bytes;\r
+ EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *Passthru;\r
\r
DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: start\n"));\r
\r
- Private = NULL;\r
+ Private = NULL;\r
+ Passthru = NULL;\r
ParentDevicePath = NULL;\r
\r
Status = gBS->OpenProtocol (\r
if (Private == NULL) {\r
DEBUG ((EFI_D_ERROR, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n"));\r
Status = EFI_OUT_OF_RESOURCES;\r
- goto Exit2;\r
+ goto Exit;\r
}\r
\r
//\r
0\r
);\r
if (EFI_ERROR (Status)) {\r
- goto Exit2;\r
+ goto Exit;\r
}\r
\r
Bytes = EFI_PAGES_TO_SIZE (4);\r
);\r
\r
if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (4))) {\r
- goto Exit2;\r
+ goto Exit;\r
}\r
\r
Private->BufferPciAddr = (UINT8 *)(UINTN)MappedAddr;\r
Private->Passthru.GetNextNamespace = NvmExpressGetNextNamespace;\r
Private->Passthru.BuildDevicePath = NvmExpressBuildDevicePath;\r
Private->Passthru.GetNamespace = NvmExpressGetNamespace;\r
- Private->PassThruMode.Attributes = NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL;\r
+ CopyMem (&Private->PassThruMode, &gEfiNvmExpressPassThruMode, sizeof (EFI_NVM_EXPRESS_PASS_THRU_MODE));\r
\r
Status = NvmeControllerInit (Private);\r
-\r
if (EFI_ERROR(Status)) {\r
- goto Exit2;\r
+ goto Exit;\r
}\r
\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&Controller,\r
- &gEfiCallerIdGuid,\r
- Private,\r
+ &gEfiNvmExpressPassThruProtocolGuid,\r
+ &Private->Passthru,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
- goto Exit2;\r
+ goto Exit;\r
}\r
} else {\r
Status = gBS->OpenProtocol (\r
Controller,\r
- &gEfiCallerIdGuid,\r
- (VOID **) &Private,\r
+ &gEfiNvmExpressPassThruProtocolGuid,\r
+ (VOID **) &Passthru,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
);\r
if (EFI_ERROR (Status)) {\r
- Private = NULL;\r
- goto Exit1;\r
+ goto Exit;\r
}\r
+\r
+ Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (Passthru);\r
}\r
\r
if (RemainingDevicePath == NULL) {\r
Status = Private->Passthru.GetNamespace (\r
&Private->Passthru,\r
RemainingDevicePath,\r
- &NamespaceId,\r
- &NamespaceUuid\r
+ &NamespaceId\r
);\r
\r
if (!EFI_ERROR (Status)) {\r
- Status = EnumerateNvmeDevNamespace (\r
- Private,\r
- NamespaceId,\r
- NamespaceUuid\r
- );\r
+ Status = EnumerateNvmeDevNamespace (\r
+ Private,\r
+ NamespaceId\r
+ );\r
}\r
}\r
\r
DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: end successfully\n"));\r
return EFI_SUCCESS;\r
\r
-Exit1:\r
- gBS->UninstallMultipleProtocolInterfaces (\r
- Controller,\r
- &gEfiCallerIdGuid,\r
- Private,\r
- NULL\r
- );\r
-Exit2:\r
+Exit:\r
if ((Private != NULL) && (Private->Mapping != NULL)) {\r
PciIo->Unmap (PciIo, Private->Mapping);\r
}\r
PciIo->FreeBuffer (PciIo, 4, Private->Buffer);\r
}\r
\r
+ if ((Private != NULL) && (Private->ControllerData != NULL)) {\r
+ FreePool (Private->ControllerData);\r
+ }\r
+\r
if (Private != NULL) {\r
FreePool (Private);\r
}\r
BOOLEAN AllChildrenStopped;\r
UINTN Index;\r
NVME_CONTROLLER_PRIVATE_DATA *Private;\r
+ EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *PassThru;\r
\r
if (NumberOfChildren == 0) {\r
Status = gBS->OpenProtocol (\r
Controller,\r
- &gEfiCallerIdGuid,\r
- (VOID **) &Private,\r
+ &gEfiNvmExpressPassThruProtocolGuid,\r
+ (VOID **) &PassThru,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
);\r
\r
if (!EFI_ERROR (Status)) {\r
+ Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (PassThru);\r
gBS->UninstallMultipleProtocolInterfaces (\r
Controller,\r
- &gEfiCallerIdGuid,\r
- Private,\r
+ &gEfiNvmExpressPassThruProtocolGuid,\r
+ PassThru,\r
NULL\r
);\r
\r
EFI_HANDLE *DeviceHandleBuffer;\r
UINTN DeviceHandleCount;\r
UINTN Index;\r
- EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
EFI_COMPONENT_NAME_PROTOCOL *ComponentName;\r
EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;\r
\r
//\r
- // Get the list of all the handles in the handle database.\r
- // If there is an error getting the list, then the unload\r
- // operation fails.\r
+ // Get the list of the device handles managed by this driver.\r
+ // If there is an error getting the list, then means the driver\r
+ // doesn't manage any device. At this way, we would only close\r
+ // those protocols installed at image handle.\r
//\r
+ DeviceHandleBuffer = NULL;\r
Status = gBS->LocateHandleBuffer (\r
- AllHandles,\r
- NULL,\r
+ ByProtocol,\r
+ &gEfiNvmExpressPassThruProtocolGuid,\r
NULL,\r
&DeviceHandleCount,\r
&DeviceHandleBuffer\r
);\r
\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Disconnect the driver specified by ImageHandle from all\r
+ // the devices in the handle database.\r
+ //\r
+ for (Index = 0; Index < DeviceHandleCount; Index++) {\r
+ Status = gBS->DisconnectController (\r
+ DeviceHandleBuffer[Index],\r
+ ImageHandle,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto EXIT;\r
+ }\r
+ }\r
}\r
\r
//\r
- // Disconnect the driver specified by ImageHandle from all\r
- // the devices in the handle database.\r
+ // Uninstall all the protocols installed in the driver entry point\r
//\r
- for (Index = 0; Index < DeviceHandleCount; Index++) {\r
- Status = gBS->DisconnectController (\r
- DeviceHandleBuffer[Index],\r
- ImageHandle,\r
- NULL\r
- );\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ ImageHandle,\r
+ &gEfiDriverBindingProtocolGuid,\r
+ &gNvmExpressDriverBinding,\r
+ &gEfiDriverSupportedEfiVersionProtocolGuid,\r
+ &gNvmExpressDriverSupportedEfiVersion,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto EXIT;\r
}\r
\r
//\r
- // Uninstall all the protocols installed in the driver entry point\r
+ // Note we have to one by one uninstall the following protocols.\r
+ // It's because some of them are optionally installed based on\r
+ // the following PCD settings.\r
+ // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable\r
+ // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable\r
+ // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable\r
+ // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable\r
//\r
- for (Index = 0; Index < DeviceHandleCount; Index++) {\r
- Status = gBS->HandleProtocol (\r
- DeviceHandleBuffer[Index],\r
- &gEfiDriverBindingProtocolGuid,\r
- (VOID **) &DriverBinding\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- if (DriverBinding->ImageHandle != ImageHandle) {\r
- continue;\r
- }\r
-\r
+ Status = gBS->HandleProtocol (\r
+ ImageHandle,\r
+ &gEfiComponentNameProtocolGuid,\r
+ (VOID **) &ComponentName\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
gBS->UninstallProtocolInterface (\r
ImageHandle,\r
- &gEfiDriverBindingProtocolGuid,\r
- DriverBinding\r
+ &gEfiComponentNameProtocolGuid,\r
+ ComponentName\r
);\r
+ }\r
\r
- Status = gBS->HandleProtocol (\r
- DeviceHandleBuffer[Index],\r
- &gEfiComponentNameProtocolGuid,\r
- (VOID **) &ComponentName\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- gBS->UninstallProtocolInterface (\r
- ImageHandle,\r
- &gEfiComponentNameProtocolGuid,\r
- ComponentName\r
- );\r
- }\r
-\r
- Status = gBS->HandleProtocol (\r
- DeviceHandleBuffer[Index],\r
- &gEfiComponentName2ProtocolGuid,\r
- (VOID **) &ComponentName2\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- gBS->UninstallProtocolInterface (\r
- ImageHandle,\r
- &gEfiComponentName2ProtocolGuid,\r
- ComponentName2\r
- );\r
- }\r
+ Status = gBS->HandleProtocol (\r
+ ImageHandle,\r
+ &gEfiComponentName2ProtocolGuid,\r
+ (VOID **) &ComponentName2\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ gBS->UninstallProtocolInterface (\r
+ ImageHandle,\r
+ &gEfiComponentName2ProtocolGuid,\r
+ ComponentName2\r
+ );\r
}\r
\r
+ Status = EFI_SUCCESS;\r
+\r
+EXIT:\r
//\r
// Free the buffer containing the list of handles from the handle database\r
//\r
if (DeviceHandleBuffer != NULL) {\r
gBS->FreePool (DeviceHandleBuffer);\r
}\r
- return EFI_SUCCESS;\r
+ return Status;\r
}\r
\r
/**\r