xref: /netbsd-src/sys/external/bsd/acpica/dist/namespace/nsxfname.c (revision 2c7d7e3ca2e4f0b675c6c58e614f6aede66c678e)
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 - 2023, 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 MERCHANTABILITY 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 EXPORT_ACPI_INTERFACES
46 
47 #include "acpi.h"
48 #include "accommon.h"
49 #include "acnamesp.h"
50 #include "acparser.h"
51 #include "amlcode.h"
52 
53 
54 #define _COMPONENT          ACPI_NAMESPACE
55         ACPI_MODULE_NAME    ("nsxfname")
56 
57 /* Local prototypes */
58 
59 static char *
60 AcpiNsCopyDeviceId (
61     ACPI_PNP_DEVICE_ID      *Dest,
62     ACPI_PNP_DEVICE_ID      *Source,
63     char                    *StringArea);
64 
65 
66 /******************************************************************************
67  *
68  * FUNCTION:    AcpiGetHandle
69  *
70  * PARAMETERS:  Parent          - Object to search under (search scope).
71  *              Pathname        - Pointer to an asciiz string containing the
72  *                                name
73  *              RetHandle       - Where the return handle is returned
74  *
75  * RETURN:      Status
76  *
77  * DESCRIPTION: This routine will search for a caller specified name in the
78  *              name space. The caller can restrict the search region by
79  *              specifying a non NULL parent. The parent value is itself a
80  *              namespace handle.
81  *
82  ******************************************************************************/
83 
84 ACPI_STATUS
AcpiGetHandle(ACPI_HANDLE Parent,const char * Pathname,ACPI_HANDLE * RetHandle)85 AcpiGetHandle (
86     ACPI_HANDLE             Parent,
87     const char              *Pathname,
88     ACPI_HANDLE             *RetHandle)
89 {
90     ACPI_STATUS             Status;
91     ACPI_NAMESPACE_NODE     *Node = NULL;
92     ACPI_NAMESPACE_NODE     *PrefixNode = NULL;
93     ACPI_STRING             UPathname = __UNCONST(Pathname);
94 
95 
96     ACPI_FUNCTION_ENTRY ();
97 
98 
99     /* Parameter Validation */
100 
101     if (!RetHandle || !Pathname)
102     {
103         return (AE_BAD_PARAMETER);
104     }
105 
106     /* Convert a parent handle to a prefix node */
107 
108     if (Parent)
109     {
110         PrefixNode = AcpiNsValidateHandle (Parent);
111         if (!PrefixNode)
112         {
113             return (AE_BAD_PARAMETER);
114         }
115     }
116 
117     /*
118      * Valid cases are:
119      * 1) Fully qualified pathname
120      * 2) Parent + Relative pathname
121      *
122      * Error for <null Parent + relative path>
123      */
124     if (ACPI_IS_ROOT_PREFIX (Pathname[0]))
125     {
126         /* Pathname is fully qualified (starts with '\') */
127 
128         /* Special case for root-only, since we can't search for it */
129 
130         if (!strcmp (Pathname, ACPI_NS_ROOT_PATH))
131         {
132             *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, AcpiGbl_RootNode);
133             return (AE_OK);
134         }
135     }
136     else if (!PrefixNode)
137     {
138         /* Relative path with null prefix is disallowed */
139 
140         return (AE_BAD_PARAMETER);
141     }
142 
143     /* Find the Node and convert to a handle */
144 
145     Status = AcpiNsGetNode (PrefixNode, UPathname, ACPI_NS_NO_UPSEARCH, &Node);
146     if (ACPI_SUCCESS (Status))
147     {
148         *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, Node);
149     }
150 
151     return (Status);
152 }
153 
ACPI_EXPORT_SYMBOL(AcpiGetHandle)154 ACPI_EXPORT_SYMBOL (AcpiGetHandle)
155 
156 
157 /******************************************************************************
158  *
159  * FUNCTION:    AcpiGetName
160  *
161  * PARAMETERS:  Handle          - Handle to be converted to a pathname
162  *              NameType        - Full pathname or single segment
163  *              Buffer          - Buffer for returned path
164  *
165  * RETURN:      Pointer to a string containing the fully qualified Name.
166  *
167  * DESCRIPTION: This routine returns the fully qualified name associated with
168  *              the Handle parameter. This and the AcpiPathnameToHandle are
169  *              complementary functions.
170  *
171  ******************************************************************************/
172 
173 ACPI_STATUS
174 AcpiGetName (
175     ACPI_HANDLE             Handle,
176     UINT32                  NameType,
177     ACPI_BUFFER             *Buffer)
178 {
179     ACPI_STATUS             Status;
180 
181 
182     /* Parameter validation */
183 
184     if (NameType > ACPI_NAME_TYPE_MAX)
185     {
186         return (AE_BAD_PARAMETER);
187     }
188 
189     Status = AcpiUtValidateBuffer (Buffer);
190     if (ACPI_FAILURE (Status))
191     {
192         return (Status);
193     }
194 
195     /*
196      * Wants the single segment ACPI name.
197      * Validate handle and convert to a namespace Node
198      */
199     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
200     if (ACPI_FAILURE (Status))
201     {
202         return (Status);
203     }
204 
205     if (NameType == ACPI_FULL_PATHNAME ||
206         NameType == ACPI_FULL_PATHNAME_NO_TRAILING)
207     {
208         /* Get the full pathname (From the namespace root) */
209 
210         Status = AcpiNsHandleToPathname (Handle, Buffer,
211             NameType == ACPI_FULL_PATHNAME ? FALSE : TRUE);
212     }
213     else
214     {
215         /* Get the single name */
216 
217         Status = AcpiNsHandleToName (Handle, Buffer);
218     }
219 
220     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
221     return (Status);
222 }
223 
ACPI_EXPORT_SYMBOL(AcpiGetName)224 ACPI_EXPORT_SYMBOL (AcpiGetName)
225 
226 
227 /******************************************************************************
228  *
229  * FUNCTION:    AcpiNsCopyDeviceId
230  *
231  * PARAMETERS:  Dest                - Pointer to the destination PNP_DEVICE_ID
232  *              Source              - Pointer to the source PNP_DEVICE_ID
233  *              StringArea          - Pointer to where to copy the dest string
234  *
235  * RETURN:      Pointer to the next string area
236  *
237  * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data.
238  *
239  ******************************************************************************/
240 
241 static char *
242 AcpiNsCopyDeviceId (
243     ACPI_PNP_DEVICE_ID      *Dest,
244     ACPI_PNP_DEVICE_ID      *Source,
245     char                    *StringArea)
246 {
247     /* Create the destination PNP_DEVICE_ID */
248 
249     Dest->String = StringArea;
250     Dest->Length = Source->Length;
251 
252     /* Copy actual string and return a pointer to the next string area */
253 
254     memcpy (StringArea, Source->String, Source->Length);
255     return (StringArea + Source->Length);
256 }
257 
258 
259 /******************************************************************************
260  *
261  * FUNCTION:    AcpiGetObjectInfo
262  *
263  * PARAMETERS:  Handle              - Object Handle
264  *              ReturnBuffer        - Where the info is returned
265  *
266  * RETURN:      Status
267  *
268  * DESCRIPTION: Returns information about an object as gleaned from the
269  *              namespace node and possibly by running several standard
270  *              control methods (Such as in the case of a device.)
271  *
272  * For Device and Processor objects, run the Device _HID, _UID, _CID,
273  * _CLS, _ADR, _SxW, and _SxD methods.
274  *
275  * Note: Allocates the return buffer, must be freed by the caller.
276  *
277  * Note: This interface is intended to be used during the initial device
278  * discovery namespace traversal. Therefore, no complex methods can be
279  * executed, especially those that access operation regions. Therefore, do
280  * not add any additional methods that could cause problems in this area.
281  * Because of this reason support for the following methods has been removed:
282  * 1) _SUB method was removed (11/2015)
283  * 2) _STA method was removed (02/2018)
284  *
285  ******************************************************************************/
286 
287 ACPI_STATUS
AcpiGetObjectInfo(ACPI_HANDLE Handle,ACPI_DEVICE_INFO ** ReturnBuffer)288 AcpiGetObjectInfo (
289     ACPI_HANDLE             Handle,
290     ACPI_DEVICE_INFO        **ReturnBuffer)
291 {
292     ACPI_NAMESPACE_NODE     *Node;
293     ACPI_DEVICE_INFO        *Info;
294     ACPI_PNP_DEVICE_ID_LIST *CidList = NULL;
295     ACPI_PNP_DEVICE_ID      *Hid = NULL;
296     ACPI_PNP_DEVICE_ID      *Uid = NULL;
297     ACPI_PNP_DEVICE_ID      *Cls = NULL;
298     char                    *NextIdString;
299     ACPI_OBJECT_TYPE        Type;
300     ACPI_NAME               Name;
301     UINT8                   ParamCount= 0;
302     UINT16                  Valid = 0;
303     UINT32                  InfoSize;
304     UINT32                  i;
305     ACPI_STATUS             Status;
306 
307 
308     /* Parameter validation */
309 
310     if (!Handle || !ReturnBuffer)
311     {
312         return (AE_BAD_PARAMETER);
313     }
314 
315     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
316     if (ACPI_FAILURE (Status))
317     {
318         return (Status);
319     }
320 
321     Node = AcpiNsValidateHandle (Handle);
322     if (!Node)
323     {
324         (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
325         return (AE_BAD_PARAMETER);
326     }
327 
328     /* Get the namespace node data while the namespace is locked */
329 
330     InfoSize = sizeof (ACPI_DEVICE_INFO);
331     Type = Node->Type;
332     Name = Node->Name.Integer;
333 
334     if (Node->Type == ACPI_TYPE_METHOD)
335     {
336         ParamCount = Node->Object->Method.ParamCount;
337     }
338 
339     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
340     if (ACPI_FAILURE (Status))
341     {
342         return (Status);
343     }
344 
345     if ((Type == ACPI_TYPE_DEVICE) ||
346         (Type == ACPI_TYPE_PROCESSOR))
347     {
348         /*
349          * Get extra info for ACPI Device/Processor objects only:
350          * Run the Device _HID, _UID, _CLS, and _CID methods.
351          *
352          * Note: none of these methods are required, so they may or may
353          * not be present for this device. The Info->Valid bitfield is used
354          * to indicate which methods were found and run successfully.
355          */
356 
357         /* Execute the Device._HID method */
358 
359         Status = AcpiUtExecute_HID (Node, &Hid);
360         if (ACPI_SUCCESS (Status))
361         {
362             InfoSize += Hid->Length;
363             Valid |= ACPI_VALID_HID;
364         }
365 
366         /* Execute the Device._UID method */
367 
368         Status = AcpiUtExecute_UID (Node, &Uid);
369         if (ACPI_SUCCESS (Status))
370         {
371             InfoSize += Uid->Length;
372             Valid |= ACPI_VALID_UID;
373         }
374 
375         /* Execute the Device._CID method */
376 
377         Status = AcpiUtExecute_CID (Node, &CidList);
378         if (ACPI_SUCCESS (Status))
379         {
380             /* Add size of CID strings and CID pointer array */
381 
382             InfoSize += (CidList->ListSize - sizeof (ACPI_PNP_DEVICE_ID_LIST));
383             Valid |= ACPI_VALID_CID;
384         }
385 
386         /* Execute the Device._CLS method */
387 
388         Status = AcpiUtExecute_CLS (Node, &Cls);
389         if (ACPI_SUCCESS (Status))
390         {
391             InfoSize += Cls->Length;
392             Valid |= ACPI_VALID_CLS;
393         }
394     }
395 
396     /*
397      * Now that we have the variable-length data, we can allocate the
398      * return buffer
399      */
400     Info = ACPI_ALLOCATE_ZEROED (InfoSize);
401     if (!Info)
402     {
403         Status = AE_NO_MEMORY;
404         goto Cleanup;
405     }
406 
407     /* Get the fixed-length data */
408 
409     if ((Type == ACPI_TYPE_DEVICE) ||
410         (Type == ACPI_TYPE_PROCESSOR))
411     {
412         /*
413          * Get extra info for ACPI Device/Processor objects only:
414          * Run the _ADR and, SxW, and _SxD methods.
415          *
416          * Notes: none of these methods are required, so they may or may
417          * not be present for this device. The Info->Valid bitfield is used
418          * to indicate which methods were found and run successfully.
419          */
420 
421         /* Execute the Device._ADR method */
422 
423         Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node,
424             &Info->Address);
425         if (ACPI_SUCCESS (Status))
426         {
427             Valid |= ACPI_VALID_ADR;
428         }
429 
430         /* Execute the Device._SxW methods */
431 
432         Status = AcpiUtExecutePowerMethods (Node,
433             AcpiGbl_LowestDstateNames, ACPI_NUM_SxW_METHODS,
434             Info->LowestDstates);
435         if (ACPI_SUCCESS (Status))
436         {
437             Valid |= ACPI_VALID_SXWS;
438         }
439 
440         /* Execute the Device._SxD methods */
441 
442         Status = AcpiUtExecutePowerMethods (Node,
443             AcpiGbl_HighestDstateNames, ACPI_NUM_SxD_METHODS,
444             Info->HighestDstates);
445         if (ACPI_SUCCESS (Status))
446         {
447             Valid |= ACPI_VALID_SXDS;
448         }
449     }
450 
451     /*
452      * Create a pointer to the string area of the return buffer.
453      * Point to the end of the base ACPI_DEVICE_INFO structure.
454      */
455     NextIdString = ACPI_CAST_PTR (char, Info->CompatibleIdList.Ids);
456     if (CidList)
457     {
458         /* Point past the CID PNP_DEVICE_ID array */
459 
460         NextIdString += ((ACPI_SIZE) CidList->Count * sizeof (ACPI_PNP_DEVICE_ID));
461     }
462 
463     /*
464      * Copy the HID, UID, and CIDs to the return buffer. The variable-length
465      * strings are copied to the reserved area at the end of the buffer.
466      *
467      * For HID and CID, check if the ID is a PCI Root Bridge.
468      */
469     if (Hid)
470     {
471         NextIdString = AcpiNsCopyDeviceId (&Info->HardwareId,
472             Hid, NextIdString);
473 
474         if (AcpiUtIsPciRootBridge (Hid->String))
475         {
476             Info->Flags |= ACPI_PCI_ROOT_BRIDGE;
477         }
478     }
479 
480     if (Uid)
481     {
482         NextIdString = AcpiNsCopyDeviceId (&Info->UniqueId,
483             Uid, NextIdString);
484     }
485 
486     if (CidList)
487     {
488         Info->CompatibleIdList.Count = CidList->Count;
489         Info->CompatibleIdList.ListSize = CidList->ListSize;
490 
491         /* Copy each CID */
492 
493         for (i = 0; i < CidList->Count; i++)
494         {
495             NextIdString = AcpiNsCopyDeviceId (&Info->CompatibleIdList.Ids[i],
496                 &CidList->Ids[i], NextIdString);
497 
498             if (AcpiUtIsPciRootBridge (CidList->Ids[i].String))
499             {
500                 Info->Flags |= ACPI_PCI_ROOT_BRIDGE;
501             }
502         }
503     }
504 
505     if (Cls)
506     {
507        (void) AcpiNsCopyDeviceId (&Info->ClassCode,
508             Cls, NextIdString);
509     }
510 
511     /* Copy the fixed-length data */
512 
513     Info->InfoSize = InfoSize;
514     Info->Type = Type;
515     Info->Name = Name;
516     Info->ParamCount = ParamCount;
517     Info->Valid = Valid;
518 
519     *ReturnBuffer = Info;
520     Status = AE_OK;
521 
522 
523 Cleanup:
524     if (Hid)
525     {
526         ACPI_FREE (Hid);
527     }
528     if (Uid)
529     {
530         ACPI_FREE (Uid);
531     }
532     if (CidList)
533     {
534         ACPI_FREE (CidList);
535     }
536     if (Cls)
537     {
538         ACPI_FREE (Cls);
539     }
540     return (Status);
541 }
542 
ACPI_EXPORT_SYMBOL(AcpiGetObjectInfo)543 ACPI_EXPORT_SYMBOL (AcpiGetObjectInfo)
544 
545 
546 /******************************************************************************
547  *
548  * FUNCTION:    AcpiInstallMethod
549  *
550  * PARAMETERS:  Buffer         - An ACPI table containing one control method
551  *
552  * RETURN:      Status
553  *
554  * DESCRIPTION: Install a control method into the namespace. If the method
555  *              name already exists in the namespace, it is overwritten. The
556  *              input buffer must contain a valid DSDT or SSDT containing a
557  *              single control method.
558  *
559  ******************************************************************************/
560 
561 ACPI_STATUS
562 AcpiInstallMethod (
563     UINT8                   *Buffer)
564 {
565     ACPI_TABLE_HEADER       *Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, Buffer);
566     UINT8                   *AmlBuffer;
567     UINT8                   *AmlStart;
568     char                    *Path;
569     ACPI_NAMESPACE_NODE     *Node;
570     ACPI_OPERAND_OBJECT     *MethodObj;
571     ACPI_PARSE_STATE        ParserState;
572     UINT32                  AmlLength;
573     UINT16                  Opcode;
574     UINT8                   MethodFlags;
575     ACPI_STATUS             Status;
576 
577 
578     /* Parameter validation */
579 
580     if (!Buffer)
581     {
582         return (AE_BAD_PARAMETER);
583     }
584 
585     /* Table must be a DSDT or SSDT */
586 
587     if (!ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_DSDT) &&
588         !ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_SSDT))
589     {
590         return (AE_BAD_HEADER);
591     }
592 
593     /* First AML opcode in the table must be a control method */
594 
595     ParserState.Aml = Buffer + sizeof (ACPI_TABLE_HEADER);
596     Opcode = AcpiPsPeekOpcode (&ParserState);
597     if (Opcode != AML_METHOD_OP)
598     {
599         return (AE_BAD_PARAMETER);
600     }
601 
602     /* Extract method information from the raw AML */
603 
604     ParserState.Aml += AcpiPsGetOpcodeSize (Opcode);
605     ParserState.PkgEnd = AcpiPsGetNextPackageEnd (&ParserState);
606     Path = AcpiPsGetNextNamestring (&ParserState);
607 
608     MethodFlags = *ParserState.Aml++;
609     AmlStart = ParserState.Aml;
610     AmlLength = (UINT32) ACPI_PTR_DIFF (ParserState.PkgEnd, AmlStart);
611 
612     /*
613      * Allocate resources up-front. We don't want to have to delete a new
614      * node from the namespace if we cannot allocate memory.
615      */
616     AmlBuffer = ACPI_ALLOCATE (AmlLength);
617     if (!AmlBuffer)
618     {
619         return (AE_NO_MEMORY);
620     }
621 
622     MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
623     if (!MethodObj)
624     {
625         ACPI_FREE (AmlBuffer);
626         return (AE_NO_MEMORY);
627     }
628 
629     /* Lock namespace for AcpiNsLookup, we may be creating a new node */
630 
631     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
632     if (ACPI_FAILURE (Status))
633     {
634         goto ErrorExit;
635     }
636 
637     /* The lookup either returns an existing node or creates a new one */
638 
639     Status = AcpiNsLookup (NULL, Path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
640         ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, NULL, &Node);
641 
642     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
643 
644     if (ACPI_FAILURE (Status)) /* NsLookup */
645     {
646         if (Status != AE_ALREADY_EXISTS)
647         {
648             goto ErrorExit;
649         }
650 
651         /* Node existed previously, make sure it is a method node */
652 
653         if (Node->Type != ACPI_TYPE_METHOD)
654         {
655             Status = AE_TYPE;
656             goto ErrorExit;
657         }
658     }
659 
660     /* Copy the method AML to the local buffer */
661 
662     memcpy (AmlBuffer, AmlStart, AmlLength);
663 
664     /* Initialize the method object with the new method's information */
665 
666     MethodObj->Method.AmlStart = AmlBuffer;
667     MethodObj->Method.AmlLength = AmlLength;
668 
669     MethodObj->Method.ParamCount = (UINT8)
670         (MethodFlags & AML_METHOD_ARG_COUNT);
671 
672     if (MethodFlags & AML_METHOD_SERIALIZED)
673     {
674         MethodObj->Method.InfoFlags = ACPI_METHOD_SERIALIZED;
675 
676         MethodObj->Method.SyncLevel = (UINT8)
677             ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4);
678     }
679 
680     /*
681      * Now that it is complete, we can attach the new method object to
682      * the method Node (detaches/deletes any existing object)
683      */
684     Status = AcpiNsAttachObject (Node, MethodObj, ACPI_TYPE_METHOD);
685 
686     /*
687      * Flag indicates AML buffer is dynamic, must be deleted later.
688      * Must be set only after attach above.
689      */
690     Node->Flags |= ANOBJ_ALLOCATED_BUFFER;
691 
692     /* Remove local reference to the method object */
693 
694     AcpiUtRemoveReference (MethodObj);
695     return (Status);
696 
697 
698 ErrorExit:
699 
700     ACPI_FREE (AmlBuffer);
701     ACPI_FREE (MethodObj);
702     return (Status);
703 }
704 
705 ACPI_EXPORT_SYMBOL (AcpiInstallMethod)
706