nsalloc.c revision 83174
1/*******************************************************************************
2 *
3 * Module Name: nsalloc - Namespace allocation and deletion utilities
4 *              $Revision: 55 $
5 *
6 ******************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999, 2000, 2001, 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
118#define __NSALLOC_C__
119
120#include "acpi.h"
121#include "acnamesp.h"
122#include "acinterp.h"
123
124
125#define _COMPONENT          ACPI_NAMESPACE
126        MODULE_NAME         ("nsalloc")
127
128
129/*******************************************************************************
130 *
131 * FUNCTION:    AcpiNsCreateNode
132 *
133 * PARAMETERS:  AcpiName        - Name of the new node
134 *
135 * RETURN:      None
136 *
137 * DESCRIPTION: Create a namespace node
138 *
139 ******************************************************************************/
140
141ACPI_NAMESPACE_NODE *
142AcpiNsCreateNode (
143    UINT32                  AcpiName)
144{
145    ACPI_NAMESPACE_NODE     *Node;
146
147
148    FUNCTION_TRACE ("NsCreateNode");
149
150
151    Node = ACPI_MEM_CALLOCATE (sizeof (ACPI_NAMESPACE_NODE));
152    if (!Node)
153    {
154        return_PTR (NULL);
155    }
156
157    ACPI_MEM_TRACKING (AcpiGbl_MemoryLists[ACPI_MEM_LIST_NSNODE].TotalAllocated++);
158
159    Node->DataType       = ACPI_DESC_TYPE_NAMED;
160    Node->Name           = AcpiName;
161    Node->ReferenceCount = 1;
162
163    return_PTR (Node);
164}
165
166
167/*******************************************************************************
168 *
169 * FUNCTION:    AcpiNsDeleteNode
170 *
171 * PARAMETERS:  Node            - Node to be deleted
172 *
173 * RETURN:      None
174 *
175 * DESCRIPTION: Delete a namespace node
176 *
177 ******************************************************************************/
178
179void
180AcpiNsDeleteNode (
181    ACPI_NAMESPACE_NODE     *Node)
182{
183    ACPI_NAMESPACE_NODE     *ParentNode;
184    ACPI_NAMESPACE_NODE     *PrevNode;
185    ACPI_NAMESPACE_NODE     *NextNode;
186
187
188    FUNCTION_TRACE_PTR ("NsDeleteNode", Node);
189
190
191    ParentNode = AcpiNsGetParentObject (Node);
192
193    PrevNode = NULL;
194    NextNode = ParentNode->Child;
195
196    while (NextNode != Node)
197    {
198        PrevNode = NextNode;
199        NextNode = PrevNode->Peer;
200    }
201
202    if (PrevNode)
203    {
204        PrevNode->Peer = NextNode->Peer;
205        if (NextNode->Flags & ANOBJ_END_OF_PEER_LIST)
206        {
207            PrevNode->Flags |= ANOBJ_END_OF_PEER_LIST;
208        }
209    }
210    else
211    {
212        ParentNode->Child = NextNode->Peer;
213    }
214
215
216    ACPI_MEM_TRACKING (AcpiGbl_MemoryLists[ACPI_MEM_LIST_NSNODE].TotalFreed++);
217
218    /*
219     * Detach an object if there is one
220     */
221    if (Node->Object)
222    {
223        AcpiNsDetachObject (Node);
224    }
225
226    ACPI_MEM_FREE (Node);
227    return_VOID;
228}
229
230
231/*******************************************************************************
232 *
233 * FUNCTION:    AcpiNsInstallNode
234 *
235 * PARAMETERS:  WalkState       - Current state of the walk
236 *              ParentNode      - The parent of the new Node
237 *              Node            - The new Node to install
238 *              Type            - ACPI object type of the new Node
239 *
240 * RETURN:      None
241 *
242 * DESCRIPTION: Initialize a new entry within a namespace table.
243 *
244 ******************************************************************************/
245
246void
247AcpiNsInstallNode (
248    ACPI_WALK_STATE         *WalkState,
249    ACPI_NAMESPACE_NODE     *ParentNode,    /* Parent */
250    ACPI_NAMESPACE_NODE     *Node,          /* New Child*/
251    ACPI_OBJECT_TYPE8       Type)
252{
253    UINT16                  OwnerId = TABLE_ID_DSDT;
254    ACPI_NAMESPACE_NODE     *ChildNode;
255
256
257    FUNCTION_TRACE ("NsInstallNode");
258
259
260    /*
261     * Get the owner ID from the Walk state
262     * The owner ID is used to track table deletion and
263     * deletion of objects created by methods
264     */
265    if (WalkState)
266    {
267        OwnerId = WalkState->OwnerId;
268    }
269
270
271    /* link the new entry into the parent and existing children */
272
273    /* TBD: Could be first, last, or alphabetic */
274
275    ChildNode = ParentNode->Child;
276    if (!ChildNode)
277    {
278        ParentNode->Child = Node;
279    }
280
281    else
282    {
283        while (!(ChildNode->Flags & ANOBJ_END_OF_PEER_LIST))
284        {
285            ChildNode = ChildNode->Peer;
286        }
287
288        ChildNode->Peer = Node;
289
290        /* Clear end-of-list flag */
291
292        ChildNode->Flags &= ~ANOBJ_END_OF_PEER_LIST;
293    }
294
295    /* Init the new entry */
296
297    Node->OwnerId   = OwnerId;
298    Node->Flags     |= ANOBJ_END_OF_PEER_LIST;
299    Node->Peer      = ParentNode;
300
301
302    /*
303     * If adding a name with unknown type, or having to
304     * add the region in order to define fields in it, we
305     * have a forward reference.
306     */
307    if ((ACPI_TYPE_ANY == Type) ||
308        (INTERNAL_TYPE_FIELD_DEFN == Type) ||
309        (INTERNAL_TYPE_BANK_FIELD_DEFN == Type))
310    {
311        /*
312         * We don't want to abort here, however!
313         * We will fill in the actual type when the
314         * real definition is found later.
315         */
316        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "[%4.4s] is a forward reference\n",
317            &Node->Name));
318    }
319
320    /*
321     * The DefFieldDefn and BankFieldDefn cases are actually
322     * looking up the Region in which the field will be defined
323     */
324    if ((INTERNAL_TYPE_FIELD_DEFN == Type) ||
325        (INTERNAL_TYPE_BANK_FIELD_DEFN == Type))
326    {
327        Type = ACPI_TYPE_REGION;
328    }
329
330    /*
331     * Scope, DefAny, and IndexFieldDefn are bogus "types" which do
332     * not actually have anything to do with the type of the name
333     * being looked up.  Save any other value of Type as the type of
334     * the entry.
335     */
336    if ((Type != INTERNAL_TYPE_SCOPE) &&
337        (Type != INTERNAL_TYPE_DEF_ANY) &&
338        (Type != INTERNAL_TYPE_INDEX_FIELD_DEFN))
339    {
340        Node->Type = (UINT8) Type;
341    }
342
343    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%4.4s added to %p at %p\n",
344        &Node->Name, ParentNode, Node));
345
346    /*
347     * Increment the reference count(s) of all parents up to
348     * the root!
349     */
350    while ((Node = AcpiNsGetParentObject (Node)) != NULL)
351    {
352        Node->ReferenceCount++;
353    }
354
355    return_VOID;
356}
357
358
359/*******************************************************************************
360 *
361 * FUNCTION:    AcpiNsDeleteChildren
362 *
363 * PARAMETERS:  ParentNode      - Delete this objects children
364 *
365 * RETURN:      None.
366 *
367 * DESCRIPTION: Delete all children of the parent object. Deletes a
368 *              "scope".
369 *
370 ******************************************************************************/
371
372void
373AcpiNsDeleteChildren (
374    ACPI_NAMESPACE_NODE     *ParentNode)
375{
376    ACPI_NAMESPACE_NODE     *ChildNode;
377    ACPI_NAMESPACE_NODE     *NextNode;
378    UINT8                   Flags;
379
380
381    FUNCTION_TRACE_PTR ("NsDeleteChildren", ParentNode);
382
383
384    if (!ParentNode)
385    {
386        return_VOID;
387    }
388
389    /* If no children, all done! */
390
391    ChildNode = ParentNode->Child;
392    if (!ChildNode)
393    {
394        return_VOID;
395    }
396
397    /*
398     * Deallocate all children at this level
399     */
400    do
401    {
402        /* Get the things we need */
403
404        NextNode    = ChildNode->Peer;
405        Flags       = ChildNode->Flags;
406
407        /* Grandchildren should have all been deleted already */
408
409        if (ChildNode->Child)
410        {
411            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found a grandchild! P=%X C=%X\n",
412                ParentNode, ChildNode));
413        }
414
415        /* Now we can free this child object */
416
417        ACPI_MEM_TRACKING (AcpiGbl_MemoryLists[ACPI_MEM_LIST_NSNODE].TotalFreed++);
418
419        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Object %p, Remaining %X\n",
420            ChildNode, AcpiGbl_CurrentNodeCount));
421
422        /*
423         * Detach an object if there is one
424         */
425        if (ChildNode->Object)
426        {
427            AcpiNsDetachObject (ChildNode);
428        }
429
430        ACPI_MEM_FREE (ChildNode);
431
432        /* And move on to the next child in the list */
433
434        ChildNode = NextNode;
435
436    } while (!(Flags & ANOBJ_END_OF_PEER_LIST));
437
438
439    /* Clear the parent's child pointer */
440
441    ParentNode->Child = NULL;
442
443    return_VOID;
444}
445
446
447/*******************************************************************************
448 *
449 * FUNCTION:    AcpiNsDeleteNamespaceSubtree
450 *
451 * PARAMETERS:  ParentNode      - Root of the subtree to be deleted
452 *
453 * RETURN:      None.
454 *
455 * DESCRIPTION: Delete a subtree of the namespace.  This includes all objects
456 *              stored within the subtree.  Scope tables are deleted also
457 *
458 ******************************************************************************/
459
460ACPI_STATUS
461AcpiNsDeleteNamespaceSubtree (
462    ACPI_NAMESPACE_NODE     *ParentNode)
463{
464    ACPI_NAMESPACE_NODE     *ChildNode;
465    ACPI_OPERAND_OBJECT     *ObjDesc;
466    UINT32                  Level;
467
468
469    FUNCTION_TRACE ("NsDeleteNamespaceSubtree");
470
471
472    if (!ParentNode)
473    {
474        return_ACPI_STATUS (AE_OK);
475    }
476
477
478    ChildNode   = 0;
479    Level       = 1;
480
481    /*
482     * Traverse the tree of objects until we bubble back up
483     * to where we started.
484     */
485    while (Level > 0)
486    {
487        /*
488         * Get the next typed object in this scope.
489         * Null returned if not found
490         */
491        ChildNode = AcpiNsGetNextObject (ACPI_TYPE_ANY, ParentNode,
492                                            ChildNode);
493        if (ChildNode)
494        {
495            /*
496             * Found an object - delete the object within
497             * the Value field
498             */
499            ObjDesc = AcpiNsGetAttachedObject (ChildNode);
500            if (ObjDesc)
501            {
502                AcpiNsDetachObject (ChildNode);
503                AcpiUtRemoveReference (ObjDesc);
504            }
505
506
507            /* Check if this object has any children */
508
509            if (AcpiNsGetNextObject (ACPI_TYPE_ANY, ChildNode, 0))
510            {
511                /*
512                 * There is at least one child of this object,
513                 * visit the object
514                 */
515                Level++;
516                ParentNode    = ChildNode;
517                ChildNode     = 0;
518            }
519        }
520
521        else
522        {
523            /*
524             * No more children in this object.
525             * We will move up to the grandparent.
526             */
527            Level--;
528
529            /*
530             * Now delete all of the children of this parent
531             * all at the same time.
532             */
533            AcpiNsDeleteChildren (ParentNode);
534
535            /* New "last child" is this parent object */
536
537            ChildNode = ParentNode;
538
539            /* Now we can move up the tree to the grandparent */
540
541            ParentNode = AcpiNsGetParentObject (ParentNode);
542        }
543    }
544
545
546    return_ACPI_STATUS (AE_OK);
547}
548
549
550/*******************************************************************************
551 *
552 * FUNCTION:    AcpiNsRemoveReference
553 *
554 * PARAMETERS:  Node           - Named object whose reference count is to be
555 *                               decremented
556 *
557 * RETURN:      None.
558 *
559 * DESCRIPTION: Remove a Node reference.  Decrements the reference count
560 *              of all parent Nodes up to the root.  Any object along
561 *              the way that reaches zero references is freed.
562 *
563 ******************************************************************************/
564
565static void
566AcpiNsRemoveReference (
567    ACPI_NAMESPACE_NODE     *Node)
568{
569    ACPI_NAMESPACE_NODE     *NextNode;
570
571
572    FUNCTION_ENTRY ();
573
574
575    /*
576     * Decrement the reference count(s) of this object and all
577     * objects up to the root,  Delete anything with zero remaining references.
578     */
579    NextNode = Node;
580    while (NextNode)
581    {
582        /* Decrement the reference count on this object*/
583
584        NextNode->ReferenceCount--;
585
586        /* Delete the object if no more references */
587
588        if (!NextNode->ReferenceCount)
589        {
590            /* Delete all children and delete the object */
591
592            AcpiNsDeleteChildren (NextNode);
593            AcpiNsDeleteNode (NextNode);
594        }
595
596        /* Move up to parent */
597
598        NextNode = AcpiNsGetParentObject (NextNode);
599    }
600}
601
602
603/*******************************************************************************
604 *
605 * FUNCTION:    AcpiNsDeleteNamespaceByOwner
606 *
607 * PARAMETERS:  OwnerId     - All nodes with this owner will be deleted
608 *
609 * RETURN:      Status
610 *
611 * DESCRIPTION: Delete entries within the namespace that are owned by a
612 *              specific ID.  Used to delete entire ACPI tables.  All
613 *              reference counts are updated.
614 *
615 ******************************************************************************/
616
617ACPI_STATUS
618AcpiNsDeleteNamespaceByOwner (
619    UINT16                  OwnerId)
620{
621    ACPI_NAMESPACE_NODE     *ChildNode;
622    UINT32                  Level;
623    ACPI_OPERAND_OBJECT     *ObjDesc;
624    ACPI_NAMESPACE_NODE     *ParentNode;
625
626
627    FUNCTION_TRACE ("NsDeleteNamespaceByOwner");
628
629
630    ParentNode  = AcpiGbl_RootNode;
631    ChildNode   = 0;
632    Level       = 1;
633
634    /*
635     * Traverse the tree of objects until we bubble back up
636     * to where we started.
637     */
638    while (Level > 0)
639    {
640        /*
641         * Get the next typed object in this scope.
642         * Null returned if not found
643         */
644        ChildNode = AcpiNsGetNextObject (ACPI_TYPE_ANY, ParentNode,
645                                            ChildNode);
646
647        if (ChildNode)
648        {
649            if (ChildNode->OwnerId == OwnerId)
650            {
651                /*
652                 * Found an object - delete the object within
653                 * the Value field
654                 */
655                ObjDesc = AcpiNsGetAttachedObject (ChildNode);
656                if (ObjDesc)
657                {
658                    AcpiNsDetachObject (ChildNode);
659                    AcpiUtRemoveReference (ObjDesc);
660                }
661            }
662
663            /* Check if this object has any children */
664
665            if (AcpiNsGetNextObject (ACPI_TYPE_ANY, ChildNode, 0))
666            {
667                /*
668                 * There is at least one child of this object,
669                 * visit the object
670                 */
671
672                Level++;
673                ParentNode    = ChildNode;
674                ChildNode     = 0;
675            }
676
677            else if (ChildNode->OwnerId == OwnerId)
678            {
679                AcpiNsRemoveReference (ChildNode);
680            }
681        }
682
683        else
684        {
685            /*
686             * No more children in this object.  Move up to grandparent.
687             */
688            Level--;
689
690            if (Level != 0)
691            {
692                if (ParentNode->OwnerId == OwnerId)
693                {
694                    AcpiNsRemoveReference (ParentNode);
695                }
696            }
697
698            /* New "last child" is this parent object */
699
700            ChildNode = ParentNode;
701
702            /* Now we can move up the tree to the grandparent */
703
704            ParentNode = AcpiNsGetParentObject (ParentNode);
705        }
706    }
707
708
709    return_ACPI_STATUS (AE_OK);
710}
711
712
713