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 - 2023, 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
AcpiOsGetTableByAddress(ACPI_PHYSICAL_ADDRESS Address,ACPI_TABLE_HEADER ** Table)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
AcpiOsGetTableByName(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)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
AcpiOsGetTableByIndex(UINT32 Index,ACPI_TABLE_HEADER ** Table,UINT32 * Instance,ACPI_PHYSICAL_ADDRESS * Address)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
OslTableInitialize(void)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
OslGetTableViaRoot(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)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
OslAddTablesToList(void)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
OslMapTable(ACPI_SIZE Address,char * Signature,ACPI_TABLE_HEADER ** Table)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