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