2 The AhciPei driver is used to manage ATA hard disk device working under AHCI
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Ppi/PciDevice.h>
13 #include <Library/DevicePathLib.h>
14 #include <IndustryStandard/Pci.h>
16 EFI_PEI_PPI_DESCRIPTOR mAhciAtaPassThruPpiListTemplate
= {
17 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
18 &gEdkiiPeiAtaPassThruPpiGuid
,
22 EFI_PEI_PPI_DESCRIPTOR mAhciBlkIoPpiListTemplate
= {
23 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
24 &gEfiPeiVirtualBlockIoPpiGuid
,
28 EFI_PEI_PPI_DESCRIPTOR mAhciBlkIo2PpiListTemplate
= {
29 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
30 &gEfiPeiVirtualBlockIo2PpiGuid
,
34 EFI_PEI_PPI_DESCRIPTOR mAhciStorageSecurityPpiListTemplate
= {
35 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
36 &gEdkiiPeiStorageSecurityCommandPpiGuid
,
40 EFI_PEI_NOTIFY_DESCRIPTOR mAhciEndOfPeiNotifyListTemplate
= {
41 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
42 &gEfiEndOfPeiSignalPpiGuid
,
46 EFI_PEI_NOTIFY_DESCRIPTOR mAtaAhciHostControllerNotify
= {
47 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
48 &gEdkiiPeiAtaAhciHostControllerPpiGuid
,
49 AtaAhciHostControllerPpiInstallationCallback
52 EFI_PEI_NOTIFY_DESCRIPTOR mPciDevicePpiNotify
= {
53 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
54 &gEdkiiPeiPciDevicePpiGuid
,
55 AtaAhciPciDevicePpiInstallationCallback
59 Free the DMA resources allocated by an ATA AHCI controller.
61 @param[in] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA data
67 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
70 EFI_AHCI_REGISTERS
*AhciRegisters
;
72 ASSERT (Private
!= NULL
);
74 AhciRegisters
= &Private
->AhciRegisters
;
76 if (AhciRegisters
->AhciRFisMap
!= NULL
) {
78 EFI_SIZE_TO_PAGES (AhciRegisters
->MaxRFisSize
),
79 AhciRegisters
->AhciRFis
,
80 AhciRegisters
->AhciRFisMap
84 if (AhciRegisters
->AhciCmdListMap
!= NULL
) {
86 EFI_SIZE_TO_PAGES (AhciRegisters
->MaxCmdListSize
),
87 AhciRegisters
->AhciCmdList
,
88 AhciRegisters
->AhciCmdListMap
92 if (AhciRegisters
->AhciCmdTableMap
!= NULL
) {
94 EFI_SIZE_TO_PAGES (AhciRegisters
->MaxCmdTableSize
),
95 AhciRegisters
->AhciCmdTable
,
96 AhciRegisters
->AhciCmdTableMap
102 One notified function to cleanup the allocated DMA buffers at EndOfPei.
104 @param[in] PeiServices Pointer to PEI Services Table.
105 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification
106 event that caused this function to execute.
107 @param[in] Ppi Pointer to the PPI data associated with this function.
109 @retval EFI_SUCCESS The function completes successfully
115 IN EFI_PEI_SERVICES
**PeiServices
,
116 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
120 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
122 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescriptor
);
123 AhciFreeDmaResource (Private
);
129 Initialize and install PrivateData PPIs.
131 @param[in] MmioBase MMIO base address of specific AHCI controller
132 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
134 @param[in] DevicePathLength Length of the device path.
136 @retval EFI_SUCCESS AHCI controller initialized and PPIs installed
137 @retval others Failed to initialize AHCI controller
140 AtaAhciInitPrivateData (
142 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
143 IN UINTN DevicePathLength
149 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
150 EFI_BOOT_MODE BootMode
;
152 DEBUG ((DEBUG_INFO
, "Initializing private data for ATA\n"));
155 // Get the current boot mode.
157 Status
= PeiServicesGetBootMode (&BootMode
);
158 if (EFI_ERROR (Status
)) {
159 DEBUG ((DEBUG_ERROR
, "%a: Fail to get the current boot mode.\n", __FUNCTION__
));
164 // Check validity of the device path of the ATA AHCI controller.
166 Status
= AhciIsHcDevicePathValid (DevicePath
, DevicePathLength
);
167 if (EFI_ERROR (Status
)) {
170 "%a: The device path is invalid.\n",
177 // For S3 resume performance consideration, not all ports on an ATA AHCI
178 // controller will be enumerated/initialized. The driver consumes the
179 // content within S3StorageDeviceInitList LockBox to get the ports that
180 // will be enumerated/initialized during S3 resume.
182 if (BootMode
== BOOT_ON_S3_RESUME
) {
183 NumberOfPorts
= AhciS3GetEumeratePorts (DevicePath
, DevicePathLength
, &PortBitMap
);
184 if (NumberOfPorts
== 0) {
188 PortBitMap
= MAX_UINT32
;
192 // Memory allocation for controller private data.
194 Private
= AllocateZeroPool (sizeof (PEI_AHCI_CONTROLLER_PRIVATE_DATA
));
195 if (Private
== NULL
) {
198 "%a: Fail to allocate private data.\n",
201 return EFI_OUT_OF_RESOURCES
;
205 // Initialize controller private data.
207 Private
->Signature
= AHCI_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE
;
208 Private
->MmioBase
= MmioBase
;
209 Private
->DevicePathLength
= DevicePathLength
;
210 Private
->DevicePath
= DevicePath
;
211 Private
->PortBitMap
= PortBitMap
;
212 InitializeListHead (&Private
->DeviceList
);
214 Status
= AhciModeInitialization (Private
);
215 if (EFI_ERROR (Status
)) {
219 Private
->AtaPassThruMode
.Attributes
= EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL
|
220 EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL
;
221 Private
->AtaPassThruMode
.IoAlign
= sizeof (UINTN
);
222 Private
->AtaPassThruPpi
.Revision
= EDKII_PEI_ATA_PASS_THRU_PPI_REVISION
;
223 Private
->AtaPassThruPpi
.Mode
= &Private
->AtaPassThruMode
;
224 Private
->AtaPassThruPpi
.PassThru
= AhciAtaPassThruPassThru
;
225 Private
->AtaPassThruPpi
.GetNextPort
= AhciAtaPassThruGetNextPort
;
226 Private
->AtaPassThruPpi
.GetNextDevice
= AhciAtaPassThruGetNextDevice
;
227 Private
->AtaPassThruPpi
.GetDevicePath
= AhciAtaPassThruGetDevicePath
;
229 &Private
->AtaPassThruPpiList
,
230 &mAhciAtaPassThruPpiListTemplate
,
231 sizeof (EFI_PEI_PPI_DESCRIPTOR
)
233 Private
->AtaPassThruPpiList
.Ppi
= &Private
->AtaPassThruPpi
;
234 PeiServicesInstallPpi (&Private
->AtaPassThruPpiList
);
236 Private
->BlkIoPpi
.GetNumberOfBlockDevices
= AhciBlockIoGetDeviceNo
;
237 Private
->BlkIoPpi
.GetBlockDeviceMediaInfo
= AhciBlockIoGetMediaInfo
;
238 Private
->BlkIoPpi
.ReadBlocks
= AhciBlockIoReadBlocks
;
240 &Private
->BlkIoPpiList
,
241 &mAhciBlkIoPpiListTemplate
,
242 sizeof (EFI_PEI_PPI_DESCRIPTOR
)
244 Private
->BlkIoPpiList
.Ppi
= &Private
->BlkIoPpi
;
245 PeiServicesInstallPpi (&Private
->BlkIoPpiList
);
247 Private
->BlkIo2Ppi
.Revision
= EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION
;
248 Private
->BlkIo2Ppi
.GetNumberOfBlockDevices
= AhciBlockIoGetDeviceNo2
;
249 Private
->BlkIo2Ppi
.GetBlockDeviceMediaInfo
= AhciBlockIoGetMediaInfo2
;
250 Private
->BlkIo2Ppi
.ReadBlocks
= AhciBlockIoReadBlocks2
;
252 &Private
->BlkIo2PpiList
,
253 &mAhciBlkIo2PpiListTemplate
,
254 sizeof (EFI_PEI_PPI_DESCRIPTOR
)
256 Private
->BlkIo2PpiList
.Ppi
= &Private
->BlkIo2Ppi
;
257 PeiServicesInstallPpi (&Private
->BlkIo2PpiList
);
259 if (Private
->TrustComputingDevices
!= 0) {
262 "%a: Security Security Command PPI will be produced.\n",
265 Private
->StorageSecurityPpi
.Revision
= EDKII_STORAGE_SECURITY_PPI_REVISION
;
266 Private
->StorageSecurityPpi
.GetNumberofDevices
= AhciStorageSecurityGetDeviceNo
;
267 Private
->StorageSecurityPpi
.GetDevicePath
= AhciStorageSecurityGetDevicePath
;
268 Private
->StorageSecurityPpi
.ReceiveData
= AhciStorageSecurityReceiveData
;
269 Private
->StorageSecurityPpi
.SendData
= AhciStorageSecuritySendData
;
271 &Private
->StorageSecurityPpiList
,
272 &mAhciStorageSecurityPpiListTemplate
,
273 sizeof (EFI_PEI_PPI_DESCRIPTOR
)
275 Private
->StorageSecurityPpiList
.Ppi
= &Private
->StorageSecurityPpi
;
276 PeiServicesInstallPpi (&Private
->StorageSecurityPpiList
);
280 &Private
->EndOfPeiNotifyList
,
281 &mAhciEndOfPeiNotifyListTemplate
,
282 sizeof (EFI_PEI_NOTIFY_DESCRIPTOR
)
284 PeiServicesNotifyPpi (&Private
->EndOfPeiNotifyList
);
290 Initialize AHCI controller from EDKII_ATA_AHCI_HOST_CONTROLLER_PPI instance.
292 @param[in] AhciHcPpi Pointer to the AHCI Host Controller PPI instance.
294 @retval EFI_SUCCESS PPI successfully installed.
297 AtaAhciInitPrivateDataFromHostControllerPpi (
298 IN EDKII_ATA_AHCI_HOST_CONTROLLER_PPI
*AhciHcPpi
303 UINTN DevicePathLength
;
304 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
310 Status
= AhciHcPpi
->GetAhciHcMmioBar (
316 // When status is error, meant no controller is found.
318 if (EFI_ERROR (Status
)) {
322 Status
= AhciHcPpi
->GetAhciHcDevicePath (
328 if (EFI_ERROR (Status
)) {
331 "%a: Fail to allocate get the device path for Controller %d.\n",
338 Status
= AtaAhciInitPrivateData (MmioBase
, DevicePath
, DevicePathLength
);
339 if (EFI_ERROR (Status
)) {
342 "%a: Controller initialization fail for Controller %d with Status - %r.\n",
350 "%a: Controller %d has been successfully initialized.\n",
363 Callback for EDKII_ATA_AHCI_HOST_CONTROLLER_PPI installation.
365 @param[in] PeiServices Pointer to PEI Services Table.
366 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification
367 event that caused this function to execute.
368 @param[in] Ppi Pointer to the PPI data associated with this function.
370 @retval EFI_SUCCESS The function completes successfully
371 @retval Others Cannot initialize AHCI controller from given EDKII_ATA_AHCI_HOST_CONTROLLER_PPI
376 AtaAhciHostControllerPpiInstallationCallback (
377 IN EFI_PEI_SERVICES
**PeiServices
,
378 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
382 EDKII_ATA_AHCI_HOST_CONTROLLER_PPI
*AhciHcPpi
;
385 return EFI_INVALID_PARAMETER
;
388 AhciHcPpi
= (EDKII_ATA_AHCI_HOST_CONTROLLER_PPI
*)Ppi
;
390 return AtaAhciInitPrivateDataFromHostControllerPpi (AhciHcPpi
);
394 Initialize AHCI controller from fiven PCI_DEVICE_PPI.
396 @param[in] PciDevice Pointer to the PCI Device PPI instance.
398 @retval EFI_SUCCESS The function completes successfully
399 @retval Others Cannot initialize AHCI controller for given device
402 AtaAhciInitPrivateDataFromPciDevice (
403 EDKII_PCI_DEVICE_PPI
*PciDevice
409 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
410 UINTN DevicePathLength
;
411 UINT64 EnabledPciAttributes
;
414 // Now further check the PCI header: Base Class (offset 0x0B) and
415 // Sub Class (offset 0x0A). This controller should be an SATA controller
417 Status
= PciDevice
->PciIo
.Pci
.Read (
420 PCI_CLASSCODE_OFFSET
,
421 sizeof (PciData
.Hdr
.ClassCode
),
422 PciData
.Hdr
.ClassCode
424 if (EFI_ERROR (Status
)) {
425 return EFI_UNSUPPORTED
;
428 if (!IS_PCI_IDE (&PciData
) && !IS_PCI_SATADPA (&PciData
)) {
429 return EFI_UNSUPPORTED
;
432 Status
= PciDevice
->PciIo
.Attributes (
434 EfiPciIoAttributeOperationSupported
,
436 &EnabledPciAttributes
438 if (EFI_ERROR (Status
)) {
439 return EFI_UNSUPPORTED
;
441 EnabledPciAttributes
&= (UINT64
)EFI_PCI_DEVICE_ENABLE
;
442 Status
= PciDevice
->PciIo
.Attributes (
444 EfiPciIoAttributeOperationEnable
,
445 EnabledPciAttributes
,
448 if (EFI_ERROR (Status
)) {
449 return EFI_UNSUPPORTED
;
453 Status
= PciDevice
->PciIo
.Pci
.Read (
460 if (EFI_ERROR (Status
)) {
461 return EFI_UNSUPPORTED
;
464 MmioBase
&= 0xFFFFFFF0;
466 DevicePathLength
= GetDevicePathSize (PciDevice
->DevicePath
);
467 DevicePath
= PciDevice
->DevicePath
;
469 Status
= AtaAhciInitPrivateData (MmioBase
, DevicePath
, DevicePathLength
);
470 if (EFI_ERROR (Status
)) {
473 "%a: Failed to init controller, with Status - %r\n",
483 Callback for EDKII_PCI_DEVICE_PPI installation.
485 @param[in] PeiServices Pointer to PEI Services Table.
486 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification
487 event that caused this function to execute.
488 @param[in] Ppi Pointer to the PPI data associated with this function.
490 @retval EFI_SUCCESS The function completes successfully
491 @retval Others Cannot initialize AHCI controller from given PCI_DEVICE_PPI
496 AtaAhciPciDevicePpiInstallationCallback (
497 IN EFI_PEI_SERVICES
**PeiServices
,
498 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
502 EDKII_PCI_DEVICE_PPI
*PciDevice
;
504 PciDevice
= (EDKII_PCI_DEVICE_PPI
*)Ppi
;
506 return AtaAhciInitPrivateDataFromPciDevice (PciDevice
);
510 Entry point of the PEIM.
512 @param[in] FileHandle Handle of the file being invoked.
513 @param[in] PeiServices Describes the list of possible PEI Services.
515 @retval EFI_SUCCESS PPI successfully installed.
521 IN EFI_PEI_FILE_HANDLE FileHandle
,
522 IN CONST EFI_PEI_SERVICES
**PeiServices
525 DEBUG ((DEBUG_INFO
, "%a: Enters.\n", __FUNCTION__
));
527 PeiServicesNotifyPpi (&mAtaAhciHostControllerNotify
);
529 PeiServicesNotifyPpi (&mPciDevicePpiNotify
);