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