Subversion Repositories Kolibri OS

Rev

Rev 1498 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1498 serge 1
/*******************************************************************************
2
 *
3
 * Module Name: nsaccess - Top-level functions for accessing ACPI namespace
4
 *
5
 ******************************************************************************/
6
 
7
/******************************************************************************
8
 *
9
 * 1. Copyright Notice
10
 *
2216 Serge 11
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
1498 serge 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
#define __NSACCESS_C__
117
 
118
#include "acpi.h"
119
#include "accommon.h"
120
#include "amlcode.h"
121
#include "acnamesp.h"
122
#include "acdispat.h"
123
 
124
 
125
#define _COMPONENT          ACPI_NAMESPACE
126
        ACPI_MODULE_NAME    ("nsaccess")
127
 
128
 
129
/*******************************************************************************
130
 *
131
 * FUNCTION:    AcpiNsRootInitialize
132
 *
133
 * PARAMETERS:  None
134
 *
135
 * RETURN:      Status
136
 *
137
 * DESCRIPTION: Allocate and initialize the default root named objects
138
 *
139
 * MUTEX:       Locks namespace for entire execution
140
 *
141
 ******************************************************************************/
142
 
143
ACPI_STATUS
144
AcpiNsRootInitialize (
145
    void)
146
{
147
    ACPI_STATUS                 Status;
148
    const ACPI_PREDEFINED_NAMES *InitVal = NULL;
149
    ACPI_NAMESPACE_NODE         *NewNode;
150
    ACPI_OPERAND_OBJECT         *ObjDesc;
151
    ACPI_STRING                 Val = NULL;
152
 
153
 
154
    ACPI_FUNCTION_TRACE (NsRootInitialize);
155
 
156
 
157
    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
158
    if (ACPI_FAILURE (Status))
159
    {
160
        return_ACPI_STATUS (Status);
161
    }
162
 
163
    /*
164
     * The global root ptr is initially NULL, so a non-NULL value indicates
165
     * that AcpiNsRootInitialize() has already been called; just return.
166
     */
167
    if (AcpiGbl_RootNode)
168
    {
169
        Status = AE_OK;
170
        goto UnlockAndExit;
171
    }
172
 
173
    /*
174
     * Tell the rest of the subsystem that the root is initialized
175
     * (This is OK because the namespace is locked)
176
     */
177
    AcpiGbl_RootNode = &AcpiGbl_RootNodeStruct;
178
 
179
    /* Enter the pre-defined names in the name table */
180
 
181
    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
182
        "Entering predefined entries into namespace\n"));
183
 
184
    for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++)
