xref: /titanic_41/usr/src/uts/intel/io/acpica/utilities/utresrc.c (revision 1babaf948dd28d81d79cf3ec089d6edc111ed4a8)
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 "acpi.h"
48 #include "accommon.h"
49 #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  */
62 const char                      *AcpiGbl_BmDecode[] =
63 {
64     "NotBusMaster",
65     "BusMaster"
66 };
67 
68 const char                      *AcpiGbl_ConfigDecode[] =
69 {
70     "0 - Good Configuration",
71     "1 - Acceptable Configuration",
72     "2 - Suboptimal Configuration",
73     "3 - ***Invalid Configuration***",
74 };
75 
76 const char                      *AcpiGbl_ConsumeDecode[] =
77 {
78     "ResourceProducer",
79     "ResourceConsumer"
80 };
81 
82 const char                      *AcpiGbl_DecDecode[] =
83 {
84     "PosDecode",
85     "SubDecode"
86 };
87 
88 const char                      *AcpiGbl_HeDecode[] =
89 {
90     "Level",
91     "Edge"
92 };
93 
94 const char                      *AcpiGbl_IoDecode[] =
95 {
96     "Decode10",
97     "Decode16"
98 };
99 
100 const char                      *AcpiGbl_LlDecode[] =
101 {
102     "ActiveHigh",
103     "ActiveLow"
104 };
105 
106 const char                      *AcpiGbl_MaxDecode[] =
107 {
108     "MaxNotFixed",
109     "MaxFixed"
110 };
111 
112 const char                      *AcpiGbl_MemDecode[] =
113 {
114     "NonCacheable",
115     "Cacheable",
116     "WriteCombining",
117     "Prefetchable"
118 };
119 
120 const char                      *AcpiGbl_MinDecode[] =
121 {
122     "MinNotFixed",
123     "MinFixed"
124 };
125 
126 const char                      *AcpiGbl_MtpDecode[] =
127 {
128     "AddressRangeMemory",
129     "AddressRangeReserved",
130     "AddressRangeACPI",
131     "AddressRangeNVS"
132 };
133 
134 const char                      *AcpiGbl_RngDecode[] =
135 {
136     "InvalidRanges",
137     "NonISAOnlyRanges",
138     "ISAOnlyRanges",
139     "EntireRange"
140 };
141 
142 const char                      *AcpiGbl_RwDecode[] =
143 {
144     "ReadOnly",
145     "ReadWrite"
146 };
147 
148 const char                      *AcpiGbl_ShrDecode[] =
149 {
150     "Exclusive",
151     "Shared"
152 };
153 
154 const char                      *AcpiGbl_SizDecode[] =
155 {
156     "Transfer8",
157     "Transfer8_16",
158     "Transfer16",
159     "InvalidSize"
160 };
161 
162 const char                      *AcpiGbl_TrsDecode[] =
163 {
164     "DenseTranslation",
165     "SparseTranslation"
166 };
167 
168 const char                      *AcpiGbl_TtpDecode[] =
169 {
170     "TypeStatic",
171     "TypeTranslation"
172 };
173 
174 const 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  */
189 const 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  */
233 static 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 
288 ACPI_STATUS
289 AcpiUtWalkAmlResources (
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 
394 ACPI_STATUS
395 AcpiUtValidateResource (
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 
524 UINT8
525 AcpiUtGetResourceType (
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 
564 UINT16
565 AcpiUtGetResourceLength (
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 
609 UINT8
610 AcpiUtGetResourceHeaderLength (
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 
643 UINT32
644 AcpiUtGetDescriptorLength (
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 
673 ACPI_STATUS
674 AcpiUtGetResourceEndTag (
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