Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1498 | serge | 1 | /****************************************************************************** |
2 | * |
||
3 | * Module Name: dsopcode - Dispatcher Op Region support and handling of |
||
4 | * "control" opcodes |
||
5 | * |
||
6 | *****************************************************************************/ |
||
7 | |||
8 | /****************************************************************************** |
||
9 | * |
||
10 | * 1. Copyright Notice |
||
11 | * |
||
12 | * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
||
13 | * All rights reserved. |
||
14 | * |
||
15 | * 2. License |
||
16 | * |
||
17 | * 2.1. This is your license from Intel Corp. under its intellectual property |
||
18 | * rights. You may have additional license terms from the party that provided |
||
19 | * you this software, covering your right to use that party's intellectual |
||
20 | * property rights. |
||
21 | * |
||
22 | * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
||
23 | * copy of the source code appearing in this file ("Covered Code") an |
||
24 | * irrevocable, perpetual, worldwide license under Intel's copyrights in the |
||
25 | * base code distributed originally by Intel ("Original Intel Code") to copy, |
||
26 | * make derivatives, distribute, use and display any portion of the Covered |
||
27 | * Code in any form, with the right to sublicense such rights; and |
||
28 | * |
||
29 | * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
||
30 | * license (with the right to sublicense), under only those claims of Intel |
||
31 | * patents that are infringed by the Original Intel Code, to make, use, sell, |
||
32 | * offer to sell, and import the Covered Code and derivative works thereof |
||
33 | * solely to the minimum extent necessary to exercise the above copyright |
||
34 | * license, and in no event shall the patent license extend to any additions |
||
35 | * to or modifications of the Original Intel Code. No other license or right |
||
36 | * is granted directly or by implication, estoppel or otherwise; |
||
37 | * |
||
38 | * The above copyright and patent license is granted only if the following |
||
39 | * conditions are met: |
||
40 | * |
||
41 | * 3. Conditions |
||
42 | * |
||
43 | * 3.1. Redistribution of Source with Rights to Further Distribute Source. |
||
44 | * Redistribution of source code of any substantial portion of the Covered |
||
45 | * Code or modification with rights to further distribute source must include |
||
46 | * the above Copyright Notice, the above License, this list of Conditions, |
||
47 | * and the following Disclaimer and Export Compliance provision. In addition, |
||
48 | * Licensee must cause all Covered Code to which Licensee contributes to |
||
49 | * contain a file documenting the changes Licensee made to create that Covered |
||
50 | * Code and the date of any change. Licensee must include in that file the |
||
51 | * documentation of any changes made by any predecessor Licensee. Licensee |
||
52 | * must include a prominent statement that the modification is derived, |
||
53 | * directly or indirectly, from Original Intel Code. |
||
54 | * |
||
55 | * 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
||
56 | * Redistribution of source code of any substantial portion of the Covered |
||
57 | * Code or modification without rights to further distribute source must |
||
58 | * include the following Disclaimer and Export Compliance provision in the |
||
59 | * documentation and/or other materials provided with distribution. In |
||
60 | * addition, Licensee may not authorize further sublicense of source of any |
||
61 | * portion of the Covered Code, and must include terms to the effect that the |
||
62 | * license from Licensee to its licensee is limited to the intellectual |
||
63 | * property embodied in the software Licensee provides to its licensee, and |
||
64 | * not to intellectual property embodied in modifications its licensee may |
||
65 | * make. |
||
66 | * |
||
67 | * 3.3. Redistribution of Executable. Redistribution in executable form of any |
||
68 | * substantial portion of the Covered Code or modification must reproduce the |
||
69 | * above Copyright Notice, and the following Disclaimer and Export Compliance |
||
70 | * provision in the documentation and/or other materials provided with the |
||
71 | * distribution. |
||
72 | * |
||
73 | * 3.4. Intel retains all right, title, and interest in and to the Original |
||
74 | * Intel Code. |
||
75 | * |
||
76 | * 3.5. Neither the name Intel nor any other trademark owned or controlled by |
||
77 | * Intel shall be used in advertising or otherwise to promote the sale, use or |
||
78 | * other dealings in products derived from or relating to the Covered Code |
||
79 | * without prior written authorization from Intel. |
||
80 | * |
||
81 | * 4. Disclaimer and Export Compliance |
||
82 | * |
||
83 | * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
||
84 | * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
||
85 | * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
||
86 | * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
||
87 | * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
||
88 | * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
||
89 | * PARTICULAR PURPOSE. |
||
90 | * |
||
91 | * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
||
92 | * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
||
93 | * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
||
94 | * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
||
95 | * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
||
96 | * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
||
97 | * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
||
98 | * LIMITED REMEDY. |
||
99 | * |
||
100 | * 4.3. Licensee shall not export, either directly or indirectly, any of this |
||
101 | * software or system incorporating such software without first obtaining any |
||
102 | * required license or other approval from the U. S. Department of Commerce or |
||
103 | * any other agency or department of the United States Government. In the |
||
104 | * event Licensee exports any such software from the United States or |
||
105 | * re-exports any such software from a foreign destination, Licensee shall |
||
106 | * ensure that the distribution and export/re-export of the software is in |
||
107 | * compliance with all laws, regulations, orders, or other restrictions of the |
||
108 | * U.S. Export Administration Regulations. Licensee agrees that neither it nor |
||
109 | * any of its subsidiaries will export/re-export any technical data, process, |
||
110 | * software, or service, directly or indirectly, to any country for which the |
||
111 | * United States government or any agency thereof requires an export license, |
||
112 | * other governmental approval, or letter of assurance, without first obtaining |
||
113 | * such license, approval or letter. |
||
114 | * |
||
115 | *****************************************************************************/ |
||
116 | |||
117 | #define __DSOPCODE_C__ |
||
118 | |||
119 | #include "acpi.h" |
||
120 | #include "accommon.h" |
||
121 | #include "acparser.h" |
||
122 | #include "amlcode.h" |
||
123 | #include "acdispat.h" |
||
124 | #include "acinterp.h" |
||
125 | #include "acnamesp.h" |
||
126 | #include "acevents.h" |
||
127 | #include "actables.h" |
||
128 | |||
129 | #define _COMPONENT ACPI_DISPATCHER |
||
130 | ACPI_MODULE_NAME ("dsopcode") |
||
131 | |||
132 | /* Local prototypes */ |
||
133 | |||
134 | static ACPI_STATUS |
||
135 | AcpiDsExecuteArguments ( |
||
136 | ACPI_NAMESPACE_NODE *Node, |
||
137 | ACPI_NAMESPACE_NODE *ScopeNode, |
||
138 | UINT32 AmlLength, |
||
139 | UINT8 *AmlStart); |
||
140 | |||
141 | static ACPI_STATUS |
||
142 | AcpiDsInitBufferField ( |
||
143 | UINT16 AmlOpcode, |
||
144 | ACPI_OPERAND_OBJECT *ObjDesc, |
||
145 | ACPI_OPERAND_OBJECT *BufferDesc, |
||
146 | ACPI_OPERAND_OBJECT *OffsetDesc, |
||
147 | ACPI_OPERAND_OBJECT *LengthDesc, |
||
148 | ACPI_OPERAND_OBJECT *ResultDesc); |
||
149 | |||
150 | |||
151 | /******************************************************************************* |
||
152 | * |
||
153 | * FUNCTION: AcpiDsExecuteArguments |
||
154 | * |
||
155 | * PARAMETERS: Node - Object NS node |
||
156 | * ScopeNode - Parent NS node |
||
157 | * AmlLength - Length of executable AML |
||
158 | * AmlStart - Pointer to the AML |
||
159 | * |
||
160 | * RETURN: Status. |
||
161 | * |
||
162 | * DESCRIPTION: Late (deferred) execution of region or field arguments |
||
163 | * |
||
164 | ******************************************************************************/ |
||
165 | |||
166 | static ACPI_STATUS |
||
167 | AcpiDsExecuteArguments ( |
||
168 | ACPI_NAMESPACE_NODE *Node, |
||
169 | ACPI_NAMESPACE_NODE *ScopeNode, |
||
170 | UINT32 AmlLength, |
||
171 | UINT8 *AmlStart) |
||
172 | { |
||
173 | ACPI_STATUS Status; |
||
174 | ACPI_PARSE_OBJECT *Op; |
||
175 | ACPI_WALK_STATE *WalkState; |
||
176 | |||
177 | |||
178 | ACPI_FUNCTION_TRACE (DsExecuteArguments); |
||
179 | |||
180 | |||
181 | /* |
||
182 | * Allocate a new parser op to be the root of the parsed tree |
||
183 | */ |
||
184 | Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP); |
||
185 | if (!Op) |
||
186 | { |
||
187 | return_ACPI_STATUS (AE_NO_MEMORY); |
||
188 | } |
||
189 | |||
190 | /* Save the Node for use in AcpiPsParseAml */ |
||
191 | |||
192 | Op->Common.Node = ScopeNode; |
||
193 | |||
194 | /* Create and initialize a new parser state */ |
||
195 | |||
196 | WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); |
||
197 | if (!WalkState) |
||
198 | { |
||
199 | Status = AE_NO_MEMORY; |
||
200 | goto Cleanup; |
||
201 | } |
||
202 | |||
203 | Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, AmlStart, |
||
204 | AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); |
||
205 | if (ACPI_FAILURE (Status)) |
||
206 | { |
||
207 | AcpiDsDeleteWalkState (WalkState); |
||
208 | goto Cleanup; |
||
209 | } |
||
210 | |||
211 | /* Mark this parse as a deferred opcode */ |
||
212 | |||
213 | WalkState->ParseFlags = ACPI_PARSE_DEFERRED_OP; |
||
214 | WalkState->DeferredNode = Node; |
||
215 | |||
216 | /* Pass1: Parse the entire declaration */ |
||
217 | |||
218 | Status = AcpiPsParseAml (WalkState); |
||
219 | if (ACPI_FAILURE (Status)) |
||
220 | { |
||
221 | goto Cleanup; |
||
222 | } |
||
223 | |||
224 | /* Get and init the Op created above */ |
||
225 | |||
226 | Op->Common.Node = Node; |
||
227 | AcpiPsDeleteParseTree (Op); |
||
228 | |||
229 | /* Evaluate the deferred arguments */ |
||
230 | |||
231 | Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP); |
||
232 | if (!Op) |
||
233 | { |
||
234 | return_ACPI_STATUS (AE_NO_MEMORY); |
||
235 | } |
||
236 | |||
237 | Op->Common.Node = ScopeNode; |
||
238 | |||
239 | /* Create and initialize a new parser state */ |
||
240 | |||
241 | WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); |
||
242 | if (!WalkState) |
||
243 | { |
||
244 | Status = AE_NO_MEMORY; |
||
245 | goto Cleanup; |
||
246 | } |
||
247 | |||
248 | /* Execute the opcode and arguments */ |
||
249 | |||
250 | Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, AmlStart, |
||
251 | AmlLength, NULL, ACPI_IMODE_EXECUTE); |
||
252 | if (ACPI_FAILURE (Status)) |
||
253 | { |
||
254 | AcpiDsDeleteWalkState (WalkState); |
||
255 | goto Cleanup; |
||
256 | } |
||
257 | |||
258 | /* Mark this execution as a deferred opcode */ |
||
259 | |||
260 | WalkState->DeferredNode = Node; |
||
261 | Status = AcpiPsParseAml (WalkState); |
||
262 | |||
263 | Cleanup: |
||
264 | AcpiPsDeleteParseTree (Op); |
||
265 | return_ACPI_STATUS (Status); |
||
266 | } |
||
267 | |||
268 | |||
269 | /******************************************************************************* |
||
270 | * |
||
271 | * FUNCTION: AcpiDsGetBufferFieldArguments |
||
272 | * |
||
273 | * PARAMETERS: ObjDesc - A valid BufferField object |
||
274 | * |
||
275 | * RETURN: Status. |
||
276 | * |
||
277 | * DESCRIPTION: Get BufferField Buffer and Index. This implements the late |
||
278 | * evaluation of these field attributes. |
||
279 | * |
||
280 | ******************************************************************************/ |
||
281 | |||
282 | ACPI_STATUS |
||
283 | AcpiDsGetBufferFieldArguments ( |
||
284 | ACPI_OPERAND_OBJECT *ObjDesc) |
||
285 | { |
||
286 | ACPI_OPERAND_OBJECT *ExtraDesc; |
||
287 | ACPI_NAMESPACE_NODE *Node; |
||
288 | ACPI_STATUS Status; |
||
289 | |||
290 | |||
291 | ACPI_FUNCTION_TRACE_PTR (DsGetBufferFieldArguments, ObjDesc); |
||
292 | |||
293 | |||
294 | if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) |
||
295 | { |
||
296 | return_ACPI_STATUS (AE_OK); |
||
297 | } |
||
298 | |||
299 | /* Get the AML pointer (method object) and BufferField node */ |
||
300 | |||
301 | ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc); |
||
302 | Node = ObjDesc->BufferField.Node; |
||
303 | |||
304 | ACPI_DEBUG_EXEC(AcpiUtDisplayInitPathname (ACPI_TYPE_BUFFER_FIELD, Node, NULL)); |
||
305 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", |
||
306 | AcpiUtGetNodeName (Node))); |
||
307 | |||
308 | /* Execute the AML code for the TermArg arguments */ |
||
309 | |||
310 | Status = AcpiDsExecuteArguments (Node, Node->Parent, |
||
311 | ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart); |
||
312 | return_ACPI_STATUS (Status); |
||
313 | } |
||
314 | |||
315 | |||
316 | /******************************************************************************* |
||
317 | * |
||
318 | * FUNCTION: AcpiDsGetBankFieldArguments |
||
319 | * |
||
320 | * PARAMETERS: ObjDesc - A valid BankField object |
||
321 | * |
||
322 | * RETURN: Status. |
||
323 | * |
||
324 | * DESCRIPTION: Get BankField BankValue. This implements the late |
||
325 | * evaluation of these field attributes. |
||
326 | * |
||
327 | ******************************************************************************/ |
||
328 | |||
329 | ACPI_STATUS |
||
330 | AcpiDsGetBankFieldArguments ( |
||
331 | ACPI_OPERAND_OBJECT *ObjDesc) |
||
332 | { |
||
333 | ACPI_OPERAND_OBJECT *ExtraDesc; |
||
334 | ACPI_NAMESPACE_NODE *Node; |
||
335 | ACPI_STATUS Status; |
||
336 | |||
337 | |||
338 | ACPI_FUNCTION_TRACE_PTR (DsGetBankFieldArguments, ObjDesc); |
||
339 | |||
340 | |||
341 | if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) |
||
342 | { |
||
343 | return_ACPI_STATUS (AE_OK); |
||
344 | } |
||
345 | |||
346 | /* Get the AML pointer (method object) and BankField node */ |
||
347 | |||
348 | ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc); |
||
349 | Node = ObjDesc->BankField.Node; |
||
350 | |||
351 | ACPI_DEBUG_EXEC(AcpiUtDisplayInitPathname (ACPI_TYPE_LOCAL_BANK_FIELD, Node, NULL)); |
||
352 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", |
||
353 | AcpiUtGetNodeName (Node))); |
||
354 | |||
355 | /* Execute the AML code for the TermArg arguments */ |
||
356 | |||
357 | Status = AcpiDsExecuteArguments (Node, Node->Parent, |
||
358 | ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart); |
||
359 | return_ACPI_STATUS (Status); |
||
360 | } |
||
361 | |||
362 | |||
363 | /******************************************************************************* |
||
364 | * |
||
365 | * FUNCTION: AcpiDsGetBufferArguments |
||
366 | * |
||
367 | * PARAMETERS: ObjDesc - A valid Buffer object |
||
368 | * |
||
369 | * RETURN: Status. |
||
370 | * |
||
371 | * DESCRIPTION: Get Buffer length and initializer byte list. This implements |
||
372 | * the late evaluation of these attributes. |
||
373 | * |
||
374 | ******************************************************************************/ |
||
375 | |||
376 | ACPI_STATUS |
||
377 | AcpiDsGetBufferArguments ( |
||
378 | ACPI_OPERAND_OBJECT *ObjDesc) |
||
379 | { |
||
380 | ACPI_NAMESPACE_NODE *Node; |
||
381 | ACPI_STATUS Status; |
||
382 | |||
383 | |||
384 | ACPI_FUNCTION_TRACE_PTR (DsGetBufferArguments, ObjDesc); |
||
385 | |||
386 | |||
387 | if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) |
||
388 | { |
||
389 | return_ACPI_STATUS (AE_OK); |
||
390 | } |
||
391 | |||
392 | /* Get the Buffer node */ |
||
393 | |||
394 | Node = ObjDesc->Buffer.Node; |
||
395 | if (!Node) |
||
396 | { |
||
397 | ACPI_ERROR ((AE_INFO, |
||
398 | "No pointer back to namespace node in buffer object %p", ObjDesc)); |
||
399 | return_ACPI_STATUS (AE_AML_INTERNAL); |
||
400 | } |
||
401 | |||
402 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer Arg Init\n")); |
||
403 | |||
404 | /* Execute the AML code for the TermArg arguments */ |
||
405 | |||
406 | Status = AcpiDsExecuteArguments (Node, Node, |
||
407 | ObjDesc->Buffer.AmlLength, ObjDesc->Buffer.AmlStart); |
||
408 | return_ACPI_STATUS (Status); |
||
409 | } |
||
410 | |||
411 | |||
412 | /******************************************************************************* |
||
413 | * |
||
414 | * FUNCTION: AcpiDsGetPackageArguments |
||
415 | * |
||
416 | * PARAMETERS: ObjDesc - A valid Package object |
||
417 | * |
||
418 | * RETURN: Status. |
||
419 | * |
||
420 | * DESCRIPTION: Get Package length and initializer byte list. This implements |
||
421 | * the late evaluation of these attributes. |
||
422 | * |
||
423 | ******************************************************************************/ |
||
424 | |||
425 | ACPI_STATUS |
||
426 | AcpiDsGetPackageArguments ( |
||
427 | ACPI_OPERAND_OBJECT *ObjDesc) |
||
428 | { |
||
429 | ACPI_NAMESPACE_NODE *Node; |
||
430 | ACPI_STATUS Status; |
||
431 | |||
432 | |||
433 | ACPI_FUNCTION_TRACE_PTR (DsGetPackageArguments, ObjDesc); |
||
434 | |||
435 | |||
436 | if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) |
||
437 | { |
||
438 | return_ACPI_STATUS (AE_OK); |
||
439 | } |
||
440 | |||
441 | /* Get the Package node */ |
||
442 | |||
443 | Node = ObjDesc->Package.Node; |
||
444 | if (!Node) |
||
445 | { |
||
446 | ACPI_ERROR ((AE_INFO, |
||
447 | "No pointer back to namespace node in package %p", ObjDesc)); |
||
448 | return_ACPI_STATUS (AE_AML_INTERNAL); |
||
449 | } |
||
450 | |||
451 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package Arg Init\n")); |
||
452 | |||
453 | /* Execute the AML code for the TermArg arguments */ |
||
454 | |||
455 | Status = AcpiDsExecuteArguments (Node, Node, |
||
456 | ObjDesc->Package.AmlLength, ObjDesc->Package.AmlStart); |
||
457 | return_ACPI_STATUS (Status); |
||
458 | } |
||
459 | |||
460 | |||
461 | /***************************************************************************** |
||
462 | * |
||
463 | * FUNCTION: AcpiDsGetRegionArguments |
||
464 | * |
||
465 | * PARAMETERS: ObjDesc - A valid region object |
||
466 | * |
||
467 | * RETURN: Status. |
||
468 | * |
||
469 | * DESCRIPTION: Get region address and length. This implements the late |
||
470 | * evaluation of these region attributes. |
||
471 | * |
||
472 | ****************************************************************************/ |
||
473 | |||
474 | ACPI_STATUS |
||
475 | AcpiDsGetRegionArguments ( |
||
476 | ACPI_OPERAND_OBJECT *ObjDesc) |
||
477 | { |
||
478 | ACPI_NAMESPACE_NODE *Node; |
||
479 | ACPI_STATUS Status; |
||
480 | ACPI_OPERAND_OBJECT *ExtraDesc; |
||
481 | |||
482 | |||
483 | ACPI_FUNCTION_TRACE_PTR (DsGetRegionArguments, ObjDesc); |
||
484 | |||
485 | |||
486 | if (ObjDesc->Region.Flags & AOPOBJ_DATA_VALID) |
||
487 | { |
||
488 | return_ACPI_STATUS (AE_OK); |
||
489 | } |
||
490 | |||
491 | ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc); |
||
492 | if (!ExtraDesc) |
||
493 | { |
||
494 | return_ACPI_STATUS (AE_NOT_EXIST); |
||
495 | } |
||
496 | |||
497 | /* Get the Region node */ |
||
498 | |||
499 | Node = ObjDesc->Region.Node; |
||
500 | |||
501 | ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_REGION, Node, NULL)); |
||
502 | |||
503 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", |
||
504 | AcpiUtGetNodeName (Node), ExtraDesc->Extra.AmlStart)); |
||
505 | |||
506 | /* Execute the argument AML */ |
||
507 | |||
508 | Status = AcpiDsExecuteArguments (Node, Node->Parent, |
||
509 | ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart); |
||
510 | return_ACPI_STATUS (Status); |
||
511 | } |
||
512 | |||
513 | |||
514 | /******************************************************************************* |
||
515 | * |
||
516 | * FUNCTION: AcpiDsInitializeRegion |
||
517 | * |
||
518 | * PARAMETERS: ObjHandle - Region namespace node |
||
519 | * |
||
520 | * RETURN: Status |
||
521 | * |
||
522 | * DESCRIPTION: Front end to EvInitializeRegion |
||
523 | * |
||
524 | ******************************************************************************/ |
||
525 | |||
526 | ACPI_STATUS |
||
527 | AcpiDsInitializeRegion ( |
||
528 | ACPI_HANDLE ObjHandle) |
||
529 | { |
||
530 | ACPI_OPERAND_OBJECT *ObjDesc; |
||
531 | ACPI_STATUS Status; |
||
532 | |||
533 | |||
534 | ObjDesc = AcpiNsGetAttachedObject (ObjHandle); |
||
535 | |||
536 | /* Namespace is NOT locked */ |
||
537 | |||
538 | Status = AcpiEvInitializeRegion (ObjDesc, FALSE); |
||
539 | return (Status); |
||
540 | } |
||
541 | |||
542 | |||
543 | /******************************************************************************* |
||
544 | * |
||
545 | * FUNCTION: AcpiDsInitBufferField |
||
546 | * |
||
547 | * PARAMETERS: AmlOpcode - CreateXxxField |
||
548 | * ObjDesc - BufferField object |
||
549 | * BufferDesc - Host Buffer |
||
550 | * OffsetDesc - Offset into buffer |
||
551 | * LengthDesc - Length of field (CREATE_FIELD_OP only) |
||
552 | * ResultDesc - Where to store the result |
||
553 | * |
||
554 | * RETURN: Status |
||
555 | * |
||
556 | * DESCRIPTION: Perform actual initialization of a buffer field |
||
557 | * |
||
558 | ******************************************************************************/ |
||
559 | |||
560 | static ACPI_STATUS |
||
561 | AcpiDsInitBufferField ( |
||
562 | UINT16 AmlOpcode, |
||
563 | ACPI_OPERAND_OBJECT *ObjDesc, |
||
564 | ACPI_OPERAND_OBJECT *BufferDesc, |
||
565 | ACPI_OPERAND_OBJECT *OffsetDesc, |
||
566 | ACPI_OPERAND_OBJECT *LengthDesc, |
||
567 | ACPI_OPERAND_OBJECT *ResultDesc) |
||
568 | { |
||
569 | UINT32 Offset; |
||
570 | UINT32 BitOffset; |
||
571 | UINT32 BitCount; |
||
572 | UINT8 FieldFlags; |
||
573 | ACPI_STATUS Status; |
||
574 | |||
575 | |||
576 | ACPI_FUNCTION_TRACE_PTR (DsInitBufferField, ObjDesc); |
||
577 | |||
578 | |||
579 | /* Host object must be a Buffer */ |
||
580 | |||
581 | if (BufferDesc->Common.Type != ACPI_TYPE_BUFFER) |
||
582 | { |
||
583 | ACPI_ERROR ((AE_INFO, |
||
584 | "Target of Create Field is not a Buffer object - %s", |
||
585 | AcpiUtGetObjectTypeName (BufferDesc))); |
||
586 | |||
587 | Status = AE_AML_OPERAND_TYPE; |
||
588 | goto Cleanup; |
||
589 | } |
||
590 | |||
591 | /* |
||
592 | * The last parameter to all of these opcodes (ResultDesc) started |
||
593 | * out as a NameString, and should therefore now be a NS node |
||
594 | * after resolution in AcpiExResolveOperands(). |
||
595 | */ |
||
596 | if (ACPI_GET_DESCRIPTOR_TYPE (ResultDesc) != ACPI_DESC_TYPE_NAMED) |
||
597 | { |
||
598 | ACPI_ERROR ((AE_INFO, |
||
599 | "(%s) destination not a NS Node [%s]", |
||
600 | AcpiPsGetOpcodeName (AmlOpcode), |
||
601 | AcpiUtGetDescriptorName (ResultDesc))); |
||
602 | |||
603 | Status = AE_AML_OPERAND_TYPE; |
||
604 | goto Cleanup; |
||
605 | } |
||
606 | |||
607 | Offset = (UINT32) OffsetDesc->Integer.Value; |
||
608 | |||
609 | /* |
||
610 | * Setup the Bit offsets and counts, according to the opcode |
||
611 | */ |
||
612 | switch (AmlOpcode) |
||
613 | { |
||
614 | case AML_CREATE_FIELD_OP: |
||
615 | |||
616 | /* Offset is in bits, count is in bits */ |
||
617 | |||
618 | FieldFlags = AML_FIELD_ACCESS_BYTE; |
||
619 | BitOffset = Offset; |
||
620 | BitCount = (UINT32) LengthDesc->Integer.Value; |
||
621 | |||
622 | /* Must have a valid (>0) bit count */ |
||
623 | |||
624 | if (BitCount == 0) |
||
625 | { |
||
626 | ACPI_ERROR ((AE_INFO, |
||
627 | "Attempt to CreateField of length zero")); |
||
628 | Status = AE_AML_OPERAND_VALUE; |
||
629 | goto Cleanup; |
||
630 | } |
||
631 | break; |
||
632 | |||
633 | case AML_CREATE_BIT_FIELD_OP: |
||
634 | |||
635 | /* Offset is in bits, Field is one bit */ |
||
636 | |||
637 | BitOffset = Offset; |
||
638 | BitCount = 1; |
||
639 | FieldFlags = AML_FIELD_ACCESS_BYTE; |
||
640 | break; |
||
641 | |||
642 | case AML_CREATE_BYTE_FIELD_OP: |
||
643 | |||
644 | /* Offset is in bytes, field is one byte */ |
||
645 | |||
646 | BitOffset = 8 * Offset; |
||
647 | BitCount = 8; |
||
648 | FieldFlags = AML_FIELD_ACCESS_BYTE; |
||
649 | break; |
||
650 | |||
651 | case AML_CREATE_WORD_FIELD_OP: |
||
652 | |||
653 | /* Offset is in bytes, field is one word */ |
||
654 | |||
655 | BitOffset = 8 * Offset; |
||
656 | BitCount = 16; |
||
657 | FieldFlags = AML_FIELD_ACCESS_WORD; |
||
658 | break; |
||
659 | |||
660 | case AML_CREATE_DWORD_FIELD_OP: |
||
661 | |||
662 | /* Offset is in bytes, field is one dword */ |
||
663 | |||
664 | BitOffset = 8 * Offset; |
||
665 | BitCount = 32; |
||
666 | FieldFlags = AML_FIELD_ACCESS_DWORD; |
||
667 | break; |
||
668 | |||
669 | case AML_CREATE_QWORD_FIELD_OP: |
||
670 | |||
671 | /* Offset is in bytes, field is one qword */ |
||
672 | |||
673 | BitOffset = 8 * Offset; |
||
674 | BitCount = 64; |
||
675 | FieldFlags = AML_FIELD_ACCESS_QWORD; |
||
676 | break; |
||
677 | |||
678 | default: |
||
679 | |||
680 | ACPI_ERROR ((AE_INFO, |
||
681 | "Unknown field creation opcode 0x%02X", |
||
682 | AmlOpcode)); |
||
683 | Status = AE_AML_BAD_OPCODE; |
||
684 | goto Cleanup; |
||
685 | } |
||
686 | |||
687 | /* Entire field must fit within the current length of the buffer */ |
||
688 | |||
689 | if ((BitOffset + BitCount) > |
||
690 | (8 * (UINT32) BufferDesc->Buffer.Length)) |
||
691 | { |
||
692 | ACPI_ERROR ((AE_INFO, |
||
693 | "Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)", |
||
694 | AcpiUtGetNodeName (ResultDesc), |
||
695 | BitOffset + BitCount, |
||
696 | AcpiUtGetNodeName (BufferDesc->Buffer.Node), |
||
697 | 8 * (UINT32) BufferDesc->Buffer.Length)); |
||
698 | Status = AE_AML_BUFFER_LIMIT; |
||
699 | goto Cleanup; |
||
700 | } |
||
701 | |||
702 | /* |
||
703 | * Initialize areas of the field object that are common to all fields |
||
704 | * For FieldFlags, use LOCK_RULE = 0 (NO_LOCK), |
||
705 | * UPDATE_RULE = 0 (UPDATE_PRESERVE) |
||
706 | */ |
||
707 | Status = AcpiExPrepCommonFieldObject (ObjDesc, FieldFlags, 0, |
||
708 | BitOffset, BitCount); |
||
709 | if (ACPI_FAILURE (Status)) |
||
710 | { |
||
711 | goto Cleanup; |
||
712 | } |
||
713 | |||
714 | ObjDesc->BufferField.BufferObj = BufferDesc; |
||
715 | |||
716 | /* Reference count for BufferDesc inherits ObjDesc count */ |
||
717 | |||
718 | BufferDesc->Common.ReferenceCount = (UINT16) |
||
719 | (BufferDesc->Common.ReferenceCount + ObjDesc->Common.ReferenceCount); |
||
720 | |||
721 | |||
722 | Cleanup: |
||
723 | |||
724 | /* Always delete the operands */ |
||
725 | |||
726 | AcpiUtRemoveReference (OffsetDesc); |
||
727 | AcpiUtRemoveReference (BufferDesc); |
||
728 | |||
729 | if (AmlOpcode == AML_CREATE_FIELD_OP) |
||
730 | { |
||
731 | AcpiUtRemoveReference (LengthDesc); |
||
732 | } |
||
733 | |||
734 | /* On failure, delete the result descriptor */ |
||
735 | |||
736 | if (ACPI_FAILURE (Status)) |
||
737 | { |
||
738 | AcpiUtRemoveReference (ResultDesc); /* Result descriptor */ |
||
739 | } |
||
740 | else |
||
741 | { |
||
742 | /* Now the address and length are valid for this BufferField */ |
||
743 | |||
744 | ObjDesc->BufferField.Flags |= AOPOBJ_DATA_VALID; |
||
745 | } |
||
746 | |||
747 | return_ACPI_STATUS (Status); |
||
748 | } |
||
749 | |||
750 | |||
751 | /******************************************************************************* |
||
752 | * |
||
753 | * FUNCTION: AcpiDsEvalBufferFieldOperands |
||
754 | * |
||
755 | * PARAMETERS: WalkState - Current walk |
||
756 | * Op - A valid BufferField Op object |
||
757 | * |
||
758 | * RETURN: Status |
||
759 | * |
||
760 | * DESCRIPTION: Get BufferField Buffer and Index |
||
761 | * Called from AcpiDsExecEndOp during BufferField parse tree walk |
||
762 | * |
||
763 | ******************************************************************************/ |
||
764 | |||
765 | ACPI_STATUS |
||
766 | AcpiDsEvalBufferFieldOperands ( |
||
767 | ACPI_WALK_STATE *WalkState, |
||
768 | ACPI_PARSE_OBJECT *Op) |
||
769 | { |
||
770 | ACPI_STATUS Status; |
||
771 | ACPI_OPERAND_OBJECT *ObjDesc; |
||
772 | ACPI_NAMESPACE_NODE *Node; |
||
773 | ACPI_PARSE_OBJECT *NextOp; |
||
774 | |||
775 | |||
776 | ACPI_FUNCTION_TRACE_PTR (DsEvalBufferFieldOperands, Op); |
||
777 | |||
778 | |||
779 | /* |
||
780 | * This is where we evaluate the address and length fields of the |
||
781 | * CreateXxxField declaration |
||
782 | */ |
||
783 | Node = Op->Common.Node; |
||
784 | |||
785 | /* NextOp points to the op that holds the Buffer */ |
||
786 | |||
787 | NextOp = Op->Common.Value.Arg; |
||
788 | |||
789 | /* Evaluate/create the address and length operands */ |
||
790 | |||
791 | Status = AcpiDsCreateOperands (WalkState, NextOp); |
||
792 | if (ACPI_FAILURE (Status)) |
||
793 | { |
||
794 | return_ACPI_STATUS (Status); |
||
795 | } |
||
796 | |||
797 | ObjDesc = AcpiNsGetAttachedObject (Node); |
||
798 | if (!ObjDesc) |
||
799 | { |
||
800 | return_ACPI_STATUS (AE_NOT_EXIST); |
||
801 | } |
||
802 | |||
803 | /* Resolve the operands */ |
||
804 | |||
805 | Status = AcpiExResolveOperands (Op->Common.AmlOpcode, |
||
806 | ACPI_WALK_OPERANDS, WalkState); |
||
807 | if (ACPI_FAILURE (Status)) |
||
808 | { |
||
809 | ACPI_ERROR ((AE_INFO, "(%s) bad operand(s), status 0x%X", |
||
810 | AcpiPsGetOpcodeName (Op->Common.AmlOpcode), Status)); |
||
811 | |||
812 | return_ACPI_STATUS (Status); |
||
813 | } |
||
814 | |||
815 | /* Initialize the Buffer Field */ |
||
816 | |||
817 | if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP) |
||
818 | { |
||
819 | /* NOTE: Slightly different operands for this opcode */ |
||
820 | |||
821 | Status = AcpiDsInitBufferField (Op->Common.AmlOpcode, ObjDesc, |
||
822 | WalkState->Operands[0], WalkState->Operands[1], |
||
823 | WalkState->Operands[2], WalkState->Operands[3]); |
||
824 | } |
||
825 | else |
||
826 | { |
||
827 | /* All other, CreateXxxField opcodes */ |
||
828 | |||
829 | Status = AcpiDsInitBufferField (Op->Common.AmlOpcode, ObjDesc, |
||
830 | WalkState->Operands[0], WalkState->Operands[1], |
||
831 | NULL, WalkState->Operands[2]); |
||
832 | } |
||
833 | |||
834 | return_ACPI_STATUS (Status); |
||
835 | } |
||
836 | |||
837 | |||
838 | /******************************************************************************* |
||
839 | * |
||
840 | * FUNCTION: AcpiDsEvalRegionOperands |
||
841 | * |
||
842 | * PARAMETERS: WalkState - Current walk |
||
843 | * Op - A valid region Op object |
||
844 | * |
||
845 | * RETURN: Status |
||
846 | * |
||
847 | * DESCRIPTION: Get region address and length |
||
848 | * Called from AcpiDsExecEndOp during OpRegion parse tree walk |
||
849 | * |
||
850 | ******************************************************************************/ |
||
851 | |||
852 | ACPI_STATUS |
||
853 | AcpiDsEvalRegionOperands ( |
||
854 | ACPI_WALK_STATE *WalkState, |
||
855 | ACPI_PARSE_OBJECT *Op) |
||
856 | { |
||
857 | ACPI_STATUS Status; |
||
858 | ACPI_OPERAND_OBJECT *ObjDesc; |
||
859 | ACPI_OPERAND_OBJECT *OperandDesc; |
||
860 | ACPI_NAMESPACE_NODE *Node; |
||
861 | ACPI_PARSE_OBJECT *NextOp; |
||
862 | |||
863 | |||
864 | ACPI_FUNCTION_TRACE_PTR (DsEvalRegionOperands, Op); |
||
865 | |||
866 | |||
867 | /* |
||
868 | * This is where we evaluate the address and length fields of the |
||
869 | * OpRegion declaration |
||
870 | */ |
||
871 | Node = Op->Common.Node; |
||
872 | |||
873 | /* NextOp points to the op that holds the SpaceID */ |
||
874 | |||
875 | NextOp = Op->Common.Value.Arg; |
||
876 | |||
877 | /* NextOp points to address op */ |
||
878 | |||
879 | NextOp = NextOp->Common.Next; |
||
880 | |||
881 | /* Evaluate/create the address and length operands */ |
||
882 | |||
883 | Status = AcpiDsCreateOperands (WalkState, NextOp); |
||
884 | if (ACPI_FAILURE (Status)) |
||
885 | { |
||
886 | return_ACPI_STATUS (Status); |
||
887 | } |
||
888 | |||
889 | /* Resolve the length and address operands to numbers */ |
||
890 | |||
891 | Status = AcpiExResolveOperands (Op->Common.AmlOpcode, |
||
892 | ACPI_WALK_OPERANDS, WalkState); |
||
893 | if (ACPI_FAILURE (Status)) |
||
894 | { |
||
895 | return_ACPI_STATUS (Status); |
||
896 | } |
||
897 | |||
898 | ObjDesc = AcpiNsGetAttachedObject (Node); |
||
899 | if (!ObjDesc) |
||
900 | { |
||
901 | return_ACPI_STATUS (AE_NOT_EXIST); |
||
902 | } |
||
903 | |||
904 | /* |
||
905 | * Get the length operand and save it |
||
906 | * (at Top of stack) |
||
907 | */ |
||
908 | OperandDesc = WalkState->Operands[WalkState->NumOperands - 1]; |
||
909 | |||
910 | ObjDesc->Region.Length = (UINT32) OperandDesc->Integer.Value; |
||
911 | AcpiUtRemoveReference (OperandDesc); |
||
912 | |||
913 | /* |
||
914 | * Get the address and save it |
||
915 | * (at top of stack - 1) |
||
916 | */ |
||
917 | OperandDesc = WalkState->Operands[WalkState->NumOperands - 2]; |
||
918 | |||
919 | ObjDesc->Region.Address = (ACPI_PHYSICAL_ADDRESS) |
||
920 | OperandDesc->Integer.Value; |
||
921 | AcpiUtRemoveReference (OperandDesc); |
||
922 | |||
923 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", |
||
924 | ObjDesc, |
||
925 | ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address), |
||
926 | ObjDesc->Region.Length)); |
||
927 | |||
928 | /* Now the address and length are valid for this opregion */ |
||
929 | |||
930 | ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID; |
||
931 | |||
932 | return_ACPI_STATUS (Status); |
||
933 | } |
||
934 | |||
935 | |||
936 | /******************************************************************************* |
||
937 | * |
||
938 | * FUNCTION: AcpiDsEvalTableRegionOperands |
||
939 | * |
||
940 | * PARAMETERS: WalkState - Current walk |
||
941 | * Op - A valid region Op object |
||
942 | * |
||
943 | * RETURN: Status |
||
944 | * |
||
945 | * DESCRIPTION: Get region address and length |
||
946 | * Called from AcpiDsExecEndOp during DataTableRegion parse tree walk |
||
947 | * |
||
948 | ******************************************************************************/ |
||
949 | |||
950 | ACPI_STATUS |
||
951 | AcpiDsEvalTableRegionOperands ( |
||
952 | ACPI_WALK_STATE *WalkState, |
||
953 | ACPI_PARSE_OBJECT *Op) |
||
954 | { |
||
955 | ACPI_STATUS Status; |
||
956 | ACPI_OPERAND_OBJECT *ObjDesc; |
||
957 | ACPI_OPERAND_OBJECT **Operand; |
||
958 | ACPI_NAMESPACE_NODE *Node; |
||
959 | ACPI_PARSE_OBJECT *NextOp; |
||
960 | UINT32 TableIndex; |
||
961 | ACPI_TABLE_HEADER *Table; |
||
962 | |||
963 | |||
964 | ACPI_FUNCTION_TRACE_PTR (DsEvalTableRegionOperands, Op); |
||
965 | |||
966 | |||
967 | /* |
||
968 | * This is where we evaluate the SignatureString and OemIDString |
||
969 | * and OemTableIDString of the DataTableRegion declaration |
||
970 | */ |
||
971 | Node = Op->Common.Node; |
||
972 | |||
973 | /* NextOp points to SignatureString op */ |
||
974 | |||
975 | NextOp = Op->Common.Value.Arg; |
||
976 | |||
977 | /* |
||
978 | * Evaluate/create the SignatureString and OemIDString |
||
979 | * and OemTableIDString operands |
||
980 | */ |
||
981 | Status = AcpiDsCreateOperands (WalkState, NextOp); |
||
982 | if (ACPI_FAILURE (Status)) |
||
983 | { |
||
984 | return_ACPI_STATUS (Status); |
||
985 | } |
||
986 | |||
987 | /* |
||
988 | * Resolve the SignatureString and OemIDString |
||
989 | * and OemTableIDString operands |
||
990 | */ |
||
991 | Status = AcpiExResolveOperands (Op->Common.AmlOpcode, |
||
992 | ACPI_WALK_OPERANDS, WalkState); |
||
993 | if (ACPI_FAILURE (Status)) |
||
994 | { |
||
995 | return_ACPI_STATUS (Status); |
||
996 | } |
||
997 | |||
998 | Operand = &WalkState->Operands[0]; |
||
999 | |||
1000 | /* Find the ACPI table */ |
||
1001 | |||
1002 | Status = AcpiTbFindTable (Operand[0]->String.Pointer, |
||
1003 | Operand[1]->String.Pointer, Operand[2]->String.Pointer, |
||
1004 | &TableIndex); |
||
1005 | if (ACPI_FAILURE (Status)) |
||
1006 | { |
||
1007 | return_ACPI_STATUS (Status); |
||
1008 | } |
||
1009 | |||
1010 | AcpiUtRemoveReference (Operand[0]); |
||
1011 | AcpiUtRemoveReference (Operand[1]); |
||
1012 | AcpiUtRemoveReference (Operand[2]); |
||
1013 | |||
1014 | Status = AcpiGetTableByIndex (TableIndex, &Table); |
||
1015 | if (ACPI_FAILURE (Status)) |
||
1016 | { |
||
1017 | return_ACPI_STATUS (Status); |
||
1018 | } |
||
1019 | |||
1020 | ObjDesc = AcpiNsGetAttachedObject (Node); |
||
1021 | if (!ObjDesc) |
||
1022 | { |
||
1023 | return_ACPI_STATUS (AE_NOT_EXIST); |
||
1024 | } |
||
1025 | |||
1026 | ObjDesc->Region.Address = (ACPI_PHYSICAL_ADDRESS) ACPI_TO_INTEGER (Table); |
||
1027 | ObjDesc->Region.Length = Table->Length; |
||
1028 | |||
1029 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", |
||
1030 | ObjDesc, |
||
1031 | ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address), |
||
1032 | ObjDesc->Region.Length)); |
||
1033 | |||
1034 | /* Now the address and length are valid for this opregion */ |
||
1035 | |||
1036 | ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID; |
||
1037 | |||
1038 | return_ACPI_STATUS (Status); |
||
1039 | } |
||
1040 | |||
1041 | |||
1042 | /******************************************************************************* |
||
1043 | * |
||
1044 | * FUNCTION: AcpiDsEvalDataObjectOperands |
||
1045 | * |
||
1046 | * PARAMETERS: WalkState - Current walk |
||
1047 | * Op - A valid DataObject Op object |
||
1048 | * ObjDesc - DataObject |
||
1049 | * |
||
1050 | * RETURN: Status |
||
1051 | * |
||
1052 | * DESCRIPTION: Get the operands and complete the following data object types: |
||
1053 | * Buffer, Package. |
||
1054 | * |
||
1055 | ******************************************************************************/ |
||
1056 | |||
1057 | ACPI_STATUS |
||
1058 | AcpiDsEvalDataObjectOperands ( |
||
1059 | ACPI_WALK_STATE *WalkState, |
||
1060 | ACPI_PARSE_OBJECT *Op, |
||
1061 | ACPI_OPERAND_OBJECT *ObjDesc) |
||
1062 | { |
||
1063 | ACPI_STATUS Status; |
||
1064 | ACPI_OPERAND_OBJECT *ArgDesc; |
||
1065 | UINT32 Length; |
||
1066 | |||
1067 | |||
1068 | ACPI_FUNCTION_TRACE (DsEvalDataObjectOperands); |
||
1069 | |||
1070 | |||
1071 | /* The first operand (for all of these data objects) is the length */ |
||
1072 | |||
1073 | /* |
||
1074 | * Set proper index into operand stack for AcpiDsObjStackPush |
||
1075 | * invoked inside AcpiDsCreateOperand. |
||
1076 | */ |
||
1077 | WalkState->OperandIndex = WalkState->NumOperands; |
||
1078 | |||
1079 | Status = AcpiDsCreateOperand (WalkState, Op->Common.Value.Arg, 1); |
||
1080 | if (ACPI_FAILURE (Status)) |
||
1081 | { |
||
1082 | return_ACPI_STATUS (Status); |
||
1083 | } |
||
1084 | |||
1085 | Status = AcpiExResolveOperands (WalkState->Opcode, |
||
1086 | &(WalkState->Operands [WalkState->NumOperands -1]), |
||
1087 | WalkState); |
||
1088 | if (ACPI_FAILURE (Status)) |
||
1089 | { |
||
1090 | return_ACPI_STATUS (Status); |
||
1091 | } |
||
1092 | |||
1093 | /* Extract length operand */ |
||
1094 | |||
1095 | ArgDesc = WalkState->Operands [WalkState->NumOperands - 1]; |
||
1096 | Length = (UINT32) ArgDesc->Integer.Value; |
||
1097 | |||
1098 | /* Cleanup for length operand */ |
||
1099 | |||
1100 | Status = AcpiDsObjStackPop (1, WalkState); |
||
1101 | if (ACPI_FAILURE (Status)) |
||
1102 | { |
||
1103 | return_ACPI_STATUS (Status); |
||
1104 | } |
||
1105 | |||
1106 | AcpiUtRemoveReference (ArgDesc); |
||
1107 | |||
1108 | /* |
||
1109 | * Create the actual data object |
||
1110 | */ |
||
1111 | switch (Op->Common.AmlOpcode) |
||
1112 | { |
||
1113 | case AML_BUFFER_OP: |
||
1114 | |||
1115 | Status = AcpiDsBuildInternalBufferObj (WalkState, Op, Length, &ObjDesc); |
||
1116 | break; |
||
1117 | |||
1118 | case AML_PACKAGE_OP: |
||
1119 | case AML_VAR_PACKAGE_OP: |
||
1120 | |||
1121 | Status = AcpiDsBuildInternalPackageObj (WalkState, Op, Length, &ObjDesc); |
||
1122 | break; |
||
1123 | |||
1124 | default: |
||
1125 | return_ACPI_STATUS (AE_AML_BAD_OPCODE); |
||
1126 | } |
||
1127 | |||
1128 | if (ACPI_SUCCESS (Status)) |
||
1129 | { |
||
1130 | /* |
||
1131 | * Return the object in the WalkState, unless the parent is a package - |
||
1132 | * in this case, the return object will be stored in the parse tree |
||
1133 | * for the package. |
||
1134 | */ |
||
1135 | if ((!Op->Common.Parent) || |
||
1136 | ((Op->Common.Parent->Common.AmlOpcode != AML_PACKAGE_OP) && |
||
1137 | (Op->Common.Parent->Common.AmlOpcode != AML_VAR_PACKAGE_OP) && |
||
1138 | (Op->Common.Parent->Common.AmlOpcode != AML_NAME_OP))) |
||
1139 | { |
||
1140 | WalkState->ResultObj = ObjDesc; |
||
1141 | } |
||
1142 | } |
||
1143 | |||
1144 | return_ACPI_STATUS (Status); |
||
1145 | } |
||
1146 | |||
1147 | |||
1148 | /******************************************************************************* |
||
1149 | * |
||
1150 | * FUNCTION: AcpiDsEvalBankFieldOperands |
||
1151 | * |
||
1152 | * PARAMETERS: WalkState - Current walk |
||
1153 | * Op - A valid BankField Op object |
||
1154 | * |
||
1155 | * RETURN: Status |
||
1156 | * |
||
1157 | * DESCRIPTION: Get BankField BankValue |
||
1158 | * Called from AcpiDsExecEndOp during BankField parse tree walk |
||
1159 | * |
||
1160 | ******************************************************************************/ |
||
1161 | |||
1162 | ACPI_STATUS |
||
1163 | AcpiDsEvalBankFieldOperands ( |
||
1164 | ACPI_WALK_STATE *WalkState, |
||
1165 | ACPI_PARSE_OBJECT *Op) |
||
1166 | { |
||
1167 | ACPI_STATUS Status; |
||
1168 | ACPI_OPERAND_OBJECT *ObjDesc; |
||
1169 | ACPI_OPERAND_OBJECT *OperandDesc; |
||
1170 | ACPI_NAMESPACE_NODE *Node; |
||
1171 | ACPI_PARSE_OBJECT *NextOp; |
||
1172 | ACPI_PARSE_OBJECT *Arg; |
||
1173 | |||
1174 | |||
1175 | ACPI_FUNCTION_TRACE_PTR (DsEvalBankFieldOperands, Op); |
||
1176 | |||
1177 | |||
1178 | /* |
||
1179 | * This is where we evaluate the BankValue field of the |
||
1180 | * BankField declaration |
||
1181 | */ |
||
1182 | |||
1183 | /* NextOp points to the op that holds the Region */ |
||
1184 | |||
1185 | NextOp = Op->Common.Value.Arg; |
||
1186 | |||
1187 | /* NextOp points to the op that holds the Bank Register */ |
||
1188 | |||
1189 | NextOp = NextOp->Common.Next; |
||
1190 | |||
1191 | /* NextOp points to the op that holds the Bank Value */ |
||
1192 | |||
1193 | NextOp = NextOp->Common.Next; |
||
1194 | |||
1195 | /* |
||
1196 | * Set proper index into operand stack for AcpiDsObjStackPush |
||
1197 | * invoked inside AcpiDsCreateOperand. |
||
1198 | * |
||
1199 | * We use WalkState->Operands[0] to store the evaluated BankValue |
||
1200 | */ |
||
1201 | WalkState->OperandIndex = 0; |
||
1202 | |||
1203 | Status = AcpiDsCreateOperand (WalkState, NextOp, 0); |
||
1204 | if (ACPI_FAILURE (Status)) |
||
1205 | { |
||
1206 | return_ACPI_STATUS (Status); |
||
1207 | } |
||
1208 | |||
1209 | Status = AcpiExResolveToValue (&WalkState->Operands[0], WalkState); |
||
1210 | if (ACPI_FAILURE (Status)) |
||
1211 | { |
||
1212 | return_ACPI_STATUS (Status); |
||
1213 | } |
||
1214 | |||
1215 | ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, |
||
1216 | AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 1); |
||
1217 | /* |
||
1218 | * Get the BankValue operand and save it |
||
1219 | * (at Top of stack) |
||
1220 | */ |
||
1221 | OperandDesc = WalkState->Operands[0]; |
||
1222 | |||
1223 | /* Arg points to the start Bank Field */ |
||
1224 | |||
1225 | Arg = AcpiPsGetArg (Op, 4); |
||
1226 | while (Arg) |
||
1227 | { |
||
1228 | /* Ignore OFFSET and ACCESSAS terms here */ |
||
1229 | |||
1230 | if (Arg->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) |
||
1231 | { |
||
1232 | Node = Arg->Common.Node; |
||
1233 | |||
1234 | ObjDesc = AcpiNsGetAttachedObject (Node); |
||
1235 | if (!ObjDesc) |
||
1236 | { |
||
1237 | return_ACPI_STATUS (AE_NOT_EXIST); |
||
1238 | } |
||
1239 | |||
1240 | ObjDesc->BankField.Value = (UINT32) OperandDesc->Integer.Value; |
||
1241 | } |
||
1242 | |||
1243 | /* Move to next field in the list */ |
||
1244 | |||
1245 | Arg = Arg->Common.Next; |
||
1246 | } |
||
1247 | |||
1248 | AcpiUtRemoveReference (OperandDesc); |
||
1249 | return_ACPI_STATUS (Status); |
||
1250 | } |
||
1251 | |||
1252 | |||
1253 | /******************************************************************************* |
||
1254 | * |
||
1255 | * FUNCTION: AcpiDsExecBeginControlOp |
||
1256 | * |
||
1257 | * PARAMETERS: WalkList - The list that owns the walk stack |
||
1258 | * Op - The control Op |
||
1259 | * |
||
1260 | * RETURN: Status |
||
1261 | * |
||
1262 | * DESCRIPTION: Handles all control ops encountered during control method |
||
1263 | * execution. |
||
1264 | * |
||
1265 | ******************************************************************************/ |
||
1266 | |||
1267 | ACPI_STATUS |
||
1268 | AcpiDsExecBeginControlOp ( |
||
1269 | ACPI_WALK_STATE *WalkState, |
||
1270 | ACPI_PARSE_OBJECT *Op) |
||
1271 | { |
||
1272 | ACPI_STATUS Status = AE_OK; |
||
1273 | ACPI_GENERIC_STATE *ControlState; |
||
1274 | |||
1275 | |||
1276 | ACPI_FUNCTION_NAME (DsExecBeginControlOp); |
||
1277 | |||
1278 | |||
1279 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", Op, |
||
1280 | Op->Common.AmlOpcode, WalkState)); |
||
1281 | |||
1282 | switch (Op->Common.AmlOpcode) |
||
1283 | { |
||
1284 | case AML_WHILE_OP: |
||
1285 | |||
1286 | /* |
||
1287 | * If this is an additional iteration of a while loop, continue. |
||
1288 | * There is no need to allocate a new control state. |
||
1289 | */ |
||
1290 | if (WalkState->ControlState) |
||
1291 | { |
||
1292 | if (WalkState->ControlState->Control.AmlPredicateStart == |
||
1293 | (WalkState->ParserState.Aml - 1)) |
||
1294 | { |
||
1295 | /* Reset the state to start-of-loop */ |
||
1296 | |||
1297 | WalkState->ControlState->Common.State = ACPI_CONTROL_CONDITIONAL_EXECUTING; |
||
1298 | break; |
||
1299 | } |
||
1300 | } |
||
1301 | |||
1302 | /*lint -fallthrough */ |
||
1303 | |||
1304 | case AML_IF_OP: |
||
1305 | |||
1306 | /* |
||
1307 | * IF/WHILE: Create a new control state to manage these |
||
1308 | * constructs. We need to manage these as a stack, in order |
||
1309 | * to handle nesting. |
||
1310 | */ |
||
1311 | ControlState = AcpiUtCreateControlState (); |
||
1312 | if (!ControlState) |
||
1313 | { |
||
1314 | Status = AE_NO_MEMORY; |
||
1315 | break; |
||
1316 | } |
||
1317 | /* |
||
1318 | * Save a pointer to the predicate for multiple executions |
||
1319 | * of a loop |
||
1320 | */ |
||
1321 | ControlState->Control.AmlPredicateStart = WalkState->ParserState.Aml - 1; |
||
1322 | ControlState->Control.PackageEnd = WalkState->ParserState.PkgEnd; |
||
1323 | ControlState->Control.Opcode = Op->Common.AmlOpcode; |
||
1324 | |||
1325 | |||
1326 | /* Push the control state on this walk's control stack */ |
||
1327 | |||
1328 | AcpiUtPushGenericState (&WalkState->ControlState, ControlState); |
||
1329 | break; |
||
1330 | |||
1331 | case AML_ELSE_OP: |
||
1332 | |||
1333 | /* Predicate is in the state object */ |
||
1334 | /* If predicate is true, the IF was executed, ignore ELSE part */ |
||
1335 | |||
1336 | if (WalkState->LastPredicate) |
||
1337 | { |
||
1338 | Status = AE_CTRL_TRUE; |
||
1339 | } |
||
1340 | |||
1341 | break; |
||
1342 | |||
1343 | case AML_RETURN_OP: |
||
1344 | |||
1345 | break; |
||
1346 | |||
1347 | default: |
||
1348 | break; |
||
1349 | } |
||
1350 | |||
1351 | return (Status); |
||
1352 | } |
||
1353 | |||
1354 | |||
1355 | /******************************************************************************* |
||
1356 | * |
||
1357 | * FUNCTION: AcpiDsExecEndControlOp |
||
1358 | * |
||
1359 | * PARAMETERS: WalkList - The list that owns the walk stack |
||
1360 | * Op - The control Op |
||
1361 | * |
||
1362 | * RETURN: Status |
||
1363 | * |
||
1364 | * DESCRIPTION: Handles all control ops encountered during control method |
||
1365 | * execution. |
||
1366 | * |
||
1367 | ******************************************************************************/ |
||
1368 | |||
1369 | ACPI_STATUS |
||
1370 | AcpiDsExecEndControlOp ( |
||
1371 | ACPI_WALK_STATE *WalkState, |
||
1372 | ACPI_PARSE_OBJECT *Op) |
||
1373 | { |
||
1374 | ACPI_STATUS Status = AE_OK; |
||
1375 | ACPI_GENERIC_STATE *ControlState; |
||
1376 | |||
1377 | |||
1378 | ACPI_FUNCTION_NAME (DsExecEndControlOp); |
||
1379 | |||
1380 | |||
1381 | switch (Op->Common.AmlOpcode) |
||
1382 | { |
||
1383 | case AML_IF_OP: |
||
1384 | |||
1385 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", Op)); |
||
1386 | |||
1387 | /* |
||
1388 | * Save the result of the predicate in case there is an |
||
1389 | * ELSE to come |
||
1390 | */ |
||
1391 | WalkState->LastPredicate = |
||
1392 | (BOOLEAN) WalkState->ControlState->Common.Value; |
||
1393 | |||
1394 | /* |
||
1395 | * Pop the control state that was created at the start |
||
1396 | * of the IF and free it |
||
1397 | */ |
||
1398 | ControlState = AcpiUtPopGenericState (&WalkState->ControlState); |
||
1399 | AcpiUtDeleteGenericState (ControlState); |
||
1400 | break; |
||
1401 | |||
1402 | |||
1403 | case AML_ELSE_OP: |
||
1404 | |||
1405 | break; |
||
1406 | |||
1407 | |||
1408 | case AML_WHILE_OP: |
||
1409 | |||
1410 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", Op)); |
||
1411 | |||
1412 | ControlState = WalkState->ControlState; |
||
1413 | if (ControlState->Common.Value) |
||
1414 | { |
||
1415 | /* Predicate was true, the body of the loop was just executed */ |
||
1416 | |||
1417 | /* |
||
1418 | * This loop counter mechanism allows the interpreter to escape |
||
1419 | * possibly infinite loops. This can occur in poorly written AML |
||
1420 | * when the hardware does not respond within a while loop and the |
||
1421 | * loop does not implement a timeout. |
||
1422 | */ |
||
1423 | ControlState->Control.LoopCount++; |
||
1424 | if (ControlState->Control.LoopCount > ACPI_MAX_LOOP_ITERATIONS) |
||
1425 | { |
||
1426 | Status = AE_AML_INFINITE_LOOP; |
||
1427 | break; |
||
1428 | } |
||
1429 | |||
1430 | /* |
||
1431 | * Go back and evaluate the predicate and maybe execute the loop |
||
1432 | * another time |
||
1433 | */ |
||
1434 | Status = AE_CTRL_PENDING; |
||
1435 | WalkState->AmlLastWhile = ControlState->Control.AmlPredicateStart; |
||
1436 | break; |
||
1437 | } |
||
1438 | |||
1439 | /* Predicate was false, terminate this while loop */ |
||
1440 | |||
1441 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, |
||
1442 | "[WHILE_OP] termination! Op=%p\n",Op)); |
||
1443 | |||
1444 | /* Pop this control state and free it */ |
||
1445 | |||
1446 | ControlState = AcpiUtPopGenericState (&WalkState->ControlState); |
||
1447 | AcpiUtDeleteGenericState (ControlState); |
||
1448 | break; |
||
1449 | |||
1450 | |||
1451 | case AML_RETURN_OP: |
||
1452 | |||
1453 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, |
||
1454 | "[RETURN_OP] Op=%p Arg=%p\n",Op, Op->Common.Value.Arg)); |
||
1455 | |||
1456 | /* |
||
1457 | * One optional operand -- the return value |
||
1458 | * It can be either an immediate operand or a result that |
||
1459 | * has been bubbled up the tree |
||
1460 | */ |
||
1461 | if (Op->Common.Value.Arg) |
||
1462 | { |
||
1463 | /* Since we have a real Return(), delete any implicit return */ |
||
1464 | |||
1465 | AcpiDsClearImplicitReturn (WalkState); |
||
1466 | |||
1467 | /* Return statement has an immediate operand */ |
||
1468 | |||
1469 | Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg); |
||
1470 | if (ACPI_FAILURE (Status)) |
||
1471 | { |
||
1472 | return (Status); |
||
1473 | } |
||
1474 | |||
1475 | /* |
||
1476 | * If value being returned is a Reference (such as |
||
1477 | * an arg or local), resolve it now because it may |
||
1478 | * cease to exist at the end of the method. |
||
1479 | */ |
||
1480 | Status = AcpiExResolveToValue (&WalkState->Operands [0], WalkState); |
||
1481 | if (ACPI_FAILURE (Status)) |
||
1482 | { |
||
1483 | return (Status); |
||
1484 | } |
||
1485 | |||
1486 | /* |
||
1487 | * Get the return value and save as the last result |
||
1488 | * value. This is the only place where WalkState->ReturnDesc |
||
1489 | * is set to anything other than zero! |
||
1490 | */ |
||
1491 | WalkState->ReturnDesc = WalkState->Operands[0]; |
||
1492 | } |
||
1493 | else if (WalkState->ResultCount) |
||
1494 | { |
||
1495 | /* Since we have a real Return(), delete any implicit return */ |
||
1496 | |||
1497 | AcpiDsClearImplicitReturn (WalkState); |
||
1498 | |||
1499 | /* |
||
1500 | * The return value has come from a previous calculation. |
||
1501 | * |
||
1502 | * If value being returned is a Reference (such as |
||
1503 | * an arg or local), resolve it now because it may |
||
1504 | * cease to exist at the end of the method. |
||
1505 | * |
||
1506 | * Allow references created by the Index operator to return unchanged. |
||
1507 | */ |
||
1508 | if ((ACPI_GET_DESCRIPTOR_TYPE (WalkState->Results->Results.ObjDesc[0]) == ACPI_DESC_TYPE_OPERAND) && |
||
1509 | ((WalkState->Results->Results.ObjDesc [0])->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && |
||
1510 | ((WalkState->Results->Results.ObjDesc [0])->Reference.Class != ACPI_REFCLASS_INDEX)) |
||
1511 | { |
||
1512 | Status = AcpiExResolveToValue (&WalkState->Results->Results.ObjDesc [0], WalkState); |
||
1513 | if (ACPI_FAILURE (Status)) |
||
1514 | { |
||
1515 | return (Status); |
||
1516 | } |
||
1517 | } |
||
1518 | |||
1519 | WalkState->ReturnDesc = WalkState->Results->Results.ObjDesc [0]; |
||
1520 | } |
||
1521 | else |
||
1522 | { |
||
1523 | /* No return operand */ |
||
1524 | |||
1525 | if (WalkState->NumOperands) |
||
1526 | { |
||
1527 | AcpiUtRemoveReference (WalkState->Operands [0]); |
||
1528 | } |
||
1529 | |||
1530 | WalkState->Operands [0] = NULL; |
||
1531 | WalkState->NumOperands = 0; |
||
1532 | WalkState->ReturnDesc = NULL; |
||
1533 | } |
||
1534 | |||
1535 | |||
1536 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, |
||
1537 | "Completed RETURN_OP State=%p, RetVal=%p\n", |
||
1538 | WalkState, WalkState->ReturnDesc)); |
||
1539 | |||
1540 | /* End the control method execution right now */ |
||
1541 | |||
1542 | Status = AE_CTRL_TERMINATE; |
||
1543 | break; |
||
1544 | |||
1545 | |||
1546 | case AML_NOOP_OP: |
||
1547 | |||
1548 | /* Just do nothing! */ |
||
1549 | break; |
||
1550 | |||
1551 | |||
1552 | case AML_BREAK_POINT_OP: |
||
1553 | |||
1554 | /* |
||
1555 | * Set the single-step flag. This will cause the debugger (if present) |
||
1556 | * to break to the console within the AML debugger at the start of the |
||
1557 | * next AML instruction. |
||
1558 | */ |
||
1559 | ACPI_DEBUGGER_EXEC ( |
||
1560 | AcpiGbl_CmSingleStep = TRUE); |
||
1561 | ACPI_DEBUGGER_EXEC ( |
||
1562 | AcpiOsPrintf ("**break** Executed AML BreakPoint opcode\n")); |
||
1563 | |||
1564 | /* Call to the OSL in case OS wants a piece of the action */ |
||
1565 | |||
1566 | Status = AcpiOsSignal (ACPI_SIGNAL_BREAKPOINT, |
||
1567 | "Executed AML Breakpoint opcode"); |
||
1568 | break; |
||
1569 | |||
1570 | |||
1571 | case AML_BREAK_OP: |
||
1572 | case AML_CONTINUE_OP: /* ACPI 2.0 */ |
||
1573 | |||
1574 | |||
1575 | /* Pop and delete control states until we find a while */ |
||
1576 | |||
1577 | while (WalkState->ControlState && |
||
1578 | (WalkState->ControlState->Control.Opcode != AML_WHILE_OP)) |
||
1579 | { |
||
1580 | ControlState = AcpiUtPopGenericState (&WalkState->ControlState); |
||
1581 | AcpiUtDeleteGenericState (ControlState); |
||
1582 | } |
||
1583 | |||
1584 | /* No while found? */ |
||
1585 | |||
1586 | if (!WalkState->ControlState) |
||
1587 | { |
||
1588 | return (AE_AML_NO_WHILE); |
||
1589 | } |
||
1590 | |||
1591 | /* Was: WalkState->AmlLastWhile = WalkState->ControlState->Control.AmlPredicateStart; */ |
||
1592 | |||
1593 | WalkState->AmlLastWhile = WalkState->ControlState->Control.PackageEnd; |
||
1594 | |||
1595 | /* Return status depending on opcode */ |
||
1596 | |||
1597 | if (Op->Common.AmlOpcode == AML_BREAK_OP) |
||
1598 | { |
||
1599 | Status = AE_CTRL_BREAK; |
||
1600 | } |
||
1601 | else |
||
1602 | { |
||
1603 | Status = AE_CTRL_CONTINUE; |
||
1604 | } |
||
1605 | break; |
||
1606 | |||
1607 | |||
1608 | default: |
||
1609 | |||
1610 | ACPI_ERROR ((AE_INFO, "Unknown control opcode=0x%X Op=%p", |
||
1611 | Op->Common.AmlOpcode, Op)); |
||
1612 | |||
1613 | Status = AE_AML_BAD_OPCODE; |
||
1614 | break; |
||
1615 | } |
||
1616 | |||
1617 | return (Status); |
||
1618 | } |
||
1619 |