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