dmrestag.c revision 252279
1/******************************************************************************
2 *
3 * Module Name: dmrestag - Add tags to resource descriptors (Application-level)
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <contrib/dev/acpica/include/acpi.h>
46#include <contrib/dev/acpica/include/accommon.h>
47#include <contrib/dev/acpica/include/acparser.h>
48#include <contrib/dev/acpica/include/acdisasm.h>
49#include <contrib/dev/acpica/include/acnamesp.h>
50#include <contrib/dev/acpica/include/amlcode.h>
51
52/* This module used for application-level code only */
53
54#define _COMPONENT          ACPI_CA_DISASSEMBLER
55        ACPI_MODULE_NAME    ("dmrestag")
56
57/* Local prototypes */
58
59static void
60AcpiDmUpdateResourceName (
61    ACPI_NAMESPACE_NODE     *ResourceNode);
62
63static char *
64AcpiDmSearchTagList (
65    UINT32                  BitIndex,
66    const ACPI_RESOURCE_TAG *TagList);
67
68static char *
69AcpiDmGetResourceTag (
70    UINT32                  BitIndex,
71    AML_RESOURCE            *Resource,
72    UINT8                   ResourceIndex);
73
74static char *
75AcpiGetTagPathname (
76    ACPI_PARSE_OBJECT       *Op,
77    ACPI_NAMESPACE_NODE     *BufferNode,
78    ACPI_NAMESPACE_NODE     *ResourceNode,
79    UINT32                  BitIndex);
80
81static ACPI_NAMESPACE_NODE *
82AcpiDmGetResourceNode (
83    ACPI_NAMESPACE_NODE     *BufferNode,
84    UINT32                  BitIndex);
85
86static ACPI_STATUS
87AcpiDmAddResourceToNamespace (
88    UINT8                   *Aml,
89    UINT32                  Length,
90    UINT32                  Offset,
91    UINT8                   ResourceIndex,
92    void                    **Context);
93
94static void
95AcpiDmAddResourcesToNamespace (
96    ACPI_NAMESPACE_NODE     *BufferNode,
97    ACPI_PARSE_OBJECT       *Op);
98
99
100/******************************************************************************
101 *
102 * Resource Tag tables
103 *
104 * These are the predefined tags that refer to elements of a resource
105 * descriptor. Each name and offset is defined in the ACPI specification.
106 *
107 * Each table entry contains the bit offset of the field and the associated
108 * name.
109 *
110 ******************************************************************************/
111
112static const ACPI_RESOURCE_TAG      AcpiDmIrqTags[] =
113{
114    {( 1 * 8),      ACPI_RESTAG_INTERRUPT},
115    {( 3 * 8) + 0,  ACPI_RESTAG_INTERRUPTTYPE},
116    {( 3 * 8) + 3,  ACPI_RESTAG_INTERRUPTLEVEL},
117    {( 3 * 8) + 4,  ACPI_RESTAG_INTERRUPTSHARE},
118    {0,             NULL}
119};
120
121static const ACPI_RESOURCE_TAG      AcpiDmDmaTags[] =
122{
123    {( 1 * 8),      ACPI_RESTAG_DMA},
124    {( 2 * 8) + 0,  ACPI_RESTAG_XFERTYPE},
125    {( 2 * 8) + 2,  ACPI_RESTAG_BUSMASTER},
126    {( 2 * 8) + 5,  ACPI_RESTAG_DMATYPE},
127    {0,             NULL}
128};
129
130static const ACPI_RESOURCE_TAG      AcpiDmIoTags[] =
131{
132    {( 1 * 8) + 0,  ACPI_RESTAG_DECODE},
133    {( 2 * 8),      ACPI_RESTAG_MINADDR},
134    {( 4 * 8),      ACPI_RESTAG_MAXADDR},
135    {( 6 * 8),      ACPI_RESTAG_ALIGNMENT},
136    {( 7 * 8),      ACPI_RESTAG_LENGTH},
137    {0,             NULL}
138};
139
140static const ACPI_RESOURCE_TAG      AcpiDmFixedIoTags[] =
141{
142    {( 1 * 8),      ACPI_RESTAG_BASEADDRESS},
143    {( 3 * 8),      ACPI_RESTAG_LENGTH},
144    {0,             NULL}
145};
146
147static const ACPI_RESOURCE_TAG      AcpiDmFixedDmaTags[] =
148{
149    {( 1 * 8),      ACPI_RESTAG_DMA},
150    {( 3 * 8),      ACPI_RESTAG_DMATYPE},
151    {( 5 * 8),      ACPI_RESTAG_XFERTYPE},
152    {0,             NULL}
153};
154
155static const ACPI_RESOURCE_TAG      AcpiDmMemory24Tags[] =
156{
157    {( 3 * 8) + 0,  ACPI_RESTAG_READWRITETYPE},
158    {( 4 * 8),      ACPI_RESTAG_MINADDR},
159    {( 6 * 8),      ACPI_RESTAG_MAXADDR},
160    {( 8 * 8),      ACPI_RESTAG_ALIGNMENT},
161    {(10 * 8),      ACPI_RESTAG_LENGTH},
162    {0,             NULL}
163};
164
165static const ACPI_RESOURCE_TAG      AcpiDmRegisterTags[] =
166{
167    {( 3 * 8),      ACPI_RESTAG_ADDRESSSPACE},
168    {( 4 * 8),      ACPI_RESTAG_REGISTERBITWIDTH},
169    {( 5 * 8),      ACPI_RESTAG_REGISTERBITOFFSET},
170    {( 6 * 8),      ACPI_RESTAG_ACCESSSIZE},
171    {( 7 * 8),      ACPI_RESTAG_ADDRESS},
172    {0,             NULL}
173};
174
175static const ACPI_RESOURCE_TAG      AcpiDmMemory32Tags[] =
176{
177    {( 3 * 8) + 0,  ACPI_RESTAG_READWRITETYPE},
178    {( 4 * 8),      ACPI_RESTAG_MINADDR},
179    {( 8 * 8),      ACPI_RESTAG_MAXADDR},
180    {(12 * 8),      ACPI_RESTAG_ALIGNMENT},
181    {(16 * 8),      ACPI_RESTAG_LENGTH},
182    {0,             NULL}
183};
184
185static const ACPI_RESOURCE_TAG      AcpiDmFixedMemory32Tags[] =
186{
187    {( 3 * 8) + 0,  ACPI_RESTAG_READWRITETYPE},
188    {( 4 * 8),      ACPI_RESTAG_BASEADDRESS},
189    {( 8 * 8),      ACPI_RESTAG_LENGTH},
190    {0,             NULL}
191};
192
193static const ACPI_RESOURCE_TAG      AcpiDmInterruptTags[] =
194{
195    {( 3 * 8) + 1,  ACPI_RESTAG_INTERRUPTTYPE},
196    {( 3 * 8) + 2,  ACPI_RESTAG_INTERRUPTLEVEL},
197    {( 3 * 8) + 3,  ACPI_RESTAG_INTERRUPTSHARE},
198    {( 5 * 8),      ACPI_RESTAG_INTERRUPT},
199    {0,             NULL}
200};
201
202static const ACPI_RESOURCE_TAG      AcpiDmAddress16Tags[] =
203{
204    {( 4 * 8) + 1,  ACPI_RESTAG_DECODE},
205    {( 4 * 8) + 2,  ACPI_RESTAG_MINTYPE},
206    {( 4 * 8) + 3,  ACPI_RESTAG_MAXTYPE},
207    {( 6 * 8),      ACPI_RESTAG_GRANULARITY},
208    {( 8 * 8),      ACPI_RESTAG_MINADDR},
209    {(10 * 8),      ACPI_RESTAG_MAXADDR},
210    {(12 * 8),      ACPI_RESTAG_TRANSLATION},
211    {(14 * 8),      ACPI_RESTAG_LENGTH},
212    {0,             NULL}
213};
214
215static const ACPI_RESOURCE_TAG      AcpiDmAddress32Tags[] =
216{
217    {( 4 * 8) + 1,  ACPI_RESTAG_DECODE},
218    {( 4 * 8) + 2,  ACPI_RESTAG_MINTYPE},
219    {( 4 * 8) + 3,  ACPI_RESTAG_MAXTYPE},
220    {( 6 * 8),      ACPI_RESTAG_GRANULARITY},
221    {(10 * 8),      ACPI_RESTAG_MINADDR},
222    {(14 * 8),      ACPI_RESTAG_MAXADDR},
223    {(18 * 8),      ACPI_RESTAG_TRANSLATION},
224    {(22 * 8),      ACPI_RESTAG_LENGTH},
225    {0,             NULL}
226};
227
228static const ACPI_RESOURCE_TAG      AcpiDmAddress64Tags[] =
229{
230    {( 4 * 8) + 1,  ACPI_RESTAG_DECODE},
231    {( 4 * 8) + 2,  ACPI_RESTAG_MINTYPE},
232    {( 4 * 8) + 3,  ACPI_RESTAG_MAXTYPE},
233    {( 6 * 8),      ACPI_RESTAG_GRANULARITY},
234    {(14 * 8),      ACPI_RESTAG_MINADDR},
235    {(22 * 8),      ACPI_RESTAG_MAXADDR},
236    {(30 * 8),      ACPI_RESTAG_TRANSLATION},
237    {(38 * 8),      ACPI_RESTAG_LENGTH},
238    {0,             NULL}
239};
240
241static const ACPI_RESOURCE_TAG      AcpiDmExtendedAddressTags[] =
242{
243    {( 4 * 8) + 1,  ACPI_RESTAG_DECODE},
244    {( 4 * 8) + 2,  ACPI_RESTAG_MINTYPE},
245    {( 4 * 8) + 3,  ACPI_RESTAG_MAXTYPE},
246    {( 8 * 8),      ACPI_RESTAG_GRANULARITY},
247    {(16 * 8),      ACPI_RESTAG_MINADDR},
248    {(24 * 8),      ACPI_RESTAG_MAXADDR},
249    {(32 * 8),      ACPI_RESTAG_TRANSLATION},
250    {(40 * 8),      ACPI_RESTAG_LENGTH},
251    {(48 * 8),      ACPI_RESTAG_TYPESPECIFICATTRIBUTES},
252    {0,             NULL}
253};
254
255/* Subtype tables for GPIO descriptors */
256
257static const ACPI_RESOURCE_TAG      AcpiDmGpioIntTags[] =
258{
259    {( 7 * 8) + 0,  ACPI_RESTAG_MODE},
260    {( 7 * 8) + 1,  ACPI_RESTAG_POLARITY},
261    {( 7 * 8) + 3,  ACPI_RESTAG_INTERRUPTSHARE},
262    {( 9 * 8),      ACPI_RESTAG_PINCONFIG},
263    {(10 * 8),      ACPI_RESTAG_DRIVESTRENGTH},
264    {(12 * 8),      ACPI_RESTAG_DEBOUNCETIME},
265    {0,             NULL}
266};
267
268static const ACPI_RESOURCE_TAG      AcpiDmGpioIoTags[] =
269{
270    {( 7 * 8) + 0,  ACPI_RESTAG_IORESTRICTION},
271    {( 7 * 8) + 3,  ACPI_RESTAG_INTERRUPTSHARE},
272    {( 9 * 8),      ACPI_RESTAG_PINCONFIG},
273    {(10 * 8),      ACPI_RESTAG_DRIVESTRENGTH},
274    {(12 * 8),      ACPI_RESTAG_DEBOUNCETIME},
275    {0,             NULL}
276};
277
278/* Subtype tables for SerialBus descriptors */
279
280static const ACPI_RESOURCE_TAG      AcpiDmI2cSerialBusTags[] =
281{
282    {( 6 * 8) + 0,  ACPI_RESTAG_SLAVEMODE},
283    {( 7 * 8) + 0,  ACPI_RESTAG_MODE},
284    {(12 * 8),      ACPI_RESTAG_SPEED},
285    {(16 * 8),      ACPI_RESTAG_ADDRESS},
286    {0,             NULL}
287};
288
289static const ACPI_RESOURCE_TAG      AcpiDmSpiSerialBusTags[] =
290{
291    {( 6 * 8) + 0,  ACPI_RESTAG_SLAVEMODE},
292    {( 7 * 8) + 0,  ACPI_RESTAG_MODE},
293    {( 7 * 8) + 1,  ACPI_RESTAG_DEVICEPOLARITY},
294    {(12 * 8),      ACPI_RESTAG_SPEED},
295    {(16 * 8),      ACPI_RESTAG_LENGTH},
296    {(17 * 8),      ACPI_RESTAG_PHASE},
297    {(18 * 8),      ACPI_RESTAG_POLARITY},
298    {(19 * 8),      ACPI_RESTAG_ADDRESS},
299    {0,             NULL}
300};
301
302static const ACPI_RESOURCE_TAG      AcpiDmUartSerialBusTags[] =
303{
304    {( 6 * 8) + 0,  ACPI_RESTAG_SLAVEMODE}, /* Note: not part of original macro */
305    {( 7 * 8) + 0,  ACPI_RESTAG_FLOWCONTROL},
306    {( 7 * 8) + 2,  ACPI_RESTAG_STOPBITS},
307    {( 7 * 8) + 4,  ACPI_RESTAG_LENGTH},
308    {( 7 * 8) + 7,  ACPI_RESTAG_ENDIANNESS},
309    {(12 * 8),      ACPI_RESTAG_SPEED},
310    {(16 * 8),      ACPI_RESTAG_LENGTH_RX},
311    {(18 * 8),      ACPI_RESTAG_LENGTH_TX},
312    {(20 * 8),      ACPI_RESTAG_PARITY},
313    {(21 * 8),      ACPI_RESTAG_LINE},
314    {0,             NULL}
315};
316
317/* Subtype tables for Address descriptor type-specific flags */
318
319static const ACPI_RESOURCE_TAG      AcpiDmMemoryFlagTags[] =
320{
321    {( 5 * 8) + 0,  ACPI_RESTAG_READWRITETYPE},
322    {( 5 * 8) + 1,  ACPI_RESTAG_MEMTYPE},
323    {( 5 * 8) + 3,  ACPI_RESTAG_MEMATTRIBUTES},
324    {( 5 * 8) + 5,  ACPI_RESTAG_TYPE},
325    {0,             NULL}
326};
327
328static const ACPI_RESOURCE_TAG      AcpiDmIoFlagTags[] =
329{
330    {( 5 * 8) + 0,  ACPI_RESTAG_RANGETYPE},
331    {( 5 * 8) + 4,  ACPI_RESTAG_TYPE},
332    {( 5 * 8) + 5,  ACPI_RESTAG_TRANSTYPE},
333    {0,             NULL}
334};
335
336
337/*
338 * Dispatch table used to obtain the correct tag table for a descriptor.
339 *
340 * A NULL in this table means one of three things:
341 * 1) The descriptor ID is reserved and invalid
342 * 2) The descriptor has no tags associated with it
343 * 3) The descriptor has subtypes and a separate table will be used.
344 */
345static const ACPI_RESOURCE_TAG      *AcpiGbl_ResourceTags[] =
346{
347    /* Small descriptors */
348
349    NULL,                           /* 0x00, Reserved */
350    NULL,                           /* 0x01, Reserved */
351    NULL,                           /* 0x02, Reserved */
352    NULL,                           /* 0x03, Reserved */
353    AcpiDmIrqTags,                  /* 0x04, ACPI_RESOURCE_NAME_IRQ_FORMAT */
354    AcpiDmDmaTags,                  /* 0x05, ACPI_RESOURCE_NAME_DMA_FORMAT */
355    NULL,                           /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */
356    NULL,                           /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */
357    AcpiDmIoTags,                   /* 0x08, ACPI_RESOURCE_NAME_IO_PORT */
358    AcpiDmFixedIoTags,              /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO_PORT */
359    AcpiDmFixedDmaTags,             /* 0x0A, ACPI_RESOURCE_NAME_FIXED_DMA */
360    NULL,                           /* 0x0B, Reserved */
361    NULL,                           /* 0x0C, Reserved */
362    NULL,                           /* 0x0D, Reserved */
363    NULL,                           /* 0x0E, ACPI_RESOURCE_NAME_SMALL_VENDOR */
364    NULL,                           /* 0x0F, ACPI_RESOURCE_NAME_END_TAG (not used) */
365
366    /* Large descriptors */
367
368    NULL,                           /* 0x00, Reserved */
369    AcpiDmMemory24Tags,             /* 0x01, ACPI_RESOURCE_NAME_MEMORY_24 */
370    AcpiDmRegisterTags,             /* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */
371    NULL,                           /* 0x03, Reserved */
372    NULL,                           /* 0x04, ACPI_RESOURCE_NAME_LARGE_VENDOR */
373    AcpiDmMemory32Tags,             /* 0x05, ACPI_RESOURCE_NAME_MEMORY_32 */
374    AcpiDmFixedMemory32Tags,        /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY_32 */
375    AcpiDmAddress32Tags,            /* 0x07, ACPI_RESOURCE_NAME_DWORD_ADDRESS_SPACE */
376    AcpiDmAddress16Tags,            /* 0x08, ACPI_RESOURCE_NAME_WORD_ADDRESS_SPACE */
377    AcpiDmInterruptTags,            /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_XRUPT */
378    AcpiDmAddress64Tags,            /* 0x0A, ACPI_RESOURCE_NAME_QWORD_ADDRESS_SPACE */
379    AcpiDmExtendedAddressTags,      /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS_SPACE */
380    NULL,                           /* 0x0C, ACPI_RESOURCE_NAME_GPIO - Use Subtype table below */
381    NULL,                           /* 0x0D, Reserved */
382    NULL                            /* 0x0E, ACPI_RESOURCE_NAME_SERIAL_BUS - Use Subtype table below */
383};
384
385/* GPIO Subtypes */
386
387static const ACPI_RESOURCE_TAG      *AcpiGbl_GpioResourceTags[] =
388{
389    AcpiDmGpioIntTags,              /* 0x00 Interrupt Connection */
390    AcpiDmGpioIoTags                /* 0x01 I/O Connection */
391};
392
393/* Serial Bus Subtypes */
394
395static const ACPI_RESOURCE_TAG      *AcpiGbl_SerialResourceTags[] =
396{
397    NULL,                           /* 0x00 Reserved */
398    AcpiDmI2cSerialBusTags,         /* 0x01 I2C SerialBus */
399    AcpiDmSpiSerialBusTags,         /* 0x02 SPI SerialBus */
400    AcpiDmUartSerialBusTags         /* 0x03 UART SerialBus */
401};
402
403/*
404 * Globals used to generate unique resource descriptor names. We use names that
405 * start with underscore and a prefix letter that is not used by other ACPI
406 * reserved names. To this, we append hex 0x00 through 0xFF. These 5 prefixes
407 * allow for 5*256 = 1280 unique names, probably sufficient for any single ASL
408 * file. If this becomes too small, we can use alpha+numerals for a total
409 * of 5*36*36 = 6480.
410 */
411#define ACPI_NUM_RES_PREFIX     5
412
413static UINT32                   AcpiGbl_NextResourceId = 0;
414static UINT8                    AcpiGbl_NextPrefix = 0;
415static char                     AcpiGbl_Prefix[ACPI_NUM_RES_PREFIX] =
416                                    {'Y','Z','J','K','X'};
417
418
419/*******************************************************************************
420 *
421 * FUNCTION:    AcpiDmCheckResourceReference
422 *
423 * PARAMETERS:  Op                  - Parse Op for the AML opcode
424 *              WalkState           - Current walk state (with valid scope)
425 *
426 * RETURN:      None
427 *
428 * DESCRIPTION: Convert a reference to a resource descriptor to a symbolic
429 *              reference if possible
430 *
431 * NOTE:        Bit index is used to transparently handle both resource bit
432 *              fields and byte fields.
433 *
434 ******************************************************************************/
435
436void
437AcpiDmCheckResourceReference (
438    ACPI_PARSE_OBJECT       *Op,
439    ACPI_WALK_STATE         *WalkState)
440{
441    ACPI_STATUS             Status;
442    ACPI_PARSE_OBJECT       *BufferNameOp;
443    ACPI_PARSE_OBJECT       *IndexOp;
444    ACPI_NAMESPACE_NODE     *BufferNode;
445    ACPI_NAMESPACE_NODE     *ResourceNode;
446    const ACPI_OPCODE_INFO  *OpInfo;
447    UINT32                  BitIndex;
448
449
450    /* We are only interested in the CreateXxxxField opcodes */
451
452    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
453    if (OpInfo->Type != AML_TYPE_CREATE_FIELD)
454    {
455        return;
456    }
457
458    /* Get the buffer term operand */
459
460    BufferNameOp = AcpiPsGetDepthNext (NULL, Op);
461
462    /* Must be a named buffer, not an arg or local or method call */
463
464    if (BufferNameOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
465    {
466        return;
467    }
468
469    /* Get the Index term, must be an integer constant to convert */
470
471    IndexOp = BufferNameOp->Common.Next;
472
473    /* Major cheat: The Node field is also used for the Tag ptr. Clear it now */
474
475    IndexOp->Common.Node = NULL;
476
477    OpInfo = AcpiPsGetOpcodeInfo (IndexOp->Common.AmlOpcode);
478    if (OpInfo->ObjectType != ACPI_TYPE_INTEGER)
479    {
480        return;
481    }
482
483    /* Get the bit offset of the descriptor within the buffer */
484
485    if ((Op->Common.AmlOpcode == AML_CREATE_BIT_FIELD_OP) ||
486        (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP))
487    {
488        /* Index operand is a bit offset */
489
490        BitIndex = (UINT32) IndexOp->Common.Value.Integer;
491    }
492    else
493    {
494        /* Index operand is a byte offset, convert to bits */
495
496        BitIndex = (UINT32) ACPI_MUL_8 (IndexOp->Common.Value.Integer);
497    }
498
499    /* Lookup the buffer in the namespace */
500
501    Status = AcpiNsLookup (WalkState->ScopeInfo,
502                BufferNameOp->Common.Value.String, ACPI_TYPE_BUFFER,
503                ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState,
504                &BufferNode);
505    if (ACPI_FAILURE (Status))
506    {
507        return;
508    }
509
510    /* Validate object type, we must have a buffer */
511
512    if (BufferNode->Type != ACPI_TYPE_BUFFER)
513    {
514        return;
515    }
516
517    /* Find the resource descriptor node corresponding to the index */
518
519    ResourceNode = AcpiDmGetResourceNode (BufferNode, BitIndex);
520    if (!ResourceNode)
521    {
522        return;
523    }
524
525    /* Translate the Index to a resource tag pathname */
526
527    AcpiGetTagPathname (IndexOp, BufferNode, ResourceNode, BitIndex);
528}
529
530
531/*******************************************************************************
532 *
533 * FUNCTION:    AcpiDmGetResourceNode
534 *
535 * PARAMETERS:  BufferNode          - Node for the parent buffer
536 *              BitIndex            - Index into the resource descriptor
537 *
538 * RETURN:      Namespace node for the resource descriptor. NULL if not found
539 *
540 * DESCRIPTION: Find a resource descriptor that corresponds to the bit index
541 *
542 ******************************************************************************/
543
544static ACPI_NAMESPACE_NODE *
545AcpiDmGetResourceNode (
546    ACPI_NAMESPACE_NODE     *BufferNode,
547    UINT32                  BitIndex)
548{
549    ACPI_NAMESPACE_NODE     *Node;
550    UINT32                  ByteIndex = ACPI_DIV_8 (BitIndex);
551
552
553    /*
554     * Child list contains an entry for each resource descriptor. Find
555     * the descriptor that corresponds to the Index.
556     *
557     * If there are no children, this is not a resource template
558     */
559    Node = BufferNode->Child;
560    while (Node)
561    {
562        /*
563         * Check if the Index falls within this resource.
564         *
565         * Value contains the resource offset, Object contains the resource
566         * length (both in bytes)
567         */
568        if ((ByteIndex >= Node->Value) &&
569            (ByteIndex < (Node->Value + Node->Length)))
570        {
571            return (Node);
572        }
573
574        Node = Node->Peer;
575    }
576
577    return (NULL);
578}
579
580
581/*******************************************************************************
582 *
583 * FUNCTION:    AcpiGetTagPathname
584 *
585 * PARAMETERS:  BufferNode          - Node for the parent buffer
586 *              ResourceNode        - Node for a resource descriptor
587 *              BitIndex            - Index into the resource descriptor
588 *
589 * RETURN:      Full pathname for a resource tag. NULL if no match.
590 *              Path is returned in AML (packed) format.
591 *
592 * DESCRIPTION: Convert a BitIndex into a symbolic resource tag (full pathname)
593 *
594 ******************************************************************************/
595
596static char *
597AcpiGetTagPathname (
598    ACPI_PARSE_OBJECT       *IndexOp,
599    ACPI_NAMESPACE_NODE     *BufferNode,
600    ACPI_NAMESPACE_NODE     *ResourceNode,
601    UINT32                  BitIndex)
602{
603    ACPI_STATUS             Status;
604    UINT32                  ResourceBitIndex;
605    UINT8                   ResourceTableIndex;
606    ACPI_SIZE               RequiredSize;
607    char                    *Pathname;
608    AML_RESOURCE            *Aml;
609    ACPI_PARSE_OBJECT       *Op;
610    char                    *InternalPath;
611    char                    *Tag;
612
613
614    /* Get the Op that contains the actual buffer data */
615
616    Op = BufferNode->Op->Common.Value.Arg;
617    Op = Op->Common.Next;
618    if (!Op)
619    {
620        return (NULL);
621    }
622
623    /* Get the individual resource descriptor and validate it */
624
625    Aml = ACPI_CAST_PTR (AML_RESOURCE,
626            &Op->Named.Data[ResourceNode->Value]);
627
628    Status = AcpiUtValidateResource (NULL, Aml, &ResourceTableIndex);
629    if (ACPI_FAILURE (Status))
630    {
631        return (NULL);
632    }
633
634    /* Get offset into this descriptor (from offset into entire buffer) */
635
636    ResourceBitIndex = BitIndex - ACPI_MUL_8 (ResourceNode->Value);
637
638    /* Get the tag associated with this resource descriptor and offset */
639
640    Tag = AcpiDmGetResourceTag (ResourceBitIndex, Aml, ResourceTableIndex);
641    if (!Tag)
642    {
643        return (NULL);
644    }
645
646    /*
647     * Now that we know that we have a reference that can be converted to a
648     * symbol, change the name of the resource to a unique name.
649     */
650    AcpiDmUpdateResourceName (ResourceNode);
651
652    /* Get the full pathname to the parent buffer */
653
654    RequiredSize = AcpiNsGetPathnameLength (BufferNode);
655    if (!RequiredSize)
656    {
657        return (NULL);
658    }
659
660    Pathname = ACPI_ALLOCATE_ZEROED (RequiredSize + ACPI_PATH_SEGMENT_LENGTH);
661    if (!Pathname)
662    {
663        return (NULL);
664    }
665
666    Status = AcpiNsBuildExternalPath (BufferNode, RequiredSize, Pathname);
667    if (ACPI_FAILURE (Status))
668    {
669        ACPI_FREE (Pathname);
670        return (NULL);
671    }
672
673    /*
674     * Create the full path to the resource and tag by: remove the buffer name,
675     * append the resource descriptor name, append a dot, append the tag name.
676     *
677     * TBD: Always using the full path is a bit brute force, the path can be
678     * often be optimized with carats (if the original buffer namepath is a
679     * single nameseg). This doesn't really matter, because these paths do not
680     * end up in the final compiled AML, it's just an appearance issue for the
681     * disassembled code.
682     */
683    Pathname[ACPI_STRLEN (Pathname) - ACPI_NAME_SIZE] = 0;
684    ACPI_STRNCAT (Pathname, ResourceNode->Name.Ascii, ACPI_NAME_SIZE);
685    ACPI_STRCAT (Pathname, ".");
686    ACPI_STRNCAT (Pathname, Tag, ACPI_NAME_SIZE);
687
688    /* Internalize the namepath to AML format */
689
690    AcpiNsInternalizeName (Pathname, &InternalPath);
691    ACPI_FREE (Pathname);
692
693    /* Update the Op with the symbol */
694
695    AcpiPsInitOp (IndexOp, AML_INT_NAMEPATH_OP);
696    IndexOp->Common.Value.String = InternalPath;
697
698    /* We will need the tag later. Cheat by putting it in the Node field */
699
700    IndexOp->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Tag);
701    return (InternalPath);
702}
703
704
705/*******************************************************************************
706 *
707 * FUNCTION:    AcpiDmUpdateResourceName
708 *
709 * PARAMETERS:  ResourceNode        - Node for a resource descriptor
710 *
711 * RETURN:      Stores new name in the ResourceNode
712 *
713 * DESCRIPTION: Create a new, unique name for a resource descriptor. Used by
714 *              both the disassembly of the descriptor itself and any symbolic
715 *              references to the descriptor. Ignored if a unique name has
716 *              already been assigned to the resource.
717 *
718 * NOTE: Single threaded, suitable for applications only!
719 *
720 ******************************************************************************/
721
722static void
723AcpiDmUpdateResourceName (
724    ACPI_NAMESPACE_NODE     *ResourceNode)
725{
726    char                    Name[ACPI_NAME_SIZE];
727
728
729    /* Ignore if a unique name has already been assigned */
730
731    if (ResourceNode->Name.Integer != ACPI_DEFAULT_RESNAME)
732    {
733        return;
734    }
735
736    /* Generate a new ACPI name for the descriptor */
737
738    Name[0] = '_';
739    Name[1] = AcpiGbl_Prefix[AcpiGbl_NextPrefix];
740    Name[2] = AcpiUtHexToAsciiChar ((UINT64) AcpiGbl_NextResourceId, 4);
741    Name[3] = AcpiUtHexToAsciiChar ((UINT64) AcpiGbl_NextResourceId, 0);
742
743    /* Update globals for next name */
744
745    AcpiGbl_NextResourceId++;
746    if (AcpiGbl_NextResourceId >= 256)
747    {
748        AcpiGbl_NextResourceId = 0;
749        AcpiGbl_NextPrefix++;
750        if (AcpiGbl_NextPrefix > ACPI_NUM_RES_PREFIX)
751        {
752            AcpiGbl_NextPrefix = 0;
753        }
754    }
755
756    /* Change the resource descriptor name */
757
758    ResourceNode->Name.Integer = *ACPI_CAST_PTR (UINT32, &Name[0]);
759}
760
761
762/*******************************************************************************
763 *
764 * FUNCTION:    AcpiDmGetResourceTag
765 *
766 * PARAMETERS:  BitIndex            - Index into the resource descriptor
767 *              Resource            - Pointer to the raw resource data
768 *              ResourceIndex       - Index correspoinding to the resource type
769 *
770 * RETURN:      Pointer to the resource tag (ACPI_NAME). NULL if no match.
771 *
772 * DESCRIPTION: Convert a BitIndex into a symbolic resource tag.
773 *
774 * Note: ResourceIndex should be previously validated and guaranteed to ve
775 *       valid.
776 *
777 ******************************************************************************/
778
779static char *
780AcpiDmGetResourceTag (
781    UINT32                  BitIndex,
782    AML_RESOURCE            *Resource,
783    UINT8                   ResourceIndex)
784{
785    const ACPI_RESOURCE_TAG *TagList;
786    char                    *Tag = NULL;
787
788
789    /* Get the tag list for this resource descriptor type */
790
791    TagList = AcpiGbl_ResourceTags[ResourceIndex];
792
793    /*
794     * Handle descriptors that have multiple subtypes
795     */
796    switch (Resource->DescriptorType)
797    {
798    case ACPI_RESOURCE_NAME_ADDRESS16:
799    case ACPI_RESOURCE_NAME_ADDRESS32:
800    case ACPI_RESOURCE_NAME_ADDRESS64:
801    case ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64:
802        /*
803         * Subtype differentiation is the flags.
804         * Kindof brute force, but just blindly search for an index match
805         */
806        if (Resource->Address.ResourceType == ACPI_ADDRESS_TYPE_MEMORY_RANGE)
807        {
808            Tag = AcpiDmSearchTagList (BitIndex, AcpiDmMemoryFlagTags);
809        }
810        else if (Resource->Address.ResourceType == ACPI_ADDRESS_TYPE_IO_RANGE)
811        {
812            Tag = AcpiDmSearchTagList (BitIndex, AcpiDmIoFlagTags);
813        }
814
815        /* If we found a match, all done. Else, drop to normal search below */
816
817        if (Tag)
818        {
819            return (Tag);
820        }
821        break;
822
823    case ACPI_RESOURCE_NAME_GPIO:
824
825        /* GPIO connection has 2 subtypes: Interrupt and I/O */
826
827        if (Resource->Gpio.ConnectionType > AML_RESOURCE_MAX_GPIOTYPE)
828        {
829            return (NULL);
830        }
831
832        TagList = AcpiGbl_GpioResourceTags[Resource->Gpio.ConnectionType];
833        break;
834
835    case ACPI_RESOURCE_NAME_SERIAL_BUS:
836
837        /* SerialBus has 3 subtypes: I2C, SPI, and UART */
838
839        if ((Resource->CommonSerialBus.Type == 0) ||
840            (Resource->CommonSerialBus.Type > AML_RESOURCE_MAX_SERIALBUSTYPE))
841        {
842            return (NULL);
843        }
844
845        TagList = AcpiGbl_SerialResourceTags[Resource->CommonSerialBus.Type];
846        break;
847
848    default:
849
850        break;
851    }
852
853    /* Search for a match against the BitIndex */
854
855    if (TagList)
856    {
857        Tag = AcpiDmSearchTagList (BitIndex, TagList);
858    }
859
860    return (Tag);
861}
862
863
864/*******************************************************************************
865 *
866 * FUNCTION:    AcpiDmSearchTagList
867 *
868 * PARAMETERS:  BitIndex            - Index into the resource descriptor
869 *              TagList             - List to search
870 *
871 * RETURN:      Pointer to a tag (ACPI_NAME). NULL if no match found.
872 *
873 * DESCRIPTION: Search a tag list for a match to the input BitIndex. Matches
874 *              a fixed offset to a symbolic resource tag name.
875 *
876 ******************************************************************************/
877
878static char *
879AcpiDmSearchTagList (
880    UINT32                  BitIndex,
881    const ACPI_RESOURCE_TAG *TagList)
882{
883
884    /*
885     * Walk the null-terminated tag list to find a matching bit offset.
886     * We are looking for an exact match.
887     */
888    for ( ; TagList->Tag; TagList++)
889    {
890        if (BitIndex == TagList->BitIndex)
891        {
892            return (TagList->Tag);
893        }
894    }
895
896    /* A matching offset was not found */
897
898    return (NULL);
899}
900
901
902/*******************************************************************************
903 *
904 * FUNCTION:    AcpiDmFindResources
905 *
906 * PARAMETERS:  Root                - Root of the parse tree
907 *
908 * RETURN:      None
909 *
910 * DESCRIPTION: Add all ResourceTemplate declarations to the namespace. Each
911 *              resource descriptor in each template is given a node -- used
912 *              for later conversion of resource references to symbolic refs.
913 *
914 ******************************************************************************/
915
916void
917AcpiDmFindResources (
918    ACPI_PARSE_OBJECT       *Root)
919{
920    ACPI_PARSE_OBJECT       *Op = Root;
921    ACPI_PARSE_OBJECT       *Parent;
922
923
924    /* Walk the entire parse tree */
925
926    while (Op)
927    {
928        /* We are interested in Buffer() declarations */
929
930        if (Op->Common.AmlOpcode == AML_BUFFER_OP)
931        {
932            /* And only declarations of the form Name (XXXX, Buffer()... ) */
933
934            Parent = Op->Common.Parent;
935            if (Parent->Common.AmlOpcode == AML_NAME_OP)
936            {
937                /*
938                 * If the buffer is a resource template, add the individual
939                 * resource descriptors to the namespace, as children of the
940                 * buffer node.
941                 */
942                if (ACPI_SUCCESS (AcpiDmIsResourceTemplate (NULL, Op)))
943                {
944                    Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
945                    AcpiDmAddResourcesToNamespace (Parent->Common.Node, Op);
946                }
947            }
948        }
949
950        Op = AcpiPsGetDepthNext (Root, Op);
951    }
952}
953
954
955/*******************************************************************************
956 *
957 * FUNCTION:    AcpiDmAddResourcesToNamespace
958 *
959 * PARAMETERS:  BufferNode          - Node for the parent buffer
960 *              Op                  - Parse op for the buffer
961 *
962 * RETURN:      None
963 *
964 * DESCRIPTION: Add an entire resource template to the namespace. Each
965 *              resource descriptor is added as a namespace node.
966 *
967 ******************************************************************************/
968
969static void
970AcpiDmAddResourcesToNamespace (
971    ACPI_NAMESPACE_NODE     *BufferNode,
972    ACPI_PARSE_OBJECT       *Op)
973{
974    ACPI_PARSE_OBJECT       *NextOp;
975
976
977    /* Get to the ByteData list */
978
979    NextOp = Op->Common.Value.Arg;
980    NextOp = NextOp->Common.Next;
981    if (!NextOp)
982    {
983        return;
984    }
985
986    /* Set Node and Op to point to each other */
987
988    BufferNode->Op = Op;
989    Op->Common.Node = BufferNode;
990
991    /*
992     * Insert each resource into the namespace
993     * NextOp contains the Aml pointer and the Aml length
994     */
995    AcpiUtWalkAmlResources (NULL, (UINT8 *) NextOp->Named.Data,
996        (ACPI_SIZE) NextOp->Common.Value.Integer,
997        AcpiDmAddResourceToNamespace, (void **) BufferNode);
998}
999
1000
1001/*******************************************************************************
1002 *
1003 * FUNCTION:    AcpiDmAddResourceToNamespace
1004 *
1005 * PARAMETERS:  ACPI_WALK_AML_CALLBACK
1006 *              BufferNode              - Node for the parent buffer
1007 *
1008 * RETURN:      Status
1009 *
1010 * DESCRIPTION: Add one resource descriptor to the namespace as a child of the
1011 *              parent buffer. The same name is used for each descriptor. This
1012 *              is changed later to a unique name if the resource is actually
1013 *              referenced by an AML operator.
1014 *
1015 ******************************************************************************/
1016
1017static ACPI_STATUS
1018AcpiDmAddResourceToNamespace (
1019    UINT8                   *Aml,
1020    UINT32                  Length,
1021    UINT32                  Offset,
1022    UINT8                   ResourceIndex,
1023    void                    **Context)
1024{
1025    ACPI_STATUS             Status;
1026    ACPI_GENERIC_STATE      ScopeInfo;
1027    ACPI_NAMESPACE_NODE     *Node;
1028
1029
1030    /* TBD: Don't need to add descriptors that have no tags defined? */
1031
1032    /* Add the resource to the namespace, as child of the buffer */
1033
1034    ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Context);
1035    Status = AcpiNsLookup (&ScopeInfo, "_TMP", ACPI_TYPE_LOCAL_RESOURCE,
1036                ACPI_IMODE_LOAD_PASS2,
1037                ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_PREFIX_IS_SCOPE,
1038                NULL, &Node);
1039    if (ACPI_FAILURE (Status))
1040    {
1041        return (AE_OK);
1042    }
1043
1044    /* Set the name to the default, changed later if resource is referenced */
1045
1046    Node->Name.Integer = ACPI_DEFAULT_RESNAME;
1047
1048    /* Save the offset of the descriptor (within the original buffer) */
1049
1050    Node->Value = Offset;
1051    Node->Length = Length;
1052    return (AE_OK);
1053}
1054