Home | History | Annotate | Line # | Download | only in service_layers
      1 /******************************************************************************
      2  *
      3  * Module Name: osbsdtbl - BSD OSL for obtaining ACPI tables
      4  *
      5  *****************************************************************************/
      6 
      7 /******************************************************************************
      8  *
      9  * 1. Copyright Notice
     10  *
     11  * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
     12  * All rights reserved.
     13  *
     14  * 2. License
     15  *
     16  * 2.1. This is your license from Intel Corp. under its intellectual property
     17  * rights. You may have additional license terms from the party that provided
     18  * you this software, covering your right to use that party's intellectual
     19  * property rights.
     20  *
     21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     22  * copy of the source code appearing in this file ("Covered Code") an
     23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     24  * base code distributed originally by Intel ("Original Intel Code") to copy,
     25  * make derivatives, distribute, use and display any portion of the Covered
     26  * Code in any form, with the right to sublicense such rights; and
     27  *
     28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     29  * license (with the right to sublicense), under only those claims of Intel
     30  * patents that are infringed by the Original Intel Code, to make, use, sell,
     31  * offer to sell, and import the Covered Code and derivative works thereof
     32  * solely to the minimum extent necessary to exercise the above copyright
     33  * license, and in no event shall the patent license extend to any additions
     34  * to or modifications of the Original Intel Code. No other license or right
     35  * is granted directly or by implication, estoppel or otherwise;
     36  *
     37  * The above copyright and patent license is granted only if the following
     38  * conditions are met:
     39  *
     40  * 3. Conditions
     41  *
     42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     43  * Redistribution of source code of any substantial portion of the Covered
     44  * Code or modification with rights to further distribute source must include
     45  * the above Copyright Notice, the above License, this list of Conditions,
     46  * and the following Disclaimer and Export Compliance provision. In addition,
     47  * Licensee must cause all Covered Code to which Licensee contributes to
     48  * contain a file documenting the changes Licensee made to create that Covered
     49  * Code and the date of any change. Licensee must include in that file the
     50  * documentation of any changes made by any predecessor Licensee. Licensee
     51  * must include a prominent statement that the modification is derived,
     52  * directly or indirectly, from Original Intel Code.
     53  *
     54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     55  * Redistribution of source code of any substantial portion of the Covered
     56  * Code or modification without rights to further distribute source must
     57  * include the following Disclaimer and Export Compliance provision in the
     58  * documentation and/or other materials provided with distribution. In
     59  * addition, Licensee may not authorize further sublicense of source of any
     60  * portion of the Covered Code, and must include terms to the effect that the
     61  * license from Licensee to its licensee is limited to the intellectual
     62  * property embodied in the software Licensee provides to its licensee, and
     63  * not to intellectual property embodied in modifications its licensee may
     64  * make.
     65  *
     66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     67  * substantial portion of the Covered Code or modification must reproduce the
     68  * above Copyright Notice, and the following Disclaimer and Export Compliance
     69  * provision in the documentation and/or other materials provided with the
     70  * distribution.
     71  *
     72  * 3.4. Intel retains all right, title, and interest in and to the Original
     73  * Intel Code.
     74  *
     75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     76  * Intel shall be used in advertising or otherwise to promote the sale, use or
     77  * other dealings in products derived from or relating to the Covered Code
     78  * without prior written authorization from Intel.
     79  *
     80  * 4. Disclaimer and Export Compliance
     81  *
     82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
     85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
     86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
     87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     88  * PARTICULAR PURPOSE.
     89  *
     90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
     96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     97  * LIMITED REMEDY.
     98  *
     99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    100  * software or system incorporating such software without first obtaining any
    101  * required license or other approval from the U. S. Department of Commerce or
    102  * any other agency or department of the United States Government. In the
    103  * event Licensee exports any such software from the United States or
    104  * re-exports any such software from a foreign destination, Licensee shall
    105  * ensure that the distribution and export/re-export of the software is in
    106  * compliance with all laws, regulations, orders, or other restrictions of the
    107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    108  * any of its subsidiaries will export/re-export any technical data, process,
    109  * software, or service, directly or indirectly, to any country for which the
    110  * United States government or any agency thereof requires an export license,
    111  * other governmental approval, or letter of assurance, without first obtaining
    112  * such license, approval or letter.
    113  *
    114  *****************************************************************************
    115  *
    116  * Alternatively, you may choose to be licensed under the terms of the
    117  * following license:
    118  *
    119  * Redistribution and use in source and binary forms, with or without
    120  * modification, are permitted provided that the following conditions
    121  * are met:
    122  * 1. Redistributions of source code must retain the above copyright
    123  *    notice, this list of conditions, and the following disclaimer,
    124  *    without modification.
    125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
    126  *    substantially similar to the "NO WARRANTY" disclaimer below
    127  *    ("Disclaimer") and any redistribution must be conditioned upon
    128  *    including a substantially similar Disclaimer requirement for further
    129  *    binary redistribution.
    130  * 3. Neither the names of the above-listed copyright holders nor the names
    131  *    of any contributors may be used to endorse or promote products derived
    132  *    from this software without specific prior written permission.
    133  *
    134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    145  *
    146  * Alternatively, you may choose to be licensed under the terms of the
    147  * GNU General Public License ("GPL") version 2 as published by the Free
    148  * Software Foundation.
    149  *
    150  *****************************************************************************/
    151 
    152 #include "acpidump.h"
    153 
    154 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__)
    155 #include <kenv.h>
    156 #endif
    157 #include <unistd.h>
    158 #include <sys/param.h>
    159 #include <sys/sysctl.h>
    160 
    161 
    162 #define _COMPONENT          ACPI_OS_SERVICES
    163         ACPI_MODULE_NAME    ("osbsdtbl")
    164 
    165 
    166 /* Local prototypes */
    167 
    168 static ACPI_STATUS
    169 OslTableInitialize (
    170     void);
    171 
    172 static ACPI_STATUS
    173 OslMapTable (
    174     ACPI_SIZE               Address,
    175     char                    *Signature,
    176     ACPI_TABLE_HEADER       **Table);
    177 
    178 static ACPI_STATUS
    179 OslAddTablesToList (
    180     void);
    181 
    182 static ACPI_STATUS
    183 OslGetTableViaRoot (
    184     char                    *Signature,
    185     UINT32                  Instance,
    186     ACPI_TABLE_HEADER       **Table,
    187     ACPI_PHYSICAL_ADDRESS   *Address);
    188 
    189 
    190 /* Hints for RSDP */
    191 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
    192 #define SYSTEM_KENV         "hint.acpi.0.rsdp"
    193 #define SYSTEM_SYSCTL       "machdep.acpi_root"
    194 #elif defined(__NetBSD__)
    195 #define SYSTEM_SYSCTL       "hw.acpi.root"
    196 #endif
    197 
    198 /* Initialization flags */
    199 
    200 UINT8                   Gbl_TableListInitialized = FALSE;
    201 UINT8                   Gbl_MainTableObtained = FALSE;
    202 
    203 /* Local copies of main ACPI tables */
    204 
    205 ACPI_TABLE_RSDP         Gbl_Rsdp;
    206 ACPI_TABLE_FADT         *Gbl_Fadt;
    207 ACPI_TABLE_RSDT         *Gbl_Rsdt;
    208 ACPI_TABLE_XSDT         *Gbl_Xsdt;
    209 
    210 /* Fadt address */
    211 
    212 ACPI_PHYSICAL_ADDRESS   Gbl_FadtAddress;
    213 
    214 /* Revision of RSD PTR */
    215 
    216 UINT8                   Gbl_Revision;
    217 
    218 /* List of information about obtained ACPI tables */
    219 
    220 typedef struct          table_info
    221 {
    222     struct table_info       *Next;
    223     char                    Signature[4];
    224     UINT32                  Instance;
    225     ACPI_PHYSICAL_ADDRESS   Address;
    226 
    227 } OSL_TABLE_INFO;
    228 
    229 OSL_TABLE_INFO          *Gbl_TableListHead = NULL;
    230 
    231 
    232 /******************************************************************************
    233  *
    234  * FUNCTION:    AcpiOsGetTableByAddress
    235  *
    236  * PARAMETERS:  Address         - Physical address of the ACPI table
    237  *              Table           - Where a pointer to the table is returned
    238  *
    239  * RETURN:      Status; Table buffer is returned if AE_OK.
    240  *              AE_NOT_FOUND: A valid table was not found at the address
    241  *
    242  * DESCRIPTION: Get an ACPI table via a physical memory address.
    243  *
    244  *****************************************************************************/
    245 
    246 ACPI_STATUS
    247 AcpiOsGetTableByAddress (
    248     ACPI_PHYSICAL_ADDRESS   Address,
    249     ACPI_TABLE_HEADER       **Table)
    250 {
    251     ACPI_TABLE_HEADER       *MappedTable;
    252     ACPI_TABLE_HEADER       *LocalTable;
    253     ACPI_STATUS             Status;
    254 
    255 
    256     /* Validate the input physical address to avoid program crash */
    257 
    258     if (Address < ACPI_HI_RSDP_WINDOW_BASE)
    259     {
    260         fprintf (stderr, "Invalid table address: 0x%8.8X%8.8X\n",
    261             ACPI_FORMAT_UINT64 (Address));
    262         return (AE_BAD_ADDRESS);
    263     }
    264 
    265     /* Map the table and validate it */
    266 
    267     Status = OslMapTable (Address, NULL, &MappedTable);
    268     if (ACPI_FAILURE (Status))
    269     {
    270         return (Status);
    271     }
    272 
    273     /* Copy table to local buffer and return it */
    274 
    275     LocalTable = calloc (1, MappedTable->Length);
    276     if (!LocalTable)
    277     {
    278         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    279         return (AE_NO_MEMORY);
    280     }
    281 
    282     memcpy (LocalTable, MappedTable, MappedTable->Length);
    283     AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    284 
    285     *Table = LocalTable;
    286     return (AE_OK);
    287 }
    288 
    289 
    290 /******************************************************************************
    291  *
    292  * FUNCTION:    AcpiOsGetTableByName
    293  *
    294  * PARAMETERS:  Signature       - ACPI Signature for desired table. Must be
    295  *                                a null terminated 4-character string.
    296  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
    297  *                                Must be 0 for other tables.
    298  *              Table           - Where a pointer to the table is returned
    299  *              Address         - Where the table physical address is returned
    300  *
    301  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
    302  *              AE_LIMIT: Instance is beyond valid limit
    303  *              AE_NOT_FOUND: A table with the signature was not found
    304  *
    305  * NOTE:        Assumes the input signature is uppercase.
    306  *
    307  *****************************************************************************/
    308 
    309 ACPI_STATUS
    310 AcpiOsGetTableByName (
    311     char                    *Signature,
    312     UINT32                  Instance,
    313     ACPI_TABLE_HEADER       **Table,
    314     ACPI_PHYSICAL_ADDRESS   *Address)
    315 {
    316     ACPI_STATUS             Status;
    317 
    318 
    319     /* Instance is only valid for SSDT/UEFI tables */
    320 
    321     if (Instance &&
    322         !ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_SSDT) &&
    323         !ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_UEFI))
    324     {
    325         return (AE_LIMIT);
    326     }
    327 
    328     /* Initialize main tables */
    329 
    330     Status = OslTableInitialize ();
    331     if (ACPI_FAILURE (Status))
    332     {
    333         return (Status);
    334     }
    335 
    336     /*
    337      * If one of the main ACPI tables was requested (RSDT/XSDT/FADT),
    338      * simply return it immediately.
    339      */
    340     if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT))
    341     {
    342         if (!Gbl_Revision)
    343         {
    344             return (AE_NOT_FOUND);
    345         }
    346 
    347         *Address = Gbl_Rsdp.XsdtPhysicalAddress;
    348         *Table = (ACPI_TABLE_HEADER *) Gbl_Xsdt;
    349         return (AE_OK);
    350     }
    351 
    352     if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT))
    353     {
    354         if (!Gbl_Rsdp.RsdtPhysicalAddress)
    355         {
    356             return (AE_NOT_FOUND);
    357         }
    358 
    359         *Address = Gbl_Rsdp.RsdtPhysicalAddress;
    360         *Table = (ACPI_TABLE_HEADER *) Gbl_Rsdt;
    361         return (AE_OK);
    362     }
    363 
    364     if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FADT))
    365     {
    366         *Address = Gbl_FadtAddress;
    367         *Table = (ACPI_TABLE_HEADER *) Gbl_Fadt;
    368         return (AE_OK);
    369     }
    370 
    371     /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
    372 
    373     Status = OslGetTableViaRoot (Signature, Instance, Table, Address);
    374     if (ACPI_FAILURE (Status))
    375     {
    376         return (Status);
    377     }
    378 
    379     return (AE_OK);
    380 }
    381 
    382 
    383 /******************************************************************************
    384  *
    385  * FUNCTION:    AcpiOsGetTableByIndex
    386  *
    387  * PARAMETERS:  Index           - Which table to get
    388  *              Table           - Where a pointer to the table is returned
    389  *              Instance        - Where a pointer to the table instance no. is
    390  *                                returned
    391  *              Address         - Where the table physical address is returned
    392  *
    393  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
    394  *              AE_LIMIT: Index is beyond valid limit
    395  *
    396  * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
    397  *              AE_LIMIT when an invalid index is reached. Index is not
    398  *              necessarily an index into the RSDT/XSDT.
    399  *
    400  *****************************************************************************/
    401 
    402 ACPI_STATUS
    403 AcpiOsGetTableByIndex (
    404     UINT32                  Index,
    405     ACPI_TABLE_HEADER       **Table,
    406     UINT32                  *Instance,
    407     ACPI_PHYSICAL_ADDRESS   *Address)
    408 {
    409     OSL_TABLE_INFO          *Info;
    410     ACPI_STATUS             Status;
    411     UINT32                  i;
    412 
    413 
    414     /* Initialize main tables */
    415 
    416     Status = OslTableInitialize ();
    417     if (ACPI_FAILURE (Status))
    418     {
    419         return (Status);
    420     }
    421 
    422     /* Add all tables to list */
    423 
    424     Status = OslAddTablesToList ();
    425     if (ACPI_FAILURE (Status))
    426     {
    427         return (Status);
    428     }
    429 
    430     /* Validate Index */
    431 
    432     if (Index >= Gbl_TableListHead->Instance)
    433     {
    434         return (AE_LIMIT);
    435     }
    436 
    437     /* Point to the table list entry specified by the Index argument */
    438 
    439     Info = Gbl_TableListHead;
    440     for (i = 0; i <= Index; i++)
    441     {
    442         Info = Info->Next;
    443     }
    444 
    445     /* Now we can just get the table via the address or name */
    446 
    447     if (Info->Address)
    448     {
    449         Status = AcpiOsGetTableByAddress (Info->Address, Table);
    450         if (ACPI_SUCCESS (Status))
    451         {
    452             *Address = Info->Address;
    453         }
    454     }
    455     else
    456     {
    457         Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
    458             Table, Address);
    459     }
    460 
    461     if (ACPI_SUCCESS (Status))
    462     {
    463         *Instance = Info->Instance;
    464     }
    465     return (Status);
    466 }
    467 
    468 
    469 /******************************************************************************
    470  *
    471  * FUNCTION:    OslTableInitialize
    472  *
    473  * PARAMETERS:  None
    474  *
    475  * RETURN:      Status
    476  *
    477  * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
    478  *              local variables. Main ACPI tables include RSDP, FADT, RSDT,
    479  *              and/or XSDT.
    480  *
    481  *****************************************************************************/
    482 
    483 static ACPI_STATUS
    484 OslTableInitialize (
    485     void)
    486 {
    487 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
    488     char                    Buffer[32];
    489 #endif
    490     ACPI_TABLE_HEADER       *MappedTable;
    491     UINT8                   *TableAddress;
    492     UINT8                   *RsdpAddress;
    493     ACPI_PHYSICAL_ADDRESS   RsdpBase;
    494     ACPI_SIZE               RsdpSize;
    495     ACPI_STATUS             Status;
    496     u_long                  Address = 0;
    497 #if defined(SYSTEM_SYSCTL)
    498     size_t                  Length = sizeof (Address);
    499 #endif
    500 
    501 
    502     /* Get main ACPI tables from memory on first invocation of this function */
    503 
    504     if (Gbl_MainTableObtained)
    505     {
    506         return (AE_OK);
    507     }
    508 
    509     /* Attempt to use kenv or sysctl to find RSD PTR record. */
    510 
    511     if (Gbl_RsdpBase)
    512     {
    513         Address = Gbl_RsdpBase;
    514     }
    515 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__)
    516     else if (kenv (KENV_GET, SYSTEM_KENV, Buffer, sizeof (Buffer)) > 0)
    517     {
    518         Address = strtoul (Buffer, NULL, 0);
    519     }
    520 #endif
    521 #if defined(SYSTEM_SYSCTL)
    522     if (!Address)
    523     {
    524         if (sysctlbyname (SYSTEM_SYSCTL, &Address, &Length, NULL, 0) != 0)
    525         {
    526             Address = 0;
    527         }
    528     }
    529 #endif
    530     if (Address)
    531     {
    532         RsdpBase = Address;
    533         RsdpSize = sizeof (Gbl_Rsdp);
    534     }
    535     else
    536     {
    537         RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
    538         RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
    539     }
    540 
    541     /* Get RSDP from memory */
    542 
    543     RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
    544     if (!RsdpAddress)
    545     {
    546         return (AE_BAD_ADDRESS);
    547     }
    548 
    549     /* Search low memory for the RSDP */
    550 
    551     TableAddress = AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize);
    552     if (!TableAddress)
    553     {
    554         AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
    555         return (AE_ERROR);
    556     }
    557 
    558     memcpy (&Gbl_Rsdp, TableAddress, sizeof (Gbl_Rsdp));
    559     AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
    560 
    561     /* Get XSDT from memory */
    562 
    563     if (Gbl_Rsdp.Revision)
    564     {
    565         Status = OslMapTable (Gbl_Rsdp.XsdtPhysicalAddress,
    566             ACPI_SIG_XSDT, &MappedTable);
    567         if (ACPI_FAILURE (Status))
    568         {
    569             return (Status);
    570         }
    571 
    572         Gbl_Revision = 2;
    573         Gbl_Xsdt = calloc (1, MappedTable->Length);
    574         if (!Gbl_Xsdt)
    575         {
    576             fprintf (stderr,
    577                 "XSDT: Could not allocate buffer for table of length %X\n",
    578                 MappedTable->Length);
    579             AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    580             return (AE_NO_MEMORY);
    581         }
    582 
    583         memcpy (Gbl_Xsdt, MappedTable, MappedTable->Length);
    584         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    585     }
    586 
    587     /* Get RSDT from memory */
    588 
    589     if (Gbl_Rsdp.RsdtPhysicalAddress)
    590     {
    591         Status = OslMapTable (Gbl_Rsdp.RsdtPhysicalAddress,
    592             ACPI_SIG_RSDT, &MappedTable);
    593         if (ACPI_FAILURE (Status))
    594         {
    595             return (Status);
    596         }
    597 
    598         Gbl_Rsdt = calloc (1, MappedTable->Length);
    599         if (!Gbl_Rsdt)
    600         {
    601             fprintf (stderr,
    602                 "RSDT: Could not allocate buffer for table of length %X\n",
    603                 MappedTable->Length);
    604             AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    605             return (AE_NO_MEMORY);
    606         }
    607 
    608         memcpy (Gbl_Rsdt, MappedTable, MappedTable->Length);
    609         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    610     }
    611 
    612     /* Get FADT from memory */
    613 
    614     if (Gbl_Revision)
    615     {
    616         Gbl_FadtAddress = Gbl_Xsdt->TableOffsetEntry[0];
    617     }
    618     else
    619     {
    620         Gbl_FadtAddress = Gbl_Rsdt->TableOffsetEntry[0];
    621     }
    622 
    623     if (!Gbl_FadtAddress)
    624     {
    625         fprintf(stderr, "FADT: Table could not be found\n");
    626         return (AE_ERROR);
    627     }
    628 
    629     Status = OslMapTable (Gbl_FadtAddress, ACPI_SIG_FADT, &MappedTable);
    630     if (ACPI_FAILURE (Status))
    631     {
    632         return (Status);
    633     }
    634 
    635     Gbl_Fadt = calloc (1, MappedTable->Length);
    636     if (!Gbl_Fadt)
    637     {
    638         fprintf (stderr,
    639             "FADT: Could not allocate buffer for table of length %X\n",
    640             MappedTable->Length);
    641         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    642         return (AE_NO_MEMORY);
    643     }
    644 
    645     memcpy (Gbl_Fadt, MappedTable, MappedTable->Length);
    646     AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    647     Gbl_MainTableObtained = TRUE;
    648     return (AE_OK);
    649 }
    650 
    651 
    652 /******************************************************************************
    653  *
    654  * FUNCTION:    OslGetTableViaRoot
    655  *
    656  * PARAMETERS:  Signature       - ACPI Signature for common table. Must be
    657  *                                a null terminated 4-character string.
    658  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
    659  *                                Must be 0 for other tables.
    660  *              Table           - Where a pointer to the table is returned
    661  *              Address         - Where the table physical address is returned
    662  *
    663  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
    664  *              AE_LIMIT: Instance is beyond valid limit
    665  *              AE_NOT_FOUND: A table with the signature was not found
    666  *
    667  * DESCRIPTION: Get an ACPI table via the root table (RSDT/XSDT)
    668  *
    669  * NOTE:        Assumes the input signature is uppercase.
    670  *
    671  *****************************************************************************/
    672 
    673 static ACPI_STATUS
    674 OslGetTableViaRoot (
    675     char                    *Signature,
    676     UINT32                  Instance,
    677     ACPI_TABLE_HEADER       **Table,
    678     ACPI_PHYSICAL_ADDRESS   *Address)
    679 {
    680     ACPI_TABLE_HEADER       *LocalTable = NULL;
    681     ACPI_TABLE_HEADER       *MappedTable = NULL;
    682     UINT8                   NumberOfTables;
    683     UINT32                  CurrentInstance = 0;
    684     ACPI_PHYSICAL_ADDRESS   TableAddress = 0;
    685     ACPI_STATUS             Status;
    686     UINT32                  i;
    687 
    688 
    689     /* DSDT and FACS address must be extracted from the FADT */
    690 
    691     if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT) ||
    692         ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS))
    693     {
    694         /*
    695          * Get the appropriate address, either 32-bit or 64-bit. Be very
    696          * careful about the FADT length and validate table addresses.
    697          * Note: The 64-bit addresses have priority.
    698          */
    699         if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT))
    700         {
    701             if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
    702                 Gbl_Fadt->XDsdt)
    703             {
    704                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
    705             }
    706             else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
    707                 Gbl_Fadt->Dsdt)
    708             {
    709                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
    710             }
    711         }
    712         else /* FACS */
    713         {
    714             if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
    715                 Gbl_Fadt->XFacs)
    716             {
    717                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
    718             }
    719             else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
    720                 Gbl_Fadt->Facs)
    721             {
    722                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
    723             }
    724         }
    725     }
    726     else /* Case for a normal ACPI table */
    727     {
    728         if (Gbl_Revision)
    729         {
    730             NumberOfTables =
    731                 (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
    732                 / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
    733         }
    734         else /* Use RSDT if XSDT is not available */
    735         {
    736             NumberOfTables =
    737                 (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
    738                 / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
    739         }
    740 
    741         /* Search RSDT/XSDT for the requested table */
    742 
    743         for (i = 0; i < NumberOfTables; i++)
    744         {
    745             if (Gbl_Revision)
    746             {
    747                 TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
    748             }
    749             else
    750             {
    751                 TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
    752             }
    753 
    754             MappedTable = AcpiOsMapMemory (TableAddress, sizeof (*MappedTable));
    755             if (!MappedTable)
    756             {
    757                 return (AE_BAD_ADDRESS);
    758             }
    759 
    760             /* Does this table match the requested signature? */
    761 
    762             if (ACPI_COMPARE_NAMESEG (MappedTable->Signature, Signature))
    763             {
    764 
    765                 /* Match table instance (for SSDT/UEFI tables) */
    766 
    767                 if (CurrentInstance == Instance)
    768                 {
    769                     AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
    770                     break;
    771                 }
    772 
    773                 CurrentInstance++;
    774             }
    775 
    776             AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    777             TableAddress = 0;
    778         }
    779     }
    780 
    781     if (!TableAddress)
    782     {
    783         if (CurrentInstance)
    784         {
    785             return (AE_LIMIT);
    786         }
    787         return (AE_NOT_FOUND);
    788     }
    789 
    790     /* Now we can get the requested table */
    791 
    792     Status = OslMapTable (TableAddress, Signature, &MappedTable);
    793     if (ACPI_FAILURE (Status))
    794     {
    795         return (Status);
    796     }
    797 
    798     /* Copy table to local buffer and return it */
    799 
    800     LocalTable = calloc (1, MappedTable->Length);
    801     if (!LocalTable)
    802     {
    803         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    804         return (AE_NO_MEMORY);
    805     }
    806 
    807     memcpy (LocalTable, MappedTable, MappedTable->Length);
    808     AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    809     *Table = LocalTable;
    810     *Address = TableAddress;
    811     return (AE_OK);
    812 }
    813 
    814 
    815 /******************************************************************************
    816  *
    817  * FUNCTION:    OslAddTablesToList
    818  *
    819  * PARAMETERS:  None
    820  *
    821  * RETURN:      Status; Table list is initialized if AE_OK.
    822  *
    823  * DESCRIPTION: Add ACPI tables to the table list.
    824  *
    825  *****************************************************************************/
    826 
    827 static ACPI_STATUS
    828 OslAddTablesToList(
    829     void)
    830 {
    831     ACPI_PHYSICAL_ADDRESS   TableAddress;
    832     OSL_TABLE_INFO          *Info = NULL;
    833     OSL_TABLE_INFO          *NewInfo;
    834     ACPI_TABLE_HEADER       *Table;
    835     UINT8                   Instance;
    836     UINT8                   NumberOfTables;
    837     int                     i;
    838 
    839 
    840     /* Initialize the table list on first invocation */
    841 
    842     if (Gbl_TableListInitialized)
    843     {
    844         return (AE_OK);
    845     }
    846 
    847     /* Add mandatory tables to global table list first */
    848 
    849     for (i = 0; i < 4; i++)
    850     {
    851         NewInfo = calloc (1, sizeof (*NewInfo));
    852         if (!NewInfo)
    853         {
    854             return (AE_NO_MEMORY);
    855         }
    856 
    857         switch (i) {
    858         case 0:
    859 
    860             Gbl_TableListHead = Info = NewInfo;
    861             continue;
    862 
    863         case 1:
    864 
    865             ACPI_COPY_NAMESEG (NewInfo->Signature,
    866                 Gbl_Revision ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
    867             break;
    868 
    869         case 2:
    870 
    871             ACPI_COPY_NAMESEG (NewInfo->Signature, ACPI_SIG_FACS);
    872             break;
    873 
    874         default:
    875 
    876             ACPI_COPY_NAMESEG (NewInfo->Signature, ACPI_SIG_DSDT);
    877 
    878         }
    879 
    880         Info->Next = NewInfo;
    881         Info = NewInfo;
    882         Gbl_TableListHead->Instance++;
    883     }
    884 
    885     /* Add normal tables from RSDT/XSDT to global list */
    886 
    887     if (Gbl_Revision)
    888     {
    889         NumberOfTables =
    890             (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
    891             / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
    892     }
    893     else
    894     {
    895         NumberOfTables =
    896             (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
    897             / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
    898     }
    899 
    900     for (i = 0; i < NumberOfTables; i++)
    901     {
    902         if (Gbl_Revision)
    903         {
    904             TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
    905         }
    906         else
    907         {
    908             TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
    909         }
    910 
    911         Table = AcpiOsMapMemory (TableAddress, sizeof (*Table));
    912         if (!Table)
    913         {
    914             return (AE_BAD_ADDRESS);
    915         }
    916 
    917         Instance = 0;
    918         NewInfo = Gbl_TableListHead;
    919         while (NewInfo->Next != NULL)
    920         {
    921             NewInfo = NewInfo->Next;
    922             if (ACPI_COMPARE_NAMESEG (Table->Signature, NewInfo->Signature))
    923             {
    924                 Instance++;
    925             }
    926         }
    927 
    928         NewInfo = calloc (1, sizeof (*NewInfo));
    929         if (!NewInfo)
    930         {
    931             AcpiOsUnmapMemory (Table, sizeof (*Table));
    932             return (AE_NO_MEMORY);
    933         }
    934 
    935         ACPI_COPY_NAMESEG (NewInfo->Signature, Table->Signature);
    936 
    937         AcpiOsUnmapMemory (Table, sizeof (*Table));
    938 
    939         NewInfo->Instance = Instance;
    940         NewInfo->Address = TableAddress;
    941         Info->Next = NewInfo;
    942         Info = NewInfo;
    943         Gbl_TableListHead->Instance++;
    944     }
    945 
    946     Gbl_TableListInitialized = TRUE;
    947     return (AE_OK);
    948 }
    949 
    950 
    951 /******************************************************************************
    952  *
    953  * FUNCTION:    OslMapTable
    954  *
    955  * PARAMETERS:  Address             - Address of the table in memory
    956  *              Signature           - Optional ACPI Signature for desired table.
    957  *                                    Null terminated 4-character string.
    958  *              Table               - Where a pointer to the mapped table is
    959  *                                    returned
    960  *
    961  * RETURN:      Status; Mapped table is returned if AE_OK.
    962  *
    963  * DESCRIPTION: Map entire ACPI table into caller's address space. Also
    964  *              validates the table and checksum.
    965  *
    966  *****************************************************************************/
    967 
    968 static ACPI_STATUS
    969 OslMapTable (
    970     ACPI_SIZE               Address,
    971     char                    *Signature,
    972     ACPI_TABLE_HEADER       **Table)
    973 {
    974     ACPI_TABLE_HEADER       *MappedTable;
    975     UINT32                  Length;
    976 
    977 
    978     /* Map the header so we can get the table length */
    979 
    980     MappedTable = AcpiOsMapMemory (Address, sizeof (*MappedTable));
    981     if (!MappedTable)
    982     {
    983         return (AE_BAD_ADDRESS);
    984     }
    985 
    986     /* Check if table is valid */
    987 
    988     if (!ApIsValidHeader (MappedTable))
    989     {
    990         AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
    991         return (AE_BAD_HEADER);
    992     }
    993 
    994     /* If specified, signature must match */
    995 
    996     if (Signature &&
    997         !ACPI_COMPARE_NAMESEG (Signature, MappedTable->Signature))
    998     {
    999         AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
   1000         return (AE_NOT_EXIST);
   1001     }
   1002 
   1003     /* Map the entire table */
   1004 
   1005     Length = MappedTable->Length;
   1006     AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
   1007 
   1008     MappedTable = AcpiOsMapMemory (Address, Length);
   1009     if (!MappedTable)
   1010     {
   1011         return (AE_BAD_ADDRESS);
   1012     }
   1013 
   1014     (void) ApIsValidChecksum (MappedTable);
   1015 
   1016     *Table = MappedTable;
   1017 
   1018     return (AE_OK);
   1019 }
   1020