15943f66cSSascha Wildner /******************************************************************************
25943f66cSSascha Wildner  *
35943f66cSSascha Wildner  * Module Name: osbsdtbl - BSD OSL for obtaining ACPI tables
45943f66cSSascha Wildner  *
55943f66cSSascha Wildner  *****************************************************************************/
65943f66cSSascha Wildner 
7b4315fc7SSascha Wildner /******************************************************************************
8b4315fc7SSascha Wildner  *
9b4315fc7SSascha Wildner  * 1. Copyright Notice
10b4315fc7SSascha Wildner  *
11*383048acSSascha Wildner  * Some or all of this work - Copyright (c) 1999 - 2021, Intel Corp.
125943f66cSSascha Wildner  * All rights reserved.
135943f66cSSascha Wildner  *
14b4315fc7SSascha Wildner  * 2. License
15b4315fc7SSascha Wildner  *
16b4315fc7SSascha Wildner  * 2.1. This is your license from Intel Corp. under its intellectual property
17b4315fc7SSascha Wildner  * rights. You may have additional license terms from the party that provided
18b4315fc7SSascha Wildner  * you this software, covering your right to use that party's intellectual
19b4315fc7SSascha Wildner  * property rights.
20b4315fc7SSascha Wildner  *
21b4315fc7SSascha Wildner  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22b4315fc7SSascha Wildner  * copy of the source code appearing in this file ("Covered Code") an
23b4315fc7SSascha Wildner  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24b4315fc7SSascha Wildner  * base code distributed originally by Intel ("Original Intel Code") to copy,
25b4315fc7SSascha Wildner  * make derivatives, distribute, use and display any portion of the Covered
26b4315fc7SSascha Wildner  * Code in any form, with the right to sublicense such rights; and
27b4315fc7SSascha Wildner  *
28b4315fc7SSascha Wildner  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29b4315fc7SSascha Wildner  * license (with the right to sublicense), under only those claims of Intel
30b4315fc7SSascha Wildner  * patents that are infringed by the Original Intel Code, to make, use, sell,
31b4315fc7SSascha Wildner  * offer to sell, and import the Covered Code and derivative works thereof
32b4315fc7SSascha Wildner  * solely to the minimum extent necessary to exercise the above copyright
33b4315fc7SSascha Wildner  * license, and in no event shall the patent license extend to any additions
34b4315fc7SSascha Wildner  * to or modifications of the Original Intel Code. No other license or right
35b4315fc7SSascha Wildner  * is granted directly or by implication, estoppel or otherwise;
36b4315fc7SSascha Wildner  *
37b4315fc7SSascha Wildner  * The above copyright and patent license is granted only if the following
38b4315fc7SSascha Wildner  * conditions are met:
39b4315fc7SSascha Wildner  *
40b4315fc7SSascha Wildner  * 3. Conditions
41b4315fc7SSascha Wildner  *
42b4315fc7SSascha Wildner  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43b4315fc7SSascha Wildner  * Redistribution of source code of any substantial portion of the Covered
44b4315fc7SSascha Wildner  * Code or modification with rights to further distribute source must include
45b4315fc7SSascha Wildner  * the above Copyright Notice, the above License, this list of Conditions,
46b4315fc7SSascha Wildner  * and the following Disclaimer and Export Compliance provision. In addition,
47b4315fc7SSascha Wildner  * Licensee must cause all Covered Code to which Licensee contributes to
48b4315fc7SSascha Wildner  * contain a file documenting the changes Licensee made to create that Covered
49b4315fc7SSascha Wildner  * Code and the date of any change. Licensee must include in that file the
50b4315fc7SSascha Wildner  * documentation of any changes made by any predecessor Licensee. Licensee
51b4315fc7SSascha Wildner  * must include a prominent statement that the modification is derived,
52b4315fc7SSascha Wildner  * directly or indirectly, from Original Intel Code.
53b4315fc7SSascha Wildner  *
54b4315fc7SSascha Wildner  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55b4315fc7SSascha Wildner  * Redistribution of source code of any substantial portion of the Covered
56b4315fc7SSascha Wildner  * Code or modification without rights to further distribute source must
57b4315fc7SSascha Wildner  * include the following Disclaimer and Export Compliance provision in the
58b4315fc7SSascha Wildner  * documentation and/or other materials provided with distribution. In
59b4315fc7SSascha Wildner  * addition, Licensee may not authorize further sublicense of source of any
60b4315fc7SSascha Wildner  * portion of the Covered Code, and must include terms to the effect that the
61b4315fc7SSascha Wildner  * license from Licensee to its licensee is limited to the intellectual
62b4315fc7SSascha Wildner  * property embodied in the software Licensee provides to its licensee, and
63b4315fc7SSascha Wildner  * not to intellectual property embodied in modifications its licensee may
64b4315fc7SSascha Wildner  * make.
65b4315fc7SSascha Wildner  *
66b4315fc7SSascha Wildner  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67b4315fc7SSascha Wildner  * substantial portion of the Covered Code or modification must reproduce the
68b4315fc7SSascha Wildner  * above Copyright Notice, and the following Disclaimer and Export Compliance
69b4315fc7SSascha Wildner  * provision in the documentation and/or other materials provided with the
70b4315fc7SSascha Wildner  * distribution.
71b4315fc7SSascha Wildner  *
72b4315fc7SSascha Wildner  * 3.4. Intel retains all right, title, and interest in and to the Original
73b4315fc7SSascha Wildner  * Intel Code.
74b4315fc7SSascha Wildner  *
75b4315fc7SSascha Wildner  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76b4315fc7SSascha Wildner  * Intel shall be used in advertising or otherwise to promote the sale, use or
77b4315fc7SSascha Wildner  * other dealings in products derived from or relating to the Covered Code
78b4315fc7SSascha Wildner  * without prior written authorization from Intel.
79b4315fc7SSascha Wildner  *
80b4315fc7SSascha Wildner  * 4. Disclaimer and Export Compliance
81b4315fc7SSascha Wildner  *
82b4315fc7SSascha Wildner  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83b4315fc7SSascha Wildner  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84b4315fc7SSascha Wildner  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85b4315fc7SSascha Wildner  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86b4315fc7SSascha Wildner  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87b4315fc7SSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88b4315fc7SSascha Wildner  * PARTICULAR PURPOSE.
89b4315fc7SSascha Wildner  *
90b4315fc7SSascha Wildner  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91b4315fc7SSascha Wildner  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92b4315fc7SSascha Wildner  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93b4315fc7SSascha Wildner  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94b4315fc7SSascha Wildner  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95b4315fc7SSascha Wildner  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96b4315fc7SSascha Wildner  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97b4315fc7SSascha Wildner  * LIMITED REMEDY.
98b4315fc7SSascha Wildner  *
99b4315fc7SSascha Wildner  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100b4315fc7SSascha Wildner  * software or system incorporating such software without first obtaining any
101b4315fc7SSascha Wildner  * required license or other approval from the U. S. Department of Commerce or
102b4315fc7SSascha Wildner  * any other agency or department of the United States Government. In the
103b4315fc7SSascha Wildner  * event Licensee exports any such software from the United States or
104b4315fc7SSascha Wildner  * re-exports any such software from a foreign destination, Licensee shall
105b4315fc7SSascha Wildner  * ensure that the distribution and export/re-export of the software is in
106b4315fc7SSascha Wildner  * compliance with all laws, regulations, orders, or other restrictions of the
107b4315fc7SSascha Wildner  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108b4315fc7SSascha Wildner  * any of its subsidiaries will export/re-export any technical data, process,
109b4315fc7SSascha Wildner  * software, or service, directly or indirectly, to any country for which the
110b4315fc7SSascha Wildner  * United States government or any agency thereof requires an export license,
111b4315fc7SSascha Wildner  * other governmental approval, or letter of assurance, without first obtaining
112b4315fc7SSascha Wildner  * such license, approval or letter.
113b4315fc7SSascha Wildner  *
114b4315fc7SSascha Wildner  *****************************************************************************
115b4315fc7SSascha Wildner  *
116b4315fc7SSascha Wildner  * Alternatively, you may choose to be licensed under the terms of the
117b4315fc7SSascha Wildner  * following license:
118b4315fc7SSascha Wildner  *
1195943f66cSSascha Wildner  * Redistribution and use in source and binary forms, with or without
1205943f66cSSascha Wildner  * modification, are permitted provided that the following conditions
1215943f66cSSascha Wildner  * are met:
1225943f66cSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
1235943f66cSSascha Wildner  *    notice, this list of conditions, and the following disclaimer,
1245943f66cSSascha Wildner  *    without modification.
1255943f66cSSascha Wildner  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1265943f66cSSascha Wildner  *    substantially similar to the "NO WARRANTY" disclaimer below
1275943f66cSSascha Wildner  *    ("Disclaimer") and any redistribution must be conditioned upon
1285943f66cSSascha Wildner  *    including a substantially similar Disclaimer requirement for further
1295943f66cSSascha Wildner  *    binary redistribution.
1305943f66cSSascha Wildner  * 3. Neither the names of the above-listed copyright holders nor the names
1315943f66cSSascha Wildner  *    of any contributors may be used to endorse or promote products derived
1325943f66cSSascha Wildner  *    from this software without specific prior written permission.
1335943f66cSSascha Wildner  *
134b4315fc7SSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135b4315fc7SSascha Wildner  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136b4315fc7SSascha Wildner  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137b4315fc7SSascha Wildner  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138b4315fc7SSascha Wildner  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139b4315fc7SSascha Wildner  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140b4315fc7SSascha Wildner  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141b4315fc7SSascha Wildner  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142b4315fc7SSascha Wildner  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143b4315fc7SSascha Wildner  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144b4315fc7SSascha Wildner  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145b4315fc7SSascha Wildner  *
146b4315fc7SSascha Wildner  * Alternatively, you may choose to be licensed under the terms of the
1475943f66cSSascha Wildner  * GNU General Public License ("GPL") version 2 as published by the Free
1485943f66cSSascha Wildner  * Software Foundation.
1495943f66cSSascha Wildner  *
150b4315fc7SSascha Wildner  *****************************************************************************/
1515943f66cSSascha Wildner 
1525943f66cSSascha Wildner #include "acpidump.h"
1535943f66cSSascha Wildner 
1542e03c868SSascha Wildner #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__)
1555943f66cSSascha Wildner #include <kenv.h>
1565943f66cSSascha Wildner #endif
1575943f66cSSascha Wildner #include <unistd.h>
1585943f66cSSascha Wildner #include <sys/param.h>
1595943f66cSSascha Wildner #include <sys/sysctl.h>
1605943f66cSSascha Wildner 
1615943f66cSSascha Wildner 
1625943f66cSSascha Wildner #define _COMPONENT          ACPI_OS_SERVICES
1635943f66cSSascha Wildner         ACPI_MODULE_NAME    ("osbsdtbl")
1645943f66cSSascha Wildner 
1655943f66cSSascha Wildner 
1665943f66cSSascha Wildner /* Local prototypes */
1675943f66cSSascha Wildner 
1685943f66cSSascha Wildner static ACPI_STATUS
1695943f66cSSascha Wildner OslTableInitialize (
1705943f66cSSascha Wildner     void);
1715943f66cSSascha Wildner 
1725943f66cSSascha Wildner static ACPI_STATUS
1735943f66cSSascha Wildner OslMapTable (
1745943f66cSSascha Wildner     ACPI_SIZE               Address,
1755943f66cSSascha Wildner     char                    *Signature,
1765943f66cSSascha Wildner     ACPI_TABLE_HEADER       **Table);
1775943f66cSSascha Wildner 
1785943f66cSSascha Wildner static ACPI_STATUS
1795943f66cSSascha Wildner OslAddTablesToList (
1805943f66cSSascha Wildner     void);
1815943f66cSSascha Wildner 
1825943f66cSSascha Wildner static ACPI_STATUS
1835943f66cSSascha Wildner OslGetTableViaRoot (
1845943f66cSSascha Wildner     char                    *Signature,
1855943f66cSSascha Wildner     UINT32                  Instance,
1865943f66cSSascha Wildner     ACPI_TABLE_HEADER       **Table,
1875943f66cSSascha Wildner     ACPI_PHYSICAL_ADDRESS   *Address);
1885943f66cSSascha Wildner 
1895943f66cSSascha Wildner 
1905943f66cSSascha Wildner /* Hints for RSDP */
1915943f66cSSascha Wildner #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
1925943f66cSSascha Wildner #define SYSTEM_KENV         "hint.acpi.0.rsdp"
1935943f66cSSascha Wildner #define SYSTEM_SYSCTL       "machdep.acpi_root"
1945943f66cSSascha Wildner #elif defined(__NetBSD__)
1955943f66cSSascha Wildner #define SYSTEM_SYSCTL       "hw.acpi.root"
1965943f66cSSascha Wildner #endif
1975943f66cSSascha Wildner 
1985943f66cSSascha Wildner /* Initialization flags */
1995943f66cSSascha Wildner 
2005943f66cSSascha Wildner UINT8                   Gbl_TableListInitialized = FALSE;
2015943f66cSSascha Wildner UINT8                   Gbl_MainTableObtained = FALSE;
2025943f66cSSascha Wildner 
2035943f66cSSascha Wildner /* Local copies of main ACPI tables */
2045943f66cSSascha Wildner 
2055943f66cSSascha Wildner ACPI_TABLE_RSDP         Gbl_Rsdp;
2065943f66cSSascha Wildner ACPI_TABLE_FADT         *Gbl_Fadt;
2075943f66cSSascha Wildner ACPI_TABLE_RSDT         *Gbl_Rsdt;
2085943f66cSSascha Wildner ACPI_TABLE_XSDT         *Gbl_Xsdt;
2095943f66cSSascha Wildner 
2105943f66cSSascha Wildner /* Fadt address */
2115943f66cSSascha Wildner 
2125943f66cSSascha Wildner ACPI_PHYSICAL_ADDRESS   Gbl_FadtAddress;
2135943f66cSSascha Wildner 
2145943f66cSSascha Wildner /* Revision of RSD PTR */
2155943f66cSSascha Wildner 
2165943f66cSSascha Wildner UINT8                   Gbl_Revision;
2175943f66cSSascha Wildner 
2185943f66cSSascha Wildner /* List of information about obtained ACPI tables */
2195943f66cSSascha Wildner 
2205943f66cSSascha Wildner typedef struct          table_info
2215943f66cSSascha Wildner {
2225943f66cSSascha Wildner     struct table_info       *Next;
2235943f66cSSascha Wildner     char                    Signature[4];
2245943f66cSSascha Wildner     UINT32                  Instance;
2255943f66cSSascha Wildner     ACPI_PHYSICAL_ADDRESS   Address;
2265943f66cSSascha Wildner 
2275943f66cSSascha Wildner } OSL_TABLE_INFO;
2285943f66cSSascha Wildner 
2295943f66cSSascha Wildner OSL_TABLE_INFO          *Gbl_TableListHead = NULL;
2305943f66cSSascha Wildner 
2315943f66cSSascha Wildner 
2325943f66cSSascha Wildner /******************************************************************************
2335943f66cSSascha Wildner  *
2345943f66cSSascha Wildner  * FUNCTION:    AcpiOsGetTableByAddress
2355943f66cSSascha Wildner  *
2365943f66cSSascha Wildner  * PARAMETERS:  Address         - Physical address of the ACPI table
2375943f66cSSascha Wildner  *              Table           - Where a pointer to the table is returned
2385943f66cSSascha Wildner  *
2395943f66cSSascha Wildner  * RETURN:      Status; Table buffer is returned if AE_OK.
2405943f66cSSascha Wildner  *              AE_NOT_FOUND: A valid table was not found at the address
2415943f66cSSascha Wildner  *
2425943f66cSSascha Wildner  * DESCRIPTION: Get an ACPI table via a physical memory address.
2435943f66cSSascha Wildner  *
2445943f66cSSascha Wildner  *****************************************************************************/
2455943f66cSSascha Wildner 
2465943f66cSSascha Wildner ACPI_STATUS
AcpiOsGetTableByAddress(ACPI_PHYSICAL_ADDRESS Address,ACPI_TABLE_HEADER ** Table)2475943f66cSSascha Wildner AcpiOsGetTableByAddress (
2485943f66cSSascha Wildner     ACPI_PHYSICAL_ADDRESS   Address,
2495943f66cSSascha Wildner     ACPI_TABLE_HEADER       **Table)
2505943f66cSSascha Wildner {
2515943f66cSSascha Wildner     ACPI_TABLE_HEADER       *MappedTable;
2525943f66cSSascha Wildner     ACPI_TABLE_HEADER       *LocalTable;
2535943f66cSSascha Wildner     ACPI_STATUS             Status;
2545943f66cSSascha Wildner 
2555943f66cSSascha Wildner 
2565943f66cSSascha Wildner     /* Validate the input physical address to avoid program crash */
2575943f66cSSascha Wildner 
2585943f66cSSascha Wildner     if (Address < ACPI_HI_RSDP_WINDOW_BASE)
2595943f66cSSascha Wildner     {
2605943f66cSSascha Wildner         fprintf (stderr, "Invalid table address: 0x%8.8X%8.8X\n",
2615943f66cSSascha Wildner             ACPI_FORMAT_UINT64 (Address));
2625943f66cSSascha Wildner         return (AE_BAD_ADDRESS);
2635943f66cSSascha Wildner     }
2645943f66cSSascha Wildner 
2655943f66cSSascha Wildner     /* Map the table and validate it */
2665943f66cSSascha Wildner 
2675943f66cSSascha Wildner     Status = OslMapTable (Address, NULL, &MappedTable);
2685943f66cSSascha Wildner     if (ACPI_FAILURE (Status))
2695943f66cSSascha Wildner     {
2705943f66cSSascha Wildner         return (Status);
2715943f66cSSascha Wildner     }
2725943f66cSSascha Wildner 
2735943f66cSSascha Wildner     /* Copy table to local buffer and return it */
2745943f66cSSascha Wildner 
2755943f66cSSascha Wildner     LocalTable = calloc (1, MappedTable->Length);
2765943f66cSSascha Wildner     if (!LocalTable)
2775943f66cSSascha Wildner     {
2785943f66cSSascha Wildner         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
2795943f66cSSascha Wildner         return (AE_NO_MEMORY);
2805943f66cSSascha Wildner     }
2815943f66cSSascha Wildner 
28225ca8c79SSascha Wildner     memcpy (LocalTable, MappedTable, MappedTable->Length);
2835943f66cSSascha Wildner     AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
2845943f66cSSascha Wildner 
2855943f66cSSascha Wildner     *Table = LocalTable;
2865943f66cSSascha Wildner     return (AE_OK);
2875943f66cSSascha Wildner }
2885943f66cSSascha Wildner 
2895943f66cSSascha Wildner 
2905943f66cSSascha Wildner /******************************************************************************
2915943f66cSSascha Wildner  *
2925943f66cSSascha Wildner  * FUNCTION:    AcpiOsGetTableByName
2935943f66cSSascha Wildner  *
2945943f66cSSascha Wildner  * PARAMETERS:  Signature       - ACPI Signature for desired table. Must be
2955943f66cSSascha Wildner  *                                a null terminated 4-character string.
2965943f66cSSascha Wildner  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
2975943f66cSSascha Wildner  *                                Must be 0 for other tables.
2985943f66cSSascha Wildner  *              Table           - Where a pointer to the table is returned
2995943f66cSSascha Wildner  *              Address         - Where the table physical address is returned
3005943f66cSSascha Wildner  *
3015943f66cSSascha Wildner  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
3025943f66cSSascha Wildner  *              AE_LIMIT: Instance is beyond valid limit
3035943f66cSSascha Wildner  *              AE_NOT_FOUND: A table with the signature was not found
3045943f66cSSascha Wildner  *
3055943f66cSSascha Wildner  * NOTE:        Assumes the input signature is uppercase.
3065943f66cSSascha Wildner  *
3075943f66cSSascha Wildner  *****************************************************************************/
3085943f66cSSascha Wildner 
3095943f66cSSascha Wildner ACPI_STATUS
AcpiOsGetTableByName(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)3105943f66cSSascha Wildner AcpiOsGetTableByName (
3115943f66cSSascha Wildner     char                    *Signature,
3125943f66cSSascha Wildner     UINT32                  Instance,
3135943f66cSSascha Wildner     ACPI_TABLE_HEADER       **Table,
3145943f66cSSascha Wildner     ACPI_PHYSICAL_ADDRESS   *Address)
3155943f66cSSascha Wildner {
3165943f66cSSascha Wildner     ACPI_STATUS             Status;
3175943f66cSSascha Wildner 
3185943f66cSSascha Wildner 
3195943f66cSSascha Wildner     /* Instance is only valid for SSDT/UEFI tables */
3205943f66cSSascha Wildner 
3215943f66cSSascha Wildner     if (Instance &&
322c1776041SSascha Wildner         !ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_SSDT) &&
323c1776041SSascha Wildner         !ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_UEFI))
3245943f66cSSascha Wildner     {
3255943f66cSSascha Wildner         return (AE_LIMIT);
3265943f66cSSascha Wildner     }
3275943f66cSSascha Wildner 
3285943f66cSSascha Wildner     /* Initialize main tables */
3295943f66cSSascha Wildner 
3305943f66cSSascha Wildner     Status = OslTableInitialize ();
3315943f66cSSascha Wildner     if (ACPI_FAILURE (Status))
3325943f66cSSascha Wildner     {
3335943f66cSSascha Wildner         return (Status);
3345943f66cSSascha Wildner     }
3355943f66cSSascha Wildner 
3365943f66cSSascha Wildner     /*
3375943f66cSSascha Wildner      * If one of the main ACPI tables was requested (RSDT/XSDT/FADT),
3385943f66cSSascha Wildner      * simply return it immediately.
3395943f66cSSascha Wildner      */
340c1776041SSascha Wildner     if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT))
3415943f66cSSascha Wildner     {
3425943f66cSSascha Wildner         if (!Gbl_Revision)
3435943f66cSSascha Wildner         {
3445943f66cSSascha Wildner             return (AE_NOT_FOUND);
3455943f66cSSascha Wildner         }
3465943f66cSSascha Wildner 
3475943f66cSSascha Wildner         *Address = Gbl_Rsdp.XsdtPhysicalAddress;
3485943f66cSSascha Wildner         *Table = (ACPI_TABLE_HEADER *) Gbl_Xsdt;
3495943f66cSSascha Wildner         return (AE_OK);
3505943f66cSSascha Wildner     }
3515943f66cSSascha Wildner 
352c1776041SSascha Wildner     if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT))
3535943f66cSSascha Wildner     {
3545943f66cSSascha Wildner         if (!Gbl_Rsdp.RsdtPhysicalAddress)
3555943f66cSSascha Wildner         {
3565943f66cSSascha Wildner             return (AE_NOT_FOUND);
3575943f66cSSascha Wildner         }
3585943f66cSSascha Wildner 
3595943f66cSSascha Wildner         *Address = Gbl_Rsdp.RsdtPhysicalAddress;
3605943f66cSSascha Wildner         *Table = (ACPI_TABLE_HEADER *) Gbl_Rsdt;
3615943f66cSSascha Wildner         return (AE_OK);
3625943f66cSSascha Wildner     }
3635943f66cSSascha Wildner 
364c1776041SSascha Wildner     if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FADT))
3655943f66cSSascha Wildner     {
3665943f66cSSascha Wildner         *Address = Gbl_FadtAddress;
3675943f66cSSascha Wildner         *Table = (ACPI_TABLE_HEADER *) Gbl_Fadt;
3685943f66cSSascha Wildner         return (AE_OK);
3695943f66cSSascha Wildner     }
3705943f66cSSascha Wildner 
3715943f66cSSascha Wildner     /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
3725943f66cSSascha Wildner 
3735943f66cSSascha Wildner     Status = OslGetTableViaRoot (Signature, Instance, Table, Address);
3745943f66cSSascha Wildner     if (ACPI_FAILURE (Status))
3755943f66cSSascha Wildner     {
3765943f66cSSascha Wildner         return (Status);
3775943f66cSSascha Wildner     }
3785943f66cSSascha Wildner 
3795943f66cSSascha Wildner     return (AE_OK);
3805943f66cSSascha Wildner }
3815943f66cSSascha Wildner 
3825943f66cSSascha Wildner 
3835943f66cSSascha Wildner /******************************************************************************
3845943f66cSSascha Wildner  *
3855943f66cSSascha Wildner  * FUNCTION:    AcpiOsGetTableByIndex
3865943f66cSSascha Wildner  *
3875943f66cSSascha Wildner  * PARAMETERS:  Index           - Which table to get
3885943f66cSSascha Wildner  *              Table           - Where a pointer to the table is returned
3895943f66cSSascha Wildner  *              Instance        - Where a pointer to the table instance no. is
3905943f66cSSascha Wildner  *                                returned
3915943f66cSSascha Wildner  *              Address         - Where the table physical address is returned
3925943f66cSSascha Wildner  *
3935943f66cSSascha Wildner  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
3945943f66cSSascha Wildner  *              AE_LIMIT: Index is beyond valid limit
3955943f66cSSascha Wildner  *
3965943f66cSSascha Wildner  * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
3975943f66cSSascha Wildner  *              AE_LIMIT when an invalid index is reached. Index is not
3985943f66cSSascha Wildner  *              necessarily an index into the RSDT/XSDT.
3995943f66cSSascha Wildner  *
4005943f66cSSascha Wildner  *****************************************************************************/
4015943f66cSSascha Wildner 
4025943f66cSSascha Wildner ACPI_STATUS
AcpiOsGetTableByIndex(UINT32 Index,ACPI_TABLE_HEADER ** Table,UINT32 * Instance,ACPI_PHYSICAL_ADDRESS * Address)4035943f66cSSascha Wildner AcpiOsGetTableByIndex (
4045943f66cSSascha Wildner     UINT32                  Index,
4055943f66cSSascha Wildner     ACPI_TABLE_HEADER       **Table,
4065943f66cSSascha Wildner     UINT32                  *Instance,
4075943f66cSSascha Wildner     ACPI_PHYSICAL_ADDRESS   *Address)
4085943f66cSSascha Wildner {
4095943f66cSSascha Wildner     OSL_TABLE_INFO          *Info;
4105943f66cSSascha Wildner     ACPI_STATUS             Status;
4115943f66cSSascha Wildner     UINT32                  i;
4125943f66cSSascha Wildner 
4135943f66cSSascha Wildner 
4145943f66cSSascha Wildner     /* Initialize main tables */
4155943f66cSSascha Wildner 
4165943f66cSSascha Wildner     Status = OslTableInitialize ();
4175943f66cSSascha Wildner     if (ACPI_FAILURE (Status))
4185943f66cSSascha Wildner     {
4195943f66cSSascha Wildner         return (Status);
4205943f66cSSascha Wildner     }
4215943f66cSSascha Wildner 
4225943f66cSSascha Wildner     /* Add all tables to list */
4235943f66cSSascha Wildner 
4245943f66cSSascha Wildner     Status = OslAddTablesToList ();
4255943f66cSSascha Wildner     if (ACPI_FAILURE (Status))
4265943f66cSSascha Wildner     {
4275943f66cSSascha Wildner         return (Status);
4285943f66cSSascha Wildner     }
4295943f66cSSascha Wildner 
4305943f66cSSascha Wildner     /* Validate Index */
4315943f66cSSascha Wildner 
4325943f66cSSascha Wildner     if (Index >= Gbl_TableListHead->Instance)
4335943f66cSSascha Wildner     {
4345943f66cSSascha Wildner         return (AE_LIMIT);
4355943f66cSSascha Wildner     }
4365943f66cSSascha Wildner 
4375943f66cSSascha Wildner     /* Point to the table list entry specified by the Index argument */
4385943f66cSSascha Wildner 
4395943f66cSSascha Wildner     Info = Gbl_TableListHead;
4405943f66cSSascha Wildner     for (i = 0; i <= Index; i++)
4415943f66cSSascha Wildner     {
4425943f66cSSascha Wildner         Info = Info->Next;
4435943f66cSSascha Wildner     }
4445943f66cSSascha Wildner 
4455943f66cSSascha Wildner     /* Now we can just get the table via the address or name */
4465943f66cSSascha Wildner 
4475943f66cSSascha Wildner     if (Info->Address)
4485943f66cSSascha Wildner     {
4495943f66cSSascha Wildner         Status = AcpiOsGetTableByAddress (Info->Address, Table);
4505943f66cSSascha Wildner         if (ACPI_SUCCESS (Status))
4515943f66cSSascha Wildner         {
4525943f66cSSascha Wildner             *Address = Info->Address;
4535943f66cSSascha Wildner         }
4545943f66cSSascha Wildner     }
4555943f66cSSascha Wildner     else
4565943f66cSSascha Wildner     {
4575943f66cSSascha Wildner         Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
4585943f66cSSascha Wildner             Table, Address);
4595943f66cSSascha Wildner     }
4605943f66cSSascha Wildner 
4615943f66cSSascha Wildner     if (ACPI_SUCCESS (Status))
4625943f66cSSascha Wildner     {
4635943f66cSSascha Wildner         *Instance = Info->Instance;
4645943f66cSSascha Wildner     }
4655943f66cSSascha Wildner     return (Status);
4665943f66cSSascha Wildner }
4675943f66cSSascha Wildner 
4685943f66cSSascha Wildner 
4695943f66cSSascha Wildner /******************************************************************************
4705943f66cSSascha Wildner  *
4715943f66cSSascha Wildner  * FUNCTION:    OslTableInitialize
4725943f66cSSascha Wildner  *
4735943f66cSSascha Wildner  * PARAMETERS:  None
4745943f66cSSascha Wildner  *
4755943f66cSSascha Wildner  * RETURN:      Status
4765943f66cSSascha Wildner  *
4775943f66cSSascha Wildner  * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
4785943f66cSSascha Wildner  *              local variables. Main ACPI tables include RSDP, FADT, RSDT,
4795943f66cSSascha Wildner  *              and/or XSDT.
4805943f66cSSascha Wildner  *
4815943f66cSSascha Wildner  *****************************************************************************/
4825943f66cSSascha Wildner 
4835943f66cSSascha Wildner static ACPI_STATUS
OslTableInitialize(void)4845943f66cSSascha Wildner OslTableInitialize (
4855943f66cSSascha Wildner     void)
4865943f66cSSascha Wildner {
4872e03c868SSascha Wildner #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
4885943f66cSSascha Wildner     char                    Buffer[32];
4895943f66cSSascha Wildner #endif
4905943f66cSSascha Wildner     ACPI_TABLE_HEADER       *MappedTable;
4915943f66cSSascha Wildner     UINT8                   *TableAddress;
4925943f66cSSascha Wildner     UINT8                   *RsdpAddress;
4935943f66cSSascha Wildner     ACPI_PHYSICAL_ADDRESS   RsdpBase;
4945943f66cSSascha Wildner     ACPI_SIZE               RsdpSize;
4955943f66cSSascha Wildner     ACPI_STATUS             Status;
4965943f66cSSascha Wildner     u_long                  Address = 0;
4972ffe9f16SSascha Wildner #if defined(SYSTEM_SYSCTL)
4985943f66cSSascha Wildner     size_t                  Length = sizeof (Address);
4992ffe9f16SSascha Wildner #endif
5005943f66cSSascha Wildner 
5015943f66cSSascha Wildner 
5025943f66cSSascha Wildner     /* Get main ACPI tables from memory on first invocation of this function */
5035943f66cSSascha Wildner 
5045943f66cSSascha Wildner     if (Gbl_MainTableObtained)
5055943f66cSSascha Wildner     {
5065943f66cSSascha Wildner         return (AE_OK);
5075943f66cSSascha Wildner     }
5085943f66cSSascha Wildner 
5095943f66cSSascha Wildner     /* Attempt to use kenv or sysctl to find RSD PTR record. */
5105943f66cSSascha Wildner 
5115943f66cSSascha Wildner     if (Gbl_RsdpBase)
5125943f66cSSascha Wildner     {
5135943f66cSSascha Wildner         Address = Gbl_RsdpBase;
5145943f66cSSascha Wildner     }
5152e03c868SSascha Wildner #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__)
5165943f66cSSascha Wildner     else if (kenv (KENV_GET, SYSTEM_KENV, Buffer, sizeof (Buffer)) > 0)
5175943f66cSSascha Wildner     {
51825ca8c79SSascha Wildner         Address = strtoul (Buffer, NULL, 0);
5195943f66cSSascha Wildner     }
5205943f66cSSascha Wildner #endif
5212ffe9f16SSascha Wildner #if defined(SYSTEM_SYSCTL)
5225943f66cSSascha Wildner     if (!Address)
5235943f66cSSascha Wildner     {
5245943f66cSSascha Wildner         if (sysctlbyname (SYSTEM_SYSCTL, &Address, &Length, NULL, 0) != 0)
5255943f66cSSascha Wildner         {
5265943f66cSSascha Wildner             Address = 0;
5275943f66cSSascha Wildner         }
5285943f66cSSascha Wildner     }
5292ffe9f16SSascha Wildner #endif
5305943f66cSSascha Wildner     if (Address)
5315943f66cSSascha Wildner     {
5325943f66cSSascha Wildner         RsdpBase = Address;
5335943f66cSSascha Wildner         RsdpSize = sizeof (Gbl_Rsdp);
5345943f66cSSascha Wildner     }
5355943f66cSSascha Wildner     else
5365943f66cSSascha Wildner     {
5375943f66cSSascha Wildner         RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
5385943f66cSSascha Wildner         RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
5395943f66cSSascha Wildner     }
5405943f66cSSascha Wildner 
5415943f66cSSascha Wildner     /* Get RSDP from memory */
5425943f66cSSascha Wildner 
5435943f66cSSascha Wildner     RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
5445943f66cSSascha Wildner     if (!RsdpAddress)
5455943f66cSSascha Wildner     {
5465943f66cSSascha Wildner         return (AE_BAD_ADDRESS);
5475943f66cSSascha Wildner     }
5485943f66cSSascha Wildner 
5495943f66cSSascha Wildner     /* Search low memory for the RSDP */
5505943f66cSSascha Wildner 
5515943f66cSSascha Wildner     TableAddress = AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize);
5525943f66cSSascha Wildner     if (!TableAddress)
5535943f66cSSascha Wildner     {
5545943f66cSSascha Wildner         AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
5555943f66cSSascha Wildner         return (AE_ERROR);
5565943f66cSSascha Wildner     }
5575943f66cSSascha Wildner 
55825ca8c79SSascha Wildner     memcpy (&Gbl_Rsdp, TableAddress, sizeof (Gbl_Rsdp));
5595943f66cSSascha Wildner     AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
5605943f66cSSascha Wildner 
5615943f66cSSascha Wildner     /* Get XSDT from memory */
5625943f66cSSascha Wildner 
5635943f66cSSascha Wildner     if (Gbl_Rsdp.Revision)
5645943f66cSSascha Wildner     {
5655943f66cSSascha Wildner         Status = OslMapTable (Gbl_Rsdp.XsdtPhysicalAddress,
5665943f66cSSascha Wildner             ACPI_SIG_XSDT, &MappedTable);
5675943f66cSSascha Wildner         if (ACPI_FAILURE (Status))
5685943f66cSSascha Wildner         {
5695943f66cSSascha Wildner             return (Status);
5705943f66cSSascha Wildner         }
5715943f66cSSascha Wildner 
5725943f66cSSascha Wildner         Gbl_Revision = 2;
5735943f66cSSascha Wildner         Gbl_Xsdt = calloc (1, MappedTable->Length);
5745943f66cSSascha Wildner         if (!Gbl_Xsdt)
5755943f66cSSascha Wildner         {
5765943f66cSSascha Wildner             fprintf (stderr,
5775943f66cSSascha Wildner                 "XSDT: Could not allocate buffer for table of length %X\n",
5785943f66cSSascha Wildner                 MappedTable->Length);
5795943f66cSSascha Wildner             AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
5805943f66cSSascha Wildner             return (AE_NO_MEMORY);
5815943f66cSSascha Wildner         }
5825943f66cSSascha Wildner 
58325ca8c79SSascha Wildner         memcpy (Gbl_Xsdt, MappedTable, MappedTable->Length);
5845943f66cSSascha Wildner         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
5855943f66cSSascha Wildner     }
5865943f66cSSascha Wildner 
5875943f66cSSascha Wildner     /* Get RSDT from memory */
5885943f66cSSascha Wildner 
5895943f66cSSascha Wildner     if (Gbl_Rsdp.RsdtPhysicalAddress)
5905943f66cSSascha Wildner     {
5915943f66cSSascha Wildner         Status = OslMapTable (Gbl_Rsdp.RsdtPhysicalAddress,
5925943f66cSSascha Wildner             ACPI_SIG_RSDT, &MappedTable);
5935943f66cSSascha Wildner         if (ACPI_FAILURE (Status))
5945943f66cSSascha Wildner         {
5955943f66cSSascha Wildner             return (Status);
5965943f66cSSascha Wildner         }
5975943f66cSSascha Wildner 
5985943f66cSSascha Wildner         Gbl_Rsdt = calloc (1, MappedTable->Length);
5995943f66cSSascha Wildner         if (!Gbl_Rsdt)
6005943f66cSSascha Wildner         {
6015943f66cSSascha Wildner             fprintf (stderr,
6025943f66cSSascha Wildner                 "RSDT: Could not allocate buffer for table of length %X\n",
6035943f66cSSascha Wildner                 MappedTable->Length);
6045943f66cSSascha Wildner             AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
6055943f66cSSascha Wildner             return (AE_NO_MEMORY);
6065943f66cSSascha Wildner         }
6075943f66cSSascha Wildner 
60825ca8c79SSascha Wildner         memcpy (Gbl_Rsdt, MappedTable, MappedTable->Length);
6095943f66cSSascha Wildner         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
6105943f66cSSascha Wildner     }
6115943f66cSSascha Wildner 
6125943f66cSSascha Wildner     /* Get FADT from memory */
6135943f66cSSascha Wildner 
6145943f66cSSascha Wildner     if (Gbl_Revision)
6155943f66cSSascha Wildner     {
6165943f66cSSascha Wildner         Gbl_FadtAddress = Gbl_Xsdt->TableOffsetEntry[0];
6175943f66cSSascha Wildner     }
6185943f66cSSascha Wildner     else
6195943f66cSSascha Wildner     {
6205943f66cSSascha Wildner         Gbl_FadtAddress = Gbl_Rsdt->TableOffsetEntry[0];
6215943f66cSSascha Wildner     }
6225943f66cSSascha Wildner 
6235943f66cSSascha Wildner     if (!Gbl_FadtAddress)
6245943f66cSSascha Wildner     {
6255943f66cSSascha Wildner         fprintf(stderr, "FADT: Table could not be found\n");
6265943f66cSSascha Wildner         return (AE_ERROR);
6275943f66cSSascha Wildner     }
6285943f66cSSascha Wildner 
6295943f66cSSascha Wildner     Status = OslMapTable (Gbl_FadtAddress, ACPI_SIG_FADT, &MappedTable);
6305943f66cSSascha Wildner     if (ACPI_FAILURE (Status))
6315943f66cSSascha Wildner     {
6325943f66cSSascha Wildner         return (Status);
6335943f66cSSascha Wildner     }
6345943f66cSSascha Wildner 
6355943f66cSSascha Wildner     Gbl_Fadt = calloc (1, MappedTable->Length);
6365943f66cSSascha Wildner     if (!Gbl_Fadt)
6375943f66cSSascha Wildner     {
6385943f66cSSascha Wildner         fprintf (stderr,
6395943f66cSSascha Wildner             "FADT: Could not allocate buffer for table of length %X\n",
6405943f66cSSascha Wildner             MappedTable->Length);
6415943f66cSSascha Wildner         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
6425943f66cSSascha Wildner         return (AE_NO_MEMORY);
6435943f66cSSascha Wildner     }
6445943f66cSSascha Wildner 
64525ca8c79SSascha Wildner     memcpy (Gbl_Fadt, MappedTable, MappedTable->Length);
6465943f66cSSascha Wildner     AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
6475943f66cSSascha Wildner     Gbl_MainTableObtained = TRUE;
6485943f66cSSascha Wildner     return (AE_OK);
6495943f66cSSascha Wildner }
6505943f66cSSascha Wildner 
6515943f66cSSascha Wildner 
6525943f66cSSascha Wildner /******************************************************************************
6535943f66cSSascha Wildner  *
6545943f66cSSascha Wildner  * FUNCTION:    OslGetTableViaRoot
6555943f66cSSascha Wildner  *
6565943f66cSSascha Wildner  * PARAMETERS:  Signature       - ACPI Signature for common table. Must be
6575943f66cSSascha Wildner  *                                a null terminated 4-character string.
6585943f66cSSascha Wildner  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
6595943f66cSSascha Wildner  *                                Must be 0 for other tables.
6605943f66cSSascha Wildner  *              Table           - Where a pointer to the table is returned
6615943f66cSSascha Wildner  *              Address         - Where the table physical address is returned
6625943f66cSSascha Wildner  *
6635943f66cSSascha Wildner  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
6645943f66cSSascha Wildner  *              AE_LIMIT: Instance is beyond valid limit
6655943f66cSSascha Wildner  *              AE_NOT_FOUND: A table with the signature was not found
6665943f66cSSascha Wildner  *
6675943f66cSSascha Wildner  * DESCRIPTION: Get an ACPI table via the root table (RSDT/XSDT)
6685943f66cSSascha Wildner  *
6695943f66cSSascha Wildner  * NOTE:        Assumes the input signature is uppercase.
6705943f66cSSascha Wildner  *
6715943f66cSSascha Wildner  *****************************************************************************/
6725943f66cSSascha Wildner 
6735943f66cSSascha Wildner static ACPI_STATUS
OslGetTableViaRoot(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)6745943f66cSSascha Wildner OslGetTableViaRoot (
6755943f66cSSascha Wildner     char                    *Signature,
6765943f66cSSascha Wildner     UINT32                  Instance,
6775943f66cSSascha Wildner     ACPI_TABLE_HEADER       **Table,
6785943f66cSSascha Wildner     ACPI_PHYSICAL_ADDRESS   *Address)
6795943f66cSSascha Wildner {
6805943f66cSSascha Wildner     ACPI_TABLE_HEADER       *LocalTable = NULL;
6815943f66cSSascha Wildner     ACPI_TABLE_HEADER       *MappedTable = NULL;
6825943f66cSSascha Wildner     UINT8                   NumberOfTables;
6835943f66cSSascha Wildner     UINT32                  CurrentInstance = 0;
6845943f66cSSascha Wildner     ACPI_PHYSICAL_ADDRESS   TableAddress = 0;
6855943f66cSSascha Wildner     ACPI_STATUS             Status;
6865943f66cSSascha Wildner     UINT32                  i;
6875943f66cSSascha Wildner 
6885943f66cSSascha Wildner 
6895943f66cSSascha Wildner     /* DSDT and FACS address must be extracted from the FADT */
6905943f66cSSascha Wildner 
691c1776041SSascha Wildner     if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT) ||
692c1776041SSascha Wildner         ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS))
6935943f66cSSascha Wildner     {
6945943f66cSSascha Wildner         /*
6955943f66cSSascha Wildner          * Get the appropriate address, either 32-bit or 64-bit. Be very
6965943f66cSSascha Wildner          * careful about the FADT length and validate table addresses.
6975943f66cSSascha Wildner          * Note: The 64-bit addresses have priority.
6985943f66cSSascha Wildner          */
699c1776041SSascha Wildner         if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT))
7005943f66cSSascha Wildner         {
7015943f66cSSascha Wildner             if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
7025943f66cSSascha Wildner                 Gbl_Fadt->XDsdt)
7035943f66cSSascha Wildner             {
7045943f66cSSascha Wildner                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
7055943f66cSSascha Wildner             }
7065943f66cSSascha Wildner             else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
7075943f66cSSascha Wildner                 Gbl_Fadt->Dsdt)
7085943f66cSSascha Wildner             {
7095943f66cSSascha Wildner                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
7105943f66cSSascha Wildner             }
7115943f66cSSascha Wildner         }
7125943f66cSSascha Wildner         else /* FACS */
7135943f66cSSascha Wildner         {
7145943f66cSSascha Wildner             if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
7155943f66cSSascha Wildner                 Gbl_Fadt->XFacs)
7165943f66cSSascha Wildner             {
7175943f66cSSascha Wildner                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
7185943f66cSSascha Wildner             }
7195943f66cSSascha Wildner             else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
7205943f66cSSascha Wildner                 Gbl_Fadt->Facs)
7215943f66cSSascha Wildner             {
7225943f66cSSascha Wildner                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
7235943f66cSSascha Wildner             }
7245943f66cSSascha Wildner         }
7255943f66cSSascha Wildner     }
7265943f66cSSascha Wildner     else /* Case for a normal ACPI table */
7275943f66cSSascha Wildner     {
7285943f66cSSascha Wildner         if (Gbl_Revision)
7295943f66cSSascha Wildner         {
7305943f66cSSascha Wildner             NumberOfTables =
7315943f66cSSascha Wildner                 (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
7325943f66cSSascha Wildner                 / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
7335943f66cSSascha Wildner         }
7345943f66cSSascha Wildner         else /* Use RSDT if XSDT is not available */
7355943f66cSSascha Wildner         {
7365943f66cSSascha Wildner             NumberOfTables =
7375943f66cSSascha Wildner                 (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
7385943f66cSSascha Wildner                 / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
7395943f66cSSascha Wildner         }
7405943f66cSSascha Wildner 
7415943f66cSSascha Wildner         /* Search RSDT/XSDT for the requested table */
7425943f66cSSascha Wildner 
7435943f66cSSascha Wildner         for (i = 0; i < NumberOfTables; i++)
7445943f66cSSascha Wildner         {
7455943f66cSSascha Wildner             if (Gbl_Revision)
7465943f66cSSascha Wildner             {
7475943f66cSSascha Wildner                 TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
7485943f66cSSascha Wildner             }
7495943f66cSSascha Wildner             else
7505943f66cSSascha Wildner             {
7515943f66cSSascha Wildner                 TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
7525943f66cSSascha Wildner             }
7535943f66cSSascha Wildner 
7545943f66cSSascha Wildner             MappedTable = AcpiOsMapMemory (TableAddress, sizeof (*MappedTable));
7555943f66cSSascha Wildner             if (!MappedTable)
7565943f66cSSascha Wildner             {
7575943f66cSSascha Wildner                 return (AE_BAD_ADDRESS);
7585943f66cSSascha Wildner             }
7595943f66cSSascha Wildner 
7605943f66cSSascha Wildner             /* Does this table match the requested signature? */
7615943f66cSSascha Wildner 
762c1776041SSascha Wildner             if (ACPI_COMPARE_NAMESEG (MappedTable->Signature, Signature))
7635943f66cSSascha Wildner             {
7645943f66cSSascha Wildner 
7655943f66cSSascha Wildner                 /* Match table instance (for SSDT/UEFI tables) */
7665943f66cSSascha Wildner 
7675943f66cSSascha Wildner                 if (CurrentInstance == Instance)
7685943f66cSSascha Wildner                 {
7695943f66cSSascha Wildner                     AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
7705943f66cSSascha Wildner                     break;
7715943f66cSSascha Wildner                 }
7725943f66cSSascha Wildner 
7735943f66cSSascha Wildner                 CurrentInstance++;
7745943f66cSSascha Wildner             }
7755943f66cSSascha Wildner 
7765943f66cSSascha Wildner             AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
7775943f66cSSascha Wildner             TableAddress = 0;
7785943f66cSSascha Wildner         }
7795943f66cSSascha Wildner     }
7805943f66cSSascha Wildner 
7815943f66cSSascha Wildner     if (!TableAddress)
7825943f66cSSascha Wildner     {
7835943f66cSSascha Wildner         if (CurrentInstance)
7845943f66cSSascha Wildner         {
7855943f66cSSascha Wildner             return (AE_LIMIT);
7865943f66cSSascha Wildner         }
7875943f66cSSascha Wildner         return (AE_NOT_FOUND);
7885943f66cSSascha Wildner     }
7895943f66cSSascha Wildner 
7905943f66cSSascha Wildner     /* Now we can get the requested table */
7915943f66cSSascha Wildner 
7925943f66cSSascha Wildner     Status = OslMapTable (TableAddress, Signature, &MappedTable);
7935943f66cSSascha Wildner     if (ACPI_FAILURE (Status))
7945943f66cSSascha Wildner     {
7955943f66cSSascha Wildner         return (Status);
7965943f66cSSascha Wildner     }
7975943f66cSSascha Wildner 
7985943f66cSSascha Wildner     /* Copy table to local buffer and return it */
7995943f66cSSascha Wildner 
8005943f66cSSascha Wildner     LocalTable = calloc (1, MappedTable->Length);
8015943f66cSSascha Wildner     if (!LocalTable)
8025943f66cSSascha Wildner     {
8035943f66cSSascha Wildner         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
8045943f66cSSascha Wildner         return (AE_NO_MEMORY);
8055943f66cSSascha Wildner     }
8065943f66cSSascha Wildner 
80725ca8c79SSascha Wildner     memcpy (LocalTable, MappedTable, MappedTable->Length);
8085943f66cSSascha Wildner     AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
8095943f66cSSascha Wildner     *Table = LocalTable;
8105943f66cSSascha Wildner     *Address = TableAddress;
8115943f66cSSascha Wildner     return (AE_OK);
8125943f66cSSascha Wildner }
8135943f66cSSascha Wildner 
8145943f66cSSascha Wildner 
8155943f66cSSascha Wildner /******************************************************************************
8165943f66cSSascha Wildner  *
8175943f66cSSascha Wildner  * FUNCTION:    OslAddTablesToList
8185943f66cSSascha Wildner  *
8195943f66cSSascha Wildner  * PARAMETERS:  None
8205943f66cSSascha Wildner  *
8215943f66cSSascha Wildner  * RETURN:      Status; Table list is initialized if AE_OK.
8225943f66cSSascha Wildner  *
8235943f66cSSascha Wildner  * DESCRIPTION: Add ACPI tables to the table list.
8245943f66cSSascha Wildner  *
8255943f66cSSascha Wildner  *****************************************************************************/
8265943f66cSSascha Wildner 
8275943f66cSSascha Wildner static ACPI_STATUS
OslAddTablesToList(void)8285943f66cSSascha Wildner OslAddTablesToList(
8295943f66cSSascha Wildner     void)
8305943f66cSSascha Wildner {
8315943f66cSSascha Wildner     ACPI_PHYSICAL_ADDRESS   TableAddress;
8325943f66cSSascha Wildner     OSL_TABLE_INFO          *Info = NULL;
8335943f66cSSascha Wildner     OSL_TABLE_INFO          *NewInfo;
8345943f66cSSascha Wildner     ACPI_TABLE_HEADER       *Table;
8355943f66cSSascha Wildner     UINT8                   Instance;
8365943f66cSSascha Wildner     UINT8                   NumberOfTables;
8375943f66cSSascha Wildner     int                     i;
8385943f66cSSascha Wildner 
8395943f66cSSascha Wildner 
8405943f66cSSascha Wildner     /* Initialize the table list on first invocation */
8415943f66cSSascha Wildner 
8425943f66cSSascha Wildner     if (Gbl_TableListInitialized)
8435943f66cSSascha Wildner     {
8445943f66cSSascha Wildner         return (AE_OK);
8455943f66cSSascha Wildner     }
8465943f66cSSascha Wildner 
8475943f66cSSascha Wildner     /* Add mandatory tables to global table list first */
8485943f66cSSascha Wildner 
8495943f66cSSascha Wildner     for (i = 0; i < 4; i++)
8505943f66cSSascha Wildner     {
8515943f66cSSascha Wildner         NewInfo = calloc (1, sizeof (*NewInfo));
8525943f66cSSascha Wildner         if (!NewInfo)
8535943f66cSSascha Wildner         {
8545943f66cSSascha Wildner             return (AE_NO_MEMORY);
8555943f66cSSascha Wildner         }
8565943f66cSSascha Wildner 
8575943f66cSSascha Wildner         switch (i) {
8585943f66cSSascha Wildner         case 0:
8595943f66cSSascha Wildner 
8605943f66cSSascha Wildner             Gbl_TableListHead = Info = NewInfo;
8615943f66cSSascha Wildner             continue;
8625943f66cSSascha Wildner 
8635943f66cSSascha Wildner         case 1:
8645943f66cSSascha Wildner 
865c1776041SSascha Wildner             ACPI_COPY_NAMESEG (NewInfo->Signature,
8665943f66cSSascha Wildner                 Gbl_Revision ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
8675943f66cSSascha Wildner             break;
8685943f66cSSascha Wildner 
8695943f66cSSascha Wildner         case 2:
8705943f66cSSascha Wildner 
871c1776041SSascha Wildner             ACPI_COPY_NAMESEG (NewInfo->Signature, ACPI_SIG_FACS);
8725943f66cSSascha Wildner             break;
8735943f66cSSascha Wildner 
8745943f66cSSascha Wildner         default:
8755943f66cSSascha Wildner 
876c1776041SSascha Wildner             ACPI_COPY_NAMESEG (NewInfo->Signature, ACPI_SIG_DSDT);
8775943f66cSSascha Wildner 
8785943f66cSSascha Wildner         }
8795943f66cSSascha Wildner 
8805943f66cSSascha Wildner         Info->Next = NewInfo;
8815943f66cSSascha Wildner         Info = NewInfo;
8825943f66cSSascha Wildner         Gbl_TableListHead->Instance++;
8835943f66cSSascha Wildner     }
8845943f66cSSascha Wildner 
8855943f66cSSascha Wildner     /* Add normal tables from RSDT/XSDT to global list */
8865943f66cSSascha Wildner 
8875943f66cSSascha Wildner     if (Gbl_Revision)
8885943f66cSSascha Wildner     {
8895943f66cSSascha Wildner         NumberOfTables =
8905943f66cSSascha Wildner             (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
8915943f66cSSascha Wildner             / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
8925943f66cSSascha Wildner     }
8935943f66cSSascha Wildner     else
8945943f66cSSascha Wildner     {
8955943f66cSSascha Wildner         NumberOfTables =
8965943f66cSSascha Wildner             (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
8975943f66cSSascha Wildner             / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
8985943f66cSSascha Wildner     }
8995943f66cSSascha Wildner 
9005943f66cSSascha Wildner     for (i = 0; i < NumberOfTables; i++)
9015943f66cSSascha Wildner     {
9025943f66cSSascha Wildner         if (Gbl_Revision)
9035943f66cSSascha Wildner         {
9045943f66cSSascha Wildner             TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
9055943f66cSSascha Wildner         }
9065943f66cSSascha Wildner         else
9075943f66cSSascha Wildner         {
9085943f66cSSascha Wildner             TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
9095943f66cSSascha Wildner         }
9105943f66cSSascha Wildner 
9115943f66cSSascha Wildner         Table = AcpiOsMapMemory (TableAddress, sizeof (*Table));
9125943f66cSSascha Wildner         if (!Table)
9135943f66cSSascha Wildner         {
9145943f66cSSascha Wildner             return (AE_BAD_ADDRESS);
9155943f66cSSascha Wildner         }
9165943f66cSSascha Wildner 
9175943f66cSSascha Wildner         Instance = 0;
9185943f66cSSascha Wildner         NewInfo = Gbl_TableListHead;
9195943f66cSSascha Wildner         while (NewInfo->Next != NULL)
9205943f66cSSascha Wildner         {
9215943f66cSSascha Wildner             NewInfo = NewInfo->Next;
922c1776041SSascha Wildner             if (ACPI_COMPARE_NAMESEG (Table->Signature, NewInfo->Signature))
9235943f66cSSascha Wildner             {
9245943f66cSSascha Wildner                 Instance++;
9255943f66cSSascha Wildner             }
9265943f66cSSascha Wildner         }
9275943f66cSSascha Wildner 
9285943f66cSSascha Wildner         NewInfo = calloc (1, sizeof (*NewInfo));
9295943f66cSSascha Wildner         if (!NewInfo)
9305943f66cSSascha Wildner         {
9315943f66cSSascha Wildner             AcpiOsUnmapMemory (Table, sizeof (*Table));
9325943f66cSSascha Wildner             return (AE_NO_MEMORY);
9335943f66cSSascha Wildner         }
9345943f66cSSascha Wildner 
935c1776041SSascha Wildner         ACPI_COPY_NAMESEG (NewInfo->Signature, Table->Signature);
9365943f66cSSascha Wildner 
9375943f66cSSascha Wildner         AcpiOsUnmapMemory (Table, sizeof (*Table));
9385943f66cSSascha Wildner 
9395943f66cSSascha Wildner         NewInfo->Instance = Instance;
9405943f66cSSascha Wildner         NewInfo->Address = TableAddress;
9415943f66cSSascha Wildner         Info->Next = NewInfo;
9425943f66cSSascha Wildner         Info = NewInfo;
9435943f66cSSascha Wildner         Gbl_TableListHead->Instance++;
9445943f66cSSascha Wildner     }
9455943f66cSSascha Wildner 
9465943f66cSSascha Wildner     Gbl_TableListInitialized = TRUE;
9475943f66cSSascha Wildner     return (AE_OK);
9485943f66cSSascha Wildner }
9495943f66cSSascha Wildner 
9505943f66cSSascha Wildner 
9515943f66cSSascha Wildner /******************************************************************************
9525943f66cSSascha Wildner  *
9535943f66cSSascha Wildner  * FUNCTION:    OslMapTable
9545943f66cSSascha Wildner  *
9555943f66cSSascha Wildner  * PARAMETERS:  Address             - Address of the table in memory
9565943f66cSSascha Wildner  *              Signature           - Optional ACPI Signature for desired table.
9575943f66cSSascha Wildner  *                                    Null terminated 4-character string.
9585943f66cSSascha Wildner  *              Table               - Where a pointer to the mapped table is
9595943f66cSSascha Wildner  *                                    returned
9605943f66cSSascha Wildner  *
9615943f66cSSascha Wildner  * RETURN:      Status; Mapped table is returned if AE_OK.
9625943f66cSSascha Wildner  *
9635943f66cSSascha Wildner  * DESCRIPTION: Map entire ACPI table into caller's address space. Also
9645943f66cSSascha Wildner  *              validates the table and checksum.
9655943f66cSSascha Wildner  *
9665943f66cSSascha Wildner  *****************************************************************************/
9675943f66cSSascha Wildner 
9685943f66cSSascha Wildner static ACPI_STATUS
OslMapTable(ACPI_SIZE Address,char * Signature,ACPI_TABLE_HEADER ** Table)9695943f66cSSascha Wildner OslMapTable (
9705943f66cSSascha Wildner     ACPI_SIZE               Address,
9715943f66cSSascha Wildner     char                    *Signature,
9725943f66cSSascha Wildner     ACPI_TABLE_HEADER       **Table)
9735943f66cSSascha Wildner {
9745943f66cSSascha Wildner     ACPI_TABLE_HEADER       *MappedTable;
9755943f66cSSascha Wildner     UINT32                  Length;
9765943f66cSSascha Wildner 
9775943f66cSSascha Wildner 
9785943f66cSSascha Wildner     /* Map the header so we can get the table length */
9795943f66cSSascha Wildner 
9805943f66cSSascha Wildner     MappedTable = AcpiOsMapMemory (Address, sizeof (*MappedTable));
9815943f66cSSascha Wildner     if (!MappedTable)
9825943f66cSSascha Wildner     {
9835943f66cSSascha Wildner         return (AE_BAD_ADDRESS);
9845943f66cSSascha Wildner     }
9855943f66cSSascha Wildner 
9865943f66cSSascha Wildner     /* Check if table is valid */
9875943f66cSSascha Wildner 
9885943f66cSSascha Wildner     if (!ApIsValidHeader (MappedTable))
9895943f66cSSascha Wildner     {
9905943f66cSSascha Wildner         AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
9915943f66cSSascha Wildner         return (AE_BAD_HEADER);
9925943f66cSSascha Wildner     }
9935943f66cSSascha Wildner 
9945943f66cSSascha Wildner     /* If specified, signature must match */
9955943f66cSSascha Wildner 
9965943f66cSSascha Wildner     if (Signature &&
997c1776041SSascha Wildner         !ACPI_COMPARE_NAMESEG (Signature, MappedTable->Signature))
9985943f66cSSascha Wildner     {
9995943f66cSSascha Wildner         AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
10005943f66cSSascha Wildner         return (AE_NOT_EXIST);
10015943f66cSSascha Wildner     }
10025943f66cSSascha Wildner 
10035943f66cSSascha Wildner     /* Map the entire table */
10045943f66cSSascha Wildner 
10055943f66cSSascha Wildner     Length = MappedTable->Length;
10065943f66cSSascha Wildner     AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
10075943f66cSSascha Wildner 
10085943f66cSSascha Wildner     MappedTable = AcpiOsMapMemory (Address, Length);
10095943f66cSSascha Wildner     if (!MappedTable)
10105943f66cSSascha Wildner     {
10115943f66cSSascha Wildner         return (AE_BAD_ADDRESS);
10125943f66cSSascha Wildner     }
10135943f66cSSascha Wildner 
10145943f66cSSascha Wildner     (void) ApIsValidChecksum (MappedTable);
10155943f66cSSascha Wildner 
10165943f66cSSascha Wildner     *Table = MappedTable;
10175943f66cSSascha Wildner 
10185943f66cSSascha Wildner     return (AE_OK);
10195943f66cSSascha Wildner }
1020