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