utresrc.c revision 245582
1167802Sjkim/*******************************************************************************
2167802Sjkim *
3238381Sjkim * Module Name: utresrc - Resource management utilities
4167802Sjkim *
5167802Sjkim ******************************************************************************/
6167802Sjkim
7217365Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
9167802Sjkim * All rights reserved.
10167802Sjkim *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25167802Sjkim *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29167802Sjkim *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43167802Sjkim
44167802Sjkim
45167802Sjkim#define __UTRESRC_C__
46167802Sjkim
47193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
48193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
49228110Sjkim#include <contrib/dev/acpica/include/acresrc.h>
50167802Sjkim
51167802Sjkim
52167802Sjkim#define _COMPONENT          ACPI_UTILITIES
53167802Sjkim        ACPI_MODULE_NAME    ("utresrc")
54167802Sjkim
55167802Sjkim
56167802Sjkim#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
57167802Sjkim
58167802Sjkim/*
59167802Sjkim * Strings used to decode resource descriptors.
60238381Sjkim * Used by both the disassembler and the debugger resource dump routines
61167802Sjkim */
62167802Sjkimconst char                      *AcpiGbl_BmDecode[] =
63167802Sjkim{
64167802Sjkim    "NotBusMaster",
65167802Sjkim    "BusMaster"
66167802Sjkim};
67167802Sjkim
68167802Sjkimconst char                      *AcpiGbl_ConfigDecode[] =
69167802Sjkim{
70167802Sjkim    "0 - Good Configuration",
71167802Sjkim    "1 - Acceptable Configuration",
72167802Sjkim    "2 - Suboptimal Configuration",
73167802Sjkim    "3 - ***Invalid Configuration***",
74167802Sjkim};
75167802Sjkim
76167802Sjkimconst char                      *AcpiGbl_ConsumeDecode[] =
77167802Sjkim{
78167802Sjkim    "ResourceProducer",
79167802Sjkim    "ResourceConsumer"
80167802Sjkim};
81167802Sjkim
82167802Sjkimconst char                      *AcpiGbl_DecDecode[] =
83167802Sjkim{
84167802Sjkim    "PosDecode",
85167802Sjkim    "SubDecode"
86167802Sjkim};
87167802Sjkim
88167802Sjkimconst char                      *AcpiGbl_HeDecode[] =
89167802Sjkim{
90167802Sjkim    "Level",
91167802Sjkim    "Edge"
92167802Sjkim};
93167802Sjkim
94167802Sjkimconst char                      *AcpiGbl_IoDecode[] =
95167802Sjkim{
96167802Sjkim    "Decode10",
97167802Sjkim    "Decode16"
98167802Sjkim};
99167802Sjkim
100167802Sjkimconst char                      *AcpiGbl_LlDecode[] =
101167802Sjkim{
102167802Sjkim    "ActiveHigh",
103167802Sjkim    "ActiveLow"
104167802Sjkim};
105167802Sjkim
106167802Sjkimconst char                      *AcpiGbl_MaxDecode[] =
107167802Sjkim{
108167802Sjkim    "MaxNotFixed",
109167802Sjkim    "MaxFixed"
110167802Sjkim};
111167802Sjkim
112167802Sjkimconst char                      *AcpiGbl_MemDecode[] =
113167802Sjkim{
114167802Sjkim    "NonCacheable",
115167802Sjkim    "Cacheable",
116167802Sjkim    "WriteCombining",
117167802Sjkim    "Prefetchable"
118167802Sjkim};
119167802Sjkim
120167802Sjkimconst char                      *AcpiGbl_MinDecode[] =
121167802Sjkim{
122167802Sjkim    "MinNotFixed",
123167802Sjkim    "MinFixed"
124167802Sjkim};
125167802Sjkim
126167802Sjkimconst char                      *AcpiGbl_MtpDecode[] =
127167802Sjkim{
128167802Sjkim    "AddressRangeMemory",
129167802Sjkim    "AddressRangeReserved",
130167802Sjkim    "AddressRangeACPI",
131167802Sjkim    "AddressRangeNVS"
132167802Sjkim};
133167802Sjkim
134167802Sjkimconst char                      *AcpiGbl_RngDecode[] =
135167802Sjkim{
136167802Sjkim    "InvalidRanges",
137167802Sjkim    "NonISAOnlyRanges",
138167802Sjkim    "ISAOnlyRanges",
139167802Sjkim    "EntireRange"
140167802Sjkim};
141167802Sjkim
142167802Sjkimconst char                      *AcpiGbl_RwDecode[] =
143167802Sjkim{
144167802Sjkim    "ReadOnly",
145167802Sjkim    "ReadWrite"
146167802Sjkim};
147167802Sjkim
148167802Sjkimconst char                      *AcpiGbl_ShrDecode[] =
149167802Sjkim{
150167802Sjkim    "Exclusive",
151243347Sjkim    "Shared",
152243347Sjkim    "ExclusiveAndWake",         /* ACPI 5.0 */
153243347Sjkim    "SharedAndWake"             /* ACPI 5.0 */
154167802Sjkim};
155167802Sjkim
156167802Sjkimconst char                      *AcpiGbl_SizDecode[] =
157167802Sjkim{
158167802Sjkim    "Transfer8",
159167802Sjkim    "Transfer8_16",
160167802Sjkim    "Transfer16",
161167802Sjkim    "InvalidSize"
162167802Sjkim};
163167802Sjkim
164167802Sjkimconst char                      *AcpiGbl_TrsDecode[] =
165167802Sjkim{
166167802Sjkim    "DenseTranslation",
167167802Sjkim    "SparseTranslation"
168167802Sjkim};
169167802Sjkim
170167802Sjkimconst char                      *AcpiGbl_TtpDecode[] =
171167802Sjkim{
172167802Sjkim    "TypeStatic",
173167802Sjkim    "TypeTranslation"
174167802Sjkim};
175167802Sjkim
176167802Sjkimconst char                      *AcpiGbl_TypDecode[] =
177167802Sjkim{
178167802Sjkim    "Compatibility",
179167802Sjkim    "TypeA",
180167802Sjkim    "TypeB",
181167802Sjkim    "TypeF"
182167802Sjkim};
183167802Sjkim
184228110Sjkimconst char                      *AcpiGbl_PpcDecode[] =
185228110Sjkim{
186228110Sjkim    "PullDefault",
187228110Sjkim    "PullUp",
188228110Sjkim    "PullDown",
189228110Sjkim    "PullNone"
190228110Sjkim};
191228110Sjkim
192228110Sjkimconst char                      *AcpiGbl_IorDecode[] =
193228110Sjkim{
194228110Sjkim    "IoRestrictionNone",
195228110Sjkim    "IoRestrictionInputOnly",
196228110Sjkim    "IoRestrictionOutputOnly",
197228110Sjkim    "IoRestrictionNoneAndPreserve"
198228110Sjkim};
199228110Sjkim
200228110Sjkimconst char                      *AcpiGbl_DtsDecode[] =
201228110Sjkim{
202228110Sjkim    "Width8bit",
203228110Sjkim    "Width16bit",
204228110Sjkim    "Width32bit",
205228110Sjkim    "Width64bit",
206228110Sjkim    "Width128bit",
207228110Sjkim    "Width256bit",
208228110Sjkim};
209228110Sjkim
210228110Sjkim/* GPIO connection type */
211228110Sjkim
212228110Sjkimconst char                      *AcpiGbl_CtDecode[] =
213228110Sjkim{
214228110Sjkim    "Interrupt",
215228110Sjkim    "I/O"
216228110Sjkim};
217228110Sjkim
218228110Sjkim/* Serial bus type */
219228110Sjkim
220228110Sjkimconst char                      *AcpiGbl_SbtDecode[] =
221228110Sjkim{
222228110Sjkim    "/* UNKNOWN serial bus type */",
223228110Sjkim    "I2C",
224228110Sjkim    "SPI",
225228110Sjkim    "UART"
226228110Sjkim};
227228110Sjkim
228228110Sjkim/* I2C serial bus access mode */
229228110Sjkim
230228110Sjkimconst char                      *AcpiGbl_AmDecode[] =
231228110Sjkim{
232228110Sjkim    "AddressingMode7Bit",
233228110Sjkim    "AddressingMode10Bit"
234228110Sjkim};
235228110Sjkim
236228110Sjkim/* I2C serial bus slave mode */
237228110Sjkim
238228110Sjkimconst char                      *AcpiGbl_SmDecode[] =
239228110Sjkim{
240228110Sjkim    "ControllerInitiated",
241228110Sjkim    "DeviceInitiated"
242228110Sjkim};
243228110Sjkim
244228110Sjkim/* SPI serial bus wire mode */
245228110Sjkim
246228110Sjkimconst char                      *AcpiGbl_WmDecode[] =
247228110Sjkim{
248228110Sjkim    "FourWireMode",
249228110Sjkim    "ThreeWireMode"
250228110Sjkim};
251228110Sjkim
252228110Sjkim/* SPI serial clock phase */
253228110Sjkim
254228110Sjkimconst char                      *AcpiGbl_CphDecode[] =
255228110Sjkim{
256228110Sjkim    "ClockPhaseFirst",
257228110Sjkim    "ClockPhaseSecond"
258228110Sjkim};
259228110Sjkim
260228110Sjkim/* SPI serial bus clock polarity */
261228110Sjkim
262228110Sjkimconst char                      *AcpiGbl_CpoDecode[] =
263228110Sjkim{
264228110Sjkim    "ClockPolarityLow",
265228110Sjkim    "ClockPolarityHigh"
266228110Sjkim};
267228110Sjkim
268228110Sjkim/* SPI serial bus device polarity */
269228110Sjkim
270228110Sjkimconst char                      *AcpiGbl_DpDecode[] =
271228110Sjkim{
272228110Sjkim    "PolarityLow",
273228110Sjkim    "PolarityHigh"
274228110Sjkim};
275228110Sjkim
276228110Sjkim/* UART serial bus endian */
277228110Sjkim
278228110Sjkimconst char                      *AcpiGbl_EdDecode[] =
279228110Sjkim{
280228110Sjkim    "LittleEndian",
281228110Sjkim    "BigEndian"
282228110Sjkim};
283228110Sjkim
284228110Sjkim/* UART serial bus bits per byte */
285228110Sjkim
286228110Sjkimconst char                      *AcpiGbl_BpbDecode[] =
287228110Sjkim{
288228110Sjkim    "DataBitsFive",
289228110Sjkim    "DataBitsSix",
290228110Sjkim    "DataBitsSeven",
291228110Sjkim    "DataBitsEight",
292228110Sjkim    "DataBitsNine",
293228110Sjkim    "/* UNKNOWN Bits per byte */",
294228110Sjkim    "/* UNKNOWN Bits per byte */",
295228110Sjkim    "/* UNKNOWN Bits per byte */"
296228110Sjkim};
297228110Sjkim
298228110Sjkim/* UART serial bus stop bits */
299228110Sjkim
300228110Sjkimconst char                      *AcpiGbl_SbDecode[] =
301228110Sjkim{
302228110Sjkim    "StopBitsNone",
303228110Sjkim    "StopBitsOne",
304228110Sjkim    "StopBitsOnePlusHalf",
305228110Sjkim    "StopBitsTwo"
306228110Sjkim};
307228110Sjkim
308228110Sjkim/* UART serial bus flow control */
309228110Sjkim
310228110Sjkimconst char                      *AcpiGbl_FcDecode[] =
311228110Sjkim{
312228110Sjkim    "FlowControlNone",
313228110Sjkim    "FlowControlHardware",
314228110Sjkim    "FlowControlXON",
315228110Sjkim    "/* UNKNOWN flow control keyword */"
316228110Sjkim};
317228110Sjkim
318228110Sjkim/* UART serial bus parity type */
319228110Sjkim
320228110Sjkimconst char                      *AcpiGbl_PtDecode[] =
321228110Sjkim{
322228110Sjkim    "ParityTypeNone",
323228110Sjkim    "ParityTypeEven",
324228110Sjkim    "ParityTypeOdd",
325228110Sjkim    "ParityTypeMark",
326228110Sjkim    "ParityTypeSpace",
327228110Sjkim    "/* UNKNOWN parity keyword */",
328228110Sjkim    "/* UNKNOWN parity keyword */",
329228110Sjkim    "/* UNKNOWN parity keyword */"
330228110Sjkim};
331228110Sjkim
332167802Sjkim#endif
333167802Sjkim
334167802Sjkim
335167802Sjkim/*
336167802Sjkim * Base sizes of the raw AML resource descriptors, indexed by resource type.
337167802Sjkim * Zero indicates a reserved (and therefore invalid) resource type.
338167802Sjkim */
339167802Sjkimconst UINT8                 AcpiGbl_ResourceAmlSizes[] =
340167802Sjkim{
341167802Sjkim    /* Small descriptors */
342167802Sjkim
343167802Sjkim    0,
344167802Sjkim    0,
345167802Sjkim    0,
346167802Sjkim    0,
347167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_IRQ),
348167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_DMA),
349167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_START_DEPENDENT),
350167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_DEPENDENT),
351167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_IO),
352167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_IO),
353228110Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_DMA),
354167802Sjkim    0,
355167802Sjkim    0,
356167802Sjkim    0,
357167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_VENDOR_SMALL),
358167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_TAG),
359167802Sjkim
360167802Sjkim    /* Large descriptors */
361167802Sjkim
362167802Sjkim    0,
363167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY24),
364167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_GENERIC_REGISTER),
365167802Sjkim    0,
366167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_VENDOR_LARGE),
367167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY32),
368167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_FIXED_MEMORY32),
369167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS32),
370167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS16),
371167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_IRQ),
372167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS64),
373228110Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_ADDRESS64),
374228110Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_GPIO),
375228110Sjkim    0,
376228110Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_COMMON_SERIALBUS),
377167802Sjkim};
378167802Sjkim
379228110Sjkimconst UINT8                 AcpiGbl_ResourceAmlSerialBusSizes[] =
380228110Sjkim{
381228110Sjkim    0,
382228110Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_I2C_SERIALBUS),
383228110Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_SPI_SERIALBUS),
384228110Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_UART_SERIALBUS),
385228110Sjkim};
386167802Sjkim
387228110Sjkim
388167802Sjkim/*
389167802Sjkim * Resource types, used to validate the resource length field.
390167802Sjkim * The length of fixed-length types must match exactly, variable
391167802Sjkim * lengths must meet the minimum required length, etc.
392167802Sjkim * Zero indicates a reserved (and therefore invalid) resource type.
393167802Sjkim */
394167802Sjkimstatic const UINT8          AcpiGbl_ResourceTypes[] =
395167802Sjkim{
396167802Sjkim    /* Small descriptors */
397167802Sjkim
398167802Sjkim    0,
399167802Sjkim    0,
400167802Sjkim    0,
401167802Sjkim    0,
402228110Sjkim    ACPI_SMALL_VARIABLE_LENGTH,     /* 04 IRQ */
403228110Sjkim    ACPI_FIXED_LENGTH,              /* 05 DMA */
404228110Sjkim    ACPI_SMALL_VARIABLE_LENGTH,     /* 06 StartDependentFunctions */
405228110Sjkim    ACPI_FIXED_LENGTH,              /* 07 EndDependentFunctions */
406228110Sjkim    ACPI_FIXED_LENGTH,              /* 08 IO */
407228110Sjkim    ACPI_FIXED_LENGTH,              /* 09 FixedIO */
408228110Sjkim    ACPI_FIXED_LENGTH,              /* 0A FixedDMA */
409167802Sjkim    0,
410167802Sjkim    0,
411167802Sjkim    0,
412228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 0E VendorShort */
413228110Sjkim    ACPI_FIXED_LENGTH,              /* 0F EndTag */
414167802Sjkim
415167802Sjkim    /* Large descriptors */
416167802Sjkim
417167802Sjkim    0,
418228110Sjkim    ACPI_FIXED_LENGTH,              /* 01 Memory24 */
419228110Sjkim    ACPI_FIXED_LENGTH,              /* 02 GenericRegister */
420167802Sjkim    0,
421228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 04 VendorLong */
422228110Sjkim    ACPI_FIXED_LENGTH,              /* 05 Memory32 */
423228110Sjkim    ACPI_FIXED_LENGTH,              /* 06 Memory32Fixed */
424228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 07 Dword* address */
425228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 08 Word* address */
426228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 09 ExtendedIRQ */
427228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 0A Qword* address */
428228110Sjkim    ACPI_FIXED_LENGTH,              /* 0B Extended* address */
429228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 0C Gpio* */
430228110Sjkim    0,
431228110Sjkim    ACPI_VARIABLE_LENGTH            /* 0E *SerialBus */
432167802Sjkim};
433167802Sjkim
434167802Sjkim
435167802Sjkim/*******************************************************************************
436167802Sjkim *
437167802Sjkim * FUNCTION:    AcpiUtWalkAmlResources
438167802Sjkim *
439243347Sjkim * PARAMETERS:  WalkState           - Current walk info
440243347Sjkim * PARAMETERS:  Aml                 - Pointer to the raw AML resource template
441243347Sjkim *              AmlLength           - Length of the entire template
442243347Sjkim *              UserFunction        - Called once for each descriptor found. If
443243347Sjkim *                                    NULL, a pointer to the EndTag is returned
444243347Sjkim *              Context             - Passed to UserFunction
445167802Sjkim *
446167802Sjkim * RETURN:      Status
447167802Sjkim *
448167802Sjkim * DESCRIPTION: Walk a raw AML resource list(buffer). User function called
449167802Sjkim *              once for each resource found.
450167802Sjkim *
451167802Sjkim ******************************************************************************/
452167802Sjkim
453167802SjkimACPI_STATUS
454167802SjkimAcpiUtWalkAmlResources (
455243347Sjkim    ACPI_WALK_STATE         *WalkState,
456167802Sjkim    UINT8                   *Aml,
457167802Sjkim    ACPI_SIZE               AmlLength,
458167802Sjkim    ACPI_WALK_AML_CALLBACK  UserFunction,
459245582Sjkim    void                    **Context)
460167802Sjkim{
461167802Sjkim    ACPI_STATUS             Status;
462167802Sjkim    UINT8                   *EndAml;
463167802Sjkim    UINT8                   ResourceIndex;
464167802Sjkim    UINT32                  Length;
465167802Sjkim    UINT32                  Offset = 0;
466228110Sjkim    UINT8                   EndTag[2] = {0x79, 0x00};
467167802Sjkim
468167802Sjkim
469167802Sjkim    ACPI_FUNCTION_TRACE (UtWalkAmlResources);
470167802Sjkim
471167802Sjkim
472167802Sjkim    /* The absolute minimum resource template is one EndTag descriptor */
473167802Sjkim
474167802Sjkim    if (AmlLength < sizeof (AML_RESOURCE_END_TAG))
475167802Sjkim    {
476167802Sjkim        return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
477167802Sjkim    }
478167802Sjkim
479167802Sjkim    /* Point to the end of the resource template buffer */
480167802Sjkim
481167802Sjkim    EndAml = Aml + AmlLength;
482167802Sjkim
483167802Sjkim    /* Walk the byte list, abort on any invalid descriptor type or length */
484167802Sjkim
485167802Sjkim    while (Aml < EndAml)
486167802Sjkim    {
487167802Sjkim        /* Validate the Resource Type and Resource Length */
488167802Sjkim
489243347Sjkim        Status = AcpiUtValidateResource (WalkState, Aml, &ResourceIndex);
490167802Sjkim        if (ACPI_FAILURE (Status))
491167802Sjkim        {
492228110Sjkim            /*
493228110Sjkim             * Exit on failure. Cannot continue because the descriptor length
494228110Sjkim             * may be bogus also.
495228110Sjkim             */
496167802Sjkim            return_ACPI_STATUS (Status);
497167802Sjkim        }
498167802Sjkim
499167802Sjkim        /* Get the length of this descriptor */
500167802Sjkim
501167802Sjkim        Length = AcpiUtGetDescriptorLength (Aml);
502167802Sjkim
503167802Sjkim        /* Invoke the user function */
504167802Sjkim
505167802Sjkim        if (UserFunction)
506167802Sjkim        {
507167802Sjkim            Status = UserFunction (Aml, Length, Offset, ResourceIndex, Context);
508167802Sjkim            if (ACPI_FAILURE (Status))
509167802Sjkim            {
510228110Sjkim                return_ACPI_STATUS (Status);
511167802Sjkim            }
512167802Sjkim        }
513167802Sjkim
514167802Sjkim        /* An EndTag descriptor terminates this resource template */
515167802Sjkim
516167802Sjkim        if (AcpiUtGetResourceType (Aml) == ACPI_RESOURCE_NAME_END_TAG)
517167802Sjkim        {
518167802Sjkim            /*
519167802Sjkim             * There must be at least one more byte in the buffer for
520167802Sjkim             * the 2nd byte of the EndTag
521167802Sjkim             */
522167802Sjkim            if ((Aml + 1) >= EndAml)
523167802Sjkim            {
524167802Sjkim                return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
525167802Sjkim            }
526167802Sjkim
527167802Sjkim            /* Return the pointer to the EndTag if requested */
528167802Sjkim
529167802Sjkim            if (!UserFunction)
530167802Sjkim            {
531245582Sjkim                *Context = Aml;
532167802Sjkim            }
533167802Sjkim
534167802Sjkim            /* Normal exit */
535167802Sjkim
536167802Sjkim            return_ACPI_STATUS (AE_OK);
537167802Sjkim        }
538167802Sjkim
539167802Sjkim        Aml += Length;
540167802Sjkim        Offset += Length;
541167802Sjkim    }
542167802Sjkim
543167802Sjkim    /* Did not find an EndTag descriptor */
544167802Sjkim
545228110Sjkim    if (UserFunction)
546228110Sjkim    {
547228110Sjkim        /* Insert an EndTag anyway. AcpiRsGetListLength always leaves room */
548228110Sjkim
549243347Sjkim        (void) AcpiUtValidateResource (WalkState, EndTag, &ResourceIndex);
550228110Sjkim        Status = UserFunction (EndTag, 2, Offset, ResourceIndex, Context);
551228110Sjkim        if (ACPI_FAILURE (Status))
552228110Sjkim        {
553228110Sjkim            return_ACPI_STATUS (Status);
554228110Sjkim        }
555228110Sjkim    }
556228110Sjkim
557228110Sjkim    return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
558167802Sjkim}
559167802Sjkim
560167802Sjkim
561167802Sjkim/*******************************************************************************
562167802Sjkim *
563167802Sjkim * FUNCTION:    AcpiUtValidateResource
564167802Sjkim *
565243347Sjkim * PARAMETERS:  WalkState           - Current walk info
566243347Sjkim *              Aml                 - Pointer to the raw AML resource descriptor
567243347Sjkim *              ReturnIndex         - Where the resource index is returned. NULL
568243347Sjkim *                                    if the index is not required.
569167802Sjkim *
570167802Sjkim * RETURN:      Status, and optionally the Index into the global resource tables
571167802Sjkim *
572167802Sjkim * DESCRIPTION: Validate an AML resource descriptor by checking the Resource
573167802Sjkim *              Type and Resource Length. Returns an index into the global
574167802Sjkim *              resource information/dispatch tables for later use.
575167802Sjkim *
576167802Sjkim ******************************************************************************/
577167802Sjkim
578167802SjkimACPI_STATUS
579167802SjkimAcpiUtValidateResource (
580243347Sjkim    ACPI_WALK_STATE         *WalkState,
581167802Sjkim    void                    *Aml,
582167802Sjkim    UINT8                   *ReturnIndex)
583167802Sjkim{
584228110Sjkim    AML_RESOURCE            *AmlResource;
585167802Sjkim    UINT8                   ResourceType;
586167802Sjkim    UINT8                   ResourceIndex;
587167802Sjkim    ACPI_RS_LENGTH          ResourceLength;
588167802Sjkim    ACPI_RS_LENGTH          MinimumResourceLength;
589167802Sjkim
590167802Sjkim
591167802Sjkim    ACPI_FUNCTION_ENTRY ();
592167802Sjkim
593167802Sjkim
594167802Sjkim    /*
595167802Sjkim     * 1) Validate the ResourceType field (Byte 0)
596167802Sjkim     */
597167802Sjkim    ResourceType = ACPI_GET8 (Aml);
598167802Sjkim
599167802Sjkim    /*
600167802Sjkim     * Byte 0 contains the descriptor name (Resource Type)
601167802Sjkim     * Examine the large/small bit in the resource header
602167802Sjkim     */
603167802Sjkim    if (ResourceType & ACPI_RESOURCE_NAME_LARGE)
604167802Sjkim    {
605167802Sjkim        /* Verify the large resource type (name) against the max */
606167802Sjkim
607167802Sjkim        if (ResourceType > ACPI_RESOURCE_NAME_LARGE_MAX)
608167802Sjkim        {
609228110Sjkim            goto InvalidResource;
610167802Sjkim        }
611167802Sjkim
612167802Sjkim        /*
613167802Sjkim         * Large Resource Type -- bits 6:0 contain the name
614167802Sjkim         * Translate range 0x80-0x8B to index range 0x10-0x1B
615167802Sjkim         */
616167802Sjkim        ResourceIndex = (UINT8) (ResourceType - 0x70);
617167802Sjkim    }
618167802Sjkim    else
619167802Sjkim    {
620167802Sjkim        /*
621167802Sjkim         * Small Resource Type -- bits 6:3 contain the name
622167802Sjkim         * Shift range to index range 0x00-0x0F
623167802Sjkim         */
624167802Sjkim        ResourceIndex = (UINT8)
625167802Sjkim            ((ResourceType & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
626167802Sjkim    }
627167802Sjkim
628228110Sjkim    /*
629228110Sjkim     * Check validity of the resource type, via AcpiGbl_ResourceTypes. Zero
630228110Sjkim     * indicates an invalid resource.
631228110Sjkim     */
632167802Sjkim    if (!AcpiGbl_ResourceTypes[ResourceIndex])
633167802Sjkim    {
634228110Sjkim        goto InvalidResource;
635167802Sjkim    }
636167802Sjkim
637167802Sjkim    /*
638228110Sjkim     * Validate the ResourceLength field. This ensures that the length
639228110Sjkim     * is at least reasonable, and guarantees that it is non-zero.
640167802Sjkim     */
641167802Sjkim    ResourceLength = AcpiUtGetResourceLength (Aml);
642167802Sjkim    MinimumResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex];
643167802Sjkim
644167802Sjkim    /* Validate based upon the type of resource - fixed length or variable */
645167802Sjkim
646167802Sjkim    switch (AcpiGbl_ResourceTypes[ResourceIndex])
647167802Sjkim    {
648167802Sjkim    case ACPI_FIXED_LENGTH:
649167802Sjkim
650167802Sjkim        /* Fixed length resource, length must match exactly */
651167802Sjkim
652167802Sjkim        if (ResourceLength != MinimumResourceLength)
653167802Sjkim        {
654228110Sjkim            goto BadResourceLength;
655167802Sjkim        }
656167802Sjkim        break;
657167802Sjkim
658167802Sjkim    case ACPI_VARIABLE_LENGTH:
659167802Sjkim
660167802Sjkim        /* Variable length resource, length must be at least the minimum */
661167802Sjkim
662167802Sjkim        if (ResourceLength < MinimumResourceLength)
663167802Sjkim        {
664228110Sjkim            goto BadResourceLength;
665167802Sjkim        }
666167802Sjkim        break;
667167802Sjkim
668167802Sjkim    case ACPI_SMALL_VARIABLE_LENGTH:
669167802Sjkim
670167802Sjkim        /* Small variable length resource, length can be (Min) or (Min-1) */
671167802Sjkim
672167802Sjkim        if ((ResourceLength > MinimumResourceLength) ||
673167802Sjkim            (ResourceLength < (MinimumResourceLength - 1)))
674167802Sjkim        {
675228110Sjkim            goto BadResourceLength;
676167802Sjkim        }
677167802Sjkim        break;
678167802Sjkim
679167802Sjkim    default:
680167802Sjkim
681167802Sjkim        /* Shouldn't happen (because of validation earlier), but be sure */
682167802Sjkim
683228110Sjkim        goto InvalidResource;
684167802Sjkim    }
685167802Sjkim
686228110Sjkim    AmlResource = ACPI_CAST_PTR (AML_RESOURCE, Aml);
687228110Sjkim    if (ResourceType == ACPI_RESOURCE_NAME_SERIAL_BUS)
688228110Sjkim    {
689228110Sjkim        /* Validate the BusType field */
690228110Sjkim
691228110Sjkim        if ((AmlResource->CommonSerialBus.Type == 0) ||
692228110Sjkim            (AmlResource->CommonSerialBus.Type > AML_RESOURCE_MAX_SERIALBUSTYPE))
693228110Sjkim        {
694243347Sjkim            if (WalkState)
695243347Sjkim            {
696243347Sjkim                ACPI_ERROR ((AE_INFO,
697243347Sjkim                    "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X",
698243347Sjkim                    AmlResource->CommonSerialBus.Type));
699243347Sjkim            }
700228110Sjkim            return (AE_AML_INVALID_RESOURCE_TYPE);
701228110Sjkim        }
702228110Sjkim    }
703228110Sjkim
704167802Sjkim    /* Optionally return the resource table index */
705167802Sjkim
706167802Sjkim    if (ReturnIndex)
707167802Sjkim    {
708167802Sjkim        *ReturnIndex = ResourceIndex;
709167802Sjkim    }
710167802Sjkim
711167802Sjkim    return (AE_OK);
712228110Sjkim
713228110Sjkim
714228110SjkimInvalidResource:
715228110Sjkim
716243347Sjkim    if (WalkState)
717243347Sjkim    {
718243347Sjkim        ACPI_ERROR ((AE_INFO,
719243347Sjkim            "Invalid/unsupported resource descriptor: Type 0x%2.2X",
720243347Sjkim            ResourceType));
721243347Sjkim    }
722228110Sjkim    return (AE_AML_INVALID_RESOURCE_TYPE);
723228110Sjkim
724228110SjkimBadResourceLength:
725228110Sjkim
726243347Sjkim    if (WalkState)
727243347Sjkim    {
728243347Sjkim        ACPI_ERROR ((AE_INFO,
729243347Sjkim            "Invalid resource descriptor length: Type "
730243347Sjkim            "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X",
731243347Sjkim            ResourceType, ResourceLength, MinimumResourceLength));
732243347Sjkim    }
733228110Sjkim    return (AE_AML_BAD_RESOURCE_LENGTH);
734167802Sjkim}
735167802Sjkim
736167802Sjkim
737167802Sjkim/*******************************************************************************
738167802Sjkim *
739167802Sjkim * FUNCTION:    AcpiUtGetResourceType
740167802Sjkim *
741167802Sjkim * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
742167802Sjkim *
743167802Sjkim * RETURN:      The Resource Type with no extraneous bits (except the
744167802Sjkim *              Large/Small descriptor bit -- this is left alone)
745167802Sjkim *
746167802Sjkim * DESCRIPTION: Extract the Resource Type/Name from the first byte of
747167802Sjkim *              a resource descriptor.
748167802Sjkim *
749167802Sjkim ******************************************************************************/
750167802Sjkim
751167802SjkimUINT8
752167802SjkimAcpiUtGetResourceType (
753167802Sjkim    void                    *Aml)
754167802Sjkim{
755167802Sjkim    ACPI_FUNCTION_ENTRY ();
756167802Sjkim
757167802Sjkim
758167802Sjkim    /*
759167802Sjkim     * Byte 0 contains the descriptor name (Resource Type)
760167802Sjkim     * Examine the large/small bit in the resource header
761167802Sjkim     */
762167802Sjkim    if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE)
763167802Sjkim    {
764167802Sjkim        /* Large Resource Type -- bits 6:0 contain the name */
765167802Sjkim
766167802Sjkim        return (ACPI_GET8 (Aml));
767167802Sjkim    }
768167802Sjkim    else
769167802Sjkim    {
770167802Sjkim        /* Small Resource Type -- bits 6:3 contain the name */
771167802Sjkim
772167802Sjkim        return ((UINT8) (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_SMALL_MASK));
773167802Sjkim    }
774167802Sjkim}
775167802Sjkim
776167802Sjkim
777167802Sjkim/*******************************************************************************
778167802Sjkim *
779167802Sjkim * FUNCTION:    AcpiUtGetResourceLength
780167802Sjkim *
781167802Sjkim * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
782167802Sjkim *
783167802Sjkim * RETURN:      Byte Length
784167802Sjkim *
785167802Sjkim * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By
786167802Sjkim *              definition, this does not include the size of the descriptor
787167802Sjkim *              header or the length field itself.
788167802Sjkim *
789167802Sjkim ******************************************************************************/
790167802Sjkim
791167802SjkimUINT16
792167802SjkimAcpiUtGetResourceLength (
793167802Sjkim    void                    *Aml)
794167802Sjkim{
795167802Sjkim    ACPI_RS_LENGTH          ResourceLength;
796167802Sjkim
797167802Sjkim
798167802Sjkim    ACPI_FUNCTION_ENTRY ();
799167802Sjkim
800167802Sjkim
801167802Sjkim    /*
802167802Sjkim     * Byte 0 contains the descriptor name (Resource Type)
803167802Sjkim     * Examine the large/small bit in the resource header
804167802Sjkim     */
805167802Sjkim    if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE)
806167802Sjkim    {
807167802Sjkim        /* Large Resource type -- bytes 1-2 contain the 16-bit length */
808167802Sjkim
809167802Sjkim        ACPI_MOVE_16_TO_16 (&ResourceLength, ACPI_ADD_PTR (UINT8, Aml, 1));
810167802Sjkim
811167802Sjkim    }
812167802Sjkim    else
813167802Sjkim    {
814167802Sjkim        /* Small Resource type -- bits 2:0 of byte 0 contain the length */
815167802Sjkim
816167802Sjkim        ResourceLength = (UINT16) (ACPI_GET8 (Aml) &
817167802Sjkim                                    ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
818167802Sjkim    }
819167802Sjkim
820167802Sjkim    return (ResourceLength);
821167802Sjkim}
822167802Sjkim
823167802Sjkim
824167802Sjkim/*******************************************************************************
825167802Sjkim *
826167802Sjkim * FUNCTION:    AcpiUtGetResourceHeaderLength
827167802Sjkim *
828167802Sjkim * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
829167802Sjkim *
830167802Sjkim * RETURN:      Length of the AML header (depends on large/small descriptor)
831167802Sjkim *
832167802Sjkim * DESCRIPTION: Get the length of the header for this resource.
833167802Sjkim *
834167802Sjkim ******************************************************************************/
835167802Sjkim
836167802SjkimUINT8
837167802SjkimAcpiUtGetResourceHeaderLength (
838167802Sjkim    void                    *Aml)
839167802Sjkim{
840167802Sjkim    ACPI_FUNCTION_ENTRY ();
841167802Sjkim
842167802Sjkim
843167802Sjkim    /* Examine the large/small bit in the resource header */
844167802Sjkim
845167802Sjkim    if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE)
846167802Sjkim    {
847167802Sjkim        return (sizeof (AML_RESOURCE_LARGE_HEADER));
848167802Sjkim    }
849167802Sjkim    else
850167802Sjkim    {
851167802Sjkim        return (sizeof (AML_RESOURCE_SMALL_HEADER));
852167802Sjkim    }
853167802Sjkim}
854167802Sjkim
855167802Sjkim
856167802Sjkim/*******************************************************************************
857167802Sjkim *
858167802Sjkim * FUNCTION:    AcpiUtGetDescriptorLength
859167802Sjkim *
860167802Sjkim * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
861167802Sjkim *
862167802Sjkim * RETURN:      Byte length
863167802Sjkim *
864167802Sjkim * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the
865167802Sjkim *              length of the descriptor header and the length field itself.
866167802Sjkim *              Used to walk descriptor lists.
867167802Sjkim *
868167802Sjkim ******************************************************************************/
869167802Sjkim
870167802SjkimUINT32
871167802SjkimAcpiUtGetDescriptorLength (
872167802Sjkim    void                    *Aml)
873167802Sjkim{
874167802Sjkim    ACPI_FUNCTION_ENTRY ();
875167802Sjkim
876167802Sjkim
877167802Sjkim    /*
878167802Sjkim     * Get the Resource Length (does not include header length) and add
879167802Sjkim     * the header length (depends on if this is a small or large resource)
880167802Sjkim     */
881167802Sjkim    return (AcpiUtGetResourceLength (Aml) +
882167802Sjkim            AcpiUtGetResourceHeaderLength (Aml));
883167802Sjkim}
884167802Sjkim
885167802Sjkim
886167802Sjkim/*******************************************************************************
887167802Sjkim *
888167802Sjkim * FUNCTION:    AcpiUtGetResourceEndTag
889167802Sjkim *
890167802Sjkim * PARAMETERS:  ObjDesc         - The resource template buffer object
891167802Sjkim *              EndTag          - Where the pointer to the EndTag is returned
892167802Sjkim *
893167802Sjkim * RETURN:      Status, pointer to the end tag
894167802Sjkim *
895167802Sjkim * DESCRIPTION: Find the EndTag resource descriptor in an AML resource template
896167802Sjkim *              Note: allows a buffer length of zero.
897167802Sjkim *
898167802Sjkim ******************************************************************************/
899167802Sjkim
900167802SjkimACPI_STATUS
901167802SjkimAcpiUtGetResourceEndTag (
902167802Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc,
903167802Sjkim    UINT8                   **EndTag)
904167802Sjkim{
905167802Sjkim    ACPI_STATUS             Status;
906167802Sjkim
907167802Sjkim
908167802Sjkim    ACPI_FUNCTION_TRACE (UtGetResourceEndTag);
909167802Sjkim
910167802Sjkim
911167802Sjkim    /* Allow a buffer length of zero */
912167802Sjkim
913167802Sjkim    if (!ObjDesc->Buffer.Length)
914167802Sjkim    {
915167802Sjkim        *EndTag = ObjDesc->Buffer.Pointer;
916167802Sjkim        return_ACPI_STATUS (AE_OK);
917167802Sjkim    }
918167802Sjkim
919167802Sjkim    /* Validate the template and get a pointer to the EndTag */
920167802Sjkim
921243347Sjkim    Status = AcpiUtWalkAmlResources (NULL, ObjDesc->Buffer.Pointer,
922245582Sjkim                ObjDesc->Buffer.Length, NULL, (void **) EndTag);
923167802Sjkim
924167802Sjkim    return_ACPI_STATUS (Status);
925167802Sjkim}
926