1 /******************************************************************************
2 *
3 * Module Name: dswload - Dispatcher namespace load callbacks
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 #include "aslcompiler.h"
45 #include "amlcode.h"
46 #include "acdispat.h"
47 #include "acnamesp.h"
48
49 #include "aslcompiler.y.h"
50
51 #define _COMPONENT ACPI_COMPILER
52 ACPI_MODULE_NAME ("aslload")
53
54 /* Local prototypes */
55
56 static ACPI_STATUS
57 LdLoadFieldElements (
58 ACPI_PARSE_OBJECT *Op,
59 ACPI_WALK_STATE *WalkState);
60
61 static ACPI_STATUS
62 LdLoadResourceElements (
63 ACPI_PARSE_OBJECT *Op,
64 ACPI_WALK_STATE *WalkState);
65
66 static ACPI_STATUS
67 LdNamespace1Begin (
68 ACPI_PARSE_OBJECT *Op,
69 UINT32 Level,
70 void *Context);
71
72 static ACPI_STATUS
73 LdNamespace2Begin (
74 ACPI_PARSE_OBJECT *Op,
75 UINT32 Level,
76 void *Context);
77
78 static ACPI_STATUS
79 LdCommonNamespaceEnd (
80 ACPI_PARSE_OBJECT *Op,
81 UINT32 Level,
82 void *Context);
83
84
85 /*******************************************************************************
86 *
87 * FUNCTION: LdLoadNamespace
88 *
89 * PARAMETERS: RootOp - Root of the parse tree
90 *
91 * RETURN: Status
92 *
93 * DESCRIPTION: Perform a walk of the parse tree that in turn loads all of the
94 * named ASL/AML objects into the namespace. The namespace is
95 * constructed in order to resolve named references and references
96 * to named fields within resource templates/descriptors.
97 *
98 ******************************************************************************/
99
100 ACPI_STATUS
LdLoadNamespace(ACPI_PARSE_OBJECT * RootOp)101 LdLoadNamespace (
102 ACPI_PARSE_OBJECT *RootOp)
103 {
104 ACPI_WALK_STATE *WalkState;
105
106
107 DbgPrint (ASL_DEBUG_OUTPUT, "\nCreating namespace\n\n");
108
109 /* Create a new walk state */
110
111 WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
112 if (!WalkState)
113 {
114 return (AE_NO_MEMORY);
115 }
116
117 /* Walk the entire parse tree, first pass */
118
119 TrWalkParseTree (RootOp, ASL_WALK_VISIT_TWICE, LdNamespace1Begin,
120 LdCommonNamespaceEnd, WalkState);
121
122 /* Second pass to handle forward references */
123
124 TrWalkParseTree (RootOp, ASL_WALK_VISIT_TWICE, LdNamespace2Begin,
125 LdCommonNamespaceEnd, WalkState);
126
127 /* Dump the namespace if debug is enabled */
128
129 AcpiNsDumpTables (ACPI_NS_ALL, ACPI_UINT32_MAX);
130 ACPI_FREE (WalkState);
131 return (AE_OK);
132 }
133
134
135 /*******************************************************************************
136 *
137 * FUNCTION: LdLoadFieldElements
138 *
139 * PARAMETERS: Op - Parent node (Field)
140 * WalkState - Current walk state
141 *
142 * RETURN: Status
143 *
144 * DESCRIPTION: Enter the named elements of the field (children of the parent)
145 * into the namespace.
146 *
147 ******************************************************************************/
148
149 static ACPI_STATUS
LdLoadFieldElements(ACPI_PARSE_OBJECT * Op,ACPI_WALK_STATE * WalkState)150 LdLoadFieldElements (
151 ACPI_PARSE_OBJECT *Op,
152 ACPI_WALK_STATE *WalkState)
153 {
154 ACPI_PARSE_OBJECT *Child = NULL;
155 ACPI_NAMESPACE_NODE *Node;
156 ACPI_STATUS Status;
157
158
159 /* Get the first named field element */
160
161 switch (Op->Asl.AmlOpcode)
162 {
163 case AML_BANK_FIELD_OP:
164
165 Child = UtGetArg (Op, 6);
166 break;
167
168 case AML_INDEX_FIELD_OP:
169
170 Child = UtGetArg (Op, 5);
171 break;
172
173 case AML_FIELD_OP:
174
175 Child = UtGetArg (Op, 4);
176 break;
177
178 default:
179
180 /* No other opcodes should arrive here */
181
182 return (AE_BAD_PARAMETER);
183 }
184
185 /* Enter all elements into the namespace */
186
187 while (Child)
188 {
189 switch (Child->Asl.AmlOpcode)
190 {
191 case AML_INT_RESERVEDFIELD_OP:
192 case AML_INT_ACCESSFIELD_OP:
193 case AML_INT_CONNECTION_OP:
194 break;
195
196 default:
197
198 Status = AcpiNsLookup (WalkState->ScopeInfo,
199 Child->Asl.Value.String,
200 ACPI_TYPE_LOCAL_REGION_FIELD,
201 ACPI_IMODE_LOAD_PASS1,
202 ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
203 ACPI_NS_ERROR_IF_FOUND, NULL, &Node);
204 if (ACPI_FAILURE (Status))
205 {
206 if (Status != AE_ALREADY_EXISTS)
207 {
208 AslError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, Child,
209 Child->Asl.Value.String);
210 return (Status);
211 }
212
213 /*
214 * The name already exists in this scope
215 * But continue processing the elements
216 */
217 AslError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Child,
218 Child->Asl.Value.String);
219 }
220 else
221 {
222 Child->Asl.Node = Node;
223 Node->Op = Child;
224 }
225 break;
226 }
227
228 Child = Child->Asl.Next;
229 }
230
231 return (AE_OK);
232 }
233
234
235 /*******************************************************************************
236 *
237 * FUNCTION: LdLoadResourceElements
238 *
239 * PARAMETERS: Op - Parent node (Resource Descriptor)
240 * WalkState - Current walk state
241 *
242 * RETURN: Status
243 *
244 * DESCRIPTION: Enter the named elements of the resource descriptor (children
245 * of the parent) into the namespace.
246 *
247 * NOTE: In the real AML namespace, these named elements never exist. But
248 * we simply use the namespace here as a symbol table so we can look
249 * them up as they are referenced.
250 *
251 ******************************************************************************/
252
253 static ACPI_STATUS
LdLoadResourceElements(ACPI_PARSE_OBJECT * Op,ACPI_WALK_STATE * WalkState)254 LdLoadResourceElements (
255 ACPI_PARSE_OBJECT *Op,
256 ACPI_WALK_STATE *WalkState)
257 {
258 ACPI_PARSE_OBJECT *InitializerOp = NULL;
259 ACPI_NAMESPACE_NODE *Node;
260 ACPI_STATUS Status;
261
262
263 /*
264 * Enter the resource name into the namespace. Name must not already exist.
265 * This opens a scope, so later field names are guaranteed to be new/unique.
266 */
267 Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Asl.Namepath,
268 ACPI_TYPE_LOCAL_RESOURCE, ACPI_IMODE_LOAD_PASS1,
269 ACPI_NS_NO_UPSEARCH | ACPI_NS_ERROR_IF_FOUND,
270 WalkState, &Node);
271 if (ACPI_FAILURE (Status))
272 {
273 if (Status == AE_ALREADY_EXISTS)
274 {
275 /* Actual node causing the error was saved in ParentMethod */
276
277 AslError (ASL_ERROR, ASL_MSG_NAME_EXISTS,
278 (ACPI_PARSE_OBJECT *) Op->Asl.ParentMethod, Op->Asl.Namepath);
279 return (AE_OK);
280 }
281 return (Status);
282 }
283
284 Node->Value = (UINT32) Op->Asl.Value.Integer;
285 Node->Op = Op;
286 Op->Asl.Node = Node;
287
288 /*
289 * Now enter the predefined fields, for easy lookup when referenced
290 * by the source ASL
291 */
292 InitializerOp = ASL_GET_CHILD_NODE (Op);
293 while (InitializerOp)
294 {
295 if (InitializerOp->Asl.ExternalName)
296 {
297 Status = AcpiNsLookup (WalkState->ScopeInfo,
298 InitializerOp->Asl.ExternalName,
299 ACPI_TYPE_LOCAL_RESOURCE_FIELD,
300 ACPI_IMODE_LOAD_PASS1,
301 ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE,
302 NULL, &Node);
303 if (ACPI_FAILURE (Status))
304 {
305 return (Status);
306 }
307
308 /*
309 * Store the field offset and length in the namespace node
310 * so it can be used when the field is referenced
311 */
312 Node->Value = InitializerOp->Asl.Value.Tag.BitOffset;
313 Node->Length = InitializerOp->Asl.Value.Tag.BitLength;
314 InitializerOp->Asl.Node = Node;
315 Node->Op = InitializerOp;
316 }
317
318 InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
319 }
320
321 return (AE_OK);
322 }
323
324
325 /*******************************************************************************
326 *
327 * FUNCTION: LdNamespace1Begin
328 *
329 * PARAMETERS: ASL_WALK_CALLBACK
330 *
331 * RETURN: Status
332 *
333 * DESCRIPTION: Descending callback used during the parse tree walk. If this
334 * is a named AML opcode, enter into the namespace
335 *
336 ******************************************************************************/
337
338 static ACPI_STATUS
LdNamespace1Begin(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)339 LdNamespace1Begin (
340 ACPI_PARSE_OBJECT *Op,
341 UINT32 Level,
342 void *Context)
343 {
344 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context;
345 ACPI_NAMESPACE_NODE *Node;
346 ACPI_PARSE_OBJECT *MethodOp;
347 ACPI_STATUS Status;
348 ACPI_OBJECT_TYPE ObjectType;
349 ACPI_OBJECT_TYPE ActualObjectType = ACPI_TYPE_ANY;
350 char *Path;
351 UINT32 Flags = ACPI_NS_NO_UPSEARCH;
352 ACPI_PARSE_OBJECT *Arg;
353 UINT32 i;
354 BOOLEAN ForceNewScope = FALSE;
355
356
357 ACPI_FUNCTION_NAME (LdNamespace1Begin);
358 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n",
359 Op, Op->Asl.ParseOpName));
360
361 /*
362 * We are only interested in opcodes that have an associated name
363 * (or multiple names)
364 */
365 switch (Op->Asl.AmlOpcode)
366 {
367 case AML_BANK_FIELD_OP:
368 case AML_INDEX_FIELD_OP:
369 case AML_FIELD_OP:
370
371 Status = LdLoadFieldElements (Op, WalkState);
372 return (Status);
373
374 case AML_INT_CONNECTION_OP:
375
376
377 if (Op->Asl.Child->Asl.AmlOpcode != AML_INT_NAMEPATH_OP)
378 {
379 break;
380 }
381 Arg = Op->Asl.Child;
382
383 Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Asl.ExternalName,
384 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
385 WalkState, &Node);
386 if (ACPI_FAILURE (Status))
387 {
388 break;
389 }
390
391 if (Node->Type == ACPI_TYPE_BUFFER)
392 {
393 Arg->Asl.Node = Node;
394
395 Arg = Node->Op->Asl.Child; /* Get namepath */
396 Arg = Arg->Asl.Next; /* Get actual buffer */
397 Arg = Arg->Asl.Child; /* Buffer length */
398 Arg = Arg->Asl.Next; /* RAW_DATA buffer */
399 }
400 break;
401
402 default:
403
404 /* All other opcodes go below */
405
406 break;
407 }
408
409 /* Check if this object has already been installed in the namespace */
410
411 if (Op->Asl.Node)
412 {
413 return (AE_OK);
414 }
415
416 Path = Op->Asl.Namepath;
417 if (!Path)
418 {
419 return (AE_OK);
420 }
421
422 /* Map the raw opcode into an internal object type */
423
424 switch (Op->Asl.ParseOpcode)
425 {
426 case PARSEOP_NAME:
427
428 Arg = Op->Asl.Child; /* Get the NameSeg/NameString node */
429 Arg = Arg->Asl.Next; /* First peer is the object to be associated with the name */
430
431 /*
432 * If this name refers to a ResourceTemplate, we will need to open
433 * a new scope so that the resource subfield names can be entered into
434 * the namespace underneath this name
435 */
436 if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
437 {
438 ForceNewScope = TRUE;
439 }
440
441 /* Get the data type associated with the named object, not the name itself */
442
443 /* Log2 loop to convert from Btype (binary) to Etype (encoded) */
444
445 ObjectType = 1;
446 for (i = 1; i < Arg->Asl.AcpiBtype; i *= 2)
447 {
448 ObjectType++;
449 }
450 break;
451
452
453 case PARSEOP_EXTERNAL:
454 /*
455 * "External" simply enters a name and type into the namespace.
456 * We must be careful to not open a new scope, however, no matter
457 * what type the external name refers to (e.g., a method)
458 *
459 * first child is name, next child is ObjectType
460 */
461 ActualObjectType = (UINT8) Op->Asl.Child->Asl.Next->Asl.Value.Integer;
462 ObjectType = ACPI_TYPE_ANY;
463
464 /*
465 * We will mark every new node along the path as "External". This
466 * allows some or all of the nodes to be created later in the ASL
467 * code. Handles cases like this:
468 *
469 * External (\_SB_.PCI0.ABCD, IntObj)
470 * Scope (_SB_)
471 * {
472 * Device (PCI0)
473 * {
474 * }
475 * }
476 * Method (X)
477 * {
478 * Store (\_SB_.PCI0.ABCD, Local0)
479 * }
480 */
481 Flags |= ACPI_NS_EXTERNAL;
482 break;
483
484 case PARSEOP_DEFAULT_ARG:
485
486 if (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC)
487 {
488 Status = LdLoadResourceElements (Op, WalkState);
489 return_ACPI_STATUS (Status);
490 }
491
492 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
493 break;
494
495 case PARSEOP_SCOPE:
496 /*
497 * The name referenced by Scope(Name) must already exist at this point.
498 * In other words, forward references for Scope() are not supported.
499 * The only real reason for this is that the MS interpreter cannot
500 * handle this case. Perhaps someday this case can go away.
501 */
502 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
503 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
504 WalkState, &(Node));
505 if (ACPI_FAILURE (Status))
506 {
507 if (Status == AE_NOT_FOUND)
508 {
509 /* The name was not found, go ahead and create it */
510
511 Status = AcpiNsLookup (WalkState->ScopeInfo, Path,
512 ACPI_TYPE_LOCAL_SCOPE,
513 ACPI_IMODE_LOAD_PASS1, Flags,
514 WalkState, &(Node));
515 if (ACPI_FAILURE (Status))
516 {
517 return_ACPI_STATUS (Status);
518 }
519
520 /*
521 * However, this is an error -- primarily because the MS
522 * interpreter can't handle a forward reference from the
523 * Scope() operator.
524 */
525 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
526 Op->Asl.ExternalName);
527 AslError (ASL_ERROR, ASL_MSG_SCOPE_FWD_REF, Op,
528 Op->Asl.ExternalName);
529 goto FinishNode;
530 }
531
532 AslCoreSubsystemError (Op, Status,
533 "Failure from namespace lookup", FALSE);
534
535 return_ACPI_STATUS (Status);
536 }
537 else /* Status AE_OK */
538 {
539 /*
540 * Do not allow references to external scopes from the DSDT.
541 * This is because the DSDT is always loaded first, and the
542 * external reference cannot be resolved -- causing a runtime
543 * error because Scope() must be resolved immediately.
544 * 10/2015.
545 */
546 if ((Node->Flags & ANOBJ_IS_EXTERNAL) &&
547 (ACPI_COMPARE_NAME (Gbl_TableSignature, "DSDT")))
548 {
549 /* However, allowed if the reference is within a method */
550
551 MethodOp = Op->Asl.Parent;
552 while (MethodOp &&
553 (MethodOp->Asl.ParseOpcode != PARSEOP_METHOD))
554 {
555 MethodOp = MethodOp->Asl.Parent;
556 }
557
558 if (!MethodOp)
559 {
560 /* Not in a control method, error */
561
562 AslError (ASL_ERROR, ASL_MSG_CROSS_TABLE_SCOPE, Op, NULL);
563 }
564 }
565 }
566
567 /* We found a node with this name, now check the type */
568
569 switch (Node->Type)
570 {
571 case ACPI_TYPE_LOCAL_SCOPE:
572 case ACPI_TYPE_DEVICE:
573 case ACPI_TYPE_POWER:
574 case ACPI_TYPE_PROCESSOR:
575 case ACPI_TYPE_THERMAL:
576
577 /* These are acceptable types - they all open a new scope */
578 break;
579
580 case ACPI_TYPE_INTEGER:
581 case ACPI_TYPE_STRING:
582 case ACPI_TYPE_BUFFER:
583 /*
584 * These types we will allow, but we will change the type.
585 * This enables some existing code of the form:
586 *
587 * Name (DEB, 0)
588 * Scope (DEB) { ... }
589 *
590 * Which is used to workaround the fact that the MS interpreter
591 * does not allow Scope() forward references.
592 */
593 sprintf (MsgBuffer, "%s [%s], changing type to [Scope]",
594 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
595 AslError (ASL_REMARK, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer);
596
597 /* Switch the type to scope, open the new scope */
598
599 Node->Type = ACPI_TYPE_LOCAL_SCOPE;
600 Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE,
601 WalkState);
602 if (ACPI_FAILURE (Status))
603 {
604 return_ACPI_STATUS (Status);
605 }
606 break;
607
608 default:
609
610 /* All other types are an error */
611
612 sprintf (MsgBuffer, "%s [%s]", Op->Asl.ExternalName,
613 AcpiUtGetTypeName (Node->Type));
614 AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer);
615
616 /*
617 * However, switch the type to be an actual scope so
618 * that compilation can continue without generating a whole
619 * cascade of additional errors. Open the new scope.
620 */
621 Node->Type = ACPI_TYPE_LOCAL_SCOPE;
622 Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE,
623 WalkState);
624 if (ACPI_FAILURE (Status))
625 {
626 return_ACPI_STATUS (Status);
627 }
628 break;
629 }
630
631 Status = AE_OK;
632 goto FinishNode;
633
634
635 default:
636
637 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
638 break;
639 }
640
641
642 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Loading name: %s, (%s)\n",
643 Op->Asl.ExternalName, AcpiUtGetTypeName (ObjectType)));
644
645 /* The name must not already exist */
646
647 Flags |= ACPI_NS_ERROR_IF_FOUND;
648
649 /*
650 * Enter the named type into the internal namespace. We enter the name
651 * as we go downward in the parse tree. Any necessary subobjects that
652 * involve arguments to the opcode must be created as we go back up the
653 * parse tree later.
654 */
655 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
656 ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node);
657 if (ACPI_FAILURE (Status))
658 {
659 if (Status == AE_ALREADY_EXISTS)
660 {
661 /* The name already exists in this scope */
662
663 if (Node->Type == ACPI_TYPE_LOCAL_SCOPE)
664 {
665 /* Allow multiple references to the same scope */
666
667 Node->Type = (UINT8) ObjectType;
668 Status = AE_OK;
669 }
670 else if ((Node->Flags & ANOBJ_IS_EXTERNAL) &&
671 (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL))
672 {
673 /*
674 * Allow one create on an object or segment that was
675 * previously declared External
676 */
677 Node->Flags &= ~ANOBJ_IS_EXTERNAL;
678 Node->Type = (UINT8) ObjectType;
679
680 /* Just retyped a node, probably will need to open a scope */
681
682 if (AcpiNsOpensScope (ObjectType))
683 {
684 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState);
685 if (ACPI_FAILURE (Status))
686 {
687 return_ACPI_STATUS (Status);
688 }
689 }
690
691 Status = AE_OK;
692 }
693 else if (!(Node->Flags & ANOBJ_IS_EXTERNAL) &&
694 (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL))
695 {
696 /*
697 * Allow externals in same scope as the definition of the
698 * actual object. Similar to C. Allows multiple definition
699 * blocks that refer to each other in the same file.
700 */
701 Status = AE_OK;
702 }
703 else
704 {
705 /* Valid error, object already exists */
706
707 AslError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Op,
708 Op->Asl.ExternalName);
709 return_ACPI_STATUS (AE_OK);
710 }
711 }
712 else
713 {
714 AslCoreSubsystemError (Op, Status,
715 "Failure from namespace lookup", FALSE);
716 return_ACPI_STATUS (Status);
717 }
718 }
719
720 if (ForceNewScope)
721 {
722 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState);
723 if (ACPI_FAILURE (Status))
724 {
725 return_ACPI_STATUS (Status);
726 }
727 }
728
729 FinishNode:
730 /*
731 * Point the parse node to the new namespace node, and point
732 * the Node back to the original Parse node
733 */
734 Op->Asl.Node = Node;
735 Node->Op = Op;
736
737 /* Set the actual data type if appropriate (EXTERNAL term only) */
738
739 if (ActualObjectType != ACPI_TYPE_ANY)
740 {
741 Node->Type = (UINT8) ActualObjectType;
742 Node->Value = ASL_EXTERNAL_METHOD;
743 }
744
745 if (Op->Asl.ParseOpcode == PARSEOP_METHOD)
746 {
747 /*
748 * Get the method argument count from "Extra" and save
749 * it in the namespace node
750 */
751 Node->Value = (UINT32) Op->Asl.Extra;
752 }
753
754 return_ACPI_STATUS (Status);
755 }
756
757
758 /*******************************************************************************
759 *
760 * FUNCTION: LdNamespace2Begin
761 *
762 * PARAMETERS: ASL_WALK_CALLBACK
763 *
764 * RETURN: Status
765 *
766 * DESCRIPTION: Descending callback used during the pass 2 parse tree walk.
767 * Second pass resolves some forward references.
768 *
769 * Notes:
770 * Currently only needs to handle the Alias operator.
771 * Could be used to allow forward references from the Scope() operator, but
772 * the MS interpreter does not allow this, so this compiler does not either.
773 *
774 ******************************************************************************/
775
776 static ACPI_STATUS
LdNamespace2Begin(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)777 LdNamespace2Begin (
778 ACPI_PARSE_OBJECT *Op,
779 UINT32 Level,
780 void *Context)
781 {
782 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context;
783 ACPI_STATUS Status;
784 ACPI_NAMESPACE_NODE *Node;
785 ACPI_OBJECT_TYPE ObjectType;
786 BOOLEAN ForceNewScope = FALSE;
787 ACPI_PARSE_OBJECT *Arg;
788 char *Path;
789 ACPI_NAMESPACE_NODE *TargetNode;
790
791
792 ACPI_FUNCTION_NAME (LdNamespace2Begin);
793 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n",
794 Op, Op->Asl.ParseOpName));
795
796
797 /* Ignore Ops with no namespace node */
798
799 Node = Op->Asl.Node;
800 if (!Node)
801 {
802 return (AE_OK);
803 }
804
805 /* Get the type to determine if we should push the scope */
806
807 if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) &&
808 (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC))
809 {
810 ObjectType = ACPI_TYPE_LOCAL_RESOURCE;
811 }
812 else
813 {
814 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
815 }
816
817 /* Push scope for Resource Templates */
818
819 if (Op->Asl.ParseOpcode == PARSEOP_NAME)
820 {
821 if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
822 {
823 ForceNewScope = TRUE;
824 }
825 }
826
827 /* Push the scope stack */
828
829 if (ForceNewScope || AcpiNsOpensScope (ObjectType))
830 {
831 Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState);
832 if (ACPI_FAILURE (Status))
833 {
834 return_ACPI_STATUS (Status);
835 }
836 }
837
838 if (Op->Asl.ParseOpcode == PARSEOP_ALIAS)
839 {
840 /* Complete the alias node by getting and saving the target node */
841
842 /* First child is the alias target */
843
844 Arg = Op->Asl.Child;
845
846 /* Get the target pathname */
847
848 Path = Arg->Asl.Namepath;
849 if (!Path)
850 {
851 Status = UtInternalizeName (Arg->Asl.ExternalName, &Path);
852 if (ACPI_FAILURE (Status))
853 {
854 return (Status);
855 }
856 }
857
858 /* Get the NS node associated with the target. It must exist. */
859
860 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
861 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
862 WalkState, &TargetNode);
863 if (ACPI_FAILURE (Status))
864 {
865 if (Status == AE_NOT_FOUND)
866 {
867 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
868 Op->Asl.ExternalName);
869
870 /*
871 * The name was not found, go ahead and create it.
872 * This prevents more errors later.
873 */
874 Status = AcpiNsLookup (WalkState->ScopeInfo, Path,
875 ACPI_TYPE_ANY,
876 ACPI_IMODE_LOAD_PASS1, ACPI_NS_NO_UPSEARCH,
877 WalkState, &(Node));
878 return (AE_OK);
879 }
880
881 AslCoreSubsystemError (Op, Status,
882 "Failure from namespace lookup", FALSE);
883 return (AE_OK);
884 }
885
886 /* Save the target node within the alias node */
887
888 Node->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode);
889 }
890
891 return (AE_OK);
892 }
893
894
895 /*******************************************************************************
896 *
897 * FUNCTION: LdCommonNamespaceEnd
898 *
899 * PARAMETERS: ASL_WALK_CALLBACK
900 *
901 * RETURN: Status
902 *
903 * DESCRIPTION: Ascending callback used during the loading of the namespace,
904 * We only need to worry about managing the scope stack here.
905 *
906 ******************************************************************************/
907
908 static ACPI_STATUS
LdCommonNamespaceEnd(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)909 LdCommonNamespaceEnd (
910 ACPI_PARSE_OBJECT *Op,
911 UINT32 Level,
912 void *Context)
913 {
914 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context;
915 ACPI_OBJECT_TYPE ObjectType;
916 BOOLEAN ForceNewScope = FALSE;
917
918
919 ACPI_FUNCTION_NAME (LdCommonNamespaceEnd);
920
921
922 /* We are only interested in opcodes that have an associated name */
923
924 if (!Op->Asl.Namepath)
925 {
926 return (AE_OK);
927 }
928
929 /* Get the type to determine if we should pop the scope */
930
931 if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) &&
932 (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC))
933 {
934 /* TBD: Merge into AcpiDsMapNamedOpcodeToDataType */
935
936 ObjectType = ACPI_TYPE_LOCAL_RESOURCE;
937 }
938 else
939 {
940 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
941 }
942
943 /* Pop scope that was pushed for Resource Templates */
944
945 if (Op->Asl.ParseOpcode == PARSEOP_NAME)
946 {
947 if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
948 {
949 ForceNewScope = TRUE;
950 }
951 }
952
953 /* Pop the scope stack */
954
955 if (ForceNewScope || AcpiNsOpensScope (ObjectType))
956 {
957 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
958 "(%s): Popping scope for Op [%s] %p\n",
959 AcpiUtGetTypeName (ObjectType), Op->Asl.ParseOpName, Op));
960
961 (void) AcpiDsScopeStackPop (WalkState);
962 }
963
964 return (AE_OK);
965 }
966