1 /******************************************************************************
3 * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes)
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2007, R. Byron Moore
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/amlcode.h>
47 #include <acpi/acnamesp.h>
48 #include <acpi/acevents.h>
49 #include <acpi/actables.h>
50 #include <acpi/acdispat.h>
52 #define _COMPONENT ACPI_EXECUTER
53 ACPI_MODULE_NAME("exconfig")
55 /* Local prototypes */
57 acpi_ex_add_table(acpi_native_uint table_index
,
58 struct acpi_namespace_node
*parent_node
,
59 union acpi_operand_object
**ddb_handle
);
61 /*******************************************************************************
63 * FUNCTION: acpi_ex_add_table
65 * PARAMETERS: Table - Pointer to raw table
66 * parent_node - Where to load the table (scope)
67 * ddb_handle - Where to return the table handle.
71 * DESCRIPTION: Common function to Install and Load an ACPI table with a
72 * returned table handle.
74 ******************************************************************************/
77 acpi_ex_add_table(acpi_native_uint table_index
,
78 struct acpi_namespace_node
*parent_node
,
79 union acpi_operand_object
**ddb_handle
)
82 union acpi_operand_object
*obj_desc
;
84 ACPI_FUNCTION_TRACE(ex_add_table
);
86 /* Create an object to be the table handle */
88 obj_desc
= acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE
);
90 return_ACPI_STATUS(AE_NO_MEMORY
);
93 /* Init the table handle */
95 obj_desc
->reference
.opcode
= AML_LOAD_OP
;
96 *ddb_handle
= obj_desc
;
98 /* Install the new table into the local data structures */
100 obj_desc
->reference
.object
= ACPI_CAST_PTR(void, table_index
);
102 /* Add the table to the namespace */
104 status
= acpi_ns_load_table(table_index
, parent_node
);
105 if (ACPI_FAILURE(status
)) {
106 acpi_ut_remove_reference(obj_desc
);
110 return_ACPI_STATUS(status
);
113 /*******************************************************************************
115 * FUNCTION: acpi_ex_load_table_op
117 * PARAMETERS: walk_state - Current state with operands
118 * return_desc - Where to store the return object
122 * DESCRIPTION: Load an ACPI table from the RSDT/XSDT
124 ******************************************************************************/
127 acpi_ex_load_table_op(struct acpi_walk_state
*walk_state
,
128 union acpi_operand_object
**return_desc
)
131 union acpi_operand_object
**operand
= &walk_state
->operands
[0];
132 acpi_native_uint table_index
;
133 struct acpi_namespace_node
*parent_node
;
134 struct acpi_namespace_node
*start_node
;
135 struct acpi_namespace_node
*parameter_node
= NULL
;
136 union acpi_operand_object
*ddb_handle
;
137 struct acpi_table_header
*table
;
139 ACPI_FUNCTION_TRACE(ex_load_table_op
);
141 /* Find the ACPI table in the RSDT/XSDT */
143 status
= acpi_tb_find_table(operand
[0]->string
.pointer
,
144 operand
[1]->string
.pointer
,
145 operand
[2]->string
.pointer
, &table_index
);
146 if (ACPI_FAILURE(status
)) {
147 if (status
!= AE_NOT_FOUND
) {
148 return_ACPI_STATUS(status
);
151 /* Table not found, return an Integer=0 and AE_OK */
153 ddb_handle
= acpi_ut_create_internal_object(ACPI_TYPE_INTEGER
);
155 return_ACPI_STATUS(AE_NO_MEMORY
);
158 ddb_handle
->integer
.value
= 0;
159 *return_desc
= ddb_handle
;
161 return_ACPI_STATUS(AE_OK
);
166 start_node
= walk_state
->scope_info
->scope
.node
;
167 parent_node
= acpi_gbl_root_node
;
169 /* root_path (optional parameter) */
171 if (operand
[3]->string
.length
> 0) {
173 * Find the node referenced by the root_path_string. This is the
174 * location within the namespace where the table will be loaded.
177 acpi_ns_get_node(start_node
, operand
[3]->string
.pointer
,
178 ACPI_NS_SEARCH_PARENT
, &parent_node
);
179 if (ACPI_FAILURE(status
)) {
180 return_ACPI_STATUS(status
);
184 /* parameter_path (optional parameter) */
186 if (operand
[4]->string
.length
> 0) {
187 if ((operand
[4]->string
.pointer
[0] != '\\') &&
188 (operand
[4]->string
.pointer
[0] != '^')) {
190 * Path is not absolute, so it will be relative to the node
191 * referenced by the root_path_string (or the NS root if omitted)
193 start_node
= parent_node
;
196 /* Find the node referenced by the parameter_path_string */
199 acpi_ns_get_node(start_node
, operand
[4]->string
.pointer
,
200 ACPI_NS_SEARCH_PARENT
, ¶meter_node
);
201 if (ACPI_FAILURE(status
)) {
202 return_ACPI_STATUS(status
);
206 /* Load the table into the namespace */
208 status
= acpi_ex_add_table(table_index
, parent_node
, &ddb_handle
);
209 if (ACPI_FAILURE(status
)) {
210 return_ACPI_STATUS(status
);
213 /* Parameter Data (optional) */
215 if (parameter_node
) {
217 /* Store the parameter data into the optional parameter object */
219 status
= acpi_ex_store(operand
[5],
220 ACPI_CAST_PTR(union acpi_operand_object
,
223 if (ACPI_FAILURE(status
)) {
224 (void)acpi_ex_unload_table(ddb_handle
);
225 return_ACPI_STATUS(status
);
229 status
= acpi_get_table_by_index(table_index
, &table
);
230 if (ACPI_SUCCESS(status
)) {
232 "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]",
233 table
->signature
, table
->oem_id
,
234 table
->oem_table_id
));
237 *return_desc
= ddb_handle
;
238 return_ACPI_STATUS(status
);
241 /*******************************************************************************
243 * FUNCTION: acpi_ex_load_op
245 * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be
247 * Target - Where a handle to the table will be stored
248 * walk_state - Current state
252 * DESCRIPTION: Load an ACPI table from a field or operation region
254 * NOTE: Region Fields (Field, bank_field, index_fields) are resolved to buffer
255 * objects before this code is reached.
257 * If source is an operation region, it must refer to system_memory, as
258 * per the ACPI specification.
260 ******************************************************************************/
263 acpi_ex_load_op(union acpi_operand_object
*obj_desc
,
264 union acpi_operand_object
*target
,
265 struct acpi_walk_state
*walk_state
)
267 union acpi_operand_object
*ddb_handle
;
268 struct acpi_table_desc table_desc
;
269 acpi_native_uint table_index
;
272 ACPI_FUNCTION_TRACE(ex_load_op
);
274 ACPI_MEMSET(&table_desc
, 0, sizeof(struct acpi_table_desc
));
276 /* Source Object can be either an op_region or a Buffer/Field */
278 switch (ACPI_GET_OBJECT_TYPE(obj_desc
)) {
279 case ACPI_TYPE_REGION
:
281 /* Region must be system_memory (from ACPI spec) */
283 if (obj_desc
->region
.space_id
!= ACPI_ADR_SPACE_SYSTEM_MEMORY
) {
284 return_ACPI_STATUS(AE_AML_OPERAND_TYPE
);
287 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
, "Load from Region %p %s\n",
289 acpi_ut_get_object_type_name(obj_desc
)));
292 * If the Region Address and Length have not been previously evaluated,
293 * evaluate them now and save the results.
295 if (!(obj_desc
->common
.flags
& AOPOBJ_DATA_VALID
)) {
296 status
= acpi_ds_get_region_arguments(obj_desc
);
297 if (ACPI_FAILURE(status
)) {
298 return_ACPI_STATUS(status
);
302 table_desc
.address
= obj_desc
->region
.address
;
303 table_desc
.length
= obj_desc
->region
.length
;
304 table_desc
.flags
= ACPI_TABLE_ORIGIN_MAPPED
;
307 case ACPI_TYPE_BUFFER
: /* Buffer or resolved region_field */
309 /* Simply extract the buffer from the buffer object */
311 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
,
312 "Load from Buffer or Field %p %s\n", obj_desc
,
313 acpi_ut_get_object_type_name(obj_desc
)));
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
;
320 obj_desc
->buffer
.pointer
= NULL
;
324 return_ACPI_STATUS(AE_AML_OPERAND_TYPE
);
328 * Install the new table into the local data structures
330 status
= acpi_tb_add_table(&table_desc
, &table_index
);
331 if (ACPI_FAILURE(status
)) {
336 acpi_ex_add_table(table_index
, acpi_gbl_root_node
, &ddb_handle
);
337 if (ACPI_FAILURE(status
)) {
339 /* On error, table_ptr was deallocated above */
341 return_ACPI_STATUS(status
);
344 /* Store the ddb_handle into the Target operand */
346 status
= acpi_ex_store(ddb_handle
, target
, walk_state
);
347 if (ACPI_FAILURE(status
)) {
348 (void)acpi_ex_unload_table(ddb_handle
);
350 /* table_ptr was deallocated above */
352 return_ACPI_STATUS(status
);
356 if (ACPI_FAILURE(status
)) {
357 acpi_tb_delete_table(&table_desc
);
359 return_ACPI_STATUS(status
);
362 /*******************************************************************************
364 * FUNCTION: acpi_ex_unload_table
366 * PARAMETERS: ddb_handle - Handle to a previously loaded table
370 * DESCRIPTION: Unload an ACPI table
372 ******************************************************************************/
374 acpi_status
acpi_ex_unload_table(union acpi_operand_object
*ddb_handle
)
376 acpi_status status
= AE_OK
;
377 union acpi_operand_object
*table_desc
= ddb_handle
;
378 acpi_native_uint table_index
;
380 ACPI_FUNCTION_TRACE(ex_unload_table
);
383 * Validate the handle
384 * Although the handle is partially validated in acpi_ex_reconfiguration(),
385 * when it calls acpi_ex_resolve_operands(), the handle is more completely
389 (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle
) != ACPI_DESC_TYPE_OPERAND
) ||
390 (ACPI_GET_OBJECT_TYPE(ddb_handle
) != ACPI_TYPE_LOCAL_REFERENCE
)) {
391 return_ACPI_STATUS(AE_BAD_PARAMETER
);
394 /* Get the table index from the ddb_handle */
396 table_index
= (acpi_native_uint
) table_desc
->reference
.object
;
399 * Delete the entire namespace under this table Node
400 * (Offset contains the table_id)
402 acpi_tb_delete_namespace_by_owner(table_index
);
403 acpi_tb_release_owner_id(table_index
);
405 acpi_tb_set_table_loaded_flag(table_index
, FALSE
);
407 /* Delete the table descriptor (ddb_handle) */
409 acpi_ut_remove_reference(table_desc
);
410 return_ACPI_STATUS(status
);