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