diff options
author | Jung-uk Kim <jkim@FreeBSD.org> | 2007-03-22 17:24:05 +0000 |
---|---|---|
committer | Jung-uk Kim <jkim@FreeBSD.org> | 2007-03-22 17:24:05 +0000 |
commit | 1a39cfb03c6797452971010e59462692d346a22b (patch) | |
tree | 69d0fa3b3760b0abcc0335ff748e39701a8bf064 /sys/contrib/dev/acpica/tbutils.c | |
parent | e9bfb92a8e683016c7f6c24104fce9db9567ee1c (diff) | |
download | src-1a39cfb03c6797452971010e59462692d346a22b.tar.gz src-1a39cfb03c6797452971010e59462692d346a22b.zip |
Vendor import of Intel ACPI-CA 20070320
Notes
Notes:
svn path=/vendor-sys/acpica/dist/; revision=167802
Diffstat (limited to 'sys/contrib/dev/acpica/tbutils.c')
-rw-r--r-- | sys/contrib/dev/acpica/tbutils.c | 521 |
1 files changed, 354 insertions, 167 deletions
diff --git a/sys/contrib/dev/acpica/tbutils.c b/sys/contrib/dev/acpica/tbutils.c index 3429ebf3d061..5b64e2005e5f 100644 --- a/sys/contrib/dev/acpica/tbutils.c +++ b/sys/contrib/dev/acpica/tbutils.c @@ -1,7 +1,7 @@ /****************************************************************************** * - * Module Name: tbutils - Table manipulation utilities - * $Revision: 1.71 $ + * Module Name: tbutils - table utilities + * $Revision: 1.88 $ * *****************************************************************************/ @@ -9,7 +9,7 @@ * * 1. Copyright Notice * - * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp. + * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp. * All rights reserved. * * 2. License @@ -119,289 +119,476 @@ #include <contrib/dev/acpica/acpi.h> #include <contrib/dev/acpica/actables.h> - #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME ("tbutils") /* Local prototypes */ -#ifdef ACPI_OBSOLETE_FUNCTIONS -ACPI_STATUS -AcpiTbHandleToObject ( - UINT16 TableId, - ACPI_TABLE_DESC **TableDesc); -#endif +static ACPI_PHYSICAL_ADDRESS +AcpiTbGetRootTableEntry ( + UINT8 *TableEntry, + ACPI_NATIVE_UINT TableEntrySize); /******************************************************************************* * - * FUNCTION: AcpiTbIsTableInstalled + * FUNCTION: AcpiTbTablesLoaded * - * PARAMETERS: NewTableDesc - Descriptor for new table being installed + * PARAMETERS: None * - * RETURN: Status - AE_ALREADY_EXISTS if the table is already installed + * RETURN: TRUE if required ACPI tables are loaded * - * DESCRIPTION: Determine if an ACPI table is already installed - * - * MUTEX: Table data structures should be locked + * DESCRIPTION: Determine if the minimum required ACPI tables are present + * (FADT, FACS, DSDT) * ******************************************************************************/ -ACPI_STATUS -AcpiTbIsTableInstalled ( - ACPI_TABLE_DESC *NewTableDesc) +BOOLEAN +AcpiTbTablesLoaded ( + void) { - ACPI_TABLE_DESC *TableDesc; + if (AcpiGbl_RootTableList.Count >= 3) + { + return (TRUE); + } - ACPI_FUNCTION_TRACE ("TbIsTableInstalled"); - + return (FALSE); +} - /* Get the list descriptor and first table descriptor */ - TableDesc = AcpiGbl_TableLists[NewTableDesc->Type].Next; +/******************************************************************************* + * + * FUNCTION: AcpiTbPrintTableHeader + * + * PARAMETERS: Address - Table physical address + * Header - Table header + * + * RETURN: None + * + * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. + * + ******************************************************************************/ - /* Examine all installed tables of this type */ +void +AcpiTbPrintTableHeader ( + ACPI_PHYSICAL_ADDRESS Address, + ACPI_TABLE_HEADER *Header) +{ - while (TableDesc) + if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_FACS)) { - /* - * If the table lengths match, perform a full bytewise compare. This - * means that we will allow tables with duplicate OemTableId(s), as - * long as the tables are different in some way. - * - * Checking if the table has been loaded into the namespace means that - * we don't check for duplicate tables during the initial installation - * of tables within the RSDT/XSDT. - */ - if ((TableDesc->LoadedIntoNamespace) && - (TableDesc->Pointer->Length == NewTableDesc->Pointer->Length) && - (!ACPI_MEMCMP (TableDesc->Pointer, NewTableDesc->Pointer, - NewTableDesc->Pointer->Length))) - { - /* Match: this table is already installed */ - - ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, - "Table [%4.4s] already installed: Rev %X OemTableId [%8.8s]\n", - NewTableDesc->Pointer->Signature, - NewTableDesc->Pointer->Revision, - NewTableDesc->Pointer->OemTableId)); - - NewTableDesc->OwnerId = TableDesc->OwnerId; - NewTableDesc->InstalledDesc = TableDesc; - - return_ACPI_STATUS (AE_ALREADY_EXISTS); - } - - /* Get next table on the list */ + /* FACS only has signature and length fields of common table header */ - TableDesc = TableDesc->Next; + ACPI_INFO ((AE_INFO, "%4.4s @ 0x%p/0x%04X", + Header->Signature, ACPI_CAST_PTR (void, Address), Header->Length)); + } + else if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_RSDP)) + { + /* RSDP has no common fields */ + + ACPI_INFO ((AE_INFO, "RSDP @ 0x%p/0x%04X (v%3.3d %6.6s)", + ACPI_CAST_PTR (void, Address), + (ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision > 0) ? + ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Length : 20, + ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision, + ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->OemId)); + } + else + { + /* Standard ACPI table with full common header */ + + ACPI_INFO ((AE_INFO, + "%4.4s @ 0x%p/0x%04X (v%3.3d %6.6s %8.8s 0x%08X %4.4s 0x%08X)", + Header->Signature, ACPI_CAST_PTR (void, Address), + Header->Length, Header->Revision, Header->OemId, + Header->OemTableId, Header->OemRevision, Header->AslCompilerId, + Header->AslCompilerRevision)); } - - return_ACPI_STATUS (AE_OK); } /******************************************************************************* * - * FUNCTION: AcpiTbValidateTableHeader + * FUNCTION: AcpiTbValidateChecksum * - * PARAMETERS: TableHeader - Logical pointer to the table + * PARAMETERS: Table - ACPI table to verify + * Length - Length of entire table * * RETURN: Status * - * DESCRIPTION: Check an ACPI table header for validity - * - * NOTE: Table pointers are validated as follows: - * 1) Table pointer must point to valid physical memory - * 2) Signature must be 4 ASCII chars, even if we don't recognize the - * name - * 3) Table must be readable for length specified in the header - * 4) Table checksum must be valid (with the exception of the FACS - * which has no checksum because it contains variable fields) + * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns + * exception on bad checksum. * ******************************************************************************/ ACPI_STATUS -AcpiTbValidateTableHeader ( - ACPI_TABLE_HEADER *TableHeader) +AcpiTbVerifyChecksum ( + ACPI_TABLE_HEADER *Table, + UINT32 Length) { - ACPI_NAME Signature; + UINT8 Checksum; - ACPI_FUNCTION_NAME ("TbValidateTableHeader"); + /* Compute the checksum on the table */ + Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Length); - /* Verify that this is a valid address */ + /* Checksum ok? (should be zero) */ - if (!AcpiOsReadable (TableHeader, sizeof (ACPI_TABLE_HEADER))) + if (Checksum) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Cannot read table header at %p\n", TableHeader)); + ACPI_WARNING ((AE_INFO, + "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", + Table->Signature, Table->Checksum, (UINT8) (Table->Checksum - Checksum))); - return (AE_BAD_ADDRESS); +#if (ACPI_CHECKSUM_ABORT) + return (AE_BAD_CHECKSUM); +#endif } - /* Ensure that the signature is 4 ASCII characters */ + return (AE_OK); +} - ACPI_MOVE_32_TO_32 (&Signature, TableHeader->Signature); - if (!AcpiUtValidAcpiName (Signature)) - { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Table signature at %p [%p] has invalid characters\n", - TableHeader, &Signature)); - ACPI_REPORT_WARNING (("Invalid table signature found: [%4.4s]\n", - (char *) &Signature)); +/******************************************************************************* + * + * FUNCTION: AcpiTbChecksum + * + * PARAMETERS: Buffer - Pointer to memory region to be checked + * Length - Length of this memory region + * + * RETURN: Checksum (UINT8) + * + * DESCRIPTION: Calculates circular checksum of memory region. + * + ******************************************************************************/ - ACPI_DUMP_BUFFER (TableHeader, sizeof (ACPI_TABLE_HEADER)); - return (AE_BAD_SIGNATURE); - } +UINT8 +AcpiTbChecksum ( + UINT8 *Buffer, + ACPI_NATIVE_UINT Length) +{ + UINT8 Sum = 0; + UINT8 *End = Buffer + Length; - /* Validate the table length */ - if (TableHeader->Length < sizeof (ACPI_TABLE_HEADER)) + while (Buffer < End) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Invalid length in table header %p name %4.4s\n", - TableHeader, (char *) &Signature)); - - ACPI_REPORT_WARNING (("Invalid table header length (0x%X) found\n", - (UINT32) TableHeader->Length)); - - ACPI_DUMP_BUFFER (TableHeader, sizeof (ACPI_TABLE_HEADER)); - return (AE_BAD_HEADER); + Sum = (UINT8) (Sum + *(Buffer++)); } - return (AE_OK); + return Sum; } /******************************************************************************* * - * FUNCTION: AcpiTbVerifyTableChecksum + * FUNCTION: AcpiTbInstallTable * - * PARAMETERS: *TableHeader - ACPI table to verify + * PARAMETERS: Address - Physical address of DSDT or FACS + * Flags - Flags + * Signature - Table signature, NULL if no need to + * match + * TableIndex - Index into root table array * - * RETURN: 8 bit checksum of table + * RETURN: None * - * DESCRIPTION: Does an 8 bit checksum of table and returns status. A correct - * table should have a checksum of 0. + * DESCRIPTION: Install an ACPI table into the global data structure. * ******************************************************************************/ -ACPI_STATUS -AcpiTbVerifyTableChecksum ( - ACPI_TABLE_HEADER *TableHeader) +void +AcpiTbInstallTable ( + ACPI_PHYSICAL_ADDRESS Address, + UINT8 Flags, + char *Signature, + ACPI_NATIVE_UINT TableIndex) { - UINT8 Checksum; - ACPI_STATUS Status = AE_OK; + ACPI_TABLE_HEADER *Table; - ACPI_FUNCTION_TRACE ("TbVerifyTableChecksum"); + if (!Address) + { + ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]", + Signature)); + return; + } + /* Map just the table header */ - /* Compute the checksum on the table */ + Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); + if (!Table) + { + return; + } + + /* If a particular signature is expected, signature must match */ + + if (Signature && + !ACPI_COMPARE_NAME (Table->Signature, Signature)) + { + ACPI_ERROR ((AE_INFO, "Invalid signature 0x%X for ACPI table [%s]", + *ACPI_CAST_PTR (UINT32, Table->Signature), Signature)); + goto UnmapAndExit; + } - Checksum = AcpiTbGenerateChecksum (TableHeader, TableHeader->Length); + /* Initialize the table entry */ - /* Return the appropriate exception */ + AcpiGbl_RootTableList.Tables[TableIndex].Address = Address; + AcpiGbl_RootTableList.Tables[TableIndex].Length = Table->Length; + AcpiGbl_RootTableList.Tables[TableIndex].Flags = Flags; - if (Checksum) + ACPI_MOVE_32_TO_32 ( + &(AcpiGbl_RootTableList.Tables[TableIndex].Signature), + Table->Signature); + + AcpiTbPrintTableHeader (Address, Table); + + if (TableIndex == ACPI_TABLE_INDEX_DSDT) { - ACPI_REPORT_WARNING (( - "Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)\n", - TableHeader->Signature, (UINT32) TableHeader->Checksum, - (UINT32) Checksum)); + /* Global integer width is based upon revision of the DSDT */ - Status = AE_BAD_CHECKSUM; + AcpiUtSetIntegerWidth (Table->Revision); } - return_ACPI_STATUS (Status); + +UnmapAndExit: + AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); } /******************************************************************************* * - * FUNCTION: AcpiTbGenerateChecksum + * FUNCTION: AcpiTbGetRootTableEntry + * + * PARAMETERS: TableEntry - Pointer to the RSDT/XSDT table entry + * TableEntrySize - sizeof 32 or 64 (RSDT or XSDT) * - * PARAMETERS: Buffer - Buffer to checksum - * Length - Size of the buffer + * RETURN: Physical address extracted from the root table * - * RETURN: 8 bit checksum of buffer + * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on + * both 32-bit and 64-bit platforms * - * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it. + * NOTE: ACPI_PHYSICAL_ADDRESS is 32-bit on 32-bit platforms, 64-bit on + * 64-bit platforms. * ******************************************************************************/ -UINT8 -AcpiTbGenerateChecksum ( - void *Buffer, - UINT32 Length) +static ACPI_PHYSICAL_ADDRESS +AcpiTbGetRootTableEntry ( + UINT8 *TableEntry, + ACPI_NATIVE_UINT TableEntrySize) { - const UINT8 *limit; - const UINT8 *rover; - UINT8 sum = 0; + UINT64 Address64; - if (Buffer && Length) + /* + * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): + * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT + */ + if (TableEntrySize == sizeof (UINT32)) { - /* Buffer and Length are valid */ - - limit = (UINT8 *) Buffer + Length; + /* + * 32-bit platform, RSDT: Return 32-bit table entry + * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return + */ + return ((ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST_PTR (UINT32, TableEntry))); + } + else + { + /* + * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return + * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit + */ + ACPI_MOVE_64_TO_64 (&Address64, TableEntry); - for (rover = Buffer; rover < limit; rover++) +#if ACPI_MACHINE_WIDTH == 32 + if (Address64 > ACPI_UINT32_MAX) { - sum = (UINT8) (sum + *rover); + /* Will truncate 64-bit address to 32 bits, issue warning */ + + ACPI_WARNING ((AE_INFO, + "64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating", + ACPI_FORMAT_UINT64 (Address64))); } +#endif + return ((ACPI_PHYSICAL_ADDRESS) (Address64)); } - return (sum); } -#ifdef ACPI_OBSOLETE_FUNCTIONS /******************************************************************************* * - * FUNCTION: AcpiTbHandleToObject + * FUNCTION: AcpiTbParseRootTable + * + * PARAMETERS: Rsdp - Pointer to the RSDP + * Flags - Flags + * + * RETURN: Status * - * PARAMETERS: TableId - Id for which the function is searching - * TableDesc - Pointer to return the matching table - * descriptor. + * DESCRIPTION: This function is called to parse the Root System Description + * Table (RSDT or XSDT) * - * RETURN: Search the tables to find one with a matching TableId and - * return a pointer to that table descriptor. + * NOTE: Tables are mapped (not copied) for efficiency. The FACS must + * be mapped and cannot be copied because it contains the actual + * memory location of the ACPI Global Lock. * ******************************************************************************/ ACPI_STATUS -AcpiTbHandleToObject ( - UINT16 TableId, - ACPI_TABLE_DESC **ReturnTableDesc) +AcpiTbParseRootTable ( + ACPI_PHYSICAL_ADDRESS RsdpAddress, + UINT8 Flags) { - UINT32 i; - ACPI_TABLE_DESC *TableDesc; + ACPI_TABLE_RSDP *Rsdp; + ACPI_NATIVE_UINT TableEntrySize; + ACPI_NATIVE_UINT i; + UINT32 TableCount; + ACPI_TABLE_HEADER *Table; + ACPI_PHYSICAL_ADDRESS Address; + UINT32 Length; + UINT8 *TableEntry; + ACPI_STATUS Status; + + + 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)); + + /* Differentiate between RSDT and XSDT root tables */ + + if (Rsdp->Revision > 1 && Rsdp->XsdtPhysicalAddress) + { + /* + * Root table is 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 = sizeof (UINT64); + } + else + { + /* Root table is an RSDT (32-bit physical addresses) */ + + Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress; + TableEntrySize = sizeof (UINT32); + } + /* + * 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)); - ACPI_FUNCTION_NAME ("TbHandleToObject"); + /* Map the RSDT/XSDT table header to get the full table length */ - for (i = 0; i < ACPI_TABLE_MAX; i++) + Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); + if (!Table) { - TableDesc = AcpiGbl_TableLists[i].Next; - while (TableDesc) + return_ACPI_STATUS (AE_NO_MEMORY); + } + + AcpiTbPrintTableHeader (Address, Table); + + /* Get the length of the full table, verify length and map entire table */ + + Length = Table->Length; + AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); + + if (Length < sizeof (ACPI_TABLE_HEADER)) + { + ACPI_ERROR ((AE_INFO, "Invalid 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); + } + + /* Calculate the number of tables described in the root table */ + + TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) / TableEntrySize); + + /* + * First two entries in the table array are reserved for the DSDT and FACS, + * which are not actually present in the RSDT/XSDT - they come from the FADT + */ + TableEntry = ACPI_CAST_PTR (UINT8, Table) + sizeof (ACPI_TABLE_HEADER); + AcpiGbl_RootTableList.Count = 2; + + /* + * Initialize the root table array from the RSDT/XSDT + */ + for (i = 0; i < TableCount; i++) + { + if (AcpiGbl_RootTableList.Count >= AcpiGbl_RootTableList.Size) { - if (TableDesc->TableId == TableId) + /* There is no more room in the root table array, attempt resize */ + + Status = AcpiTbResizeRootTableList (); + if (ACPI_FAILURE (Status)) { - *ReturnTableDesc = TableDesc; - return (AE_OK); + ACPI_WARNING ((AE_INFO, "Truncating %u table entries!", + (unsigned) (AcpiGbl_RootTableList.Size - AcpiGbl_RootTableList.Count))); + break; } - - TableDesc = TableDesc->Next; } + + /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ + + AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Address = + AcpiTbGetRootTableEntry (TableEntry, TableEntrySize); + + TableEntry += TableEntrySize; + AcpiGbl_RootTableList.Count++; } - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "TableId=%X does not exist\n", TableId)); - return (AE_BAD_PARAMETER); -} -#endif + /* + * It is not possible to map more than one entry in some environments, + * so unmap the root table here before mapping other tables + */ + AcpiOsUnmapMemory (Table, Length); + + /* + * Complete the initialization of the root table array by examining + * the header of each table + */ + for (i = 2; i < AcpiGbl_RootTableList.Count; i++) + { + AcpiTbInstallTable (AcpiGbl_RootTableList.Tables[i].Address, + Flags, NULL, i); + /* Special case for FADT - get the DSDT and FACS */ + + if (ACPI_COMPARE_NAME ( + &AcpiGbl_RootTableList.Tables[i].Signature, ACPI_SIG_FADT)) + { + AcpiTbParseFadt (i, Flags); + } + } + return_ACPI_STATUS (AE_OK); +} |