185
    {
186
        /* _OSI is optional for now, will be permanent later */
187
 
188
        if (!ACPI_STRCMP (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod)
189
        {
190
            continue;
191
        }
192
 
193
        Status = AcpiNsLookup (NULL, InitVal->Name, InitVal->Type,
194
                        ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
195
                        NULL, &NewNode);
196
 
197
        if (ACPI_FAILURE (Status) || (!NewNode)) /* Must be on same line for code converter */
198
        {
199
            ACPI_EXCEPTION ((AE_INFO, Status,
200
                "Could not create predefined name %s",
201
                InitVal->Name));
202
        }
203
 
204
        /*
205
         * Name entered successfully. If entry in PreDefinedNames[] specifies
206
         * an initial value, create the initial value.
207
         */
208
        if (InitVal->Val)
209
        {
210
            Status = AcpiOsPredefinedOverride (InitVal, &Val);
211
            if (ACPI_FAILURE (Status))
212
            {
213
                ACPI_ERROR ((AE_INFO,
214
                    "Could not override predefined %s",
215
                    InitVal->Name));
216
            }
217
 
218
            if (!Val)
219
            {
220
                Val = InitVal->Val;
221
            }
222
 
223
            /*
224
             * Entry requests an initial value, allocate a
225
             * descriptor for it.
226
             */
227
            ObjDesc = AcpiUtCreateInternalObject (InitVal->Type);
228
            if (!ObjDesc)
229
            {
230
                Status = AE_NO_MEMORY;
231
                goto UnlockAndExit;
232
            }
233
 
234
            /*
235
             * Convert value string from table entry to
236
             * internal representation. Only types actually
237
             * used for initial values are implemented here.
238
             */
239
            switch (InitVal->Type)
240
            {
241
            case ACPI_TYPE_METHOD:
242
                ObjDesc->Method.ParamCount = (UINT8) ACPI_TO_INTEGER (Val);
243
                ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID;
244
 
245
#if defined (ACPI_ASL_COMPILER)
246
 
247
                /* Save the parameter count for the iASL compiler */
248
 
249
                NewNode->Value = ObjDesc->Method.ParamCount;
250
#else
251
                /* Mark this as a very SPECIAL method */
252
 
2216 Serge 253
                ObjDesc->Method.InfoFlags = ACPI_METHOD_INTERNAL_ONLY;
254
                ObjDesc->Method.Dispatch.Implementation = AcpiUtOsiImplementation;
1498 serge 255
#endif
256
                break;
257
 
258
            case ACPI_TYPE_INTEGER:
259
 
260
                ObjDesc->Integer.Value = ACPI_TO_INTEGER (Val);
261
                break;
262
 
263
 
264
            case ACPI_TYPE_STRING:
265
 
266
                /* Build an object around the static string */
267
 
268
                ObjDesc->String.Length = (UINT32) ACPI_STRLEN (Val);
269
                ObjDesc->String.Pointer = Val;
270
                ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
271
                break;
272
 
273
 
274
            case ACPI_TYPE_MUTEX:
275
 
276
                ObjDesc->Mutex.Node = NewNode;
277
                ObjDesc->Mutex.SyncLevel = (UINT8) (ACPI_TO_INTEGER (Val) - 1);
278
 
279
                /* Create a mutex */
280
 
281
                Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex);
282
                if (ACPI_FAILURE (Status))
283
                {
284
                    AcpiUtRemoveReference (ObjDesc);
285
                    goto UnlockAndExit;
286
                }
287
 
288
                /* Special case for ACPI Global Lock */
289
 
290
                if (ACPI_STRCMP (InitVal->Name, "_GL_") == 0)
291
                {
292
                    AcpiGbl_GlobalLockMutex = ObjDesc;
293
 
294
                    /* Create additional counting semaphore for global lock */
295
 
296
                    Status = AcpiOsCreateSemaphore (
297
                                1, 0, &AcpiGbl_GlobalLockSemaphore);
298
                    if (ACPI_FAILURE (Status))
299
                    {
300
                        AcpiUtRemoveReference (ObjDesc);
301
                        goto UnlockAndExit;
302
                    }
303
                }
304
                break;
305
 
306
 
307
            default:
308
 
309
                ACPI_ERROR ((AE_INFO, "Unsupported initial type value 0x%X",
310
                    InitVal->Type));
311
                AcpiUtRemoveReference (ObjDesc);
312
                ObjDesc = NULL;
313
                continue;
314
            }
315
 
316
            /* Store pointer to value descriptor in the Node */
317
 
318
            Status = AcpiNsAttachObject (NewNode, ObjDesc,
319
                        ObjDesc->Common.Type);
320
 
321
            /* Remove local reference to the object */
322
 
323
            AcpiUtRemoveReference (ObjDesc);
324
        }
325
    }
326
 
327
 
328
UnlockAndExit:
329
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
330
 
331
    /* Save a handle to "_GPE", it is always present */
332
 
333
    if (ACPI_SUCCESS (Status))
334
    {
335
        Status = AcpiNsGetNode (NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH,
336
                    &AcpiGbl_FadtGpeDevice);
337
    }
338
 
339
    return_ACPI_STATUS (Status);
340
}
341
 
342
 
