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