Beispiel #1
0
ACPI_STATUS
AcpiTbParseRootTable (
    ACPI_PHYSICAL_ADDRESS   RsdpAddress)
{
    ACPI_TABLE_RSDP         *Rsdp;
    UINT32                  TableEntrySize;
    UINT32                  i;
    UINT32                  TableCount;
    ACPI_TABLE_HEADER       *Table;
    ACPI_PHYSICAL_ADDRESS   Address;
    UINT32                  Length;
    UINT8                   *TableEntry;
    ACPI_STATUS             Status;
    UINT32                  TableIndex;


    ACPI_FUNCTION_TRACE (TbParseRootTable);


    /* Map the entire RSDP and extract the address of the RSDT or XSDT */

    Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP));
    if (!Rsdp)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    AcpiTbPrintTableHeader (RsdpAddress,
        ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp));

    /* Use XSDT if present and not overridden. Otherwise, use RSDT */

    if ((Rsdp->Revision > 1) &&
        Rsdp->XsdtPhysicalAddress &&
        !AcpiGbl_DoNotUseXsdt)
    {
        /*
         * RSDP contains an XSDT (64-bit physical addresses). We must use
         * the XSDT if the revision is > 1 and the XSDT pointer is present,
         * as per the ACPI specification.
         */
        Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress;
        TableEntrySize = ACPI_XSDT_ENTRY_SIZE;
    }
    else
    {
        /* Root table is an RSDT (32-bit physical addresses) */

        Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress;
        TableEntrySize = ACPI_RSDT_ENTRY_SIZE;
    }

    /*
     * It is not possible to map more than one entry in some environments,
     * so unmap the RSDP here before mapping other tables
     */
    AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP));

    /* Map the RSDT/XSDT table header to get the full table length */

    Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
    if (!Table)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    AcpiTbPrintTableHeader (Address, Table);

    /*
     * Validate length of the table, and map entire table.
     * Minimum length table must contain at least one entry.
     */
    Length = Table->Length;
    AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER));

    if (Length < (sizeof (ACPI_TABLE_HEADER) + TableEntrySize))
    {
        ACPI_BIOS_ERROR ((AE_INFO,
            "Invalid table length 0x%X in RSDT/XSDT", Length));
        return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
    }

    Table = AcpiOsMapMemory (Address, Length);
    if (!Table)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Validate the root table checksum */

    Status = AcpiTbVerifyChecksum (Table, Length);
    if (ACPI_FAILURE (Status))
    {
        AcpiOsUnmapMemory (Table, Length);
        return_ACPI_STATUS (Status);
    }

    /* Get the number of entries and pointer to first entry */

    TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) /
        TableEntrySize);
    TableEntry = ACPI_ADD_PTR (UINT8, Table, sizeof (ACPI_TABLE_HEADER));

    /* Initialize the root table array from the RSDT/XSDT */

    for (i = 0; i < TableCount; i++)
    {
        /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */

        Address = AcpiTbGetRootTableEntry (TableEntry, TableEntrySize);

        /* Skip NULL entries in RSDT/XSDT */

        if (!Address)
        {
            goto NextTable;
        }

        Status = AcpiTbInstallStandardTable (Address,
            ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, FALSE, TRUE, &TableIndex);

        if (ACPI_SUCCESS (Status) &&
            ACPI_COMPARE_NAME (
                &AcpiGbl_RootTableList.Tables[TableIndex].Signature,
                ACPI_SIG_FADT))
        {
            AcpiGbl_FadtIndex = TableIndex;
            AcpiTbParseFadt ();
        }

NextTable:

        TableEntry += TableEntrySize;
    }

    AcpiOsUnmapMemory (Table, Length);
    return_ACPI_STATUS (AE_OK);
}
Beispiel #2
0
static ACPI_STATUS
AcpiTbValidateXsdt (
    ACPI_PHYSICAL_ADDRESS   XsdtAddress)
{
    ACPI_TABLE_HEADER       *Table;
    UINT8                   *NextEntry;
    ACPI_PHYSICAL_ADDRESS   Address;
    UINT32                  Length;
    UINT32                  EntryCount;
    ACPI_STATUS             Status;
    UINT32                  i;


    /* Get the XSDT length */

    Table = AcpiOsMapMemory (XsdtAddress, sizeof (ACPI_TABLE_HEADER));
    if (!Table)
    {
        return (AE_NO_MEMORY);
    }

    Length = Table->Length;
    AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER));

    /*
     * Minimum XSDT length is the size of the standard ACPI header
     * plus one physical address entry
     */
    if (Length < (sizeof (ACPI_TABLE_HEADER) + ACPI_XSDT_ENTRY_SIZE))
    {
        return (AE_INVALID_TABLE_LENGTH);
    }

    /* Map the entire XSDT */

    Table = AcpiOsMapMemory (XsdtAddress, Length);
    if (!Table)
    {
        return (AE_NO_MEMORY);
    }

    /* Get the number of entries and pointer to first entry */

    Status = AE_OK;
    NextEntry = ACPI_ADD_PTR (UINT8, Table, sizeof (ACPI_TABLE_HEADER));
    EntryCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) /
        ACPI_XSDT_ENTRY_SIZE);

    /* Validate each entry (physical address) within the XSDT */

    for (i = 0; i < EntryCount; i++)
    {
        Address = AcpiTbGetRootTableEntry (NextEntry, ACPI_XSDT_ENTRY_SIZE);
        if (!Address)
        {
            /* Detected a NULL entry, XSDT is invalid */

            Status = AE_NULL_ENTRY;
            break;
        }

        NextEntry += ACPI_XSDT_ENTRY_SIZE;
    }

    /* Unmap table */

    AcpiOsUnmapMemory (Table, Length);
    return (Status);
}