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