diff options
Diffstat (limited to 'drivers/acpi/acpica/tbutils.c')
| -rw-r--r-- | drivers/acpi/acpica/tbutils.c | 106 |
1 files changed, 72 insertions, 34 deletions
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 22ce48985720..ef7d2c2d8f0b 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c | |||
| @@ -177,19 +177,23 @@ acpi_tb_print_table_header(acpi_physical_address address, | |||
| 177 | struct acpi_table_header *header) | 177 | struct acpi_table_header *header) |
| 178 | { | 178 | { |
| 179 | 179 | ||
| 180 | /* | ||
| 181 | * The reason that the Address is cast to a void pointer is so that we | ||
| 182 | * can use %p which will work properly on both 32-bit and 64-bit hosts. | ||
| 183 | */ | ||
| 180 | if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { | 184 | if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { |
| 181 | 185 | ||
| 182 | /* FACS only has signature and length fields of common table header */ | 186 | /* FACS only has signature and length fields */ |
| 183 | 187 | ||
| 184 | ACPI_INFO((AE_INFO, "%4.4s %08lX, %04X", | 188 | ACPI_INFO((AE_INFO, "%4.4s %p %05X", |
| 185 | header->signature, (unsigned long)address, | 189 | header->signature, ACPI_CAST_PTR(void, address), |
| 186 | header->length)); | 190 | header->length)); |
| 187 | } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { | 191 | } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { |
| 188 | 192 | ||
| 189 | /* RSDP has no common fields */ | 193 | /* RSDP has no common fields */ |
| 190 | 194 | ||
| 191 | ACPI_INFO((AE_INFO, "RSDP %08lX, %04X (r%d %6.6s)", | 195 | ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", |
| 192 | (unsigned long)address, | 196 | ACPI_CAST_PTR (void, address), |
| 193 | (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> | 197 | (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> |
| 194 | revision > | 198 | revision > |
| 195 | 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, | 199 | 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, |
| @@ -202,8 +206,8 @@ acpi_tb_print_table_header(acpi_physical_address address, | |||
| 202 | /* Standard ACPI table with full common header */ | 206 | /* Standard ACPI table with full common header */ |
| 203 | 207 | ||
| 204 | ACPI_INFO((AE_INFO, | 208 | ACPI_INFO((AE_INFO, |
| 205 | "%4.4s %08lX, %04X (r%d %6.6s %8.8s %8X %4.4s %8X)", | 209 | "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", |
| 206 | header->signature, (unsigned long)address, | 210 | header->signature, ACPI_CAST_PTR (void, address), |
| 207 | header->length, header->revision, header->oem_id, | 211 | header->length, header->revision, header->oem_id, |
| 208 | header->oem_table_id, header->oem_revision, | 212 | header->oem_table_id, header->oem_revision, |
| 209 | header->asl_compiler_id, | 213 | header->asl_compiler_id, |
| @@ -280,22 +284,28 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length) | |||
| 280 | * FUNCTION: acpi_tb_install_table | 284 | * FUNCTION: acpi_tb_install_table |
| 281 | * | 285 | * |
| 282 | * PARAMETERS: Address - Physical address of DSDT or FACS | 286 | * PARAMETERS: Address - Physical address of DSDT or FACS |
| 283 | * Flags - Flags | ||
| 284 | * Signature - Table signature, NULL if no need to | 287 | * Signature - Table signature, NULL if no need to |
| 285 | * match | 288 | * match |
| 286 | * table_index - Index into root table array | 289 | * table_index - Index into root table array |
| 287 | * | 290 | * |
| 288 | * RETURN: None | 291 | * RETURN: None |
| 289 | * | 292 | * |
| 290 | * DESCRIPTION: Install an ACPI table into the global data structure. | 293 | * DESCRIPTION: Install an ACPI table into the global data structure. The |
| 294 | * table override mechanism is implemented here to allow the host | ||
| 295 | * OS to replace any table before it is installed in the root | ||
| 296 | * table array. | ||
| 291 | * | 297 | * |
| 292 | ******************************************************************************/ | 298 | ******************************************************************************/ |
| 293 | 299 | ||
| 294 | void | 300 | void |
| 295 | acpi_tb_install_table(acpi_physical_address address, | 301 | acpi_tb_install_table(acpi_physical_address address, |
| 296 | u8 flags, char *signature, u32 table_index) | 302 | char *signature, u32 table_index) |
| 297 | { | 303 | { |
| 298 | struct acpi_table_header *table; | 304 | u8 flags; |
| 305 | acpi_status status; | ||
| 306 | struct acpi_table_header *table_to_install; | ||
| 307 | struct acpi_table_header *mapped_table; | ||
| 308 | struct acpi_table_header *override_table = NULL; | ||
| 299 | 309 | ||
| 300 | if (!address) { | 310 | if (!address) { |
| 301 | ACPI_ERROR((AE_INFO, | 311 | ACPI_ERROR((AE_INFO, |
| @@ -306,41 +316,69 @@ acpi_tb_install_table(acpi_physical_address address, | |||
| 306 | 316 | ||
| 307 | /* Map just the table header */ | 317 | /* Map just the table header */ |
| 308 | 318 | ||
| 309 | table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); | 319 | mapped_table = |
| 310 | if (!table) { | 320 | acpi_os_map_memory(address, sizeof(struct acpi_table_header)); |
| 321 | if (!mapped_table) { | ||
| 311 | return; | 322 | return; |
| 312 | } | 323 | } |
| 313 | 324 | ||
| 314 | /* If a particular signature is expected, signature must match */ | 325 | /* If a particular signature is expected (DSDT/FACS), it must match */ |
| 315 | 326 | ||
| 316 | if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) { | 327 | if (signature && !ACPI_COMPARE_NAME(mapped_table->signature, signature)) { |
| 317 | ACPI_ERROR((AE_INFO, | 328 | ACPI_ERROR((AE_INFO, |
| 318 | "Invalid signature 0x%X for ACPI table [%s]", | 329 | "Invalid signature 0x%X for ACPI table, expected [%s]", |
| 319 | *ACPI_CAST_PTR(u32, table->signature), signature)); | 330 | *ACPI_CAST_PTR(u32, mapped_table->signature), |
| 331 | signature)); | ||
| 320 | goto unmap_and_exit; | 332 | goto unmap_and_exit; |
| 321 | } | 333 | } |
| 322 | 334 | ||
| 335 | /* | ||
| 336 | * ACPI Table Override: | ||
| 337 | * | ||
| 338 | * Before we install the table, let the host OS override it with a new | ||
| 339 | * one if desired. Any table within the RSDT/XSDT can be replaced, | ||
| 340 | * including the DSDT which is pointed to by the FADT. | ||
| 341 | */ | ||
| 342 | status = acpi_os_table_override(mapped_table, &override_table); | ||
| 343 | if (ACPI_SUCCESS(status) && override_table) { | ||
| 344 | ACPI_INFO((AE_INFO, | ||
| 345 | "%4.4s @ 0x%p Table override, replaced with:", | ||
| 346 | mapped_table->signature, ACPI_CAST_PTR(void, | ||
| 347 | address))); | ||
| 348 | |||
| 349 | acpi_gbl_root_table_list.tables[table_index].pointer = | ||
| 350 | override_table; | ||
| 351 | address = ACPI_PTR_TO_PHYSADDR(override_table); | ||
| 352 | |||
| 353 | table_to_install = override_table; | ||
| 354 | flags = ACPI_TABLE_ORIGIN_OVERRIDE; | ||
| 355 | } else { | ||
| 356 | table_to_install = mapped_table; | ||
| 357 | flags = ACPI_TABLE_ORIGIN_MAPPED; | ||
| 358 | } | ||
| 359 | |||
| 323 | /* Initialize the table entry */ | 360 | /* Initialize the table entry */ |
| 324 | 361 | ||
| 325 | acpi_gbl_root_table_list.tables[table_index].address = address; | 362 | acpi_gbl_root_table_list.tables[table_index].address = address; |
| 326 | acpi_gbl_root_table_list.tables[table_index].length = table->length; | 363 | acpi_gbl_root_table_list.tables[table_index].length = |
| 364 | table_to_install->length; | ||
| 327 | acpi_gbl_root_table_list.tables[table_index].flags = flags; | 365 | acpi_gbl_root_table_list.tables[table_index].flags = flags; |
| 328 | 366 | ||
| 329 | ACPI_MOVE_32_TO_32(& | 367 | ACPI_MOVE_32_TO_32(& |
| 330 | (acpi_gbl_root_table_list.tables[table_index]. | 368 | (acpi_gbl_root_table_list.tables[table_index]. |
| 331 | signature), table->signature); | 369 | signature), table_to_install->signature); |
| 332 | 370 | ||
| 333 | acpi_tb_print_table_header(address, table); | 371 | acpi_tb_print_table_header(address, table_to_install); |
| 334 | 372 | ||
| 335 | if (table_index == ACPI_TABLE_INDEX_DSDT) { | 373 | if (table_index == ACPI_TABLE_INDEX_DSDT) { |
| 336 | 374 | ||
| 337 | /* Global integer width is based upon revision of the DSDT */ | 375 | /* Global integer width is based upon revision of the DSDT */ |
| 338 | 376 | ||
| 339 | acpi_ut_set_integer_width(table->revision); | 377 | acpi_ut_set_integer_width(table_to_install->revision); |
| 340 | } | 378 | } |
| 341 | 379 | ||
| 342 | unmap_and_exit: | 380 | unmap_and_exit: |
| 343 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); | 381 | acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header)); |
| 344 | } | 382 | } |
| 345 | 383 | ||
| 346 | /******************************************************************************* | 384 | /******************************************************************************* |
| @@ -379,7 +417,8 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) | |||
| 379 | } else { | 417 | } else { |
| 380 | /* | 418 | /* |
| 381 | * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return | 419 | * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return |
| 382 | * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit | 420 | * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, |
| 421 | * return 64-bit | ||
| 383 | */ | 422 | */ |
| 384 | ACPI_MOVE_64_TO_64(&address64, table_entry); | 423 | ACPI_MOVE_64_TO_64(&address64, table_entry); |
| 385 | 424 | ||
| @@ -389,7 +428,8 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) | |||
| 389 | /* Will truncate 64-bit address to 32 bits, issue warning */ | 428 | /* Will truncate 64-bit address to 32 bits, issue warning */ |
| 390 | 429 | ||
| 391 | ACPI_WARNING((AE_INFO, | 430 | ACPI_WARNING((AE_INFO, |
| 392 | "64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating", | 431 | "64-bit Physical Address in XSDT is too large (%8.8X%8.8X)," |
| 432 | " truncating", | ||
| 393 | ACPI_FORMAT_UINT64(address64))); | 433 | ACPI_FORMAT_UINT64(address64))); |
| 394 | } | 434 | } |
| 395 | #endif | 435 | #endif |
| @@ -402,7 +442,6 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) | |||
| 402 | * FUNCTION: acpi_tb_parse_root_table | 442 | * FUNCTION: acpi_tb_parse_root_table |
| 403 | * | 443 | * |
| 404 | * PARAMETERS: Rsdp - Pointer to the RSDP | 444 | * PARAMETERS: Rsdp - Pointer to the RSDP |
| 405 | * Flags - Flags | ||
| 406 | * | 445 | * |
| 407 | * RETURN: Status | 446 | * RETURN: Status |
| 408 | * | 447 | * |
| @@ -416,7 +455,7 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) | |||
| 416 | ******************************************************************************/ | 455 | ******************************************************************************/ |
| 417 | 456 | ||
| 418 | acpi_status __init | 457 | acpi_status __init |
| 419 | acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) | 458 | acpi_tb_parse_root_table(acpi_physical_address rsdp_address) |
| 420 | { | 459 | { |
| 421 | struct acpi_table_rsdp *rsdp; | 460 | struct acpi_table_rsdp *rsdp; |
| 422 | u32 table_entry_size; | 461 | u32 table_entry_size; |
| @@ -513,13 +552,12 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) | |||
| 513 | 552 | ||
| 514 | /* Calculate the number of tables described in the root table */ | 553 | /* Calculate the number of tables described in the root table */ |
| 515 | 554 | ||
| 516 | table_count = | 555 | table_count = (u32)((table->length - sizeof(struct acpi_table_header)) / |
| 517 | (u32) ((table->length - | 556 | table_entry_size); |
| 518 | sizeof(struct acpi_table_header)) / table_entry_size); | ||
| 519 | |||
| 520 | /* | 557 | /* |
| 521 | * First two entries in the table array are reserved for the DSDT and FACS, | 558 | * First two entries in the table array are reserved for the DSDT |
| 522 | * which are not actually present in the RSDT/XSDT - they come from the FADT | 559 | * and FACS, which are not actually present in the RSDT/XSDT - they |
| 560 | * come from the FADT | ||
| 523 | */ | 561 | */ |
| 524 | table_entry = | 562 | table_entry = |
| 525 | ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); | 563 | ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); |
| @@ -567,14 +605,14 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) | |||
| 567 | */ | 605 | */ |
| 568 | for (i = 2; i < acpi_gbl_root_table_list.count; i++) { | 606 | for (i = 2; i < acpi_gbl_root_table_list.count; i++) { |
| 569 | acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. | 607 | acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. |
| 570 | address, flags, NULL, i); | 608 | address, NULL, i); |
| 571 | 609 | ||
| 572 | /* Special case for FADT - get the DSDT and FACS */ | 610 | /* Special case for FADT - get the DSDT and FACS */ |
| 573 | 611 | ||
| 574 | if (ACPI_COMPARE_NAME | 612 | if (ACPI_COMPARE_NAME |
| 575 | (&acpi_gbl_root_table_list.tables[i].signature, | 613 | (&acpi_gbl_root_table_list.tables[i].signature, |
| 576 | ACPI_SIG_FADT)) { | 614 | ACPI_SIG_FADT)) { |
| 577 | acpi_tb_parse_fadt(i, flags); | 615 | acpi_tb_parse_fadt(i); |
| 578 | } | 616 | } |
| 579 | } | 617 | } |
| 580 | 618 | ||
