]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/UefiLib/Acpi.c
MdePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdePkg / Library / UefiLib / Acpi.c
CommitLineData
af5e9521
SZ
1/** @file\r
2 This module provides help function for finding ACPI table.\r
3\r
4 Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
9344f092 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
af5e9521
SZ
6\r
7**/\r
8\r
9#include "UefiLibInternal.h"\r
10#include <IndustryStandard/Acpi.h>\r
11#include <Guid/Acpi.h>\r
12\r
13/**\r
14 This function scans ACPI table in XSDT/RSDT.\r
15\r
16 @param Sdt ACPI XSDT/RSDT.\r
17 @param TablePointerSize Size of table pointer: 8(XSDT) or 4(RSDT).\r
18 @param Signature ACPI table signature.\r
19 @param PreviousTable Pointer to previous returned table to locate\r
20 next table, or NULL to locate first table.\r
21 @param PreviousTableLocated Pointer to the indicator about whether the\r
22 previous returned table could be located, or\r
23 NULL if PreviousTable is NULL.\r
24\r
25 If PreviousTable is NULL and PreviousTableLocated is not NULL, then ASSERT().\r
26 If PreviousTable is not NULL and PreviousTableLocated is NULL, then ASSERT().\r
27\r
28 @return ACPI table or NULL if not found.\r
29\r
30**/\r
31EFI_ACPI_COMMON_HEADER *\r
32ScanTableInSDT (\r
33 IN EFI_ACPI_DESCRIPTION_HEADER *Sdt,\r
34 IN UINTN TablePointerSize,\r
35 IN UINT32 Signature,\r
36 IN EFI_ACPI_COMMON_HEADER *PreviousTable, OPTIONAL\r
37 OUT BOOLEAN *PreviousTableLocated OPTIONAL\r
38 )\r
39{\r
40 UINTN Index;\r
41 UINTN EntryCount;\r
42 UINT64 EntryPtr;\r
43 UINTN BasePtr;\r
44 EFI_ACPI_COMMON_HEADER *Table;\r
45\r
46 if (PreviousTableLocated != NULL) {\r
47 ASSERT (PreviousTable != NULL);\r
48 *PreviousTableLocated = FALSE;\r
49 } else {\r
50 ASSERT (PreviousTable == NULL);\r
51 }\r
52\r
53 if (Sdt == NULL) {\r
54 return NULL;\r
55 }\r
56\r
57 EntryCount = (Sdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / TablePointerSize;\r
58\r
59 BasePtr = (UINTN)(Sdt + 1);\r
60 for (Index = 0; Index < EntryCount; Index ++) {\r
61 EntryPtr = 0;\r
62 CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * TablePointerSize), TablePointerSize);\r
63 Table = (EFI_ACPI_COMMON_HEADER *)((UINTN)(EntryPtr));\r
e7ac09b9 64 if ((Table != NULL) && (Table->Signature == Signature)) {\r
af5e9521
SZ
65 if (PreviousTable != NULL) {\r
66 if (Table == PreviousTable) {\r
67 *PreviousTableLocated = TRUE;\r
68 } else if (*PreviousTableLocated) {\r
69 //\r
70 // Return next table.\r
71 //\r
72 return Table;\r
73 }\r
74 } else {\r
75 //\r
76 // Return first table.\r
77 //\r
78 return Table;\r
79 }\r
80\r
81 }\r
82 }\r
83\r
84 return NULL;\r
85}\r
86\r
87/**\r
88 To locate FACS in FADT.\r
89\r
90 @param Fadt FADT table pointer.\r
91\r
92 @return FACS table pointer or NULL if not found.\r
93\r
94**/\r
95EFI_ACPI_COMMON_HEADER *\r
96LocateAcpiFacsFromFadt (\r
97 IN EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt\r
98 )\r
99{\r
100 EFI_ACPI_COMMON_HEADER *Facs;\r
101 UINT64 Data64;\r
102\r
103 if (Fadt == NULL) {\r
104 return NULL;\r
105 }\r
106\r
107 if (Fadt->Header.Revision < EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {\r
108 Facs = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->FirmwareCtrl;\r
109 } else {\r
110 CopyMem (&Data64, &Fadt->XFirmwareCtrl, sizeof(UINT64));\r
111 if (Data64 != 0) {\r
112 Facs = (EFI_ACPI_COMMON_HEADER *)(UINTN)Data64;\r
113 } else {\r
114 Facs = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->FirmwareCtrl;\r
115 }\r
116 }\r
117 return Facs;\r
118}\r
119\r
120/**\r
121 To locate DSDT in FADT.\r
122\r
123 @param Fadt FADT table pointer.\r
124\r
125 @return DSDT table pointer or NULL if not found.\r
126\r
127**/\r
128EFI_ACPI_COMMON_HEADER *\r
129LocateAcpiDsdtFromFadt (\r
130 IN EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt\r
131 )\r
132{\r
133 EFI_ACPI_COMMON_HEADER *Dsdt;\r
134 UINT64 Data64;\r
135\r
136 if (Fadt == NULL) {\r
137 return NULL;\r
138 }\r
139\r
140 if (Fadt->Header.Revision < EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {\r
141 Dsdt = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->Dsdt;\r
142 } else {\r
143 CopyMem (&Data64, &Fadt->XDsdt, sizeof(UINT64));\r
144 if (Data64 != 0) {\r
145 Dsdt = (EFI_ACPI_COMMON_HEADER *)(UINTN)Data64;\r
146 } else {\r
147 Dsdt = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->Dsdt;\r
148 }\r
149 }\r
150 return Dsdt;\r
151}\r
152\r
153/**\r
154 To locate ACPI table in ACPI ConfigurationTable.\r
155\r
156 @param AcpiGuid The GUID used to get ACPI ConfigurationTable.\r
157 @param Signature ACPI table signature.\r
158 @param PreviousTable Pointer to previous returned table to locate\r
159 next table, or NULL to locate first table.\r
160 @param PreviousTableLocated Pointer to the indicator to return whether the\r
161 previous returned table could be located or not,\r
162 or NULL if PreviousTable is NULL.\r
163\r
164 If PreviousTable is NULL and PreviousTableLocated is not NULL, then ASSERT().\r
165 If PreviousTable is not NULL and PreviousTableLocated is NULL, then ASSERT().\r
166 If AcpiGuid is NULL, then ASSERT().\r
167\r
168 @return ACPI table or NULL if not found.\r
169\r
170**/\r
171EFI_ACPI_COMMON_HEADER *\r
172LocateAcpiTableInAcpiConfigurationTable (\r
173 IN EFI_GUID *AcpiGuid,\r
174 IN UINT32 Signature,\r
175 IN EFI_ACPI_COMMON_HEADER *PreviousTable, OPTIONAL\r
176 OUT BOOLEAN *PreviousTableLocated OPTIONAL\r
177 )\r
178{\r
179 EFI_STATUS Status;\r
180 EFI_ACPI_COMMON_HEADER *Table;\r
181 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;\r
182 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;\r
183 EFI_ACPI_DESCRIPTION_HEADER *Xsdt;\r
184 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;\r
185\r
186 if (PreviousTableLocated != NULL) {\r
187 ASSERT (PreviousTable != NULL);\r
188 *PreviousTableLocated = FALSE;\r
189 } else {\r
190 ASSERT (PreviousTable == NULL);\r
191 }\r
192\r
193 Rsdp = NULL;\r
194 //\r
195 // Get ACPI ConfigurationTable (RSD_PTR)\r
196 //\r
197 Status = EfiGetSystemConfigurationTable(AcpiGuid, (VOID **)&Rsdp);\r
198 if (EFI_ERROR (Status) || (Rsdp == NULL)) {\r
199 return NULL;\r
200 }\r
201\r
202 Table = NULL;\r
203\r
204 //\r
205 // Search XSDT\r
206 //\r
207 if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) {\r
208 Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->XsdtAddress;\r
209 if (Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {\r
210 ASSERT (PreviousTable == NULL);\r
211 //\r
212 // It is to locate DSDT,\r
213 // need to locate FADT first.\r
214 //\r
215 Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInSDT (\r
216 Xsdt,\r
217 sizeof (UINT64),\r
218 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,\r
219 NULL,\r
220 NULL\r
221 );\r
222 Table = LocateAcpiDsdtFromFadt (Fadt);\r
223 } else if (Signature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {\r
224 ASSERT (PreviousTable == NULL);\r
225 //\r
226 // It is to locate FACS,\r
227 // need to locate FADT first.\r
228 //\r
229 Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInSDT (\r
230 Xsdt,\r
231 sizeof (UINT64),\r
232 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,\r
233 NULL,\r
234 NULL\r
235 );\r
236 Table = LocateAcpiFacsFromFadt (Fadt);\r
237 } else {\r
238 Table = ScanTableInSDT (\r
239 Xsdt,\r
240 sizeof (UINT64),\r
241 Signature,\r
242 PreviousTable,\r
243 PreviousTableLocated\r
244 );\r
245 }\r
246 }\r
247\r
248 if (Table != NULL) {\r
249 return Table;\r
250 } else if ((PreviousTableLocated != NULL) &&\r
251 *PreviousTableLocated) {\r
252 //\r
253 // PreviousTable could be located in XSDT,\r
254 // but next table could not be located in XSDT.\r
255 //\r
256 return NULL;\r
257 }\r
258\r
259 //\r
260 // Search RSDT\r
261 //\r
262 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->RsdtAddress;\r
263 if (Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {\r
264 ASSERT (PreviousTable == NULL);\r
265 //\r
266 // It is to locate DSDT,\r
267 // need to locate FADT first.\r
268 //\r
269 Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInSDT (\r
270 Rsdt,\r
271 sizeof (UINT32),\r
272 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,\r
273 NULL,\r
274 NULL\r
275 );\r
276 Table = LocateAcpiDsdtFromFadt (Fadt);\r
277 } else if (Signature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {\r
278 ASSERT (PreviousTable == NULL);\r
279 //\r
280 // It is to locate FACS,\r
281 // need to locate FADT first.\r
282 //\r
283 Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInSDT (\r
284 Rsdt,\r
285 sizeof (UINT32),\r
286 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,\r
287 NULL,\r
288 NULL\r
289 );\r
290 Table = LocateAcpiFacsFromFadt (Fadt);\r
291 } else {\r
292 Table = ScanTableInSDT (\r
293 Rsdt,\r
294 sizeof (UINT32),\r
295 Signature,\r
296 PreviousTable,\r
297 PreviousTableLocated\r
298 );\r
299 }\r
300\r
301 return Table;\r
302}\r
303\r
304/**\r
305 This function locates next ACPI table in XSDT/RSDT based on Signature and\r
306 previous returned Table.\r
307\r
308 If PreviousTable is NULL:\r
309 This function will locate the first ACPI table in XSDT/RSDT based on\r
310 Signature in gEfiAcpi20TableGuid system configuration table first, and then\r
311 gEfiAcpi10TableGuid system configuration table.\r
312 This function will locate in XSDT first, and then RSDT.\r
313 For DSDT, this function will locate XDsdt in FADT first, and then Dsdt in\r
314 FADT.\r
315 For FACS, this function will locate XFirmwareCtrl in FADT first, and then\r
316 FirmwareCtrl in FADT.\r
317\r
318 If PreviousTable is not NULL:\r
319 1. If it could be located in XSDT in gEfiAcpi20TableGuid system configuration\r
320 table, then this function will just locate next table in XSDT in\r
321 gEfiAcpi20TableGuid system configuration table.\r
322 2. If it could be located in RSDT in gEfiAcpi20TableGuid system configuration\r
323 table, then this function will just locate next table in RSDT in\r
324 gEfiAcpi20TableGuid system configuration table.\r
325 3. If it could be located in RSDT in gEfiAcpi10TableGuid system configuration\r
326 table, then this function will just locate next table in RSDT in\r
327 gEfiAcpi10TableGuid system configuration table.\r
328\r
329 It's not supported that PreviousTable is not NULL but PreviousTable->Signature\r
330 is not same with Signature, NULL will be returned.\r
331\r
332 @param Signature ACPI table signature.\r
333 @param PreviousTable Pointer to previous returned table to locate next\r
334 table, or NULL to locate first table.\r
335\r
336 @return Next ACPI table or NULL if not found.\r
337\r
338**/\r
339EFI_ACPI_COMMON_HEADER *\r
340EFIAPI\r
341EfiLocateNextAcpiTable (\r
342 IN UINT32 Signature,\r
343 IN EFI_ACPI_COMMON_HEADER *PreviousTable OPTIONAL\r
344 )\r
345{\r
346 EFI_ACPI_COMMON_HEADER *Table;\r
347 BOOLEAN TempPreviousTableLocated;\r
348 BOOLEAN *PreviousTableLocated;\r
349\r
350 if (PreviousTable != NULL) {\r
351 if (PreviousTable->Signature != Signature) {\r
352 //\r
353 // PreviousTable->Signature is not same with Signature.\r
354 //\r
355 return NULL;\r
356 } else if ((Signature == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) ||\r
357 (Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) ||\r
358 (Signature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE)) {\r
359 //\r
360 // There is only one FADT/DSDT/FACS table,\r
361 // so don't try to locate next one.\r
362 //\r
363 return NULL;\r
364 }\r
365\r
366 PreviousTableLocated = &TempPreviousTableLocated;\r
367 *PreviousTableLocated = FALSE;\r
368 } else {\r
369 PreviousTableLocated = NULL;\r
370 }\r
371\r
372 Table = LocateAcpiTableInAcpiConfigurationTable (\r
373 &gEfiAcpi20TableGuid,\r
374 Signature,\r
375 PreviousTable,\r
376 PreviousTableLocated\r
377 );\r
378 if (Table != NULL) {\r
379 return Table;\r
380 } else if ((PreviousTableLocated != NULL) &&\r
381 *PreviousTableLocated) {\r
382 //\r
383 // PreviousTable could be located in gEfiAcpi20TableGuid system\r
384 // configuration table, but next table could not be located in\r
385 // gEfiAcpi20TableGuid system configuration table.\r
386 //\r
387 return NULL;\r
388 }\r
389\r
390 return LocateAcpiTableInAcpiConfigurationTable (\r
391 &gEfiAcpi10TableGuid,\r
392 Signature,\r
393 PreviousTable,\r
394 PreviousTableLocated\r
395 );\r
396}\r
397\r
398/**\r
399 This function locates first ACPI table in XSDT/RSDT based on Signature.\r
400\r
401 This function will locate the first ACPI table in XSDT/RSDT based on\r
402 Signature in gEfiAcpi20TableGuid system configuration table first, and then\r
403 gEfiAcpi10TableGuid system configuration table.\r
404 This function will locate in XSDT first, and then RSDT.\r
405 For DSDT, this function will locate XDsdt in FADT first, and then Dsdt in\r
406 FADT.\r
407 For FACS, this function will locate XFirmwareCtrl in FADT first, and then\r
408 FirmwareCtrl in FADT.\r
409\r
410 @param Signature ACPI table signature.\r
411\r
412 @return First ACPI table or NULL if not found.\r
413\r
414**/\r
415EFI_ACPI_COMMON_HEADER *\r
416EFIAPI\r
417EfiLocateFirstAcpiTable (\r
418 IN UINT32 Signature\r
419 )\r
420{\r
421 return EfiLocateNextAcpiTable (Signature, NULL);\r
422}\r