Merge branch 'vendor/GCC50'
[dragonfly.git] / sys / contrib / dev / acpica / source / os_specific / service_layers / osefitbl.c
1 /******************************************************************************
2  *
3  * Module Name: osefitbl - EFI 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
47 #define _COMPONENT          ACPI_OS_SERVICES
48         ACPI_MODULE_NAME    ("osefitbl")
49
50
51 #ifndef PATH_MAX
52 #define PATH_MAX 256
53 #endif
54
55
56 /* List of information about obtained ACPI tables */
57
58 typedef struct osl_table_info
59 {
60     struct osl_table_info   *Next;
61     UINT32                  Instance;
62     char                    Signature[ACPI_NAME_SIZE];
63
64 } OSL_TABLE_INFO;
65
66 /* Local prototypes */
67
68 static ACPI_STATUS
69 OslTableInitialize (
70     void);
71
72 static ACPI_STATUS
73 OslAddTableToList (
74     char                    *Signature,
75     UINT32                  Instance);
76
77 static ACPI_STATUS
78 OslMapTable (
79     ACPI_SIZE               Address,
80     char                    *Signature,
81     ACPI_TABLE_HEADER       **Table);
82
83 static void
84 OslUnmapTable (
85     ACPI_TABLE_HEADER       *Table);
86
87 static ACPI_STATUS
88 OslLoadRsdp (
89     void);
90
91 static ACPI_STATUS
92 OslListTables (
93     void);
94
95 static ACPI_STATUS
96 OslGetTable (
97     char                    *Signature,
98     UINT32                  Instance,
99     ACPI_TABLE_HEADER       **Table,
100     ACPI_PHYSICAL_ADDRESS   *Address);
101
102
103 /* File locations */
104
105 #define EFI_SYSTAB          "/sys/firmware/efi/systab"
106
107 /* Initialization flags */
108
109 UINT8                   Gbl_TableListInitialized = FALSE;
110
111 /* Local copies of main ACPI tables */
112
113 ACPI_TABLE_RSDP         Gbl_Rsdp;
114 ACPI_TABLE_FADT         *Gbl_Fadt = NULL;
115 ACPI_TABLE_RSDT         *Gbl_Rsdt = NULL;
116 ACPI_TABLE_XSDT         *Gbl_Xsdt = NULL;
117
118 /* Table addresses */
119
120 ACPI_PHYSICAL_ADDRESS   Gbl_FadtAddress = 0;
121 ACPI_PHYSICAL_ADDRESS   Gbl_RsdpAddress = 0;
122
123 /* Revision of RSD PTR */
124
125 UINT8                   Gbl_Revision = 0;
126
127 OSL_TABLE_INFO          *Gbl_TableListHead = NULL;
128 UINT32                  Gbl_TableCount = 0;
129
130
131 /******************************************************************************
132  *
133  * FUNCTION:    AcpiOsGetTableByAddress
134  *
135  * PARAMETERS:  Address         - Physical address of the ACPI table
136  *              Table           - Where a pointer to the table is returned
137  *
138  * RETURN:      Status; Table buffer is returned if AE_OK.
139  *              AE_NOT_FOUND: A valid table was not found at the address
140  *
141  * DESCRIPTION: Get an ACPI table via a physical memory address.
142  *
143  *****************************************************************************/
144
145 ACPI_STATUS
146 AcpiOsGetTableByAddress (
147     ACPI_PHYSICAL_ADDRESS   Address,
148     ACPI_TABLE_HEADER       **Table)
149 {
150     UINT32                  TableLength;
151     ACPI_TABLE_HEADER       *MappedTable;
152     ACPI_TABLE_HEADER       *LocalTable = NULL;
153     ACPI_STATUS             Status = AE_OK;
154
155
156     /* Get main ACPI tables from memory on first invocation of this function */
157
158     Status = OslTableInitialize ();
159     if (ACPI_FAILURE (Status))
160     {
161         return (Status);
162     }
163
164     /* Map the table and validate it */
165
166     Status = OslMapTable (Address, NULL, &MappedTable);
167     if (ACPI_FAILURE (Status))
168     {
169         return (Status);
170     }
171
172     /* Copy table to local buffer and return it */
173
174     TableLength = ApGetTableLength (MappedTable);
175     if (TableLength == 0)
176     {
177         Status = AE_BAD_HEADER;
178         goto Exit;
179     }
180
181     LocalTable = ACPI_ALLOCATE_ZEROED (TableLength);
182     if (!LocalTable)
183     {
184         Status = AE_NO_MEMORY;
185         goto Exit;
186     }
187
188     ACPI_MEMCPY (LocalTable, MappedTable, TableLength);
189
190 Exit:
191     OslUnmapTable (MappedTable);
192     *Table = LocalTable;
193     return (Status);
194 }
195
196
197 /******************************************************************************
198  *
199  * FUNCTION:    AcpiOsGetTableByName
200  *
201  * PARAMETERS:  Signature       - ACPI Signature for desired table. Must be
202  *                                a null terminated 4-character string.
203  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
204  *                                Must be 0 for other tables.
205  *              Table           - Where a pointer to the table is returned
206  *              Address         - Where the table physical address is returned
207  *
208  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
209  *              AE_LIMIT: Instance is beyond valid limit
210  *              AE_NOT_FOUND: A table with the signature was not found
211  *
212  * NOTE:        Assumes the input signature is uppercase.
213  *
214  *****************************************************************************/
215
216 ACPI_STATUS
217 AcpiOsGetTableByName (
218     char                    *Signature,
219     UINT32                  Instance,
220     ACPI_TABLE_HEADER       **Table,
221     ACPI_PHYSICAL_ADDRESS   *Address)
222 {
223     ACPI_STATUS             Status;
224
225
226     /* Get main ACPI tables from memory on first invocation of this function */
227
228     Status = OslTableInitialize ();
229     if (ACPI_FAILURE (Status))
230     {
231         return (Status);
232     }
233
234     /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
235
236     if (!Gbl_DumpCustomizedTables)
237     {
238         /* Attempt to get the table from the memory */
239
240         Status = OslGetTable (Signature, Instance, Table, Address);
241     }
242     else
243     {
244         /* Attempt to get the table from the static directory */
245
246         Status = AE_SUPPORT;
247     }
248
249     return (Status);
250 }
251
252
253 /******************************************************************************
254  *
255  * FUNCTION:    OslAddTableToList
256  *
257  * PARAMETERS:  Signature       - Table signature
258  *              Instance        - Table instance
259  *
260  * RETURN:      Status; Successfully added if AE_OK.
261  *              AE_NO_MEMORY: Memory allocation error
262  *
263  * DESCRIPTION: Insert a table structure into OSL table list.
264  *
265  *****************************************************************************/
266
267 static ACPI_STATUS
268 OslAddTableToList (
269     char                    *Signature,
270     UINT32                  Instance)
271 {
272     OSL_TABLE_INFO          *NewInfo;
273     OSL_TABLE_INFO          *Next;
274     UINT32                  NextInstance = 0;
275     BOOLEAN                 Found = FALSE;
276
277
278     NewInfo = ACPI_ALLOCATE_ZEROED (sizeof (OSL_TABLE_INFO));
279     if (!NewInfo)
280     {
281         return (AE_NO_MEMORY);
282     }
283
284     ACPI_MOVE_NAME (NewInfo->Signature, Signature);
285
286     if (!Gbl_TableListHead)
287     {
288         Gbl_TableListHead = NewInfo;
289     }
290     else
291     {
292         Next = Gbl_TableListHead;
293         while (1)
294         {
295             if (ACPI_COMPARE_NAME (Next->Signature, Signature))
296             {
297                 if (Next->Instance == Instance)
298                 {
299                     Found = TRUE;
300                 }
301                 if (Next->Instance >= NextInstance)
302                 {
303                     NextInstance = Next->Instance + 1;
304                 }
305             }
306
307             if (!Next->Next)
308             {
309                 break;
310             }
311             Next = Next->Next;
312         }
313         Next->Next = NewInfo;
314     }
315
316     if (Found)
317     {
318         if (Instance)
319         {
320             AcpiLogError (
321                 "%4.4s: Warning unmatched table instance %d, expected %d\n",
322                 Signature, Instance, NextInstance);
323         }
324         Instance = NextInstance;
325     }
326
327     NewInfo->Instance = Instance;
328     Gbl_TableCount++;
329
330     return (AE_OK);
331 }
332
333
334 /******************************************************************************
335  *
336  * FUNCTION:    AcpiOsGetTableByIndex
337  *
338  * PARAMETERS:  Index           - Which table to get
339  *              Table           - Where a pointer to the table is returned
340  *              Instance        - Where a pointer to the table instance no. is
341  *                                returned
342  *              Address         - Where the table physical address is returned
343  *
344  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
345  *              AE_LIMIT: Index is beyond valid limit
346  *
347  * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
348  *              AE_LIMIT when an invalid index is reached. Index is not
349  *              necessarily an index into the RSDT/XSDT.
350  *
351  *****************************************************************************/
352
353 ACPI_STATUS
354 AcpiOsGetTableByIndex (
355     UINT32                  Index,
356     ACPI_TABLE_HEADER       **Table,
357     UINT32                  *Instance,
358     ACPI_PHYSICAL_ADDRESS   *Address)
359 {
360     OSL_TABLE_INFO          *Info;
361     ACPI_STATUS             Status;
362     UINT32                  i;
363
364
365     /* Get main ACPI tables from memory on first invocation of this function */
366
367     Status = OslTableInitialize ();
368     if (ACPI_FAILURE (Status))
369     {
370         return (Status);
371     }
372
373     /* Validate Index */
374
375     if (Index >= Gbl_TableCount)
376     {
377         return (AE_LIMIT);
378     }
379
380     /* Point to the table list entry specified by the Index argument */
381
382     Info = Gbl_TableListHead;
383     for (i = 0; i < Index; i++)
384     {
385         Info = Info->Next;
386     }
387
388     /* Now we can just get the table via the signature */
389
390     Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
391         Table, Address);
392
393     if (ACPI_SUCCESS (Status))
394     {
395         *Instance = Info->Instance;
396     }
397     return (Status);
398 }
399
400
401 /******************************************************************************
402  *
403  * FUNCTION:    OslLoadRsdp
404  *
405  * PARAMETERS:  None
406  *
407  * RETURN:      Status
408  *
409  * DESCRIPTION: Scan and load RSDP.
410  *
411  *****************************************************************************/
412
413 static ACPI_STATUS
414 OslLoadRsdp (
415     void)
416 {
417     ACPI_TABLE_HEADER       *MappedTable;
418     UINT8                   *RsdpAddress;
419     ACPI_PHYSICAL_ADDRESS   RsdpBase;
420     ACPI_SIZE               RsdpSize;
421
422
423     /* Get RSDP from memory */
424
425     RsdpSize = sizeof (ACPI_TABLE_RSDP);
426     if (Gbl_RsdpBase)
427     {
428         RsdpBase = Gbl_RsdpBase;
429     }
430     else
431     {
432         RsdpBase = AcpiOsGetRootPointer ();
433     }
434
435     if (!RsdpBase)
436     {
437         RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
438         RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
439     }
440
441     RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
442     if (!RsdpAddress)
443     {
444         return (AE_BAD_ADDRESS);
445     }
446
447     /* Search low memory for the RSDP */
448
449     MappedTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER,
450         AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize));
451     if (!MappedTable)
452     {
453         AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
454         return (AE_NOT_FOUND);
455     }
456
457     Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8 (MappedTable) - RsdpAddress);
458
459     ACPI_MEMCPY (&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP));
460     AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
461
462     return (AE_OK);
463 }
464
465
466 /******************************************************************************
467  *
468  * FUNCTION:    OslCanUseXsdt
469  *
470  * PARAMETERS:  None
471  *
472  * RETURN:      TRUE if XSDT is allowed to be used.
473  *
474  * DESCRIPTION: This function collects logic that can be used to determine if
475  *              XSDT should be used instead of RSDT.
476  *
477  *****************************************************************************/
478
479 static BOOLEAN
480 OslCanUseXsdt (
481     void)
482 {
483     if (Gbl_Revision && !AcpiGbl_DoNotUseXsdt)
484     {
485         return (TRUE);
486     }
487     else
488     {
489         return (FALSE);
490     }
491 }
492
493
494 /******************************************************************************
495  *
496  * FUNCTION:    OslTableInitialize
497  *
498  * PARAMETERS:  None
499  *
500  * RETURN:      Status
501  *
502  * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
503  *              local variables. Main ACPI tables include RSDT, FADT, RSDT,
504  *              and/or XSDT.
505  *
506  *****************************************************************************/
507
508 static ACPI_STATUS
509 OslTableInitialize (
510     void)
511 {
512     ACPI_STATUS             Status;
513     ACPI_PHYSICAL_ADDRESS   Address;
514
515
516     if (Gbl_TableListInitialized)
517     {
518         return (AE_OK);
519     }
520
521     /* Get RSDP from memory */
522
523     Status = OslLoadRsdp ();
524     if (ACPI_FAILURE (Status))
525     {
526         return (Status);
527     }
528
529     /* Get XSDT from memory */
530
531     if (Gbl_Rsdp.Revision && !Gbl_DoNotDumpXsdt)
532     {
533         if (Gbl_Xsdt)
534         {
535             ACPI_FREE (Gbl_Xsdt);
536             Gbl_Xsdt = NULL;
537         }
538
539         Gbl_Revision = 2;
540         Status = OslGetTable (ACPI_SIG_XSDT, 0,
541             ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address);
542         if (ACPI_FAILURE (Status))
543         {
544             return (Status);
545         }
546     }
547
548     /* Get RSDT from memory */
549
550     if (Gbl_Rsdp.RsdtPhysicalAddress)
551     {
552         if (Gbl_Rsdt)
553         {
554             ACPI_FREE (Gbl_Rsdt);
555             Gbl_Rsdt = NULL;
556         }
557
558         Status = OslGetTable (ACPI_SIG_RSDT, 0,
559             ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address);
560         if (ACPI_FAILURE (Status))
561         {
562             return (Status);
563         }
564     }
565
566     /* Get FADT from memory */
567
568     if (Gbl_Fadt)
569     {
570         ACPI_FREE (Gbl_Fadt);
571         Gbl_Fadt = NULL;
572     }
573
574     Status = OslGetTable (ACPI_SIG_FADT, 0,
575         ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress);
576     if (ACPI_FAILURE (Status))
577     {
578         return (Status);
579     }
580
581     if (!Gbl_DumpCustomizedTables)
582     {
583         /* Add mandatory tables to global table list first */
584
585         Status = OslAddTableToList (ACPI_RSDP_NAME, 0);
586         if (ACPI_FAILURE (Status))
587         {
588             return (Status);
589         }
590
591         Status = OslAddTableToList (ACPI_SIG_RSDT, 0);
592         if (ACPI_FAILURE (Status))
593         {
594             return (Status);
595         }
596
597         if (Gbl_Revision == 2)
598         {
599             Status = OslAddTableToList (ACPI_SIG_XSDT, 0);
600             if (ACPI_FAILURE (Status))
601             {
602                 return (Status);
603             }
604         }
605
606         Status = OslAddTableToList (ACPI_SIG_DSDT, 0);
607         if (ACPI_FAILURE (Status))
608         {
609             return (Status);
610         }
611
612         Status = OslAddTableToList (ACPI_SIG_FACS, 0);
613         if (ACPI_FAILURE (Status))
614         {
615             return (Status);
616         }
617
618         /* Add all tables found in the memory */
619
620         Status = OslListTables ();
621         if (ACPI_FAILURE (Status))
622         {
623             return (Status);
624         }
625     }
626     else
627     {
628         /* Add all tables found in the static directory */
629
630         Status = AE_SUPPORT;
631     }
632
633     Gbl_TableListInitialized = TRUE;
634     return (AE_OK);
635 }
636
637
638 /******************************************************************************
639  *
640  * FUNCTION:    OslListTables
641  *
642  * PARAMETERS:  None
643  *
644  * RETURN:      Status; Table list is initialized if AE_OK.
645  *
646  * DESCRIPTION: Add ACPI tables to the table list from memory.
647  *
648  *****************************************************************************/
649
650 static ACPI_STATUS
651 OslListTables (
652     void)
653 {
654     ACPI_TABLE_HEADER       *MappedTable = NULL;
655     UINT8                   *TableData;
656     UINT8                   NumberOfTables;
657     UINT8                   ItemSize;
658     ACPI_PHYSICAL_ADDRESS   TableAddress = 0;
659     ACPI_STATUS             Status = AE_OK;
660     UINT32                  i;
661
662
663     if (OslCanUseXsdt ())
664     {
665         ItemSize = sizeof (UINT64);
666         TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
667         NumberOfTables =
668             (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
669             / ItemSize);
670     }
671     else /* Use RSDT if XSDT is not available */
672     {
673         ItemSize = sizeof (UINT32);
674         TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
675         NumberOfTables =
676             (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
677             / ItemSize);
678     }
679
680     /* Search RSDT/XSDT for the requested table */
681
682     for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
683     {
684         if (OslCanUseXsdt ())
685         {
686             TableAddress =
687                 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
688         }
689         else
690         {
691             TableAddress =
692                 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
693         }
694
695         /* Skip NULL entries in RSDT/XSDT */
696
697         if (!TableAddress)
698         {
699             continue;
700         }
701
702         Status = OslMapTable (TableAddress, NULL, &MappedTable);
703         if (ACPI_FAILURE (Status))
704         {
705             return (Status);
706         }
707
708         OslAddTableToList (MappedTable->Signature, 0);
709         OslUnmapTable (MappedTable);
710     }
711
712     return (AE_OK);
713 }
714
715
716 /******************************************************************************
717  *
718  * FUNCTION:    OslGetTable
719  *
720  * PARAMETERS:  Signature       - ACPI Signature for common table. Must be
721  *                                a null terminated 4-character string.
722  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
723  *                                Must be 0 for other tables.
724  *              Table           - Where a pointer to the table is returned
725  *              Address         - Where the table physical address is returned
726  *
727  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
728  *              AE_LIMIT: Instance is beyond valid limit
729  *              AE_NOT_FOUND: A table with the signature was not found
730  *
731  * DESCRIPTION: Get a BIOS provided ACPI table
732  *
733  * NOTE:        Assumes the input signature is uppercase.
734  *
735  *****************************************************************************/
736
737 static ACPI_STATUS
738 OslGetTable (
739     char                    *Signature,
740     UINT32                  Instance,
741     ACPI_TABLE_HEADER       **Table,
742     ACPI_PHYSICAL_ADDRESS   *Address)
743 {
744     ACPI_TABLE_HEADER       *LocalTable = NULL;
745     ACPI_TABLE_HEADER       *MappedTable = NULL;
746     UINT8                   *TableData;
747     UINT8                   NumberOfTables;
748     UINT8                   ItemSize;
749     UINT32                  CurrentInstance = 0;
750     ACPI_PHYSICAL_ADDRESS   TableAddress = 0;
751     UINT32                  TableLength = 0;
752     ACPI_STATUS             Status = AE_OK;
753     UINT32                  i;
754
755
756     /* Handle special tables whose addresses are not in RSDT/XSDT */
757
758     if (ACPI_COMPARE_NAME (Signature, ACPI_RSDP_NAME) ||
759         ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT) ||
760         ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT) ||
761         ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) ||
762         ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
763     {
764         /*
765          * Get the appropriate address, either 32-bit or 64-bit. Be very
766          * careful about the FADT length and validate table addresses.
767          * Note: The 64-bit addresses have priority.
768          */
769         if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT))
770         {
771             if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
772                 Gbl_Fadt->XDsdt)
773             {
774                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
775             }
776             else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
777                 Gbl_Fadt->Dsdt)
778             {
779                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
780             }
781         }
782         else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
783         {
784             if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
785                 Gbl_Fadt->XFacs)
786             {
787                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
788             }
789             else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
790                 Gbl_Fadt->Facs)
791             {
792                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
793             }
794         }
795         else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT))
796         {
797             if (!Gbl_Revision)
798             {
799                 return (AE_BAD_SIGNATURE);
800             }
801             TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress;
802         }
803         else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT))
804         {
805             TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress;
806         }
807         else
808         {
809             TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
810             Signature = ACPI_SIG_RSDP;
811         }
812
813         /* Now we can get the requested special table */
814
815         Status = OslMapTable (TableAddress, Signature, &MappedTable);
816         if (ACPI_FAILURE (Status))
817         {
818             return (Status);
819         }
820
821         TableLength = ApGetTableLength (MappedTable);
822     }
823     else /* Case for a normal ACPI table */
824     {
825         if (OslCanUseXsdt ())
826         {
827             ItemSize = sizeof (UINT64);
828             TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
829             NumberOfTables =
830                 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
831                 / ItemSize);
832         }
833         else /* Use RSDT if XSDT is not available */
834         {
835             ItemSize = sizeof (UINT32);
836             TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
837             NumberOfTables =
838                 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
839                 / ItemSize);
840         }
841
842         /* Search RSDT/XSDT for the requested table */
843
844         for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
845         {
846             if (OslCanUseXsdt ())
847             {
848                 TableAddress =
849                     (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
850             }
851             else
852             {
853                 TableAddress =
854                     (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
855             }
856
857             /* Skip NULL entries in RSDT/XSDT */
858
859             if (!TableAddress)
860             {
861                 continue;
862             }
863
864             Status = OslMapTable (TableAddress, NULL, &MappedTable);
865             if (ACPI_FAILURE (Status))
866             {
867                 return (Status);
868             }
869             TableLength = MappedTable->Length;
870
871             /* Does this table match the requested signature? */
872
873             if (!ACPI_COMPARE_NAME (MappedTable->Signature, Signature))
874             {
875                 OslUnmapTable (MappedTable);
876                 MappedTable = NULL;
877                 continue;
878             }
879
880             /* Match table instance (for SSDT/UEFI tables) */
881
882             if (CurrentInstance != Instance)
883             {
884                 OslUnmapTable (MappedTable);
885                 MappedTable = NULL;
886                 CurrentInstance++;
887                 continue;
888             }
889
890             break;
891         }
892     }
893
894     if (!MappedTable)
895     {
896         return (AE_LIMIT);
897     }
898
899     if (TableLength == 0)
900     {
901         Status = AE_BAD_HEADER;
902         goto Exit;
903     }
904
905     /* Copy table to local buffer and return it */
906
907     LocalTable = ACPI_ALLOCATE_ZEROED (TableLength);
908     if (!LocalTable)
909     {
910         Status = AE_NO_MEMORY;
911         goto Exit;
912     }
913
914     ACPI_MEMCPY (LocalTable, MappedTable, TableLength);
915     *Address = TableAddress;
916     *Table = LocalTable;
917
918 Exit:
919     OslUnmapTable (MappedTable);
920     return (Status);
921 }
922
923
924 /******************************************************************************
925  *
926  * FUNCTION:    OslMapTable
927  *
928  * PARAMETERS:  Address             - Address of the table in memory
929  *              Signature           - Optional ACPI Signature for desired table.
930  *                                    Null terminated 4-character string.
931  *              Table               - Where a pointer to the mapped table is
932  *                                    returned
933  *
934  * RETURN:      Status; Mapped table is returned if AE_OK.
935  *              AE_NOT_FOUND: A valid table was not found at the address
936  *
937  * DESCRIPTION: Map entire ACPI table into caller's address space.
938  *
939  *****************************************************************************/
940
941 static ACPI_STATUS
942 OslMapTable (
943     ACPI_SIZE               Address,
944     char                    *Signature,
945     ACPI_TABLE_HEADER       **Table)
946 {
947     ACPI_TABLE_HEADER       *MappedTable;
948     UINT32                  Length;
949
950
951     if (!Address)
952     {
953         return (AE_BAD_ADDRESS);
954     }
955
956     /*
957      * Map the header so we can get the table length.
958      * Use sizeof (ACPI_TABLE_HEADER) as:
959      * 1. it is bigger than 24 to include RSDP->Length
960      * 2. it is smaller than sizeof (ACPI_TABLE_RSDP)
961      */
962     MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
963     if (!MappedTable)
964     {
965         AcpiLogError ("Could not map table header at 0x%8.8X%8.8X\n",
966             ACPI_FORMAT_UINT64 (Address));
967         return (AE_BAD_ADDRESS);
968     }
969
970     /* If specified, signature must match */
971
972     if (Signature)
973     {
974         if (ACPI_VALIDATE_RSDP_SIG (Signature))
975         {
976             if (!ACPI_VALIDATE_RSDP_SIG (MappedTable->Signature))
977             {
978                 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
979                 return (AE_BAD_SIGNATURE);
980             }
981         }
982         else if (!ACPI_COMPARE_NAME (Signature, MappedTable->Signature))
983         {
984             AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
985             return (AE_BAD_SIGNATURE);
986         }
987     }
988
989     /* Map the entire table */
990
991     Length = ApGetTableLength (MappedTable);
992     AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
993     if (Length == 0)
994     {
995         return (AE_BAD_HEADER);
996     }
997
998     MappedTable = AcpiOsMapMemory (Address, Length);
999     if (!MappedTable)
1000     {
1001         AcpiLogError ("Could not map table at 0x%8.8X%8.8X length %8.8X\n",
1002             ACPI_FORMAT_UINT64 (Address), Length);
1003         return (AE_INVALID_TABLE_LENGTH);
1004     }
1005
1006     (void) ApIsValidChecksum (MappedTable);
1007
1008     *Table = MappedTable;
1009     return (AE_OK);
1010 }
1011
1012
1013 /******************************************************************************
1014  *
1015  * FUNCTION:    OslUnmapTable
1016  *
1017  * PARAMETERS:  Table               - A pointer to the mapped table
1018  *
1019  * RETURN:      None
1020  *
1021  * DESCRIPTION: Unmap entire ACPI table.
1022  *
1023  *****************************************************************************/
1024
1025 static void
1026 OslUnmapTable (
1027     ACPI_TABLE_HEADER       *Table)
1028 {
1029     if (Table)
1030     {
1031         AcpiOsUnmapMemory (Table, ApGetTableLength (Table));
1032     }
1033 }