xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/tables/tbutils.c (revision 44d19f4d32b8f7e9c01f00294c87ca5cc2e057f7)
1 /******************************************************************************
2  *
3  * Module Name: tbutils - ACPI Table utilities
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2016, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115 
116 #include "acpi.h"
117 #include "accommon.h"
118 #include "actables.h"
119 
120 #define _COMPONENT          ACPI_TABLES
121         ACPI_MODULE_NAME    ("tbutils")
122 
123 
124 /* Local prototypes */
125 
126 static ACPI_PHYSICAL_ADDRESS
127 AcpiTbGetRootTableEntry (
128     UINT8                   *TableEntry,
129     UINT32                  TableEntrySize);
130 
131 
132 #if (!ACPI_REDUCED_HARDWARE)
133 /*******************************************************************************
134  *
135  * FUNCTION:    AcpiTbInitializeFacs
136  *
137  * PARAMETERS:  None
138  *
139  * RETURN:      Status
140  *
141  * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global
142  *              for accessing the Global Lock and Firmware Waking Vector
143  *
144  ******************************************************************************/
145 
146 ACPI_STATUS
147 AcpiTbInitializeFacs (
148     void)
149 {
150     ACPI_TABLE_FACS         *Facs;
151 
152 
153     /* If Hardware Reduced flag is set, there is no FACS */
154 
155     if (AcpiGbl_ReducedHardware)
156     {
157         AcpiGbl_FACS = NULL;
158         return (AE_OK);
159     }
160     else if (AcpiGbl_FADT.XFacs &&
161          (!AcpiGbl_FADT.Facs || !AcpiGbl_Use32BitFacsAddresses))
162     {
163         (void) AcpiGetTableByIndex (AcpiGbl_XFacsIndex,
164             ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Facs));
165         AcpiGbl_FACS = Facs;
166     }
167     else if (AcpiGbl_FADT.Facs)
168     {
169         (void) AcpiGetTableByIndex (AcpiGbl_FacsIndex,
170             ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Facs));
171         AcpiGbl_FACS = Facs;
172     }
173 
174     /* If there is no FACS, just continue. There was already an error msg */
175 
176     return (AE_OK);
177 }
178 #endif /* !ACPI_REDUCED_HARDWARE */
179 
180 
181 /*******************************************************************************
182  *
183  * FUNCTION:    AcpiTbCheckDsdtHeader
184  *
185  * PARAMETERS:  None
186  *
187  * RETURN:      None
188  *
189  * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect
190  *              if the DSDT has been replaced from outside the OS and/or if
191  *              the DSDT header has been corrupted.
192  *
193  ******************************************************************************/
194 
195 void
196 AcpiTbCheckDsdtHeader (
197     void)
198 {
199 
200     /* Compare original length and checksum to current values */
201 
202     if (AcpiGbl_OriginalDsdtHeader.Length != AcpiGbl_DSDT->Length ||
203         AcpiGbl_OriginalDsdtHeader.Checksum != AcpiGbl_DSDT->Checksum)
204     {
205         ACPI_BIOS_ERROR ((AE_INFO,
206             "The DSDT has been corrupted or replaced - "
207             "old, new headers below"));
208 
209         AcpiTbPrintTableHeader (0, &AcpiGbl_OriginalDsdtHeader);
210         AcpiTbPrintTableHeader (0, AcpiGbl_DSDT);
211 
212         /* Disable further error messages */
213 
214         AcpiGbl_OriginalDsdtHeader.Length = AcpiGbl_DSDT->Length;
215         AcpiGbl_OriginalDsdtHeader.Checksum = AcpiGbl_DSDT->Checksum;
216     }
217 }
218 
219 
220 /*******************************************************************************
221  *
222  * FUNCTION:    AcpiTbCopyDsdt
223  *
224  * PARAMETERS:  TableDesc           - Installed table to copy
225  *
226  * RETURN:      None
227  *
228  * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory.
229  *              Some very bad BIOSs are known to either corrupt the DSDT or
230  *              install a new, bad DSDT. This copy works around the problem.
231  *
232  ******************************************************************************/
233 
234 ACPI_TABLE_HEADER *
235 AcpiTbCopyDsdt (
236     UINT32                  TableIndex)
237 {
238     ACPI_TABLE_HEADER       *NewTable;
239     ACPI_TABLE_DESC         *TableDesc;
240 
241 
242     TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex];
243 
244     NewTable = ACPI_ALLOCATE (TableDesc->Length);
245     if (!NewTable)
246     {
247         ACPI_ERROR ((AE_INFO, "Could not copy DSDT of length 0x%X",
248             TableDesc->Length));
249         return (NULL);
250     }
251 
252     memcpy (NewTable, TableDesc->Pointer, TableDesc->Length);
253     AcpiTbUninstallTable (TableDesc);
254 
255     AcpiTbInitTableDescriptor (
256         &AcpiGbl_RootTableList.Tables[AcpiGbl_DsdtIndex],
257         ACPI_PTR_TO_PHYSADDR (NewTable),
258         ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, NewTable);
259 
260     ACPI_INFO ((AE_INFO,
261         "Forced DSDT copy: length 0x%05X copied locally, original unmapped",
262         NewTable->Length));
263 
264     return (NewTable);
265 }
266 
267 
268 /*******************************************************************************
269  *
270  * FUNCTION:    AcpiTbGetRootTableEntry
271  *
272  * PARAMETERS:  TableEntry          - Pointer to the RSDT/XSDT table entry
273  *              TableEntrySize      - sizeof 32 or 64 (RSDT or XSDT)
274  *
275  * RETURN:      Physical address extracted from the root table
276  *
277  * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on
278  *              both 32-bit and 64-bit platforms
279  *
280  * NOTE:        ACPI_PHYSICAL_ADDRESS is 32-bit on 32-bit platforms, 64-bit on
281  *              64-bit platforms.
282  *
283  ******************************************************************************/
284 
285 static ACPI_PHYSICAL_ADDRESS
286 AcpiTbGetRootTableEntry (
287     UINT8                   *TableEntry,
288     UINT32                  TableEntrySize)
289 {
290     UINT64                  Address64;
291 
292 
293     /*
294      * Get the table physical address (32-bit for RSDT, 64-bit for XSDT):
295      * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT
296      */
297     if (TableEntrySize == ACPI_RSDT_ENTRY_SIZE)
298     {
299         /*
300          * 32-bit platform, RSDT: Return 32-bit table entry
301          * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return
302          */
303         return ((ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST_PTR (
304             UINT32, TableEntry)));
305     }
306     else
307     {
308         /*
309          * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return
310          * 64-bit platform, XSDT: Move (unaligned) 64-bit to local,
311          *  return 64-bit
312          */
313         ACPI_MOVE_64_TO_64 (&Address64, TableEntry);
314 
315 #if ACPI_MACHINE_WIDTH == 32
316         if (Address64 > ACPI_UINT32_MAX)
317         {
318             /* Will truncate 64-bit address to 32 bits, issue warning */
319 
320             ACPI_BIOS_WARNING ((AE_INFO,
321                 "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X),"
322                 " truncating",
323                 ACPI_FORMAT_UINT64 (Address64)));
324         }
325 #endif
326         return ((ACPI_PHYSICAL_ADDRESS) (Address64));
327     }
328 }
329 
330 
331 /*******************************************************************************
332  *
333  * FUNCTION:    AcpiTbParseRootTable
334  *
335  * PARAMETERS:  Rsdp                    - Pointer to the RSDP
336  *
337  * RETURN:      Status
338  *
339  * DESCRIPTION: This function is called to parse the Root System Description
340  *              Table (RSDT or XSDT)
341  *
342  * NOTE:        Tables are mapped (not copied) for efficiency. The FACS must
343  *              be mapped and cannot be copied because it contains the actual
344  *              memory location of the ACPI Global Lock.
345  *
346  ******************************************************************************/
347 
348 ACPI_STATUS
349 AcpiTbParseRootTable (
350     ACPI_PHYSICAL_ADDRESS   RsdpAddress)
351 {
352     ACPI_TABLE_RSDP         *Rsdp;
353     UINT32                  TableEntrySize;
354     UINT32                  i;
355     UINT32                  TableCount;
356     ACPI_TABLE_HEADER       *Table;
357     ACPI_PHYSICAL_ADDRESS   Address;
358     UINT32                  Length;
359     UINT8                   *TableEntry;
360     ACPI_STATUS             Status;
361     UINT32                  TableIndex;
362 
363 
364     ACPI_FUNCTION_TRACE (TbParseRootTable);
365 
366 
367     /* Map the entire RSDP and extract the address of the RSDT or XSDT */
368 
369     Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP));
370     if (!Rsdp)
371     {
372         return_ACPI_STATUS (AE_NO_MEMORY);
373     }
374 
375     AcpiTbPrintTableHeader (RsdpAddress,
376         ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp));
377 
378     /* Use XSDT if present and not overridden. Otherwise, use RSDT */
379 
380     if ((Rsdp->Revision > 1) &&
381         Rsdp->XsdtPhysicalAddress &&
382         !AcpiGbl_DoNotUseXsdt)
383     {
384         /*
385          * RSDP contains an XSDT (64-bit physical addresses). We must use
386          * the XSDT if the revision is > 1 and the XSDT pointer is present,
387          * as per the ACPI specification.
388          */
389         Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress;
390         TableEntrySize = ACPI_XSDT_ENTRY_SIZE;
391     }
392     else
393     {
394         /* Root table is an RSDT (32-bit physical addresses) */
395 
396         Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress;
397         TableEntrySize = ACPI_RSDT_ENTRY_SIZE;
398     }
399 
400     /*
401      * It is not possible to map more than one entry in some environments,
402      * so unmap the RSDP here before mapping other tables
403      */
404     AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP));
405 
406     /* Map the RSDT/XSDT table header to get the full table length */
407 
408     Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
409     if (!Table)
410     {
411         return_ACPI_STATUS (AE_NO_MEMORY);
412     }
413 
414     AcpiTbPrintTableHeader (Address, Table);
415 
416     /*
417      * Validate length of the table, and map entire table.
418      * Minimum length table must contain at least one entry.
419      */
420     Length = Table->Length;
421     AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER));
422 
423     if (Length < (sizeof (ACPI_TABLE_HEADER) + TableEntrySize))
424     {
425         ACPI_BIOS_ERROR ((AE_INFO,
426             "Invalid table length 0x%X in RSDT/XSDT", Length));
427         return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
428     }
429 
430     Table = AcpiOsMapMemory (Address, Length);
431     if (!Table)
432     {
433         return_ACPI_STATUS (AE_NO_MEMORY);
434     }
435 
436     /* Validate the root table checksum */
437 
438     Status = AcpiTbVerifyChecksum (Table, Length);
439     if (ACPI_FAILURE (Status))
440     {
441         AcpiOsUnmapMemory (Table, Length);
442         return_ACPI_STATUS (Status);
443     }
444 
445     /* Get the number of entries and pointer to first entry */
446 
447     TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) /
448         TableEntrySize);
449     TableEntry = ACPI_ADD_PTR (UINT8, Table, sizeof (ACPI_TABLE_HEADER));
450 
451     /* Initialize the root table array from the RSDT/XSDT */
452 
453     for (i = 0; i < TableCount; i++)
454     {
455         /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
456 
457         Address = AcpiTbGetRootTableEntry (TableEntry, TableEntrySize);
458 
459         /* Skip NULL entries in RSDT/XSDT */
460 
461         if (!Address)
462         {
463             goto NextTable;
464         }
465 
466         Status = AcpiTbInstallStandardTable (Address,
467             ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, FALSE, TRUE, &TableIndex);
468 
469         if (ACPI_SUCCESS (Status) &&
470             ACPI_COMPARE_NAME (
471                 &AcpiGbl_RootTableList.Tables[TableIndex].Signature,
472                 ACPI_SIG_FADT))
473         {
474             AcpiGbl_FadtIndex = TableIndex;
475             AcpiTbParseFadt ();
476         }
477 
478 NextTable:
479 
480         TableEntry += TableEntrySize;
481     }
482 
483     AcpiOsUnmapMemory (Table, Length);
484     return_ACPI_STATUS (AE_OK);
485 }
486 
487 
488 /*******************************************************************************
489  *
490  * FUNCTION:    AcpiIsValidSignature
491  *
492  * PARAMETERS:  Signature           - Sig string to be validated
493  *
494  * RETURN:      TRUE if signature is has 4 valid ACPI characters
495  *
496  * DESCRIPTION: Validate an ACPI table signature.
497  *
498  ******************************************************************************/
499 
500 BOOLEAN
501 AcpiIsValidSignature (
502     char                    *Signature)
503 {
504     UINT32                  i;
505 
506 
507     /* Validate each character in the signature */
508 
509     for (i = 0; i < ACPI_NAME_SIZE; i++)
510     {
511         if (!AcpiUtValidAcpiChar (Signature[i], i))
512         {
513             return (FALSE);
514         }
515     }
516 
517     return (TRUE);
518 }
519