343
/*******************************************************************************
344
 *
345
 * FUNCTION:    AcpiNsLookup
346
 *
347
 * PARAMETERS:  ScopeInfo       - Current scope info block
348
 *              Pathname        - Search pathname, in internal format
349
 *                                (as represented in the AML stream)
350
 *              Type            - Type associated with name
351
 *              InterpreterMode - IMODE_LOAD_PASS2 => add name if not found
352
 *              Flags           - Flags describing the search restrictions
353
 *              WalkState       - Current state of the walk
354
 *              ReturnNode      - Where the Node is placed (if found
355
 *                                or created successfully)
356
 *
357
 * RETURN:      Status
358
 *
359
 * DESCRIPTION: Find or enter the passed name in the name space.
360
 *              Log an error if name not found in Exec mode.
361
 *
362
 * MUTEX:       Assumes namespace is locked.
363
 *
364
 ******************************************************************************/
365
 
366
ACPI_STATUS
367
AcpiNsLookup (
368
    ACPI_GENERIC_STATE      *ScopeInfo,
369
    char                    *Pathname,
370
    ACPI_OBJECT_TYPE        Type,
371
    ACPI_INTERPRETER_MODE   InterpreterMode,
372
    UINT32                  Flags,
373
    ACPI_WALK_STATE         *WalkState,
374
    ACPI_NAMESPACE_NODE     **ReturnNode)
375
{
376
    ACPI_STATUS             Status;
377
    char                    *Path = Pathname;
378
    ACPI_NAMESPACE_NODE     *PrefixNode;
379
    ACPI_NAMESPACE_NODE     *CurrentNode = NULL;
380
    ACPI_NAMESPACE_NODE     *ThisNode = NULL;
381
    UINT32                  NumSegments;
382
    UINT32                  NumCarats;
383
    ACPI_NAME               SimpleName;
384
    ACPI_OBJECT_TYPE        TypeToCheckFor;
385
    ACPI_OBJECT_TYPE        ThisSearchType;
386
    UINT32                  SearchParentFlag = ACPI_NS_SEARCH_PARENT;
387
    UINT32                  LocalFlags;
388
 
389
 
390
    ACPI_FUNCTION_TRACE (NsLookup);
391
 
392
 
393
    if (!ReturnNode)
394
    {
395
        return_ACPI_STATUS (AE_BAD_PARAMETER);
396
    }
397
 
398
    LocalFlags = Flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT);
399
    *ReturnNode = ACPI_ENTRY_NOT_FOUND;
400
    AcpiGbl_NsLookupCount++;
401
 
402
    if (!AcpiGbl_RootNode)
403
    {
404
        return_ACPI_STATUS (AE_NO_NAMESPACE);
405
    }
406
 
407
    /* Get the prefix scope. A null scope means use the root scope */
408
 
409
    if ((!ScopeInfo) ||
410
        (!ScopeInfo->Scope.Node))
411
    {
412
        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
413
            "Null scope prefix, using root node (%p)\n",
414
            AcpiGbl_RootNode));
415
 
416
        PrefixNode = AcpiGbl_RootNode;
417
    }
418
    else
419
    {
420
        PrefixNode = ScopeInfo->Scope.Node;
421
        if (ACPI_GET_DESCRIPTOR_TYPE (PrefixNode) != ACPI_DESC_TYPE_NAMED)
422
        {
423
            ACPI_ERROR ((AE_INFO, "%p is not a namespace node [%s]",
424
                PrefixNode, AcpiUtGetDescriptorName (PrefixNode)));
425
            return_ACPI_STATUS (AE_AML_INTERNAL);
426
        }
427
 
428
        if (!(Flags & ACPI_NS_PREFIX_IS_SCOPE))
429
        {
430
            /*
431
             * This node might not be a actual "scope" node (such as a
432
             * Device/Method, etc.)  It could be a Package or other object
433
             * node. Backup up the tree to find the containing scope node.
434
             */
435
            while (!AcpiNsOpensScope (PrefixNode->Type) &&
436
                    PrefixNode->Type != ACPI_TYPE_ANY)
437
            {
438
                PrefixNode = PrefixNode->Parent;
439
            }
440
        }
441
    }
