xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/namespace/nsxfname.c (revision ca8ed5ea660fb6275799a3b7f138b201c41a667b)
1 /******************************************************************************
2  *
3  * Module Name: nsxfname - Public interfaces to the ACPI subsystem
4  *                         ACPI Namespace oriented interfaces
5  *
6  *****************************************************************************/
7 
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2014, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights. You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code. No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision. In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change. Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee. Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution. In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
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 #define EXPORT_ACPI_INTERFACES
119 
120 #include "acpi.h"
121 #include "accommon.h"
122 #include "acnamesp.h"
123 #include "acparser.h"
124 #include "amlcode.h"
125 
126 
127 #define _COMPONENT          ACPI_NAMESPACE
128         ACPI_MODULE_NAME    ("nsxfname")
129 
130 /* Local prototypes */
131 
132 static char *
133 AcpiNsCopyDeviceId (
134     ACPI_PNP_DEVICE_ID      *Dest,
135     ACPI_PNP_DEVICE_ID      *Source,
136     char                    *StringArea);
137 
138 
139 /******************************************************************************
140  *
141  * FUNCTION:    AcpiGetHandle
142  *
143  * PARAMETERS:  Parent          - Object to search under (search scope).
144  *              Pathname        - Pointer to an asciiz string containing the
145  *                                name
146  *              RetHandle       - Where the return handle is returned
147  *
148  * RETURN:      Status
149  *
150  * DESCRIPTION: This routine will search for a caller specified name in the
151  *              name space. The caller can restrict the search region by
152  *              specifying a non NULL parent. The parent value is itself a
153  *              namespace handle.
154  *
155  ******************************************************************************/
156 
157 ACPI_STATUS
158 AcpiGetHandle (
159     ACPI_HANDLE             Parent,
160     ACPI_STRING             Pathname,
161     ACPI_HANDLE             *RetHandle)
162 {
163     ACPI_STATUS             Status;
164     ACPI_NAMESPACE_NODE     *Node = NULL;
165     ACPI_NAMESPACE_NODE     *PrefixNode = NULL;
166 
167 
168     ACPI_FUNCTION_ENTRY ();
169 
170 
171     /* Parameter Validation */
172 
173     if (!RetHandle || !Pathname)
174     {
175         return (AE_BAD_PARAMETER);
176     }
177 
178     /* Convert a parent handle to a prefix node */
179 
180     if (Parent)
181     {
182         PrefixNode = AcpiNsValidateHandle (Parent);
183         if (!PrefixNode)
184         {
185             return (AE_BAD_PARAMETER);
186         }
187     }
188 
189     /*
190      * Valid cases are:
191      * 1) Fully qualified pathname
192      * 2) Parent + Relative pathname
193      *
194      * Error for <null Parent + relative path>
195      */
196     if (ACPI_IS_ROOT_PREFIX (Pathname[0]))
197     {
198         /* Pathname is fully qualified (starts with '\') */
199 
200         /* Special case for root-only, since we can't search for it */
201 
202         if (!ACPI_STRCMP (Pathname, ACPI_NS_ROOT_PATH))
203         {
204             *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, AcpiGbl_RootNode);
205             return (AE_OK);
206         }
207     }
208     else if (!PrefixNode)
209     {
210         /* Relative path with null prefix is disallowed */
211 
212         return (AE_BAD_PARAMETER);
213     }
214 
215     /* Find the Node and convert to a handle */
216 
217     Status = AcpiNsGetNode (PrefixNode, Pathname, ACPI_NS_NO_UPSEARCH, &Node);
218     if (ACPI_SUCCESS (Status))
219     {
220         *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, Node);
221     }
222 
223     return (Status);
224 }
225 
226 ACPI_EXPORT_SYMBOL (AcpiGetHandle)
227 
228 
229 /******************************************************************************
230  *
231  * FUNCTION:    AcpiGetName
232  *
233  * PARAMETERS:  Handle          - Handle to be converted to a pathname
234  *              NameType        - Full pathname or single segment
235  *              Buffer          - Buffer for returned path
236  *
237  * RETURN:      Pointer to a string containing the fully qualified Name.
238  *
239  * DESCRIPTION: This routine returns the fully qualified name associated with
240  *              the Handle parameter. This and the AcpiPathnameToHandle are
241  *              complementary functions.
242  *
243  ******************************************************************************/
244 
245 ACPI_STATUS
246 AcpiGetName (
247     ACPI_HANDLE             Handle,
248     UINT32                  NameType,
249     ACPI_BUFFER             *Buffer)
250 {
251     ACPI_STATUS             Status;
252     ACPI_NAMESPACE_NODE     *Node;
253     char                    *NodeName;
254 
255 
256     /* Parameter validation */
257 
258     if (NameType > ACPI_NAME_TYPE_MAX)
259     {
260         return (AE_BAD_PARAMETER);
261     }
262 
263     Status = AcpiUtValidateBuffer (Buffer);
264     if (ACPI_FAILURE (Status))
265     {
266         return (Status);
267     }
268 
269     if (NameType == ACPI_FULL_PATHNAME)
270     {
271         /* Get the full pathname (From the namespace root) */
272 
273         Status = AcpiNsHandleToPathname (Handle, Buffer);
274         return (Status);
275     }
276 
277     /*
278      * Wants the single segment ACPI name.
279      * Validate handle and convert to a namespace Node
280      */
281     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
282     if (ACPI_FAILURE (Status))
283     {
284         return (Status);
285     }
286 
287     Node = AcpiNsValidateHandle (Handle);
288     if (!Node)
289     {
290         Status = AE_BAD_PARAMETER;
291         goto UnlockAndExit;
292     }
293 
294     /* Validate/Allocate/Clear caller buffer */
295 
296     Status = AcpiUtInitializeBuffer (Buffer, ACPI_PATH_SEGMENT_LENGTH);
297     if (ACPI_FAILURE (Status))
298     {
299         goto UnlockAndExit;
300     }
301 
302     /* Just copy the ACPI name from the Node and zero terminate it */
303 
304     NodeName = AcpiUtGetNodeName (Node);
305     ACPI_MOVE_NAME (Buffer->Pointer, NodeName);
306     ((char *) Buffer->Pointer) [ACPI_NAME_SIZE] = 0;
307     Status = AE_OK;
308 
309 
310 UnlockAndExit:
311 
312     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
313     return (Status);
314 }
315 
316 ACPI_EXPORT_SYMBOL (AcpiGetName)
317 
318 
319 /******************************************************************************
320  *
321  * FUNCTION:    AcpiNsCopyDeviceId
322  *
323  * PARAMETERS:  Dest                - Pointer to the destination PNP_DEVICE_ID
324  *              Source              - Pointer to the source PNP_DEVICE_ID
325  *              StringArea          - Pointer to where to copy the dest string
326  *
327  * RETURN:      Pointer to the next string area
328  *
329  * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data.
330  *
331  ******************************************************************************/
332 
333 static char *
334 AcpiNsCopyDeviceId (
335     ACPI_PNP_DEVICE_ID      *Dest,
336     ACPI_PNP_DEVICE_ID      *Source,
337     char                    *StringArea)
338 {
339 
340     /* Create the destination PNP_DEVICE_ID */
341 
342     Dest->String = StringArea;
343     Dest->Length = Source->Length;
344 
345     /* Copy actual string and return a pointer to the next string area */
346 
347     ACPI_MEMCPY (StringArea, Source->String, Source->Length);
348     return (StringArea + Source->Length);
349 }
350 
351 
352 /******************************************************************************
353  *
354  * FUNCTION:    AcpiGetObjectInfo
355  *
356  * PARAMETERS:  Handle              - Object Handle
357  *              ReturnBuffer        - Where the info is returned
358  *
359  * RETURN:      Status
360  *
361  * DESCRIPTION: Returns information about an object as gleaned from the
362  *              namespace node and possibly by running several standard
363  *              control methods (Such as in the case of a device.)
364  *
365  * For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB,
366  * _STA, _ADR, _SxW, and _SxD methods.
367  *
368  * Note: Allocates the return buffer, must be freed by the caller.
369  *
370  ******************************************************************************/
371 
372 ACPI_STATUS
373 AcpiGetObjectInfo (
374     ACPI_HANDLE             Handle,
375     ACPI_DEVICE_INFO        **ReturnBuffer)
376 {
377     ACPI_NAMESPACE_NODE     *Node;
378     ACPI_DEVICE_INFO        *Info;
379     ACPI_PNP_DEVICE_ID_LIST *CidList = NULL;
380     ACPI_PNP_DEVICE_ID      *Hid = NULL;
381     ACPI_PNP_DEVICE_ID      *Uid = NULL;
382     ACPI_PNP_DEVICE_ID      *Sub = NULL;
383     char                    *NextIdString;
384     ACPI_OBJECT_TYPE        Type;
385     ACPI_NAME               Name;
386     UINT8                   ParamCount= 0;
387     UINT8                   Valid = 0;
388     UINT32                  InfoSize;
389     UINT32                  i;
390     ACPI_STATUS             Status;
391 
392 
393     /* Parameter validation */
394 
395     if (!Handle || !ReturnBuffer)
396     {
397         return (AE_BAD_PARAMETER);
398     }
399 
400     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
401     if (ACPI_FAILURE (Status))
402     {
403         return (Status);
404     }
405 
406     Node = AcpiNsValidateHandle (Handle);
407     if (!Node)
408     {
409         (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
410         return (AE_BAD_PARAMETER);
411     }
412 
413     /* Get the namespace node data while the namespace is locked */
414 
415     InfoSize = sizeof (ACPI_DEVICE_INFO);
416     Type = Node->Type;
417     Name = Node->Name.Integer;
418 
419     if (Node->Type == ACPI_TYPE_METHOD)
420     {
421         ParamCount = Node->Object->Method.ParamCount;
422     }
423 
424     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
425     if (ACPI_FAILURE (Status))
426     {
427         return (Status);
428     }
429 
430     if ((Type == ACPI_TYPE_DEVICE) ||
431         (Type == ACPI_TYPE_PROCESSOR))
432     {
433         /*
434          * Get extra info for ACPI Device/Processor objects only:
435          * Run the Device _HID, _UID, _SUB, and _CID methods.
436          *
437          * Note: none of these methods are required, so they may or may
438          * not be present for this device. The Info->Valid bitfield is used
439          * to indicate which methods were found and run successfully.
440          */
441 
442         /* Execute the Device._HID method */
443 
444         Status = AcpiUtExecute_HID (Node, &Hid);
445         if (ACPI_SUCCESS (Status))
446         {
447             InfoSize += Hid->Length;
448             Valid |= ACPI_VALID_HID;
449         }
450 
451         /* Execute the Device._UID method */
452 
453         Status = AcpiUtExecute_UID (Node, &Uid);
454         if (ACPI_SUCCESS (Status))
455         {
456             InfoSize += Uid->Length;
457             Valid |= ACPI_VALID_UID;
458         }
459 
460         /* Execute the Device._SUB method */
461 
462         Status = AcpiUtExecute_SUB (Node, &Sub);
463         if (ACPI_SUCCESS (Status))
464         {
465             InfoSize += Sub->Length;
466             Valid |= ACPI_VALID_SUB;
467         }
468 
469         /* Execute the Device._CID method */
470 
471         Status = AcpiUtExecute_CID (Node, &CidList);
472         if (ACPI_SUCCESS (Status))
473         {
474             /* Add size of CID strings and CID pointer array */
475 
476             InfoSize += (CidList->ListSize - sizeof (ACPI_PNP_DEVICE_ID_LIST));
477             Valid |= ACPI_VALID_CID;
478         }
479     }
480 
481     /*
482      * Now that we have the variable-length data, we can allocate the
483      * return buffer
484      */
485     Info = ACPI_ALLOCATE_ZEROED (InfoSize);
486     if (!Info)
487     {
488         Status = AE_NO_MEMORY;
489         goto Cleanup;
490     }
491 
492     /* Get the fixed-length data */
493 
494     if ((Type == ACPI_TYPE_DEVICE) ||
495         (Type == ACPI_TYPE_PROCESSOR))
496     {
497         /*
498          * Get extra info for ACPI Device/Processor objects only:
499          * Run the _STA, _ADR and, SxW, and _SxD methods.
500          *
501          * Notes: none of these methods are required, so they may or may
502          * not be present for this device. The Info->Valid bitfield is used
503          * to indicate which methods were found and run successfully.
504          *
505          * For _STA, if the method does not exist, then (as per the ACPI
506          * specification), the returned CurrentStatus flags will indicate
507          * that the device is present/functional/enabled. Otherwise, the
508          * CurrentStatus flags reflect the value returned from _STA.
509          */
510 
511         /* Execute the Device._STA method */
512 
513         Status = AcpiUtExecute_STA (Node, &Info->CurrentStatus);
514         if (ACPI_SUCCESS (Status))
515         {
516             Valid |= ACPI_VALID_STA;
517         }
518 
519         /* Execute the Device._ADR method */
520 
521         Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node,
522                     &Info->Address);
523         if (ACPI_SUCCESS (Status))
524         {
525             Valid |= ACPI_VALID_ADR;
526         }
527 
528         /* Execute the Device._SxW methods */
529 
530         Status = AcpiUtExecutePowerMethods (Node,
531                     AcpiGbl_LowestDstateNames, ACPI_NUM_SxW_METHODS,
532                     Info->LowestDstates);
533         if (ACPI_SUCCESS (Status))
534         {
535             Valid |= ACPI_VALID_SXWS;
536         }
537 
538         /* Execute the Device._SxD methods */
539 
540         Status = AcpiUtExecutePowerMethods (Node,
541                     AcpiGbl_HighestDstateNames, ACPI_NUM_SxD_METHODS,
542                     Info->HighestDstates);
543         if (ACPI_SUCCESS (Status))
544         {
545             Valid |= ACPI_VALID_SXDS;
546         }
547     }
548 
549     /*
550      * Create a pointer to the string area of the return buffer.
551      * Point to the end of the base ACPI_DEVICE_INFO structure.
552      */
553     NextIdString = ACPI_CAST_PTR (char, Info->CompatibleIdList.Ids);
554     if (CidList)
555     {
556         /* Point past the CID PNP_DEVICE_ID array */
557 
558         NextIdString += ((ACPI_SIZE) CidList->Count * sizeof (ACPI_PNP_DEVICE_ID));
559     }
560 
561     /*
562      * Copy the HID, UID, SUB, and CIDs to the return buffer.
563      * The variable-length strings are copied to the reserved area
564      * at the end of the buffer.
565      *
566      * For HID and CID, check if the ID is a PCI Root Bridge.
567      */
568     if (Hid)
569     {
570         NextIdString = AcpiNsCopyDeviceId (&Info->HardwareId,
571             Hid, NextIdString);
572 
573         if (AcpiUtIsPciRootBridge (Hid->String))
574         {
575             Info->Flags |= ACPI_PCI_ROOT_BRIDGE;
576         }
577     }
578 
579     if (Uid)
580     {
581         NextIdString = AcpiNsCopyDeviceId (&Info->UniqueId,
582             Uid, NextIdString);
583     }
584 
585     if (Sub)
586     {
587         NextIdString = AcpiNsCopyDeviceId (&Info->SubsystemId,
588             Sub, NextIdString);
589     }
590 
591     if (CidList)
592     {
593         Info->CompatibleIdList.Count = CidList->Count;
594         Info->CompatibleIdList.ListSize = CidList->ListSize;
595 
596         /* Copy each CID */
597 
598         for (i = 0; i < CidList->Count; i++)
599         {
600             NextIdString = AcpiNsCopyDeviceId (&Info->CompatibleIdList.Ids[i],
601                 &CidList->Ids[i], NextIdString);
602 
603             if (AcpiUtIsPciRootBridge (CidList->Ids[i].String))
604             {
605                 Info->Flags |= ACPI_PCI_ROOT_BRIDGE;
606             }
607         }
608     }
609 
610     /* Copy the fixed-length data */
611 
612     Info->InfoSize = InfoSize;
613     Info->Type = Type;
614     Info->Name = Name;
615     Info->ParamCount = ParamCount;
616     Info->Valid = Valid;
617 
618     *ReturnBuffer = Info;
619     Status = AE_OK;
620 
621 
622 Cleanup:
623     if (Hid)
624     {
625         ACPI_FREE (Hid);
626     }
627     if (Uid)
628     {
629         ACPI_FREE (Uid);
630     }
631     if (Sub)
632     {
633         ACPI_FREE (Sub);
634     }
635     if (CidList)
636     {
637         ACPI_FREE (CidList);
638     }
639     return (Status);
640 }
641 
642 ACPI_EXPORT_SYMBOL (AcpiGetObjectInfo)
643 
644 
645 /******************************************************************************
646  *
647  * FUNCTION:    AcpiInstallMethod
648  *
649  * PARAMETERS:  Buffer         - An ACPI table containing one control method
650  *
651  * RETURN:      Status
652  *
653  * DESCRIPTION: Install a control method into the namespace. If the method
654  *              name already exists in the namespace, it is overwritten. The
655  *              input buffer must contain a valid DSDT or SSDT containing a
656  *              single control method.
657  *
658  ******************************************************************************/
659 
660 ACPI_STATUS
661 AcpiInstallMethod (
662     UINT8                   *Buffer)
663 {
664     ACPI_TABLE_HEADER       *Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, Buffer);
665     UINT8                   *AmlBuffer;
666     UINT8                   *AmlStart;
667     char                    *Path;
668     ACPI_NAMESPACE_NODE     *Node;
669     ACPI_OPERAND_OBJECT     *MethodObj;
670     ACPI_PARSE_STATE        ParserState;
671     UINT32                  AmlLength;
672     UINT16                  Opcode;
673     UINT8                   MethodFlags;
674     ACPI_STATUS             Status;
675 
676 
677     /* Parameter validation */
678 
679     if (!Buffer)
680     {
681         return (AE_BAD_PARAMETER);
682     }
683 
684     /* Table must be a DSDT or SSDT */
685 
686     if (!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) &&
687         !ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT))
688     {
689         return (AE_BAD_HEADER);
690     }
691 
692     /* First AML opcode in the table must be a control method */
693 
694     ParserState.Aml = Buffer + sizeof (ACPI_TABLE_HEADER);
695     Opcode = AcpiPsPeekOpcode (&ParserState);
696     if (Opcode != AML_METHOD_OP)
697     {
698         return (AE_BAD_PARAMETER);
699     }
700 
701     /* Extract method information from the raw AML */
702 
703     ParserState.Aml += AcpiPsGetOpcodeSize (Opcode);
704     ParserState.PkgEnd = AcpiPsGetNextPackageEnd (&ParserState);
705     Path = AcpiPsGetNextNamestring (&ParserState);
706     MethodFlags = *ParserState.Aml++;
707     AmlStart = ParserState.Aml;
708     AmlLength = ACPI_PTR_DIFF (ParserState.PkgEnd, AmlStart);
709 
710     /*
711      * Allocate resources up-front. We don't want to have to delete a new
712      * node from the namespace if we cannot allocate memory.
713      */
714     AmlBuffer = ACPI_ALLOCATE (AmlLength);
715     if (!AmlBuffer)
716     {
717         return (AE_NO_MEMORY);
718     }
719 
720     MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
721     if (!MethodObj)
722     {
723         ACPI_FREE (AmlBuffer);
724         return (AE_NO_MEMORY);
725     }
726 
727     /* Lock namespace for AcpiNsLookup, we may be creating a new node */
728 
729     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
730     if (ACPI_FAILURE (Status))
731     {
732         goto ErrorExit;
733     }
734 
735     /* The lookup either returns an existing node or creates a new one */
736 
737     Status = AcpiNsLookup (NULL, Path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
738                 ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, NULL, &Node);
739 
740     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
741 
742     if (ACPI_FAILURE (Status)) /* NsLookup */
743     {
744         if (Status != AE_ALREADY_EXISTS)
745         {
746             goto ErrorExit;
747         }
748 
749         /* Node existed previously, make sure it is a method node */
750 
751         if (Node->Type != ACPI_TYPE_METHOD)
752         {
753             Status = AE_TYPE;
754             goto ErrorExit;
755         }
756     }
757 
758     /* Copy the method AML to the local buffer */
759 
760     ACPI_MEMCPY (AmlBuffer, AmlStart, AmlLength);
761 
762     /* Initialize the method object with the new method's information */
763 
764     MethodObj->Method.AmlStart = AmlBuffer;
765     MethodObj->Method.AmlLength = AmlLength;
766 
767     MethodObj->Method.ParamCount = (UINT8)
768         (MethodFlags & AML_METHOD_ARG_COUNT);
769 
770     if (MethodFlags & AML_METHOD_SERIALIZED)
771     {
772         MethodObj->Method.InfoFlags = ACPI_METHOD_SERIALIZED;
773 
774         MethodObj->Method.SyncLevel = (UINT8)
775             ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4);
776     }
777 
778     /*
779      * Now that it is complete, we can attach the new method object to
780      * the method Node (detaches/deletes any existing object)
781      */
782     Status = AcpiNsAttachObject (Node, MethodObj, ACPI_TYPE_METHOD);
783 
784     /*
785      * Flag indicates AML buffer is dynamic, must be deleted later.
786      * Must be set only after attach above.
787      */
788     Node->Flags |= ANOBJ_ALLOCATED_BUFFER;
789 
790     /* Remove local reference to the method object */
791 
792     AcpiUtRemoveReference (MethodObj);
793     return (Status);
794 
795 
796 ErrorExit:
797 
798     ACPI_FREE (AmlBuffer);
799     ACPI_FREE (MethodObj);
800     return (Status);
801 }
802 
803 ACPI_EXPORT_SYMBOL (AcpiInstallMethod)
804