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
49ACPI_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 */
56static void acpi_rs_out_string(char *title, char *value);
57
58static void acpi_rs_out_integer8(char *title, u8 value);
59
60static void acpi_rs_out_integer16(char *title, u16 value);
61
62static void acpi_rs_out_integer32(char *title, u32 value);
63
64static void acpi_rs_out_integer64(char *title, u64 value);
65
66static void acpi_rs_out_title(char *title);
67
68static void acpi_rs_dump_byte_list(u16 length, u8 *data);
69
70static void acpi_rs_dump_word_list(u16 length, u16 *data);
71
72static void acpi_rs_dump_dword_list(u8 length, u32 *data);
73
74static void acpi_rs_dump_short_byte_list(u8 length, u8 *data);
75
76static void
77acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source);
78
79static void acpi_rs_dump_address_common(union acpi_resource_data *resource);
80
81static void
82acpi_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
96void 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
167void 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
207static void
208acpi_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
408static void
409acpi_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
437static 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
485static 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
494static void acpi_rs_out_integer8(char *title, u8 value)
495{
496	acpi_os_printf("%27s : %2.2X\n", title, value);
497}
498
499static void acpi_rs_out_integer16(char *title, u16 value)
500{
501	acpi_os_printf("%27s : %4.4X\n", title, value);
502}
503
504static void acpi_rs_out_integer32(char *title, u32 value)
505{
506	acpi_os_printf("%27s : %8.8X\n", title, value);
507}
508
509static 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
514static 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
532static 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
541static 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
551static 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
560static 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