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