xref: /openbmc/linux/drivers/acpi/acpica/utresrc.c (revision f8a6c866)
1 /*******************************************************************************
2  *
3  * Module Name: utresrc - Resource management utilities
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2017, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include <acpi/acpi.h>
45 #include "accommon.h"
46 #include "acresrc.h"
47 
48 #define _COMPONENT          ACPI_UTILITIES
49 ACPI_MODULE_NAME("utresrc")
50 
51 #if defined(ACPI_DEBUG_OUTPUT) || defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
52 /*
53  * Strings used to decode resource descriptors.
54  * Used by both the disassembler and the debugger resource dump routines
55  */
56 const char *acpi_gbl_bm_decode[] = {
57 	"NotBusMaster",
58 	"BusMaster"
59 };
60 
61 const char *acpi_gbl_config_decode[] = {
62 	"0 - Good Configuration",
63 	"1 - Acceptable Configuration",
64 	"2 - Suboptimal Configuration",
65 	"3 - ***Invalid Configuration***",
66 };
67 
68 const char *acpi_gbl_consume_decode[] = {
69 	"ResourceProducer",
70 	"ResourceConsumer"
71 };
72 
73 const char *acpi_gbl_dec_decode[] = {
74 	"PosDecode",
75 	"SubDecode"
76 };
77 
78 const char *acpi_gbl_he_decode[] = {
79 	"Level",
80 	"Edge"
81 };
82 
83 const char *acpi_gbl_io_decode[] = {
84 	"Decode10",
85 	"Decode16"
86 };
87 
88 const char *acpi_gbl_ll_decode[] = {
89 	"ActiveHigh",
90 	"ActiveLow",
91 	"ActiveBoth",
92 	"Reserved"
93 };
94 
95 const char *acpi_gbl_max_decode[] = {
96 	"MaxNotFixed",
97 	"MaxFixed"
98 };
99 
100 const char *acpi_gbl_mem_decode[] = {
101 	"NonCacheable",
102 	"Cacheable",
103 	"WriteCombining",
104 	"Prefetchable"
105 };
106 
107 const char *acpi_gbl_min_decode[] = {
108 	"MinNotFixed",
109 	"MinFixed"
110 };
111 
112 const char *acpi_gbl_mtp_decode[] = {
113 	"AddressRangeMemory",
114 	"AddressRangeReserved",
115 	"AddressRangeACPI",
116 	"AddressRangeNVS"
117 };
118 
119 const char *acpi_gbl_rng_decode[] = {
120 	"InvalidRanges",
121 	"NonISAOnlyRanges",
122 	"ISAOnlyRanges",
123 	"EntireRange"
124 };
125 
126 const char *acpi_gbl_rw_decode[] = {
127 	"ReadOnly",
128 	"ReadWrite"
129 };
130 
131 const char *acpi_gbl_shr_decode[] = {
132 	"Exclusive",
133 	"Shared",
134 	"ExclusiveAndWake",	/* ACPI 5.0 */
135 	"SharedAndWake"		/* ACPI 5.0 */
136 };
137 
138 const char *acpi_gbl_siz_decode[] = {
139 	"Transfer8",
140 	"Transfer8_16",
141 	"Transfer16",
142 	"InvalidSize"
143 };
144 
145 const char *acpi_gbl_trs_decode[] = {
146 	"DenseTranslation",
147 	"SparseTranslation"
148 };
149 
150 const char *acpi_gbl_ttp_decode[] = {
151 	"TypeStatic",
152 	"TypeTranslation"
153 };
154 
155 const char *acpi_gbl_typ_decode[] = {
156 	"Compatibility",
157 	"TypeA",
158 	"TypeB",
159 	"TypeF"
160 };
161 
162 const char *acpi_gbl_ppc_decode[] = {
163 	"PullDefault",
164 	"PullUp",
165 	"PullDown",
166 	"PullNone"
167 };
168 
169 const char *acpi_gbl_ior_decode[] = {
170 	"IoRestrictionNone",
171 	"IoRestrictionInputOnly",
172 	"IoRestrictionOutputOnly",
173 	"IoRestrictionNoneAndPreserve"
174 };
175 
176 const char *acpi_gbl_dts_decode[] = {
177 	"Width8bit",
178 	"Width16bit",
179 	"Width32bit",
180 	"Width64bit",
181 	"Width128bit",
182 	"Width256bit",
183 };
184 
185 /* GPIO connection type */
186 
187 const char *acpi_gbl_ct_decode[] = {
188 	"Interrupt",
189 	"I/O"
190 };
191 
192 /* Serial bus type */
193 
194 const char *acpi_gbl_sbt_decode[] = {
195 	"/* UNKNOWN serial bus type */",
196 	"I2C",
197 	"SPI",
198 	"UART"
199 };
200 
201 /* I2C serial bus access mode */
202 
203 const char *acpi_gbl_am_decode[] = {
204 	"AddressingMode7Bit",
205 	"AddressingMode10Bit"
206 };
207 
208 /* I2C serial bus slave mode */
209 
210 const char *acpi_gbl_sm_decode[] = {
211 	"ControllerInitiated",
212 	"DeviceInitiated"
213 };
214 
215 /* SPI serial bus wire mode */
216 
217 const char *acpi_gbl_wm_decode[] = {
218 	"FourWireMode",
219 	"ThreeWireMode"
220 };
221 
222 /* SPI serial clock phase */
223 
224 const char *acpi_gbl_cph_decode[] = {
225 	"ClockPhaseFirst",
226 	"ClockPhaseSecond"
227 };
228 
229 /* SPI serial bus clock polarity */
230 
231 const char *acpi_gbl_cpo_decode[] = {
232 	"ClockPolarityLow",
233 	"ClockPolarityHigh"
234 };
235 
236 /* SPI serial bus device polarity */
237 
238 const char *acpi_gbl_dp_decode[] = {
239 	"PolarityLow",
240 	"PolarityHigh"
241 };
242 
243 /* UART serial bus endian */
244 
245 const char *acpi_gbl_ed_decode[] = {
246 	"LittleEndian",
247 	"BigEndian"
248 };
249 
250 /* UART serial bus bits per byte */
251 
252 const char *acpi_gbl_bpb_decode[] = {
253 	"DataBitsFive",
254 	"DataBitsSix",
255 	"DataBitsSeven",
256 	"DataBitsEight",
257 	"DataBitsNine",
258 	"/* UNKNOWN Bits per byte */",
259 	"/* UNKNOWN Bits per byte */",
260 	"/* UNKNOWN Bits per byte */"
261 };
262 
263 /* UART serial bus stop bits */
264 
265 const char *acpi_gbl_sb_decode[] = {
266 	"StopBitsZero",
267 	"StopBitsOne",
268 	"StopBitsOnePlusHalf",
269 	"StopBitsTwo"
270 };
271 
272 /* UART serial bus flow control */
273 
274 const char *acpi_gbl_fc_decode[] = {
275 	"FlowControlNone",
276 	"FlowControlHardware",
277 	"FlowControlXON",
278 	"/* UNKNOWN flow control keyword */"
279 };
280 
281 /* UART serial bus parity type */
282 
283 const char *acpi_gbl_pt_decode[] = {
284 	"ParityTypeNone",
285 	"ParityTypeEven",
286 	"ParityTypeOdd",
287 	"ParityTypeMark",
288 	"ParityTypeSpace",
289 	"/* UNKNOWN parity keyword */",
290 	"/* UNKNOWN parity keyword */",
291 	"/* UNKNOWN parity keyword */"
292 };
293 
294 /* pin_config type */
295 
296 const char *acpi_gbl_ptyp_decode[] = {
297 	"Default",
298 	"Bias Pull-up",
299 	"Bias Pull-down",
300 	"Bias Default",
301 	"Bias Disable",
302 	"Bias High Impedance",
303 	"Bias Bus Hold",
304 	"Drive Open Drain",
305 	"Drive Open Source",
306 	"Drive Push Pull",
307 	"Drive Strength",
308 	"Slew Rate",
309 	"Input Debounce",
310 	"Input Schmitt Trigger",
311 };
312 
313 #endif
314 
315 /*
316  * Base sizes of the raw AML resource descriptors, indexed by resource type.
317  * Zero indicates a reserved (and therefore invalid) resource type.
318  */
319 const u8 acpi_gbl_resource_aml_sizes[] = {
320 	/* Small descriptors */
321 
322 	0,
323 	0,
324 	0,
325 	0,
326 	ACPI_AML_SIZE_SMALL(struct aml_resource_irq),
327 	ACPI_AML_SIZE_SMALL(struct aml_resource_dma),
328 	ACPI_AML_SIZE_SMALL(struct aml_resource_start_dependent),
329 	ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent),
330 	ACPI_AML_SIZE_SMALL(struct aml_resource_io),
331 	ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io),
332 	ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_dma),
333 	0,
334 	0,
335 	0,
336 	ACPI_AML_SIZE_SMALL(struct aml_resource_vendor_small),
337 	ACPI_AML_SIZE_SMALL(struct aml_resource_end_tag),
338 
339 	/* Large descriptors */
340 
341 	0,
342 	ACPI_AML_SIZE_LARGE(struct aml_resource_memory24),
343 	ACPI_AML_SIZE_LARGE(struct aml_resource_generic_register),
344 	0,
345 	ACPI_AML_SIZE_LARGE(struct aml_resource_vendor_large),
346 	ACPI_AML_SIZE_LARGE(struct aml_resource_memory32),
347 	ACPI_AML_SIZE_LARGE(struct aml_resource_fixed_memory32),
348 	ACPI_AML_SIZE_LARGE(struct aml_resource_address32),
349 	ACPI_AML_SIZE_LARGE(struct aml_resource_address16),
350 	ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq),
351 	ACPI_AML_SIZE_LARGE(struct aml_resource_address64),
352 	ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64),
353 	ACPI_AML_SIZE_LARGE(struct aml_resource_gpio),
354 	ACPI_AML_SIZE_LARGE(struct aml_resource_pin_function),
355 	ACPI_AML_SIZE_LARGE(struct aml_resource_common_serialbus),
356 	ACPI_AML_SIZE_LARGE(struct aml_resource_pin_config),
357 	ACPI_AML_SIZE_LARGE(struct aml_resource_pin_group),
358 	ACPI_AML_SIZE_LARGE(struct aml_resource_pin_group_function),
359 };
360 
361 const u8 acpi_gbl_resource_aml_serial_bus_sizes[] = {
362 	0,
363 	ACPI_AML_SIZE_LARGE(struct aml_resource_i2c_serialbus),
364 	ACPI_AML_SIZE_LARGE(struct aml_resource_spi_serialbus),
365 	ACPI_AML_SIZE_LARGE(struct aml_resource_uart_serialbus),
366 };
367 
368 /*
369  * Resource types, used to validate the resource length field.
370  * The length of fixed-length types must match exactly, variable
371  * lengths must meet the minimum required length, etc.
372  * Zero indicates a reserved (and therefore invalid) resource type.
373  */
374 static const u8 acpi_gbl_resource_types[] = {
375 	/* Small descriptors */
376 
377 	0,
378 	0,
379 	0,
380 	0,
381 	ACPI_SMALL_VARIABLE_LENGTH,	/* 04 IRQ */
382 	ACPI_FIXED_LENGTH,	/* 05 DMA */
383 	ACPI_SMALL_VARIABLE_LENGTH,	/* 06 start_dependent_functions */
384 	ACPI_FIXED_LENGTH,	/* 07 end_dependent_functions */
385 	ACPI_FIXED_LENGTH,	/* 08 IO */
386 	ACPI_FIXED_LENGTH,	/* 09 fixed_IO */
387 	ACPI_FIXED_LENGTH,	/* 0A fixed_DMA */
388 	0,
389 	0,
390 	0,
391 	ACPI_VARIABLE_LENGTH,	/* 0E vendor_short */
392 	ACPI_FIXED_LENGTH,	/* 0F end_tag */
393 
394 	/* Large descriptors */
395 
396 	0,
397 	ACPI_FIXED_LENGTH,	/* 01 Memory24 */
398 	ACPI_FIXED_LENGTH,	/* 02 generic_register */
399 	0,
400 	ACPI_VARIABLE_LENGTH,	/* 04 vendor_long */
401 	ACPI_FIXED_LENGTH,	/* 05 Memory32 */
402 	ACPI_FIXED_LENGTH,	/* 06 memory32_fixed */
403 	ACPI_VARIABLE_LENGTH,	/* 07 Dword* address */
404 	ACPI_VARIABLE_LENGTH,	/* 08 Word* address */
405 	ACPI_VARIABLE_LENGTH,	/* 09 extended_IRQ */
406 	ACPI_VARIABLE_LENGTH,	/* 0A Qword* address */
407 	ACPI_FIXED_LENGTH,	/* 0B Extended* address */
408 	ACPI_VARIABLE_LENGTH,	/* 0C Gpio* */
409 	ACPI_VARIABLE_LENGTH,	/* 0D pin_function */
410 	ACPI_VARIABLE_LENGTH,	/* 0E *serial_bus */
411 	ACPI_VARIABLE_LENGTH,	/* 0F pin_config */
412 	ACPI_VARIABLE_LENGTH,	/* 10 pin_group */
413 	ACPI_VARIABLE_LENGTH,	/* 11 pin_group_function */
414 };
415 
416 /*******************************************************************************
417  *
418  * FUNCTION:    acpi_ut_walk_aml_resources
419  *
420  * PARAMETERS:  walk_state          - Current walk info
421  * PARAMETERS:  aml                 - Pointer to the raw AML resource template
422  *              aml_length          - Length of the entire template
423  *              user_function       - Called once for each descriptor found. If
424  *                                    NULL, a pointer to the end_tag is returned
425  *              context             - Passed to user_function
426  *
427  * RETURN:      Status
428  *
429  * DESCRIPTION: Walk a raw AML resource list(buffer). User function called
430  *              once for each resource found.
431  *
432  ******************************************************************************/
433 
434 acpi_status
435 acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
436 			   u8 *aml,
437 			   acpi_size aml_length,
438 			   acpi_walk_aml_callback user_function, void **context)
439 {
440 	acpi_status status;
441 	u8 *end_aml;
442 	u8 resource_index;
443 	u32 length;
444 	u32 offset = 0;
445 	u8 end_tag[2] = { 0x79, 0x00 };
446 
447 	ACPI_FUNCTION_TRACE(ut_walk_aml_resources);
448 
449 	/* The absolute minimum resource template is one end_tag descriptor */
450 
451 	if (aml_length < sizeof(struct aml_resource_end_tag)) {
452 		return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
453 	}
454 
455 	/* Point to the end of the resource template buffer */
456 
457 	end_aml = aml + aml_length;
458 
459 	/* Walk the byte list, abort on any invalid descriptor type or length */
460 
461 	while (aml < end_aml) {
462 
463 		/* Validate the Resource Type and Resource Length */
464 
465 		status =
466 		    acpi_ut_validate_resource(walk_state, aml, &resource_index);
467 		if (ACPI_FAILURE(status)) {
468 			/*
469 			 * Exit on failure. Cannot continue because the descriptor
470 			 * length may be bogus also.
471 			 */
472 			return_ACPI_STATUS(status);
473 		}
474 
475 		/* Get the length of this descriptor */
476 
477 		length = acpi_ut_get_descriptor_length(aml);
478 
479 		/* Invoke the user function */
480 
481 		if (user_function) {
482 			status =
483 			    user_function(aml, length, offset, resource_index,
484 					  context);
485 			if (ACPI_FAILURE(status)) {
486 				return_ACPI_STATUS(status);
487 			}
488 		}
489 
490 		/* An end_tag descriptor terminates this resource template */
491 
492 		if (acpi_ut_get_resource_type(aml) ==
493 		    ACPI_RESOURCE_NAME_END_TAG) {
494 			/*
495 			 * There must be at least one more byte in the buffer for
496 			 * the 2nd byte of the end_tag
497 			 */
498 			if ((aml + 1) >= end_aml) {
499 				return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
500 			}
501 
502 			/*
503 			 * The end_tag opcode must be followed by a zero byte.
504 			 * Although this byte is technically defined to be a checksum,
505 			 * in practice, all ASL compilers set this byte to zero.
506 			 */
507 			if (*(aml + 1) != 0) {
508 				return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
509 			}
510 
511 			/* Return the pointer to the end_tag if requested */
512 
513 			if (!user_function) {
514 				*context = aml;
515 			}
516 
517 			/* Normal exit */
518 
519 			return_ACPI_STATUS(AE_OK);
520 		}
521 
522 		aml += length;
523 		offset += length;
524 	}
525 
526 	/* Did not find an end_tag descriptor */
527 
528 	if (user_function) {
529 
530 		/* Insert an end_tag anyway. acpi_rs_get_list_length always leaves room */
531 
532 		(void)acpi_ut_validate_resource(walk_state, end_tag,
533 						&resource_index);
534 		status =
535 		    user_function(end_tag, 2, offset, resource_index, context);
536 		if (ACPI_FAILURE(status)) {
537 			return_ACPI_STATUS(status);
538 		}
539 	}
540 
541 	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
542 }
543 
544 /*******************************************************************************
545  *
546  * FUNCTION:    acpi_ut_validate_resource
547  *
548  * PARAMETERS:  walk_state          - Current walk info
549  *              aml                 - Pointer to the raw AML resource descriptor
550  *              return_index        - Where the resource index is returned. NULL
551  *                                    if the index is not required.
552  *
553  * RETURN:      Status, and optionally the Index into the global resource tables
554  *
555  * DESCRIPTION: Validate an AML resource descriptor by checking the Resource
556  *              Type and Resource Length. Returns an index into the global
557  *              resource information/dispatch tables for later use.
558  *
559  ******************************************************************************/
560 
561 acpi_status
562 acpi_ut_validate_resource(struct acpi_walk_state *walk_state,
563 			  void *aml, u8 *return_index)
564 {
565 	union aml_resource *aml_resource;
566 	u8 resource_type;
567 	u8 resource_index;
568 	acpi_rs_length resource_length;
569 	acpi_rs_length minimum_resource_length;
570 
571 	ACPI_FUNCTION_ENTRY();
572 
573 	/*
574 	 * 1) Validate the resource_type field (Byte 0)
575 	 */
576 	resource_type = ACPI_GET8(aml);
577 
578 	/*
579 	 * Byte 0 contains the descriptor name (Resource Type)
580 	 * Examine the large/small bit in the resource header
581 	 */
582 	if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
583 
584 		/* Verify the large resource type (name) against the max */
585 
586 		if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
587 			goto invalid_resource;
588 		}
589 
590 		/*
591 		 * Large Resource Type -- bits 6:0 contain the name
592 		 * Translate range 0x80-0x8B to index range 0x10-0x1B
593 		 */
594 		resource_index = (u8) (resource_type - 0x70);
595 	} else {
596 		/*
597 		 * Small Resource Type -- bits 6:3 contain the name
598 		 * Shift range to index range 0x00-0x0F
599 		 */
600 		resource_index = (u8)
601 		    ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
602 	}
603 
604 	/*
605 	 * Check validity of the resource type, via acpi_gbl_resource_types.
606 	 * Zero indicates an invalid resource.
607 	 */
608 	if (!acpi_gbl_resource_types[resource_index]) {
609 		goto invalid_resource;
610 	}
611 
612 	/*
613 	 * Validate the resource_length field. This ensures that the length
614 	 * is at least reasonable, and guarantees that it is non-zero.
615 	 */
616 	resource_length = acpi_ut_get_resource_length(aml);
617 	minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index];
618 
619 	/* Validate based upon the type of resource - fixed length or variable */
620 
621 	switch (acpi_gbl_resource_types[resource_index]) {
622 	case ACPI_FIXED_LENGTH:
623 
624 		/* Fixed length resource, length must match exactly */
625 
626 		if (resource_length != minimum_resource_length) {
627 			goto bad_resource_length;
628 		}
629 		break;
630 
631 	case ACPI_VARIABLE_LENGTH:
632 
633 		/* Variable length resource, length must be at least the minimum */
634 
635 		if (resource_length < minimum_resource_length) {
636 			goto bad_resource_length;
637 		}
638 		break;
639 
640 	case ACPI_SMALL_VARIABLE_LENGTH:
641 
642 		/* Small variable length resource, length can be (Min) or (Min-1) */
643 
644 		if ((resource_length > minimum_resource_length) ||
645 		    (resource_length < (minimum_resource_length - 1))) {
646 			goto bad_resource_length;
647 		}
648 		break;
649 
650 	default:
651 
652 		/* Shouldn't happen (because of validation earlier), but be sure */
653 
654 		goto invalid_resource;
655 	}
656 
657 	aml_resource = ACPI_CAST_PTR(union aml_resource, aml);
658 	if (resource_type == ACPI_RESOURCE_NAME_SERIAL_BUS) {
659 
660 		/* Validate the bus_type field */
661 
662 		if ((aml_resource->common_serial_bus.type == 0) ||
663 		    (aml_resource->common_serial_bus.type >
664 		     AML_RESOURCE_MAX_SERIALBUSTYPE)) {
665 			if (walk_state) {
666 				ACPI_ERROR((AE_INFO,
667 					    "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X",
668 					    aml_resource->common_serial_bus.
669 					    type));
670 			}
671 			return (AE_AML_INVALID_RESOURCE_TYPE);
672 		}
673 	}
674 
675 	/* Optionally return the resource table index */
676 
677 	if (return_index) {
678 		*return_index = resource_index;
679 	}
680 
681 	return (AE_OK);
682 
683 invalid_resource:
684 
685 	if (walk_state) {
686 		ACPI_ERROR((AE_INFO,
687 			    "Invalid/unsupported resource descriptor: Type 0x%2.2X",
688 			    resource_type));
689 	}
690 	return (AE_AML_INVALID_RESOURCE_TYPE);
691 
692 bad_resource_length:
693 
694 	if (walk_state) {
695 		ACPI_ERROR((AE_INFO,
696 			    "Invalid resource descriptor length: Type "
697 			    "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X",
698 			    resource_type, resource_length,
699 			    minimum_resource_length));
700 	}
701 	return (AE_AML_BAD_RESOURCE_LENGTH);
702 }
703 
704 /*******************************************************************************
705  *
706  * FUNCTION:    acpi_ut_get_resource_type
707  *
708  * PARAMETERS:  aml             - Pointer to the raw AML resource descriptor
709  *
710  * RETURN:      The Resource Type with no extraneous bits (except the
711  *              Large/Small descriptor bit -- this is left alone)
712  *
713  * DESCRIPTION: Extract the Resource Type/Name from the first byte of
714  *              a resource descriptor.
715  *
716  ******************************************************************************/
717 
718 u8 acpi_ut_get_resource_type(void *aml)
719 {
720 	ACPI_FUNCTION_ENTRY();
721 
722 	/*
723 	 * Byte 0 contains the descriptor name (Resource Type)
724 	 * Examine the large/small bit in the resource header
725 	 */
726 	if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
727 
728 		/* Large Resource Type -- bits 6:0 contain the name */
729 
730 		return (ACPI_GET8(aml));
731 	} else {
732 		/* Small Resource Type -- bits 6:3 contain the name */
733 
734 		return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK));
735 	}
736 }
737 
738 /*******************************************************************************
739  *
740  * FUNCTION:    acpi_ut_get_resource_length
741  *
742  * PARAMETERS:  aml             - Pointer to the raw AML resource descriptor
743  *
744  * RETURN:      Byte Length
745  *
746  * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By
747  *              definition, this does not include the size of the descriptor
748  *              header or the length field itself.
749  *
750  ******************************************************************************/
751 
752 u16 acpi_ut_get_resource_length(void *aml)
753 {
754 	acpi_rs_length resource_length;
755 
756 	ACPI_FUNCTION_ENTRY();
757 
758 	/*
759 	 * Byte 0 contains the descriptor name (Resource Type)
760 	 * Examine the large/small bit in the resource header
761 	 */
762 	if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
763 
764 		/* Large Resource type -- bytes 1-2 contain the 16-bit length */
765 
766 		ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1));
767 
768 	} else {
769 		/* Small Resource type -- bits 2:0 of byte 0 contain the length */
770 
771 		resource_length = (u16) (ACPI_GET8(aml) &
772 					 ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
773 	}
774 
775 	return (resource_length);
776 }
777 
778 /*******************************************************************************
779  *
780  * FUNCTION:    acpi_ut_get_resource_header_length
781  *
782  * PARAMETERS:  aml             - Pointer to the raw AML resource descriptor
783  *
784  * RETURN:      Length of the AML header (depends on large/small descriptor)
785  *
786  * DESCRIPTION: Get the length of the header for this resource.
787  *
788  ******************************************************************************/
789 
790 u8 acpi_ut_get_resource_header_length(void *aml)
791 {
792 	ACPI_FUNCTION_ENTRY();
793 
794 	/* Examine the large/small bit in the resource header */
795 
796 	if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
797 		return (sizeof(struct aml_resource_large_header));
798 	} else {
799 		return (sizeof(struct aml_resource_small_header));
800 	}
801 }
802 
803 /*******************************************************************************
804  *
805  * FUNCTION:    acpi_ut_get_descriptor_length
806  *
807  * PARAMETERS:  aml             - Pointer to the raw AML resource descriptor
808  *
809  * RETURN:      Byte length
810  *
811  * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the
812  *              length of the descriptor header and the length field itself.
813  *              Used to walk descriptor lists.
814  *
815  ******************************************************************************/
816 
817 u32 acpi_ut_get_descriptor_length(void *aml)
818 {
819 	ACPI_FUNCTION_ENTRY();
820 
821 	/*
822 	 * Get the Resource Length (does not include header length) and add
823 	 * the header length (depends on if this is a small or large resource)
824 	 */
825 	return (acpi_ut_get_resource_length(aml) +
826 		acpi_ut_get_resource_header_length(aml));
827 }
828 
829 /*******************************************************************************
830  *
831  * FUNCTION:    acpi_ut_get_resource_end_tag
832  *
833  * PARAMETERS:  obj_desc        - The resource template buffer object
834  *              end_tag         - Where the pointer to the end_tag is returned
835  *
836  * RETURN:      Status, pointer to the end tag
837  *
838  * DESCRIPTION: Find the end_tag resource descriptor in an AML resource template
839  *              Note: allows a buffer length of zero.
840  *
841  ******************************************************************************/
842 
843 acpi_status
844 acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag)
845 {
846 	acpi_status status;
847 
848 	ACPI_FUNCTION_TRACE(ut_get_resource_end_tag);
849 
850 	/* Allow a buffer length of zero */
851 
852 	if (!obj_desc->buffer.length) {
853 		*end_tag = obj_desc->buffer.pointer;
854 		return_ACPI_STATUS(AE_OK);
855 	}
856 
857 	/* Validate the template and get a pointer to the end_tag */
858 
859 	status = acpi_ut_walk_aml_resources(NULL, obj_desc->buffer.pointer,
860 					    obj_desc->buffer.length, NULL,
861 					    (void **)end_tag);
862 
863 	return_ACPI_STATUS(status);
864 }
865