1149703c7Sjruoho /******************************************************************************
2149703c7Sjruoho  *
333841f6dSchristos  * Module Name: tbutils - ACPI Table utilities
4149703c7Sjruoho  *
5149703c7Sjruoho  *****************************************************************************/
6149703c7Sjruoho 
77af23240Sjruoho /*
8ec12a2faSchristos  * Copyright (C) 2000 - 2022, Intel Corp.
9149703c7Sjruoho  * All rights reserved.
10149703c7Sjruoho  *
117af23240Sjruoho  * Redistribution and use in source and binary forms, with or without
127af23240Sjruoho  * modification, are permitted provided that the following conditions
137af23240Sjruoho  * are met:
147af23240Sjruoho  * 1. Redistributions of source code must retain the above copyright
157af23240Sjruoho  *    notice, this list of conditions, and the following disclaimer,
167af23240Sjruoho  *    without modification.
177af23240Sjruoho  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
187af23240Sjruoho  *    substantially similar to the "NO WARRANTY" disclaimer below
197af23240Sjruoho  *    ("Disclaimer") and any redistribution must be conditioned upon
207af23240Sjruoho  *    including a substantially similar Disclaimer requirement for further
217af23240Sjruoho  *    binary redistribution.
227af23240Sjruoho  * 3. Neither the names of the above-listed copyright holders nor the names
237af23240Sjruoho  *    of any contributors may be used to endorse or promote products derived
247af23240Sjruoho  *    from this software without specific prior written permission.
25149703c7Sjruoho  *
267af23240Sjruoho  * Alternatively, this software may be distributed under the terms of the
277af23240Sjruoho  * GNU General Public License ("GPL") version 2 as published by the Free
287af23240Sjruoho  * Software Foundation.
29149703c7Sjruoho  *
307af23240Sjruoho  * NO WARRANTY
317af23240Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
327af23240Sjruoho  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33adee7055Schristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
347af23240Sjruoho  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
357af23240Sjruoho  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
367af23240Sjruoho  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
377af23240Sjruoho  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
387af23240Sjruoho  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
397af23240Sjruoho  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
407af23240Sjruoho  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
417af23240Sjruoho  * POSSIBILITY OF SUCH DAMAGES.
427af23240Sjruoho  */
43149703c7Sjruoho 
44149703c7Sjruoho #include "acpi.h"
45149703c7Sjruoho #include "accommon.h"
46149703c7Sjruoho #include "actables.h"
47149703c7Sjruoho 
48149703c7Sjruoho #define _COMPONENT          ACPI_TABLES
49149703c7Sjruoho         ACPI_MODULE_NAME    ("tbutils")
50149703c7Sjruoho 
5133841f6dSchristos 
52149703c7Sjruoho /* Local prototypes */
53149703c7Sjruoho 
54149703c7Sjruoho static ACPI_PHYSICAL_ADDRESS
55149703c7Sjruoho AcpiTbGetRootTableEntry (
56149703c7Sjruoho     UINT8                   *TableEntry,
57149703c7Sjruoho     UINT32                  TableEntrySize);
58149703c7Sjruoho 
59149703c7Sjruoho 
6033841f6dSchristos #if (!ACPI_REDUCED_HARDWARE)
61149703c7Sjruoho /*******************************************************************************
62149703c7Sjruoho  *
63149703c7Sjruoho  * FUNCTION:    AcpiTbInitializeFacs
64149703c7Sjruoho  *
65149703c7Sjruoho  * PARAMETERS:  None
66149703c7Sjruoho  *
67149703c7Sjruoho  * RETURN:      Status
68149703c7Sjruoho  *
69149703c7Sjruoho  * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global
70149703c7Sjruoho  *              for accessing the Global Lock and Firmware Waking Vector
71149703c7Sjruoho  *
72149703c7Sjruoho  ******************************************************************************/
73149703c7Sjruoho 
74149703c7Sjruoho ACPI_STATUS
AcpiTbInitializeFacs(void)75149703c7Sjruoho AcpiTbInitializeFacs (
76149703c7Sjruoho     void)
77149703c7Sjruoho {
7894e0d463Schristos     ACPI_TABLE_FACS         *Facs;
7994e0d463Schristos 
80149703c7Sjruoho 
8133841f6dSchristos     /* If Hardware Reduced flag is set, there is no FACS */
8233841f6dSchristos 
8333841f6dSchristos     if (AcpiGbl_ReducedHardware)
8433841f6dSchristos     {
8533841f6dSchristos         AcpiGbl_FACS = NULL;
8633841f6dSchristos         return (AE_OK);
8733841f6dSchristos     }
8894e0d463Schristos     else if (AcpiGbl_FADT.XFacs &&
8994e0d463Schristos          (!AcpiGbl_FADT.Facs || !AcpiGbl_Use32BitFacsAddresses))
90e34402d4Schristos     {
9194e0d463Schristos         (void) AcpiGetTableByIndex (AcpiGbl_XFacsIndex,
9294e0d463Schristos             ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Facs));
9394e0d463Schristos         AcpiGbl_FACS = Facs;
94e34402d4Schristos     }
9594e0d463Schristos     else if (AcpiGbl_FADT.Facs)
96e34402d4Schristos     {
9794e0d463Schristos         (void) AcpiGetTableByIndex (AcpiGbl_FacsIndex,
9894e0d463Schristos             ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Facs));
9994e0d463Schristos         AcpiGbl_FACS = Facs;
100e34402d4Schristos     }
101e34402d4Schristos 
102e34402d4Schristos     /* If there is no FACS, just continue. There was already an error msg */
103e34402d4Schristos 
104e34402d4Schristos     return (AE_OK);
105149703c7Sjruoho }
10633841f6dSchristos #endif /* !ACPI_REDUCED_HARDWARE */
107149703c7Sjruoho 
108149703c7Sjruoho 
109149703c7Sjruoho /*******************************************************************************
110149703c7Sjruoho  *
111149703c7Sjruoho  * FUNCTION:    AcpiTbCheckDsdtHeader
112149703c7Sjruoho  *
113149703c7Sjruoho  * PARAMETERS:  None
114149703c7Sjruoho  *
115149703c7Sjruoho  * RETURN:      None
116149703c7Sjruoho  *
117149703c7Sjruoho  * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect
118149703c7Sjruoho  *              if the DSDT has been replaced from outside the OS and/or if
119149703c7Sjruoho  *              the DSDT header has been corrupted.
120149703c7Sjruoho  *
121149703c7Sjruoho  ******************************************************************************/
122149703c7Sjruoho 
123149703c7Sjruoho void
AcpiTbCheckDsdtHeader(void)124149703c7Sjruoho AcpiTbCheckDsdtHeader (
125149703c7Sjruoho     void)
126149703c7Sjruoho {
127149703c7Sjruoho 
128149703c7Sjruoho     /* Compare original length and checksum to current values */
129149703c7Sjruoho 
130149703c7Sjruoho     if (AcpiGbl_OriginalDsdtHeader.Length != AcpiGbl_DSDT->Length ||
131149703c7Sjruoho         AcpiGbl_OriginalDsdtHeader.Checksum != AcpiGbl_DSDT->Checksum)
132149703c7Sjruoho     {
13333841f6dSchristos         ACPI_BIOS_ERROR ((AE_INFO,
13433841f6dSchristos             "The DSDT has been corrupted or replaced - "
13533841f6dSchristos             "old, new headers below"));
13694e0d463Schristos 
137149703c7Sjruoho         AcpiTbPrintTableHeader (0, &AcpiGbl_OriginalDsdtHeader);
138149703c7Sjruoho         AcpiTbPrintTableHeader (0, AcpiGbl_DSDT);
139149703c7Sjruoho 
140149703c7Sjruoho         /* Disable further error messages */
141149703c7Sjruoho 
142149703c7Sjruoho         AcpiGbl_OriginalDsdtHeader.Length = AcpiGbl_DSDT->Length;
143149703c7Sjruoho         AcpiGbl_OriginalDsdtHeader.Checksum = AcpiGbl_DSDT->Checksum;
144149703c7Sjruoho     }
145149703c7Sjruoho }
146149703c7Sjruoho 
147149703c7Sjruoho 
148149703c7Sjruoho /*******************************************************************************
149149703c7Sjruoho  *
150149703c7Sjruoho  * FUNCTION:    AcpiTbCopyDsdt
151149703c7Sjruoho  *
15235a687ffSchristos  * PARAMETERS:  TableIndex          - Index of installed table to copy
153149703c7Sjruoho  *
15435a687ffSchristos  * RETURN:      The copied DSDT
155149703c7Sjruoho  *
156149703c7Sjruoho  * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory.
157149703c7Sjruoho  *              Some very bad BIOSs are known to either corrupt the DSDT or
158149703c7Sjruoho  *              install a new, bad DSDT. This copy works around the problem.
159149703c7Sjruoho  *
160149703c7Sjruoho  ******************************************************************************/
161149703c7Sjruoho 
162149703c7Sjruoho ACPI_TABLE_HEADER *
AcpiTbCopyDsdt(UINT32 TableIndex)163149703c7Sjruoho AcpiTbCopyDsdt (
164149703c7Sjruoho     UINT32                  TableIndex)
165149703c7Sjruoho {
166149703c7Sjruoho     ACPI_TABLE_HEADER       *NewTable;
167149703c7Sjruoho     ACPI_TABLE_DESC         *TableDesc;
168149703c7Sjruoho 
169149703c7Sjruoho 
170149703c7Sjruoho     TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex];
171149703c7Sjruoho 
172149703c7Sjruoho     NewTable = ACPI_ALLOCATE (TableDesc->Length);
173149703c7Sjruoho     if (!NewTable)
174149703c7Sjruoho     {
175149703c7Sjruoho         ACPI_ERROR ((AE_INFO, "Could not copy DSDT of length 0x%X",
176149703c7Sjruoho             TableDesc->Length));
177149703c7Sjruoho         return (NULL);
178149703c7Sjruoho     }
179149703c7Sjruoho 
180e34402d4Schristos     memcpy (NewTable, TableDesc->Pointer, TableDesc->Length);
181ea4d7e80Schristos     AcpiTbUninstallTable (TableDesc);
182ea4d7e80Schristos 
183ea4d7e80Schristos     AcpiTbInitTableDescriptor (
18494e0d463Schristos         &AcpiGbl_RootTableList.Tables[AcpiGbl_DsdtIndex],
18594e0d463Schristos         ACPI_PTR_TO_PHYSADDR (NewTable),
18694e0d463Schristos         ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, NewTable);
187149703c7Sjruoho 
188dc79220aSchristos     ACPI_INFO ((
189149703c7Sjruoho         "Forced DSDT copy: length 0x%05X copied locally, original unmapped",
190149703c7Sjruoho         NewTable->Length));
191149703c7Sjruoho 
192149703c7Sjruoho     return (NewTable);
193149703c7Sjruoho }
194149703c7Sjruoho 
195149703c7Sjruoho 
196149703c7Sjruoho /*******************************************************************************
197149703c7Sjruoho  *
198149703c7Sjruoho  * FUNCTION:    AcpiTbGetRootTableEntry
199149703c7Sjruoho  *
200149703c7Sjruoho  * PARAMETERS:  TableEntry          - Pointer to the RSDT/XSDT table entry
201149703c7Sjruoho  *              TableEntrySize      - sizeof 32 or 64 (RSDT or XSDT)
202149703c7Sjruoho  *
203149703c7Sjruoho  * RETURN:      Physical address extracted from the root table
204149703c7Sjruoho  *
205149703c7Sjruoho  * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on
206149703c7Sjruoho  *              both 32-bit and 64-bit platforms
207149703c7Sjruoho  *
208149703c7Sjruoho  * NOTE:        ACPI_PHYSICAL_ADDRESS is 32-bit on 32-bit platforms, 64-bit on
209149703c7Sjruoho  *              64-bit platforms.
210149703c7Sjruoho  *
211149703c7Sjruoho  ******************************************************************************/
212149703c7Sjruoho 
213149703c7Sjruoho static ACPI_PHYSICAL_ADDRESS
AcpiTbGetRootTableEntry(UINT8 * TableEntry,UINT32 TableEntrySize)214149703c7Sjruoho AcpiTbGetRootTableEntry (
215149703c7Sjruoho     UINT8                   *TableEntry,
216149703c7Sjruoho     UINT32                  TableEntrySize)
217149703c7Sjruoho {
218149703c7Sjruoho     UINT64                  Address64;
219149703c7Sjruoho 
220149703c7Sjruoho 
221149703c7Sjruoho     /*
222149703c7Sjruoho      * Get the table physical address (32-bit for RSDT, 64-bit for XSDT):
223149703c7Sjruoho      * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT
224149703c7Sjruoho      */
22533841f6dSchristos     if (TableEntrySize == ACPI_RSDT_ENTRY_SIZE)
226149703c7Sjruoho     {
227149703c7Sjruoho         /*
228149703c7Sjruoho          * 32-bit platform, RSDT: Return 32-bit table entry
229149703c7Sjruoho          * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return
230149703c7Sjruoho          */
231bff9fc28Schristos         return ((ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST_PTR (
232bff9fc28Schristos             UINT32, TableEntry)));
233149703c7Sjruoho     }
234149703c7Sjruoho     else
235149703c7Sjruoho     {
236149703c7Sjruoho         /*
237149703c7Sjruoho          * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return
238149703c7Sjruoho          * 64-bit platform, XSDT: Move (unaligned) 64-bit to local,
239149703c7Sjruoho          *  return 64-bit
240149703c7Sjruoho          */
241149703c7Sjruoho         ACPI_MOVE_64_TO_64 (&Address64, TableEntry);
242149703c7Sjruoho 
243149703c7Sjruoho #if ACPI_MACHINE_WIDTH == 32
244149703c7Sjruoho         if (Address64 > ACPI_UINT32_MAX)
245149703c7Sjruoho         {
246149703c7Sjruoho             /* Will truncate 64-bit address to 32 bits, issue warning */
247149703c7Sjruoho 
24833841f6dSchristos             ACPI_BIOS_WARNING ((AE_INFO,
249149703c7Sjruoho                 "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X),"
250149703c7Sjruoho                 " truncating",
251149703c7Sjruoho                 ACPI_FORMAT_UINT64 (Address64)));
252149703c7Sjruoho         }
253149703c7Sjruoho #endif
254149703c7Sjruoho         return ((ACPI_PHYSICAL_ADDRESS) (Address64));
255149703c7Sjruoho     }
256149703c7Sjruoho }
257149703c7Sjruoho 
258149703c7Sjruoho 
259149703c7Sjruoho /*******************************************************************************
260149703c7Sjruoho  *
261149703c7Sjruoho  * FUNCTION:    AcpiTbParseRootTable
262149703c7Sjruoho  *
26335a687ffSchristos  * PARAMETERS:  RsdpAddress         - Pointer to the RSDP
264149703c7Sjruoho  *
265149703c7Sjruoho  * RETURN:      Status
266149703c7Sjruoho  *
267149703c7Sjruoho  * DESCRIPTION: This function is called to parse the Root System Description
268149703c7Sjruoho  *              Table (RSDT or XSDT)
269149703c7Sjruoho  *
270149703c7Sjruoho  * NOTE:        Tables are mapped (not copied) for efficiency. The FACS must
271149703c7Sjruoho  *              be mapped and cannot be copied because it contains the actual
272149703c7Sjruoho  *              memory location of the ACPI Global Lock.
273149703c7Sjruoho  *
274149703c7Sjruoho  ******************************************************************************/
275149703c7Sjruoho 
276abb0e338Schristos ACPI_STATUS ACPI_INIT_FUNCTION
AcpiTbParseRootTable(ACPI_PHYSICAL_ADDRESS RsdpAddress)277149703c7Sjruoho AcpiTbParseRootTable (
278149703c7Sjruoho     ACPI_PHYSICAL_ADDRESS   RsdpAddress)
279149703c7Sjruoho {
280149703c7Sjruoho     ACPI_TABLE_RSDP         *Rsdp;
281149703c7Sjruoho     UINT32                  TableEntrySize;
282149703c7Sjruoho     UINT32                  i;
283149703c7Sjruoho     UINT32                  TableCount;
284149703c7Sjruoho     ACPI_TABLE_HEADER       *Table;
285149703c7Sjruoho     ACPI_PHYSICAL_ADDRESS   Address;
286149703c7Sjruoho     UINT32                  Length;
287149703c7Sjruoho     UINT8                   *TableEntry;
288149703c7Sjruoho     ACPI_STATUS             Status;
289ea4d7e80Schristos     UINT32                  TableIndex;
290149703c7Sjruoho 
291149703c7Sjruoho 
292149703c7Sjruoho     ACPI_FUNCTION_TRACE (TbParseRootTable);
293149703c7Sjruoho 
294149703c7Sjruoho 
29533841f6dSchristos     /* Map the entire RSDP and extract the address of the RSDT or XSDT */
29633841f6dSchristos 
297149703c7Sjruoho     Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP));
298149703c7Sjruoho     if (!Rsdp)
299149703c7Sjruoho     {
300149703c7Sjruoho         return_ACPI_STATUS (AE_NO_MEMORY);
301149703c7Sjruoho     }
302149703c7Sjruoho 
303149703c7Sjruoho     AcpiTbPrintTableHeader (RsdpAddress,
304149703c7Sjruoho         ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp));
305149703c7Sjruoho 
30633841f6dSchristos     /* Use XSDT if present and not overridden. Otherwise, use RSDT */
307149703c7Sjruoho 
30833841f6dSchristos     if ((Rsdp->Revision > 1) &&
30933841f6dSchristos         Rsdp->XsdtPhysicalAddress &&
31033841f6dSchristos         !AcpiGbl_DoNotUseXsdt)
311149703c7Sjruoho     {
312149703c7Sjruoho         /*
31333841f6dSchristos          * RSDP contains an XSDT (64-bit physical addresses). We must use
31433841f6dSchristos          * the XSDT if the revision is > 1 and the XSDT pointer is present,
31533841f6dSchristos          * as per the ACPI specification.
316149703c7Sjruoho          */
317149703c7Sjruoho         Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress;
31833841f6dSchristos         TableEntrySize = ACPI_XSDT_ENTRY_SIZE;
319149703c7Sjruoho     }
320149703c7Sjruoho     else
321149703c7Sjruoho     {
322149703c7Sjruoho         /* Root table is an RSDT (32-bit physical addresses) */
323149703c7Sjruoho 
324149703c7Sjruoho         Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress;
32533841f6dSchristos         TableEntrySize = ACPI_RSDT_ENTRY_SIZE;
326149703c7Sjruoho     }
327149703c7Sjruoho 
328149703c7Sjruoho     /*
32934dabbfeSriastradh      * It is not possible to map more than one entry in some environments,
33034dabbfeSriastradh      * so unmap the RSDP here before mapping other tables
33134dabbfeSriastradh      */
33234dabbfeSriastradh     AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP));
33334dabbfeSriastradh 
334149703c7Sjruoho     /* Map the RSDT/XSDT table header to get the full table length */
335149703c7Sjruoho 
336149703c7Sjruoho     Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
337149703c7Sjruoho     if (!Table)
338149703c7Sjruoho     {
339149703c7Sjruoho         return_ACPI_STATUS (AE_NO_MEMORY);
340149703c7Sjruoho     }
341149703c7Sjruoho 
342149703c7Sjruoho     AcpiTbPrintTableHeader (Address, Table);
343149703c7Sjruoho 
34433841f6dSchristos     /*
34533841f6dSchristos      * Validate length of the table, and map entire table.
34633841f6dSchristos      * Minimum length table must contain at least one entry.
34733841f6dSchristos      */
348149703c7Sjruoho     Length = Table->Length;
349149703c7Sjruoho     AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER));
350149703c7Sjruoho 
35133841f6dSchristos     if (Length < (sizeof (ACPI_TABLE_HEADER) + TableEntrySize))
352149703c7Sjruoho     {
35333841f6dSchristos         ACPI_BIOS_ERROR ((AE_INFO,
35433841f6dSchristos             "Invalid table length 0x%X in RSDT/XSDT", Length));
355149703c7Sjruoho         return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
356149703c7Sjruoho     }
357149703c7Sjruoho 
358149703c7Sjruoho     Table = AcpiOsMapMemory (Address, Length);
359149703c7Sjruoho     if (!Table)
360149703c7Sjruoho     {
361149703c7Sjruoho         return_ACPI_STATUS (AE_NO_MEMORY);
362149703c7Sjruoho     }
363149703c7Sjruoho 
364149703c7Sjruoho     /* Validate the root table checksum */
365149703c7Sjruoho 
366*1d995a70Schristos     Status = AcpiUtVerifyChecksum (Table, Length);
367149703c7Sjruoho     if (ACPI_FAILURE (Status))
368149703c7Sjruoho     {
369149703c7Sjruoho         AcpiOsUnmapMemory (Table, Length);
370149703c7Sjruoho         return_ACPI_STATUS (Status);
371149703c7Sjruoho     }
372149703c7Sjruoho 
37333841f6dSchristos     /* Get the number of entries and pointer to first entry */
374149703c7Sjruoho 
375149703c7Sjruoho     TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) /
376149703c7Sjruoho         TableEntrySize);
37733841f6dSchristos     TableEntry = ACPI_ADD_PTR (UINT8, Table, sizeof (ACPI_TABLE_HEADER));
378149703c7Sjruoho 
37933841f6dSchristos     /* Initialize the root table array from the RSDT/XSDT */
38033841f6dSchristos 
381149703c7Sjruoho     for (i = 0; i < TableCount; i++)
382149703c7Sjruoho     {
383149703c7Sjruoho         /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
384149703c7Sjruoho 
385ea4d7e80Schristos         Address = AcpiTbGetRootTableEntry (TableEntry, TableEntrySize);
386ea4d7e80Schristos 
387ea4d7e80Schristos         /* Skip NULL entries in RSDT/XSDT */
388ea4d7e80Schristos 
389ea4d7e80Schristos         if (!Address)
390ea4d7e80Schristos         {
391ea4d7e80Schristos             goto NextTable;
392ea4d7e80Schristos         }
393ea4d7e80Schristos 
394ea4d7e80Schristos         Status = AcpiTbInstallStandardTable (Address,
395bff9fc28Schristos             ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL, FALSE, TRUE,
396bff9fc28Schristos             &TableIndex);
397ea4d7e80Schristos 
398ea4d7e80Schristos         if (ACPI_SUCCESS (Status) &&
399f5a85da7Schristos             ACPI_COMPARE_NAMESEG (
40094e0d463Schristos                 &AcpiGbl_RootTableList.Tables[TableIndex].Signature,
401ea4d7e80Schristos                 ACPI_SIG_FADT))
402ea4d7e80Schristos         {
40394e0d463Schristos             AcpiGbl_FadtIndex = TableIndex;
40494e0d463Schristos             AcpiTbParseFadt ();
405ea4d7e80Schristos         }
406ea4d7e80Schristos 
407ea4d7e80Schristos NextTable:
408149703c7Sjruoho 
409149703c7Sjruoho         TableEntry += TableEntrySize;
410149703c7Sjruoho     }
411149703c7Sjruoho 
412149703c7Sjruoho     AcpiOsUnmapMemory (Table, Length);
413149703c7Sjruoho     return_ACPI_STATUS (AE_OK);
414149703c7Sjruoho }
415d592fd16Schristos 
416d592fd16Schristos 
417d592fd16Schristos /*******************************************************************************
418d592fd16Schristos  *
419d592fd16Schristos  * FUNCTION:    AcpiTbGetTable
420d592fd16Schristos  *
421d592fd16Schristos  * PARAMETERS:  TableDesc           - Table descriptor
422d592fd16Schristos  *              OutTable            - Where the pointer to the table is returned
423d592fd16Schristos  *
424d592fd16Schristos  * RETURN:      Status and pointer to the requested table
425d592fd16Schristos  *
426d592fd16Schristos  * DESCRIPTION: Increase a reference to a table descriptor and return the
427d592fd16Schristos  *              validated table pointer.
428d592fd16Schristos  *              If the table descriptor is an entry of the root table list,
429d592fd16Schristos  *              this API must be invoked with ACPI_MTX_TABLES acquired.
430d592fd16Schristos  *
431d592fd16Schristos  ******************************************************************************/
432d592fd16Schristos 
433d592fd16Schristos ACPI_STATUS
AcpiTbGetTable(ACPI_TABLE_DESC * TableDesc,ACPI_TABLE_HEADER ** OutTable)434d592fd16Schristos AcpiTbGetTable (
435d592fd16Schristos     ACPI_TABLE_DESC        *TableDesc,
436d592fd16Schristos     ACPI_TABLE_HEADER      **OutTable)
437d592fd16Schristos {
438d592fd16Schristos     ACPI_STATUS            Status;
439d592fd16Schristos 
440d592fd16Schristos 
441d592fd16Schristos     ACPI_FUNCTION_TRACE (AcpiTbGetTable);
442d592fd16Schristos 
443d592fd16Schristos 
444d592fd16Schristos     if (TableDesc->ValidationCount == 0)
445d592fd16Schristos     {
446d592fd16Schristos         /* Table need to be "VALIDATED" */
447d592fd16Schristos 
448d592fd16Schristos         Status = AcpiTbValidateTable (TableDesc);
449d592fd16Schristos         if (ACPI_FAILURE (Status))
450d592fd16Schristos         {
451d592fd16Schristos             return_ACPI_STATUS (Status);
452d592fd16Schristos         }
453d592fd16Schristos     }
454d592fd16Schristos 
45535a687ffSchristos     if (TableDesc->ValidationCount < ACPI_MAX_TABLE_VALIDATIONS)
456d592fd16Schristos     {
45735a687ffSchristos         TableDesc->ValidationCount++;
45835a687ffSchristos 
45935a687ffSchristos         /*
46035a687ffSchristos          * Detect ValidationCount overflows to ensure that the warning
46135a687ffSchristos          * message will only be printed once.
46235a687ffSchristos          */
46335a687ffSchristos         if (TableDesc->ValidationCount >= ACPI_MAX_TABLE_VALIDATIONS)
46435a687ffSchristos         {
46535a687ffSchristos             ACPI_WARNING((AE_INFO,
46635a687ffSchristos                 "Table %p, Validation count overflows\n", TableDesc));
46735a687ffSchristos         }
468d592fd16Schristos     }
469d592fd16Schristos 
470d592fd16Schristos     *OutTable = TableDesc->Pointer;
471d592fd16Schristos     return_ACPI_STATUS (AE_OK);
472d592fd16Schristos }
473d592fd16Schristos 
474d592fd16Schristos 
475d592fd16Schristos /*******************************************************************************
476d592fd16Schristos  *
477d592fd16Schristos  * FUNCTION:    AcpiTbPutTable
478d592fd16Schristos  *
479d592fd16Schristos  * PARAMETERS:  TableDesc           - Table descriptor
480d592fd16Schristos  *
481d592fd16Schristos  * RETURN:      None
482d592fd16Schristos  *
483d592fd16Schristos  * DESCRIPTION: Decrease a reference to a table descriptor and release the
484d592fd16Schristos  *              validated table pointer if no references.
485d592fd16Schristos  *              If the table descriptor is an entry of the root table list,
486d592fd16Schristos  *              this API must be invoked with ACPI_MTX_TABLES acquired.
487d592fd16Schristos  *
488d592fd16Schristos  ******************************************************************************/
489d592fd16Schristos 
490d592fd16Schristos void
AcpiTbPutTable(ACPI_TABLE_DESC * TableDesc)491d592fd16Schristos AcpiTbPutTable (
492d592fd16Schristos     ACPI_TABLE_DESC        *TableDesc)
493d592fd16Schristos {
494d592fd16Schristos 
495d592fd16Schristos     ACPI_FUNCTION_TRACE (AcpiTbPutTable);
496d592fd16Schristos 
497d592fd16Schristos 
49835a687ffSchristos     if (TableDesc->ValidationCount < ACPI_MAX_TABLE_VALIDATIONS)
49935a687ffSchristos     {
50035a687ffSchristos         TableDesc->ValidationCount--;
50135a687ffSchristos 
50235a687ffSchristos         /*
50335a687ffSchristos          * Detect ValidationCount underflows to ensure that the warning
50435a687ffSchristos          * message will only be printed once.
50535a687ffSchristos          */
50635a687ffSchristos         if (TableDesc->ValidationCount >= ACPI_MAX_TABLE_VALIDATIONS)
507d592fd16Schristos         {
508d592fd16Schristos             ACPI_WARNING ((AE_INFO,
50935a687ffSchristos                 "Table %p, Validation count underflows\n", TableDesc));
510d592fd16Schristos             return_VOID;
511d592fd16Schristos         }
51235a687ffSchristos     }
513d592fd16Schristos 
514d592fd16Schristos     if (TableDesc->ValidationCount == 0)
515d592fd16Schristos     {
516d592fd16Schristos         /* Table need to be "INVALIDATED" */
517d592fd16Schristos 
518d592fd16Schristos         AcpiTbInvalidateTable (TableDesc);
519d592fd16Schristos     }
520d592fd16Schristos 
521d592fd16Schristos     return_VOID;
522d592fd16Schristos }
523