Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.23-rc6 411 lines 12 kB view raw
1/****************************************************************************** 2 * 3 * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes) 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2007, R. Byron Moore 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 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. 25 * 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. 29 * 30 * NO WARRANTY 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. 42 */ 43 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> 51 52#define _COMPONENT ACPI_EXECUTER 53ACPI_MODULE_NAME("exconfig") 54 55/* Local prototypes */ 56static acpi_status 57acpi_ex_add_table(acpi_native_uint table_index, 58 struct acpi_namespace_node *parent_node, 59 union acpi_operand_object **ddb_handle); 60 61/******************************************************************************* 62 * 63 * FUNCTION: acpi_ex_add_table 64 * 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. 68 * 69 * RETURN: Status 70 * 71 * DESCRIPTION: Common function to Install and Load an ACPI table with a 72 * returned table handle. 73 * 74 ******************************************************************************/ 75 76static acpi_status 77acpi_ex_add_table(acpi_native_uint table_index, 78 struct acpi_namespace_node *parent_node, 79 union acpi_operand_object **ddb_handle) 80{ 81 acpi_status status; 82 union acpi_operand_object *obj_desc; 83 84 ACPI_FUNCTION_TRACE(ex_add_table); 85 86 /* Create an object to be the table handle */ 87 88 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); 89 if (!obj_desc) { 90 return_ACPI_STATUS(AE_NO_MEMORY); 91 } 92 93 /* Init the table handle */ 94 95 obj_desc->reference.opcode = AML_LOAD_OP; 96 *ddb_handle = obj_desc; 97 98 /* Install the new table into the local data structures */ 99 100 obj_desc->reference.object = ACPI_CAST_PTR(void, table_index); 101 102 /* Add the table to the namespace */ 103 104 status = acpi_ns_load_table(table_index, parent_node); 105 if (ACPI_FAILURE(status)) { 106 acpi_ut_remove_reference(obj_desc); 107 *ddb_handle = NULL; 108 } 109 110 return_ACPI_STATUS(status); 111} 112 113/******************************************************************************* 114 * 115 * FUNCTION: acpi_ex_load_table_op 116 * 117 * PARAMETERS: walk_state - Current state with operands 118 * return_desc - Where to store the return object 119 * 120 * RETURN: Status 121 * 122 * DESCRIPTION: Load an ACPI table from the RSDT/XSDT 123 * 124 ******************************************************************************/ 125 126acpi_status 127acpi_ex_load_table_op(struct acpi_walk_state *walk_state, 128 union acpi_operand_object **return_desc) 129{ 130 acpi_status status; 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; 138 139 ACPI_FUNCTION_TRACE(ex_load_table_op); 140 141 /* Find the ACPI table in the RSDT/XSDT */ 142 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); 149 } 150 151 /* Table not found, return an Integer=0 and AE_OK */ 152 153 ddb_handle = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); 154 if (!ddb_handle) { 155 return_ACPI_STATUS(AE_NO_MEMORY); 156 } 157 158 ddb_handle->integer.value = 0; 159 *return_desc = ddb_handle; 160 161 return_ACPI_STATUS(AE_OK); 162 } 163 164 /* Default nodes */ 165 166 start_node = walk_state->scope_info->scope.node; 167 parent_node = acpi_gbl_root_node; 168 169 /* root_path (optional parameter) */ 170 171 if (operand[3]->string.length > 0) { 172 /* 173 * Find the node referenced by the root_path_string. This is the 174 * location within the namespace where the table will be loaded. 175 */ 176 status = 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); 181 } 182 } 183 184 /* parameter_path (optional parameter) */ 185 186 if (operand[4]->string.length > 0) { 187 if ((operand[4]->string.pointer[0] != '\\') && 188 (operand[4]->string.pointer[0] != '^')) { 189 /* 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) 192 */ 193 start_node = parent_node; 194 } 195 196 /* Find the node referenced by the parameter_path_string */ 197 198 status = 199 acpi_ns_get_node(start_node, operand[4]->string.pointer, 200 ACPI_NS_SEARCH_PARENT, &parameter_node); 201 if (ACPI_FAILURE(status)) { 202 return_ACPI_STATUS(status); 203 } 204 } 205 206 /* Load the table into the namespace */ 207 208 status = acpi_ex_add_table(table_index, parent_node, &ddb_handle); 209 if (ACPI_FAILURE(status)) { 210 return_ACPI_STATUS(status); 211 } 212 213 /* Parameter Data (optional) */ 214 215 if (parameter_node) { 216 217 /* Store the parameter data into the optional parameter object */ 218 219 status = acpi_ex_store(operand[5], 220 ACPI_CAST_PTR(union acpi_operand_object, 221 parameter_node), 222 walk_state); 223 if (ACPI_FAILURE(status)) { 224 (void)acpi_ex_unload_table(ddb_handle); 225 return_ACPI_STATUS(status); 226 } 227 } 228 229 status = acpi_get_table_by_index(table_index, &table); 230 if (ACPI_SUCCESS(status)) { 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 } 236 237 *return_desc = ddb_handle; 238 return_ACPI_STATUS(status); 239} 240 241/******************************************************************************* 242 * 243 * FUNCTION: acpi_ex_load_op 244 * 245 * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be 246 * obtained 247 * Target - Where a handle to the table will be stored 248 * walk_state - Current state 249 * 250 * RETURN: Status 251 * 252 * DESCRIPTION: Load an ACPI table from a field or operation region 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 * 260 ******************************************************************************/ 261 262acpi_status 263acpi_ex_load_op(union acpi_operand_object *obj_desc, 264 union acpi_operand_object *target, 265 struct acpi_walk_state *walk_state) 266{ 267 union acpi_operand_object *ddb_handle; 268 struct acpi_table_desc table_desc; 269 acpi_native_uint table_index; 270 acpi_status status; 271 272 ACPI_FUNCTION_TRACE(ex_load_op); 273 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 */ 277 278 switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { 279 case ACPI_TYPE_REGION: 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 287 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", 288 obj_desc, 289 acpi_ut_get_object_type_name(obj_desc))); 290 291 /* 292 * If the Region Address and Length have not been previously evaluated, 293 * evaluate them now and save the results. 294 */ 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); 299 } 300 } 301 302 table_desc.address = obj_desc->region.address; 303 table_desc.length = obj_desc->region.length; 304 table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; 305 break; 306 307 case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ 308 309 /* Simply extract the buffer from the buffer object */ 310 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))); 314 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; 319 320 obj_desc->buffer.pointer = NULL; 321 break; 322 323 default: 324 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 325 } 326 327 /* 328 * Install the new table into the local data structures 329 */ 330 status = acpi_tb_add_table(&table_desc, &table_index); 331 if (ACPI_FAILURE(status)) { 332 goto cleanup; 333 } 334 335 status = 336 acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); 337 if (ACPI_FAILURE(status)) { 338 339 /* On error, table_ptr was deallocated above */ 340 341 return_ACPI_STATUS(status); 342 } 343 344 /* Store the ddb_handle into the Target operand */ 345 346 status = acpi_ex_store(ddb_handle, target, walk_state); 347 if (ACPI_FAILURE(status)) { 348 (void)acpi_ex_unload_table(ddb_handle); 349 350 /* table_ptr was deallocated above */ 351 352 return_ACPI_STATUS(status); 353 } 354 355 cleanup: 356 if (ACPI_FAILURE(status)) { 357 acpi_tb_delete_table(&table_desc); 358 } 359 return_ACPI_STATUS(status); 360} 361 362/******************************************************************************* 363 * 364 * FUNCTION: acpi_ex_unload_table 365 * 366 * PARAMETERS: ddb_handle - Handle to a previously loaded table 367 * 368 * RETURN: Status 369 * 370 * DESCRIPTION: Unload an ACPI table 371 * 372 ******************************************************************************/ 373 374acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) 375{ 376 acpi_status status = AE_OK; 377 union acpi_operand_object *table_desc = ddb_handle; 378 acpi_native_uint table_index; 379 380 ACPI_FUNCTION_TRACE(ex_unload_table); 381 382 /* 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 386 * validated here. 387 */ 388 if ((!ddb_handle) || 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); 392 } 393 394 /* Get the table index from the ddb_handle */ 395 396 table_index = (acpi_native_uint) table_desc->reference.object; 397 398 /* 399 * Delete the entire namespace under this table Node 400 * (Offset contains the table_id) 401 */ 402 acpi_tb_delete_namespace_by_owner(table_index); 403 acpi_tb_release_owner_id(table_index); 404 405 acpi_tb_set_table_loaded_flag(table_index, FALSE); 406 407 /* Delete the table descriptor (ddb_handle) */ 408 409 acpi_ut_remove_reference(table_desc); 410 return_ACPI_STATUS(status); 411}