Merge branch 'vendor/GREP'
[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 - 2015, 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__)
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__)
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     size_t                  Length = sizeof (Address);
390
391
392     /* Get main ACPI tables from memory on first invocation of this function */
393
394     if (Gbl_MainTableObtained)
395     {
396         return (AE_OK);
397     }
398
399     /* Attempt to use kenv or sysctl to find RSD PTR record. */
400
401     if (Gbl_RsdpBase)
402     {
403         Address = Gbl_RsdpBase;
404     }
405 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
406     else if (kenv (KENV_GET, SYSTEM_KENV, Buffer, sizeof (Buffer)) > 0)
407     {
408         Address = strtoul (Buffer, NULL, 0);
409     }
410 #endif
411     if (!Address)
412     {
413         if (sysctlbyname (SYSTEM_SYSCTL, &Address, &Length, NULL, 0) != 0)
414         {
415             Address = 0;
416         }
417     }
418     if (Address)
419     {
420         RsdpBase = Address;
421         RsdpSize = sizeof (Gbl_Rsdp);
422     }
423     else
424     {
425         RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
426         RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
427     }
428
429     /* Get RSDP from memory */
430
431     RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
432     if (!RsdpAddress)
433     {
434         return (AE_BAD_ADDRESS);
435     }
436
437     /* Search low memory for the RSDP */
438
439     TableAddress = AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize);
440     if (!TableAddress)
441     {
442         AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
443         return (AE_ERROR);
444     }
445
446     memcpy (&Gbl_Rsdp, TableAddress, sizeof (Gbl_Rsdp));
447     AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
448
449     /* Get XSDT from memory */
450
451     if (Gbl_Rsdp.Revision)
452     {
453         Status = OslMapTable (Gbl_Rsdp.XsdtPhysicalAddress,
454             ACPI_SIG_XSDT, &MappedTable);
455         if (ACPI_FAILURE (Status))
456         {
457             return (Status);
458         }
459
460         Gbl_Revision = 2;
461         Gbl_Xsdt = calloc (1, MappedTable->Length);
462         if (!Gbl_Xsdt)
463         {
464             fprintf (stderr,
465                 "XSDT: Could not allocate buffer for table of length %X\n",
466                 MappedTable->Length);
467             AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
468             return (AE_NO_MEMORY);
469         }
470
471         memcpy (Gbl_Xsdt, MappedTable, MappedTable->Length);
472         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
473     }
474
475     /* Get RSDT from memory */
476
477     if (Gbl_Rsdp.RsdtPhysicalAddress)
478     {
479         Status = OslMapTable (Gbl_Rsdp.RsdtPhysicalAddress,
480             ACPI_SIG_RSDT, &MappedTable);
481         if (ACPI_FAILURE (Status))
482         {
483             return (Status);
484         }
485
486         Gbl_Rsdt = calloc (1, MappedTable->Length);
487         if (!Gbl_Rsdt)
488         {
489             fprintf (stderr,
490                 "RSDT: Could not allocate buffer for table of length %X\n",
491                 MappedTable->Length);
492             AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
493             return (AE_NO_MEMORY);
494         }
495
496         memcpy (Gbl_Rsdt, MappedTable, MappedTable->Length);
497         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
498     }
499
500     /* Get FADT from memory */
501
502     if (Gbl_Revision)
503     {
504         Gbl_FadtAddress = Gbl_Xsdt->TableOffsetEntry[0];
505     }
506     else
507     {
508         Gbl_FadtAddress = Gbl_Rsdt->TableOffsetEntry[0];
509     }
510
511     if (!Gbl_FadtAddress)
512     {
513         fprintf(stderr, "FADT: Table could not be found\n");
514         return (AE_ERROR);
515     }
516
517     Status = OslMapTable (Gbl_FadtAddress, ACPI_SIG_FADT, &MappedTable);
518     if (ACPI_FAILURE (Status))
519     {
520         return (Status);
521     }
522
523     Gbl_Fadt = calloc (1, MappedTable->Length);
524     if (!Gbl_Fadt)
525     {
526         fprintf (stderr,
527             "FADT: Could not allocate buffer for table of length %X\n",
528             MappedTable->Length);
529         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
530         return (AE_NO_MEMORY);
531     }
532
533     memcpy (Gbl_Fadt, MappedTable, MappedTable->Length);
534     AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
535     Gbl_MainTableObtained = TRUE;
536     return (AE_OK);
537 }
538
539
540 /******************************************************************************
541  *
542  * FUNCTION:    OslGetTableViaRoot
543  *
544  * PARAMETERS:  Signature       - ACPI Signature for common table. Must be
545  *                                a null terminated 4-character string.
546  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
547  *                                Must be 0 for other tables.
548  *              Table           - Where a pointer to the table is returned
549  *              Address         - Where the table physical address is returned
550  *
551  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
552  *              AE_LIMIT: Instance is beyond valid limit
553  *              AE_NOT_FOUND: A table with the signature was not found
554  *
555  * DESCRIPTION: Get an ACPI table via the root table (RSDT/XSDT)
556  *
557  * NOTE:        Assumes the input signature is uppercase.
558  *
559  *****************************************************************************/
560
561 static ACPI_STATUS
562 OslGetTableViaRoot (
563     char                    *Signature,
564     UINT32                  Instance,
565     ACPI_TABLE_HEADER       **Table,
566     ACPI_PHYSICAL_ADDRESS   *Address)
567 {
568     ACPI_TABLE_HEADER       *LocalTable = NULL;
569     ACPI_TABLE_HEADER       *MappedTable = NULL;
570     UINT8                   NumberOfTables;
571     UINT32                  CurrentInstance = 0;
572     ACPI_PHYSICAL_ADDRESS   TableAddress = 0;
573     ACPI_STATUS             Status;
574     UINT32                  i;
575
576
577     /* DSDT and FACS address must be extracted from the FADT */
578
579     if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) ||
580         ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
581     {
582         /*
583          * Get the appropriate address, either 32-bit or 64-bit. Be very
584          * careful about the FADT length and validate table addresses.
585          * Note: The 64-bit addresses have priority.
586          */
587         if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT))
588         {
589             if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
590                 Gbl_Fadt->XDsdt)
591             {
592                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
593             }
594             else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
595                 Gbl_Fadt->Dsdt)
596             {
597                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
598             }
599         }
600         else /* FACS */
601         {
602             if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
603                 Gbl_Fadt->XFacs)
604             {
605                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
606             }
607             else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
608                 Gbl_Fadt->Facs)
609             {
610                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
611             }
612         }
613     }
614     else /* Case for a normal ACPI table */
615     {
616         if (Gbl_Revision)
617         {
618             NumberOfTables =
619                 (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
620                 / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
621         }
622         else /* Use RSDT if XSDT is not available */
623         {
624             NumberOfTables =
625                 (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
626                 / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
627         }
628
629         /* Search RSDT/XSDT for the requested table */
630
631         for (i = 0; i < NumberOfTables; i++)
632         {
633             if (Gbl_Revision)
634             {
635                 TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
636             }
637             else
638             {
639                 TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
640             }
641
642             MappedTable = AcpiOsMapMemory (TableAddress, sizeof (*MappedTable));
643             if (!MappedTable)
644             {
645                 return (AE_BAD_ADDRESS);
646             }
647
648             /* Does this table match the requested signature? */
649
650             if (ACPI_COMPARE_NAME (MappedTable->Signature, Signature))
651             {
652
653                 /* Match table instance (for SSDT/UEFI tables) */
654
655                 if (CurrentInstance == Instance)
656                 {
657                     AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
658                     break;
659                 }
660
661                 CurrentInstance++;
662             }
663
664             AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
665             TableAddress = 0;
666         }
667     }
668
669     if (!TableAddress)
670     {
671         if (CurrentInstance)
672         {
673             return (AE_LIMIT);
674         }
675         return (AE_NOT_FOUND);
676     }
677
678     /* Now we can get the requested table */
679
680     Status = OslMapTable (TableAddress, Signature, &MappedTable);
681     if (ACPI_FAILURE (Status))
682     {
683         return (Status);
684     }
685
686     /* Copy table to local buffer and return it */
687
688     LocalTable = calloc (1, MappedTable->Length);
689     if (!LocalTable)
690     {
691         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
692         return (AE_NO_MEMORY);
693     }
694
695     memcpy (LocalTable, MappedTable, MappedTable->Length);
696     AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
697     *Table = LocalTable;
698     *Address = TableAddress;
699     return (AE_OK);
700 }
701
702
703 /******************************************************************************
704  *
705  * FUNCTION:    OslAddTablesToList
706  *
707  * PARAMETERS:  None
708  *
709  * RETURN:      Status; Table list is initialized if AE_OK.
710  *
711  * DESCRIPTION: Add ACPI tables to the table list.
712  *
713  *****************************************************************************/
714
715 static ACPI_STATUS
716 OslAddTablesToList(
717     void)
718 {
719     ACPI_PHYSICAL_ADDRESS   TableAddress;
720     OSL_TABLE_INFO          *Info = NULL;
721     OSL_TABLE_INFO          *NewInfo;
722     ACPI_TABLE_HEADER       *Table;
723     UINT8                   Instance;
724     UINT8                   NumberOfTables;
725     int                     i;
726
727
728     /* Initialize the table list on first invocation */
729
730     if (Gbl_TableListInitialized)
731     {
732         return (AE_OK);
733     }
734
735     /* Add mandatory tables to global table list first */
736
737     for (i = 0; i < 4; i++)
738     {
739         NewInfo = calloc (1, sizeof (*NewInfo));
740         if (!NewInfo)
741         {
742             return (AE_NO_MEMORY);
743         }
744
745         switch (i) {
746         case 0:
747
748             Gbl_TableListHead = Info = NewInfo;
749             continue;
750
751         case 1:
752
753             ACPI_MOVE_NAME (NewInfo->Signature,
754                 Gbl_Revision ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
755             break;
756
757         case 2:
758
759             ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_FACS);
760             break;
761
762         default:
763
764             ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_DSDT);
765
766         }
767
768         Info->Next = NewInfo;
769         Info = NewInfo;
770         Gbl_TableListHead->Instance++;
771     }
772
773     /* Add normal tables from RSDT/XSDT to global list */
774
775     if (Gbl_Revision)
776     {
777         NumberOfTables =
778             (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
779             / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
780     }
781     else
782     {
783         NumberOfTables =
784             (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
785             / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
786     }
787
788     for (i = 0; i < NumberOfTables; i++)
789     {
790         if (Gbl_Revision)
791         {
792             TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
793         }
794         else
795         {
796             TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
797         }
798
799         Table = AcpiOsMapMemory (TableAddress, sizeof (*Table));
800         if (!Table)
801         {
802             return (AE_BAD_ADDRESS);
803         }
804
805         Instance = 0;
806         NewInfo = Gbl_TableListHead;
807         while (NewInfo->Next != NULL)
808         {
809             NewInfo = NewInfo->Next;
810             if (ACPI_COMPARE_NAME (Table->Signature, NewInfo->Signature))
811             {
812                 Instance++;
813             }
814         }
815
816         NewInfo = calloc (1, sizeof (*NewInfo));
817         if (!NewInfo)
818         {
819             AcpiOsUnmapMemory (Table, sizeof (*Table));
820             return (AE_NO_MEMORY);
821         }
822
823         ACPI_MOVE_NAME (NewInfo->Signature, Table->Signature);
824
825         AcpiOsUnmapMemory (Table, sizeof (*Table));
826
827         NewInfo->Instance = Instance;
828         NewInfo->Address = TableAddress;
829         Info->Next = NewInfo;
830         Info = NewInfo;
831         Gbl_TableListHead->Instance++;
832     }
833
834     Gbl_TableListInitialized = TRUE;
835     return (AE_OK);
836 }
837
838
839 /******************************************************************************
840  *
841  * FUNCTION:    OslMapTable
842  *
843  * PARAMETERS:  Address             - Address of the table in memory
844  *              Signature           - Optional ACPI Signature for desired table.
845  *                                    Null terminated 4-character string.
846  *              Table               - Where a pointer to the mapped table is
847  *                                    returned
848  *
849  * RETURN:      Status; Mapped table is returned if AE_OK.
850  *
851  * DESCRIPTION: Map entire ACPI table into caller's address space. Also
852  *              validates the table and checksum.
853  *
854  *****************************************************************************/
855
856 static ACPI_STATUS
857 OslMapTable (
858     ACPI_SIZE               Address,
859     char                    *Signature,
860     ACPI_TABLE_HEADER       **Table)
861 {
862     ACPI_TABLE_HEADER       *MappedTable;
863     UINT32                  Length;
864
865
866     /* Map the header so we can get the table length */
867
868     MappedTable = AcpiOsMapMemory (Address, sizeof (*MappedTable));
869     if (!MappedTable)
870     {
871         return (AE_BAD_ADDRESS);
872     }
873
874     /* Check if table is valid */
875
876     if (!ApIsValidHeader (MappedTable))
877     {
878         AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
879         return (AE_BAD_HEADER);
880     }
881
882     /* If specified, signature must match */
883
884     if (Signature &&
885         !ACPI_COMPARE_NAME (Signature, MappedTable->Signature))
886     {
887         AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
888         return (AE_NOT_EXIST);
889     }
890
891     /* Map the entire table */
892
893     Length = MappedTable->Length;
894     AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
895
896     MappedTable = AcpiOsMapMemory (Address, Length);
897     if (!MappedTable)
898     {
899         return (AE_BAD_ADDRESS);
900     }
901
902     (void) ApIsValidChecksum (MappedTable);
903
904     *Table = MappedTable;
905
906     return (AE_OK);
907 }