Home | History | Annotate | Line # | Download | only in namespace
nsxfname.c revision 1.16
      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
     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 
    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 
    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
    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 
    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