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