]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
MdeModulePkg/NvmExpress: Clean Phase/CqHdbl/SqTdbl fields to restart HC
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NvmExpressDxe / NvmExpress.c
CommitLineData
eb290d02
FT
1/** @file\r
2 NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows\r
3 NVM Express specification.\r
4\r
d2a2678b 5 Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>\r
eb290d02
FT
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php.\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "NvmExpress.h"\r
17\r
18//\r
19// NVM Express Driver Binding Protocol Instance\r
20//\r
21EFI_DRIVER_BINDING_PROTOCOL gNvmExpressDriverBinding = {\r
22 NvmExpressDriverBindingSupported,\r
23 NvmExpressDriverBindingStart,\r
24 NvmExpressDriverBindingStop,\r
25 0x10,\r
26 NULL,\r
27 NULL\r
28};\r
29\r
30//\r
31// NVM Express EFI Driver Supported EFI Version Protocol Instance\r
32//\r
33EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiVersion = {\r
34 sizeof (EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL), // Size of Protocol structure.\r
35 0 // Version number to be filled at start up.\r
36};\r
37\r
d6c55989
FT
38//\r
39// Template for NVM Express Pass Thru Mode data structure.\r
40//\r
41GLOBAL_REMOVE_IF_UNREFERENCED EFI_NVM_EXPRESS_PASS_THRU_MODE gEfiNvmExpressPassThruMode = {\r
42 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL | EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM,\r
43 sizeof (UINTN),\r
44 0x10100\r
45};\r
46\r
eb290d02
FT
47/**\r
48 Check if the specified Nvm Express device namespace is active, and create child handles\r
49 for them with BlockIo and DiskInfo protocol instances.\r
50\r
51 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.\r
52 @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be\r
53 allocated and built. Caller must set the NamespaceId to zero if the\r
54 device path node will contain a valid UUID.\r
eb290d02
FT
55\r
56 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.\r
57 @return Others Some error occurs when enumerating the namespaces.\r
58\r
59**/\r
60EFI_STATUS\r
61EnumerateNvmeDevNamespace (\r
62 IN NVME_CONTROLLER_PRIVATE_DATA *Private,\r
d6c55989 63 UINT32 NamespaceId\r
eb290d02
FT
64 )\r
65{\r
66 NVME_ADMIN_NAMESPACE_DATA *NamespaceData;\r
67 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
68 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
69 EFI_HANDLE DeviceHandle;\r
70 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
71 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
72 NVME_DEVICE_PRIVATE_DATA *Device;\r
73 EFI_STATUS Status;\r
74 UINT32 Lbads;\r
75 UINT32 Flbas;\r
76 UINT32 LbaFmtIdx;\r
da7c7274
FT
77 UINT8 Sn[21];\r
78 UINT8 Mn[41];\r
eb290d02
FT
79\r
80 NewDevicePathNode = NULL;\r
81 DevicePath = NULL;\r
82 Device = NULL;\r
83\r
84 //\r
85 // Allocate a buffer for Identify Namespace data\r
86 //\r
87 NamespaceData = AllocateZeroPool(sizeof (NVME_ADMIN_NAMESPACE_DATA));\r
88 if(NamespaceData == NULL) {\r
89 return EFI_OUT_OF_RESOURCES;\r
90 }\r
91\r
92 ParentDevicePath = Private->ParentDevicePath;\r
93 //\r
94 // Identify Namespace\r
95 //\r
96 Status = NvmeIdentifyNamespace (\r
97 Private,\r
98 NamespaceId,\r
99 (VOID *)NamespaceData\r
100 );\r
101 if (EFI_ERROR(Status)) {\r
102 goto Exit;\r
103 }\r
104 //\r
105 // Validate Namespace\r
106 //\r
107 if (NamespaceData->Ncap == 0) {\r
108 Status = EFI_DEVICE_ERROR;\r
109 } else {\r
110 //\r
111 // allocate device private data for each discovered namespace\r
112 //\r
113 Device = AllocateZeroPool(sizeof(NVME_DEVICE_PRIVATE_DATA));\r
114 if (Device == NULL) {\r
6a54db85 115 Status = EFI_OUT_OF_RESOURCES;\r
eb290d02
FT
116 goto Exit;\r
117 }\r
118\r
119 //\r
120 // Initialize SSD namespace instance data\r
121 //\r
122 Device->Signature = NVME_DEVICE_PRIVATE_DATA_SIGNATURE;\r
123 Device->NamespaceId = NamespaceId;\r
124 Device->NamespaceUuid = NamespaceData->Eui64;\r
125\r
126 Device->ControllerHandle = Private->ControllerHandle;\r
127 Device->DriverBindingHandle = Private->DriverBindingHandle;\r
128 Device->Controller = Private;\r
129\r
130 //\r
131 // Build BlockIo media structure\r
132 //\r
133 Device->Media.MediaId = 0;\r
134 Device->Media.RemovableMedia = FALSE;\r
135 Device->Media.MediaPresent = TRUE;\r
136 Device->Media.LogicalPartition = FALSE;\r
137 Device->Media.ReadOnly = FALSE;\r
138 Device->Media.WriteCaching = FALSE;\r
139\r
140 Flbas = NamespaceData->Flbas;\r
2f34e065 141 LbaFmtIdx = Flbas & 0xF;\r
eb290d02
FT
142 Lbads = NamespaceData->LbaFormat[LbaFmtIdx].Lbads;\r
143 Device->Media.BlockSize = (UINT32)1 << Lbads;\r
144\r
145 Device->Media.LastBlock = NamespaceData->Nsze - 1;\r
146 Device->Media.LogicalBlocksPerPhysicalBlock = 1;\r
147 Device->Media.LowestAlignedLba = 1;\r
148\r
149 //\r
150 // Create BlockIo Protocol instance\r
151 //\r
152 Device->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2;\r
153 Device->BlockIo.Media = &Device->Media;\r
154 Device->BlockIo.Reset = NvmeBlockIoReset;\r
155 Device->BlockIo.ReadBlocks = NvmeBlockIoReadBlocks;\r
156 Device->BlockIo.WriteBlocks = NvmeBlockIoWriteBlocks;\r
157 Device->BlockIo.FlushBlocks = NvmeBlockIoFlushBlocks;\r
158\r
754b489b
TF
159 //\r
160 // Create StorageSecurityProtocol Instance\r
161 //\r
162 Device->StorageSecurity.ReceiveData = NvmeStorageSecurityReceiveData;\r
163 Device->StorageSecurity.SendData = NvmeStorageSecuritySendData;\r
164\r
eb290d02
FT
165 //\r
166 // Create DiskInfo Protocol instance\r
167 //\r
d2a2678b 168 CopyMem (&Device->NamespaceData, NamespaceData, sizeof (NVME_ADMIN_NAMESPACE_DATA));\r
eb290d02
FT
169 InitializeDiskInfo (Device);\r
170\r
171 //\r
172 // Create a Nvm Express Namespace Device Path Node\r
173 //\r
174 Status = Private->Passthru.BuildDevicePath (\r
175 &Private->Passthru,\r
176 Device->NamespaceId,\r
eb290d02
FT
177 &NewDevicePathNode\r
178 );\r
179\r
180 if (EFI_ERROR(Status)) {\r
181 goto Exit;\r
182 }\r
183\r
184 //\r
185 // Append the SSD node to the controller's device path\r
186 //\r
187 DevicePath = AppendDevicePathNode (ParentDevicePath, NewDevicePathNode);\r
188 if (DevicePath == NULL) {\r
189 Status = EFI_OUT_OF_RESOURCES;\r
190 goto Exit;\r
191 }\r
192\r
193 DeviceHandle = NULL;\r
194 RemainingDevicePath = DevicePath;\r
195 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);\r
196 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {\r
197 Status = EFI_ALREADY_STARTED;\r
198 FreePool (DevicePath);\r
199 goto Exit;\r
200 }\r
201\r
202 Device->DevicePath = DevicePath;\r
203\r
204 //\r
205 // Make sure the handle is NULL so we create a new handle\r
206 //\r
207 Device->DeviceHandle = NULL;\r
208\r
209 Status = gBS->InstallMultipleProtocolInterfaces (\r
210 &Device->DeviceHandle,\r
211 &gEfiDevicePathProtocolGuid,\r
212 Device->DevicePath,\r
213 &gEfiBlockIoProtocolGuid,\r
214 &Device->BlockIo,\r
215 &gEfiDiskInfoProtocolGuid,\r
216 &Device->DiskInfo,\r
217 NULL\r
218 );\r
219\r
220 if(EFI_ERROR(Status)) {\r
221 goto Exit;\r
222 }\r
754b489b
TF
223\r
224 //\r
225 // Check if the NVMe controller supports the Security Send and Security Receive commands\r
226 //\r
227 if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {\r
228 Status = gBS->InstallProtocolInterface (\r
229 &Device->DeviceHandle,\r
230 &gEfiStorageSecurityCommandProtocolGuid,\r
231 EFI_NATIVE_INTERFACE,\r
232 &Device->StorageSecurity\r
233 );\r
234 if(EFI_ERROR(Status)) {\r
235 gBS->UninstallMultipleProtocolInterfaces (\r
236 &Device->DeviceHandle,\r
237 &gEfiDevicePathProtocolGuid,\r
238 Device->DevicePath,\r
239 &gEfiBlockIoProtocolGuid,\r
240 &Device->BlockIo,\r
241 &gEfiDiskInfoProtocolGuid,\r
242 &Device->DiskInfo,\r
243 NULL\r
244 );\r
245 goto Exit;\r
246 }\r
247 }\r
248\r
eb290d02
FT
249 gBS->OpenProtocol (\r
250 Private->ControllerHandle,\r
beeeb22c
TF
251 &gEfiNvmExpressPassThruProtocolGuid,\r
252 (VOID **) &Private->Passthru,\r
eb290d02
FT
253 Private->DriverBindingHandle,\r
254 Device->DeviceHandle,\r
255 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
256 );\r
257\r
7b8883c6
FT
258 //\r
259 // Dump NvmExpress Identify Namespace Data\r
260 //\r
261 DEBUG ((EFI_D_INFO, " == NVME IDENTIFY NAMESPACE [%d] DATA ==\n", NamespaceId));\r
262 DEBUG ((EFI_D_INFO, " NSZE : 0x%x\n", NamespaceData->Nsze));\r
263 DEBUG ((EFI_D_INFO, " NCAP : 0x%x\n", NamespaceData->Ncap));\r
264 DEBUG ((EFI_D_INFO, " NUSE : 0x%x\n", NamespaceData->Nuse));\r
265 DEBUG ((EFI_D_INFO, " LBAF0.LBADS : 0x%x\n", (NamespaceData->LbaFormat[0].Lbads)));\r
266\r
eb290d02
FT
267 //\r
268 // Build controller name for Component Name (2) protocol.\r
269 //\r
da7c7274
FT
270 CopyMem (Sn, Private->ControllerData->Sn, sizeof (Private->ControllerData->Sn));\r
271 Sn[20] = 0;\r
272 CopyMem (Mn, Private->ControllerData->Mn, sizeof (Private->ControllerData->Mn));\r
273 Mn[40] = 0;\r
274 UnicodeSPrintAsciiFormat (Device->ModelName, sizeof (Device->ModelName), "%a-%a-%x", Sn, Mn, NamespaceData->Eui64);\r
eb290d02
FT
275\r
276 AddUnicodeString2 (\r
277 "eng",\r
278 gNvmExpressComponentName.SupportedLanguages,\r
279 &Device->ControllerNameTable,\r
280 Device->ModelName,\r
281 TRUE\r
282 );\r
283\r
284 AddUnicodeString2 (\r
285 "en",\r
286 gNvmExpressComponentName2.SupportedLanguages,\r
287 &Device->ControllerNameTable,\r
288 Device->ModelName,\r
289 FALSE\r
290 );\r
291 }\r
292\r
293Exit:\r
294 if(NamespaceData != NULL) {\r
295 FreePool (NamespaceData);\r
296 }\r
297\r
6a54db85
FT
298 if (NewDevicePathNode != NULL) {\r
299 FreePool (NewDevicePathNode);\r
300 }\r
301\r
eb290d02
FT
302 if(EFI_ERROR(Status) && (Device != NULL) && (Device->DevicePath != NULL)) {\r
303 FreePool (Device->DevicePath);\r
304 }\r
305 if(EFI_ERROR(Status) && (Device != NULL)) {\r
306 FreePool (Device);\r
307 }\r
308 return Status;\r
309}\r
310\r
311/**\r
312 Discover all Nvm Express device namespaces, and create child handles for them with BlockIo\r
313 and DiskInfo protocol instances.\r
314\r
315 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.\r
316\r
317 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.\r
318 @return Others Some error occurs when enumerating the namespaces.\r
319\r
320**/\r
321EFI_STATUS\r
322DiscoverAllNamespaces (\r
323 IN NVME_CONTROLLER_PRIVATE_DATA *Private\r
324 )\r
325{\r
326 EFI_STATUS Status;\r
327 UINT32 NamespaceId;\r
d6c55989 328 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *Passthru;\r
eb290d02
FT
329\r
330 NamespaceId = 0xFFFFFFFF;\r
eb290d02
FT
331 Passthru = &Private->Passthru;\r
332\r
333 while (TRUE) {\r
334 Status = Passthru->GetNextNamespace (\r
335 Passthru,\r
d6c55989 336 (UINT32 *)&NamespaceId\r
eb290d02
FT
337 );\r
338\r
339 if (EFI_ERROR (Status)) {\r
340 break;\r
341 }\r
342\r
343 Status = EnumerateNvmeDevNamespace (\r
344 Private,\r
d6c55989 345 NamespaceId\r
eb290d02
FT
346 );\r
347\r
348 if (EFI_ERROR(Status)) {\r
349 continue;\r
350 }\r
351 }\r
352\r
353 return EFI_SUCCESS;\r
354}\r
355\r
356/**\r
357 Unregisters a Nvm Express device namespace.\r
358\r
359 This function removes the protocols installed on the controller handle and\r
360 frees the resources allocated for the namespace.\r
361\r
362 @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.\r
363 @param Controller The controller handle of the namespace.\r
364 @param Handle The child handle.\r
365\r
366 @retval EFI_SUCCESS The namespace is successfully unregistered.\r
367 @return Others Some error occurs when unregistering the namespace.\r
368\r
369**/\r
370EFI_STATUS\r
371UnregisterNvmeNamespace (\r
372 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
373 IN EFI_HANDLE Controller,\r
374 IN EFI_HANDLE Handle\r
375 )\r
376{\r
377 EFI_STATUS Status;\r
eb290d02
FT
378 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
379 NVME_DEVICE_PRIVATE_DATA *Device;\r
beeeb22c 380 NVME_CONTROLLER_PRIVATE_DATA *Private;\r
754b489b 381 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity;\r
eb290d02
FT
382\r
383 BlockIo = NULL;\r
384\r
385 Status = gBS->OpenProtocol (\r
386 Handle,\r
387 &gEfiBlockIoProtocolGuid,\r
388 (VOID **) &BlockIo,\r
389 This->DriverBindingHandle,\r
390 Controller,\r
391 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
392 );\r
393 if (EFI_ERROR (Status)) {\r
394 return Status;\r
395 }\r
396\r
beeeb22c
TF
397 Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo);\r
398 Private = Device->Controller;\r
eb290d02
FT
399\r
400 //\r
401 // Close the child handle\r
402 //\r
403 gBS->CloseProtocol (\r
404 Controller,\r
beeeb22c 405 &gEfiNvmExpressPassThruProtocolGuid,\r
eb290d02
FT
406 This->DriverBindingHandle,\r
407 Handle\r
408 );\r
409\r
410 //\r
411 // The Nvm Express driver installs the BlockIo and DiskInfo in the DriverBindingStart().\r
412 // Here should uninstall both of them.\r
413 //\r
414 Status = gBS->UninstallMultipleProtocolInterfaces (\r
415 Handle,\r
416 &gEfiDevicePathProtocolGuid,\r
417 Device->DevicePath,\r
418 &gEfiBlockIoProtocolGuid,\r
419 &Device->BlockIo,\r
420 &gEfiDiskInfoProtocolGuid,\r
421 &Device->DiskInfo,\r
422 NULL\r
423 );\r
424\r
425 if (EFI_ERROR (Status)) {\r
426 gBS->OpenProtocol (\r
427 Controller,\r
beeeb22c
TF
428 &gEfiNvmExpressPassThruProtocolGuid,\r
429 (VOID **) &Private->Passthru,\r
eb290d02
FT
430 This->DriverBindingHandle,\r
431 Handle,\r
432 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
433 );\r
434 return Status;\r
435 }\r
436\r
754b489b
TF
437 //\r
438 // If Storage Security Command Protocol is installed, then uninstall this protocol.\r
439 //\r
440 Status = gBS->OpenProtocol (\r
441 Handle,\r
442 &gEfiStorageSecurityCommandProtocolGuid,\r
443 (VOID **) &StorageSecurity,\r
444 This->DriverBindingHandle,\r
445 Controller,\r
446 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
447 );\r
448\r
449 if (!EFI_ERROR (Status)) {\r
450 Status = gBS->UninstallProtocolInterface (\r
451 Handle,\r
452 &gEfiStorageSecurityCommandProtocolGuid,\r
453 &Device->StorageSecurity\r
454 );\r
455 if (EFI_ERROR (Status)) {\r
456 gBS->OpenProtocol (\r
457 Controller,\r
458 &gEfiNvmExpressPassThruProtocolGuid,\r
459 (VOID **) &Private->Passthru,\r
460 This->DriverBindingHandle,\r
461 Handle,\r
462 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
463 );\r
464 return Status;\r
465 }\r
466 }\r
467\r
eb290d02
FT
468 if(Device->DevicePath != NULL) {\r
469 FreePool (Device->DevicePath);\r
470 }\r
471\r
472 if (Device->ControllerNameTable != NULL) {\r
473 FreeUnicodeStringTable (Device->ControllerNameTable);\r
474 }\r
475\r
6a54db85
FT
476 FreePool (Device);\r
477\r
eb290d02
FT
478 return EFI_SUCCESS;\r
479}\r
480\r
481/**\r
482 Tests to see if this driver supports a given controller. If a child device is provided,\r
483 it further tests to see if this driver supports creating a handle for the specified child device.\r
484\r
485 This function checks to see if the driver specified by This supports the device specified by\r
486 ControllerHandle. Drivers will typically use the device path attached to\r
487 ControllerHandle and/or the services from the bus I/O abstraction attached to\r
488 ControllerHandle to determine if the driver supports ControllerHandle. This function\r
489 may be called many times during platform initialization. In order to reduce boot times, the tests\r
490 performed by this function must be very small, and take as little time as possible to execute. This\r
491 function must not change the state of any hardware devices, and this function must be aware that the\r
492 device specified by ControllerHandle may already be managed by the same driver or a\r
493 different driver. This function must match its calls to AllocatePages() with FreePages(),\r
494 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().\r
495 Since ControllerHandle may have been previously started by the same driver, if a protocol is\r
496 already in the opened state, then it must not be closed with CloseProtocol(). This is required\r
497 to guarantee the state of ControllerHandle is not modified by this function.\r
498\r
499 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
500 @param[in] ControllerHandle The handle of the controller to test. This handle\r
501 must support a protocol interface that supplies\r
502 an I/O abstraction to the driver.\r
503 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
504 parameter is ignored by device drivers, and is optional for bus\r
505 drivers. For bus drivers, if this parameter is not NULL, then\r
506 the bus driver must determine if the bus controller specified\r
507 by ControllerHandle and the child controller specified\r
508 by RemainingDevicePath are both supported by this\r
509 bus driver.\r
510\r
511 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
512 RemainingDevicePath is supported by the driver specified by This.\r
513 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
514 RemainingDevicePath is already being managed by the driver\r
515 specified by This.\r
516 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
517 RemainingDevicePath is already being managed by a different\r
518 driver or an application that requires exclusive access.\r
519 Currently not implemented.\r
520 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
521 RemainingDevicePath is not supported by the driver specified by This.\r
522**/\r
523EFI_STATUS\r
524EFIAPI\r
525NvmExpressDriverBindingSupported (\r
526 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
527 IN EFI_HANDLE Controller,\r
528 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
529 )\r
530{\r
531 EFI_STATUS Status;\r
532 EFI_DEV_PATH_PTR DevicePathNode;\r
533 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
534 EFI_PCI_IO_PROTOCOL *PciIo;\r
535 UINT8 ClassCode[3];\r
536\r
537 //\r
538 // Check whether device path is valid\r
539 //\r
540 if (RemainingDevicePath != NULL) {\r
541 //\r
542 // Check if RemainingDevicePath is the End of Device Path Node,\r
543 // if yes, go on checking other conditions\r
544 //\r
545 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
546 //\r
547 // If RemainingDevicePath isn't the End of Device Path Node,\r
548 // check its validation\r
549 //\r
550 DevicePathNode.DevPath = RemainingDevicePath;\r
551\r
552 if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||\r
553 (DevicePathNode.DevPath->SubType != MSG_NVME_NAMESPACE_DP) ||\r
754b489b
TF
554 (DevicePathNodeLength(DevicePathNode.DevPath) != sizeof(NVME_NAMESPACE_DEVICE_PATH))) {\r
555 return EFI_UNSUPPORTED;\r
eb290d02
FT
556 }\r
557 }\r
558 }\r
559\r
560 //\r
561 // Open the EFI Device Path protocol needed to perform the supported test\r
562 //\r
563 Status = gBS->OpenProtocol (\r
564 Controller,\r
565 &gEfiDevicePathProtocolGuid,\r
566 (VOID **) &ParentDevicePath,\r
567 This->DriverBindingHandle,\r
568 Controller,\r
569 EFI_OPEN_PROTOCOL_BY_DRIVER\r
570 );\r
571 if (Status == EFI_ALREADY_STARTED) {\r
572 return EFI_SUCCESS;\r
573 }\r
574\r
575 if (EFI_ERROR (Status)) {\r
576 return Status;\r
577 }\r
578\r
579 //\r
580 // Close protocol, don't use device path protocol in the Support() function\r
581 //\r
582 gBS->CloseProtocol (\r
583 Controller,\r
584 &gEfiDevicePathProtocolGuid,\r
585 This->DriverBindingHandle,\r
586 Controller\r
587 );\r
588\r
589 //\r
590 // Attempt to Open PCI I/O Protocol\r
591 //\r
592 Status = gBS->OpenProtocol (\r
593 Controller,\r
594 &gEfiPciIoProtocolGuid,\r
595 (VOID **) &PciIo,\r
596 This->DriverBindingHandle,\r
597 Controller,\r
598 EFI_OPEN_PROTOCOL_BY_DRIVER\r
599 );\r
600 if (Status == EFI_ALREADY_STARTED) {\r
601 return EFI_SUCCESS;\r
602 }\r
603\r
604 if (EFI_ERROR (Status)) {\r
605 return Status;\r
606 }\r
607\r
608 //\r
609 // Now further check the PCI header: Base class (offset 0x0B) and Sub Class (offset 0x0A).\r
610 // This controller should be a Nvm Express controller.\r
611 //\r
612 Status = PciIo->Pci.Read (\r
613 PciIo,\r
614 EfiPciIoWidthUint8,\r
615 PCI_CLASSCODE_OFFSET,\r
616 sizeof (ClassCode),\r
617 ClassCode\r
618 );\r
619 if (EFI_ERROR (Status)) {\r
620 goto Done;\r
621 }\r
622\r
623 //\r
624 // Examine Nvm Express controller PCI Configuration table fields\r
625 //\r
626 if ((ClassCode[0] != PCI_IF_NVMHCI) || (ClassCode[1] != PCI_CLASS_MASS_STORAGE_NVM) || (ClassCode[2] != PCI_CLASS_MASS_STORAGE)) {\r
627 Status = EFI_UNSUPPORTED;\r
628 }\r
629\r
630Done:\r
631 gBS->CloseProtocol (\r
632 Controller,\r
633 &gEfiPciIoProtocolGuid,\r
634 This->DriverBindingHandle,\r
635 Controller\r
636 );\r
637\r
638 return Status;\r
639}\r
640\r
641\r
642/**\r
643 Starts a device controller or a bus controller.\r
644\r
645 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
646 As a result, much of the error checking on the parameters to Start() has been moved into this\r
647 common boot service. It is legal to call Start() from other locations,\r
648 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
649 1. ControllerHandle must be a valid EFI_HANDLE.\r
650 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
651 EFI_DEVICE_PATH_PROTOCOL.\r
652 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
653 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
654\r
655 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
656 @param[in] ControllerHandle The handle of the controller to start. This handle\r
657 must support a protocol interface that supplies\r
658 an I/O abstraction to the driver.\r
659 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
660 parameter is ignored by device drivers, and is optional for bus\r
661 drivers. For a bus driver, if this parameter is NULL, then handles\r
662 for all the children of Controller are created by this driver.\r
663 If this parameter is not NULL and the first Device Path Node is\r
664 not the End of Device Path Node, then only the handle for the\r
665 child device specified by the first Device Path Node of\r
666 RemainingDevicePath is created by this driver.\r
667 If the first Device Path Node of RemainingDevicePath is\r
668 the End of Device Path Node, no child handle is created by this\r
669 driver.\r
670\r
671 @retval EFI_SUCCESS The device was started.\r
672 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
673 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
674 @retval Others The driver failded to start the device.\r
675\r
676**/\r
677EFI_STATUS\r
678EFIAPI\r
679NvmExpressDriverBindingStart (\r
680 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
681 IN EFI_HANDLE Controller,\r
682 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
683 )\r
684{\r
d6c55989
FT
685 EFI_STATUS Status;\r
686 EFI_PCI_IO_PROTOCOL *PciIo;\r
687 NVME_CONTROLLER_PRIVATE_DATA *Private;\r
688 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
689 UINT32 NamespaceId;\r
690 EFI_PHYSICAL_ADDRESS MappedAddr;\r
691 UINTN Bytes;\r
692 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *Passthru;\r
eb290d02
FT
693\r
694 DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: start\n"));\r
695\r
d6c55989
FT
696 Private = NULL;\r
697 Passthru = NULL;\r
eb290d02
FT
698 ParentDevicePath = NULL;\r
699\r
700 Status = gBS->OpenProtocol (\r
701 Controller,\r
702 &gEfiDevicePathProtocolGuid,\r
703 (VOID **) &ParentDevicePath,\r
704 This->DriverBindingHandle,\r
705 Controller,\r
706 EFI_OPEN_PROTOCOL_BY_DRIVER\r
707 );\r
708 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
709 return Status;\r
710 }\r
711\r
712 Status = gBS->OpenProtocol (\r
713 Controller,\r
714 &gEfiPciIoProtocolGuid,\r
715 (VOID **) &PciIo,\r
716 This->DriverBindingHandle,\r
717 Controller,\r
718 EFI_OPEN_PROTOCOL_BY_DRIVER\r
719 );\r
720\r
721 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
722 return Status;\r
723 }\r
724\r
725 //\r
726 // Check EFI_ALREADY_STARTED to reuse the original NVME_CONTROLLER_PRIVATE_DATA.\r
727 //\r
728 if (Status != EFI_ALREADY_STARTED) {\r
729 Private = AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA));\r
730\r
731 if (Private == NULL) {\r
732 DEBUG ((EFI_D_ERROR, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n"));\r
733 Status = EFI_OUT_OF_RESOURCES;\r
d6c55989 734 goto Exit;\r
eb290d02
FT
735 }\r
736\r
737 //\r
738 // 4 x 4kB aligned buffers will be carved out of this buffer.\r
739 // 1st 4kB boundary is the start of the admin submission queue.\r
740 // 2nd 4kB boundary is the start of the admin completion queue.\r
741 // 3rd 4kB boundary is the start of I/O submission queue #1.\r
742 // 4th 4kB boundary is the start of I/O completion queue #1.\r
743 //\r
744 // Allocate 4 pages of memory, then map it for bus master read and write.\r
745 //\r
746 Status = PciIo->AllocateBuffer (\r
747 PciIo,\r
748 AllocateAnyPages,\r
749 EfiBootServicesData,\r
7b8883c6 750 4,\r
eb290d02
FT
751 (VOID**)&Private->Buffer,\r
752 0\r
753 );\r
754 if (EFI_ERROR (Status)) {\r
d6c55989 755 goto Exit;\r
eb290d02
FT
756 }\r
757\r
758 Bytes = EFI_PAGES_TO_SIZE (4);\r
759 Status = PciIo->Map (\r
760 PciIo,\r
761 EfiPciIoOperationBusMasterCommonBuffer,\r
762 Private->Buffer,\r
763 &Bytes,\r
764 &MappedAddr,\r
765 &Private->Mapping\r
766 );\r
767\r
768 if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (4))) {\r
d6c55989 769 goto Exit;\r
eb290d02
FT
770 }\r
771\r
772 Private->BufferPciAddr = (UINT8 *)(UINTN)MappedAddr;\r
eb290d02
FT
773\r
774 Private->Signature = NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE;\r
775 Private->ControllerHandle = Controller;\r
776 Private->ImageHandle = This->DriverBindingHandle;\r
777 Private->DriverBindingHandle = This->DriverBindingHandle;\r
778 Private->PciIo = PciIo;\r
779 Private->ParentDevicePath = ParentDevicePath;\r
780 Private->Passthru.Mode = &Private->PassThruMode;\r
781 Private->Passthru.PassThru = NvmExpressPassThru;\r
782 Private->Passthru.GetNextNamespace = NvmExpressGetNextNamespace;\r
783 Private->Passthru.BuildDevicePath = NvmExpressBuildDevicePath;\r
784 Private->Passthru.GetNamespace = NvmExpressGetNamespace;\r
d6c55989 785 CopyMem (&Private->PassThruMode, &gEfiNvmExpressPassThruMode, sizeof (EFI_NVM_EXPRESS_PASS_THRU_MODE));\r
eb290d02
FT
786\r
787 Status = NvmeControllerInit (Private);\r
eb290d02 788 if (EFI_ERROR(Status)) {\r
d6c55989 789 goto Exit;\r
eb290d02
FT
790 }\r
791\r
792 Status = gBS->InstallMultipleProtocolInterfaces (\r
793 &Controller,\r
d6c55989
FT
794 &gEfiNvmExpressPassThruProtocolGuid,\r
795 &Private->Passthru,\r
eb290d02
FT
796 NULL\r
797 );\r
798 if (EFI_ERROR (Status)) {\r
d6c55989 799 goto Exit;\r
eb290d02
FT
800 }\r
801 } else {\r
802 Status = gBS->OpenProtocol (\r
803 Controller,\r
d6c55989
FT
804 &gEfiNvmExpressPassThruProtocolGuid,\r
805 (VOID **) &Passthru,\r
eb290d02
FT
806 This->DriverBindingHandle,\r
807 Controller,\r
808 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
809 );\r
810 if (EFI_ERROR (Status)) {\r
d6c55989 811 goto Exit;\r
eb290d02 812 }\r
d6c55989
FT
813\r
814 Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (Passthru);\r
eb290d02
FT
815 }\r
816\r
817 if (RemainingDevicePath == NULL) {\r
818 //\r
819 // Enumerate all NVME namespaces in the controller\r
820 //\r
821 Status = DiscoverAllNamespaces (\r
822 Private\r
823 );\r
824\r
825 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
826 //\r
827 // Enumerate the specified NVME namespace\r
828 //\r
829 Status = Private->Passthru.GetNamespace (\r
830 &Private->Passthru,\r
831 RemainingDevicePath,\r
d6c55989 832 &NamespaceId\r
eb290d02
FT
833 );\r
834\r
835 if (!EFI_ERROR (Status)) {\r
d6c55989
FT
836 Status = EnumerateNvmeDevNamespace (\r
837 Private,\r
838 NamespaceId\r
839 );\r
eb290d02
FT
840 }\r
841 }\r
842\r
843 DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: end successfully\n"));\r
844 return EFI_SUCCESS;\r
845\r
d6c55989 846Exit:\r
eb290d02
FT
847 if ((Private != NULL) && (Private->Mapping != NULL)) {\r
848 PciIo->Unmap (PciIo, Private->Mapping);\r
849 }\r
850\r
851 if ((Private != NULL) && (Private->Buffer != NULL)) {\r
852 PciIo->FreeBuffer (PciIo, 4, Private->Buffer);\r
853 }\r
854\r
ac231001
TF
855 if ((Private != NULL) && (Private->ControllerData != NULL)) {\r
856 FreePool (Private->ControllerData);\r
857 }\r
858\r
eb290d02
FT
859 if (Private != NULL) {\r
860 FreePool (Private);\r
861 }\r
862\r
863 gBS->CloseProtocol (\r
864 Controller,\r
865 &gEfiPciIoProtocolGuid,\r
866 This->DriverBindingHandle,\r
867 Controller\r
868 );\r
869\r
870 gBS->CloseProtocol (\r
871 Controller,\r
872 &gEfiDevicePathProtocolGuid,\r
873 This->DriverBindingHandle,\r
874 Controller\r
875 );\r
876\r
877 DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: end with %r\n", Status));\r
878\r
879 return Status;\r
880}\r
881\r
882\r
883/**\r
884 Stops a device controller or a bus controller.\r
885\r
886 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().\r
887 As a result, much of the error checking on the parameters to Stop() has been moved\r
888 into this common boot service. It is legal to call Stop() from other locations,\r
889 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
890 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
891 same driver's Start() function.\r
892 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
893 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
894 Start() function, and the Start() function must have called OpenProtocol() on\r
895 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
896\r
897 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
898 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
899 support a bus specific I/O protocol for the driver\r
900 to use to stop the device.\r
901 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
902 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
903 if NumberOfChildren is 0.\r
904\r
905 @retval EFI_SUCCESS The device was stopped.\r
906 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
907\r
908**/\r
909EFI_STATUS\r
910EFIAPI\r
911NvmExpressDriverBindingStop (\r
912 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
913 IN EFI_HANDLE Controller,\r
914 IN UINTN NumberOfChildren,\r
915 IN EFI_HANDLE *ChildHandleBuffer\r
916 )\r
917{\r
918 EFI_STATUS Status;\r
919 BOOLEAN AllChildrenStopped;\r
920 UINTN Index;\r
921 NVME_CONTROLLER_PRIVATE_DATA *Private;\r
beeeb22c 922 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *PassThru;\r
eb290d02
FT
923\r
924 if (NumberOfChildren == 0) {\r
925 Status = gBS->OpenProtocol (\r
926 Controller,\r
beeeb22c
TF
927 &gEfiNvmExpressPassThruProtocolGuid,\r
928 (VOID **) &PassThru,\r
eb290d02
FT
929 This->DriverBindingHandle,\r
930 Controller,\r
931 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
932 );\r
933\r
934 if (!EFI_ERROR (Status)) {\r
beeeb22c 935 Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (PassThru);\r
eb290d02
FT
936 gBS->UninstallMultipleProtocolInterfaces (\r
937 Controller,\r
beeeb22c
TF
938 &gEfiNvmExpressPassThruProtocolGuid,\r
939 PassThru,\r
eb290d02
FT
940 NULL\r
941 );\r
942\r
943 if (Private->Mapping != NULL) {\r
944 Private->PciIo->Unmap (Private->PciIo, Private->Mapping);\r
945 }\r
946\r
947 if (Private->Buffer != NULL) {\r
948 Private->PciIo->FreeBuffer (Private->PciIo, 4, Private->Buffer);\r
949 }\r
950\r
951 FreePool (Private->ControllerData);\r
952 FreePool (Private);\r
953 }\r
954\r
955 gBS->CloseProtocol (\r
956 Controller,\r
957 &gEfiPciIoProtocolGuid,\r
958 This->DriverBindingHandle,\r
959 Controller\r
960 );\r
961 gBS->CloseProtocol (\r
962 Controller,\r
963 &gEfiDevicePathProtocolGuid,\r
964 This->DriverBindingHandle,\r
965 Controller\r
966 );\r
967 return EFI_SUCCESS;\r
968 }\r
969\r
970 AllChildrenStopped = TRUE;\r
971\r
972 for (Index = 0; Index < NumberOfChildren; Index++) {\r
973 Status = UnregisterNvmeNamespace (This, Controller, ChildHandleBuffer[Index]);\r
974 if (EFI_ERROR (Status)) {\r
975 AllChildrenStopped = FALSE;\r
976 }\r
977 }\r
978\r
979 if (!AllChildrenStopped) {\r
980 return EFI_DEVICE_ERROR;\r
981 }\r
982\r
983 return EFI_SUCCESS;\r
984}\r
985\r
986/**\r
987 This is the unload handle for the NVM Express driver.\r
988\r
989 Disconnect the driver specified by ImageHandle from the NVMe device in the handle database.\r
990 Uninstall all the protocols installed in the driver.\r
991\r
992 @param[in] ImageHandle The drivers' driver image.\r
993\r
994 @retval EFI_SUCCESS The image is unloaded.\r
995 @retval Others Failed to unload the image.\r
996\r
997**/\r
998EFI_STATUS\r
999EFIAPI\r
1000NvmExpressUnload (\r
1001 IN EFI_HANDLE ImageHandle\r
1002 )\r
1003{\r
1004 EFI_STATUS Status;\r
1005 EFI_HANDLE *DeviceHandleBuffer;\r
1006 UINTN DeviceHandleCount;\r
1007 UINTN Index;\r
eb290d02
FT
1008 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;\r
1009 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;\r
1010\r
1011 //\r
0a2326af
FT
1012 // Get the list of the device handles managed by this driver.\r
1013 // If there is an error getting the list, then means the driver\r
1014 // doesn't manage any device. At this way, we would only close\r
1015 // those protocols installed at image handle.\r
eb290d02 1016 //\r
0a2326af 1017 DeviceHandleBuffer = NULL;\r
eb290d02 1018 Status = gBS->LocateHandleBuffer (\r
0a2326af 1019 ByProtocol,\r
beeeb22c 1020 &gEfiNvmExpressPassThruProtocolGuid,\r
eb290d02
FT
1021 NULL,\r
1022 &DeviceHandleCount,\r
1023 &DeviceHandleBuffer\r
1024 );\r
1025\r
0a2326af
FT
1026 if (!EFI_ERROR (Status)) {\r
1027 //\r
1028 // Disconnect the driver specified by ImageHandle from all\r
1029 // the devices in the handle database.\r
1030 //\r
1031 for (Index = 0; Index < DeviceHandleCount; Index++) {\r
1032 Status = gBS->DisconnectController (\r
1033 DeviceHandleBuffer[Index],\r
1034 ImageHandle,\r
1035 NULL\r
1036 );\r
1037 if (EFI_ERROR (Status)) {\r
1038 goto EXIT;\r
1039 }\r
1040 }\r
eb290d02
FT
1041 }\r
1042\r
1043 //\r
0a2326af 1044 // Uninstall all the protocols installed in the driver entry point\r
eb290d02 1045 //\r
0a2326af
FT
1046 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1047 ImageHandle,\r
1048 &gEfiDriverBindingProtocolGuid,\r
1049 &gNvmExpressDriverBinding,\r
1050 &gEfiDriverSupportedEfiVersionProtocolGuid,\r
1051 &gNvmExpressDriverSupportedEfiVersion,\r
1052 NULL\r
1053 );\r
1054\r
1055 if (EFI_ERROR (Status)) {\r
1056 goto EXIT;\r
eb290d02
FT
1057 }\r
1058\r
1059 //\r
0a2326af
FT
1060 // Note we have to one by one uninstall the following protocols.\r
1061 // It's because some of them are optionally installed based on\r
1062 // the following PCD settings.\r
1063 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable\r
1064 // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable\r
1065 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable\r
1066 // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable\r
eb290d02 1067 //\r
0a2326af
FT
1068 Status = gBS->HandleProtocol (\r
1069 ImageHandle,\r
1070 &gEfiComponentNameProtocolGuid,\r
1071 (VOID **) &ComponentName\r
1072 );\r
1073 if (!EFI_ERROR (Status)) {\r
eb290d02
FT
1074 gBS->UninstallProtocolInterface (\r
1075 ImageHandle,\r
0a2326af
FT
1076 &gEfiComponentNameProtocolGuid,\r
1077 ComponentName\r
eb290d02 1078 );\r
0a2326af 1079 }\r
eb290d02 1080\r
0a2326af
FT
1081 Status = gBS->HandleProtocol (\r
1082 ImageHandle,\r
1083 &gEfiComponentName2ProtocolGuid,\r
1084 (VOID **) &ComponentName2\r
1085 );\r
1086 if (!EFI_ERROR (Status)) {\r
1087 gBS->UninstallProtocolInterface (\r
1088 ImageHandle,\r
1089 &gEfiComponentName2ProtocolGuid,\r
1090 ComponentName2\r
1091 );\r
eb290d02
FT
1092 }\r
1093\r
0a2326af
FT
1094 Status = EFI_SUCCESS;\r
1095\r
1096EXIT:\r
eb290d02
FT
1097 //\r
1098 // Free the buffer containing the list of handles from the handle database\r
1099 //\r
1100 if (DeviceHandleBuffer != NULL) {\r
1101 gBS->FreePool (DeviceHandleBuffer);\r
1102 }\r
0a2326af 1103 return Status;\r
eb290d02
FT
1104}\r
1105\r
1106/**\r
1107 The entry point for Nvm Express driver, used to install Nvm Express driver on the ImageHandle.\r
1108\r
1109 @param ImageHandle The firmware allocated handle for this driver image.\r
1110 @param SystemTable Pointer to the EFI system table.\r
1111\r
1112 @retval EFI_SUCCESS Driver loaded.\r
1113 @retval other Driver not loaded.\r
1114\r
1115**/\r
1116EFI_STATUS\r
1117EFIAPI\r
1118NvmExpressDriverEntry (\r
1119 IN EFI_HANDLE ImageHandle,\r
1120 IN EFI_SYSTEM_TABLE *SystemTable\r
1121 )\r
1122{\r
1123 EFI_STATUS Status;\r
1124\r
1125 Status = EfiLibInstallDriverBindingComponentName2 (\r
1126 ImageHandle,\r
1127 SystemTable,\r
1128 &gNvmExpressDriverBinding,\r
1129 ImageHandle,\r
1130 &gNvmExpressComponentName,\r
1131 &gNvmExpressComponentName2\r
1132 );\r
1133 ASSERT_EFI_ERROR (Status);\r
1134\r
1135 //\r
1136 // Install EFI Driver Supported EFI Version Protocol required for\r
1137 // EFI drivers that are on PCI and other plug in cards.\r
1138 //\r
1139 gNvmExpressDriverSupportedEfiVersion.FirmwareVersion = 0x00020028;\r
1140 Status = gBS->InstallMultipleProtocolInterfaces (\r
1141 &ImageHandle,\r
1142 &gEfiDriverSupportedEfiVersionProtocolGuid,\r
1143 &gNvmExpressDriverSupportedEfiVersion,\r
1144 NULL\r
1145 );\r
1146 ASSERT_EFI_ERROR (Status);\r
1147 return Status;\r
1148}\r