diff options
Diffstat (limited to 'drivers/acpi/executer/exconfig.c')
-rw-r--r-- | drivers/acpi/executer/exconfig.c | 235 |
1 files changed, 66 insertions, 169 deletions
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index c8341fa5fe01..25802f302ffe 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2006, R. Byron Moore | 8 | * Copyright (C) 2000 - 2007, R. Byron Moore |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -54,7 +54,7 @@ ACPI_MODULE_NAME("exconfig") | |||
54 | 54 | ||
55 | /* Local prototypes */ | 55 | /* Local prototypes */ |
56 | static acpi_status | 56 | static acpi_status |
57 | acpi_ex_add_table(struct acpi_table_header *table, | 57 | acpi_ex_add_table(acpi_native_uint table_index, |
58 | struct acpi_namespace_node *parent_node, | 58 | struct acpi_namespace_node *parent_node, |
59 | union acpi_operand_object **ddb_handle); | 59 | union acpi_operand_object **ddb_handle); |
60 | 60 | ||
@@ -74,12 +74,11 @@ acpi_ex_add_table(struct acpi_table_header *table, | |||
74 | ******************************************************************************/ | 74 | ******************************************************************************/ |
75 | 75 | ||
76 | static acpi_status | 76 | static acpi_status |
77 | acpi_ex_add_table(struct acpi_table_header *table, | 77 | acpi_ex_add_table(acpi_native_uint table_index, |
78 | struct acpi_namespace_node *parent_node, | 78 | struct acpi_namespace_node *parent_node, |
79 | union acpi_operand_object **ddb_handle) | 79 | union acpi_operand_object **ddb_handle) |
80 | { | 80 | { |
81 | acpi_status status; | 81 | acpi_status status; |
82 | struct acpi_table_desc table_info; | ||
83 | union acpi_operand_object *obj_desc; | 82 | union acpi_operand_object *obj_desc; |
84 | 83 | ||
85 | ACPI_FUNCTION_TRACE(ex_add_table); | 84 | ACPI_FUNCTION_TRACE(ex_add_table); |
@@ -98,42 +97,16 @@ acpi_ex_add_table(struct acpi_table_header *table, | |||
98 | 97 | ||
99 | /* Install the new table into the local data structures */ | 98 | /* Install the new table into the local data structures */ |
100 | 99 | ||
101 | ACPI_MEMSET(&table_info, 0, sizeof(struct acpi_table_desc)); | 100 | obj_desc->reference.object = ACPI_CAST_PTR(void, table_index); |
102 | |||
103 | table_info.type = ACPI_TABLE_ID_SSDT; | ||
104 | table_info.pointer = table; | ||
105 | table_info.length = (acpi_size) table->length; | ||
106 | table_info.allocation = ACPI_MEM_ALLOCATED; | ||
107 | |||
108 | status = acpi_tb_install_table(&table_info); | ||
109 | obj_desc->reference.object = table_info.installed_desc; | ||
110 | |||
111 | if (ACPI_FAILURE(status)) { | ||
112 | if (status == AE_ALREADY_EXISTS) { | ||
113 | |||
114 | /* Table already exists, just return the handle */ | ||
115 | |||
116 | return_ACPI_STATUS(AE_OK); | ||
117 | } | ||
118 | goto cleanup; | ||
119 | } | ||
120 | 101 | ||
121 | /* Add the table to the namespace */ | 102 | /* Add the table to the namespace */ |
122 | 103 | ||
123 | status = acpi_ns_load_table(table_info.installed_desc, parent_node); | 104 | status = acpi_ns_load_table(table_index, parent_node); |
124 | if (ACPI_FAILURE(status)) { | 105 | if (ACPI_FAILURE(status)) { |
125 | 106 | acpi_ut_remove_reference(obj_desc); | |
126 | /* Uninstall table on error */ | 107 | *ddb_handle = NULL; |
127 | |||
128 | (void)acpi_tb_uninstall_table(table_info.installed_desc); | ||
129 | goto cleanup; | ||
130 | } | 108 | } |
131 | 109 | ||
132 | return_ACPI_STATUS(AE_OK); | ||
133 | |||
134 | cleanup: | ||
135 | acpi_ut_remove_reference(obj_desc); | ||
136 | *ddb_handle = NULL; | ||
137 | return_ACPI_STATUS(status); | 110 | return_ACPI_STATUS(status); |
138 | } | 111 | } |
139 | 112 | ||
@@ -146,7 +119,7 @@ acpi_ex_add_table(struct acpi_table_header *table, | |||
146 | * | 119 | * |
147 | * RETURN: Status | 120 | * RETURN: Status |
148 | * | 121 | * |
149 | * DESCRIPTION: Load an ACPI table | 122 | * DESCRIPTION: Load an ACPI table from the RSDT/XSDT |
150 | * | 123 | * |
151 | ******************************************************************************/ | 124 | ******************************************************************************/ |
152 | 125 | ||
@@ -156,33 +129,20 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
156 | { | 129 | { |
157 | acpi_status status; | 130 | acpi_status status; |
158 | union acpi_operand_object **operand = &walk_state->operands[0]; | 131 | union acpi_operand_object **operand = &walk_state->operands[0]; |
159 | struct acpi_table_header *table; | 132 | acpi_native_uint table_index; |
160 | struct acpi_namespace_node *parent_node; | 133 | struct acpi_namespace_node *parent_node; |
161 | struct acpi_namespace_node *start_node; | 134 | struct acpi_namespace_node *start_node; |
162 | struct acpi_namespace_node *parameter_node = NULL; | 135 | struct acpi_namespace_node *parameter_node = NULL; |
163 | union acpi_operand_object *ddb_handle; | 136 | union acpi_operand_object *ddb_handle; |
137 | struct acpi_table_header *table; | ||
164 | 138 | ||
165 | ACPI_FUNCTION_TRACE(ex_load_table_op); | 139 | ACPI_FUNCTION_TRACE(ex_load_table_op); |
166 | 140 | ||
167 | #if 0 | 141 | /* Find the ACPI table in the RSDT/XSDT */ |
168 | /* | ||
169 | * Make sure that the signature does not match one of the tables that | ||
170 | * is already loaded. | ||
171 | */ | ||
172 | status = acpi_tb_match_signature(operand[0]->string.pointer, NULL); | ||
173 | if (status == AE_OK) { | ||
174 | |||
175 | /* Signature matched -- don't allow override */ | ||
176 | |||
177 | return_ACPI_STATUS(AE_ALREADY_EXISTS); | ||
178 | } | ||
179 | #endif | ||
180 | |||
181 | /* Find the ACPI table */ | ||
182 | 142 | ||
183 | status = acpi_tb_find_table(operand[0]->string.pointer, | 143 | status = acpi_tb_find_table(operand[0]->string.pointer, |
184 | operand[1]->string.pointer, | 144 | operand[1]->string.pointer, |
185 | operand[2]->string.pointer, &table); | 145 | operand[2]->string.pointer, &table_index); |
186 | if (ACPI_FAILURE(status)) { | 146 | if (ACPI_FAILURE(status)) { |
187 | if (status != AE_NOT_FOUND) { | 147 | if (status != AE_NOT_FOUND) { |
188 | return_ACPI_STATUS(status); | 148 | return_ACPI_STATUS(status); |
@@ -245,7 +205,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
245 | 205 | ||
246 | /* Load the table into the namespace */ | 206 | /* Load the table into the namespace */ |
247 | 207 | ||
248 | status = acpi_ex_add_table(table, parent_node, &ddb_handle); | 208 | status = acpi_ex_add_table(table_index, parent_node, &ddb_handle); |
249 | if (ACPI_FAILURE(status)) { | 209 | if (ACPI_FAILURE(status)) { |
250 | return_ACPI_STATUS(status); | 210 | return_ACPI_STATUS(status); |
251 | } | 211 | } |
@@ -266,9 +226,13 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
266 | } | 226 | } |
267 | } | 227 | } |
268 | 228 | ||
269 | ACPI_INFO((AE_INFO, | 229 | status = acpi_get_table_by_index(table_index, &table); |
270 | "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]", | 230 | if (ACPI_SUCCESS(status)) { |
271 | table->signature, table->oem_id, table->oem_table_id)); | 231 | ACPI_INFO((AE_INFO, |
232 | "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]", | ||
233 | table->signature, table->oem_id, | ||
234 | table->oem_table_id)); | ||
235 | } | ||
272 | 236 | ||
273 | *return_desc = ddb_handle; | 237 | *return_desc = ddb_handle; |
274 | return_ACPI_STATUS(status); | 238 | return_ACPI_STATUS(status); |
@@ -278,7 +242,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
278 | * | 242 | * |
279 | * FUNCTION: acpi_ex_load_op | 243 | * FUNCTION: acpi_ex_load_op |
280 | * | 244 | * |
281 | * PARAMETERS: obj_desc - Region or Field where the table will be | 245 | * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be |
282 | * obtained | 246 | * obtained |
283 | * Target - Where a handle to the table will be stored | 247 | * Target - Where a handle to the table will be stored |
284 | * walk_state - Current state | 248 | * walk_state - Current state |
@@ -287,6 +251,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
287 | * | 251 | * |
288 | * DESCRIPTION: Load an ACPI table from a field or operation region | 252 | * DESCRIPTION: Load an ACPI table from a field or operation region |
289 | * | 253 | * |
254 | * NOTE: Region Fields (Field, bank_field, index_fields) are resolved to buffer | ||
255 | * objects before this code is reached. | ||
256 | * | ||
257 | * If source is an operation region, it must refer to system_memory, as | ||
258 | * per the ACPI specification. | ||
259 | * | ||
290 | ******************************************************************************/ | 260 | ******************************************************************************/ |
291 | 261 | ||
292 | acpi_status | 262 | acpi_status |
@@ -294,22 +264,26 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
294 | union acpi_operand_object *target, | 264 | union acpi_operand_object *target, |
295 | struct acpi_walk_state *walk_state) | 265 | struct acpi_walk_state *walk_state) |
296 | { | 266 | { |
297 | acpi_status status; | ||
298 | union acpi_operand_object *ddb_handle; | 267 | union acpi_operand_object *ddb_handle; |
299 | union acpi_operand_object *buffer_desc = NULL; | 268 | struct acpi_table_desc table_desc; |
300 | struct acpi_table_header *table_ptr = NULL; | 269 | acpi_native_uint table_index; |
301 | acpi_physical_address address; | 270 | acpi_status status; |
302 | struct acpi_table_header table_header; | ||
303 | acpi_integer temp; | ||
304 | u32 i; | ||
305 | 271 | ||
306 | ACPI_FUNCTION_TRACE(ex_load_op); | 272 | ACPI_FUNCTION_TRACE(ex_load_op); |
307 | 273 | ||
308 | /* Object can be either an op_region or a Field */ | 274 | ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); |
275 | |||
276 | /* Source Object can be either an op_region or a Buffer/Field */ | ||
309 | 277 | ||
310 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { | 278 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { |
311 | case ACPI_TYPE_REGION: | 279 | case ACPI_TYPE_REGION: |
312 | 280 | ||
281 | /* Region must be system_memory (from ACPI spec) */ | ||
282 | |||
283 | if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { | ||
284 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | ||
285 | } | ||
286 | |||
313 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", | 287 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", |
314 | obj_desc, | 288 | obj_desc, |
315 | acpi_ut_get_object_type_name(obj_desc))); | 289 | acpi_ut_get_object_type_name(obj_desc))); |
@@ -325,113 +299,41 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
325 | } | 299 | } |
326 | } | 300 | } |
327 | 301 | ||
328 | /* Get the base physical address of the region */ | 302 | table_desc.address = obj_desc->region.address; |
329 | 303 | table_desc.length = obj_desc->region.length; | |
330 | address = obj_desc->region.address; | 304 | table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; |
331 | |||
332 | /* Get part of the table header to get the table length */ | ||
333 | |||
334 | table_header.length = 0; | ||
335 | for (i = 0; i < 8; i++) { | ||
336 | status = | ||
337 | acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, | ||
338 | (acpi_physical_address) | ||
339 | (i + address), 8, | ||
340 | &temp); | ||
341 | if (ACPI_FAILURE(status)) { | ||
342 | return_ACPI_STATUS(status); | ||
343 | } | ||
344 | |||
345 | /* Get the one valid byte of the returned 64-bit value */ | ||
346 | |||
347 | ACPI_CAST_PTR(u8, &table_header)[i] = (u8) temp; | ||
348 | } | ||
349 | |||
350 | /* Sanity check the table length */ | ||
351 | |||
352 | if (table_header.length < sizeof(struct acpi_table_header)) { | ||
353 | return_ACPI_STATUS(AE_BAD_HEADER); | ||
354 | } | ||
355 | |||
356 | /* Allocate a buffer for the entire table */ | ||
357 | |||
358 | table_ptr = ACPI_ALLOCATE(table_header.length); | ||
359 | if (!table_ptr) { | ||
360 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
361 | } | ||
362 | |||
363 | /* Get the entire table from the op region */ | ||
364 | |||
365 | for (i = 0; i < table_header.length; i++) { | ||
366 | status = | ||
367 | acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, | ||
368 | (acpi_physical_address) | ||
369 | (i + address), 8, | ||
370 | &temp); | ||
371 | if (ACPI_FAILURE(status)) { | ||
372 | goto cleanup; | ||
373 | } | ||
374 | |||
375 | /* Get the one valid byte of the returned 64-bit value */ | ||
376 | |||
377 | ACPI_CAST_PTR(u8, table_ptr)[i] = (u8) temp; | ||
378 | } | ||
379 | break; | 305 | break; |
380 | 306 | ||
381 | case ACPI_TYPE_LOCAL_REGION_FIELD: | 307 | case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ |
382 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
383 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
384 | 308 | ||
385 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Field %p %s\n", | 309 | /* Simply extract the buffer from the buffer object */ |
386 | obj_desc, | ||
387 | acpi_ut_get_object_type_name(obj_desc))); | ||
388 | 310 | ||
389 | /* | 311 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
390 | * The length of the field must be at least as large as the table. | 312 | "Load from Buffer or Field %p %s\n", obj_desc, |
391 | * Read the entire field and thus the entire table. Buffer is | 313 | acpi_ut_get_object_type_name(obj_desc))); |
392 | * allocated during the read. | ||
393 | */ | ||
394 | status = | ||
395 | acpi_ex_read_data_from_field(walk_state, obj_desc, | ||
396 | &buffer_desc); | ||
397 | if (ACPI_FAILURE(status)) { | ||
398 | return_ACPI_STATUS(status); | ||
399 | } | ||
400 | |||
401 | table_ptr = ACPI_CAST_PTR(struct acpi_table_header, | ||
402 | buffer_desc->buffer.pointer); | ||
403 | |||
404 | /* All done with the buffer_desc, delete it */ | ||
405 | |||
406 | buffer_desc->buffer.pointer = NULL; | ||
407 | acpi_ut_remove_reference(buffer_desc); | ||
408 | 314 | ||
409 | /* Sanity check the table length */ | 315 | table_desc.pointer = ACPI_CAST_PTR(struct acpi_table_header, |
316 | obj_desc->buffer.pointer); | ||
317 | table_desc.length = table_desc.pointer->length; | ||
318 | table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; | ||
410 | 319 | ||
411 | if (table_ptr->length < sizeof(struct acpi_table_header)) { | 320 | obj_desc->buffer.pointer = NULL; |
412 | status = AE_BAD_HEADER; | ||
413 | goto cleanup; | ||
414 | } | ||
415 | break; | 321 | break; |
416 | 322 | ||
417 | default: | 323 | default: |
418 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | 324 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
419 | } | 325 | } |
420 | 326 | ||
421 | /* The table must be either an SSDT or a PSDT */ | 327 | /* |
422 | 328 | * Install the new table into the local data structures | |
423 | if ((!ACPI_COMPARE_NAME(table_ptr->signature, PSDT_SIG)) && | 329 | */ |
424 | (!ACPI_COMPARE_NAME(table_ptr->signature, SSDT_SIG))) { | 330 | status = acpi_tb_add_table(&table_desc, &table_index); |
425 | ACPI_ERROR((AE_INFO, | 331 | if (ACPI_FAILURE(status)) { |
426 | "Table has invalid signature [%4.4s], must be SSDT or PSDT", | ||
427 | table_ptr->signature)); | ||
428 | status = AE_BAD_SIGNATURE; | ||
429 | goto cleanup; | 332 | goto cleanup; |
430 | } | 333 | } |
431 | 334 | ||
432 | /* Install the new table into the local data structures */ | 335 | status = |
433 | 336 | acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); | |
434 | status = acpi_ex_add_table(table_ptr, acpi_gbl_root_node, &ddb_handle); | ||
435 | if (ACPI_FAILURE(status)) { | 337 | if (ACPI_FAILURE(status)) { |
436 | 338 | ||
437 | /* On error, table_ptr was deallocated above */ | 339 | /* On error, table_ptr was deallocated above */ |
@@ -450,13 +352,9 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
450 | return_ACPI_STATUS(status); | 352 | return_ACPI_STATUS(status); |
451 | } | 353 | } |
452 | 354 | ||
453 | ACPI_INFO((AE_INFO, | ||
454 | "Dynamic SSDT Load - OemId [%6.6s] OemTableId [%8.8s]", | ||
455 | table_ptr->oem_id, table_ptr->oem_table_id)); | ||
456 | |||
457 | cleanup: | 355 | cleanup: |
458 | if (ACPI_FAILURE(status)) { | 356 | if (ACPI_FAILURE(status)) { |
459 | ACPI_FREE(table_ptr); | 357 | acpi_tb_delete_table(&table_desc); |
460 | } | 358 | } |
461 | return_ACPI_STATUS(status); | 359 | return_ACPI_STATUS(status); |
462 | } | 360 | } |
@@ -477,7 +375,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) | |||
477 | { | 375 | { |
478 | acpi_status status = AE_OK; | 376 | acpi_status status = AE_OK; |
479 | union acpi_operand_object *table_desc = ddb_handle; | 377 | union acpi_operand_object *table_desc = ddb_handle; |
480 | struct acpi_table_desc *table_info; | 378 | acpi_native_uint table_index; |
481 | 379 | ||
482 | ACPI_FUNCTION_TRACE(ex_unload_table); | 380 | ACPI_FUNCTION_TRACE(ex_unload_table); |
483 | 381 | ||
@@ -493,19 +391,18 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) | |||
493 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 391 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
494 | } | 392 | } |
495 | 393 | ||
496 | /* Get the actual table descriptor from the ddb_handle */ | 394 | /* Get the table index from the ddb_handle */ |
497 | 395 | ||
498 | table_info = (struct acpi_table_desc *)table_desc->reference.object; | 396 | table_index = (acpi_native_uint) table_desc->reference.object; |
499 | 397 | ||
500 | /* | 398 | /* |
501 | * Delete the entire namespace under this table Node | 399 | * Delete the entire namespace under this table Node |
502 | * (Offset contains the table_id) | 400 | * (Offset contains the table_id) |
503 | */ | 401 | */ |
504 | acpi_ns_delete_namespace_by_owner(table_info->owner_id); | 402 | acpi_tb_delete_namespace_by_owner(table_index); |
505 | 403 | acpi_tb_release_owner_id(table_index); | |
506 | /* Delete the table itself */ | ||
507 | 404 | ||
508 | (void)acpi_tb_uninstall_table(table_info->installed_desc); | 405 | acpi_tb_set_table_loaded_flag(table_index, FALSE); |
509 | 406 | ||
510 | /* Delete the table descriptor (ddb_handle) */ | 407 | /* Delete the table descriptor (ddb_handle) */ |
511 | 408 | ||