Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/acpica/components/namespace/nsaccess.c
48524 views
1
/*******************************************************************************
2
*
3
* Module Name: nsaccess - Top-level functions for accessing ACPI namespace
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/amlcode.h>
155
#include <contrib/dev/acpica/include/acnamesp.h>
156
#include <contrib/dev/acpica/include/acdispat.h>
157
158
#ifdef ACPI_ASL_COMPILER
159
#include <contrib/dev/acpica/include/acdisasm.h>
160
#endif
161
162
#define _COMPONENT ACPI_NAMESPACE
163
ACPI_MODULE_NAME ("nsaccess")
164
165
166
/*******************************************************************************
167
*
168
* FUNCTION: AcpiNsRootInitialize
169
*
170
* PARAMETERS: None
171
*
172
* RETURN: Status
173
*
174
* DESCRIPTION: Allocate and initialize the default root named objects
175
*
176
* MUTEX: Locks namespace for entire execution
177
*
178
******************************************************************************/
179
180
ACPI_STATUS
181
AcpiNsRootInitialize (
182
void)
183
{
184
ACPI_STATUS Status;
185
const ACPI_PREDEFINED_NAMES *InitVal = NULL;
186
ACPI_NAMESPACE_NODE *NewNode;
187
ACPI_NAMESPACE_NODE *PrevNode = NULL;
188
ACPI_OPERAND_OBJECT *ObjDesc;
189
ACPI_STRING Val = NULL;
190
191
192
ACPI_FUNCTION_TRACE (NsRootInitialize);
193
194
195
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
196
if (ACPI_FAILURE (Status))
197
{
198
return_ACPI_STATUS (Status);
199
}
200
201
/*
202
* The global root ptr is initially NULL, so a non-NULL value indicates
203
* that AcpiNsRootInitialize() has already been called; just return.
204
*/
205
if (AcpiGbl_RootNode)
206
{
207
Status = AE_OK;
208
goto UnlockAndExit;
209
}
210
211
/*
212
* Tell the rest of the subsystem that the root is initialized
213
* (This is OK because the namespace is locked)
214
*/
215
AcpiGbl_RootNode = &AcpiGbl_RootNodeStruct;
216
217
/* Enter the predefined names in the name table */
218
219
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
220
"Entering predefined entries into namespace\n"));
221
222
/*
223
* Create the initial (default) namespace.
224
* This namespace looks like something similar to this:
225
*
226
* ACPI Namespace (from Namespace Root):
227
* 0 _GPE Scope 00203160 00
228
* 0 _PR_ Scope 002031D0 00
229
* 0 _SB_ Device 00203240 00 Notify Object: 0020ADD8
230
* 0 _SI_ Scope 002032B0 00
231
* 0 _TZ_ Device 00203320 00
232
* 0 _REV Integer 00203390 00 = 0000000000000002
233
* 0 _OS_ String 00203488 00 Len 14 "Microsoft Windows NT"
234
* 0 _GL_ Mutex 00203580 00 Object 002035F0
235
* 0 _OSI Method 00203678 00 Args 1 Len 0000 Aml 00000000
236
*/
237
for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++)
238
{
239
Status = AE_OK;
240
241
/* _OSI is optional for now, will be permanent later */
242
243
if (!strcmp (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod)
244
{
245
continue;
246
}
247
248
/*
249
* Create, init, and link the new predefined name
250
* Note: No need to use AcpiNsLookup here because all the
251
* predefined names are at the root level. It is much easier to
252
* just create and link the new node(s) here.
253
*/
254
NewNode = AcpiNsCreateNode (*ACPI_CAST_PTR (UINT32, InitVal->Name));
255
if (!NewNode)
256
{
257
Status = AE_NO_MEMORY;
258
goto UnlockAndExit;
259
}
260
261
NewNode->DescriptorType = ACPI_DESC_TYPE_NAMED;
262
NewNode->Type = InitVal->Type;
263
264
if (!PrevNode)
265
{
266
AcpiGbl_RootNodeStruct.Child = NewNode;
267
}
268
else
269
{
270
PrevNode->Peer = NewNode;
271
}
272
273
NewNode->Parent = &AcpiGbl_RootNodeStruct;
274
PrevNode = NewNode;
275
276
/*
277
* Name entered successfully. If entry in PreDefinedNames[] specifies
278
* an initial value, create the initial value.
279
*/
280
if (InitVal->Val)
281
{
282
Status = AcpiOsPredefinedOverride (InitVal, &Val);
283
if (ACPI_FAILURE (Status))
284
{
285
ACPI_ERROR ((AE_INFO,
286
"Could not override predefined %s",
287
InitVal->Name));
288
}
289
290
if (!Val)
291
{
292
Val = InitVal->Val;
293
}
294
295
/*
296
* Entry requests an initial value, allocate a
297
* descriptor for it.
298
*/
299
ObjDesc = AcpiUtCreateInternalObject (InitVal->Type);
300
if (!ObjDesc)
301
{
302
Status = AE_NO_MEMORY;
303
goto UnlockAndExit;
304
}
305
306
/*
307
* Convert value string from table entry to
308
* internal representation. Only types actually
309
* used for initial values are implemented here.
310
*/
311
switch (InitVal->Type)
312
{
313
case ACPI_TYPE_METHOD:
314
315
ObjDesc->Method.ParamCount = (UINT8) ACPI_TO_INTEGER (Val);
316
ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID;
317
318
#if defined (ACPI_ASL_COMPILER)
319
320
/* Save the parameter count for the iASL compiler */
321
322
NewNode->Value = ObjDesc->Method.ParamCount;
323
#else
324
/* Mark this as a very SPECIAL method (_OSI) */
325
326
ObjDesc->Method.InfoFlags = ACPI_METHOD_INTERNAL_ONLY;
327
ObjDesc->Method.Dispatch.Implementation = AcpiUtOsiImplementation;
328
#endif
329
break;
330
331
case ACPI_TYPE_INTEGER:
332
333
ObjDesc->Integer.Value = ACPI_TO_INTEGER (Val);
334
break;
335
336
case ACPI_TYPE_STRING:
337
338
/* Build an object around the static string */
339
340
ObjDesc->String.Length = (UINT32) strlen (Val);
341
ObjDesc->String.Pointer = Val;
342
ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
343
break;
344
345
case ACPI_TYPE_MUTEX:
346
347
ObjDesc->Mutex.Node = NewNode;
348
ObjDesc->Mutex.SyncLevel = (UINT8) (ACPI_TO_INTEGER (Val) - 1);
349
350
/* Create a mutex */
351
352
Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex);
353
if (ACPI_FAILURE (Status))
354
{
355
AcpiUtRemoveReference (ObjDesc);
356
goto UnlockAndExit;
357
}
358
359
/* Special case for ACPI Global Lock */
360
361
if (strcmp (InitVal->Name, "_GL_") == 0)
362
{
363
AcpiGbl_GlobalLockMutex = ObjDesc;
364
365
/* Create additional counting semaphore for global lock */
366
367
Status = AcpiOsCreateSemaphore (
368
1, 0, &AcpiGbl_GlobalLockSemaphore);
369
if (ACPI_FAILURE (Status))
370
{
371
AcpiUtRemoveReference (ObjDesc);
372
goto UnlockAndExit;
373
}
374
}
375
break;
376
377
default:
378
379
ACPI_ERROR ((AE_INFO, "Unsupported initial type value 0x%X",
380
InitVal->Type));
381
AcpiUtRemoveReference (ObjDesc);
382
ObjDesc = NULL;
383
continue;
384
}
385
386
/* Store pointer to value descriptor in the Node */
387
388
Status = AcpiNsAttachObject (NewNode, ObjDesc,
389
ObjDesc->Common.Type);
390
391
/* Remove local reference to the object */
392
393
AcpiUtRemoveReference (ObjDesc);
394
}
395
}
396
397
UnlockAndExit:
398
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
399
400
/* Save a handle to "_GPE", it is always present */
401
402
if (ACPI_SUCCESS (Status))
403
{
404
Status = AcpiNsGetNode (NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH,
405
&AcpiGbl_FadtGpeDevice);
406
}
407
408
return_ACPI_STATUS (Status);
409
}
410
411
412
/*******************************************************************************
413
*
414
* FUNCTION: AcpiNsLookup
415
*
416
* PARAMETERS: ScopeInfo - Current scope info block
417
* Pathname - Search pathname, in internal format
418
* (as represented in the AML stream)
419
* Type - Type associated with name
420
* InterpreterMode - IMODE_LOAD_PASS2 => add name if not found
421
* Flags - Flags describing the search restrictions
422
* WalkState - Current state of the walk
423
* ReturnNode - Where the Node is placed (if found
424
* or created successfully)
425
*
426
* RETURN: Status
427
*
428
* DESCRIPTION: Find or enter the passed name in the name space.
429
* Log an error if name not found in Exec mode.
430
*
431
* MUTEX: Assumes namespace is locked.
432
*
433
******************************************************************************/
434
435
ACPI_STATUS
436
AcpiNsLookup (
437
ACPI_GENERIC_STATE *ScopeInfo,
438
char *Pathname,
439
ACPI_OBJECT_TYPE Type,
440
ACPI_INTERPRETER_MODE InterpreterMode,
441
UINT32 Flags,
442
ACPI_WALK_STATE *WalkState,
443
ACPI_NAMESPACE_NODE **ReturnNode)
444
{
445
ACPI_STATUS Status;
446
char *Path = Pathname;
447
char *ExternalPath;
448
ACPI_NAMESPACE_NODE *PrefixNode;
449
ACPI_NAMESPACE_NODE *CurrentNode = NULL;
450
ACPI_NAMESPACE_NODE *ThisNode = NULL;
451
UINT32 NumSegments;
452
#ifdef ACPI_DEBUG_OUTPUT
453
UINT32 NumCarats;
454
#endif
455
ACPI_NAME SimpleName;
456
ACPI_OBJECT_TYPE TypeToCheckFor;
457
ACPI_OBJECT_TYPE ThisSearchType;
458
UINT32 SearchParentFlag = ACPI_NS_SEARCH_PARENT;
459
UINT32 LocalFlags;
460
ACPI_INTERPRETER_MODE LocalInterpreterMode;
461
462
463
ACPI_FUNCTION_TRACE (NsLookup);
464
465
466
if (!ReturnNode)
467
{
468
return_ACPI_STATUS (AE_BAD_PARAMETER);
469
}
470
471
LocalFlags = Flags &
472
~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_OVERRIDE_IF_FOUND |
473
ACPI_NS_SEARCH_PARENT);
474
*ReturnNode = ACPI_ENTRY_NOT_FOUND;
475
AcpiGbl_NsLookupCount++;
476
477
if (!AcpiGbl_RootNode)
478
{
479
return_ACPI_STATUS (AE_NO_NAMESPACE);
480
}
481
482
/* Get the prefix scope. A null scope means use the root scope */
483
484
if ((!ScopeInfo) ||
485
(!ScopeInfo->Scope.Node))
486
{
487
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
488
"Null scope prefix, using root node (%p)\n",
489
AcpiGbl_RootNode));
490
491
PrefixNode = AcpiGbl_RootNode;
492
}
493
else
494
{
495
PrefixNode = ScopeInfo->Scope.Node;
496
if (ACPI_GET_DESCRIPTOR_TYPE (PrefixNode) != ACPI_DESC_TYPE_NAMED)
497
{
498
ACPI_ERROR ((AE_INFO, "%p is not a namespace node [%s]",
499
PrefixNode, AcpiUtGetDescriptorName (PrefixNode)));
500
return_ACPI_STATUS (AE_AML_INTERNAL);
501
}
502
503
if (!(Flags & ACPI_NS_PREFIX_IS_SCOPE))
504
{
505
/*
506
* This node might not be a actual "scope" node (such as a
507
* Device/Method, etc.) It could be a Package or other object
508
* node. Backup up the tree to find the containing scope node.
509
*/
510
while (!AcpiNsOpensScope (PrefixNode->Type) &&
511
PrefixNode->Type != ACPI_TYPE_ANY)
512
{
513
PrefixNode = PrefixNode->Parent;
514
}
515
}
516
}
517
518
/* Save type. TBD: may be no longer necessary */
519
520
TypeToCheckFor = Type;
521
522
/*
523
* Begin examination of the actual pathname
524
*/
525
if (!Pathname)
526
{
527
/* A Null NamePath is allowed and refers to the root */
528
529
NumSegments = 0;
530
ThisNode = AcpiGbl_RootNode;
531
Path = "";
532
533
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
534
"Null Pathname (Zero segments), Flags=%X\n", Flags));
535
}
536
else
537
{
538
/*
539
* Name pointer is valid (and must be in internal name format)
540
*
541
* Check for scope prefixes:
542
*
543
* As represented in the AML stream, a namepath consists of an
544
* optional scope prefix followed by a name segment part.
545
*
546
* If present, the scope prefix is either a Root Prefix (in
547
* which case the name is fully qualified), or one or more
548
* Parent Prefixes (in which case the name's scope is relative
549
* to the current scope).
550
*/
551
if (*Path == (UINT8) AML_ROOT_PREFIX)
552
{
553
/* Pathname is fully qualified, start from the root */
554
555
ThisNode = AcpiGbl_RootNode;
556
SearchParentFlag = ACPI_NS_NO_UPSEARCH;
557
558
/* Point to name segment part */
559
560
Path++;
561
562
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
563
"Path is absolute from root [%p]\n", ThisNode));
564
}
565
else
566
{
567
/* Pathname is relative to current scope, start there */
568
569
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
570
"Searching relative to prefix scope [%4.4s] (%p)\n",
571
AcpiUtGetNodeName (PrefixNode), PrefixNode));
572
573
/*
574
* Handle multiple Parent Prefixes (carat) by just getting
575
* the parent node for each prefix instance.
576
*/
577
ThisNode = PrefixNode;
578
#ifdef ACPI_DEBUG_OUTPUT
579
NumCarats = 0;
580
#endif
581
while (*Path == (UINT8) AML_PARENT_PREFIX)
582
{
583
/* Name is fully qualified, no search rules apply */
584
585
SearchParentFlag = ACPI_NS_NO_UPSEARCH;
586
587
/*
588
* Point past this prefix to the name segment
589
* part or the next Parent Prefix
590
*/
591
Path++;
592
593
/* Backup to the parent node */
594
595
#ifdef ACPI_DEBUG_OUTPUT
596
NumCarats++;
597
#endif
598
ThisNode = ThisNode->Parent;
599
if (!ThisNode)
600
{
601
/*
602
* Current scope has no parent scope. Externalize
603
* the internal path for error message.
604
*/
605
Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Pathname,
606
NULL, &ExternalPath);
607
if (ACPI_SUCCESS (Status))
608
{
609
ACPI_ERROR ((AE_INFO,
610
"%s: Path has too many parent prefixes (^)",
611
ExternalPath));
612
613
ACPI_FREE (ExternalPath);
614
}
615
616
return_ACPI_STATUS (AE_NOT_FOUND);
617
}
618
}
619
620
#ifdef ACPI_DEBUG_OUTPUT
621
if (SearchParentFlag == ACPI_NS_NO_UPSEARCH)
622
{
623
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
624
"Search scope is [%4.4s], path has %u carat(s)\n",
625
AcpiUtGetNodeName (ThisNode), NumCarats));
626
}
627
#endif
628
}
629
630
/*
631
* Determine the number of ACPI name segments in this pathname.
632
*
633
* The segment part consists of either:
634
* - A Null name segment (0)
635
* - A DualNamePrefix followed by two 4-byte name segments
636
* - A MultiNamePrefix followed by a byte indicating the
637
* number of segments and the segments themselves.
638
* - A single 4-byte name segment
639
*
640
* Examine the name prefix opcode, if any, to determine the number of
641
* segments.
642
*/
643
switch (*Path)
644
{
645
case 0:
646
/*
647
* Null name after a root or parent prefixes. We already
648
* have the correct target node and there are no name segments.
649
*/
650
NumSegments = 0;
651
Type = ThisNode->Type;
652
653
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
654
"Prefix-only Pathname (Zero name segments), Flags=%X\n",
655
Flags));
656
break;
657
658
case AML_DUAL_NAME_PREFIX:
659
660
/* More than one NameSeg, search rules do not apply */
661
662
SearchParentFlag = ACPI_NS_NO_UPSEARCH;
663
664
/* Two segments, point to first name segment */
665
666
NumSegments = 2;
667
Path++;
668
669
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
670
"Dual Pathname (2 segments, Flags=%X)\n", Flags));
671
break;
672
673
case AML_MULTI_NAME_PREFIX:
674
675
/* More than one NameSeg, search rules do not apply */
676
677
SearchParentFlag = ACPI_NS_NO_UPSEARCH;
678
679
/* Extract segment count, point to first name segment */
680
681
Path++;
682
NumSegments = (UINT32) (UINT8) *Path;
683
Path++;
684
685
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
686
"Multi Pathname (%u Segments, Flags=%X)\n",
687
NumSegments, Flags));
688
break;
689
690
default:
691
/*
692
* Not a Null name, no Dual or Multi prefix, hence there is
693
* only one name segment and Pathname is already pointing to it.
694
*/
695
NumSegments = 1;
696
697
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
698
"Simple Pathname (1 segment, Flags=%X)\n", Flags));
699
break;
700
}
701
702
ACPI_DEBUG_EXEC (AcpiNsPrintPathname (NumSegments, Path));
703
}
704
705
706
/*
707
* Search namespace for each segment of the name. Loop through and
708
* verify (or add to the namespace) each name segment.
709
*
710
* The object type is significant only at the last name
711
* segment. (We don't care about the types along the path, only
712
* the type of the final target object.)
713
*/
714
ThisSearchType = ACPI_TYPE_ANY;
715
CurrentNode = ThisNode;
716
717
while (NumSegments && CurrentNode)
718
{
719
NumSegments--;
720
if (!NumSegments)
721
{
722
/* This is the last segment, enable typechecking */
723
724
ThisSearchType = Type;
725
726
/*
727
* Only allow automatic parent search (search rules) if the caller
728
* requested it AND we have a single, non-fully-qualified NameSeg
729
*/
730
if ((SearchParentFlag != ACPI_NS_NO_UPSEARCH) &&
731
(Flags & ACPI_NS_SEARCH_PARENT))
732
{
733
LocalFlags |= ACPI_NS_SEARCH_PARENT;
734
}
735
736
/* Set error flag according to caller */
737
738
if (Flags & ACPI_NS_ERROR_IF_FOUND)
739
{
740
LocalFlags |= ACPI_NS_ERROR_IF_FOUND;
741
}
742
743
/* Set override flag according to caller */
744
745
if (Flags & ACPI_NS_OVERRIDE_IF_FOUND)
746
{
747
LocalFlags |= ACPI_NS_OVERRIDE_IF_FOUND;
748
}
749
}
750
751
/* Handle opcodes that create a new NameSeg via a full NamePath */
752
753
LocalInterpreterMode = InterpreterMode;
754
if ((Flags & ACPI_NS_PREFIX_MUST_EXIST) && (NumSegments > 0))
755
{
756
/* Every element of the path must exist (except for the final NameSeg) */
757
758
LocalInterpreterMode = ACPI_IMODE_EXECUTE;
759
}
760
761
/* Extract one ACPI name from the front of the pathname */
762
763
ACPI_MOVE_32_TO_32 (&SimpleName, Path);
764
765
/* Try to find the single (4 character) ACPI name */
766
767
Status = AcpiNsSearchAndEnter (SimpleName, WalkState, CurrentNode,
768
LocalInterpreterMode, ThisSearchType, LocalFlags, &ThisNode);
769
if (ACPI_FAILURE (Status))
770
{
771
if (Status == AE_NOT_FOUND)
772
{
773
#if !defined ACPI_ASL_COMPILER /* Note: iASL reports this error by itself, not needed here */
774
if (Flags & ACPI_NS_PREFIX_MUST_EXIST)
775
{
776
AcpiOsPrintf (ACPI_MSG_BIOS_ERROR
777
"Object does not exist: %4.4s\n", (char *) &SimpleName);
778
}
779
#endif
780
/* Name not found in ACPI namespace */
781
782
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
783
"Name [%4.4s] not found in scope [%4.4s] %p\n",
784
(char *) &SimpleName, (char *) &CurrentNode->Name,
785
CurrentNode));
786
}
787
788
#ifdef ACPI_EXEC_APP
789
if ((Status == AE_ALREADY_EXISTS) &&
790
(ThisNode->Flags & ANOBJ_NODE_EARLY_INIT))
791
{
792
ThisNode->Flags &= ~ANOBJ_NODE_EARLY_INIT;
793
Status = AE_OK;
794
}
795
#endif
796
797
#ifdef ACPI_ASL_COMPILER
798
/*
799
* If this ACPI name already exists within the namespace as an
800
* external declaration, then mark the external as a conflicting
801
* declaration and proceed to process the current node as if it did
802
* not exist in the namespace. If this node is not processed as
803
* normal, then it could cause improper namespace resolution
804
* by failing to open a new scope.
805
*/
806
if (AcpiGbl_DisasmFlag &&
807
(Status == AE_ALREADY_EXISTS) &&
808
((ThisNode->Flags & ANOBJ_IS_EXTERNAL) ||
809
(WalkState && WalkState->Opcode == AML_EXTERNAL_OP)))
810
{
811
ThisNode->Flags &= ~ANOBJ_IS_EXTERNAL;
812
ThisNode->Type = (UINT8)ThisSearchType;
813
if (WalkState->Opcode != AML_EXTERNAL_OP)
814
{
815
AcpiDmMarkExternalConflict (ThisNode);
816
}
817
break;
818
}
819
#endif
820
821
*ReturnNode = ThisNode;
822
return_ACPI_STATUS (Status);
823
}
824
825
/* More segments to follow? */
826
827
if (NumSegments > 0)
828
{
829
/*
830
* If we have an alias to an object that opens a scope (such as a
831
* device or processor), we need to dereference the alias here so
832
* that we can access any children of the original node (via the
833
* remaining segments).
834
*/
835
if (ThisNode->Type == ACPI_TYPE_LOCAL_ALIAS)
836
{
837
if (!ThisNode->Object)
838
{
839
return_ACPI_STATUS (AE_NOT_EXIST);
840
}
841
842
if (AcpiNsOpensScope (((ACPI_NAMESPACE_NODE *)
843
ThisNode->Object)->Type))
844
{
845
ThisNode = (ACPI_NAMESPACE_NODE *) ThisNode->Object;
846
}
847
}
848
}
849
850
/* Special handling for the last segment (NumSegments == 0) */
851
852
else
853
{
854
/*
855
* Sanity typecheck of the target object:
856
*
857
* If 1) This is the last segment (NumSegments == 0)
858
* 2) And we are looking for a specific type
859
* (Not checking for TYPE_ANY)
860
* 3) Which is not an alias
861
* 4) Which is not a local type (TYPE_SCOPE)
862
* 5) And the type of target object is known (not TYPE_ANY)
863
* 6) And target object does not match what we are looking for
864
*
865
* Then we have a type mismatch. Just warn and ignore it.
866
*/
867
if ((TypeToCheckFor != ACPI_TYPE_ANY) &&
868
(TypeToCheckFor != ACPI_TYPE_LOCAL_ALIAS) &&
869
(TypeToCheckFor != ACPI_TYPE_LOCAL_METHOD_ALIAS) &&
870
(TypeToCheckFor != ACPI_TYPE_LOCAL_SCOPE) &&
871
(ThisNode->Type != ACPI_TYPE_ANY) &&
872
(ThisNode->Type != TypeToCheckFor))
873
{
874
/* Complain about a type mismatch */
875
876
ACPI_WARNING ((AE_INFO,
877
"NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
878
ACPI_CAST_PTR (char, &SimpleName),
879
AcpiUtGetTypeName (ThisNode->Type),
880
AcpiUtGetTypeName (TypeToCheckFor)));
881
}
882
883
/*
884
* If this is the last name segment and we are not looking for a
885
* specific type, but the type of found object is known, use that
886
* type to (later) see if it opens a scope.
887
*/
888
if (Type == ACPI_TYPE_ANY)
889
{
890
Type = ThisNode->Type;
891
}
892
}
893
894
/* Point to next name segment and make this node current */
895
896
Path += ACPI_NAMESEG_SIZE;
897
CurrentNode = ThisNode;
898
}
899
900
/* Always check if we need to open a new scope */
901
902
if (!(Flags & ACPI_NS_DONT_OPEN_SCOPE) && (WalkState))
903
{
904
/*
905
* If entry is a type which opens a scope, push the new scope on the
906
* scope stack.
907
*/
908
if (AcpiNsOpensScope (Type))
909
{
910
Status = AcpiDsScopeStackPush (ThisNode, Type, WalkState);
911
if (ACPI_FAILURE (Status))
912
{
913
return_ACPI_STATUS (Status);
914
}
915
}
916
}
917
918
#ifdef ACPI_EXEC_APP
919
if (Flags & ACPI_NS_EARLY_INIT)
920
{
921
ThisNode->Flags |= ANOBJ_NODE_EARLY_INIT;
922
}
923
#endif
924
925
*ReturnNode = ThisNode;
926
return_ACPI_STATUS (AE_OK);
927
}
928
929