]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
0d02c2785da795acf77e926e513016a30ece66fa
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NvmExpressPei / NvmExpressPei.c
1 /** @file
2 The NvmExpressPei driver is used to manage non-volatile memory subsystem
3 which follows NVM Express specification at PEI phase.
4
5 Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "NvmExpressPei.h"
12
13 EFI_PEI_PPI_DESCRIPTOR mNvmeBlkIoPpiListTemplate = {
14 EFI_PEI_PPI_DESCRIPTOR_PPI,
15 &gEfiPeiVirtualBlockIoPpiGuid,
16 NULL
17 };
18
19 EFI_PEI_PPI_DESCRIPTOR mNvmeBlkIo2PpiListTemplate = {
20 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
21 &gEfiPeiVirtualBlockIo2PpiGuid,
22 NULL
23 };
24
25 EFI_PEI_PPI_DESCRIPTOR mNvmeStorageSecurityPpiListTemplate = {
26 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
27 &gEdkiiPeiStorageSecurityCommandPpiGuid,
28 NULL
29 };
30
31 EFI_PEI_PPI_DESCRIPTOR mNvmePassThruPpiListTemplate = {
32 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
33 &gEdkiiPeiNvmExpressPassThruPpiGuid,
34 NULL
35 };
36
37 EFI_PEI_NOTIFY_DESCRIPTOR mNvmeEndOfPeiNotifyListTemplate = {
38 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
39 &gEfiEndOfPeiSignalPpiGuid,
40 NvmePeimEndOfPei
41 };
42
43 EFI_PEI_NOTIFY_DESCRIPTOR mNvmeHostControllerNotify = {
44 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
45 &gEdkiiPeiNvmExpressHostControllerPpiGuid,
46 NvmeHostControllerPpiInstallationCallback
47 };
48
49 EFI_PEI_NOTIFY_DESCRIPTOR mPciDevicePpiNotify = {
50 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
51 &gEdkiiPeiPciDevicePpiGuid,
52 NvmePciDevicePpiInstallationCallback
53 };
54
55 /**
56 Check if the specified Nvm Express device namespace is active, and then get the Identify
57 Namespace data.
58
59 @param[in,out] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
60 @param[in] NamespaceId The specified namespace identifier.
61
62 @retval EFI_SUCCESS The specified namespace in the device is successfully enumerated.
63 @return Others Error occurs when enumerating the namespace.
64
65 **/
66 EFI_STATUS
67 EnumerateNvmeDevNamespace (
68 IN OUT PEI_NVME_CONTROLLER_PRIVATE_DATA *Private,
69 IN UINT32 NamespaceId
70 )
71 {
72 EFI_STATUS Status;
73 NVME_ADMIN_NAMESPACE_DATA *NamespaceData;
74 PEI_NVME_NAMESPACE_INFO *NamespaceInfo;
75 UINT32 DeviceIndex;
76 UINT32 Lbads;
77 UINT32 Flbas;
78 UINT32 LbaFmtIdx;
79
80 NamespaceData = (NVME_ADMIN_NAMESPACE_DATA *)AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA));
81 if (NamespaceData == NULL) {
82 return EFI_OUT_OF_RESOURCES;
83 }
84
85 //
86 // Identify Namespace
87 //
88 Status = NvmeIdentifyNamespace (
89 Private,
90 NamespaceId,
91 NamespaceData
92 );
93 if (EFI_ERROR (Status)) {
94 DEBUG ((DEBUG_ERROR, "%a: NvmeIdentifyNamespace fail, Status - %r\n", __FUNCTION__, Status));
95 goto Exit;
96 }
97
98 //
99 // Validate Namespace
100 //
101 if (NamespaceData->Ncap == 0) {
102 DEBUG ((DEBUG_INFO, "%a: Namespace ID %d is an inactive one.\n", __FUNCTION__, NamespaceId));
103 Status = EFI_DEVICE_ERROR;
104 goto Exit;
105 }
106
107 DeviceIndex = Private->ActiveNamespaceNum;
108 NamespaceInfo = &Private->NamespaceInfo[DeviceIndex];
109 NamespaceInfo->NamespaceId = NamespaceId;
110 NamespaceInfo->NamespaceUuid = NamespaceData->Eui64;
111 NamespaceInfo->Controller = Private;
112 Private->ActiveNamespaceNum++;
113
114 //
115 // Build BlockIo media structure
116 //
117 Flbas = NamespaceData->Flbas;
118 LbaFmtIdx = Flbas & 0xF;
119
120 //
121 // Currently this NVME driver only suport Metadata Size == 0
122 //
123 if (NamespaceData->LbaFormat[LbaFmtIdx].Ms != 0) {
124 DEBUG ((
125 DEBUG_ERROR,
126 "NVME IDENTIFY NAMESPACE [%d] Ms(%d) is not supported.\n",
127 NamespaceId,
128 NamespaceData->LbaFormat[LbaFmtIdx].Ms
129 ));
130 Status = EFI_UNSUPPORTED;
131 goto Exit;
132 }
133
134 Lbads = NamespaceData->LbaFormat[LbaFmtIdx].Lbads;
135
136 NamespaceInfo->Media.InterfaceType = MSG_NVME_NAMESPACE_DP;
137 NamespaceInfo->Media.RemovableMedia = FALSE;
138 NamespaceInfo->Media.MediaPresent = TRUE;
139 NamespaceInfo->Media.ReadOnly = FALSE;
140 NamespaceInfo->Media.BlockSize = (UINT32)1 << Lbads;
141 NamespaceInfo->Media.LastBlock = (EFI_PEI_LBA)NamespaceData->Nsze - 1;
142 DEBUG ((
143 DEBUG_INFO,
144 "%a: Namespace ID %d - BlockSize = 0x%x, LastBlock = 0x%lx\n",
145 __FUNCTION__,
146 NamespaceId,
147 NamespaceInfo->Media.BlockSize,
148 NamespaceInfo->Media.LastBlock
149 ));
150
151 Exit:
152 if (NamespaceData != NULL) {
153 FreePool (NamespaceData);
154 }
155
156 return Status;
157 }
158
159 /**
160 Discover all Nvm Express device active namespaces.
161
162 @param[in,out] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
163
164 @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
165 @return EFI_NOT_FOUND No active namespaces can be found.
166
167 **/
168 EFI_STATUS
169 NvmeDiscoverNamespaces (
170 IN OUT PEI_NVME_CONTROLLER_PRIVATE_DATA *Private
171 )
172 {
173 UINT32 NamespaceId;
174
175 Private->ActiveNamespaceNum = 0;
176 Private->NamespaceInfo = AllocateZeroPool (Private->ControllerData->Nn * sizeof (PEI_NVME_NAMESPACE_INFO));
177
178 //
179 // According to Nvm Express 1.1 spec Figure 82, the field 'Nn' of the identify
180 // controller data defines the number of valid namespaces present for the
181 // controller. Namespaces shall be allocated in order (starting with 1) and
182 // packed sequentially.
183 //
184 for (NamespaceId = 1; NamespaceId <= Private->ControllerData->Nn; NamespaceId++) {
185 //
186 // For now, we do not care the return status. Since if a valid namespace is inactive,
187 // error status will be returned. But we continue to enumerate other valid namespaces.
188 //
189 EnumerateNvmeDevNamespace (Private, NamespaceId);
190 }
191
192 if (Private->ActiveNamespaceNum == 0) {
193 return EFI_NOT_FOUND;
194 }
195
196 return EFI_SUCCESS;
197 }
198
199 /**
200 One notified function to cleanup the allocated resources at the end of PEI.
201
202 @param[in] PeiServices Pointer to PEI Services Table.
203 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification
204 event that caused this function to execute.
205 @param[in] Ppi Pointer to the PPI data associated with this function.
206
207 @retval EFI_SUCCESS The function completes successfully
208
209 **/
210 EFI_STATUS
211 EFIAPI
212 NvmePeimEndOfPei (
213 IN EFI_PEI_SERVICES **PeiServices,
214 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
215 IN VOID *Ppi
216 )
217 {
218 PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;
219
220 Private = GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescriptor);
221 NvmeFreeDmaResource (Private);
222
223 return EFI_SUCCESS;
224 }
225
226 /**
227 Initialize and install PrivateData PPIs.
228
229 @param[in] MmioBase MMIO base address of specific Nvme controller
230 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
231 structure.
232 @param[in] DevicePathLength Length of the device path.
233
234 @retval EFI_SUCCESS Nvme controller initialized and PPIs installed
235 @retval others Failed to initialize Nvme controller
236 **/
237 EFI_STATUS
238 NvmeInitPrivateData (
239 IN UINTN MmioBase,
240 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
241 IN UINTN DevicePathLength
242 )
243 {
244 EFI_STATUS Status;
245 EFI_BOOT_MODE BootMode;
246 PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;
247 EFI_PHYSICAL_ADDRESS DeviceAddress;
248
249 DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
250
251 //
252 // Get the current boot mode.
253 //
254 Status = PeiServicesGetBootMode (&BootMode);
255 if (EFI_ERROR (Status)) {
256 DEBUG ((DEBUG_ERROR, "%a: Fail to get the current boot mode.\n", __FUNCTION__));
257 return Status;
258 }
259
260 //
261 // Check validity of the device path of the NVM Express controller.
262 //
263 Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
264 if (EFI_ERROR (Status)) {
265 DEBUG ((
266 DEBUG_ERROR,
267 "%a: The device path is invalid for Controller %d.\n",
268 __FUNCTION__
269 ));
270 return Status;
271 }
272
273 //
274 // For S3 resume performance consideration, not all NVM Express controllers
275 // will be initialized. The driver consumes the content within
276 // S3StorageDeviceInitList LockBox to see if a controller will be skipped
277 // during S3 resume.
278 //
279 if ((BootMode == BOOT_ON_S3_RESUME) &&
280 (NvmeS3SkipThisController (DevicePath, DevicePathLength)))
281 {
282 DEBUG ((
283 DEBUG_ERROR,
284 "%a: skipped during S3.\n",
285 __FUNCTION__
286 ));
287 return EFI_SUCCESS;
288 }
289
290 //
291 // Memory allocation for controller private data
292 //
293 Private = AllocateZeroPool (sizeof (PEI_NVME_CONTROLLER_PRIVATE_DATA));
294 if (Private == NULL) {
295 DEBUG ((
296 DEBUG_ERROR,
297 "%a: Fail to allocate private data.\n",
298 __FUNCTION__
299 ));
300 return EFI_OUT_OF_RESOURCES;
301 }
302
303 //
304 // Memory allocation for transfer-related data
305 //
306 Status = IoMmuAllocateBuffer (
307 NVME_MEM_MAX_PAGES,
308 &Private->Buffer,
309 &DeviceAddress,
310 &Private->BufferMapping
311 );
312 if (EFI_ERROR (Status)) {
313 DEBUG ((
314 DEBUG_ERROR,
315 "%a: Fail to allocate DMA buffers.\n",
316 __FUNCTION__
317 ));
318 return Status;
319 }
320
321 ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)Private->Buffer));
322 DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n", __FUNCTION__, Private->Buffer));
323
324 //
325 // Initialize controller private data
326 //
327 Private->Signature = NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
328 Private->MmioBase = MmioBase;
329 Private->DevicePathLength = DevicePathLength;
330 Private->DevicePath = DevicePath;
331
332 //
333 // Initialize the NVME controller
334 //
335 Status = NvmeControllerInit (Private);
336 if (EFI_ERROR (Status)) {
337 DEBUG ((
338 DEBUG_ERROR,
339 "%a: Controller initialization fail with Status - %r.\n",
340 __FUNCTION__,
341 Status
342 ));
343 NvmeFreeDmaResource (Private);
344 return Status;
345 }
346
347 //
348 // Enumerate the NVME namespaces on the controller
349 //
350 Status = NvmeDiscoverNamespaces (Private);
351 if (EFI_ERROR (Status)) {
352 //
353 // No active namespace was found on the controller
354 //
355 DEBUG ((
356 DEBUG_ERROR,
357 "%a: Namespaces discovery fail with Status - %r.\n",
358 __FUNCTION__,
359 Status
360 ));
361 NvmeFreeDmaResource (Private);
362 return Status;
363 }
364
365 //
366 // Nvm Express Pass Thru PPI
367 //
368 Private->PassThruMode.Attributes = EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
369 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL |
370 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
371 Private->PassThruMode.IoAlign = sizeof (UINTN);
372 Private->PassThruMode.NvmeVersion = EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
373 Private->NvmePassThruPpi.Mode = &Private->PassThruMode;
374 Private->NvmePassThruPpi.GetDevicePath = NvmePassThruGetDevicePath;
375 Private->NvmePassThruPpi.GetNextNameSpace = NvmePassThruGetNextNameSpace;
376 Private->NvmePassThruPpi.PassThru = NvmePassThru;
377 CopyMem (
378 &Private->NvmePassThruPpiList,
379 &mNvmePassThruPpiListTemplate,
380 sizeof (EFI_PEI_PPI_DESCRIPTOR)
381 );
382 Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
383 PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
384
385 //
386 // Block Io PPI
387 //
388 Private->BlkIoPpi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo;
389 Private->BlkIoPpi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo;
390 Private->BlkIoPpi.ReadBlocks = NvmeBlockIoPeimReadBlocks;
391 CopyMem (
392 &Private->BlkIoPpiList,
393 &mNvmeBlkIoPpiListTemplate,
394 sizeof (EFI_PEI_PPI_DESCRIPTOR)
395 );
396 Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
397
398 Private->BlkIo2Ppi.Revision = EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
399 Private->BlkIo2Ppi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo2;
400 Private->BlkIo2Ppi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo2;
401 Private->BlkIo2Ppi.ReadBlocks = NvmeBlockIoPeimReadBlocks2;
402 CopyMem (
403 &Private->BlkIo2PpiList,
404 &mNvmeBlkIo2PpiListTemplate,
405 sizeof (EFI_PEI_PPI_DESCRIPTOR)
406 );
407 Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
408 PeiServicesInstallPpi (&Private->BlkIoPpiList);
409
410 //
411 // Check if the NVME controller supports the Security Receive/Send commands
412 //
413 if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
414 DEBUG ((
415 DEBUG_INFO,
416 "%a: Security Security Command PPI will be produced.\n",
417 __FUNCTION__
418 ));
419 Private->StorageSecurityPpi.Revision = EDKII_STORAGE_SECURITY_PPI_REVISION;
420 Private->StorageSecurityPpi.GetNumberofDevices = NvmeStorageSecurityGetDeviceNo;
421 Private->StorageSecurityPpi.GetDevicePath = NvmeStorageSecurityGetDevicePath;
422 Private->StorageSecurityPpi.ReceiveData = NvmeStorageSecurityReceiveData;
423 Private->StorageSecurityPpi.SendData = NvmeStorageSecuritySendData;
424 CopyMem (
425 &Private->StorageSecurityPpiList,
426 &mNvmeStorageSecurityPpiListTemplate,
427 sizeof (EFI_PEI_PPI_DESCRIPTOR)
428 );
429 Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
430 PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
431 }
432
433 CopyMem (
434 &Private->EndOfPeiNotifyList,
435 &mNvmeEndOfPeiNotifyListTemplate,
436 sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
437 );
438 PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
439
440 return EFI_SUCCESS;
441 }
442
443 /**
444 Initialize Nvme controller from fiven PCI_DEVICE_PPI.
445
446 @param[in] PciDevice Pointer to the PCI Device PPI instance.
447
448 @retval EFI_SUCCESS The function completes successfully
449 @retval Others Cannot initialize Nvme controller for given device
450 **/
451 EFI_STATUS
452 NvmeInitControllerDataFromPciDevice (
453 EDKII_PCI_DEVICE_PPI *PciDevice
454 )
455 {
456 EFI_STATUS Status;
457 PCI_TYPE00 PciData;
458 UINTN MmioBase;
459 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
460 UINTN DevicePathLength;
461 UINT64 EnabledPciAttributes;
462 UINT32 MmioBaseH;
463
464 //
465 // Now further check the PCI header: Base Class (offset 0x0B), Sub Class (offset 0x0A) and
466 // Programming Interface (offset 0x09). This controller should be an Nvme controller
467 //
468 Status = PciDevice->PciIo.Pci.Read (
469 &PciDevice->PciIo,
470 EfiPciIoWidthUint8,
471 PCI_CLASSCODE_OFFSET,
472 sizeof (PciData.Hdr.ClassCode),
473 PciData.Hdr.ClassCode
474 );
475 if (EFI_ERROR (Status)) {
476 return EFI_UNSUPPORTED;
477 }
478
479 if (!IS_PCI_NVMHCI (&PciData)) {
480 return EFI_UNSUPPORTED;
481 }
482
483 Status = PciDevice->PciIo.Attributes (
484 &PciDevice->PciIo,
485 EfiPciIoAttributeOperationSupported,
486 0,
487 &EnabledPciAttributes
488 );
489 if (EFI_ERROR (Status)) {
490 return EFI_UNSUPPORTED;
491 } else {
492 EnabledPciAttributes &= (UINT64)EFI_PCI_DEVICE_ENABLE;
493 Status = PciDevice->PciIo.Attributes (
494 &PciDevice->PciIo,
495 EfiPciIoAttributeOperationEnable,
496 EnabledPciAttributes,
497 NULL
498 );
499 if (EFI_ERROR (Status)) {
500 return EFI_UNSUPPORTED;
501 }
502 }
503
504 Status = PciDevice->PciIo.Pci.Read (
505 &PciDevice->PciIo,
506 EfiPciIoWidthUint32,
507 PCI_BASE_ADDRESSREG_OFFSET,
508 1,
509 &MmioBase
510 );
511 if (EFI_ERROR (Status)) {
512 return EFI_UNSUPPORTED;
513 }
514
515 switch (MmioBase & 0x07) {
516 case 0x0:
517 //
518 // Memory space for 32 bit bar address
519 //
520 MmioBase = MmioBase & 0xFFFFFFF0;
521 break;
522 case 0x4:
523 //
524 // For 64 bit bar address, read the high 32bits of this 64 bit bar
525 //
526 Status = PciDevice->PciIo.Pci.Read (
527 &PciDevice->PciIo,
528 EfiPciIoWidthUint32,
529 PCI_BASE_ADDRESSREG_OFFSET + 4,
530 1,
531 &MmioBaseH
532 );
533 //
534 // For 32 bit environment, high 32bits of the bar should be zero.
535 //
536 if ( EFI_ERROR (Status)
537 || ((MmioBaseH != 0) && (sizeof (UINTN) == sizeof (UINT32))))
538 {
539 return EFI_UNSUPPORTED;
540 }
541
542 MmioBase = MmioBase & 0xFFFFFFF0;
543 MmioBase |= LShiftU64 ((UINT64)MmioBaseH, 32);
544 break;
545 default:
546 //
547 // Unknown bar type
548 //
549 return EFI_UNSUPPORTED;
550 }
551
552 DevicePathLength = GetDevicePathSize (PciDevice->DevicePath);
553 DevicePath = PciDevice->DevicePath;
554
555 Status = NvmeInitPrivateData (MmioBase, DevicePath, DevicePathLength);
556 if (EFI_ERROR (Status)) {
557 DEBUG ((
558 DEBUG_INFO,
559 "%a: Failed to init controller, with Status - %r\n",
560 __FUNCTION__,
561 Status
562 ));
563 }
564
565 return EFI_SUCCESS;
566 }
567
568 /**
569 Callback for EDKII_PCI_DEVICE_PPI installation.
570
571 @param[in] PeiServices Pointer to PEI Services Table.
572 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification
573 event that caused this function to execute.
574 @param[in] Ppi Pointer to the PPI data associated with this function.
575
576 @retval EFI_SUCCESS The function completes successfully
577 @retval Others Cannot initialize Nvme controller from given PCI_DEVICE_PPI
578
579 **/
580 EFI_STATUS
581 EFIAPI
582 NvmePciDevicePpiInstallationCallback (
583 IN EFI_PEI_SERVICES **PeiServices,
584 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
585 IN VOID *Ppi
586 )
587 {
588 EDKII_PCI_DEVICE_PPI *PciDevice;
589
590 PciDevice = (EDKII_PCI_DEVICE_PPI *)Ppi;
591
592 return NvmeInitControllerDataFromPciDevice (PciDevice);
593 }
594
595 /**
596 Initialize Nvme controller from EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI instance.
597
598 @param[in] NvmeHcPpi Pointer to the Nvme Host Controller PPI instance.
599
600 @retval EFI_SUCCESS PPI successfully installed.
601 **/
602 EFI_STATUS
603 NvmeInitControllerFromHostControllerPpi (
604 IN EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi
605 )
606 {
607 UINT8 Controller;
608 UINTN MmioBase;
609 UINTN DevicePathLength;
610 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
611 EFI_STATUS Status;
612
613 Controller = 0;
614 MmioBase = 0;
615 while (TRUE) {
616 Status = NvmeHcPpi->GetNvmeHcMmioBar (
617 NvmeHcPpi,
618 Controller,
619 &MmioBase
620 );
621 //
622 // When status is error, meant no controller is found
623 //
624 if (EFI_ERROR (Status)) {
625 break;
626 }
627
628 Status = NvmeHcPpi->GetNvmeHcDevicePath (
629 NvmeHcPpi,
630 Controller,
631 &DevicePathLength,
632 &DevicePath
633 );
634 if (EFI_ERROR (Status)) {
635 DEBUG ((
636 DEBUG_ERROR,
637 "%a: Fail to allocate get the device path for Controller %d.\n",
638 __FUNCTION__,
639 Controller
640 ));
641 return Status;
642 }
643
644 Status = NvmeInitPrivateData (MmioBase, DevicePath, DevicePathLength);
645 if (EFI_ERROR (Status)) {
646 DEBUG ((
647 DEBUG_ERROR,
648 "%a: Controller initialization fail for Controller %d with Status - %r.\n",
649 __FUNCTION__,
650 Controller,
651 Status
652 ));
653 } else {
654 DEBUG ((
655 DEBUG_INFO,
656 "%a: Controller %d has been successfully initialized.\n",
657 __FUNCTION__,
658 Controller
659 ));
660 }
661
662 Controller++;
663 }
664
665 return EFI_SUCCESS;
666 }
667
668 /**
669 Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
670
671 @param[in] PeiServices Pointer to PEI Services Table.
672 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification
673 event that caused this function to execute.
674 @param[in] Ppi Pointer to the PPI data associated with this function.
675
676 @retval EFI_SUCCESS The function completes successfully
677 @retval Others Cannot initialize Nvme controller from given EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
678
679 **/
680 EFI_STATUS
681 EFIAPI
682 NvmeHostControllerPpiInstallationCallback (
683 IN EFI_PEI_SERVICES **PeiServices,
684 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
685 IN VOID *Ppi
686 )
687 {
688 EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi;
689
690 if (Ppi == NULL) {
691 return EFI_INVALID_PARAMETER;
692 }
693
694 NvmeHcPpi = (EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *)Ppi;
695
696 return NvmeInitControllerFromHostControllerPpi (NvmeHcPpi);
697 }
698
699 /**
700 Entry point of the PEIM.
701
702 @param[in] FileHandle Handle of the file being invoked.
703 @param[in] PeiServices Describes the list of possible PEI Services.
704
705 @retval EFI_SUCCESS PPI successfully installed.
706
707 **/
708 EFI_STATUS
709 EFIAPI
710 NvmExpressPeimEntry (
711 IN EFI_PEI_FILE_HANDLE FileHandle,
712 IN CONST EFI_PEI_SERVICES **PeiServices
713 )
714 {
715 DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
716
717 PeiServicesNotifyPpi (&mNvmeHostControllerNotify);
718
719 PeiServicesNotifyPpi (&mPciDevicePpiNotify);
720
721 return EFI_SUCCESS;
722 }