diff options
Diffstat (limited to 'drivers/acpi/executer')
24 files changed, 11955 insertions, 0 deletions
diff --git a/drivers/acpi/executer/Makefile b/drivers/acpi/executer/Makefile new file mode 100644 index 000000000000..e09998aa012f --- /dev/null +++ b/drivers/acpi/executer/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | # | ||
2 | # Makefile for all Linux ACPI interpreter subdirectories | ||
3 | # | ||
4 | |||
5 | obj-y := exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\ | ||
6 | exconvrt.o exfldio.o exoparg1.o exprep.o exresop.o exsystem.o\ | ||
7 | excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \ | ||
8 | exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o | ||
9 | |||
10 | EXTRA_CFLAGS += $(ACPI_CFLAGS) | ||
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c new file mode 100644 index 000000000000..ac3c061967f2 --- /dev/null +++ b/drivers/acpi/executer/exconfig.c | |||
@@ -0,0 +1,487 @@ | |||
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 | |||
58 | /******************************************************************************* | ||
59 | * | ||
60 | * FUNCTION: acpi_ex_add_table | ||
61 | * | ||
62 | * PARAMETERS: Table - Pointer to raw table | ||
63 | * parent_node - Where to load the table (scope) | ||
64 | * ddb_handle - Where to return the table handle. | ||
65 | * | ||
66 | * RETURN: Status | ||
67 | * | ||
68 | * DESCRIPTION: Common function to Install and Load an ACPI table with a | ||
69 | * returned table handle. | ||
70 | * | ||
71 | ******************************************************************************/ | ||
72 | |||
73 | acpi_status | ||
74 | acpi_ex_add_table ( | ||
75 | struct acpi_table_header *table, | ||
76 | struct acpi_namespace_node *parent_node, | ||
77 | union acpi_operand_object **ddb_handle) | ||
78 | { | ||
79 | acpi_status status; | ||
80 | struct acpi_table_desc table_info; | ||
81 | union acpi_operand_object *obj_desc; | ||
82 | |||
83 | |||
84 | ACPI_FUNCTION_TRACE ("ex_add_table"); | ||
85 | |||
86 | |||
87 | /* Create an object to be the table handle */ | ||
88 | |||
89 | obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE); | ||
90 | if (!obj_desc) { | ||
91 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
92 | } | ||
93 | |||
94 | /* Install the new table into the local data structures */ | ||
95 | |||
96 | ACPI_MEMSET (&table_info, 0, sizeof (struct acpi_table_desc)); | ||
97 | |||
98 | table_info.type = ACPI_TABLE_SSDT; | ||
99 | table_info.pointer = table; | ||
100 | table_info.length = (acpi_size) table->length; | ||
101 | table_info.allocation = ACPI_MEM_ALLOCATED; | ||
102 | |||
103 | status = acpi_tb_install_table (&table_info); | ||
104 | if (ACPI_FAILURE (status)) { | ||
105 | goto cleanup; | ||
106 | } | ||
107 | |||
108 | /* Add the table to the namespace */ | ||
109 | |||
110 | status = acpi_ns_load_table (table_info.installed_desc, parent_node); | ||
111 | if (ACPI_FAILURE (status)) { | ||
112 | /* Uninstall table on error */ | ||
113 | |||
114 | (void) acpi_tb_uninstall_table (table_info.installed_desc); | ||
115 | goto cleanup; | ||
116 | } | ||
117 | |||
118 | /* Init the table handle */ | ||
119 | |||
120 | obj_desc->reference.opcode = AML_LOAD_OP; | ||
121 | obj_desc->reference.object = table_info.installed_desc; | ||
122 | *ddb_handle = obj_desc; | ||
123 | return_ACPI_STATUS (AE_OK); | ||
124 | |||
125 | |||
126 | cleanup: | ||
127 | acpi_ut_remove_reference (obj_desc); | ||
128 | return_ACPI_STATUS (status); | ||
129 | } | ||
130 | |||
131 | |||
132 | /******************************************************************************* | ||
133 | * | ||
134 | * FUNCTION: acpi_ex_load_table_op | ||
135 | * | ||
136 | * PARAMETERS: walk_state - Current state with operands | ||
137 | * return_desc - Where to store the return object | ||
138 | * | ||
139 | * RETURN: Status | ||
140 | * | ||
141 | * DESCRIPTION: Load an ACPI table | ||
142 | * | ||
143 | ******************************************************************************/ | ||
144 | |||
145 | acpi_status | ||
146 | acpi_ex_load_table_op ( | ||
147 | struct acpi_walk_state *walk_state, | ||
148 | union acpi_operand_object **return_desc) | ||
149 | { | ||
150 | acpi_status status; | ||
151 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
152 | struct acpi_table_header *table; | ||
153 | struct acpi_namespace_node *parent_node; | ||
154 | struct acpi_namespace_node *start_node; | ||
155 | struct acpi_namespace_node *parameter_node = NULL; | ||
156 | union acpi_operand_object *ddb_handle; | ||
157 | |||
158 | |||
159 | ACPI_FUNCTION_TRACE ("ex_load_table_op"); | ||
160 | |||
161 | |||
162 | #if 0 | ||
163 | /* | ||
164 | * Make sure that the signature does not match one of the tables that | ||
165 | * is already loaded. | ||
166 | */ | ||
167 | status = acpi_tb_match_signature (operand[0]->string.pointer, NULL); | ||
168 | if (status == AE_OK) { | ||
169 | /* Signature matched -- don't allow override */ | ||
170 | |||
171 | return_ACPI_STATUS (AE_ALREADY_EXISTS); | ||
172 | } | ||
173 | #endif | ||
174 | |||
175 | /* Find the ACPI table */ | ||
176 | |||
177 | status = acpi_tb_find_table (operand[0]->string.pointer, | ||
178 | operand[1]->string.pointer, | ||
179 | operand[2]->string.pointer, &table); | ||
180 | if (ACPI_FAILURE (status)) { | ||
181 | if (status != AE_NOT_FOUND) { | ||
182 | return_ACPI_STATUS (status); | ||
183 | } | ||
184 | |||
185 | /* Table not found, return an Integer=0 and AE_OK */ | ||
186 | |||
187 | ddb_handle = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
188 | if (!ddb_handle) { | ||
189 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
190 | } | ||
191 | |||
192 | ddb_handle->integer.value = 0; | ||
193 | *return_desc = ddb_handle; | ||
194 | |||
195 | return_ACPI_STATUS (AE_OK); | ||
196 | } | ||
197 | |||
198 | /* Default nodes */ | ||
199 | |||
200 | start_node = walk_state->scope_info->scope.node; | ||
201 | parent_node = acpi_gbl_root_node; | ||
202 | |||
203 | /* root_path (optional parameter) */ | ||
204 | |||
205 | if (operand[3]->string.length > 0) { | ||
206 | /* | ||
207 | * Find the node referenced by the root_path_string. This is the | ||
208 | * location within the namespace where the table will be loaded. | ||
209 | */ | ||
210 | status = acpi_ns_get_node_by_path (operand[3]->string.pointer, start_node, | ||
211 | ACPI_NS_SEARCH_PARENT, &parent_node); | ||
212 | if (ACPI_FAILURE (status)) { | ||
213 | return_ACPI_STATUS (status); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | /* parameter_path (optional parameter) */ | ||
218 | |||
219 | if (operand[4]->string.length > 0) { | ||
220 | if ((operand[4]->string.pointer[0] != '\\') && | ||
221 | (operand[4]->string.pointer[0] != '^')) { | ||
222 | /* | ||
223 | * Path is not absolute, so it will be relative to the node | ||
224 | * referenced by the root_path_string (or the NS root if omitted) | ||
225 | */ | ||
226 | start_node = parent_node; | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * Find the node referenced by the parameter_path_string | ||
231 | */ | ||
232 | status = acpi_ns_get_node_by_path (operand[4]->string.pointer, start_node, | ||
233 | ACPI_NS_SEARCH_PARENT, ¶meter_node); | ||
234 | if (ACPI_FAILURE (status)) { | ||
235 | return_ACPI_STATUS (status); | ||
236 | } | ||
237 | } | ||
238 | |||
239 | /* Load the table into the namespace */ | ||
240 | |||
241 | status = acpi_ex_add_table (table, parent_node, &ddb_handle); | ||
242 | if (ACPI_FAILURE (status)) { | ||
243 | return_ACPI_STATUS (status); | ||
244 | } | ||
245 | |||
246 | /* Parameter Data (optional) */ | ||
247 | |||
248 | if (parameter_node) { | ||
249 | /* Store the parameter data into the optional parameter object */ | ||
250 | |||
251 | status = acpi_ex_store (operand[5], ACPI_CAST_PTR (union acpi_operand_object, parameter_node), | ||
252 | walk_state); | ||
253 | if (ACPI_FAILURE (status)) { | ||
254 | (void) acpi_ex_unload_table (ddb_handle); | ||
255 | return_ACPI_STATUS (status); | ||
256 | } | ||
257 | } | ||
258 | |||
259 | *return_desc = ddb_handle; | ||
260 | return_ACPI_STATUS (status); | ||
261 | } | ||
262 | |||
263 | |||
264 | /******************************************************************************* | ||
265 | * | ||
266 | * FUNCTION: acpi_ex_load_op | ||
267 | * | ||
268 | * PARAMETERS: obj_desc - Region or Field where the table will be | ||
269 | * obtained | ||
270 | * Target - Where a handle to the table will be stored | ||
271 | * walk_state - Current state | ||
272 | * | ||
273 | * RETURN: Status | ||
274 | * | ||
275 | * DESCRIPTION: Load an ACPI table from a field or operation region | ||
276 | * | ||
277 | ******************************************************************************/ | ||
278 | |||
279 | acpi_status | ||
280 | acpi_ex_load_op ( | ||
281 | union acpi_operand_object *obj_desc, | ||
282 | union acpi_operand_object *target, | ||
283 | struct acpi_walk_state *walk_state) | ||
284 | { | ||
285 | acpi_status status; | ||
286 | union acpi_operand_object *ddb_handle; | ||
287 | union acpi_operand_object *buffer_desc = NULL; | ||
288 | struct acpi_table_header *table_ptr = NULL; | ||
289 | acpi_physical_address address; | ||
290 | struct acpi_table_header table_header; | ||
291 | u32 i; | ||
292 | |||
293 | ACPI_FUNCTION_TRACE ("ex_load_op"); | ||
294 | |||
295 | |||
296 | /* Object can be either an op_region or a Field */ | ||
297 | |||
298 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
299 | case ACPI_TYPE_REGION: | ||
300 | |||
301 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n", | ||
302 | obj_desc, acpi_ut_get_object_type_name (obj_desc))); | ||
303 | |||
304 | /* | ||
305 | * If the Region Address and Length have not been previously evaluated, | ||
306 | * evaluate them now and save the results. | ||
307 | */ | ||
308 | if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { | ||
309 | status = acpi_ds_get_region_arguments (obj_desc); | ||
310 | if (ACPI_FAILURE (status)) { | ||
311 | return_ACPI_STATUS (status); | ||
312 | } | ||
313 | } | ||
314 | |||
315 | /* Get the base physical address of the region */ | ||
316 | |||
317 | address = obj_desc->region.address; | ||
318 | |||
319 | /* Get the table length from the table header */ | ||
320 | |||
321 | table_header.length = 0; | ||
322 | for (i = 0; i < 8; i++) { | ||
323 | status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ, | ||
324 | (acpi_physical_address) (i + address), 8, | ||
325 | ((u8 *) &table_header) + i); | ||
326 | if (ACPI_FAILURE (status)) { | ||
327 | return_ACPI_STATUS (status); | ||
328 | } | ||
329 | } | ||
330 | |||
331 | /* Sanity check the table length */ | ||
332 | |||
333 | if (table_header.length < sizeof (struct acpi_table_header)) { | ||
334 | return_ACPI_STATUS (AE_BAD_HEADER); | ||
335 | } | ||
336 | |||
337 | /* Allocate a buffer for the entire table */ | ||
338 | |||
339 | table_ptr = ACPI_MEM_ALLOCATE (table_header.length); | ||
340 | if (!table_ptr) { | ||
341 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
342 | } | ||
343 | |||
344 | /* Get the entire table from the op region */ | ||
345 | |||
346 | for (i = 0; i < table_header.length; i++) { | ||
347 | status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ, | ||
348 | (acpi_physical_address) (i + address), 8, | ||
349 | ((u8 *) table_ptr + i)); | ||
350 | if (ACPI_FAILURE (status)) { | ||
351 | goto cleanup; | ||
352 | } | ||
353 | } | ||
354 | break; | ||
355 | |||
356 | |||
357 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
358 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
359 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
360 | |||
361 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Field %p %s\n", | ||
362 | obj_desc, acpi_ut_get_object_type_name (obj_desc))); | ||
363 | |||
364 | /* | ||
365 | * The length of the field must be at least as large as the table. | ||
366 | * Read the entire field and thus the entire table. Buffer is | ||
367 | * allocated during the read. | ||
368 | */ | ||
369 | status = acpi_ex_read_data_from_field (walk_state, obj_desc, &buffer_desc); | ||
370 | if (ACPI_FAILURE (status)) { | ||
371 | goto cleanup; | ||
372 | } | ||
373 | |||
374 | table_ptr = ACPI_CAST_PTR (struct acpi_table_header, buffer_desc->buffer.pointer); | ||
375 | |||
376 | /* Sanity check the table length */ | ||
377 | |||
378 | if (table_ptr->length < sizeof (struct acpi_table_header)) { | ||
379 | return_ACPI_STATUS (AE_BAD_HEADER); | ||
380 | } | ||
381 | break; | ||
382 | |||
383 | |||
384 | default: | ||
385 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
386 | } | ||
387 | |||
388 | /* The table must be either an SSDT or a PSDT */ | ||
389 | |||
390 | if ((!ACPI_STRNCMP (table_ptr->signature, | ||
391 | acpi_gbl_table_data[ACPI_TABLE_PSDT].signature, | ||
392 | acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) && | ||
393 | (!ACPI_STRNCMP (table_ptr->signature, | ||
394 | acpi_gbl_table_data[ACPI_TABLE_SSDT].signature, | ||
395 | acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) { | ||
396 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
397 | "Table has invalid signature [%4.4s], must be SSDT or PSDT\n", | ||
398 | table_ptr->signature)); | ||
399 | status = AE_BAD_SIGNATURE; | ||
400 | goto cleanup; | ||
401 | } | ||
402 | |||
403 | /* Install the new table into the local data structures */ | ||
404 | |||
405 | status = acpi_ex_add_table (table_ptr, acpi_gbl_root_node, &ddb_handle); | ||
406 | if (ACPI_FAILURE (status)) { | ||
407 | goto cleanup; | ||
408 | } | ||
409 | |||
410 | /* Store the ddb_handle into the Target operand */ | ||
411 | |||
412 | status = acpi_ex_store (ddb_handle, target, walk_state); | ||
413 | if (ACPI_FAILURE (status)) { | ||
414 | (void) acpi_ex_unload_table (ddb_handle); | ||
415 | } | ||
416 | |||
417 | return_ACPI_STATUS (status); | ||
418 | |||
419 | |||
420 | cleanup: | ||
421 | |||
422 | if (buffer_desc) { | ||
423 | acpi_ut_remove_reference (buffer_desc); | ||
424 | } | ||
425 | else { | ||
426 | ACPI_MEM_FREE (table_ptr); | ||
427 | } | ||
428 | return_ACPI_STATUS (status); | ||
429 | } | ||
430 | |||
431 | |||
432 | /******************************************************************************* | ||
433 | * | ||
434 | * FUNCTION: acpi_ex_unload_table | ||
435 | * | ||
436 | * PARAMETERS: ddb_handle - Handle to a previously loaded table | ||
437 | * | ||
438 | * RETURN: Status | ||
439 | * | ||
440 | * DESCRIPTION: Unload an ACPI table | ||
441 | * | ||
442 | ******************************************************************************/ | ||
443 | |||
444 | acpi_status | ||
445 | acpi_ex_unload_table ( | ||
446 | union acpi_operand_object *ddb_handle) | ||
447 | { | ||
448 | acpi_status status = AE_OK; | ||
449 | union acpi_operand_object *table_desc = ddb_handle; | ||
450 | struct acpi_table_desc *table_info; | ||
451 | |||
452 | |||
453 | ACPI_FUNCTION_TRACE ("ex_unload_table"); | ||
454 | |||
455 | |||
456 | /* | ||
457 | * Validate the handle | ||
458 | * Although the handle is partially validated in acpi_ex_reconfiguration(), | ||
459 | * when it calls acpi_ex_resolve_operands(), the handle is more completely | ||
460 | * validated here. | ||
461 | */ | ||
462 | if ((!ddb_handle) || | ||
463 | (ACPI_GET_DESCRIPTOR_TYPE (ddb_handle) != ACPI_DESC_TYPE_OPERAND) || | ||
464 | (ACPI_GET_OBJECT_TYPE (ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) { | ||
465 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
466 | } | ||
467 | |||
468 | /* Get the actual table descriptor from the ddb_handle */ | ||
469 | |||
470 | table_info = (struct acpi_table_desc *) table_desc->reference.object; | ||
471 | |||
472 | /* | ||
473 | * Delete the entire namespace under this table Node | ||
474 | * (Offset contains the table_id) | ||
475 | */ | ||
476 | acpi_ns_delete_namespace_by_owner (table_info->table_id); | ||
477 | |||
478 | /* Delete the table itself */ | ||
479 | |||
480 | (void) acpi_tb_uninstall_table (table_info->installed_desc); | ||
481 | |||
482 | /* Delete the table descriptor (ddb_handle) */ | ||
483 | |||
484 | acpi_ut_remove_reference (table_desc); | ||
485 | return_ACPI_STATUS (status); | ||
486 | } | ||
487 | |||
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c new file mode 100644 index 000000000000..df7ba1219bf6 --- /dev/null +++ b/drivers/acpi/executer/exconvrt.c | |||
@@ -0,0 +1,708 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: exconvrt - Object conversion routines | ||
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 | |||
49 | |||
50 | #define _COMPONENT ACPI_EXECUTER | ||
51 | ACPI_MODULE_NAME ("exconvrt") | ||
52 | |||
53 | |||
54 | /******************************************************************************* | ||
55 | * | ||
56 | * FUNCTION: acpi_ex_convert_to_integer | ||
57 | * | ||
58 | * PARAMETERS: obj_desc - Object to be converted. Must be an | ||
59 | * Integer, Buffer, or String | ||
60 | * result_desc - Where the new Integer object is returned | ||
61 | * Flags - Used for string conversion | ||
62 | * | ||
63 | * RETURN: Status | ||
64 | * | ||
65 | * DESCRIPTION: Convert an ACPI Object to an integer. | ||
66 | * | ||
67 | ******************************************************************************/ | ||
68 | |||
69 | acpi_status | ||
70 | acpi_ex_convert_to_integer ( | ||
71 | union acpi_operand_object *obj_desc, | ||
72 | union acpi_operand_object **result_desc, | ||
73 | u32 flags) | ||
74 | { | ||
75 | union acpi_operand_object *return_desc; | ||
76 | u8 *pointer; | ||
77 | acpi_integer result; | ||
78 | u32 i; | ||
79 | u32 count; | ||
80 | acpi_status status; | ||
81 | |||
82 | |||
83 | ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_integer", obj_desc); | ||
84 | |||
85 | |||
86 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
87 | case ACPI_TYPE_INTEGER: | ||
88 | |||
89 | /* No conversion necessary */ | ||
90 | |||
91 | *result_desc = obj_desc; | ||
92 | return_ACPI_STATUS (AE_OK); | ||
93 | |||
94 | case ACPI_TYPE_BUFFER: | ||
95 | case ACPI_TYPE_STRING: | ||
96 | |||
97 | /* Note: Takes advantage of common buffer/string fields */ | ||
98 | |||
99 | pointer = obj_desc->buffer.pointer; | ||
100 | count = obj_desc->buffer.length; | ||
101 | break; | ||
102 | |||
103 | default: | ||
104 | return_ACPI_STATUS (AE_TYPE); | ||
105 | } | ||
106 | |||
107 | /* | ||
108 | * Convert the buffer/string to an integer. Note that both buffers and | ||
109 | * strings are treated as raw data - we don't convert ascii to hex for | ||
110 | * strings. | ||
111 | * | ||
112 | * There are two terminating conditions for the loop: | ||
113 | * 1) The size of an integer has been reached, or | ||
114 | * 2) The end of the buffer or string has been reached | ||
115 | */ | ||
116 | result = 0; | ||
117 | |||
118 | /* | ||
119 | * String conversion is different than Buffer conversion | ||
120 | */ | ||
121 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
122 | case ACPI_TYPE_STRING: | ||
123 | |||
124 | /* | ||
125 | * Convert string to an integer - for most cases, the string must be | ||
126 | * hexadecimal as per the ACPI specification. The only exception (as | ||
127 | * of ACPI 3.0) is that the to_integer() operator allows both decimal | ||
128 | * and hexadecimal strings (hex prefixed with "0x"). | ||
129 | */ | ||
130 | status = acpi_ut_strtoul64 ((char *) pointer, flags, &result); | ||
131 | if (ACPI_FAILURE (status)) { | ||
132 | return_ACPI_STATUS (status); | ||
133 | } | ||
134 | break; | ||
135 | |||
136 | |||
137 | case ACPI_TYPE_BUFFER: | ||
138 | |||
139 | /* Check for zero-length buffer */ | ||
140 | |||
141 | if (!count) { | ||
142 | return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); | ||
143 | } | ||
144 | |||
145 | /* Transfer no more than an integer's worth of data */ | ||
146 | |||
147 | if (count > acpi_gbl_integer_byte_width) { | ||
148 | count = acpi_gbl_integer_byte_width; | ||
149 | } | ||
150 | |||
151 | /* | ||
152 | * Convert buffer to an integer - we simply grab enough raw data | ||
153 | * from the buffer to fill an integer | ||
154 | */ | ||
155 | for (i = 0; i < count; i++) { | ||
156 | /* | ||
157 | * Get next byte and shift it into the Result. | ||
158 | * Little endian is used, meaning that the first byte of the buffer | ||
159 | * is the LSB of the integer | ||
160 | */ | ||
161 | result |= (((acpi_integer) pointer[i]) << (i * 8)); | ||
162 | } | ||
163 | break; | ||
164 | |||
165 | |||
166 | default: | ||
167 | /* No other types can get here */ | ||
168 | break; | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * Create a new integer | ||
173 | */ | ||
174 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
175 | if (!return_desc) { | ||
176 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
177 | } | ||
178 | |||
179 | /* Save the Result */ | ||
180 | |||
181 | return_desc->integer.value = result; | ||
182 | acpi_ex_truncate_for32bit_table (return_desc); | ||
183 | *result_desc = return_desc; | ||
184 | return_ACPI_STATUS (AE_OK); | ||
185 | } | ||
186 | |||
187 | |||
188 | /******************************************************************************* | ||
189 | * | ||
190 | * FUNCTION: acpi_ex_convert_to_buffer | ||
191 | * | ||
192 | * PARAMETERS: obj_desc - Object to be converted. Must be an | ||
193 | * Integer, Buffer, or String | ||
194 | * result_desc - Where the new buffer object is returned | ||
195 | * | ||
196 | * RETURN: Status | ||
197 | * | ||
198 | * DESCRIPTION: Convert an ACPI Object to a Buffer | ||
199 | * | ||
200 | ******************************************************************************/ | ||
201 | |||
202 | acpi_status | ||
203 | acpi_ex_convert_to_buffer ( | ||
204 | union acpi_operand_object *obj_desc, | ||
205 | union acpi_operand_object **result_desc) | ||
206 | { | ||
207 | union acpi_operand_object *return_desc; | ||
208 | u8 *new_buf; | ||
209 | |||
210 | |||
211 | ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_buffer", obj_desc); | ||
212 | |||
213 | |||
214 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
215 | case ACPI_TYPE_BUFFER: | ||
216 | |||
217 | /* No conversion necessary */ | ||
218 | |||
219 | *result_desc = obj_desc; | ||
220 | return_ACPI_STATUS (AE_OK); | ||
221 | |||
222 | |||
223 | case ACPI_TYPE_INTEGER: | ||
224 | |||
225 | /* | ||
226 | * Create a new Buffer object. | ||
227 | * Need enough space for one integer | ||
228 | */ | ||
229 | return_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width); | ||
230 | if (!return_desc) { | ||
231 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
232 | } | ||
233 | |||
234 | /* Copy the integer to the buffer, LSB first */ | ||
235 | |||
236 | new_buf = return_desc->buffer.pointer; | ||
237 | ACPI_MEMCPY (new_buf, | ||
238 | &obj_desc->integer.value, | ||
239 | acpi_gbl_integer_byte_width); | ||
240 | break; | ||
241 | |||
242 | |||
243 | case ACPI_TYPE_STRING: | ||
244 | |||
245 | /* | ||
246 | * Create a new Buffer object | ||
247 | * Size will be the string length | ||
248 | * | ||
249 | * NOTE: Add one to the string length to include the null terminator. | ||
250 | * The ACPI spec is unclear on this subject, but there is existing | ||
251 | * ASL/AML code that depends on the null being transferred to the new | ||
252 | * buffer. | ||
253 | */ | ||
254 | return_desc = acpi_ut_create_buffer_object ((acpi_size) obj_desc->string.length + 1); | ||
255 | if (!return_desc) { | ||
256 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
257 | } | ||
258 | |||
259 | /* Copy the string to the buffer */ | ||
260 | |||
261 | new_buf = return_desc->buffer.pointer; | ||
262 | ACPI_STRNCPY ((char *) new_buf, (char *) obj_desc->string.pointer, | ||
263 | obj_desc->string.length); | ||
264 | break; | ||
265 | |||
266 | |||
267 | default: | ||
268 | return_ACPI_STATUS (AE_TYPE); | ||
269 | } | ||
270 | |||
271 | /* Mark buffer initialized */ | ||
272 | |||
273 | return_desc->common.flags |= AOPOBJ_DATA_VALID; | ||
274 | *result_desc = return_desc; | ||
275 | return_ACPI_STATUS (AE_OK); | ||
276 | } | ||
277 | |||
278 | |||
279 | /******************************************************************************* | ||
280 | * | ||
281 | * FUNCTION: acpi_ex_convert_to_ascii | ||
282 | * | ||
283 | * PARAMETERS: Integer - Value to be converted | ||
284 | * Base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX | ||
285 | * String - Where the string is returned | ||
286 | * data_width - Size of data item to be converted, in bytes | ||
287 | * | ||
288 | * RETURN: Actual string length | ||
289 | * | ||
290 | * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string | ||
291 | * | ||
292 | ******************************************************************************/ | ||
293 | |||
294 | u32 | ||
295 | acpi_ex_convert_to_ascii ( | ||
296 | acpi_integer integer, | ||
297 | u16 base, | ||
298 | u8 *string, | ||
299 | u8 data_width) | ||
300 | { | ||
301 | acpi_integer digit; | ||
302 | acpi_native_uint i; | ||
303 | acpi_native_uint j; | ||
304 | acpi_native_uint k = 0; | ||
305 | acpi_native_uint hex_length; | ||
306 | acpi_native_uint decimal_length; | ||
307 | u32 remainder; | ||
308 | u8 supress_zeros; | ||
309 | |||
310 | |||
311 | ACPI_FUNCTION_ENTRY (); | ||
312 | |||
313 | |||
314 | switch (base) { | ||
315 | case 10: | ||
316 | |||
317 | /* Setup max length for the decimal number */ | ||
318 | |||
319 | switch (data_width) { | ||
320 | case 1: | ||
321 | decimal_length = ACPI_MAX8_DECIMAL_DIGITS; | ||
322 | break; | ||
323 | |||
324 | case 4: | ||
325 | decimal_length = ACPI_MAX32_DECIMAL_DIGITS; | ||
326 | break; | ||
327 | |||
328 | case 8: | ||
329 | default: | ||
330 | decimal_length = ACPI_MAX64_DECIMAL_DIGITS; | ||
331 | break; | ||
332 | } | ||
333 | |||
334 | supress_zeros = TRUE; /* No leading zeros */ | ||
335 | remainder = 0; | ||
336 | |||
337 | for (i = decimal_length; i > 0; i--) { | ||
338 | /* Divide by nth factor of 10 */ | ||
339 | |||
340 | digit = integer; | ||
341 | for (j = 0; j < i; j++) { | ||
342 | (void) acpi_ut_short_divide (digit, 10, &digit, &remainder); | ||
343 | } | ||
344 | |||
345 | /* Handle leading zeros */ | ||
346 | |||
347 | if (remainder != 0) { | ||
348 | supress_zeros = FALSE; | ||
349 | } | ||
350 | |||
351 | if (!supress_zeros) { | ||
352 | string[k] = (u8) (ACPI_ASCII_ZERO + remainder); | ||
353 | k++; | ||
354 | } | ||
355 | } | ||
356 | break; | ||
357 | |||
358 | case 16: | ||
359 | |||
360 | hex_length = ACPI_MUL_2 (data_width); /* 2 ascii hex chars per data byte */ | ||
361 | |||
362 | for (i = 0, j = (hex_length-1); i < hex_length; i++, j--) { | ||
363 | /* Get one hex digit, most significant digits first */ | ||
364 | |||
365 | string[k] = (u8) acpi_ut_hex_to_ascii_char (integer, ACPI_MUL_4 (j)); | ||
366 | k++; | ||
367 | } | ||
368 | break; | ||
369 | |||
370 | default: | ||
371 | return (0); | ||
372 | } | ||
373 | |||
374 | /* | ||
375 | * Since leading zeros are supressed, we must check for the case where | ||
376 | * the integer equals 0 | ||
377 | * | ||
378 | * Finally, null terminate the string and return the length | ||
379 | */ | ||
380 | if (!k) { | ||
381 | string [0] = ACPI_ASCII_ZERO; | ||
382 | k = 1; | ||
383 | } | ||
384 | |||
385 | string [k] = 0; | ||
386 | return ((u32) k); | ||
387 | } | ||
388 | |||
389 | |||
390 | /******************************************************************************* | ||
391 | * | ||
392 | * FUNCTION: acpi_ex_convert_to_string | ||
393 | * | ||
394 | * PARAMETERS: obj_desc - Object to be converted. Must be an | ||
395 | * Integer, Buffer, or String | ||
396 | * result_desc - Where the string object is returned | ||
397 | * Type - String flags (base and conversion type) | ||
398 | * | ||
399 | * RETURN: Status | ||
400 | * | ||
401 | * DESCRIPTION: Convert an ACPI Object to a string | ||
402 | * | ||
403 | ******************************************************************************/ | ||
404 | |||
405 | acpi_status | ||
406 | acpi_ex_convert_to_string ( | ||
407 | union acpi_operand_object *obj_desc, | ||
408 | union acpi_operand_object **result_desc, | ||
409 | u32 type) | ||
410 | { | ||
411 | union acpi_operand_object *return_desc; | ||
412 | u8 *new_buf; | ||
413 | u32 i; | ||
414 | u32 string_length = 0; | ||
415 | u16 base = 16; | ||
416 | u8 separator = ','; | ||
417 | |||
418 | |||
419 | ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_string", obj_desc); | ||
420 | |||
421 | |||
422 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
423 | case ACPI_TYPE_STRING: | ||
424 | |||
425 | /* No conversion necessary */ | ||
426 | |||
427 | *result_desc = obj_desc; | ||
428 | return_ACPI_STATUS (AE_OK); | ||
429 | |||
430 | |||
431 | case ACPI_TYPE_INTEGER: | ||
432 | |||
433 | switch (type) { | ||
434 | case ACPI_EXPLICIT_CONVERT_DECIMAL: | ||
435 | |||
436 | /* Make room for maximum decimal number */ | ||
437 | |||
438 | string_length = ACPI_MAX_DECIMAL_DIGITS; | ||
439 | base = 10; | ||
440 | break; | ||
441 | |||
442 | default: | ||
443 | |||
444 | /* Two hex string characters for each integer byte */ | ||
445 | |||
446 | string_length = ACPI_MUL_2 (acpi_gbl_integer_byte_width); | ||
447 | break; | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * Create a new String | ||
452 | * Need enough space for one ASCII integer (plus null terminator) | ||
453 | */ | ||
454 | return_desc = acpi_ut_create_string_object ((acpi_size) string_length); | ||
455 | if (!return_desc) { | ||
456 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
457 | } | ||
458 | |||
459 | new_buf = return_desc->buffer.pointer; | ||
460 | |||
461 | /* Convert integer to string */ | ||
462 | |||
463 | string_length = acpi_ex_convert_to_ascii (obj_desc->integer.value, base, | ||
464 | new_buf, acpi_gbl_integer_byte_width); | ||
465 | |||
466 | /* Null terminate at the correct place */ | ||
467 | |||
468 | return_desc->string.length = string_length; | ||
469 | new_buf [string_length] = 0; | ||
470 | break; | ||
471 | |||
472 | |||
473 | case ACPI_TYPE_BUFFER: | ||
474 | |||
475 | /* Setup string length, base, and separator */ | ||
476 | |||
477 | switch (type) { | ||
478 | case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string operator */ | ||
479 | /* | ||
480 | * From ACPI: "If Data is a buffer, it is converted to a string of | ||
481 | * decimal values separated by commas." | ||
482 | */ | ||
483 | base = 10; | ||
484 | |||
485 | /* | ||
486 | * Calculate the final string length. Individual string values | ||
487 | * are variable length (include separator for each) | ||
488 | */ | ||
489 | for (i = 0; i < obj_desc->buffer.length; i++) { | ||
490 | if (obj_desc->buffer.pointer[i] >= 100) { | ||
491 | string_length += 4; | ||
492 | } | ||
493 | else if (obj_desc->buffer.pointer[i] >= 10) { | ||
494 | string_length += 3; | ||
495 | } | ||
496 | else { | ||
497 | string_length += 2; | ||
498 | } | ||
499 | } | ||
500 | break; | ||
501 | |||
502 | case ACPI_IMPLICIT_CONVERT_HEX: | ||
503 | /* | ||
504 | * From the ACPI spec: | ||
505 | *"The entire contents of the buffer are converted to a string of | ||
506 | * two-character hexadecimal numbers, each separated by a space." | ||
507 | */ | ||
508 | separator = ' '; | ||
509 | string_length = (obj_desc->buffer.length * 3); | ||
510 | break; | ||
511 | |||
512 | case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string operator */ | ||
513 | /* | ||
514 | * From ACPI: "If Data is a buffer, it is converted to a string of | ||
515 | * hexadecimal values separated by commas." | ||
516 | */ | ||
517 | string_length = (obj_desc->buffer.length * 3); | ||
518 | break; | ||
519 | |||
520 | default: | ||
521 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
522 | } | ||
523 | |||
524 | /* | ||
525 | * Perform the conversion. | ||
526 | * (-1 because of extra separator included in string_length from above) | ||
527 | */ | ||
528 | string_length--; | ||
529 | if (string_length > ACPI_MAX_STRING_CONVERSION) /* ACPI limit */ { | ||
530 | return_ACPI_STATUS (AE_AML_STRING_LIMIT); | ||
531 | } | ||
532 | |||
533 | /* | ||
534 | * Create a new string object and string buffer | ||
535 | */ | ||
536 | return_desc = acpi_ut_create_string_object ((acpi_size) string_length); | ||
537 | if (!return_desc) { | ||
538 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
539 | } | ||
540 | |||
541 | new_buf = return_desc->buffer.pointer; | ||
542 | |||
543 | /* | ||
544 | * Convert buffer bytes to hex or decimal values | ||
545 | * (separated by commas or spaces) | ||
546 | */ | ||
547 | for (i = 0; i < obj_desc->buffer.length; i++) { | ||
548 | new_buf += acpi_ex_convert_to_ascii ( | ||
549 | (acpi_integer) obj_desc->buffer.pointer[i], base, | ||
550 | new_buf, 1); | ||
551 | *new_buf++ = separator; /* each separated by a comma or space */ | ||
552 | } | ||
553 | |||
554 | /* Null terminate the string (overwrites final comma/space from above) */ | ||
555 | |||
556 | new_buf--; | ||
557 | *new_buf = 0; | ||
558 | break; | ||
559 | |||
560 | default: | ||
561 | return_ACPI_STATUS (AE_TYPE); | ||
562 | } | ||
563 | |||
564 | *result_desc = return_desc; | ||
565 | return_ACPI_STATUS (AE_OK); | ||
566 | } | ||
567 | |||
568 | |||
569 | /******************************************************************************* | ||
570 | * | ||
571 | * FUNCTION: acpi_ex_convert_to_target_type | ||
572 | * | ||
573 | * PARAMETERS: destination_type - Current type of the destination | ||
574 | * source_desc - Source object to be converted. | ||
575 | * result_desc - Where the converted object is returned | ||
576 | * walk_state - Current method state | ||
577 | * | ||
578 | * RETURN: Status | ||
579 | * | ||
580 | * DESCRIPTION: Implements "implicit conversion" rules for storing an object. | ||
581 | * | ||
582 | ******************************************************************************/ | ||
583 | |||
584 | acpi_status | ||
585 | acpi_ex_convert_to_target_type ( | ||
586 | acpi_object_type destination_type, | ||
587 | union acpi_operand_object *source_desc, | ||
588 | union acpi_operand_object **result_desc, | ||
589 | struct acpi_walk_state *walk_state) | ||
590 | { | ||
591 | acpi_status status = AE_OK; | ||
592 | |||
593 | |||
594 | ACPI_FUNCTION_TRACE ("ex_convert_to_target_type"); | ||
595 | |||
596 | |||
597 | /* Default behavior */ | ||
598 | |||
599 | *result_desc = source_desc; | ||
600 | |||
601 | /* | ||
602 | * If required by the target, | ||
603 | * perform implicit conversion on the source before we store it. | ||
604 | */ | ||
605 | switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)) { | ||
606 | case ARGI_SIMPLE_TARGET: | ||
607 | case ARGI_FIXED_TARGET: | ||
608 | case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ | ||
609 | |||
610 | switch (destination_type) { | ||
611 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
612 | /* | ||
613 | * Named field can always handle conversions | ||
614 | */ | ||
615 | break; | ||
616 | |||
617 | default: | ||
618 | /* No conversion allowed for these types */ | ||
619 | |||
620 | if (destination_type != ACPI_GET_OBJECT_TYPE (source_desc)) { | ||
621 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
622 | "Explicit operator, will store (%s) over existing type (%s)\n", | ||
623 | acpi_ut_get_object_type_name (source_desc), | ||
624 | acpi_ut_get_type_name (destination_type))); | ||
625 | status = AE_TYPE; | ||
626 | } | ||
627 | } | ||
628 | break; | ||
629 | |||
630 | |||
631 | case ARGI_TARGETREF: | ||
632 | |||
633 | switch (destination_type) { | ||
634 | case ACPI_TYPE_INTEGER: | ||
635 | case ACPI_TYPE_BUFFER_FIELD: | ||
636 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
637 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
638 | /* | ||
639 | * These types require an Integer operand. We can convert | ||
640 | * a Buffer or a String to an Integer if necessary. | ||
641 | */ | ||
642 | status = acpi_ex_convert_to_integer (source_desc, result_desc, | ||
643 | 16); | ||
644 | break; | ||
645 | |||
646 | |||
647 | case ACPI_TYPE_STRING: | ||
648 | |||
649 | /* | ||
650 | * The operand must be a String. We can convert an | ||
651 | * Integer or Buffer if necessary | ||
652 | */ | ||
653 | status = acpi_ex_convert_to_string (source_desc, result_desc, | ||
654 | ACPI_IMPLICIT_CONVERT_HEX); | ||
655 | break; | ||
656 | |||
657 | |||
658 | case ACPI_TYPE_BUFFER: | ||
659 | |||
660 | /* | ||
661 | * The operand must be a Buffer. We can convert an | ||
662 | * Integer or String if necessary | ||
663 | */ | ||
664 | status = acpi_ex_convert_to_buffer (source_desc, result_desc); | ||
665 | break; | ||
666 | |||
667 | |||
668 | default: | ||
669 | ACPI_REPORT_ERROR (("Bad destination type during conversion: %X\n", | ||
670 | destination_type)); | ||
671 | status = AE_AML_INTERNAL; | ||
672 | break; | ||
673 | } | ||
674 | break; | ||
675 | |||
676 | |||
677 | case ARGI_REFERENCE: | ||
678 | /* | ||
679 | * create_xxxx_field cases - we are storing the field object into the name | ||
680 | */ | ||
681 | break; | ||
682 | |||
683 | |||
684 | default: | ||
685 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
686 | "Unknown Target type ID 0x%X Op %s dest_type %s\n", | ||
687 | GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args), | ||
688 | walk_state->op_info->name, acpi_ut_get_type_name (destination_type))); | ||
689 | |||
690 | ACPI_REPORT_ERROR (("Bad Target Type (ARGI): %X\n", | ||
691 | GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args))) | ||
692 | status = AE_AML_INTERNAL; | ||
693 | } | ||
694 | |||
695 | /* | ||
696 | * Source-to-Target conversion semantics: | ||
697 | * | ||
698 | * If conversion to the target type cannot be performed, then simply | ||
699 | * overwrite the target with the new object and type. | ||
700 | */ | ||
701 | if (status == AE_TYPE) { | ||
702 | status = AE_OK; | ||
703 | } | ||
704 | |||
705 | return_ACPI_STATUS (status); | ||
706 | } | ||
707 | |||
708 | |||
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c new file mode 100644 index 000000000000..d94c260dac6d --- /dev/null +++ b/drivers/acpi/executer/excreate.c | |||
@@ -0,0 +1,646 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: excreate - Named object creation | ||
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 | |||
52 | |||
53 | #define _COMPONENT ACPI_EXECUTER | ||
54 | ACPI_MODULE_NAME ("excreate") | ||
55 | |||
56 | |||
57 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
58 | /***************************************************************************** | ||
59 | * | ||
60 | * FUNCTION: acpi_ex_create_alias | ||
61 | * | ||
62 | * PARAMETERS: walk_state - Current state, contains operands | ||
63 | * | ||
64 | * RETURN: Status | ||
65 | * | ||
66 | * DESCRIPTION: Create a new named alias | ||
67 | * | ||
68 | ****************************************************************************/ | ||
69 | |||
70 | acpi_status | ||
71 | acpi_ex_create_alias ( | ||
72 | struct acpi_walk_state *walk_state) | ||
73 | { | ||
74 | struct acpi_namespace_node *target_node; | ||
75 | struct acpi_namespace_node *alias_node; | ||
76 | acpi_status status = AE_OK; | ||
77 | |||
78 | |||
79 | ACPI_FUNCTION_TRACE ("ex_create_alias"); | ||
80 | |||
81 | |||
82 | /* Get the source/alias operands (both namespace nodes) */ | ||
83 | |||
84 | alias_node = (struct acpi_namespace_node *) walk_state->operands[0]; | ||
85 | target_node = (struct acpi_namespace_node *) walk_state->operands[1]; | ||
86 | |||
87 | if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) || | ||
88 | (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { | ||
89 | /* | ||
90 | * Dereference an existing alias so that we don't create a chain | ||
91 | * of aliases. With this code, we guarantee that an alias is | ||
92 | * always exactly one level of indirection away from the | ||
93 | * actual aliased name. | ||
94 | */ | ||
95 | target_node = ACPI_CAST_PTR (struct acpi_namespace_node, target_node->object); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * For objects that can never change (i.e., the NS node will | ||
100 | * permanently point to the same object), we can simply attach | ||
101 | * the object to the new NS node. For other objects (such as | ||
102 | * Integers, buffers, etc.), we have to point the Alias node | ||
103 | * to the original Node. | ||
104 | */ | ||
105 | switch (target_node->type) { | ||
106 | case ACPI_TYPE_INTEGER: | ||
107 | case ACPI_TYPE_STRING: | ||
108 | case ACPI_TYPE_BUFFER: | ||
109 | case ACPI_TYPE_PACKAGE: | ||
110 | case ACPI_TYPE_BUFFER_FIELD: | ||
111 | |||
112 | /* | ||
113 | * The new alias has the type ALIAS and points to the original | ||
114 | * NS node, not the object itself. This is because for these | ||
115 | * types, the object can change dynamically via a Store. | ||
116 | */ | ||
117 | alias_node->type = ACPI_TYPE_LOCAL_ALIAS; | ||
118 | alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node); | ||
119 | break; | ||
120 | |||
121 | case ACPI_TYPE_METHOD: | ||
122 | |||
123 | /* | ||
124 | * The new alias has the type ALIAS and points to the original | ||
125 | * NS node, not the object itself. This is because for these | ||
126 | * types, the object can change dynamically via a Store. | ||
127 | */ | ||
128 | alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS; | ||
129 | alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node); | ||
130 | break; | ||
131 | |||
132 | default: | ||
133 | |||
134 | /* Attach the original source object to the new Alias Node */ | ||
135 | |||
136 | /* | ||
137 | * The new alias assumes the type of the target, and it points | ||
138 | * to the same object. The reference count of the object has an | ||
139 | * additional reference to prevent deletion out from under either the | ||
140 | * target node or the alias Node | ||
141 | */ | ||
142 | status = acpi_ns_attach_object (alias_node, | ||
143 | acpi_ns_get_attached_object (target_node), | ||
144 | target_node->type); | ||
145 | break; | ||
146 | } | ||
147 | |||
148 | /* Since both operands are Nodes, we don't need to delete them */ | ||
149 | |||
150 | return_ACPI_STATUS (status); | ||
151 | } | ||
152 | |||
153 | |||
154 | /***************************************************************************** | ||
155 | * | ||
156 | * FUNCTION: acpi_ex_create_event | ||
157 | * | ||
158 | * PARAMETERS: walk_state - Current state | ||
159 | * | ||
160 | * RETURN: Status | ||
161 | * | ||
162 | * DESCRIPTION: Create a new event object | ||
163 | * | ||
164 | ****************************************************************************/ | ||
165 | |||
166 | acpi_status | ||
167 | acpi_ex_create_event ( | ||
168 | struct acpi_walk_state *walk_state) | ||
169 | { | ||
170 | acpi_status status; | ||
171 | union acpi_operand_object *obj_desc; | ||
172 | |||
173 | |||
174 | ACPI_FUNCTION_TRACE ("ex_create_event"); | ||
175 | |||
176 | |||
177 | obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_EVENT); | ||
178 | if (!obj_desc) { | ||
179 | status = AE_NO_MEMORY; | ||
180 | goto cleanup; | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * Create the actual OS semaphore, with zero initial units -- meaning | ||
185 | * that the event is created in an unsignalled state | ||
186 | */ | ||
187 | status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, | ||
188 | &obj_desc->event.semaphore); | ||
189 | if (ACPI_FAILURE (status)) { | ||
190 | goto cleanup; | ||
191 | } | ||
192 | |||
193 | /* Attach object to the Node */ | ||
194 | |||
195 | status = acpi_ns_attach_object ((struct acpi_namespace_node *) walk_state->operands[0], | ||
196 | obj_desc, ACPI_TYPE_EVENT); | ||
197 | |||
198 | cleanup: | ||
199 | /* | ||
200 | * Remove local reference to the object (on error, will cause deletion | ||
201 | * of both object and semaphore if present.) | ||
202 | */ | ||
203 | acpi_ut_remove_reference (obj_desc); | ||
204 | return_ACPI_STATUS (status); | ||
205 | } | ||
206 | |||
207 | |||
208 | /***************************************************************************** | ||
209 | * | ||
210 | * FUNCTION: acpi_ex_create_mutex | ||
211 | * | ||
212 | * PARAMETERS: walk_state - Current state | ||
213 | * | ||
214 | * RETURN: Status | ||
215 | * | ||
216 | * DESCRIPTION: Create a new mutex object | ||
217 | * | ||
218 | * Mutex (Name[0], sync_level[1]) | ||
219 | * | ||
220 | ****************************************************************************/ | ||
221 | |||
222 | acpi_status | ||
223 | acpi_ex_create_mutex ( | ||
224 | struct acpi_walk_state *walk_state) | ||
225 | { | ||
226 | acpi_status status = AE_OK; | ||
227 | union acpi_operand_object *obj_desc; | ||
228 | |||
229 | |||
230 | ACPI_FUNCTION_TRACE_PTR ("ex_create_mutex", ACPI_WALK_OPERANDS); | ||
231 | |||
232 | |||
233 | /* Create the new mutex object */ | ||
234 | |||
235 | obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_MUTEX); | ||
236 | if (!obj_desc) { | ||
237 | status = AE_NO_MEMORY; | ||
238 | goto cleanup; | ||
239 | } | ||
240 | |||
241 | /* | ||
242 | * Create the actual OS semaphore. | ||
243 | * One unit max to make it a mutex, with one initial unit to allow | ||
244 | * the mutex to be acquired. | ||
245 | */ | ||
246 | status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore); | ||
247 | if (ACPI_FAILURE (status)) { | ||
248 | goto cleanup; | ||
249 | } | ||
250 | |||
251 | /* Init object and attach to NS node */ | ||
252 | |||
253 | obj_desc->mutex.sync_level = (u8) walk_state->operands[1]->integer.value; | ||
254 | obj_desc->mutex.node = (struct acpi_namespace_node *) walk_state->operands[0]; | ||
255 | |||
256 | status = acpi_ns_attach_object (obj_desc->mutex.node, | ||
257 | obj_desc, ACPI_TYPE_MUTEX); | ||
258 | |||
259 | |||
260 | cleanup: | ||
261 | /* | ||
262 | * Remove local reference to the object (on error, will cause deletion | ||
263 | * of both object and semaphore if present.) | ||
264 | */ | ||
265 | acpi_ut_remove_reference (obj_desc); | ||
266 | return_ACPI_STATUS (status); | ||
267 | } | ||
268 | |||
269 | |||
270 | /***************************************************************************** | ||
271 | * | ||
272 | * FUNCTION: acpi_ex_create_region | ||
273 | * | ||
274 | * PARAMETERS: aml_start - Pointer to the region declaration AML | ||
275 | * aml_length - Max length of the declaration AML | ||
276 | * Operands - List of operands for the opcode | ||
277 | * walk_state - Current state | ||
278 | * | ||
279 | * RETURN: Status | ||
280 | * | ||
281 | * DESCRIPTION: Create a new operation region object | ||
282 | * | ||
283 | ****************************************************************************/ | ||
284 | |||
285 | acpi_status | ||
286 | acpi_ex_create_region ( | ||
287 | u8 *aml_start, | ||
288 | u32 aml_length, | ||
289 | u8 region_space, | ||
290 | struct acpi_walk_state *walk_state) | ||
291 | { | ||
292 | acpi_status status; | ||
293 | union acpi_operand_object *obj_desc; | ||
294 | struct acpi_namespace_node *node; | ||
295 | union acpi_operand_object *region_obj2; | ||
296 | |||
297 | |||
298 | ACPI_FUNCTION_TRACE ("ex_create_region"); | ||
299 | |||
300 | |||
301 | /* Get the Namespace Node */ | ||
302 | |||
303 | node = walk_state->op->common.node; | ||
304 | |||
305 | /* | ||
306 | * If the region object is already attached to this node, | ||
307 | * just return | ||
308 | */ | ||
309 | if (acpi_ns_get_attached_object (node)) { | ||
310 | return_ACPI_STATUS (AE_OK); | ||
311 | } | ||
312 | |||
313 | /* | ||
314 | * Space ID must be one of the predefined IDs, or in the user-defined | ||
315 | * range | ||
316 | */ | ||
317 | if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) && | ||
318 | (region_space < ACPI_USER_REGION_BEGIN)) { | ||
319 | ACPI_REPORT_ERROR (("Invalid address_space type %X\n", region_space)); | ||
320 | return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID); | ||
321 | } | ||
322 | |||
323 | ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (%X)\n", | ||
324 | acpi_ut_get_region_name (region_space), region_space)); | ||
325 | |||
326 | /* Create the region descriptor */ | ||
327 | |||
328 | obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION); | ||
329 | if (!obj_desc) { | ||
330 | status = AE_NO_MEMORY; | ||
331 | goto cleanup; | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * Remember location in AML stream of address & length | ||
336 | * operands since they need to be evaluated at run time. | ||
337 | */ | ||
338 | region_obj2 = obj_desc->common.next_object; | ||
339 | region_obj2->extra.aml_start = aml_start; | ||
340 | region_obj2->extra.aml_length = aml_length; | ||
341 | |||
342 | /* Init the region from the operands */ | ||
343 | |||
344 | obj_desc->region.space_id = region_space; | ||
345 | obj_desc->region.address = 0; | ||
346 | obj_desc->region.length = 0; | ||
347 | obj_desc->region.node = node; | ||
348 | |||
349 | /* Install the new region object in the parent Node */ | ||
350 | |||
351 | status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION); | ||
352 | |||
353 | |||
354 | cleanup: | ||
355 | |||
356 | /* Remove local reference to the object */ | ||
357 | |||
358 | acpi_ut_remove_reference (obj_desc); | ||
359 | return_ACPI_STATUS (status); | ||
360 | } | ||
361 | |||
362 | |||
363 | /***************************************************************************** | ||
364 | * | ||
365 | * FUNCTION: acpi_ex_create_table_region | ||
366 | * | ||
367 | * PARAMETERS: walk_state - Current state | ||
368 | * | ||
369 | * RETURN: Status | ||
370 | * | ||
371 | * DESCRIPTION: Create a new data_table_region object | ||
372 | * | ||
373 | ****************************************************************************/ | ||
374 | |||
375 | acpi_status | ||
376 | acpi_ex_create_table_region ( | ||
377 | struct acpi_walk_state *walk_state) | ||
378 | { | ||
379 | acpi_status status; | ||
380 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
381 | union acpi_operand_object *obj_desc; | ||
382 | struct acpi_namespace_node *node; | ||
383 | struct acpi_table_header *table; | ||
384 | union acpi_operand_object *region_obj2; | ||
385 | |||
386 | |||
387 | ACPI_FUNCTION_TRACE ("ex_create_table_region"); | ||
388 | |||
389 | |||
390 | /* Get the Node from the object stack */ | ||
391 | |||
392 | node = walk_state->op->common.node; | ||
393 | |||
394 | /* | ||
395 | * If the region object is already attached to this node, | ||
396 | * just return | ||
397 | */ | ||
398 | if (acpi_ns_get_attached_object (node)) { | ||
399 | return_ACPI_STATUS (AE_OK); | ||
400 | } | ||
401 | |||
402 | /* Find the ACPI table */ | ||
403 | |||
404 | status = acpi_tb_find_table (operand[1]->string.pointer, | ||
405 | operand[2]->string.pointer, | ||
406 | operand[3]->string.pointer, &table); | ||
407 | if (ACPI_FAILURE (status)) { | ||
408 | return_ACPI_STATUS (status); | ||
409 | } | ||
410 | |||
411 | /* Create the region descriptor */ | ||
412 | |||
413 | obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION); | ||
414 | if (!obj_desc) { | ||
415 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
416 | } | ||
417 | |||
418 | region_obj2 = obj_desc->common.next_object; | ||
419 | region_obj2->extra.region_context = NULL; | ||
420 | |||
421 | /* Init the region from the operands */ | ||
422 | |||
423 | obj_desc->region.space_id = REGION_DATA_TABLE; | ||
424 | obj_desc->region.address = (acpi_physical_address) ACPI_TO_INTEGER (table); | ||
425 | obj_desc->region.length = table->length; | ||
426 | obj_desc->region.node = node; | ||
427 | obj_desc->region.flags = AOPOBJ_DATA_VALID; | ||
428 | |||
429 | /* Install the new region object in the parent Node */ | ||
430 | |||
431 | status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION); | ||
432 | if (ACPI_FAILURE (status)) { | ||
433 | goto cleanup; | ||
434 | } | ||
435 | |||
436 | status = acpi_ev_initialize_region (obj_desc, FALSE); | ||
437 | if (ACPI_FAILURE (status)) { | ||
438 | if (status == AE_NOT_EXIST) { | ||
439 | status = AE_OK; | ||
440 | } | ||
441 | else { | ||
442 | goto cleanup; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE; | ||
447 | |||
448 | |||
449 | cleanup: | ||
450 | |||
451 | /* Remove local reference to the object */ | ||
452 | |||
453 | acpi_ut_remove_reference (obj_desc); | ||
454 | return_ACPI_STATUS (status); | ||
455 | } | ||
456 | |||
457 | |||
458 | /***************************************************************************** | ||
459 | * | ||
460 | * FUNCTION: acpi_ex_create_processor | ||
461 | * | ||
462 | * PARAMETERS: walk_state - Current state | ||
463 | * | ||
464 | * RETURN: Status | ||
465 | * | ||
466 | * DESCRIPTION: Create a new processor object and populate the fields | ||
467 | * | ||
468 | * Processor (Name[0], cpu_iD[1], pblock_addr[2], pblock_length[3]) | ||
469 | * | ||
470 | ****************************************************************************/ | ||
471 | |||
472 | acpi_status | ||
473 | acpi_ex_create_processor ( | ||
474 | struct acpi_walk_state *walk_state) | ||
475 | { | ||
476 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
477 | union acpi_operand_object *obj_desc; | ||
478 | acpi_status status; | ||
479 | |||
480 | |||
481 | ACPI_FUNCTION_TRACE_PTR ("ex_create_processor", walk_state); | ||
482 | |||
483 | |||
484 | /* Create the processor object */ | ||
485 | |||
486 | obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PROCESSOR); | ||
487 | if (!obj_desc) { | ||
488 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
489 | } | ||
490 | |||
491 | /* | ||
492 | * Initialize the processor object from the operands | ||
493 | */ | ||
494 | obj_desc->processor.proc_id = (u8) operand[1]->integer.value; | ||
495 | obj_desc->processor.address = (acpi_io_address) operand[2]->integer.value; | ||
496 | obj_desc->processor.length = (u8) operand[3]->integer.value; | ||
497 | |||
498 | /* Install the processor object in the parent Node */ | ||
499 | |||
500 | status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0], | ||
501 | obj_desc, ACPI_TYPE_PROCESSOR); | ||
502 | |||
503 | /* Remove local reference to the object */ | ||
504 | |||
505 | acpi_ut_remove_reference (obj_desc); | ||
506 | return_ACPI_STATUS (status); | ||
507 | } | ||
508 | |||
509 | |||
510 | /***************************************************************************** | ||
511 | * | ||
512 | * FUNCTION: acpi_ex_create_power_resource | ||
513 | * | ||
514 | * PARAMETERS: walk_state - Current state | ||
515 | * | ||
516 | * RETURN: Status | ||
517 | * | ||
518 | * DESCRIPTION: Create a new power_resource object and populate the fields | ||
519 | * | ||
520 | * power_resource (Name[0], system_level[1], resource_order[2]) | ||
521 | * | ||
522 | ****************************************************************************/ | ||
523 | |||
524 | acpi_status | ||
525 | acpi_ex_create_power_resource ( | ||
526 | struct acpi_walk_state *walk_state) | ||
527 | { | ||
528 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
529 | acpi_status status; | ||
530 | union acpi_operand_object *obj_desc; | ||
531 | |||
532 | |||
533 | ACPI_FUNCTION_TRACE_PTR ("ex_create_power_resource", walk_state); | ||
534 | |||
535 | |||
536 | /* Create the power resource object */ | ||
537 | |||
538 | obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_POWER); | ||
539 | if (!obj_desc) { | ||
540 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
541 | } | ||
542 | |||
543 | /* Initialize the power object from the operands */ | ||
544 | |||
545 | obj_desc->power_resource.system_level = (u8) operand[1]->integer.value; | ||
546 | obj_desc->power_resource.resource_order = (u16) operand[2]->integer.value; | ||
547 | |||
548 | /* Install the power resource object in the parent Node */ | ||
549 | |||
550 | status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0], | ||
551 | obj_desc, ACPI_TYPE_POWER); | ||
552 | |||
553 | /* Remove local reference to the object */ | ||
554 | |||
555 | acpi_ut_remove_reference (obj_desc); | ||
556 | return_ACPI_STATUS (status); | ||
557 | } | ||
558 | |||
559 | #endif | ||
560 | |||
561 | /***************************************************************************** | ||
562 | * | ||
563 | * FUNCTION: acpi_ex_create_method | ||
564 | * | ||
565 | * PARAMETERS: aml_start - First byte of the method's AML | ||
566 | * aml_length - AML byte count for this method | ||
567 | * walk_state - Current state | ||
568 | * | ||
569 | * RETURN: Status | ||
570 | * | ||
571 | * DESCRIPTION: Create a new method object | ||
572 | * | ||
573 | ****************************************************************************/ | ||
574 | |||
575 | acpi_status | ||
576 | acpi_ex_create_method ( | ||
577 | u8 *aml_start, | ||
578 | u32 aml_length, | ||
579 | struct acpi_walk_state *walk_state) | ||
580 | { | ||
581 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
582 | union acpi_operand_object *obj_desc; | ||
583 | acpi_status status; | ||
584 | u8 method_flags; | ||
585 | |||
586 | |||
587 | ACPI_FUNCTION_TRACE_PTR ("ex_create_method", walk_state); | ||
588 | |||
589 | |||
590 | /* Create a new method object */ | ||
591 | |||
592 | obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_METHOD); | ||
593 | if (!obj_desc) { | ||
594 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
595 | } | ||
596 | |||
597 | /* Save the method's AML pointer and length */ | ||
598 | |||
599 | obj_desc->method.aml_start = aml_start; | ||
600 | obj_desc->method.aml_length = aml_length; | ||
601 | |||
602 | /* | ||
603 | * Disassemble the method flags. Split off the Arg Count | ||
604 | * for efficiency | ||
605 | */ | ||
606 | method_flags = (u8) operand[1]->integer.value; | ||
607 | |||
608 | obj_desc->method.method_flags = (u8) (method_flags & ~AML_METHOD_ARG_COUNT); | ||
609 | obj_desc->method.param_count = (u8) (method_flags & AML_METHOD_ARG_COUNT); | ||
610 | |||
611 | /* | ||
612 | * Get the concurrency count. If required, a semaphore will be | ||
613 | * created for this method when it is parsed. | ||
614 | */ | ||
615 | if (acpi_gbl_all_methods_serialized) { | ||
616 | obj_desc->method.concurrency = 1; | ||
617 | obj_desc->method.method_flags |= AML_METHOD_SERIALIZED; | ||
618 | } | ||
619 | else if (method_flags & AML_METHOD_SERIALIZED) { | ||
620 | /* | ||
621 | * ACPI 1.0: Concurrency = 1 | ||
622 | * ACPI 2.0: Concurrency = (sync_level (in method declaration) + 1) | ||
623 | */ | ||
624 | obj_desc->method.concurrency = (u8) | ||
625 | (((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4) + 1); | ||
626 | } | ||
627 | else { | ||
628 | obj_desc->method.concurrency = ACPI_INFINITE_CONCURRENCY; | ||
629 | } | ||
630 | |||
631 | /* Attach the new object to the method Node */ | ||
632 | |||
633 | status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0], | ||
634 | obj_desc, ACPI_TYPE_METHOD); | ||
635 | |||
636 | /* Remove local reference to the object */ | ||
637 | |||
638 | acpi_ut_remove_reference (obj_desc); | ||
639 | |||
640 | /* Remove a reference to the operand */ | ||
641 | |||
642 | acpi_ut_remove_reference (operand[1]); | ||
643 | return_ACPI_STATUS (status); | ||
644 | } | ||
645 | |||
646 | |||
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c new file mode 100644 index 000000000000..e2f7c32f28de --- /dev/null +++ b/drivers/acpi/executer/exdump.c | |||
@@ -0,0 +1,793 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: exdump - Interpreter debug output routines | ||
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/acparser.h> | ||
50 | |||
51 | #define _COMPONENT ACPI_EXECUTER | ||
52 | ACPI_MODULE_NAME ("exdump") | ||
53 | |||
54 | |||
55 | /* | ||
56 | * The following routines are used for debug output only | ||
57 | */ | ||
58 | #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) | ||
59 | |||
60 | /***************************************************************************** | ||
61 | * | ||
62 | * FUNCTION: acpi_ex_dump_operand | ||
63 | * | ||
64 | * PARAMETERS: *obj_desc - Pointer to entry to be dumped | ||
65 | * | ||
66 | * RETURN: None | ||
67 | * | ||
68 | * DESCRIPTION: Dump an operand object | ||
69 | * | ||
70 | ****************************************************************************/ | ||
71 | |||
72 | void | ||
73 | acpi_ex_dump_operand ( | ||
74 | union acpi_operand_object *obj_desc, | ||
75 | u32 depth) | ||
76 | { | ||
77 | u32 length; | ||
78 | u32 index; | ||
79 | |||
80 | |||
81 | ACPI_FUNCTION_NAME ("ex_dump_operand") | ||
82 | |||
83 | |||
84 | if (!((ACPI_LV_EXEC & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) { | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | if (!obj_desc) { | ||
89 | /* | ||
90 | * This could be a null element of a package | ||
91 | */ | ||
92 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Null Object Descriptor\n")); | ||
93 | return; | ||
94 | } | ||
95 | |||
96 | if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) { | ||
97 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p is a NS Node: ", obj_desc)); | ||
98 | ACPI_DUMP_ENTRY (obj_desc, ACPI_LV_EXEC); | ||
99 | return; | ||
100 | } | ||
101 | |||
102 | if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { | ||
103 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, | ||
104 | "%p is not a node or operand object: [%s]\n", | ||
105 | obj_desc, acpi_ut_get_descriptor_name (obj_desc))); | ||
106 | ACPI_DUMP_BUFFER (obj_desc, sizeof (union acpi_operand_object)); | ||
107 | return; | ||
108 | } | ||
109 | |||
110 | /* obj_desc is a valid object */ | ||
111 | |||
112 | if (depth > 0) { | ||
113 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%*s[%u] %p ", | ||
114 | depth, " ", depth, obj_desc)); | ||
115 | } | ||
116 | else { | ||
117 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p ", obj_desc)); | ||
118 | } | ||
119 | |||
120 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
121 | case ACPI_TYPE_LOCAL_REFERENCE: | ||
122 | |||
123 | switch (obj_desc->reference.opcode) { | ||
124 | case AML_DEBUG_OP: | ||
125 | |||
126 | acpi_os_printf ("Reference: Debug\n"); | ||
127 | break; | ||
128 | |||
129 | |||
130 | case AML_NAME_OP: | ||
131 | |||
132 | ACPI_DUMP_PATHNAME (obj_desc->reference.object, | ||
133 | "Reference: Name: ", ACPI_LV_INFO, _COMPONENT); | ||
134 | ACPI_DUMP_ENTRY (obj_desc->reference.object, ACPI_LV_INFO); | ||
135 | break; | ||
136 | |||
137 | |||
138 | case AML_INDEX_OP: | ||
139 | |||
140 | acpi_os_printf ("Reference: Index %p\n", | ||
141 | obj_desc->reference.object); | ||
142 | break; | ||
143 | |||
144 | |||
145 | case AML_REF_OF_OP: | ||
146 | |||
147 | acpi_os_printf ("Reference: (ref_of) %p\n", | ||
148 | obj_desc->reference.object); | ||
149 | break; | ||
150 | |||
151 | |||
152 | case AML_ARG_OP: | ||
153 | |||
154 | acpi_os_printf ("Reference: Arg%d", | ||
155 | obj_desc->reference.offset); | ||
156 | |||
157 | if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { | ||
158 | /* Value is an Integer */ | ||
159 | |||
160 | acpi_os_printf (" value is [%8.8X%8.8x]", | ||
161 | ACPI_FORMAT_UINT64 (obj_desc->integer.value)); | ||
162 | } | ||
163 | |||
164 | acpi_os_printf ("\n"); | ||
165 | break; | ||
166 | |||
167 | |||
168 | case AML_LOCAL_OP: | ||
169 | |||
170 | acpi_os_printf ("Reference: Local%d", | ||
171 | obj_desc->reference.offset); | ||
172 | |||
173 | if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { | ||
174 | |||
175 | /* Value is an Integer */ | ||
176 | |||
177 | acpi_os_printf (" value is [%8.8X%8.8x]", | ||
178 | ACPI_FORMAT_UINT64 (obj_desc->integer.value)); | ||
179 | } | ||
180 | |||
181 | acpi_os_printf ("\n"); | ||
182 | break; | ||
183 | |||
184 | |||
185 | case AML_INT_NAMEPATH_OP: | ||
186 | |||
187 | acpi_os_printf ("Reference.Node->Name %X\n", | ||
188 | obj_desc->reference.node->name.integer); | ||
189 | break; | ||
190 | |||
191 | |||
192 | default: | ||
193 | |||
194 | /* Unknown opcode */ | ||
195 | |||
196 | acpi_os_printf ("Unknown Reference opcode=%X\n", | ||
197 | obj_desc->reference.opcode); | ||
198 | break; | ||
199 | |||
200 | } | ||
201 | break; | ||
202 | |||
203 | |||
204 | case ACPI_TYPE_BUFFER: | ||
205 | |||
206 | acpi_os_printf ("Buffer len %X @ %p \n", | ||
207 | obj_desc->buffer.length, obj_desc->buffer.pointer); | ||
208 | |||
209 | length = obj_desc->buffer.length; | ||
210 | if (length > 64) { | ||
211 | length = 64; | ||
212 | } | ||
213 | |||
214 | /* Debug only -- dump the buffer contents */ | ||
215 | |||
216 | if (obj_desc->buffer.pointer) { | ||
217 | acpi_os_printf ("Buffer Contents: "); | ||
218 | |||
219 | for (index = 0; index < length; index++) { | ||
220 | acpi_os_printf (" %02x", obj_desc->buffer.pointer[index]); | ||
221 | } | ||
222 | acpi_os_printf ("\n"); | ||
223 | } | ||
224 | break; | ||
225 | |||
226 | |||
227 | case ACPI_TYPE_INTEGER: | ||
228 | |||
229 | acpi_os_printf ("Integer %8.8X%8.8X\n", | ||
230 | ACPI_FORMAT_UINT64 (obj_desc->integer.value)); | ||
231 | break; | ||
232 | |||
233 | |||
234 | case ACPI_TYPE_PACKAGE: | ||
235 | |||
236 | acpi_os_printf ("Package [Len %X] element_array %p\n", | ||
237 | obj_desc->package.count, obj_desc->package.elements); | ||
238 | |||
239 | /* | ||
240 | * If elements exist, package element pointer is valid, | ||
241 | * and debug_level exceeds 1, dump package's elements. | ||
242 | */ | ||
243 | if (obj_desc->package.count && | ||
244 | obj_desc->package.elements && | ||
245 | acpi_dbg_level > 1) { | ||
246 | for (index = 0; index < obj_desc->package.count; index++) { | ||
247 | acpi_ex_dump_operand (obj_desc->package.elements[index], depth+1); | ||
248 | } | ||
249 | } | ||
250 | break; | ||
251 | |||
252 | |||
253 | case ACPI_TYPE_REGION: | ||
254 | |||
255 | acpi_os_printf ("Region %s (%X)", | ||
256 | acpi_ut_get_region_name (obj_desc->region.space_id), | ||
257 | obj_desc->region.space_id); | ||
258 | |||
259 | /* | ||
260 | * If the address and length have not been evaluated, | ||
261 | * don't print them. | ||
262 | */ | ||
263 | if (!(obj_desc->region.flags & AOPOBJ_DATA_VALID)) { | ||
264 | acpi_os_printf ("\n"); | ||
265 | } | ||
266 | else { | ||
267 | acpi_os_printf (" base %8.8X%8.8X Length %X\n", | ||
268 | ACPI_FORMAT_UINT64 (obj_desc->region.address), | ||
269 | obj_desc->region.length); | ||
270 | } | ||
271 | break; | ||
272 | |||
273 | |||
274 | case ACPI_TYPE_STRING: | ||
275 | |||
276 | acpi_os_printf ("String length %X @ %p ", | ||
277 | obj_desc->string.length, obj_desc->string.pointer); | ||
278 | acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX); | ||
279 | acpi_os_printf ("\n"); | ||
280 | break; | ||
281 | |||
282 | |||
283 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
284 | |||
285 | acpi_os_printf ("bank_field\n"); | ||
286 | break; | ||
287 | |||
288 | |||
289 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
290 | |||
291 | acpi_os_printf ( | ||
292 | "region_field: Bits=%X acc_width=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n", | ||
293 | obj_desc->field.bit_length, obj_desc->field.access_byte_width, | ||
294 | obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK, | ||
295 | obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK, | ||
296 | obj_desc->field.base_byte_offset, obj_desc->field.start_field_bit_offset); | ||
297 | acpi_ex_dump_operand (obj_desc->field.region_obj, depth+1); | ||
298 | break; | ||
299 | |||
300 | |||
301 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
302 | |||
303 | acpi_os_printf ("index_field\n"); | ||
304 | break; | ||
305 | |||
306 | |||
307 | case ACPI_TYPE_BUFFER_FIELD: | ||
308 | |||
309 | acpi_os_printf ( | ||
310 | "buffer_field: %X bits at byte %X bit %X of \n", | ||
311 | obj_desc->buffer_field.bit_length, obj_desc->buffer_field.base_byte_offset, | ||
312 | obj_desc->buffer_field.start_field_bit_offset); | ||
313 | |||
314 | if (!obj_desc->buffer_field.buffer_obj) { | ||
315 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*NULL* \n")); | ||
316 | } | ||
317 | else if (ACPI_GET_OBJECT_TYPE (obj_desc->buffer_field.buffer_obj) != ACPI_TYPE_BUFFER) { | ||
318 | acpi_os_printf ("*not a Buffer* \n"); | ||
319 | } | ||
320 | else { | ||
321 | acpi_ex_dump_operand (obj_desc->buffer_field.buffer_obj, depth+1); | ||
322 | } | ||
323 | break; | ||
324 | |||
325 | |||
326 | case ACPI_TYPE_EVENT: | ||
327 | |||
328 | acpi_os_printf ("Event\n"); | ||
329 | break; | ||
330 | |||
331 | |||
332 | case ACPI_TYPE_METHOD: | ||
333 | |||
334 | acpi_os_printf ( | ||
335 | "Method(%X) @ %p:%X\n", | ||
336 | obj_desc->method.param_count, | ||
337 | obj_desc->method.aml_start, obj_desc->method.aml_length); | ||
338 | break; | ||
339 | |||
340 | |||
341 | case ACPI_TYPE_MUTEX: | ||
342 | |||
343 | acpi_os_printf ("Mutex\n"); | ||
344 | break; | ||
345 | |||
346 | |||
347 | case ACPI_TYPE_DEVICE: | ||
348 | |||
349 | acpi_os_printf ("Device\n"); | ||
350 | break; | ||
351 | |||
352 | |||
353 | case ACPI_TYPE_POWER: | ||
354 | |||
355 | acpi_os_printf ("Power\n"); | ||
356 | break; | ||
357 | |||
358 | |||
359 | case ACPI_TYPE_PROCESSOR: | ||
360 | |||
361 | acpi_os_printf ("Processor\n"); | ||
362 | break; | ||
363 | |||
364 | |||
365 | case ACPI_TYPE_THERMAL: | ||
366 | |||
367 | acpi_os_printf ("Thermal\n"); | ||
368 | break; | ||
369 | |||
370 | |||
371 | default: | ||
372 | /* Unknown Type */ | ||
373 | |||
374 | acpi_os_printf ("Unknown Type %X\n", ACPI_GET_OBJECT_TYPE (obj_desc)); | ||
375 | break; | ||
376 | } | ||
377 | |||
378 | return; | ||
379 | } | ||
380 | |||
381 | |||
382 | /***************************************************************************** | ||
383 | * | ||
384 | * FUNCTION: acpi_ex_dump_operands | ||
385 | * | ||
386 | * PARAMETERS: Operands - Operand list | ||
387 | * interpreter_mode - Load or Exec | ||
388 | * Ident - Identification | ||
389 | * num_levels - # of stack entries to dump above line | ||
390 | * Note - Output notation | ||
391 | * module_name - Caller's module name | ||
392 | * line_number - Caller's invocation line number | ||
393 | * | ||
394 | * DESCRIPTION: Dump the object stack | ||
395 | * | ||
396 | ****************************************************************************/ | ||
397 | |||
398 | void | ||
399 | acpi_ex_dump_operands ( | ||
400 | union acpi_operand_object **operands, | ||
401 | acpi_interpreter_mode interpreter_mode, | ||
402 | char *ident, | ||
403 | u32 num_levels, | ||
404 | char *note, | ||
405 | char *module_name, | ||
406 | u32 line_number) | ||
407 | { | ||
408 | acpi_native_uint i; | ||
409 | |||
410 | |||
411 | ACPI_FUNCTION_NAME ("ex_dump_operands"); | ||
412 | |||
413 | |||
414 | if (!ident) { | ||
415 | ident = "?"; | ||
416 | } | ||
417 | |||
418 | if (!note) { | ||
419 | note = "?"; | ||
420 | } | ||
421 | |||
422 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, | ||
423 | "************* Operand Stack Contents (Opcode [%s], %d Operands)\n", | ||
424 | ident, num_levels)); | ||
425 | |||
426 | if (num_levels == 0) { | ||
427 | num_levels = 1; | ||
428 | } | ||
429 | |||
430 | /* Dump the operand stack starting at the top */ | ||
431 | |||
432 | for (i = 0; num_levels > 0; i--, num_levels--) { | ||
433 | acpi_ex_dump_operand (operands[i], 0); | ||
434 | } | ||
435 | |||
436 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, | ||
437 | "************* Stack dump from %s(%d), %s\n", | ||
438 | module_name, line_number, note)); | ||
439 | return; | ||
440 | } | ||
441 | |||
442 | |||
443 | #ifdef ACPI_FUTURE_USAGE | ||
444 | |||
445 | /***************************************************************************** | ||
446 | * | ||
447 | * FUNCTION: acpi_ex_out* | ||
448 | * | ||
449 | * PARAMETERS: Title - Descriptive text | ||
450 | * Value - Value to be displayed | ||
451 | * | ||
452 | * DESCRIPTION: Object dump output formatting functions. These functions | ||
453 | * reduce the number of format strings required and keeps them | ||
454 | * all in one place for easy modification. | ||
455 | * | ||
456 | ****************************************************************************/ | ||
457 | |||
458 | void | ||
459 | acpi_ex_out_string ( | ||
460 | char *title, | ||
461 | char *value) | ||
462 | { | ||
463 | acpi_os_printf ("%20s : %s\n", title, value); | ||
464 | } | ||
465 | |||
466 | void | ||
467 | acpi_ex_out_pointer ( | ||
468 | char *title, | ||
469 | void *value) | ||
470 | { | ||
471 | acpi_os_printf ("%20s : %p\n", title, value); | ||
472 | } | ||
473 | |||
474 | void | ||
475 | acpi_ex_out_integer ( | ||
476 | char *title, | ||
477 | u32 value) | ||
478 | { | ||
479 | acpi_os_printf ("%20s : %X\n", title, value); | ||
480 | } | ||
481 | |||
482 | void | ||
483 | acpi_ex_out_address ( | ||
484 | char *title, | ||
485 | acpi_physical_address value) | ||
486 | { | ||
487 | |||
488 | #if ACPI_MACHINE_WIDTH == 16 | ||
489 | acpi_os_printf ("%20s : %p\n", title, value); | ||
490 | #else | ||
491 | acpi_os_printf ("%20s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64 (value)); | ||
492 | #endif | ||
493 | } | ||
494 | |||
495 | |||
496 | /***************************************************************************** | ||
497 | * | ||
498 | * FUNCTION: acpi_ex_dump_node | ||
499 | * | ||
500 | * PARAMETERS: *Node - Descriptor to dump | ||
501 | * Flags - Force display | ||
502 | * | ||
503 | * DESCRIPTION: Dumps the members of the given.Node | ||
504 | * | ||
505 | ****************************************************************************/ | ||
506 | |||
507 | void | ||
508 | acpi_ex_dump_node ( | ||
509 | struct acpi_namespace_node *node, | ||
510 | u32 flags) | ||
511 | { | ||
512 | |||
513 | ACPI_FUNCTION_ENTRY (); | ||
514 | |||
515 | |||
516 | if (!flags) { | ||
517 | if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) { | ||
518 | return; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | acpi_os_printf ("%20s : %4.4s\n", "Name", acpi_ut_get_node_name (node)); | ||
523 | acpi_ex_out_string ("Type", acpi_ut_get_type_name (node->type)); | ||
524 | acpi_ex_out_integer ("Flags", node->flags); | ||
525 | acpi_ex_out_integer ("Owner Id", node->owner_id); | ||
526 | acpi_ex_out_integer ("Reference Count", node->reference_count); | ||
527 | acpi_ex_out_pointer ("Attached Object", acpi_ns_get_attached_object (node)); | ||
528 | acpi_ex_out_pointer ("child_list", node->child); | ||
529 | acpi_ex_out_pointer ("next_peer", node->peer); | ||
530 | acpi_ex_out_pointer ("Parent", acpi_ns_get_parent_node (node)); | ||
531 | } | ||
532 | |||
533 | |||
534 | /***************************************************************************** | ||
535 | * | ||
536 | * FUNCTION: acpi_ex_dump_object_descriptor | ||
537 | * | ||
538 | * PARAMETERS: *Object - Descriptor to dump | ||
539 | * Flags - Force display | ||
540 | * | ||
541 | * DESCRIPTION: Dumps the members of the object descriptor given. | ||
542 | * | ||
543 | ****************************************************************************/ | ||
544 | |||
545 | void | ||
546 | acpi_ex_dump_object_descriptor ( | ||
547 | union acpi_operand_object *obj_desc, | ||
548 | u32 flags) | ||
549 | { | ||
550 | u32 i; | ||
551 | |||
552 | |||
553 | ACPI_FUNCTION_TRACE ("ex_dump_object_descriptor"); | ||
554 | |||
555 | |||
556 | if (!flags) { | ||
557 | if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) { | ||
558 | return_VOID; | ||
559 | } | ||
560 | } | ||
561 | |||
562 | if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) { | ||
563 | acpi_ex_dump_node ((struct acpi_namespace_node *) obj_desc, flags); | ||
564 | acpi_os_printf ("\nAttached Object (%p):\n", | ||
565 | ((struct acpi_namespace_node *) obj_desc)->object); | ||
566 | acpi_ex_dump_object_descriptor ( | ||
567 | ((struct acpi_namespace_node *) obj_desc)->object, flags); | ||
568 | return_VOID; | ||
569 | } | ||
570 | |||
571 | if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { | ||
572 | acpi_os_printf ( | ||
573 | "ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n", | ||
574 | obj_desc, acpi_ut_get_descriptor_name (obj_desc)); | ||
575 | return_VOID; | ||
576 | } | ||
577 | |||
578 | /* Common Fields */ | ||
579 | |||
580 | acpi_ex_out_string ("Type", acpi_ut_get_object_type_name (obj_desc)); | ||
581 | acpi_ex_out_integer ("Reference Count", obj_desc->common.reference_count); | ||
582 | acpi_ex_out_integer ("Flags", obj_desc->common.flags); | ||
583 | |||
584 | /* Object-specific Fields */ | ||
585 | |||
586 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
587 | case ACPI_TYPE_INTEGER: | ||
588 | |||
589 | acpi_os_printf ("%20s : %8.8X%8.8X\n", "Value", | ||
590 | ACPI_FORMAT_UINT64 (obj_desc->integer.value)); | ||
591 | break; | ||
592 | |||
593 | |||
594 | case ACPI_TYPE_STRING: | ||
595 | |||
596 | acpi_ex_out_integer ("Length", obj_desc->string.length); | ||
597 | |||
598 | acpi_os_printf ("%20s : %p ", "Pointer", obj_desc->string.pointer); | ||
599 | acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX); | ||
600 | acpi_os_printf ("\n"); | ||
601 | break; | ||
602 | |||
603 | |||
604 | case ACPI_TYPE_BUFFER: | ||
605 | |||
606 | acpi_ex_out_integer ("Length", obj_desc->buffer.length); | ||
607 | acpi_ex_out_pointer ("Pointer", obj_desc->buffer.pointer); | ||
608 | ACPI_DUMP_BUFFER (obj_desc->buffer.pointer, obj_desc->buffer.length); | ||
609 | break; | ||
610 | |||
611 | |||
612 | case ACPI_TYPE_PACKAGE: | ||
613 | |||
614 | acpi_ex_out_integer ("Flags", obj_desc->package.flags); | ||
615 | acpi_ex_out_integer ("Count", obj_desc->package.count); | ||
616 | acpi_ex_out_pointer ("Elements", obj_desc->package.elements); | ||
617 | |||
618 | /* Dump the package contents */ | ||
619 | |||
620 | if (obj_desc->package.count > 0) { | ||
621 | acpi_os_printf ("\nPackage Contents:\n"); | ||
622 | for (i = 0; i < obj_desc->package.count; i++) { | ||
623 | acpi_os_printf ("[%.3d] %p", i, obj_desc->package.elements[i]); | ||
624 | if (obj_desc->package.elements[i]) { | ||
625 | acpi_os_printf (" %s", | ||
626 | acpi_ut_get_object_type_name (obj_desc->package.elements[i])); | ||
627 | } | ||
628 | acpi_os_printf ("\n"); | ||
629 | } | ||
630 | } | ||
631 | break; | ||
632 | |||
633 | |||
634 | case ACPI_TYPE_DEVICE: | ||
635 | |||
636 | acpi_ex_out_pointer ("Handler", obj_desc->device.handler); | ||
637 | acpi_ex_out_pointer ("system_notify", obj_desc->device.system_notify); | ||
638 | acpi_ex_out_pointer ("device_notify", obj_desc->device.device_notify); | ||
639 | break; | ||
640 | |||
641 | |||
642 | case ACPI_TYPE_EVENT: | ||
643 | |||
644 | acpi_ex_out_pointer ("Semaphore", obj_desc->event.semaphore); | ||
645 | break; | ||
646 | |||
647 | |||
648 | case ACPI_TYPE_METHOD: | ||
649 | |||
650 | acpi_ex_out_integer ("param_count", obj_desc->method.param_count); | ||
651 | acpi_ex_out_integer ("Concurrency", obj_desc->method.concurrency); | ||
652 | acpi_ex_out_pointer ("Semaphore", obj_desc->method.semaphore); | ||
653 | acpi_ex_out_integer ("owning_id", obj_desc->method.owning_id); | ||
654 | acpi_ex_out_integer ("aml_length", obj_desc->method.aml_length); | ||
655 | acpi_ex_out_pointer ("aml_start", obj_desc->method.aml_start); | ||
656 | break; | ||
657 | |||
658 | |||
659 | case ACPI_TYPE_MUTEX: | ||
660 | |||
661 | acpi_ex_out_integer ("sync_level", obj_desc->mutex.sync_level); | ||
662 | acpi_ex_out_pointer ("owner_thread", obj_desc->mutex.owner_thread); | ||
663 | acpi_ex_out_integer ("acquire_depth", obj_desc->mutex.acquisition_depth); | ||
664 | acpi_ex_out_pointer ("Semaphore", obj_desc->mutex.semaphore); | ||
665 | break; | ||
666 | |||
667 | |||
668 | case ACPI_TYPE_REGION: | ||
669 | |||
670 | acpi_ex_out_integer ("space_id", obj_desc->region.space_id); | ||
671 | acpi_ex_out_integer ("Flags", obj_desc->region.flags); | ||
672 | acpi_ex_out_address ("Address", obj_desc->region.address); | ||
673 | acpi_ex_out_integer ("Length", obj_desc->region.length); | ||
674 | acpi_ex_out_pointer ("Handler", obj_desc->region.handler); | ||
675 | acpi_ex_out_pointer ("Next", obj_desc->region.next); | ||
676 | break; | ||
677 | |||
678 | |||
679 | case ACPI_TYPE_POWER: | ||
680 | |||
681 | acpi_ex_out_integer ("system_level", obj_desc->power_resource.system_level); | ||
682 | acpi_ex_out_integer ("resource_order", obj_desc->power_resource.resource_order); | ||
683 | acpi_ex_out_pointer ("system_notify", obj_desc->power_resource.system_notify); | ||
684 | acpi_ex_out_pointer ("device_notify", obj_desc->power_resource.device_notify); | ||
685 | break; | ||
686 | |||
687 | |||
688 | case ACPI_TYPE_PROCESSOR: | ||
689 | |||
690 | acpi_ex_out_integer ("Processor ID", obj_desc->processor.proc_id); | ||
691 | acpi_ex_out_integer ("Length", obj_desc->processor.length); | ||
692 | acpi_ex_out_address ("Address", (acpi_physical_address) obj_desc->processor.address); | ||
693 | acpi_ex_out_pointer ("system_notify", obj_desc->processor.system_notify); | ||
694 | acpi_ex_out_pointer ("device_notify", obj_desc->processor.device_notify); | ||
695 | acpi_ex_out_pointer ("Handler", obj_desc->processor.handler); | ||
696 | break; | ||
697 | |||
698 | |||
699 | case ACPI_TYPE_THERMAL: | ||
700 | |||
701 | acpi_ex_out_pointer ("system_notify", obj_desc->thermal_zone.system_notify); | ||
702 | acpi_ex_out_pointer ("device_notify", obj_desc->thermal_zone.device_notify); | ||
703 | acpi_ex_out_pointer ("Handler", obj_desc->thermal_zone.handler); | ||
704 | break; | ||
705 | |||
706 | |||
707 | case ACPI_TYPE_BUFFER_FIELD: | ||
708 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
709 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
710 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
711 | |||
712 | acpi_ex_out_integer ("field_flags", obj_desc->common_field.field_flags); | ||
713 | acpi_ex_out_integer ("access_byte_width",obj_desc->common_field.access_byte_width); | ||
714 | acpi_ex_out_integer ("bit_length", obj_desc->common_field.bit_length); | ||
715 | acpi_ex_out_integer ("fld_bit_offset", obj_desc->common_field.start_field_bit_offset); | ||
716 | acpi_ex_out_integer ("base_byte_offset", obj_desc->common_field.base_byte_offset); | ||
717 | acpi_ex_out_pointer ("parent_node", obj_desc->common_field.node); | ||
718 | |||
719 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
720 | case ACPI_TYPE_BUFFER_FIELD: | ||
721 | acpi_ex_out_pointer ("buffer_obj", obj_desc->buffer_field.buffer_obj); | ||
722 | break; | ||
723 | |||
724 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
725 | acpi_ex_out_pointer ("region_obj", obj_desc->field.region_obj); | ||
726 | break; | ||
727 | |||
728 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
729 | acpi_ex_out_integer ("Value", obj_desc->bank_field.value); | ||
730 | acpi_ex_out_pointer ("region_obj", obj_desc->bank_field.region_obj); | ||
731 | acpi_ex_out_pointer ("bank_obj", obj_desc->bank_field.bank_obj); | ||
732 | break; | ||
733 | |||
734 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
735 | acpi_ex_out_integer ("Value", obj_desc->index_field.value); | ||
736 | acpi_ex_out_pointer ("Index", obj_desc->index_field.index_obj); | ||
737 | acpi_ex_out_pointer ("Data", obj_desc->index_field.data_obj); | ||
738 | break; | ||
739 | |||
740 | default: | ||
741 | /* All object types covered above */ | ||
742 | break; | ||
743 | } | ||
744 | break; | ||
745 | |||
746 | |||
747 | case ACPI_TYPE_LOCAL_REFERENCE: | ||
748 | |||
749 | acpi_ex_out_integer ("target_type", obj_desc->reference.target_type); | ||
750 | acpi_ex_out_string ("Opcode", (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name); | ||
751 | acpi_ex_out_integer ("Offset", obj_desc->reference.offset); | ||
752 | acpi_ex_out_pointer ("obj_desc", obj_desc->reference.object); | ||
753 | acpi_ex_out_pointer ("Node", obj_desc->reference.node); | ||
754 | acpi_ex_out_pointer ("Where", obj_desc->reference.where); | ||
755 | break; | ||
756 | |||
757 | |||
758 | case ACPI_TYPE_LOCAL_ADDRESS_HANDLER: | ||
759 | |||
760 | acpi_ex_out_integer ("space_id", obj_desc->address_space.space_id); | ||
761 | acpi_ex_out_pointer ("Next", obj_desc->address_space.next); | ||
762 | acpi_ex_out_pointer ("region_list", obj_desc->address_space.region_list); | ||
763 | acpi_ex_out_pointer ("Node", obj_desc->address_space.node); | ||
764 | acpi_ex_out_pointer ("Context", obj_desc->address_space.context); | ||
765 | break; | ||
766 | |||
767 | |||
768 | case ACPI_TYPE_LOCAL_NOTIFY: | ||
769 | |||
770 | acpi_ex_out_pointer ("Node", obj_desc->notify.node); | ||
771 | acpi_ex_out_pointer ("Context", obj_desc->notify.context); | ||
772 | break; | ||
773 | |||
774 | |||
775 | case ACPI_TYPE_LOCAL_ALIAS: | ||
776 | case ACPI_TYPE_LOCAL_METHOD_ALIAS: | ||
777 | case ACPI_TYPE_LOCAL_EXTRA: | ||
778 | case ACPI_TYPE_LOCAL_DATA: | ||
779 | default: | ||
780 | |||
781 | acpi_os_printf ( | ||
782 | "ex_dump_object_descriptor: Display not implemented for object type %s\n", | ||
783 | acpi_ut_get_object_type_name (obj_desc)); | ||
784 | break; | ||
785 | } | ||
786 | |||
787 | return_VOID; | ||
788 | } | ||
789 | |||
790 | #endif /* ACPI_FUTURE_USAGE */ | ||
791 | |||
792 | #endif | ||
793 | |||
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c new file mode 100644 index 000000000000..be7f2124fa02 --- /dev/null +++ b/drivers/acpi/executer/exfield.c | |||
@@ -0,0 +1,367 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: exfield - ACPI AML (p-code) execution - field manipulation | ||
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/acdispat.h> | ||
47 | #include <acpi/acinterp.h> | ||
48 | |||
49 | |||
50 | #define _COMPONENT ACPI_EXECUTER | ||
51 | ACPI_MODULE_NAME ("exfield") | ||
52 | |||
53 | |||
54 | /******************************************************************************* | ||
55 | * | ||
56 | * FUNCTION: acpi_ex_read_data_from_field | ||
57 | * | ||
58 | * PARAMETERS: walk_state - Current execution state | ||
59 | * obj_desc - The named field | ||
60 | * ret_buffer_desc - Where the return data object is stored | ||
61 | * | ||
62 | * RETURN: Status | ||
63 | * | ||
64 | * DESCRIPTION: Read from a named field. Returns either an Integer or a | ||
65 | * Buffer, depending on the size of the field. | ||
66 | * | ||
67 | ******************************************************************************/ | ||
68 | |||
69 | acpi_status | ||
70 | acpi_ex_read_data_from_field ( | ||
71 | struct acpi_walk_state *walk_state, | ||
72 | union acpi_operand_object *obj_desc, | ||
73 | union acpi_operand_object **ret_buffer_desc) | ||
74 | { | ||
75 | acpi_status status; | ||
76 | union acpi_operand_object *buffer_desc; | ||
77 | acpi_size length; | ||
78 | void *buffer; | ||
79 | u8 locked; | ||
80 | |||
81 | |||
82 | ACPI_FUNCTION_TRACE_PTR ("ex_read_data_from_field", obj_desc); | ||
83 | |||
84 | |||
85 | /* Parameter validation */ | ||
86 | |||
87 | if (!obj_desc) { | ||
88 | return_ACPI_STATUS (AE_AML_NO_OPERAND); | ||
89 | } | ||
90 | |||
91 | if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) { | ||
92 | /* | ||
93 | * If the buffer_field arguments have not been previously evaluated, | ||
94 | * evaluate them now and save the results. | ||
95 | */ | ||
96 | if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { | ||
97 | status = acpi_ds_get_buffer_field_arguments (obj_desc); | ||
98 | if (ACPI_FAILURE (status)) { | ||
99 | return_ACPI_STATUS (status); | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) && | ||
104 | (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) { | ||
105 | /* | ||
106 | * This is an SMBus read. We must create a buffer to hold the data | ||
107 | * and directly access the region handler. | ||
108 | */ | ||
109 | buffer_desc = acpi_ut_create_buffer_object (ACPI_SMBUS_BUFFER_SIZE); | ||
110 | if (!buffer_desc) { | ||
111 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
112 | } | ||
113 | |||
114 | /* Lock entire transaction if requested */ | ||
115 | |||
116 | locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags); | ||
117 | |||
118 | /* | ||
119 | * Perform the read. | ||
120 | * Note: Smbus protocol value is passed in upper 16-bits of Function | ||
121 | */ | ||
122 | status = acpi_ex_access_region (obj_desc, 0, | ||
123 | ACPI_CAST_PTR (acpi_integer, buffer_desc->buffer.pointer), | ||
124 | ACPI_READ | (obj_desc->field.attribute << 16)); | ||
125 | acpi_ex_release_global_lock (locked); | ||
126 | goto exit; | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * Allocate a buffer for the contents of the field. | ||
131 | * | ||
132 | * If the field is larger than the size of an acpi_integer, create | ||
133 | * a BUFFER to hold it. Otherwise, use an INTEGER. This allows | ||
134 | * the use of arithmetic operators on the returned value if the | ||
135 | * field size is equal or smaller than an Integer. | ||
136 | * | ||
137 | * Note: Field.length is in bits. | ||
138 | */ | ||
139 | length = (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->field.bit_length); | ||
140 | if (length > acpi_gbl_integer_byte_width) { | ||
141 | /* Field is too large for an Integer, create a Buffer instead */ | ||
142 | |||
143 | buffer_desc = acpi_ut_create_buffer_object (length); | ||
144 | if (!buffer_desc) { | ||
145 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
146 | } | ||
147 | buffer = buffer_desc->buffer.pointer; | ||
148 | } | ||
149 | else { | ||
150 | /* Field will fit within an Integer (normal case) */ | ||
151 | |||
152 | buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
153 | if (!buffer_desc) { | ||
154 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
155 | } | ||
156 | |||
157 | length = acpi_gbl_integer_byte_width; | ||
158 | buffer_desc->integer.value = 0; | ||
159 | buffer = &buffer_desc->integer.value; | ||
160 | } | ||
161 | |||
162 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
163 | "field_read [TO]: Obj %p, Type %X, Buf %p, byte_len %X\n", | ||
164 | obj_desc, ACPI_GET_OBJECT_TYPE (obj_desc), buffer, (u32) length)); | ||
165 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
166 | "field_read [FROM]: bit_len %X, bit_off %X, byte_off %X\n", | ||
167 | obj_desc->common_field.bit_length, | ||
168 | obj_desc->common_field.start_field_bit_offset, | ||
169 | obj_desc->common_field.base_byte_offset)); | ||
170 | |||
171 | /* Lock entire transaction if requested */ | ||
172 | |||
173 | locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags); | ||
174 | |||
175 | /* Read from the field */ | ||
176 | |||
177 | status = acpi_ex_extract_from_field (obj_desc, buffer, (u32) length); | ||
178 | acpi_ex_release_global_lock (locked); | ||
179 | |||
180 | |||
181 | exit: | ||
182 | if (ACPI_FAILURE (status)) { | ||
183 | acpi_ut_remove_reference (buffer_desc); | ||
184 | } | ||
185 | else if (ret_buffer_desc) { | ||
186 | *ret_buffer_desc = buffer_desc; | ||
187 | } | ||
188 | |||
189 | return_ACPI_STATUS (status); | ||
190 | } | ||
191 | |||
192 | |||
193 | /******************************************************************************* | ||
194 | * | ||
195 | * FUNCTION: acpi_ex_write_data_to_field | ||
196 | * | ||
197 | * PARAMETERS: source_desc - Contains data to write | ||
198 | * obj_desc - The named field | ||
199 | * | ||
200 | * RETURN: Status | ||
201 | * | ||
202 | * DESCRIPTION: Write to a named field | ||
203 | * | ||
204 | ******************************************************************************/ | ||
205 | |||
206 | acpi_status | ||
207 | acpi_ex_write_data_to_field ( | ||
208 | union acpi_operand_object *source_desc, | ||
209 | union acpi_operand_object *obj_desc, | ||
210 | union acpi_operand_object **result_desc) | ||
211 | { | ||
212 | acpi_status status; | ||
213 | u32 length; | ||
214 | u32 required_length; | ||
215 | void *buffer; | ||
216 | void *new_buffer; | ||
217 | u8 locked; | ||
218 | union acpi_operand_object *buffer_desc; | ||
219 | |||
220 | |||
221 | ACPI_FUNCTION_TRACE_PTR ("ex_write_data_to_field", obj_desc); | ||
222 | |||
223 | |||
224 | /* Parameter validation */ | ||
225 | |||
226 | if (!source_desc || !obj_desc) { | ||
227 | return_ACPI_STATUS (AE_AML_NO_OPERAND); | ||
228 | } | ||
229 | |||
230 | if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) { | ||
231 | /* | ||
232 | * If the buffer_field arguments have not been previously evaluated, | ||
233 | * evaluate them now and save the results. | ||
234 | */ | ||
235 | if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { | ||
236 | status = acpi_ds_get_buffer_field_arguments (obj_desc); | ||
237 | if (ACPI_FAILURE (status)) { | ||
238 | return_ACPI_STATUS (status); | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) && | ||
243 | (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) { | ||
244 | /* | ||
245 | * This is an SMBus write. We will bypass the entire field mechanism | ||
246 | * and handoff the buffer directly to the handler. | ||
247 | * | ||
248 | * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE). | ||
249 | */ | ||
250 | if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) { | ||
251 | ACPI_REPORT_ERROR (("SMBus write requires Buffer, found type %s\n", | ||
252 | acpi_ut_get_object_type_name (source_desc))); | ||
253 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
254 | } | ||
255 | |||
256 | if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) { | ||
257 | ACPI_REPORT_ERROR (("SMBus write requires Buffer of length %X, found length %X\n", | ||
258 | ACPI_SMBUS_BUFFER_SIZE, source_desc->buffer.length)); | ||
259 | return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); | ||
260 | } | ||
261 | |||
262 | buffer_desc = acpi_ut_create_buffer_object (ACPI_SMBUS_BUFFER_SIZE); | ||
263 | if (!buffer_desc) { | ||
264 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
265 | } | ||
266 | |||
267 | buffer = buffer_desc->buffer.pointer; | ||
268 | ACPI_MEMCPY (buffer, source_desc->buffer.pointer, ACPI_SMBUS_BUFFER_SIZE); | ||
269 | |||
270 | /* Lock entire transaction if requested */ | ||
271 | |||
272 | locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags); | ||
273 | |||
274 | /* | ||
275 | * Perform the write (returns status and perhaps data in the same buffer) | ||
276 | * Note: SMBus protocol type is passed in upper 16-bits of Function. | ||
277 | */ | ||
278 | status = acpi_ex_access_region (obj_desc, 0, | ||
279 | (acpi_integer *) buffer, | ||
280 | ACPI_WRITE | (obj_desc->field.attribute << 16)); | ||
281 | acpi_ex_release_global_lock (locked); | ||
282 | |||
283 | *result_desc = buffer_desc; | ||
284 | return_ACPI_STATUS (status); | ||
285 | } | ||
286 | |||
287 | /* | ||
288 | * Get a pointer to the data to be written | ||
289 | */ | ||
290 | switch (ACPI_GET_OBJECT_TYPE (source_desc)) { | ||
291 | case ACPI_TYPE_INTEGER: | ||
292 | buffer = &source_desc->integer.value; | ||
293 | length = sizeof (source_desc->integer.value); | ||
294 | break; | ||
295 | |||
296 | case ACPI_TYPE_BUFFER: | ||
297 | buffer = source_desc->buffer.pointer; | ||
298 | length = source_desc->buffer.length; | ||
299 | break; | ||
300 | |||
301 | case ACPI_TYPE_STRING: | ||
302 | buffer = source_desc->string.pointer; | ||
303 | length = source_desc->string.length; | ||
304 | break; | ||
305 | |||
306 | default: | ||
307 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * We must have a buffer that is at least as long as the field | ||
312 | * we are writing to. This is because individual fields are | ||
313 | * indivisible and partial writes are not supported -- as per | ||
314 | * the ACPI specification. | ||
315 | */ | ||
316 | new_buffer = NULL; | ||
317 | required_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length); | ||
318 | |||
319 | if (length < required_length) { | ||
320 | /* We need to create a new buffer */ | ||
321 | |||
322 | new_buffer = ACPI_MEM_CALLOCATE (required_length); | ||
323 | if (!new_buffer) { | ||
324 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
325 | } | ||
326 | |||
327 | /* | ||
328 | * Copy the original data to the new buffer, starting | ||
329 | * at Byte zero. All unused (upper) bytes of the | ||
330 | * buffer will be 0. | ||
331 | */ | ||
332 | ACPI_MEMCPY ((char *) new_buffer, (char *) buffer, length); | ||
333 | buffer = new_buffer; | ||
334 | length = required_length; | ||
335 | } | ||
336 | |||
337 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
338 | "field_write [FROM]: Obj %p (%s:%X), Buf %p, byte_len %X\n", | ||
339 | source_desc, acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (source_desc)), | ||
340 | ACPI_GET_OBJECT_TYPE (source_desc), buffer, length)); | ||
341 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
342 | "field_write [TO]: Obj %p (%s:%X), bit_len %X, bit_off %X, byte_off %X\n", | ||
343 | obj_desc, acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (obj_desc)), | ||
344 | ACPI_GET_OBJECT_TYPE (obj_desc), | ||
345 | obj_desc->common_field.bit_length, | ||
346 | obj_desc->common_field.start_field_bit_offset, | ||
347 | obj_desc->common_field.base_byte_offset)); | ||
348 | |||
349 | /* Lock entire transaction if requested */ | ||
350 | |||
351 | locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags); | ||
352 | |||
353 | /* Write to the field */ | ||
354 | |||
355 | status = acpi_ex_insert_into_field (obj_desc, buffer, length); | ||
356 | acpi_ex_release_global_lock (locked); | ||
357 | |||
358 | /* Free temporary buffer if we used one */ | ||
359 | |||
360 | if (new_buffer) { | ||
361 | ACPI_MEM_FREE (new_buffer); | ||
362 | } | ||
363 | |||
364 | return_ACPI_STATUS (status); | ||
365 | } | ||
366 | |||
367 | |||
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c new file mode 100644 index 000000000000..9d0f9d2e9061 --- /dev/null +++ b/drivers/acpi/executer/exfldio.c | |||
@@ -0,0 +1,835 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: exfldio - Aml Field I/O | ||
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/acevents.h> | ||
49 | #include <acpi/acdispat.h> | ||
50 | |||
51 | |||
52 | #define _COMPONENT ACPI_EXECUTER | ||
53 | ACPI_MODULE_NAME ("exfldio") | ||
54 | |||
55 | |||
56 | /******************************************************************************* | ||
57 | * | ||
58 | * FUNCTION: acpi_ex_setup_region | ||
59 | * | ||
60 | * PARAMETERS: *obj_desc - Field to be read or written | ||
61 | * field_datum_byte_offset - Byte offset of this datum within the | ||
62 | * parent field | ||
63 | * | ||
64 | * RETURN: Status | ||
65 | * | ||
66 | * DESCRIPTION: Common processing for acpi_ex_extract_from_field and | ||
67 | * acpi_ex_insert_into_field. Initialize the Region if necessary and | ||
68 | * validate the request. | ||
69 | * | ||
70 | ******************************************************************************/ | ||
71 | |||
72 | acpi_status | ||
73 | acpi_ex_setup_region ( | ||
74 | union acpi_operand_object *obj_desc, | ||
75 | u32 field_datum_byte_offset) | ||
76 | { | ||
77 | acpi_status status = AE_OK; | ||
78 | union acpi_operand_object *rgn_desc; | ||
79 | |||
80 | |||
81 | ACPI_FUNCTION_TRACE_U32 ("ex_setup_region", field_datum_byte_offset); | ||
82 | |||
83 | |||
84 | rgn_desc = obj_desc->common_field.region_obj; | ||
85 | |||
86 | /* We must have a valid region */ | ||
87 | |||
88 | if (ACPI_GET_OBJECT_TYPE (rgn_desc) != ACPI_TYPE_REGION) { | ||
89 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n", | ||
90 | ACPI_GET_OBJECT_TYPE (rgn_desc), | ||
91 | acpi_ut_get_object_type_name (rgn_desc))); | ||
92 | |||
93 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * If the Region Address and Length have not been previously evaluated, | ||
98 | * evaluate them now and save the results. | ||
99 | */ | ||
100 | if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) { | ||
101 | status = acpi_ds_get_region_arguments (rgn_desc); | ||
102 | if (ACPI_FAILURE (status)) { | ||
103 | return_ACPI_STATUS (status); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { | ||
108 | /* SMBus has a non-linear address space */ | ||
109 | |||
110 | return_ACPI_STATUS (AE_OK); | ||
111 | } | ||
112 | |||
113 | #ifdef ACPI_UNDER_DEVELOPMENT | ||
114 | /* | ||
115 | * If the Field access is any_acc, we can now compute the optimal | ||
116 | * access (because we know know the length of the parent region) | ||
117 | */ | ||
118 | if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { | ||
119 | if (ACPI_FAILURE (status)) { | ||
120 | return_ACPI_STATUS (status); | ||
121 | } | ||
122 | } | ||
123 | #endif | ||
124 | |||
125 | /* | ||
126 | * Validate the request. The entire request from the byte offset for a | ||
127 | * length of one field datum (access width) must fit within the region. | ||
128 | * (Region length is specified in bytes) | ||
129 | */ | ||
130 | if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset | ||
131 | + field_datum_byte_offset | ||
132 | + obj_desc->common_field.access_byte_width)) { | ||
133 | if (acpi_gbl_enable_interpreter_slack) { | ||
134 | /* | ||
135 | * Slack mode only: We will go ahead and allow access to this | ||
136 | * field if it is within the region length rounded up to the next | ||
137 | * access width boundary. | ||
138 | */ | ||
139 | if (ACPI_ROUND_UP (rgn_desc->region.length, | ||
140 | obj_desc->common_field.access_byte_width) >= | ||
141 | (obj_desc->common_field.base_byte_offset + | ||
142 | (acpi_native_uint) obj_desc->common_field.access_byte_width + | ||
143 | field_datum_byte_offset)) { | ||
144 | return_ACPI_STATUS (AE_OK); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) { | ||
149 | /* | ||
150 | * This is the case where the access_type (acc_word, etc.) is wider | ||
151 | * than the region itself. For example, a region of length one | ||
152 | * byte, and a field with Dword access specified. | ||
153 | */ | ||
154 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
155 | "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n", | ||
156 | acpi_ut_get_node_name (obj_desc->common_field.node), | ||
157 | obj_desc->common_field.access_byte_width, | ||
158 | acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length)); | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Offset rounded up to next multiple of field width | ||
163 | * exceeds region length, indicate an error | ||
164 | */ | ||
165 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
166 | "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n", | ||
167 | acpi_ut_get_node_name (obj_desc->common_field.node), | ||
168 | obj_desc->common_field.base_byte_offset, | ||
169 | field_datum_byte_offset, obj_desc->common_field.access_byte_width, | ||
170 | acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length)); | ||
171 | |||
172 | return_ACPI_STATUS (AE_AML_REGION_LIMIT); | ||
173 | } | ||
174 | |||
175 | return_ACPI_STATUS (AE_OK); | ||
176 | } | ||
177 | |||
178 | |||
179 | /******************************************************************************* | ||
180 | * | ||
181 | * FUNCTION: acpi_ex_access_region | ||
182 | * | ||
183 | * PARAMETERS: *obj_desc - Field to be read | ||
184 | * field_datum_byte_offset - Byte offset of this datum within the | ||
185 | * parent field | ||
186 | * *Value - Where to store value (must at least | ||
187 | * the size of acpi_integer) | ||
188 | * Function - Read or Write flag plus other region- | ||
189 | * dependent flags | ||
190 | * | ||
191 | * RETURN: Status | ||
192 | * | ||
193 | * DESCRIPTION: Read or Write a single field datum to an Operation Region. | ||
194 | * | ||
195 | ******************************************************************************/ | ||
196 | |||
197 | acpi_status | ||
198 | acpi_ex_access_region ( | ||
199 | union acpi_operand_object *obj_desc, | ||
200 | u32 field_datum_byte_offset, | ||
201 | acpi_integer *value, | ||
202 | u32 function) | ||
203 | { | ||
204 | acpi_status status; | ||
205 | union acpi_operand_object *rgn_desc; | ||
206 | acpi_physical_address address; | ||
207 | |||
208 | |||
209 | ACPI_FUNCTION_TRACE ("ex_access_region"); | ||
210 | |||
211 | |||
212 | /* | ||
213 | * Ensure that the region operands are fully evaluated and verify | ||
214 | * the validity of the request | ||
215 | */ | ||
216 | status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset); | ||
217 | if (ACPI_FAILURE (status)) { | ||
218 | return_ACPI_STATUS (status); | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * The physical address of this field datum is: | ||
223 | * | ||
224 | * 1) The base of the region, plus | ||
225 | * 2) The base offset of the field, plus | ||
226 | * 3) The current offset into the field | ||
227 | */ | ||
228 | rgn_desc = obj_desc->common_field.region_obj; | ||
229 | address = rgn_desc->region.address | ||
230 | + obj_desc->common_field.base_byte_offset | ||
231 | + field_datum_byte_offset; | ||
232 | |||
233 | if ((function & ACPI_IO_MASK) == ACPI_READ) { | ||
234 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]")); | ||
235 | } | ||
236 | else { | ||
237 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]")); | ||
238 | } | ||
239 | |||
240 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD, | ||
241 | " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n", | ||
242 | acpi_ut_get_region_name (rgn_desc->region.space_id), | ||
243 | rgn_desc->region.space_id, | ||
244 | obj_desc->common_field.access_byte_width, | ||
245 | obj_desc->common_field.base_byte_offset, | ||
246 | field_datum_byte_offset, | ||
247 | ACPI_FORMAT_UINT64 (address))); | ||
248 | |||
249 | /* Invoke the appropriate address_space/op_region handler */ | ||
250 | |||
251 | status = acpi_ev_address_space_dispatch (rgn_desc, function, | ||
252 | address, ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value); | ||
253 | |||
254 | if (ACPI_FAILURE (status)) { | ||
255 | if (status == AE_NOT_IMPLEMENTED) { | ||
256 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
257 | "Region %s(%X) not implemented\n", | ||
258 | acpi_ut_get_region_name (rgn_desc->region.space_id), | ||
259 | rgn_desc->region.space_id)); | ||
260 | } | ||
261 | else if (status == AE_NOT_EXIST) { | ||
262 | ACPI_REPORT_ERROR (( | ||
263 | "Region %s(%X) has no handler\n", | ||
264 | acpi_ut_get_region_name (rgn_desc->region.space_id), | ||
265 | rgn_desc->region.space_id)); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | return_ACPI_STATUS (status); | ||
270 | } | ||
271 | |||
272 | |||
273 | /******************************************************************************* | ||
274 | * | ||
275 | * FUNCTION: acpi_ex_register_overflow | ||
276 | * | ||
277 | * PARAMETERS: *obj_desc - Register(Field) to be written | ||
278 | * Value - Value to be stored | ||
279 | * | ||
280 | * RETURN: TRUE if value overflows the field, FALSE otherwise | ||
281 | * | ||
282 | * DESCRIPTION: Check if a value is out of range of the field being written. | ||
283 | * Used to check if the values written to Index and Bank registers | ||
284 | * are out of range. Normally, the value is simply truncated | ||
285 | * to fit the field, but this case is most likely a serious | ||
286 | * coding error in the ASL. | ||
287 | * | ||
288 | ******************************************************************************/ | ||
289 | |||
290 | u8 | ||
291 | acpi_ex_register_overflow ( | ||
292 | union acpi_operand_object *obj_desc, | ||
293 | acpi_integer value) | ||
294 | { | ||
295 | |||
296 | if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) { | ||
297 | /* | ||
298 | * The field is large enough to hold the maximum integer, so we can | ||
299 | * never overflow it. | ||
300 | */ | ||
301 | return (FALSE); | ||
302 | } | ||
303 | |||
304 | if (value >= ((acpi_integer) 1 << obj_desc->common_field.bit_length)) { | ||
305 | /* | ||
306 | * The Value is larger than the maximum value that can fit into | ||
307 | * the register. | ||
308 | */ | ||
309 | return (TRUE); | ||
310 | } | ||
311 | |||
312 | /* The Value will fit into the field with no truncation */ | ||
313 | |||
314 | return (FALSE); | ||
315 | } | ||
316 | |||
317 | |||
318 | /******************************************************************************* | ||
319 | * | ||
320 | * FUNCTION: acpi_ex_field_datum_io | ||
321 | * | ||
322 | * PARAMETERS: *obj_desc - Field to be read | ||
323 | * field_datum_byte_offset - Byte offset of this datum within the | ||
324 | * parent field | ||
325 | * *Value - Where to store value (must be 64 bits) | ||
326 | * read_write - Read or Write flag | ||
327 | * | ||
328 | * RETURN: Status | ||
329 | * | ||
330 | * DESCRIPTION: Read or Write a single datum of a field. The field_type is | ||
331 | * demultiplexed here to handle the different types of fields | ||
332 | * (buffer_field, region_field, index_field, bank_field) | ||
333 | * | ||
334 | ******************************************************************************/ | ||
335 | |||
336 | acpi_status | ||
337 | acpi_ex_field_datum_io ( | ||
338 | union acpi_operand_object *obj_desc, | ||
339 | u32 field_datum_byte_offset, | ||
340 | acpi_integer *value, | ||
341 | u32 read_write) | ||
342 | { | ||
343 | acpi_status status; | ||
344 | acpi_integer local_value; | ||
345 | |||
346 | |||
347 | ACPI_FUNCTION_TRACE_U32 ("ex_field_datum_io", field_datum_byte_offset); | ||
348 | |||
349 | |||
350 | if (read_write == ACPI_READ) { | ||
351 | if (!value) { | ||
352 | local_value = 0; | ||
353 | value = &local_value; /* To support reads without saving return value */ | ||
354 | } | ||
355 | |||
356 | /* Clear the entire return buffer first, [Very Important!] */ | ||
357 | |||
358 | *value = 0; | ||
359 | } | ||
360 | |||
361 | /* | ||
362 | * The four types of fields are: | ||
363 | * | ||
364 | * buffer_field - Read/write from/to a Buffer | ||
365 | * region_field - Read/write from/to a Operation Region. | ||
366 | * bank_field - Write to a Bank Register, then read/write from/to an op_region | ||
367 | * index_field - Write to an Index Register, then read/write from/to a Data Register | ||
368 | */ | ||
369 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
370 | case ACPI_TYPE_BUFFER_FIELD: | ||
371 | /* | ||
372 | * If the buffer_field arguments have not been previously evaluated, | ||
373 | * evaluate them now and save the results. | ||
374 | */ | ||
375 | if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { | ||
376 | status = acpi_ds_get_buffer_field_arguments (obj_desc); | ||
377 | if (ACPI_FAILURE (status)) { | ||
378 | return_ACPI_STATUS (status); | ||
379 | } | ||
380 | } | ||
381 | |||
382 | if (read_write == ACPI_READ) { | ||
383 | /* | ||
384 | * Copy the data from the source buffer. | ||
385 | * Length is the field width in bytes. | ||
386 | */ | ||
387 | ACPI_MEMCPY (value, (obj_desc->buffer_field.buffer_obj)->buffer.pointer | ||
388 | + obj_desc->buffer_field.base_byte_offset | ||
389 | + field_datum_byte_offset, | ||
390 | obj_desc->common_field.access_byte_width); | ||
391 | } | ||
392 | else { | ||
393 | /* | ||
394 | * Copy the data to the target buffer. | ||
395 | * Length is the field width in bytes. | ||
396 | */ | ||
397 | ACPI_MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer | ||
398 | + obj_desc->buffer_field.base_byte_offset | ||
399 | + field_datum_byte_offset, | ||
400 | value, obj_desc->common_field.access_byte_width); | ||
401 | } | ||
402 | |||
403 | status = AE_OK; | ||
404 | break; | ||
405 | |||
406 | |||
407 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
408 | |||
409 | /* Ensure that the bank_value is not beyond the capacity of the register */ | ||
410 | |||
411 | if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj, | ||
412 | (acpi_integer) obj_desc->bank_field.value)) { | ||
413 | return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); | ||
414 | } | ||
415 | |||
416 | /* | ||
417 | * For bank_fields, we must write the bank_value to the bank_register | ||
418 | * (itself a region_field) before we can access the data. | ||
419 | */ | ||
420 | status = acpi_ex_insert_into_field (obj_desc->bank_field.bank_obj, | ||
421 | &obj_desc->bank_field.value, | ||
422 | sizeof (obj_desc->bank_field.value)); | ||
423 | if (ACPI_FAILURE (status)) { | ||
424 | return_ACPI_STATUS (status); | ||
425 | } | ||
426 | |||
427 | /* | ||
428 | * Now that the Bank has been selected, fall through to the | ||
429 | * region_field case and write the datum to the Operation Region | ||
430 | */ | ||
431 | |||
432 | /*lint -fallthrough */ | ||
433 | |||
434 | |||
435 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
436 | /* | ||
437 | * For simple region_fields, we just directly access the owning | ||
438 | * Operation Region. | ||
439 | */ | ||
440 | status = acpi_ex_access_region (obj_desc, field_datum_byte_offset, value, | ||
441 | read_write); | ||
442 | break; | ||
443 | |||
444 | |||
445 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
446 | |||
447 | |||
448 | /* Ensure that the index_value is not beyond the capacity of the register */ | ||
449 | |||
450 | if (acpi_ex_register_overflow (obj_desc->index_field.index_obj, | ||
451 | (acpi_integer) obj_desc->index_field.value)) { | ||
452 | return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); | ||
453 | } | ||
454 | |||
455 | /* Write the index value to the index_register (itself a region_field) */ | ||
456 | |||
457 | field_datum_byte_offset += obj_desc->index_field.value; | ||
458 | |||
459 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
460 | "Write to Index Register: Value %8.8X\n", | ||
461 | field_datum_byte_offset)); | ||
462 | |||
463 | status = acpi_ex_insert_into_field (obj_desc->index_field.index_obj, | ||
464 | &field_datum_byte_offset, | ||
465 | sizeof (field_datum_byte_offset)); | ||
466 | if (ACPI_FAILURE (status)) { | ||
467 | return_ACPI_STATUS (status); | ||
468 | } | ||
469 | |||
470 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
471 | "I/O to Data Register: value_ptr %p\n", | ||
472 | value)); | ||
473 | |||
474 | if (read_write == ACPI_READ) { | ||
475 | /* Read the datum from the data_register */ | ||
476 | |||
477 | status = acpi_ex_extract_from_field (obj_desc->index_field.data_obj, | ||
478 | value, sizeof (acpi_integer)); | ||
479 | } | ||
480 | else { | ||
481 | /* Write the datum to the data_register */ | ||
482 | |||
483 | status = acpi_ex_insert_into_field (obj_desc->index_field.data_obj, | ||
484 | value, sizeof (acpi_integer)); | ||
485 | } | ||
486 | break; | ||
487 | |||
488 | |||
489 | default: | ||
490 | |||
491 | ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n", | ||
492 | ACPI_GET_OBJECT_TYPE (obj_desc))); | ||
493 | status = AE_AML_INTERNAL; | ||
494 | break; | ||
495 | } | ||
496 | |||
497 | if (ACPI_SUCCESS (status)) { | ||
498 | if (read_write == ACPI_READ) { | ||
499 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read %8.8X%8.8X, Width %d\n", | ||
500 | ACPI_FORMAT_UINT64 (*value), | ||
501 | obj_desc->common_field.access_byte_width)); | ||
502 | } | ||
503 | else { | ||
504 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n", | ||
505 | ACPI_FORMAT_UINT64 (*value), | ||
506 | obj_desc->common_field.access_byte_width)); | ||
507 | } | ||
508 | } | ||
509 | |||
510 | return_ACPI_STATUS (status); | ||
511 | } | ||
512 | |||
513 | |||
514 | /******************************************************************************* | ||
515 | * | ||
516 | * FUNCTION: acpi_ex_write_with_update_rule | ||
517 | * | ||
518 | * PARAMETERS: *obj_desc - Field to be set | ||
519 | * Value - Value to store | ||
520 | * | ||
521 | * RETURN: Status | ||
522 | * | ||
523 | * DESCRIPTION: Apply the field update rule to a field write | ||
524 | * | ||
525 | ******************************************************************************/ | ||
526 | |||
527 | acpi_status | ||
528 | acpi_ex_write_with_update_rule ( | ||
529 | union acpi_operand_object *obj_desc, | ||
530 | acpi_integer mask, | ||
531 | acpi_integer field_value, | ||
532 | u32 field_datum_byte_offset) | ||
533 | { | ||
534 | acpi_status status = AE_OK; | ||
535 | acpi_integer merged_value; | ||
536 | acpi_integer current_value; | ||
537 | |||
538 | |||
539 | ACPI_FUNCTION_TRACE_U32 ("ex_write_with_update_rule", mask); | ||
540 | |||
541 | |||
542 | /* Start with the new bits */ | ||
543 | |||
544 | merged_value = field_value; | ||
545 | |||
546 | /* If the mask is all ones, we don't need to worry about the update rule */ | ||
547 | |||
548 | if (mask != ACPI_INTEGER_MAX) { | ||
549 | /* Decode the update rule */ | ||
550 | |||
551 | switch (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK) { | ||
552 | case AML_FIELD_UPDATE_PRESERVE: | ||
553 | /* | ||
554 | * Check if update rule needs to be applied (not if mask is all | ||
555 | * ones) The left shift drops the bits we want to ignore. | ||
556 | */ | ||
557 | if ((~mask << (ACPI_MUL_8 (sizeof (mask)) - | ||
558 | ACPI_MUL_8 (obj_desc->common_field.access_byte_width))) != 0) { | ||
559 | /* | ||
560 | * Read the current contents of the byte/word/dword containing | ||
561 | * the field, and merge with the new field value. | ||
562 | */ | ||
563 | status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, | ||
564 | ¤t_value, ACPI_READ); | ||
565 | if (ACPI_FAILURE (status)) { | ||
566 | return_ACPI_STATUS (status); | ||
567 | } | ||
568 | |||
569 | merged_value |= (current_value & ~mask); | ||
570 | } | ||
571 | break; | ||
572 | |||
573 | case AML_FIELD_UPDATE_WRITE_AS_ONES: | ||
574 | |||
575 | /* Set positions outside the field to all ones */ | ||
576 | |||
577 | merged_value |= ~mask; | ||
578 | break; | ||
579 | |||
580 | case AML_FIELD_UPDATE_WRITE_AS_ZEROS: | ||
581 | |||
582 | /* Set positions outside the field to all zeros */ | ||
583 | |||
584 | merged_value &= mask; | ||
585 | break; | ||
586 | |||
587 | default: | ||
588 | |||
589 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
590 | "write_with_update_rule: Unknown update_rule setting: %X\n", | ||
591 | (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK))); | ||
592 | return_ACPI_STATUS (AE_AML_OPERAND_VALUE); | ||
593 | } | ||
594 | } | ||
595 | |||
596 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
597 | "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n", | ||
598 | ACPI_FORMAT_UINT64 (mask), | ||
599 | field_datum_byte_offset, | ||
600 | obj_desc->common_field.access_byte_width, | ||
601 | ACPI_FORMAT_UINT64 (field_value), | ||
602 | ACPI_FORMAT_UINT64 (merged_value))); | ||
603 | |||
604 | /* Write the merged value */ | ||
605 | |||
606 | status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, | ||
607 | &merged_value, ACPI_WRITE); | ||
608 | |||
609 | return_ACPI_STATUS (status); | ||
610 | } | ||
611 | |||
612 | |||
613 | /******************************************************************************* | ||
614 | * | ||
615 | * FUNCTION: acpi_ex_extract_from_field | ||
616 | * | ||
617 | * PARAMETERS: obj_desc - Field to be read | ||
618 | * Buffer - Where to store the field data | ||
619 | * buffer_length - Length of Buffer | ||
620 | * | ||
621 | * RETURN: Status | ||
622 | * | ||
623 | * DESCRIPTION: Retrieve the current value of the given field | ||
624 | * | ||
625 | ******************************************************************************/ | ||
626 | |||
627 | acpi_status | ||
628 | acpi_ex_extract_from_field ( | ||
629 | union acpi_operand_object *obj_desc, | ||
630 | void *buffer, | ||
631 | u32 buffer_length) | ||
632 | { | ||
633 | acpi_status status; | ||
634 | acpi_integer raw_datum; | ||
635 | acpi_integer merged_datum; | ||
636 | u32 field_offset = 0; | ||
637 | u32 buffer_offset = 0; | ||
638 | u32 buffer_tail_bits; | ||
639 | u32 datum_count; | ||
640 | u32 field_datum_count; | ||
641 | u32 i; | ||
642 | |||
643 | |||
644 | ACPI_FUNCTION_TRACE ("ex_extract_from_field"); | ||
645 | |||
646 | |||
647 | /* Validate target buffer and clear it */ | ||
648 | |||
649 | if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES ( | ||
650 | obj_desc->common_field.bit_length)) { | ||
651 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
652 | "Field size %X (bits) is too large for buffer (%X)\n", | ||
653 | obj_desc->common_field.bit_length, buffer_length)); | ||
654 | |||
655 | return_ACPI_STATUS (AE_BUFFER_OVERFLOW); | ||
656 | } | ||
657 | ACPI_MEMSET (buffer, 0, buffer_length); | ||
658 | |||
659 | /* Compute the number of datums (access width data items) */ | ||
660 | |||
661 | datum_count = ACPI_ROUND_UP_TO ( | ||
662 | obj_desc->common_field.bit_length, | ||
663 | obj_desc->common_field.access_bit_width); | ||
664 | field_datum_count = ACPI_ROUND_UP_TO ( | ||
665 | obj_desc->common_field.bit_length + | ||
666 | obj_desc->common_field.start_field_bit_offset, | ||
667 | obj_desc->common_field.access_bit_width); | ||
668 | |||
669 | /* Priming read from the field */ | ||
670 | |||
671 | status = acpi_ex_field_datum_io (obj_desc, field_offset, &raw_datum, ACPI_READ); | ||
672 | if (ACPI_FAILURE (status)) { | ||
673 | return_ACPI_STATUS (status); | ||
674 | } | ||
675 | merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset; | ||
676 | |||
677 | /* Read the rest of the field */ | ||
678 | |||
679 | for (i = 1; i < field_datum_count; i++) { | ||
680 | /* Get next input datum from the field */ | ||
681 | |||
682 | field_offset += obj_desc->common_field.access_byte_width; | ||
683 | status = acpi_ex_field_datum_io (obj_desc, field_offset, | ||
684 | &raw_datum, ACPI_READ); | ||
685 | if (ACPI_FAILURE (status)) { | ||
686 | return_ACPI_STATUS (status); | ||
687 | } | ||
688 | |||
689 | /* Merge with previous datum if necessary */ | ||
690 | |||
691 | merged_datum |= raw_datum << | ||
692 | (obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset); | ||
693 | |||
694 | if (i == datum_count) { | ||
695 | break; | ||
696 | } | ||
697 | |||
698 | /* Write merged datum to target buffer */ | ||
699 | |||
700 | ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum, | ||
701 | ACPI_MIN(obj_desc->common_field.access_byte_width, | ||
702 | buffer_length - buffer_offset)); | ||
703 | |||
704 | buffer_offset += obj_desc->common_field.access_byte_width; | ||
705 | merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset; | ||
706 | } | ||
707 | |||
708 | /* Mask off any extra bits in the last datum */ | ||
709 | |||
710 | buffer_tail_bits = obj_desc->common_field.bit_length % obj_desc->common_field.access_bit_width; | ||
711 | if (buffer_tail_bits) { | ||
712 | merged_datum &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits); | ||
713 | } | ||
714 | |||
715 | /* Write the last datum to the buffer */ | ||
716 | |||
717 | ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum, | ||
718 | ACPI_MIN(obj_desc->common_field.access_byte_width, | ||
719 | buffer_length - buffer_offset)); | ||
720 | |||
721 | return_ACPI_STATUS (AE_OK); | ||
722 | } | ||
723 | |||
724 | |||
725 | /******************************************************************************* | ||
726 | * | ||
727 | * FUNCTION: acpi_ex_insert_into_field | ||
728 | * | ||
729 | * PARAMETERS: obj_desc - Field to be written | ||
730 | * Buffer - Data to be written | ||
731 | * buffer_length - Length of Buffer | ||
732 | * | ||
733 | * RETURN: Status | ||
734 | * | ||
735 | * DESCRIPTION: Store the Buffer contents into the given field | ||
736 | * | ||
737 | ******************************************************************************/ | ||
738 | |||
739 | acpi_status | ||
740 | acpi_ex_insert_into_field ( | ||
741 | union acpi_operand_object *obj_desc, | ||
742 | void *buffer, | ||
743 | u32 buffer_length) | ||
744 | { | ||
745 | acpi_status status; | ||
746 | acpi_integer mask; | ||
747 | acpi_integer merged_datum; | ||
748 | acpi_integer raw_datum = 0; | ||
749 | u32 field_offset = 0; | ||
750 | u32 buffer_offset = 0; | ||
751 | u32 buffer_tail_bits; | ||
752 | u32 datum_count; | ||
753 | u32 field_datum_count; | ||
754 | u32 i; | ||
755 | |||
756 | |||
757 | ACPI_FUNCTION_TRACE ("ex_insert_into_field"); | ||
758 | |||
759 | |||
760 | /* Validate input buffer */ | ||
761 | |||
762 | if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES ( | ||
763 | obj_desc->common_field.bit_length)) { | ||
764 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
765 | "Field size %X (bits) is too large for buffer (%X)\n", | ||
766 | obj_desc->common_field.bit_length, buffer_length)); | ||
767 | |||
768 | return_ACPI_STATUS (AE_BUFFER_OVERFLOW); | ||
769 | } | ||
770 | |||
771 | /* Compute the number of datums (access width data items) */ | ||
772 | |||
773 | mask = ACPI_MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset); | ||
774 | datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length, | ||
775 | obj_desc->common_field.access_bit_width); | ||
776 | field_datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length + | ||
777 | obj_desc->common_field.start_field_bit_offset, | ||
778 | obj_desc->common_field.access_bit_width); | ||
779 | |||
780 | /* Get initial Datum from the input buffer */ | ||
781 | |||
782 | ACPI_MEMCPY (&raw_datum, buffer, | ||
783 | ACPI_MIN(obj_desc->common_field.access_byte_width, | ||
784 | buffer_length - buffer_offset)); | ||
785 | |||
786 | merged_datum = raw_datum << obj_desc->common_field.start_field_bit_offset; | ||
787 | |||
788 | /* Write the entire field */ | ||
789 | |||
790 | for (i = 1; i < field_datum_count; i++) { | ||
791 | /* Write merged datum to the target field */ | ||
792 | |||
793 | merged_datum &= mask; | ||
794 | status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset); | ||
795 | if (ACPI_FAILURE (status)) { | ||
796 | return_ACPI_STATUS (status); | ||
797 | } | ||
798 | |||
799 | /* Start new output datum by merging with previous input datum */ | ||
800 | |||
801 | field_offset += obj_desc->common_field.access_byte_width; | ||
802 | merged_datum = raw_datum >> | ||
803 | (obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset); | ||
804 | mask = ACPI_INTEGER_MAX; | ||
805 | |||
806 | if (i == datum_count) { | ||
807 | break; | ||
808 | } | ||
809 | |||
810 | /* Get the next input datum from the buffer */ | ||
811 | |||
812 | buffer_offset += obj_desc->common_field.access_byte_width; | ||
813 | ACPI_MEMCPY (&raw_datum, ((char *) buffer) + buffer_offset, | ||
814 | ACPI_MIN(obj_desc->common_field.access_byte_width, | ||
815 | buffer_length - buffer_offset)); | ||
816 | merged_datum |= raw_datum << obj_desc->common_field.start_field_bit_offset; | ||
817 | } | ||
818 | |||
819 | /* Mask off any extra bits in the last datum */ | ||
820 | |||
821 | buffer_tail_bits = (obj_desc->common_field.bit_length + | ||
822 | obj_desc->common_field.start_field_bit_offset) % obj_desc->common_field.access_bit_width; | ||
823 | if (buffer_tail_bits) { | ||
824 | mask &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits); | ||
825 | } | ||
826 | |||
827 | /* Write the last datum to the field */ | ||
828 | |||
829 | merged_datum &= mask; | ||
830 | status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset); | ||
831 | |||
832 | return_ACPI_STATUS (status); | ||
833 | } | ||
834 | |||
835 | |||
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c new file mode 100644 index 000000000000..b542dcd58c07 --- /dev/null +++ b/drivers/acpi/executer/exmisc.c | |||
@@ -0,0 +1,738 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acinterp.h> | ||
48 | #include <acpi/amlcode.h> | ||
49 | |||
50 | |||
51 | #define _COMPONENT ACPI_EXECUTER | ||
52 | ACPI_MODULE_NAME ("exmisc") | ||
53 | |||
54 | |||
55 | /******************************************************************************* | ||
56 | * | ||
57 | * FUNCTION: acpi_ex_get_object_reference | ||
58 | * | ||
59 | * PARAMETERS: obj_desc - Create a reference to this object | ||
60 | * return_desc - Where to store the reference | ||
61 | * walk_state - Current state | ||
62 | * | ||
63 | * RETURN: Status | ||
64 | * | ||
65 | * DESCRIPTION: Obtain and return a "reference" to the target object | ||
66 | * Common code for the ref_of_op and the cond_ref_of_op. | ||
67 | * | ||
68 | ******************************************************************************/ | ||
69 | |||
70 | acpi_status | ||
71 | acpi_ex_get_object_reference ( | ||
72 | union acpi_operand_object *obj_desc, | ||
73 | union acpi_operand_object **return_desc, | ||
74 | struct acpi_walk_state *walk_state) | ||
75 | { | ||
76 | union acpi_operand_object *reference_obj; | ||
77 | union acpi_operand_object *referenced_obj; | ||
78 | |||
79 | |||
80 | ACPI_FUNCTION_TRACE_PTR ("ex_get_object_reference", obj_desc); | ||
81 | |||
82 | |||
83 | *return_desc = NULL; | ||
84 | |||
85 | switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) { | ||
86 | case ACPI_DESC_TYPE_OPERAND: | ||
87 | |||
88 | if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) { | ||
89 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * Must be a reference to a Local or Arg | ||
94 | */ | ||
95 | switch (obj_desc->reference.opcode) { | ||
96 | case AML_LOCAL_OP: | ||
97 | case AML_ARG_OP: | ||
98 | case AML_DEBUG_OP: | ||
99 | |||
100 | /* The referenced object is the pseudo-node for the local/arg */ | ||
101 | |||
102 | referenced_obj = obj_desc->reference.object; | ||
103 | break; | ||
104 | |||
105 | default: | ||
106 | |||
107 | ACPI_REPORT_ERROR (("Unknown Reference opcode in get_reference %X\n", | ||
108 | obj_desc->reference.opcode)); | ||
109 | return_ACPI_STATUS (AE_AML_INTERNAL); | ||
110 | } | ||
111 | break; | ||
112 | |||
113 | |||
114 | case ACPI_DESC_TYPE_NAMED: | ||
115 | |||
116 | /* | ||
117 | * A named reference that has already been resolved to a Node | ||
118 | */ | ||
119 | referenced_obj = obj_desc; | ||
120 | break; | ||
121 | |||
122 | |||
123 | default: | ||
124 | |||
125 | ACPI_REPORT_ERROR (("Invalid descriptor type in get_reference: %X\n", | ||
126 | ACPI_GET_DESCRIPTOR_TYPE (obj_desc))); | ||
127 | return_ACPI_STATUS (AE_TYPE); | ||
128 | } | ||
129 | |||
130 | |||
131 | /* Create a new reference object */ | ||
132 | |||
133 | reference_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE); | ||
134 | if (!reference_obj) { | ||
135 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
136 | } | ||
137 | |||
138 | reference_obj->reference.opcode = AML_REF_OF_OP; | ||
139 | reference_obj->reference.object = referenced_obj; | ||
140 | *return_desc = reference_obj; | ||
141 | |||
142 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p Type [%s], returning Reference %p\n", | ||
143 | obj_desc, acpi_ut_get_object_type_name (obj_desc), *return_desc)); | ||
144 | |||
145 | return_ACPI_STATUS (AE_OK); | ||
146 | } | ||
147 | |||
148 | |||
149 | /******************************************************************************* | ||
150 | * | ||
151 | * FUNCTION: acpi_ex_concat_template | ||
152 | * | ||
153 | * PARAMETERS: Operand0 - First source object | ||
154 | * Operand1 - Second source object | ||
155 | * actual_return_desc - Where to place the return object | ||
156 | * walk_state - Current walk state | ||
157 | * | ||
158 | * RETURN: Status | ||
159 | * | ||
160 | * DESCRIPTION: Concatenate two resource templates | ||
161 | * | ||
162 | ******************************************************************************/ | ||
163 | |||
164 | acpi_status | ||
165 | acpi_ex_concat_template ( | ||
166 | union acpi_operand_object *operand0, | ||
167 | union acpi_operand_object *operand1, | ||
168 | union acpi_operand_object **actual_return_desc, | ||
169 | struct acpi_walk_state *walk_state) | ||
170 | { | ||
171 | union acpi_operand_object *return_desc; | ||
172 | u8 *new_buf; | ||
173 | u8 *end_tag1; | ||
174 | u8 *end_tag2; | ||
175 | acpi_size length1; | ||
176 | acpi_size length2; | ||
177 | |||
178 | |||
179 | ACPI_FUNCTION_TRACE ("ex_concat_template"); | ||
180 | |||
181 | |||
182 | /* Find the end_tags in each resource template */ | ||
183 | |||
184 | end_tag1 = acpi_ut_get_resource_end_tag (operand0); | ||
185 | end_tag2 = acpi_ut_get_resource_end_tag (operand1); | ||
186 | if (!end_tag1 || !end_tag2) { | ||
187 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
188 | } | ||
189 | |||
190 | /* Compute the length of each part */ | ||
191 | |||
192 | length1 = ACPI_PTR_DIFF (end_tag1, operand0->buffer.pointer); | ||
193 | length2 = ACPI_PTR_DIFF (end_tag2, operand1->buffer.pointer) + | ||
194 | 2; /* Size of END_TAG */ | ||
195 | |||
196 | /* Create a new buffer object for the result */ | ||
197 | |||
198 | return_desc = acpi_ut_create_buffer_object (length1 + length2); | ||
199 | if (!return_desc) { | ||
200 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
201 | } | ||
202 | |||
203 | /* Copy the templates to the new descriptor */ | ||
204 | |||
205 | new_buf = return_desc->buffer.pointer; | ||
206 | ACPI_MEMCPY (new_buf, operand0->buffer.pointer, length1); | ||
207 | ACPI_MEMCPY (new_buf + length1, operand1->buffer.pointer, length2); | ||
208 | |||
209 | /* Compute the new checksum */ | ||
210 | |||
211 | new_buf[return_desc->buffer.length - 1] = | ||
212 | acpi_ut_generate_checksum (return_desc->buffer.pointer, | ||
213 | (return_desc->buffer.length - 1)); | ||
214 | |||
215 | /* Return the completed template descriptor */ | ||
216 | |||
217 | *actual_return_desc = return_desc; | ||
218 | return_ACPI_STATUS (AE_OK); | ||
219 | } | ||
220 | |||
221 | |||
222 | /******************************************************************************* | ||
223 | * | ||
224 | * FUNCTION: acpi_ex_do_concatenate | ||
225 | * | ||
226 | * PARAMETERS: Operand0 - First source object | ||
227 | * Operand1 - Second source object | ||
228 | * actual_return_desc - Where to place the return object | ||
229 | * walk_state - Current walk state | ||
230 | * | ||
231 | * RETURN: Status | ||
232 | * | ||
233 | * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. | ||
234 | * | ||
235 | ******************************************************************************/ | ||
236 | |||
237 | acpi_status | ||
238 | acpi_ex_do_concatenate ( | ||
239 | union acpi_operand_object *operand0, | ||
240 | union acpi_operand_object *operand1, | ||
241 | union acpi_operand_object **actual_return_desc, | ||
242 | struct acpi_walk_state *walk_state) | ||
243 | { | ||
244 | union acpi_operand_object *local_operand1 = operand1; | ||
245 | union acpi_operand_object *return_desc; | ||
246 | char *new_buf; | ||
247 | acpi_status status; | ||
248 | acpi_size new_length; | ||
249 | |||
250 | |||
251 | ACPI_FUNCTION_TRACE ("ex_do_concatenate"); | ||
252 | |||
253 | |||
254 | /* | ||
255 | * Convert the second operand if necessary. The first operand | ||
256 | * determines the type of the second operand, (See the Data Types | ||
257 | * section of the ACPI specification.) Both object types are | ||
258 | * guaranteed to be either Integer/String/Buffer by the operand | ||
259 | * resolution mechanism. | ||
260 | */ | ||
261 | switch (ACPI_GET_OBJECT_TYPE (operand0)) { | ||
262 | case ACPI_TYPE_INTEGER: | ||
263 | status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16); | ||
264 | break; | ||
265 | |||
266 | case ACPI_TYPE_STRING: | ||
267 | status = acpi_ex_convert_to_string (operand1, &local_operand1, | ||
268 | ACPI_IMPLICIT_CONVERT_HEX); | ||
269 | break; | ||
270 | |||
271 | case ACPI_TYPE_BUFFER: | ||
272 | status = acpi_ex_convert_to_buffer (operand1, &local_operand1); | ||
273 | break; | ||
274 | |||
275 | default: | ||
276 | ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n", | ||
277 | ACPI_GET_OBJECT_TYPE (operand0))); | ||
278 | status = AE_AML_INTERNAL; | ||
279 | } | ||
280 | |||
281 | if (ACPI_FAILURE (status)) { | ||
282 | goto cleanup; | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * Both operands are now known to be the same object type | ||
287 | * (Both are Integer, String, or Buffer), and we can now perform the | ||
288 | * concatenation. | ||
289 | */ | ||
290 | |||
291 | /* | ||
292 | * There are three cases to handle: | ||
293 | * | ||
294 | * 1) Two Integers concatenated to produce a new Buffer | ||
295 | * 2) Two Strings concatenated to produce a new String | ||
296 | * 3) Two Buffers concatenated to produce a new Buffer | ||
297 | */ | ||
298 | switch (ACPI_GET_OBJECT_TYPE (operand0)) { | ||
299 | case ACPI_TYPE_INTEGER: | ||
300 | |||
301 | /* Result of two Integers is a Buffer */ | ||
302 | /* Need enough buffer space for two integers */ | ||
303 | |||
304 | return_desc = acpi_ut_create_buffer_object ( | ||
305 | ACPI_MUL_2 (acpi_gbl_integer_byte_width)); | ||
306 | if (!return_desc) { | ||
307 | status = AE_NO_MEMORY; | ||
308 | goto cleanup; | ||
309 | } | ||
310 | |||
311 | new_buf = (char *) return_desc->buffer.pointer; | ||
312 | |||
313 | /* Copy the first integer, LSB first */ | ||
314 | |||
315 | ACPI_MEMCPY (new_buf, | ||
316 | &operand0->integer.value, | ||
317 | acpi_gbl_integer_byte_width); | ||
318 | |||
319 | /* Copy the second integer (LSB first) after the first */ | ||
320 | |||
321 | ACPI_MEMCPY (new_buf + acpi_gbl_integer_byte_width, | ||
322 | &local_operand1->integer.value, | ||
323 | acpi_gbl_integer_byte_width); | ||
324 | break; | ||
325 | |||
326 | case ACPI_TYPE_STRING: | ||
327 | |||
328 | /* Result of two Strings is a String */ | ||
329 | |||
330 | new_length = (acpi_size) operand0->string.length + | ||
331 | (acpi_size) local_operand1->string.length; | ||
332 | if (new_length > ACPI_MAX_STRING_CONVERSION) { | ||
333 | status = AE_AML_STRING_LIMIT; | ||
334 | goto cleanup; | ||
335 | } | ||
336 | |||
337 | return_desc = acpi_ut_create_string_object (new_length); | ||
338 | if (!return_desc) { | ||
339 | status = AE_NO_MEMORY; | ||
340 | goto cleanup; | ||
341 | } | ||
342 | |||
343 | new_buf = return_desc->string.pointer; | ||
344 | |||
345 | /* Concatenate the strings */ | ||
346 | |||
347 | ACPI_STRCPY (new_buf, | ||
348 | operand0->string.pointer); | ||
349 | ACPI_STRCPY (new_buf + operand0->string.length, | ||
350 | local_operand1->string.pointer); | ||
351 | break; | ||
352 | |||
353 | case ACPI_TYPE_BUFFER: | ||
354 | |||
355 | /* Result of two Buffers is a Buffer */ | ||
356 | |||
357 | return_desc = acpi_ut_create_buffer_object ( | ||
358 | (acpi_size) operand0->buffer.length + | ||
359 | (acpi_size) local_operand1->buffer.length); | ||
360 | if (!return_desc) { | ||
361 | status = AE_NO_MEMORY; | ||
362 | goto cleanup; | ||
363 | } | ||
364 | |||
365 | new_buf = (char *) return_desc->buffer.pointer; | ||
366 | |||
367 | /* Concatenate the buffers */ | ||
368 | |||
369 | ACPI_MEMCPY (new_buf, | ||
370 | operand0->buffer.pointer, | ||
371 | operand0->buffer.length); | ||
372 | ACPI_MEMCPY (new_buf + operand0->buffer.length, | ||
373 | local_operand1->buffer.pointer, | ||
374 | local_operand1->buffer.length); | ||
375 | break; | ||
376 | |||
377 | default: | ||
378 | |||
379 | /* Invalid object type, should not happen here */ | ||
380 | |||
381 | ACPI_REPORT_ERROR (("Concatenate - Invalid object type: %X\n", | ||
382 | ACPI_GET_OBJECT_TYPE (operand0))); | ||
383 | status =AE_AML_INTERNAL; | ||
384 | goto cleanup; | ||
385 | } | ||
386 | |||
387 | *actual_return_desc = return_desc; | ||
388 | |||
389 | cleanup: | ||
390 | if (local_operand1 != operand1) { | ||
391 | acpi_ut_remove_reference (local_operand1); | ||
392 | } | ||
393 | return_ACPI_STATUS (status); | ||
394 | } | ||
395 | |||
396 | |||
397 | /******************************************************************************* | ||
398 | * | ||
399 | * FUNCTION: acpi_ex_do_math_op | ||
400 | * | ||
401 | * PARAMETERS: Opcode - AML opcode | ||
402 | * Integer0 - Integer operand #0 | ||
403 | * Integer1 - Integer operand #1 | ||
404 | * | ||
405 | * RETURN: Integer result of the operation | ||
406 | * | ||
407 | * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the | ||
408 | * math functions here is to prevent a lot of pointer dereferencing | ||
409 | * to obtain the operands. | ||
410 | * | ||
411 | ******************************************************************************/ | ||
412 | |||
413 | acpi_integer | ||
414 | acpi_ex_do_math_op ( | ||
415 | u16 opcode, | ||
416 | acpi_integer integer0, | ||
417 | acpi_integer integer1) | ||
418 | { | ||
419 | |||
420 | ACPI_FUNCTION_ENTRY (); | ||
421 | |||
422 | |||
423 | switch (opcode) { | ||
424 | case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ | ||
425 | |||
426 | return (integer0 + integer1); | ||
427 | |||
428 | |||
429 | case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ | ||
430 | |||
431 | return (integer0 & integer1); | ||
432 | |||
433 | |||
434 | case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ | ||
435 | |||
436 | return (~(integer0 & integer1)); | ||
437 | |||
438 | |||
439 | case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ | ||
440 | |||
441 | return (integer0 | integer1); | ||
442 | |||
443 | |||
444 | case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ | ||
445 | |||
446 | return (~(integer0 | integer1)); | ||
447 | |||
448 | |||
449 | case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ | ||
450 | |||
451 | return (integer0 ^ integer1); | ||
452 | |||
453 | |||
454 | case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ | ||
455 | |||
456 | return (integer0 * integer1); | ||
457 | |||
458 | |||
459 | case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */ | ||
460 | |||
461 | return (integer0 << integer1); | ||
462 | |||
463 | |||
464 | case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */ | ||
465 | |||
466 | return (integer0 >> integer1); | ||
467 | |||
468 | |||
469 | case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ | ||
470 | |||
471 | return (integer0 - integer1); | ||
472 | |||
473 | default: | ||
474 | |||
475 | return (0); | ||
476 | } | ||
477 | } | ||
478 | |||
479 | |||
480 | /******************************************************************************* | ||
481 | * | ||
482 | * FUNCTION: acpi_ex_do_logical_numeric_op | ||
483 | * | ||
484 | * PARAMETERS: Opcode - AML opcode | ||
485 | * Integer0 - Integer operand #0 | ||
486 | * Integer1 - Integer operand #1 | ||
487 | * logical_result - TRUE/FALSE result of the operation | ||
488 | * | ||
489 | * RETURN: Status | ||
490 | * | ||
491 | * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric | ||
492 | * operators (LAnd and LOr), both operands must be integers. | ||
493 | * | ||
494 | * Note: cleanest machine code seems to be produced by the code | ||
495 | * below, rather than using statements of the form: | ||
496 | * Result = (Integer0 && Integer1); | ||
497 | * | ||
498 | ******************************************************************************/ | ||
499 | |||
500 | acpi_status | ||
501 | acpi_ex_do_logical_numeric_op ( | ||
502 | u16 opcode, | ||
503 | acpi_integer integer0, | ||
504 | acpi_integer integer1, | ||
505 | u8 *logical_result) | ||
506 | { | ||
507 | acpi_status status = AE_OK; | ||
508 | u8 local_result = FALSE; | ||
509 | |||
510 | |||
511 | ACPI_FUNCTION_TRACE ("ex_do_logical_numeric_op"); | ||
512 | |||
513 | |||
514 | switch (opcode) { | ||
515 | case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ | ||
516 | |||
517 | if (integer0 && integer1) { | ||
518 | local_result = TRUE; | ||
519 | } | ||
520 | break; | ||
521 | |||
522 | case AML_LOR_OP: /* LOr (Integer0, Integer1) */ | ||
523 | |||
524 | if (integer0 || integer1) { | ||
525 | local_result = TRUE; | ||
526 | } | ||
527 | break; | ||
528 | |||
529 | default: | ||
530 | status = AE_AML_INTERNAL; | ||
531 | break; | ||
532 | } | ||
533 | |||
534 | /* Return the logical result and status */ | ||
535 | |||
536 | *logical_result = local_result; | ||
537 | return_ACPI_STATUS (status); | ||
538 | } | ||
539 | |||
540 | |||
541 | /******************************************************************************* | ||
542 | * | ||
543 | * FUNCTION: acpi_ex_do_logical_op | ||
544 | * | ||
545 | * PARAMETERS: Opcode - AML opcode | ||
546 | * Operand0 - operand #0 | ||
547 | * Operand1 - operand #1 | ||
548 | * logical_result - TRUE/FALSE result of the operation | ||
549 | * | ||
550 | * RETURN: Status | ||
551 | * | ||
552 | * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the | ||
553 | * functions here is to prevent a lot of pointer dereferencing | ||
554 | * to obtain the operands and to simplify the generation of the | ||
555 | * logical value. For the Numeric operators (LAnd and LOr), both | ||
556 | * operands must be integers. For the other logical operators, | ||
557 | * operands can be any combination of Integer/String/Buffer. The | ||
558 | * first operand determines the type to which the second operand | ||
559 | * will be converted. | ||
560 | * | ||
561 | * Note: cleanest machine code seems to be produced by the code | ||
562 | * below, rather than using statements of the form: | ||
563 | * Result = (Operand0 == Operand1); | ||
564 | * | ||
565 | ******************************************************************************/ | ||
566 | |||
567 | acpi_status | ||
568 | acpi_ex_do_logical_op ( | ||
569 | u16 opcode, | ||
570 | union acpi_operand_object *operand0, | ||
571 | union acpi_operand_object *operand1, | ||
572 | u8 *logical_result) | ||
573 | { | ||
574 | union acpi_operand_object *local_operand1 = operand1; | ||
575 | acpi_integer integer0; | ||
576 | acpi_integer integer1; | ||
577 | u32 length0; | ||
578 | u32 length1; | ||
579 | acpi_status status = AE_OK; | ||
580 | u8 local_result = FALSE; | ||
581 | int compare; | ||
582 | |||
583 | |||
584 | ACPI_FUNCTION_TRACE ("ex_do_logical_op"); | ||
585 | |||
586 | |||
587 | /* | ||
588 | * Convert the second operand if necessary. The first operand | ||
589 | * determines the type of the second operand, (See the Data Types | ||
590 | * section of the ACPI 3.0+ specification.) Both object types are | ||
591 | * guaranteed to be either Integer/String/Buffer by the operand | ||
592 | * resolution mechanism. | ||
593 | */ | ||
594 | switch (ACPI_GET_OBJECT_TYPE (operand0)) { | ||
595 | case ACPI_TYPE_INTEGER: | ||
596 | status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16); | ||
597 | break; | ||
598 | |||
599 | case ACPI_TYPE_STRING: | ||
600 | status = acpi_ex_convert_to_string (operand1, &local_operand1, | ||
601 | ACPI_IMPLICIT_CONVERT_HEX); | ||
602 | break; | ||
603 | |||
604 | case ACPI_TYPE_BUFFER: | ||
605 | status = acpi_ex_convert_to_buffer (operand1, &local_operand1); | ||
606 | break; | ||
607 | |||
608 | default: | ||
609 | status = AE_AML_INTERNAL; | ||
610 | break; | ||
611 | } | ||
612 | |||
613 | if (ACPI_FAILURE (status)) { | ||
614 | goto cleanup; | ||
615 | } | ||
616 | |||
617 | /* | ||
618 | * Two cases: 1) Both Integers, 2) Both Strings or Buffers | ||
619 | */ | ||
620 | if (ACPI_GET_OBJECT_TYPE (operand0) == ACPI_TYPE_INTEGER) { | ||
621 | /* | ||
622 | * 1) Both operands are of type integer | ||
623 | * Note: local_operand1 may have changed above | ||
624 | */ | ||
625 | integer0 = operand0->integer.value; | ||
626 | integer1 = local_operand1->integer.value; | ||
627 | |||
628 | switch (opcode) { | ||
629 | case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ | ||
630 | |||
631 | if (integer0 == integer1) { | ||
632 | local_result = TRUE; | ||
633 | } | ||
634 | break; | ||
635 | |||
636 | case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ | ||
637 | |||
638 | if (integer0 > integer1) { | ||
639 | local_result = TRUE; | ||
640 | } | ||
641 | break; | ||
642 | |||
643 | case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ | ||
644 | |||
645 | if (integer0 < integer1) { | ||
646 | local_result = TRUE; | ||
647 | } | ||
648 | break; | ||
649 | |||
650 | default: | ||
651 | status = AE_AML_INTERNAL; | ||
652 | break; | ||
653 | } | ||
654 | } | ||
655 | else { | ||
656 | /* | ||
657 | * 2) Both operands are Strings or both are Buffers | ||
658 | * Note: Code below takes advantage of common Buffer/String | ||
659 | * object fields. local_operand1 may have changed above. Use | ||
660 | * memcmp to handle nulls in buffers. | ||
661 | */ | ||
662 | length0 = operand0->buffer.length; | ||
663 | length1 = local_operand1->buffer.length; | ||
664 | |||
665 | /* Lexicographic compare: compare the data bytes */ | ||
666 | |||
667 | compare = ACPI_MEMCMP ((const char * ) operand0->buffer.pointer, | ||
668 | (const char * ) local_operand1->buffer.pointer, | ||
669 | (length0 > length1) ? length1 : length0); | ||
670 | |||
671 | switch (opcode) { | ||
672 | case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ | ||
673 | |||
674 | /* Length and all bytes must be equal */ | ||
675 | |||
676 | if ((length0 == length1) && | ||
677 | (compare == 0)) { | ||
678 | /* Length and all bytes match ==> TRUE */ | ||
679 | |||
680 | local_result = TRUE; | ||
681 | } | ||
682 | break; | ||
683 | |||
684 | case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ | ||
685 | |||
686 | if (compare > 0) { | ||
687 | local_result = TRUE; | ||
688 | goto cleanup; /* TRUE */ | ||
689 | } | ||
690 | if (compare < 0) { | ||
691 | goto cleanup; /* FALSE */ | ||
692 | } | ||
693 | |||
694 | /* Bytes match (to shortest length), compare lengths */ | ||
695 | |||
696 | if (length0 > length1) { | ||
697 | local_result = TRUE; | ||
698 | } | ||
699 | break; | ||
700 | |||
701 | case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ | ||
702 | |||
703 | if (compare > 0) { | ||
704 | goto cleanup; /* FALSE */ | ||
705 | } | ||
706 | if (compare < 0) { | ||
707 | local_result = TRUE; | ||
708 | goto cleanup; /* TRUE */ | ||
709 | } | ||
710 | |||
711 | /* Bytes match (to shortest length), compare lengths */ | ||
712 | |||
713 | if (length0 < length1) { | ||
714 | local_result = TRUE; | ||
715 | } | ||
716 | break; | ||
717 | |||
718 | default: | ||
719 | status = AE_AML_INTERNAL; | ||
720 | break; | ||
721 | } | ||
722 | } | ||
723 | |||
724 | cleanup: | ||
725 | |||
726 | /* New object was created if implicit conversion performed - delete */ | ||
727 | |||
728 | if (local_operand1 != operand1) { | ||
729 | acpi_ut_remove_reference (local_operand1); | ||
730 | } | ||
731 | |||
732 | /* Return the logical result and status */ | ||
733 | |||
734 | *logical_result = local_result; | ||
735 | return_ACPI_STATUS (status); | ||
736 | } | ||
737 | |||
738 | |||
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c new file mode 100644 index 000000000000..68c4bb1970a5 --- /dev/null +++ b/drivers/acpi/executer/exmutex.c | |||
@@ -0,0 +1,363 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exmutex - ASL Mutex Acquire/Release functions | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acinterp.h> | ||
48 | |||
49 | #define _COMPONENT ACPI_EXECUTER | ||
50 | ACPI_MODULE_NAME ("exmutex") | ||
51 | |||
52 | |||
53 | /******************************************************************************* | ||
54 | * | ||
55 | * FUNCTION: acpi_ex_unlink_mutex | ||
56 | * | ||
57 | * PARAMETERS: obj_desc - The mutex to be unlinked | ||
58 | * | ||
59 | * RETURN: Status | ||
60 | * | ||
61 | * DESCRIPTION: Remove a mutex from the "acquired_mutex" list | ||
62 | * | ||
63 | ******************************************************************************/ | ||
64 | |||
65 | void | ||
66 | acpi_ex_unlink_mutex ( | ||
67 | union acpi_operand_object *obj_desc) | ||
68 | { | ||
69 | struct acpi_thread_state *thread = obj_desc->mutex.owner_thread; | ||
70 | |||
71 | |||
72 | if (!thread) { | ||
73 | return; | ||
74 | } | ||
75 | |||
76 | /* Doubly linked list */ | ||
77 | |||
78 | if (obj_desc->mutex.next) { | ||
79 | (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev; | ||
80 | } | ||
81 | |||
82 | if (obj_desc->mutex.prev) { | ||
83 | (obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next; | ||
84 | } | ||
85 | else { | ||
86 | thread->acquired_mutex_list = obj_desc->mutex.next; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | |||
91 | /******************************************************************************* | ||
92 | * | ||
93 | * FUNCTION: acpi_ex_link_mutex | ||
94 | * | ||
95 | * PARAMETERS: obj_desc - The mutex to be linked | ||
96 | * list_head - head of the "acquired_mutex" list | ||
97 | * | ||
98 | * RETURN: Status | ||
99 | * | ||
100 | * DESCRIPTION: Add a mutex to the "acquired_mutex" list for this walk | ||
101 | * | ||
102 | ******************************************************************************/ | ||
103 | |||
104 | void | ||
105 | acpi_ex_link_mutex ( | ||
106 | union acpi_operand_object *obj_desc, | ||
107 | struct acpi_thread_state *thread) | ||
108 | { | ||
109 | union acpi_operand_object *list_head; | ||
110 | |||
111 | |||
112 | list_head = thread->acquired_mutex_list; | ||
113 | |||
114 | /* This object will be the first object in the list */ | ||
115 | |||
116 | obj_desc->mutex.prev = NULL; | ||
117 | obj_desc->mutex.next = list_head; | ||
118 | |||
119 | /* Update old first object to point back to this object */ | ||
120 | |||
121 | if (list_head) { | ||
122 | list_head->mutex.prev = obj_desc; | ||
123 | } | ||
124 | |||
125 | /* Update list head */ | ||
126 | |||
127 | thread->acquired_mutex_list = obj_desc; | ||
128 | } | ||
129 | |||
130 | |||
131 | /******************************************************************************* | ||
132 | * | ||
133 | * FUNCTION: acpi_ex_acquire_mutex | ||
134 | * | ||
135 | * PARAMETERS: time_desc - The 'time to delay' object descriptor | ||
136 | * obj_desc - The object descriptor for this op | ||
137 | * | ||
138 | * RETURN: Status | ||
139 | * | ||
140 | * DESCRIPTION: Acquire an AML mutex | ||
141 | * | ||
142 | ******************************************************************************/ | ||
143 | |||
144 | acpi_status | ||
145 | acpi_ex_acquire_mutex ( | ||
146 | union acpi_operand_object *time_desc, | ||
147 | union acpi_operand_object *obj_desc, | ||
148 | struct acpi_walk_state *walk_state) | ||
149 | { | ||
150 | acpi_status status; | ||
151 | |||
152 | |||
153 | ACPI_FUNCTION_TRACE_PTR ("ex_acquire_mutex", obj_desc); | ||
154 | |||
155 | |||
156 | if (!obj_desc) { | ||
157 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
158 | } | ||
159 | |||
160 | /* Sanity check -- we must have a valid thread ID */ | ||
161 | |||
162 | if (!walk_state->thread) { | ||
163 | ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], null thread info\n", | ||
164 | acpi_ut_get_node_name (obj_desc->mutex.node))); | ||
165 | return_ACPI_STATUS (AE_AML_INTERNAL); | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * Current Sync must be less than or equal to the sync level of the | ||
170 | * mutex. This mechanism provides some deadlock prevention | ||
171 | */ | ||
172 | if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { | ||
173 | ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], incorrect sync_level\n", | ||
174 | acpi_ut_get_node_name (obj_desc->mutex.node))); | ||
175 | return_ACPI_STATUS (AE_AML_MUTEX_ORDER); | ||
176 | } | ||
177 | |||
178 | /* Support for multiple acquires by the owning thread */ | ||
179 | |||
180 | if (obj_desc->mutex.owner_thread) { | ||
181 | /* Special case for Global Lock, allow all threads */ | ||
182 | |||
183 | if ((obj_desc->mutex.owner_thread->thread_id == walk_state->thread->thread_id) || | ||
184 | (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore)) { | ||
185 | /* | ||
186 | * The mutex is already owned by this thread, | ||
187 | * just increment the acquisition depth | ||
188 | */ | ||
189 | obj_desc->mutex.acquisition_depth++; | ||
190 | return_ACPI_STATUS (AE_OK); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | /* Acquire the mutex, wait if necessary */ | ||
195 | |||
196 | status = acpi_ex_system_acquire_mutex (time_desc, obj_desc); | ||
197 | if (ACPI_FAILURE (status)) { | ||
198 | /* Includes failure from a timeout on time_desc */ | ||
199 | |||
200 | return_ACPI_STATUS (status); | ||
201 | } | ||
202 | |||
203 | /* Have the mutex: update mutex and walk info and save the sync_level */ | ||
204 | |||
205 | obj_desc->mutex.owner_thread = walk_state->thread; | ||
206 | obj_desc->mutex.acquisition_depth = 1; | ||
207 | obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level; | ||
208 | |||
209 | walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; | ||
210 | |||
211 | /* Link the mutex to the current thread for force-unlock at method exit */ | ||
212 | |||
213 | acpi_ex_link_mutex (obj_desc, walk_state->thread); | ||
214 | |||
215 | return_ACPI_STATUS (AE_OK); | ||
216 | } | ||
217 | |||
218 | |||
219 | /******************************************************************************* | ||
220 | * | ||
221 | * FUNCTION: acpi_ex_release_mutex | ||
222 | * | ||
223 | * PARAMETERS: obj_desc - The object descriptor for this op | ||
224 | * | ||
225 | * RETURN: Status | ||
226 | * | ||
227 | * DESCRIPTION: Release a previously acquired Mutex. | ||
228 | * | ||
229 | ******************************************************************************/ | ||
230 | |||
231 | acpi_status | ||
232 | acpi_ex_release_mutex ( | ||
233 | union acpi_operand_object *obj_desc, | ||
234 | struct acpi_walk_state *walk_state) | ||
235 | { | ||
236 | acpi_status status; | ||
237 | |||
238 | |||
239 | ACPI_FUNCTION_TRACE ("ex_release_mutex"); | ||
240 | |||
241 | |||
242 | if (!obj_desc) { | ||
243 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
244 | } | ||
245 | |||
246 | /* The mutex must have been previously acquired in order to release it */ | ||
247 | |||
248 | if (!obj_desc->mutex.owner_thread) { | ||
249 | ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], not acquired\n", | ||
250 | acpi_ut_get_node_name (obj_desc->mutex.node))); | ||
251 | return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED); | ||
252 | } | ||
253 | |||
254 | /* Sanity check -- we must have a valid thread ID */ | ||
255 | |||
256 | if (!walk_state->thread) { | ||
257 | ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], null thread info\n", | ||
258 | acpi_ut_get_node_name (obj_desc->mutex.node))); | ||
259 | return_ACPI_STATUS (AE_AML_INTERNAL); | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * The Mutex is owned, but this thread must be the owner. | ||
264 | * Special case for Global Lock, any thread can release | ||
265 | */ | ||
266 | if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) && | ||
267 | (obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) { | ||
268 | ACPI_REPORT_ERROR (( | ||
269 | "Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n", | ||
270 | walk_state->thread->thread_id, | ||
271 | acpi_ut_get_node_name (obj_desc->mutex.node), | ||
272 | obj_desc->mutex.owner_thread->thread_id)); | ||
273 | return_ACPI_STATUS (AE_AML_NOT_OWNER); | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * The sync level of the mutex must be less than or | ||
278 | * equal to the current sync level | ||
279 | */ | ||
280 | if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { | ||
281 | ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], incorrect sync_level\n", | ||
282 | acpi_ut_get_node_name (obj_desc->mutex.node))); | ||
283 | return_ACPI_STATUS (AE_AML_MUTEX_ORDER); | ||
284 | } | ||
285 | |||
286 | /* Match multiple Acquires with multiple Releases */ | ||
287 | |||
288 | obj_desc->mutex.acquisition_depth--; | ||
289 | if (obj_desc->mutex.acquisition_depth != 0) { | ||
290 | /* Just decrement the depth and return */ | ||
291 | |||
292 | return_ACPI_STATUS (AE_OK); | ||
293 | } | ||
294 | |||
295 | /* Unlink the mutex from the owner's list */ | ||
296 | |||
297 | acpi_ex_unlink_mutex (obj_desc); | ||
298 | |||
299 | /* Release the mutex */ | ||
300 | |||
301 | status = acpi_ex_system_release_mutex (obj_desc); | ||
302 | |||
303 | /* Update the mutex and walk state, restore sync_level before acquire */ | ||
304 | |||
305 | obj_desc->mutex.owner_thread = NULL; | ||
306 | walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level; | ||
307 | |||
308 | return_ACPI_STATUS (status); | ||
309 | } | ||
310 | |||
311 | |||
312 | /******************************************************************************* | ||
313 | * | ||
314 | * FUNCTION: acpi_ex_release_all_mutexes | ||
315 | * | ||
316 | * PARAMETERS: mutex_list - Head of the mutex list | ||
317 | * | ||
318 | * RETURN: Status | ||
319 | * | ||
320 | * DESCRIPTION: Release all mutexes in the list | ||
321 | * | ||
322 | ******************************************************************************/ | ||
323 | |||
324 | void | ||
325 | acpi_ex_release_all_mutexes ( | ||
326 | struct acpi_thread_state *thread) | ||
327 | { | ||
328 | union acpi_operand_object *next = thread->acquired_mutex_list; | ||
329 | union acpi_operand_object *this; | ||
330 | acpi_status status; | ||
331 | |||
332 | |||
333 | ACPI_FUNCTION_ENTRY (); | ||
334 | |||
335 | |||
336 | /* Traverse the list of owned mutexes, releasing each one */ | ||
337 | |||
338 | while (next) { | ||
339 | this = next; | ||
340 | next = this->mutex.next; | ||
341 | |||
342 | this->mutex.acquisition_depth = 1; | ||
343 | this->mutex.prev = NULL; | ||
344 | this->mutex.next = NULL; | ||
345 | |||
346 | /* Release the mutex */ | ||
347 | |||
348 | status = acpi_ex_system_release_mutex (this); | ||
349 | if (ACPI_FAILURE (status)) { | ||
350 | continue; | ||
351 | } | ||
352 | |||
353 | /* Mark mutex unowned */ | ||
354 | |||
355 | this->mutex.owner_thread = NULL; | ||
356 | |||
357 | /* Update Thread sync_level (Last mutex is the important one) */ | ||
358 | |||
359 | thread->current_sync_level = this->mutex.original_sync_level; | ||
360 | } | ||
361 | } | ||
362 | |||
363 | |||
diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c new file mode 100644 index 000000000000..7911c533c265 --- /dev/null +++ b/drivers/acpi/executer/exnames.c | |||
@@ -0,0 +1,427 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exnames - interpreter/scanner name load/execute | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acinterp.h> | ||
48 | #include <acpi/amlcode.h> | ||
49 | |||
50 | #define _COMPONENT ACPI_EXECUTER | ||
51 | ACPI_MODULE_NAME ("exnames") | ||
52 | |||
53 | |||
54 | /* AML Package Length encodings */ | ||
55 | |||
56 | #define ACPI_AML_PACKAGE_TYPE1 0x40 | ||
57 | #define ACPI_AML_PACKAGE_TYPE2 0x4000 | ||
58 | #define ACPI_AML_PACKAGE_TYPE3 0x400000 | ||
59 | #define ACPI_AML_PACKAGE_TYPE4 0x40000000 | ||
60 | |||
61 | |||
62 | /******************************************************************************* | ||
63 | * | ||
64 | * FUNCTION: acpi_ex_allocate_name_string | ||
65 | * | ||
66 | * PARAMETERS: prefix_count - Count of parent levels. Special cases: | ||
67 | * (-1) = root, 0 = none | ||
68 | * num_name_segs - count of 4-character name segments | ||
69 | * | ||
70 | * RETURN: A pointer to the allocated string segment. This segment must | ||
71 | * be deleted by the caller. | ||
72 | * | ||
73 | * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name | ||
74 | * string is long enough, and set up prefix if any. | ||
75 | * | ||
76 | ******************************************************************************/ | ||
77 | |||
78 | char * | ||
79 | acpi_ex_allocate_name_string ( | ||
80 | u32 prefix_count, | ||
81 | u32 num_name_segs) | ||
82 | { | ||
83 | char *temp_ptr; | ||
84 | char *name_string; | ||
85 | u32 size_needed; | ||
86 | |||
87 | ACPI_FUNCTION_TRACE ("ex_allocate_name_string"); | ||
88 | |||
89 | |||
90 | /* | ||
91 | * Allow room for all \ and ^ prefixes, all segments, and a multi_name_prefix. | ||
92 | * Also, one byte for the null terminator. | ||
93 | * This may actually be somewhat longer than needed. | ||
94 | */ | ||
95 | if (prefix_count == ACPI_UINT32_MAX) { | ||
96 | /* Special case for root */ | ||
97 | |||
98 | size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; | ||
99 | } | ||
100 | else { | ||
101 | size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * Allocate a buffer for the name. | ||
106 | * This buffer must be deleted by the caller! | ||
107 | */ | ||
108 | name_string = ACPI_MEM_ALLOCATE (size_needed); | ||
109 | if (!name_string) { | ||
110 | ACPI_REPORT_ERROR (("ex_allocate_name_string: Could not allocate size %d\n", size_needed)); | ||
111 | return_PTR (NULL); | ||
112 | } | ||
113 | |||
114 | temp_ptr = name_string; | ||
115 | |||
116 | /* Set up Root or Parent prefixes if needed */ | ||
117 | |||
118 | if (prefix_count == ACPI_UINT32_MAX) { | ||
119 | *temp_ptr++ = AML_ROOT_PREFIX; | ||
120 | } | ||
121 | else { | ||
122 | while (prefix_count--) { | ||
123 | *temp_ptr++ = AML_PARENT_PREFIX; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | |||
128 | /* Set up Dual or Multi prefixes if needed */ | ||
129 | |||
130 | if (num_name_segs > 2) { | ||
131 | /* Set up multi prefixes */ | ||
132 | |||
133 | *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; | ||
134 | *temp_ptr++ = (char) num_name_segs; | ||
135 | } | ||
136 | else if (2 == num_name_segs) { | ||
137 | /* Set up dual prefixes */ | ||
138 | |||
139 | *temp_ptr++ = AML_DUAL_NAME_PREFIX; | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | * Terminate string following prefixes. acpi_ex_name_segment() will | ||
144 | * append the segment(s) | ||
145 | */ | ||
146 | *temp_ptr = 0; | ||
147 | |||
148 | return_PTR (name_string); | ||
149 | } | ||
150 | |||
151 | /******************************************************************************* | ||
152 | * | ||
153 | * FUNCTION: acpi_ex_name_segment | ||
154 | * | ||
155 | * PARAMETERS: interpreter_mode - Current running mode (load1/Load2/Exec) | ||
156 | * | ||
157 | * RETURN: Status | ||
158 | * | ||
159 | * DESCRIPTION: Execute a name segment (4 bytes) | ||
160 | * | ||
161 | ******************************************************************************/ | ||
162 | |||
163 | acpi_status | ||
164 | acpi_ex_name_segment ( | ||
165 | u8 **in_aml_address, | ||
166 | char *name_string) | ||
167 | { | ||
168 | char *aml_address = (void *) *in_aml_address; | ||
169 | acpi_status status = AE_OK; | ||
170 | u32 index; | ||
171 | char char_buf[5]; | ||
172 | |||
173 | |||
174 | ACPI_FUNCTION_TRACE ("ex_name_segment"); | ||
175 | |||
176 | |||
177 | /* | ||
178 | * If first character is a digit, then we know that we aren't looking at a | ||
179 | * valid name segment | ||
180 | */ | ||
181 | char_buf[0] = *aml_address; | ||
182 | |||
183 | if ('0' <= char_buf[0] && char_buf[0] <= '9') { | ||
184 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "leading digit: %c\n", char_buf[0])); | ||
185 | return_ACPI_STATUS (AE_CTRL_PENDING); | ||
186 | } | ||
187 | |||
188 | ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n")); | ||
189 | |||
190 | for (index = 0; | ||
191 | (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_character (*aml_address)); | ||
192 | index++) { | ||
193 | char_buf[index] = *aml_address++; | ||
194 | ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[index])); | ||
195 | } | ||
196 | |||
197 | |||
198 | /* Valid name segment */ | ||
199 | |||
200 | if (index == 4) { | ||
201 | /* Found 4 valid characters */ | ||
202 | |||
203 | char_buf[4] = '\0'; | ||
204 | |||
205 | if (name_string) { | ||
206 | ACPI_STRCAT (name_string, char_buf); | ||
207 | ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, | ||
208 | "Appended to - %s \n", name_string)); | ||
209 | } | ||
210 | else { | ||
211 | ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, | ||
212 | "No Name string - %s \n", char_buf)); | ||
213 | } | ||
214 | } | ||
215 | else if (index == 0) { | ||
216 | /* | ||
217 | * First character was not a valid name character, | ||
218 | * so we are looking at something other than a name. | ||
219 | */ | ||
220 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
221 | "Leading character is not alpha: %02Xh (not a name)\n", | ||
222 | char_buf[0])); | ||
223 | status = AE_CTRL_PENDING; | ||
224 | } | ||
225 | else { | ||
226 | /* Segment started with one or more valid characters, but fewer than 4 */ | ||
227 | |||
228 | status = AE_AML_BAD_NAME; | ||
229 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad character %02x in name, at %p\n", | ||
230 | *aml_address, aml_address)); | ||
231 | } | ||
232 | |||
233 | *in_aml_address = (u8 *) aml_address; | ||
234 | return_ACPI_STATUS (status); | ||
235 | } | ||
236 | |||
237 | |||
238 | /******************************************************************************* | ||
239 | * | ||
240 | * FUNCTION: acpi_ex_get_name_string | ||
241 | * | ||
242 | * PARAMETERS: data_type - Data type to be associated with this name | ||
243 | * | ||
244 | * RETURN: Status | ||
245 | * | ||
246 | * DESCRIPTION: Get a name, including any prefixes. | ||
247 | * | ||
248 | ******************************************************************************/ | ||
249 | |||
250 | acpi_status | ||
251 | acpi_ex_get_name_string ( | ||
252 | acpi_object_type data_type, | ||
253 | u8 *in_aml_address, | ||
254 | char **out_name_string, | ||
255 | u32 *out_name_length) | ||
256 | { | ||
257 | acpi_status status = AE_OK; | ||
258 | u8 *aml_address = in_aml_address; | ||
259 | char *name_string = NULL; | ||
260 | u32 num_segments; | ||
261 | u32 prefix_count = 0; | ||
262 | u8 has_prefix = FALSE; | ||
263 | |||
264 | |||
265 | ACPI_FUNCTION_TRACE_PTR ("ex_get_name_string", aml_address); | ||
266 | |||
267 | |||
268 | if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type || | ||
269 | ACPI_TYPE_LOCAL_BANK_FIELD == data_type || | ||
270 | ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) { | ||
271 | /* Disallow prefixes for types associated with field_unit names */ | ||
272 | |||
273 | name_string = acpi_ex_allocate_name_string (0, 1); | ||
274 | if (!name_string) { | ||
275 | status = AE_NO_MEMORY; | ||
276 | } | ||
277 | else { | ||
278 | status = acpi_ex_name_segment (&aml_address, name_string); | ||
279 | } | ||
280 | } | ||
281 | else { | ||
282 | /* | ||
283 | * data_type is not a field name. | ||
284 | * Examine first character of name for root or parent prefix operators | ||
285 | */ | ||
286 | switch (*aml_address) { | ||
287 | case AML_ROOT_PREFIX: | ||
288 | |||
289 | ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "root_prefix(\\) at %p\n", aml_address)); | ||
290 | |||
291 | /* | ||
292 | * Remember that we have a root_prefix -- | ||
293 | * see comment in acpi_ex_allocate_name_string() | ||
294 | */ | ||
295 | aml_address++; | ||
296 | prefix_count = ACPI_UINT32_MAX; | ||
297 | has_prefix = TRUE; | ||
298 | break; | ||
299 | |||
300 | |||
301 | case AML_PARENT_PREFIX: | ||
302 | |||
303 | /* Increment past possibly multiple parent prefixes */ | ||
304 | |||
305 | do { | ||
306 | ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "parent_prefix (^) at %p\n", aml_address)); | ||
307 | |||
308 | aml_address++; | ||
309 | prefix_count++; | ||
310 | |||
311 | } while (*aml_address == AML_PARENT_PREFIX); | ||
312 | |||
313 | has_prefix = TRUE; | ||
314 | break; | ||
315 | |||
316 | |||
317 | default: | ||
318 | |||
319 | /* Not a prefix character */ | ||
320 | |||
321 | break; | ||
322 | } | ||
323 | |||
324 | |||
325 | /* Examine first character of name for name segment prefix operator */ | ||
326 | |||
327 | switch (*aml_address) { | ||
328 | case AML_DUAL_NAME_PREFIX: | ||
329 | |||
330 | ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "dual_name_prefix at %p\n", aml_address)); | ||
331 | |||
332 | aml_address++; | ||
333 | name_string = acpi_ex_allocate_name_string (prefix_count, 2); | ||
334 | if (!name_string) { | ||
335 | status = AE_NO_MEMORY; | ||
336 | break; | ||
337 | } | ||
338 | |||
339 | /* Indicate that we processed a prefix */ | ||
340 | |||
341 | has_prefix = TRUE; | ||
342 | |||
343 | status = acpi_ex_name_segment (&aml_address, name_string); | ||
344 | if (ACPI_SUCCESS (status)) { | ||
345 | status = acpi_ex_name_segment (&aml_address, name_string); | ||
346 | } | ||
347 | break; | ||
348 | |||
349 | |||
350 | case AML_MULTI_NAME_PREFIX_OP: | ||
351 | |||
352 | ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "multi_name_prefix at %p\n", aml_address)); | ||
353 | |||
354 | /* Fetch count of segments remaining in name path */ | ||
355 | |||
356 | aml_address++; | ||
357 | num_segments = *aml_address; | ||
358 | |||
359 | name_string = acpi_ex_allocate_name_string (prefix_count, num_segments); | ||
360 | if (!name_string) { | ||
361 | status = AE_NO_MEMORY; | ||
362 | break; | ||
363 | } | ||
364 | |||
365 | /* Indicate that we processed a prefix */ | ||
366 | |||
367 | aml_address++; | ||
368 | has_prefix = TRUE; | ||
369 | |||
370 | while (num_segments && | ||
371 | (status = acpi_ex_name_segment (&aml_address, name_string)) == AE_OK) { | ||
372 | num_segments--; | ||
373 | } | ||
374 | |||
375 | break; | ||
376 | |||
377 | |||
378 | case 0: | ||
379 | |||
380 | /* null_name valid as of 8-12-98 ASL/AML Grammar Update */ | ||
381 | |||
382 | if (prefix_count == ACPI_UINT32_MAX) { | ||
383 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "name_seg is \"\\\" followed by NULL\n")); | ||
384 | } | ||
385 | |||
386 | /* Consume the NULL byte */ | ||
387 | |||
388 | aml_address++; | ||
389 | name_string = acpi_ex_allocate_name_string (prefix_count, 0); | ||
390 | if (!name_string) { | ||
391 | status = AE_NO_MEMORY; | ||
392 | break; | ||
393 | } | ||
394 | |||
395 | break; | ||
396 | |||
397 | |||
398 | default: | ||
399 | |||
400 | /* Name segment string */ | ||
401 | |||
402 | name_string = acpi_ex_allocate_name_string (prefix_count, 1); | ||
403 | if (!name_string) { | ||
404 | status = AE_NO_MEMORY; | ||
405 | break; | ||
406 | } | ||
407 | |||
408 | status = acpi_ex_name_segment (&aml_address, name_string); | ||
409 | break; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | if (AE_CTRL_PENDING == status && has_prefix) { | ||
414 | /* Ran out of segments after processing a prefix */ | ||
415 | |||
416 | ACPI_REPORT_ERROR ( | ||
417 | ("ex_do_name: Malformed Name at %p\n", name_string)); | ||
418 | status = AE_AML_BAD_NAME; | ||
419 | } | ||
420 | |||
421 | *out_name_string = name_string; | ||
422 | *out_name_length = (u32) (aml_address - in_aml_address); | ||
423 | |||
424 | return_ACPI_STATUS (status); | ||
425 | } | ||
426 | |||
427 | |||
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c new file mode 100644 index 000000000000..8482aefaf38b --- /dev/null +++ b/drivers/acpi/executer/exoparg1.c | |||
@@ -0,0 +1,1013 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exoparg1 - AML execution - opcodes with 1 argument | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acparser.h> | ||
48 | #include <acpi/acdispat.h> | ||
49 | #include <acpi/acinterp.h> | ||
50 | #include <acpi/amlcode.h> | ||
51 | #include <acpi/acnamesp.h> | ||
52 | |||
53 | |||
54 | #define _COMPONENT ACPI_EXECUTER | ||
55 | ACPI_MODULE_NAME ("exoparg1") | ||
56 | |||
57 | |||
58 | /*! | ||
59 | * Naming convention for AML interpreter execution routines. | ||
60 | * | ||
61 | * The routines that begin execution of AML opcodes are named with a common | ||
62 | * convention based upon the number of arguments, the number of target operands, | ||
63 | * and whether or not a value is returned: | ||
64 | * | ||
65 | * AcpiExOpcode_xA_yT_zR | ||
66 | * | ||
67 | * Where: | ||
68 | * | ||
69 | * xA - ARGUMENTS: The number of arguments (input operands) that are | ||
70 | * required for this opcode type (0 through 6 args). | ||
71 | * yT - TARGETS: The number of targets (output operands) that are required | ||
72 | * for this opcode type (0, 1, or 2 targets). | ||
73 | * zR - RETURN VALUE: Indicates whether this opcode type returns a value | ||
74 | * as the function return (0 or 1). | ||
75 | * | ||
76 | * The AcpiExOpcode* functions are called via the Dispatcher component with | ||
77 | * fully resolved operands. | ||
78 | !*/ | ||
79 | |||
80 | /******************************************************************************* | ||
81 | * | ||
82 | * FUNCTION: acpi_ex_opcode_0A_0T_1R | ||
83 | * | ||
84 | * PARAMETERS: walk_state - Current state (contains AML opcode) | ||
85 | * | ||
86 | * RETURN: Status | ||
87 | * | ||
88 | * DESCRIPTION: Execute operator with no operands, one return value | ||
89 | * | ||
90 | ******************************************************************************/ | ||
91 | |||
92 | acpi_status | ||
93 | acpi_ex_opcode_0A_0T_1R ( | ||
94 | struct acpi_walk_state *walk_state) | ||
95 | { | ||
96 | acpi_status status = AE_OK; | ||
97 | union acpi_operand_object *return_desc = NULL; | ||
98 | |||
99 | |||
100 | ACPI_FUNCTION_TRACE_STR ("ex_opcode_0A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); | ||
101 | |||
102 | |||
103 | /* Examine the AML opcode */ | ||
104 | |||
105 | switch (walk_state->opcode) { | ||
106 | case AML_TIMER_OP: /* Timer () */ | ||
107 | |||
108 | /* Create a return object of type Integer */ | ||
109 | |||
110 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
111 | if (!return_desc) { | ||
112 | status = AE_NO_MEMORY; | ||
113 | goto cleanup; | ||
114 | } | ||
115 | |||
116 | return_desc->integer.value = acpi_os_get_timer (); | ||
117 | break; | ||
118 | |||
119 | default: /* Unknown opcode */ | ||
120 | |||
121 | ACPI_REPORT_ERROR (("acpi_ex_opcode_0A_0T_1R: Unknown opcode %X\n", | ||
122 | walk_state->opcode)); | ||
123 | status = AE_AML_BAD_OPCODE; | ||
124 | break; | ||
125 | } | ||
126 | |||
127 | cleanup: | ||
128 | |||
129 | if (!walk_state->result_obj) { | ||
130 | walk_state->result_obj = return_desc; | ||
131 | } | ||
132 | |||
133 | /* Delete return object on error */ | ||
134 | |||
135 | if (ACPI_FAILURE (status)) { | ||
136 | acpi_ut_remove_reference (return_desc); | ||
137 | } | ||
138 | |||
139 | return_ACPI_STATUS (status); | ||
140 | } | ||
141 | |||
142 | |||
143 | /******************************************************************************* | ||
144 | * | ||
145 | * FUNCTION: acpi_ex_opcode_1A_0T_0R | ||
146 | * | ||
147 | * PARAMETERS: walk_state - Current state (contains AML opcode) | ||
148 | * | ||
149 | * RETURN: Status | ||
150 | * | ||
151 | * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on | ||
152 | * object stack | ||
153 | * | ||
154 | ******************************************************************************/ | ||
155 | |||
156 | acpi_status | ||
157 | acpi_ex_opcode_1A_0T_0R ( | ||
158 | struct acpi_walk_state *walk_state) | ||
159 | { | ||
160 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
161 | acpi_status status = AE_OK; | ||
162 | |||
163 | |||
164 | ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); | ||
165 | |||
166 | |||
167 | /* Examine the AML opcode */ | ||
168 | |||
169 | switch (walk_state->opcode) { | ||
170 | case AML_RELEASE_OP: /* Release (mutex_object) */ | ||
171 | |||
172 | status = acpi_ex_release_mutex (operand[0], walk_state); | ||
173 | break; | ||
174 | |||
175 | |||
176 | case AML_RESET_OP: /* Reset (event_object) */ | ||
177 | |||
178 | status = acpi_ex_system_reset_event (operand[0]); | ||
179 | break; | ||
180 | |||
181 | |||
182 | case AML_SIGNAL_OP: /* Signal (event_object) */ | ||
183 | |||
184 | status = acpi_ex_system_signal_event (operand[0]); | ||
185 | break; | ||
186 | |||
187 | |||
188 | case AML_SLEEP_OP: /* Sleep (msec_time) */ | ||
189 | |||
190 | status = acpi_ex_system_do_suspend (operand[0]->integer.value); | ||
191 | break; | ||
192 | |||
193 | |||
194 | case AML_STALL_OP: /* Stall (usec_time) */ | ||
195 | |||
196 | status = acpi_ex_system_do_stall ((u32) operand[0]->integer.value); | ||
197 | break; | ||
198 | |||
199 | |||
200 | case AML_UNLOAD_OP: /* Unload (Handle) */ | ||
201 | |||
202 | status = acpi_ex_unload_table (operand[0]); | ||
203 | break; | ||
204 | |||
205 | |||
206 | default: /* Unknown opcode */ | ||
207 | |||
208 | ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_0T_0R: Unknown opcode %X\n", | ||
209 | walk_state->opcode)); | ||
210 | status = AE_AML_BAD_OPCODE; | ||
211 | break; | ||
212 | } | ||
213 | |||
214 | return_ACPI_STATUS (status); | ||
215 | } | ||
216 | |||
217 | |||
218 | /******************************************************************************* | ||
219 | * | ||
220 | * FUNCTION: acpi_ex_opcode_1A_1T_0R | ||
221 | * | ||
222 | * PARAMETERS: walk_state - Current state (contains AML opcode) | ||
223 | * | ||
224 | * RETURN: Status | ||
225 | * | ||
226 | * DESCRIPTION: Execute opcode with one argument, one target, and no | ||
227 | * return value. | ||
228 | * | ||
229 | ******************************************************************************/ | ||
230 | |||
231 | acpi_status | ||
232 | acpi_ex_opcode_1A_1T_0R ( | ||
233 | struct acpi_walk_state *walk_state) | ||
234 | { | ||
235 | acpi_status status = AE_OK; | ||
236 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
237 | |||
238 | |||
239 | ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_1T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); | ||
240 | |||
241 | |||
242 | /* Examine the AML opcode */ | ||
243 | |||
244 | switch (walk_state->opcode) { | ||
245 | case AML_LOAD_OP: | ||
246 | |||
247 | status = acpi_ex_load_op (operand[0], operand[1], walk_state); | ||
248 | break; | ||
249 | |||
250 | default: /* Unknown opcode */ | ||
251 | |||
252 | ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_1T_0R: Unknown opcode %X\n", | ||
253 | walk_state->opcode)); | ||
254 | status = AE_AML_BAD_OPCODE; | ||
255 | goto cleanup; | ||
256 | } | ||
257 | |||
258 | |||
259 | cleanup: | ||
260 | |||
261 | return_ACPI_STATUS (status); | ||
262 | } | ||
263 | |||
264 | |||
265 | /******************************************************************************* | ||
266 | * | ||
267 | * FUNCTION: acpi_ex_opcode_1A_1T_1R | ||
268 | * | ||
269 | * PARAMETERS: walk_state - Current state (contains AML opcode) | ||
270 | * | ||
271 | * RETURN: Status | ||
272 | * | ||
273 | * DESCRIPTION: Execute opcode with one argument, one target, and a | ||
274 | * return value. | ||
275 | * | ||
276 | ******************************************************************************/ | ||
277 | |||
278 | acpi_status | ||
279 | acpi_ex_opcode_1A_1T_1R ( | ||
280 | struct acpi_walk_state *walk_state) | ||
281 | { | ||
282 | acpi_status status = AE_OK; | ||
283 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
284 | union acpi_operand_object *return_desc = NULL; | ||
285 | union acpi_operand_object *return_desc2 = NULL; | ||
286 | u32 temp32; | ||
287 | u32 i; | ||
288 | acpi_integer power_of_ten; | ||
289 | acpi_integer digit; | ||
290 | |||
291 | |||
292 | ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); | ||
293 | |||
294 | |||
295 | /* Examine the AML opcode */ | ||
296 | |||
297 | switch (walk_state->opcode) { | ||
298 | case AML_BIT_NOT_OP: | ||
299 | case AML_FIND_SET_LEFT_BIT_OP: | ||
300 | case AML_FIND_SET_RIGHT_BIT_OP: | ||
301 | case AML_FROM_BCD_OP: | ||
302 | case AML_TO_BCD_OP: | ||
303 | case AML_COND_REF_OF_OP: | ||
304 | |||
305 | /* Create a return object of type Integer for these opcodes */ | ||
306 | |||
307 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
308 | if (!return_desc) { | ||
309 | status = AE_NO_MEMORY; | ||
310 | goto cleanup; | ||
311 | } | ||
312 | |||
313 | switch (walk_state->opcode) { | ||
314 | case AML_BIT_NOT_OP: /* Not (Operand, Result) */ | ||
315 | |||
316 | return_desc->integer.value = ~operand[0]->integer.value; | ||
317 | break; | ||
318 | |||
319 | |||
320 | case AML_FIND_SET_LEFT_BIT_OP: /* find_set_left_bit (Operand, Result) */ | ||
321 | |||
322 | return_desc->integer.value = operand[0]->integer.value; | ||
323 | |||
324 | /* | ||
325 | * Acpi specification describes Integer type as a little | ||
326 | * endian unsigned value, so this boundary condition is valid. | ||
327 | */ | ||
328 | for (temp32 = 0; return_desc->integer.value && | ||
329 | temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { | ||
330 | return_desc->integer.value >>= 1; | ||
331 | } | ||
332 | |||
333 | return_desc->integer.value = temp32; | ||
334 | break; | ||
335 | |||
336 | |||
337 | case AML_FIND_SET_RIGHT_BIT_OP: /* find_set_right_bit (Operand, Result) */ | ||
338 | |||
339 | return_desc->integer.value = operand[0]->integer.value; | ||
340 | |||
341 | /* | ||
342 | * The Acpi specification describes Integer type as a little | ||
343 | * endian unsigned value, so this boundary condition is valid. | ||
344 | */ | ||
345 | for (temp32 = 0; return_desc->integer.value && | ||
346 | temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { | ||
347 | return_desc->integer.value <<= 1; | ||
348 | } | ||
349 | |||
350 | /* Since the bit position is one-based, subtract from 33 (65) */ | ||
351 | |||
352 | return_desc->integer.value = temp32 == 0 ? 0 : | ||
353 | (ACPI_INTEGER_BIT_SIZE + 1) - temp32; | ||
354 | break; | ||
355 | |||
356 | |||
357 | case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */ | ||
358 | |||
359 | /* | ||
360 | * The 64-bit ACPI integer can hold 16 4-bit BCD characters | ||
361 | * (if table is 32-bit, integer can hold 8 BCD characters) | ||
362 | * Convert each 4-bit BCD value | ||
363 | */ | ||
364 | power_of_ten = 1; | ||
365 | return_desc->integer.value = 0; | ||
366 | digit = operand[0]->integer.value; | ||
367 | |||
368 | /* Convert each BCD digit (each is one nybble wide) */ | ||
369 | |||
370 | for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) { | ||
371 | /* Get the least significant 4-bit BCD digit */ | ||
372 | |||
373 | temp32 = ((u32) digit) & 0xF; | ||
374 | |||
375 | /* Check the range of the digit */ | ||
376 | |||
377 | if (temp32 > 9) { | ||
378 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
379 | "BCD digit too large (not decimal): 0x%X\n", | ||
380 | temp32)); | ||
381 | |||
382 | status = AE_AML_NUMERIC_OVERFLOW; | ||
383 | goto cleanup; | ||
384 | } | ||
385 | |||
386 | /* Sum the digit into the result with the current power of 10 */ | ||
387 | |||
388 | return_desc->integer.value += (((acpi_integer) temp32) * | ||
389 | power_of_ten); | ||
390 | |||
391 | /* Shift to next BCD digit */ | ||
392 | |||
393 | digit >>= 4; | ||
394 | |||
395 | /* Next power of 10 */ | ||
396 | |||
397 | power_of_ten *= 10; | ||
398 | } | ||
399 | break; | ||
400 | |||
401 | |||
402 | case AML_TO_BCD_OP: /* to_bcd (Operand, Result) */ | ||
403 | |||
404 | return_desc->integer.value = 0; | ||
405 | digit = operand[0]->integer.value; | ||
406 | |||
407 | /* Each BCD digit is one nybble wide */ | ||
408 | |||
409 | for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) { | ||
410 | (void) acpi_ut_short_divide (digit, 10, &digit, &temp32); | ||
411 | |||
412 | /* Insert the BCD digit that resides in the remainder from above */ | ||
413 | |||
414 | return_desc->integer.value |= (((acpi_integer) temp32) << | ||
415 | ACPI_MUL_4 (i)); | ||
416 | } | ||
417 | |||
418 | /* Overflow if there is any data left in Digit */ | ||
419 | |||
420 | if (digit > 0) { | ||
421 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
422 | "Integer too large to convert to BCD: %8.8X%8.8X\n", | ||
423 | ACPI_FORMAT_UINT64 (operand[0]->integer.value))); | ||
424 | status = AE_AML_NUMERIC_OVERFLOW; | ||
425 | goto cleanup; | ||
426 | } | ||
427 | break; | ||
428 | |||
429 | |||
430 | case AML_COND_REF_OF_OP: /* cond_ref_of (source_object, Result) */ | ||
431 | |||
432 | /* | ||
433 | * This op is a little strange because the internal return value is | ||
434 | * different than the return value stored in the result descriptor | ||
435 | * (There are really two return values) | ||
436 | */ | ||
437 | if ((struct acpi_namespace_node *) operand[0] == acpi_gbl_root_node) { | ||
438 | /* | ||
439 | * This means that the object does not exist in the namespace, | ||
440 | * return FALSE | ||
441 | */ | ||
442 | return_desc->integer.value = 0; | ||
443 | goto cleanup; | ||
444 | } | ||
445 | |||
446 | /* Get the object reference, store it, and remove our reference */ | ||
447 | |||
448 | status = acpi_ex_get_object_reference (operand[0], &return_desc2, walk_state); | ||
449 | if (ACPI_FAILURE (status)) { | ||
450 | goto cleanup; | ||
451 | } | ||
452 | |||
453 | status = acpi_ex_store (return_desc2, operand[1], walk_state); | ||
454 | acpi_ut_remove_reference (return_desc2); | ||
455 | |||
456 | /* The object exists in the namespace, return TRUE */ | ||
457 | |||
458 | return_desc->integer.value = ACPI_INTEGER_MAX; | ||
459 | goto cleanup; | ||
460 | |||
461 | |||
462 | default: | ||
463 | /* No other opcodes get here */ | ||
464 | break; | ||
465 | } | ||
466 | break; | ||
467 | |||
468 | |||
469 | case AML_STORE_OP: /* Store (Source, Target) */ | ||
470 | |||
471 | /* | ||
472 | * A store operand is typically a number, string, buffer or lvalue | ||
473 | * Be careful about deleting the source object, | ||
474 | * since the object itself may have been stored. | ||
475 | */ | ||
476 | status = acpi_ex_store (operand[0], operand[1], walk_state); | ||
477 | if (ACPI_FAILURE (status)) { | ||
478 | return_ACPI_STATUS (status); | ||
479 | } | ||
480 | |||
481 | /* It is possible that the Store already produced a return object */ | ||
482 | |||
483 | if (!walk_state->result_obj) { | ||
484 | /* | ||
485 | * Normally, we would remove a reference on the Operand[0] parameter; | ||
486 | * But since it is being used as the internal return object | ||
487 | * (meaning we would normally increment it), the two cancel out, | ||
488 | * and we simply don't do anything. | ||
489 | */ | ||
490 | walk_state->result_obj = operand[0]; | ||
491 | walk_state->operands[0] = NULL; /* Prevent deletion */ | ||
492 | } | ||
493 | return_ACPI_STATUS (status); | ||
494 | |||
495 | |||
496 | /* | ||
497 | * ACPI 2.0 Opcodes | ||
498 | */ | ||
499 | case AML_COPY_OP: /* Copy (Source, Target) */ | ||
500 | |||
501 | status = acpi_ut_copy_iobject_to_iobject (operand[0], &return_desc, | ||
502 | walk_state); | ||
503 | break; | ||
504 | |||
505 | |||
506 | case AML_TO_DECSTRING_OP: /* to_decimal_string (Data, Result) */ | ||
507 | |||
508 | status = acpi_ex_convert_to_string (operand[0], &return_desc, | ||
509 | ACPI_EXPLICIT_CONVERT_DECIMAL); | ||
510 | if (return_desc == operand[0]) { | ||
511 | /* No conversion performed, add ref to handle return value */ | ||
512 | acpi_ut_add_reference (return_desc); | ||
513 | } | ||
514 | break; | ||
515 | |||
516 | |||
517 | case AML_TO_HEXSTRING_OP: /* to_hex_string (Data, Result) */ | ||
518 | |||
519 | status = acpi_ex_convert_to_string (operand[0], &return_desc, | ||
520 | ACPI_EXPLICIT_CONVERT_HEX); | ||
521 | if (return_desc == operand[0]) { | ||
522 | /* No conversion performed, add ref to handle return value */ | ||
523 | acpi_ut_add_reference (return_desc); | ||
524 | } | ||
525 | break; | ||
526 | |||
527 | |||
528 | case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */ | ||
529 | |||
530 | status = acpi_ex_convert_to_buffer (operand[0], &return_desc); | ||
531 | if (return_desc == operand[0]) { | ||
532 | /* No conversion performed, add ref to handle return value */ | ||
533 | acpi_ut_add_reference (return_desc); | ||
534 | } | ||
535 | break; | ||
536 | |||
537 | |||
538 | case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */ | ||
539 | |||
540 | status = acpi_ex_convert_to_integer (operand[0], &return_desc, | ||
541 | ACPI_ANY_BASE); | ||
542 | if (return_desc == operand[0]) { | ||
543 | /* No conversion performed, add ref to handle return value */ | ||
544 | acpi_ut_add_reference (return_desc); | ||
545 | } | ||
546 | break; | ||
547 | |||
548 | |||
549 | case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */ | ||
550 | case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */ | ||
551 | |||
552 | /* | ||
553 | * These are two obsolete opcodes | ||
554 | */ | ||
555 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
556 | "%s is obsolete and not implemented\n", | ||
557 | acpi_ps_get_opcode_name (walk_state->opcode))); | ||
558 | status = AE_SUPPORT; | ||
559 | goto cleanup; | ||
560 | |||
561 | |||
562 | default: /* Unknown opcode */ | ||
563 | |||
564 | ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_1T_1R: Unknown opcode %X\n", | ||
565 | walk_state->opcode)); | ||
566 | status = AE_AML_BAD_OPCODE; | ||
567 | goto cleanup; | ||
568 | } | ||
569 | |||
570 | if (ACPI_SUCCESS (status)) { | ||
571 | /* | ||
572 | * Store the return value computed above into the target object | ||
573 | */ | ||
574 | status = acpi_ex_store (return_desc, operand[1], walk_state); | ||
575 | } | ||
576 | |||
577 | |||
578 | cleanup: | ||
579 | |||
580 | if (!walk_state->result_obj) { | ||
581 | walk_state->result_obj = return_desc; | ||
582 | } | ||
583 | |||
584 | /* Delete return object on error */ | ||
585 | |||
586 | if (ACPI_FAILURE (status)) { | ||
587 | acpi_ut_remove_reference (return_desc); | ||
588 | } | ||
589 | |||
590 | return_ACPI_STATUS (status); | ||
591 | } | ||
592 | |||
593 | |||
594 | /******************************************************************************* | ||
595 | * | ||
596 | * FUNCTION: acpi_ex_opcode_1A_0T_1R | ||
597 | * | ||
598 | * PARAMETERS: walk_state - Current state (contains AML opcode) | ||
599 | * | ||
600 | * RETURN: Status | ||
601 | * | ||
602 | * DESCRIPTION: Execute opcode with one argument, no target, and a return value | ||
603 | * | ||
604 | ******************************************************************************/ | ||
605 | |||
606 | acpi_status | ||
607 | acpi_ex_opcode_1A_0T_1R ( | ||
608 | struct acpi_walk_state *walk_state) | ||
609 | { | ||
610 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
611 | union acpi_operand_object *temp_desc; | ||
612 | union acpi_operand_object *return_desc = NULL; | ||
613 | acpi_status status = AE_OK; | ||
614 | u32 type; | ||
615 | acpi_integer value; | ||
616 | |||
617 | |||
618 | ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); | ||
619 | |||
620 | |||
621 | /* Examine the AML opcode */ | ||
622 | |||
623 | switch (walk_state->opcode) { | ||
624 | case AML_LNOT_OP: /* LNot (Operand) */ | ||
625 | |||
626 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
627 | if (!return_desc) { | ||
628 | status = AE_NO_MEMORY; | ||
629 | goto cleanup; | ||
630 | } | ||
631 | |||
632 | /* | ||
633 | * Set result to ONES (TRUE) if Value == 0. Note: | ||
634 | * return_desc->Integer.Value is initially == 0 (FALSE) from above. | ||
635 | */ | ||
636 | if (!operand[0]->integer.value) { | ||
637 | return_desc->integer.value = ACPI_INTEGER_MAX; | ||
638 | } | ||
639 | break; | ||
640 | |||
641 | |||
642 | case AML_DECREMENT_OP: /* Decrement (Operand) */ | ||
643 | case AML_INCREMENT_OP: /* Increment (Operand) */ | ||
644 | |||
645 | /* | ||
646 | * Create a new integer. Can't just get the base integer and | ||
647 | * increment it because it may be an Arg or Field. | ||
648 | */ | ||
649 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
650 | if (!return_desc) { | ||
651 | status = AE_NO_MEMORY; | ||
652 | goto cleanup; | ||
653 | } | ||
654 | |||
655 | /* | ||
656 | * Since we are expecting a Reference operand, it can be either a | ||
657 | * NS Node or an internal object. | ||
658 | */ | ||
659 | temp_desc = operand[0]; | ||
660 | if (ACPI_GET_DESCRIPTOR_TYPE (temp_desc) == ACPI_DESC_TYPE_OPERAND) { | ||
661 | /* Internal reference object - prevent deletion */ | ||
662 | |||
663 | acpi_ut_add_reference (temp_desc); | ||
664 | } | ||
665 | |||
666 | /* | ||
667 | * Convert the Reference operand to an Integer (This removes a | ||
668 | * reference on the Operand[0] object) | ||
669 | * | ||
670 | * NOTE: We use LNOT_OP here in order to force resolution of the | ||
671 | * reference operand to an actual integer. | ||
672 | */ | ||
673 | status = acpi_ex_resolve_operands (AML_LNOT_OP, &temp_desc, walk_state); | ||
674 | if (ACPI_FAILURE (status)) { | ||
675 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s: bad operand(s) %s\n", | ||
676 | acpi_ps_get_opcode_name (walk_state->opcode), | ||
677 | acpi_format_exception(status))); | ||
678 | |||
679 | goto cleanup; | ||
680 | } | ||
681 | |||
682 | /* | ||
683 | * temp_desc is now guaranteed to be an Integer object -- | ||
684 | * Perform the actual increment or decrement | ||
685 | */ | ||
686 | if (walk_state->opcode == AML_INCREMENT_OP) { | ||
687 | return_desc->integer.value = temp_desc->integer.value +1; | ||
688 | } | ||
689 | else { | ||
690 | return_desc->integer.value = temp_desc->integer.value -1; | ||
691 | } | ||
692 | |||
693 | /* Finished with this Integer object */ | ||
694 | |||
695 | acpi_ut_remove_reference (temp_desc); | ||
696 | |||
697 | /* | ||
698 | * Store the result back (indirectly) through the original | ||
699 | * Reference object | ||
700 | */ | ||
701 | status = acpi_ex_store (return_desc, operand[0], walk_state); | ||
702 | break; | ||
703 | |||
704 | |||
705 | case AML_TYPE_OP: /* object_type (source_object) */ | ||
706 | |||
707 | /* | ||
708 | * Note: The operand is not resolved at this point because we want to | ||
709 | * get the associated object, not its value. For example, we don't want | ||
710 | * to resolve a field_unit to its value, we want the actual field_unit | ||
711 | * object. | ||
712 | */ | ||
713 | |||
714 | /* Get the type of the base object */ | ||
715 | |||
716 | status = acpi_ex_resolve_multiple (walk_state, operand[0], &type, NULL); | ||
717 | if (ACPI_FAILURE (status)) { | ||
718 | goto cleanup; | ||
719 | } | ||
720 | /* Allocate a descriptor to hold the type. */ | ||
721 | |||
722 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
723 | if (!return_desc) { | ||
724 | status = AE_NO_MEMORY; | ||
725 | goto cleanup; | ||
726 | } | ||
727 | |||
728 | return_desc->integer.value = type; | ||
729 | break; | ||
730 | |||
731 | |||
732 | case AML_SIZE_OF_OP: /* size_of (source_object) */ | ||
733 | |||
734 | /* | ||
735 | * Note: The operand is not resolved at this point because we want to | ||
736 | * get the associated object, not its value. | ||
737 | */ | ||
738 | |||
739 | /* Get the base object */ | ||
740 | |||
741 | status = acpi_ex_resolve_multiple (walk_state, operand[0], &type, &temp_desc); | ||
742 | if (ACPI_FAILURE (status)) { | ||
743 | goto cleanup; | ||
744 | } | ||
745 | |||
746 | /* | ||
747 | * The type of the base object must be integer, buffer, string, or | ||
748 | * package. All others are not supported. | ||
749 | * | ||
750 | * NOTE: Integer is not specifically supported by the ACPI spec, | ||
751 | * but is supported implicitly via implicit operand conversion. | ||
752 | * rather than bother with conversion, we just use the byte width | ||
753 | * global (4 or 8 bytes). | ||
754 | */ | ||
755 | switch (type) { | ||
756 | case ACPI_TYPE_INTEGER: | ||
757 | value = acpi_gbl_integer_byte_width; | ||
758 | break; | ||
759 | |||
760 | case ACPI_TYPE_BUFFER: | ||
761 | value = temp_desc->buffer.length; | ||
762 | break; | ||
763 | |||
764 | case ACPI_TYPE_STRING: | ||
765 | value = temp_desc->string.length; | ||
766 | break; | ||
767 | |||
768 | case ACPI_TYPE_PACKAGE: | ||
769 | value = temp_desc->package.count; | ||
770 | break; | ||
771 | |||
772 | default: | ||
773 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
774 | "size_of - Operand is not Buf/Int/Str/Pkg - found type %s\n", | ||
775 | acpi_ut_get_type_name (type))); | ||
776 | status = AE_AML_OPERAND_TYPE; | ||
777 | goto cleanup; | ||
778 | } | ||
779 | |||
780 | /* | ||
781 | * Now that we have the size of the object, create a result | ||
782 | * object to hold the value | ||
783 | */ | ||
784 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
785 | if (!return_desc) { | ||
786 | status = AE_NO_MEMORY; | ||
787 | goto cleanup; | ||
788 | } | ||
789 | |||
790 | return_desc->integer.value = value; | ||
791 | break; | ||
792 | |||
793 | |||
794 | case AML_REF_OF_OP: /* ref_of (source_object) */ | ||
795 | |||
796 | status = acpi_ex_get_object_reference (operand[0], &return_desc, walk_state); | ||
797 | if (ACPI_FAILURE (status)) { | ||
798 | goto cleanup; | ||
799 | } | ||
800 | break; | ||
801 | |||
802 | |||
803 | case AML_DEREF_OF_OP: /* deref_of (obj_reference | String) */ | ||
804 | |||
805 | /* Check for a method local or argument, or standalone String */ | ||
806 | |||
807 | if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) != ACPI_DESC_TYPE_NAMED) { | ||
808 | switch (ACPI_GET_OBJECT_TYPE (operand[0])) { | ||
809 | case ACPI_TYPE_LOCAL_REFERENCE: | ||
810 | /* | ||
811 | * This is a deref_of (local_x | arg_x) | ||
812 | * | ||
813 | * Must resolve/dereference the local/arg reference first | ||
814 | */ | ||
815 | switch (operand[0]->reference.opcode) { | ||
816 | case AML_LOCAL_OP: | ||
817 | case AML_ARG_OP: | ||
818 | |||
819 | /* Set Operand[0] to the value of the local/arg */ | ||
820 | |||
821 | status = acpi_ds_method_data_get_value (operand[0]->reference.opcode, | ||
822 | operand[0]->reference.offset, walk_state, &temp_desc); | ||
823 | if (ACPI_FAILURE (status)) { | ||
824 | goto cleanup; | ||
825 | } | ||
826 | |||
827 | /* | ||
828 | * Delete our reference to the input object and | ||
829 | * point to the object just retrieved | ||
830 | */ | ||
831 | acpi_ut_remove_reference (operand[0]); | ||
832 | operand[0] = temp_desc; | ||
833 | break; | ||
834 | |||
835 | case AML_REF_OF_OP: | ||
836 | |||
837 | /* Get the object to which the reference refers */ | ||
838 | |||
839 | temp_desc = operand[0]->reference.object; | ||
840 | acpi_ut_remove_reference (operand[0]); | ||
841 | operand[0] = temp_desc; | ||
842 | break; | ||
843 | |||
844 | default: | ||
845 | |||
846 | /* Must be an Index op - handled below */ | ||
847 | break; | ||
848 | } | ||
849 | break; | ||
850 | |||
851 | |||
852 | case ACPI_TYPE_STRING: | ||
853 | |||
854 | /* | ||
855 | * This is a deref_of (String). The string is a reference to a named ACPI object. | ||
856 | * | ||
857 | * 1) Find the owning Node | ||
858 | * 2) Dereference the node to an actual object. Could be a Field, so we nee | ||
859 | * to resolve the node to a value. | ||
860 | */ | ||
861 | status = acpi_ns_get_node_by_path (operand[0]->string.pointer, | ||
862 | walk_state->scope_info->scope.node, ACPI_NS_SEARCH_PARENT, | ||
863 | ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, &return_desc)); | ||
864 | if (ACPI_FAILURE (status)) { | ||
865 | goto cleanup; | ||
866 | } | ||
867 | |||
868 | status = acpi_ex_resolve_node_to_value ( | ||
869 | ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, &return_desc), walk_state); | ||
870 | goto cleanup; | ||
871 | |||
872 | |||
873 | default: | ||
874 | |||
875 | status = AE_AML_OPERAND_TYPE; | ||
876 | goto cleanup; | ||
877 | } | ||
878 | } | ||
879 | |||
880 | /* Operand[0] may have changed from the code above */ | ||
881 | |||
882 | if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) == ACPI_DESC_TYPE_NAMED) { | ||
883 | /* | ||
884 | * This is a deref_of (object_reference) | ||
885 | * Get the actual object from the Node (This is the dereference). | ||
886 | * -- This case may only happen when a local_x or arg_x is dereferenced above. | ||
887 | */ | ||
888 | return_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) operand[0]); | ||
889 | } | ||
890 | else { | ||
891 | /* | ||
892 | * This must be a reference object produced by either the Index() or | ||
893 | * ref_of() operator | ||
894 | */ | ||
895 | switch (operand[0]->reference.opcode) { | ||
896 | case AML_INDEX_OP: | ||
897 | |||
898 | /* | ||
899 | * The target type for the Index operator must be | ||
900 | * either a Buffer or a Package | ||
901 | */ | ||
902 | switch (operand[0]->reference.target_type) { | ||
903 | case ACPI_TYPE_BUFFER_FIELD: | ||
904 | |||
905 | temp_desc = operand[0]->reference.object; | ||
906 | |||
907 | /* | ||
908 | * Create a new object that contains one element of the | ||
909 | * buffer -- the element pointed to by the index. | ||
910 | * | ||
911 | * NOTE: index into a buffer is NOT a pointer to a | ||
912 | * sub-buffer of the main buffer, it is only a pointer to a | ||
913 | * single element (byte) of the buffer! | ||
914 | */ | ||
915 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
916 | if (!return_desc) { | ||
917 | status = AE_NO_MEMORY; | ||
918 | goto cleanup; | ||
919 | } | ||
920 | |||
921 | /* | ||
922 | * Since we are returning the value of the buffer at the | ||
923 | * indexed location, we don't need to add an additional | ||
924 | * reference to the buffer itself. | ||
925 | */ | ||
926 | return_desc->integer.value = | ||
927 | temp_desc->buffer.pointer[operand[0]->reference.offset]; | ||
928 | break; | ||
929 | |||
930 | |||
931 | case ACPI_TYPE_PACKAGE: | ||
932 | |||
933 | /* | ||
934 | * Return the referenced element of the package. We must add | ||
935 | * another reference to the referenced object, however. | ||
936 | */ | ||
937 | return_desc = *(operand[0]->reference.where); | ||
938 | if (!return_desc) { | ||
939 | /* | ||
940 | * We can't return a NULL dereferenced value. This is | ||
941 | * an uninitialized package element and is thus a | ||
942 | * severe error. | ||
943 | */ | ||
944 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
945 | "NULL package element obj %p\n", | ||
946 | operand[0])); | ||
947 | status = AE_AML_UNINITIALIZED_ELEMENT; | ||
948 | goto cleanup; | ||
949 | } | ||
950 | |||
951 | acpi_ut_add_reference (return_desc); | ||
952 | break; | ||
953 | |||
954 | |||
955 | default: | ||
956 | |||
957 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
958 | "Unknown Index target_type %X in obj %p\n", | ||
959 | operand[0]->reference.target_type, operand[0])); | ||
960 | status = AE_AML_OPERAND_TYPE; | ||
961 | goto cleanup; | ||
962 | } | ||
963 | break; | ||
964 | |||
965 | |||
966 | case AML_REF_OF_OP: | ||
967 | |||
968 | return_desc = operand[0]->reference.object; | ||
969 | |||
970 | if (ACPI_GET_DESCRIPTOR_TYPE (return_desc) == ACPI_DESC_TYPE_NAMED) { | ||
971 | |||
972 | return_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) return_desc); | ||
973 | } | ||
974 | |||
975 | /* Add another reference to the object! */ | ||
976 | |||
977 | acpi_ut_add_reference (return_desc); | ||
978 | break; | ||
979 | |||
980 | |||
981 | default: | ||
982 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
983 | "Unknown opcode in ref(%p) - %X\n", | ||
984 | operand[0], operand[0]->reference.opcode)); | ||
985 | |||
986 | status = AE_TYPE; | ||
987 | goto cleanup; | ||
988 | } | ||
989 | } | ||
990 | break; | ||
991 | |||
992 | |||
993 | default: | ||
994 | |||
995 | ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_0T_1R: Unknown opcode %X\n", | ||
996 | walk_state->opcode)); | ||
997 | status = AE_AML_BAD_OPCODE; | ||
998 | goto cleanup; | ||
999 | } | ||
1000 | |||
1001 | |||
1002 | cleanup: | ||
1003 | |||
1004 | /* Delete return object on error */ | ||
1005 | |||
1006 | if (ACPI_FAILURE (status)) { | ||
1007 | acpi_ut_remove_reference (return_desc); | ||
1008 | } | ||
1009 | |||
1010 | walk_state->result_obj = return_desc; | ||
1011 | return_ACPI_STATUS (status); | ||
1012 | } | ||
1013 | |||
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c new file mode 100644 index 000000000000..8be4d80ceed5 --- /dev/null +++ b/drivers/acpi/executer/exoparg2.c | |||
@@ -0,0 +1,608 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: exoparg2 - AML execution - opcodes with 2 arguments | ||
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/acparser.h> | ||
47 | #include <acpi/acinterp.h> | ||
48 | #include <acpi/acevents.h> | ||
49 | #include <acpi/amlcode.h> | ||
50 | |||
51 | |||
52 | #define _COMPONENT ACPI_EXECUTER | ||
53 | ACPI_MODULE_NAME ("exoparg2") | ||
54 | |||
55 | |||
56 | /*! | ||
57 | * Naming convention for AML interpreter execution routines. | ||
58 | * | ||
59 | * The routines that begin execution of AML opcodes are named with a common | ||
60 | * convention based upon the number of arguments, the number of target operands, | ||
61 | * and whether or not a value is returned: | ||
62 | * | ||
63 | * AcpiExOpcode_xA_yT_zR | ||
64 | * | ||
65 | * Where: | ||
66 | * | ||
67 | * xA - ARGUMENTS: The number of arguments (input operands) that are | ||
68 | * required for this opcode type (1 through 6 args). | ||
69 | * yT - TARGETS: The number of targets (output operands) that are required | ||
70 | * for this opcode type (0, 1, or 2 targets). | ||
71 | * zR - RETURN VALUE: Indicates whether this opcode type returns a value | ||
72 | * as the function return (0 or 1). | ||
73 | * | ||
74 | * The AcpiExOpcode* functions are called via the Dispatcher component with | ||
75 | * fully resolved operands. | ||
76 | !*/ | ||
77 | |||
78 | |||
79 | /******************************************************************************* | ||
80 | * | ||
81 | * FUNCTION: acpi_ex_opcode_2A_0T_0R | ||
82 | * | ||
83 | * PARAMETERS: walk_state - Current walk state | ||
84 | * | ||
85 | * RETURN: Status | ||
86 | * | ||
87 | * DESCRIPTION: Execute opcode with two arguments, no target, and no return | ||
88 | * value. | ||
89 | * | ||
90 | * ALLOCATION: Deletes both operands | ||
91 | * | ||
92 | ******************************************************************************/ | ||
93 | |||
94 | acpi_status | ||
95 | acpi_ex_opcode_2A_0T_0R ( | ||
96 | struct acpi_walk_state *walk_state) | ||
97 | { | ||
98 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
99 | struct acpi_namespace_node *node; | ||
100 | u32 value; | ||
101 | acpi_status status = AE_OK; | ||
102 | |||
103 | |||
104 | ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_0R", | ||
105 | acpi_ps_get_opcode_name (walk_state->opcode)); | ||
106 | |||
107 | |||
108 | /* Examine the opcode */ | ||
109 | |||
110 | switch (walk_state->opcode) { | ||
111 | case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */ | ||
112 | |||
113 | /* The first operand is a namespace node */ | ||
114 | |||
115 | node = (struct acpi_namespace_node *) operand[0]; | ||
116 | |||
117 | /* Second value is the notify value */ | ||
118 | |||
119 | value = (u32) operand[1]->integer.value; | ||
120 | |||
121 | /* Notifies allowed on this object? */ | ||
122 | |||
123 | if (!acpi_ev_is_notify_object (node)) { | ||
124 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
125 | "Unexpected notify object type [%s]\n", | ||
126 | acpi_ut_get_type_name (node->type))); | ||
127 | |||
128 | status = AE_AML_OPERAND_TYPE; | ||
129 | break; | ||
130 | } | ||
131 | |||
132 | #ifdef ACPI_GPE_NOTIFY_CHECK | ||
133 | /* | ||
134 | * GPE method wake/notify check. Here, we want to ensure that we | ||
135 | * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx | ||
136 | * GPE method during system runtime. If we do, the GPE is marked | ||
137 | * as "wake-only" and disabled. | ||
138 | * | ||
139 | * 1) Is the Notify() value == device_wake? | ||
140 | * 2) Is this a GPE deferred method? (An _Lxx or _Exx method) | ||
141 | * 3) Did the original GPE happen at system runtime? | ||
142 | * (versus during wake) | ||
143 | * | ||
144 | * If all three cases are true, this is a wake-only GPE that should | ||
145 | * be disabled at runtime. | ||
146 | */ | ||
147 | if (value == 2) /* device_wake */ { | ||
148 | status = acpi_ev_check_for_wake_only_gpe (walk_state->gpe_event_info); | ||
149 | if (ACPI_FAILURE (status)) { | ||
150 | /* AE_WAKE_ONLY_GPE only error, means ignore this notify */ | ||
151 | |||
152 | return_ACPI_STATUS (AE_OK) | ||
153 | } | ||
154 | } | ||
155 | #endif | ||
156 | |||
157 | /* | ||
158 | * Dispatch the notify to the appropriate handler | ||
159 | * NOTE: the request is queued for execution after this method | ||
160 | * completes. The notify handlers are NOT invoked synchronously | ||
161 | * from this thread -- because handlers may in turn run other | ||
162 | * control methods. | ||
163 | */ | ||
164 | status = acpi_ev_queue_notify_request (node, value); | ||
165 | break; | ||
166 | |||
167 | |||
168 | default: | ||
169 | |||
170 | ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n", | ||
171 | walk_state->opcode)); | ||
172 | status = AE_AML_BAD_OPCODE; | ||
173 | } | ||
174 | |||
175 | return_ACPI_STATUS (status); | ||
176 | } | ||
177 | |||
178 | |||
179 | /******************************************************************************* | ||
180 | * | ||
181 | * FUNCTION: acpi_ex_opcode_2A_2T_1R | ||
182 | * | ||
183 | * PARAMETERS: walk_state - Current walk state | ||
184 | * | ||
185 | * RETURN: Status | ||
186 | * | ||
187 | * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets | ||
188 | * and one implicit return value. | ||
189 | * | ||
190 | ******************************************************************************/ | ||
191 | |||
192 | acpi_status | ||
193 | acpi_ex_opcode_2A_2T_1R ( | ||
194 | struct acpi_walk_state *walk_state) | ||
195 | { | ||
196 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
197 | union acpi_operand_object *return_desc1 = NULL; | ||
198 | union acpi_operand_object *return_desc2 = NULL; | ||
199 | acpi_status status; | ||
200 | |||
201 | |||
202 | ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_2T_1R", | ||
203 | acpi_ps_get_opcode_name (walk_state->opcode)); | ||
204 | |||
205 | |||
206 | /* | ||
207 | * Execute the opcode | ||
208 | */ | ||
209 | switch (walk_state->opcode) { | ||
210 | case AML_DIVIDE_OP: /* Divide (Dividend, Divisor, remainder_result quotient_result) */ | ||
211 | |||
212 | return_desc1 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
213 | if (!return_desc1) { | ||
214 | status = AE_NO_MEMORY; | ||
215 | goto cleanup; | ||
216 | } | ||
217 | |||
218 | return_desc2 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
219 | if (!return_desc2) { | ||
220 | status = AE_NO_MEMORY; | ||
221 | goto cleanup; | ||
222 | } | ||
223 | |||
224 | /* Quotient to return_desc1, remainder to return_desc2 */ | ||
225 | |||
226 | status = acpi_ut_divide (operand[0]->integer.value, | ||
227 | operand[1]->integer.value, | ||
228 | &return_desc1->integer.value, | ||
229 | &return_desc2->integer.value); | ||
230 | if (ACPI_FAILURE (status)) { | ||
231 | goto cleanup; | ||
232 | } | ||
233 | break; | ||
234 | |||
235 | |||
236 | default: | ||
237 | |||
238 | ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n", | ||
239 | walk_state->opcode)); | ||
240 | status = AE_AML_BAD_OPCODE; | ||
241 | goto cleanup; | ||
242 | } | ||
243 | |||
244 | |||
245 | /* Store the results to the target reference operands */ | ||
246 | |||
247 | status = acpi_ex_store (return_desc2, operand[2], walk_state); | ||
248 | if (ACPI_FAILURE (status)) { | ||
249 | goto cleanup; | ||
250 | } | ||
251 | |||
252 | status = acpi_ex_store (return_desc1, operand[3], walk_state); | ||
253 | if (ACPI_FAILURE (status)) { | ||
254 | goto cleanup; | ||
255 | } | ||
256 | |||
257 | /* Return the remainder */ | ||
258 | |||
259 | walk_state->result_obj = return_desc1; | ||
260 | |||
261 | |||
262 | cleanup: | ||
263 | /* | ||
264 | * Since the remainder is not returned indirectly, remove a reference to | ||
265 | * it. Only the quotient is returned indirectly. | ||
266 | */ | ||
267 | acpi_ut_remove_reference (return_desc2); | ||
268 | |||
269 | if (ACPI_FAILURE (status)) { | ||
270 | /* Delete the return object */ | ||
271 | |||
272 | acpi_ut_remove_reference (return_desc1); | ||
273 | } | ||
274 | |||
275 | return_ACPI_STATUS (status); | ||
276 | } | ||
277 | |||
278 | |||
279 | /******************************************************************************* | ||
280 | * | ||
281 | * FUNCTION: acpi_ex_opcode_2A_1T_1R | ||
282 | * | ||
283 | * PARAMETERS: walk_state - Current walk state | ||
284 | * | ||
285 | * RETURN: Status | ||
286 | * | ||
287 | * DESCRIPTION: Execute opcode with two arguments, one target, and a return | ||
288 | * value. | ||
289 | * | ||
290 | ******************************************************************************/ | ||
291 | |||
292 | acpi_status | ||
293 | acpi_ex_opcode_2A_1T_1R ( | ||
294 | struct acpi_walk_state *walk_state) | ||
295 | { | ||
296 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
297 | union acpi_operand_object *return_desc = NULL; | ||
298 | u32 index; | ||
299 | acpi_status status = AE_OK; | ||
300 | acpi_size length; | ||
301 | |||
302 | |||
303 | ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_1T_1R", | ||
304 | acpi_ps_get_opcode_name (walk_state->opcode)); | ||
305 | |||
306 | |||
307 | /* | ||
308 | * Execute the opcode | ||
309 | */ | ||
310 | if (walk_state->op_info->flags & AML_MATH) { | ||
311 | /* All simple math opcodes (add, etc.) */ | ||
312 | |||
313 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
314 | if (!return_desc) { | ||
315 | status = AE_NO_MEMORY; | ||
316 | goto cleanup; | ||
317 | } | ||
318 | |||
319 | return_desc->integer.value = acpi_ex_do_math_op (walk_state->opcode, | ||
320 | operand[0]->integer.value, | ||
321 | operand[1]->integer.value); | ||
322 | goto store_result_to_target; | ||
323 | } | ||
324 | |||
325 | |||
326 | switch (walk_state->opcode) { | ||
327 | case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */ | ||
328 | |||
329 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
330 | if (!return_desc) { | ||
331 | status = AE_NO_MEMORY; | ||
332 | goto cleanup; | ||
333 | } | ||
334 | |||
335 | /* return_desc will contain the remainder */ | ||
336 | |||
337 | status = acpi_ut_divide (operand[0]->integer.value, | ||
338 | operand[1]->integer.value, | ||
339 | NULL, | ||
340 | &return_desc->integer.value); | ||
341 | break; | ||
342 | |||
343 | |||
344 | case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */ | ||
345 | |||
346 | status = acpi_ex_do_concatenate (operand[0], operand[1], | ||
347 | &return_desc, walk_state); | ||
348 | break; | ||
349 | |||
350 | |||
351 | case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */ | ||
352 | |||
353 | /* | ||
354 | * Input object is guaranteed to be a buffer at this point (it may have | ||
355 | * been converted.) Copy the raw buffer data to a new object of type String. | ||
356 | */ | ||
357 | |||
358 | /* | ||
359 | * Get the length of the new string. It is the smallest of: | ||
360 | * 1) Length of the input buffer | ||
361 | * 2) Max length as specified in the to_string operator | ||
362 | * 3) Length of input buffer up to a zero byte (null terminator) | ||
363 | * | ||
364 | * NOTE: A length of zero is ok, and will create a zero-length, null | ||
365 | * terminated string. | ||
366 | */ | ||
367 | length = 0; | ||
368 | while ((length < operand[0]->buffer.length) && | ||
369 | (length < operand[1]->integer.value) && | ||
370 | (operand[0]->buffer.pointer[length])) { | ||
371 | length++; | ||
372 | if (length > ACPI_MAX_STRING_CONVERSION) { | ||
373 | status = AE_AML_STRING_LIMIT; | ||
374 | goto cleanup; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | /* Allocate a new string object */ | ||
379 | |||
380 | return_desc = acpi_ut_create_string_object (length); | ||
381 | if (!return_desc) { | ||
382 | status = AE_NO_MEMORY; | ||
383 | goto cleanup; | ||
384 | } | ||
385 | |||
386 | /* Copy the raw buffer data with no transform. NULL terminated already. */ | ||
387 | |||
388 | ACPI_MEMCPY (return_desc->string.pointer, | ||
389 | operand[0]->buffer.pointer, length); | ||
390 | break; | ||
391 | |||
392 | |||
393 | case AML_CONCAT_RES_OP: /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */ | ||
394 | |||
395 | status = acpi_ex_concat_template (operand[0], operand[1], | ||
396 | &return_desc, walk_state); | ||
397 | break; | ||
398 | |||
399 | |||
400 | case AML_INDEX_OP: /* Index (Source Index Result) */ | ||
401 | |||
402 | /* Create the internal return object */ | ||
403 | |||
404 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE); | ||
405 | if (!return_desc) { | ||
406 | status = AE_NO_MEMORY; | ||
407 | goto cleanup; | ||
408 | } | ||
409 | |||
410 | index = (u32) operand[1]->integer.value; | ||
411 | |||
412 | /* | ||
413 | * At this point, the Source operand is a Package, Buffer, or String | ||
414 | */ | ||
415 | if (ACPI_GET_OBJECT_TYPE (operand[0]) == ACPI_TYPE_PACKAGE) { | ||
416 | /* Object to be indexed is a Package */ | ||
417 | |||
418 | if (index >= operand[0]->package.count) { | ||
419 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
420 | "Index value (%X) beyond package end (%X)\n", | ||
421 | index, operand[0]->package.count)); | ||
422 | status = AE_AML_PACKAGE_LIMIT; | ||
423 | goto cleanup; | ||
424 | } | ||
425 | |||
426 | return_desc->reference.target_type = ACPI_TYPE_PACKAGE; | ||
427 | return_desc->reference.object = operand[0]; | ||
428 | return_desc->reference.where = &operand[0]->package.elements [index]; | ||
429 | } | ||
430 | else { | ||
431 | /* Object to be indexed is a Buffer/String */ | ||
432 | |||
433 | if (index >= operand[0]->buffer.length) { | ||
434 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
435 | "Index value (%X) beyond end of buffer (%X)\n", | ||
436 | index, operand[0]->buffer.length)); | ||
437 | status = AE_AML_BUFFER_LIMIT; | ||
438 | goto cleanup; | ||
439 | } | ||
440 | |||
441 | return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD; | ||
442 | return_desc->reference.object = operand[0]; | ||
443 | } | ||
444 | |||
445 | /* | ||
446 | * Add a reference to the target package/buffer/string for the life | ||
447 | * of the index. | ||
448 | */ | ||
449 | acpi_ut_add_reference (operand[0]); | ||
450 | |||
451 | /* Complete the Index reference object */ | ||
452 | |||
453 | return_desc->reference.opcode = AML_INDEX_OP; | ||
454 | return_desc->reference.offset = index; | ||
455 | |||
456 | /* Store the reference to the Target */ | ||
457 | |||
458 | status = acpi_ex_store (return_desc, operand[2], walk_state); | ||
459 | |||
460 | /* Return the reference */ | ||
461 | |||
462 | walk_state->result_obj = return_desc; | ||
463 | goto cleanup; | ||
464 | |||
465 | |||
466 | default: | ||
467 | |||
468 | ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n", | ||
469 | walk_state->opcode)); | ||
470 | status = AE_AML_BAD_OPCODE; | ||
471 | break; | ||
472 | } | ||
473 | |||
474 | |||
475 | store_result_to_target: | ||
476 | |||
477 | if (ACPI_SUCCESS (status)) { | ||
478 | /* | ||
479 | * Store the result of the operation (which is now in return_desc) into | ||
480 | * the Target descriptor. | ||
481 | */ | ||
482 | status = acpi_ex_store (return_desc, operand[2], walk_state); | ||
483 | if (ACPI_FAILURE (status)) { | ||
484 | goto cleanup; | ||
485 | } | ||
486 | |||
487 | if (!walk_state->result_obj) { | ||
488 | walk_state->result_obj = return_desc; | ||
489 | } | ||
490 | } | ||
491 | |||
492 | |||
493 | cleanup: | ||
494 | |||
495 | /* Delete return object on error */ | ||
496 | |||
497 | if (ACPI_FAILURE (status)) { | ||
498 | acpi_ut_remove_reference (return_desc); | ||
499 | } | ||
500 | |||
501 | return_ACPI_STATUS (status); | ||
502 | } | ||
503 | |||
504 | |||
505 | /******************************************************************************* | ||
506 | * | ||
507 | * FUNCTION: acpi_ex_opcode_2A_0T_1R | ||
508 | * | ||
509 | * PARAMETERS: walk_state - Current walk state | ||
510 | * | ||
511 | * RETURN: Status | ||
512 | * | ||
513 | * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value | ||
514 | * | ||
515 | ******************************************************************************/ | ||
516 | |||
517 | acpi_status | ||
518 | acpi_ex_opcode_2A_0T_1R ( | ||
519 | struct acpi_walk_state *walk_state) | ||
520 | { | ||
521 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
522 | union acpi_operand_object *return_desc = NULL; | ||
523 | acpi_status status = AE_OK; | ||
524 | u8 logical_result = FALSE; | ||
525 | |||
526 | |||
527 | ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_1R", | ||
528 | acpi_ps_get_opcode_name (walk_state->opcode)); | ||
529 | |||
530 | |||
531 | /* Create the internal return object */ | ||
532 | |||
533 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
534 | if (!return_desc) { | ||
535 | status = AE_NO_MEMORY; | ||
536 | goto cleanup; | ||
537 | } | ||
538 | |||
539 | /* | ||
540 | * Execute the Opcode | ||
541 | */ | ||
542 | if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) /* logical_op (Operand0, Operand1) */ { | ||
543 | status = acpi_ex_do_logical_numeric_op (walk_state->opcode, | ||
544 | operand[0]->integer.value, operand[1]->integer.value, | ||
545 | &logical_result); | ||
546 | goto store_logical_result; | ||
547 | } | ||
548 | else if (walk_state->op_info->flags & AML_LOGICAL) /* logical_op (Operand0, Operand1) */ { | ||
549 | status = acpi_ex_do_logical_op (walk_state->opcode, operand[0], | ||
550 | operand[1], &logical_result); | ||
551 | goto store_logical_result; | ||
552 | } | ||
553 | |||
554 | |||
555 | switch (walk_state->opcode) { | ||
556 | case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */ | ||
557 | |||
558 | status = acpi_ex_acquire_mutex (operand[1], operand[0], walk_state); | ||
559 | if (status == AE_TIME) { | ||
560 | logical_result = TRUE; /* TRUE = Acquire timed out */ | ||
561 | status = AE_OK; | ||
562 | } | ||
563 | break; | ||
564 | |||
565 | |||
566 | case AML_WAIT_OP: /* Wait (event_object, Timeout) */ | ||
567 | |||
568 | status = acpi_ex_system_wait_event (operand[1], operand[0]); | ||
569 | if (status == AE_TIME) { | ||
570 | logical_result = TRUE; /* TRUE, Wait timed out */ | ||
571 | status = AE_OK; | ||
572 | } | ||
573 | break; | ||
574 | |||
575 | |||
576 | default: | ||
577 | |||
578 | ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n", | ||
579 | walk_state->opcode)); | ||
580 | status = AE_AML_BAD_OPCODE; | ||
581 | goto cleanup; | ||
582 | } | ||
583 | |||
584 | |||
585 | store_logical_result: | ||
586 | /* | ||
587 | * Set return value to according to logical_result. logical TRUE (all ones) | ||
588 | * Default is FALSE (zero) | ||
589 | */ | ||
590 | if (logical_result) { | ||
591 | return_desc->integer.value = ACPI_INTEGER_MAX; | ||
592 | } | ||
593 | |||
594 | walk_state->result_obj = return_desc; | ||
595 | |||
596 | |||
597 | cleanup: | ||
598 | |||
599 | /* Delete return object on error */ | ||
600 | |||
601 | if (ACPI_FAILURE (status)) { | ||
602 | acpi_ut_remove_reference (return_desc); | ||
603 | } | ||
604 | |||
605 | return_ACPI_STATUS (status); | ||
606 | } | ||
607 | |||
608 | |||
diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c new file mode 100644 index 000000000000..29d0b167745d --- /dev/null +++ b/drivers/acpi/executer/exoparg3.c | |||
@@ -0,0 +1,256 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exoparg3 - AML execution - opcodes with 3 arguments | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acinterp.h> | ||
48 | #include <acpi/acparser.h> | ||
49 | #include <acpi/amlcode.h> | ||
50 | |||
51 | |||
52 | #define _COMPONENT ACPI_EXECUTER | ||
53 | ACPI_MODULE_NAME ("exoparg3") | ||
54 | |||
55 | |||
56 | /*! | ||
57 | * Naming convention for AML interpreter execution routines. | ||
58 | * | ||
59 | * The routines that begin execution of AML opcodes are named with a common | ||
60 | * convention based upon the number of arguments, the number of target operands, | ||
61 | * and whether or not a value is returned: | ||
62 | * | ||
63 | * AcpiExOpcode_xA_yT_zR | ||
64 | * | ||
65 | * Where: | ||
66 | * | ||
67 | * xA - ARGUMENTS: The number of arguments (input operands) that are | ||
68 | * required for this opcode type (1 through 6 args). | ||
69 | * yT - TARGETS: The number of targets (output operands) that are required | ||
70 | * for this opcode type (0, 1, or 2 targets). | ||
71 | * zR - RETURN VALUE: Indicates whether this opcode type returns a value | ||
72 | * as the function return (0 or 1). | ||
73 | * | ||
74 | * The AcpiExOpcode* functions are called via the Dispatcher component with | ||
75 | * fully resolved operands. | ||
76 | !*/ | ||
77 | |||
78 | |||
79 | /******************************************************************************* | ||
80 | * | ||
81 | * FUNCTION: acpi_ex_opcode_3A_0T_0R | ||
82 | * | ||
83 | * PARAMETERS: walk_state - Current walk state | ||
84 | * | ||
85 | * RETURN: Status | ||
86 | * | ||
87 | * DESCRIPTION: Execute Triadic operator (3 operands) | ||
88 | * | ||
89 | ******************************************************************************/ | ||
90 | |||
91 | acpi_status | ||
92 | acpi_ex_opcode_3A_0T_0R ( | ||
93 | struct acpi_walk_state *walk_state) | ||
94 | { | ||
95 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
96 | struct acpi_signal_fatal_info *fatal; | ||
97 | acpi_status status = AE_OK; | ||
98 | |||
99 | |||
100 | ACPI_FUNCTION_TRACE_STR ("ex_opcode_3A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); | ||
101 | |||
102 | |||
103 | switch (walk_state->opcode) { | ||
104 | case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */ | ||
105 | |||
106 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
107 | "fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", | ||
108 | (u32) operand[0]->integer.value, | ||
109 | (u32) operand[1]->integer.value, | ||
110 | (u32) operand[2]->integer.value)); | ||
111 | |||
112 | fatal = ACPI_MEM_ALLOCATE (sizeof (struct acpi_signal_fatal_info)); | ||
113 | if (fatal) { | ||
114 | fatal->type = (u32) operand[0]->integer.value; | ||
115 | fatal->code = (u32) operand[1]->integer.value; | ||
116 | fatal->argument = (u32) operand[2]->integer.value; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * Always signal the OS! | ||
121 | */ | ||
122 | status = acpi_os_signal (ACPI_SIGNAL_FATAL, fatal); | ||
123 | |||
124 | /* Might return while OS is shutting down, just continue */ | ||
125 | |||
126 | ACPI_MEM_FREE (fatal); | ||
127 | break; | ||
128 | |||
129 | |||
130 | default: | ||
131 | |||
132 | ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", | ||
133 | walk_state->opcode)); | ||
134 | status = AE_AML_BAD_OPCODE; | ||
135 | goto cleanup; | ||
136 | } | ||
137 | |||
138 | |||
139 | cleanup: | ||
140 | |||
141 | return_ACPI_STATUS (status); | ||
142 | } | ||
143 | |||
144 | |||
145 | /******************************************************************************* | ||
146 | * | ||
147 | * FUNCTION: acpi_ex_opcode_3A_1T_1R | ||
148 | * | ||
149 | * PARAMETERS: walk_state - Current walk state | ||
150 | * | ||
151 | * RETURN: Status | ||
152 | * | ||
153 | * DESCRIPTION: Execute Triadic operator (3 operands) | ||
154 | * | ||
155 | ******************************************************************************/ | ||
156 | |||
157 | acpi_status | ||
158 | acpi_ex_opcode_3A_1T_1R ( | ||
159 | struct acpi_walk_state *walk_state) | ||
160 | { | ||
161 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
162 | union acpi_operand_object *return_desc = NULL; | ||
163 | char *buffer; | ||
164 | acpi_status status = AE_OK; | ||
165 | acpi_native_uint index; | ||
166 | acpi_size length; | ||
167 | |||
168 | |||
169 | ACPI_FUNCTION_TRACE_STR ("ex_opcode_3A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); | ||
170 | |||
171 | |||
172 | switch (walk_state->opcode) { | ||
173 | case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */ | ||
174 | |||
175 | /* | ||
176 | * Create the return object. The Source operand is guaranteed to be | ||
177 | * either a String or a Buffer, so just use its type. | ||
178 | */ | ||
179 | return_desc = acpi_ut_create_internal_object (ACPI_GET_OBJECT_TYPE (operand[0])); | ||
180 | if (!return_desc) { | ||
181 | status = AE_NO_MEMORY; | ||
182 | goto cleanup; | ||
183 | } | ||
184 | |||
185 | /* Get the Integer values from the objects */ | ||
186 | |||
187 | index = (acpi_native_uint) operand[1]->integer.value; | ||
188 | length = (acpi_size) operand[2]->integer.value; | ||
189 | |||
190 | /* | ||
191 | * If the index is beyond the length of the String/Buffer, or if the | ||
192 | * requested length is zero, return a zero-length String/Buffer | ||
193 | */ | ||
194 | if ((index < operand[0]->string.length) && | ||
195 | (length > 0)) { | ||
196 | /* Truncate request if larger than the actual String/Buffer */ | ||
197 | |||
198 | if ((index + length) > | ||
199 | operand[0]->string.length) { | ||
200 | length = (acpi_size) operand[0]->string.length - index; | ||
201 | } | ||
202 | |||
203 | /* Allocate a new buffer for the String/Buffer */ | ||
204 | |||
205 | buffer = ACPI_MEM_CALLOCATE ((acpi_size) length + 1); | ||
206 | if (!buffer) { | ||
207 | status = AE_NO_MEMORY; | ||
208 | goto cleanup; | ||
209 | } | ||
210 | |||
211 | /* Copy the portion requested */ | ||
212 | |||
213 | ACPI_MEMCPY (buffer, operand[0]->string.pointer + index, | ||
214 | length); | ||
215 | |||
216 | /* Set the length of the new String/Buffer */ | ||
217 | |||
218 | return_desc->string.pointer = buffer; | ||
219 | return_desc->string.length = (u32) length; | ||
220 | } | ||
221 | |||
222 | /* Mark buffer initialized */ | ||
223 | |||
224 | return_desc->buffer.flags |= AOPOBJ_DATA_VALID; | ||
225 | break; | ||
226 | |||
227 | |||
228 | default: | ||
229 | |||
230 | ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", | ||
231 | walk_state->opcode)); | ||
232 | status = AE_AML_BAD_OPCODE; | ||
233 | goto cleanup; | ||
234 | } | ||
235 | |||
236 | /* Store the result in the target */ | ||
237 | |||
238 | status = acpi_ex_store (return_desc, operand[3], walk_state); | ||
239 | |||
240 | cleanup: | ||
241 | |||
242 | /* Delete return object on error */ | ||
243 | |||
244 | if (ACPI_FAILURE (status)) { | ||
245 | acpi_ut_remove_reference (return_desc); | ||
246 | } | ||
247 | |||
248 | /* Set the return object and exit */ | ||
249 | |||
250 | if (!walk_state->result_obj) { | ||
251 | walk_state->result_obj = return_desc; | ||
252 | } | ||
253 | return_ACPI_STATUS (status); | ||
254 | } | ||
255 | |||
256 | |||
diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c new file mode 100644 index 000000000000..d32624331626 --- /dev/null +++ b/drivers/acpi/executer/exoparg6.c | |||
@@ -0,0 +1,336 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exoparg6 - AML execution - opcodes with 6 arguments | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acinterp.h> | ||
48 | #include <acpi/acparser.h> | ||
49 | #include <acpi/amlcode.h> | ||
50 | |||
51 | |||
52 | #define _COMPONENT ACPI_EXECUTER | ||
53 | ACPI_MODULE_NAME ("exoparg6") | ||
54 | |||
55 | |||
56 | /*! | ||
57 | * Naming convention for AML interpreter execution routines. | ||
58 | * | ||
59 | * The routines that begin execution of AML opcodes are named with a common | ||
60 | * convention based upon the number of arguments, the number of target operands, | ||
61 | * and whether or not a value is returned: | ||
62 | * | ||
63 | * AcpiExOpcode_xA_yT_zR | ||
64 | * | ||
65 | * Where: | ||
66 | * | ||
67 | * xA - ARGUMENTS: The number of arguments (input operands) that are | ||
68 | * required for this opcode type (1 through 6 args). | ||
69 | * yT - TARGETS: The number of targets (output operands) that are required | ||
70 | * for this opcode type (0, 1, or 2 targets). | ||
71 | * zR - RETURN VALUE: Indicates whether this opcode type returns a value | ||
72 | * as the function return (0 or 1). | ||
73 | * | ||
74 | * The AcpiExOpcode* functions are called via the Dispatcher component with | ||
75 | * fully resolved operands. | ||
76 | !*/ | ||
77 | |||
78 | |||
79 | /******************************************************************************* | ||
80 | * | ||
81 | * FUNCTION: acpi_ex_do_match | ||
82 | * | ||
83 | * PARAMETERS: match_op - The AML match operand | ||
84 | * package_obj - Object from the target package | ||
85 | * match_obj - Object to be matched | ||
86 | * | ||
87 | * RETURN: TRUE if the match is successful, FALSE otherwise | ||
88 | * | ||
89 | * DESCRIPTION: Implements the low-level match for the ASL Match operator. | ||
90 | * Package elements will be implicitly converted to the type of | ||
91 | * the match object (Integer/Buffer/String). | ||
92 | * | ||
93 | ******************************************************************************/ | ||
94 | |||
95 | u8 | ||
96 | acpi_ex_do_match ( | ||
97 | u32 match_op, | ||
98 | union acpi_operand_object *package_obj, | ||
99 | union acpi_operand_object *match_obj) | ||
100 | { | ||
101 | u8 logical_result = TRUE; | ||
102 | acpi_status status; | ||
103 | |||
104 | |||
105 | /* | ||
106 | * Note: Since the package_obj/match_obj ordering is opposite to that of | ||
107 | * the standard logical operators, we have to reverse them when we call | ||
108 | * do_logical_op in order to make the implicit conversion rules work | ||
109 | * correctly. However, this means we have to flip the entire equation | ||
110 | * also. A bit ugly perhaps, but overall, better than fussing the | ||
111 | * parameters around at runtime, over and over again. | ||
112 | * | ||
113 | * Below, P[i] refers to the package element, M refers to the Match object. | ||
114 | */ | ||
115 | switch (match_op) { | ||
116 | case MATCH_MTR: | ||
117 | |||
118 | /* Always true */ | ||
119 | |||
120 | break; | ||
121 | |||
122 | case MATCH_MEQ: | ||
123 | |||
124 | /* | ||
125 | * True if equal: (P[i] == M) | ||
126 | * Change to: (M == P[i]) | ||
127 | */ | ||
128 | status = acpi_ex_do_logical_op (AML_LEQUAL_OP, match_obj, package_obj, | ||
129 | &logical_result); | ||
130 | if (ACPI_FAILURE (status)) { | ||
131 | return (FALSE); | ||
132 | } | ||
133 | break; | ||
134 | |||
135 | case MATCH_MLE: | ||
136 | |||
137 | /* | ||
138 | * True if less than or equal: (P[i] <= M) (P[i] not_greater than M) | ||
139 | * Change to: (M >= P[i]) (M not_less than P[i]) | ||
140 | */ | ||
141 | status = acpi_ex_do_logical_op (AML_LLESS_OP, match_obj, package_obj, | ||
142 | &logical_result); | ||
143 | if (ACPI_FAILURE (status)) { | ||
144 | return (FALSE); | ||
145 | } | ||
146 | logical_result = (u8) !logical_result; | ||
147 | break; | ||
148 | |||
149 | case MATCH_MLT: | ||
150 | |||
151 | /* | ||
152 | * True if less than: (P[i] < M) | ||
153 | * Change to: (M > P[i]) | ||
154 | */ | ||
155 | status = acpi_ex_do_logical_op (AML_LGREATER_OP, match_obj, package_obj, | ||
156 | &logical_result); | ||
157 | if (ACPI_FAILURE (status)) { | ||
158 | return (FALSE); | ||
159 | } | ||
160 | break; | ||
161 | |||
162 | case MATCH_MGE: | ||
163 | |||
164 | /* | ||
165 | * True if greater than or equal: (P[i] >= M) (P[i] not_less than M) | ||
166 | * Change to: (M <= P[i]) (M not_greater than P[i]) | ||
167 | */ | ||
168 | status = acpi_ex_do_logical_op (AML_LGREATER_OP, match_obj, package_obj, | ||
169 | &logical_result); | ||
170 | if (ACPI_FAILURE (status)) { | ||
171 | return (FALSE); | ||
172 | } | ||
173 | logical_result = (u8)!logical_result; | ||
174 | break; | ||
175 | |||
176 | case MATCH_MGT: | ||
177 | |||
178 | /* | ||
179 | * True if greater than: (P[i] > M) | ||
180 | * Change to: (M < P[i]) | ||
181 | */ | ||
182 | status = acpi_ex_do_logical_op (AML_LLESS_OP, match_obj, package_obj, | ||
183 | &logical_result); | ||
184 | if (ACPI_FAILURE (status)) { | ||
185 | return (FALSE); | ||
186 | } | ||
187 | break; | ||
188 | |||
189 | default: | ||
190 | |||
191 | /* Undefined */ | ||
192 | |||
193 | return (FALSE); | ||
194 | } | ||
195 | |||
196 | return logical_result; | ||
197 | } | ||
198 | |||
199 | |||
200 | /******************************************************************************* | ||
201 | * | ||
202 | * FUNCTION: acpi_ex_opcode_6A_0T_1R | ||
203 | * | ||
204 | * PARAMETERS: walk_state - Current walk state | ||
205 | * | ||
206 | * RETURN: Status | ||
207 | * | ||
208 | * DESCRIPTION: Execute opcode with 6 arguments, no target, and a return value | ||
209 | * | ||
210 | ******************************************************************************/ | ||
211 | |||
212 | acpi_status | ||
213 | acpi_ex_opcode_6A_0T_1R ( | ||
214 | struct acpi_walk_state *walk_state) | ||
215 | { | ||
216 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
217 | union acpi_operand_object *return_desc = NULL; | ||
218 | acpi_status status = AE_OK; | ||
219 | u32 index; | ||
220 | union acpi_operand_object *this_element; | ||
221 | |||
222 | |||
223 | ACPI_FUNCTION_TRACE_STR ("ex_opcode_6A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); | ||
224 | |||
225 | |||
226 | switch (walk_state->opcode) { | ||
227 | case AML_MATCH_OP: | ||
228 | /* | ||
229 | * Match (search_pkg[0], match_op1[1], match_obj1[2], | ||
230 | * match_op2[3], match_obj2[4], start_index[5]) | ||
231 | */ | ||
232 | |||
233 | /* Validate both Match Term Operators (MTR, MEQ, etc.) */ | ||
234 | |||
235 | if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) || | ||
236 | (operand[3]->integer.value > MAX_MATCH_OPERATOR)) { | ||
237 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Match operator out of range\n")); | ||
238 | status = AE_AML_OPERAND_VALUE; | ||
239 | goto cleanup; | ||
240 | } | ||
241 | |||
242 | /* Get the package start_index, validate against the package length */ | ||
243 | |||
244 | index = (u32) operand[5]->integer.value; | ||
245 | if (index >= (u32) operand[0]->package.count) { | ||
246 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index beyond package end\n")); | ||
247 | status = AE_AML_PACKAGE_LIMIT; | ||
248 | goto cleanup; | ||
249 | } | ||
250 | |||
251 | /* Create an integer for the return value */ | ||
252 | |||
253 | return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); | ||
254 | if (!return_desc) { | ||
255 | status = AE_NO_MEMORY; | ||
256 | goto cleanup; | ||
257 | |||
258 | } | ||
259 | |||
260 | /* Default return value if no match found */ | ||
261 | |||
262 | return_desc->integer.value = ACPI_INTEGER_MAX; | ||
263 | |||
264 | /* | ||
265 | * Examine each element until a match is found. Both match conditions | ||
266 | * must be satisfied for a match to occur. Within the loop, | ||
267 | * "continue" signifies that the current element does not match | ||
268 | * and the next should be examined. | ||
269 | * | ||
270 | * Upon finding a match, the loop will terminate via "break" at | ||
271 | * the bottom. If it terminates "normally", match_value will be | ||
272 | * ACPI_INTEGER_MAX (Ones) (its initial value) indicating that no | ||
273 | * match was found. | ||
274 | */ | ||
275 | for ( ; index < operand[0]->package.count; index++) { | ||
276 | /* Get the current package element */ | ||
277 | |||
278 | this_element = operand[0]->package.elements[index]; | ||
279 | |||
280 | /* Treat any uninitialized (NULL) elements as non-matching */ | ||
281 | |||
282 | if (!this_element) { | ||
283 | continue; | ||
284 | } | ||
285 | |||
286 | /* | ||
287 | * Both match conditions must be satisfied. Execution of a continue | ||
288 | * (proceed to next iteration of enclosing for loop) signifies a | ||
289 | * non-match. | ||
290 | */ | ||
291 | if (!acpi_ex_do_match ((u32) operand[1]->integer.value, | ||
292 | this_element, operand[2])) { | ||
293 | continue; | ||
294 | } | ||
295 | |||
296 | if (!acpi_ex_do_match ((u32) operand[3]->integer.value, | ||
297 | this_element, operand[4])) { | ||
298 | continue; | ||
299 | } | ||
300 | |||
301 | /* Match found: Index is the return value */ | ||
302 | |||
303 | return_desc->integer.value = index; | ||
304 | break; | ||
305 | } | ||
306 | break; | ||
307 | |||
308 | |||
309 | case AML_LOAD_TABLE_OP: | ||
310 | |||
311 | status = acpi_ex_load_table_op (walk_state, &return_desc); | ||
312 | break; | ||
313 | |||
314 | |||
315 | default: | ||
316 | |||
317 | ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", | ||
318 | walk_state->opcode)); | ||
319 | status = AE_AML_BAD_OPCODE; | ||
320 | goto cleanup; | ||
321 | } | ||
322 | |||
323 | |||
324 | walk_state->result_obj = return_desc; | ||
325 | |||
326 | |||
327 | cleanup: | ||
328 | |||
329 | /* Delete return object on error */ | ||
330 | |||
331 | if (ACPI_FAILURE (status)) { | ||
332 | acpi_ut_remove_reference (return_desc); | ||
333 | } | ||
334 | |||
335 | return_ACPI_STATUS (status); | ||
336 | } | ||
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c new file mode 100644 index 000000000000..264ef3bba31b --- /dev/null +++ b/drivers/acpi/executer/exprep.c | |||
@@ -0,0 +1,530 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acinterp.h> | ||
48 | #include <acpi/amlcode.h> | ||
49 | #include <acpi/acnamesp.h> | ||
50 | |||
51 | |||
52 | #define _COMPONENT ACPI_EXECUTER | ||
53 | ACPI_MODULE_NAME ("exprep") | ||
54 | |||
55 | |||
56 | #ifdef ACPI_UNDER_DEVELOPMENT | ||
57 | /******************************************************************************* | ||
58 | * | ||
59 | * FUNCTION: acpi_ex_generate_access | ||
60 | * | ||
61 | * PARAMETERS: field_bit_offset - Start of field within parent region/buffer | ||
62 | * field_bit_length - Length of field in bits | ||
63 | * region_length - Length of parent in bytes | ||
64 | * | ||
65 | * RETURN: Field granularity (8, 16, 32 or 64) and | ||
66 | * byte_alignment (1, 2, 3, or 4) | ||
67 | * | ||
68 | * DESCRIPTION: Generate an optimal access width for fields defined with the | ||
69 | * any_acc keyword. | ||
70 | * | ||
71 | * NOTE: Need to have the region_length in order to check for boundary | ||
72 | * conditions (end-of-region). However, the region_length is a deferred | ||
73 | * operation. Therefore, to complete this implementation, the generation | ||
74 | * of this access width must be deferred until the region length has | ||
75 | * been evaluated. | ||
76 | * | ||
77 | ******************************************************************************/ | ||
78 | |||
79 | static u32 | ||
80 | acpi_ex_generate_access ( | ||
81 | u32 field_bit_offset, | ||
82 | u32 field_bit_length, | ||
83 | u32 region_length) | ||
84 | { | ||
85 | u32 field_byte_length; | ||
86 | u32 field_byte_offset; | ||
87 | u32 field_byte_end_offset; | ||
88 | u32 access_byte_width; | ||
89 | u32 field_start_offset; | ||
90 | u32 field_end_offset; | ||
91 | u32 minimum_access_width = 0xFFFFFFFF; | ||
92 | u32 minimum_accesses = 0xFFFFFFFF; | ||
93 | u32 accesses; | ||
94 | |||
95 | |||
96 | ACPI_FUNCTION_TRACE ("ex_generate_access"); | ||
97 | |||
98 | |||
99 | /* Round Field start offset and length to "minimal" byte boundaries */ | ||
100 | |||
101 | field_byte_offset = ACPI_DIV_8 (ACPI_ROUND_DOWN (field_bit_offset, 8)); | ||
102 | field_byte_end_offset = ACPI_DIV_8 (ACPI_ROUND_UP (field_bit_length + field_bit_offset, 8)); | ||
103 | field_byte_length = field_byte_end_offset - field_byte_offset; | ||
104 | |||
105 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
106 | "Bit length %d, Bit offset %d\n", | ||
107 | field_bit_length, field_bit_offset)); | ||
108 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
109 | "Byte Length %d, Byte Offset %d, End Offset %d\n", | ||
110 | field_byte_length, field_byte_offset, field_byte_end_offset)); | ||
111 | |||
112 | /* | ||
113 | * Iterative search for the maximum access width that is both aligned | ||
114 | * and does not go beyond the end of the region | ||
115 | * | ||
116 | * Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes) | ||
117 | */ | ||
118 | for (access_byte_width = 1; access_byte_width <= 8; access_byte_width <<= 1) { | ||
119 | /* | ||
120 | * 1) Round end offset up to next access boundary and make sure that this | ||
121 | * does not go beyond the end of the parent region. | ||
122 | * 2) When the Access width is greater than the field_byte_length, we are done. | ||
123 | * (This does not optimize for the perfectly aligned case yet). | ||
124 | */ | ||
125 | if (ACPI_ROUND_UP (field_byte_end_offset, access_byte_width) <= region_length) { | ||
126 | field_start_offset = ACPI_ROUND_DOWN (field_byte_offset, access_byte_width) / | ||
127 | access_byte_width; | ||
128 | field_end_offset = ACPI_ROUND_UP ((field_byte_length + field_byte_offset), | ||
129 | access_byte_width) / access_byte_width; | ||
130 | accesses = field_end_offset - field_start_offset; | ||
131 | |||
132 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
133 | "access_width %d end is within region\n", access_byte_width)); | ||
134 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
135 | "Field Start %d, Field End %d -- requires %d accesses\n", | ||
136 | field_start_offset, field_end_offset, accesses)); | ||
137 | |||
138 | /* Single access is optimal */ | ||
139 | |||
140 | if (accesses <= 1) { | ||
141 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
142 | "Entire field can be accessed with one operation of size %d\n", | ||
143 | access_byte_width)); | ||
144 | return_VALUE (access_byte_width); | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * Fits in the region, but requires more than one read/write. | ||
149 | * try the next wider access on next iteration | ||
150 | */ | ||
151 | if (accesses < minimum_accesses) { | ||
152 | minimum_accesses = accesses; | ||
153 | minimum_access_width = access_byte_width; | ||
154 | } | ||
155 | } | ||
156 | else { | ||
157 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
158 | "access_width %d end is NOT within region\n", access_byte_width)); | ||
159 | if (access_byte_width == 1) { | ||
160 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
161 | "Field goes beyond end-of-region!\n")); | ||
162 | return_VALUE (0); /* Field does not fit in the region at all */ | ||
163 | } | ||
164 | |||
165 | /* This width goes beyond the end-of-region, back off to previous access */ | ||
166 | |||
167 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
168 | "Backing off to previous optimal access width of %d\n", | ||
169 | minimum_access_width)); | ||
170 | return_VALUE (minimum_access_width); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | /* Could not read/write field with one operation, just use max access width */ | ||
175 | |||
176 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
177 | "Cannot access field in one operation, using width 8\n")); | ||
178 | return_VALUE (8); | ||
179 | } | ||
180 | #endif /* ACPI_UNDER_DEVELOPMENT */ | ||
181 | |||
182 | |||
183 | /******************************************************************************* | ||
184 | * | ||
185 | * FUNCTION: acpi_ex_decode_field_access | ||
186 | * | ||
187 | * PARAMETERS: Access - Encoded field access bits | ||
188 | * Length - Field length. | ||
189 | * | ||
190 | * RETURN: Field granularity (8, 16, 32 or 64) and | ||
191 | * byte_alignment (1, 2, 3, or 4) | ||
192 | * | ||
193 | * DESCRIPTION: Decode the access_type bits of a field definition. | ||
194 | * | ||
195 | ******************************************************************************/ | ||
196 | |||
197 | static u32 | ||
198 | acpi_ex_decode_field_access ( | ||
199 | union acpi_operand_object *obj_desc, | ||
200 | u8 field_flags, | ||
201 | u32 *return_byte_alignment) | ||
202 | { | ||
203 | u32 access; | ||
204 | u32 byte_alignment; | ||
205 | u32 bit_length; | ||
206 | |||
207 | |||
208 | ACPI_FUNCTION_TRACE ("ex_decode_field_access"); | ||
209 | |||
210 | |||
211 | access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK); | ||
212 | |||
213 | switch (access) { | ||
214 | case AML_FIELD_ACCESS_ANY: | ||
215 | |||
216 | #ifdef ACPI_UNDER_DEVELOPMENT | ||
217 | byte_alignment = acpi_ex_generate_access (obj_desc->common_field.start_field_bit_offset, | ||
218 | obj_desc->common_field.bit_length, | ||
219 | 0xFFFFFFFF /* Temp until we pass region_length as param */); | ||
220 | bit_length = byte_alignment * 8; | ||
221 | #endif | ||
222 | |||
223 | byte_alignment = 1; | ||
224 | bit_length = 8; | ||
225 | break; | ||
226 | |||
227 | case AML_FIELD_ACCESS_BYTE: | ||
228 | case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */ | ||
229 | byte_alignment = 1; | ||
230 | bit_length = 8; | ||
231 | break; | ||
232 | |||
233 | case AML_FIELD_ACCESS_WORD: | ||
234 | byte_alignment = 2; | ||
235 | bit_length = 16; | ||
236 | break; | ||
237 | |||
238 | case AML_FIELD_ACCESS_DWORD: | ||
239 | byte_alignment = 4; | ||
240 | bit_length = 32; | ||
241 | break; | ||
242 | |||
243 | case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */ | ||
244 | byte_alignment = 8; | ||
245 | bit_length = 64; | ||
246 | break; | ||
247 | |||
248 | default: | ||
249 | /* Invalid field access type */ | ||
250 | |||
251 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
252 | "Unknown field access type %X\n", | ||
253 | access)); | ||
254 | return_VALUE (0); | ||
255 | } | ||
256 | |||
257 | if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) { | ||
258 | /* | ||
259 | * buffer_field access can be on any byte boundary, so the | ||
260 | * byte_alignment is always 1 byte -- regardless of any byte_alignment | ||
261 | * implied by the field access type. | ||
262 | */ | ||
263 | byte_alignment = 1; | ||
264 | } | ||
265 | |||
266 | *return_byte_alignment = byte_alignment; | ||
267 | return_VALUE (bit_length); | ||
268 | } | ||
269 | |||
270 | |||
271 | /******************************************************************************* | ||
272 | * | ||
273 | * FUNCTION: acpi_ex_prep_common_field_object | ||
274 | * | ||
275 | * PARAMETERS: obj_desc - The field object | ||
276 | * field_flags - Access, lock_rule, and update_rule. | ||
277 | * The format of a field_flag is described | ||
278 | * in the ACPI specification | ||
279 | * field_bit_position - Field start position | ||
280 | * field_bit_length - Field length in number of bits | ||
281 | * | ||
282 | * RETURN: Status | ||
283 | * | ||
284 | * DESCRIPTION: Initialize the areas of the field object that are common | ||
285 | * to the various types of fields. Note: This is very "sensitive" | ||
286 | * code because we are solving the general case for field | ||
287 | * alignment. | ||
288 | * | ||
289 | ******************************************************************************/ | ||
290 | |||
291 | acpi_status | ||
292 | acpi_ex_prep_common_field_object ( | ||
293 | union acpi_operand_object *obj_desc, | ||
294 | u8 field_flags, | ||
295 | u8 field_attribute, | ||
296 | u32 field_bit_position, | ||
297 | u32 field_bit_length) | ||
298 | { | ||
299 | u32 access_bit_width; | ||
300 | u32 byte_alignment; | ||
301 | u32 nearest_byte_address; | ||
302 | |||
303 | |||
304 | ACPI_FUNCTION_TRACE ("ex_prep_common_field_object"); | ||
305 | |||
306 | |||
307 | /* | ||
308 | * Note: the structure being initialized is the | ||
309 | * ACPI_COMMON_FIELD_INFO; No structure fields outside of the common | ||
310 | * area are initialized by this procedure. | ||
311 | */ | ||
312 | obj_desc->common_field.field_flags = field_flags; | ||
313 | obj_desc->common_field.attribute = field_attribute; | ||
314 | obj_desc->common_field.bit_length = field_bit_length; | ||
315 | |||
316 | /* | ||
317 | * Decode the access type so we can compute offsets. The access type gives | ||
318 | * two pieces of information - the width of each field access and the | ||
319 | * necessary byte_alignment (address granularity) of the access. | ||
320 | * | ||
321 | * For any_acc, the access_bit_width is the largest width that is both | ||
322 | * necessary and possible in an attempt to access the whole field in one | ||
323 | * I/O operation. However, for any_acc, the byte_alignment is always one | ||
324 | * byte. | ||
325 | * | ||
326 | * For all Buffer Fields, the byte_alignment is always one byte. | ||
327 | * | ||
328 | * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is | ||
329 | * the same (equivalent) as the byte_alignment. | ||
330 | */ | ||
331 | access_bit_width = acpi_ex_decode_field_access (obj_desc, field_flags, | ||
332 | &byte_alignment); | ||
333 | if (!access_bit_width) { | ||
334 | return_ACPI_STATUS (AE_AML_OPERAND_VALUE); | ||
335 | } | ||
336 | |||
337 | /* Setup width (access granularity) fields */ | ||
338 | |||
339 | obj_desc->common_field.access_byte_width = (u8) | ||
340 | ACPI_DIV_8 (access_bit_width); /* 1, 2, 4, 8 */ | ||
341 | |||
342 | obj_desc->common_field.access_bit_width = (u8) access_bit_width; | ||
343 | |||
344 | /* | ||
345 | * base_byte_offset is the address of the start of the field within the | ||
346 | * region. It is the byte address of the first *datum* (field-width data | ||
347 | * unit) of the field. (i.e., the first datum that contains at least the | ||
348 | * first *bit* of the field.) | ||
349 | * | ||
350 | * Note: byte_alignment is always either equal to the access_bit_width or 8 | ||
351 | * (Byte access), and it defines the addressing granularity of the parent | ||
352 | * region or buffer. | ||
353 | */ | ||
354 | nearest_byte_address = | ||
355 | ACPI_ROUND_BITS_DOWN_TO_BYTES (field_bit_position); | ||
356 | obj_desc->common_field.base_byte_offset = (u32) | ||
357 | ACPI_ROUND_DOWN (nearest_byte_address, byte_alignment); | ||
358 | |||
359 | /* | ||
360 | * start_field_bit_offset is the offset of the first bit of the field within | ||
361 | * a field datum. | ||
362 | */ | ||
363 | obj_desc->common_field.start_field_bit_offset = (u8) | ||
364 | (field_bit_position - ACPI_MUL_8 (obj_desc->common_field.base_byte_offset)); | ||
365 | |||
366 | /* | ||
367 | * Does the entire field fit within a single field access element? (datum) | ||
368 | * (i.e., without crossing a datum boundary) | ||
369 | */ | ||
370 | if ((obj_desc->common_field.start_field_bit_offset + field_bit_length) <= | ||
371 | (u16) access_bit_width) { | ||
372 | obj_desc->common.flags |= AOPOBJ_SINGLE_DATUM; | ||
373 | } | ||
374 | |||
375 | return_ACPI_STATUS (AE_OK); | ||
376 | } | ||
377 | |||
378 | |||
379 | /******************************************************************************* | ||
380 | * | ||
381 | * FUNCTION: acpi_ex_prep_field_value | ||
382 | * | ||
383 | * PARAMETERS: Node - Owning Node | ||
384 | * region_node - Region in which field is being defined | ||
385 | * field_flags - Access, lock_rule, and update_rule. | ||
386 | * field_bit_position - Field start position | ||
387 | * field_bit_length - Field length in number of bits | ||
388 | * | ||
389 | * RETURN: Status | ||
390 | * | ||
391 | * DESCRIPTION: Construct an union acpi_operand_object of type def_field and | ||
392 | * connect it to the parent Node. | ||
393 | * | ||
394 | ******************************************************************************/ | ||
395 | |||
396 | acpi_status | ||
397 | acpi_ex_prep_field_value ( | ||
398 | struct acpi_create_field_info *info) | ||
399 | { | ||
400 | union acpi_operand_object *obj_desc; | ||
401 | u32 type; | ||
402 | acpi_status status; | ||
403 | |||
404 | |||
405 | ACPI_FUNCTION_TRACE ("ex_prep_field_value"); | ||
406 | |||
407 | |||
408 | /* Parameter validation */ | ||
409 | |||
410 | if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) { | ||
411 | if (!info->region_node) { | ||
412 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null region_node\n")); | ||
413 | return_ACPI_STATUS (AE_AML_NO_OPERAND); | ||
414 | } | ||
415 | |||
416 | type = acpi_ns_get_type (info->region_node); | ||
417 | if (type != ACPI_TYPE_REGION) { | ||
418 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
419 | "Needed Region, found type %X (%s)\n", | ||
420 | type, acpi_ut_get_type_name (type))); | ||
421 | |||
422 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | /* Allocate a new field object */ | ||
427 | |||
428 | obj_desc = acpi_ut_create_internal_object (info->field_type); | ||
429 | if (!obj_desc) { | ||
430 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
431 | } | ||
432 | |||
433 | /* Initialize areas of the object that are common to all fields */ | ||
434 | |||
435 | obj_desc->common_field.node = info->field_node; | ||
436 | status = acpi_ex_prep_common_field_object (obj_desc, info->field_flags, | ||
437 | info->attribute, info->field_bit_position, info->field_bit_length); | ||
438 | if (ACPI_FAILURE (status)) { | ||
439 | acpi_ut_delete_object_desc (obj_desc); | ||
440 | return_ACPI_STATUS (status); | ||
441 | } | ||
442 | |||
443 | /* Initialize areas of the object that are specific to the field type */ | ||
444 | |||
445 | switch (info->field_type) { | ||
446 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
447 | |||
448 | obj_desc->field.region_obj = acpi_ns_get_attached_object (info->region_node); | ||
449 | |||
450 | /* An additional reference for the container */ | ||
451 | |||
452 | acpi_ut_add_reference (obj_desc->field.region_obj); | ||
453 | |||
454 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
455 | "region_field: bit_off %X, Off %X, Gran %X, Region %p\n", | ||
456 | obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset, | ||
457 | obj_desc->field.access_byte_width, obj_desc->field.region_obj)); | ||
458 | break; | ||
459 | |||
460 | |||
461 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
462 | |||
463 | obj_desc->bank_field.value = info->bank_value; | ||
464 | obj_desc->bank_field.region_obj = acpi_ns_get_attached_object (info->region_node); | ||
465 | obj_desc->bank_field.bank_obj = acpi_ns_get_attached_object (info->register_node); | ||
466 | |||
467 | /* An additional reference for the attached objects */ | ||
468 | |||
469 | acpi_ut_add_reference (obj_desc->bank_field.region_obj); | ||
470 | acpi_ut_add_reference (obj_desc->bank_field.bank_obj); | ||
471 | |||
472 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
473 | "Bank Field: bit_off %X, Off %X, Gran %X, Region %p, bank_reg %p\n", | ||
474 | obj_desc->bank_field.start_field_bit_offset, | ||
475 | obj_desc->bank_field.base_byte_offset, | ||
476 | obj_desc->field.access_byte_width, | ||
477 | obj_desc->bank_field.region_obj, | ||
478 | obj_desc->bank_field.bank_obj)); | ||
479 | break; | ||
480 | |||
481 | |||
482 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
483 | |||
484 | obj_desc->index_field.index_obj = acpi_ns_get_attached_object (info->register_node); | ||
485 | obj_desc->index_field.data_obj = acpi_ns_get_attached_object (info->data_register_node); | ||
486 | obj_desc->index_field.value = (u32) | ||
487 | (info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width)); | ||
488 | |||
489 | if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) { | ||
490 | ACPI_REPORT_ERROR (("Null Index Object during field prep\n")); | ||
491 | acpi_ut_delete_object_desc (obj_desc); | ||
492 | return_ACPI_STATUS (AE_AML_INTERNAL); | ||
493 | } | ||
494 | |||
495 | /* An additional reference for the attached objects */ | ||
496 | |||
497 | acpi_ut_add_reference (obj_desc->index_field.data_obj); | ||
498 | acpi_ut_add_reference (obj_desc->index_field.index_obj); | ||
499 | |||
500 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, | ||
501 | "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", | ||
502 | obj_desc->index_field.start_field_bit_offset, | ||
503 | obj_desc->index_field.base_byte_offset, | ||
504 | obj_desc->index_field.value, | ||
505 | obj_desc->field.access_byte_width, | ||
506 | obj_desc->index_field.index_obj, | ||
507 | obj_desc->index_field.data_obj)); | ||
508 | break; | ||
509 | |||
510 | default: | ||
511 | /* No other types should get here */ | ||
512 | break; | ||
513 | } | ||
514 | |||
515 | /* | ||
516 | * Store the constructed descriptor (obj_desc) into the parent Node, | ||
517 | * preserving the current type of that named_obj. | ||
518 | */ | ||
519 | status = acpi_ns_attach_object (info->field_node, obj_desc, | ||
520 | acpi_ns_get_type (info->field_node)); | ||
521 | |||
522 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set named_obj %p [%4.4s], obj_desc %p\n", | ||
523 | info->field_node, acpi_ut_get_node_name (info->field_node), obj_desc)); | ||
524 | |||
525 | /* Remove local reference to the object */ | ||
526 | |||
527 | acpi_ut_remove_reference (obj_desc); | ||
528 | return_ACPI_STATUS (status); | ||
529 | } | ||
530 | |||
diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c new file mode 100644 index 000000000000..7cfd0684c70b --- /dev/null +++ b/drivers/acpi/executer/exregion.c | |||
@@ -0,0 +1,528 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exregion - ACPI default op_region (address space) handlers | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acinterp.h> | ||
48 | |||
49 | |||
50 | #define _COMPONENT ACPI_EXECUTER | ||
51 | ACPI_MODULE_NAME ("exregion") | ||
52 | |||
53 | |||
54 | /******************************************************************************* | ||
55 | * | ||
56 | * FUNCTION: acpi_ex_system_memory_space_handler | ||
57 | * | ||
58 | * PARAMETERS: Function - Read or Write operation | ||
59 | * Address - Where in the space to read or write | ||
60 | * bit_width - Field width in bits (8, 16, or 32) | ||
61 | * Value - Pointer to in or out value | ||
62 | * handler_context - Pointer to Handler's context | ||
63 | * region_context - Pointer to context specific to the | ||
64 | * accessed region | ||
65 | * | ||
66 | * RETURN: Status | ||
67 | * | ||
68 | * DESCRIPTION: Handler for the System Memory address space (Op Region) | ||
69 | * | ||
70 | ******************************************************************************/ | ||
71 | |||
72 | acpi_status | ||
73 | acpi_ex_system_memory_space_handler ( | ||
74 | u32 function, | ||
75 | acpi_physical_address address, | ||
76 | u32 bit_width, | ||
77 | acpi_integer *value, | ||
78 | void *handler_context, | ||
79 | void *region_context) | ||
80 | { | ||
81 | acpi_status status = AE_OK; | ||
82 | void *logical_addr_ptr = NULL; | ||
83 | struct acpi_mem_space_context *mem_info = region_context; | ||
84 | u32 length; | ||
85 | acpi_size window_size; | ||
86 | #ifndef ACPI_MISALIGNED_TRANSFERS | ||
87 | u32 remainder; | ||
88 | #endif | ||
89 | |||
90 | ACPI_FUNCTION_TRACE ("ex_system_memory_space_handler"); | ||
91 | |||
92 | |||
93 | /* Validate and translate the bit width */ | ||
94 | |||
95 | switch (bit_width) { | ||
96 | case 8: | ||
97 | length = 1; | ||
98 | break; | ||
99 | |||
100 | case 16: | ||
101 | length = 2; | ||
102 | break; | ||
103 | |||
104 | case 32: | ||
105 | length = 4; | ||
106 | break; | ||
107 | |||
108 | case 64: | ||
109 | length = 8; | ||
110 | break; | ||
111 | |||
112 | default: | ||
113 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid system_memory width %d\n", | ||
114 | bit_width)); | ||
115 | return_ACPI_STATUS (AE_AML_OPERAND_VALUE); | ||
116 | } | ||
117 | |||
118 | |||
119 | #ifndef ACPI_MISALIGNED_TRANSFERS | ||
120 | /* | ||
121 | * Hardware does not support non-aligned data transfers, we must verify | ||
122 | * the request. | ||
123 | */ | ||
124 | (void) acpi_ut_short_divide ((acpi_integer) address, length, NULL, &remainder); | ||
125 | if (remainder != 0) { | ||
126 | return_ACPI_STATUS (AE_AML_ALIGNMENT); | ||
127 | } | ||
128 | #endif | ||
129 | |||
130 | /* | ||
131 | * Does the request fit into the cached memory mapping? | ||
132 | * Is 1) Address below the current mapping? OR | ||
133 | * 2) Address beyond the current mapping? | ||
134 | */ | ||
135 | if ((address < mem_info->mapped_physical_address) || | ||
136 | (((acpi_integer) address + length) > | ||
137 | ((acpi_integer) mem_info->mapped_physical_address + mem_info->mapped_length))) { | ||
138 | /* | ||
139 | * The request cannot be resolved by the current memory mapping; | ||
140 | * Delete the existing mapping and create a new one. | ||
141 | */ | ||
142 | if (mem_info->mapped_length) { | ||
143 | /* Valid mapping, delete it */ | ||
144 | |||
145 | acpi_os_unmap_memory (mem_info->mapped_logical_address, | ||
146 | mem_info->mapped_length); | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * Don't attempt to map memory beyond the end of the region, and | ||
151 | * constrain the maximum mapping size to something reasonable. | ||
152 | */ | ||
153 | window_size = (acpi_size) ((mem_info->address + mem_info->length) - address); | ||
154 | if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) { | ||
155 | window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE; | ||
156 | } | ||
157 | |||
158 | /* Create a new mapping starting at the address given */ | ||
159 | |||
160 | status = acpi_os_map_memory (address, window_size, | ||
161 | (void **) &mem_info->mapped_logical_address); | ||
162 | if (ACPI_FAILURE (status)) { | ||
163 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X%8.8X, size %X\n", | ||
164 | ACPI_FORMAT_UINT64 (address), (u32) window_size)); | ||
165 | mem_info->mapped_length = 0; | ||
166 | return_ACPI_STATUS (status); | ||
167 | } | ||
168 | |||
169 | /* Save the physical address and mapping size */ | ||
170 | |||
171 | mem_info->mapped_physical_address = address; | ||
172 | mem_info->mapped_length = window_size; | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * Generate a logical pointer corresponding to the address we want to | ||
177 | * access | ||
178 | */ | ||
179 | logical_addr_ptr = mem_info->mapped_logical_address + | ||
180 | ((acpi_integer) address - (acpi_integer) mem_info->mapped_physical_address); | ||
181 | |||
182 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
183 | "system_memory %d (%d width) Address=%8.8X%8.8X\n", function, bit_width, | ||
184 | ACPI_FORMAT_UINT64 (address))); | ||
185 | |||
186 | /* | ||
187 | * Perform the memory read or write | ||
188 | * | ||
189 | * Note: For machines that do not support non-aligned transfers, the target | ||
190 | * address was checked for alignment above. We do not attempt to break the | ||
191 | * transfer up into smaller (byte-size) chunks because the AML specifically | ||
192 | * asked for a transfer width that the hardware may require. | ||
193 | */ | ||
194 | switch (function) { | ||
195 | case ACPI_READ: | ||
196 | |||
197 | *value = 0; | ||
198 | switch (bit_width) { | ||
199 | case 8: | ||
200 | *value = (acpi_integer) *((u8 *) logical_addr_ptr); | ||
201 | break; | ||
202 | |||
203 | case 16: | ||
204 | *value = (acpi_integer) *((u16 *) logical_addr_ptr); | ||
205 | break; | ||
206 | |||
207 | case 32: | ||
208 | *value = (acpi_integer) *((u32 *) logical_addr_ptr); | ||
209 | break; | ||
210 | |||
211 | #if ACPI_MACHINE_WIDTH != 16 | ||
212 | case 64: | ||
213 | *value = (acpi_integer) *((u64 *) logical_addr_ptr); | ||
214 | break; | ||
215 | #endif | ||
216 | default: | ||
217 | /* bit_width was already validated */ | ||
218 | break; | ||
219 | } | ||
220 | break; | ||
221 | |||
222 | case ACPI_WRITE: | ||
223 | |||
224 | switch (bit_width) { | ||
225 | case 8: | ||
226 | *(u8 *) logical_addr_ptr = (u8) *value; | ||
227 | break; | ||
228 | |||
229 | case 16: | ||
230 | *(u16 *) logical_addr_ptr = (u16) *value; | ||
231 | break; | ||
232 | |||
233 | case 32: | ||
234 | *(u32 *) logical_addr_ptr = (u32) *value; | ||
235 | break; | ||
236 | |||
237 | #if ACPI_MACHINE_WIDTH != 16 | ||
238 | case 64: | ||
239 | *(u64 *) logical_addr_ptr = (u64) *value; | ||
240 | break; | ||
241 | #endif | ||
242 | |||
243 | default: | ||
244 | /* bit_width was already validated */ | ||
245 | break; | ||
246 | } | ||
247 | break; | ||
248 | |||
249 | default: | ||
250 | status = AE_BAD_PARAMETER; | ||
251 | break; | ||
252 | } | ||
253 | |||
254 | return_ACPI_STATUS (status); | ||
255 | } | ||
256 | |||
257 | |||
258 | /******************************************************************************* | ||
259 | * | ||
260 | * FUNCTION: acpi_ex_system_io_space_handler | ||
261 | * | ||
262 | * PARAMETERS: Function - Read or Write operation | ||
263 | * Address - Where in the space to read or write | ||
264 | * bit_width - Field width in bits (8, 16, or 32) | ||
265 | * Value - Pointer to in or out value | ||
266 | * handler_context - Pointer to Handler's context | ||
267 | * region_context - Pointer to context specific to the | ||
268 | * accessed region | ||
269 | * | ||
270 | * RETURN: Status | ||
271 | * | ||
272 | * DESCRIPTION: Handler for the System IO address space (Op Region) | ||
273 | * | ||
274 | ******************************************************************************/ | ||
275 | |||
276 | acpi_status | ||
277 | acpi_ex_system_io_space_handler ( | ||
278 | u32 function, | ||
279 | acpi_physical_address address, | ||
280 | u32 bit_width, | ||
281 | acpi_integer *value, | ||
282 | void *handler_context, | ||
283 | void *region_context) | ||
284 | { | ||
285 | acpi_status status = AE_OK; | ||
286 | u32 value32; | ||
287 | |||
288 | |||
289 | ACPI_FUNCTION_TRACE ("ex_system_io_space_handler"); | ||
290 | |||
291 | |||
292 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
293 | "system_iO %d (%d width) Address=%8.8X%8.8X\n", function, bit_width, | ||
294 | ACPI_FORMAT_UINT64 (address))); | ||
295 | |||
296 | /* Decode the function parameter */ | ||
297 | |||
298 | switch (function) { | ||
299 | case ACPI_READ: | ||
300 | |||
301 | status = acpi_os_read_port ((acpi_io_address) address, &value32, bit_width); | ||
302 | *value = value32; | ||
303 | break; | ||
304 | |||
305 | case ACPI_WRITE: | ||
306 | |||
307 | status = acpi_os_write_port ((acpi_io_address) address, (u32) *value, bit_width); | ||
308 | break; | ||
309 | |||
310 | default: | ||
311 | status = AE_BAD_PARAMETER; | ||
312 | break; | ||
313 | } | ||
314 | |||
315 | return_ACPI_STATUS (status); | ||
316 | } | ||
317 | |||
318 | |||
319 | /******************************************************************************* | ||
320 | * | ||
321 | * FUNCTION: acpi_ex_pci_config_space_handler | ||
322 | * | ||
323 | * PARAMETERS: Function - Read or Write operation | ||
324 | * Address - Where in the space to read or write | ||
325 | * bit_width - Field width in bits (8, 16, or 32) | ||
326 | * Value - Pointer to in or out value | ||
327 | * handler_context - Pointer to Handler's context | ||
328 | * region_context - Pointer to context specific to the | ||
329 | * accessed region | ||
330 | * | ||
331 | * RETURN: Status | ||
332 | * | ||
333 | * DESCRIPTION: Handler for the PCI Config address space (Op Region) | ||
334 | * | ||
335 | ******************************************************************************/ | ||
336 | |||
337 | acpi_status | ||
338 | acpi_ex_pci_config_space_handler ( | ||
339 | u32 function, | ||
340 | acpi_physical_address address, | ||
341 | u32 bit_width, | ||
342 | acpi_integer *value, | ||
343 | void *handler_context, | ||
344 | void *region_context) | ||
345 | { | ||
346 | acpi_status status = AE_OK; | ||
347 | struct acpi_pci_id *pci_id; | ||
348 | u16 pci_register; | ||
349 | |||
350 | |||
351 | ACPI_FUNCTION_TRACE ("ex_pci_config_space_handler"); | ||
352 | |||
353 | |||
354 | /* | ||
355 | * The arguments to acpi_os(Read|Write)pci_configuration are: | ||
356 | * | ||
357 | * pci_segment is the PCI bus segment range 0-31 | ||
358 | * pci_bus is the PCI bus number range 0-255 | ||
359 | * pci_device is the PCI device number range 0-31 | ||
360 | * pci_function is the PCI device function number | ||
361 | * pci_register is the Config space register range 0-255 bytes | ||
362 | * | ||
363 | * Value - input value for write, output address for read | ||
364 | * | ||
365 | */ | ||
366 | pci_id = (struct acpi_pci_id *) region_context; | ||
367 | pci_register = (u16) (u32) address; | ||
368 | |||
369 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
370 | "pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", | ||
371 | function, bit_width, pci_id->segment, pci_id->bus, pci_id->device, | ||
372 | pci_id->function, pci_register)); | ||
373 | |||
374 | switch (function) { | ||
375 | case ACPI_READ: | ||
376 | |||
377 | *value = 0; | ||
378 | status = acpi_os_read_pci_configuration (pci_id, pci_register, value, bit_width); | ||
379 | break; | ||
380 | |||
381 | case ACPI_WRITE: | ||
382 | |||
383 | status = acpi_os_write_pci_configuration (pci_id, pci_register, *value, bit_width); | ||
384 | break; | ||
385 | |||
386 | default: | ||
387 | |||
388 | status = AE_BAD_PARAMETER; | ||
389 | break; | ||
390 | } | ||
391 | |||
392 | return_ACPI_STATUS (status); | ||
393 | } | ||
394 | |||
395 | |||
396 | /******************************************************************************* | ||
397 | * | ||
398 | * FUNCTION: acpi_ex_cmos_space_handler | ||
399 | * | ||
400 | * PARAMETERS: Function - Read or Write operation | ||
401 | * Address - Where in the space to read or write | ||
402 | * bit_width - Field width in bits (8, 16, or 32) | ||
403 | * Value - Pointer to in or out value | ||
404 | * handler_context - Pointer to Handler's context | ||
405 | * region_context - Pointer to context specific to the | ||
406 | * accessed region | ||
407 | * | ||
408 | * RETURN: Status | ||
409 | * | ||
410 | * DESCRIPTION: Handler for the CMOS address space (Op Region) | ||
411 | * | ||
412 | ******************************************************************************/ | ||
413 | |||
414 | acpi_status | ||
415 | acpi_ex_cmos_space_handler ( | ||
416 | u32 function, | ||
417 | acpi_physical_address address, | ||
418 | u32 bit_width, | ||
419 | acpi_integer *value, | ||
420 | void *handler_context, | ||
421 | void *region_context) | ||
422 | { | ||
423 | acpi_status status = AE_OK; | ||
424 | |||
425 | |||
426 | ACPI_FUNCTION_TRACE ("ex_cmos_space_handler"); | ||
427 | |||
428 | |||
429 | return_ACPI_STATUS (status); | ||
430 | } | ||
431 | |||
432 | |||
433 | /******************************************************************************* | ||
434 | * | ||
435 | * FUNCTION: acpi_ex_pci_bar_space_handler | ||
436 | * | ||
437 | * PARAMETERS: Function - Read or Write operation | ||
438 | * Address - Where in the space to read or write | ||
439 | * bit_width - Field width in bits (8, 16, or 32) | ||
440 | * Value - Pointer to in or out value | ||
441 | * handler_context - Pointer to Handler's context | ||
442 | * region_context - Pointer to context specific to the | ||
443 | * accessed region | ||
444 | * | ||
445 | * RETURN: Status | ||
446 | * | ||
447 | * DESCRIPTION: Handler for the PCI bar_target address space (Op Region) | ||
448 | * | ||
449 | ******************************************************************************/ | ||
450 | |||
451 | acpi_status | ||
452 | acpi_ex_pci_bar_space_handler ( | ||
453 | u32 function, | ||
454 | acpi_physical_address address, | ||
455 | u32 bit_width, | ||
456 | acpi_integer *value, | ||
457 | void *handler_context, | ||
458 | void *region_context) | ||
459 | { | ||
460 | acpi_status status = AE_OK; | ||
461 | |||
462 | |||
463 | ACPI_FUNCTION_TRACE ("ex_pci_bar_space_handler"); | ||
464 | |||
465 | |||
466 | return_ACPI_STATUS (status); | ||
467 | } | ||
468 | |||
469 | |||
470 | /******************************************************************************* | ||
471 | * | ||
472 | * FUNCTION: acpi_ex_data_table_space_handler | ||
473 | * | ||
474 | * PARAMETERS: Function - Read or Write operation | ||
475 | * Address - Where in the space to read or write | ||
476 | * bit_width - Field width in bits (8, 16, or 32) | ||
477 | * Value - Pointer to in or out value | ||
478 | * handler_context - Pointer to Handler's context | ||
479 | * region_context - Pointer to context specific to the | ||
480 | * accessed region | ||
481 | * | ||
482 | * RETURN: Status | ||
483 | * | ||
484 | * DESCRIPTION: Handler for the Data Table address space (Op Region) | ||
485 | * | ||
486 | ******************************************************************************/ | ||
487 | |||
488 | acpi_status | ||
489 | acpi_ex_data_table_space_handler ( | ||
490 | u32 function, | ||
491 | acpi_physical_address address, | ||
492 | u32 bit_width, | ||
493 | acpi_integer *value, | ||
494 | void *handler_context, | ||
495 | void *region_context) | ||
496 | { | ||
497 | acpi_status status = AE_OK; | ||
498 | u32 byte_width = ACPI_DIV_8 (bit_width); | ||
499 | u32 i; | ||
500 | char *logical_addr_ptr; | ||
501 | |||
502 | |||
503 | ACPI_FUNCTION_TRACE ("ex_data_table_space_handler"); | ||
504 | |||
505 | |||
506 | logical_addr_ptr = ACPI_PHYSADDR_TO_PTR (address); | ||
507 | |||
508 | |||
509 | /* Perform the memory read or write */ | ||
510 | |||
511 | switch (function) { | ||
512 | case ACPI_READ: | ||
513 | |||
514 | for (i = 0; i < byte_width; i++) { | ||
515 | ((char *) value) [i] = logical_addr_ptr[i]; | ||
516 | } | ||
517 | break; | ||
518 | |||
519 | case ACPI_WRITE: | ||
520 | default: | ||
521 | |||
522 | return_ACPI_STATUS (AE_SUPPORT); | ||
523 | } | ||
524 | |||
525 | return_ACPI_STATUS (status); | ||
526 | } | ||
527 | |||
528 | |||
diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c new file mode 100644 index 000000000000..7936329a0e35 --- /dev/null +++ b/drivers/acpi/executer/exresnte.c | |||
@@ -0,0 +1,289 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exresnte - AML Interpreter object resolution | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acdispat.h> | ||
48 | #include <acpi/acinterp.h> | ||
49 | #include <acpi/acnamesp.h> | ||
50 | #include <acpi/acparser.h> | ||
51 | #include <acpi/amlcode.h> | ||
52 | |||
53 | |||
54 | #define _COMPONENT ACPI_EXECUTER | ||
55 | ACPI_MODULE_NAME ("exresnte") | ||
56 | |||
57 | |||
58 | /******************************************************************************* | ||
59 | * | ||
60 | * FUNCTION: acpi_ex_resolve_node_to_value | ||
61 | * | ||
62 | * PARAMETERS: object_ptr - Pointer to a location that contains | ||
63 | * a pointer to a NS node, and will receive a | ||
64 | * pointer to the resolved object. | ||
65 | * walk_state - Current state. Valid only if executing AML | ||
66 | * code. NULL if simply resolving an object | ||
67 | * | ||
68 | * RETURN: Status | ||
69 | * | ||
70 | * DESCRIPTION: Resolve a Namespace node to a valued object | ||
71 | * | ||
72 | * Note: for some of the data types, the pointer attached to the Node | ||
73 | * can be either a pointer to an actual internal object or a pointer into the | ||
74 | * AML stream itself. These types are currently: | ||
75 | * | ||
76 | * ACPI_TYPE_INTEGER | ||
77 | * ACPI_TYPE_STRING | ||
78 | * ACPI_TYPE_BUFFER | ||
79 | * ACPI_TYPE_MUTEX | ||
80 | * ACPI_TYPE_PACKAGE | ||
81 | * | ||
82 | ******************************************************************************/ | ||
83 | |||
84 | acpi_status | ||
85 | acpi_ex_resolve_node_to_value ( | ||
86 | struct acpi_namespace_node **object_ptr, | ||
87 | struct acpi_walk_state *walk_state) | ||
88 | |||
89 | { | ||
90 | acpi_status status = AE_OK; | ||
91 | union acpi_operand_object *source_desc; | ||
92 | union acpi_operand_object *obj_desc = NULL; | ||
93 | struct acpi_namespace_node *node; | ||
94 | acpi_object_type entry_type; | ||
95 | |||
96 | |||
97 | ACPI_FUNCTION_TRACE ("ex_resolve_node_to_value"); | ||
98 | |||
99 | |||
100 | /* | ||
101 | * The stack pointer points to a struct acpi_namespace_node (Node). Get the | ||
102 | * object that is attached to the Node. | ||
103 | */ | ||
104 | node = *object_ptr; | ||
105 | source_desc = acpi_ns_get_attached_object (node); | ||
106 | entry_type = acpi_ns_get_type ((acpi_handle) node); | ||
107 | |||
108 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n", | ||
109 | node, source_desc, acpi_ut_get_type_name (entry_type))); | ||
110 | |||
111 | if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) || | ||
112 | (entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { | ||
113 | /* There is always exactly one level of indirection */ | ||
114 | |||
115 | node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object); | ||
116 | source_desc = acpi_ns_get_attached_object (node); | ||
117 | entry_type = acpi_ns_get_type ((acpi_handle) node); | ||
118 | *object_ptr = node; | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Several object types require no further processing: | ||
123 | * 1) Devices rarely have an attached object, return the Node | ||
124 | * 2) Method locals and arguments have a pseudo-Node | ||
125 | */ | ||
126 | if (entry_type == ACPI_TYPE_DEVICE || | ||
127 | (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { | ||
128 | return_ACPI_STATUS (AE_OK); | ||
129 | } | ||
130 | |||
131 | if (!source_desc) { | ||
132 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No object attached to node %p\n", | ||
133 | node)); | ||
134 | return_ACPI_STATUS (AE_AML_NO_OPERAND); | ||
135 | } | ||
136 | |||
137 | /* | ||
138 | * Action is based on the type of the Node, which indicates the type | ||
139 | * of the attached object or pointer | ||
140 | */ | ||
141 | switch (entry_type) { | ||
142 | case ACPI_TYPE_PACKAGE: | ||
143 | |||
144 | if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_PACKAGE) { | ||
145 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Package, type %s\n", | ||
146 | acpi_ut_get_object_type_name (source_desc))); | ||
147 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
148 | } | ||
149 | |||
150 | status = acpi_ds_get_package_arguments (source_desc); | ||
151 | if (ACPI_SUCCESS (status)) { | ||
152 | /* Return an additional reference to the object */ | ||
153 | |||
154 | obj_desc = source_desc; | ||
155 | acpi_ut_add_reference (obj_desc); | ||
156 | } | ||
157 | break; | ||
158 | |||
159 | |||
160 | case ACPI_TYPE_BUFFER: | ||
161 | |||
162 | if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) { | ||
163 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Buffer, type %s\n", | ||
164 | acpi_ut_get_object_type_name (source_desc))); | ||
165 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
166 | } | ||
167 | |||
168 | status = acpi_ds_get_buffer_arguments (source_desc); | ||
169 | if (ACPI_SUCCESS (status)) { | ||
170 | /* Return an additional reference to the object */ | ||
171 | |||
172 | obj_desc = source_desc; | ||
173 | acpi_ut_add_reference (obj_desc); | ||
174 | } | ||
175 | break; | ||
176 | |||
177 | |||
178 | case ACPI_TYPE_STRING: | ||
179 | |||
180 | if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING) { | ||
181 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a String, type %s\n", | ||
182 | acpi_ut_get_object_type_name (source_desc))); | ||
183 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
184 | } | ||
185 | |||
186 | /* Return an additional reference to the object */ | ||
187 | |||
188 | obj_desc = source_desc; | ||
189 | acpi_ut_add_reference (obj_desc); | ||
190 | break; | ||
191 | |||
192 | |||
193 | case ACPI_TYPE_INTEGER: | ||
194 | |||
195 | if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) { | ||
196 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Integer, type %s\n", | ||
197 | acpi_ut_get_object_type_name (source_desc))); | ||
198 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
199 | } | ||
200 | |||
201 | /* Return an additional reference to the object */ | ||
202 | |||
203 | obj_desc = source_desc; | ||
204 | acpi_ut_add_reference (obj_desc); | ||
205 | break; | ||
206 | |||
207 | |||
208 | case ACPI_TYPE_BUFFER_FIELD: | ||
209 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
210 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
211 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
212 | |||
213 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "field_read Node=%p source_desc=%p Type=%X\n", | ||
214 | node, source_desc, entry_type)); | ||
215 | |||
216 | status = acpi_ex_read_data_from_field (walk_state, source_desc, &obj_desc); | ||
217 | break; | ||
218 | |||
219 | /* | ||
220 | * For these objects, just return the object attached to the Node | ||
221 | */ | ||
222 | case ACPI_TYPE_MUTEX: | ||
223 | case ACPI_TYPE_METHOD: | ||
224 | case ACPI_TYPE_POWER: | ||
225 | case ACPI_TYPE_PROCESSOR: | ||
226 | case ACPI_TYPE_THERMAL: | ||
227 | case ACPI_TYPE_EVENT: | ||
228 | case ACPI_TYPE_REGION: | ||
229 | |||
230 | /* Return an additional reference to the object */ | ||
231 | |||
232 | obj_desc = source_desc; | ||
233 | acpi_ut_add_reference (obj_desc); | ||
234 | break; | ||
235 | |||
236 | |||
237 | /* TYPE_ANY is untyped, and thus there is no object associated with it */ | ||
238 | |||
239 | case ACPI_TYPE_ANY: | ||
240 | |||
241 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Untyped entry %p, no attached object!\n", | ||
242 | node)); | ||
243 | |||
244 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */ | ||
245 | |||
246 | |||
247 | case ACPI_TYPE_LOCAL_REFERENCE: | ||
248 | |||
249 | switch (source_desc->reference.opcode) { | ||
250 | case AML_LOAD_OP: | ||
251 | |||
252 | /* This is a ddb_handle */ | ||
253 | /* Return an additional reference to the object */ | ||
254 | |||
255 | obj_desc = source_desc; | ||
256 | acpi_ut_add_reference (obj_desc); | ||
257 | break; | ||
258 | |||
259 | default: | ||
260 | /* No named references are allowed here */ | ||
261 | |||
262 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported Reference opcode %X (%s)\n", | ||
263 | source_desc->reference.opcode, | ||
264 | acpi_ps_get_opcode_name (source_desc->reference.opcode))); | ||
265 | |||
266 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
267 | } | ||
268 | break; | ||
269 | |||
270 | |||
271 | /* Default case is for unknown types */ | ||
272 | |||
273 | default: | ||
274 | |||
275 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Node %p - Unknown object type %X\n", | ||
276 | node, entry_type)); | ||
277 | |||
278 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
279 | |||
280 | } /* switch (entry_type) */ | ||
281 | |||
282 | |||
283 | /* Put the object descriptor on the stack */ | ||
284 | |||
285 | *object_ptr = (void *) obj_desc; | ||
286 | return_ACPI_STATUS (status); | ||
287 | } | ||
288 | |||
289 | |||
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c new file mode 100644 index 000000000000..7be604911156 --- /dev/null +++ b/drivers/acpi/executer/exresolv.c | |||
@@ -0,0 +1,546 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exresolv - AML Interpreter object resolution | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/amlcode.h> | ||
48 | #include <acpi/acdispat.h> | ||
49 | #include <acpi/acinterp.h> | ||
50 | #include <acpi/acnamesp.h> | ||
51 | #include <acpi/acparser.h> | ||
52 | |||
53 | |||
54 | #define _COMPONENT ACPI_EXECUTER | ||
55 | ACPI_MODULE_NAME ("exresolv") | ||
56 | |||
57 | |||
58 | /******************************************************************************* | ||
59 | * | ||
60 | * FUNCTION: acpi_ex_resolve_to_value | ||
61 | * | ||
62 | * PARAMETERS: **stack_ptr - Points to entry on obj_stack, which can | ||
63 | * be either an (union acpi_operand_object *) | ||
64 | * or an acpi_handle. | ||
65 | * walk_state - Current method state | ||
66 | * | ||
67 | * RETURN: Status | ||
68 | * | ||
69 | * DESCRIPTION: Convert Reference objects to values | ||
70 | * | ||
71 | ******************************************************************************/ | ||
72 | |||
73 | acpi_status | ||
74 | acpi_ex_resolve_to_value ( | ||
75 | union acpi_operand_object **stack_ptr, | ||
76 | struct acpi_walk_state *walk_state) | ||
77 | { | ||
78 | acpi_status status; | ||
79 | |||
80 | |||
81 | ACPI_FUNCTION_TRACE_PTR ("ex_resolve_to_value", stack_ptr); | ||
82 | |||
83 | |||
84 | if (!stack_ptr || !*stack_ptr) { | ||
85 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null pointer\n")); | ||
86 | return_ACPI_STATUS (AE_AML_NO_OPERAND); | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * The entity pointed to by the stack_ptr can be either | ||
91 | * 1) A valid union acpi_operand_object, or | ||
92 | * 2) A struct acpi_namespace_node (named_obj) | ||
93 | */ | ||
94 | if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_OPERAND) { | ||
95 | status = acpi_ex_resolve_object_to_value (stack_ptr, walk_state); | ||
96 | if (ACPI_FAILURE (status)) { | ||
97 | return_ACPI_STATUS (status); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * Object on the stack may have changed if acpi_ex_resolve_object_to_value() | ||
103 | * was called (i.e., we can't use an _else_ here.) | ||
104 | */ | ||
105 | if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_NAMED) { | ||
106 | status = acpi_ex_resolve_node_to_value ( | ||
107 | ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, stack_ptr), | ||
108 | walk_state); | ||
109 | if (ACPI_FAILURE (status)) { | ||
110 | return_ACPI_STATUS (status); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr)); | ||
115 | return_ACPI_STATUS (AE_OK); | ||
116 | } | ||
117 | |||
118 | |||
119 | /******************************************************************************* | ||
120 | * | ||
121 | * FUNCTION: acpi_ex_resolve_object_to_value | ||
122 | * | ||
123 | * PARAMETERS: stack_ptr - Pointer to a stack location that contains a | ||
124 | * ptr to an internal object. | ||
125 | * walk_state - Current method state | ||
126 | * | ||
127 | * RETURN: Status | ||
128 | * | ||
129 | * DESCRIPTION: Retrieve the value from an internal object. The Reference type | ||
130 | * uses the associated AML opcode to determine the value. | ||
131 | * | ||
132 | ******************************************************************************/ | ||
133 | |||
134 | acpi_status | ||
135 | acpi_ex_resolve_object_to_value ( | ||
136 | union acpi_operand_object **stack_ptr, | ||
137 | struct acpi_walk_state *walk_state) | ||
138 | { | ||
139 | acpi_status status = AE_OK; | ||
140 | union acpi_operand_object *stack_desc; | ||
141 | void *temp_node; | ||
142 | union acpi_operand_object *obj_desc; | ||
143 | u16 opcode; | ||
144 | |||
145 | |||
146 | ACPI_FUNCTION_TRACE ("ex_resolve_object_to_value"); | ||
147 | |||
148 | |||
149 | stack_desc = *stack_ptr; | ||
150 | |||
151 | /* This is an union acpi_operand_object */ | ||
152 | |||
153 | switch (ACPI_GET_OBJECT_TYPE (stack_desc)) { | ||
154 | case ACPI_TYPE_LOCAL_REFERENCE: | ||
155 | |||
156 | opcode = stack_desc->reference.opcode; | ||
157 | |||
158 | switch (opcode) { | ||
159 | case AML_NAME_OP: | ||
160 | |||
161 | /* | ||
162 | * Convert indirect name ptr to a direct name ptr. | ||
163 | * Then, acpi_ex_resolve_node_to_value can be used to get the value | ||
164 | */ | ||
165 | temp_node = stack_desc->reference.object; | ||
166 | |||
167 | /* Delete the Reference Object */ | ||
168 | |||
169 | acpi_ut_remove_reference (stack_desc); | ||
170 | |||
171 | /* Put direct name pointer onto stack and exit */ | ||
172 | |||
173 | (*stack_ptr) = temp_node; | ||
174 | break; | ||
175 | |||
176 | |||
177 | case AML_LOCAL_OP: | ||
178 | case AML_ARG_OP: | ||
179 | |||
180 | /* | ||
181 | * Get the local from the method's state info | ||
182 | * Note: this increments the local's object reference count | ||
183 | */ | ||
184 | status = acpi_ds_method_data_get_value (opcode, | ||
185 | stack_desc->reference.offset, walk_state, &obj_desc); | ||
186 | if (ACPI_FAILURE (status)) { | ||
187 | return_ACPI_STATUS (status); | ||
188 | } | ||
189 | |||
190 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] value_obj is %p\n", | ||
191 | stack_desc->reference.offset, obj_desc)); | ||
192 | |||
193 | /* | ||
194 | * Now we can delete the original Reference Object and | ||
195 | * replace it with the resolved value | ||
196 | */ | ||
197 | acpi_ut_remove_reference (stack_desc); | ||
198 | *stack_ptr = obj_desc; | ||
199 | break; | ||
200 | |||
201 | |||
202 | case AML_INDEX_OP: | ||
203 | |||
204 | switch (stack_desc->reference.target_type) { | ||
205 | case ACPI_TYPE_BUFFER_FIELD: | ||
206 | |||
207 | /* Just return - leave the Reference on the stack */ | ||
208 | break; | ||
209 | |||
210 | |||
211 | case ACPI_TYPE_PACKAGE: | ||
212 | |||
213 | obj_desc = *stack_desc->reference.where; | ||
214 | if (obj_desc) { | ||
215 | /* | ||
216 | * Valid obj descriptor, copy pointer to return value | ||
217 | * (i.e., dereference the package index) | ||
218 | * Delete the ref object, increment the returned object | ||
219 | */ | ||
220 | acpi_ut_remove_reference (stack_desc); | ||
221 | acpi_ut_add_reference (obj_desc); | ||
222 | *stack_ptr = obj_desc; | ||
223 | } | ||
224 | else { | ||
225 | /* | ||
226 | * A NULL object descriptor means an unitialized element of | ||
227 | * the package, can't dereference it | ||
228 | */ | ||
229 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
230 | "Attempt to deref an Index to NULL pkg element Idx=%p\n", | ||
231 | stack_desc)); | ||
232 | status = AE_AML_UNINITIALIZED_ELEMENT; | ||
233 | } | ||
234 | break; | ||
235 | |||
236 | |||
237 | default: | ||
238 | |||
239 | /* Invalid reference object */ | ||
240 | |||
241 | ACPI_REPORT_ERROR (( | ||
242 | "During resolve, Unknown target_type %X in Index/Reference obj %p\n", | ||
243 | stack_desc->reference.target_type, stack_desc)); | ||
244 | status = AE_AML_INTERNAL; | ||
245 | break; | ||
246 | } | ||
247 | break; | ||
248 | |||
249 | |||
250 | case AML_REF_OF_OP: | ||
251 | case AML_DEBUG_OP: | ||
252 | case AML_LOAD_OP: | ||
253 | |||
254 | /* Just leave the object as-is */ | ||
255 | |||
256 | break; | ||
257 | |||
258 | |||
259 | default: | ||
260 | |||
261 | ACPI_REPORT_ERROR (("During resolve, Unknown Reference opcode %X (%s) in %p\n", | ||
262 | opcode, acpi_ps_get_opcode_name (opcode), stack_desc)); | ||
263 | status = AE_AML_INTERNAL; | ||
264 | break; | ||
265 | } | ||
266 | break; | ||
267 | |||
268 | |||
269 | case ACPI_TYPE_BUFFER: | ||
270 | |||
271 | status = acpi_ds_get_buffer_arguments (stack_desc); | ||
272 | break; | ||
273 | |||
274 | |||
275 | case ACPI_TYPE_PACKAGE: | ||
276 | |||
277 | status = acpi_ds_get_package_arguments (stack_desc); | ||
278 | break; | ||
279 | |||
280 | |||
281 | /* | ||
282 | * These cases may never happen here, but just in case.. | ||
283 | */ | ||
284 | case ACPI_TYPE_BUFFER_FIELD: | ||
285 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
286 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
287 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
288 | |||
289 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "field_read source_desc=%p Type=%X\n", | ||
290 | stack_desc, ACPI_GET_OBJECT_TYPE (stack_desc))); | ||
291 | |||
292 | status = acpi_ex_read_data_from_field (walk_state, stack_desc, &obj_desc); | ||
293 | *stack_ptr = (void *) obj_desc; | ||
294 | break; | ||
295 | |||
296 | default: | ||
297 | break; | ||
298 | } | ||
299 | |||
300 | return_ACPI_STATUS (status); | ||
301 | } | ||
302 | |||
303 | |||
304 | /******************************************************************************* | ||
305 | * | ||
306 | * FUNCTION: acpi_ex_resolve_multiple | ||
307 | * | ||
308 | * PARAMETERS: walk_state - Current state (contains AML opcode) | ||
309 | * Operand - Starting point for resolution | ||
310 | * return_type - Where the object type is returned | ||
311 | * return_desc - Where the resolved object is returned | ||
312 | * | ||
313 | * RETURN: Status | ||
314 | * | ||
315 | * DESCRIPTION: Return the base object and type. Traverse a reference list if | ||
316 | * necessary to get to the base object. | ||
317 | * | ||
318 | ******************************************************************************/ | ||
319 | |||
320 | acpi_status | ||
321 | acpi_ex_resolve_multiple ( | ||
322 | struct acpi_walk_state *walk_state, | ||
323 | union acpi_operand_object *operand, | ||
324 | acpi_object_type *return_type, | ||
325 | union acpi_operand_object **return_desc) | ||
326 | { | ||
327 | union acpi_operand_object *obj_desc = (void *) operand; | ||
328 | struct acpi_namespace_node *node; | ||
329 | acpi_object_type type; | ||
330 | acpi_status status; | ||
331 | |||
332 | |||
333 | ACPI_FUNCTION_TRACE ("acpi_ex_resolve_multiple"); | ||
334 | |||
335 | |||
336 | /* | ||
337 | * Operand can be either a namespace node or an operand descriptor | ||
338 | */ | ||
339 | switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) { | ||
340 | case ACPI_DESC_TYPE_OPERAND: | ||
341 | type = obj_desc->common.type; | ||
342 | break; | ||
343 | |||
344 | case ACPI_DESC_TYPE_NAMED: | ||
345 | type = ((struct acpi_namespace_node *) obj_desc)->type; | ||
346 | obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) obj_desc); | ||
347 | |||
348 | /* If we had an Alias node, use the attached object for type info */ | ||
349 | |||
350 | if (type == ACPI_TYPE_LOCAL_ALIAS) { | ||
351 | type = ((struct acpi_namespace_node *) obj_desc)->type; | ||
352 | obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) obj_desc); | ||
353 | } | ||
354 | break; | ||
355 | |||
356 | default: | ||
357 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
358 | } | ||
359 | |||
360 | |||
361 | /* | ||
362 | * If type is anything other than a reference, we are done | ||
363 | */ | ||
364 | if (type != ACPI_TYPE_LOCAL_REFERENCE) { | ||
365 | goto exit; | ||
366 | } | ||
367 | |||
368 | /* | ||
369 | * For reference objects created via the ref_of or Index operators, | ||
370 | * we need to get to the base object (as per the ACPI specification | ||
371 | * of the object_type and size_of operators). This means traversing | ||
372 | * the list of possibly many nested references. | ||
373 | */ | ||
374 | while (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { | ||
375 | switch (obj_desc->reference.opcode) { | ||
376 | case AML_REF_OF_OP: | ||
377 | |||
378 | /* Dereference the reference pointer */ | ||
379 | |||
380 | node = obj_desc->reference.object; | ||
381 | |||
382 | /* All "References" point to a NS node */ | ||
383 | |||
384 | if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) { | ||
385 | ACPI_REPORT_ERROR (("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", | ||
386 | node, acpi_ut_get_descriptor_name (node))); | ||
387 | return_ACPI_STATUS (AE_AML_INTERNAL); | ||
388 | } | ||
389 | |||
390 | /* Get the attached object */ | ||
391 | |||
392 | obj_desc = acpi_ns_get_attached_object (node); | ||
393 | if (!obj_desc) { | ||
394 | /* No object, use the NS node type */ | ||
395 | |||
396 | type = acpi_ns_get_type (node); | ||
397 | goto exit; | ||
398 | } | ||
399 | |||
400 | /* Check for circular references */ | ||
401 | |||
402 | if (obj_desc == operand) { | ||
403 | return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE); | ||
404 | } | ||
405 | break; | ||
406 | |||
407 | |||
408 | case AML_INDEX_OP: | ||
409 | |||
410 | /* Get the type of this reference (index into another object) */ | ||
411 | |||
412 | type = obj_desc->reference.target_type; | ||
413 | if (type != ACPI_TYPE_PACKAGE) { | ||
414 | goto exit; | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | * The main object is a package, we want to get the type | ||
419 | * of the individual package element that is referenced by | ||
420 | * the index. | ||
421 | * | ||
422 | * This could of course in turn be another reference object. | ||
423 | */ | ||
424 | obj_desc = *(obj_desc->reference.where); | ||
425 | if (!obj_desc) { | ||
426 | /* NULL package elements are allowed */ | ||
427 | |||
428 | type = 0; /* Uninitialized */ | ||
429 | goto exit; | ||
430 | } | ||
431 | break; | ||
432 | |||
433 | |||
434 | case AML_INT_NAMEPATH_OP: | ||
435 | |||
436 | /* Dereference the reference pointer */ | ||
437 | |||
438 | node = obj_desc->reference.node; | ||
439 | |||
440 | /* All "References" point to a NS node */ | ||
441 | |||
442 | if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) { | ||
443 | ACPI_REPORT_ERROR (("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", | ||
444 | node, acpi_ut_get_descriptor_name (node))); | ||
445 | return_ACPI_STATUS (AE_AML_INTERNAL); | ||
446 | } | ||
447 | |||
448 | /* Get the attached object */ | ||
449 | |||
450 | obj_desc = acpi_ns_get_attached_object (node); | ||
451 | if (!obj_desc) { | ||
452 | /* No object, use the NS node type */ | ||
453 | |||
454 | type = acpi_ns_get_type (node); | ||
455 | goto exit; | ||
456 | } | ||
457 | |||
458 | /* Check for circular references */ | ||
459 | |||
460 | if (obj_desc == operand) { | ||
461 | return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE); | ||
462 | } | ||
463 | break; | ||
464 | |||
465 | |||
466 | case AML_LOCAL_OP: | ||
467 | case AML_ARG_OP: | ||
468 | |||
469 | if (return_desc) { | ||
470 | status = acpi_ds_method_data_get_value (obj_desc->reference.opcode, | ||
471 | obj_desc->reference.offset, walk_state, &obj_desc); | ||
472 | if (ACPI_FAILURE (status)) { | ||
473 | return_ACPI_STATUS (status); | ||
474 | } | ||
475 | acpi_ut_remove_reference (obj_desc); | ||
476 | } | ||
477 | else { | ||
478 | status = acpi_ds_method_data_get_node (obj_desc->reference.opcode, | ||
479 | obj_desc->reference.offset, walk_state, &node); | ||
480 | if (ACPI_FAILURE (status)) { | ||
481 | return_ACPI_STATUS (status); | ||
482 | } | ||
483 | |||
484 | obj_desc = acpi_ns_get_attached_object (node); | ||
485 | if (!obj_desc) { | ||
486 | type = ACPI_TYPE_ANY; | ||
487 | goto exit; | ||
488 | } | ||
489 | } | ||
490 | break; | ||
491 | |||
492 | |||
493 | case AML_DEBUG_OP: | ||
494 | |||
495 | /* The Debug Object is of type "debug_object" */ | ||
496 | |||
497 | type = ACPI_TYPE_DEBUG_OBJECT; | ||
498 | goto exit; | ||
499 | |||
500 | |||
501 | default: | ||
502 | |||
503 | ACPI_REPORT_ERROR (("acpi_ex_resolve_multiple: Unknown Reference subtype %X\n", | ||
504 | obj_desc->reference.opcode)); | ||
505 | return_ACPI_STATUS (AE_AML_INTERNAL); | ||
506 | } | ||
507 | } | ||
508 | |||
509 | /* | ||
510 | * Now we are guaranteed to have an object that has not been created | ||
511 | * via the ref_of or Index operators. | ||
512 | */ | ||
513 | type = ACPI_GET_OBJECT_TYPE (obj_desc); | ||
514 | |||
515 | |||
516 | exit: | ||
517 | /* Convert internal types to external types */ | ||
518 | |||
519 | switch (type) { | ||
520 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
521 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
522 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
523 | |||
524 | type = ACPI_TYPE_FIELD_UNIT; | ||
525 | break; | ||
526 | |||
527 | case ACPI_TYPE_LOCAL_SCOPE: | ||
528 | |||
529 | /* Per ACPI Specification, Scope is untyped */ | ||
530 | |||
531 | type = ACPI_TYPE_ANY; | ||
532 | break; | ||
533 | |||
534 | default: | ||
535 | /* No change to Type required */ | ||
536 | break; | ||
537 | } | ||
538 | |||
539 | *return_type = type; | ||
540 | if (return_desc) { | ||
541 | *return_desc = obj_desc; | ||
542 | } | ||
543 | return_ACPI_STATUS (AE_OK); | ||
544 | } | ||
545 | |||
546 | |||
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c new file mode 100644 index 000000000000..c92890220c32 --- /dev/null +++ b/drivers/acpi/executer/exresop.c | |||
@@ -0,0 +1,661 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exresop - AML Interpreter operand/object resolution | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/amlcode.h> | ||
48 | #include <acpi/acparser.h> | ||
49 | #include <acpi/acinterp.h> | ||
50 | |||
51 | |||
52 | #define _COMPONENT ACPI_EXECUTER | ||
53 | ACPI_MODULE_NAME ("exresop") | ||
54 | |||
55 | |||
56 | /******************************************************************************* | ||
57 | * | ||
58 | * FUNCTION: acpi_ex_check_object_type | ||
59 | * | ||
60 | * PARAMETERS: type_needed Object type needed | ||
61 | * this_type Actual object type | ||
62 | * Object Object pointer | ||
63 | * | ||
64 | * RETURN: Status | ||
65 | * | ||
66 | * DESCRIPTION: Check required type against actual type | ||
67 | * | ||
68 | ******************************************************************************/ | ||
69 | |||
70 | acpi_status | ||
71 | acpi_ex_check_object_type ( | ||
72 | acpi_object_type type_needed, | ||
73 | acpi_object_type this_type, | ||
74 | void *object) | ||
75 | { | ||
76 | ACPI_FUNCTION_NAME ("ex_check_object_type"); | ||
77 | |||
78 | |||
79 | if (type_needed == ACPI_TYPE_ANY) { | ||
80 | /* All types OK, so we don't perform any typechecks */ | ||
81 | |||
82 | return (AE_OK); | ||
83 | } | ||
84 | |||
85 | if (type_needed == ACPI_TYPE_LOCAL_REFERENCE) { | ||
86 | /* | ||
87 | * Allow the AML "Constant" opcodes (Zero, One, etc.) to be reference | ||
88 | * objects and thus allow them to be targets. (As per the ACPI | ||
89 | * specification, a store to a constant is a noop.) | ||
90 | */ | ||
91 | if ((this_type == ACPI_TYPE_INTEGER) && | ||
92 | (((union acpi_operand_object *) object)->common.flags & AOPOBJ_AML_CONSTANT)) { | ||
93 | return (AE_OK); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | if (type_needed != this_type) { | ||
98 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
99 | "Needed [%s], found [%s] %p\n", | ||
100 | acpi_ut_get_type_name (type_needed), | ||
101 | acpi_ut_get_type_name (this_type), object)); | ||
102 | |||
103 | return (AE_AML_OPERAND_TYPE); | ||
104 | } | ||
105 | |||
106 | return (AE_OK); | ||
107 | } | ||
108 | |||
109 | |||
110 | /******************************************************************************* | ||
111 | * | ||
112 | * FUNCTION: acpi_ex_resolve_operands | ||
113 | * | ||
114 | * PARAMETERS: Opcode - Opcode being interpreted | ||
115 | * stack_ptr - Pointer to the operand stack to be | ||
116 | * resolved | ||
117 | * walk_state - Current state | ||
118 | * | ||
119 | * RETURN: Status | ||
120 | * | ||
121 | * DESCRIPTION: Convert multiple input operands to the types required by the | ||
122 | * target operator. | ||
123 | * | ||
124 | * Each 5-bit group in arg_types represents one required | ||
125 | * operand and indicates the required Type. The corresponding operand | ||
126 | * will be converted to the required type if possible, otherwise we | ||
127 | * abort with an exception. | ||
128 | * | ||
129 | ******************************************************************************/ | ||
130 | |||
131 | acpi_status | ||
132 | acpi_ex_resolve_operands ( | ||
133 | u16 opcode, | ||
134 | union acpi_operand_object **stack_ptr, | ||
135 | struct acpi_walk_state *walk_state) | ||
136 | { | ||
137 | union acpi_operand_object *obj_desc; | ||
138 | acpi_status status = AE_OK; | ||
139 | u8 object_type; | ||
140 | void *temp_node; | ||
141 | u32 arg_types; | ||
142 | const struct acpi_opcode_info *op_info; | ||
143 | u32 this_arg_type; | ||
144 | acpi_object_type type_needed; | ||
145 | |||
146 | |||
147 | ACPI_FUNCTION_TRACE_U32 ("ex_resolve_operands", opcode); | ||
148 | |||
149 | |||
150 | op_info = acpi_ps_get_opcode_info (opcode); | ||
151 | if (op_info->class == AML_CLASS_UNKNOWN) { | ||
152 | return_ACPI_STATUS (AE_AML_BAD_OPCODE); | ||
153 | } | ||
154 | |||
155 | arg_types = op_info->runtime_args; | ||
156 | if (arg_types == ARGI_INVALID_OPCODE) { | ||
157 | ACPI_REPORT_ERROR (("resolve_operands: %X is not a valid AML opcode\n", | ||
158 | opcode)); | ||
159 | |||
160 | return_ACPI_STATUS (AE_AML_INTERNAL); | ||
161 | } | ||
162 | |||
163 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode %X [%s] required_operand_types=%8.8X \n", | ||
164 | opcode, op_info->name, arg_types)); | ||
165 | |||
166 | /* | ||
167 | * Normal exit is with (arg_types == 0) at end of argument list. | ||
168 | * Function will return an exception from within the loop upon | ||
169 | * finding an entry which is not (or cannot be converted | ||
170 | * to) the required type; if stack underflows; or upon | ||
171 | * finding a NULL stack entry (which should not happen). | ||
172 | */ | ||
173 | while (GET_CURRENT_ARG_TYPE (arg_types)) { | ||
174 | if (!stack_ptr || !*stack_ptr) { | ||
175 | ACPI_REPORT_ERROR (("resolve_operands: Null stack entry at %p\n", | ||
176 | stack_ptr)); | ||
177 | |||
178 | return_ACPI_STATUS (AE_AML_INTERNAL); | ||
179 | } | ||
180 | |||
181 | /* Extract useful items */ | ||
182 | |||
183 | obj_desc = *stack_ptr; | ||
184 | |||
185 | /* Decode the descriptor type */ | ||
186 | |||
187 | switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) { | ||
188 | case ACPI_DESC_TYPE_NAMED: | ||
189 | |||
190 | /* Node */ | ||
191 | |||
192 | object_type = ((struct acpi_namespace_node *) obj_desc)->type; | ||
193 | break; | ||
194 | |||
195 | |||
196 | case ACPI_DESC_TYPE_OPERAND: | ||
197 | |||
198 | /* ACPI internal object */ | ||
199 | |||
200 | object_type = ACPI_GET_OBJECT_TYPE (obj_desc); | ||
201 | |||
202 | /* Check for bad acpi_object_type */ | ||
203 | |||
204 | if (!acpi_ut_valid_object_type (object_type)) { | ||
205 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad operand object type [%X]\n", | ||
206 | object_type)); | ||
207 | |||
208 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
209 | } | ||
210 | |||
211 | if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) { | ||
212 | /* | ||
213 | * Decode the Reference | ||
214 | */ | ||
215 | op_info = acpi_ps_get_opcode_info (opcode); | ||
216 | if (op_info->class == AML_CLASS_UNKNOWN) { | ||
217 | return_ACPI_STATUS (AE_AML_BAD_OPCODE); | ||
218 | } | ||
219 | |||
220 | switch (obj_desc->reference.opcode) { | ||
221 | case AML_DEBUG_OP: | ||
222 | case AML_NAME_OP: | ||
223 | case AML_INDEX_OP: | ||
224 | case AML_REF_OF_OP: | ||
225 | case AML_ARG_OP: | ||
226 | case AML_LOCAL_OP: | ||
227 | case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */ | ||
228 | |||
229 | ACPI_DEBUG_ONLY_MEMBERS (ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, | ||
230 | "Operand is a Reference, ref_opcode [%s]\n", | ||
231 | (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name))); | ||
232 | break; | ||
233 | |||
234 | default: | ||
235 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
236 | "Operand is a Reference, Unknown Reference Opcode %X [%s]\n", | ||
237 | obj_desc->reference.opcode, | ||
238 | (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name)); | ||
239 | |||
240 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
241 | } | ||
242 | } | ||
243 | break; | ||
244 | |||
245 | |||
246 | default: | ||
247 | |||
248 | /* Invalid descriptor */ | ||
249 | |||
250 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
251 | "Invalid descriptor %p [%s]\n", | ||
252 | obj_desc, acpi_ut_get_descriptor_name (obj_desc))); | ||
253 | |||
254 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
255 | } | ||
256 | |||
257 | |||
258 | /* | ||
259 | * Get one argument type, point to the next | ||
260 | */ | ||
261 | this_arg_type = GET_CURRENT_ARG_TYPE (arg_types); | ||
262 | INCREMENT_ARG_LIST (arg_types); | ||
263 | |||
264 | /* | ||
265 | * Handle cases where the object does not need to be | ||
266 | * resolved to a value | ||
267 | */ | ||
268 | switch (this_arg_type) { | ||
269 | case ARGI_REF_OR_STRING: /* Can be a String or Reference */ | ||
270 | |||
271 | if ((ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_OPERAND) && | ||
272 | (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_STRING)) { | ||
273 | /* | ||
274 | * String found - the string references a named object and must be | ||
275 | * resolved to a node | ||
276 | */ | ||
277 | goto next_operand; | ||
278 | } | ||
279 | |||
280 | /* Else not a string - fall through to the normal Reference case below */ | ||
281 | /*lint -fallthrough */ | ||
282 | |||
283 | case ARGI_REFERENCE: /* References: */ | ||
284 | case ARGI_INTEGER_REF: | ||
285 | case ARGI_OBJECT_REF: | ||
286 | case ARGI_DEVICE_REF: | ||
287 | case ARGI_TARGETREF: /* Allows implicit conversion rules before store */ | ||
288 | case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ | ||
289 | case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */ | ||
290 | |||
291 | /* Need an operand of type ACPI_TYPE_LOCAL_REFERENCE */ | ||
292 | |||
293 | if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) /* Node (name) ptr OK as-is */ { | ||
294 | goto next_operand; | ||
295 | } | ||
296 | |||
297 | status = acpi_ex_check_object_type (ACPI_TYPE_LOCAL_REFERENCE, | ||
298 | object_type, obj_desc); | ||
299 | if (ACPI_FAILURE (status)) { | ||
300 | return_ACPI_STATUS (status); | ||
301 | } | ||
302 | |||
303 | if (AML_NAME_OP == obj_desc->reference.opcode) { | ||
304 | /* | ||
305 | * Convert an indirect name ptr to direct name ptr and put | ||
306 | * it on the stack | ||
307 | */ | ||
308 | temp_node = obj_desc->reference.object; | ||
309 | acpi_ut_remove_reference (obj_desc); | ||
310 | (*stack_ptr) = temp_node; | ||
311 | } | ||
312 | goto next_operand; | ||
313 | |||
314 | |||
315 | case ARGI_DATAREFOBJ: /* Store operator only */ | ||
316 | |||
317 | /* | ||
318 | * We don't want to resolve index_op reference objects during | ||
319 | * a store because this would be an implicit de_ref_of operation. | ||
320 | * Instead, we just want to store the reference object. | ||
321 | * -- All others must be resolved below. | ||
322 | */ | ||
323 | if ((opcode == AML_STORE_OP) && | ||
324 | (ACPI_GET_OBJECT_TYPE (*stack_ptr) == ACPI_TYPE_LOCAL_REFERENCE) && | ||
325 | ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) { | ||
326 | goto next_operand; | ||
327 | } | ||
328 | break; | ||
329 | |||
330 | default: | ||
331 | /* All cases covered above */ | ||
332 | break; | ||
333 | } | ||
334 | |||
335 | |||
336 | /* | ||
337 | * Resolve this object to a value | ||
338 | */ | ||
339 | status = acpi_ex_resolve_to_value (stack_ptr, walk_state); | ||
340 | if (ACPI_FAILURE (status)) { | ||
341 | return_ACPI_STATUS (status); | ||
342 | } | ||
343 | |||
344 | /* Get the resolved object */ | ||
345 | |||
346 | obj_desc = *stack_ptr; | ||
347 | |||
348 | /* | ||
349 | * Check the resulting object (value) type | ||
350 | */ | ||
351 | switch (this_arg_type) { | ||
352 | /* | ||
353 | * For the simple cases, only one type of resolved object | ||
354 | * is allowed | ||
355 | */ | ||
356 | case ARGI_MUTEX: | ||
357 | |||
358 | /* Need an operand of type ACPI_TYPE_MUTEX */ | ||
359 | |||
360 | type_needed = ACPI_TYPE_MUTEX; | ||
361 | break; | ||
362 | |||
363 | case ARGI_EVENT: | ||
364 | |||
365 | /* Need an operand of type ACPI_TYPE_EVENT */ | ||
366 | |||
367 | type_needed = ACPI_TYPE_EVENT; | ||
368 | break; | ||
369 | |||
370 | case ARGI_PACKAGE: /* Package */ | ||
371 | |||
372 | /* Need an operand of type ACPI_TYPE_PACKAGE */ | ||
373 | |||
374 | type_needed = ACPI_TYPE_PACKAGE; | ||
375 | break; | ||
376 | |||
377 | case ARGI_ANYTYPE: | ||
378 | |||
379 | /* Any operand type will do */ | ||
380 | |||
381 | type_needed = ACPI_TYPE_ANY; | ||
382 | break; | ||
383 | |||
384 | case ARGI_DDBHANDLE: | ||
385 | |||
386 | /* Need an operand of type ACPI_TYPE_DDB_HANDLE */ | ||
387 | |||
388 | type_needed = ACPI_TYPE_LOCAL_REFERENCE; | ||
389 | break; | ||
390 | |||
391 | |||
392 | /* | ||
393 | * The more complex cases allow multiple resolved object types | ||
394 | */ | ||
395 | case ARGI_INTEGER: /* Number */ | ||
396 | |||
397 | /* | ||
398 | * Need an operand of type ACPI_TYPE_INTEGER, | ||
399 | * But we can implicitly convert from a STRING or BUFFER | ||
400 | * Aka - "Implicit Source Operand Conversion" | ||
401 | */ | ||
402 | status = acpi_ex_convert_to_integer (obj_desc, stack_ptr, 16); | ||
403 | if (ACPI_FAILURE (status)) { | ||
404 | if (status == AE_TYPE) { | ||
405 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
406 | "Needed [Integer/String/Buffer], found [%s] %p\n", | ||
407 | acpi_ut_get_object_type_name (obj_desc), obj_desc)); | ||
408 | |||
409 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
410 | } | ||
411 | |||
412 | return_ACPI_STATUS (status); | ||
413 | } | ||
414 | goto next_operand; | ||
415 | |||
416 | |||
417 | case ARGI_BUFFER: | ||
418 | |||
419 | /* | ||
420 | * Need an operand of type ACPI_TYPE_BUFFER, | ||
421 | * But we can implicitly convert from a STRING or INTEGER | ||
422 | * Aka - "Implicit Source Operand Conversion" | ||
423 | */ | ||
424 | status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr); | ||
425 | if (ACPI_FAILURE (status)) { | ||
426 | if (status == AE_TYPE) { | ||
427 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
428 | "Needed [Integer/String/Buffer], found [%s] %p\n", | ||
429 | acpi_ut_get_object_type_name (obj_desc), obj_desc)); | ||
430 | |||
431 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
432 | } | ||
433 | |||
434 | return_ACPI_STATUS (status); | ||
435 | } | ||
436 | goto next_operand; | ||
437 | |||
438 | |||
439 | case ARGI_STRING: | ||
440 | |||
441 | /* | ||
442 | * Need an operand of type ACPI_TYPE_STRING, | ||
443 | * But we can implicitly convert from a BUFFER or INTEGER | ||
444 | * Aka - "Implicit Source Operand Conversion" | ||
445 | */ | ||
446 | status = acpi_ex_convert_to_string (obj_desc, stack_ptr, | ||
447 | ACPI_IMPLICIT_CONVERT_HEX); | ||
448 | if (ACPI_FAILURE (status)) { | ||
449 | if (status == AE_TYPE) { | ||
450 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
451 | "Needed [Integer/String/Buffer], found [%s] %p\n", | ||
452 | acpi_ut_get_object_type_name (obj_desc), obj_desc)); | ||
453 | |||
454 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
455 | } | ||
456 | |||
457 | return_ACPI_STATUS (status); | ||
458 | } | ||
459 | goto next_operand; | ||
460 | |||
461 | |||
462 | case ARGI_COMPUTEDATA: | ||
463 | |||
464 | /* Need an operand of type INTEGER, STRING or BUFFER */ | ||
465 | |||
466 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
467 | case ACPI_TYPE_INTEGER: | ||
468 | case ACPI_TYPE_STRING: | ||
469 | case ACPI_TYPE_BUFFER: | ||
470 | |||
471 | /* Valid operand */ | ||
472 | break; | ||
473 | |||
474 | default: | ||
475 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
476 | "Needed [Integer/String/Buffer], found [%s] %p\n", | ||
477 | acpi_ut_get_object_type_name (obj_desc), obj_desc)); | ||
478 | |||
479 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
480 | } | ||
481 | goto next_operand; | ||
482 | |||
483 | |||
484 | case ARGI_BUFFER_OR_STRING: | ||
485 | |||
486 | /* Need an operand of type STRING or BUFFER */ | ||
487 | |||
488 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
489 | case ACPI_TYPE_STRING: | ||
490 | case ACPI_TYPE_BUFFER: | ||
491 | |||
492 | /* Valid operand */ | ||
493 | break; | ||
494 | |||
495 | case ACPI_TYPE_INTEGER: | ||
496 | |||
497 | /* Highest priority conversion is to type Buffer */ | ||
498 | |||
499 | status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr); | ||
500 | if (ACPI_FAILURE (status)) { | ||
501 | return_ACPI_STATUS (status); | ||
502 | } | ||
503 | break; | ||
504 | |||
505 | default: | ||
506 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
507 | "Needed [Integer/String/Buffer], found [%s] %p\n", | ||
508 | acpi_ut_get_object_type_name (obj_desc), obj_desc)); | ||
509 | |||
510 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
511 | } | ||
512 | goto next_operand; | ||
513 | |||
514 | |||
515 | case ARGI_DATAOBJECT: | ||
516 | /* | ||
517 | * ARGI_DATAOBJECT is only used by the size_of operator. | ||
518 | * Need a buffer, string, package, or ref_of reference. | ||
519 | * | ||
520 | * The only reference allowed here is a direct reference to | ||
521 | * a namespace node. | ||
522 | */ | ||
523 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
524 | case ACPI_TYPE_PACKAGE: | ||
525 | case ACPI_TYPE_STRING: | ||
526 | case ACPI_TYPE_BUFFER: | ||
527 | case ACPI_TYPE_LOCAL_REFERENCE: | ||
528 | |||
529 | /* Valid operand */ | ||
530 | break; | ||
531 | |||
532 | default: | ||
533 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
534 | "Needed [Buffer/String/Package/Reference], found [%s] %p\n", | ||
535 | acpi_ut_get_object_type_name (obj_desc), obj_desc)); | ||
536 | |||
537 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
538 | } | ||
539 | goto next_operand; | ||
540 | |||
541 | |||
542 | case ARGI_COMPLEXOBJ: | ||
543 | |||
544 | /* Need a buffer or package or (ACPI 2.0) String */ | ||
545 | |||
546 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
547 | case ACPI_TYPE_PACKAGE: | ||
548 | case ACPI_TYPE_STRING: | ||
549 | case ACPI_TYPE_BUFFER: | ||
550 | |||
551 | /* Valid operand */ | ||
552 | break; | ||
553 | |||
554 | default: | ||
555 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
556 | "Needed [Buffer/String/Package], found [%s] %p\n", | ||
557 | acpi_ut_get_object_type_name (obj_desc), obj_desc)); | ||
558 | |||
559 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
560 | } | ||
561 | goto next_operand; | ||
562 | |||
563 | |||
564 | case ARGI_REGION_OR_FIELD: | ||
565 | |||
566 | /* Need an operand of type ACPI_TYPE_REGION or a FIELD in a region */ | ||
567 | |||
568 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
569 | case ACPI_TYPE_REGION: | ||
570 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
571 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
572 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
573 | |||
574 | /* Valid operand */ | ||
575 | break; | ||
576 | |||
577 | default: | ||
578 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
579 | "Needed [Region/region_field], found [%s] %p\n", | ||
580 | acpi_ut_get_object_type_name (obj_desc), obj_desc)); | ||
581 | |||
582 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
583 | } | ||
584 | goto next_operand; | ||
585 | |||
586 | |||
587 | case ARGI_DATAREFOBJ: | ||
588 | |||
589 | /* Used by the Store() operator only */ | ||
590 | |||
591 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | ||
592 | case ACPI_TYPE_INTEGER: | ||
593 | case ACPI_TYPE_PACKAGE: | ||
594 | case ACPI_TYPE_STRING: | ||
595 | case ACPI_TYPE_BUFFER: | ||
596 | case ACPI_TYPE_BUFFER_FIELD: | ||
597 | case ACPI_TYPE_LOCAL_REFERENCE: | ||
598 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
599 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
600 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
601 | case ACPI_TYPE_DDB_HANDLE: | ||
602 | |||
603 | /* Valid operand */ | ||
604 | break; | ||
605 | |||
606 | default: | ||
607 | |||
608 | if (acpi_gbl_enable_interpreter_slack) { | ||
609 | /* | ||
610 | * Enable original behavior of Store(), allowing any and all | ||
611 | * objects as the source operand. The ACPI spec does not | ||
612 | * allow this, however. | ||
613 | */ | ||
614 | break; | ||
615 | } | ||
616 | |||
617 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
618 | "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p\n", | ||
619 | acpi_ut_get_object_type_name (obj_desc), obj_desc)); | ||
620 | |||
621 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
622 | } | ||
623 | goto next_operand; | ||
624 | |||
625 | |||
626 | default: | ||
627 | |||
628 | /* Unknown type */ | ||
629 | |||
630 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
631 | "Internal - Unknown ARGI (required operand) type %X\n", | ||
632 | this_arg_type)); | ||
633 | |||
634 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
635 | } | ||
636 | |||
637 | /* | ||
638 | * Make sure that the original object was resolved to the | ||
639 | * required object type (Simple cases only). | ||
640 | */ | ||
641 | status = acpi_ex_check_object_type (type_needed, | ||
642 | ACPI_GET_OBJECT_TYPE (*stack_ptr), *stack_ptr); | ||
643 | if (ACPI_FAILURE (status)) { | ||
644 | return_ACPI_STATUS (status); | ||
645 | } | ||
646 | |||
647 | next_operand: | ||
648 | /* | ||
649 | * If more operands needed, decrement stack_ptr to point | ||
650 | * to next operand on stack | ||
651 | */ | ||
652 | if (GET_CURRENT_ARG_TYPE (arg_types)) { | ||
653 | stack_ptr--; | ||
654 | } | ||
655 | |||
656 | } /* while (*Types) */ | ||
657 | |||
658 | return_ACPI_STATUS (status); | ||
659 | } | ||
660 | |||
661 | |||
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c new file mode 100644 index 000000000000..e0fc6aba1253 --- /dev/null +++ b/drivers/acpi/executer/exstore.c | |||
@@ -0,0 +1,536 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exstore - AML Interpreter object store support | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acdispat.h> | ||
48 | #include <acpi/acinterp.h> | ||
49 | #include <acpi/amlcode.h> | ||
50 | #include <acpi/acnamesp.h> | ||
51 | |||
52 | |||
53 | #define _COMPONENT ACPI_EXECUTER | ||
54 | ACPI_MODULE_NAME ("exstore") | ||
55 | |||
56 | |||
57 | /******************************************************************************* | ||
58 | * | ||
59 | * FUNCTION: acpi_ex_store | ||
60 | * | ||
61 | * PARAMETERS: *source_desc - Value to be stored | ||
62 | * *dest_desc - Where to store it. Must be an NS node | ||
63 | * or an union acpi_operand_object of type | ||
64 | * Reference; | ||
65 | * walk_state - Current walk state | ||
66 | * | ||
67 | * RETURN: Status | ||
68 | * | ||
69 | * DESCRIPTION: Store the value described by source_desc into the location | ||
70 | * described by dest_desc. Called by various interpreter | ||
71 | * functions to store the result of an operation into | ||
72 | * the destination operand -- not just simply the actual "Store" | ||
73 | * ASL operator. | ||
74 | * | ||
75 | ******************************************************************************/ | ||
76 | |||
77 | acpi_status | ||
78 | acpi_ex_store ( | ||
79 | union acpi_operand_object *source_desc, | ||
80 | union acpi_operand_object *dest_desc, | ||
81 | struct acpi_walk_state *walk_state) | ||
82 | { | ||
83 | acpi_status status = AE_OK; | ||
84 | union acpi_operand_object *ref_desc = dest_desc; | ||
85 | |||
86 | |||
87 | ACPI_FUNCTION_TRACE_PTR ("ex_store", dest_desc); | ||
88 | |||
89 | |||
90 | /* Validate parameters */ | ||
91 | |||
92 | if (!source_desc || !dest_desc) { | ||
93 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null parameter\n")); | ||
94 | return_ACPI_STATUS (AE_AML_NO_OPERAND); | ||
95 | } | ||
96 | |||
97 | /* dest_desc can be either a namespace node or an ACPI object */ | ||
98 | |||
99 | if (ACPI_GET_DESCRIPTOR_TYPE (dest_desc) == ACPI_DESC_TYPE_NAMED) { | ||
100 | /* | ||
101 | * Dest is a namespace node, | ||
102 | * Storing an object into a Named node. | ||
103 | */ | ||
104 | status = acpi_ex_store_object_to_node (source_desc, | ||
105 | (struct acpi_namespace_node *) dest_desc, walk_state, | ||
106 | ACPI_IMPLICIT_CONVERSION); | ||
107 | |||
108 | return_ACPI_STATUS (status); | ||
109 | } | ||
110 | |||
111 | /* Destination object must be a Reference or a Constant object */ | ||
112 | |||
113 | switch (ACPI_GET_OBJECT_TYPE (dest_desc)) { | ||
114 | case ACPI_TYPE_LOCAL_REFERENCE: | ||
115 | break; | ||
116 | |||
117 | case ACPI_TYPE_INTEGER: | ||
118 | |||
119 | /* Allow stores to Constants -- a Noop as per ACPI spec */ | ||
120 | |||
121 | if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) { | ||
122 | return_ACPI_STATUS (AE_OK); | ||
123 | } | ||
124 | |||
125 | /*lint -fallthrough */ | ||
126 | |||
127 | default: | ||
128 | |||
129 | /* Destination is not a Reference object */ | ||
130 | |||
131 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
132 | "Target is not a Reference or Constant object - %s [%p]\n", | ||
133 | acpi_ut_get_object_type_name (dest_desc), dest_desc)); | ||
134 | |||
135 | ACPI_DUMP_STACK_ENTRY (source_desc); | ||
136 | ACPI_DUMP_STACK_ENTRY (dest_desc); | ||
137 | ACPI_DUMP_OPERANDS (&dest_desc, ACPI_IMODE_EXECUTE, "ex_store", | ||
138 | 2, "Target is not a Reference or Constant object"); | ||
139 | |||
140 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * Examine the Reference opcode. These cases are handled: | ||
145 | * | ||
146 | * 1) Store to Name (Change the object associated with a name) | ||
147 | * 2) Store to an indexed area of a Buffer or Package | ||
148 | * 3) Store to a Method Local or Arg | ||
149 | * 4) Store to the debug object | ||
150 | */ | ||
151 | switch (ref_desc->reference.opcode) { | ||
152 | case AML_NAME_OP: | ||
153 | case AML_REF_OF_OP: | ||
154 | |||
155 | /* Storing an object into a Name "container" */ | ||
156 | |||
157 | status = acpi_ex_store_object_to_node (source_desc, ref_desc->reference.object, | ||
158 | walk_state, ACPI_IMPLICIT_CONVERSION); | ||
159 | break; | ||
160 | |||
161 | |||
162 | case AML_INDEX_OP: | ||
163 | |||
164 | /* Storing to an Index (pointer into a packager or buffer) */ | ||
165 | |||
166 | status = acpi_ex_store_object_to_index (source_desc, ref_desc, walk_state); | ||
167 | break; | ||
168 | |||
169 | |||
170 | case AML_LOCAL_OP: | ||
171 | case AML_ARG_OP: | ||
172 | |||
173 | /* Store to a method local/arg */ | ||
174 | |||
175 | status = acpi_ds_store_object_to_local (ref_desc->reference.opcode, | ||
176 | ref_desc->reference.offset, source_desc, walk_state); | ||
177 | break; | ||
178 | |||
179 | |||
180 | case AML_DEBUG_OP: | ||
181 | |||
182 | /* | ||
183 | * Storing to the Debug object causes the value stored to be | ||
184 | * displayed and otherwise has no effect -- see ACPI Specification | ||
185 | */ | ||
186 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, | ||
187 | "**** Write to Debug Object: Object %p %s ****:\n\n", | ||
188 | source_desc, acpi_ut_get_object_type_name (source_desc))); | ||
189 | |||
190 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %s: ", | ||
191 | acpi_ut_get_object_type_name (source_desc))); | ||
192 | |||
193 | if (!acpi_ut_valid_internal_object (source_desc)) { | ||
194 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, | ||
195 | "%p, Invalid Internal Object!\n", source_desc)); | ||
196 | break; | ||
197 | } | ||
198 | |||
199 | switch (ACPI_GET_OBJECT_TYPE (source_desc)) { | ||
200 | case ACPI_TYPE_INTEGER: | ||
201 | |||
202 | if (acpi_gbl_integer_byte_width == 4) { | ||
203 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n", | ||
204 | (u32) source_desc->integer.value)); | ||
205 | } | ||
206 | else { | ||
207 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n", | ||
208 | ACPI_FORMAT_UINT64 (source_desc->integer.value))); | ||
209 | } | ||
210 | break; | ||
211 | |||
212 | |||
213 | case ACPI_TYPE_BUFFER: | ||
214 | |||
215 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]", | ||
216 | (u32) source_desc->buffer.length)); | ||
217 | ACPI_DUMP_BUFFER (source_desc->buffer.pointer, | ||
218 | (source_desc->buffer.length < 32) ? source_desc->buffer.length : 32); | ||
219 | break; | ||
220 | |||
221 | |||
222 | case ACPI_TYPE_STRING: | ||
223 | |||
224 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n", | ||
225 | source_desc->string.length, source_desc->string.pointer)); | ||
226 | break; | ||
227 | |||
228 | |||
229 | case ACPI_TYPE_PACKAGE: | ||
230 | |||
231 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] Elements Ptr - %p\n", | ||
232 | source_desc->package.count, source_desc->package.elements)); | ||
233 | break; | ||
234 | |||
235 | |||
236 | default: | ||
237 | |||
238 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%p\n", | ||
239 | source_desc)); | ||
240 | break; | ||
241 | } | ||
242 | |||
243 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n")); | ||
244 | break; | ||
245 | |||
246 | |||
247 | default: | ||
248 | |||
249 | ACPI_REPORT_ERROR (("ex_store: Unknown Reference opcode %X\n", | ||
250 | ref_desc->reference.opcode)); | ||
251 | ACPI_DUMP_ENTRY (ref_desc, ACPI_LV_ERROR); | ||
252 | |||
253 | status = AE_AML_INTERNAL; | ||
254 | break; | ||
255 | } | ||
256 | |||
257 | return_ACPI_STATUS (status); | ||
258 | } | ||
259 | |||
260 | |||
261 | /******************************************************************************* | ||
262 | * | ||
263 | * FUNCTION: acpi_ex_store_object_to_index | ||
264 | * | ||
265 | * PARAMETERS: *source_desc - Value to be stored | ||
266 | * *dest_desc - Named object to receive the value | ||
267 | * walk_state - Current walk state | ||
268 | * | ||
269 | * RETURN: Status | ||
270 | * | ||
271 | * DESCRIPTION: Store the object to indexed Buffer or Package element | ||
272 | * | ||
273 | ******************************************************************************/ | ||
274 | |||
275 | acpi_status | ||
276 | acpi_ex_store_object_to_index ( | ||
277 | union acpi_operand_object *source_desc, | ||
278 | union acpi_operand_object *index_desc, | ||
279 | struct acpi_walk_state *walk_state) | ||
280 | { | ||
281 | acpi_status status = AE_OK; | ||
282 | union acpi_operand_object *obj_desc; | ||
283 | union acpi_operand_object *new_desc; | ||
284 | u8 value = 0; | ||
285 | u32 i; | ||
286 | |||
287 | |||
288 | ACPI_FUNCTION_TRACE ("ex_store_object_to_index"); | ||
289 | |||
290 | |||
291 | /* | ||
292 | * Destination must be a reference pointer, and | ||
293 | * must point to either a buffer or a package | ||
294 | */ | ||
295 | switch (index_desc->reference.target_type) { | ||
296 | case ACPI_TYPE_PACKAGE: | ||
297 | /* | ||
298 | * Storing to a package element. Copy the object and replace | ||
299 | * any existing object with the new object. No implicit | ||
300 | * conversion is performed. | ||
301 | * | ||
302 | * The object at *(index_desc->Reference.Where) is the | ||
303 | * element within the package that is to be modified. | ||
304 | * The parent package object is at index_desc->Reference.Object | ||
305 | */ | ||
306 | obj_desc = *(index_desc->reference.where); | ||
307 | |||
308 | status = acpi_ut_copy_iobject_to_iobject (source_desc, &new_desc, walk_state); | ||
309 | if (ACPI_FAILURE (status)) { | ||
310 | return_ACPI_STATUS (status); | ||
311 | } | ||
312 | |||
313 | if (obj_desc) { | ||
314 | /* Decrement reference count by the ref count of the parent package */ | ||
315 | |||
316 | for (i = 0; i < ((union acpi_operand_object *) index_desc->reference.object)->common.reference_count; i++) { | ||
317 | acpi_ut_remove_reference (obj_desc); | ||
318 | } | ||
319 | } | ||
320 | |||
321 | *(index_desc->reference.where) = new_desc; | ||
322 | |||
323 | /* Increment reference count by the ref count of the parent package -1 */ | ||
324 | |||
325 | for (i = 1; i < ((union acpi_operand_object *) index_desc->reference.object)->common.reference_count; i++) { | ||
326 | acpi_ut_add_reference (new_desc); | ||
327 | } | ||
328 | |||
329 | break; | ||
330 | |||
331 | |||
332 | case ACPI_TYPE_BUFFER_FIELD: | ||
333 | |||
334 | /* | ||
335 | * Store into a Buffer or String (not actually a real buffer_field) | ||
336 | * at a location defined by an Index. | ||
337 | * | ||
338 | * The first 8-bit element of the source object is written to the | ||
339 | * 8-bit Buffer location defined by the Index destination object, | ||
340 | * according to the ACPI 2.0 specification. | ||
341 | */ | ||
342 | |||
343 | /* | ||
344 | * Make sure the target is a Buffer or String. An error should | ||
345 | * not happen here, since the reference_object was constructed | ||
346 | * by the INDEX_OP code. | ||
347 | */ | ||
348 | obj_desc = index_desc->reference.object; | ||
349 | if ((ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_BUFFER) && | ||
350 | (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_STRING)) { | ||
351 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * The assignment of the individual elements will be slightly | ||
356 | * different for each source type. | ||
357 | */ | ||
358 | switch (ACPI_GET_OBJECT_TYPE (source_desc)) { | ||
359 | case ACPI_TYPE_INTEGER: | ||
360 | |||
361 | /* Use the least-significant byte of the integer */ | ||
362 | |||
363 | value = (u8) (source_desc->integer.value); | ||
364 | break; | ||
365 | |||
366 | case ACPI_TYPE_BUFFER: | ||
367 | case ACPI_TYPE_STRING: | ||
368 | |||
369 | /* Note: Takes advantage of common string/buffer fields */ | ||
370 | |||
371 | value = source_desc->buffer.pointer[0]; | ||
372 | break; | ||
373 | |||
374 | default: | ||
375 | |||
376 | /* All other types are invalid */ | ||
377 | |||
378 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
379 | "Source must be Integer/Buffer/String type, not %s\n", | ||
380 | acpi_ut_get_object_type_name (source_desc))); | ||
381 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); | ||
382 | } | ||
383 | |||
384 | /* Store the source value into the target buffer byte */ | ||
385 | |||
386 | obj_desc->buffer.pointer[index_desc->reference.offset] = value; | ||
387 | break; | ||
388 | |||
389 | |||
390 | default: | ||
391 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
392 | "Target is not a Package or buffer_field\n")); | ||
393 | status = AE_AML_OPERAND_TYPE; | ||
394 | break; | ||
395 | } | ||
396 | |||
397 | return_ACPI_STATUS (status); | ||
398 | } | ||
399 | |||
400 | |||
401 | /******************************************************************************* | ||
402 | * | ||
403 | * FUNCTION: acpi_ex_store_object_to_node | ||
404 | * | ||
405 | * PARAMETERS: source_desc - Value to be stored | ||
406 | * Node - Named object to receive the value | ||
407 | * walk_state - Current walk state | ||
408 | * implicit_conversion - Perform implicit conversion (yes/no) | ||
409 | * | ||
410 | * RETURN: Status | ||
411 | * | ||
412 | * DESCRIPTION: Store the object to the named object. | ||
413 | * | ||
414 | * The Assignment of an object to a named object is handled here | ||
415 | * The value passed in will replace the current value (if any) | ||
416 | * with the input value. | ||
417 | * | ||
418 | * When storing into an object the data is converted to the | ||
419 | * target object type then stored in the object. This means | ||
420 | * that the target object type (for an initialized target) will | ||
421 | * not be changed by a store operation. | ||
422 | * | ||
423 | * Assumes parameters are already validated. | ||
424 | * | ||
425 | ******************************************************************************/ | ||
426 | |||
427 | acpi_status | ||
428 | acpi_ex_store_object_to_node ( | ||
429 | union acpi_operand_object *source_desc, | ||
430 | struct acpi_namespace_node *node, | ||
431 | struct acpi_walk_state *walk_state, | ||
432 | u8 implicit_conversion) | ||
433 | { | ||
434 | acpi_status status = AE_OK; | ||
435 | union acpi_operand_object *target_desc; | ||
436 | union acpi_operand_object *new_desc; | ||
437 | acpi_object_type target_type; | ||
438 | |||
439 | |||
440 | ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_node", source_desc); | ||
441 | |||
442 | |||
443 | /* | ||
444 | * Get current type of the node, and object attached to Node | ||
445 | */ | ||
446 | target_type = acpi_ns_get_type (node); | ||
447 | target_desc = acpi_ns_get_attached_object (node); | ||
448 | |||
449 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", | ||
450 | source_desc, acpi_ut_get_object_type_name (source_desc), | ||
451 | node, acpi_ut_get_type_name (target_type))); | ||
452 | |||
453 | /* | ||
454 | * Resolve the source object to an actual value | ||
455 | * (If it is a reference object) | ||
456 | */ | ||
457 | status = acpi_ex_resolve_object (&source_desc, target_type, walk_state); | ||
458 | if (ACPI_FAILURE (status)) { | ||
459 | return_ACPI_STATUS (status); | ||
460 | } | ||
461 | |||
462 | /* If no implicit conversion, drop into the default case below */ | ||
463 | |||
464 | if (!implicit_conversion) { | ||
465 | /* Force execution of default (no implicit conversion) */ | ||
466 | |||
467 | target_type = ACPI_TYPE_ANY; | ||
468 | } | ||
469 | |||
470 | /* | ||
471 | * Do the actual store operation | ||
472 | */ | ||
473 | switch (target_type) { | ||
474 | case ACPI_TYPE_BUFFER_FIELD: | ||
475 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
476 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
477 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
478 | |||
479 | /* | ||
480 | * For fields, copy the source data to the target field. | ||
481 | */ | ||
482 | status = acpi_ex_write_data_to_field (source_desc, target_desc, &walk_state->result_obj); | ||
483 | break; | ||
484 | |||
485 | |||
486 | case ACPI_TYPE_INTEGER: | ||
487 | case ACPI_TYPE_STRING: | ||
488 | case ACPI_TYPE_BUFFER: | ||
489 | |||
490 | /* | ||
491 | * These target types are all of type Integer/String/Buffer, and | ||
492 | * therefore support implicit conversion before the store. | ||
493 | * | ||
494 | * Copy and/or convert the source object to a new target object | ||
495 | */ | ||
496 | status = acpi_ex_store_object_to_object (source_desc, target_desc, &new_desc, walk_state); | ||
497 | if (ACPI_FAILURE (status)) { | ||
498 | return_ACPI_STATUS (status); | ||
499 | } | ||
500 | |||
501 | if (new_desc != target_desc) { | ||
502 | /* | ||
503 | * Store the new new_desc as the new value of the Name, and set | ||
504 | * the Name's type to that of the value being stored in it. | ||
505 | * source_desc reference count is incremented by attach_object. | ||
506 | * | ||
507 | * Note: This may change the type of the node if an explicit store | ||
508 | * has been performed such that the node/object type has been | ||
509 | * changed. | ||
510 | */ | ||
511 | status = acpi_ns_attach_object (node, new_desc, new_desc->common.type); | ||
512 | |||
513 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, | ||
514 | "Store %s into %s via Convert/Attach\n", | ||
515 | acpi_ut_get_object_type_name (source_desc), | ||
516 | acpi_ut_get_object_type_name (new_desc))); | ||
517 | } | ||
518 | break; | ||
519 | |||
520 | |||
521 | default: | ||
522 | |||
523 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, | ||
524 | "Storing %s (%p) directly into node (%p), no implicit conversion\n", | ||
525 | acpi_ut_get_object_type_name (source_desc), source_desc, node)); | ||
526 | |||
527 | /* No conversions for all other types. Just attach the source object */ | ||
528 | |||
529 | status = acpi_ns_attach_object (node, source_desc, ACPI_GET_OBJECT_TYPE (source_desc)); | ||
530 | break; | ||
531 | } | ||
532 | |||
533 | return_ACPI_STATUS (status); | ||
534 | } | ||
535 | |||
536 | |||
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c new file mode 100644 index 000000000000..d3677feb07fd --- /dev/null +++ b/drivers/acpi/executer/exstoren.c | |||
@@ -0,0 +1,306 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exstoren - AML Interpreter object store support, | ||
5 | * Store to Node (namespace object) | ||
6 | * | ||
7 | *****************************************************************************/ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
11 | * All rights reserved. | ||
12 | * | ||
13 | * Redistribution and use in source and binary forms, with or without | ||
14 | * modification, are permitted provided that the following conditions | ||
15 | * are met: | ||
16 | * 1. Redistributions of source code must retain the above copyright | ||
17 | * notice, this list of conditions, and the following disclaimer, | ||
18 | * without modification. | ||
19 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
20 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
21 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
22 | * including a substantially similar Disclaimer requirement for further | ||
23 | * binary redistribution. | ||
24 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
25 | * of any contributors may be used to endorse or promote products derived | ||
26 | * from this software without specific prior written permission. | ||
27 | * | ||
28 | * Alternatively, this software may be distributed under the terms of the | ||
29 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
30 | * Software Foundation. | ||
31 | * | ||
32 | * NO WARRANTY | ||
33 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
34 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
35 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
36 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
37 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
38 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
39 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
40 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
41 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
42 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
43 | * POSSIBILITY OF SUCH DAMAGES. | ||
44 | */ | ||
45 | |||
46 | |||
47 | #include <acpi/acpi.h> | ||
48 | #include <acpi/acinterp.h> | ||
49 | #include <acpi/amlcode.h> | ||
50 | |||
51 | |||
52 | #define _COMPONENT ACPI_EXECUTER | ||
53 | ACPI_MODULE_NAME ("exstoren") | ||
54 | |||
55 | |||
56 | /******************************************************************************* | ||
57 | * | ||
58 | * FUNCTION: acpi_ex_resolve_object | ||
59 | * | ||
60 | * PARAMETERS: source_desc_ptr - Pointer to the source object | ||
61 | * target_type - Current type of the target | ||
62 | * walk_state - Current walk state | ||
63 | * | ||
64 | * RETURN: Status, resolved object in source_desc_ptr. | ||
65 | * | ||
66 | * DESCRIPTION: Resolve an object. If the object is a reference, dereference | ||
67 | * it and return the actual object in the source_desc_ptr. | ||
68 | * | ||
69 | ******************************************************************************/ | ||
70 | |||
71 | acpi_status | ||
72 | acpi_ex_resolve_object ( | ||
73 | union acpi_operand_object **source_desc_ptr, | ||
74 | acpi_object_type target_type, | ||
75 | struct acpi_walk_state *walk_state) | ||
76 | { | ||
77 | union acpi_operand_object *source_desc = *source_desc_ptr; | ||
78 | acpi_status status = AE_OK; | ||
79 | |||
80 | |||
81 | ACPI_FUNCTION_TRACE ("ex_resolve_object"); | ||
82 | |||
83 | |||
84 | /* | ||
85 | * Ensure we have a Target that can be stored to | ||
86 | */ | ||
87 | switch (target_type) { | ||
88 | case ACPI_TYPE_BUFFER_FIELD: | ||
89 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
90 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
91 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
92 | /* | ||
93 | * These cases all require only Integers or values that | ||
94 | * can be converted to Integers (Strings or Buffers) | ||
95 | */ | ||
96 | |||
97 | case ACPI_TYPE_INTEGER: | ||
98 | case ACPI_TYPE_STRING: | ||
99 | case ACPI_TYPE_BUFFER: | ||
100 | |||
101 | /* | ||
102 | * Stores into a Field/Region or into a Integer/Buffer/String | ||
103 | * are all essentially the same. This case handles the | ||
104 | * "interchangeable" types Integer, String, and Buffer. | ||
105 | */ | ||
106 | if (ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_LOCAL_REFERENCE) { | ||
107 | /* Resolve a reference object first */ | ||
108 | |||
109 | status = acpi_ex_resolve_to_value (source_desc_ptr, walk_state); | ||
110 | if (ACPI_FAILURE (status)) { | ||
111 | break; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* For copy_object, no further validation necessary */ | ||
116 | |||
117 | if (walk_state->opcode == AML_COPY_OP) { | ||
118 | break; | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Must have a Integer, Buffer, or String | ||
123 | */ | ||
124 | if ((ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) && | ||
125 | (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) && | ||
126 | (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING) && | ||
127 | !((ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_LOCAL_REFERENCE) && (source_desc->reference.opcode == AML_LOAD_OP))) { | ||
128 | /* | ||
129 | * Conversion successful but still not a valid type | ||
130 | */ | ||
131 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
132 | "Cannot assign type %s to %s (must be type Int/Str/Buf)\n", | ||
133 | acpi_ut_get_object_type_name (source_desc), | ||
134 | acpi_ut_get_type_name (target_type))); | ||
135 | status = AE_AML_OPERAND_TYPE; | ||
136 | } | ||
137 | break; | ||
138 | |||
139 | |||
140 | case ACPI_TYPE_LOCAL_ALIAS: | ||
141 | case ACPI_TYPE_LOCAL_METHOD_ALIAS: | ||
142 | |||
143 | /* | ||
144 | * Aliases are resolved by acpi_ex_prep_operands | ||
145 | */ | ||
146 | ACPI_REPORT_ERROR (("Store into Alias - should never happen\n")); | ||
147 | status = AE_AML_INTERNAL; | ||
148 | break; | ||
149 | |||
150 | |||
151 | case ACPI_TYPE_PACKAGE: | ||
152 | default: | ||
153 | |||
154 | /* | ||
155 | * All other types than Alias and the various Fields come here, | ||
156 | * including the untyped case - ACPI_TYPE_ANY. | ||
157 | */ | ||
158 | break; | ||
159 | } | ||
160 | |||
161 | return_ACPI_STATUS (status); | ||
162 | } | ||
163 | |||
164 | |||
165 | /******************************************************************************* | ||
166 | * | ||
167 | * FUNCTION: acpi_ex_store_object_to_object | ||
168 | * | ||
169 | * PARAMETERS: source_desc - Object to store | ||
170 | * dest_desc - Object to receive a copy of the source | ||
171 | * new_desc - New object if dest_desc is obsoleted | ||
172 | * walk_state - Current walk state | ||
173 | * | ||
174 | * RETURN: Status | ||
175 | * | ||
176 | * DESCRIPTION: "Store" an object to another object. This may include | ||
177 | * converting the source type to the target type (implicit | ||
178 | * conversion), and a copy of the value of the source to | ||
179 | * the target. | ||
180 | * | ||
181 | * The Assignment of an object to another (not named) object | ||
182 | * is handled here. | ||
183 | * The Source passed in will replace the current value (if any) | ||
184 | * with the input value. | ||
185 | * | ||
186 | * When storing into an object the data is converted to the | ||
187 | * target object type then stored in the object. This means | ||
188 | * that the target object type (for an initialized target) will | ||
189 | * not be changed by a store operation. | ||
190 | * | ||
191 | * This module allows destination types of Number, String, | ||
192 | * Buffer, and Package. | ||
193 | * | ||
194 | * Assumes parameters are already validated. NOTE: source_desc | ||
195 | * resolution (from a reference object) must be performed by | ||
196 | * the caller if necessary. | ||
197 | * | ||
198 | ******************************************************************************/ | ||
199 | |||
200 | acpi_status | ||
201 | acpi_ex_store_object_to_object ( | ||
202 | union acpi_operand_object *source_desc, | ||
203 | union acpi_operand_object *dest_desc, | ||
204 | union acpi_operand_object **new_desc, | ||
205 | struct acpi_walk_state *walk_state) | ||
206 | { | ||
207 | union acpi_operand_object *actual_src_desc; | ||
208 | acpi_status status = AE_OK; | ||
209 | |||
210 | |||
211 | ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_object", source_desc); | ||
212 | |||
213 | |||
214 | actual_src_desc = source_desc; | ||
215 | if (!dest_desc) { | ||
216 | /* | ||
217 | * There is no destination object (An uninitialized node or | ||
218 | * package element), so we can simply copy the source object | ||
219 | * creating a new destination object | ||
220 | */ | ||
221 | status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, new_desc, walk_state); | ||
222 | return_ACPI_STATUS (status); | ||
223 | } | ||
224 | |||
225 | if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_GET_OBJECT_TYPE (dest_desc)) { | ||
226 | /* | ||
227 | * The source type does not match the type of the destination. | ||
228 | * Perform the "implicit conversion" of the source to the current type | ||
229 | * of the target as per the ACPI specification. | ||
230 | * | ||
231 | * If no conversion performed, actual_src_desc = source_desc. | ||
232 | * Otherwise, actual_src_desc is a temporary object to hold the | ||
233 | * converted object. | ||
234 | */ | ||
235 | status = acpi_ex_convert_to_target_type (ACPI_GET_OBJECT_TYPE (dest_desc), | ||
236 | source_desc, &actual_src_desc, walk_state); | ||
237 | if (ACPI_FAILURE (status)) { | ||
238 | return_ACPI_STATUS (status); | ||
239 | } | ||
240 | |||
241 | if (source_desc == actual_src_desc) { | ||
242 | /* | ||
243 | * No conversion was performed. Return the source_desc as the | ||
244 | * new object. | ||
245 | */ | ||
246 | *new_desc = source_desc; | ||
247 | return_ACPI_STATUS (AE_OK); | ||
248 | } | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * We now have two objects of identical types, and we can perform a | ||
253 | * copy of the *value* of the source object. | ||
254 | */ | ||
255 | switch (ACPI_GET_OBJECT_TYPE (dest_desc)) { | ||
256 | case ACPI_TYPE_INTEGER: | ||
257 | |||
258 | dest_desc->integer.value = actual_src_desc->integer.value; | ||
259 | |||
260 | /* Truncate value if we are executing from a 32-bit ACPI table */ | ||
261 | |||
262 | acpi_ex_truncate_for32bit_table (dest_desc); | ||
263 | break; | ||
264 | |||
265 | case ACPI_TYPE_STRING: | ||
266 | |||
267 | status = acpi_ex_store_string_to_string (actual_src_desc, dest_desc); | ||
268 | break; | ||
269 | |||
270 | case ACPI_TYPE_BUFFER: | ||
271 | |||
272 | /* | ||
273 | * Note: There is different store behavior depending on the original | ||
274 | * source type | ||
275 | */ | ||
276 | status = acpi_ex_store_buffer_to_buffer (actual_src_desc, dest_desc); | ||
277 | break; | ||
278 | |||
279 | case ACPI_TYPE_PACKAGE: | ||
280 | |||
281 | status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, &dest_desc, | ||
282 | walk_state); | ||
283 | break; | ||
284 | |||
285 | default: | ||
286 | /* | ||
287 | * All other types come here. | ||
288 | */ | ||
289 | ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Store into type %s not implemented\n", | ||
290 | acpi_ut_get_object_type_name (dest_desc))); | ||
291 | |||
292 | status = AE_NOT_IMPLEMENTED; | ||
293 | break; | ||
294 | } | ||
295 | |||
296 | if (actual_src_desc != source_desc) { | ||
297 | /* Delete the intermediate (temporary) source object */ | ||
298 | |||
299 | acpi_ut_remove_reference (actual_src_desc); | ||
300 | } | ||
301 | |||
302 | *new_desc = dest_desc; | ||
303 | return_ACPI_STATUS (status); | ||
304 | } | ||
305 | |||
306 | |||
diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c new file mode 100644 index 000000000000..05e1ecae8d92 --- /dev/null +++ b/drivers/acpi/executer/exstorob.c | |||
@@ -0,0 +1,216 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exstorob - AML Interpreter object store support, store to object | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acinterp.h> | ||
48 | |||
49 | |||
50 | #define _COMPONENT ACPI_EXECUTER | ||
51 | ACPI_MODULE_NAME ("exstorob") | ||
52 | |||
53 | |||
54 | /******************************************************************************* | ||
55 | * | ||
56 | * FUNCTION: acpi_ex_store_buffer_to_buffer | ||
57 | * | ||
58 | * PARAMETERS: source_desc - Source object to copy | ||
59 | * target_desc - Destination object of the copy | ||
60 | * | ||
61 | * RETURN: Status | ||
62 | * | ||
63 | * DESCRIPTION: Copy a buffer object to another buffer object. | ||
64 | * | ||
65 | ******************************************************************************/ | ||
66 | |||
67 | acpi_status | ||
68 | acpi_ex_store_buffer_to_buffer ( | ||
69 | union acpi_operand_object *source_desc, | ||
70 | union acpi_operand_object *target_desc) | ||
71 | { | ||
72 | u32 length; | ||
73 | u8 *buffer; | ||
74 | |||
75 | |||
76 | ACPI_FUNCTION_TRACE_PTR ("ex_store_buffer_to_buffer", source_desc); | ||
77 | |||
78 | |||
79 | /* We know that source_desc is a buffer by now */ | ||
80 | |||
81 | buffer = (u8 *) source_desc->buffer.pointer; | ||
82 | length = source_desc->buffer.length; | ||
83 | |||
84 | /* | ||
85 | * If target is a buffer of length zero or is a static buffer, | ||
86 | * allocate a new buffer of the proper length | ||
87 | */ | ||
88 | if ((target_desc->buffer.length == 0) || | ||
89 | (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) { | ||
90 | target_desc->buffer.pointer = ACPI_MEM_ALLOCATE (length); | ||
91 | if (!target_desc->buffer.pointer) { | ||
92 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
93 | } | ||
94 | |||
95 | target_desc->buffer.length = length; | ||
96 | } | ||
97 | |||
98 | /* Copy source buffer to target buffer */ | ||
99 | |||
100 | if (length <= target_desc->buffer.length) { | ||
101 | /* Clear existing buffer and copy in the new one */ | ||
102 | |||
103 | ACPI_MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length); | ||
104 | ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length); | ||
105 | |||
106 | #ifdef ACPI_OBSOLETE_BEHAVIOR | ||
107 | /* | ||
108 | * NOTE: ACPI versions up to 3.0 specified that the buffer must be | ||
109 | * truncated if the string is smaller than the buffer. However, "other" | ||
110 | * implementations of ACPI never did this and thus became the defacto | ||
111 | * standard. ACPi 3.0_a changes this behavior such that the buffer | ||
112 | * is no longer truncated. | ||
113 | */ | ||
114 | |||
115 | /* | ||
116 | * OBSOLETE BEHAVIOR: | ||
117 | * If the original source was a string, we must truncate the buffer, | ||
118 | * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer | ||
119 | * copy must not truncate the original buffer. | ||
120 | */ | ||
121 | if (original_src_type == ACPI_TYPE_STRING) { | ||
122 | /* Set the new length of the target */ | ||
123 | |||
124 | target_desc->buffer.length = length; | ||
125 | } | ||
126 | #endif | ||
127 | } | ||
128 | else { | ||
129 | /* Truncate the source, copy only what will fit */ | ||
130 | |||
131 | ACPI_MEMCPY (target_desc->buffer.pointer, buffer, target_desc->buffer.length); | ||
132 | |||
133 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
134 | "Truncating source buffer from %X to %X\n", | ||
135 | length, target_desc->buffer.length)); | ||
136 | } | ||
137 | |||
138 | /* Copy flags */ | ||
139 | |||
140 | target_desc->buffer.flags = source_desc->buffer.flags; | ||
141 | target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; | ||
142 | return_ACPI_STATUS (AE_OK); | ||
143 | } | ||
144 | |||
145 | |||
146 | /******************************************************************************* | ||
147 | * | ||
148 | * FUNCTION: acpi_ex_store_string_to_string | ||
149 | * | ||
150 | * PARAMETERS: source_desc - Source object to copy | ||
151 | * target_desc - Destination object of the copy | ||
152 | * | ||
153 | * RETURN: Status | ||
154 | * | ||
155 | * DESCRIPTION: Copy a String object to another String object | ||
156 | * | ||
157 | ******************************************************************************/ | ||
158 | |||
159 | acpi_status | ||
160 | acpi_ex_store_string_to_string ( | ||
161 | union acpi_operand_object *source_desc, | ||
162 | union acpi_operand_object *target_desc) | ||
163 | { | ||
164 | u32 length; | ||
165 | u8 *buffer; | ||
166 | |||
167 | |||
168 | ACPI_FUNCTION_TRACE_PTR ("ex_store_string_to_string", source_desc); | ||
169 | |||
170 | |||
171 | /* We know that source_desc is a string by now */ | ||
172 | |||
173 | buffer = (u8 *) source_desc->string.pointer; | ||
174 | length = source_desc->string.length; | ||
175 | |||
176 | /* | ||
177 | * Replace existing string value if it will fit and the string | ||
178 | * pointer is not a static pointer (part of an ACPI table) | ||
179 | */ | ||
180 | if ((length < target_desc->string.length) && | ||
181 | (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) { | ||
182 | /* | ||
183 | * String will fit in existing non-static buffer. | ||
184 | * Clear old string and copy in the new one | ||
185 | */ | ||
186 | ACPI_MEMSET (target_desc->string.pointer, 0, (acpi_size) target_desc->string.length + 1); | ||
187 | ACPI_MEMCPY (target_desc->string.pointer, buffer, length); | ||
188 | } | ||
189 | else { | ||
190 | /* | ||
191 | * Free the current buffer, then allocate a new buffer | ||
192 | * large enough to hold the value | ||
193 | */ | ||
194 | if (target_desc->string.pointer && | ||
195 | (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) { | ||
196 | /* Only free if not a pointer into the DSDT */ | ||
197 | |||
198 | ACPI_MEM_FREE (target_desc->string.pointer); | ||
199 | } | ||
200 | |||
201 | target_desc->string.pointer = ACPI_MEM_CALLOCATE ((acpi_size) length + 1); | ||
202 | if (!target_desc->string.pointer) { | ||
203 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
204 | } | ||
205 | |||
206 | target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; | ||
207 | ACPI_MEMCPY (target_desc->string.pointer, buffer, length); | ||
208 | } | ||
209 | |||
210 | /* Set the new target length */ | ||
211 | |||
212 | target_desc->string.length = length; | ||
213 | return_ACPI_STATUS (AE_OK); | ||
214 | } | ||
215 | |||
216 | |||
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c new file mode 100644 index 000000000000..f92efc512890 --- /dev/null +++ b/drivers/acpi/executer/exsystem.c | |||
@@ -0,0 +1,378 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exsystem - Interface to OS services | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acinterp.h> | ||
48 | #include <acpi/acevents.h> | ||
49 | |||
50 | #define _COMPONENT ACPI_EXECUTER | ||
51 | ACPI_MODULE_NAME ("exsystem") | ||
52 | |||
53 | |||
54 | /******************************************************************************* | ||
55 | * | ||
56 | * FUNCTION: acpi_ex_system_wait_semaphore | ||
57 | * | ||
58 | * PARAMETERS: Semaphore - OSD semaphore to wait on | ||
59 | * Timeout - Max time to wait | ||
60 | * | ||
61 | * RETURN: Status | ||
62 | * | ||
63 | * DESCRIPTION: Implements a semaphore wait with a check to see if the | ||
64 | * semaphore is available immediately. If it is not, the | ||
65 | * interpreter is released. | ||
66 | * | ||
67 | ******************************************************************************/ | ||
68 | |||
69 | acpi_status | ||
70 | acpi_ex_system_wait_semaphore ( | ||
71 | acpi_handle semaphore, | ||
72 | u16 timeout) | ||
73 | { | ||
74 | acpi_status status; | ||
75 | acpi_status status2; | ||
76 | |||
77 | |||
78 | ACPI_FUNCTION_TRACE ("ex_system_wait_semaphore"); | ||
79 | |||
80 | |||
81 | status = acpi_os_wait_semaphore (semaphore, 1, 0); | ||
82 | if (ACPI_SUCCESS (status)) { | ||
83 | return_ACPI_STATUS (status); | ||
84 | } | ||
85 | |||
86 | if (status == AE_TIME) { | ||
87 | /* We must wait, so unlock the interpreter */ | ||
88 | |||
89 | acpi_ex_exit_interpreter (); | ||
90 | |||
91 | status = acpi_os_wait_semaphore (semaphore, 1, timeout); | ||
92 | |||
93 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*** Thread awake after blocking, %s\n", | ||
94 | acpi_format_exception (status))); | ||
95 | |||
96 | /* Reacquire the interpreter */ | ||
97 | |||
98 | status2 = acpi_ex_enter_interpreter (); | ||
99 | if (ACPI_FAILURE (status2)) { | ||
100 | /* Report fatal error, could not acquire interpreter */ | ||
101 | |||
102 | return_ACPI_STATUS (status2); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | return_ACPI_STATUS (status); | ||
107 | } | ||
108 | |||
109 | |||
110 | /******************************************************************************* | ||
111 | * | ||
112 | * FUNCTION: acpi_ex_system_do_stall | ||
113 | * | ||
114 | * PARAMETERS: how_long - The amount of time to stall, | ||
115 | * in microseconds | ||
116 | * | ||
117 | * RETURN: Status | ||
118 | * | ||
119 | * DESCRIPTION: Suspend running thread for specified amount of time. | ||
120 | * Note: ACPI specification requires that Stall() does not | ||
121 | * relinquish the processor, and delays longer than 100 usec | ||
122 | * should use Sleep() instead. We allow stalls up to 255 usec | ||
123 | * for compatibility with other interpreters and existing BIOSs. | ||
124 | * | ||
125 | ******************************************************************************/ | ||
126 | |||
127 | acpi_status | ||
128 | acpi_ex_system_do_stall ( | ||
129 | u32 how_long) | ||
130 | { | ||
131 | acpi_status status = AE_OK; | ||
132 | |||
133 | |||
134 | ACPI_FUNCTION_ENTRY (); | ||
135 | |||
136 | |||
137 | if (how_long > 255) /* 255 microseconds */ { | ||
138 | /* | ||
139 | * Longer than 255 usec, this is an error | ||
140 | * | ||
141 | * (ACPI specifies 100 usec as max, but this gives some slack in | ||
142 | * order to support existing BIOSs) | ||
143 | */ | ||
144 | ACPI_REPORT_ERROR (("Stall: Time parameter is too large (%d)\n", how_long)); | ||
145 | status = AE_AML_OPERAND_VALUE; | ||
146 | } | ||
147 | else { | ||
148 | acpi_os_stall (how_long); | ||
149 | } | ||
150 | |||
151 | return (status); | ||
152 | } | ||
153 | |||
154 | |||
155 | /******************************************************************************* | ||
156 | * | ||
157 | * FUNCTION: acpi_ex_system_do_suspend | ||
158 | * | ||
159 | * PARAMETERS: how_long - The amount of time to suspend, | ||
160 | * in milliseconds | ||
161 | * | ||
162 | * RETURN: None | ||
163 | * | ||
164 | * DESCRIPTION: Suspend running thread for specified amount of time. | ||
165 | * | ||
166 | ******************************************************************************/ | ||
167 | |||
168 | acpi_status | ||
169 | acpi_ex_system_do_suspend ( | ||
170 | acpi_integer how_long) | ||
171 | { | ||
172 | acpi_status status; | ||
173 | |||
174 | |||
175 | ACPI_FUNCTION_ENTRY (); | ||
176 | |||
177 | |||
178 | /* Since this thread will sleep, we must release the interpreter */ | ||
179 | |||
180 | acpi_ex_exit_interpreter (); | ||
181 | |||
182 | acpi_os_sleep (how_long); | ||
183 | |||
184 | /* And now we must get the interpreter again */ | ||
185 | |||
186 | status = acpi_ex_enter_interpreter (); | ||
187 | return (status); | ||
188 | } | ||
189 | |||
190 | |||
191 | /******************************************************************************* | ||
192 | * | ||
193 | * FUNCTION: acpi_ex_system_acquire_mutex | ||
194 | * | ||
195 | * PARAMETERS: *time_desc - The 'time to delay' object descriptor | ||
196 | * *obj_desc - The object descriptor for this op | ||
197 | * | ||
198 | * RETURN: Status | ||
199 | * | ||
200 | * DESCRIPTION: Provides an access point to perform synchronization operations | ||
201 | * within the AML. This function will cause a lock to be generated | ||
202 | * for the Mutex pointed to by obj_desc. | ||
203 | * | ||
204 | ******************************************************************************/ | ||
205 | |||
206 | acpi_status | ||
207 | acpi_ex_system_acquire_mutex ( | ||
208 | union acpi_operand_object *time_desc, | ||
209 | union acpi_operand_object *obj_desc) | ||
210 | { | ||
211 | acpi_status status = AE_OK; | ||
212 | |||
213 | |||
214 | ACPI_FUNCTION_TRACE_PTR ("ex_system_acquire_mutex", obj_desc); | ||
215 | |||
216 | |||
217 | if (!obj_desc) { | ||
218 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Support for the _GL_ Mutex object -- go get the global lock | ||
223 | */ | ||
224 | if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { | ||
225 | status = acpi_ev_acquire_global_lock ((u16) time_desc->integer.value); | ||
226 | return_ACPI_STATUS (status); | ||
227 | } | ||
228 | |||
229 | status = acpi_ex_system_wait_semaphore (obj_desc->mutex.semaphore, | ||
230 | (u16) time_desc->integer.value); | ||
231 | return_ACPI_STATUS (status); | ||
232 | } | ||
233 | |||
234 | |||
235 | /******************************************************************************* | ||
236 | * | ||
237 | * FUNCTION: acpi_ex_system_release_mutex | ||
238 | * | ||
239 | * PARAMETERS: *obj_desc - The object descriptor for this op | ||
240 | * | ||
241 | * RETURN: Status | ||
242 | * | ||
243 | * DESCRIPTION: Provides an access point to perform synchronization operations | ||
244 | * within the AML. This operation is a request to release a | ||
245 | * previously acquired Mutex. If the Mutex variable is set then | ||
246 | * it will be decremented. | ||
247 | * | ||
248 | ******************************************************************************/ | ||
249 | |||
250 | acpi_status | ||
251 | acpi_ex_system_release_mutex ( | ||
252 | union acpi_operand_object *obj_desc) | ||
253 | { | ||
254 | acpi_status status = AE_OK; | ||
255 | |||
256 | |||
257 | ACPI_FUNCTION_TRACE ("ex_system_release_mutex"); | ||
258 | |||
259 | |||
260 | if (!obj_desc) { | ||
261 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * Support for the _GL_ Mutex object -- release the global lock | ||
266 | */ | ||
267 | if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { | ||
268 | status = acpi_ev_release_global_lock (); | ||
269 | return_ACPI_STATUS (status); | ||
270 | } | ||
271 | |||
272 | status = acpi_os_signal_semaphore (obj_desc->mutex.semaphore, 1); | ||
273 | return_ACPI_STATUS (status); | ||
274 | } | ||
275 | |||
276 | |||
277 | /******************************************************************************* | ||
278 | * | ||
279 | * FUNCTION: acpi_ex_system_signal_event | ||
280 | * | ||
281 | * PARAMETERS: *obj_desc - The object descriptor for this op | ||
282 | * | ||
283 | * RETURN: AE_OK | ||
284 | * | ||
285 | * DESCRIPTION: Provides an access point to perform synchronization operations | ||
286 | * within the AML. | ||
287 | * | ||
288 | ******************************************************************************/ | ||
289 | |||
290 | acpi_status | ||
291 | acpi_ex_system_signal_event ( | ||
292 | union acpi_operand_object *obj_desc) | ||
293 | { | ||
294 | acpi_status status = AE_OK; | ||
295 | |||
296 | |||
297 | ACPI_FUNCTION_TRACE ("ex_system_signal_event"); | ||
298 | |||
299 | |||
300 | if (obj_desc) { | ||
301 | status = acpi_os_signal_semaphore (obj_desc->event.semaphore, 1); | ||
302 | } | ||
303 | |||
304 | return_ACPI_STATUS (status); | ||
305 | } | ||
306 | |||
307 | |||
308 | /******************************************************************************* | ||
309 | * | ||
310 | * FUNCTION: acpi_ex_system_wait_event | ||
311 | * | ||
312 | * PARAMETERS: *time_desc - The 'time to delay' object descriptor | ||
313 | * *obj_desc - The object descriptor for this op | ||
314 | * | ||
315 | * RETURN: Status | ||
316 | * | ||
317 | * DESCRIPTION: Provides an access point to perform synchronization operations | ||
318 | * within the AML. This operation is a request to wait for an | ||
319 | * event. | ||
320 | * | ||
321 | ******************************************************************************/ | ||
322 | |||
323 | acpi_status | ||
324 | acpi_ex_system_wait_event ( | ||
325 | union acpi_operand_object *time_desc, | ||
326 | union acpi_operand_object *obj_desc) | ||
327 | { | ||
328 | acpi_status status = AE_OK; | ||
329 | |||
330 | |||
331 | ACPI_FUNCTION_TRACE ("ex_system_wait_event"); | ||
332 | |||
333 | |||
334 | if (obj_desc) { | ||
335 | status = acpi_ex_system_wait_semaphore (obj_desc->event.semaphore, | ||
336 | (u16) time_desc->integer.value); | ||
337 | } | ||
338 | |||
339 | return_ACPI_STATUS (status); | ||
340 | } | ||
341 | |||
342 | |||
343 | /******************************************************************************* | ||
344 | * | ||
345 | * FUNCTION: acpi_ex_system_reset_event | ||
346 | * | ||
347 | * PARAMETERS: *obj_desc - The object descriptor for this op | ||
348 | * | ||
349 | * RETURN: Status | ||
350 | * | ||
351 | * DESCRIPTION: Reset an event to a known state. | ||
352 | * | ||
353 | ******************************************************************************/ | ||
354 | |||
355 | acpi_status | ||
356 | acpi_ex_system_reset_event ( | ||
357 | union acpi_operand_object *obj_desc) | ||
358 | { | ||
359 | acpi_status status = AE_OK; | ||
360 | void *temp_semaphore; | ||
361 | |||
362 | |||
363 | ACPI_FUNCTION_ENTRY (); | ||
364 | |||
365 | |||
366 | /* | ||
367 | * We are going to simply delete the existing semaphore and | ||
368 | * create a new one! | ||
369 | */ | ||
370 | status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore); | ||
371 | if (ACPI_SUCCESS (status)) { | ||
372 | (void) acpi_os_delete_semaphore (obj_desc->event.semaphore); | ||
373 | obj_desc->event.semaphore = temp_semaphore; | ||
374 | } | ||
375 | |||
376 | return (status); | ||
377 | } | ||
378 | |||
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c new file mode 100644 index 000000000000..40c6abb8b49a --- /dev/null +++ b/drivers/acpi/executer/exutils.c | |||
@@ -0,0 +1,378 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: exutils - interpreter/scanner utilities | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | |||
46 | /* | ||
47 | * DEFINE_AML_GLOBALS is tested in amlcode.h | ||
48 | * to determine whether certain global names should be "defined" or only | ||
49 | * "declared" in the current compilation. This enhances maintainability | ||
50 | * by enabling a single header file to embody all knowledge of the names | ||
51 | * in question. | ||
52 | * | ||
53 | * Exactly one module of any executable should #define DEFINE_GLOBALS | ||
54 | * before #including the header files which use this convention. The | ||
55 | * names in question will be defined and initialized in that module, | ||
56 | * and declared as extern in all other modules which #include those | ||
57 | * header files. | ||
58 | */ | ||
59 | |||
60 | #define DEFINE_AML_GLOBALS | ||
61 | |||
62 | #include <acpi/acpi.h> | ||
63 | #include <acpi/acinterp.h> | ||
64 | #include <acpi/amlcode.h> | ||
65 | #include <acpi/acevents.h> | ||
66 | |||
67 | #define _COMPONENT ACPI_EXECUTER | ||
68 | ACPI_MODULE_NAME ("exutils") | ||
69 | |||
70 | |||
71 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
72 | |||
73 | /******************************************************************************* | ||
74 | * | ||
75 | * FUNCTION: acpi_ex_enter_interpreter | ||
76 | * | ||
77 | * PARAMETERS: None | ||
78 | * | ||
79 | * DESCRIPTION: Enter the interpreter execution region. Failure to enter | ||
80 | * the interpreter region is a fatal system error | ||
81 | * | ||
82 | ******************************************************************************/ | ||
83 | |||
84 | acpi_status | ||
85 | acpi_ex_enter_interpreter (void) | ||
86 | { | ||
87 | acpi_status status; | ||
88 | |||
89 | ACPI_FUNCTION_TRACE ("ex_enter_interpreter"); | ||
90 | |||
91 | |||
92 | status = acpi_ut_acquire_mutex (ACPI_MTX_EXECUTE); | ||
93 | if (ACPI_FAILURE (status)) { | ||
94 | ACPI_REPORT_ERROR (("Could not acquire interpreter mutex\n")); | ||
95 | } | ||
96 | |||
97 | return_ACPI_STATUS (status); | ||
98 | } | ||
99 | |||
100 | |||
101 | /******************************************************************************* | ||
102 | * | ||
103 | * FUNCTION: acpi_ex_exit_interpreter | ||
104 | * | ||
105 | * PARAMETERS: None | ||
106 | * | ||
107 | * DESCRIPTION: Exit the interpreter execution region | ||
108 | * | ||
109 | * Cases where the interpreter is unlocked: | ||
110 | * 1) Completion of the execution of a control method | ||
111 | * 2) Method blocked on a Sleep() AML opcode | ||
112 | * 3) Method blocked on an Acquire() AML opcode | ||
113 | * 4) Method blocked on a Wait() AML opcode | ||
114 | * 5) Method blocked to acquire the global lock | ||
115 | * 6) Method blocked to execute a serialized control method that is | ||
116 | * already executing | ||
117 | * 7) About to invoke a user-installed opregion handler | ||
118 | * | ||
119 | ******************************************************************************/ | ||
120 | |||
121 | void | ||
122 | acpi_ex_exit_interpreter (void) | ||
123 | { | ||
124 | acpi_status status; | ||
125 | |||
126 | |||
127 | ACPI_FUNCTION_TRACE ("ex_exit_interpreter"); | ||
128 | |||
129 | |||
130 | status = acpi_ut_release_mutex (ACPI_MTX_EXECUTE); | ||
131 | if (ACPI_FAILURE (status)) { | ||
132 | ACPI_REPORT_ERROR (("Could not release interpreter mutex\n")); | ||
133 | } | ||
134 | |||
135 | return_VOID; | ||
136 | } | ||
137 | |||
138 | |||
139 | /******************************************************************************* | ||
140 | * | ||
141 | * FUNCTION: acpi_ex_truncate_for32bit_table | ||
142 | * | ||
143 | * PARAMETERS: obj_desc - Object to be truncated | ||
144 | * | ||
145 | * RETURN: none | ||
146 | * | ||
147 | * DESCRIPTION: Truncate a number to 32-bits if the currently executing method | ||
148 | * belongs to a 32-bit ACPI table. | ||
149 | * | ||
150 | ******************************************************************************/ | ||
151 | |||
152 | void | ||
153 | acpi_ex_truncate_for32bit_table ( | ||
154 | union acpi_operand_object *obj_desc) | ||
155 | { | ||
156 | |||
157 | ACPI_FUNCTION_ENTRY (); | ||
158 | |||
159 | |||
160 | /* | ||
161 | * Object must be a valid number and we must be executing | ||
162 | * a control method | ||
163 | */ | ||
164 | if ((!obj_desc) || | ||
165 | (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER)) { | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | if (acpi_gbl_integer_byte_width == 4) { | ||
170 | /* | ||
171 | * We are running a method that exists in a 32-bit ACPI table. | ||
172 | * Truncate the value to 32 bits by zeroing out the upper 32-bit field | ||
173 | */ | ||
174 | obj_desc->integer.value &= (acpi_integer) ACPI_UINT32_MAX; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | |||
179 | /******************************************************************************* | ||
180 | * | ||
181 | * FUNCTION: acpi_ex_acquire_global_lock | ||
182 | * | ||
183 | * PARAMETERS: field_flags - Flags with Lock rule: | ||
184 | * always_lock or never_lock | ||
185 | * | ||
186 | * RETURN: TRUE/FALSE indicating whether the lock was actually acquired | ||
187 | * | ||
188 | * DESCRIPTION: Obtain the global lock and keep track of this fact via two | ||
189 | * methods. A global variable keeps the state of the lock, and | ||
190 | * the state is returned to the caller. | ||
191 | * | ||
192 | ******************************************************************************/ | ||
193 | |||
194 | u8 | ||
195 | acpi_ex_acquire_global_lock ( | ||
196 | u32 field_flags) | ||
197 | { | ||
198 | u8 locked = FALSE; | ||
199 | acpi_status status; | ||
200 | |||
201 | |||
202 | ACPI_FUNCTION_TRACE ("ex_acquire_global_lock"); | ||
203 | |||
204 | |||
205 | /* Only attempt lock if the always_lock bit is set */ | ||
206 | |||
207 | if (field_flags & AML_FIELD_LOCK_RULE_MASK) { | ||
208 | /* We should attempt to get the lock, wait forever */ | ||
209 | |||
210 | status = acpi_ev_acquire_global_lock (ACPI_WAIT_FOREVER); | ||
211 | if (ACPI_SUCCESS (status)) { | ||
212 | locked = TRUE; | ||
213 | } | ||
214 | else { | ||
215 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not acquire Global Lock, %s\n", | ||
216 | acpi_format_exception (status))); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | return_VALUE (locked); | ||
221 | } | ||
222 | |||
223 | |||
224 | /******************************************************************************* | ||
225 | * | ||
226 | * FUNCTION: acpi_ex_release_global_lock | ||
227 | * | ||
228 | * PARAMETERS: locked_by_me - Return value from corresponding call to | ||
229 | * acquire_global_lock. | ||
230 | * | ||
231 | * RETURN: Status | ||
232 | * | ||
233 | * DESCRIPTION: Release the global lock if it is locked. | ||
234 | * | ||
235 | ******************************************************************************/ | ||
236 | |||
237 | void | ||
238 | acpi_ex_release_global_lock ( | ||
239 | u8 locked_by_me) | ||
240 | { | ||
241 | acpi_status status; | ||
242 | |||
243 | |||
244 | ACPI_FUNCTION_TRACE ("ex_release_global_lock"); | ||
245 | |||
246 | |||
247 | /* Only attempt unlock if the caller locked it */ | ||
248 | |||
249 | if (locked_by_me) { | ||
250 | /* OK, now release the lock */ | ||
251 | |||
252 | status = acpi_ev_release_global_lock (); | ||
253 | if (ACPI_FAILURE (status)) { | ||
254 | /* Report the error, but there isn't much else we can do */ | ||
255 | |||
256 | ACPI_REPORT_ERROR (("Could not release ACPI Global Lock, %s\n", | ||
257 | acpi_format_exception (status))); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | return_VOID; | ||
262 | } | ||
263 | |||
264 | |||
265 | /******************************************************************************* | ||
266 | * | ||
267 | * FUNCTION: acpi_ex_digits_needed | ||
268 | * | ||
269 | * PARAMETERS: Value - Value to be represented | ||
270 | * Base - Base of representation | ||
271 | * | ||
272 | * RETURN: the number of digits needed to represent Value in Base | ||
273 | * | ||
274 | ******************************************************************************/ | ||
275 | |||
276 | u32 | ||
277 | acpi_ex_digits_needed ( | ||
278 | acpi_integer value, | ||
279 | u32 base) | ||
280 | { | ||
281 | u32 num_digits; | ||
282 | acpi_integer current_value; | ||
283 | |||
284 | |||
285 | ACPI_FUNCTION_TRACE ("ex_digits_needed"); | ||
286 | |||
287 | |||
288 | /* acpi_integer is unsigned, so we don't worry about a '-' prefix */ | ||
289 | |||
290 | if (value == 0) { | ||
291 | return_VALUE (1); | ||
292 | } | ||
293 | |||
294 | current_value = value; | ||
295 | num_digits = 0; | ||
296 | |||
297 | /* Count the digits in the requested base */ | ||
298 | |||
299 | while (current_value) { | ||
300 | (void) acpi_ut_short_divide (current_value, base, ¤t_value, NULL); | ||
301 | num_digits++; | ||
302 | } | ||
303 | |||
304 | return_VALUE (num_digits); | ||
305 | } | ||
306 | |||
307 | |||
308 | /******************************************************************************* | ||
309 | * | ||
310 | * FUNCTION: acpi_ex_eisa_id_to_string | ||
311 | * | ||
312 | * PARAMETERS: numeric_id - EISA ID to be converted | ||
313 | * out_string - Where to put the converted string (8 bytes) | ||
314 | * | ||
315 | * DESCRIPTION: Convert a numeric EISA ID to string representation | ||
316 | * | ||
317 | ******************************************************************************/ | ||
318 | |||
319 | void | ||
320 | acpi_ex_eisa_id_to_string ( | ||
321 | u32 numeric_id, | ||
322 | char *out_string) | ||
323 | { | ||
324 | u32 eisa_id; | ||
325 | |||
326 | |||
327 | ACPI_FUNCTION_ENTRY (); | ||
328 | |||
329 | |||
330 | /* Swap ID to big-endian to get contiguous bits */ | ||
331 | |||
332 | eisa_id = acpi_ut_dword_byte_swap (numeric_id); | ||
333 | |||
334 | out_string[0] = (char) ('@' + (((unsigned long) eisa_id >> 26) & 0x1f)); | ||
335 | out_string[1] = (char) ('@' + ((eisa_id >> 21) & 0x1f)); | ||
336 | out_string[2] = (char) ('@' + ((eisa_id >> 16) & 0x1f)); | ||
337 | out_string[3] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 12); | ||
338 | out_string[4] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 8); | ||
339 | out_string[5] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 4); | ||
340 | out_string[6] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 0); | ||
341 | out_string[7] = 0; | ||
342 | } | ||
343 | |||
344 | |||
345 | /******************************************************************************* | ||
346 | * | ||
347 | * FUNCTION: acpi_ex_unsigned_integer_to_string | ||
348 | * | ||
349 | * PARAMETERS: Value - Value to be converted | ||
350 | * out_string - Where to put the converted string (8 bytes) | ||
351 | * | ||
352 | * RETURN: Convert a number to string representation | ||
353 | * | ||
354 | ******************************************************************************/ | ||
355 | |||
356 | void | ||
357 | acpi_ex_unsigned_integer_to_string ( | ||
358 | acpi_integer value, | ||
359 | char *out_string) | ||
360 | { | ||
361 | u32 count; | ||
362 | u32 digits_needed; | ||
363 | u32 remainder; | ||
364 | |||
365 | |||
366 | ACPI_FUNCTION_ENTRY (); | ||
367 | |||
368 | |||
369 | digits_needed = acpi_ex_digits_needed (value, 10); | ||
370 | out_string[digits_needed] = 0; | ||
371 | |||
372 | for (count = digits_needed; count > 0; count--) { | ||
373 | (void) acpi_ut_short_divide (value, 10, &value, &remainder); | ||
374 | out_string[count-1] = (char) ('0' + remainder);\ | ||
375 | } | ||
376 | } | ||
377 | |||
378 | #endif | ||