Auto merge with /home/aegl/GIT/linus
[linux-2.6] / drivers / acpi / executer / exconfig.c
1 /******************************************************************************
2  *
3  * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes)
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2005, 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
45 #include <acpi/acpi.h>
46 #include <acpi/acinterp.h>
47 #include <acpi/amlcode.h>
48 #include <acpi/acnamesp.h>
49 #include <acpi/acevents.h>
50 #include <acpi/actables.h>
51 #include <acpi/acdispat.h>
52
53
54 #define _COMPONENT          ACPI_EXECUTER
55          ACPI_MODULE_NAME    ("exconfig")
56
57 /* Local prototypes */
58
59 static acpi_status
60 acpi_ex_add_table (
61         struct acpi_table_header        *table,
62         struct acpi_namespace_node      *parent_node,
63         union acpi_operand_object       **ddb_handle);
64
65
66 /*******************************************************************************
67  *
68  * FUNCTION:    acpi_ex_add_table
69  *
70  * PARAMETERS:  Table               - Pointer to raw table
71  *              parent_node         - Where to load the table (scope)
72  *              ddb_handle          - Where to return the table handle.
73  *
74  * RETURN:      Status
75  *
76  * DESCRIPTION: Common function to Install and Load an ACPI table with a
77  *              returned table handle.
78  *
79  ******************************************************************************/
80
81 static acpi_status
82 acpi_ex_add_table (
83         struct acpi_table_header        *table,
84         struct acpi_namespace_node      *parent_node,
85         union acpi_operand_object       **ddb_handle)
86 {
87         acpi_status                     status;
88         struct acpi_table_desc          table_info;
89         union acpi_operand_object       *obj_desc;
90
91
92         ACPI_FUNCTION_TRACE ("ex_add_table");
93
94
95         /* Create an object to be the table handle */
96
97         obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
98         if (!obj_desc) {
99                 return_ACPI_STATUS (AE_NO_MEMORY);
100         }
101
102         /* Install the new table into the local data structures */
103
104         ACPI_MEMSET (&table_info, 0, sizeof (struct acpi_table_desc));
105
106         table_info.type      = ACPI_TABLE_SSDT;
107         table_info.pointer   = table;
108         table_info.length    = (acpi_size) table->length;
109         table_info.allocation = ACPI_MEM_ALLOCATED;
110
111         status = acpi_tb_install_table (&table_info);
112         if (ACPI_FAILURE (status)) {
113                 goto cleanup;
114         }
115
116         /* Add the table to the namespace */
117
118         status = acpi_ns_load_table (table_info.installed_desc, parent_node);
119         if (ACPI_FAILURE (status)) {
120                 /* Uninstall table on error */
121
122                 (void) acpi_tb_uninstall_table (table_info.installed_desc);
123                 goto cleanup;
124         }
125
126         /* Init the table handle */
127
128         obj_desc->reference.opcode = AML_LOAD_OP;
129         obj_desc->reference.object = table_info.installed_desc;
130         *ddb_handle = obj_desc;
131         return_ACPI_STATUS (AE_OK);
132
133
134 cleanup:
135         acpi_ut_remove_reference (obj_desc);
136         return_ACPI_STATUS (status);
137 }
138
139
140 /*******************************************************************************
141  *
142  * FUNCTION:    acpi_ex_load_table_op
143  *
144  * PARAMETERS:  walk_state          - Current state with operands
145  *              return_desc         - Where to store the return object
146  *
147  * RETURN:      Status
148  *
149  * DESCRIPTION: Load an ACPI table
150  *
151  ******************************************************************************/
152
153 acpi_status
154 acpi_ex_load_table_op (
155         struct acpi_walk_state          *walk_state,
156         union acpi_operand_object       **return_desc)
157 {
158         acpi_status                     status;
159         union acpi_operand_object       **operand = &walk_state->operands[0];
160         struct acpi_table_header        *table;
161         struct acpi_namespace_node      *parent_node;
162         struct acpi_namespace_node      *start_node;
163         struct acpi_namespace_node      *parameter_node = NULL;
164         union acpi_operand_object       *ddb_handle;
165
166
167         ACPI_FUNCTION_TRACE ("ex_load_table_op");
168
169
170 #if 0
171         /*
172          * Make sure that the signature does not match one of the tables that
173          * is already loaded.
174          */
175         status = acpi_tb_match_signature (operand[0]->string.pointer, NULL);
176         if (status == AE_OK) {
177                 /* Signature matched -- don't allow override */
178
179                 return_ACPI_STATUS (AE_ALREADY_EXISTS);
180         }
181 #endif
182
183         /* Find the ACPI table */
184
185         status = acpi_tb_find_table (operand[0]->string.pointer,
186                            operand[1]->string.pointer,
187                            operand[2]->string.pointer, &table);
188         if (ACPI_FAILURE (status)) {
189                 if (status != AE_NOT_FOUND) {
190                         return_ACPI_STATUS (status);
191                 }
192
193                 /* Table not found, return an Integer=0 and AE_OK */
194
195                 ddb_handle = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
196                 if (!ddb_handle) {
197                         return_ACPI_STATUS (AE_NO_MEMORY);
198                 }
199
200                 ddb_handle->integer.value = 0;
201                 *return_desc = ddb_handle;
202
203                 return_ACPI_STATUS (AE_OK);
204         }
205
206         /* Default nodes */
207
208         start_node = walk_state->scope_info->scope.node;
209         parent_node = acpi_gbl_root_node;
210
211         /* root_path (optional parameter) */
212
213         if (operand[3]->string.length > 0) {
214                 /*
215                  * Find the node referenced by the root_path_string. This is the
216                  * location within the namespace where the table will be loaded.
217                  */
218                 status = acpi_ns_get_node_by_path (operand[3]->string.pointer, start_node,
219                                    ACPI_NS_SEARCH_PARENT, &parent_node);
220                 if (ACPI_FAILURE (status)) {
221                         return_ACPI_STATUS (status);
222                 }
223         }
224
225         /* parameter_path (optional parameter) */
226
227         if (operand[4]->string.length > 0) {
228                 if ((operand[4]->string.pointer[0] != '\\') &&
229                         (operand[4]->string.pointer[0] != '^')) {
230                         /*
231                          * Path is not absolute, so it will be relative to the node
232                          * referenced by the root_path_string (or the NS root if omitted)
233                          */
234                         start_node = parent_node;
235                 }
236
237                 /* Find the node referenced by the parameter_path_string */
238
239                 status = acpi_ns_get_node_by_path (operand[4]->string.pointer, start_node,
240                                  ACPI_NS_SEARCH_PARENT, &parameter_node);
241                 if (ACPI_FAILURE (status)) {
242                         return_ACPI_STATUS (status);
243                 }
244         }
245
246         /* Load the table into the namespace */
247
248         status = acpi_ex_add_table (table, parent_node, &ddb_handle);
249         if (ACPI_FAILURE (status)) {
250                 return_ACPI_STATUS (status);
251         }
252
253         /* Parameter Data (optional) */
254
255         if (parameter_node) {
256                 /* Store the parameter data into the optional parameter object */
257
258                 status = acpi_ex_store (operand[5],
259                                  ACPI_CAST_PTR (union acpi_operand_object, parameter_node),
260                                  walk_state);
261                 if (ACPI_FAILURE (status)) {
262                         (void) acpi_ex_unload_table (ddb_handle);
263                         return_ACPI_STATUS (status);
264                 }
265         }
266
267         *return_desc = ddb_handle;
268         return_ACPI_STATUS  (status);
269 }
270
271
272 /*******************************************************************************
273  *
274  * FUNCTION:    acpi_ex_load_op
275  *
276  * PARAMETERS:  obj_desc        - Region or Field where the table will be
277  *                                obtained
278  *              Target          - Where a handle to the table will be stored
279  *              walk_state      - Current state
280  *
281  * RETURN:      Status
282  *
283  * DESCRIPTION: Load an ACPI table from a field or operation region
284  *
285  ******************************************************************************/
286
287 acpi_status
288 acpi_ex_load_op (
289         union acpi_operand_object       *obj_desc,
290         union acpi_operand_object       *target,
291         struct acpi_walk_state          *walk_state)
292 {
293         acpi_status                     status;
294         union acpi_operand_object       *ddb_handle;
295         union acpi_operand_object       *buffer_desc = NULL;
296         struct acpi_table_header        *table_ptr = NULL;
297         acpi_physical_address           address;
298         struct acpi_table_header        table_header;
299         u32                             i;
300
301         ACPI_FUNCTION_TRACE ("ex_load_op");
302
303
304         /* Object can be either an op_region or a Field */
305
306         switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
307         case ACPI_TYPE_REGION:
308
309                 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n",
310                         obj_desc, acpi_ut_get_object_type_name (obj_desc)));
311
312                 /*
313                  * If the Region Address and Length have not been previously evaluated,
314                  * evaluate them now and save the results.
315                  */
316                 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
317                         status = acpi_ds_get_region_arguments (obj_desc);
318                         if (ACPI_FAILURE (status)) {
319                                 return_ACPI_STATUS (status);
320                         }
321                 }
322
323                 /* Get the base physical address of the region */
324
325                 address = obj_desc->region.address;
326
327                 /* Get the table length from the table header */
328
329                 table_header.length = 0;
330                 for (i = 0; i < 8; i++) {
331                         status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
332                                            (acpi_physical_address) (i + address), 8,
333                                            ((u8 *) &table_header) + i);
334                         if (ACPI_FAILURE (status)) {
335                                 return_ACPI_STATUS (status);
336                         }
337                 }
338
339                 /* Sanity check the table length */
340
341                 if (table_header.length < sizeof (struct acpi_table_header)) {
342                         return_ACPI_STATUS (AE_BAD_HEADER);
343                 }
344
345                 /* Allocate a buffer for the entire table */
346
347                 table_ptr = ACPI_MEM_ALLOCATE (table_header.length);
348                 if (!table_ptr) {
349                         return_ACPI_STATUS (AE_NO_MEMORY);
350                 }
351
352                 /* Get the entire table from the op region */
353
354                 for (i = 0; i < table_header.length; i++) {
355                         status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
356                                            (acpi_physical_address) (i + address), 8,
357                                            ((u8 *) table_ptr + i));
358                         if (ACPI_FAILURE (status)) {
359                                 goto cleanup;
360                         }
361                 }
362                 break;
363
364
365         case ACPI_TYPE_LOCAL_REGION_FIELD:
366         case ACPI_TYPE_LOCAL_BANK_FIELD:
367         case ACPI_TYPE_LOCAL_INDEX_FIELD:
368
369                 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Field %p %s\n",
370                         obj_desc, acpi_ut_get_object_type_name (obj_desc)));
371
372                 /*
373                  * The length of the field must be at least as large as the table.
374                  * Read the entire field and thus the entire table.  Buffer is
375                  * allocated during the read.
376                  */
377                 status = acpi_ex_read_data_from_field (walk_state, obj_desc, &buffer_desc);
378                 if (ACPI_FAILURE (status)) {
379                         goto cleanup;
380                 }
381
382                 table_ptr = ACPI_CAST_PTR (struct acpi_table_header,
383                                   buffer_desc->buffer.pointer);
384
385                  /* Sanity check the table length */
386
387                 if (table_ptr->length < sizeof (struct acpi_table_header)) {
388                         return_ACPI_STATUS (AE_BAD_HEADER);
389                 }
390                 break;
391
392
393         default:
394                 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
395         }
396
397         /* The table must be either an SSDT or a PSDT */
398
399         if ((!ACPI_STRNCMP (table_ptr->signature,
400                           acpi_gbl_table_data[ACPI_TABLE_PSDT].signature,
401                           acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) &&
402                 (!ACPI_STRNCMP (table_ptr->signature,
403                                  acpi_gbl_table_data[ACPI_TABLE_SSDT].signature,
404                                  acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) {
405                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
406                         "Table has invalid signature [%4.4s], must be SSDT or PSDT\n",
407                         table_ptr->signature));
408                 status = AE_BAD_SIGNATURE;
409                 goto cleanup;
410         }
411
412         /* Install the new table into the local data structures */
413
414         status = acpi_ex_add_table (table_ptr, acpi_gbl_root_node, &ddb_handle);
415         if (ACPI_FAILURE (status)) {
416                 goto cleanup;
417         }
418
419         /* Store the ddb_handle into the Target operand */
420
421         status = acpi_ex_store (ddb_handle, target, walk_state);
422         if (ACPI_FAILURE (status)) {
423                 (void) acpi_ex_unload_table (ddb_handle);
424         }
425
426         return_ACPI_STATUS (status);
427
428
429 cleanup:
430
431         if (buffer_desc) {
432                 acpi_ut_remove_reference (buffer_desc);
433         }
434         else {
435                 ACPI_MEM_FREE (table_ptr);
436         }
437         return_ACPI_STATUS (status);
438 }
439
440
441 /*******************************************************************************
442  *
443  * FUNCTION:    acpi_ex_unload_table
444  *
445  * PARAMETERS:  ddb_handle          - Handle to a previously loaded table
446  *
447  * RETURN:      Status
448  *
449  * DESCRIPTION: Unload an ACPI table
450  *
451  ******************************************************************************/
452
453 acpi_status
454 acpi_ex_unload_table (
455         union acpi_operand_object       *ddb_handle)
456 {
457         acpi_status                     status = AE_OK;
458         union acpi_operand_object       *table_desc = ddb_handle;
459         struct acpi_table_desc          *table_info;
460
461
462         ACPI_FUNCTION_TRACE ("ex_unload_table");
463
464
465         /*
466          * Validate the handle
467          * Although the handle is partially validated in acpi_ex_reconfiguration(),
468          * when it calls acpi_ex_resolve_operands(), the handle is more completely
469          * validated here.
470          */
471         if ((!ddb_handle) ||
472                 (ACPI_GET_DESCRIPTOR_TYPE (ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
473                 (ACPI_GET_OBJECT_TYPE (ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) {
474                 return_ACPI_STATUS (AE_BAD_PARAMETER);
475         }
476
477         /* Get the actual table descriptor from the ddb_handle */
478
479         table_info = (struct acpi_table_desc *) table_desc->reference.object;
480
481         /*
482          * Delete the entire namespace under this table Node
483          * (Offset contains the table_id)
484          */
485         acpi_ns_delete_namespace_by_owner (table_info->table_id);
486
487         /* Delete the table itself */
488
489         (void) acpi_tb_uninstall_table (table_info->installed_desc);
490
491         /* Delete the table descriptor (ddb_handle) */
492
493         acpi_ut_remove_reference (table_desc);
494         return_ACPI_STATUS (status);
495 }
496