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