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