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