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