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