]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Ata/AhciPei/AhciPei.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AhciPei / AhciPei.c
CommitLineData
87bc3f19
HW
1/** @file\r
2 The AhciPei driver is used to manage ATA hard disk device working under AHCI\r
3 mode at PEI phase.\r
4\r
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
6\r
9d510e61 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
87bc3f19
HW
8\r
9**/\r
10\r
11#include "AhciPei.h"\r
12\r
13EFI_PEI_PPI_DESCRIPTOR mAhciAtaPassThruPpiListTemplate = {\r
14 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
15 &gEdkiiPeiAtaPassThruPpiGuid,\r
16 NULL\r
17};\r
18\r
19EFI_PEI_PPI_DESCRIPTOR mAhciStorageSecurityPpiListTemplate = {\r
20 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
21 &gEdkiiPeiStorageSecurityCommandPpiGuid,\r
22 NULL\r
23};\r
24\r
25EFI_PEI_NOTIFY_DESCRIPTOR mAhciEndOfPeiNotifyListTemplate = {\r
26 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
27 &gEfiEndOfPeiSignalPpiGuid,\r
28 AhciPeimEndOfPei\r
29};\r
30\r
31\r
32/**\r
33 Free the DMA resources allocated by an ATA AHCI controller.\r
34\r
35 @param[in] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA data\r
36 structure.\r
37\r
38**/\r
39VOID\r
40AhciFreeDmaResource (\r
41 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private\r
42 )\r
43{\r
44 EFI_AHCI_REGISTERS *AhciRegisters;\r
45\r
46 ASSERT (Private != NULL);\r
47\r
48 AhciRegisters = &Private->AhciRegisters;\r
49\r
50 if (AhciRegisters->AhciRFisMap != NULL) {\r
51 IoMmuFreeBuffer (\r
52 EFI_SIZE_TO_PAGES (AhciRegisters->MaxRFisSize),\r
53 AhciRegisters->AhciRFis,\r
54 AhciRegisters->AhciRFisMap\r
55 );\r
56 }\r
57\r
58 if (AhciRegisters->AhciCmdListMap != NULL) {\r
59 IoMmuFreeBuffer (\r
60 EFI_SIZE_TO_PAGES (AhciRegisters->MaxCmdListSize),\r
61 AhciRegisters->AhciCmdList,\r
62 AhciRegisters->AhciCmdListMap\r
63 );\r
64 }\r
65\r
66 if (AhciRegisters->AhciCmdTableMap != NULL) {\r
67 IoMmuFreeBuffer (\r
68 EFI_SIZE_TO_PAGES (AhciRegisters->MaxCmdTableSize),\r
69 AhciRegisters->AhciCmdTable,\r
70 AhciRegisters->AhciCmdTableMap\r
71 );\r
72 }\r
73\r
74}\r
75\r
76/**\r
77 One notified function to cleanup the allocated DMA buffers at EndOfPei.\r
78\r
79 @param[in] PeiServices Pointer to PEI Services Table.\r
80 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification\r
81 event that caused this function to execute.\r
82 @param[in] Ppi Pointer to the PPI data associated with this function.\r
83\r
84 @retval EFI_SUCCESS The function completes successfully\r
85\r
86**/\r
87EFI_STATUS\r
88EFIAPI\r
89AhciPeimEndOfPei (\r
90 IN EFI_PEI_SERVICES **PeiServices,\r
91 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
92 IN VOID *Ppi\r
93 )\r
94{\r
95 PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;\r
96\r
97 Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescriptor);\r
98 AhciFreeDmaResource (Private);\r
99\r
100 return EFI_SUCCESS;\r
101}\r
102\r
103/**\r
104 Entry point of the PEIM.\r
105\r
106 @param[in] FileHandle Handle of the file being invoked.\r
107 @param[in] PeiServices Describes the list of possible PEI Services.\r
108\r
109 @retval EFI_SUCCESS PPI successfully installed.\r
110\r
111**/\r
112EFI_STATUS\r
113EFIAPI\r
114AtaAhciPeimEntry (\r
115 IN EFI_PEI_FILE_HANDLE FileHandle,\r
116 IN CONST EFI_PEI_SERVICES **PeiServices\r
117 )\r
118{\r
119 EFI_STATUS Status;\r
120 EFI_BOOT_MODE BootMode;\r
121 EDKII_ATA_AHCI_HOST_CONTROLLER_PPI *AhciHcPpi;\r
122 UINT8 Controller;\r
123 UINTN MmioBase;\r
124 UINTN DevicePathLength;\r
125 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
126 UINT32 PortBitMap;\r
127 PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;\r
128 UINT8 NumberOfPorts;\r
129\r
130 DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));\r
131\r
132 //\r
133 // Get the current boot mode.\r
134 //\r
135 Status = PeiServicesGetBootMode (&BootMode);\r
136 if (EFI_ERROR (Status)) {\r
137 DEBUG ((DEBUG_ERROR, "%a: Fail to get the current boot mode.\n", __FUNCTION__));\r
138 return Status;\r
139 }\r
140\r
141 //\r
142 // Locate the ATA AHCI host controller PPI.\r
143 //\r
144 Status = PeiServicesLocatePpi (\r
145 &gEdkiiPeiAtaAhciHostControllerPpiGuid,\r
146 0,\r
147 NULL,\r
148 (VOID **) &AhciHcPpi\r
149 );\r
150 if (EFI_ERROR (Status)) {\r
151 DEBUG ((DEBUG_ERROR, "%a: Failed to locate AtaAhciHostControllerPpi.\n", __FUNCTION__));\r
152 return EFI_UNSUPPORTED;\r
153 }\r
154\r
155 Controller = 0;\r
156 MmioBase = 0;\r
157 while (TRUE) {\r
158 Status = AhciHcPpi->GetAhciHcMmioBar (\r
159 AhciHcPpi,\r
160 Controller,\r
161 &MmioBase\r
162 );\r
163 //\r
164 // When status is error, meant no controller is found.\r
165 //\r
166 if (EFI_ERROR (Status)) {\r
167 break;\r
168 }\r
169\r
170 Status = AhciHcPpi->GetAhciHcDevicePath (\r
171 AhciHcPpi,\r
172 Controller,\r
173 &DevicePathLength,\r
174 &DevicePath\r
175 );\r
176 if (EFI_ERROR (Status)) {\r
177 DEBUG ((\r
178 DEBUG_ERROR, "%a: Fail to allocate get the device path for Controller %d.\n",\r
179 __FUNCTION__, Controller\r
180 ));\r
181 return Status;\r
182 }\r
183\r
184 //\r
185 // Check validity of the device path of the ATA AHCI controller.\r
186 //\r
187 Status = AhciIsHcDevicePathValid (DevicePath, DevicePathLength);\r
188 if (EFI_ERROR (Status)) {\r
189 DEBUG ((\r
190 DEBUG_ERROR, "%a: The device path is invalid for Controller %d.\n",\r
191 __FUNCTION__, Controller\r
192 ));\r
193 Controller++;\r
194 continue;\r
195 }\r
196\r
197 //\r
198 // For S3 resume performance consideration, not all ports on an ATA AHCI\r
199 // controller will be enumerated/initialized. The driver consumes the\r
200 // content within S3StorageDeviceInitList LockBox to get the ports that\r
201 // will be enumerated/initialized during S3 resume.\r
202 //\r
203 if (BootMode == BOOT_ON_S3_RESUME) {\r
204 NumberOfPorts = AhciS3GetEumeratePorts (DevicePath, DevicePathLength, &PortBitMap);\r
205 if (NumberOfPorts == 0) {\r
206 //\r
207 // No ports need to be enumerated for this controller.\r
208 //\r
209 Controller++;\r
210 continue;\r
211 }\r
212 } else {\r
213 PortBitMap = MAX_UINT32;\r
214 }\r
215\r
216 //\r
217 // Memory allocation for controller private data.\r
218 //\r
219 Private = AllocateZeroPool (sizeof (PEI_AHCI_CONTROLLER_PRIVATE_DATA));\r
220 if (Private == NULL) {\r
221 DEBUG ((\r
222 DEBUG_ERROR, "%a: Fail to allocate private data for Controller %d.\n",\r
223 __FUNCTION__, Controller\r
224 ));\r
225 return EFI_OUT_OF_RESOURCES;\r
226 }\r
227\r
228 //\r
229 // Initialize controller private data.\r
230 //\r
231 Private->Signature = AHCI_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;\r
232 Private->MmioBase = MmioBase;\r
233 Private->DevicePathLength = DevicePathLength;\r
234 Private->DevicePath = DevicePath;\r
235 Private->PortBitMap = PortBitMap;\r
236 InitializeListHead (&Private->DeviceList);\r
237\r
238 Status = AhciModeInitialization (Private);\r
239 if (EFI_ERROR (Status)) {\r
240 DEBUG ((\r
241 DEBUG_ERROR,\r
242 "%a: Controller initialization fail for Controller %d with Status - %r.\n",\r
243 __FUNCTION__,\r
244 Controller,\r
245 Status\r
246 ));\r
247 Controller++;\r
248 continue;\r
249 }\r
250\r
251 Private->AtaPassThruMode.Attributes = EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL |\r
252 EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL;\r
253 Private->AtaPassThruMode.IoAlign = sizeof (UINTN);\r
254 Private->AtaPassThruPpi.Revision = EDKII_PEI_ATA_PASS_THRU_PPI_REVISION;\r
255 Private->AtaPassThruPpi.Mode = &Private->AtaPassThruMode;\r
256 Private->AtaPassThruPpi.PassThru = AhciAtaPassThruPassThru;\r
257 Private->AtaPassThruPpi.GetNextPort = AhciAtaPassThruGetNextPort;\r
258 Private->AtaPassThruPpi.GetNextDevice = AhciAtaPassThruGetNextDevice;\r
259 Private->AtaPassThruPpi.GetDevicePath = AhciAtaPassThruGetDevicePath;\r
260 CopyMem (\r
261 &Private->AtaPassThruPpiList,\r
262 &mAhciAtaPassThruPpiListTemplate,\r
263 sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
264 );\r
265 Private->AtaPassThruPpiList.Ppi = &Private->AtaPassThruPpi;\r
266 PeiServicesInstallPpi (&Private->AtaPassThruPpiList);\r
267\r
268 if (Private->TrustComputingDevices != 0) {\r
269 DEBUG ((\r
270 DEBUG_INFO,\r
271 "%a: Security Security Command PPI will be produced for Controller %d.\n",\r
272 __FUNCTION__, Controller\r
273 ));\r
274 Private->StorageSecurityPpi.Revision = EDKII_STORAGE_SECURITY_PPI_REVISION;\r
275 Private->StorageSecurityPpi.GetNumberofDevices = AhciStorageSecurityGetDeviceNo;\r
276 Private->StorageSecurityPpi.GetDevicePath = AhciStorageSecurityGetDevicePath;\r
277 Private->StorageSecurityPpi.ReceiveData = AhciStorageSecurityReceiveData;\r
278 Private->StorageSecurityPpi.SendData = AhciStorageSecuritySendData;\r
279 CopyMem (\r
280 &Private->StorageSecurityPpiList,\r
281 &mAhciStorageSecurityPpiListTemplate,\r
282 sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
283 );\r
284 Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;\r
285 PeiServicesInstallPpi (&Private->StorageSecurityPpiList);\r
286 }\r
287\r
288 CopyMem (\r
289 &Private->EndOfPeiNotifyList,\r
290 &mAhciEndOfPeiNotifyListTemplate,\r
291 sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)\r
292 );\r
293 PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);\r
294\r
295 DEBUG ((\r
296 DEBUG_INFO, "%a: Controller %d has been successfully initialized.\n",\r
297 __FUNCTION__, Controller\r
298 ));\r
299 Controller++;\r
300 }\r
301\r
302 return EFI_SUCCESS;\r
303}\r