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 } 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 134 void 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 174 static void 175 acpi_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 387 static void 388 acpi_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 416 static void 417 acpi_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 440 static 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 488 static 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 498 static void acpi_rs_out_integer8(const char *title, u8 value) 499 { 500 acpi_os_printf("%27s : %2.2X\n", title, value); 501 } 502 503 static void acpi_rs_out_integer16(const char *title, u16 value) 504 { 505 506 acpi_os_printf("%27s : %4.4X\n", title, value); 507 } 508 509 static void acpi_rs_out_integer32(const char *title, u32 value) 510 { 511 512 acpi_os_printf("%27s : %8.8X\n", title, value); 513 } 514 515 static 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 521 static 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 540 static 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 549 static 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 560 static 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 569 static 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