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 - 2014, 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_STRING             Pathname,
  89     ACPI_HANDLE             *RetHandle)
  90 {
  91     ACPI_STATUS             Status;
  92     ACPI_NAMESPACE_NODE     *Node = NULL;
  93     ACPI_NAMESPACE_NODE     *PrefixNode = NULL;
  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 (!ACPI_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, Pathname, 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     ACPI_NAMESPACE_NODE     *Node;
 181     char                    *NodeName;
 182 
 183 
 184     /* Parameter validation */
 185 
 186     if (NameType > ACPI_NAME_TYPE_MAX)
 187     {
 188         return (AE_BAD_PARAMETER);
 189     }
 190 
 191     Status = AcpiUtValidateBuffer (Buffer);
 192     if (ACPI_FAILURE (Status))
 193     {
 194         return (Status);
 195     }
 196 
 197     if (NameType == ACPI_FULL_PATHNAME)
 198     {
 199         /* Get the full pathname (From the namespace root) */
 200 
 201         Status = AcpiNsHandleToPathname (Handle, Buffer);
 202         return (Status);
 203     }
 204 
 205     /*
 206      * Wants the single segment ACPI name.
 207      * Validate handle and convert to a namespace Node
 208      */
 209     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 210     if (ACPI_FAILURE (Status))
 211     {
 212         return (Status);
 213     }
 214 
 215     Node = AcpiNsValidateHandle (Handle);
 216     if (!Node)
 217     {
 218         Status = AE_BAD_PARAMETER;
 219         goto UnlockAndExit;
 220     }
 221 
 222     /* Validate/Allocate/Clear caller buffer */
 223 
 224     Status = AcpiUtInitializeBuffer (Buffer, ACPI_PATH_SEGMENT_LENGTH);
 225     if (ACPI_FAILURE (Status))
 226     {
 227         goto UnlockAndExit;
 228     }
 229 
 230     /* Just copy the ACPI name from the Node and zero terminate it */
 231 
 232     NodeName = AcpiUtGetNodeName (Node);
 233     ACPI_MOVE_NAME (Buffer->Pointer, NodeName);
 234     ((char *) Buffer->Pointer) [ACPI_NAME_SIZE] = 0;
 235     Status = AE_OK;
 236 
 237 
 238 UnlockAndExit:
 239 
 240     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 241     return (Status);
 242 }
 243 
 244 ACPI_EXPORT_SYMBOL (AcpiGetName)
 245 
 246 
 247 /******************************************************************************
 248  *
 249  * FUNCTION:    AcpiNsCopyDeviceId
 250  *
 251  * PARAMETERS:  Dest                - Pointer to the destination PNP_DEVICE_ID
 252  *              Source              - Pointer to the source PNP_DEVICE_ID
 253  *              StringArea          - Pointer to where to copy the dest string
 254  *
 255  * RETURN:      Pointer to the next string area
 256  *
 257  * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data.
 258  *
 259  ******************************************************************************/
 260 
 261 static char *
 262 AcpiNsCopyDeviceId (
 263     ACPI_PNP_DEVICE_ID      *Dest,
 264     ACPI_PNP_DEVICE_ID      *Source,
 265     char                    *StringArea)
 266 {
 267 
 268     /* Create the destination PNP_DEVICE_ID */
 269 
 270     Dest->String = StringArea;
 271     Dest->Length = Source->Length;
 272 
 273     /* Copy actual string and return a pointer to the next string area */
 274 
 275     ACPI_MEMCPY (StringArea, Source->String, Source->Length);
 276     return (StringArea + Source->Length);
 277 }
 278 
 279 
 280 /******************************************************************************
 281  *
 282  * FUNCTION:    AcpiGetObjectInfo
 283  *
 284  * PARAMETERS:  Handle              - Object Handle
 285  *              ReturnBuffer        - Where the info is returned
 286  *
 287  * RETURN:      Status
 288  *
 289  * DESCRIPTION: Returns information about an object as gleaned from the
 290  *              namespace node and possibly by running several standard
 291  *              control methods (Such as in the case of a device.)
 292  *
 293  * For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB,
 294  * _STA, _ADR, _SxW, and _SxD methods.
 295  *
 296  * Note: Allocates the return buffer, must be freed by the caller.
 297  *
 298  ******************************************************************************/
 299 
 300 ACPI_STATUS
 301 AcpiGetObjectInfo (
 302     ACPI_HANDLE             Handle,
 303     ACPI_DEVICE_INFO        **ReturnBuffer)
 304 {
 305     ACPI_NAMESPACE_NODE     *Node;
 306     ACPI_DEVICE_INFO        *Info;
 307     ACPI_PNP_DEVICE_ID_LIST *CidList = NULL;
 308     ACPI_PNP_DEVICE_ID      *Hid = NULL;
 309     ACPI_PNP_DEVICE_ID      *Uid = NULL;
 310     ACPI_PNP_DEVICE_ID      *Sub = NULL;
 311     char                    *NextIdString;
 312     ACPI_OBJECT_TYPE        Type;
 313     ACPI_NAME               Name;
 314     UINT8                   ParamCount= 0;
 315     UINT8                   Valid = 0;
 316     UINT32                  InfoSize;
 317     UINT32                  i;
 318     ACPI_STATUS             Status;
 319 
 320 
 321     /* Parameter validation */
 322 
 323     if (!Handle || !ReturnBuffer)
 324     {
 325         return (AE_BAD_PARAMETER);
 326     }
 327 
 328     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 329     if (ACPI_FAILURE (Status))
 330     {
 331         return (Status);
 332     }
 333 
 334     Node = AcpiNsValidateHandle (Handle);
 335     if (!Node)
 336     {
 337         (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 338         return (AE_BAD_PARAMETER);
 339     }
 340 
 341     /* Get the namespace node data while the namespace is locked */
 342 
 343     InfoSize = sizeof (ACPI_DEVICE_INFO);
 344     Type = Node->Type;
 345     Name = Node->Name.Integer;
 346 
 347     if (Node->Type == ACPI_TYPE_METHOD)
 348     {
 349         ParamCount = Node->Object->Method.ParamCount;
 350     }
 351 
 352     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 353     if (ACPI_FAILURE (Status))
 354     {
 355         return (Status);
 356     }
 357 
 358     if ((Type == ACPI_TYPE_DEVICE) ||
 359         (Type == ACPI_TYPE_PROCESSOR))
 360     {
 361         /*
 362          * Get extra info for ACPI Device/Processor objects only:
 363          * Run the Device _HID, _UID, _SUB, and _CID methods.
 364          *
 365          * Note: none of these methods are required, so they may or may
 366          * not be present for this device. The Info->Valid bitfield is used
 367          * to indicate which methods were found and run successfully.
 368          */
 369 
 370         /* Execute the Device._HID method */
 371 
 372         Status = AcpiUtExecute_HID (Node, &Hid);
 373         if (ACPI_SUCCESS (Status))
 374         {
 375             InfoSize += Hid->Length;
 376             Valid |= ACPI_VALID_HID;
 377         }
 378 
 379         /* Execute the Device._UID method */
 380 
 381         Status = AcpiUtExecute_UID (Node, &Uid);
 382         if (ACPI_SUCCESS (Status))
 383         {
 384             InfoSize += Uid->Length;
 385             Valid |= ACPI_VALID_UID;
 386         }
 387 
 388         /* Execute the Device._SUB method */
 389 
 390         Status = AcpiUtExecute_SUB (Node, &Sub);
 391         if (ACPI_SUCCESS (Status))
 392         {
 393             InfoSize += Sub->Length;
 394             Valid |= ACPI_VALID_SUB;
 395         }
 396 
 397         /* Execute the Device._CID method */
 398 
 399         Status = AcpiUtExecute_CID (Node, &CidList);
 400         if (ACPI_SUCCESS (Status))
 401         {
 402             /* Add size of CID strings and CID pointer array */
 403 
 404             InfoSize += (CidList->ListSize - sizeof (ACPI_PNP_DEVICE_ID_LIST));
 405             Valid |= ACPI_VALID_CID;
 406         }
 407     }
 408 
 409     /*
 410      * Now that we have the variable-length data, we can allocate the
 411      * return buffer
 412      */
 413     Info = ACPI_ALLOCATE_ZEROED (InfoSize);
 414     if (!Info)
 415     {
 416         Status = AE_NO_MEMORY;
 417         goto Cleanup;
 418     }
 419 
 420     /* Get the fixed-length data */
 421 
 422     if ((Type == ACPI_TYPE_DEVICE) ||
 423         (Type == ACPI_TYPE_PROCESSOR))
 424     {
 425         /*
 426          * Get extra info for ACPI Device/Processor objects only:
 427          * Run the _STA, _ADR and, SxW, and _SxD methods.
 428          *
 429          * Notes: none of these methods are required, so they may or may
 430          * not be present for this device. The Info->Valid bitfield is used
 431          * to indicate which methods were found and run successfully.
 432          *
 433          * For _STA, if the method does not exist, then (as per the ACPI
 434          * specification), the returned CurrentStatus flags will indicate
 435          * that the device is present/functional/enabled. Otherwise, the
 436          * CurrentStatus flags reflect the value returned from _STA.
 437          */
 438 
 439         /* Execute the Device._STA method */
 440 
 441         Status = AcpiUtExecute_STA (Node, &Info->CurrentStatus);
 442         if (ACPI_SUCCESS (Status))
 443         {
 444             Valid |= ACPI_VALID_STA;
 445         }
 446 
 447         /* Execute the Device._ADR method */
 448 
 449         Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node,
 450                     &Info->Address);
 451         if (ACPI_SUCCESS (Status))
 452         {
 453             Valid |= ACPI_VALID_ADR;
 454         }
 455 
 456         /* Execute the Device._SxW methods */
 457 
 458         Status = AcpiUtExecutePowerMethods (Node,
 459                     AcpiGbl_LowestDstateNames, ACPI_NUM_SxW_METHODS,
 460                     Info->LowestDstates);
 461         if (ACPI_SUCCESS (Status))
 462         {
 463             Valid |= ACPI_VALID_SXWS;
 464         }
 465 
 466         /* Execute the Device._SxD methods */
 467 
 468         Status = AcpiUtExecutePowerMethods (Node,
 469                     AcpiGbl_HighestDstateNames, ACPI_NUM_SxD_METHODS,
 470                     Info->HighestDstates);
 471         if (ACPI_SUCCESS (Status))
 472         {
 473             Valid |= ACPI_VALID_SXDS;
 474         }
 475     }
 476 
 477     /*
 478      * Create a pointer to the string area of the return buffer.
 479      * Point to the end of the base ACPI_DEVICE_INFO structure.
 480      */
 481     NextIdString = ACPI_CAST_PTR (char, Info->CompatibleIdList.Ids);
 482     if (CidList)
 483     {
 484         /* Point past the CID PNP_DEVICE_ID array */
 485 
 486         NextIdString += ((ACPI_SIZE) CidList->Count * sizeof (ACPI_PNP_DEVICE_ID));
 487     }
 488 
 489     /*
 490      * Copy the HID, UID, SUB, and CIDs to the return buffer.
 491      * The variable-length strings are copied to the reserved area
 492      * at the end of the buffer.
 493      *
 494      * For HID and CID, check if the ID is a PCI Root Bridge.
 495      */
 496     if (Hid)
 497     {
 498         NextIdString = AcpiNsCopyDeviceId (&Info->HardwareId,
 499             Hid, NextIdString);
 500 
 501         if (AcpiUtIsPciRootBridge (Hid->String))
 502         {
 503             Info->Flags |= ACPI_PCI_ROOT_BRIDGE;
 504         }
 505     }
 506 
 507     if (Uid)
 508     {
 509         NextIdString = AcpiNsCopyDeviceId (&Info->UniqueId,
 510             Uid, NextIdString);
 511     }
 512 
 513     if (Sub)
 514     {
 515         NextIdString = AcpiNsCopyDeviceId (&Info->SubsystemId,
 516             Sub, NextIdString);
 517     }
 518 
 519     if (CidList)
 520     {
 521         Info->CompatibleIdList.Count = CidList->Count;
 522         Info->CompatibleIdList.ListSize = CidList->ListSize;
 523 
 524         /* Copy each CID */
 525 
 526         for (i = 0; i < CidList->Count; i++)
 527         {
 528             NextIdString = AcpiNsCopyDeviceId (&Info->CompatibleIdList.Ids[i],
 529                 &CidList->Ids[i], NextIdString);
 530 
 531             if (AcpiUtIsPciRootBridge (CidList->Ids[i].String))
 532             {
 533                 Info->Flags |= ACPI_PCI_ROOT_BRIDGE;
 534             }
 535         }
 536     }
 537 
 538     /* Copy the fixed-length data */
 539 
 540     Info->InfoSize = InfoSize;
 541     Info->Type = Type;
 542     Info->Name = Name;
 543     Info->ParamCount = ParamCount;
 544     Info->Valid = Valid;
 545 
 546     *ReturnBuffer = Info;
 547     Status = AE_OK;
 548 
 549 
 550 Cleanup:
 551     if (Hid)
 552     {
 553         ACPI_FREE (Hid);
 554     }
 555     if (Uid)
 556     {
 557         ACPI_FREE (Uid);
 558     }
 559     if (Sub)
 560     {
 561         ACPI_FREE (Sub);
 562     }
 563     if (CidList)
 564     {
 565         ACPI_FREE (CidList);
 566     }
 567     return (Status);
 568 }
 569 
 570 ACPI_EXPORT_SYMBOL (AcpiGetObjectInfo)
 571 
 572 
 573 /******************************************************************************
 574  *
 575  * FUNCTION:    AcpiInstallMethod
 576  *
 577  * PARAMETERS:  Buffer         - An ACPI table containing one control method
 578  *
 579  * RETURN:      Status
 580  *
 581  * DESCRIPTION: Install a control method into the namespace. If the method
 582  *              name already exists in the namespace, it is overwritten. The
 583  *              input buffer must contain a valid DSDT or SSDT containing a
 584  *              single control method.
 585  *
 586  ******************************************************************************/
 587 
 588 ACPI_STATUS
 589 AcpiInstallMethod (
 590     UINT8                   *Buffer)
 591 {
 592     ACPI_TABLE_HEADER       *Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, Buffer);
 593     UINT8                   *AmlBuffer;
 594     UINT8                   *AmlStart;
 595     char                    *Path;
 596     ACPI_NAMESPACE_NODE     *Node;
 597     ACPI_OPERAND_OBJECT     *MethodObj;
 598     ACPI_PARSE_STATE        ParserState;
 599     UINT32                  AmlLength;
 600     UINT16                  Opcode;
 601     UINT8                   MethodFlags;
 602     ACPI_STATUS             Status;
 603 
 604 
 605     /* Parameter validation */
 606 
 607     if (!Buffer)
 608     {
 609         return (AE_BAD_PARAMETER);
 610     }
 611 
 612     /* Table must be a DSDT or SSDT */
 613 
 614     if (!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) &&
 615         !ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT))
 616     {
 617         return (AE_BAD_HEADER);
 618     }
 619 
 620     /* First AML opcode in the table must be a control method */
 621 
 622     ParserState.Aml = Buffer + sizeof (ACPI_TABLE_HEADER);
 623     Opcode = AcpiPsPeekOpcode (&ParserState);
 624     if (Opcode != AML_METHOD_OP)
 625     {
 626         return (AE_BAD_PARAMETER);
 627     }
 628 
 629     /* Extract method information from the raw AML */
 630 
 631     ParserState.Aml += AcpiPsGetOpcodeSize (Opcode);
 632     ParserState.PkgEnd = AcpiPsGetNextPackageEnd (&ParserState);
 633     Path = AcpiPsGetNextNamestring (&ParserState);
 634     MethodFlags = *ParserState.Aml++;
 635     AmlStart = ParserState.Aml;
 636     AmlLength = ACPI_PTR_DIFF (ParserState.PkgEnd, AmlStart);
 637 
 638     /*
 639      * Allocate resources up-front. We don't want to have to delete a new
 640      * node from the namespace if we cannot allocate memory.
 641      */
 642     AmlBuffer = ACPI_ALLOCATE (AmlLength);
 643     if (!AmlBuffer)
 644     {
 645         return (AE_NO_MEMORY);
 646     }
 647 
 648     MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
 649     if (!MethodObj)
 650     {
 651         ACPI_FREE (AmlBuffer);
 652         return (AE_NO_MEMORY);
 653     }
 654 
 655     /* Lock namespace for AcpiNsLookup, we may be creating a new node */
 656 
 657     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 658     if (ACPI_FAILURE (Status))
 659     {
 660         goto ErrorExit;
 661     }
 662 
 663     /* The lookup either returns an existing node or creates a new one */
 664 
 665     Status = AcpiNsLookup (NULL, Path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
 666                 ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, NULL, &Node);
 667 
 668     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 669 
 670     if (ACPI_FAILURE (Status)) /* NsLookup */
 671     {
 672         if (Status != AE_ALREADY_EXISTS)
 673         {
 674             goto ErrorExit;
 675         }
 676 
 677         /* Node existed previously, make sure it is a method node */
 678 
 679         if (Node->Type != ACPI_TYPE_METHOD)
 680         {
 681             Status = AE_TYPE;
 682             goto ErrorExit;
 683         }
 684     }
 685 
 686     /* Copy the method AML to the local buffer */
 687 
 688     ACPI_MEMCPY (AmlBuffer, AmlStart, AmlLength);
 689 
 690     /* Initialize the method object with the new method's information */
 691 
 692     MethodObj->Method.AmlStart = AmlBuffer;
 693     MethodObj->Method.AmlLength = AmlLength;
 694 
 695     MethodObj->Method.ParamCount = (UINT8)
 696         (MethodFlags & AML_METHOD_ARG_COUNT);
 697 
 698     if (MethodFlags & AML_METHOD_SERIALIZED)
 699     {
 700         MethodObj->Method.InfoFlags = ACPI_METHOD_SERIALIZED;
 701 
 702         MethodObj->Method.SyncLevel = (UINT8)
 703             ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4);
 704     }
 705 
 706     /*
 707      * Now that it is complete, we can attach the new method object to
 708      * the method Node (detaches/deletes any existing object)
 709      */
 710     Status = AcpiNsAttachObject (Node, MethodObj, ACPI_TYPE_METHOD);
 711 
 712     /*
 713      * Flag indicates AML buffer is dynamic, must be deleted later.
 714      * Must be set only after attach above.
 715      */
 716     Node->Flags |= ANOBJ_ALLOCATED_BUFFER;
 717 
 718     /* Remove local reference to the method object */
 719 
 720     AcpiUtRemoveReference (MethodObj);
 721     return (Status);
 722 
 723 
 724 ErrorExit:
 725 
 726     ACPI_FREE (AmlBuffer);
 727     ACPI_FREE (MethodObj);
 728     return (Status);
 729 }
 730 
 731 ACPI_EXPORT_SYMBOL (AcpiInstallMethod)