442
 
443
    /* Save type. TBD: may be no longer necessary */
444
 
445
    TypeToCheckFor = Type;
446
 
447
    /*
448
     * Begin examination of the actual pathname
449
     */
450
    if (!Pathname)
451
    {
452
        /* A Null NamePath is allowed and refers to the root */
453
 
454
        NumSegments = 0;
455
        ThisNode = AcpiGbl_RootNode;
456
        Path = "";
457
 
458
        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
459
            "Null Pathname (Zero segments), Flags=%X\n", Flags));
460
    }
461
    else
462
    {
463
        /*
464
         * Name pointer is valid (and must be in internal name format)
465
         *
466
         * Check for scope prefixes:
467
         *
468
         * As represented in the AML stream, a namepath consists of an
469
         * optional scope prefix followed by a name segment part.
470
         *
471
         * If present, the scope prefix is either a Root Prefix (in
472
         * which case the name is fully qualified), or one or more
473
         * Parent Prefixes (in which case the name's scope is relative
474
         * to the current scope).
475
         */
476
        if (*Path == (UINT8) AML_ROOT_PREFIX)
477
        {
478
            /* Pathname is fully qualified, start from the root */
479
 
480
            ThisNode = AcpiGbl_RootNode;
481
            SearchParentFlag = ACPI_NS_NO_UPSEARCH;
482
 
483
            /* Point to name segment part */
484
 
485
            Path++;
486
 
487
            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
488
                "Path is absolute from root [%p]\n", ThisNode));
489
        }
490
        else
491
        {
492
            /* Pathname is relative to current scope, start there */
493
 
494
            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
495
                "Searching relative to prefix scope [%4.4s] (%p)\n",
496
                AcpiUtGetNodeName (PrefixNode), PrefixNode));
497
 
498
            /*
499
             * Handle multiple Parent Prefixes (carat) by just getting
500
             * the parent node for each prefix instance.
501
             */
502
            ThisNode = PrefixNode;
503
            NumCarats = 0;
504
            while (*Path == (UINT8) AML_PARENT_PREFIX)
505
            {
506
                /* Name is fully qualified, no search rules apply */
507
 
508
                SearchParentFlag = ACPI_NS_NO_UPSEARCH;
509
 
510
                /*
511
                 * Point past this prefix to the name segment
512
                 * part or the next Parent Prefix
513
                 */
514
                Path++;
515
 
516
                /* Backup to the parent node */
517
 
518
                NumCarats++;
519
                ThisNode = ThisNode->Parent;
520
                if (!ThisNode)
521
                {
522
                    /* Current scope has no parent scope */
523
 
524
                    ACPI_ERROR ((AE_INFO,
525
                        "ACPI path has too many parent prefixes (^) "
526
                        "- reached beyond root node"));
527
                    return_ACPI_STATUS (AE_NOT_FOUND);
528
                }
529
            }
530
 
531
            if (SearchParentFlag == ACPI_NS_NO_UPSEARCH)
532
            {
533
                ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
534
                    "Search scope is [%4.4s], path has %u carat(s)\n",
535
                    AcpiUtGetNodeName (ThisNode), NumCarats));
536
            }
537
        }
538
 
539
        /*
540
         * Determine the number of ACPI name segments in this pathname.
541
         *
542
         * The segment part consists of either:
543
         *  - A Null name segment (0)
544
         *  - A DualNamePrefix followed by two 4-byte name segments
545
         *  - A MultiNamePrefix followed by a byte indicating the
546
         *      number of segments and the segments themselves.
547
         *  - A single 4-byte name segment
548
         *
549
         * Examine the name prefix opcode, if any, to determine the number of
550
         * segments.
551
         */
