dect
/
linux-2.6
Archived
13
0
Fork 0

Pull bugzilla-8630 into release branch

This commit is contained in:
Len Brown 2007-08-24 22:19:20 -04:00
commit de9bde9adb
1 changed files with 71 additions and 0 deletions

View File

@ -51,6 +51,65 @@ ACPI_MODULE_NAME("tbutils")
static acpi_physical_address
acpi_tb_get_root_table_entry(u8 * table_entry,
acpi_native_uint table_entry_size);
/*******************************************************************************
*
* FUNCTION: acpi_tb_check_xsdt
*
* PARAMETERS: address - Pointer to the XSDT
*
* RETURN: status
* AE_OK - XSDT is okay
* AE_NO_MEMORY - can't map XSDT
* AE_INVALID_TABLE_LENGTH - invalid table length
* AE_NULL_ENTRY - XSDT has NULL entry
*
* DESCRIPTION: validate XSDT
******************************************************************************/
static acpi_status
acpi_tb_check_xsdt(acpi_physical_address address)
{
struct acpi_table_header *table;
u32 length;
u64 xsdt_entry_address;
u8 *table_entry;
u32 table_count;
int i;
table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
if (!table)
return AE_NO_MEMORY;
length = table->length;
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
if (length < sizeof(struct acpi_table_header))
return AE_INVALID_TABLE_LENGTH;
table = acpi_os_map_memory(address, length);
if (!table)
return AE_NO_MEMORY;
/* Calculate the number of tables described in XSDT */
table_count =
(u32) ((table->length -
sizeof(struct acpi_table_header)) / sizeof(u64));
table_entry =
ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header);
for (i = 0; i < table_count; i++) {
ACPI_MOVE_64_TO_64(&xsdt_entry_address, table_entry);
if (!xsdt_entry_address) {
/* XSDT has NULL entry */
break;
}
table_entry += sizeof(u64);
}
acpi_os_unmap_memory(table, length);
if (i < table_count)
return AE_NULL_ENTRY;
else
return AE_OK;
}
/*******************************************************************************
*
@ -341,6 +400,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
u32 table_count;
struct acpi_table_header *table;
acpi_physical_address address;
acpi_physical_address rsdt_address;
u32 length;
u8 *table_entry;
acpi_status status;
@ -369,6 +429,8 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
*/
address = (acpi_physical_address) rsdp->xsdt_physical_address;
table_entry_size = sizeof(u64);
rsdt_address = (acpi_physical_address)
rsdp->rsdt_physical_address;
} else {
/* Root table is an RSDT (32-bit physical addresses) */
@ -382,6 +444,15 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
*/
acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
if (table_entry_size == sizeof(u64)) {
if (acpi_tb_check_xsdt(address) == AE_NULL_ENTRY) {
/* XSDT has NULL entry, RSDT is used */
address = rsdt_address;
table_entry_size = sizeof(u32);
ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry,"
"using RSDT"));
}
}
/* Map the RSDT/XSDT table header to get the full table length */
table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));