Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
utresrc.c
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * Module Name: utresrc - Resource management utilities
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2012, 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 #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
51 /*
52  * Strings used to decode resource descriptors.
53  * Used by both the disassembler and the debugger resource dump routines
54  */
55 const char *acpi_gbl_bm_decode[] = {
56  "NotBusMaster",
57  "BusMaster"
58 };
59 
60 const char *acpi_gbl_config_decode[] = {
61  "0 - Good Configuration",
62  "1 - Acceptable Configuration",
63  "2 - Suboptimal Configuration",
64  "3 - ***Invalid Configuration***",
65 };
66 
67 const char *acpi_gbl_consume_decode[] = {
68  "ResourceProducer",
69  "ResourceConsumer"
70 };
71 
72 const char *acpi_gbl_dec_decode[] = {
73  "PosDecode",
74  "SubDecode"
75 };
76 
77 const char *acpi_gbl_he_decode[] = {
78  "Level",
79  "Edge"
80 };
81 
82 const char *acpi_gbl_io_decode[] = {
83  "Decode10",
84  "Decode16"
85 };
86 
87 const char *acpi_gbl_ll_decode[] = {
88  "ActiveHigh",
89  "ActiveLow"
90 };
91 
92 const char *acpi_gbl_max_decode[] = {
93  "MaxNotFixed",
94  "MaxFixed"
95 };
96 
97 const char *acpi_gbl_mem_decode[] = {
98  "NonCacheable",
99  "Cacheable",
100  "WriteCombining",
101  "Prefetchable"
102 };
103 
104 const char *acpi_gbl_min_decode[] = {
105  "MinNotFixed",
106  "MinFixed"
107 };
108 
109 const char *acpi_gbl_mtp_decode[] = {
110  "AddressRangeMemory",
111  "AddressRangeReserved",
112  "AddressRangeACPI",
113  "AddressRangeNVS"
114 };
115 
116 const char *acpi_gbl_rng_decode[] = {
117  "InvalidRanges",
118  "NonISAOnlyRanges",
119  "ISAOnlyRanges",
120  "EntireRange"
121 };
122 
123 const char *acpi_gbl_rw_decode[] = {
124  "ReadOnly",
125  "ReadWrite"
126 };
127 
128 const char *acpi_gbl_shr_decode[] = {
129  "Exclusive",
130  "Shared"
131 };
132 
133 const char *acpi_gbl_siz_decode[] = {
134  "Transfer8",
135  "Transfer8_16",
136  "Transfer16",
137  "InvalidSize"
138 };
139 
140 const char *acpi_gbl_trs_decode[] = {
141  "DenseTranslation",
142  "SparseTranslation"
143 };
144 
145 const char *acpi_gbl_ttp_decode[] = {
146  "TypeStatic",
147  "TypeTranslation"
148 };
149 
150 const char *acpi_gbl_typ_decode[] = {
151  "Compatibility",
152  "TypeA",
153  "TypeB",
154  "TypeF"
155 };
156 
157 const char *acpi_gbl_ppc_decode[] = {
158  "PullDefault",
159  "PullUp",
160  "PullDown",
161  "PullNone"
162 };
163 
164 const char *acpi_gbl_ior_decode[] = {
165  "IoRestrictionNone",
166  "IoRestrictionInputOnly",
167  "IoRestrictionOutputOnly",
168  "IoRestrictionNoneAndPreserve"
169 };
170 
171 const char *acpi_gbl_dts_decode[] = {
172  "Width8bit",
173  "Width16bit",
174  "Width32bit",
175  "Width64bit",
176  "Width128bit",
177  "Width256bit",
178 };
179 
180 /* GPIO connection type */
181 
182 const char *acpi_gbl_ct_decode[] = {
183  "Interrupt",
184  "I/O"
185 };
186 
187 /* Serial bus type */
188 
189 const char *acpi_gbl_sbt_decode[] = {
190  "/* UNKNOWN serial bus type */",
191  "I2C",
192  "SPI",
193  "UART"
194 };
195 
196 /* I2C serial bus access mode */
197 
198 const char *acpi_gbl_am_decode[] = {
199  "AddressingMode7Bit",
200  "AddressingMode10Bit"
201 };
202 
203 /* I2C serial bus slave mode */
204 
205 const char *acpi_gbl_sm_decode[] = {
206  "ControllerInitiated",
207  "DeviceInitiated"
208 };
209 
210 /* SPI serial bus wire mode */
211 
212 const char *acpi_gbl_wm_decode[] = {
213  "FourWireMode",
214  "ThreeWireMode"
215 };
216 
217 /* SPI serial clock phase */
218 
219 const char *acpi_gbl_cph_decode[] = {
220  "ClockPhaseFirst",
221  "ClockPhaseSecond"
222 };
223 
224 /* SPI serial bus clock polarity */
225 
226 const char *acpi_gbl_cpo_decode[] = {
227  "ClockPolarityLow",
228  "ClockPolarityHigh"
229 };
230 
231 /* SPI serial bus device polarity */
232 
233 const char *acpi_gbl_dp_decode[] = {
234  "PolarityLow",
235  "PolarityHigh"
236 };
237 
238 /* UART serial bus endian */
239 
240 const char *acpi_gbl_ed_decode[] = {
241  "LittleEndian",
242  "BigEndian"
243 };
244 
245 /* UART serial bus bits per byte */
246 
247 const char *acpi_gbl_bpb_decode[] = {
248  "DataBitsFive",
249  "DataBitsSix",
250  "DataBitsSeven",
251  "DataBitsEight",
252  "DataBitsNine",
253  "/* UNKNOWN Bits per byte */",
254  "/* UNKNOWN Bits per byte */",
255  "/* UNKNOWN Bits per byte */"
256 };
257 
258 /* UART serial bus stop bits */
259 
260 const char *acpi_gbl_sb_decode[] = {
261  "StopBitsNone",
262  "StopBitsOne",
263  "StopBitsOnePlusHalf",
264  "StopBitsTwo"
265 };
266 
267 /* UART serial bus flow control */
268 
269 const char *acpi_gbl_fc_decode[] = {
270  "FlowControlNone",
271  "FlowControlHardware",
272  "FlowControlXON",
273  "/* UNKNOWN flow control keyword */"
274 };
275 
276 /* UART serial bus parity type */
277 
278 const char *acpi_gbl_pt_decode[] = {
279  "ParityTypeNone",
280  "ParityTypeEven",
281  "ParityTypeOdd",
282  "ParityTypeMark",
283  "ParityTypeSpace",
284  "/* UNKNOWN parity keyword */",
285  "/* UNKNOWN parity keyword */",
286  "/* UNKNOWN parity keyword */"
287 };
288 
289 #endif
290 
291 /*
292  * Base sizes of the raw AML resource descriptors, indexed by resource type.
293  * Zero indicates a reserved (and therefore invalid) resource type.
294  */
296  /* Small descriptors */
297 
298  0,
299  0,
300  0,
301  0,
309  0,
310  0,
311  0,
314 
315  /* Large descriptors */
316 
317  0,
320  0,
330  0,
332 };
333 
335  0,
339 };
340 
341 /*
342  * Resource types, used to validate the resource length field.
343  * The length of fixed-length types must match exactly, variable
344  * lengths must meet the minimum required length, etc.
345  * Zero indicates a reserved (and therefore invalid) resource type.
346  */
347 static const u8 acpi_gbl_resource_types[] = {
348  /* Small descriptors */
349 
350  0,
351  0,
352  0,
353  0,
354  ACPI_SMALL_VARIABLE_LENGTH, /* 04 IRQ */
355  ACPI_FIXED_LENGTH, /* 05 DMA */
356  ACPI_SMALL_VARIABLE_LENGTH, /* 06 start_dependent_functions */
357  ACPI_FIXED_LENGTH, /* 07 end_dependent_functions */
358  ACPI_FIXED_LENGTH, /* 08 IO */
359  ACPI_FIXED_LENGTH, /* 09 fixed_IO */
360  ACPI_FIXED_LENGTH, /* 0A fixed_DMA */
361  0,
362  0,
363  0,
364  ACPI_VARIABLE_LENGTH, /* 0E vendor_short */
365  ACPI_FIXED_LENGTH, /* 0F end_tag */
366 
367  /* Large descriptors */
368 
369  0,
370  ACPI_FIXED_LENGTH, /* 01 Memory24 */
371  ACPI_FIXED_LENGTH, /* 02 generic_register */
372  0,
373  ACPI_VARIABLE_LENGTH, /* 04 vendor_long */
374  ACPI_FIXED_LENGTH, /* 05 Memory32 */
375  ACPI_FIXED_LENGTH, /* 06 memory32_fixed */
376  ACPI_VARIABLE_LENGTH, /* 07 Dword* address */
377  ACPI_VARIABLE_LENGTH, /* 08 Word* address */
378  ACPI_VARIABLE_LENGTH, /* 09 extended_IRQ */
379  ACPI_VARIABLE_LENGTH, /* 0A Qword* address */
380  ACPI_FIXED_LENGTH, /* 0B Extended* address */
381  ACPI_VARIABLE_LENGTH, /* 0C Gpio* */
382  0,
383  ACPI_VARIABLE_LENGTH /* 0E *serial_bus */
384 };
385 
386 /*
387  * For the iASL compiler/disassembler, we don't want any error messages
388  * because the disassembler uses the resource validation code to determine
389  * if Buffer objects are actually Resource Templates.
390  */
391 #ifdef ACPI_ASL_COMPILER
392 #define ACPI_RESOURCE_ERROR(plist)
393 #else
394 #define ACPI_RESOURCE_ERROR(plist) ACPI_ERROR(plist)
395 #endif
396 
397 /*******************************************************************************
398  *
399  * FUNCTION: acpi_ut_walk_aml_resources
400  *
401  * PARAMETERS: aml - Pointer to the raw AML resource template
402  * aml_length - Length of the entire template
403  * user_function - Called once for each descriptor found. If
404  * NULL, a pointer to the end_tag is returned
405  * context - Passed to user_function
406  *
407  * RETURN: Status
408  *
409  * DESCRIPTION: Walk a raw AML resource list(buffer). User function called
410  * once for each resource found.
411  *
412  ******************************************************************************/
413 
416  acpi_size aml_length,
417  acpi_walk_aml_callback user_function, void **context)
418 {
420  u8 *end_aml;
421  u8 resource_index;
422  u32 length;
423  u32 offset = 0;
424  u8 end_tag[2] = { 0x79, 0x00 };
425 
426  ACPI_FUNCTION_TRACE(ut_walk_aml_resources);
427 
428  /* The absolute minimum resource template is one end_tag descriptor */
429 
430  if (aml_length < sizeof(struct aml_resource_end_tag)) {
432  }
433 
434  /* Point to the end of the resource template buffer */
435 
436  end_aml = aml + aml_length;
437 
438  /* Walk the byte list, abort on any invalid descriptor type or length */
439 
440  while (aml < end_aml) {
441 
442  /* Validate the Resource Type and Resource Length */
443 
444  status = acpi_ut_validate_resource(aml, &resource_index);
445  if (ACPI_FAILURE(status)) {
446  /*
447  * Exit on failure. Cannot continue because the descriptor length
448  * may be bogus also.
449  */
450  return_ACPI_STATUS(status);
451  }
452 
453  /* Get the length of this descriptor */
454 
455  length = acpi_ut_get_descriptor_length(aml);
456 
457  /* Invoke the user function */
458 
459  if (user_function) {
460  status =
461  user_function(aml, length, offset, resource_index,
462  context);
463  if (ACPI_FAILURE(status)) {
464  return_ACPI_STATUS(status);
465  }
466  }
467 
468  /* An end_tag descriptor terminates this resource template */
469 
470  if (acpi_ut_get_resource_type(aml) ==
472  /*
473  * There must be at least one more byte in the buffer for
474  * the 2nd byte of the end_tag
475  */
476  if ((aml + 1) >= end_aml) {
478  }
479 
480  /* Return the pointer to the end_tag if requested */
481 
482  if (!user_function) {
483  *context = aml;
484  }
485 
486  /* Normal exit */
487 
489  }
490 
491  aml += length;
492  offset += length;
493  }
494 
495  /* Did not find an end_tag descriptor */
496 
497  if (user_function) {
498 
499  /* Insert an end_tag anyway. acpi_rs_get_list_length always leaves room */
500 
501  (void)acpi_ut_validate_resource(end_tag, &resource_index);
502  status =
503  user_function(end_tag, 2, offset, resource_index, context);
504  if (ACPI_FAILURE(status)) {
505  return_ACPI_STATUS(status);
506  }
507  }
508 
510 }
511 
512 /*******************************************************************************
513  *
514  * FUNCTION: acpi_ut_validate_resource
515  *
516  * PARAMETERS: aml - Pointer to the raw AML resource descriptor
517  * return_index - Where the resource index is returned. NULL
518  * if the index is not required.
519  *
520  * RETURN: Status, and optionally the Index into the global resource tables
521  *
522  * DESCRIPTION: Validate an AML resource descriptor by checking the Resource
523  * Type and Resource Length. Returns an index into the global
524  * resource information/dispatch tables for later use.
525  *
526  ******************************************************************************/
527 
528 acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
529 {
530  union aml_resource *aml_resource;
532  u8 resource_index;
533  acpi_rs_length resource_length;
534  acpi_rs_length minimum_resource_length;
535 
537 
538  /*
539  * 1) Validate the resource_type field (Byte 0)
540  */
541  resource_type = ACPI_GET8(aml);
542 
543  /*
544  * Byte 0 contains the descriptor name (Resource Type)
545  * Examine the large/small bit in the resource header
546  */
547  if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
548 
549  /* Verify the large resource type (name) against the max */
550 
551  if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
552  goto invalid_resource;
553  }
554 
555  /*
556  * Large Resource Type -- bits 6:0 contain the name
557  * Translate range 0x80-0x8B to index range 0x10-0x1B
558  */
559  resource_index = (u8) (resource_type - 0x70);
560  } else {
561  /*
562  * Small Resource Type -- bits 6:3 contain the name
563  * Shift range to index range 0x00-0x0F
564  */
565  resource_index = (u8)
566  ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
567  }
568 
569  /*
570  * Check validity of the resource type, via acpi_gbl_resource_types. Zero
571  * indicates an invalid resource.
572  */
573  if (!acpi_gbl_resource_types[resource_index]) {
574  goto invalid_resource;
575  }
576 
577  /*
578  * Validate the resource_length field. This ensures that the length
579  * is at least reasonable, and guarantees that it is non-zero.
580  */
581  resource_length = acpi_ut_get_resource_length(aml);
582  minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index];
583 
584  /* Validate based upon the type of resource - fixed length or variable */
585 
586  switch (acpi_gbl_resource_types[resource_index]) {
587  case ACPI_FIXED_LENGTH:
588 
589  /* Fixed length resource, length must match exactly */
590 
591  if (resource_length != minimum_resource_length) {
592  goto bad_resource_length;
593  }
594  break;
595 
597 
598  /* Variable length resource, length must be at least the minimum */
599 
600  if (resource_length < minimum_resource_length) {
601  goto bad_resource_length;
602  }
603  break;
604 
606 
607  /* Small variable length resource, length can be (Min) or (Min-1) */
608 
609  if ((resource_length > minimum_resource_length) ||
610  (resource_length < (minimum_resource_length - 1))) {
611  goto bad_resource_length;
612  }
613  break;
614 
615  default:
616 
617  /* Shouldn't happen (because of validation earlier), but be sure */
618 
619  goto invalid_resource;
620  }
621 
622  aml_resource = ACPI_CAST_PTR(union aml_resource, aml);
623  if (resource_type == ACPI_RESOURCE_NAME_SERIAL_BUS) {
624 
625  /* Validate the bus_type field */
626 
627  if ((aml_resource->common_serial_bus.type == 0) ||
628  (aml_resource->common_serial_bus.type >
631  "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X",
632  aml_resource->common_serial_bus.
633  type));
635  }
636  }
637 
638  /* Optionally return the resource table index */
639 
640  if (return_index) {
641  *return_index = resource_index;
642  }
643 
644  return (AE_OK);
645 
646  invalid_resource:
647 
649  "Invalid/unsupported resource descriptor: Type 0x%2.2X",
650  resource_type));
652 
653  bad_resource_length:
654 
656  "Invalid resource descriptor length: Type "
657  "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X",
658  resource_type, resource_length,
659  minimum_resource_length));
661 }
662 
663 /*******************************************************************************
664  *
665  * FUNCTION: acpi_ut_get_resource_type
666  *
667  * PARAMETERS: aml - Pointer to the raw AML resource descriptor
668  *
669  * RETURN: The Resource Type with no extraneous bits (except the
670  * Large/Small descriptor bit -- this is left alone)
671  *
672  * DESCRIPTION: Extract the Resource Type/Name from the first byte of
673  * a resource descriptor.
674  *
675  ******************************************************************************/
676 
678 {
680 
681  /*
682  * Byte 0 contains the descriptor name (Resource Type)
683  * Examine the large/small bit in the resource header
684  */
685  if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
686 
687  /* Large Resource Type -- bits 6:0 contain the name */
688 
689  return (ACPI_GET8(aml));
690  } else {
691  /* Small Resource Type -- bits 6:3 contain the name */
692 
693  return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK));
694  }
695 }
696 
697 /*******************************************************************************
698  *
699  * FUNCTION: acpi_ut_get_resource_length
700  *
701  * PARAMETERS: aml - Pointer to the raw AML resource descriptor
702  *
703  * RETURN: Byte Length
704  *
705  * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By
706  * definition, this does not include the size of the descriptor
707  * header or the length field itself.
708  *
709  ******************************************************************************/
710 
712 {
713  acpi_rs_length resource_length;
714 
716 
717  /*
718  * Byte 0 contains the descriptor name (Resource Type)
719  * Examine the large/small bit in the resource header
720  */
721  if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
722 
723  /* Large Resource type -- bytes 1-2 contain the 16-bit length */
724 
725  ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1));
726 
727  } else {
728  /* Small Resource type -- bits 2:0 of byte 0 contain the length */
729 
730  resource_length = (u16) (ACPI_GET8(aml) &
732  }
733 
734  return (resource_length);
735 }
736 
737 /*******************************************************************************
738  *
739  * FUNCTION: acpi_ut_get_resource_header_length
740  *
741  * PARAMETERS: aml - Pointer to the raw AML resource descriptor
742  *
743  * RETURN: Length of the AML header (depends on large/small descriptor)
744  *
745  * DESCRIPTION: Get the length of the header for this resource.
746  *
747  ******************************************************************************/
748 
750 {
752 
753  /* Examine the large/small bit in the resource header */
754 
755  if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
756  return (sizeof(struct aml_resource_large_header));
757  } else {
758  return (sizeof(struct aml_resource_small_header));
759  }
760 }
761 
762 /*******************************************************************************
763  *
764  * FUNCTION: acpi_ut_get_descriptor_length
765  *
766  * PARAMETERS: aml - Pointer to the raw AML resource descriptor
767  *
768  * RETURN: Byte length
769  *
770  * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the
771  * length of the descriptor header and the length field itself.
772  * Used to walk descriptor lists.
773  *
774  ******************************************************************************/
775 
777 {
779 
780  /*
781  * Get the Resource Length (does not include header length) and add
782  * the header length (depends on if this is a small or large resource)
783  */
784  return (acpi_ut_get_resource_length(aml) +
786 }
787 
788 /*******************************************************************************
789  *
790  * FUNCTION: acpi_ut_get_resource_end_tag
791  *
792  * PARAMETERS: obj_desc - The resource template buffer object
793  * end_tag - Where the pointer to the end_tag is returned
794  *
795  * RETURN: Status, pointer to the end tag
796  *
797  * DESCRIPTION: Find the end_tag resource descriptor in an AML resource template
798  * Note: allows a buffer length of zero.
799  *
800  ******************************************************************************/
801 
804  u8 ** end_tag)
805 {
807 
808  ACPI_FUNCTION_TRACE(ut_get_resource_end_tag);
809 
810  /* Allow a buffer length of zero */
811 
812  if (!obj_desc->buffer.length) {
813  *end_tag = obj_desc->buffer.pointer;
815  }
816 
817  /* Validate the template and get a pointer to the end_tag */
818 
819  status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer,
820  obj_desc->buffer.length, NULL,
821  (void **)end_tag);
822 
823  return_ACPI_STATUS(status);
824 }