552
        switch (*Path)
553
        {
554
        case 0:
555
            /*
556
             * Null name after a root or parent prefixes. We already
557
             * have the correct target node and there are no name segments.
558
             */
559
            NumSegments  = 0;
560
            Type = ThisNode->Type;
561
 
562
            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
563
                "Prefix-only Pathname (Zero name segments), Flags=%X\n",
564
                Flags));
565
            break;
566
 
567
        case AML_DUAL_NAME_PREFIX:
568
 
569
            /* More than one NameSeg, search rules do not apply */
570
 
571
            SearchParentFlag = ACPI_NS_NO_UPSEARCH;
572
 
573
            /* Two segments, point to first name segment */
574
 
575
            NumSegments = 2;
576
            Path++;
577
 
578
            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
579
                "Dual Pathname (2 segments, Flags=%X)\n", Flags));
580
            break;
581
 
582
        case AML_MULTI_NAME_PREFIX_OP:
583
 
584
            /* More than one NameSeg, search rules do not apply */
585
 
586
            SearchParentFlag = ACPI_NS_NO_UPSEARCH;
587
 
588
            /* Extract segment count, point to first name segment */
589
 
590
            Path++;
591
            NumSegments = (UINT32) (UINT8) *Path;
592
            Path++;
593
 
594
            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
595
                "Multi Pathname (%u Segments, Flags=%X)\n",
596
                NumSegments, Flags));
597
            break;
598
 
599
        default:
600
            /*
601
             * Not a Null name, no Dual or Multi prefix, hence there is
602
             * only one name segment and Pathname is already pointing to it.
603
             */
604
            NumSegments = 1;
605
 
606
            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
607
                "Simple Pathname (1 segment, Flags=%X)\n", Flags));
608
            break;
609
        }
610
 
611
        ACPI_DEBUG_EXEC (AcpiNsPrintPathname (NumSegments, Path));
612
    }
613
 
614
 
615
    /*
616
     * Search namespace for each segment of the name. Loop through and
617
     * verify (or add to the namespace) each name segment.
618
     *
619
     * The object type is significant only at the last name
620
     * segment. (We don't care about the types along the path, only
621
     * the type of the final target object.)
622
     */
623
    ThisSearchType = ACPI_TYPE_ANY;
624
    CurrentNode = ThisNode;
625
    while (NumSegments && CurrentNode)
626
    {
627
        NumSegments--;
628
        if (!NumSegments)
629
        {
630
            /* This is the last segment, enable typechecking */
631
 
632
            ThisSearchType = Type;
633
 
634
            /*
635
             * Only allow automatic parent search (search rules) if the caller
636
             * requested it AND we have a single, non-fully-qualified NameSeg
637
             */
638
            if ((SearchParentFlag != ACPI_NS_NO_UPSEARCH) &&
639
                (Flags & ACPI_NS_SEARCH_PARENT))
640
            {
641
                LocalFlags |= ACPI_NS_SEARCH_PARENT;
642
            }
643
 
644
            /* Set error flag according to caller */
645
 
646
            if (Flags & ACPI_NS_ERROR_IF_FOUND)
647
            {
648
                LocalFlags |= ACPI_NS_ERROR_IF_FOUND;
649
            }
650
        }
651
 
652
        /* Extract one ACPI name from the front of the pathname */
653
 
654
        ACPI_MOVE_32_TO_32 (&SimpleName, Path);
655
 
656
        /* Try to find the single (4 character) ACPI name */
657
 
658
        Status = AcpiNsSearchAndEnter (SimpleName, WalkState, CurrentNode,
659
                    InterpreterMode, ThisSearchType, LocalFlags, &ThisNode);
660
        if (ACPI_FAILURE (Status))
661
        {
662
            if (Status == AE_NOT_FOUND)
663
            {
664
                /* Name not found in ACPI namespace */
665
 
666
                ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
667
                    "Name [%4.4s] not found in scope [%4.4s] %p\n",
668
                    (char *) &SimpleName, (char *) &CurrentNode->Name,
669
                    CurrentNode));
670
            }
