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 - 2016, 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#include "acpidump.h"
117
118#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__)
119#include <kenv.h>
120#endif
121#include <unistd.h>
122#include <sys/param.h>
123#include <sys/sysctl.h>
124
125
126#define _COMPONENT          ACPI_OS_SERVICES
127        ACPI_MODULE_NAME    ("osbsdtbl")
128
129
130/* Local prototypes */
131
132static ACPI_STATUS
133OslTableInitialize (
134    void);
135
136static ACPI_STATUS
137OslMapTable (
138    ACPI_SIZE               Address,
139    char                    *Signature,
140    ACPI_TABLE_HEADER       **Table);
141
142static ACPI_STATUS
143OslAddTablesToList (
144    void);
145
146static ACPI_STATUS
147OslGetTableViaRoot (
148    char                    *Signature,
149    UINT32                  Instance,
150    ACPI_TABLE_HEADER       **Table,
151    ACPI_PHYSICAL_ADDRESS   *Address);
152
153
154/* Hints for RSDP */
155#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
156#define SYSTEM_KENV         "hint.acpi.0.rsdp"
157#define SYSTEM_SYSCTL       "machdep.acpi_root"
158#elif defined(__NetBSD__)
159#define SYSTEM_SYSCTL       "hw.acpi.root"
160#endif
161
162/* Initialization flags */
163
164UINT8                   Gbl_TableListInitialized = FALSE;
165UINT8                   Gbl_MainTableObtained = FALSE;
166
167/* Local copies of main ACPI tables */
168
169ACPI_TABLE_RSDP         Gbl_Rsdp;
170ACPI_TABLE_FADT         *Gbl_Fadt;
171ACPI_TABLE_RSDT         *Gbl_Rsdt;
172ACPI_TABLE_XSDT         *Gbl_Xsdt;
173
174/* Fadt address */
175
176ACPI_PHYSICAL_ADDRESS   Gbl_FadtAddress;
177
178/* Revision of RSD PTR */
179
180UINT8                   Gbl_Revision;
181
182/* List of information about obtained ACPI tables */
183
184typedef struct          table_info
185{
186    struct table_info       *Next;
187    char                    Signature[4];
188    UINT32                  Instance;
189    ACPI_PHYSICAL_ADDRESS   Address;
190
191} OSL_TABLE_INFO;
192
193OSL_TABLE_INFO          *Gbl_TableListHead = NULL;
194
195
196/******************************************************************************
197 *
198 * FUNCTION:    AcpiOsGetTableByAddress
199 *
200 * PARAMETERS:  Address         - Physical address of the ACPI table
201 *              Table           - Where a pointer to the table is returned
202 *
203 * RETURN:      Status; Table buffer is returned if AE_OK.
204 *              AE_NOT_FOUND: A valid table was not found at the address
205 *
206 * DESCRIPTION: Get an ACPI table via a physical memory address.
207 *
208 *****************************************************************************/
209
210ACPI_STATUS
211AcpiOsGetTableByAddress (
212    ACPI_PHYSICAL_ADDRESS   Address,
213    ACPI_TABLE_HEADER       **Table)
214{
215    ACPI_TABLE_HEADER       *MappedTable;
216    ACPI_TABLE_HEADER       *LocalTable;
217    ACPI_STATUS             Status;
218
219
220    /* Validate the input physical address to avoid program crash */
221
222    if (Address < ACPI_HI_RSDP_WINDOW_BASE)
223    {
224        fprintf (stderr, "Invalid table address: 0x%8.8X%8.8X\n",
225            ACPI_FORMAT_UINT64 (Address));
226        return (AE_BAD_ADDRESS);
227    }
228
229    /* Map the table and validate it */
230
231    Status = OslMapTable (Address, NULL, &MappedTable);
232    if (ACPI_FAILURE (Status))
233    {
234        return (Status);
235    }
236
237    /* Copy table to local buffer and return it */
238
239    LocalTable = calloc (1, MappedTable->Length);
240    if (!LocalTable)
241    {
242        AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
243        return (AE_NO_MEMORY);
244    }
245
246    memcpy (LocalTable, MappedTable, MappedTable->Length);
247    AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
248
249    *Table = LocalTable;
250    return (AE_OK);
251}
252
253
254/******************************************************************************
255 *
256 * FUNCTION:    AcpiOsGetTableByName
257 *
258 * PARAMETERS:  Signature       - ACPI Signature for desired table. Must be
259 *                                a null terminated 4-character string.
260 *              Instance        - Multiple table support for SSDT/UEFI (0...n)
261 *                                Must be 0 for other tables.
262 *              Table           - Where a pointer to the table is returned
263 *              Address         - Where the table physical address is returned
264 *
265 * RETURN:      Status; Table buffer and physical address returned if AE_OK.
266 *              AE_LIMIT: Instance is beyond valid limit
267 *              AE_NOT_FOUND: A table with the signature was not found
268 *
269 * NOTE:        Assumes the input signature is uppercase.
270 *
271 *****************************************************************************/
272
273ACPI_STATUS
274AcpiOsGetTableByName (
275    char                    *Signature,
276    UINT32                  Instance,
277    ACPI_TABLE_HEADER       **Table,
278    ACPI_PHYSICAL_ADDRESS   *Address)
279{
280    ACPI_STATUS             Status;
281
282
283    /* Instance is only valid for SSDT/UEFI tables */
284
285    if (Instance &&
286        !ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT) &&
287        !ACPI_COMPARE_NAME (Signature, ACPI_SIG_UEFI))
288    {
289        return (AE_LIMIT);
290    }
291
292    /* Initialize main tables */
293
294    Status = OslTableInitialize ();
295    if (ACPI_FAILURE (Status))
296    {
297        return (Status);
298    }
299
300    /*
301     * If one of the main ACPI tables was requested (RSDT/XSDT/FADT),
302     * simply return it immediately.
303     */
304    if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT))
305    {
306        if (!Gbl_Revision)
307        {
308            return (AE_NOT_FOUND);
309        }
310
311        *Address = Gbl_Rsdp.XsdtPhysicalAddress;
312        *Table = (ACPI_TABLE_HEADER *) Gbl_Xsdt;
313        return (AE_OK);
314    }
315
316    if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT))
317    {
318        if (!Gbl_Rsdp.RsdtPhysicalAddress)
319        {
320            return (AE_NOT_FOUND);
321        }
322
323        *Address = Gbl_Rsdp.RsdtPhysicalAddress;
324        *Table = (ACPI_TABLE_HEADER *) Gbl_Rsdt;
325        return (AE_OK);
326    }
327
328    if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FADT))
329    {
330        *Address = Gbl_FadtAddress;
331        *Table = (ACPI_TABLE_HEADER *) Gbl_Fadt;
332        return (AE_OK);
333    }
334
335    /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
336
337    Status = OslGetTableViaRoot (Signature, Instance, Table, Address);
338    if (ACPI_FAILURE (Status))
339    {
340        return (Status);
341    }
342
343    return (AE_OK);
344}
345
346
347/******************************************************************************
348 *
349 * FUNCTION:    AcpiOsGetTableByIndex
350 *
351 * PARAMETERS:  Index           - Which table to get
352 *              Table           - Where a pointer to the table is returned
353 *              Instance        - Where a pointer to the table instance no. is
354 *                                returned
355 *              Address         - Where the table physical address is returned
356 *
357 * RETURN:      Status; Table buffer and physical address returned if AE_OK.
358 *              AE_LIMIT: Index is beyond valid limit
359 *
360 * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
361 *              AE_LIMIT when an invalid index is reached. Index is not
362 *              necessarily an index into the RSDT/XSDT.
363 *
364 *****************************************************************************/
365
366ACPI_STATUS
367AcpiOsGetTableByIndex (
368    UINT32                  Index,
369    ACPI_TABLE_HEADER       **Table,
370    UINT32                  *Instance,
371    ACPI_PHYSICAL_ADDRESS   *Address)
372{
373    OSL_TABLE_INFO          *Info;
374    ACPI_STATUS             Status;
375    UINT32                  i;
376
377
378    /* Initialize main tables */
379
380    Status = OslTableInitialize ();
381    if (ACPI_FAILURE (Status))
382    {
383        return (Status);
384    }
385
386    /* Add all tables to list */
387
388    Status = OslAddTablesToList ();
389    if (ACPI_FAILURE (Status))
390    {
391        return (Status);
392    }
393
394    /* Validate Index */
395
396    if (Index >= Gbl_TableListHead->Instance)
397    {
398        return (AE_LIMIT);
399    }
400
401    /* Point to the table list entry specified by the Index argument */
402
403    Info = Gbl_TableListHead;
404    for (i = 0; i <= Index; i++)
405    {
406        Info = Info->Next;
407    }
408
409    /* Now we can just get the table via the address or name */
410
411    if (Info->Address)
412    {
413        Status = AcpiOsGetTableByAddress (Info->Address, Table);
414        if (ACPI_SUCCESS (Status))
415        {
416            *Address = Info->Address;
417        }
418    }
419    else
420    {
421        Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
422            Table, Address);
423    }
424
425    if (ACPI_SUCCESS (Status))
426    {
427        *Instance = Info->Instance;
428    }
429    return (Status);
430}
431
432
433/******************************************************************************
434 *
435 * FUNCTION:    OslTableInitialize
436 *
437 * PARAMETERS:  None
438 *
439 * RETURN:      Status
440 *
441 * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
442 *              local variables. Main ACPI tables include RSDP, FADT, RSDT,
443 *              and/or XSDT.
444 *
445 *****************************************************************************/
446
447static ACPI_STATUS
448OslTableInitialize (
449    void)
450{
451#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
452    char                    Buffer[32];
453#endif
454    ACPI_TABLE_HEADER       *MappedTable;
455    UINT8                   *TableAddress;
456    UINT8                   *RsdpAddress;
457    ACPI_PHYSICAL_ADDRESS   RsdpBase;
458    ACPI_SIZE               RsdpSize;
459    ACPI_STATUS             Status;
460    u_long                  Address = 0;
461#if defined(SYSTEM_SYSCTL)
462    size_t                  Length = sizeof (Address);
463#endif
464
465
466    /* Get main ACPI tables from memory on first invocation of this function */
467
468    if (Gbl_MainTableObtained)
469    {
470        return (AE_OK);
471    }
472
473    /* Attempt to use kenv or sysctl to find RSD PTR record. */
474
475    if (Gbl_RsdpBase)
476    {
477        Address = Gbl_RsdpBase;
478    }
479#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__)
480    else if (kenv (KENV_GET, SYSTEM_KENV, Buffer, sizeof (Buffer)) > 0)
481    {
482        Address = strtoul (Buffer, NULL, 0);
483    }
484#endif
485#if defined(SYSTEM_SYSCTL)
486    if (!Address)
487    {
488        if (sysctlbyname (SYSTEM_SYSCTL, &Address, &Length, NULL, 0) != 0)
489        {
490            Address = 0;
491        }
492    }
493#endif
494    if (Address)
495    {
496        RsdpBase = Address;
497        RsdpSize = sizeof (Gbl_Rsdp);
498    }
499    else
500    {
501        RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
502        RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
503    }
504
505    /* Get RSDP from memory */
506
507    RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
508    if (!RsdpAddress)
509    {
510        return (AE_BAD_ADDRESS);
511    }
512
513    /* Search low memory for the RSDP */
514
515    TableAddress = AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize);
516    if (!TableAddress)
517    {
518        AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
519        return (AE_ERROR);
520    }
521
522    memcpy (&Gbl_Rsdp, TableAddress, sizeof (Gbl_Rsdp));
523    AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
524
525    /* Get XSDT from memory */
526
527    if (Gbl_Rsdp.Revision)
528    {
529        Status = OslMapTable (Gbl_Rsdp.XsdtPhysicalAddress,
530            ACPI_SIG_XSDT, &MappedTable);
531        if (ACPI_FAILURE (Status))
532        {
533            return (Status);
534        }
535
536        Gbl_Revision = 2;
537        Gbl_Xsdt = calloc (1, MappedTable->Length);
538        if (!Gbl_Xsdt)
539        {
540            fprintf (stderr,
541                "XSDT: Could not allocate buffer for table of length %X\n",
542                MappedTable->Length);
543            AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
544            return (AE_NO_MEMORY);
545        }
546
547        memcpy (Gbl_Xsdt, MappedTable, MappedTable->Length);
548        AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
549    }
550
551    /* Get RSDT from memory */
552
553    if (Gbl_Rsdp.RsdtPhysicalAddress)
554    {
555        Status = OslMapTable (Gbl_Rsdp.RsdtPhysicalAddress,
556            ACPI_SIG_RSDT, &MappedTable);
557        if (ACPI_FAILURE (Status))
558        {
559            return (Status);
560        }
561
562        Gbl_Rsdt = calloc (1, MappedTable->Length);
563        if (!Gbl_Rsdt)
564        {
565            fprintf (stderr,
566                "RSDT: Could not allocate buffer for table of length %X\n",
567                MappedTable->Length);
568            AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
569            return (AE_NO_MEMORY);
570        }
571
572        memcpy (Gbl_Rsdt, MappedTable, MappedTable->Length);
573        AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
574    }
575
576    /* Get FADT from memory */
577
578    if (Gbl_Revision)
579    {
580        Gbl_FadtAddress = Gbl_Xsdt->TableOffsetEntry[0];
581    }
582    else
583    {
584        Gbl_FadtAddress = Gbl_Rsdt->TableOffsetEntry[0];
585    }
586
587    if (!Gbl_FadtAddress)
588    {
589        fprintf(stderr, "FADT: Table could not be found\n");
590        return (AE_ERROR);
591    }
592
593    Status = OslMapTable (Gbl_FadtAddress, ACPI_SIG_FADT, &MappedTable);
594    if (ACPI_FAILURE (Status))
595    {
596        return (Status);
597    }
598
599    Gbl_Fadt = calloc (1, MappedTable->Length);
600    if (!Gbl_Fadt)
601    {
602        fprintf (stderr,
603            "FADT: Could not allocate buffer for table of length %X\n",
604            MappedTable->Length);
605        AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
606        return (AE_NO_MEMORY);
607    }
608
609    memcpy (Gbl_Fadt, MappedTable, MappedTable->Length);
610    AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
611    Gbl_MainTableObtained = TRUE;
612    return (AE_OK);
613}
614
615
616/******************************************************************************
617 *
618 * FUNCTION:    OslGetTableViaRoot
619 *
620 * PARAMETERS:  Signature       - ACPI Signature for common table. Must be
621 *                                a null terminated 4-character string.
622 *              Instance        - Multiple table support for SSDT/UEFI (0...n)
623 *                                Must be 0 for other tables.
624 *              Table           - Where a pointer to the table is returned
625 *              Address         - Where the table physical address is returned
626 *
627 * RETURN:      Status; Table buffer and physical address returned if AE_OK.
628 *              AE_LIMIT: Instance is beyond valid limit
629 *              AE_NOT_FOUND: A table with the signature was not found
630 *
631 * DESCRIPTION: Get an ACPI table via the root table (RSDT/XSDT)
632 *
633 * NOTE:        Assumes the input signature is uppercase.
634 *
635 *****************************************************************************/
636
637static ACPI_STATUS
638OslGetTableViaRoot (
639    char                    *Signature,
640    UINT32                  Instance,
641    ACPI_TABLE_HEADER       **Table,
642    ACPI_PHYSICAL_ADDRESS   *Address)
643{
644    ACPI_TABLE_HEADER       *LocalTable = NULL;
645    ACPI_TABLE_HEADER       *MappedTable = NULL;
646    UINT8                   NumberOfTables;
647    UINT32                  CurrentInstance = 0;
648    ACPI_PHYSICAL_ADDRESS   TableAddress = 0;
649    ACPI_STATUS             Status;
650    UINT32                  i;
651
652
653    /* DSDT and FACS address must be extracted from the FADT */
654
655    if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) ||
656        ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
657    {
658        /*
659         * Get the appropriate address, either 32-bit or 64-bit. Be very
660         * careful about the FADT length and validate table addresses.
661         * Note: The 64-bit addresses have priority.
662         */
663        if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT))
664        {
665            if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
666                Gbl_Fadt->XDsdt)
667            {
668                TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
669            }
670            else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
671                Gbl_Fadt->Dsdt)
672            {
673                TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
674            }
675        }
676        else /* FACS */
677        {
678            if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
679                Gbl_Fadt->XFacs)
680            {
681                TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
682            }
683            else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
684                Gbl_Fadt->Facs)
685            {
686                TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
687            }
688        }
689    }
690    else /* Case for a normal ACPI table */
691    {
692        if (Gbl_Revision)
693        {
694            NumberOfTables =
695                (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
696                / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
697        }
698        else /* Use RSDT if XSDT is not available */
699        {
700            NumberOfTables =
701                (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
702                / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
703        }
704
705        /* Search RSDT/XSDT for the requested table */
706
707        for (i = 0; i < NumberOfTables; i++)
708        {
709            if (Gbl_Revision)
710            {
711                TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
712            }
713            else
714            {
715                TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
716            }
717
718            MappedTable = AcpiOsMapMemory (TableAddress, sizeof (*MappedTable));
719            if (!MappedTable)
720            {
721                return (AE_BAD_ADDRESS);
722            }
723
724            /* Does this table match the requested signature? */
725
726            if (ACPI_COMPARE_NAME (MappedTable->Signature, Signature))
727            {
728
729                /* Match table instance (for SSDT/UEFI tables) */
730
731                if (CurrentInstance == Instance)
732                {
733                    AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
734                    break;
735                }
736
737                CurrentInstance++;
738            }
739
740            AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
741            TableAddress = 0;
742        }
743    }
744
745    if (!TableAddress)
746    {
747        if (CurrentInstance)
748        {
749            return (AE_LIMIT);
750        }
751        return (AE_NOT_FOUND);
752    }
753
754    /* Now we can get the requested table */
755
756    Status = OslMapTable (TableAddress, Signature, &MappedTable);
757    if (ACPI_FAILURE (Status))
758    {
759        return (Status);
760    }
761
762    /* Copy table to local buffer and return it */
763
764    LocalTable = calloc (1, MappedTable->Length);
765    if (!LocalTable)
766    {
767        AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
768        return (AE_NO_MEMORY);
769    }
770
771    memcpy (LocalTable, MappedTable, MappedTable->Length);
772    AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
773    *Table = LocalTable;
774    *Address = TableAddress;
775    return (AE_OK);
776}
777
778
779/******************************************************************************
780 *
781 * FUNCTION:    OslAddTablesToList
782 *
783 * PARAMETERS:  None
784 *
785 * RETURN:      Status; Table list is initialized if AE_OK.
786 *
787 * DESCRIPTION: Add ACPI tables to the table list.
788 *
789 *****************************************************************************/
790
791static ACPI_STATUS
792OslAddTablesToList(
793    void)
794{
795    ACPI_PHYSICAL_ADDRESS   TableAddress;
796    OSL_TABLE_INFO          *Info = NULL;
797    OSL_TABLE_INFO          *NewInfo;
798    ACPI_TABLE_HEADER       *Table;
799    UINT8                   Instance;
800    UINT8                   NumberOfTables;
801    int                     i;
802
803
804    /* Initialize the table list on first invocation */
805
806    if (Gbl_TableListInitialized)
807    {
808        return (AE_OK);
809    }
810
811    /* Add mandatory tables to global table list first */
812
813    for (i = 0; i < 4; i++)
814    {
815        NewInfo = calloc (1, sizeof (*NewInfo));
816        if (!NewInfo)
817        {
818            return (AE_NO_MEMORY);
819        }
820
821        switch (i) {
822        case 0:
823
824            Gbl_TableListHead = Info = NewInfo;
825            continue;
826
827        case 1:
828
829            ACPI_MOVE_NAME (NewInfo->Signature,
830                Gbl_Revision ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
831            break;
832
833        case 2:
834
835            ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_FACS);
836            break;
837
838        default:
839
840            ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_DSDT);
841
842        }
843
844        Info->Next = NewInfo;
845        Info = NewInfo;
846        Gbl_TableListHead->Instance++;
847    }
848
849    /* Add normal tables from RSDT/XSDT to global list */
850
851    if (Gbl_Revision)
852    {
853        NumberOfTables =
854            (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
855            / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
856    }
857    else
858    {
859        NumberOfTables =
860            (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
861            / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
862    }
863
864    for (i = 0; i < NumberOfTables; i++)
865    {
866        if (Gbl_Revision)
867        {
868            TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
869        }
870        else
871        {
872            TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
873        }
874
875        Table = AcpiOsMapMemory (TableAddress, sizeof (*Table));
876        if (!Table)
877        {
878            return (AE_BAD_ADDRESS);
879        }
880
881        Instance = 0;
882        NewInfo = Gbl_TableListHead;
883        while (NewInfo->Next != NULL)
884        {
885            NewInfo = NewInfo->Next;
886            if (ACPI_COMPARE_NAME (Table->Signature, NewInfo->Signature))
887            {
888                Instance++;
889            }
890        }
891
892        NewInfo = calloc (1, sizeof (*NewInfo));
893        if (!NewInfo)
894        {
895            AcpiOsUnmapMemory (Table, sizeof (*Table));
896            return (AE_NO_MEMORY);
897        }
898
899        ACPI_MOVE_NAME (NewInfo->Signature, Table->Signature);
900
901        AcpiOsUnmapMemory (Table, sizeof (*Table));
902
903        NewInfo->Instance = Instance;
904        NewInfo->Address = TableAddress;
905        Info->Next = NewInfo;
906        Info = NewInfo;
907        Gbl_TableListHead->Instance++;
908    }
909
910    Gbl_TableListInitialized = TRUE;
911    return (AE_OK);
912}
913
914
915/******************************************************************************
916 *
917 * FUNCTION:    OslMapTable
918 *
919 * PARAMETERS:  Address             - Address of the table in memory
920 *              Signature           - Optional ACPI Signature for desired table.
921 *                                    Null terminated 4-character string.
922 *              Table               - Where a pointer to the mapped table is
923 *                                    returned
924 *
925 * RETURN:      Status; Mapped table is returned if AE_OK.
926 *
927 * DESCRIPTION: Map entire ACPI table into caller's address space. Also
928 *              validates the table and checksum.
929 *
930 *****************************************************************************/
931
932static ACPI_STATUS
933OslMapTable (
934    ACPI_SIZE               Address,
935    char                    *Signature,
936    ACPI_TABLE_HEADER       **Table)
937{
938    ACPI_TABLE_HEADER       *MappedTable;
939    UINT32                  Length;
940
941
942    /* Map the header so we can get the table length */
943
944    MappedTable = AcpiOsMapMemory (Address, sizeof (*MappedTable));
945    if (!MappedTable)
946    {
947        return (AE_BAD_ADDRESS);
948    }
949
950    /* Check if table is valid */
951
952    if (!ApIsValidHeader (MappedTable))
953    {
954        AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
955        return (AE_BAD_HEADER);
956    }
957
958    /* If specified, signature must match */
959
960    if (Signature &&
961        !ACPI_COMPARE_NAME (Signature, MappedTable->Signature))
962    {
963        AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
964        return (AE_NOT_EXIST);
965    }
966
967    /* Map the entire table */
968
969    Length = MappedTable->Length;
970    AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
971
972    MappedTable = AcpiOsMapMemory (Address, Length);
973    if (!MappedTable)
974    {
975        return (AE_BAD_ADDRESS);
976    }
977
978    (void) ApIsValidChecksum (MappedTable);
979
980    *Table = MappedTable;
981
982    return (AE_OK);
983}
984