xref: /titanic_51/usr/src/uts/intel/io/acpica/tables/tbutils.c (revision 3c7284bd3243d42a710edac3a15f6019b4c849be)
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 "acpi.h"
47 #include "accommon.h"
48 #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     /* If a particular signature is expected (DSDT/FACS), it must match */
453 
454     if (Signature &&
455         !ACPI_COMPARE_NAME (MappedTable->Signature, Signature))
456     {
457         ACPI_ERROR ((AE_INFO,
458             "Invalid signature 0x%X for ACPI table, expected [%s]",
459             *ACPI_CAST_PTR (UINT32, MappedTable->Signature), Signature));
460         goto UnmapAndExit;
461     }
462 
463     /*
464      * ACPI Table Override:
465      *
466      * Before we install the table, let the host OS override it with a new
467      * one if desired. Any table within the RSDT/XSDT can be replaced,
468      * including the DSDT which is pointed to by the FADT.
469      */
470     Status = AcpiOsTableOverride (MappedTable, &OverrideTable);
471     if (ACPI_SUCCESS (Status) && OverrideTable)
472     {
473         ACPI_INFO ((AE_INFO,
474             "%4.4s @ 0x%p Table override, replaced with:",
475             MappedTable->Signature, ACPI_CAST_PTR (void, Address)));
476 
477         AcpiGbl_RootTableList.Tables[TableIndex].Pointer = OverrideTable;
478         Address = ACPI_PTR_TO_PHYSADDR (OverrideTable);
479 
480         TableToInstall = OverrideTable;
481         Flags = ACPI_TABLE_ORIGIN_OVERRIDE;
482     }
483     else
484     {
485         TableToInstall = MappedTable;
486         Flags = ACPI_TABLE_ORIGIN_MAPPED;
487     }
488 
489     /* Initialize the table entry */
490 
491     AcpiGbl_RootTableList.Tables[TableIndex].Address = Address;
492     AcpiGbl_RootTableList.Tables[TableIndex].Length = TableToInstall->Length;
493     AcpiGbl_RootTableList.Tables[TableIndex].Flags = Flags;
494 
495     ACPI_MOVE_32_TO_32 (
496         &(AcpiGbl_RootTableList.Tables[TableIndex].Signature),
497         TableToInstall->Signature);
498 
499     AcpiTbPrintTableHeader (Address, TableToInstall);
500 
501     if (TableIndex == ACPI_TABLE_INDEX_DSDT)
502     {
503         /* Global integer width is based upon revision of the DSDT */
504 
505         AcpiUtSetIntegerWidth (TableToInstall->Revision);
506     }
507 
508 UnmapAndExit:
509     AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
510 }
511 
512 
513 /*******************************************************************************
514  *
515  * FUNCTION:    AcpiTbGetRootTableEntry
516  *
517  * PARAMETERS:  TableEntry          - Pointer to the RSDT/XSDT table entry
518  *              TableEntrySize      - sizeof 32 or 64 (RSDT or XSDT)
519  *
520  * RETURN:      Physical address extracted from the root table
521  *
522  * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on
523  *              both 32-bit and 64-bit platforms
524  *
525  * NOTE:        ACPI_PHYSICAL_ADDRESS is 32-bit on 32-bit platforms, 64-bit on
526  *              64-bit platforms.
527  *
528  ******************************************************************************/
529 
530 static ACPI_PHYSICAL_ADDRESS
531 AcpiTbGetRootTableEntry (
532     UINT8                   *TableEntry,
533     UINT32                  TableEntrySize)
534 {
535     UINT64                  Address64;
536 
537 
538     /*
539      * Get the table physical address (32-bit for RSDT, 64-bit for XSDT):
540      * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT
541      */
542     if (TableEntrySize == sizeof (UINT32))
543     {
544         /*
545          * 32-bit platform, RSDT: Return 32-bit table entry
546          * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return
547          */
548         return ((ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST_PTR (UINT32, TableEntry)));
549     }
550     else
551     {
552         /*
553          * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return
554          * 64-bit platform, XSDT: Move (unaligned) 64-bit to local,
555          *  return 64-bit
556          */
557         ACPI_MOVE_64_TO_64 (&Address64, TableEntry);
558 
559 #if ACPI_MACHINE_WIDTH == 32
560         if (Address64 > ACPI_UINT32_MAX)
561         {
562             /* Will truncate 64-bit address to 32 bits, issue warning */
563 
564             ACPI_WARNING ((AE_INFO,
565                 "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X),"
566                 " truncating",
567                 ACPI_FORMAT_UINT64 (Address64)));
568         }
569 #endif
570         return ((ACPI_PHYSICAL_ADDRESS) (Address64));
571     }
572 }
573 
574 
575 /*******************************************************************************
576  *
577  * FUNCTION:    AcpiTbParseRootTable
578  *
579  * PARAMETERS:  Rsdp                    - Pointer to the RSDP
580  *
581  * RETURN:      Status
582  *
583  * DESCRIPTION: This function is called to parse the Root System Description
584  *              Table (RSDT or XSDT)
585  *
586  * NOTE:        Tables are mapped (not copied) for efficiency. The FACS must
587  *              be mapped and cannot be copied because it contains the actual
588  *              memory location of the ACPI Global Lock.
589  *
590  ******************************************************************************/
591 
592 ACPI_STATUS
593 AcpiTbParseRootTable (
594     ACPI_PHYSICAL_ADDRESS   RsdpAddress)
595 {
596     ACPI_TABLE_RSDP         *Rsdp;
597     UINT32                  TableEntrySize;
598     UINT32                  i;
599     UINT32                  TableCount;
600     ACPI_TABLE_HEADER       *Table;
601     ACPI_PHYSICAL_ADDRESS   Address;
602     UINT32                  Length;
603     UINT8                   *TableEntry;
604     ACPI_STATUS             Status;
605 
606 
607     ACPI_FUNCTION_TRACE (TbParseRootTable);
608 
609 
610     /*
611      * Map the entire RSDP and extract the address of the RSDT or XSDT
612      */
613     Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP));
614     if (!Rsdp)
615     {
616         return_ACPI_STATUS (AE_NO_MEMORY);
617     }
618 
619     AcpiTbPrintTableHeader (RsdpAddress,
620         ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp));
621 
622     /* Differentiate between RSDT and XSDT root tables */
623 
624     if (Rsdp->Revision > 1 && Rsdp->XsdtPhysicalAddress)
625     {
626         /*
627          * Root table is an XSDT (64-bit physical addresses). We must use the
628          * XSDT if the revision is > 1 and the XSDT pointer is present, as per
629          * the ACPI specification.
630          */
631         Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress;
632         TableEntrySize = sizeof (UINT64);
633     }
634     else
635     {
636         /* Root table is an RSDT (32-bit physical addresses) */
637 
638         Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress;
639         TableEntrySize = sizeof (UINT32);
640     }
641 
642     /*
643      * It is not possible to map more than one entry in some environments,
644      * so unmap the RSDP here before mapping other tables
645      */
646     AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP));
647 
648 
649     /* Map the RSDT/XSDT table header to get the full table length */
650 
651     Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
652     if (!Table)
653     {
654         return_ACPI_STATUS (AE_NO_MEMORY);
655     }
656 
657     AcpiTbPrintTableHeader (Address, Table);
658 
659     /* Get the length of the full table, verify length and map entire table */
660 
661     Length = Table->Length;
662     AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER));
663 
664     if (Length < sizeof (ACPI_TABLE_HEADER))
665     {
666         ACPI_ERROR ((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", Length));
667         return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
668     }
669 
670     Table = AcpiOsMapMemory (Address, Length);
671     if (!Table)
672     {
673         return_ACPI_STATUS (AE_NO_MEMORY);
674     }
675 
676     /* Validate the root table checksum */
677 
678     Status = AcpiTbVerifyChecksum (Table, Length);
679     if (ACPI_FAILURE (Status))
680     {
681         AcpiOsUnmapMemory (Table, Length);
682         return_ACPI_STATUS (Status);
683     }
684 
685     /* Calculate the number of tables described in the root table */
686 
687     TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) /
688         TableEntrySize);
689 
690     /*
691      * First two entries in the table array are reserved for the DSDT
692      * and FACS, which are not actually present in the RSDT/XSDT - they
693      * come from the FADT
694      */
695     TableEntry = ACPI_CAST_PTR (UINT8, Table) + sizeof (ACPI_TABLE_HEADER);
696     AcpiGbl_RootTableList.CurrentTableCount = 2;
697 
698     /*
699      * Initialize the root table array from the RSDT/XSDT
700      */
701     for (i = 0; i < TableCount; i++)
702     {
703         if (AcpiGbl_RootTableList.CurrentTableCount >=
704             AcpiGbl_RootTableList.MaxTableCount)
705         {
706             /* There is no more room in the root table array, attempt resize */
707 
708             Status = AcpiTbResizeRootTableList ();
709             if (ACPI_FAILURE (Status))
710             {
711                 ACPI_WARNING ((AE_INFO, "Truncating %u table entries!",
712                     (unsigned) (TableCount -
713                     (AcpiGbl_RootTableList.CurrentTableCount - 2))));
714                 break;
715             }
716         }
717 
718         /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
719 
720         AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount].Address =
721             AcpiTbGetRootTableEntry (TableEntry, TableEntrySize);
722 
723         TableEntry += TableEntrySize;
724         AcpiGbl_RootTableList.CurrentTableCount++;
725     }
726 
727     /*
728      * It is not possible to map more than one entry in some environments,
729      * so unmap the root table here before mapping other tables
730      */
731     AcpiOsUnmapMemory (Table, Length);
732 
733     /*
734      * Complete the initialization of the root table array by examining
735      * the header of each table
736      */
737     for (i = 2; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
738     {
739         AcpiTbInstallTable (AcpiGbl_RootTableList.Tables[i].Address,
740             NULL, i);
741 
742         /* Special case for FADT - get the DSDT and FACS */
743 
744         if (ACPI_COMPARE_NAME (
745                 &AcpiGbl_RootTableList.Tables[i].Signature, ACPI_SIG_FADT))
746         {
747             AcpiTbParseFadt (i);
748         }
749     }
750 
751     return_ACPI_STATUS (AE_OK);
752 }
753