671
 
672
            *ReturnNode = ThisNode;
673
            return_ACPI_STATUS (Status);
674
        }
675
 
676
        /* More segments to follow? */
677
 
678
        if (NumSegments > 0)
679
        {
680
            /*
681
             * If we have an alias to an object that opens a scope (such as a
682
             * device or processor), we need to dereference the alias here so
683
             * that we can access any children of the original node (via the
684
             * remaining segments).
685
             */
686
            if (ThisNode->Type == ACPI_TYPE_LOCAL_ALIAS)
687
            {
688
                if (!ThisNode->Object)
689
                {
690
                    return_ACPI_STATUS (AE_NOT_EXIST);
691
                }
692
 
693
                if (AcpiNsOpensScope (((ACPI_NAMESPACE_NODE *)
694
                        ThisNode->Object)->Type))
695
                {
696
                    ThisNode = (ACPI_NAMESPACE_NODE *) ThisNode->Object;
697
                }
698
            }
699
        }
700
 
701
        /* Special handling for the last segment (NumSegments == 0) */
702
 
703
        else
704
        {
705
            /*
706
             * Sanity typecheck of the target object:
707
             *
708
             * If 1) This is the last segment (NumSegments == 0)
709
             *    2) And we are looking for a specific type
710
             *       (Not checking for TYPE_ANY)
711
             *    3) Which is not an alias
712
             *    4) Which is not a local type (TYPE_SCOPE)
713
             *    5) And the type of target object is known (not TYPE_ANY)
714
             *    6) And target object does not match what we are looking for
715
             *
716
             * Then we have a type mismatch. Just warn and ignore it.
717
             */
718
            if ((TypeToCheckFor != ACPI_TYPE_ANY)                   &&
719
                (TypeToCheckFor != ACPI_TYPE_LOCAL_ALIAS)           &&
720
                (TypeToCheckFor != ACPI_TYPE_LOCAL_METHOD_ALIAS)    &&
721
                (TypeToCheckFor != ACPI_TYPE_LOCAL_SCOPE)           &&
722
                (ThisNode->Type != ACPI_TYPE_ANY)                   &&
723
                (ThisNode->Type != TypeToCheckFor))
724
            {
725
                /* Complain about a type mismatch */
726
 
727
                ACPI_WARNING ((AE_INFO,
728
                    "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
729
                    ACPI_CAST_PTR (char, &SimpleName),
730
                    AcpiUtGetTypeName (ThisNode->Type),
731
                    AcpiUtGetTypeName (TypeToCheckFor)));
732
            }
733
 
734
            /*
735
             * If this is the last name segment and we are not looking for a
736
             * specific type, but the type of found object is known, use that
737
             * type to (later) see if it opens a scope.
738
             */
739
            if (Type == ACPI_TYPE_ANY)
740
            {
741
                Type = ThisNode->Type;
742
            }
743
        }
744
 
745
        /* Point to next name segment and make this node current */
746
 
747
        Path += ACPI_NAME_SIZE;
748
        CurrentNode = ThisNode;
749
    }
750
 
751
    /* Always check if we need to open a new scope */
752
 
753
    if (!(Flags & ACPI_NS_DONT_OPEN_SCOPE) && (WalkState))
754
    {
755
        /*
756
         * If entry is a type which opens a scope, push the new scope on the
757
         * scope stack.
758
         */
759
        if (AcpiNsOpensScope (Type))
760
        {
761
            Status = AcpiDsScopeStackPush (ThisNode, Type, WalkState);
762
            if (ACPI_FAILURE (Status))
763
            {
764
                return_ACPI_STATUS (Status);
765
            }
766
        }
767
    }
768
 
769
    *ReturnNode = ThisNode;
770
    return_ACPI_STATUS (AE_OK);
771
}
772