1167802Sjkim/*******************************************************************************
2167802Sjkim *
3238381Sjkim * Module Name: utresrc - Resource management utilities
4167802Sjkim *
5167802Sjkim ******************************************************************************/
6167802Sjkim
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, 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
44193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
45193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
46228110Sjkim#include <contrib/dev/acpica/include/acresrc.h>
47167802Sjkim
48167802Sjkim
49167802Sjkim#define _COMPONENT          ACPI_UTILITIES
50167802Sjkim        ACPI_MODULE_NAME    ("utresrc")
51167802Sjkim
52167802Sjkim
53281075Sdim#if defined(ACPI_DEBUG_OUTPUT) || defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
54167802Sjkim
55167802Sjkim/*
56167802Sjkim * Strings used to decode resource descriptors.
57238381Sjkim * Used by both the disassembler and the debugger resource dump routines
58167802Sjkim */
59167802Sjkimconst char                      *AcpiGbl_BmDecode[] =
60167802Sjkim{
61167802Sjkim    "NotBusMaster",
62167802Sjkim    "BusMaster"
63167802Sjkim};
64167802Sjkim
65167802Sjkimconst char                      *AcpiGbl_ConfigDecode[] =
66167802Sjkim{
67167802Sjkim    "0 - Good Configuration",
68167802Sjkim    "1 - Acceptable Configuration",
69167802Sjkim    "2 - Suboptimal Configuration",
70167802Sjkim    "3 - ***Invalid Configuration***",
71167802Sjkim};
72167802Sjkim
73167802Sjkimconst char                      *AcpiGbl_ConsumeDecode[] =
74167802Sjkim{
75167802Sjkim    "ResourceProducer",
76167802Sjkim    "ResourceConsumer"
77167802Sjkim};
78167802Sjkim
79167802Sjkimconst char                      *AcpiGbl_DecDecode[] =
80167802Sjkim{
81167802Sjkim    "PosDecode",
82167802Sjkim    "SubDecode"
83167802Sjkim};
84167802Sjkim
85167802Sjkimconst char                      *AcpiGbl_HeDecode[] =
86167802Sjkim{
87167802Sjkim    "Level",
88167802Sjkim    "Edge"
89167802Sjkim};
90167802Sjkim
91167802Sjkimconst char                      *AcpiGbl_IoDecode[] =
92167802Sjkim{
93167802Sjkim    "Decode10",
94167802Sjkim    "Decode16"
95167802Sjkim};
96167802Sjkim
97167802Sjkimconst char                      *AcpiGbl_LlDecode[] =
98167802Sjkim{
99167802Sjkim    "ActiveHigh",
100281075Sdim    "ActiveLow",
101281075Sdim    "ActiveBoth",
102281075Sdim    "Reserved"
103167802Sjkim};
104167802Sjkim
105167802Sjkimconst char                      *AcpiGbl_MaxDecode[] =
106167802Sjkim{
107167802Sjkim    "MaxNotFixed",
108167802Sjkim    "MaxFixed"
109167802Sjkim};
110167802Sjkim
111167802Sjkimconst char                      *AcpiGbl_MemDecode[] =
112167802Sjkim{
113167802Sjkim    "NonCacheable",
114167802Sjkim    "Cacheable",
115167802Sjkim    "WriteCombining",
116167802Sjkim    "Prefetchable"
117167802Sjkim};
118167802Sjkim
119167802Sjkimconst char                      *AcpiGbl_MinDecode[] =
120167802Sjkim{
121167802Sjkim    "MinNotFixed",
122167802Sjkim    "MinFixed"
123167802Sjkim};
124167802Sjkim
125167802Sjkimconst char                      *AcpiGbl_MtpDecode[] =
126167802Sjkim{
127167802Sjkim    "AddressRangeMemory",
128167802Sjkim    "AddressRangeReserved",
129167802Sjkim    "AddressRangeACPI",
130167802Sjkim    "AddressRangeNVS"
131167802Sjkim};
132167802Sjkim
133167802Sjkimconst char                      *AcpiGbl_RngDecode[] =
134167802Sjkim{
135167802Sjkim    "InvalidRanges",
136167802Sjkim    "NonISAOnlyRanges",
137167802Sjkim    "ISAOnlyRanges",
138167802Sjkim    "EntireRange"
139167802Sjkim};
140167802Sjkim
141167802Sjkimconst char                      *AcpiGbl_RwDecode[] =
142167802Sjkim{
143167802Sjkim    "ReadOnly",
144167802Sjkim    "ReadWrite"
145167802Sjkim};
146167802Sjkim
147167802Sjkimconst char                      *AcpiGbl_ShrDecode[] =
148167802Sjkim{
149167802Sjkim    "Exclusive",
150243347Sjkim    "Shared",
151243347Sjkim    "ExclusiveAndWake",         /* ACPI 5.0 */
152243347Sjkim    "SharedAndWake"             /* ACPI 5.0 */
153167802Sjkim};
154167802Sjkim
155167802Sjkimconst char                      *AcpiGbl_SizDecode[] =
156167802Sjkim{
157167802Sjkim    "Transfer8",
158167802Sjkim    "Transfer8_16",
159167802Sjkim    "Transfer16",
160167802Sjkim    "InvalidSize"
161167802Sjkim};
162167802Sjkim
163167802Sjkimconst char                      *AcpiGbl_TrsDecode[] =
164167802Sjkim{
165167802Sjkim    "DenseTranslation",
166167802Sjkim    "SparseTranslation"
167167802Sjkim};
168167802Sjkim
169167802Sjkimconst char                      *AcpiGbl_TtpDecode[] =
170167802Sjkim{
171167802Sjkim    "TypeStatic",
172167802Sjkim    "TypeTranslation"
173167802Sjkim};
174167802Sjkim
175167802Sjkimconst char                      *AcpiGbl_TypDecode[] =
176167802Sjkim{
177167802Sjkim    "Compatibility",
178167802Sjkim    "TypeA",
179167802Sjkim    "TypeB",
180167802Sjkim    "TypeF"
181167802Sjkim};
182167802Sjkim
183228110Sjkimconst char                      *AcpiGbl_PpcDecode[] =
184228110Sjkim{
185228110Sjkim    "PullDefault",
186228110Sjkim    "PullUp",
187228110Sjkim    "PullDown",
188228110Sjkim    "PullNone"
189228110Sjkim};
190228110Sjkim
191228110Sjkimconst char                      *AcpiGbl_IorDecode[] =
192228110Sjkim{
193228110Sjkim    "IoRestrictionNone",
194228110Sjkim    "IoRestrictionInputOnly",
195228110Sjkim    "IoRestrictionOutputOnly",
196228110Sjkim    "IoRestrictionNoneAndPreserve"
197228110Sjkim};
198228110Sjkim
199228110Sjkimconst char                      *AcpiGbl_DtsDecode[] =
200228110Sjkim{
201228110Sjkim    "Width8bit",
202228110Sjkim    "Width16bit",
203228110Sjkim    "Width32bit",
204228110Sjkim    "Width64bit",
205228110Sjkim    "Width128bit",
206228110Sjkim    "Width256bit",
207228110Sjkim};
208228110Sjkim
209228110Sjkim/* GPIO connection type */
210228110Sjkim
211228110Sjkimconst char                      *AcpiGbl_CtDecode[] =
212228110Sjkim{
213228110Sjkim    "Interrupt",
214228110Sjkim    "I/O"
215228110Sjkim};
216228110Sjkim
217228110Sjkim/* Serial bus type */
218228110Sjkim
219228110Sjkimconst char                      *AcpiGbl_SbtDecode[] =
220228110Sjkim{
221228110Sjkim    "/* UNKNOWN serial bus type */",
222228110Sjkim    "I2C",
223228110Sjkim    "SPI",
224228110Sjkim    "UART"
225228110Sjkim};
226228110Sjkim
227228110Sjkim/* I2C serial bus access mode */
228228110Sjkim
229228110Sjkimconst char                      *AcpiGbl_AmDecode[] =
230228110Sjkim{
231228110Sjkim    "AddressingMode7Bit",
232228110Sjkim    "AddressingMode10Bit"
233228110Sjkim};
234228110Sjkim
235228110Sjkim/* I2C serial bus slave mode */
236228110Sjkim
237228110Sjkimconst char                      *AcpiGbl_SmDecode[] =
238228110Sjkim{
239228110Sjkim    "ControllerInitiated",
240228110Sjkim    "DeviceInitiated"
241228110Sjkim};
242228110Sjkim
243228110Sjkim/* SPI serial bus wire mode */
244228110Sjkim
245228110Sjkimconst char                      *AcpiGbl_WmDecode[] =
246228110Sjkim{
247228110Sjkim    "FourWireMode",
248228110Sjkim    "ThreeWireMode"
249228110Sjkim};
250228110Sjkim
251228110Sjkim/* SPI serial clock phase */
252228110Sjkim
253228110Sjkimconst char                      *AcpiGbl_CphDecode[] =
254228110Sjkim{
255228110Sjkim    "ClockPhaseFirst",
256228110Sjkim    "ClockPhaseSecond"
257228110Sjkim};
258228110Sjkim
259228110Sjkim/* SPI serial bus clock polarity */
260228110Sjkim
261228110Sjkimconst char                      *AcpiGbl_CpoDecode[] =
262228110Sjkim{
263228110Sjkim    "ClockPolarityLow",
264228110Sjkim    "ClockPolarityHigh"
265228110Sjkim};
266228110Sjkim
267228110Sjkim/* SPI serial bus device polarity */
268228110Sjkim
269228110Sjkimconst char                      *AcpiGbl_DpDecode[] =
270228110Sjkim{
271228110Sjkim    "PolarityLow",
272228110Sjkim    "PolarityHigh"
273228110Sjkim};
274228110Sjkim
275228110Sjkim/* UART serial bus endian */
276228110Sjkim
277228110Sjkimconst char                      *AcpiGbl_EdDecode[] =
278228110Sjkim{
279228110Sjkim    "LittleEndian",
280228110Sjkim    "BigEndian"
281228110Sjkim};
282228110Sjkim
283228110Sjkim/* UART serial bus bits per byte */
284228110Sjkim
285228110Sjkimconst char                      *AcpiGbl_BpbDecode[] =
286228110Sjkim{
287228110Sjkim    "DataBitsFive",
288228110Sjkim    "DataBitsSix",
289228110Sjkim    "DataBitsSeven",
290228110Sjkim    "DataBitsEight",
291228110Sjkim    "DataBitsNine",
292228110Sjkim    "/* UNKNOWN Bits per byte */",
293228110Sjkim    "/* UNKNOWN Bits per byte */",
294228110Sjkim    "/* UNKNOWN Bits per byte */"
295228110Sjkim};
296228110Sjkim
297228110Sjkim/* UART serial bus stop bits */
298228110Sjkim
299228110Sjkimconst char                      *AcpiGbl_SbDecode[] =
300228110Sjkim{
301281075Sdim    "StopBitsZero",
302228110Sjkim    "StopBitsOne",
303228110Sjkim    "StopBitsOnePlusHalf",
304228110Sjkim    "StopBitsTwo"
305228110Sjkim};
306228110Sjkim
307228110Sjkim/* UART serial bus flow control */
308228110Sjkim
309228110Sjkimconst char                      *AcpiGbl_FcDecode[] =
310228110Sjkim{
311228110Sjkim    "FlowControlNone",
312228110Sjkim    "FlowControlHardware",
313228110Sjkim    "FlowControlXON",
314228110Sjkim    "/* UNKNOWN flow control keyword */"
315228110Sjkim};
316228110Sjkim
317228110Sjkim/* UART serial bus parity type */
318228110Sjkim
319228110Sjkimconst char                      *AcpiGbl_PtDecode[] =
320228110Sjkim{
321228110Sjkim    "ParityTypeNone",
322228110Sjkim    "ParityTypeEven",
323228110Sjkim    "ParityTypeOdd",
324228110Sjkim    "ParityTypeMark",
325228110Sjkim    "ParityTypeSpace",
326228110Sjkim    "/* UNKNOWN parity keyword */",
327228110Sjkim    "/* UNKNOWN parity keyword */",
328228110Sjkim    "/* UNKNOWN parity keyword */"
329228110Sjkim};
330228110Sjkim
331167802Sjkim#endif
332167802Sjkim
333167802Sjkim
334167802Sjkim/*
335167802Sjkim * Base sizes of the raw AML resource descriptors, indexed by resource type.
336167802Sjkim * Zero indicates a reserved (and therefore invalid) resource type.
337167802Sjkim */
338167802Sjkimconst UINT8                 AcpiGbl_ResourceAmlSizes[] =
339167802Sjkim{
340167802Sjkim    /* Small descriptors */
341167802Sjkim
342167802Sjkim    0,
343167802Sjkim    0,
344167802Sjkim    0,
345167802Sjkim    0,
346167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_IRQ),
347167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_DMA),
348167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_START_DEPENDENT),
349167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_DEPENDENT),
350167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_IO),
351167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_IO),
352228110Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_DMA),
353167802Sjkim    0,
354167802Sjkim    0,
355167802Sjkim    0,
356167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_VENDOR_SMALL),
357167802Sjkim    ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_TAG),
358167802Sjkim
359167802Sjkim    /* Large descriptors */
360167802Sjkim
361167802Sjkim    0,
362167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY24),
363167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_GENERIC_REGISTER),
364167802Sjkim    0,
365167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_VENDOR_LARGE),
366167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY32),
367167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_FIXED_MEMORY32),
368167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS32),
369167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS16),
370167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_IRQ),
371167802Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS64),
372228110Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_ADDRESS64),
373228110Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_GPIO),
374228110Sjkim    0,
375228110Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_COMMON_SERIALBUS),
376167802Sjkim};
377167802Sjkim
378228110Sjkimconst UINT8                 AcpiGbl_ResourceAmlSerialBusSizes[] =
379228110Sjkim{
380228110Sjkim    0,
381228110Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_I2C_SERIALBUS),
382228110Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_SPI_SERIALBUS),
383228110Sjkim    ACPI_AML_SIZE_LARGE (AML_RESOURCE_UART_SERIALBUS),
384228110Sjkim};
385167802Sjkim
386228110Sjkim
387167802Sjkim/*
388167802Sjkim * Resource types, used to validate the resource length field.
389167802Sjkim * The length of fixed-length types must match exactly, variable
390167802Sjkim * lengths must meet the minimum required length, etc.
391167802Sjkim * Zero indicates a reserved (and therefore invalid) resource type.
392167802Sjkim */
393167802Sjkimstatic const UINT8          AcpiGbl_ResourceTypes[] =
394167802Sjkim{
395167802Sjkim    /* Small descriptors */
396167802Sjkim
397167802Sjkim    0,
398167802Sjkim    0,
399167802Sjkim    0,
400167802Sjkim    0,
401228110Sjkim    ACPI_SMALL_VARIABLE_LENGTH,     /* 04 IRQ */
402228110Sjkim    ACPI_FIXED_LENGTH,              /* 05 DMA */
403228110Sjkim    ACPI_SMALL_VARIABLE_LENGTH,     /* 06 StartDependentFunctions */
404228110Sjkim    ACPI_FIXED_LENGTH,              /* 07 EndDependentFunctions */
405228110Sjkim    ACPI_FIXED_LENGTH,              /* 08 IO */
406228110Sjkim    ACPI_FIXED_LENGTH,              /* 09 FixedIO */
407228110Sjkim    ACPI_FIXED_LENGTH,              /* 0A FixedDMA */
408167802Sjkim    0,
409167802Sjkim    0,
410167802Sjkim    0,
411228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 0E VendorShort */
412228110Sjkim    ACPI_FIXED_LENGTH,              /* 0F EndTag */
413167802Sjkim
414167802Sjkim    /* Large descriptors */
415167802Sjkim
416167802Sjkim    0,
417228110Sjkim    ACPI_FIXED_LENGTH,              /* 01 Memory24 */
418228110Sjkim    ACPI_FIXED_LENGTH,              /* 02 GenericRegister */
419167802Sjkim    0,
420228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 04 VendorLong */
421228110Sjkim    ACPI_FIXED_LENGTH,              /* 05 Memory32 */
422228110Sjkim    ACPI_FIXED_LENGTH,              /* 06 Memory32Fixed */
423228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 07 Dword* address */
424228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 08 Word* address */
425228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 09 ExtendedIRQ */
426228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 0A Qword* address */
427228110Sjkim    ACPI_FIXED_LENGTH,              /* 0B Extended* address */
428228110Sjkim    ACPI_VARIABLE_LENGTH,           /* 0C Gpio* */
429228110Sjkim    0,
430228110Sjkim    ACPI_VARIABLE_LENGTH            /* 0E *SerialBus */
431167802Sjkim};
432167802Sjkim
433167802Sjkim
434167802Sjkim/*******************************************************************************
435167802Sjkim *
436167802Sjkim * FUNCTION:    AcpiUtWalkAmlResources
437167802Sjkim *
438243347Sjkim * PARAMETERS:  WalkState           - Current walk info
439243347Sjkim * PARAMETERS:  Aml                 - Pointer to the raw AML resource template
440243347Sjkim *              AmlLength           - Length of the entire template
441243347Sjkim *              UserFunction        - Called once for each descriptor found. If
442243347Sjkim *                                    NULL, a pointer to the EndTag is returned
443243347Sjkim *              Context             - Passed to UserFunction
444167802Sjkim *
445167802Sjkim * RETURN:      Status
446167802Sjkim *
447167802Sjkim * DESCRIPTION: Walk a raw AML resource list(buffer). User function called
448167802Sjkim *              once for each resource found.
449167802Sjkim *
450167802Sjkim ******************************************************************************/
451167802Sjkim
452167802SjkimACPI_STATUS
453167802SjkimAcpiUtWalkAmlResources (
454243347Sjkim    ACPI_WALK_STATE         *WalkState,
455167802Sjkim    UINT8                   *Aml,
456167802Sjkim    ACPI_SIZE               AmlLength,
457167802Sjkim    ACPI_WALK_AML_CALLBACK  UserFunction,
458245582Sjkim    void                    **Context)
459167802Sjkim{
460167802Sjkim    ACPI_STATUS             Status;
461167802Sjkim    UINT8                   *EndAml;
462167802Sjkim    UINT8                   ResourceIndex;
463167802Sjkim    UINT32                  Length;
464167802Sjkim    UINT32                  Offset = 0;
465228110Sjkim    UINT8                   EndTag[2] = {0x79, 0x00};
466167802Sjkim
467167802Sjkim
468167802Sjkim    ACPI_FUNCTION_TRACE (UtWalkAmlResources);
469167802Sjkim
470167802Sjkim
471167802Sjkim    /* The absolute minimum resource template is one EndTag descriptor */
472167802Sjkim
473167802Sjkim    if (AmlLength < sizeof (AML_RESOURCE_END_TAG))
474167802Sjkim    {
475167802Sjkim        return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
476167802Sjkim    }
477167802Sjkim
478167802Sjkim    /* Point to the end of the resource template buffer */
479167802Sjkim
480167802Sjkim    EndAml = Aml + AmlLength;
481167802Sjkim
482167802Sjkim    /* Walk the byte list, abort on any invalid descriptor type or length */
483167802Sjkim
484167802Sjkim    while (Aml < EndAml)
485167802Sjkim    {
486167802Sjkim        /* Validate the Resource Type and Resource Length */
487167802Sjkim
488243347Sjkim        Status = AcpiUtValidateResource (WalkState, Aml, &ResourceIndex);
489167802Sjkim        if (ACPI_FAILURE (Status))
490167802Sjkim        {
491228110Sjkim            /*
492306536Sjkim             * Exit on failure. Cannot continue because the descriptor
493306536Sjkim             * length may be bogus also.
494228110Sjkim             */
495167802Sjkim            return_ACPI_STATUS (Status);
496167802Sjkim        }
497167802Sjkim
498167802Sjkim        /* Get the length of this descriptor */
499167802Sjkim
500167802Sjkim        Length = AcpiUtGetDescriptorLength (Aml);
501167802Sjkim
502167802Sjkim        /* Invoke the user function */
503167802Sjkim
504167802Sjkim        if (UserFunction)
505167802Sjkim        {
506306536Sjkim            Status = UserFunction (
507306536Sjkim                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    /*
629306536Sjkim     * Check validity of the resource type, via AcpiGbl_ResourceTypes.
630306536Sjkim     * Zero 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) &
817306536Sjkim            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) +
882306536Sjkim        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,
922306536Sjkim        ObjDesc->Buffer.Length, NULL, (void **) EndTag);
923167802Sjkim
924167802Sjkim    return_ACPI_STATUS (Status);
925167802Sjkim}
926