Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/acpica/components/dispatcher/dsutils.c
48521 views
1
/*******************************************************************************
2
*
3
* Module Name: dsutils - Dispatcher utilities
4
*
5
******************************************************************************/
6
7
/******************************************************************************
8
*
9
* 1. Copyright Notice
10
*
11
* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
12
* All rights reserved.
13
*
14
* 2. License
15
*
16
* 2.1. This is your license from Intel Corp. under its intellectual property
17
* rights. You may have additional license terms from the party that provided
18
* you this software, covering your right to use that party's intellectual
19
* property rights.
20
*
21
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22
* copy of the source code appearing in this file ("Covered Code") an
23
* irrevocable, perpetual, worldwide license under Intel's copyrights in the
24
* base code distributed originally by Intel ("Original Intel Code") to copy,
25
* make derivatives, distribute, use and display any portion of the Covered
26
* Code in any form, with the right to sublicense such rights; and
27
*
28
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29
* license (with the right to sublicense), under only those claims of Intel
30
* patents that are infringed by the Original Intel Code, to make, use, sell,
31
* offer to sell, and import the Covered Code and derivative works thereof
32
* solely to the minimum extent necessary to exercise the above copyright
33
* license, and in no event shall the patent license extend to any additions
34
* to or modifications of the Original Intel Code. No other license or right
35
* is granted directly or by implication, estoppel or otherwise;
36
*
37
* The above copyright and patent license is granted only if the following
38
* conditions are met:
39
*
40
* 3. Conditions
41
*
42
* 3.1. Redistribution of Source with Rights to Further Distribute Source.
43
* Redistribution of source code of any substantial portion of the Covered
44
* Code or modification with rights to further distribute source must include
45
* the above Copyright Notice, the above License, this list of Conditions,
46
* and the following Disclaimer and Export Compliance provision. In addition,
47
* Licensee must cause all Covered Code to which Licensee contributes to
48
* contain a file documenting the changes Licensee made to create that Covered
49
* Code and the date of any change. Licensee must include in that file the
50
* documentation of any changes made by any predecessor Licensee. Licensee
51
* must include a prominent statement that the modification is derived,
52
* directly or indirectly, from Original Intel Code.
53
*
54
* 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55
* Redistribution of source code of any substantial portion of the Covered
56
* Code or modification without rights to further distribute source must
57
* include the following Disclaimer and Export Compliance provision in the
58
* documentation and/or other materials provided with distribution. In
59
* addition, Licensee may not authorize further sublicense of source of any
60
* portion of the Covered Code, and must include terms to the effect that the
61
* license from Licensee to its licensee is limited to the intellectual
62
* property embodied in the software Licensee provides to its licensee, and
63
* not to intellectual property embodied in modifications its licensee may
64
* make.
65
*
66
* 3.3. Redistribution of Executable. Redistribution in executable form of any
67
* substantial portion of the Covered Code or modification must reproduce the
68
* above Copyright Notice, and the following Disclaimer and Export Compliance
69
* provision in the documentation and/or other materials provided with the
70
* distribution.
71
*
72
* 3.4. Intel retains all right, title, and interest in and to the Original
73
* Intel Code.
74
*
75
* 3.5. Neither the name Intel nor any other trademark owned or controlled by
76
* Intel shall be used in advertising or otherwise to promote the sale, use or
77
* other dealings in products derived from or relating to the Covered Code
78
* without prior written authorization from Intel.
79
*
80
* 4. Disclaimer and Export Compliance
81
*
82
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88
* PARTICULAR PURPOSE.
89
*
90
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97
* LIMITED REMEDY.
98
*
99
* 4.3. Licensee shall not export, either directly or indirectly, any of this
100
* software or system incorporating such software without first obtaining any
101
* required license or other approval from the U. S. Department of Commerce or
102
* any other agency or department of the United States Government. In the
103
* event Licensee exports any such software from the United States or
104
* re-exports any such software from a foreign destination, Licensee shall
105
* ensure that the distribution and export/re-export of the software is in
106
* compliance with all laws, regulations, orders, or other restrictions of the
107
* U.S. Export Administration Regulations. Licensee agrees that neither it nor
108
* any of its subsidiaries will export/re-export any technical data, process,
109
* software, or service, directly or indirectly, to any country for which the
110
* United States government or any agency thereof requires an export license,
111
* other governmental approval, or letter of assurance, without first obtaining
112
* such license, approval or letter.
113
*
114
*****************************************************************************
115
*
116
* Alternatively, you may choose to be licensed under the terms of the
117
* following license:
118
*
119
* Redistribution and use in source and binary forms, with or without
120
* modification, are permitted provided that the following conditions
121
* are met:
122
* 1. Redistributions of source code must retain the above copyright
123
* notice, this list of conditions, and the following disclaimer,
124
* without modification.
125
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
126
* substantially similar to the "NO WARRANTY" disclaimer below
127
* ("Disclaimer") and any redistribution must be conditioned upon
128
* including a substantially similar Disclaimer requirement for further
129
* binary redistribution.
130
* 3. Neither the names of the above-listed copyright holders nor the names
131
* of any contributors may be used to endorse or promote products derived
132
* from this software without specific prior written permission.
133
*
134
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145
*
146
* Alternatively, you may choose to be licensed under the terms of the
147
* GNU General Public License ("GPL") version 2 as published by the Free
148
* Software Foundation.
149
*
150
*****************************************************************************/
151
152
#include <contrib/dev/acpica/include/acpi.h>
153
#include <contrib/dev/acpica/include/accommon.h>
154
#include <contrib/dev/acpica/include/acparser.h>
155
#include <contrib/dev/acpica/include/amlcode.h>
156
#include <contrib/dev/acpica/include/acdispat.h>
157
#include <contrib/dev/acpica/include/acinterp.h>
158
#include <contrib/dev/acpica/include/acnamesp.h>
159
#include <contrib/dev/acpica/include/acdebug.h>
160
161
#define _COMPONENT ACPI_DISPATCHER
162
ACPI_MODULE_NAME ("dsutils")
163
164
165
/*******************************************************************************
166
*
167
* FUNCTION: AcpiDsClearImplicitReturn
168
*
169
* PARAMETERS: WalkState - Current State
170
*
171
* RETURN: None.
172
*
173
* DESCRIPTION: Clear and remove a reference on an implicit return value. Used
174
* to delete "stale" return values (if enabled, the return value
175
* from every operator is saved at least momentarily, in case the
176
* parent method exits.)
177
*
178
******************************************************************************/
179
180
void
181
AcpiDsClearImplicitReturn (
182
ACPI_WALK_STATE *WalkState)
183
{
184
ACPI_FUNCTION_NAME (DsClearImplicitReturn);
185
186
187
/*
188
* Slack must be enabled for this feature
189
*/
190
if (!AcpiGbl_EnableInterpreterSlack)
191
{
192
return;
193
}
194
195
if (WalkState->ImplicitReturnObj)
196
{
197
/*
198
* Delete any "stale" implicit return. However, in
199
* complex statements, the implicit return value can be
200
* bubbled up several levels.
201
*/
202
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
203
"Removing reference on stale implicit return obj %p\n",
204
WalkState->ImplicitReturnObj));
205
206
AcpiUtRemoveReference (WalkState->ImplicitReturnObj);
207
WalkState->ImplicitReturnObj = NULL;
208
}
209
}
210
211
212
/*******************************************************************************
213
*
214
* FUNCTION: AcpiDsDoImplicitReturn
215
*
216
* PARAMETERS: ReturnDesc - The return value
217
* WalkState - Current State
218
* AddReference - True if a reference should be added to the
219
* return object
220
*
221
* RETURN: TRUE if implicit return enabled, FALSE otherwise
222
*
223
* DESCRIPTION: Implements the optional "implicit return". We save the result
224
* of every ASL operator and control method invocation in case the
225
* parent method exit. Before storing a new return value, we
226
* delete the previous return value.
227
*
228
******************************************************************************/
229
230
BOOLEAN
231
AcpiDsDoImplicitReturn (
232
ACPI_OPERAND_OBJECT *ReturnDesc,
233
ACPI_WALK_STATE *WalkState,
234
BOOLEAN AddReference)
235
{
236
ACPI_FUNCTION_NAME (DsDoImplicitReturn);
237
238
239
/*
240
* Slack must be enabled for this feature, and we must
241
* have a valid return object
242
*/
243
if ((!AcpiGbl_EnableInterpreterSlack) ||
244
(!ReturnDesc))
245
{
246
return (FALSE);
247
}
248
249
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
250
"Result %p will be implicitly returned; Prev=%p\n",
251
ReturnDesc,
252
WalkState->ImplicitReturnObj));
253
254
/*
255
* Delete any "stale" implicit return value first. However, in
256
* complex statements, the implicit return value can be
257
* bubbled up several levels, so we don't clear the value if it
258
* is the same as the ReturnDesc.
259
*/
260
if (WalkState->ImplicitReturnObj)
261
{
262
if (WalkState->ImplicitReturnObj == ReturnDesc)
263
{
264
return (TRUE);
265
}
266
AcpiDsClearImplicitReturn (WalkState);
267
}
268
269
/* Save the implicit return value, add a reference if requested */
270
271
WalkState->ImplicitReturnObj = ReturnDesc;
272
if (AddReference)
273
{
274
AcpiUtAddReference (ReturnDesc);
275
}
276
277
return (TRUE);
278
}
279
280
281
/*******************************************************************************
282
*
283
* FUNCTION: AcpiDsIsResultUsed
284
*
285
* PARAMETERS: Op - Current Op
286
* WalkState - Current State
287
*
288
* RETURN: TRUE if result is used, FALSE otherwise
289
*
290
* DESCRIPTION: Check if a result object will be used by the parent
291
*
292
******************************************************************************/
293
294
BOOLEAN
295
AcpiDsIsResultUsed (
296
ACPI_PARSE_OBJECT *Op,
297
ACPI_WALK_STATE *WalkState)
298
{
299
const ACPI_OPCODE_INFO *ParentInfo;
300
301
ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op);
302
303
304
/* Must have both an Op and a Result Object */
305
306
if (!Op)
307
{
308
ACPI_ERROR ((AE_INFO, "Null Op"));
309
return_UINT8 (TRUE);
310
}
311
312
/*
313
* We know that this operator is not a
314
* Return() operator (would not come here.) The following code is the
315
* optional support for a so-called "implicit return". Some AML code
316
* assumes that the last value of the method is "implicitly" returned
317
* to the caller. Just save the last result as the return value.
318
* NOTE: this is optional because the ASL language does not actually
319
* support this behavior.
320
*/
321
(void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE);
322
323
/*
324
* Now determine if the parent will use the result
325
*
326
* If there is no parent, or the parent is a ScopeOp, we are executing
327
* at the method level. An executing method typically has no parent,
328
* since each method is parsed separately. A method invoked externally
329
* via ExecuteControlMethod has a ScopeOp as the parent.
330
*/
331
if ((!Op->Common.Parent) ||
332
(Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
333
{
334
/* No parent, the return value cannot possibly be used */
335
336
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
337
"At Method level, result of [%s] not used\n",
338
AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
339
return_UINT8 (FALSE);
340
}
341
342
/* Get info on the parent. The RootOp is AML_SCOPE */
343
344
ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
345
if (ParentInfo->Class == AML_CLASS_UNKNOWN)
346
{
347
ACPI_ERROR ((AE_INFO,
348
"Unknown parent opcode Op=%p", Op));
349
return_UINT8 (FALSE);
350
}
351
352
/*
353
* Decide what to do with the result based on the parent. If
354
* the parent opcode will not use the result, delete the object.
355
* Otherwise leave it as is, it will be deleted when it is used
356
* as an operand later.
357
*/
358
switch (ParentInfo->Class)
359
{
360
case AML_CLASS_CONTROL:
361
362
switch (Op->Common.Parent->Common.AmlOpcode)
363
{
364
case AML_RETURN_OP:
365
366
/* Never delete the return value associated with a return opcode */
367
368
goto ResultUsed;
369
370
case AML_IF_OP:
371
case AML_WHILE_OP:
372
/*
373
* If we are executing the predicate AND this is the predicate op,
374
* we will use the return value
375
*/
376
if ((WalkState->ControlState->Common.State ==
377
ACPI_CONTROL_PREDICATE_EXECUTING) &&
378
(WalkState->ControlState->Control.PredicateOp == Op))
379
{
380
goto ResultUsed;
381
}
382
break;
383
384
default:
385
386
/* Ignore other control opcodes */
387
388
break;
389
}
390
391
/* The general control opcode returns no result */
392
393
goto ResultNotUsed;
394
395
case AML_CLASS_CREATE:
396
/*
397
* These opcodes allow TermArg(s) as operands and therefore
398
* the operands can be method calls. The result is used.
399
*/
400
goto ResultUsed;
401
402
case AML_CLASS_NAMED_OBJECT:
403
404
if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) ||
405
(Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) ||
406
(Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
407
(Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) ||
408
(Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP) ||
409
(Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) ||
410
(Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP))
411
{
412
/*
413
* These opcodes allow TermArg(s) as operands and therefore
414
* the operands can be method calls. The result is used.
415
*/
416
goto ResultUsed;
417
}
418
419
goto ResultNotUsed;
420
421
default:
422
/*
423
* In all other cases. the parent will actually use the return
424
* object, so keep it.
425
*/
426
goto ResultUsed;
427
}
428
429
430
ResultUsed:
431
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
432
"Result of [%s] used by Parent [%s] Op=%p\n",
433
AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
434
AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
435
436
return_UINT8 (TRUE);
437
438
439
ResultNotUsed:
440
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
441
"Result of [%s] not used by Parent [%s] Op=%p\n",
442
AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
443
AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
444
445
return_UINT8 (FALSE);
446
}
447
448
449
/*******************************************************************************
450
*
451
* FUNCTION: AcpiDsDeleteResultIfNotUsed
452
*
453
* PARAMETERS: Op - Current parse Op
454
* ResultObj - Result of the operation
455
* WalkState - Current state
456
*
457
* RETURN: Status
458
*
459
* DESCRIPTION: Used after interpretation of an opcode. If there is an internal
460
* result descriptor, check if the parent opcode will actually use
461
* this result. If not, delete the result now so that it will
462
* not become orphaned.
463
*
464
******************************************************************************/
465
466
void
467
AcpiDsDeleteResultIfNotUsed (
468
ACPI_PARSE_OBJECT *Op,
469
ACPI_OPERAND_OBJECT *ResultObj,
470
ACPI_WALK_STATE *WalkState)
471
{
472
ACPI_OPERAND_OBJECT *ObjDesc;
473
ACPI_STATUS Status;
474
475
476
ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj);
477
478
479
if (!Op)
480
{
481
ACPI_ERROR ((AE_INFO, "Null Op"));
482
return_VOID;
483
}
484
485
if (!ResultObj)
486
{
487
return_VOID;
488
}
489
490
if (!AcpiDsIsResultUsed (Op, WalkState))
491
{
492
/* Must pop the result stack (ObjDesc should be equal to ResultObj) */
493
494
Status = AcpiDsResultPop (&ObjDesc, WalkState);
495
if (ACPI_SUCCESS (Status))
496
{
497
AcpiUtRemoveReference (ResultObj);
498
}
499
}
500
501
return_VOID;
502
}
503
504
505
/*******************************************************************************
506
*
507
* FUNCTION: AcpiDsResolveOperands
508
*
509
* PARAMETERS: WalkState - Current walk state with operands on stack
510
*
511
* RETURN: Status
512
*
513
* DESCRIPTION: Resolve all operands to their values. Used to prepare
514
* arguments to a control method invocation (a call from one
515
* method to another.)
516
*
517
******************************************************************************/
518
519
ACPI_STATUS
520
AcpiDsResolveOperands (
521
ACPI_WALK_STATE *WalkState)
522
{
523
UINT32 i;
524
ACPI_STATUS Status = AE_OK;
525
526
527
ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState);
528
529
530
/*
531
* Attempt to resolve each of the valid operands
532
* Method arguments are passed by reference, not by value. This means
533
* that the actual objects are passed, not copies of the objects.
534
*/
535
for (i = 0; i < WalkState->NumOperands; i++)
536
{
537
Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState);
538
if (ACPI_FAILURE (Status))
539
{
540
break;
541
}
542
}
543
544
return_ACPI_STATUS (Status);
545
}
546
547
548
/*******************************************************************************
549
*
550
* FUNCTION: AcpiDsClearOperands
551
*
552
* PARAMETERS: WalkState - Current walk state with operands on stack
553
*
554
* RETURN: None
555
*
556
* DESCRIPTION: Clear all operands on the current walk state operand stack.
557
*
558
******************************************************************************/
559
560
void
561
AcpiDsClearOperands (
562
ACPI_WALK_STATE *WalkState)
563
{
564
UINT32 i;
565
566
567
ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState);
568
569
570
/* Remove a reference on each operand on the stack */
571
572
for (i = 0; i < WalkState->NumOperands; i++)
573
{
574
/*
575
* Remove a reference to all operands, including both
576
* "Arguments" and "Targets".
577
*/
578
AcpiUtRemoveReference (WalkState->Operands[i]);
579
WalkState->Operands[i] = NULL;
580
}
581
582
WalkState->NumOperands = 0;
583
return_VOID;
584
}
585
586
587
/*******************************************************************************
588
*
589
* FUNCTION: AcpiDsCreateOperand
590
*
591
* PARAMETERS: WalkState - Current walk state
592
* Arg - Parse object for the argument
593
* ArgIndex - Which argument (zero based)
594
*
595
* RETURN: Status
596
*
597
* DESCRIPTION: Translate a parse tree object that is an argument to an AML
598
* opcode to the equivalent interpreter object. This may include
599
* looking up a name or entering a new name into the internal
600
* namespace.
601
*
602
******************************************************************************/
603
604
ACPI_STATUS
605
AcpiDsCreateOperand (
606
ACPI_WALK_STATE *WalkState,
607
ACPI_PARSE_OBJECT *Arg,
608
UINT32 ArgIndex)
609
{
610
ACPI_STATUS Status = AE_OK;
611
char *NameString;
612
UINT32 NameLength;
613
ACPI_OPERAND_OBJECT *ObjDesc;
614
ACPI_PARSE_OBJECT *ParentOp;
615
UINT16 Opcode;
616
ACPI_INTERPRETER_MODE InterpreterMode;
617
const ACPI_OPCODE_INFO *OpInfo;
618
619
620
ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg);
621
622
623
/* A valid name must be looked up in the namespace */
624
625
if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
626
(Arg->Common.Value.String) &&
627
!(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
628
{
629
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg));
630
631
/* Get the entire name string from the AML stream */
632
633
Status = AcpiExGetNameString (ACPI_TYPE_ANY,
634
Arg->Common.Value.Buffer, &NameString, &NameLength);
635
636
if (ACPI_FAILURE (Status))
637
{
638
return_ACPI_STATUS (Status);
639
}
640
641
/* All prefixes have been handled, and the name is in NameString */
642
643
/*
644
* Special handling for BufferField declarations. This is a deferred
645
* opcode that unfortunately defines the field name as the last
646
* parameter instead of the first. We get here when we are performing
647
* the deferred execution, so the actual name of the field is already
648
* in the namespace. We don't want to attempt to look it up again
649
* because we may be executing in a different scope than where the
650
* actual opcode exists.
651
*/
652
if ((WalkState->DeferredNode) &&
653
(WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) &&
654
(ArgIndex == (UINT32)
655
((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2)))
656
{
657
ObjDesc = ACPI_CAST_PTR (
658
ACPI_OPERAND_OBJECT, WalkState->DeferredNode);
659
Status = AE_OK;
660
}
661
else /* All other opcodes */
662
{
663
/*
664
* Differentiate between a namespace "create" operation
665
* versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
666
* IMODE_EXECUTE) in order to support the creation of
667
* namespace objects during the execution of control methods.
668
*/
669
ParentOp = Arg->Common.Parent;
670
OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
671
672
if ((OpInfo->Flags & AML_NSNODE) &&
673
(ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
674
(ParentOp->Common.AmlOpcode != AML_REGION_OP) &&
675
(ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
676
{
677
/* Enter name into namespace if not found */
678
679
InterpreterMode = ACPI_IMODE_LOAD_PASS2;
680
}
681
else
682
{
683
/* Return a failure if name not found */
684
685
InterpreterMode = ACPI_IMODE_EXECUTE;
686
}
687
688
Status = AcpiNsLookup (WalkState->ScopeInfo, NameString,
689
ACPI_TYPE_ANY, InterpreterMode,
690
ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, WalkState,
691
ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc));
692
/*
693
* The only case where we pass through (ignore) a NOT_FOUND
694
* error is for the CondRefOf opcode.
695
*/
696
if (Status == AE_NOT_FOUND)
697
{
698
if (ParentOp->Common.AmlOpcode == AML_CONDITIONAL_REF_OF_OP)
699
{
700
/*
701
* For the Conditional Reference op, it's OK if
702
* the name is not found; We just need a way to
703
* indicate this to the interpreter, set the
704
* object to the root
705
*/
706
ObjDesc = ACPI_CAST_PTR (
707
ACPI_OPERAND_OBJECT, AcpiGbl_RootNode);
708
Status = AE_OK;
709
}
710
else if (ParentOp->Common.AmlOpcode == AML_EXTERNAL_OP)
711
{
712
/*
713
* This opcode should never appear here. It is used only
714
* by AML disassemblers and is surrounded by an If(0)
715
* by the ASL compiler.
716
*
717
* Therefore, if we see it here, it is a serious error.
718
*/
719
Status = AE_AML_BAD_OPCODE;
720
}
721
else
722
{
723
/*
724
* We just plain didn't find it -- which is a
725
* very serious error at this point
726
*/
727
Status = AE_AML_NAME_NOT_FOUND;
728
}
729
}
730
731
if (ACPI_FAILURE (Status))
732
{
733
ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
734
NameString, Status);
735
}
736
}
737
738
/* Free the namestring created above */
739
740
ACPI_FREE (NameString);
741
742
/* Check status from the lookup */
743
744
if (ACPI_FAILURE (Status))
745
{
746
return_ACPI_STATUS (Status);
747
}
748
749
/* Put the resulting object onto the current object stack */
750
751
Status = AcpiDsObjStackPush (ObjDesc, WalkState);
752
if (ACPI_FAILURE (Status))
753
{
754
return_ACPI_STATUS (Status);
755
}
756
757
AcpiDbDisplayArgumentObject (ObjDesc, WalkState);
758
}
759
else
760
{
761
/* Check for null name case */
762
763
if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
764
!(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
765
{
766
/*
767
* If the name is null, this means that this is an
768
* optional result parameter that was not specified
769
* in the original ASL. Create a Zero Constant for a
770
* placeholder. (Store to a constant is a Noop.)
771
*/
772
Opcode = AML_ZERO_OP; /* Has no arguments! */
773
774
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
775
"Null namepath: Arg=%p\n", Arg));
776
}
777
else
778
{
779
Opcode = Arg->Common.AmlOpcode;
780
}
781
782
/* Get the object type of the argument */
783
784
OpInfo = AcpiPsGetOpcodeInfo (Opcode);
785
if (OpInfo->ObjectType == ACPI_TYPE_INVALID)
786
{
787
return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
788
}
789
790
if ((OpInfo->Flags & AML_HAS_RETVAL) ||
791
(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
792
{
793
/*
794
* Use value that was already previously returned
795
* by the evaluation of this argument
796
*/
797
Status = AcpiDsResultPop (&ObjDesc, WalkState);
798
if (ACPI_FAILURE (Status))
799
{
800
/*
801
* Only error is underflow, and this indicates
802
* a missing or null operand!
803
*/
804
ACPI_EXCEPTION ((AE_INFO, Status,
805
"Missing or null operand"));
806
return_ACPI_STATUS (Status);
807
}
808
}
809
else
810
{
811
/* Create an ACPI_INTERNAL_OBJECT for the argument */
812
813
ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType);
814
if (!ObjDesc)
815
{
816
return_ACPI_STATUS (AE_NO_MEMORY);
817
}
818
819
/* Initialize the new object */
820
821
Status = AcpiDsInitObjectFromOp (
822
WalkState, Arg, Opcode, &ObjDesc);
823
if (ACPI_FAILURE (Status))
824
{
825
AcpiUtDeleteObjectDesc (ObjDesc);
826
return_ACPI_STATUS (Status);
827
}
828
}
829
830
/* Put the operand object on the object stack */
831
832
Status = AcpiDsObjStackPush (ObjDesc, WalkState);
833
if (ACPI_FAILURE (Status))
834
{
835
return_ACPI_STATUS (Status);
836
}
837
838
AcpiDbDisplayArgumentObject (ObjDesc, WalkState);
839
}
840
841
return_ACPI_STATUS (AE_OK);
842
}
843
844
845
/*******************************************************************************
846
*
847
* FUNCTION: AcpiDsCreateOperands
848
*
849
* PARAMETERS: WalkState - Current state
850
* FirstArg - First argument of a parser argument tree
851
*
852
* RETURN: Status
853
*
854
* DESCRIPTION: Convert an operator's arguments from a parse tree format to
855
* namespace objects and place those argument object on the object
856
* stack in preparation for evaluation by the interpreter.
857
*
858
******************************************************************************/
859
860
ACPI_STATUS
861
AcpiDsCreateOperands (
862
ACPI_WALK_STATE *WalkState,
863
ACPI_PARSE_OBJECT *FirstArg)
864
{
865
ACPI_STATUS Status = AE_OK;
866
ACPI_PARSE_OBJECT *Arg;
867
ACPI_PARSE_OBJECT *Arguments[ACPI_OBJ_NUM_OPERANDS];
868
UINT32 ArgCount = 0;
869
UINT32 Index = WalkState->NumOperands;
870
UINT32 PrevNumOperands = WalkState->NumOperands;
871
UINT32 NewNumOperands;
872
UINT32 i;
873
874
875
ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg);
876
877
878
/* Get all arguments in the list */
879
880
Arg = FirstArg;
881
while (Arg)
882
{
883
if (Index >= ACPI_OBJ_NUM_OPERANDS)
884
{
885
return_ACPI_STATUS (AE_BAD_DATA);
886
}
887
888
Arguments[Index] = Arg;
889
WalkState->Operands [Index] = NULL;
890
891
/* Move on to next argument, if any */
892
893
Arg = Arg->Common.Next;
894
ArgCount++;
895
Index++;
896
}
897
898
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
899
"NumOperands %d, ArgCount %d, Index %d\n",
900
WalkState->NumOperands, ArgCount, Index));
901
902
/* Create the interpreter arguments, in reverse order */
903
904
NewNumOperands = Index;
905
Index--;
906
for (i = 0; i < ArgCount; i++)
907
{
908
Arg = Arguments[Index];
909
WalkState->OperandIndex = (UINT8) Index;
910
911
Status = AcpiDsCreateOperand (WalkState, Arg, Index);
912
if (ACPI_FAILURE (Status))
913
{
914
goto Cleanup;
915
}
916
917
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
918
"Created Arg #%u (%p) %u args total\n",
919
Index, Arg, ArgCount));
920
Index--;
921
}
922
923
return_ACPI_STATUS (Status);
924
925
926
Cleanup:
927
/*
928
* We must undo everything done above; meaning that we must
929
* pop everything off of the operand stack and delete those
930
* objects
931
*/
932
WalkState->NumOperands = (UINT8) (i);
933
AcpiDsObjStackPopAndDelete (NewNumOperands, WalkState);
934
935
/* Restore operand count */
936
WalkState->NumOperands = (UINT8) (PrevNumOperands);
937
938
ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index));
939
return_ACPI_STATUS (Status);
940
}
941
942
943
/*****************************************************************************
944
*
945
* FUNCTION: AcpiDsEvaluateNamePath
946
*
947
* PARAMETERS: WalkState - Current state of the parse tree walk,
948
* the opcode of current operation should be
949
* AML_INT_NAMEPATH_OP
950
*
951
* RETURN: Status
952
*
953
* DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent
954
* interpreter object, convert it to value, if needed, duplicate
955
* it, if needed, and push it onto the current result stack.
956
*
957
****************************************************************************/
958
959
ACPI_STATUS
960
AcpiDsEvaluateNamePath (
961
ACPI_WALK_STATE *WalkState)
962
{
963
ACPI_STATUS Status = AE_OK;
964
ACPI_PARSE_OBJECT *Op = WalkState->Op;
965
ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];
966
ACPI_OPERAND_OBJECT *NewObjDesc;
967
UINT8 Type;
968
969
970
ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState);
971
972
973
if (!Op->Common.Parent)
974
{
975
/* This happens after certain exception processing */
976
977
goto Exit;
978
}
979
980
if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
981
(Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP) ||
982
(Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP))
983
{
984
/* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */
985
986
goto Exit;
987
}
988
989
Status = AcpiDsCreateOperand (WalkState, Op, 0);
990
if (ACPI_FAILURE (Status))
991
{
992
goto Exit;
993
}
994
995
if (Op->Common.Flags & ACPI_PARSEOP_TARGET)
996
{
997
NewObjDesc = *Operand;
998
goto PushResult;
999
}
1000
1001
Type = (*Operand)->Common.Type;
1002
1003
Status = AcpiExResolveToValue (Operand, WalkState);
1004
if (ACPI_FAILURE (Status))
1005
{
1006
goto Exit;
1007
}
1008
1009
if (Type == ACPI_TYPE_INTEGER)
1010
{
1011
/* It was incremented by AcpiExResolveToValue */
1012
1013
AcpiUtRemoveReference (*Operand);
1014
1015
Status = AcpiUtCopyIobjectToIobject (
1016
*Operand, &NewObjDesc, WalkState);
1017
if (ACPI_FAILURE (Status))
1018
{
1019
goto Exit;
1020
}
1021
}
1022
else
1023
{
1024
/*
1025
* The object either was anew created or is
1026
* a Namespace node - don't decrement it.
1027
*/
1028
NewObjDesc = *Operand;
1029
}
1030
1031
/* Cleanup for name-path operand */
1032
1033
Status = AcpiDsObjStackPop (1, WalkState);
1034
if (ACPI_FAILURE (Status))
1035
{
1036
WalkState->ResultObj = NewObjDesc;
1037
goto Exit;
1038
}
1039
1040
PushResult:
1041
1042
WalkState->ResultObj = NewObjDesc;
1043
1044
Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
1045
if (ACPI_SUCCESS (Status))
1046
{
1047
/* Force to take it from stack */
1048
1049
Op->Common.Flags |= ACPI_PARSEOP_IN_STACK;
1050
}
1051
1052
Exit:
1053
1054
return_ACPI_STATUS (Status);
1055
}
1056
1057