xref: /freebsd/sys/contrib/dev/acpica/components/tables/tbutils.c (revision bd18fd57db1df29da1a3adf94d47924a977a29c2)
1 /******************************************************************************
2  *
3  * Module Name: tbutils - ACPI Table utilities
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/actables.h>
47 
48 #define _COMPONENT          ACPI_TABLES
49         ACPI_MODULE_NAME    ("tbutils")
50 
51 
52 /* Local prototypes */
53 
54 static ACPI_PHYSICAL_ADDRESS
55 AcpiTbGetRootTableEntry (
56     UINT8                   *TableEntry,
57     UINT32                  TableEntrySize);
58 
59 
60 #if (!ACPI_REDUCED_HARDWARE)
61 /*******************************************************************************
62  *
63  * FUNCTION:    AcpiTbInitializeFacs
64  *
65  * PARAMETERS:  None
66  *
67  * RETURN:      Status
68  *
69  * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global
70  *              for accessing the Global Lock and Firmware Waking Vector
71  *
72  ******************************************************************************/
73 
74 ACPI_STATUS
75 AcpiTbInitializeFacs (
76     void)
77 {
78     ACPI_TABLE_FACS         *Facs;
79 
80 
81     /* If Hardware Reduced flag is set, there is no FACS */
82 
83     if (AcpiGbl_ReducedHardware)
84     {
85         AcpiGbl_FACS = NULL;
86         return (AE_OK);
87     }
88     else if (AcpiGbl_FADT.XFacs &&
89              (!AcpiGbl_FADT.Facs || !AcpiGbl_Use32BitFacsAddresses))
90     {
91         (void) AcpiGetTableByIndex (AcpiGbl_XFacsIndex,
92                     ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Facs));
93         AcpiGbl_FACS = Facs;
94     }
95     else if (AcpiGbl_FADT.Facs)
96     {
97         (void) AcpiGetTableByIndex (AcpiGbl_FacsIndex,
98                     ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Facs));
99         AcpiGbl_FACS = Facs;
100     }
101 
102     /* If there is no FACS, just continue. There was already an error msg */
103 
104     return (AE_OK);
105 }
106 #endif /* !ACPI_REDUCED_HARDWARE */
107 
108 
109 /*******************************************************************************
110  *
111  * FUNCTION:    AcpiTbTablesLoaded
112  *
113  * PARAMETERS:  None
114  *
115  * RETURN:      TRUE if required ACPI tables are loaded
116  *
117  * DESCRIPTION: Determine if the minimum required ACPI tables are present
118  *              (FADT, FACS, DSDT)
119  *
120  ******************************************************************************/
121 
122 BOOLEAN
123 AcpiTbTablesLoaded (
124     void)
125 {
126 
127     if (AcpiGbl_RootTableList.CurrentTableCount >= 4)
128     {
129         return (TRUE);
130     }
131 
132     return (FALSE);
133 }
134 
135 
136 /*******************************************************************************
137  *
138  * FUNCTION:    AcpiTbCheckDsdtHeader
139  *
140  * PARAMETERS:  None
141  *
142  * RETURN:      None
143  *
144  * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect
145  *              if the DSDT has been replaced from outside the OS and/or if
146  *              the DSDT header has been corrupted.
147  *
148  ******************************************************************************/
149 
150 void
151 AcpiTbCheckDsdtHeader (
152     void)
153 {
154 
155     /* Compare original length and checksum to current values */
156 
157     if (AcpiGbl_OriginalDsdtHeader.Length != AcpiGbl_DSDT->Length ||
158         AcpiGbl_OriginalDsdtHeader.Checksum != AcpiGbl_DSDT->Checksum)
159     {
160         ACPI_BIOS_ERROR ((AE_INFO,
161             "The DSDT has been corrupted or replaced - "
162             "old, new headers below"));
163         AcpiTbPrintTableHeader (0, &AcpiGbl_OriginalDsdtHeader);
164         AcpiTbPrintTableHeader (0, AcpiGbl_DSDT);
165 
166         /* Disable further error messages */
167 
168         AcpiGbl_OriginalDsdtHeader.Length = AcpiGbl_DSDT->Length;
169         AcpiGbl_OriginalDsdtHeader.Checksum = AcpiGbl_DSDT->Checksum;
170     }
171 }
172 
173 
174 /*******************************************************************************
175  *
176  * FUNCTION:    AcpiTbCopyDsdt
177  *
178  * PARAMETERS:  TableDesc           - Installed table to copy
179  *
180  * RETURN:      None
181  *
182  * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory.
183  *              Some very bad BIOSs are known to either corrupt the DSDT or
184  *              install a new, bad DSDT. This copy works around the problem.
185  *
186  ******************************************************************************/
187 
188 ACPI_TABLE_HEADER *
189 AcpiTbCopyDsdt (
190     UINT32                  TableIndex)
191 {
192     ACPI_TABLE_HEADER       *NewTable;
193     ACPI_TABLE_DESC         *TableDesc;
194 
195 
196     TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex];
197 
198     NewTable = ACPI_ALLOCATE (TableDesc->Length);
199     if (!NewTable)
200     {
201         ACPI_ERROR ((AE_INFO, "Could not copy DSDT of length 0x%X",
202             TableDesc->Length));
203         return (NULL);
204     }
205 
206     memcpy (NewTable, TableDesc->Pointer, TableDesc->Length);
207     AcpiTbUninstallTable (TableDesc);
208 
209     AcpiTbInitTableDescriptor (
210         &AcpiGbl_RootTableList.Tables[AcpiGbl_DsdtIndex],
211         ACPI_PTR_TO_PHYSADDR (NewTable), ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
212         NewTable);
213 
214     ACPI_INFO ((AE_INFO,
215         "Forced DSDT copy: length 0x%05X copied locally, original unmapped",
216         NewTable->Length));
217 
218     return (NewTable);
219 }
220 
221 
222 /*******************************************************************************
223  *
224  * FUNCTION:    AcpiTbGetRootTableEntry
225  *
226  * PARAMETERS:  TableEntry          - Pointer to the RSDT/XSDT table entry
227  *              TableEntrySize      - sizeof 32 or 64 (RSDT or XSDT)
228  *
229  * RETURN:      Physical address extracted from the root table
230  *
231  * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on
232  *              both 32-bit and 64-bit platforms
233  *
234  * NOTE:        ACPI_PHYSICAL_ADDRESS is 32-bit on 32-bit platforms, 64-bit on
235  *              64-bit platforms.
236  *
237  ******************************************************************************/
238 
239 static ACPI_PHYSICAL_ADDRESS
240 AcpiTbGetRootTableEntry (
241     UINT8                   *TableEntry,
242     UINT32                  TableEntrySize)
243 {
244     UINT64                  Address64;
245 
246 
247     /*
248      * Get the table physical address (32-bit for RSDT, 64-bit for XSDT):
249      * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT
250      */
251     if (TableEntrySize == ACPI_RSDT_ENTRY_SIZE)
252     {
253         /*
254          * 32-bit platform, RSDT: Return 32-bit table entry
255          * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return
256          */
257         return ((ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST_PTR (UINT32, TableEntry)));
258     }
259     else
260     {
261         /*
262          * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return
263          * 64-bit platform, XSDT: Move (unaligned) 64-bit to local,
264          *  return 64-bit
265          */
266         ACPI_MOVE_64_TO_64 (&Address64, TableEntry);
267 
268 #if ACPI_MACHINE_WIDTH == 32
269         if (Address64 > ACPI_UINT32_MAX)
270         {
271             /* Will truncate 64-bit address to 32 bits, issue warning */
272 
273             ACPI_BIOS_WARNING ((AE_INFO,
274                 "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X),"
275                 " truncating",
276                 ACPI_FORMAT_UINT64 (Address64)));
277         }
278 #endif
279         return ((ACPI_PHYSICAL_ADDRESS) (Address64));
280     }
281 }
282 
283 
284 /*******************************************************************************
285  *
286  * FUNCTION:    AcpiTbParseRootTable
287  *
288  * PARAMETERS:  Rsdp                    - Pointer to the RSDP
289  *
290  * RETURN:      Status
291  *
292  * DESCRIPTION: This function is called to parse the Root System Description
293  *              Table (RSDT or XSDT)
294  *
295  * NOTE:        Tables are mapped (not copied) for efficiency. The FACS must
296  *              be mapped and cannot be copied because it contains the actual
297  *              memory location of the ACPI Global Lock.
298  *
299  ******************************************************************************/
300 
301 ACPI_STATUS
302 AcpiTbParseRootTable (
303     ACPI_PHYSICAL_ADDRESS   RsdpAddress)
304 {
305     ACPI_TABLE_RSDP         *Rsdp;
306     UINT32                  TableEntrySize;
307     UINT32                  i;
308     UINT32                  TableCount;
309     ACPI_TABLE_HEADER       *Table;
310     ACPI_PHYSICAL_ADDRESS   Address;
311     UINT32                  Length;
312     UINT8                   *TableEntry;
313     ACPI_STATUS             Status;
314     UINT32                  TableIndex;
315 
316 
317     ACPI_FUNCTION_TRACE (TbParseRootTable);
318 
319 
320     /* Map the entire RSDP and extract the address of the RSDT or XSDT */
321 
322     Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP));
323     if (!Rsdp)
324     {
325         return_ACPI_STATUS (AE_NO_MEMORY);
326     }
327 
328     AcpiTbPrintTableHeader (RsdpAddress,
329         ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp));
330 
331     /* Use XSDT if present and not overridden. Otherwise, use RSDT */
332 
333     if ((Rsdp->Revision > 1) &&
334         Rsdp->XsdtPhysicalAddress &&
335         !AcpiGbl_DoNotUseXsdt)
336     {
337         /*
338          * RSDP contains an XSDT (64-bit physical addresses). We must use
339          * the XSDT if the revision is > 1 and the XSDT pointer is present,
340          * as per the ACPI specification.
341          */
342         Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress;
343         TableEntrySize = ACPI_XSDT_ENTRY_SIZE;
344     }
345     else
346     {
347         /* Root table is an RSDT (32-bit physical addresses) */
348 
349         Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress;
350         TableEntrySize = ACPI_RSDT_ENTRY_SIZE;
351     }
352 
353     /*
354      * It is not possible to map more than one entry in some environments,
355      * so unmap the RSDP here before mapping other tables
356      */
357     AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP));
358 
359     /* Map the RSDT/XSDT table header to get the full table length */
360 
361     Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
362     if (!Table)
363     {
364         return_ACPI_STATUS (AE_NO_MEMORY);
365     }
366 
367     AcpiTbPrintTableHeader (Address, Table);
368 
369     /*
370      * Validate length of the table, and map entire table.
371      * Minimum length table must contain at least one entry.
372      */
373     Length = Table->Length;
374     AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER));
375 
376     if (Length < (sizeof (ACPI_TABLE_HEADER) + TableEntrySize))
377     {
378         ACPI_BIOS_ERROR ((AE_INFO,
379             "Invalid table length 0x%X in RSDT/XSDT", Length));
380         return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
381     }
382 
383     Table = AcpiOsMapMemory (Address, Length);
384     if (!Table)
385     {
386         return_ACPI_STATUS (AE_NO_MEMORY);
387     }
388 
389     /* Validate the root table checksum */
390 
391     Status = AcpiTbVerifyChecksum (Table, Length);
392     if (ACPI_FAILURE (Status))
393     {
394         AcpiOsUnmapMemory (Table, Length);
395         return_ACPI_STATUS (Status);
396     }
397 
398     /* Get the number of entries and pointer to first entry */
399 
400     TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) /
401         TableEntrySize);
402     TableEntry = ACPI_ADD_PTR (UINT8, Table, sizeof (ACPI_TABLE_HEADER));
403 
404     /* Initialize the root table array from the RSDT/XSDT */
405 
406     for (i = 0; i < TableCount; i++)
407     {
408         /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
409 
410         Address = AcpiTbGetRootTableEntry (TableEntry, TableEntrySize);
411 
412         /* Skip NULL entries in RSDT/XSDT */
413 
414         if (!Address)
415         {
416             goto NextTable;
417         }
418 
419         Status = AcpiTbInstallStandardTable (Address,
420             ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, FALSE, TRUE, &TableIndex);
421 
422         if (ACPI_SUCCESS (Status) &&
423             ACPI_COMPARE_NAME (&AcpiGbl_RootTableList.Tables[TableIndex].Signature,
424                 ACPI_SIG_FADT))
425         {
426             AcpiTbParseFadt (TableIndex);
427         }
428 
429 NextTable:
430 
431         TableEntry += TableEntrySize;
432     }
433 
434     AcpiOsUnmapMemory (Table, Length);
435 
436     return_ACPI_STATUS (AE_OK);
437 }
438 
439 
440 /*******************************************************************************
441  *
442  * FUNCTION:    AcpiIsValidSignature
443  *
444  * PARAMETERS:  Signature           - Sig string to be validated
445  *
446  * RETURN:      TRUE if signature is correct length and has valid characters
447  *
448  * DESCRIPTION: Validate an ACPI table signature.
449  *
450  ******************************************************************************/
451 
452 BOOLEAN
453 AcpiIsValidSignature (
454     char                    *Signature)
455 {
456     UINT32                  i;
457 
458 
459     /* Validate the signature length */
460 
461     if (strlen (Signature) != ACPI_NAME_SIZE)
462     {
463         return (FALSE);
464     }
465 
466     /* Validate each character in the signature */
467 
468     for (i = 0; i < ACPI_NAME_SIZE; i++)
469     {
470         if (!AcpiUtValidAcpiChar (Signature[i], i))
471         {
472             return (FALSE);
473         }
474     }
475 
476     return (TRUE);
477 }
478