]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/dev/acpica/tables/tbutils.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / dev / acpica / tables / tbutils.c
1 /******************************************************************************
2  *
3  * Module Name: tbutils   - table utilities
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2011, 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 #define __TBUTILS_C__
45
46 #include <contrib/dev/acpica/include/acpi.h>
47 #include <contrib/dev/acpica/include/accommon.h>
48 #include <contrib/dev/acpica/include/actables.h>
49
50 #define _COMPONENT          ACPI_TABLES
51         ACPI_MODULE_NAME    ("tbutils")
52
53 /* Local prototypes */
54
55 static void
56 AcpiTbFixString (
57     char                    *String,
58     ACPI_SIZE               Length);
59
60 static void
61 AcpiTbCleanupTableHeader (
62     ACPI_TABLE_HEADER       *OutHeader,
63     ACPI_TABLE_HEADER       *Header);
64
65 static ACPI_PHYSICAL_ADDRESS
66 AcpiTbGetRootTableEntry (
67     UINT8                   *TableEntry,
68     UINT32                  TableEntrySize);
69
70
71 /*******************************************************************************
72  *
73  * FUNCTION:    AcpiTbInitializeFacs
74  *
75  * PARAMETERS:  None
76  *
77  * RETURN:      Status
78  *
79  * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global
80  *              for accessing the Global Lock and Firmware Waking Vector
81  *
82  ******************************************************************************/
83
84 ACPI_STATUS
85 AcpiTbInitializeFacs (
86     void)
87 {
88     ACPI_STATUS             Status;
89
90
91     Status = AcpiGetTableByIndex (ACPI_TABLE_INDEX_FACS,
92                 ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &AcpiGbl_FACS));
93     return (Status);
94 }
95
96
97 /*******************************************************************************
98  *
99  * FUNCTION:    AcpiTbTablesLoaded
100  *
101  * PARAMETERS:  None
102  *
103  * RETURN:      TRUE if required ACPI tables are loaded
104  *
105  * DESCRIPTION: Determine if the minimum required ACPI tables are present
106  *              (FADT, FACS, DSDT)
107  *
108  ******************************************************************************/
109
110 BOOLEAN
111 AcpiTbTablesLoaded (
112     void)
113 {
114
115     if (AcpiGbl_RootTableList.CurrentTableCount >= 3)
116     {
117         return (TRUE);
118     }
119
120     return (FALSE);
121 }
122
123
124 /*******************************************************************************
125  *
126  * FUNCTION:    AcpiTbFixString
127  *
128  * PARAMETERS:  String              - String to be repaired
129  *              Length              - Maximum length
130  *
131  * RETURN:      None
132  *
133  * DESCRIPTION: Replace every non-printable or non-ascii byte in the string
134  *              with a question mark '?'.
135  *
136  ******************************************************************************/
137
138 static void
139 AcpiTbFixString (
140     char                    *String,
141     ACPI_SIZE               Length)
142 {
143
144     while (Length && *String)
145     {
146         if (!ACPI_IS_PRINT (*String))
147         {
148             *String = '?';
149         }
150         String++;
151         Length--;
152     }
153 }
154
155
156 /*******************************************************************************
157  *
158  * FUNCTION:    AcpiTbCleanupTableHeader
159  *
160  * PARAMETERS:  OutHeader           - Where the cleaned header is returned
161  *              Header              - Input ACPI table header
162  *
163  * RETURN:      Returns the cleaned header in OutHeader
164  *
165  * DESCRIPTION: Copy the table header and ensure that all "string" fields in
166  *              the header consist of printable characters.
167  *
168  ******************************************************************************/
169
170 static void
171 AcpiTbCleanupTableHeader (
172     ACPI_TABLE_HEADER       *OutHeader,
173     ACPI_TABLE_HEADER       *Header)
174 {
175
176     ACPI_MEMCPY (OutHeader, Header, sizeof (ACPI_TABLE_HEADER));
177
178     AcpiTbFixString (OutHeader->Signature, ACPI_NAME_SIZE);
179     AcpiTbFixString (OutHeader->OemId, ACPI_OEM_ID_SIZE);
180     AcpiTbFixString (OutHeader->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
181     AcpiTbFixString (OutHeader->AslCompilerId, ACPI_NAME_SIZE);
182 }
183
184
185 /*******************************************************************************
186  *
187  * FUNCTION:    AcpiTbPrintTableHeader
188  *
189  * PARAMETERS:  Address             - Table physical address
190  *              Header              - Table header
191  *
192  * RETURN:      None
193  *
194  * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP.
195  *
196  ******************************************************************************/
197
198 void
199 AcpiTbPrintTableHeader (
200     ACPI_PHYSICAL_ADDRESS   Address,
201     ACPI_TABLE_HEADER       *Header)
202 {
203     ACPI_TABLE_HEADER       LocalHeader;
204
205
206     /*
207      * The reason that the Address is cast to a void pointer is so that we
208      * can use %p which will work properly on both 32-bit and 64-bit hosts.
209      */
210     if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_FACS))
211     {
212         /* FACS only has signature and length fields */
213
214         ACPI_INFO ((AE_INFO, "%4.4s %p %05X",
215             Header->Signature, ACPI_CAST_PTR (void, Address),
216             Header->Length));
217     }
218     else if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_RSDP))
219     {
220         /* RSDP has no common fields */
221
222         ACPI_MEMCPY (LocalHeader.OemId,
223             ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->OemId, ACPI_OEM_ID_SIZE);
224         AcpiTbFixString (LocalHeader.OemId, ACPI_OEM_ID_SIZE);
225
226         ACPI_INFO ((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)",
227             ACPI_CAST_PTR (void, Address),
228             (ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision > 0) ?
229                 ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Length : 20,
230             ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision,
231             LocalHeader.OemId));
232     }
233     else
234     {
235         /* Standard ACPI table with full common header */
236
237         AcpiTbCleanupTableHeader (&LocalHeader, Header);
238
239         ACPI_INFO ((AE_INFO,
240             "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)",
241             LocalHeader.Signature, ACPI_CAST_PTR (void, Address),
242             LocalHeader.Length, LocalHeader.Revision, LocalHeader.OemId,
243             LocalHeader.OemTableId, LocalHeader.OemRevision,
244             LocalHeader.AslCompilerId, LocalHeader.AslCompilerRevision));
245     }
246 }
247
248
249 /*******************************************************************************
250  *
251  * FUNCTION:    AcpiTbValidateChecksum
252  *
253  * PARAMETERS:  Table               - ACPI table to verify
254  *              Length              - Length of entire table
255  *
256  * RETURN:      Status
257  *
258  * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns
259  *              exception on bad checksum.
260  *
261  ******************************************************************************/
262
263 ACPI_STATUS
264 AcpiTbVerifyChecksum (
265     ACPI_TABLE_HEADER       *Table,
266     UINT32                  Length)
267 {
268     UINT8                   Checksum;
269
270
271     /* Compute the checksum on the table */
272
273     Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Length);
274
275     /* Checksum ok? (should be zero) */
276
277     if (Checksum)
278     {
279         ACPI_WARNING ((AE_INFO,
280             "Incorrect checksum in table [%4.4s] - 0x%2.2X, should be 0x%2.2X",
281             Table->Signature, Table->Checksum,
282             (UINT8) (Table->Checksum - Checksum)));
283
284 #if (ACPI_CHECKSUM_ABORT)
285         return (AE_BAD_CHECKSUM);
286 #endif
287     }
288
289     return (AE_OK);
290 }
291
292
293 /*******************************************************************************
294  *
295  * FUNCTION:    AcpiTbChecksum
296  *
297  * PARAMETERS:  Buffer          - Pointer to memory region to be checked
298  *              Length          - Length of this memory region
299  *
300  * RETURN:      Checksum (UINT8)
301  *
302  * DESCRIPTION: Calculates circular checksum of memory region.
303  *
304  ******************************************************************************/
305
306 UINT8
307 AcpiTbChecksum (
308     UINT8                   *Buffer,
309     UINT32                  Length)
310 {
311     UINT8                   Sum = 0;
312     UINT8                   *End = Buffer + Length;
313
314
315     while (Buffer < End)
316     {
317         Sum = (UINT8) (Sum + *(Buffer++));
318     }
319
320     return Sum;
321 }
322
323
324 /*******************************************************************************
325  *
326  * FUNCTION:    AcpiTbCheckDsdtHeader
327  *
328  * PARAMETERS:  None
329  *
330  * RETURN:      None
331  *
332  * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect
333  *              if the DSDT has been replaced from outside the OS and/or if
334  *              the DSDT header has been corrupted.
335  *
336  ******************************************************************************/
337
338 void
339 AcpiTbCheckDsdtHeader (
340     void)
341 {
342
343     /* Compare original length and checksum to current values */
344
345     if (AcpiGbl_OriginalDsdtHeader.Length != AcpiGbl_DSDT->Length ||
346         AcpiGbl_OriginalDsdtHeader.Checksum != AcpiGbl_DSDT->Checksum)
347     {
348         ACPI_ERROR ((AE_INFO,
349             "The DSDT has been corrupted or replaced - old, new headers below"));
350         AcpiTbPrintTableHeader (0, &AcpiGbl_OriginalDsdtHeader);
351         AcpiTbPrintTableHeader (0, AcpiGbl_DSDT);
352
353         /* Disable further error messages */
354
355         AcpiGbl_OriginalDsdtHeader.Length = AcpiGbl_DSDT->Length;
356         AcpiGbl_OriginalDsdtHeader.Checksum = AcpiGbl_DSDT->Checksum;
357     }
358 }
359
360
361 /*******************************************************************************
362  *
363  * FUNCTION:    AcpiTbCopyDsdt
364  *
365  * PARAMETERS:  TableDesc           - Installed table to copy
366  *
367  * RETURN:      None
368  *
369  * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory.
370  *              Some very bad BIOSs are known to either corrupt the DSDT or
371  *              install a new, bad DSDT. This copy works around the problem.
372  *
373  ******************************************************************************/
374
375 ACPI_TABLE_HEADER *
376 AcpiTbCopyDsdt (
377     UINT32                  TableIndex)
378 {
379     ACPI_TABLE_HEADER       *NewTable;
380     ACPI_TABLE_DESC         *TableDesc;
381
382
383     TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex];
384
385     NewTable = ACPI_ALLOCATE (TableDesc->Length);
386     if (!NewTable)
387     {
388         ACPI_ERROR ((AE_INFO, "Could not copy DSDT of length 0x%X",
389             TableDesc->Length));
390         return (NULL);
391     }
392
393     ACPI_MEMCPY (NewTable, TableDesc->Pointer, TableDesc->Length);
394     AcpiTbDeleteTable (TableDesc);
395     TableDesc->Pointer = NewTable;
396     TableDesc->Flags = ACPI_TABLE_ORIGIN_ALLOCATED;
397
398     ACPI_INFO ((AE_INFO,
399         "Forced DSDT copy: length 0x%05X copied locally, original unmapped",
400         NewTable->Length));
401
402     return (NewTable);
403 }
404
405
406 /*******************************************************************************
407  *
408  * FUNCTION:    AcpiTbInstallTable
409  *
410  * PARAMETERS:  Address                 - Physical address of DSDT or FACS
411  *              Signature               - Table signature, NULL if no need to
412  *                                        match
413  *              TableIndex              - Index into root table array
414  *
415  * RETURN:      None
416  *
417  * DESCRIPTION: Install an ACPI table into the global data structure. The
418  *              table override mechanism is implemented here to allow the host
419  *              OS to replace any table before it is installed in the root
420  *              table array.
421  *
422  ******************************************************************************/
423
424 void
425 AcpiTbInstallTable (
426     ACPI_PHYSICAL_ADDRESS   Address,
427     char                    *Signature,
428     UINT32                  TableIndex)
429 {
430     UINT8                   Flags;
431     ACPI_STATUS             Status;
432     ACPI_TABLE_HEADER       *TableToInstall;
433     ACPI_TABLE_HEADER       *MappedTable;
434     ACPI_TABLE_HEADER       *OverrideTable = NULL;
435
436
437     if (!Address)
438     {
439         ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]",
440             Signature));
441         return;
442     }
443
444     /* Map just the table header */
445
446     MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
447     if (!MappedTable)
448     {
449         return;
450     }
451
452     /* Skip SSDT when DSDT is overriden */
453
454     if (ACPI_COMPARE_NAME (MappedTable->Signature, ACPI_SIG_SSDT) &&
455        (AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Flags &
456             ACPI_TABLE_ORIGIN_OVERRIDE))
457     {
458         ACPI_INFO ((AE_INFO,
459             "%4.4s @ 0x%p Table override, replaced with:", ACPI_SIG_SSDT,
460             ACPI_CAST_PTR (void, Address)));
461         AcpiTbPrintTableHeader (
462             AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Address,
463             AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer);
464         goto UnmapAndExit;
465     }
466
467     /* If a particular signature is expected (DSDT/FACS), it must match */
468
469     if (Signature &&
470         !ACPI_COMPARE_NAME (MappedTable->Signature, Signature))
471     {
472         ACPI_ERROR ((AE_INFO,
473             "Invalid signature 0x%X for ACPI table, expected [%s]",
474             *ACPI_CAST_PTR (UINT32, MappedTable->Signature), Signature));
475         goto UnmapAndExit;
476     }
477
478     /*
479      * ACPI Table Override:
480      *
481      * Before we install the table, let the host OS override it with a new
482      * one if desired. Any table within the RSDT/XSDT can be replaced,
483      * including the DSDT which is pointed to by the FADT.
484      */
485     Status = AcpiOsTableOverride (MappedTable, &OverrideTable);
486     if (ACPI_SUCCESS (Status) && OverrideTable)
487     {
488         ACPI_INFO ((AE_INFO,
489             "%4.4s @ 0x%p Table override, replaced with:",
490             MappedTable->Signature, ACPI_CAST_PTR (void, Address)));
491
492         AcpiGbl_RootTableList.Tables[TableIndex].Pointer = OverrideTable;
493         Address = ACPI_PTR_TO_PHYSADDR (OverrideTable);
494
495         TableToInstall = OverrideTable;
496         Flags = ACPI_TABLE_ORIGIN_OVERRIDE;
497     }
498     else
499     {
500         TableToInstall = MappedTable;
501         Flags = ACPI_TABLE_ORIGIN_MAPPED;
502     }
503
504     /* Initialize the table entry */
505
506     AcpiGbl_RootTableList.Tables[TableIndex].Address = Address;
507     AcpiGbl_RootTableList.Tables[TableIndex].Length = TableToInstall->Length;
508     AcpiGbl_RootTableList.Tables[TableIndex].Flags = Flags;
509
510     ACPI_MOVE_32_TO_32 (
511         &(AcpiGbl_RootTableList.Tables[TableIndex].Signature),
512         TableToInstall->Signature);
513
514     AcpiTbPrintTableHeader (Address, TableToInstall);
515
516     if (TableIndex == ACPI_TABLE_INDEX_DSDT)
517     {
518         /* Global integer width is based upon revision of the DSDT */
519
520         AcpiUtSetIntegerWidth (TableToInstall->Revision);
521     }
522
523 UnmapAndExit:
524     AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
525 }
526
527
528 /*******************************************************************************
529  *
530  * FUNCTION:    AcpiTbGetRootTableEntry
531  *
532  * PARAMETERS:  TableEntry          - Pointer to the RSDT/XSDT table entry
533  *              TableEntrySize      - sizeof 32 or 64 (RSDT or XSDT)
534  *
535  * RETURN:      Physical address extracted from the root table
536  *
537  * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on
538  *              both 32-bit and 64-bit platforms
539  *
540  * NOTE:        ACPI_PHYSICAL_ADDRESS is 32-bit on 32-bit platforms, 64-bit on
541  *              64-bit platforms.
542  *
543  ******************************************************************************/
544
545 static ACPI_PHYSICAL_ADDRESS
546 AcpiTbGetRootTableEntry (
547     UINT8                   *TableEntry,
548     UINT32                  TableEntrySize)
549 {
550     UINT64                  Address64;
551
552
553     /*
554      * Get the table physical address (32-bit for RSDT, 64-bit for XSDT):
555      * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT
556      */
557     if (TableEntrySize == sizeof (UINT32))
558     {
559         /*
560          * 32-bit platform, RSDT: Return 32-bit table entry
561          * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return
562          */
563         return ((ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST_PTR (UINT32, TableEntry)));
564     }
565     else
566     {
567         /*
568          * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return
569          * 64-bit platform, XSDT: Move (unaligned) 64-bit to local,
570          *  return 64-bit
571          */
572         ACPI_MOVE_64_TO_64 (&Address64, TableEntry);
573
574 #if ACPI_MACHINE_WIDTH == 32
575         if (Address64 > ACPI_UINT32_MAX)
576         {
577             /* Will truncate 64-bit address to 32 bits, issue warning */
578
579             ACPI_WARNING ((AE_INFO,
580                 "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X),"
581                 " truncating",
582                 ACPI_FORMAT_UINT64 (Address64)));
583         }
584 #endif
585         return ((ACPI_PHYSICAL_ADDRESS) (Address64));
586     }
587 }
588
589
590 /*******************************************************************************
591  *
592  * FUNCTION:    AcpiTbParseRootTable
593  *
594  * PARAMETERS:  Rsdp                    - Pointer to the RSDP
595  *
596  * RETURN:      Status
597  *
598  * DESCRIPTION: This function is called to parse the Root System Description
599  *              Table (RSDT or XSDT)
600  *
601  * NOTE:        Tables are mapped (not copied) for efficiency. The FACS must
602  *              be mapped and cannot be copied because it contains the actual
603  *              memory location of the ACPI Global Lock.
604  *
605  ******************************************************************************/
606
607 ACPI_STATUS
608 AcpiTbParseRootTable (
609     ACPI_PHYSICAL_ADDRESS   RsdpAddress)
610 {
611     ACPI_TABLE_RSDP         *Rsdp;
612     UINT32                  TableEntrySize;
613     UINT32                  i;
614     UINT32                  TableCount;
615     ACPI_TABLE_HEADER       *Table;
616     ACPI_PHYSICAL_ADDRESS   Address;
617     UINT32                  Length;
618     UINT8                   *TableEntry;
619     ACPI_STATUS             Status;
620
621
622     ACPI_FUNCTION_TRACE (TbParseRootTable);
623
624
625     /*
626      * Map the entire RSDP and extract the address of the RSDT or XSDT
627      */
628     Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP));
629     if (!Rsdp)
630     {
631         return_ACPI_STATUS (AE_NO_MEMORY);
632     }
633
634     AcpiTbPrintTableHeader (RsdpAddress,
635         ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp));
636
637     /* Differentiate between RSDT and XSDT root tables */
638
639     if (Rsdp->Revision > 1 && Rsdp->XsdtPhysicalAddress)
640     {
641         /*
642          * Root table is an XSDT (64-bit physical addresses). We must use the
643          * XSDT if the revision is > 1 and the XSDT pointer is present, as per
644          * the ACPI specification.
645          */
646         Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress;
647         TableEntrySize = sizeof (UINT64);
648     }
649     else
650     {
651         /* Root table is an RSDT (32-bit physical addresses) */
652
653         Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress;
654         TableEntrySize = sizeof (UINT32);
655     }
656
657     /*
658      * It is not possible to map more than one entry in some environments,
659      * so unmap the RSDP here before mapping other tables
660      */
661     AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP));
662
663
664     /* Map the RSDT/XSDT table header to get the full table length */
665
666     Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
667     if (!Table)
668     {
669         return_ACPI_STATUS (AE_NO_MEMORY);
670     }
671
672     AcpiTbPrintTableHeader (Address, Table);
673
674     /* Get the length of the full table, verify length and map entire table */
675
676     Length = Table->Length;
677     AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER));
678
679     if (Length < sizeof (ACPI_TABLE_HEADER))
680     {
681         ACPI_ERROR ((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", Length));
682         return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
683     }
684
685     Table = AcpiOsMapMemory (Address, Length);
686     if (!Table)
687     {
688         return_ACPI_STATUS (AE_NO_MEMORY);
689     }
690
691     /* Validate the root table checksum */
692
693     Status = AcpiTbVerifyChecksum (Table, Length);
694     if (ACPI_FAILURE (Status))
695     {
696         AcpiOsUnmapMemory (Table, Length);
697         return_ACPI_STATUS (Status);
698     }
699
700     /* Calculate the number of tables described in the root table */
701
702     TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) /
703         TableEntrySize);
704
705     /*
706      * First two entries in the table array are reserved for the DSDT
707      * and FACS, which are not actually present in the RSDT/XSDT - they
708      * come from the FADT
709      */
710     TableEntry = ACPI_CAST_PTR (UINT8, Table) + sizeof (ACPI_TABLE_HEADER);
711     AcpiGbl_RootTableList.CurrentTableCount = 2;
712
713     /*
714      * Initialize the root table array from the RSDT/XSDT
715      */
716     for (i = 0; i < TableCount; i++)
717     {
718         if (AcpiGbl_RootTableList.CurrentTableCount >=
719             AcpiGbl_RootTableList.MaxTableCount)
720         {
721             /* There is no more room in the root table array, attempt resize */
722
723             Status = AcpiTbResizeRootTableList ();
724             if (ACPI_FAILURE (Status))
725             {
726                 ACPI_WARNING ((AE_INFO, "Truncating %u table entries!",
727                     (unsigned) (TableCount -
728                     (AcpiGbl_RootTableList.CurrentTableCount - 2))));
729                 break;
730             }
731         }
732
733         /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
734
735         AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount].Address =
736             AcpiTbGetRootTableEntry (TableEntry, TableEntrySize);
737
738         TableEntry += TableEntrySize;
739         AcpiGbl_RootTableList.CurrentTableCount++;
740     }
741
742     /*
743      * It is not possible to map more than one entry in some environments,
744      * so unmap the root table here before mapping other tables
745      */
746     AcpiOsUnmapMemory (Table, Length);
747
748     /*
749      * Complete the initialization of the root table array by examining
750      * the header of each table
751      */
752     for (i = 2; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
753     {
754         AcpiTbInstallTable (AcpiGbl_RootTableList.Tables[i].Address,
755             NULL, i);
756
757         /* Special case for FADT - get the DSDT and FACS */
758
759         if (ACPI_COMPARE_NAME (
760                 &AcpiGbl_RootTableList.Tables[i].Signature, ACPI_SIG_FADT))
761         {
762             AcpiTbParseFadt (i);
763         }
764     }
765
766     return_ACPI_STATUS (AE_OK);
767 }