1 /******************************************************************************
3 * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes)
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2008, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
44 #include <acpi/acpi.h>
45 #include <acpi/acinterp.h>
46 #include <acpi/acnamesp.h>
47 #include <acpi/actables.h>
48 #include <acpi/acdispat.h>
50 #define _COMPONENT ACPI_EXECUTER
51 ACPI_MODULE_NAME("exconfig")
53 /* Local prototypes */
55 acpi_ex_add_table(u32 table_index
,
56 struct acpi_namespace_node
*parent_node
,
57 union acpi_operand_object
**ddb_handle
);
59 /*******************************************************************************
61 * FUNCTION: acpi_ex_add_table
63 * PARAMETERS: Table - Pointer to raw table
64 * parent_node - Where to load the table (scope)
65 * ddb_handle - Where to return the table handle.
69 * DESCRIPTION: Common function to Install and Load an ACPI table with a
70 * returned table handle.
72 ******************************************************************************/
75 acpi_ex_add_table(u32 table_index
,
76 struct acpi_namespace_node
*parent_node
,
77 union acpi_operand_object
**ddb_handle
)
80 union acpi_operand_object
*obj_desc
;
82 ACPI_FUNCTION_TRACE(ex_add_table
);
84 /* Create an object to be the table handle */
86 obj_desc
= acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE
);
88 return_ACPI_STATUS(AE_NO_MEMORY
);
91 /* Init the table handle */
93 obj_desc
->reference
.class = ACPI_REFCLASS_TABLE
;
94 *ddb_handle
= obj_desc
;
96 /* Install the new table into the local data structures */
98 obj_desc
->reference
.value
= table_index
;
100 /* Add the table to the namespace */
102 status
= acpi_ns_load_table(table_index
, parent_node
);
103 if (ACPI_FAILURE(status
)) {
104 acpi_ut_remove_reference(obj_desc
);
108 return_ACPI_STATUS(status
);
111 /*******************************************************************************
113 * FUNCTION: acpi_ex_load_table_op
115 * PARAMETERS: walk_state - Current state with operands
116 * return_desc - Where to store the return object
120 * DESCRIPTION: Load an ACPI table from the RSDT/XSDT
122 ******************************************************************************/
125 acpi_ex_load_table_op(struct acpi_walk_state
*walk_state
,
126 union acpi_operand_object
**return_desc
)
129 union acpi_operand_object
**operand
= &walk_state
->operands
[0];
130 struct acpi_namespace_node
*parent_node
;
131 struct acpi_namespace_node
*start_node
;
132 struct acpi_namespace_node
*parameter_node
= NULL
;
133 union acpi_operand_object
*ddb_handle
;
134 struct acpi_table_header
*table
;
137 ACPI_FUNCTION_TRACE(ex_load_table_op
);
139 /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */
141 if ((operand
[0]->string
.length
> ACPI_NAME_SIZE
) ||
142 (operand
[1]->string
.length
> ACPI_OEM_ID_SIZE
) ||
143 (operand
[2]->string
.length
> ACPI_OEM_TABLE_ID_SIZE
)) {
144 return_ACPI_STATUS(AE_BAD_PARAMETER
);
147 /* Find the ACPI table in the RSDT/XSDT */
149 status
= acpi_tb_find_table(operand
[0]->string
.pointer
,
150 operand
[1]->string
.pointer
,
151 operand
[2]->string
.pointer
, &table_index
);
152 if (ACPI_FAILURE(status
)) {
153 if (status
!= AE_NOT_FOUND
) {
154 return_ACPI_STATUS(status
);
157 /* Table not found, return an Integer=0 and AE_OK */
159 ddb_handle
= acpi_ut_create_internal_object(ACPI_TYPE_INTEGER
);
161 return_ACPI_STATUS(AE_NO_MEMORY
);
164 ddb_handle
->integer
.value
= 0;
165 *return_desc
= ddb_handle
;
167 return_ACPI_STATUS(AE_OK
);
172 start_node
= walk_state
->scope_info
->scope
.node
;
173 parent_node
= acpi_gbl_root_node
;
175 /* root_path (optional parameter) */
177 if (operand
[3]->string
.length
> 0) {
179 * Find the node referenced by the root_path_string. This is the
180 * location within the namespace where the table will be loaded.
183 acpi_ns_get_node(start_node
, operand
[3]->string
.pointer
,
184 ACPI_NS_SEARCH_PARENT
, &parent_node
);
185 if (ACPI_FAILURE(status
)) {
186 return_ACPI_STATUS(status
);
190 /* parameter_path (optional parameter) */
192 if (operand
[4]->string
.length
> 0) {
193 if ((operand
[4]->string
.pointer
[0] != '\\') &&
194 (operand
[4]->string
.pointer
[0] != '^')) {
196 * Path is not absolute, so it will be relative to the node
197 * referenced by the root_path_string (or the NS root if omitted)
199 start_node
= parent_node
;
202 /* Find the node referenced by the parameter_path_string */
205 acpi_ns_get_node(start_node
, operand
[4]->string
.pointer
,
206 ACPI_NS_SEARCH_PARENT
, ¶meter_node
);
207 if (ACPI_FAILURE(status
)) {
208 return_ACPI_STATUS(status
);
212 /* Load the table into the namespace */
214 status
= acpi_ex_add_table(table_index
, parent_node
, &ddb_handle
);
215 if (ACPI_FAILURE(status
)) {
216 return_ACPI_STATUS(status
);
219 /* Parameter Data (optional) */
221 if (parameter_node
) {
223 /* Store the parameter data into the optional parameter object */
225 status
= acpi_ex_store(operand
[5],
226 ACPI_CAST_PTR(union acpi_operand_object
,
229 if (ACPI_FAILURE(status
)) {
230 (void)acpi_ex_unload_table(ddb_handle
);
231 return_ACPI_STATUS(status
);
235 status
= acpi_get_table_by_index(table_index
, &table
);
236 if (ACPI_SUCCESS(status
)) {
238 "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]",
239 table
->signature
, table
->oem_id
,
240 table
->oem_table_id
));
243 /* Invoke table handler if present */
245 if (acpi_gbl_table_handler
) {
246 (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD
, table
,
247 acpi_gbl_table_handler_context
);
250 *return_desc
= ddb_handle
;
251 return_ACPI_STATUS(status
);
254 /*******************************************************************************
256 * FUNCTION: acpi_ex_load_op
258 * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be
260 * Target - Where a handle to the table will be stored
261 * walk_state - Current state
265 * DESCRIPTION: Load an ACPI table from a field or operation region
267 * NOTE: Region Fields (Field, bank_field, index_fields) are resolved to buffer
268 * objects before this code is reached.
270 * If source is an operation region, it must refer to system_memory, as
271 * per the ACPI specification.
273 ******************************************************************************/
276 acpi_ex_load_op(union acpi_operand_object
*obj_desc
,
277 union acpi_operand_object
*target
,
278 struct acpi_walk_state
*walk_state
)
280 union acpi_operand_object
*ddb_handle
;
281 struct acpi_table_header
*table
;
282 struct acpi_table_desc table_desc
;
287 ACPI_FUNCTION_TRACE(ex_load_op
);
289 ACPI_MEMSET(&table_desc
, 0, sizeof(struct acpi_table_desc
));
291 /* Source Object can be either an op_region or a Buffer/Field */
293 switch (ACPI_GET_OBJECT_TYPE(obj_desc
)) {
294 case ACPI_TYPE_REGION
:
296 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
,
297 "Load table from Region %p\n", obj_desc
));
299 /* Region must be system_memory (from ACPI spec) */
301 if (obj_desc
->region
.space_id
!= ACPI_ADR_SPACE_SYSTEM_MEMORY
) {
302 return_ACPI_STATUS(AE_AML_OPERAND_TYPE
);
306 * If the Region Address and Length have not been previously evaluated,
307 * evaluate them now and save the results.
309 if (!(obj_desc
->common
.flags
& AOPOBJ_DATA_VALID
)) {
310 status
= acpi_ds_get_region_arguments(obj_desc
);
311 if (ACPI_FAILURE(status
)) {
312 return_ACPI_STATUS(status
);
317 * Map the table header and get the actual table length. The region
318 * length is not guaranteed to be the same as the table length.
320 table
= acpi_os_map_memory(obj_desc
->region
.address
,
321 sizeof(struct acpi_table_header
));
323 return_ACPI_STATUS(AE_NO_MEMORY
);
326 length
= table
->length
;
327 acpi_os_unmap_memory(table
, sizeof(struct acpi_table_header
));
329 /* Must have at least an ACPI table header */
331 if (length
< sizeof(struct acpi_table_header
)) {
332 return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH
);
336 * The memory region is not guaranteed to remain stable and we must
337 * copy the table to a local buffer. For example, the memory region
338 * is corrupted after suspend on some machines. Dynamically loaded
339 * tables are usually small, so this overhead is minimal.
342 /* Allocate a buffer for the table */
344 table_desc
.pointer
= ACPI_ALLOCATE(length
);
345 if (!table_desc
.pointer
) {
346 return_ACPI_STATUS(AE_NO_MEMORY
);
349 /* Map the entire table and copy it */
351 table
= acpi_os_map_memory(obj_desc
->region
.address
, length
);
353 ACPI_FREE(table_desc
.pointer
);
354 return_ACPI_STATUS(AE_NO_MEMORY
);
357 ACPI_MEMCPY(table_desc
.pointer
, table
, length
);
358 acpi_os_unmap_memory(table
, length
);
360 table_desc
.address
= obj_desc
->region
.address
;
363 case ACPI_TYPE_BUFFER
: /* Buffer or resolved region_field */
365 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
,
366 "Load table from Buffer or Field %p\n",
369 /* Must have at least an ACPI table header */
371 if (obj_desc
->buffer
.length
< sizeof(struct acpi_table_header
)) {
372 return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH
);
375 /* Get the actual table length from the table header */
378 ACPI_CAST_PTR(struct acpi_table_header
,
379 obj_desc
->buffer
.pointer
);
380 length
= table
->length
;
382 /* Table cannot extend beyond the buffer */
384 if (length
> obj_desc
->buffer
.length
) {
385 return_ACPI_STATUS(AE_AML_BUFFER_LIMIT
);
387 if (length
< sizeof(struct acpi_table_header
)) {
388 return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH
);
392 * Copy the table from the buffer because the buffer could be modified
393 * or even deleted in the future
395 table_desc
.pointer
= ACPI_ALLOCATE(length
);
396 if (!table_desc
.pointer
) {
397 return_ACPI_STATUS(AE_NO_MEMORY
);
400 ACPI_MEMCPY(table_desc
.pointer
, table
, length
);
401 table_desc
.address
= ACPI_TO_INTEGER(table_desc
.pointer
);
405 return_ACPI_STATUS(AE_AML_OPERAND_TYPE
);
408 /* Validate table checksum (will not get validated in tb_add_table) */
410 status
= acpi_tb_verify_checksum(table_desc
.pointer
, length
);
411 if (ACPI_FAILURE(status
)) {
412 ACPI_FREE(table_desc
.pointer
);
413 return_ACPI_STATUS(status
);
416 /* Complete the table descriptor */
418 table_desc
.length
= length
;
419 table_desc
.flags
= ACPI_TABLE_ORIGIN_ALLOCATED
;
421 /* Install the new table into the local data structures */
423 status
= acpi_tb_add_table(&table_desc
, &table_index
);
424 if (ACPI_FAILURE(status
)) {
429 * Add the table to the namespace.
431 * Note: Load the table objects relative to the root of the namespace.
432 * This appears to go against the ACPI specification, but we do it for
433 * compatibility with other ACPI implementations.
436 acpi_ex_add_table(table_index
, acpi_gbl_root_node
, &ddb_handle
);
437 if (ACPI_FAILURE(status
)) {
439 /* On error, table_ptr was deallocated above */
441 return_ACPI_STATUS(status
);
444 /* Store the ddb_handle into the Target operand */
446 status
= acpi_ex_store(ddb_handle
, target
, walk_state
);
447 if (ACPI_FAILURE(status
)) {
448 (void)acpi_ex_unload_table(ddb_handle
);
450 /* table_ptr was deallocated above */
452 acpi_ut_remove_reference(ddb_handle
);
453 return_ACPI_STATUS(status
);
456 /* Invoke table handler if present */
458 if (acpi_gbl_table_handler
) {
459 (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD
,
461 acpi_gbl_table_handler_context
);
465 if (ACPI_FAILURE(status
)) {
467 /* Delete allocated table buffer */
469 acpi_tb_delete_table(&table_desc
);
471 return_ACPI_STATUS(status
);
474 /*******************************************************************************
476 * FUNCTION: acpi_ex_unload_table
478 * PARAMETERS: ddb_handle - Handle to a previously loaded table
482 * DESCRIPTION: Unload an ACPI table
484 ******************************************************************************/
486 acpi_status
acpi_ex_unload_table(union acpi_operand_object
*ddb_handle
)
488 acpi_status status
= AE_OK
;
489 union acpi_operand_object
*table_desc
= ddb_handle
;
491 struct acpi_table_header
*table
;
493 ACPI_FUNCTION_TRACE(ex_unload_table
);
496 * Validate the handle
497 * Although the handle is partially validated in acpi_ex_reconfiguration(),
498 * when it calls acpi_ex_resolve_operands(), the handle is more completely
502 (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle
) != ACPI_DESC_TYPE_OPERAND
) ||
503 (ACPI_GET_OBJECT_TYPE(ddb_handle
) != ACPI_TYPE_LOCAL_REFERENCE
)) {
504 return_ACPI_STATUS(AE_BAD_PARAMETER
);
507 /* Get the table index from the ddb_handle */
509 table_index
= table_desc
->reference
.value
;
511 /* Invoke table handler if present */
513 if (acpi_gbl_table_handler
) {
514 status
= acpi_get_table_by_index(table_index
, &table
);
515 if (ACPI_SUCCESS(status
)) {
516 (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD
,
518 acpi_gbl_table_handler_context
);
523 * Delete the entire namespace under this table Node
524 * (Offset contains the table_id)
526 acpi_tb_delete_namespace_by_owner(table_index
);
527 (void)acpi_tb_release_owner_id(table_index
);
529 acpi_tb_set_table_loaded_flag(table_index
, FALSE
);
531 /* Table unloaded, remove a reference to the ddb_handle object */
533 acpi_ut_remove_reference(ddb_handle
);
534 return_ACPI_STATUS(AE_OK
);