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