2 /******************************************************************************
4 * Module Name: amutils - interpreter/scanner utilities
7 *****************************************************************************/
10 * Copyright (C) 2000 R. Byron Moore
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 #define _COMPONENT INTERPRETER
36 MODULE_NAME ("amutils")
39 typedef struct internal_search_st
41 ACPI_OPERAND_OBJECT
*dest_obj
;
43 ACPI_OPERAND_OBJECT
*source_obj
;
45 } INTERNAL_PKG_SEARCH_INFO
;
48 /* Used to traverse nested packages when copying*/
50 INTERNAL_PKG_SEARCH_INFO copy_level
[MAX_PACKAGE_DEPTH
];
53 static NATIVE_CHAR hex
[] =
54 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
57 /*******************************************************************************
59 * FUNCTION: Acpi_aml_enter_interpreter
63 * DESCRIPTION: Enter the interpreter execution region
65 ******************************************************************************/
68 acpi_aml_enter_interpreter (void)
71 acpi_cm_acquire_mutex (ACPI_MTX_EXECUTE
);
77 /*******************************************************************************
79 * FUNCTION: Acpi_aml_exit_interpreter
83 * DESCRIPTION: Exit the interpreter execution region
85 * Cases where the interpreter is unlocked:
86 * 1) Completion of the execution of a control method
87 * 2) Method blocked on a Sleep() AML opcode
88 * 3) Method blocked on an Acquire() AML opcode
89 * 4) Method blocked on a Wait() AML opcode
90 * 5) Method blocked to acquire the global lock
91 * 6) Method blocked to execute a serialized control method that is
93 * 7) About to invoke a user-installed opregion handler
95 ******************************************************************************/
98 acpi_aml_exit_interpreter (void)
101 acpi_cm_release_mutex (ACPI_MTX_EXECUTE
);
107 /*******************************************************************************
109 * FUNCTION: Acpi_aml_validate_object_type
111 * PARAMETERS: Type Object type to validate
113 * DESCRIPTION: Determine if a type is a valid ACPI object type
115 ******************************************************************************/
118 acpi_aml_validate_object_type (
119 ACPI_OBJECT_TYPE type
)
122 if ((type
> ACPI_TYPE_MAX
&& type
< INTERNAL_TYPE_BEGIN
) ||
123 (type
> INTERNAL_TYPE_MAX
))
132 /*******************************************************************************
134 * FUNCTION: Acpi_aml_truncate_for32bit_table
136 * PARAMETERS: Obj_desc - Object to be truncated
137 * Walk_state - Current walk state
138 * (A method must be executing)
142 * DESCRIPTION: Truncate a number to 32-bits if the currently executing method
143 * belongs to a 32-bit ACPI table.
145 ******************************************************************************/
148 acpi_aml_truncate_for32bit_table (
149 ACPI_OPERAND_OBJECT
*obj_desc
,
150 ACPI_WALK_STATE
*walk_state
)
154 * Object must be a valid number and we must be executing
159 (obj_desc
->common
.type
!= ACPI_TYPE_NUMBER
) ||
160 (!walk_state
->method_node
))
165 if (walk_state
->method_node
->flags
& ANOBJ_DATA_WIDTH_32
) {
167 * We are running a method that exists in a 32-bit ACPI table.
168 * Truncate the value to 32 bits by zeroing out the upper 32-bit field
170 obj_desc
->number
.value
&= (UINT64
) ACPI_UINT32_MAX
;
175 /*******************************************************************************
177 * FUNCTION: Acpi_aml_acquire_global_lock
179 * PARAMETERS: Rule - Lock rule: Always_lock, Never_lock
181 * RETURN: TRUE/FALSE indicating whether the lock was actually acquired
183 * DESCRIPTION: Obtain the global lock and keep track of this fact via two
184 * methods. A global variable keeps the state of the lock, and
185 * the state is returned to the caller.
187 ******************************************************************************/
190 acpi_aml_acquire_global_lock (
197 /* Only attempt lock if the Rule says so */
199 if (rule
== (u32
) GLOCK_ALWAYS_LOCK
) {
200 /* OK to get the lock */
202 status
= acpi_ev_acquire_global_lock ();
204 if (ACPI_SUCCESS (status
)) {
205 acpi_gbl_global_lock_set
= TRUE
;
214 /*******************************************************************************
216 * FUNCTION: Acpi_aml_release_global_lock
218 * PARAMETERS: Locked_by_me - Return value from corresponding call to
219 * Acquire_global_lock.
223 * DESCRIPTION: Release the global lock if it is locked.
225 ******************************************************************************/
228 acpi_aml_release_global_lock (
233 /* Only attempt unlock if the caller locked it */
236 /* Double check against the global flag */
238 if (acpi_gbl_global_lock_set
) {
239 /* OK, now release the lock */
241 acpi_ev_release_global_lock ();
242 acpi_gbl_global_lock_set
= FALSE
;
252 /*******************************************************************************
254 * FUNCTION: Acpi_aml_digits_needed
256 * PARAMETERS: val - Value to be represented
257 * base - Base of representation
259 * RETURN: the number of digits needed to represent val in base
261 ******************************************************************************/
264 acpi_aml_digits_needed (
272 REPORT_ERROR (("Aml_digits_needed: Internal error - Invalid base\n"));
276 for (num_digits
= 1 + (val
< 0); (val
= ACPI_DIVIDE (val
,base
)); ++num_digits
) { ; }
283 /*******************************************************************************
287 * PARAMETERS: Value - Value to be converted
289 * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)
291 ******************************************************************************/
312 out
.bytes
[0] = in
.bytes
[3];
313 out
.bytes
[1] = in
.bytes
[2];
314 out
.bytes
[2] = in
.bytes
[1];
315 out
.bytes
[3] = in
.bytes
[0];
321 /*******************************************************************************
323 * FUNCTION: Acpi_aml_eisa_id_to_string
325 * PARAMETERS: Numeric_id - EISA ID to be converted
326 * Out_string - Where to put the converted string (8 bytes)
328 * DESCRIPTION: Convert a numeric EISA ID to string representation
330 ******************************************************************************/
333 acpi_aml_eisa_id_to_string (
335 NATIVE_CHAR
*out_string
)
339 /* swap to big-endian to get contiguous bits */
341 id
= _ntohl (numeric_id
);
343 out_string
[0] = (char) ('@' + ((id
>> 26) & 0x1f));
344 out_string
[1] = (char) ('@' + ((id
>> 21) & 0x1f));
345 out_string
[2] = (char) ('@' + ((id
>> 16) & 0x1f));
346 out_string
[3] = hex
[(id
>> 12) & 0xf];
347 out_string
[4] = hex
[(id
>> 8) & 0xf];
348 out_string
[5] = hex
[(id
>> 4) & 0xf];
349 out_string
[6] = hex
[id
& 0xf];
356 /*******************************************************************************
358 * FUNCTION: Acpi_aml_unsigned_integer_to_string
360 * PARAMETERS: Value - Value to be converted
361 * Out_string - Where to put the converted string (8 bytes)
363 * RETURN: Convert a number to string representation
365 ******************************************************************************/
368 acpi_aml_unsigned_integer_to_string (
370 NATIVE_CHAR
*out_string
)
376 digits_needed
= acpi_aml_digits_needed (value
, 10);
378 out_string
[digits_needed
] = '\0';
380 for (count
= digits_needed
; count
> 0; count
--) {
381 out_string
[count
-1] = (NATIVE_CHAR
) ('0' + (ACPI_MODULO (value
, 10)));
382 value
= ACPI_DIVIDE (value
, 10);
389 /*******************************************************************************
391 * FUNCTION: Acpi_aml_build_copy_internal_package_object
393 * PARAMETERS: *Source_obj - Pointer to the source package object
394 * *Dest_obj - Where the internal object is returned
396 * RETURN: Status - the status of the call
398 * DESCRIPTION: This function is called to copy an internal package object
399 * into another internal package object.
401 ******************************************************************************/
404 acpi_aml_build_copy_internal_package_object (
405 ACPI_OPERAND_OBJECT
*source_obj
,
406 ACPI_OPERAND_OBJECT
*dest_obj
,
407 ACPI_WALK_STATE
*walk_state
)
409 u32 current_depth
= 0;
410 ACPI_STATUS status
= AE_OK
;
413 u32 object_space
= 0;
414 ACPI_OPERAND_OBJECT
*this_dest_obj
;
415 ACPI_OPERAND_OBJECT
*this_source_obj
;
416 INTERNAL_PKG_SEARCH_INFO
*level_ptr
;
420 * Initialize the working variables
423 MEMSET ((void *) copy_level
, 0, sizeof(copy_level
));
425 copy_level
[0].dest_obj
= dest_obj
;
426 copy_level
[0].source_obj
= source_obj
;
427 level_ptr
= ©_level
[0];
430 dest_obj
->common
.type
= source_obj
->common
.type
;
431 dest_obj
->package
.count
= source_obj
->package
.count
;
435 * Build an array of ACPI_OBJECTS in the buffer
436 * and move the free space past it
439 dest_obj
->package
.elements
= acpi_cm_callocate (
440 (dest_obj
->package
.count
+ 1) *
442 if (!dest_obj
->package
.elements
) {
443 /* Package vector allocation failure */
445 REPORT_ERROR (("Aml_build_copy_internal_package_object: Package vector allocation failure\n"));
446 return (AE_NO_MEMORY
);
449 dest_obj
->package
.next_element
= dest_obj
->package
.elements
;
453 this_index
= level_ptr
->index
;
454 this_dest_obj
= (ACPI_OPERAND_OBJECT
*) level_ptr
->dest_obj
->package
.elements
[this_index
];
455 this_source_obj
= (ACPI_OPERAND_OBJECT
*) level_ptr
->source_obj
->package
.elements
[this_index
];
457 if (IS_THIS_OBJECT_TYPE (this_source_obj
, ACPI_TYPE_PACKAGE
)) {
459 * If this object is a package then we go one deeper
461 if (current_depth
>= MAX_PACKAGE_DEPTH
-1) {
463 * Too many nested levels of packages for us to handle
469 * Build the package object
471 this_dest_obj
= acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE
);
472 level_ptr
->dest_obj
->package
.elements
[this_index
] = this_dest_obj
;
475 this_dest_obj
->common
.type
= ACPI_TYPE_PACKAGE
;
476 this_dest_obj
->package
.count
= this_dest_obj
->package
.count
;
479 * Save space for the array of objects (Package elements)
480 * update the buffer length counter
482 object_space
= this_dest_obj
->package
.count
*
483 sizeof (ACPI_OPERAND_OBJECT
);
484 length
+= object_space
;
486 level_ptr
= ©_level
[current_depth
];
487 level_ptr
->dest_obj
= this_dest_obj
;
488 level_ptr
->source_obj
= this_source_obj
;
489 level_ptr
->index
= 0;
491 } /* if object is a package */
495 this_dest_obj
= acpi_cm_create_internal_object (
496 this_source_obj
->common
.type
);
497 level_ptr
->dest_obj
->package
.elements
[this_index
] = this_dest_obj
;
499 status
= acpi_aml_store_object_to_object(this_source_obj
, this_dest_obj
, walk_state
);
501 if (ACPI_FAILURE (status
)) {
508 length
+=object_space
;
511 while (level_ptr
->index
>= level_ptr
->dest_obj
->package
.count
) {
513 * We've handled all of the objects at this level, This means
514 * that we have just completed a package. That package may
515 * have contained one or more packages itself
517 if (current_depth
== 0) {
519 * We have handled all of the objects in the top level
520 * package just add the length of the package objects
527 * Go back up a level and move the index past the just
528 * completed package object.
531 level_ptr
= ©_level
[current_depth
];
534 } /* else object is NOT a package */