nsxfname.c revision 200553
1223637Sbz/******************************************************************************
2126258Smlaier *
3126258Smlaier * Module Name: nsxfname - Public interfaces to the ACPI subsystem
4126258Smlaier *                         ACPI Namespace oriented interfaces
5126258Smlaier *
6126258Smlaier *****************************************************************************/
7126258Smlaier
8126258Smlaier/******************************************************************************
9126258Smlaier *
10126258Smlaier * 1. Copyright Notice
11126258Smlaier *
12126258Smlaier * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
13126258Smlaier * All rights reserved.
14126258Smlaier *
15126258Smlaier * 2. License
16126258Smlaier *
17126258Smlaier * 2.1. This is your license from Intel Corp. under its intellectual property
18126258Smlaier * rights.  You may have additional license terms from the party that provided
19126258Smlaier * you this software, covering your right to use that party's intellectual
20126258Smlaier * property rights.
21126258Smlaier *
22126258Smlaier * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23126258Smlaier * copy of the source code appearing in this file ("Covered Code") an
24126258Smlaier * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25126258Smlaier * base code distributed originally by Intel ("Original Intel Code") to copy,
26126258Smlaier * make derivatives, distribute, use and display any portion of the Covered
27126258Smlaier * Code in any form, with the right to sublicense such rights; and
28223637Sbz *
29126258Smlaier * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30171168Smlaier * license (with the right to sublicense), under only those claims of Intel
31171168Smlaier * patents that are infringed by the Original Intel Code, to make, use, sell,
32223637Sbz * offer to sell, and import the Covered Code and derivative works thereof
33126258Smlaier * solely to the minimum extent necessary to exercise the above copyright
34126258Smlaier * license, and in no event shall the patent license extend to any additions
35126258Smlaier * to or modifications of the Original Intel Code.  No other license or right
36126258Smlaier * is granted directly or by implication, estoppel or otherwise;
37126258Smlaier *
38126258Smlaier * The above copyright and patent license is granted only if the following
39126258Smlaier * conditions are met:
40145836Smlaier *
41126258Smlaier * 3. Conditions
42126258Smlaier *
43171168Smlaier * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44171168Smlaier * Redistribution of source code of any substantial portion of the Covered
45171168Smlaier * Code or modification with rights to further distribute source must include
46171168Smlaier * the above Copyright Notice, the above License, this list of Conditions,
47126258Smlaier * and the following Disclaimer and Export Compliance provision.  In addition,
48126258Smlaier * Licensee must cause all Covered Code to which Licensee contributes to
49126258Smlaier * contain a file documenting the changes Licensee made to create that Covered
50126258Smlaier * Code and the date of any change.  Licensee must include in that file the
51223637Sbz * documentation of any changes made by any predecessor Licensee.  Licensee
52126258Smlaier * must include a prominent statement that the modification is derived,
53223637Sbz * directly or indirectly, from Original Intel Code.
54126258Smlaier *
55126258Smlaier * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56156500Syar * Redistribution of source code of any substantial portion of the Covered
57156500Syar * Code or modification without rights to further distribute source must
58156500Syar * include the following Disclaimer and Export Compliance provision in the
59171168Smlaier * documentation and/or other materials provided with distribution.  In
60155337Smlaier * addition, Licensee may not authorize further sublicense of source of any
61240233Sglebius * portion of the Covered Code, and must include terms to the effect that the
62223637Sbz * license from Licensee to its licensee is limited to the intellectual
63240233Sglebius * property embodied in the software Licensee provides to its licensee, and
64155337Smlaier * not to intellectual property embodied in modifications its licensee may
65126258Smlaier * make.
66126258Smlaier *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117#define __NSXFNAME_C__
118
119#include <contrib/dev/acpica/include/acpi.h>
120#include <contrib/dev/acpica/include/accommon.h>
121#include <contrib/dev/acpica/include/acnamesp.h>
122#include <contrib/dev/acpica/include/acparser.h>
123#include <contrib/dev/acpica/include/amlcode.h>
124
125
126#define _COMPONENT          ACPI_NAMESPACE
127        ACPI_MODULE_NAME    ("nsxfname")
128
129/* Local prototypes */
130
131static char *
132AcpiNsCopyDeviceId (
133    ACPI_DEVICE_ID          *Dest,
134    ACPI_DEVICE_ID          *Source,
135    char                    *StringArea);
136
137
138/******************************************************************************
139 *
140 * FUNCTION:    AcpiGetHandle
141 *
142 * PARAMETERS:  Parent          - Object to search under (search scope).
143 *              Pathname        - Pointer to an asciiz string containing the
144 *                                name
145 *              RetHandle       - Where the return handle is returned
146 *
147 * RETURN:      Status
148 *
149 * DESCRIPTION: This routine will search for a caller specified name in the
150 *              name space.  The caller can restrict the search region by
151 *              specifying a non NULL parent.  The parent value is itself a
152 *              namespace handle.
153 *
154 ******************************************************************************/
155
156ACPI_STATUS
157AcpiGetHandle (
158    ACPI_HANDLE             Parent,
159    ACPI_STRING             Pathname,
160    ACPI_HANDLE             *RetHandle)
161{
162    ACPI_STATUS             Status;
163    ACPI_NAMESPACE_NODE     *Node = NULL;
164    ACPI_NAMESPACE_NODE     *PrefixNode = NULL;
165
166
167    ACPI_FUNCTION_ENTRY ();
168
169
170    /* Parameter Validation */
171
172    if (!RetHandle || !Pathname)
173    {
174        return (AE_BAD_PARAMETER);
175    }
176
177    /* Convert a parent handle to a prefix node */
178
179    if (Parent)
180    {
181        PrefixNode = AcpiNsValidateHandle (Parent);
182        if (!PrefixNode)
183        {
184            return (AE_BAD_PARAMETER);
185        }
186    }
187
188    /*
189     * Valid cases are:
190     * 1) Fully qualified pathname
191     * 2) Parent + Relative pathname
192     *
193     * Error for <null Parent + relative path>
194     */
195    if (AcpiNsValidRootPrefix (Pathname[0]))
196    {
197        /* Pathname is fully qualified (starts with '\') */
198
199        /* Special case for root-only, since we can't search for it */
200
201        if (!ACPI_STRCMP (Pathname, ACPI_NS_ROOT_PATH))
202        {
203            *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, AcpiGbl_RootNode);
204            return (AE_OK);
205        }
206    }
207    else if (!PrefixNode)
208    {
209        /* Relative path with null prefix is disallowed */
210
211        return (AE_BAD_PARAMETER);
212    }
213
214    /* Find the Node and convert to a handle */
215
216    Status = AcpiNsGetNode (PrefixNode, Pathname, ACPI_NS_NO_UPSEARCH, &Node);
217    if (ACPI_SUCCESS (Status))
218    {
219        *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, Node);
220    }
221
222    return (Status);
223}
224
225ACPI_EXPORT_SYMBOL (AcpiGetHandle)
226
227
228/******************************************************************************
229 *
230 * FUNCTION:    AcpiGetName
231 *
232 * PARAMETERS:  Handle          - Handle to be converted to a pathname
233 *              NameType        - Full pathname or single segment
234 *              Buffer          - Buffer for returned path
235 *
236 * RETURN:      Pointer to a string containing the fully qualified Name.
237 *
238 * DESCRIPTION: This routine returns the fully qualified name associated with
239 *              the Handle parameter.  This and the AcpiPathnameToHandle are
240 *              complementary functions.
241 *
242 ******************************************************************************/
243
244ACPI_STATUS
245AcpiGetName (
246    ACPI_HANDLE             Handle,
247    UINT32                  NameType,
248    ACPI_BUFFER             *Buffer)
249{
250    ACPI_STATUS             Status;
251    ACPI_NAMESPACE_NODE     *Node;
252
253
254    /* Parameter validation */
255
256    if (NameType > ACPI_NAME_TYPE_MAX)
257    {
258        return (AE_BAD_PARAMETER);
259    }
260
261    Status = AcpiUtValidateBuffer (Buffer);
262    if (ACPI_FAILURE (Status))
263    {
264        return (Status);
265    }
266
267    if (NameType == ACPI_FULL_PATHNAME)
268    {
269        /* Get the full pathname (From the namespace root) */
270
271        Status = AcpiNsHandleToPathname (Handle, Buffer);
272        return (Status);
273    }
274
275    /*
276     * Wants the single segment ACPI name.
277     * Validate handle and convert to a namespace Node
278     */
279    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
280    if (ACPI_FAILURE (Status))
281    {
282        return (Status);
283    }
284
285    Node = AcpiNsValidateHandle (Handle);
286    if (!Node)
287    {
288        Status = AE_BAD_PARAMETER;
289        goto UnlockAndExit;
290    }
291
292    /* Validate/Allocate/Clear caller buffer */
293
294    Status = AcpiUtInitializeBuffer (Buffer, ACPI_PATH_SEGMENT_LENGTH);
295    if (ACPI_FAILURE (Status))
296    {
297        goto UnlockAndExit;
298    }
299
300    /* Just copy the ACPI name from the Node and zero terminate it */
301
302    ACPI_STRNCPY (Buffer->Pointer, AcpiUtGetNodeName (Node),
303                ACPI_NAME_SIZE);
304    ((char *) Buffer->Pointer) [ACPI_NAME_SIZE] = 0;
305    Status = AE_OK;
306
307
308UnlockAndExit:
309
310    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
311    return (Status);
312}
313
314ACPI_EXPORT_SYMBOL (AcpiGetName)
315
316
317/******************************************************************************
318 *
319 * FUNCTION:    AcpiNsCopyDeviceId
320 *
321 * PARAMETERS:  Dest                - Pointer to the destination DEVICE_ID
322 *              Source              - Pointer to the source DEVICE_ID
323 *              StringArea          - Pointer to where to copy the dest string
324 *
325 * RETURN:      Pointer to the next string area
326 *
327 * DESCRIPTION: Copy a single DEVICE_ID, including the string data.
328 *
329 ******************************************************************************/
330
331static char *
332AcpiNsCopyDeviceId (
333    ACPI_DEVICE_ID          *Dest,
334    ACPI_DEVICE_ID          *Source,
335    char                    *StringArea)
336{
337    /* Create the destination DEVICE_ID */
338
339    Dest->String = StringArea;
340    Dest->Length = Source->Length;
341
342    /* Copy actual string and return a pointer to the next string area */
343
344    ACPI_MEMCPY (StringArea, Source->String, Source->Length);
345    return (StringArea + Source->Length);
346}
347
348
349/******************************************************************************
350 *
351 * FUNCTION:    AcpiGetObjectInfo
352 *
353 * PARAMETERS:  Handle              - Object Handle
354 *              ReturnBuffer        - Where the info is returned
355 *
356 * RETURN:      Status
357 *
358 * DESCRIPTION: Returns information about an object as gleaned from the
359 *              namespace node and possibly by running several standard
360 *              control methods (Such as in the case of a device.)
361 *
362 * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA,
363 * _ADR, _SxW, and _SxD methods.
364 *
365 * Note: Allocates the return buffer, must be freed by the caller.
366 *
367 ******************************************************************************/
368
369ACPI_STATUS
370AcpiGetObjectInfo (
371    ACPI_HANDLE             Handle,
372    ACPI_DEVICE_INFO        **ReturnBuffer)
373{
374    ACPI_NAMESPACE_NODE     *Node;
375    ACPI_DEVICE_INFO        *Info;
376    ACPI_DEVICE_ID_LIST     *CidList = NULL;
377    ACPI_DEVICE_ID          *Hid = NULL;
378    ACPI_DEVICE_ID          *Uid = NULL;
379    char                    *NextIdString;
380    ACPI_OBJECT_TYPE        Type;
381    ACPI_NAME               Name;
382    UINT8                   ParamCount= 0;
383    UINT8                   Valid = 0;
384    UINT32                  InfoSize;
385    UINT32                  i;
386    ACPI_STATUS             Status;
387
388
389    /* Parameter validation */
390
391    if (!Handle || !ReturnBuffer)
392    {
393        return (AE_BAD_PARAMETER);
394    }
395
396    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
397    if (ACPI_FAILURE (Status))
398    {
399        goto Cleanup;
400    }
401
402    Node = AcpiNsValidateHandle (Handle);
403    if (!Node)
404    {
405        (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
406        return (AE_BAD_PARAMETER);
407    }
408
409    /* Get the namespace node data while the namespace is locked */
410
411    InfoSize = sizeof (ACPI_DEVICE_INFO);
412    Type = Node->Type;
413    Name = Node->Name.Integer;
414
415    if (Node->Type == ACPI_TYPE_METHOD)
416    {
417        ParamCount = Node->Object->Method.ParamCount;
418    }
419
420    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
421    if (ACPI_FAILURE (Status))
422    {
423        return (Status);
424    }
425
426    if ((Type == ACPI_TYPE_DEVICE) ||
427        (Type == ACPI_TYPE_PROCESSOR))
428    {
429        /*
430         * Get extra info for ACPI Device/Processor objects only:
431         * Run the Device _HID, _UID, and _CID methods.
432         *
433         * Note: none of these methods are required, so they may or may
434         * not be present for this device. The Info->Valid bitfield is used
435         * to indicate which methods were found and run successfully.
436         */
437
438        /* Execute the Device._HID method */
439
440        Status = AcpiUtExecute_HID (Node, &Hid);
441        if (ACPI_SUCCESS (Status))
442        {
443            InfoSize += Hid->Length;
444            Valid |= ACPI_VALID_HID;
445        }
446
447        /* Execute the Device._UID method */
448
449        Status = AcpiUtExecute_UID (Node, &Uid);
450        if (ACPI_SUCCESS (Status))
451        {
452            InfoSize += Uid->Length;
453            Valid |= ACPI_VALID_UID;
454        }
455
456        /* Execute the Device._CID method */
457
458        Status = AcpiUtExecute_CID (Node, &CidList);
459        if (ACPI_SUCCESS (Status))
460        {
461            /* Add size of CID strings and CID pointer array */
462
463            InfoSize += (CidList->ListSize - sizeof (ACPI_DEVICE_ID_LIST));
464            Valid |= ACPI_VALID_CID;
465        }
466    }
467
468    /*
469     * Now that we have the variable-length data, we can allocate the
470     * return buffer
471     */
472    Info = ACPI_ALLOCATE_ZEROED (InfoSize);
473    if (!Info)
474    {
475        Status = AE_NO_MEMORY;
476        goto Cleanup;
477    }
478
479    /* Get the fixed-length data */
480
481    if ((Type == ACPI_TYPE_DEVICE) ||
482        (Type == ACPI_TYPE_PROCESSOR))
483    {
484        /*
485         * Get extra info for ACPI Device/Processor objects only:
486         * Run the _STA, _ADR and, SxW, and _SxD methods.
487         *
488         * Note: none of these methods are required, so they may or may
489         * not be present for this device. The Info->Valid bitfield is used
490         * to indicate which methods were found and run successfully.
491         */
492
493        /* Execute the Device._STA method */
494
495        Status = AcpiUtExecute_STA (Node, &Info->CurrentStatus);
496        if (ACPI_SUCCESS (Status))
497        {
498            Valid |= ACPI_VALID_STA;
499        }
500
501        /* Execute the Device._ADR method */
502
503        Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node,
504                    &Info->Address);
505        if (ACPI_SUCCESS (Status))
506        {
507            Valid |= ACPI_VALID_ADR;
508        }
509
510        /* Execute the Device._SxW methods */
511
512        Status = AcpiUtExecutePowerMethods (Node,
513                    AcpiGbl_LowestDstateNames, ACPI_NUM_SxW_METHODS,
514                    Info->LowestDstates);
515        if (ACPI_SUCCESS (Status))
516        {
517            Valid |= ACPI_VALID_SXWS;
518        }
519
520        /* Execute the Device._SxD methods */
521
522        Status = AcpiUtExecutePowerMethods (Node,
523                    AcpiGbl_HighestDstateNames, ACPI_NUM_SxD_METHODS,
524                    Info->HighestDstates);
525        if (ACPI_SUCCESS (Status))
526        {
527            Valid |= ACPI_VALID_SXDS;
528        }
529    }
530
531    /*
532     * Create a pointer to the string area of the return buffer.
533     * Point to the end of the base ACPI_DEVICE_INFO structure.
534     */
535    NextIdString = ACPI_CAST_PTR (char, Info->CompatibleIdList.Ids);
536    if (CidList)
537    {
538        /* Point past the CID DEVICE_ID array */
539
540        NextIdString += ((ACPI_SIZE) CidList->Count * sizeof (ACPI_DEVICE_ID));
541    }
542
543    /*
544     * Copy the HID, UID, and CIDs to the return buffer. The variable-length
545     * strings are copied to the reserved area at the end of the buffer.
546     *
547     * For HID and CID, check if the ID is a PCI Root Bridge.
548     */
549    if (Hid)
550    {
551        NextIdString = AcpiNsCopyDeviceId (&Info->HardwareId,
552            Hid, NextIdString);
553
554        if (AcpiUtIsPciRootBridge (Hid->String))
555        {
556            Info->Flags |= ACPI_PCI_ROOT_BRIDGE;
557        }
558    }
559
560    if (Uid)
561    {
562        NextIdString = AcpiNsCopyDeviceId (&Info->UniqueId,
563            Uid, NextIdString);
564    }
565
566    if (CidList)
567    {
568        Info->CompatibleIdList.Count = CidList->Count;
569        Info->CompatibleIdList.ListSize = CidList->ListSize;
570
571        /* Copy each CID */
572
573        for (i = 0; i < CidList->Count; i++)
574        {
575            NextIdString = AcpiNsCopyDeviceId (&Info->CompatibleIdList.Ids[i],
576                &CidList->Ids[i], NextIdString);
577
578            if (AcpiUtIsPciRootBridge (CidList->Ids[i].String))
579            {
580                Info->Flags |= ACPI_PCI_ROOT_BRIDGE;
581            }
582        }
583    }
584
585    /* Copy the fixed-length data */
586
587    Info->InfoSize = InfoSize;
588    Info->Type = Type;
589    Info->Name = Name;
590    Info->ParamCount = ParamCount;
591    Info->Valid = Valid;
592
593    *ReturnBuffer = Info;
594    Status = AE_OK;
595
596
597Cleanup:
598    if (Hid)
599    {
600        ACPI_FREE (Hid);
601    }
602    if (Uid)
603    {
604        ACPI_FREE (Uid);
605    }
606    if (CidList)
607    {
608        ACPI_FREE (CidList);
609    }
610    return (Status);
611}
612
613ACPI_EXPORT_SYMBOL (AcpiGetObjectInfo)
614
615
616/******************************************************************************
617 *
618 * FUNCTION:    AcpiInstallMethod
619 *
620 * PARAMETERS:  Buffer         - An ACPI table containing one control method
621 *
622 * RETURN:      Status
623 *
624 * DESCRIPTION: Install a control method into the namespace. If the method
625 *              name already exists in the namespace, it is overwritten. The
626 *              input buffer must contain a valid DSDT or SSDT containing a
627 *              single control method.
628 *
629 ******************************************************************************/
630
631ACPI_STATUS
632AcpiInstallMethod (
633    UINT8                   *Buffer)
634{
635    ACPI_TABLE_HEADER       *Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, Buffer);
636    UINT8                   *AmlBuffer;
637    UINT8                   *AmlStart;
638    char                    *Path;
639    ACPI_NAMESPACE_NODE     *Node;
640    ACPI_OPERAND_OBJECT     *MethodObj;
641    ACPI_PARSE_STATE        ParserState;
642    UINT32                  AmlLength;
643    UINT16                  Opcode;
644    UINT8                   MethodFlags;
645    ACPI_STATUS             Status;
646
647
648    /* Parameter validation */
649
650    if (!Buffer)
651    {
652        return (AE_BAD_PARAMETER);
653    }
654
655    /* Table must be a DSDT or SSDT */
656
657    if (!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) &&
658        !ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT))
659    {
660        return (AE_BAD_HEADER);
661    }
662
663    /* First AML opcode in the table must be a control method */
664
665    ParserState.Aml = Buffer + sizeof (ACPI_TABLE_HEADER);
666    Opcode = AcpiPsPeekOpcode (&ParserState);
667    if (Opcode != AML_METHOD_OP)
668    {
669        return (AE_BAD_PARAMETER);
670    }
671
672    /* Extract method information from the raw AML */
673
674    ParserState.Aml += AcpiPsGetOpcodeSize (Opcode);
675    ParserState.PkgEnd = AcpiPsGetNextPackageEnd (&ParserState);
676    Path = AcpiPsGetNextNamestring (&ParserState);
677    MethodFlags = *ParserState.Aml++;
678    AmlStart = ParserState.Aml;
679    AmlLength = ACPI_PTR_DIFF (ParserState.PkgEnd, AmlStart);
680
681    /*
682     * Allocate resources up-front. We don't want to have to delete a new
683     * node from the namespace if we cannot allocate memory.
684     */
685    AmlBuffer = ACPI_ALLOCATE (AmlLength);
686    if (!AmlBuffer)
687    {
688        return (AE_NO_MEMORY);
689    }
690
691    MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
692    if (!MethodObj)
693    {
694        ACPI_FREE (AmlBuffer);
695        return (AE_NO_MEMORY);
696    }
697
698    /* Lock namespace for AcpiNsLookup, we may be creating a new node */
699
700    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
701    if (ACPI_FAILURE (Status))
702    {
703        goto ErrorExit;
704    }
705
706    /* The lookup either returns an existing node or creates a new one */
707
708    Status = AcpiNsLookup (NULL, Path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
709                ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, NULL, &Node);
710
711    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
712
713    if (ACPI_FAILURE (Status)) /* NsLookup */
714    {
715        if (Status != AE_ALREADY_EXISTS)
716        {
717            goto ErrorExit;
718        }
719
720        /* Node existed previously, make sure it is a method node */
721
722        if (Node->Type != ACPI_TYPE_METHOD)
723        {
724            Status = AE_TYPE;
725            goto ErrorExit;
726        }
727    }
728
729    /* Copy the method AML to the local buffer */
730
731    ACPI_MEMCPY (AmlBuffer, AmlStart, AmlLength);
732
733    /* Initialize the method object with the new method's information */
734
735    MethodObj->Method.AmlStart = AmlBuffer;
736    MethodObj->Method.AmlLength = AmlLength;
737
738    MethodObj->Method.ParamCount = (UINT8)
739        (MethodFlags & AML_METHOD_ARG_COUNT);
740
741    MethodObj->Method.MethodFlags = (UINT8)
742        (MethodFlags & ~AML_METHOD_ARG_COUNT);
743
744    if (MethodFlags & AML_METHOD_SERIALIZED)
745    {
746        MethodObj->Method.SyncLevel = (UINT8)
747            ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4);
748    }
749
750    /*
751     * Now that it is complete, we can attach the new method object to
752     * the method Node (detaches/deletes any existing object)
753     */
754    Status = AcpiNsAttachObject (Node, MethodObj,
755                ACPI_TYPE_METHOD);
756
757    /*
758     * Flag indicates AML buffer is dynamic, must be deleted later.
759     * Must be set only after attach above.
760     */
761    Node->Flags |= ANOBJ_ALLOCATED_BUFFER;
762
763    /* Remove local reference to the method object */
764
765    AcpiUtRemoveReference (MethodObj);
766    return (Status);
767
768
769ErrorExit:
770
771    ACPI_FREE (AmlBuffer);
772    ACPI_FREE (MethodObj);
773    return (Status);
774}
775
776ACPI_EXPORT_SYMBOL (AcpiInstallMethod)
777