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