xref: /linux/drivers/acpi/acpica/rsdump.c (revision b85d45947951d23cb22d90caecf4c1eb81342c96)
1 /*******************************************************************************
2  *
3  * Module Name: rsdump - AML debugger support for resource structures.
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, 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_RESOURCES
49 ACPI_MODULE_NAME("rsdump")
50 
51 /*
52  * All functions in this module are used by the AML Debugger only
53  */
54 #if defined(ACPI_DEBUGGER)
55 /* Local prototypes */
56 static void acpi_rs_out_string(char *title, char *value);
57 
58 static void acpi_rs_out_integer8(char *title, u8 value);
59 
60 static void acpi_rs_out_integer16(char *title, u16 value);
61 
62 static void acpi_rs_out_integer32(char *title, u32 value);
63 
64 static void acpi_rs_out_integer64(char *title, u64 value);
65 
66 static void acpi_rs_out_title(char *title);
67 
68 static void acpi_rs_dump_byte_list(u16 length, u8 *data);
69 
70 static void acpi_rs_dump_word_list(u16 length, u16 *data);
71 
72 static void acpi_rs_dump_dword_list(u8 length, u32 *data);
73 
74 static void acpi_rs_dump_short_byte_list(u8 length, u8 *data);
75 
76 static void
77 acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source);
78 
79 static void acpi_rs_dump_address_common(union acpi_resource_data *resource);
80 
81 static void
82 acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table);
83 
84 /*******************************************************************************
85  *
86  * FUNCTION:    acpi_rs_dump_resource_list
87  *
88  * PARAMETERS:  resource_list       - Pointer to a resource descriptor list
89  *
90  * RETURN:      None
91  *
92  * DESCRIPTION: Dispatches the structure to the correct dump routine.
93  *
94  ******************************************************************************/
95 
96 void acpi_rs_dump_resource_list(struct acpi_resource *resource_list)
97 {
98 	u32 count = 0;
99 	u32 type;
100 
101 	ACPI_FUNCTION_ENTRY();
102 
103 	/* Check if debug output enabled */
104 
105 	if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_RESOURCES, _COMPONENT)) {
106 		return;
107 	}
108 
109 	/* Walk list and dump all resource descriptors (END_TAG terminates) */
110 
111 	do {
112 		acpi_os_printf("\n[%02X] ", count);
113 		count++;
114 
115 		/* Validate Type before dispatch */
116 
117 		type = resource_list->type;
118 		if (type > ACPI_RESOURCE_TYPE_MAX) {
119 			acpi_os_printf
120 			    ("Invalid descriptor type (%X) in resource list\n",
121 			     resource_list->type);
122 			return;
123 		}
124 
125 		/* Sanity check the length. It must not be zero, or we loop forever */
126 
127 		if (!resource_list->length) {
128 			acpi_os_printf
129 			    ("Invalid zero length descriptor in resource list\n");
130 			return;
131 		}
132 
133 		/* Dump the resource descriptor */
134 
135 		if (type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
136 			acpi_rs_dump_descriptor(&resource_list->data,
137 						acpi_gbl_dump_serial_bus_dispatch
138 						[resource_list->data.
139 						 common_serial_bus.type]);
140 		} else {
141 			acpi_rs_dump_descriptor(&resource_list->data,
142 						acpi_gbl_dump_resource_dispatch
143 						[type]);
144 		}
145 
146 		/* Point to the next resource structure */
147 
148 		resource_list = ACPI_NEXT_RESOURCE(resource_list);
149 
150 		/* Exit when END_TAG descriptor is reached */
151 
152 	} while (type != ACPI_RESOURCE_TYPE_END_TAG);
153 }
154 
155 /*******************************************************************************
156  *
157  * FUNCTION:    acpi_rs_dump_irq_list
158  *
159  * PARAMETERS:  route_table     - Pointer to the routing table to dump.
160  *
161  * RETURN:      None
162  *
163  * DESCRIPTION: Print IRQ routing table
164  *
165  ******************************************************************************/
166 
167 void acpi_rs_dump_irq_list(u8 *route_table)
168 {
169 	struct acpi_pci_routing_table *prt_element;
170 	u8 count;
171 
172 	ACPI_FUNCTION_ENTRY();
173 
174 	/* Check if debug output enabled */
175 
176 	if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_RESOURCES, _COMPONENT)) {
177 		return;
178 	}
179 
180 	prt_element = ACPI_CAST_PTR(struct acpi_pci_routing_table, route_table);
181 
182 	/* Dump all table elements, Exit on zero length element */
183 
184 	for (count = 0; prt_element->length; count++) {
185 		acpi_os_printf("\n[%02X] PCI IRQ Routing Table Package\n",
186 			       count);
187 		acpi_rs_dump_descriptor(prt_element, acpi_rs_dump_prt);
188 
189 		prt_element = ACPI_ADD_PTR(struct acpi_pci_routing_table,
190 					   prt_element, prt_element->length);
191 	}
192 }
193 
194 /*******************************************************************************
195  *
196  * FUNCTION:    acpi_rs_dump_descriptor
197  *
198  * PARAMETERS:  resource            - Buffer containing the resource
199  *              table               - Table entry to decode the resource
200  *
201  * RETURN:      None
202  *
203  * DESCRIPTION: Dump a resource descriptor based on a dump table entry.
204  *
205  ******************************************************************************/
206 
207 static void
208 acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
209 {
210 	u8 *target = NULL;
211 	u8 *previous_target;
212 	char *name;
213 	u8 count;
214 
215 	/* First table entry must contain the table length (# of table entries) */
216 
217 	count = table->offset;
218 
219 	while (count) {
220 		previous_target = target;
221 		target = ACPI_ADD_PTR(u8, resource, table->offset);
222 		name = table->name;
223 
224 		switch (table->opcode) {
225 		case ACPI_RSD_TITLE:
226 			/*
227 			 * Optional resource title
228 			 */
229 			if (table->name) {
230 				acpi_os_printf("%s Resource\n", name);
231 			}
232 			break;
233 
234 			/* Strings */
235 
236 		case ACPI_RSD_LITERAL:
237 
238 			acpi_rs_out_string(name,
239 					   ACPI_CAST_PTR(char, table->pointer));
240 			break;
241 
242 		case ACPI_RSD_STRING:
243 
244 			acpi_rs_out_string(name, ACPI_CAST_PTR(char, target));
245 			break;
246 
247 			/* Data items, 8/16/32/64 bit */
248 
249 		case ACPI_RSD_UINT8:
250 
251 			if (table->pointer) {
252 				acpi_rs_out_string(name, ACPI_CAST_PTR(char,
253 								       table->
254 								       pointer
255 								       [*target]));
256 			} else {
257 				acpi_rs_out_integer8(name, ACPI_GET8(target));
258 			}
259 			break;
260 
261 		case ACPI_RSD_UINT16:
262 
263 			acpi_rs_out_integer16(name, ACPI_GET16(target));
264 			break;
265 
266 		case ACPI_RSD_UINT32:
267 
268 			acpi_rs_out_integer32(name, ACPI_GET32(target));
269 			break;
270 
271 		case ACPI_RSD_UINT64:
272 
273 			acpi_rs_out_integer64(name, ACPI_GET64(target));
274 			break;
275 
276 			/* Flags: 1-bit and 2-bit flags supported */
277 
278 		case ACPI_RSD_1BITFLAG:
279 
280 			acpi_rs_out_string(name, ACPI_CAST_PTR(char,
281 							       table->
282 							       pointer[*target &
283 								       0x01]));
284 			break;
285 
286 		case ACPI_RSD_2BITFLAG:
287 
288 			acpi_rs_out_string(name, ACPI_CAST_PTR(char,
289 							       table->
290 							       pointer[*target &
291 								       0x03]));
292 			break;
293 
294 		case ACPI_RSD_3BITFLAG:
295 
296 			acpi_rs_out_string(name, ACPI_CAST_PTR(char,
297 							       table->
298 							       pointer[*target &
299 								       0x07]));
300 			break;
301 
302 		case ACPI_RSD_SHORTLIST:
303 			/*
304 			 * Short byte list (single line output) for DMA and IRQ resources
305 			 * Note: The list length is obtained from the previous table entry
306 			 */
307 			if (previous_target) {
308 				acpi_rs_out_title(name);
309 				acpi_rs_dump_short_byte_list(*previous_target,
310 							     target);
311 			}
312 			break;
313 
314 		case ACPI_RSD_SHORTLISTX:
315 			/*
316 			 * Short byte list (single line output) for GPIO vendor data
317 			 * Note: The list length is obtained from the previous table entry
318 			 */
319 			if (previous_target) {
320 				acpi_rs_out_title(name);
321 				acpi_rs_dump_short_byte_list(*previous_target,
322 							     *
323 							     (ACPI_CAST_INDIRECT_PTR
324 							      (u8, target)));
325 			}
326 			break;
327 
328 		case ACPI_RSD_LONGLIST:
329 			/*
330 			 * Long byte list for Vendor resource data
331 			 * Note: The list length is obtained from the previous table entry
332 			 */
333 			if (previous_target) {
334 				acpi_rs_dump_byte_list(ACPI_GET16
335 						       (previous_target),
336 						       target);
337 			}
338 			break;
339 
340 		case ACPI_RSD_DWORDLIST:
341 			/*
342 			 * Dword list for Extended Interrupt resources
343 			 * Note: The list length is obtained from the previous table entry
344 			 */
345 			if (previous_target) {
346 				acpi_rs_dump_dword_list(*previous_target,
347 							ACPI_CAST_PTR(u32,
348 								      target));
349 			}
350 			break;
351 
352 		case ACPI_RSD_WORDLIST:
353 			/*
354 			 * Word list for GPIO Pin Table
355 			 * Note: The list length is obtained from the previous table entry
356 			 */
357 			if (previous_target) {
358 				acpi_rs_dump_word_list(*previous_target,
359 						       *(ACPI_CAST_INDIRECT_PTR
360 							 (u16, target)));
361 			}
362 			break;
363 
364 		case ACPI_RSD_ADDRESS:
365 			/*
366 			 * Common flags for all Address resources
367 			 */
368 			acpi_rs_dump_address_common(ACPI_CAST_PTR
369 						    (union acpi_resource_data,
370 						     target));
371 			break;
372 
373 		case ACPI_RSD_SOURCE:
374 			/*
375 			 * Optional resource_source for Address resources
376 			 */
377 			acpi_rs_dump_resource_source(ACPI_CAST_PTR
378 						     (struct
379 								   acpi_resource_source,
380 								   target));
381 			break;
382 
383 		default:
384 
385 			acpi_os_printf("**** Invalid table opcode [%X] ****\n",
386 				       table->opcode);
387 			return;
388 		}
389 
390 		table++;
391 		count--;
392 	}
393 }
394 
395 /*******************************************************************************
396  *
397  * FUNCTION:    acpi_rs_dump_resource_source
398  *
399  * PARAMETERS:  resource_source     - Pointer to a Resource Source struct
400  *
401  * RETURN:      None
402  *
403  * DESCRIPTION: Common routine for dumping the optional resource_source and the
404  *              corresponding resource_source_index.
405  *
406  ******************************************************************************/
407 
408 static void
409 acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source)
410 {
411 	ACPI_FUNCTION_ENTRY();
412 
413 	if (resource_source->index == 0xFF) {
414 		return;
415 	}
416 
417 	acpi_rs_out_integer8("Resource Source Index", resource_source->index);
418 
419 	acpi_rs_out_string("Resource Source",
420 			   resource_source->string_ptr ?
421 			   resource_source->string_ptr : "[Not Specified]");
422 }
423 
424 /*******************************************************************************
425  *
426  * FUNCTION:    acpi_rs_dump_address_common
427  *
428  * PARAMETERS:  resource        - Pointer to an internal resource descriptor
429  *
430  * RETURN:      None
431  *
432  * DESCRIPTION: Dump the fields that are common to all Address resource
433  *              descriptors
434  *
435  ******************************************************************************/
436 
437 static void acpi_rs_dump_address_common(union acpi_resource_data *resource)
438 {
439 	ACPI_FUNCTION_ENTRY();
440 
441 	/* Decode the type-specific flags */
442 
443 	switch (resource->address.resource_type) {
444 	case ACPI_MEMORY_RANGE:
445 
446 		acpi_rs_dump_descriptor(resource, acpi_rs_dump_memory_flags);
447 		break;
448 
449 	case ACPI_IO_RANGE:
450 
451 		acpi_rs_dump_descriptor(resource, acpi_rs_dump_io_flags);
452 		break;
453 
454 	case ACPI_BUS_NUMBER_RANGE:
455 
456 		acpi_rs_out_string("Resource Type", "Bus Number Range");
457 		break;
458 
459 	default:
460 
461 		acpi_rs_out_integer8("Resource Type",
462 				     (u8) resource->address.resource_type);
463 		break;
464 	}
465 
466 	/* Decode the general flags */
467 
468 	acpi_rs_dump_descriptor(resource, acpi_rs_dump_general_flags);
469 }
470 
471 /*******************************************************************************
472  *
473  * FUNCTION:    acpi_rs_out*
474  *
475  * PARAMETERS:  title       - Name of the resource field
476  *              value       - Value of the resource field
477  *
478  * RETURN:      None
479  *
480  * DESCRIPTION: Miscellaneous helper functions to consistently format the
481  *              output of the resource dump routines
482  *
483  ******************************************************************************/
484 
485 static void acpi_rs_out_string(char *title, char *value)
486 {
487 	acpi_os_printf("%27s : %s", title, value);
488 	if (!*value) {
489 		acpi_os_printf("[NULL NAMESTRING]");
490 	}
491 	acpi_os_printf("\n");
492 }
493 
494 static void acpi_rs_out_integer8(char *title, u8 value)
495 {
496 	acpi_os_printf("%27s : %2.2X\n", title, value);
497 }
498 
499 static void acpi_rs_out_integer16(char *title, u16 value)
500 {
501 	acpi_os_printf("%27s : %4.4X\n", title, value);
502 }
503 
504 static void acpi_rs_out_integer32(char *title, u32 value)
505 {
506 	acpi_os_printf("%27s : %8.8X\n", title, value);
507 }
508 
509 static void acpi_rs_out_integer64(char *title, u64 value)
510 {
511 	acpi_os_printf("%27s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value));
512 }
513 
514 static void acpi_rs_out_title(char *title)
515 {
516 	acpi_os_printf("%27s : ", title);
517 }
518 
519 /*******************************************************************************
520  *
521  * FUNCTION:    acpi_rs_dump*List
522  *
523  * PARAMETERS:  length      - Number of elements in the list
524  *              data        - Start of the list
525  *
526  * RETURN:      None
527  *
528  * DESCRIPTION: Miscellaneous functions to dump lists of raw data
529  *
530  ******************************************************************************/
531 
532 static void acpi_rs_dump_byte_list(u16 length, u8 * data)
533 {
534 	u8 i;
535 
536 	for (i = 0; i < length; i++) {
537 		acpi_os_printf("%25s%2.2X : %2.2X\n", "Byte", i, data[i]);
538 	}
539 }
540 
541 static void acpi_rs_dump_short_byte_list(u8 length, u8 * data)
542 {
543 	u8 i;
544 
545 	for (i = 0; i < length; i++) {
546 		acpi_os_printf("%X ", data[i]);
547 	}
548 	acpi_os_printf("\n");
549 }
550 
551 static void acpi_rs_dump_dword_list(u8 length, u32 * data)
552 {
553 	u8 i;
554 
555 	for (i = 0; i < length; i++) {
556 		acpi_os_printf("%25s%2.2X : %8.8X\n", "Dword", i, data[i]);
557 	}
558 }
559 
560 static void acpi_rs_dump_word_list(u16 length, u16 *data)
561 {
562 	u16 i;
563 
564 	for (i = 0; i < length; i++) {
565 		acpi_os_printf("%25s%2.2X : %4.4X\n", "Word", i, data[i]);
566 	}
567 }
568 
569 #endif
570