diff options
Diffstat (limited to 'drivers/acpi/acpica/tbutils.c')
-rw-r--r-- | drivers/acpi/acpica/tbutils.c | 285 |
1 files changed, 28 insertions, 257 deletions
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 9fb85f38de90..6b1ca9991b90 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c | |||
@@ -49,8 +49,6 @@ | |||
49 | ACPI_MODULE_NAME("tbutils") | 49 | ACPI_MODULE_NAME("tbutils") |
50 | 50 | ||
51 | /* Local prototypes */ | 51 | /* Local prototypes */ |
52 | static acpi_status acpi_tb_validate_xsdt(acpi_physical_address address); | ||
53 | |||
54 | static acpi_physical_address | 52 | static acpi_physical_address |
55 | acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); | 53 | acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); |
56 | 54 | ||
@@ -178,9 +176,13 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) | |||
178 | } | 176 | } |
179 | 177 | ||
180 | ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length); | 178 | ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length); |
181 | acpi_tb_delete_table(table_desc); | 179 | acpi_tb_uninstall_table(table_desc); |
182 | table_desc->pointer = new_table; | 180 | |
183 | table_desc->flags = ACPI_TABLE_ORIGIN_ALLOCATED; | 181 | acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list. |
182 | tables[ACPI_TABLE_INDEX_DSDT], | ||
183 | ACPI_PTR_TO_PHYSADDR(new_table), | ||
184 | ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, | ||
185 | new_table); | ||
184 | 186 | ||
185 | ACPI_INFO((AE_INFO, | 187 | ACPI_INFO((AE_INFO, |
186 | "Forced DSDT copy: length 0x%05X copied locally, original unmapped", | 188 | "Forced DSDT copy: length 0x%05X copied locally, original unmapped", |
@@ -191,116 +193,6 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) | |||
191 | 193 | ||
192 | /******************************************************************************* | 194 | /******************************************************************************* |
193 | * | 195 | * |
194 | * FUNCTION: acpi_tb_install_table | ||
195 | * | ||
196 | * PARAMETERS: address - Physical address of DSDT or FACS | ||
197 | * signature - Table signature, NULL if no need to | ||
198 | * match | ||
199 | * table_index - Index into root table array | ||
200 | * | ||
201 | * RETURN: None | ||
202 | * | ||
203 | * DESCRIPTION: Install an ACPI table into the global data structure. The | ||
204 | * table override mechanism is called to allow the host | ||
205 | * OS to replace any table before it is installed in the root | ||
206 | * table array. | ||
207 | * | ||
208 | ******************************************************************************/ | ||
209 | |||
210 | void | ||
211 | acpi_tb_install_table(acpi_physical_address address, | ||
212 | char *signature, u32 table_index) | ||
213 | { | ||
214 | struct acpi_table_header *table; | ||
215 | struct acpi_table_header *final_table; | ||
216 | struct acpi_table_desc *table_desc; | ||
217 | |||
218 | if (!address) { | ||
219 | ACPI_ERROR((AE_INFO, | ||
220 | "Null physical address for ACPI table [%s]", | ||
221 | signature)); | ||
222 | return; | ||
223 | } | ||
224 | |||
225 | /* Map just the table header */ | ||
226 | |||
227 | table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); | ||
228 | if (!table) { | ||
229 | ACPI_ERROR((AE_INFO, | ||
230 | "Could not map memory for table [%s] at %p", | ||
231 | signature, ACPI_CAST_PTR(void, address))); | ||
232 | return; | ||
233 | } | ||
234 | |||
235 | /* If a particular signature is expected (DSDT/FACS), it must match */ | ||
236 | |||
237 | if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) { | ||
238 | ACPI_BIOS_ERROR((AE_INFO, | ||
239 | "Invalid signature 0x%X for ACPI table, expected [%s]", | ||
240 | *ACPI_CAST_PTR(u32, table->signature), | ||
241 | signature)); | ||
242 | goto unmap_and_exit; | ||
243 | } | ||
244 | |||
245 | /* | ||
246 | * Initialize the table entry. Set the pointer to NULL, since the | ||
247 | * table is not fully mapped at this time. | ||
248 | */ | ||
249 | table_desc = &acpi_gbl_root_table_list.tables[table_index]; | ||
250 | |||
251 | table_desc->address = address; | ||
252 | table_desc->pointer = NULL; | ||
253 | table_desc->length = table->length; | ||
254 | table_desc->flags = ACPI_TABLE_ORIGIN_MAPPED; | ||
255 | ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature); | ||
256 | |||
257 | /* | ||
258 | * ACPI Table Override: | ||
259 | * | ||
260 | * Before we install the table, let the host OS override it with a new | ||
261 | * one if desired. Any table within the RSDT/XSDT can be replaced, | ||
262 | * including the DSDT which is pointed to by the FADT. | ||
263 | * | ||
264 | * NOTE: If the table is overridden, then final_table will contain a | ||
265 | * mapped pointer to the full new table. If the table is not overridden, | ||
266 | * or if there has been a physical override, then the table will be | ||
267 | * fully mapped later (in verify table). In any case, we must | ||
268 | * unmap the header that was mapped above. | ||
269 | */ | ||
270 | final_table = acpi_tb_table_override(table, table_desc); | ||
271 | if (!final_table) { | ||
272 | final_table = table; /* There was no override */ | ||
273 | } | ||
274 | |||
275 | acpi_tb_print_table_header(table_desc->address, final_table); | ||
276 | |||
277 | /* Set the global integer width (based upon revision of the DSDT) */ | ||
278 | |||
279 | if (table_index == ACPI_TABLE_INDEX_DSDT) { | ||
280 | acpi_ut_set_integer_width(final_table->revision); | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * If we have a physical override during this early loading of the ACPI | ||
285 | * tables, unmap the table for now. It will be mapped again later when | ||
286 | * it is actually used. This supports very early loading of ACPI tables, | ||
287 | * before virtual memory is fully initialized and running within the | ||
288 | * host OS. Note: A logical override has the ACPI_TABLE_ORIGIN_OVERRIDE | ||
289 | * flag set and will not be deleted below. | ||
290 | */ | ||
291 | if (final_table != table) { | ||
292 | acpi_tb_delete_table(table_desc); | ||
293 | } | ||
294 | |||
295 | unmap_and_exit: | ||
296 | |||
297 | /* Always unmap the table header that we mapped above */ | ||
298 | |||
299 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); | ||
300 | } | ||
301 | |||
302 | /******************************************************************************* | ||
303 | * | ||
304 | * FUNCTION: acpi_tb_get_root_table_entry | 196 | * FUNCTION: acpi_tb_get_root_table_entry |
305 | * | 197 | * |
306 | * PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry | 198 | * PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry |
@@ -357,87 +249,6 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) | |||
357 | 249 | ||
358 | /******************************************************************************* | 250 | /******************************************************************************* |
359 | * | 251 | * |
360 | * FUNCTION: acpi_tb_validate_xsdt | ||
361 | * | ||
362 | * PARAMETERS: address - Physical address of the XSDT (from RSDP) | ||
363 | * | ||
364 | * RETURN: Status. AE_OK if the table appears to be valid. | ||
365 | * | ||
366 | * DESCRIPTION: Validate an XSDT to ensure that it is of minimum size and does | ||
367 | * not contain any NULL entries. A problem that is seen in the | ||
368 | * field is that the XSDT exists, but is actually useless because | ||
369 | * of one or more (or all) NULL entries. | ||
370 | * | ||
371 | ******************************************************************************/ | ||
372 | |||
373 | static acpi_status acpi_tb_validate_xsdt(acpi_physical_address xsdt_address) | ||
374 | { | ||
375 | struct acpi_table_header *table; | ||
376 | u8 *next_entry; | ||
377 | acpi_physical_address address; | ||
378 | u32 length; | ||
379 | u32 entry_count; | ||
380 | acpi_status status; | ||
381 | u32 i; | ||
382 | |||
383 | /* Get the XSDT length */ | ||
384 | |||
385 | table = | ||
386 | acpi_os_map_memory(xsdt_address, sizeof(struct acpi_table_header)); | ||
387 | if (!table) { | ||
388 | return (AE_NO_MEMORY); | ||
389 | } | ||
390 | |||
391 | length = table->length; | ||
392 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); | ||
393 | |||
394 | /* | ||
395 | * Minimum XSDT length is the size of the standard ACPI header | ||
396 | * plus one physical address entry | ||
397 | */ | ||
398 | if (length < (sizeof(struct acpi_table_header) + ACPI_XSDT_ENTRY_SIZE)) { | ||
399 | return (AE_INVALID_TABLE_LENGTH); | ||
400 | } | ||
401 | |||
402 | /* Map the entire XSDT */ | ||
403 | |||
404 | table = acpi_os_map_memory(xsdt_address, length); | ||
405 | if (!table) { | ||
406 | return (AE_NO_MEMORY); | ||
407 | } | ||
408 | |||
409 | /* Get the number of entries and pointer to first entry */ | ||
410 | |||
411 | status = AE_OK; | ||
412 | next_entry = ACPI_ADD_PTR(u8, table, sizeof(struct acpi_table_header)); | ||
413 | entry_count = (u32)((table->length - sizeof(struct acpi_table_header)) / | ||
414 | ACPI_XSDT_ENTRY_SIZE); | ||
415 | |||
416 | /* Validate each entry (physical address) within the XSDT */ | ||
417 | |||
418 | for (i = 0; i < entry_count; i++) { | ||
419 | address = | ||
420 | acpi_tb_get_root_table_entry(next_entry, | ||
421 | ACPI_XSDT_ENTRY_SIZE); | ||
422 | if (!address) { | ||
423 | |||
424 | /* Detected a NULL entry, XSDT is invalid */ | ||
425 | |||
426 | status = AE_NULL_ENTRY; | ||
427 | break; | ||
428 | } | ||
429 | |||
430 | next_entry += ACPI_XSDT_ENTRY_SIZE; | ||
431 | } | ||
432 | |||
433 | /* Unmap table */ | ||
434 | |||
435 | acpi_os_unmap_memory(table, length); | ||
436 | return (status); | ||
437 | } | ||
438 | |||
439 | /******************************************************************************* | ||
440 | * | ||
441 | * FUNCTION: acpi_tb_parse_root_table | 252 | * FUNCTION: acpi_tb_parse_root_table |
442 | * | 253 | * |
443 | * PARAMETERS: rsdp - Pointer to the RSDP | 254 | * PARAMETERS: rsdp - Pointer to the RSDP |
@@ -461,10 +272,10 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) | |||
461 | u32 table_count; | 272 | u32 table_count; |
462 | struct acpi_table_header *table; | 273 | struct acpi_table_header *table; |
463 | acpi_physical_address address; | 274 | acpi_physical_address address; |
464 | acpi_physical_address rsdt_address; | ||
465 | u32 length; | 275 | u32 length; |
466 | u8 *table_entry; | 276 | u8 *table_entry; |
467 | acpi_status status; | 277 | acpi_status status; |
278 | u32 table_index; | ||
468 | 279 | ||
469 | ACPI_FUNCTION_TRACE(tb_parse_root_table); | 280 | ACPI_FUNCTION_TRACE(tb_parse_root_table); |
470 | 281 | ||
@@ -489,14 +300,11 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) | |||
489 | * as per the ACPI specification. | 300 | * as per the ACPI specification. |
490 | */ | 301 | */ |
491 | address = (acpi_physical_address) rsdp->xsdt_physical_address; | 302 | address = (acpi_physical_address) rsdp->xsdt_physical_address; |
492 | rsdt_address = | ||
493 | (acpi_physical_address) rsdp->rsdt_physical_address; | ||
494 | table_entry_size = ACPI_XSDT_ENTRY_SIZE; | 303 | table_entry_size = ACPI_XSDT_ENTRY_SIZE; |
495 | } else { | 304 | } else { |
496 | /* Root table is an RSDT (32-bit physical addresses) */ | 305 | /* Root table is an RSDT (32-bit physical addresses) */ |
497 | 306 | ||
498 | address = (acpi_physical_address) rsdp->rsdt_physical_address; | 307 | address = (acpi_physical_address) rsdp->rsdt_physical_address; |
499 | rsdt_address = address; | ||
500 | table_entry_size = ACPI_RSDT_ENTRY_SIZE; | 308 | table_entry_size = ACPI_RSDT_ENTRY_SIZE; |
501 | } | 309 | } |
502 | 310 | ||
@@ -506,24 +314,6 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) | |||
506 | */ | 314 | */ |
507 | acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); | 315 | acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); |
508 | 316 | ||
509 | /* | ||
510 | * If it is present and used, validate the XSDT for access/size | ||
511 | * and ensure that all table entries are at least non-NULL | ||
512 | */ | ||
513 | if (table_entry_size == ACPI_XSDT_ENTRY_SIZE) { | ||
514 | status = acpi_tb_validate_xsdt(address); | ||
515 | if (ACPI_FAILURE(status)) { | ||
516 | ACPI_BIOS_WARNING((AE_INFO, | ||
517 | "XSDT is invalid (%s), using RSDT", | ||
518 | acpi_format_exception(status))); | ||
519 | |||
520 | /* Fall back to the RSDT */ | ||
521 | |||
522 | address = rsdt_address; | ||
523 | table_entry_size = ACPI_RSDT_ENTRY_SIZE; | ||
524 | } | ||
525 | } | ||
526 | |||
527 | /* Map the RSDT/XSDT table header to get the full table length */ | 317 | /* Map the RSDT/XSDT table header to get the full table length */ |
528 | 318 | ||
529 | table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); | 319 | table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); |
@@ -576,55 +366,36 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) | |||
576 | /* Initialize the root table array from the RSDT/XSDT */ | 366 | /* Initialize the root table array from the RSDT/XSDT */ |
577 | 367 | ||
578 | for (i = 0; i < table_count; i++) { | 368 | for (i = 0; i < table_count; i++) { |
579 | if (acpi_gbl_root_table_list.current_table_count >= | ||
580 | acpi_gbl_root_table_list.max_table_count) { | ||
581 | |||
582 | /* There is no more room in the root table array, attempt resize */ | ||
583 | |||
584 | status = acpi_tb_resize_root_table_list(); | ||
585 | if (ACPI_FAILURE(status)) { | ||
586 | ACPI_WARNING((AE_INFO, | ||
587 | "Truncating %u table entries!", | ||
588 | (unsigned) (table_count - | ||
589 | (acpi_gbl_root_table_list. | ||
590 | current_table_count - | ||
591 | 2)))); | ||
592 | break; | ||
593 | } | ||
594 | } | ||
595 | 369 | ||
596 | /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ | 370 | /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ |
597 | 371 | ||
598 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list. | 372 | address = |
599 | current_table_count].address = | ||
600 | acpi_tb_get_root_table_entry(table_entry, table_entry_size); | 373 | acpi_tb_get_root_table_entry(table_entry, table_entry_size); |
601 | 374 | ||
602 | table_entry += table_entry_size; | 375 | /* Skip NULL entries in RSDT/XSDT */ |
603 | acpi_gbl_root_table_list.current_table_count++; | ||
604 | } | ||
605 | |||
606 | /* | ||
607 | * It is not possible to map more than one entry in some environments, | ||
608 | * so unmap the root table here before mapping other tables | ||
609 | */ | ||
610 | acpi_os_unmap_memory(table, length); | ||
611 | 376 | ||
612 | /* | 377 | if (!address) { |
613 | * Complete the initialization of the root table array by examining | 378 | goto next_table; |
614 | * the header of each table | 379 | } |
615 | */ | ||
616 | for (i = 2; i < acpi_gbl_root_table_list.current_table_count; i++) { | ||
617 | acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. | ||
618 | address, NULL, i); | ||
619 | 380 | ||
620 | /* Special case for FADT - validate it then get the DSDT and FACS */ | 381 | status = acpi_tb_install_standard_table(address, |
382 | ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, | ||
383 | FALSE, TRUE, | ||
384 | &table_index); | ||
621 | 385 | ||
622 | if (ACPI_COMPARE_NAME | 386 | if (ACPI_SUCCESS(status) && |
623 | (&acpi_gbl_root_table_list.tables[i].signature, | 387 | ACPI_COMPARE_NAME(&acpi_gbl_root_table_list. |
624 | ACPI_SIG_FADT)) { | 388 | tables[table_index].signature, |
625 | acpi_tb_parse_fadt(i); | 389 | ACPI_SIG_FADT)) { |
390 | acpi_tb_parse_fadt(table_index); | ||
626 | } | 391 | } |
392 | |||
393 | next_table: | ||
394 | |||
395 | table_entry += table_entry_size; | ||
627 | } | 396 | } |
628 | 397 | ||
398 | acpi_os_unmap_memory(table, length); | ||
399 | |||
629 | return_ACPI_STATUS(AE_OK); | 400 | return_ACPI_STATUS(AE_OK); |
630 | } | 401 | } |