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 | 43 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL | 44 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_NONBLOCKIO | 45 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM, 46 sizeof (UINTN), 47 0x10100 48 }; 49 50 /** 51 Check if the specified Nvm Express device namespace is active, and create child handles 52 for them with BlockIo and DiskInfo protocol instances. 53 54 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. 55 @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be 56 allocated and built. Caller must set the NamespaceId to zero if the 57 device path node will contain a valid UUID. 58 59 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated. 60 @return Others Some error occurs when enumerating the namespaces. 61 62 **/ 63 EFI_STATUS 64 EnumerateNvmeDevNamespace ( 65 IN NVME_CONTROLLER_PRIVATE_DATA *Private, 66 UINT32 NamespaceId 67 ) 68 { 69 NVME_ADMIN_NAMESPACE_DATA *NamespaceData; 70 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode; 71 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 72 EFI_HANDLE DeviceHandle; 73 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 74 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; 75 NVME_DEVICE_PRIVATE_DATA *Device; 76 EFI_STATUS Status; 77 UINT32 Lbads; 78 UINT32 Flbas; 79 UINT32 LbaFmtIdx; 80 UINT8 Sn[21]; 81 UINT8 Mn[41]; 82 VOID *DummyInterface; 83 84 NewDevicePathNode = NULL; 85 DevicePath = NULL; 86 Device = NULL; 87 88 // 89 // Allocate a buffer for Identify Namespace data 90 // 91 NamespaceData = AllocateZeroPool(sizeof (NVME_ADMIN_NAMESPACE_DATA)); 92 if(NamespaceData == NULL) { 93 return EFI_OUT_OF_RESOURCES; 94 } 95 96 ParentDevicePath = Private->ParentDevicePath; 97 // 98 // Identify Namespace 99 // 100 Status = NvmeIdentifyNamespace ( 101 Private, 102 NamespaceId, 103 (VOID *)NamespaceData 104 ); 105 if (EFI_ERROR(Status)) { 106 goto Exit; 107 } 108 // 109 // Validate Namespace 110 // 111 if (NamespaceData->Ncap == 0) { 112 Status = EFI_DEVICE_ERROR; 113 } else { 114 // 115 // allocate device private data for each discovered namespace 116 // 117 Device = AllocateZeroPool(sizeof(NVME_DEVICE_PRIVATE_DATA)); 118 if (Device == NULL) { 119 Status = EFI_OUT_OF_RESOURCES; 120 goto Exit; 121 } 122 123 // 124 // Initialize SSD namespace instance data 125 // 126 Device->Signature = NVME_DEVICE_PRIVATE_DATA_SIGNATURE; 127 Device->NamespaceId = NamespaceId; 128 Device->NamespaceUuid = NamespaceData->Eui64; 129 130 Device->ControllerHandle = Private->ControllerHandle; 131 Device->DriverBindingHandle = Private->DriverBindingHandle; 132 Device->Controller = Private; 133 134 // 135 // Build BlockIo media structure 136 // 137 Device->Media.MediaId = 0; 138 Device->Media.RemovableMedia = FALSE; 139 Device->Media.MediaPresent = TRUE; 140 Device->Media.LogicalPartition = FALSE; 141 Device->Media.ReadOnly = FALSE; 142 Device->Media.WriteCaching = FALSE; 143 Device->Media.IoAlign = Private->PassThruMode.IoAlign; 144 145 Flbas = NamespaceData->Flbas; 146 LbaFmtIdx = Flbas & 0xF; 147 Lbads = NamespaceData->LbaFormat[LbaFmtIdx].Lbads; 148 Device->Media.BlockSize = (UINT32)1 << Lbads; 149 150 Device->Media.LastBlock = NamespaceData->Nsze - 1; 151 Device->Media.LogicalBlocksPerPhysicalBlock = 1; 152 Device->Media.LowestAlignedLba = 1; 153 154 // 155 // Create BlockIo Protocol instance 156 // 157 Device->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2; 158 Device->BlockIo.Media = &Device->Media; 159 Device->BlockIo.Reset = NvmeBlockIoReset; 160 Device->BlockIo.ReadBlocks = NvmeBlockIoReadBlocks; 161 Device->BlockIo.WriteBlocks = NvmeBlockIoWriteBlocks; 162 Device->BlockIo.FlushBlocks = NvmeBlockIoFlushBlocks; 163 164 // 165 // Create BlockIo2 Protocol instance 166 // 167 Device->BlockIo2.Media = &Device->Media; 168 Device->BlockIo2.Reset = NvmeBlockIoResetEx; 169 Device->BlockIo2.ReadBlocksEx = NvmeBlockIoReadBlocksEx; 170 Device->BlockIo2.WriteBlocksEx = NvmeBlockIoWriteBlocksEx; 171 Device->BlockIo2.FlushBlocksEx = NvmeBlockIoFlushBlocksEx; 172 InitializeListHead (&Device->AsyncQueue); 173 174 // 175 // Create StorageSecurityProtocol Instance 176 // 177 Device->StorageSecurity.ReceiveData = NvmeStorageSecurityReceiveData; 178 Device->StorageSecurity.SendData = NvmeStorageSecuritySendData; 179 180 // 181 // Create DiskInfo Protocol instance 182 // 183 CopyMem (&Device->NamespaceData, NamespaceData, sizeof (NVME_ADMIN_NAMESPACE_DATA)); 184 InitializeDiskInfo (Device); 185 186 // 187 // Create a Nvm Express Namespace Device Path Node 188 // 189 Status = Private->Passthru.BuildDevicePath ( 190 &Private->Passthru, 191 Device->NamespaceId, 192 &NewDevicePathNode 193 ); 194 195 if (EFI_ERROR(Status)) { 196 goto Exit; 197 } 198 199 // 200 // Append the SSD node to the controller's device path 201 // 202 DevicePath = AppendDevicePathNode (ParentDevicePath, NewDevicePathNode); 203 if (DevicePath == NULL) { 204 Status = EFI_OUT_OF_RESOURCES; 205 goto Exit; 206 } 207 208 DeviceHandle = NULL; 209 RemainingDevicePath = DevicePath; 210 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle); 211 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) { 212 Status = EFI_ALREADY_STARTED; 213 FreePool (DevicePath); 214 goto Exit; 215 } 216 217 Device->DevicePath = DevicePath; 218 219 // 220 // Make sure the handle is NULL so we create a new handle 221 // 222 Device->DeviceHandle = NULL; 223 224 Status = gBS->InstallMultipleProtocolInterfaces ( 225 &Device->DeviceHandle, 226 &gEfiDevicePathProtocolGuid, 227 Device->DevicePath, 228 &gEfiBlockIoProtocolGuid, 229 &Device->BlockIo, 230 &gEfiBlockIo2ProtocolGuid, 231 &Device->BlockIo2, 232 &gEfiDiskInfoProtocolGuid, 233 &Device->DiskInfo, 234 NULL 235 ); 236 237 if(EFI_ERROR(Status)) { 238 goto Exit; 239 } 240 241 // 242 // Check if the NVMe controller supports the Security Send and Security Receive commands 243 // 244 if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) { 245 Status = gBS->InstallProtocolInterface ( 246 &Device->DeviceHandle, 247 &gEfiStorageSecurityCommandProtocolGuid, 248 EFI_NATIVE_INTERFACE, 249 &Device->StorageSecurity 250 ); 251 if(EFI_ERROR(Status)) { 252 gBS->UninstallMultipleProtocolInterfaces ( 253 &Device->DeviceHandle, 254 &gEfiDevicePathProtocolGuid, 255 Device->DevicePath, 256 &gEfiBlockIoProtocolGuid, 257 &Device->BlockIo, 258 &gEfiBlockIo2ProtocolGuid, 259 &Device->BlockIo2, 260 &gEfiDiskInfoProtocolGuid, 261 &Device->DiskInfo, 262 NULL 263 ); 264 goto Exit; 265 } 266 } 267 268 gBS->OpenProtocol ( 269 Private->ControllerHandle, 270 &gEfiNvmExpressPassThruProtocolGuid, 271 (VOID **) &DummyInterface, 272 Private->DriverBindingHandle, 273 Device->DeviceHandle, 274 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 275 ); 276 277 // 278 // Dump NvmExpress Identify Namespace Data 279 // 280 DEBUG ((EFI_D_INFO, " == NVME IDENTIFY NAMESPACE [%d] DATA ==\n", NamespaceId)); 281 DEBUG ((EFI_D_INFO, " NSZE : 0x%x\n", NamespaceData->Nsze)); 282 DEBUG ((EFI_D_INFO, " NCAP : 0x%x\n", NamespaceData->Ncap)); 283 DEBUG ((EFI_D_INFO, " NUSE : 0x%x\n", NamespaceData->Nuse)); 284 DEBUG ((EFI_D_INFO, " LBAF0.LBADS : 0x%x\n", (NamespaceData->LbaFormat[0].Lbads))); 285 286 // 287 // Build controller name for Component Name (2) protocol. 288 // 289 CopyMem (Sn, Private->ControllerData->Sn, sizeof (Private->ControllerData->Sn)); 290 Sn[20] = 0; 291 CopyMem (Mn, Private->ControllerData->Mn, sizeof (Private->ControllerData->Mn)); 292 Mn[40] = 0; 293 UnicodeSPrintAsciiFormat (Device->ModelName, sizeof (Device->ModelName), "%a-%a-%x", Sn, Mn, NamespaceData->Eui64); 294 295 AddUnicodeString2 ( 296 "eng", 297 gNvmExpressComponentName.SupportedLanguages, 298 &Device->ControllerNameTable, 299 Device->ModelName, 300 TRUE 301 ); 302 303 AddUnicodeString2 ( 304 "en", 305 gNvmExpressComponentName2.SupportedLanguages, 306 &Device->ControllerNameTable, 307 Device->ModelName, 308 FALSE 309 ); 310 } 311 312 Exit: 313 if(NamespaceData != NULL) { 314 FreePool (NamespaceData); 315 } 316 317 if (NewDevicePathNode != NULL) { 318 FreePool (NewDevicePathNode); 319 } 320 321 if(EFI_ERROR(Status) && (Device != NULL) && (Device->DevicePath != NULL)) { 322 FreePool (Device->DevicePath); 323 } 324 if(EFI_ERROR(Status) && (Device != NULL)) { 325 FreePool (Device); 326 } 327 return Status; 328 } 329 330 /** 331 Discover all Nvm Express device namespaces, and create child handles for them with BlockIo 332 and DiskInfo protocol instances. 333 334 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. 335 336 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated. 337 @return Others Some error occurs when enumerating the namespaces. 338 339 **/ 340 EFI_STATUS 341 DiscoverAllNamespaces ( 342 IN NVME_CONTROLLER_PRIVATE_DATA *Private 343 ) 344 { 345 EFI_STATUS Status; 346 UINT32 NamespaceId; 347 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *Passthru; 348 349 NamespaceId = 0xFFFFFFFF; 350 Passthru = &Private->Passthru; 351 352 while (TRUE) { 353 Status = Passthru->GetNextNamespace ( 354 Passthru, 355 (UINT32 *)&NamespaceId 356 ); 357 358 if (EFI_ERROR (Status)) { 359 break; 360 } 361 362 Status = EnumerateNvmeDevNamespace ( 363 Private, 364 NamespaceId 365 ); 366 367 if (EFI_ERROR(Status)) { 368 continue; 369 } 370 } 371 372 return EFI_SUCCESS; 373 } 374 375 /** 376 Unregisters a Nvm Express device namespace. 377 378 This function removes the protocols installed on the controller handle and 379 frees the resources allocated for the namespace. 380 381 @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance. 382 @param Controller The controller handle of the namespace. 383 @param Handle The child handle. 384 385 @retval EFI_SUCCESS The namespace is successfully unregistered. 386 @return Others Some error occurs when unregistering the namespace. 387 388 **/ 389 EFI_STATUS 390 UnregisterNvmeNamespace ( 391 IN EFI_DRIVER_BINDING_PROTOCOL *This, 392 IN EFI_HANDLE Controller, 393 IN EFI_HANDLE Handle 394 ) 395 { 396 EFI_STATUS Status; 397 EFI_BLOCK_IO_PROTOCOL *BlockIo; 398 NVME_DEVICE_PRIVATE_DATA *Device; 399 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity; 400 BOOLEAN IsEmpty; 401 EFI_TPL OldTpl; 402 VOID *DummyInterface; 403 404 BlockIo = NULL; 405 406 Status = gBS->OpenProtocol ( 407 Handle, 408 &gEfiBlockIoProtocolGuid, 409 (VOID **) &BlockIo, 410 This->DriverBindingHandle, 411 Controller, 412 EFI_OPEN_PROTOCOL_GET_PROTOCOL 413 ); 414 if (EFI_ERROR (Status)) { 415 return Status; 416 } 417 418 Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo); 419 420 // 421 // Wait for the device's asynchronous I/O queue to become empty. 422 // 423 while (TRUE) { 424 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 425 IsEmpty = IsListEmpty (&Device->AsyncQueue); 426 gBS->RestoreTPL (OldTpl); 427 428 if (IsEmpty) { 429 break; 430 } 431 432 gBS->Stall (100); 433 } 434 435 // 436 // Close the child handle 437 // 438 gBS->CloseProtocol ( 439 Controller, 440 &gEfiNvmExpressPassThruProtocolGuid, 441 This->DriverBindingHandle, 442 Handle 443 ); 444 445 // 446 // The Nvm Express driver installs the BlockIo and DiskInfo in the DriverBindingStart(). 447 // Here should uninstall both of them. 448 // 449 Status = gBS->UninstallMultipleProtocolInterfaces ( 450 Handle, 451 &gEfiDevicePathProtocolGuid, 452 Device->DevicePath, 453 &gEfiBlockIoProtocolGuid, 454 &Device->BlockIo, 455 &gEfiBlockIo2ProtocolGuid, 456 &Device->BlockIo2, 457 &gEfiDiskInfoProtocolGuid, 458 &Device->DiskInfo, 459 NULL 460 ); 461 462 if (EFI_ERROR (Status)) { 463 gBS->OpenProtocol ( 464 Controller, 465 &gEfiNvmExpressPassThruProtocolGuid, 466 (VOID **) &DummyInterface, 467 This->DriverBindingHandle, 468 Handle, 469 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 470 ); 471 return Status; 472 } 473 474 // 475 // If Storage Security Command Protocol is installed, then uninstall this protocol. 476 // 477 Status = gBS->OpenProtocol ( 478 Handle, 479 &gEfiStorageSecurityCommandProtocolGuid, 480 (VOID **) &StorageSecurity, 481 This->DriverBindingHandle, 482 Controller, 483 EFI_OPEN_PROTOCOL_GET_PROTOCOL 484 ); 485 486 if (!EFI_ERROR (Status)) { 487 Status = gBS->UninstallProtocolInterface ( 488 Handle, 489 &gEfiStorageSecurityCommandProtocolGuid, 490 &Device->StorageSecurity 491 ); 492 if (EFI_ERROR (Status)) { 493 gBS->OpenProtocol ( 494 Controller, 495 &gEfiNvmExpressPassThruProtocolGuid, 496 (VOID **) &DummyInterface, 497 This->DriverBindingHandle, 498 Handle, 499 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 500 ); 501 return Status; 502 } 503 } 504 505 if(Device->DevicePath != NULL) { 506 FreePool (Device->DevicePath); 507 } 508 509 if (Device->ControllerNameTable != NULL) { 510 FreeUnicodeStringTable (Device->ControllerNameTable); 511 } 512 513 FreePool (Device); 514 515 return EFI_SUCCESS; 516 } 517 518 /** 519 Call back function when the timer event is signaled. 520 521 @param[in] Event The Event this notify function registered to. 522 @param[in] Context Pointer to the context data registered to the 523 Event. 524 525 **/ 526 VOID 527 EFIAPI 528 ProcessAsyncTaskList ( 529 IN EFI_EVENT Event, 530 IN VOID* Context 531 ) 532 { 533 NVME_CONTROLLER_PRIVATE_DATA *Private; 534 EFI_PCI_IO_PROTOCOL *PciIo; 535 NVME_CQ *Cq; 536 UINT16 QueueId; 537 UINT32 Data; 538 LIST_ENTRY *Link; 539 LIST_ENTRY *NextLink; 540 NVME_PASS_THRU_ASYNC_REQ *AsyncRequest; 541 NVME_BLKIO2_SUBTASK *Subtask; 542 NVME_BLKIO2_REQUEST *BlkIo2Request; 543 EFI_BLOCK_IO2_TOKEN *Token; 544 BOOLEAN HasNewItem; 545 EFI_STATUS Status; 546 547 Private = (NVME_CONTROLLER_PRIVATE_DATA*)Context; 548 QueueId = 2; 549 Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh; 550 HasNewItem = FALSE; 551 552 // 553 // Submit asynchronous subtasks to the NVMe Submission Queue 554 // 555 for (Link = GetFirstNode (&Private->UnsubmittedSubtasks); 556 !IsNull (&Private->UnsubmittedSubtasks, Link); 557 Link = NextLink) { 558 NextLink = GetNextNode (&Private->UnsubmittedSubtasks, Link); 559 Subtask = NVME_BLKIO2_SUBTASK_FROM_LINK (Link); 560 BlkIo2Request = Subtask->BlockIo2Request; 561 Token = BlkIo2Request->Token; 562 RemoveEntryList (Link); 563 BlkIo2Request->UnsubmittedSubtaskNum--; 564 565 // 566 // If any previous subtask fails, do not process subsequent ones. 567 // 568 if (Token->TransactionStatus != EFI_SUCCESS) { 569 if (IsListEmpty (&BlkIo2Request->SubtasksQueue) && 570 BlkIo2Request->LastSubtaskSubmitted && 571 (BlkIo2Request->UnsubmittedSubtaskNum == 0)) { 572 // 573 // Remove the BlockIo2 request from the device asynchronous queue. 574 // 575 RemoveEntryList (&BlkIo2Request->Link); 576 FreePool (BlkIo2Request); 577 gBS->SignalEvent (Token->Event); 578 } 579 580 FreePool (Subtask->CommandPacket->NvmeCmd); 581 FreePool (Subtask->CommandPacket->NvmeCompletion); 582 FreePool (Subtask->CommandPacket); 583 FreePool (Subtask); 584 585 continue; 586 } 587 588 Status = Private->Passthru.PassThru ( 589 &Private->Passthru, 590 Subtask->NamespaceId, 591 Subtask->CommandPacket, 592 Subtask->Event 593 ); 594 if (Status == EFI_NOT_READY) { 595 InsertHeadList (&Private->UnsubmittedSubtasks, Link); 596 BlkIo2Request->UnsubmittedSubtaskNum++; 597 break; 598 } else if (EFI_ERROR (Status)) { 599 Token->TransactionStatus = EFI_DEVICE_ERROR; 600 601 if (IsListEmpty (&BlkIo2Request->SubtasksQueue) && 602 Subtask->IsLast) { 603 // 604 // Remove the BlockIo2 request from the device asynchronous queue. 605 // 606 RemoveEntryList (&BlkIo2Request->Link); 607 FreePool (BlkIo2Request); 608 gBS->SignalEvent (Token->Event); 609 } 610 611 FreePool (Subtask->CommandPacket->NvmeCmd); 612 FreePool (Subtask->CommandPacket->NvmeCompletion); 613 FreePool (Subtask->CommandPacket); 614 FreePool (Subtask); 615 } else { 616 InsertTailList (&BlkIo2Request->SubtasksQueue, Link); 617 if (Subtask->IsLast) { 618 BlkIo2Request->LastSubtaskSubmitted = TRUE; 619 } 620 } 621 } 622 623 while (Cq->Pt != Private->Pt[QueueId]) { 624 ASSERT (Cq->Sqid == QueueId); 625 626 HasNewItem = TRUE; 627 628 // 629 // Find the command with given Command Id. 630 // 631 for (Link = GetFirstNode (&Private->AsyncPassThruQueue); 632 !IsNull (&Private->AsyncPassThruQueue, Link); 633 Link = NextLink) { 634 NextLink = GetNextNode (&Private->AsyncPassThruQueue, Link); 635 AsyncRequest = NVME_PASS_THRU_ASYNC_REQ_FROM_THIS (Link); 636 if (AsyncRequest->CommandId == Cq->Cid) { 637 // 638 // Copy the Respose Queue entry for this command to the callers 639 // response buffer. 640 // 641 CopyMem ( 642 AsyncRequest->Packet->NvmeCompletion, 643 Cq, 644 sizeof(EFI_NVM_EXPRESS_COMPLETION) 645 ); 646 647 RemoveEntryList (Link); 648 gBS->SignalEvent (AsyncRequest->CallerEvent); 649 FreePool (AsyncRequest); 650 651 // 652 // Update submission queue head. 653 // 654 Private->AsyncSqHead = Cq->Sqhd; 655 break; 656 } 657 } 658 659 Private->CqHdbl[QueueId].Cqh++; 660 if (Private->CqHdbl[QueueId].Cqh > NVME_ASYNC_CCQ_SIZE) { 661 Private->CqHdbl[QueueId].Cqh = 0; 662 Private->Pt[QueueId] ^= 1; 663 } 664 665 Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh; 666 } 667 668 if (HasNewItem) { 669 PciIo = Private->PciIo; 670 Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueId]); 671 PciIo->Mem.Write ( 672 PciIo, 673 EfiPciIoWidthUint32, 674 NVME_BAR, 675 NVME_CQHDBL_OFFSET(QueueId, Private->Cap.Dstrd), 676 1, 677 &Data 678 ); 679 } 680 } 681 682 /** 683 Tests to see if this driver supports a given controller. If a child device is provided, 684 it further tests to see if this driver supports creating a handle for the specified child device. 685 686 This function checks to see if the driver specified by This supports the device specified by 687 ControllerHandle. Drivers will typically use the device path attached to 688 ControllerHandle and/or the services from the bus I/O abstraction attached to 689 ControllerHandle to determine if the driver supports ControllerHandle. This function 690 may be called many times during platform initialization. In order to reduce boot times, the tests 691 performed by this function must be very small, and take as little time as possible to execute. This 692 function must not change the state of any hardware devices, and this function must be aware that the 693 device specified by ControllerHandle may already be managed by the same driver or a 694 different driver. This function must match its calls to AllocatePages() with FreePages(), 695 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). 696 Since ControllerHandle may have been previously started by the same driver, if a protocol is 697 already in the opened state, then it must not be closed with CloseProtocol(). This is required 698 to guarantee the state of ControllerHandle is not modified by this function. 699 700 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 701 @param[in] ControllerHandle The handle of the controller to test. This handle 702 must support a protocol interface that supplies 703 an I/O abstraction to the driver. 704 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This 705 parameter is ignored by device drivers, and is optional for bus 706 drivers. For bus drivers, if this parameter is not NULL, then 707 the bus driver must determine if the bus controller specified 708 by ControllerHandle and the child controller specified 709 by RemainingDevicePath are both supported by this 710 bus driver. 711 712 @retval EFI_SUCCESS The device specified by ControllerHandle and 713 RemainingDevicePath is supported by the driver specified by This. 714 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and 715 RemainingDevicePath is already being managed by the driver 716 specified by This. 717 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and 718 RemainingDevicePath is already being managed by a different 719 driver or an application that requires exclusive access. 720 Currently not implemented. 721 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and 722 RemainingDevicePath is not supported by the driver specified by This. 723 **/ 724 EFI_STATUS 725 EFIAPI 726 NvmExpressDriverBindingSupported ( 727 IN EFI_DRIVER_BINDING_PROTOCOL *This, 728 IN EFI_HANDLE Controller, 729 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 730 ) 731 { 732 EFI_STATUS Status; 733 EFI_DEV_PATH_PTR DevicePathNode; 734 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 735 EFI_PCI_IO_PROTOCOL *PciIo; 736 UINT8 ClassCode[3]; 737 738 // 739 // Check whether device path is valid 740 // 741 if (RemainingDevicePath != NULL) { 742 // 743 // Check if RemainingDevicePath is the End of Device Path Node, 744 // if yes, go on checking other conditions 745 // 746 if (!IsDevicePathEnd (RemainingDevicePath)) { 747 // 748 // If RemainingDevicePath isn't the End of Device Path Node, 749 // check its validation 750 // 751 DevicePathNode.DevPath = RemainingDevicePath; 752 753 if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) || 754 (DevicePathNode.DevPath->SubType != MSG_NVME_NAMESPACE_DP) || 755 (DevicePathNodeLength(DevicePathNode.DevPath) != sizeof(NVME_NAMESPACE_DEVICE_PATH))) { 756 return EFI_UNSUPPORTED; 757 } 758 } 759 } 760 761 // 762 // Open the EFI Device Path protocol needed to perform the supported test 763 // 764 Status = gBS->OpenProtocol ( 765 Controller, 766 &gEfiDevicePathProtocolGuid, 767 (VOID **) &ParentDevicePath, 768 This->DriverBindingHandle, 769 Controller, 770 EFI_OPEN_PROTOCOL_BY_DRIVER 771 ); 772 if (Status == EFI_ALREADY_STARTED) { 773 return EFI_SUCCESS; 774 } 775 776 if (EFI_ERROR (Status)) { 777 return Status; 778 } 779 780 // 781 // Close protocol, don't use device path protocol in the Support() function 782 // 783 gBS->CloseProtocol ( 784 Controller, 785 &gEfiDevicePathProtocolGuid, 786 This->DriverBindingHandle, 787 Controller 788 ); 789 790 // 791 // Attempt to Open PCI I/O Protocol 792 // 793 Status = gBS->OpenProtocol ( 794 Controller, 795 &gEfiPciIoProtocolGuid, 796 (VOID **) &PciIo, 797 This->DriverBindingHandle, 798 Controller, 799 EFI_OPEN_PROTOCOL_BY_DRIVER 800 ); 801 if (Status == EFI_ALREADY_STARTED) { 802 return EFI_SUCCESS; 803 } 804 805 if (EFI_ERROR (Status)) { 806 return Status; 807 } 808 809 // 810 // Now further check the PCI header: Base class (offset 0x0B) and Sub Class (offset 0x0A). 811 // This controller should be a Nvm Express controller. 812 // 813 Status = PciIo->Pci.Read ( 814 PciIo, 815 EfiPciIoWidthUint8, 816 PCI_CLASSCODE_OFFSET, 817 sizeof (ClassCode), 818 ClassCode 819 ); 820 if (EFI_ERROR (Status)) { 821 goto Done; 822 } 823 824 // 825 // Examine Nvm Express controller PCI Configuration table fields 826 // 827 if ((ClassCode[0] != PCI_IF_NVMHCI) || (ClassCode[1] != PCI_CLASS_MASS_STORAGE_NVM) || (ClassCode[2] != PCI_CLASS_MASS_STORAGE)) { 828 Status = EFI_UNSUPPORTED; 829 } 830 831 Done: 832 gBS->CloseProtocol ( 833 Controller, 834 &gEfiPciIoProtocolGuid, 835 This->DriverBindingHandle, 836 Controller 837 ); 838 839 return Status; 840 } 841 842 843 /** 844 Starts a device controller or a bus controller. 845 846 The Start() function is designed to be invoked from the EFI boot service ConnectController(). 847 As a result, much of the error checking on the parameters to Start() has been moved into this 848 common boot service. It is legal to call Start() from other locations, 849 but the following calling restrictions must be followed or the system behavior will not be deterministic. 850 1. ControllerHandle must be a valid EFI_HANDLE. 851 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned 852 EFI_DEVICE_PATH_PROTOCOL. 853 3. Prior to calling Start(), the Supported() function for the driver specified by This must 854 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. 855 856 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 857 @param[in] ControllerHandle The handle of the controller to start. This handle 858 must support a protocol interface that supplies 859 an I/O abstraction to the driver. 860 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This 861 parameter is ignored by device drivers, and is optional for bus 862 drivers. For a bus driver, if this parameter is NULL, then handles 863 for all the children of Controller are created by this driver. 864 If this parameter is not NULL and the first Device Path Node is 865 not the End of Device Path Node, then only the handle for the 866 child device specified by the first Device Path Node of 867 RemainingDevicePath is created by this driver. 868 If the first Device Path Node of RemainingDevicePath is 869 the End of Device Path Node, no child handle is created by this 870 driver. 871 872 @retval EFI_SUCCESS The device was started. 873 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented. 874 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 875 @retval Others The driver failded to start the device. 876 877 **/ 878 EFI_STATUS 879 EFIAPI 880 NvmExpressDriverBindingStart ( 881 IN EFI_DRIVER_BINDING_PROTOCOL *This, 882 IN EFI_HANDLE Controller, 883 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 884 ) 885 { 886 EFI_STATUS Status; 887 EFI_PCI_IO_PROTOCOL *PciIo; 888 NVME_CONTROLLER_PRIVATE_DATA *Private; 889 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 890 UINT32 NamespaceId; 891 EFI_PHYSICAL_ADDRESS MappedAddr; 892 UINTN Bytes; 893 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *Passthru; 894 895 DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: start\n")); 896 897 Private = NULL; 898 Passthru = NULL; 899 ParentDevicePath = NULL; 900 901 Status = gBS->OpenProtocol ( 902 Controller, 903 &gEfiDevicePathProtocolGuid, 904 (VOID **) &ParentDevicePath, 905 This->DriverBindingHandle, 906 Controller, 907 EFI_OPEN_PROTOCOL_BY_DRIVER 908 ); 909 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { 910 return Status; 911 } 912 913 Status = gBS->OpenProtocol ( 914 Controller, 915 &gEfiPciIoProtocolGuid, 916 (VOID **) &PciIo, 917 This->DriverBindingHandle, 918 Controller, 919 EFI_OPEN_PROTOCOL_BY_DRIVER 920 ); 921 922 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { 923 return Status; 924 } 925 926 // 927 // Check EFI_ALREADY_STARTED to reuse the original NVME_CONTROLLER_PRIVATE_DATA. 928 // 929 if (Status != EFI_ALREADY_STARTED) { 930 Private = AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA)); 931 932 if (Private == NULL) { 933 DEBUG ((EFI_D_ERROR, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n")); 934 Status = EFI_OUT_OF_RESOURCES; 935 goto Exit; 936 } 937 938 // 939 // 6 x 4kB aligned buffers will be carved out of this buffer. 940 // 1st 4kB boundary is the start of the admin submission queue. 941 // 2nd 4kB boundary is the start of the admin completion queue. 942 // 3rd 4kB boundary is the start of I/O submission queue #1. 943 // 4th 4kB boundary is the start of I/O completion queue #1. 944 // 5th 4kB boundary is the start of I/O submission queue #2. 945 // 6th 4kB boundary is the start of I/O completion queue #2. 946 // 947 // Allocate 6 pages of memory, then map it for bus master read and write. 948 // 949 Status = PciIo->AllocateBuffer ( 950 PciIo, 951 AllocateAnyPages, 952 EfiBootServicesData, 953 6, 954 (VOID**)&Private->Buffer, 955 0 956 ); 957 if (EFI_ERROR (Status)) { 958 goto Exit; 959 } 960 961 Bytes = EFI_PAGES_TO_SIZE (6); 962 Status = PciIo->Map ( 963 PciIo, 964 EfiPciIoOperationBusMasterCommonBuffer, 965 Private->Buffer, 966 &Bytes, 967 &MappedAddr, 968 &Private->Mapping 969 ); 970 971 if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (6))) { 972 goto Exit; 973 } 974 975 Private->BufferPciAddr = (UINT8 *)(UINTN)MappedAddr; 976 977 Private->Signature = NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE; 978 Private->ControllerHandle = Controller; 979 Private->ImageHandle = This->DriverBindingHandle; 980 Private->DriverBindingHandle = This->DriverBindingHandle; 981 Private->PciIo = PciIo; 982 Private->ParentDevicePath = ParentDevicePath; 983 Private->Passthru.Mode = &Private->PassThruMode; 984 Private->Passthru.PassThru = NvmExpressPassThru; 985 Private->Passthru.GetNextNamespace = NvmExpressGetNextNamespace; 986 Private->Passthru.BuildDevicePath = NvmExpressBuildDevicePath; 987 Private->Passthru.GetNamespace = NvmExpressGetNamespace; 988 CopyMem (&Private->PassThruMode, &gEfiNvmExpressPassThruMode, sizeof (EFI_NVM_EXPRESS_PASS_THRU_MODE)); 989 InitializeListHead (&Private->AsyncPassThruQueue); 990 InitializeListHead (&Private->UnsubmittedSubtasks); 991 992 Status = NvmeControllerInit (Private); 993 if (EFI_ERROR(Status)) { 994 goto Exit; 995 } 996 997 // 998 // Start the asynchronous I/O completion monitor 999 // 1000 Status = gBS->CreateEvent ( 1001 EVT_TIMER | EVT_NOTIFY_SIGNAL, 1002 TPL_NOTIFY, 1003 ProcessAsyncTaskList, 1004 Private, 1005 &Private->TimerEvent 1006 ); 1007 if (EFI_ERROR (Status)) { 1008 goto Exit; 1009 } 1010 1011 Status = gBS->SetTimer ( 1012 Private->TimerEvent, 1013 TimerPeriodic, 1014 NVME_HC_ASYNC_TIMER 1015 ); 1016 if (EFI_ERROR (Status)) { 1017 goto Exit; 1018 } 1019 1020 Status = gBS->InstallMultipleProtocolInterfaces ( 1021 &Controller, 1022 &gEfiNvmExpressPassThruProtocolGuid, 1023 &Private->Passthru, 1024 NULL 1025 ); 1026 if (EFI_ERROR (Status)) { 1027 goto Exit; 1028 } 1029 } else { 1030 Status = gBS->OpenProtocol ( 1031 Controller, 1032 &gEfiNvmExpressPassThruProtocolGuid, 1033 (VOID **) &Passthru, 1034 This->DriverBindingHandle, 1035 Controller, 1036 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1037 ); 1038 if (EFI_ERROR (Status)) { 1039 goto Exit; 1040 } 1041 1042 Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (Passthru); 1043 } 1044 1045 if (RemainingDevicePath == NULL) { 1046 // 1047 // Enumerate all NVME namespaces in the controller 1048 // 1049 Status = DiscoverAllNamespaces ( 1050 Private 1051 ); 1052 1053 } else if (!IsDevicePathEnd (RemainingDevicePath)) { 1054 // 1055 // Enumerate the specified NVME namespace 1056 // 1057 Status = Private->Passthru.GetNamespace ( 1058 &Private->Passthru, 1059 RemainingDevicePath, 1060 &NamespaceId 1061 ); 1062 1063 if (!EFI_ERROR (Status)) { 1064 Status = EnumerateNvmeDevNamespace ( 1065 Private, 1066 NamespaceId 1067 ); 1068 } 1069 } 1070 1071 DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: end successfully\n")); 1072 return EFI_SUCCESS; 1073 1074 Exit: 1075 if ((Private != NULL) && (Private->Mapping != NULL)) { 1076 PciIo->Unmap (PciIo, Private->Mapping); 1077 } 1078 1079 if ((Private != NULL) && (Private->Buffer != NULL)) { 1080 PciIo->FreeBuffer (PciIo, 6, Private->Buffer); 1081 } 1082 1083 if ((Private != NULL) && (Private->ControllerData != NULL)) { 1084 FreePool (Private->ControllerData); 1085 } 1086 1087 if (Private != NULL) { 1088 if (Private->TimerEvent != NULL) { 1089 gBS->CloseEvent (Private->TimerEvent); 1090 } 1091 1092 FreePool (Private); 1093 } 1094 1095 gBS->CloseProtocol ( 1096 Controller, 1097 &gEfiPciIoProtocolGuid, 1098 This->DriverBindingHandle, 1099 Controller 1100 ); 1101 1102 gBS->CloseProtocol ( 1103 Controller, 1104 &gEfiDevicePathProtocolGuid, 1105 This->DriverBindingHandle, 1106 Controller 1107 ); 1108 1109 DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: end with %r\n", Status)); 1110 1111 return Status; 1112 } 1113 1114 1115 /** 1116 Stops a device controller or a bus controller. 1117 1118 The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). 1119 As a result, much of the error checking on the parameters to Stop() has been moved 1120 into this common boot service. It is legal to call Stop() from other locations, 1121 but the following calling restrictions must be followed or the system behavior will not be deterministic. 1122 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this 1123 same driver's Start() function. 1124 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid 1125 EFI_HANDLE. In addition, all of these handles must have been created in this driver's 1126 Start() function, and the Start() function must have called OpenProtocol() on 1127 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. 1128 1129 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 1130 @param[in] ControllerHandle A handle to the device being stopped. The handle must 1131 support a bus specific I/O protocol for the driver 1132 to use to stop the device. 1133 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. 1134 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL 1135 if NumberOfChildren is 0. 1136 1137 @retval EFI_SUCCESS The device was stopped. 1138 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. 1139 1140 **/ 1141 EFI_STATUS 1142 EFIAPI 1143 NvmExpressDriverBindingStop ( 1144 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1145 IN EFI_HANDLE Controller, 1146 IN UINTN NumberOfChildren, 1147 IN EFI_HANDLE *ChildHandleBuffer 1148 ) 1149 { 1150 EFI_STATUS Status; 1151 BOOLEAN AllChildrenStopped; 1152 UINTN Index; 1153 NVME_CONTROLLER_PRIVATE_DATA *Private; 1154 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *PassThru; 1155 BOOLEAN IsEmpty; 1156 EFI_TPL OldTpl; 1157 1158 if (NumberOfChildren == 0) { 1159 Status = gBS->OpenProtocol ( 1160 Controller, 1161 &gEfiNvmExpressPassThruProtocolGuid, 1162 (VOID **) &PassThru, 1163 This->DriverBindingHandle, 1164 Controller, 1165 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1166 ); 1167 1168 if (!EFI_ERROR (Status)) { 1169 Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (PassThru); 1170 1171 // 1172 // Wait for the asynchronous PassThru queue to become empty. 1173 // 1174 while (TRUE) { 1175 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 1176 IsEmpty = IsListEmpty (&Private->AsyncPassThruQueue) && 1177 IsListEmpty (&Private->UnsubmittedSubtasks); 1178 gBS->RestoreTPL (OldTpl); 1179 1180 if (IsEmpty) { 1181 break; 1182 } 1183 1184 gBS->Stall (100); 1185 } 1186 1187 gBS->UninstallMultipleProtocolInterfaces ( 1188 Controller, 1189 &gEfiNvmExpressPassThruProtocolGuid, 1190 PassThru, 1191 NULL 1192 ); 1193 1194 if (Private->TimerEvent != NULL) { 1195 gBS->CloseEvent (Private->TimerEvent); 1196 } 1197 1198 if (Private->Mapping != NULL) { 1199 Private->PciIo->Unmap (Private->PciIo, Private->Mapping); 1200 } 1201 1202 if (Private->Buffer != NULL) { 1203 Private->PciIo->FreeBuffer (Private->PciIo, 6, Private->Buffer); 1204 } 1205 1206 FreePool (Private->ControllerData); 1207 FreePool (Private); 1208 } 1209 1210 gBS->CloseProtocol ( 1211 Controller, 1212 &gEfiPciIoProtocolGuid, 1213 This->DriverBindingHandle, 1214 Controller 1215 ); 1216 gBS->CloseProtocol ( 1217 Controller, 1218 &gEfiDevicePathProtocolGuid, 1219 This->DriverBindingHandle, 1220 Controller 1221 ); 1222 return EFI_SUCCESS; 1223 } 1224 1225 AllChildrenStopped = TRUE; 1226 1227 for (Index = 0; Index < NumberOfChildren; Index++) { 1228 Status = UnregisterNvmeNamespace (This, Controller, ChildHandleBuffer[Index]); 1229 if (EFI_ERROR (Status)) { 1230 AllChildrenStopped = FALSE; 1231 } 1232 } 1233 1234 if (!AllChildrenStopped) { 1235 return EFI_DEVICE_ERROR; 1236 } 1237 1238 return EFI_SUCCESS; 1239 } 1240 1241 /** 1242 This is the unload handle for the NVM Express driver. 1243 1244 Disconnect the driver specified by ImageHandle from the NVMe device in the handle database. 1245 Uninstall all the protocols installed in the driver. 1246 1247 @param[in] ImageHandle The drivers' driver image. 1248 1249 @retval EFI_SUCCESS The image is unloaded. 1250 @retval Others Failed to unload the image. 1251 1252 **/ 1253 EFI_STATUS 1254 EFIAPI 1255 NvmExpressUnload ( 1256 IN EFI_HANDLE ImageHandle 1257 ) 1258 { 1259 EFI_STATUS Status; 1260 EFI_HANDLE *DeviceHandleBuffer; 1261 UINTN DeviceHandleCount; 1262 UINTN Index; 1263 EFI_COMPONENT_NAME_PROTOCOL *ComponentName; 1264 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2; 1265 1266 // 1267 // Get the list of the device handles managed by this driver. 1268 // If there is an error getting the list, then means the driver 1269 // doesn't manage any device. At this way, we would only close 1270 // those protocols installed at image handle. 1271 // 1272 DeviceHandleBuffer = NULL; 1273 Status = gBS->LocateHandleBuffer ( 1274 ByProtocol, 1275 &gEfiNvmExpressPassThruProtocolGuid, 1276 NULL, 1277 &DeviceHandleCount, 1278 &DeviceHandleBuffer 1279 ); 1280 1281 if (!EFI_ERROR (Status)) { 1282 // 1283 // Disconnect the driver specified by ImageHandle from all 1284 // the devices in the handle database. 1285 // 1286 for (Index = 0; Index < DeviceHandleCount; Index++) { 1287 Status = gBS->DisconnectController ( 1288 DeviceHandleBuffer[Index], 1289 ImageHandle, 1290 NULL 1291 ); 1292 if (EFI_ERROR (Status)) { 1293 goto EXIT; 1294 } 1295 } 1296 } 1297 1298 // 1299 // Uninstall all the protocols installed in the driver entry point 1300 // 1301 Status = gBS->UninstallMultipleProtocolInterfaces ( 1302 ImageHandle, 1303 &gEfiDriverBindingProtocolGuid, 1304 &gNvmExpressDriverBinding, 1305 &gEfiDriverSupportedEfiVersionProtocolGuid, 1306 &gNvmExpressDriverSupportedEfiVersion, 1307 NULL 1308 ); 1309 1310 if (EFI_ERROR (Status)) { 1311 goto EXIT; 1312 } 1313 1314 // 1315 // Note we have to one by one uninstall the following protocols. 1316 // It's because some of them are optionally installed based on 1317 // the following PCD settings. 1318 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable 1319 // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable 1320 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable 1321 // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable 1322 // 1323 Status = gBS->HandleProtocol ( 1324 ImageHandle, 1325 &gEfiComponentNameProtocolGuid, 1326 (VOID **) &ComponentName 1327 ); 1328 if (!EFI_ERROR (Status)) { 1329 gBS->UninstallProtocolInterface ( 1330 ImageHandle, 1331 &gEfiComponentNameProtocolGuid, 1332 ComponentName 1333 ); 1334 } 1335 1336 Status = gBS->HandleProtocol ( 1337 ImageHandle, 1338 &gEfiComponentName2ProtocolGuid, 1339 (VOID **) &ComponentName2 1340 ); 1341 if (!EFI_ERROR (Status)) { 1342 gBS->UninstallProtocolInterface ( 1343 ImageHandle, 1344 &gEfiComponentName2ProtocolGuid, 1345 ComponentName2 1346 ); 1347 } 1348 1349 Status = EFI_SUCCESS; 1350 1351 EXIT: 1352 // 1353 // Free the buffer containing the list of handles from the handle database 1354 // 1355 if (DeviceHandleBuffer != NULL) { 1356 gBS->FreePool (DeviceHandleBuffer); 1357 } 1358 return Status; 1359 } 1360 1361 /** 1362 The entry point for Nvm Express driver, used to install Nvm Express driver on the ImageHandle. 1363 1364 @param ImageHandle The firmware allocated handle for this driver image. 1365 @param SystemTable Pointer to the EFI system table. 1366 1367 @retval EFI_SUCCESS Driver loaded. 1368 @retval other Driver not loaded. 1369 1370 **/ 1371 EFI_STATUS 1372 EFIAPI 1373 NvmExpressDriverEntry ( 1374 IN EFI_HANDLE ImageHandle, 1375 IN EFI_SYSTEM_TABLE *SystemTable 1376 ) 1377 { 1378 EFI_STATUS Status; 1379 1380 Status = EfiLibInstallDriverBindingComponentName2 ( 1381 ImageHandle, 1382 SystemTable, 1383 &gNvmExpressDriverBinding, 1384 ImageHandle, 1385 &gNvmExpressComponentName, 1386 &gNvmExpressComponentName2 1387 ); 1388 ASSERT_EFI_ERROR (Status); 1389 1390 // 1391 // Install EFI Driver Supported EFI Version Protocol required for 1392 // EFI drivers that are on PCI and other plug in cards. 1393 // 1394 gNvmExpressDriverSupportedEfiVersion.FirmwareVersion = 0x00020028; 1395 Status = gBS->InstallMultipleProtocolInterfaces ( 1396 &ImageHandle, 1397 &gEfiDriverSupportedEfiVersionProtocolGuid, 1398 &gNvmExpressDriverSupportedEfiVersion, 1399 NULL 1400 ); 1401 ASSERT_EFI_ERROR (Status); 1402 return Status; 1403 } 1404