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 | ||