nsalloc.c revision 67754
1/*******************************************************************************
2 *
3 * Module Name: nsalloc - Namespace allocation and deletion utilities
4 *              $Revision: 41 $
5 *
6 ******************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999, Intel Corp.  All rights
13 * 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          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 = AcpiCmCallocate (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    AcpiCmFree (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    OBJECT_TYPE_INTERNAL    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
309    if ((ACPI_TYPE_ANY == Type) ||
310        (INTERNAL_TYPE_DEF_FIELD_DEFN == Type) ||
311        (INTERNAL_TYPE_BANK_FIELD_DEFN == Type))
312    {
313        /*
314         * We don't want to abort here, however!
315         * We will fill in the actual type when the
316         * real definition is found later.
317         */
318
319        DEBUG_PRINT (ACPI_INFO,
320            ("NsInstallNode: [%4.4s] is a forward reference\n",
321            &Node->Name));
322
323    }
324
325    /*
326     * The DefFieldDefn and BankFieldDefn cases are actually
327     * looking up the Region in which the field will be defined
328     */
329
330    if ((INTERNAL_TYPE_DEF_FIELD_DEFN == Type) ||
331        (INTERNAL_TYPE_BANK_FIELD_DEFN == Type))
332    {
333        Type = ACPI_TYPE_REGION;
334    }
335
336    /*
337     * Scope, DefAny, and IndexFieldDefn are bogus "types" which do
338     * not actually have anything to do with the type of the name
339     * being looked up.  Save any other value of Type as the type of
340     * the entry.
341     */
342
343    if ((Type != INTERNAL_TYPE_SCOPE) &&
344        (Type != INTERNAL_TYPE_DEF_ANY) &&
345        (Type != INTERNAL_TYPE_INDEX_FIELD_DEFN))
346    {
347        Node->Type = (UINT8) Type;
348    }
349
350    DEBUG_PRINT (TRACE_NAMES,
351        ("NsInstallNode: %4.4s added to %p at %p\n",
352        &Node->Name, ParentNode, Node));
353
354    /*
355     * Increment the reference count(s) of all parents up to
356     * the root!
357     */
358
359    while ((Node = AcpiNsGetParentObject (Node)) != NULL)
360    {
361        Node->ReferenceCount++;
362    }
363
364    return_VOID;
365}
366
367
368/*******************************************************************************
369 *
370 * FUNCTION:    AcpiNsDeleteChildren
371 *
372 * PARAMETERS:  ParentNode      - Delete this objects children
373 *
374 * RETURN:      None.
375 *
376 * DESCRIPTION: Delete all children of the parent object. Deletes a
377 *              "scope".
378 *
379 ******************************************************************************/
380
381void
382AcpiNsDeleteChildren (
383    ACPI_NAMESPACE_NODE     *ParentNode)
384{
385    ACPI_NAMESPACE_NODE     *ChildNode;
386    ACPI_NAMESPACE_NODE     *NextNode;
387    UINT8                   Flags;
388
389
390    FUNCTION_TRACE_PTR ("AcpiNsDeleteChildren", ParentNode);
391
392
393    if (!ParentNode)
394    {
395        return_VOID;
396    }
397
398    /* If no children, all done! */
399
400    ChildNode = ParentNode->Child;
401    if (!ChildNode)
402    {
403        return_VOID;
404    }
405
406    /*
407     * Deallocate all children at this level
408     */
409    do
410    {
411        /* Get the things we need */
412
413        NextNode    = ChildNode->Peer;
414        Flags       = ChildNode->Flags;
415
416        /* Grandchildren should have all been deleted already */
417
418        if (ChildNode->Child)
419        {
420            DEBUG_PRINT (ACPI_ERROR,
421                ("NsDeleteChildren: Found a grandchild! P=%X C=%X\n",
422                ParentNode, ChildNode));
423        }
424
425        /* Now we can free this child object */
426
427        DECREMENT_NAME_TABLE_METRICS (sizeof (ACPI_NAMESPACE_NODE));
428
429        DEBUG_PRINT (ACPI_INFO,
430            ("AcpiNsDeleteChildren: Object %p, Remaining %d\n",
431            ChildNode, AcpiGbl_CurrentNodeCount));
432
433        /*
434         * Detach an object if there is one
435         */
436
437        if (ChildNode->Object)
438        {
439            AcpiNsDetachObject (ChildNode);
440        }
441
442        AcpiCmFree (ChildNode);
443
444        /* And move on to the next child in the list */
445
446        ChildNode = NextNode;
447
448    } while (!(Flags & ANOBJ_END_OF_PEER_LIST));
449
450
451    /* Clear the parent's child pointer */
452
453    ParentNode->Child = NULL;
454
455    return_VOID;
456}
457
458
459/*******************************************************************************
460 *
461 * FUNCTION:    AcpiNsDeleteNamespaceSubtree
462 *
463 * PARAMETERS:  None.
464 *
465 * RETURN:      None.
466 *
467 * DESCRIPTION: Delete a subtree of the namespace.  This includes all objects
468 *              stored within the subtree.  Scope tables are deleted also
469 *
470 ******************************************************************************/
471
472ACPI_STATUS
473AcpiNsDeleteNamespaceSubtree (
474    ACPI_NAMESPACE_NODE     *ParentNode)
475{
476    ACPI_NAMESPACE_NODE     *ChildNode;
477    ACPI_OPERAND_OBJECT     *ObjDesc;
478    UINT32                  Level;
479
480
481    FUNCTION_TRACE ("NsDeleteNamespaceSubtree");
482
483
484    if (!ParentNode)
485    {
486        return_ACPI_STATUS (AE_OK);
487    }
488
489
490    ChildNode   = 0;
491    Level       = 1;
492
493    /*
494     * Traverse the tree of objects until we bubble back up
495     * to where we started.
496     */
497
498    while (Level > 0)
499    {
500        /*
501         * Get the next typed object in this scope.
502         * Null returned if not found
503         */
504
505        ChildNode = AcpiNsGetNextObject (ACPI_TYPE_ANY, ParentNode,
506                                            ChildNode);
507        if (ChildNode)
508        {
509            /*
510             * Found an object - delete the object within
511             * the Value field
512             */
513
514            ObjDesc = AcpiNsGetAttachedObject (ChildNode);
515            if (ObjDesc)
516            {
517                AcpiNsDetachObject (ChildNode);
518                AcpiCmRemoveReference (ObjDesc);
519            }
520
521
522            /* Check if this object has any children */
523
524            if (AcpiNsGetNextObject (ACPI_TYPE_ANY, ChildNode, 0))
525            {
526                /*
527                 * There is at least one child of this object,
528                 * visit the object
529                 */
530
531                Level++;
532                ParentNode    = ChildNode;
533                ChildNode     = 0;
534            }
535        }
536
537        else
538        {
539            /*
540             * No more children in this object.
541             * We will move up to the grandparent.
542             */
543            Level--;
544
545            /*
546             * Now delete all of the children of this parent
547             * all at the same time.
548             */
549            AcpiNsDeleteChildren (ParentNode);
550
551            /* New "last child" is this parent object */
552
553            ChildNode = ParentNode;
554
555            /* Now we can move up the tree to the grandparent */
556
557            ParentNode = AcpiNsGetParentObject (ParentNode);
558        }
559    }
560
561
562    return_ACPI_STATUS (AE_OK);
563}
564
565
566/*******************************************************************************
567 *
568 * FUNCTION:    AcpiNsRemoveReference
569 *
570 * PARAMETERS:  Node           - Named object whose reference count is to be
571 *                                decremented
572 *
573 * RETURN:      None.
574 *
575 * DESCRIPTION: Remove a Node reference.  Decrements the reference count
576 *              of all parent Nodes up to the root.  Any object along
577 *              the way that reaches zero references is freed.
578 *
579 ******************************************************************************/
580
581void
582AcpiNsRemoveReference (
583    ACPI_NAMESPACE_NODE     *Node)
584{
585    ACPI_NAMESPACE_NODE     *NextNode;
586
587
588    /*
589     * Decrement the reference count(s) of this object and all
590     * objects up to the root,  Delete anything with zero remaining references.
591     */
592    NextNode = Node;
593    while (NextNode)
594    {
595        /* Decrement the reference count on this object*/
596
597        NextNode->ReferenceCount--;
598
599        /* Delete the object if no more references */
600
601        if (!NextNode->ReferenceCount)
602        {
603            /* Delete all children and delete the object */
604
605            AcpiNsDeleteChildren (NextNode);
606            AcpiNsDeleteNode (NextNode);
607        }
608
609        /* Move up to parent */
610
611        NextNode = AcpiNsGetParentObject (NextNode);
612    }
613}
614
615
616/*******************************************************************************
617 *
618 * FUNCTION:    AcpiNsDeleteNamespaceByOwner
619 *
620 * PARAMETERS:  None.
621 *
622 * RETURN:      None.
623 *
624 * DESCRIPTION: Delete entries within the namespace that are owned by a
625 *              specific ID.  Used to delete entire ACPI tables.  All
626 *              reference counts are updated.
627 *
628 ******************************************************************************/
629
630ACPI_STATUS
631AcpiNsDeleteNamespaceByOwner (
632    UINT16                  OwnerId)
633{
634    ACPI_NAMESPACE_NODE     *ChildNode;
635    UINT32                  Level;
636    ACPI_OPERAND_OBJECT     *ObjDesc;
637    ACPI_NAMESPACE_NODE     *ParentNode;
638
639
640    FUNCTION_TRACE ("NsDeleteNamespaceSubtree");
641
642
643    ParentNode  = AcpiGbl_RootNode;
644    ChildNode   = 0;
645    Level       = 1;
646
647    /*
648     * Traverse the tree of objects until we bubble back up
649     * to where we started.
650     */
651
652    while (Level > 0)
653    {
654        /*
655         * Get the next typed object in this scope.
656         * Null returned if not found
657         */
658
659        ChildNode = AcpiNsGetNextObject (ACPI_TYPE_ANY, ParentNode,
660                                            ChildNode);
661
662        if (ChildNode)
663        {
664            if (ChildNode->OwnerId == OwnerId)
665            {
666                /*
667                 * Found an object - delete the object within
668                 * the Value field
669                 */
670
671                ObjDesc = AcpiNsGetAttachedObject (ChildNode);
672                if (ObjDesc)
673                {
674                    AcpiNsDetachObject (ChildNode);
675                    AcpiCmRemoveReference (ObjDesc);
676                }
677            }
678
679            /* Check if this object has any children */
680
681            if (AcpiNsGetNextObject (ACPI_TYPE_ANY, ChildNode, 0))
682            {
683                /*
684                 * There is at least one child of this object,
685                 * visit the object
686                 */
687
688                Level++;
689                ParentNode    = ChildNode;
690                ChildNode     = 0;
691            }
692
693            else if (ChildNode->OwnerId == OwnerId)
694            {
695                AcpiNsRemoveReference (ChildNode);
696            }
697        }
698
699        else
700        {
701            /*
702             * No more children in this object.  Move up to grandparent.
703             */
704            Level--;
705
706            if (Level != 0)
707            {
708                if (ParentNode->OwnerId == OwnerId)
709                {
710                    AcpiNsRemoveReference (ParentNode);
711                }
712            }
713
714            /* New "last child" is this parent object */
715
716            ChildNode = ParentNode;
717
718            /* Now we can move up the tree to the grandparent */
719
720            ParentNode = AcpiNsGetParentObject (ParentNode);
721        }
722    }
723
724
725    return_ACPI_STATUS (AE_OK);
726}
727
728
729