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