1 /*******************************************************************************
2  *
3  * Module Name: utresrc - Resource management utilities
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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 #include "acpi.h"
45 #include "accommon.h"
46 #include "acresrc.h"
47 
48 
49 #define _COMPONENT          ACPI_UTILITIES
50         ACPI_MODULE_NAME    ("utresrc")
51 
52 
53 /*
54  * Base sizes of the raw AML resource descriptors, indexed by resource type.
55  * Zero indicates a reserved (and therefore invalid) resource type.
56  */
57 const UINT8                 AcpiGbl_ResourceAmlSizes[] =
58 {
59     /* Small descriptors */
60 
61     0,
62     0,
63     0,
64     0,
65     ACPI_AML_SIZE_SMALL (AML_RESOURCE_IRQ),
66     ACPI_AML_SIZE_SMALL (AML_RESOURCE_DMA),
67     ACPI_AML_SIZE_SMALL (AML_RESOURCE_START_DEPENDENT),
68     ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_DEPENDENT),
69     ACPI_AML_SIZE_SMALL (AML_RESOURCE_IO),
70     ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_IO),
71     ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_DMA),
72     0,
73     0,
74     0,
75     ACPI_AML_SIZE_SMALL (AML_RESOURCE_VENDOR_SMALL),
76     ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_TAG),
77 
78     /* Large descriptors */
79 
80     0,
81     ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY24),
82     ACPI_AML_SIZE_LARGE (AML_RESOURCE_GENERIC_REGISTER),
83     0,
84     ACPI_AML_SIZE_LARGE (AML_RESOURCE_VENDOR_LARGE),
85     ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY32),
86     ACPI_AML_SIZE_LARGE (AML_RESOURCE_FIXED_MEMORY32),
87     ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS32),
88     ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS16),
89     ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_IRQ),
90     ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS64),
91     ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_ADDRESS64),
92     ACPI_AML_SIZE_LARGE (AML_RESOURCE_GPIO),
93     ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_FUNCTION),
94     ACPI_AML_SIZE_LARGE (AML_RESOURCE_COMMON_SERIALBUS),
95     ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_CONFIG),
96     ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_GROUP),
97     ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_GROUP_FUNCTION),
98     ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_GROUP_CONFIG),
99 };
100 
101 const UINT8                 AcpiGbl_ResourceAmlSerialBusSizes[] =
102 {
103     0,
104     ACPI_AML_SIZE_LARGE (AML_RESOURCE_I2C_SERIALBUS),
105     ACPI_AML_SIZE_LARGE (AML_RESOURCE_SPI_SERIALBUS),
106     ACPI_AML_SIZE_LARGE (AML_RESOURCE_UART_SERIALBUS),
107     ACPI_AML_SIZE_LARGE (AML_RESOURCE_CSI2_SERIALBUS),
108 };
109 
110 
111 /*
112  * Resource types, used to validate the resource length field.
113  * The length of fixed-length types must match exactly, variable
114  * lengths must meet the minimum required length, etc.
115  * Zero indicates a reserved (and therefore invalid) resource type.
116  */
117 static const UINT8          AcpiGbl_ResourceTypes[] =
118 {
119     /* Small descriptors */
120 
121     0,
122     0,
123     0,
124     0,
125     ACPI_SMALL_VARIABLE_LENGTH,     /* 04 IRQ */
126     ACPI_FIXED_LENGTH,              /* 05 DMA */
127     ACPI_SMALL_VARIABLE_LENGTH,     /* 06 StartDependentFunctions */
128     ACPI_FIXED_LENGTH,              /* 07 EndDependentFunctions */
129     ACPI_FIXED_LENGTH,              /* 08 IO */
130     ACPI_FIXED_LENGTH,              /* 09 FixedIO */
131     ACPI_FIXED_LENGTH,              /* 0A FixedDMA */
132     0,
133     0,
134     0,
135     ACPI_VARIABLE_LENGTH,           /* 0E VendorShort */
136     ACPI_FIXED_LENGTH,              /* 0F EndTag */
137 
138     /* Large descriptors */
139 
140     0,
141     ACPI_FIXED_LENGTH,              /* 01 Memory24 */
142     ACPI_FIXED_LENGTH,              /* 02 GenericRegister */
143     0,
144     ACPI_VARIABLE_LENGTH,           /* 04 VendorLong */
145     ACPI_FIXED_LENGTH,              /* 05 Memory32 */
146     ACPI_FIXED_LENGTH,              /* 06 Memory32Fixed */
147     ACPI_VARIABLE_LENGTH,           /* 07 Dword* address */
148     ACPI_VARIABLE_LENGTH,           /* 08 Word* address */
149     ACPI_VARIABLE_LENGTH,           /* 09 ExtendedIRQ */
150     ACPI_VARIABLE_LENGTH,           /* 0A Qword* address */
151     ACPI_FIXED_LENGTH,              /* 0B Extended* address */
152     ACPI_VARIABLE_LENGTH,           /* 0C Gpio* */
153     ACPI_VARIABLE_LENGTH,           /* 0D PinFunction */
154     ACPI_VARIABLE_LENGTH,           /* 0E *SerialBus */
155     ACPI_VARIABLE_LENGTH,           /* 0F PinConfig */
156     ACPI_VARIABLE_LENGTH,           /* 10 PinGroup */
157     ACPI_VARIABLE_LENGTH,           /* 11 PinGroupFunction */
158     ACPI_VARIABLE_LENGTH,           /* 12 PinGroupConfig */
159 };
160 
161 
162 /*******************************************************************************
163  *
164  * FUNCTION:    AcpiUtWalkAmlResources
165  *
166  * PARAMETERS:  WalkState           - Current walk info
167  * PARAMETERS:  Aml                 - Pointer to the raw AML resource template
168  *              AmlLength           - Length of the entire template
169  *              UserFunction        - Called once for each descriptor found. If
170  *                                    NULL, a pointer to the EndTag is returned
171  *              Context             - Passed to UserFunction
172  *
173  * RETURN:      Status
174  *
175  * DESCRIPTION: Walk a raw AML resource list(buffer). User function called
176  *              once for each resource found.
177  *
178  ******************************************************************************/
179 
180 ACPI_STATUS
AcpiUtWalkAmlResources(ACPI_WALK_STATE * WalkState,UINT8 * Aml,ACPI_SIZE AmlLength,ACPI_WALK_AML_CALLBACK UserFunction,void ** Context)181 AcpiUtWalkAmlResources (
182     ACPI_WALK_STATE         *WalkState,
183     UINT8                   *Aml,
184     ACPI_SIZE               AmlLength,
185     ACPI_WALK_AML_CALLBACK  UserFunction,
186     void                    **Context)
187 {
188     ACPI_STATUS             Status;
189     UINT8                   *EndAml;
190     UINT8                   ResourceIndex;
191     UINT32                  Length;
192     UINT32                  Offset = 0;
193     UINT8                   EndTag[2] = {0x79, 0x00};
194 
195 
196     ACPI_FUNCTION_TRACE (UtWalkAmlResources);
197 
198 
199     /* The absolute minimum resource template is one EndTag descriptor */
200 
201     if (AmlLength < sizeof (AML_RESOURCE_END_TAG))
202     {
203         return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
204     }
205 
206     /* Point to the end of the resource template buffer */
207 
208     EndAml = Aml + AmlLength;
209 
210     /* Walk the byte list, abort on any invalid descriptor type or length */
211 
212     while (Aml < EndAml)
213     {
214         /* Validate the Resource Type and Resource Length */
215 
216         Status = AcpiUtValidateResource (WalkState, Aml, &ResourceIndex);
217         if (ACPI_FAILURE (Status))
218         {
219             /*
220              * Exit on failure. Cannot continue because the descriptor
221              * length may be bogus also.
222              */
223             return_ACPI_STATUS (Status);
224         }
225 
226         /* Get the length of this descriptor */
227 
228         Length = AcpiUtGetDescriptorLength (Aml);
229 
230         /* Invoke the user function */
231 
232         if (UserFunction)
233         {
234             Status = UserFunction (
235                 Aml, Length, Offset, ResourceIndex, Context);
236             if (ACPI_FAILURE (Status))
237             {
238                 return_ACPI_STATUS (Status);
239             }
240         }
241 
242         /* An EndTag descriptor terminates this resource template */
243 
244         if (AcpiUtGetResourceType (Aml) == ACPI_RESOURCE_NAME_END_TAG)
245         {
246             /*
247              * There must be at least one more byte in the buffer for
248              * the 2nd byte of the EndTag
249              */
250             if ((Aml + 1) >= EndAml)
251             {
252                 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
253             }
254 
255             /*
256              * Don't attempt to perform any validation on the 2nd byte.
257              * Although all known ASL compilers insert a zero for the 2nd
258              * byte, it can also be a checksum (as per the ACPI spec),
259              * and this is occasionally seen in the field. July 2017.
260              */
261 
262             /* Return the pointer to the EndTag if requested */
263 
264             if (!UserFunction)
265             {
266                 *Context = Aml;
267             }
268 
269             /* Normal exit */
270 
271             return_ACPI_STATUS (AE_OK);
272         }
273 
274         Aml += Length;
275         Offset += Length;
276     }
277 
278     /* Did not find an EndTag descriptor */
279 
280     if (UserFunction)
281     {
282         /* Insert an EndTag anyway. AcpiRsGetListLength always leaves room */
283 
284         (void) AcpiUtValidateResource (WalkState, EndTag, &ResourceIndex);
285         Status = UserFunction (EndTag, 2, Offset, ResourceIndex, Context);
286         if (ACPI_FAILURE (Status))
287         {
288             return_ACPI_STATUS (Status);
289         }
290     }
291 
292     return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
293 }
294 
295 
296 /*******************************************************************************
297  *
298  * FUNCTION:    AcpiUtValidateResource
299  *
300  * PARAMETERS:  WalkState           - Current walk info
301  *              Aml                 - Pointer to the raw AML resource descriptor
302  *              ReturnIndex         - Where the resource index is returned. NULL
303  *                                    if the index is not required.
304  *
305  * RETURN:      Status, and optionally the Index into the global resource tables
306  *
307  * DESCRIPTION: Validate an AML resource descriptor by checking the Resource
308  *              Type and Resource Length. Returns an index into the global
309  *              resource information/dispatch tables for later use.
310  *
311  ******************************************************************************/
312 
313 ACPI_STATUS
AcpiUtValidateResource(ACPI_WALK_STATE * WalkState,void * Aml,UINT8 * ReturnIndex)314 AcpiUtValidateResource (
315     ACPI_WALK_STATE         *WalkState,
316     void                    *Aml,
317     UINT8                   *ReturnIndex)
318 {
319     AML_RESOURCE            *AmlResource;
320     UINT8                   ResourceType;
321     UINT8                   ResourceIndex;
322     ACPI_RS_LENGTH          ResourceLength;
323     ACPI_RS_LENGTH          MinimumResourceLength;
324 
325 
326     ACPI_FUNCTION_ENTRY ();
327 
328 
329     /*
330      * 1) Validate the ResourceType field (Byte 0)
331      */
332     ResourceType = ACPI_GET8 (Aml);
333 
334     /*
335      * Byte 0 contains the descriptor name (Resource Type)
336      * Examine the large/small bit in the resource header
337      */
338     if (ResourceType & ACPI_RESOURCE_NAME_LARGE)
339     {
340         /* Verify the large resource type (name) against the max */
341 
342         if (ResourceType > ACPI_RESOURCE_NAME_LARGE_MAX)
343         {
344             goto InvalidResource;
345         }
346 
347         /*
348          * Large Resource Type -- bits 6:0 contain the name
349          * Translate range 0x80-0x8B to index range 0x10-0x1B
350          */
351         ResourceIndex = (UINT8) (ResourceType - 0x70);
352     }
353     else
354     {
355         /*
356          * Small Resource Type -- bits 6:3 contain the name
357          * Shift range to index range 0x00-0x0F
358          */
359         ResourceIndex = (UINT8)
360             ((ResourceType & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
361     }
362 
363     /*
364      * Check validity of the resource type, via AcpiGbl_ResourceTypes.
365      * Zero indicates an invalid resource.
366      */
367     if (!AcpiGbl_ResourceTypes[ResourceIndex])
368     {
369         goto InvalidResource;
370     }
371 
372     /*
373      * Validate the ResourceLength field. This ensures that the length
374      * is at least reasonable, and guarantees that it is non-zero.
375      */
376     ResourceLength = AcpiUtGetResourceLength (Aml);
377     MinimumResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex];
378 
379     /* Validate based upon the type of resource - fixed length or variable */
380 
381     switch (AcpiGbl_ResourceTypes[ResourceIndex])
382     {
383     case ACPI_FIXED_LENGTH:
384 
385         /* Fixed length resource, length must match exactly */
386 
387         if (ResourceLength != MinimumResourceLength)
388         {
389             goto BadResourceLength;
390         }
391         break;
392 
393     case ACPI_VARIABLE_LENGTH:
394 
395         /* Variable length resource, length must be at least the minimum */
396 
397         if (ResourceLength < MinimumResourceLength)
398         {
399             goto BadResourceLength;
400         }
401         break;
402 
403     case ACPI_SMALL_VARIABLE_LENGTH:
404 
405         /* Small variable length resource, length can be (Min) or (Min-1) */
406 
407         if ((ResourceLength > MinimumResourceLength) ||
408             (ResourceLength < (MinimumResourceLength - 1)))
409         {
410             goto BadResourceLength;
411         }
412         break;
413 
414     default:
415 
416         /* Shouldn't happen (because of validation earlier), but be sure */
417 
418         goto InvalidResource;
419     }
420 
421     AmlResource = ACPI_CAST_PTR (AML_RESOURCE, Aml);
422     if (ResourceType == ACPI_RESOURCE_NAME_SERIAL_BUS)
423     {
424         /* Validate the BusType field */
425 
426         if ((AmlResource->CommonSerialBus.Type == 0) ||
427             (AmlResource->CommonSerialBus.Type > AML_RESOURCE_MAX_SERIALBUSTYPE))
428         {
429             if (WalkState)
430             {
431                 ACPI_ERROR ((AE_INFO,
432                     "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X",
433                     AmlResource->CommonSerialBus.Type));
434             }
435             return (AE_AML_INVALID_RESOURCE_TYPE);
436         }
437     }
438 
439     /* Optionally return the resource table index */
440 
441     if (ReturnIndex)
442     {
443         *ReturnIndex = ResourceIndex;
444     }
445 
446     return (AE_OK);
447 
448 
449 InvalidResource:
450 
451     if (WalkState)
452     {
453         ACPI_ERROR ((AE_INFO,
454             "Invalid/unsupported resource descriptor: Type 0x%2.2X",
455             ResourceType));
456     }
457     return (AE_AML_INVALID_RESOURCE_TYPE);
458 
459 BadResourceLength:
460 
461     if (WalkState)
462     {
463         ACPI_ERROR ((AE_INFO,
464             "Invalid resource descriptor length: Type "
465             "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X",
466             ResourceType, ResourceLength, MinimumResourceLength));
467     }
468     return (AE_AML_BAD_RESOURCE_LENGTH);
469 }
470 
471 
472 /*******************************************************************************
473  *
474  * FUNCTION:    AcpiUtGetResourceType
475  *
476  * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
477  *
478  * RETURN:      The Resource Type with no extraneous bits (except the
479  *              Large/Small descriptor bit -- this is left alone)
480  *
481  * DESCRIPTION: Extract the Resource Type/Name from the first byte of
482  *              a resource descriptor.
483  *
484  ******************************************************************************/
485 
486 UINT8
AcpiUtGetResourceType(void * Aml)487 AcpiUtGetResourceType (
488     void                    *Aml)
489 {
490     ACPI_FUNCTION_ENTRY ();
491 
492 
493     /*
494      * Byte 0 contains the descriptor name (Resource Type)
495      * Examine the large/small bit in the resource header
496      */
497     if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE)
498     {
499         /* Large Resource Type -- bits 6:0 contain the name */
500 
501         return (ACPI_GET8 (Aml));
502     }
503     else
504     {
505         /* Small Resource Type -- bits 6:3 contain the name */
506 
507         return ((UINT8) (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_SMALL_MASK));
508     }
509 }
510 
511 
512 /*******************************************************************************
513  *
514  * FUNCTION:    AcpiUtGetResourceLength
515  *
516  * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
517  *
518  * RETURN:      Byte Length
519  *
520  * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By
521  *              definition, this does not include the size of the descriptor
522  *              header or the length field itself.
523  *
524  ******************************************************************************/
525 
526 UINT16
AcpiUtGetResourceLength(void * Aml)527 AcpiUtGetResourceLength (
528     void                    *Aml)
529 {
530     ACPI_RS_LENGTH          ResourceLength;
531 
532 
533     ACPI_FUNCTION_ENTRY ();
534 
535 
536     /*
537      * Byte 0 contains the descriptor name (Resource Type)
538      * Examine the large/small bit in the resource header
539      */
540     if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE)
541     {
542         /* Large Resource type -- bytes 1-2 contain the 16-bit length */
543 
544         ACPI_MOVE_16_TO_16 (&ResourceLength, ACPI_ADD_PTR (UINT8, Aml, 1));
545 
546     }
547     else
548     {
549         /* Small Resource type -- bits 2:0 of byte 0 contain the length */
550 
551         ResourceLength = (UINT16) (ACPI_GET8 (Aml) &
552             ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
553     }
554 
555     return (ResourceLength);
556 }
557 
558 
559 /*******************************************************************************
560  *
561  * FUNCTION:    AcpiUtGetResourceHeaderLength
562  *
563  * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
564  *
565  * RETURN:      Length of the AML header (depends on large/small descriptor)
566  *
567  * DESCRIPTION: Get the length of the header for this resource.
568  *
569  ******************************************************************************/
570 
571 UINT8
AcpiUtGetResourceHeaderLength(void * Aml)572 AcpiUtGetResourceHeaderLength (
573     void                    *Aml)
574 {
575     ACPI_FUNCTION_ENTRY ();
576 
577 
578     /* Examine the large/small bit in the resource header */
579 
580     if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE)
581     {
582         return (sizeof (AML_RESOURCE_LARGE_HEADER));
583     }
584     else
585     {
586         return (sizeof (AML_RESOURCE_SMALL_HEADER));
587     }
588 }
589 
590 
591 /*******************************************************************************
592  *
593  * FUNCTION:    AcpiUtGetDescriptorLength
594  *
595  * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
596  *
597  * RETURN:      Byte length
598  *
599  * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the
600  *              length of the descriptor header and the length field itself.
601  *              Used to walk descriptor lists.
602  *
603  ******************************************************************************/
604 
605 UINT32
AcpiUtGetDescriptorLength(void * Aml)606 AcpiUtGetDescriptorLength (
607     void                    *Aml)
608 {
609     ACPI_FUNCTION_ENTRY ();
610 
611 
612     /*
613      * Get the Resource Length (does not include header length) and add
614      * the header length (depends on if this is a small or large resource)
615      */
616     return (AcpiUtGetResourceLength (Aml) +
617         AcpiUtGetResourceHeaderLength (Aml));
618 }
619 
620 
621 /*******************************************************************************
622  *
623  * FUNCTION:    AcpiUtGetResourceEndTag
624  *
625  * PARAMETERS:  ObjDesc         - The resource template buffer object
626  *              EndTag          - Where the pointer to the EndTag is returned
627  *
628  * RETURN:      Status, pointer to the end tag
629  *
630  * DESCRIPTION: Find the EndTag resource descriptor in an AML resource template
631  *              Note: allows a buffer length of zero.
632  *
633  ******************************************************************************/
634 
635 ACPI_STATUS
AcpiUtGetResourceEndTag(ACPI_OPERAND_OBJECT * ObjDesc,UINT8 ** EndTag)636 AcpiUtGetResourceEndTag (
637     ACPI_OPERAND_OBJECT     *ObjDesc,
638     UINT8                   **EndTag)
639 {
640     ACPI_STATUS             Status;
641 
642 
643     ACPI_FUNCTION_TRACE (UtGetResourceEndTag);
644 
645 
646     /* Allow a buffer length of zero */
647 
648     if (!ObjDesc->Buffer.Length)
649     {
650         *EndTag = ObjDesc->Buffer.Pointer;
651         return_ACPI_STATUS (AE_OK);
652     }
653 
654     /* Validate the template and get a pointer to the EndTag */
655 
656     Status = AcpiUtWalkAmlResources (NULL, ObjDesc->Buffer.Pointer,
657         ObjDesc->Buffer.Length, NULL, (void **) EndTag);
658 
659     return_ACPI_STATUS (Status);
660 }
661