excreate.c revision 298714
1193323Sed/******************************************************************************
2193323Sed *
3193323Sed * Module Name: excreate - Named object creation
4193323Sed *
5193323Sed *****************************************************************************/
6193323Sed
7193323Sed/*
8193323Sed * Copyright (C) 2000 - 2016, Intel Corp.
9193323Sed * All rights reserved.
10193323Sed *
11193323Sed * Redistribution and use in source and binary forms, with or without
12193323Sed * modification, are permitted provided that the following conditions
13210299Sed * are met:
14210299Sed * 1. Redistributions of source code must retain the above copyright
15210299Sed *    notice, this list of conditions, and the following disclaimer,
16210299Sed *    without modification.
17193323Sed * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18193323Sed *    substantially similar to the "NO WARRANTY" disclaimer below
19193323Sed *    ("Disclaimer") and any redistribution must be conditioned upon
20193323Sed *    including a substantially similar Disclaimer requirement for further
21193323Sed *    binary redistribution.
22193323Sed * 3. Neither the names of the above-listed copyright holders nor the names
23263508Sdim *    of any contributors may be used to endorse or promote products derived
24218893Sdim *    from this software without specific prior written permission.
25193323Sed *
26193323Sed * Alternatively, this software may be distributed under the terms of the
27193323Sed * GNU General Public License ("GPL") version 2 as published by the Free
28193323Sed * Software Foundation.
29193323Sed *
30193323Sed * NO WARRANTY
31193323Sed * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32226633Sdim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33193323Sed * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34226633Sdim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35193323Sed * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39226633Sdim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40226633Sdim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41193323Sed * POSSIBILITY OF SUCH DAMAGES.
42226633Sdim */
43193323Sed
44193323Sed#include <contrib/dev/acpica/include/acpi.h>
45193323Sed#include <contrib/dev/acpica/include/accommon.h>
46193323Sed#include <contrib/dev/acpica/include/acinterp.h>
47193323Sed#include <contrib/dev/acpica/include/amlcode.h>
48210299Sed#include <contrib/dev/acpica/include/acnamesp.h>
49210299Sed
50210299Sed
51210299Sed#define _COMPONENT          ACPI_EXECUTER
52210299Sed        ACPI_MODULE_NAME    ("excreate")
53210299Sed
54210299Sed
55210299Sed#ifndef ACPI_NO_METHOD_EXECUTION
56210299Sed/*******************************************************************************
57210299Sed *
58210299Sed * FUNCTION:    AcpiExCreateAlias
59210299Sed *
60210299Sed * PARAMETERS:  WalkState            - Current state, contains operands
61210299Sed *
62210299Sed * RETURN:      Status
63193323Sed *
64210299Sed * DESCRIPTION: Create a new named alias
65193323Sed *
66193323Sed ******************************************************************************/
67193323Sed
68193323SedACPI_STATUS
69193323SedAcpiExCreateAlias (
70193323Sed    ACPI_WALK_STATE         *WalkState)
71193323Sed{
72193323Sed    ACPI_NAMESPACE_NODE     *TargetNode;
73193323Sed    ACPI_NAMESPACE_NODE     *AliasNode;
74193323Sed    ACPI_STATUS             Status = AE_OK;
75193323Sed
76193323Sed
77193323Sed    ACPI_FUNCTION_TRACE (ExCreateAlias);
78210299Sed
79210299Sed
80193323Sed    /* Get the source/alias operands (both namespace nodes) */
81210299Sed
82210299Sed    AliasNode =  (ACPI_NAMESPACE_NODE *) WalkState->Operands[0];
83193323Sed    TargetNode = (ACPI_NAMESPACE_NODE *) WalkState->Operands[1];
84193323Sed
85193323Sed    if ((TargetNode->Type == ACPI_TYPE_LOCAL_ALIAS)  ||
86193323Sed        (TargetNode->Type == ACPI_TYPE_LOCAL_METHOD_ALIAS))
87193323Sed    {
88210299Sed        /*
89226633Sdim         * Dereference an existing alias so that we don't create a chain
90226633Sdim         * of aliases. With this code, we guarantee that an alias is
91226633Sdim         * always exactly one level of indirection away from the
92193323Sed         * actual aliased name.
93193323Sed         */
94193323Sed        TargetNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, TargetNode->Object);
95226633Sdim    }
96226633Sdim
97226633Sdim    /*
98226633Sdim     * For objects that can never change (i.e., the NS node will
99226633Sdim     * permanently point to the same object), we can simply attach
100226633Sdim     * the object to the new NS node. For other objects (such as
101226633Sdim     * Integers, buffers, etc.), we have to point the Alias node
102210299Sed     * to the original Node.
103210299Sed     */
104210299Sed    switch (TargetNode->Type)
105210299Sed    {
106210299Sed
107193323Sed    /* For these types, the sub-object can change dynamically via a Store */
108193323Sed
109193323Sed    case ACPI_TYPE_INTEGER:
110193323Sed    case ACPI_TYPE_STRING:
111193323Sed    case ACPI_TYPE_BUFFER:
112193323Sed    case ACPI_TYPE_PACKAGE:
113193323Sed    case ACPI_TYPE_BUFFER_FIELD:
114193323Sed    /*
115193323Sed     * These types open a new scope, so we need the NS node in order to access
116193323Sed     * any children.
117193323Sed     */
118193323Sed    case ACPI_TYPE_DEVICE:
119193323Sed    case ACPI_TYPE_POWER:
120207618Srdivacky    case ACPI_TYPE_PROCESSOR:
121207618Srdivacky    case ACPI_TYPE_THERMAL:
122207618Srdivacky    case ACPI_TYPE_LOCAL_SCOPE:
123207618Srdivacky        /*
124207618Srdivacky         * The new alias has the type ALIAS and points to the original
125207618Srdivacky         * NS node, not the object itself.
126193323Sed         */
127193323Sed        AliasNode->Type = ACPI_TYPE_LOCAL_ALIAS;
128226633Sdim        AliasNode->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode);
129226633Sdim        break;
130226633Sdim
131226633Sdim    case ACPI_TYPE_METHOD:
132226633Sdim        /*
133226633Sdim         * Control method aliases need to be differentiated
134226633Sdim         */
135226633Sdim        AliasNode->Type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
136226633Sdim        AliasNode->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode);
137226633Sdim        break;
138226633Sdim
139226633Sdim    default:
140226633Sdim
141226633Sdim        /* Attach the original source object to the new Alias Node */
142226633Sdim
143226633Sdim        /*
144226633Sdim         * The new alias assumes the type of the target, and it points
145226633Sdim         * to the same object. The reference count of the object has an
146226633Sdim         * additional reference to prevent deletion out from under either the
147226633Sdim         * target node or the alias Node
148226633Sdim         */
149226633Sdim        Status = AcpiNsAttachObject (AliasNode,
150226633Sdim            AcpiNsGetAttachedObject (TargetNode), TargetNode->Type);
151226633Sdim        break;
152226633Sdim    }
153226633Sdim
154226633Sdim    /* Since both operands are Nodes, we don't need to delete them */
155226633Sdim
156226633Sdim    return_ACPI_STATUS (Status);
157226633Sdim}
158226633Sdim
159226633Sdim
160226633Sdim/*******************************************************************************
161226633Sdim *
162226633Sdim * FUNCTION:    AcpiExCreateEvent
163226633Sdim *
164226633Sdim * PARAMETERS:  WalkState           - Current state
165226633Sdim *
166226633Sdim * RETURN:      Status
167226633Sdim *
168226633Sdim * DESCRIPTION: Create a new event object
169226633Sdim *
170226633Sdim ******************************************************************************/
171226633Sdim
172226633SdimACPI_STATUS
173226633SdimAcpiExCreateEvent (
174226633Sdim    ACPI_WALK_STATE         *WalkState)
175226633Sdim{
176226633Sdim    ACPI_STATUS             Status;
177226633Sdim    ACPI_OPERAND_OBJECT     *ObjDesc;
178226633Sdim
179226633Sdim
180226633Sdim    ACPI_FUNCTION_TRACE (ExCreateEvent);
181226633Sdim
182226633Sdim
183226633Sdim    ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_EVENT);
184226633Sdim    if (!ObjDesc)
185226633Sdim    {
186226633Sdim        Status = AE_NO_MEMORY;
187226633Sdim        goto Cleanup;
188226633Sdim    }
189226633Sdim
190226633Sdim    /*
191226633Sdim     * Create the actual OS semaphore, with zero initial units -- meaning
192226633Sdim     * that the event is created in an unsignalled state
193226633Sdim     */
194226633Sdim    Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0,
195226633Sdim        &ObjDesc->Event.OsSemaphore);
196226633Sdim    if (ACPI_FAILURE (Status))
197226633Sdim    {
198226633Sdim        goto Cleanup;
199226633Sdim    }
200226633Sdim
201226633Sdim    /* Attach object to the Node */
202226633Sdim
203226633Sdim    Status = AcpiNsAttachObject (
204226633Sdim        (ACPI_NAMESPACE_NODE *) WalkState->Operands[0],
205226633Sdim        ObjDesc, ACPI_TYPE_EVENT);
206226633Sdim
207226633SdimCleanup:
208226633Sdim    /*
209226633Sdim     * Remove local reference to the object (on error, will cause deletion
210226633Sdim     * of both object and semaphore if present.)
211226633Sdim     */
212226633Sdim    AcpiUtRemoveReference (ObjDesc);
213226633Sdim    return_ACPI_STATUS (Status);
214226633Sdim}
215226633Sdim
216226633Sdim
217226633Sdim/*******************************************************************************
218226633Sdim *
219226633Sdim * FUNCTION:    AcpiExCreateMutex
220226633Sdim *
221226633Sdim * PARAMETERS:  WalkState           - Current state
222226633Sdim *
223226633Sdim * RETURN:      Status
224226633Sdim *
225226633Sdim * DESCRIPTION: Create a new mutex object
226226633Sdim *
227226633Sdim *              Mutex (Name[0], SyncLevel[1])
228226633Sdim *
229226633Sdim ******************************************************************************/
230226633Sdim
231226633SdimACPI_STATUS
232226633SdimAcpiExCreateMutex (
233226633Sdim    ACPI_WALK_STATE         *WalkState)
234226633Sdim{
235226633Sdim    ACPI_STATUS             Status = AE_OK;
236226633Sdim    ACPI_OPERAND_OBJECT     *ObjDesc;
237226633Sdim
238226633Sdim
239226633Sdim    ACPI_FUNCTION_TRACE_PTR (ExCreateMutex, ACPI_WALK_OPERANDS);
240226633Sdim
241226633Sdim
242226633Sdim    /* Create the new mutex object */
243226633Sdim
244226633Sdim    ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX);
245226633Sdim    if (!ObjDesc)
246226633Sdim    {
247226633Sdim        Status = AE_NO_MEMORY;
248226633Sdim        goto Cleanup;
249226633Sdim    }
250226633Sdim
251226633Sdim    /* Create the actual OS Mutex */
252239462Sdim
253226633Sdim    Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex);
254226633Sdim    if (ACPI_FAILURE (Status))
255226633Sdim    {
256226633Sdim        goto Cleanup;
257226633Sdim    }
258226633Sdim
259226633Sdim    /* Init object and attach to NS node */
260226633Sdim
261226633Sdim    ObjDesc->Mutex.SyncLevel = (UINT8) WalkState->Operands[1]->Integer.Value;
262226633Sdim    ObjDesc->Mutex.Node = (ACPI_NAMESPACE_NODE *) WalkState->Operands[0];
263226633Sdim
264226633Sdim    Status = AcpiNsAttachObject (
265226633Sdim        ObjDesc->Mutex.Node, ObjDesc, ACPI_TYPE_MUTEX);
266226633Sdim
267226633Sdim
268226633SdimCleanup:
269226633Sdim    /*
270226633Sdim     * Remove local reference to the object (on error, will cause deletion
271226633Sdim     * of both object and semaphore if present.)
272226633Sdim     */
273226633Sdim    AcpiUtRemoveReference (ObjDesc);
274226633Sdim    return_ACPI_STATUS (Status);
275249423Sdim}
276226633Sdim
277226633Sdim
278226633Sdim/*******************************************************************************
279226633Sdim *
280226633Sdim * FUNCTION:    AcpiExCreateRegion
281226633Sdim *
282226633Sdim * PARAMETERS:  AmlStart            - Pointer to the region declaration AML
283226633Sdim *              AmlLength           - Max length of the declaration AML
284226633Sdim *              SpaceId             - Address space ID for the region
285226633Sdim *              WalkState           - Current state
286226633Sdim *
287226633Sdim * RETURN:      Status
288226633Sdim *
289226633Sdim * DESCRIPTION: Create a new operation region object
290263508Sdim *
291193323Sed ******************************************************************************/
292193323Sed
293193323SedACPI_STATUS
294193323SedAcpiExCreateRegion (
295218893Sdim    UINT8                   *AmlStart,
296193323Sed    UINT32                  AmlLength,
297193323Sed    UINT8                   SpaceId,
298193323Sed    ACPI_WALK_STATE         *WalkState)
299193323Sed{
300193323Sed    ACPI_STATUS             Status;
301193323Sed    ACPI_OPERAND_OBJECT     *ObjDesc;
302210299Sed    ACPI_NAMESPACE_NODE     *Node;
303193323Sed    ACPI_OPERAND_OBJECT     *RegionObj2;
304193323Sed
305193323Sed
306193323Sed    ACPI_FUNCTION_TRACE (ExCreateRegion);
307210299Sed
308207618Srdivacky
309210299Sed    /* Get the Namespace Node */
310210299Sed
311210299Sed    Node = WalkState->Op->Common.Node;
312263508Sdim
313263508Sdim    /*
314210299Sed     * If the region object is already attached to this node,
315210299Sed     * just return
316210299Sed     */
317210299Sed    if (AcpiNsGetAttachedObject (Node))
318210299Sed    {
319210299Sed        return_ACPI_STATUS (AE_OK);
320210299Sed    }
321210299Sed
322210299Sed    /*
323210299Sed     * Space ID must be one of the predefined IDs, or in the user-defined
324210299Sed     * range
325210299Sed     */
326210299Sed    if (!AcpiIsValidSpaceId (SpaceId))
327210299Sed    {
328210299Sed        /*
329210299Sed         * Print an error message, but continue. We don't want to abort
330207618Srdivacky         * a table load for this exception. Instead, if the region is
331207618Srdivacky         * actually used at runtime, abort the executing method.
332210299Sed         */
333210299Sed        ACPI_ERROR ((AE_INFO,
334210299Sed            "Invalid/unknown Address Space ID: 0x%2.2X", SpaceId));
335210299Sed    }
336210299Sed
337210299Sed    ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n",
338210299Sed        AcpiUtGetRegionName (SpaceId), SpaceId));
339210299Sed
340210299Sed    /* Create the region descriptor */
341210299Sed
342210299Sed    ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
343210299Sed    if (!ObjDesc)
344210299Sed    {
345210299Sed        Status = AE_NO_MEMORY;
346210299Sed        goto Cleanup;
347210299Sed    }
348210299Sed
349210299Sed    /*
350210299Sed     * Remember location in AML stream of address & length
351210299Sed     * operands since they need to be evaluated at run time.
352210299Sed     */
353210299Sed    RegionObj2 = AcpiNsGetSecondaryObject (ObjDesc);
354210299Sed    RegionObj2->Extra.AmlStart = AmlStart;
355210299Sed    RegionObj2->Extra.AmlLength = AmlLength;
356210299Sed    RegionObj2->Extra.Method_REG = NULL;
357210299Sed    if (WalkState->ScopeInfo)
358210299Sed    {
359210299Sed        RegionObj2->Extra.ScopeNode = WalkState->ScopeInfo->Scope.Node;
360210299Sed    }
361226633Sdim    else
362226633Sdim    {
363226633Sdim        RegionObj2->Extra.ScopeNode = Node;
364226633Sdim    }
365226633Sdim
366210299Sed    /* Init the region from the operands */
367210299Sed
368210299Sed    ObjDesc->Region.SpaceId = SpaceId;
369210299Sed    ObjDesc->Region.Address = 0;
370249423Sdim    ObjDesc->Region.Length = 0;
371249423Sdim    ObjDesc->Region.Node = Node;
372210299Sed    ObjDesc->Region.Handler = NULL;
373210299Sed    ObjDesc->Common.Flags &=
374212904Sdim        ~(AOPOBJ_SETUP_COMPLETE | AOPOBJ_REG_CONNECTED |
375212904Sdim          AOPOBJ_OBJECT_INITIALIZED);
376212904Sdim
377212904Sdim    /* Install the new region object in the parent Node */
378212904Sdim
379212904Sdim    Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_REGION);
380212904Sdim
381212904Sdim
382212904SdimCleanup:
383212904Sdim
384212904Sdim    /* Remove local reference to the object */
385212904Sdim
386212904Sdim    AcpiUtRemoveReference (ObjDesc);
387212904Sdim    return_ACPI_STATUS (Status);
388212904Sdim}
389218893Sdim
390218893Sdim
391218893Sdim/*******************************************************************************
392218893Sdim *
393218893Sdim * FUNCTION:    AcpiExCreateProcessor
394218893Sdim *
395212904Sdim * PARAMETERS:  WalkState           - Current state
396212904Sdim *
397212904Sdim * RETURN:      Status
398218893Sdim *
399218893Sdim * DESCRIPTION: Create a new processor object and populate the fields
400218893Sdim *
401218893Sdim *              Processor (Name[0], CpuID[1], PblockAddr[2], PblockLength[3])
402218893Sdim *
403218893Sdim ******************************************************************************/
404218893Sdim
405218893SdimACPI_STATUS
406218893SdimAcpiExCreateProcessor (
407218893Sdim    ACPI_WALK_STATE         *WalkState)
408218893Sdim{
409218893Sdim    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
410218893Sdim    ACPI_OPERAND_OBJECT     *ObjDesc;
411218893Sdim    ACPI_STATUS             Status;
412218893Sdim
413218893Sdim
414218893Sdim    ACPI_FUNCTION_TRACE_PTR (ExCreateProcessor, WalkState);
415218893Sdim
416218893Sdim
417218893Sdim    /* Create the processor object */
418212904Sdim
419212904Sdim    ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PROCESSOR);
420243830Sdim    if (!ObjDesc)
421226633Sdim    {
422226633Sdim        return_ACPI_STATUS (AE_NO_MEMORY);
423226633Sdim    }
424226633Sdim
425226633Sdim    /* Initialize the processor object from the operands */
426226633Sdim
427226633Sdim    ObjDesc->Processor.ProcId = (UINT8) Operand[1]->Integer.Value;
428226633Sdim    ObjDesc->Processor.Length = (UINT8) Operand[3]->Integer.Value;
429226633Sdim    ObjDesc->Processor.Address = (ACPI_IO_ADDRESS) Operand[2]->Integer.Value;
430226633Sdim
431226633Sdim    /* Install the processor object in the parent Node */
432226633Sdim
433226633Sdim    Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0],
434226633Sdim        ObjDesc, ACPI_TYPE_PROCESSOR);
435226633Sdim
436263508Sdim    /* Remove local reference to the object */
437263508Sdim
438263508Sdim    AcpiUtRemoveReference (ObjDesc);
439263508Sdim    return_ACPI_STATUS (Status);
440243830Sdim}
441263508Sdim
442263508Sdim
443263508Sdim/*******************************************************************************
444243830Sdim *
445263508Sdim * FUNCTION:    AcpiExCreatePowerResource
446263508Sdim *
447263508Sdim * PARAMETERS:  WalkState           - Current state
448263508Sdim *
449263508Sdim * RETURN:      Status
450263508Sdim *
451263508Sdim * DESCRIPTION: Create a new PowerResource object and populate the fields
452263508Sdim *
453263508Sdim *              PowerResource (Name[0], SystemLevel[1], ResourceOrder[2])
454263508Sdim *
455263508Sdim ******************************************************************************/
456263508Sdim
457263508SdimACPI_STATUS
458263508SdimAcpiExCreatePowerResource (
459263508Sdim    ACPI_WALK_STATE         *WalkState)
460263508Sdim{
461263508Sdim    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
462263508Sdim    ACPI_STATUS             Status;
463263508Sdim    ACPI_OPERAND_OBJECT     *ObjDesc;
464263508Sdim
465263508Sdim
466263508Sdim    ACPI_FUNCTION_TRACE_PTR (ExCreatePowerResource, WalkState);
467263508Sdim
468263508Sdim
469263508Sdim    /* Create the power resource object */
470263508Sdim
471263508Sdim    ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_POWER);
472263508Sdim    if (!ObjDesc)
473263508Sdim    {
474263508Sdim        return_ACPI_STATUS (AE_NO_MEMORY);
475226633Sdim    }
476218893Sdim
477243830Sdim    /* Initialize the power object from the operands */
478243830Sdim
479251662Sdim    ObjDesc->PowerResource.SystemLevel = (UINT8) Operand[1]->Integer.Value;
480249423Sdim    ObjDesc->PowerResource.ResourceOrder = (UINT16) Operand[2]->Integer.Value;
481263508Sdim
482263508Sdim    /* Install the  power resource object in the parent Node */
483243830Sdim
484243830Sdim    Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0],
485263508Sdim        ObjDesc, ACPI_TYPE_POWER);
486243830Sdim
487263508Sdim    /* Remove local reference to the object */
488263508Sdim
489243830Sdim    AcpiUtRemoveReference (ObjDesc);
490263508Sdim    return_ACPI_STATUS (Status);
491263508Sdim}
492263508Sdim#endif
493263508Sdim
494263508Sdim
495263508Sdim/*******************************************************************************
496263508Sdim *
497249423Sdim * FUNCTION:    AcpiExCreateMethod
498243830Sdim *
499243830Sdim * PARAMETERS:  AmlStart        - First byte of the method's AML
500263508Sdim *              AmlLength       - AML byte count for this method
501243830Sdim *              WalkState       - Current state
502263508Sdim *
503249423Sdim * RETURN:      Status
504243830Sdim *
505249423Sdim * DESCRIPTION: Create a new method object
506263508Sdim *
507249423Sdim ******************************************************************************/
508243830Sdim
509249423SdimACPI_STATUS
510249423SdimAcpiExCreateMethod (
511263508Sdim    UINT8                   *AmlStart,
512263508Sdim    UINT32                  AmlLength,
513249423Sdim    ACPI_WALK_STATE         *WalkState)
514249423Sdim{
515249423Sdim    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
516263508Sdim    ACPI_OPERAND_OBJECT     *ObjDesc;
517263508Sdim    ACPI_STATUS             Status;
518249423Sdim    UINT8                   MethodFlags;
519263508Sdim
520251662Sdim
521263508Sdim    ACPI_FUNCTION_TRACE_PTR (ExCreateMethod, WalkState);
522263508Sdim
523249423Sdim
524263508Sdim    /* Create a new method object */
525249423Sdim
526263508Sdim    ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
527263508Sdim    if (!ObjDesc)
528249423Sdim    {
529263508Sdim       Status = AE_NO_MEMORY;
530249423Sdim       goto Exit;
531263508Sdim    }
532249423Sdim
533263508Sdim    /* Save the method's AML pointer and length  */
534249423Sdim
535263508Sdim    ObjDesc->Method.AmlStart = AmlStart;
536249423Sdim    ObjDesc->Method.AmlLength = AmlLength;
537263508Sdim    ObjDesc->Method.Node = Operand[0];
538249423Sdim
539263508Sdim    /*
540263508Sdim     * Disassemble the method flags. Split off the ArgCount, Serialized
541263508Sdim     * flag, and SyncLevel for efficiency.
542263508Sdim     */
543263508Sdim    MethodFlags = (UINT8) Operand[1]->Integer.Value;
544263508Sdim    ObjDesc->Method.ParamCount = (UINT8)
545263508Sdim        (MethodFlags & AML_METHOD_ARG_COUNT);
546263508Sdim
547263508Sdim    /*
548263508Sdim     * Get the SyncLevel. If method is serialized, a mutex will be
549263508Sdim     * created for this method when it is parsed.
550263508Sdim     */
551263508Sdim    if (MethodFlags & AML_METHOD_SERIALIZED)
552263508Sdim    {
553263508Sdim        ObjDesc->Method.InfoFlags = ACPI_METHOD_SERIALIZED;
554263508Sdim
555249423Sdim        /*
556263508Sdim         * ACPI 1.0: SyncLevel = 0
557263508Sdim         * ACPI 2.0: SyncLevel = SyncLevel in method declaration
558263508Sdim         */
559263508Sdim        ObjDesc->Method.SyncLevel = (UINT8)
560263508Sdim            ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4);
561243830Sdim    }
562243830Sdim
563249423Sdim    /* Attach the new object to the method Node */
564249423Sdim
565249423Sdim    Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0],
566249423Sdim        ObjDesc, ACPI_TYPE_METHOD);
567249423Sdim
568249423Sdim    /* Remove local reference to the object */
569249423Sdim
570249423Sdim    AcpiUtRemoveReference (ObjDesc);
571249423Sdim
572249423SdimExit:
573249423Sdim    /* Remove a reference to the operand */
574249423Sdim
575249423Sdim    AcpiUtRemoveReference (Operand[1]);
576249423Sdim    return_ACPI_STATUS (Status);
577249423Sdim}
578249423Sdim