dmrestag.c revision 193529
1132451Sroberto/******************************************************************************
2132451Sroberto *
3132451Sroberto * Module Name: dmrestag - Add tags to resource descriptors (Application-level)
4132451Sroberto *
5132451Sroberto *****************************************************************************/
6132451Sroberto
7132451Sroberto/******************************************************************************
8132451Sroberto *
9132451Sroberto * 1. Copyright Notice
10132451Sroberto *
11132451Sroberto * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
12132451Sroberto * All rights reserved.
13132451Sroberto *
14132451Sroberto * 2. License
15132451Sroberto *
16132451Sroberto * 2.1. This is your license from Intel Corp. under its intellectual property
17132451Sroberto * rights.  You may have additional license terms from the party that provided
18132451Sroberto * you this software, covering your right to use that party's intellectual
19132451Sroberto * property rights.
20132451Sroberto *
21132451Sroberto * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22132451Sroberto * copy of the source code appearing in this file ("Covered Code") an
23132451Sroberto * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24132451Sroberto * base code distributed originally by Intel ("Original Intel Code") to copy,
25132451Sroberto * make derivatives, distribute, use and display any portion of the Covered
26132451Sroberto * Code in any form, with the right to sublicense such rights; and
27132451Sroberto *
28132451Sroberto * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29132451Sroberto * license (with the right to sublicense), under only those claims of Intel
30132451Sroberto * patents that are infringed by the Original Intel Code, to make, use, sell,
31132451Sroberto * offer to sell, and import the Covered Code and derivative works thereof
32132451Sroberto * solely to the minimum extent necessary to exercise the above copyright
33132451Sroberto * license, and in no event shall the patent license extend to any additions
34132451Sroberto * to or modifications of the Original Intel Code.  No other license or right
35132451Sroberto * is granted directly or by implication, estoppel or otherwise;
36132451Sroberto *
37132451Sroberto * The above copyright and patent license is granted only if the following
38132451Sroberto * conditions are met:
39132451Sroberto *
40132451Sroberto * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision.  In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change.  Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee.  Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution.  In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government.  In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************/
115
116
117#include <contrib/dev/acpica/include/acpi.h>
118#include <contrib/dev/acpica/include/accommon.h>
119#include <contrib/dev/acpica/include/acparser.h>
120#include <contrib/dev/acpica/include/acdisasm.h>
121#include <contrib/dev/acpica/include/acnamesp.h>
122#include <contrib/dev/acpica/include/amlcode.h>
123
124/* This module used for application-level code only */
125
126#define _COMPONENT          ACPI_CA_DISASSEMBLER
127        ACPI_MODULE_NAME    ("dmrestag")
128
129/* Local prototypes */
130
131static void
132AcpiDmUpdateResourceName (
133    ACPI_NAMESPACE_NODE     *ResourceNode);
134
135static char *
136AcpiDmSearchTagList (
137    UINT32                  BitIndex,
138    ACPI_RESOURCE_TAG       *TagList);
139
140static char *
141AcpiDmGetResourceTag (
142    UINT32                  BitIndex,
143    AML_RESOURCE            *Resource,
144    UINT8                   ResourceIndex);
145
146static char *
147AcpiGetTagPathname (
148    ACPI_NAMESPACE_NODE     *BufferNode,
149    ACPI_NAMESPACE_NODE     *ResourceNode,
150    UINT32                  BitIndex);
151
152static ACPI_NAMESPACE_NODE *
153AcpiDmGetResourceNode (
154    ACPI_NAMESPACE_NODE     *BufferNode,
155    UINT32                  BitIndex);
156
157static ACPI_STATUS
158AcpiDmAddResourceToNamespace (
159    UINT8                   *Aml,
160    UINT32                  Length,
161    UINT32                  Offset,
162    UINT8                   ResourceIndex,
163    void                    *Context);
164
165static void
166AcpiDmAddResourcesToNamespace (
167    ACPI_NAMESPACE_NODE     *BufferNode,
168    ACPI_PARSE_OBJECT       *Op);
169
170
171/******************************************************************************
172 *
173 * Resource Tag tables
174 *
175 * These are the predefined tags that refer to elements of a resource
176 * descriptor. Each name and offset is defined in the ACPI specification.
177 *
178 * Each table entry contains the bit offset of the field and the associated
179 * name.
180 *
181 ******************************************************************************/
182
183static ACPI_RESOURCE_TAG        AcpiDmIrqTags[] =
184{
185    {( 1 * 8),      ACPI_RESTAG_INTERRUPT},
186    {( 3 * 8) + 0,  ACPI_RESTAG_INTERRUPTTYPE},
187    {( 3 * 8) + 3,  ACPI_RESTAG_INTERRUPTLEVEL},
188    {( 3 * 8) + 4,  ACPI_RESTAG_INTERRUPTSHARE},
189    {0,             NULL}
190};
191
192static ACPI_RESOURCE_TAG        AcpiDmDmaTags[] =
193{
194    {( 1 * 8),      ACPI_RESTAG_DMA},
195    {( 2 * 8) + 0,  ACPI_RESTAG_XFERTYPE},
196    {( 2 * 8) + 2,  ACPI_RESTAG_BUSMASTER},
197    {( 2 * 8) + 5,  ACPI_RESTAG_DMATYPE},
198    {0,             NULL}
199};
200
201static ACPI_RESOURCE_TAG        AcpiDmIoTags[] =
202{
203    {( 1 * 8) + 0,  ACPI_RESTAG_DECODE},
204    {( 2 * 8),      ACPI_RESTAG_MINADDR},
205    {( 4 * 8),      ACPI_RESTAG_MAXADDR},
206    {( 6 * 8),      ACPI_RESTAG_ALIGNMENT},
207    {( 7 * 8),      ACPI_RESTAG_LENGTH},
208    {0,             NULL}
209};
210
211static ACPI_RESOURCE_TAG        AcpiDmFixedIoTags[] =
212{
213    {( 1 * 8),      ACPI_RESTAG_BASEADDRESS},
214    {( 3 * 8),      ACPI_RESTAG_LENGTH},
215    {0,             NULL}
216};
217
218static ACPI_RESOURCE_TAG        AcpiDmMemory24Tags[] =
219{
220    {( 3 * 8) + 0,  ACPI_RESTAG_READWRITETYPE},
221    {( 4 * 8),      ACPI_RESTAG_MINADDR},
222    {( 6 * 8),      ACPI_RESTAG_MAXADDR},
223    {( 8 * 8),      ACPI_RESTAG_ALIGNMENT},
224    {(10 * 8),      ACPI_RESTAG_LENGTH},
225    {0,             NULL}
226};
227
228static ACPI_RESOURCE_TAG        AcpiDmRegisterTags[] =
229{
230    {( 3 * 8),      ACPI_RESTAG_ADDRESSSPACE},
231    {( 4 * 8),      ACPI_RESTAG_REGISTERBITWIDTH},
232    {( 5 * 8),      ACPI_RESTAG_REGISTERBITOFFSET},
233    {( 6 * 8),      ACPI_RESTAG_ACCESSSIZE},
234    {( 7 * 8),      ACPI_RESTAG_ADDRESS},
235    {0,             NULL}
236};
237
238static ACPI_RESOURCE_TAG        AcpiDmMemory32Tags[] =
239{
240    {( 3 * 8) + 0,  ACPI_RESTAG_READWRITETYPE},
241    {( 4 * 8),      ACPI_RESTAG_MINADDR},
242    {( 8 * 8),      ACPI_RESTAG_MAXADDR},
243    {(12 * 8),      ACPI_RESTAG_ALIGNMENT},
244    {(16 * 8),      ACPI_RESTAG_LENGTH},
245    {0,             NULL}
246};
247
248static ACPI_RESOURCE_TAG        AcpiDmFixedMemory32Tags[] =
249{
250    {( 3 * 8) + 0,  ACPI_RESTAG_READWRITETYPE},
251    {( 4 * 8),      ACPI_RESTAG_BASEADDRESS},
252    {( 8 * 8),      ACPI_RESTAG_LENGTH},
253    {0,             NULL}
254};
255
256static ACPI_RESOURCE_TAG        AcpiDmInterruptTags[] =
257{
258    {( 3 * 8) + 1,  ACPI_RESTAG_INTERRUPTTYPE},
259    {( 3 * 8) + 2,  ACPI_RESTAG_INTERRUPTLEVEL},
260    {( 3 * 8) + 3,  ACPI_RESTAG_INTERRUPTSHARE},
261    {( 5 * 8),      ACPI_RESTAG_INTERRUPT},
262    {0,             NULL}
263};
264
265static ACPI_RESOURCE_TAG        AcpiDmAddress16Tags[] =
266{
267    {( 4 * 8) + 1,  ACPI_RESTAG_DECODE},
268    {( 4 * 8) + 2,  ACPI_RESTAG_MINTYPE},
269    {( 4 * 8) + 3,  ACPI_RESTAG_MAXTYPE},
270    {( 6 * 8),      ACPI_RESTAG_GRANULARITY},
271    {( 8 * 8),      ACPI_RESTAG_MINADDR},
272    {(10 * 8),      ACPI_RESTAG_MAXADDR},
273    {(12 * 8),      ACPI_RESTAG_TRANSLATION},
274    {(14 * 8),      ACPI_RESTAG_LENGTH},
275    {0,             NULL}
276};
277
278static ACPI_RESOURCE_TAG        AcpiDmAddress32Tags[] =
279{
280    {( 4 * 8) + 1,  ACPI_RESTAG_DECODE},
281    {( 4 * 8) + 2,  ACPI_RESTAG_MINTYPE},
282    {( 4 * 8) + 3,  ACPI_RESTAG_MAXTYPE},
283    {( 6 * 8),      ACPI_RESTAG_GRANULARITY},
284    {(10 * 8),      ACPI_RESTAG_MINADDR},
285    {(14 * 8),      ACPI_RESTAG_MAXADDR},
286    {(18 * 8),      ACPI_RESTAG_TRANSLATION},
287    {(22 * 8),      ACPI_RESTAG_LENGTH},
288    {0,             NULL}
289};
290
291static ACPI_RESOURCE_TAG        AcpiDmAddress64Tags[] =
292{
293    {( 4 * 8) + 1,  ACPI_RESTAG_DECODE},
294    {( 4 * 8) + 2,  ACPI_RESTAG_MINTYPE},
295    {( 4 * 8) + 3,  ACPI_RESTAG_MAXTYPE},
296    {( 6 * 8),      ACPI_RESTAG_GRANULARITY},
297    {(14 * 8),      ACPI_RESTAG_MINADDR},
298    {(22 * 8),      ACPI_RESTAG_MAXADDR},
299    {(30 * 8),      ACPI_RESTAG_TRANSLATION},
300    {(38 * 8),      ACPI_RESTAG_LENGTH},
301    {0,             NULL}
302};
303
304static ACPI_RESOURCE_TAG        AcpiDmExtendedAddressTags[] =
305{
306    {( 4 * 8) + 1,  ACPI_RESTAG_DECODE},
307    {( 4 * 8) + 2,  ACPI_RESTAG_MINTYPE},
308    {( 4 * 8) + 3,  ACPI_RESTAG_MAXTYPE},
309    {( 8 * 8),      ACPI_RESTAG_GRANULARITY},
310    {(16 * 8),      ACPI_RESTAG_MINADDR},
311    {(24 * 8),      ACPI_RESTAG_MAXADDR},
312    {(32 * 8),      ACPI_RESTAG_TRANSLATION},
313    {(40 * 8),      ACPI_RESTAG_LENGTH},
314    {(48 * 8),      ACPI_RESTAG_TYPESPECIFICATTRIBUTES},
315    {0,             NULL}
316};
317
318/* Special-case tables for the type-specific flags */
319
320static ACPI_RESOURCE_TAG        AcpiDmMemoryFlagTags[] =
321{
322    {( 5 * 8) + 0,  ACPI_RESTAG_READWRITETYPE},
323    {( 5 * 8) + 1,  ACPI_RESTAG_MEMTYPE},
324    {( 5 * 8) + 3,  ACPI_RESTAG_MEMATTRIBUTES},
325    {( 5 * 8) + 5,  ACPI_RESTAG_TYPE},
326    {0,             NULL}
327};
328
329static ACPI_RESOURCE_TAG        AcpiDmIoFlagTags[] =
330{
331    {( 5 * 8) + 0,  ACPI_RESTAG_RANGETYPE},
332    {( 5 * 8) + 4,  ACPI_RESTAG_TYPE},
333    {( 5 * 8) + 5,  ACPI_RESTAG_TRANSTYPE},
334    {0,             NULL}
335};
336
337
338/* Dispatch table used to obtain the correct tag table for a descriptor */
339
340static ACPI_RESOURCE_TAG        *AcpiGbl_ResourceTags [] =
341{
342    /* Small descriptors */
343
344    NULL,                           /* 0x00, Reserved */
345    NULL,                           /* 0x01, Reserved */
346    NULL,                           /* 0x02, Reserved */
347    NULL,                           /* 0x03, Reserved */
348    AcpiDmIrqTags,                  /* 0x04, ACPI_RESOURCE_NAME_IRQ_FORMAT */
349    AcpiDmDmaTags,                  /* 0x05, ACPI_RESOURCE_NAME_DMA_FORMAT */
350    NULL,                           /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */
351    NULL,                           /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */
352    AcpiDmIoTags,                   /* 0x08, ACPI_RESOURCE_NAME_IO_PORT */
353    AcpiDmFixedIoTags,              /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO_PORT */
354    NULL,                           /* 0x0A, Reserved */
355    NULL,                           /* 0x0B, Reserved */
356    NULL,                           /* 0x0C, Reserved */
357    NULL,                           /* 0x0D, Reserved */
358    NULL,                           /* 0x0E, ACPI_RESOURCE_NAME_SMALL_VENDOR */
359    NULL,                           /* 0x0F, ACPI_RESOURCE_NAME_END_TAG (not used) */
360
361    /* Large descriptors */
362
363    NULL,                           /* 0x00, Reserved */
364    AcpiDmMemory24Tags,             /* 0x01, ACPI_RESOURCE_NAME_MEMORY_24 */
365    AcpiDmRegisterTags,             /* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */
366    NULL,                           /* 0x03, Reserved */
367    NULL,                           /* 0x04, ACPI_RESOURCE_NAME_LARGE_VENDOR */
368    AcpiDmMemory32Tags,             /* 0x05, ACPI_RESOURCE_NAME_MEMORY_32 */
369    AcpiDmFixedMemory32Tags,        /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY_32 */
370    AcpiDmAddress32Tags,            /* 0x07, ACPI_RESOURCE_NAME_DWORD_ADDRESS_SPACE */
371    AcpiDmAddress16Tags,            /* 0x08, ACPI_RESOURCE_NAME_WORD_ADDRESS_SPACE */
372    AcpiDmInterruptTags,            /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_XRUPT */
373    AcpiDmAddress64Tags,            /* 0x0A, ACPI_RESOURCE_NAME_QWORD_ADDRESS_SPACE */
374    AcpiDmExtendedAddressTags       /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS_SPACE */
375};
376
377
378/*
379 * Globals used to generate unique resource descriptor names. We use names that
380 * start with underscore and a prefix letter that is not used by other ACPI
381 * reserved names. To this, we append hex 0x00 through 0xFF. These 5 prefixes
382 * allow for 5*256 = 1280 unique names, probably sufficient for any single ASL
383 * file. If this becomes too small, we can use alpha+numerals for a total
384 * of 5*36*36 = 6480.
385 */
386#define ACPI_NUM_RES_PREFIX     5
387
388static UINT32                   AcpiGbl_NextResourceId = 0;
389static UINT8                    AcpiGbl_NextPrefix = 0;
390static UINT8                    AcpiGbl_Prefix[ACPI_NUM_RES_PREFIX] =
391                                    {'Y','Z','J','K','X'};
392
393
394/*******************************************************************************
395 *
396 * FUNCTION:    AcpiDmCheckResourceReference
397 *
398 * PARAMETERS:  Op                  - Parse Op for the AML opcode
399 *              WalkState           - Current walk state (with valid scope)
400 *
401 * RETURN:      None
402 *
403 * DESCRIPTION: Convert a reference to a resource descriptor to a symbolic
404 *              reference if possible
405 *
406 * NOTE:        Bit index is used to transparently handle both resource bit
407 *              fields and byte fields.
408 *
409 ******************************************************************************/
410
411void
412AcpiDmCheckResourceReference (
413    ACPI_PARSE_OBJECT       *Op,
414    ACPI_WALK_STATE         *WalkState)
415{
416    ACPI_STATUS             Status;
417    ACPI_PARSE_OBJECT       *BufferNameOp;
418    ACPI_PARSE_OBJECT       *IndexOp;
419    ACPI_NAMESPACE_NODE     *BufferNode;
420    ACPI_NAMESPACE_NODE     *ResourceNode;
421    const ACPI_OPCODE_INFO  *OpInfo;
422    char                    *Pathname;
423    UINT32                  BitIndex;
424
425
426    /* We are only interested in the CreateXxxxField opcodes */
427
428    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
429    if (OpInfo->Type != AML_TYPE_CREATE_FIELD)
430    {
431        return;
432    }
433
434    /* Get the buffer term operand */
435
436    BufferNameOp = AcpiPsGetDepthNext (NULL, Op);
437
438    /* Must be a named buffer, not an arg or local or method call */
439
440    if (BufferNameOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
441    {
442        return;
443    }
444
445    /* Get the Index term, must be an integer constant to convert */
446
447    IndexOp = BufferNameOp->Common.Next;
448    OpInfo = AcpiPsGetOpcodeInfo (IndexOp->Common.AmlOpcode);
449    if (OpInfo->ObjectType != ACPI_TYPE_INTEGER)
450    {
451        return;
452    }
453
454    /* Get the bit offset of the descriptor within the buffer */
455
456    if ((Op->Common.AmlOpcode == AML_CREATE_BIT_FIELD_OP) ||
457        (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP))
458    {
459        /* Index operand is a bit offset */
460
461        BitIndex = (UINT32) IndexOp->Common.Value.Integer;
462    }
463    else
464    {
465        /* Index operand is a byte offset, convert to bits */
466
467        BitIndex = (UINT32) ACPI_MUL_8 (IndexOp->Common.Value.Integer);
468    }
469
470    /* Lookup the buffer in the namespace */
471
472    Status = AcpiNsLookup (WalkState->ScopeInfo,
473                BufferNameOp->Common.Value.String, ACPI_TYPE_BUFFER,
474                ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState,
475                &BufferNode);
476    if (ACPI_FAILURE (Status))
477    {
478        return;
479    }
480
481    /* Validate object type, we must have a buffer */
482
483    if (BufferNode->Type != ACPI_TYPE_BUFFER)
484    {
485        return;
486    }
487
488    /* Find the resource descriptor node corresponding to the index */
489
490    ResourceNode = AcpiDmGetResourceNode (BufferNode, BitIndex);
491    if (!ResourceNode)
492    {
493        return;
494    }
495
496    /* Translate the Index to a resource tag pathname */
497
498    Pathname = AcpiGetTagPathname (BufferNode, ResourceNode, BitIndex);
499    if (Pathname)
500    {
501        /* Complete the conversion of the Index to a symbol */
502
503        IndexOp->Common.AmlOpcode = AML_INT_NAMEPATH_OP;
504        IndexOp->Common.Value.String = Pathname;
505    }
506}
507
508
509/*******************************************************************************
510 *
511 * FUNCTION:    AcpiDmGetResourceNode
512 *
513 * PARAMETERS:  BufferNode          - Node for the parent buffer
514 *              BitIndex            - Index into the resource descriptor
515 *
516 * RETURN:      Namespace node for the resource descriptor. NULL if not found
517 *
518 * DESCRIPTION: Find a resource descriptor that corresponds to the bit index
519 *
520 ******************************************************************************/
521
522static ACPI_NAMESPACE_NODE *
523AcpiDmGetResourceNode (
524    ACPI_NAMESPACE_NODE     *BufferNode,
525    UINT32                  BitIndex)
526{
527    ACPI_NAMESPACE_NODE     *Node;
528    UINT32                  ByteIndex = ACPI_DIV_8 (BitIndex);
529
530
531    /*
532     * Child list contains an entry for each resource descriptor. Find
533     * the descriptor that corresponds to the Index.
534     *
535     * If there are no children, this is not a resource template
536     */
537    Node = BufferNode->Child;
538    while (Node)
539    {
540        /*
541         * Check if the Index falls within this resource.
542         *
543         * Value contains the resource offset, Object contains the resource
544         * length (both in bytes)
545         */
546        if ((ByteIndex >= Node->Value) &&
547            (ByteIndex < (Node->Value + Node->Length)))
548        {
549            return (Node);
550        }
551
552        /* List is circular, this flag marks the end */
553
554        if (Node->Flags & ANOBJ_END_OF_PEER_LIST)
555        {
556            return (NULL);
557        }
558
559        Node = Node->Peer;
560    }
561
562    return (NULL);
563}
564
565
566/*******************************************************************************
567 *
568 * FUNCTION:    AcpiGetTagPathname
569 *
570 * PARAMETERS:  BufferNode          - Node for the parent buffer
571 *              ResourceNode        - Node for a resource descriptor
572 *              BitIndex            - Index into the resource descriptor
573 *
574 * RETURN:      Full pathname for a resource tag. NULL if no match.
575 *              Path is returned in AML (packed) format.
576 *
577 * DESCRIPTION: Convert a BitIndex into a symbolic resource tag (full pathname)
578 *
579 ******************************************************************************/
580
581static char *
582AcpiGetTagPathname (
583    ACPI_NAMESPACE_NODE     *BufferNode,
584    ACPI_NAMESPACE_NODE     *ResourceNode,
585    UINT32                  BitIndex)
586{
587    ACPI_STATUS             Status;
588    UINT32                  ResourceBitIndex;
589    UINT8                   ResourceTableIndex;
590    ACPI_SIZE               RequiredSize;
591    char                    *Pathname;
592    AML_RESOURCE            *Aml;
593    ACPI_PARSE_OBJECT       *Op;
594    char                    *InternalPath;
595    char                    *Tag;
596
597
598    /* Get the Op that contains the actual buffer data */
599
600    Op = BufferNode->Op->Common.Value.Arg;
601    Op = Op->Common.Next;
602    if (!Op)
603    {
604        return (NULL);
605    }
606
607    /* Get the individual resource descriptor and validate it */
608
609    Aml = ACPI_CAST_PTR (AML_RESOURCE,
610            &Op->Named.Data[ResourceNode->Value]);
611
612    Status = AcpiUtValidateResource (Aml, &ResourceTableIndex);
613    if (ACPI_FAILURE (Status))
614    {
615        return (NULL);
616    }
617
618    /* Get offset into this descriptor (from offset into entire buffer) */
619
620    ResourceBitIndex = BitIndex - ACPI_MUL_8 (ResourceNode->Value);
621
622    /* Get the tag associated with this resource descriptor and offset */
623
624    Tag = AcpiDmGetResourceTag (ResourceBitIndex, Aml, ResourceTableIndex);
625    if (!Tag)
626    {
627        return (NULL);
628    }
629
630    /*
631     * Now that we know that we have a reference that can be converted to a
632     * symbol, change the name of the resource to a unique name.
633     */
634    AcpiDmUpdateResourceName (ResourceNode);
635
636    /* Get the full pathname to the parent buffer */
637
638    RequiredSize = AcpiNsGetPathnameLength (BufferNode);
639    if (!RequiredSize)
640    {
641        return (NULL);
642    }
643
644    Pathname = ACPI_ALLOCATE_ZEROED (RequiredSize + ACPI_PATH_SEGMENT_LENGTH);
645    if (!Pathname)
646    {
647        return (NULL);
648    }
649
650    Status = AcpiNsBuildExternalPath (BufferNode, RequiredSize, Pathname);
651    if (ACPI_FAILURE (Status))
652    {
653        return (NULL);
654    }
655
656    /*
657     * Create the full path to the resource and tag by: remove the buffer name,
658     * append the resource descriptor name, append a dot, append the tag name.
659     *
660     * TBD: Always using the full path is a bit brute force, the path can be
661     * often be optimized with carats (if the original buffer namepath is a
662     * single nameseg). This doesn't really matter, because these paths do not
663     * end up in the final compiled AML, it's just an appearance issue for the
664     * disassembled code.
665     */
666    Pathname[ACPI_STRLEN (Pathname) - ACPI_NAME_SIZE] = 0;
667    ACPI_STRNCAT (Pathname, ResourceNode->Name.Ascii, ACPI_NAME_SIZE);
668    ACPI_STRCAT (Pathname, ".");
669    ACPI_STRNCAT (Pathname, Tag, ACPI_NAME_SIZE);
670
671    /* Internalize the namepath to AML format */
672
673    AcpiNsInternalizeName (Pathname, &InternalPath);
674    ACPI_FREE (Pathname);
675    return (InternalPath);
676}
677
678
679/*******************************************************************************
680 *
681 * FUNCTION:    AcpiDmUpdateResourceName
682 *
683 * PARAMETERS:  ResourceNode        - Node for a resource descriptor
684 *
685 * RETURN:      Stores new name in the ResourceNode
686 *
687 * DESCRIPTION: Create a new, unique name for a resource descriptor. Used by
688 *              both the disassembly of the descriptor itself and any symbolic
689 *              references to the descriptor. Ignored if a unique name has
690 *              already been assigned to the resource.
691 *
692 * NOTE: Single threaded, suitable for applications only!
693 *
694 ******************************************************************************/
695
696static void
697AcpiDmUpdateResourceName (
698    ACPI_NAMESPACE_NODE     *ResourceNode)
699{
700    char                    Name[ACPI_NAME_SIZE];
701
702
703    /* Ignore if a unique name has already been assigned */
704
705    if (ResourceNode->Name.Integer != ACPI_DEFAULT_RESNAME)
706    {
707        return;
708    }
709
710    /* Generate a new ACPI name for the descriptor */
711
712    Name[0] = '_';
713    Name[1] = AcpiGbl_Prefix[AcpiGbl_NextPrefix];
714    Name[2] = AcpiUtHexToAsciiChar (AcpiGbl_NextResourceId, 4);
715    Name[3] = AcpiUtHexToAsciiChar (AcpiGbl_NextResourceId, 0);
716
717    /* Update globals for next name */
718
719    AcpiGbl_NextResourceId++;
720    if (AcpiGbl_NextResourceId >= 256)
721    {
722        AcpiGbl_NextResourceId = 0;
723        AcpiGbl_NextPrefix++;
724        if (AcpiGbl_NextPrefix > ACPI_NUM_RES_PREFIX)
725        {
726            AcpiGbl_NextPrefix = 0;
727        }
728    }
729
730    /* Change the resource descriptor name */
731
732    ResourceNode->Name.Integer = *ACPI_CAST_PTR (UINT32, &Name[0]);
733}
734
735
736/*******************************************************************************
737 *
738 * FUNCTION:    AcpiDmGetResourceTag
739 *
740 * PARAMETERS:  BitIndex            - Index into the resource descriptor
741 *              Resource            - Pointer to the raw resource data
742 *              ResourceIndex       - Index correspoinding to the resource type
743 *
744 * RETURN:      Pointer to the resource tag (ACPI_NAME). NULL if no match.
745 *
746 * DESCRIPTION: Convert a BitIndex into a symbolic resource tag.
747 *
748 ******************************************************************************/
749
750static char *
751AcpiDmGetResourceTag (
752    UINT32                  BitIndex,
753    AML_RESOURCE            *Resource,
754    UINT8                   ResourceIndex)
755{
756    ACPI_RESOURCE_TAG       *TagList;
757    char                    *Tag = NULL;
758
759
760    /* Get the tag list for this resource descriptor type */
761
762    TagList = AcpiGbl_ResourceTags[ResourceIndex];
763    if (!TagList)
764    {
765        /* There are no tags for this resource type */
766
767        return (NULL);
768    }
769
770    /*
771     * Handle the type-specific flags field for the address descriptors.
772     * Kindof brute force, but just blindly search for an index match.
773     */
774    switch (Resource->DescriptorType)
775    {
776    case ACPI_RESOURCE_NAME_ADDRESS16:
777    case ACPI_RESOURCE_NAME_ADDRESS32:
778    case ACPI_RESOURCE_NAME_ADDRESS64:
779    case ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64:
780
781        if (Resource->Address.ResourceType == ACPI_ADDRESS_TYPE_MEMORY_RANGE)
782        {
783            Tag = AcpiDmSearchTagList (BitIndex, AcpiDmMemoryFlagTags);
784        }
785        else if (Resource->Address.ResourceType == ACPI_ADDRESS_TYPE_IO_RANGE)
786        {
787            Tag = AcpiDmSearchTagList (BitIndex, AcpiDmIoFlagTags);
788        }
789
790        /* If we found a match, all done. Else, drop to normal search below */
791
792        if (Tag)
793        {
794            return (Tag);
795        }
796        break;
797
798    default:
799        break;
800    }
801
802    /* Search the tag list for this descriptor type */
803
804    Tag = AcpiDmSearchTagList (BitIndex, TagList);
805    return (Tag);
806}
807
808
809/*******************************************************************************
810 *
811 * FUNCTION:    AcpiDmSearchTagList
812 *
813 * PARAMETERS:  BitIndex            - Index into the resource descriptor
814 *              TagList             - List to search
815 *
816 * RETURN:      Pointer to a tag (ACPI_NAME). NULL if no match found.
817 *
818 * DESCRIPTION: Search a tag list for a match to the input BitIndex. Matches
819 *              a fixed offset to a symbolic resource tag name.
820 *
821 ******************************************************************************/
822
823static char *
824AcpiDmSearchTagList (
825    UINT32                  BitIndex,
826    ACPI_RESOURCE_TAG       *TagList)
827{
828
829    /*
830     * Walk the null-terminated tag list to find a matching bit offset.
831     * We are looking for an exact match.
832     */
833    for ( ; TagList->Tag; TagList++)
834    {
835        if (BitIndex == TagList->BitIndex)
836        {
837            return (TagList->Tag);
838        }
839    }
840
841    /* A matching offset was not found */
842
843    return (NULL);
844}
845
846
847/*******************************************************************************
848 *
849 * FUNCTION:    AcpiDmFindResources
850 *
851 * PARAMETERS:  Root                - Root of the parse tree
852 *
853 * RETURN:      None
854 *
855 * DESCRIPTION: Add all ResourceTemplate declarations to the namespace. Each
856 *              resource descriptor in each template is given a node -- used
857 *              for later conversion of resource references to symbolic refs.
858 *
859 ******************************************************************************/
860
861void
862AcpiDmFindResources (
863    ACPI_PARSE_OBJECT       *Root)
864{
865    ACPI_PARSE_OBJECT       *Op = Root;
866    ACPI_PARSE_OBJECT       *Parent;
867
868
869    /* Walk the entire parse tree */
870
871    while (Op)
872    {
873        /* We are interested in Buffer() declarations */
874
875        if (Op->Common.AmlOpcode == AML_BUFFER_OP)
876        {
877            /* And only declarations of the form Name (XXXX, Buffer()... ) */
878
879            Parent = Op->Common.Parent;
880            if (Parent->Common.AmlOpcode == AML_NAME_OP)
881            {
882                /*
883                 * If the buffer is a resource template, add the individual
884                 * resource descriptors to the namespace, as children of the
885                 * buffer node.
886                 */
887                if (ACPI_SUCCESS (AcpiDmIsResourceTemplate (Op)))
888                {
889                    Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
890                    AcpiDmAddResourcesToNamespace (Parent->Common.Node, Op);
891                }
892            }
893        }
894
895        Op = AcpiPsGetDepthNext (Root, Op);
896    }
897}
898
899
900/*******************************************************************************
901 *
902 * FUNCTION:    AcpiDmAddResourcesToNamespace
903 *
904 * PARAMETERS:  BufferNode          - Node for the parent buffer
905 *              Op                  - Parse op for the buffer
906 *
907 * RETURN:      None
908 *
909 * DESCRIPTION: Add an entire resource template to the namespace. Each
910 *              resource descriptor is added as a namespace node.
911 *
912 ******************************************************************************/
913
914static void
915AcpiDmAddResourcesToNamespace (
916    ACPI_NAMESPACE_NODE     *BufferNode,
917    ACPI_PARSE_OBJECT       *Op)
918{
919    ACPI_PARSE_OBJECT       *NextOp;
920
921
922    /* Get to the ByteData list */
923
924    NextOp = Op->Common.Value.Arg;
925    NextOp = NextOp->Common.Next;
926    if (!NextOp)
927    {
928        return;
929    }
930
931    /* Set Node and Op to point to each other */
932
933    BufferNode->Op = Op;
934    Op->Common.Node = BufferNode;
935
936    /*
937     * Insert each resource into the namespace
938     * NextOp contains the Aml pointer and the Aml length
939     */
940    AcpiUtWalkAmlResources ((UINT8 *) NextOp->Named.Data,
941        (ACPI_SIZE) NextOp->Common.Value.Integer,
942        AcpiDmAddResourceToNamespace, BufferNode);
943}
944
945
946/*******************************************************************************
947 *
948 * FUNCTION:    AcpiDmAddResourceToNamespace
949 *
950 * PARAMETERS:  ACPI_WALK_AML_CALLBACK
951 *              BufferNode              - Node for the parent buffer
952 *
953 * RETURN:      Status
954 *
955 * DESCRIPTION: Add one resource descriptor to the namespace as a child of the
956 *              parent buffer. The same name is used for each descriptor. This
957 *              is changed later to a unique name if the resource is actually
958 *              referenced by an AML operator.
959 *
960 ******************************************************************************/
961
962static ACPI_STATUS
963AcpiDmAddResourceToNamespace (
964    UINT8                   *Aml,
965    UINT32                  Length,
966    UINT32                  Offset,
967    UINT8                   ResourceIndex,
968    void                    *Context)
969{
970    ACPI_STATUS             Status;
971    ACPI_GENERIC_STATE      ScopeInfo;
972    ACPI_NAMESPACE_NODE     *Node;
973
974
975    /* TBD: Don't need to add descriptors that have no tags defined? */
976
977    /* Add the resource to the namespace, as child of the buffer */
978
979    ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Context);
980    Status = AcpiNsLookup (&ScopeInfo, "_TMP", ACPI_TYPE_LOCAL_RESOURCE,
981                ACPI_IMODE_LOAD_PASS2,
982                ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_PREFIX_IS_SCOPE,
983                NULL, &Node);
984    if (ACPI_FAILURE (Status))
985    {
986        return (AE_OK);
987    }
988
989    /* Set the name to the default, changed later if resource is referenced */
990
991    Node->Name.Integer = ACPI_DEFAULT_RESNAME;
992
993    /* Save the offset of the descriptor (within the original buffer) */
994
995    Node->Value = Offset;
996    Node->Length = Length;
997    return (AE_OK);
998}
999
1000