utresrc.c revision 217365
1/*******************************************************************************
2 *
3 * Module Name: utresrc - Resource managment utilities
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2011, 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#define __UTRESRC_C__
46
47#include <contrib/dev/acpica/include/acpi.h>
48#include <contrib/dev/acpica/include/accommon.h>
49#include <contrib/dev/acpica/include/amlresrc.h>
50
51
52#define _COMPONENT          ACPI_UTILITIES
53        ACPI_MODULE_NAME    ("utresrc")
54
55
56#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
57
58/*
59 * Strings used to decode resource descriptors.
60 * Used by both the disasssembler and the debugger resource dump routines
61 */
62const char                      *AcpiGbl_BmDecode[] =
63{
64    "NotBusMaster",
65    "BusMaster"
66};
67
68const char                      *AcpiGbl_ConfigDecode[] =
69{
70    "0 - Good Configuration",
71    "1 - Acceptable Configuration",
72    "2 - Suboptimal Configuration",
73    "3 - ***Invalid Configuration***",
74};
75
76const char                      *AcpiGbl_ConsumeDecode[] =
77{
78    "ResourceProducer",
79    "ResourceConsumer"
80};
81
82const char                      *AcpiGbl_DecDecode[] =
83{
84    "PosDecode",
85    "SubDecode"
86};
87
88const char                      *AcpiGbl_HeDecode[] =
89{
90    "Level",
91    "Edge"
92};
93
94const char                      *AcpiGbl_IoDecode[] =
95{
96    "Decode10",
97    "Decode16"
98};
99
100const char                      *AcpiGbl_LlDecode[] =
101{
102    "ActiveHigh",
103    "ActiveLow"
104};
105
106const char                      *AcpiGbl_MaxDecode[] =
107{
108    "MaxNotFixed",
109    "MaxFixed"
110};
111
112const char                      *AcpiGbl_MemDecode[] =
113{
114    "NonCacheable",
115    "Cacheable",
116    "WriteCombining",
117    "Prefetchable"
118};
119
120const char                      *AcpiGbl_MinDecode[] =
121{
122    "MinNotFixed",
123    "MinFixed"
124};
125
126const char                      *AcpiGbl_MtpDecode[] =
127{
128    "AddressRangeMemory",
129    "AddressRangeReserved",
130    "AddressRangeACPI",
131    "AddressRangeNVS"
132};
133
134const char                      *AcpiGbl_RngDecode[] =
135{
136    "InvalidRanges",
137    "NonISAOnlyRanges",
138    "ISAOnlyRanges",
139    "EntireRange"
140};
141
142const char                      *AcpiGbl_RwDecode[] =
143{
144    "ReadOnly",
145    "ReadWrite"
146};
147
148const char                      *AcpiGbl_ShrDecode[] =
149{
150    "Exclusive",
151    "Shared"
152};
153
154const char                      *AcpiGbl_SizDecode[] =
155{
156    "Transfer8",
157    "Transfer8_16",
158    "Transfer16",
159    "InvalidSize"
160};
161
162const char                      *AcpiGbl_TrsDecode[] =
163{
164    "DenseTranslation",
165    "SparseTranslation"
166};
167
168const char                      *AcpiGbl_TtpDecode[] =
169{
170    "TypeStatic",
171    "TypeTranslation"
172};
173
174const char                      *AcpiGbl_TypDecode[] =
175{
176    "Compatibility",
177    "TypeA",
178    "TypeB",
179    "TypeF"
180};
181
182#endif
183
184
185/*
186 * Base sizes of the raw AML resource descriptors, indexed by resource type.
187 * Zero indicates a reserved (and therefore invalid) resource type.
188 */
189const UINT8                 AcpiGbl_ResourceAmlSizes[] =
190{
191    /* Small descriptors */
192
193    0,
194    0,
195    0,
196    0,
197    ACPI_AML_SIZE_SMALL (AML_RESOURCE_IRQ),
198    ACPI_AML_SIZE_SMALL (AML_RESOURCE_DMA),
199    ACPI_AML_SIZE_SMALL (AML_RESOURCE_START_DEPENDENT),
200    ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_DEPENDENT),
201    ACPI_AML_SIZE_SMALL (AML_RESOURCE_IO),
202    ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_IO),
203    0,
204    0,
205    0,
206    0,
207    ACPI_AML_SIZE_SMALL (AML_RESOURCE_VENDOR_SMALL),
208    ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_TAG),
209
210    /* Large descriptors */
211
212    0,
213    ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY24),
214    ACPI_AML_SIZE_LARGE (AML_RESOURCE_GENERIC_REGISTER),
215    0,
216    ACPI_AML_SIZE_LARGE (AML_RESOURCE_VENDOR_LARGE),
217    ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY32),
218    ACPI_AML_SIZE_LARGE (AML_RESOURCE_FIXED_MEMORY32),
219    ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS32),
220    ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS16),
221    ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_IRQ),
222    ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS64),
223    ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_ADDRESS64)
224};
225
226
227/*
228 * Resource types, used to validate the resource length field.
229 * The length of fixed-length types must match exactly, variable
230 * lengths must meet the minimum required length, etc.
231 * Zero indicates a reserved (and therefore invalid) resource type.
232 */
233static const UINT8          AcpiGbl_ResourceTypes[] =
234{
235    /* Small descriptors */
236
237    0,
238    0,
239    0,
240    0,
241    ACPI_SMALL_VARIABLE_LENGTH,
242    ACPI_FIXED_LENGTH,
243    ACPI_SMALL_VARIABLE_LENGTH,
244    ACPI_FIXED_LENGTH,
245    ACPI_FIXED_LENGTH,
246    ACPI_FIXED_LENGTH,
247    0,
248    0,
249    0,
250    0,
251    ACPI_VARIABLE_LENGTH,
252    ACPI_FIXED_LENGTH,
253
254    /* Large descriptors */
255
256    0,
257    ACPI_FIXED_LENGTH,
258    ACPI_FIXED_LENGTH,
259    0,
260    ACPI_VARIABLE_LENGTH,
261    ACPI_FIXED_LENGTH,
262    ACPI_FIXED_LENGTH,
263    ACPI_VARIABLE_LENGTH,
264    ACPI_VARIABLE_LENGTH,
265    ACPI_VARIABLE_LENGTH,
266    ACPI_VARIABLE_LENGTH,
267    ACPI_FIXED_LENGTH
268};
269
270
271/*******************************************************************************
272 *
273 * FUNCTION:    AcpiUtWalkAmlResources
274 *
275 * PARAMETERS:  Aml             - Pointer to the raw AML resource template
276 *              AmlLength       - Length of the entire template
277 *              UserFunction    - Called once for each descriptor found. If
278 *                                NULL, a pointer to the EndTag is returned
279 *              Context         - Passed to UserFunction
280 *
281 * RETURN:      Status
282 *
283 * DESCRIPTION: Walk a raw AML resource list(buffer). User function called
284 *              once for each resource found.
285 *
286 ******************************************************************************/
287
288ACPI_STATUS
289AcpiUtWalkAmlResources (
290    UINT8                   *Aml,
291    ACPI_SIZE               AmlLength,
292    ACPI_WALK_AML_CALLBACK  UserFunction,
293    void                    *Context)
294{
295    ACPI_STATUS             Status;
296    UINT8                   *EndAml;
297    UINT8                   ResourceIndex;
298    UINT32                  Length;
299    UINT32                  Offset = 0;
300
301
302    ACPI_FUNCTION_TRACE (UtWalkAmlResources);
303
304
305    /* The absolute minimum resource template is one EndTag descriptor */
306
307    if (AmlLength < sizeof (AML_RESOURCE_END_TAG))
308    {
309        return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
310    }
311
312    /* Point to the end of the resource template buffer */
313
314    EndAml = Aml + AmlLength;
315
316    /* Walk the byte list, abort on any invalid descriptor type or length */
317
318    while (Aml < EndAml)
319    {
320        /* Validate the Resource Type and Resource Length */
321
322        Status = AcpiUtValidateResource (Aml, &ResourceIndex);
323        if (ACPI_FAILURE (Status))
324        {
325            return_ACPI_STATUS (Status);
326        }
327
328        /* Get the length of this descriptor */
329
330        Length = AcpiUtGetDescriptorLength (Aml);
331
332        /* Invoke the user function */
333
334        if (UserFunction)
335        {
336            Status = UserFunction (Aml, Length, Offset, ResourceIndex, Context);
337            if (ACPI_FAILURE (Status))
338            {
339                return (Status);
340            }
341        }
342
343        /* An EndTag descriptor terminates this resource template */
344
345        if (AcpiUtGetResourceType (Aml) == ACPI_RESOURCE_NAME_END_TAG)
346        {
347            /*
348             * There must be at least one more byte in the buffer for
349             * the 2nd byte of the EndTag
350             */
351            if ((Aml + 1) >= EndAml)
352            {
353                return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
354            }
355
356            /* Return the pointer to the EndTag if requested */
357
358            if (!UserFunction)
359            {
360                *(void **) Context = Aml;
361            }
362
363            /* Normal exit */
364
365            return_ACPI_STATUS (AE_OK);
366        }
367
368        Aml += Length;
369        Offset += Length;
370    }
371
372    /* Did not find an EndTag descriptor */
373
374    return (AE_AML_NO_RESOURCE_END_TAG);
375}
376
377
378/*******************************************************************************
379 *
380 * FUNCTION:    AcpiUtValidateResource
381 *
382 * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
383 *              ReturnIndex     - Where the resource index is returned. NULL
384 *                                if the index is not required.
385 *
386 * RETURN:      Status, and optionally the Index into the global resource tables
387 *
388 * DESCRIPTION: Validate an AML resource descriptor by checking the Resource
389 *              Type and Resource Length. Returns an index into the global
390 *              resource information/dispatch tables for later use.
391 *
392 ******************************************************************************/
393
394ACPI_STATUS
395AcpiUtValidateResource (
396    void                    *Aml,
397    UINT8                   *ReturnIndex)
398{
399    UINT8                   ResourceType;
400    UINT8                   ResourceIndex;
401    ACPI_RS_LENGTH          ResourceLength;
402    ACPI_RS_LENGTH          MinimumResourceLength;
403
404
405    ACPI_FUNCTION_ENTRY ();
406
407
408    /*
409     * 1) Validate the ResourceType field (Byte 0)
410     */
411    ResourceType = ACPI_GET8 (Aml);
412
413    /*
414     * Byte 0 contains the descriptor name (Resource Type)
415     * Examine the large/small bit in the resource header
416     */
417    if (ResourceType & ACPI_RESOURCE_NAME_LARGE)
418    {
419        /* Verify the large resource type (name) against the max */
420
421        if (ResourceType > ACPI_RESOURCE_NAME_LARGE_MAX)
422        {
423            return (AE_AML_INVALID_RESOURCE_TYPE);
424        }
425
426        /*
427         * Large Resource Type -- bits 6:0 contain the name
428         * Translate range 0x80-0x8B to index range 0x10-0x1B
429         */
430        ResourceIndex = (UINT8) (ResourceType - 0x70);
431    }
432    else
433    {
434        /*
435         * Small Resource Type -- bits 6:3 contain the name
436         * Shift range to index range 0x00-0x0F
437         */
438        ResourceIndex = (UINT8)
439            ((ResourceType & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
440    }
441
442    /* Check validity of the resource type, zero indicates name is invalid */
443
444    if (!AcpiGbl_ResourceTypes[ResourceIndex])
445    {
446        return (AE_AML_INVALID_RESOURCE_TYPE);
447    }
448
449
450    /*
451     * 2) Validate the ResourceLength field. This ensures that the length
452     *    is at least reasonable, and guarantees that it is non-zero.
453     */
454    ResourceLength = AcpiUtGetResourceLength (Aml);
455    MinimumResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex];
456
457    /* Validate based upon the type of resource - fixed length or variable */
458
459    switch (AcpiGbl_ResourceTypes[ResourceIndex])
460    {
461    case ACPI_FIXED_LENGTH:
462
463        /* Fixed length resource, length must match exactly */
464
465        if (ResourceLength != MinimumResourceLength)
466        {
467            return (AE_AML_BAD_RESOURCE_LENGTH);
468        }
469        break;
470
471    case ACPI_VARIABLE_LENGTH:
472
473        /* Variable length resource, length must be at least the minimum */
474
475        if (ResourceLength < MinimumResourceLength)
476        {
477            return (AE_AML_BAD_RESOURCE_LENGTH);
478        }
479        break;
480
481    case ACPI_SMALL_VARIABLE_LENGTH:
482
483        /* Small variable length resource, length can be (Min) or (Min-1) */
484
485        if ((ResourceLength > MinimumResourceLength) ||
486            (ResourceLength < (MinimumResourceLength - 1)))
487        {
488            return (AE_AML_BAD_RESOURCE_LENGTH);
489        }
490        break;
491
492    default:
493
494        /* Shouldn't happen (because of validation earlier), but be sure */
495
496        return (AE_AML_INVALID_RESOURCE_TYPE);
497    }
498
499    /* Optionally return the resource table index */
500
501    if (ReturnIndex)
502    {
503        *ReturnIndex = ResourceIndex;
504    }
505
506    return (AE_OK);
507}
508
509
510/*******************************************************************************
511 *
512 * FUNCTION:    AcpiUtGetResourceType
513 *
514 * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
515 *
516 * RETURN:      The Resource Type with no extraneous bits (except the
517 *              Large/Small descriptor bit -- this is left alone)
518 *
519 * DESCRIPTION: Extract the Resource Type/Name from the first byte of
520 *              a resource descriptor.
521 *
522 ******************************************************************************/
523
524UINT8
525AcpiUtGetResourceType (
526    void                    *Aml)
527{
528    ACPI_FUNCTION_ENTRY ();
529
530
531    /*
532     * Byte 0 contains the descriptor name (Resource Type)
533     * Examine the large/small bit in the resource header
534     */
535    if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE)
536    {
537        /* Large Resource Type -- bits 6:0 contain the name */
538
539        return (ACPI_GET8 (Aml));
540    }
541    else
542    {
543        /* Small Resource Type -- bits 6:3 contain the name */
544
545        return ((UINT8) (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_SMALL_MASK));
546    }
547}
548
549
550/*******************************************************************************
551 *
552 * FUNCTION:    AcpiUtGetResourceLength
553 *
554 * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
555 *
556 * RETURN:      Byte Length
557 *
558 * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By
559 *              definition, this does not include the size of the descriptor
560 *              header or the length field itself.
561 *
562 ******************************************************************************/
563
564UINT16
565AcpiUtGetResourceLength (
566    void                    *Aml)
567{
568    ACPI_RS_LENGTH          ResourceLength;
569
570
571    ACPI_FUNCTION_ENTRY ();
572
573
574    /*
575     * Byte 0 contains the descriptor name (Resource Type)
576     * Examine the large/small bit in the resource header
577     */
578    if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE)
579    {
580        /* Large Resource type -- bytes 1-2 contain the 16-bit length */
581
582        ACPI_MOVE_16_TO_16 (&ResourceLength, ACPI_ADD_PTR (UINT8, Aml, 1));
583
584    }
585    else
586    {
587        /* Small Resource type -- bits 2:0 of byte 0 contain the length */
588
589        ResourceLength = (UINT16) (ACPI_GET8 (Aml) &
590                                    ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
591    }
592
593    return (ResourceLength);
594}
595
596
597/*******************************************************************************
598 *
599 * FUNCTION:    AcpiUtGetResourceHeaderLength
600 *
601 * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
602 *
603 * RETURN:      Length of the AML header (depends on large/small descriptor)
604 *
605 * DESCRIPTION: Get the length of the header for this resource.
606 *
607 ******************************************************************************/
608
609UINT8
610AcpiUtGetResourceHeaderLength (
611    void                    *Aml)
612{
613    ACPI_FUNCTION_ENTRY ();
614
615
616    /* Examine the large/small bit in the resource header */
617
618    if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE)
619    {
620        return (sizeof (AML_RESOURCE_LARGE_HEADER));
621    }
622    else
623    {
624        return (sizeof (AML_RESOURCE_SMALL_HEADER));
625    }
626}
627
628
629/*******************************************************************************
630 *
631 * FUNCTION:    AcpiUtGetDescriptorLength
632 *
633 * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
634 *
635 * RETURN:      Byte length
636 *
637 * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the
638 *              length of the descriptor header and the length field itself.
639 *              Used to walk descriptor lists.
640 *
641 ******************************************************************************/
642
643UINT32
644AcpiUtGetDescriptorLength (
645    void                    *Aml)
646{
647    ACPI_FUNCTION_ENTRY ();
648
649
650    /*
651     * Get the Resource Length (does not include header length) and add
652     * the header length (depends on if this is a small or large resource)
653     */
654    return (AcpiUtGetResourceLength (Aml) +
655            AcpiUtGetResourceHeaderLength (Aml));
656}
657
658
659/*******************************************************************************
660 *
661 * FUNCTION:    AcpiUtGetResourceEndTag
662 *
663 * PARAMETERS:  ObjDesc         - The resource template buffer object
664 *              EndTag          - Where the pointer to the EndTag is returned
665 *
666 * RETURN:      Status, pointer to the end tag
667 *
668 * DESCRIPTION: Find the EndTag resource descriptor in an AML resource template
669 *              Note: allows a buffer length of zero.
670 *
671 ******************************************************************************/
672
673ACPI_STATUS
674AcpiUtGetResourceEndTag (
675    ACPI_OPERAND_OBJECT     *ObjDesc,
676    UINT8                   **EndTag)
677{
678    ACPI_STATUS             Status;
679
680
681    ACPI_FUNCTION_TRACE (UtGetResourceEndTag);
682
683
684    /* Allow a buffer length of zero */
685
686    if (!ObjDesc->Buffer.Length)
687    {
688        *EndTag = ObjDesc->Buffer.Pointer;
689        return_ACPI_STATUS (AE_OK);
690    }
691
692    /* Validate the template and get a pointer to the EndTag */
693
694    Status = AcpiUtWalkAmlResources (ObjDesc->Buffer.Pointer,
695                ObjDesc->Buffer.Length, NULL, EndTag);
696
697    return_ACPI_STATUS (Status);
698}
699
700
701