xref: /netbsd-src/sys/external/bsd/acpica/dist/namespace/nsxfname.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /******************************************************************************
2  *
3  * Module Name: nsxfname - Public interfaces to the ACPI subsystem
4  *                         ACPI Namespace oriented interfaces
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2013, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44 
45 #define __NSXFNAME_C__
46 #define EXPORT_ACPI_INTERFACES
47 
48 #include "acpi.h"
49 #include "accommon.h"
50 #include "acnamesp.h"
51 #include "acparser.h"
52 #include "amlcode.h"
53 
54 
55 #define _COMPONENT          ACPI_NAMESPACE
56         ACPI_MODULE_NAME    ("nsxfname")
57 
58 /* Local prototypes */
59 
60 static char *
61 AcpiNsCopyDeviceId (
62     ACPI_PNP_DEVICE_ID      *Dest,
63     ACPI_PNP_DEVICE_ID      *Source,
64     char                    *StringArea);
65 
66 
67 /******************************************************************************
68  *
69  * FUNCTION:    AcpiGetHandle
70  *
71  * PARAMETERS:  Parent          - Object to search under (search scope).
72  *              Pathname        - Pointer to an asciiz string containing the
73  *                                name
74  *              RetHandle       - Where the return handle is returned
75  *
76  * RETURN:      Status
77  *
78  * DESCRIPTION: This routine will search for a caller specified name in the
79  *              name space. The caller can restrict the search region by
80  *              specifying a non NULL parent. The parent value is itself a
81  *              namespace handle.
82  *
83  ******************************************************************************/
84 
85 ACPI_STATUS
86 AcpiGetHandle (
87     ACPI_HANDLE             Parent,
88     ACPI_CONST_STRING       Pathname,
89     ACPI_HANDLE             *RetHandle)
90 {
91     ACPI_STATUS             Status;
92     ACPI_NAMESPACE_NODE     *Node = NULL;
93     ACPI_NAMESPACE_NODE     *PrefixNode = NULL;
94     ACPI_STRING             UPathname = __UNCONST(Pathname);
95 
96 
97     ACPI_FUNCTION_ENTRY ();
98 
99 
100     /* Parameter Validation */
101 
102     if (!RetHandle || !Pathname)
103     {
104         return (AE_BAD_PARAMETER);
105     }
106 
107     /* Convert a parent handle to a prefix node */
108 
109     if (Parent)
110     {
111         PrefixNode = AcpiNsValidateHandle (Parent);
112         if (!PrefixNode)
113         {
114             return (AE_BAD_PARAMETER);
115         }
116     }
117 
118     /*
119      * Valid cases are:
120      * 1) Fully qualified pathname
121      * 2) Parent + Relative pathname
122      *
123      * Error for <null Parent + relative path>
124      */
125     if (ACPI_IS_ROOT_PREFIX (Pathname[0]))
126     {
127         /* Pathname is fully qualified (starts with '\') */
128 
129         /* Special case for root-only, since we can't search for it */
130 
131         if (!ACPI_STRCMP (UPathname, ACPI_NS_ROOT_PATH))
132         {
133             *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, AcpiGbl_RootNode);
134             return (AE_OK);
135         }
136     }
137     else if (!PrefixNode)
138     {
139         /* Relative path with null prefix is disallowed */
140 
141         return (AE_BAD_PARAMETER);
142     }
143 
144     /* Find the Node and convert to a handle */
145 
146     Status = AcpiNsGetNode (PrefixNode, UPathname, ACPI_NS_NO_UPSEARCH, &Node);
147     if (ACPI_SUCCESS (Status))
148     {
149         *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, Node);
150     }
151 
152     return (Status);
153 }
154 
155 ACPI_EXPORT_SYMBOL (AcpiGetHandle)
156 
157 
158 /******************************************************************************
159  *
160  * FUNCTION:    AcpiGetName
161  *
162  * PARAMETERS:  Handle          - Handle to be converted to a pathname
163  *              NameType        - Full pathname or single segment
164  *              Buffer          - Buffer for returned path
165  *
166  * RETURN:      Pointer to a string containing the fully qualified Name.
167  *
168  * DESCRIPTION: This routine returns the fully qualified name associated with
169  *              the Handle parameter. This and the AcpiPathnameToHandle are
170  *              complementary functions.
171  *
172  ******************************************************************************/
173 
174 ACPI_STATUS
175 AcpiGetName (
176     ACPI_HANDLE             Handle,
177     UINT32                  NameType,
178     ACPI_BUFFER             *Buffer)
179 {
180     ACPI_STATUS             Status;
181     ACPI_NAMESPACE_NODE     *Node;
182     char                    *NodeName;
183 
184 
185     /* Parameter validation */
186 
187     if (NameType > ACPI_NAME_TYPE_MAX)
188     {
189         return (AE_BAD_PARAMETER);
190     }
191 
192     Status = AcpiUtValidateBuffer (Buffer);
193     if (ACPI_FAILURE (Status))
194     {
195         return (Status);
196     }
197 
198     if (NameType == ACPI_FULL_PATHNAME)
199     {
200         /* Get the full pathname (From the namespace root) */
201 
202         Status = AcpiNsHandleToPathname (Handle, Buffer);
203         return (Status);
204     }
205 
206     /*
207      * Wants the single segment ACPI name.
208      * Validate handle and convert to a namespace Node
209      */
210     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
211     if (ACPI_FAILURE (Status))
212     {
213         return (Status);
214     }
215 
216     Node = AcpiNsValidateHandle (Handle);
217     if (!Node)
218     {
219         Status = AE_BAD_PARAMETER;
220         goto UnlockAndExit;
221     }
222 
223     /* Validate/Allocate/Clear caller buffer */
224 
225     Status = AcpiUtInitializeBuffer (Buffer, ACPI_PATH_SEGMENT_LENGTH);
226     if (ACPI_FAILURE (Status))
227     {
228         goto UnlockAndExit;
229     }
230 
231     /* Just copy the ACPI name from the Node and zero terminate it */
232 
233     NodeName = __UNCONST(AcpiUtGetNodeName (Node));
234     ACPI_MOVE_NAME (Buffer->Pointer, NodeName);
235     ((char *) Buffer->Pointer) [ACPI_NAME_SIZE] = 0;
236     Status = AE_OK;
237 
238 
239 UnlockAndExit:
240 
241     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
242     return (Status);
243 }
244 
245 ACPI_EXPORT_SYMBOL (AcpiGetName)
246 
247 
248 /******************************************************************************
249  *
250  * FUNCTION:    AcpiNsCopyDeviceId
251  *
252  * PARAMETERS:  Dest                - Pointer to the destination PNP_DEVICE_ID
253  *              Source              - Pointer to the source PNP_DEVICE_ID
254  *              StringArea          - Pointer to where to copy the dest string
255  *
256  * RETURN:      Pointer to the next string area
257  *
258  * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data.
259  *
260  ******************************************************************************/
261 
262 static char *
263 AcpiNsCopyDeviceId (
264     ACPI_PNP_DEVICE_ID      *Dest,
265     ACPI_PNP_DEVICE_ID      *Source,
266     char                    *StringArea)
267 {
268 
269     /* Create the destination PNP_DEVICE_ID */
270 
271     Dest->String = StringArea;
272     Dest->Length = Source->Length;
273 
274     /* Copy actual string and return a pointer to the next string area */
275 
276     ACPI_MEMCPY (StringArea, Source->String, Source->Length);
277     return (StringArea + Source->Length);
278 }
279 
280 
281 /******************************************************************************
282  *
283  * FUNCTION:    AcpiGetObjectInfo
284  *
285  * PARAMETERS:  Handle              - Object Handle
286  *              ReturnBuffer        - Where the info is returned
287  *
288  * RETURN:      Status
289  *
290  * DESCRIPTION: Returns information about an object as gleaned from the
291  *              namespace node and possibly by running several standard
292  *              control methods (Such as in the case of a device.)
293  *
294  * For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB,
295  * _STA, _ADR, _SxW, and _SxD methods.
296  *
297  * Note: Allocates the return buffer, must be freed by the caller.
298  *
299  ******************************************************************************/
300 
301 ACPI_STATUS
302 AcpiGetObjectInfo (
303     ACPI_HANDLE             Handle,
304     ACPI_DEVICE_INFO        **ReturnBuffer)
305 {
306     ACPI_NAMESPACE_NODE     *Node;
307     ACPI_DEVICE_INFO        *Info;
308     ACPI_PNP_DEVICE_ID_LIST *CidList = NULL;
309     ACPI_PNP_DEVICE_ID      *Hid = NULL;
310     ACPI_PNP_DEVICE_ID      *Uid = NULL;
311     ACPI_PNP_DEVICE_ID      *Sub = NULL;
312     char                    *NextIdString;
313     ACPI_OBJECT_TYPE        Type;
314     ACPI_NAME               Name;
315     UINT8                   ParamCount= 0;
316     UINT8                   Valid = 0;
317     UINT32                  InfoSize;
318     UINT32                  i;
319     ACPI_STATUS             Status;
320 
321 
322     /* Parameter validation */
323 
324     if (!Handle || !ReturnBuffer)
325     {
326         return (AE_BAD_PARAMETER);
327     }
328 
329     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
330     if (ACPI_FAILURE (Status))
331     {
332         return (Status);
333     }
334 
335     Node = AcpiNsValidateHandle (Handle);
336     if (!Node)
337     {
338         (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
339         return (AE_BAD_PARAMETER);
340     }
341 
342     /* Get the namespace node data while the namespace is locked */
343 
344     InfoSize = sizeof (ACPI_DEVICE_INFO);
345     Type = Node->Type;
346     Name = Node->Name.Integer;
347 
348     if (Node->Type == ACPI_TYPE_METHOD)
349     {
350         ParamCount = Node->Object->Method.ParamCount;
351     }
352 
353     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
354     if (ACPI_FAILURE (Status))
355     {
356         return (Status);
357     }
358 
359     if ((Type == ACPI_TYPE_DEVICE) ||
360         (Type == ACPI_TYPE_PROCESSOR))
361     {
362         /*
363          * Get extra info for ACPI Device/Processor objects only:
364          * Run the Device _HID, _UID, _SUB, and _CID methods.
365          *
366          * Note: none of these methods are required, so they may or may
367          * not be present for this device. The Info->Valid bitfield is used
368          * to indicate which methods were found and run successfully.
369          */
370 
371         /* Execute the Device._HID method */
372 
373         Status = AcpiUtExecute_HID (Node, &Hid);
374         if (ACPI_SUCCESS (Status))
375         {
376             InfoSize += Hid->Length;
377             Valid |= ACPI_VALID_HID;
378         }
379 
380         /* Execute the Device._UID method */
381 
382         Status = AcpiUtExecute_UID (Node, &Uid);
383         if (ACPI_SUCCESS (Status))
384         {
385             InfoSize += Uid->Length;
386             Valid |= ACPI_VALID_UID;
387         }
388 
389         /* Execute the Device._SUB method */
390 
391         Status = AcpiUtExecute_SUB (Node, &Sub);
392         if (ACPI_SUCCESS (Status))
393         {
394             InfoSize += Sub->Length;
395             Valid |= ACPI_VALID_SUB;
396         }
397 
398         /* Execute the Device._CID method */
399 
400         Status = AcpiUtExecute_CID (Node, &CidList);
401         if (ACPI_SUCCESS (Status))
402         {
403             /* Add size of CID strings and CID pointer array */
404 
405             InfoSize += (CidList->ListSize - sizeof (ACPI_PNP_DEVICE_ID_LIST));
406             Valid |= ACPI_VALID_CID;
407         }
408     }
409 
410     /*
411      * Now that we have the variable-length data, we can allocate the
412      * return buffer
413      */
414     Info = ACPI_ALLOCATE_ZEROED (InfoSize);
415     if (!Info)
416     {
417         Status = AE_NO_MEMORY;
418         goto Cleanup;
419     }
420 
421     /* Get the fixed-length data */
422 
423     if ((Type == ACPI_TYPE_DEVICE) ||
424         (Type == ACPI_TYPE_PROCESSOR))
425     {
426         /*
427          * Get extra info for ACPI Device/Processor objects only:
428          * Run the _STA, _ADR and, SxW, and _SxD methods.
429          *
430          * Notes: none of these methods are required, so they may or may
431          * not be present for this device. The Info->Valid bitfield is used
432          * to indicate which methods were found and run successfully.
433          *
434          * For _STA, if the method does not exist, then (as per the ACPI
435          * specification), the returned CurrentStatus flags will indicate
436          * that the device is present/functional/enabled. Otherwise, the
437          * CurrentStatus flags reflect the value returned from _STA.
438          */
439 
440         /* Execute the Device._STA method */
441 
442         Status = AcpiUtExecute_STA (Node, &Info->CurrentStatus);
443         if (ACPI_SUCCESS (Status))
444         {
445             Valid |= ACPI_VALID_STA;
446         }
447 
448         /* Execute the Device._ADR method */
449 
450         Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node,
451                     &Info->Address);
452         if (ACPI_SUCCESS (Status))
453         {
454             Valid |= ACPI_VALID_ADR;
455         }
456 
457         /* Execute the Device._SxW methods */
458 
459         Status = AcpiUtExecutePowerMethods (Node,
460                     AcpiGbl_LowestDstateNames, ACPI_NUM_SxW_METHODS,
461                     Info->LowestDstates);
462         if (ACPI_SUCCESS (Status))
463         {
464             Valid |= ACPI_VALID_SXWS;
465         }
466 
467         /* Execute the Device._SxD methods */
468 
469         Status = AcpiUtExecutePowerMethods (Node,
470                     AcpiGbl_HighestDstateNames, ACPI_NUM_SxD_METHODS,
471                     Info->HighestDstates);
472         if (ACPI_SUCCESS (Status))
473         {
474             Valid |= ACPI_VALID_SXDS;
475         }
476     }
477 
478     /*
479      * Create a pointer to the string area of the return buffer.
480      * Point to the end of the base ACPI_DEVICE_INFO structure.
481      */
482     NextIdString = ACPI_CAST_PTR (char, Info->CompatibleIdList.Ids);
483     if (CidList)
484     {
485         /* Point past the CID PNP_DEVICE_ID array */
486 
487         NextIdString += ((ACPI_SIZE) CidList->Count * sizeof (ACPI_PNP_DEVICE_ID));
488     }
489 
490     /*
491      * Copy the HID, UID, SUB, and CIDs to the return buffer.
492      * The variable-length strings are copied to the reserved area
493      * at the end of the buffer.
494      *
495      * For HID and CID, check if the ID is a PCI Root Bridge.
496      */
497     if (Hid)
498     {
499         NextIdString = AcpiNsCopyDeviceId (&Info->HardwareId,
500             Hid, NextIdString);
501 
502         if (AcpiUtIsPciRootBridge (Hid->String))
503         {
504             Info->Flags |= ACPI_PCI_ROOT_BRIDGE;
505         }
506     }
507 
508     if (Uid)
509     {
510         NextIdString = AcpiNsCopyDeviceId (&Info->UniqueId,
511             Uid, NextIdString);
512     }
513 
514     if (Sub)
515     {
516         NextIdString = AcpiNsCopyDeviceId (&Info->SubsystemId,
517             Sub, NextIdString);
518     }
519 
520     if (CidList)
521     {
522         Info->CompatibleIdList.Count = CidList->Count;
523         Info->CompatibleIdList.ListSize = CidList->ListSize;
524 
525         /* Copy each CID */
526 
527         for (i = 0; i < CidList->Count; i++)
528         {
529             NextIdString = AcpiNsCopyDeviceId (&Info->CompatibleIdList.Ids[i],
530                 &CidList->Ids[i], NextIdString);
531 
532             if (AcpiUtIsPciRootBridge (CidList->Ids[i].String))
533             {
534                 Info->Flags |= ACPI_PCI_ROOT_BRIDGE;
535             }
536         }
537     }
538 
539     /* Copy the fixed-length data */
540 
541     Info->InfoSize = InfoSize;
542     Info->Type = Type;
543     Info->Name = Name;
544     Info->ParamCount = ParamCount;
545     Info->Valid = Valid;
546 
547     *ReturnBuffer = Info;
548     Status = AE_OK;
549 
550 
551 Cleanup:
552     if (Hid)
553     {
554         ACPI_FREE (Hid);
555     }
556     if (Uid)
557     {
558         ACPI_FREE (Uid);
559     }
560     if (Sub)
561     {
562         ACPI_FREE (Sub);
563     }
564     if (CidList)
565     {
566         ACPI_FREE (CidList);
567     }
568     return (Status);
569 }
570 
571 ACPI_EXPORT_SYMBOL (AcpiGetObjectInfo)
572 
573 
574 /******************************************************************************
575  *
576  * FUNCTION:    AcpiInstallMethod
577  *
578  * PARAMETERS:  Buffer         - An ACPI table containing one control method
579  *
580  * RETURN:      Status
581  *
582  * DESCRIPTION: Install a control method into the namespace. If the method
583  *              name already exists in the namespace, it is overwritten. The
584  *              input buffer must contain a valid DSDT or SSDT containing a
585  *              single control method.
586  *
587  ******************************************************************************/
588 
589 ACPI_STATUS
590 AcpiInstallMethod (
591     UINT8                   *Buffer)
592 {
593     ACPI_TABLE_HEADER       *Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, Buffer);
594     UINT8                   *AmlBuffer;
595     UINT8                   *AmlStart;
596     char                    *Path;
597     ACPI_NAMESPACE_NODE     *Node;
598     ACPI_OPERAND_OBJECT     *MethodObj;
599     ACPI_PARSE_STATE        ParserState;
600     UINT32                  AmlLength;
601     UINT16                  Opcode;
602     UINT8                   MethodFlags;
603     ACPI_STATUS             Status;
604 
605 
606     /* Parameter validation */
607 
608     if (!Buffer)
609     {
610         return (AE_BAD_PARAMETER);
611     }
612 
613     /* Table must be a DSDT or SSDT */
614 
615     if (!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) &&
616         !ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT))
617     {
618         return (AE_BAD_HEADER);
619     }
620 
621     /* First AML opcode in the table must be a control method */
622 
623     ParserState.Aml = Buffer + sizeof (ACPI_TABLE_HEADER);
624     Opcode = AcpiPsPeekOpcode (&ParserState);
625     if (Opcode != AML_METHOD_OP)
626     {
627         return (AE_BAD_PARAMETER);
628     }
629 
630     /* Extract method information from the raw AML */
631 
632     ParserState.Aml += AcpiPsGetOpcodeSize (Opcode);
633     ParserState.PkgEnd = AcpiPsGetNextPackageEnd (&ParserState);
634     Path = AcpiPsGetNextNamestring (&ParserState);
635     MethodFlags = *ParserState.Aml++;
636     AmlStart = ParserState.Aml;
637     AmlLength = ACPI_PTR_DIFF (ParserState.PkgEnd, AmlStart);
638 
639     /*
640      * Allocate resources up-front. We don't want to have to delete a new
641      * node from the namespace if we cannot allocate memory.
642      */
643     AmlBuffer = ACPI_ALLOCATE (AmlLength);
644     if (!AmlBuffer)
645     {
646         return (AE_NO_MEMORY);
647     }
648 
649     MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
650     if (!MethodObj)
651     {
652         ACPI_FREE (AmlBuffer);
653         return (AE_NO_MEMORY);
654     }
655 
656     /* Lock namespace for AcpiNsLookup, we may be creating a new node */
657 
658     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
659     if (ACPI_FAILURE (Status))
660     {
661         goto ErrorExit;
662     }
663 
664     /* The lookup either returns an existing node or creates a new one */
665 
666     Status = AcpiNsLookup (NULL, Path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
667                 ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, NULL, &Node);
668 
669     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
670 
671     if (ACPI_FAILURE (Status)) /* NsLookup */
672     {
673         if (Status != AE_ALREADY_EXISTS)
674         {
675             goto ErrorExit;
676         }
677 
678         /* Node existed previously, make sure it is a method node */
679 
680         if (Node->Type != ACPI_TYPE_METHOD)
681         {
682             Status = AE_TYPE;
683             goto ErrorExit;
684         }
685     }
686 
687     /* Copy the method AML to the local buffer */
688 
689     ACPI_MEMCPY (AmlBuffer, AmlStart, AmlLength);
690 
691     /* Initialize the method object with the new method's information */
692 
693     MethodObj->Method.AmlStart = AmlBuffer;
694     MethodObj->Method.AmlLength = AmlLength;
695 
696     MethodObj->Method.ParamCount = (UINT8)
697         (MethodFlags & AML_METHOD_ARG_COUNT);
698 
699     if (MethodFlags & AML_METHOD_SERIALIZED)
700     {
701         MethodObj->Method.InfoFlags = ACPI_METHOD_SERIALIZED;
702 
703         MethodObj->Method.SyncLevel = (UINT8)
704             ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4);
705     }
706 
707     /*
708      * Now that it is complete, we can attach the new method object to
709      * the method Node (detaches/deletes any existing object)
710      */
711     Status = AcpiNsAttachObject (Node, MethodObj, ACPI_TYPE_METHOD);
712 
713     /*
714      * Flag indicates AML buffer is dynamic, must be deleted later.
715      * Must be set only after attach above.
716      */
717     Node->Flags |= ANOBJ_ALLOCATED_BUFFER;
718 
719     /* Remove local reference to the method object */
720 
721     AcpiUtRemoveReference (MethodObj);
722     return (Status);
723 
724 
725 ErrorExit:
726 
727     ACPI_FREE (AmlBuffer);
728     ACPI_FREE (MethodObj);
729     return (Status);
730 }
731 
732 ACPI_EXPORT_SYMBOL (AcpiInstallMethod)
733