Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 : : /******************************************************************************* 3 : : * 4 : : * Module Name: rscalc - Calculate stream and list lengths 5 : : * 6 : : ******************************************************************************/ 7 : : 8 : : #include <acpi/acpi.h> 9 : : #include "accommon.h" 10 : : #include "acresrc.h" 11 : : #include "acnamesp.h" 12 : : 13 : : #define _COMPONENT ACPI_RESOURCES 14 : : ACPI_MODULE_NAME("rscalc") 15 : : 16 : : /* Local prototypes */ 17 : : static u8 acpi_rs_count_set_bits(u16 bit_field); 18 : : 19 : : static acpi_rs_length 20 : : acpi_rs_struct_option_length(struct acpi_resource_source *resource_source); 21 : : 22 : : static u32 23 : : acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length); 24 : : 25 : : /******************************************************************************* 26 : : * 27 : : * FUNCTION: acpi_rs_count_set_bits 28 : : * 29 : : * PARAMETERS: bit_field - Field in which to count bits 30 : : * 31 : : * RETURN: Number of bits set within the field 32 : : * 33 : : * DESCRIPTION: Count the number of bits set in a resource field. Used for 34 : : * (Short descriptor) interrupt and DMA lists. 35 : : * 36 : : ******************************************************************************/ 37 : : 38 : 315 : static u8 acpi_rs_count_set_bits(u16 bit_field) 39 : : { 40 : 315 : u8 bits_set; 41 : : 42 : 315 : ACPI_FUNCTION_ENTRY(); 43 : : 44 [ + + ]: 630 : for (bits_set = 0; bit_field; bits_set++) { 45 : : 46 : : /* Zero the least significant bit that is set */ 47 : : 48 : 315 : bit_field &= (u16) (bit_field - 1); 49 : : } 50 : : 51 : 315 : return (bits_set); 52 : : } 53 : : 54 : : /******************************************************************************* 55 : : * 56 : : * FUNCTION: acpi_rs_struct_option_length 57 : : * 58 : : * PARAMETERS: resource_source - Pointer to optional descriptor field 59 : : * 60 : : * RETURN: Status 61 : : * 62 : : * DESCRIPTION: Common code to handle optional resource_source_index and 63 : : * resource_source fields in some Large descriptors. Used during 64 : : * list-to-stream conversion 65 : : * 66 : : ******************************************************************************/ 67 : : 68 : : static acpi_rs_length 69 : 21 : acpi_rs_struct_option_length(struct acpi_resource_source *resource_source) 70 : : { 71 : 21 : ACPI_FUNCTION_ENTRY(); 72 : : 73 : : /* 74 : : * If the resource_source string is valid, return the size of the string 75 : : * (string_length includes the NULL terminator) plus the size of the 76 : : * resource_source_index (1). 77 : : */ 78 [ - + ]: 21 : if (resource_source->string_ptr) { 79 : 0 : return ((acpi_rs_length)(resource_source->string_length + 1)); 80 : : } 81 : : 82 : : return (0); 83 : : } 84 : : 85 : : /******************************************************************************* 86 : : * 87 : : * FUNCTION: acpi_rs_stream_option_length 88 : : * 89 : : * PARAMETERS: resource_length - Length from the resource header 90 : : * minimum_total_length - Minimum length of this resource, before 91 : : * any optional fields. Includes header size 92 : : * 93 : : * RETURN: Length of optional string (0 if no string present) 94 : : * 95 : : * DESCRIPTION: Common code to handle optional resource_source_index and 96 : : * resource_source fields in some Large descriptors. Used during 97 : : * stream-to-list conversion 98 : : * 99 : : ******************************************************************************/ 100 : : 101 : : static u32 102 : 651 : acpi_rs_stream_option_length(u32 resource_length, 103 : : u32 minimum_aml_resource_length) 104 : : { 105 : 651 : u32 string_length = 0; 106 : : 107 : 651 : ACPI_FUNCTION_ENTRY(); 108 : : 109 : : /* 110 : : * The resource_source_index and resource_source are optional elements of 111 : : * some Large-type resource descriptors. 112 : : */ 113 : : 114 : : /* 115 : : * If the length of the actual resource descriptor is greater than the 116 : : * ACPI spec-defined minimum length, it means that a resource_source_index 117 : : * exists and is followed by a (required) null terminated string. The 118 : : * string length (including the null terminator) is the resource length 119 : : * minus the minimum length, minus one byte for the resource_source_index 120 : : * itself. 121 : : */ 122 [ - + ]: 651 : if (resource_length > minimum_aml_resource_length) { 123 : : 124 : : /* Compute the length of the optional string */ 125 : : 126 : 0 : string_length = 127 : 0 : resource_length - minimum_aml_resource_length - 1; 128 : : } 129 : : 130 : : /* 131 : : * Round the length up to a multiple of the native word in order to 132 : : * guarantee that the entire resource descriptor is native word aligned 133 : : */ 134 : 651 : return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length)); 135 : : } 136 : : 137 : : /******************************************************************************* 138 : : * 139 : : * FUNCTION: acpi_rs_get_aml_length 140 : : * 141 : : * PARAMETERS: resource - Pointer to the resource linked list 142 : : * resource_list_size - Size of the resource linked list 143 : : * size_needed - Where the required size is returned 144 : : * 145 : : * RETURN: Status 146 : : * 147 : : * DESCRIPTION: Takes a linked list of internal resource descriptors and 148 : : * calculates the size buffer needed to hold the corresponding 149 : : * external resource byte stream. 150 : : * 151 : : ******************************************************************************/ 152 : : 153 : : acpi_status 154 : 21 : acpi_rs_get_aml_length(struct acpi_resource *resource, 155 : : acpi_size resource_list_size, acpi_size *size_needed) 156 : : { 157 : 21 : acpi_size aml_size_needed = 0; 158 : 21 : struct acpi_resource *resource_end; 159 : 21 : acpi_rs_length total_size; 160 : : 161 : 21 : ACPI_FUNCTION_TRACE(rs_get_aml_length); 162 : : 163 : : /* Traverse entire list of internal resource descriptors */ 164 : : 165 : 21 : resource_end = 166 : : ACPI_ADD_PTR(struct acpi_resource, resource, resource_list_size); 167 [ + - ]: 42 : while (resource < resource_end) { 168 : : 169 : : /* Validate the descriptor type */ 170 : : 171 [ + - ]: 42 : if (resource->type > ACPI_RESOURCE_TYPE_MAX) { 172 : : return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); 173 : : } 174 : : 175 : : /* Sanity check the length. It must not be zero, or we loop forever */ 176 : : 177 [ + - ]: 42 : if (!resource->length) { 178 : : return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); 179 : : } 180 : : 181 : : /* Get the base size of the (external stream) resource descriptor */ 182 : : 183 : 42 : total_size = acpi_gbl_aml_resource_sizes[resource->type]; 184 : : 185 : : /* 186 : : * Augment the base size for descriptors with optional and/or 187 : : * variable-length fields 188 : : */ 189 [ - - - + : 42 : switch (resource->type) { - - - + - - - - - - - - ] 190 : 0 : case ACPI_RESOURCE_TYPE_IRQ: 191 : : 192 : : /* Length can be 3 or 2 */ 193 : : 194 [ # # ]: 0 : if (resource->data.irq.descriptor_length == 2) { 195 : 0 : total_size--; 196 : : } 197 : : break; 198 : : 199 : 0 : case ACPI_RESOURCE_TYPE_START_DEPENDENT: 200 : : 201 : : /* Length can be 1 or 0 */ 202 : : 203 [ # # ]: 0 : if (resource->data.irq.descriptor_length == 0) { 204 : 0 : total_size--; 205 : : } 206 : : break; 207 : : 208 : 0 : case ACPI_RESOURCE_TYPE_VENDOR: 209 : : /* 210 : : * Vendor Defined Resource: 211 : : * For a Vendor Specific resource, if the Length is between 1 and 7 212 : : * it will be created as a Small Resource data type, otherwise it 213 : : * is a Large Resource data type. 214 : : */ 215 [ # # ]: 0 : if (resource->data.vendor.byte_length > 7) { 216 : : 217 : : /* Base size of a Large resource descriptor */ 218 : : 219 : 0 : total_size = 220 : : sizeof(struct aml_resource_large_header); 221 : : } 222 : : 223 : : /* Add the size of the vendor-specific data */ 224 : : 225 : 0 : total_size = (acpi_rs_length) 226 : : (total_size + resource->data.vendor.byte_length); 227 : 0 : break; 228 : : 229 : 21 : case ACPI_RESOURCE_TYPE_END_TAG: 230 : : /* 231 : : * End Tag: 232 : : * We are done -- return the accumulated total size. 233 : : */ 234 : 21 : *size_needed = aml_size_needed + total_size; 235 : : 236 : : /* Normal exit */ 237 : : 238 : 21 : return_ACPI_STATUS(AE_OK); 239 : : 240 : 0 : case ACPI_RESOURCE_TYPE_ADDRESS16: 241 : : /* 242 : : * 16-Bit Address Resource: 243 : : * Add the size of the optional resource_source info 244 : : */ 245 : 0 : total_size = (acpi_rs_length)(total_size + 246 : 0 : acpi_rs_struct_option_length 247 : : (&resource->data. 248 : : address16. 249 : : resource_source)); 250 : 0 : break; 251 : : 252 : 0 : case ACPI_RESOURCE_TYPE_ADDRESS32: 253 : : /* 254 : : * 32-Bit Address Resource: 255 : : * Add the size of the optional resource_source info 256 : : */ 257 : 0 : total_size = (acpi_rs_length)(total_size + 258 : 0 : acpi_rs_struct_option_length 259 : : (&resource->data. 260 : : address32. 261 : : resource_source)); 262 : 0 : break; 263 : : 264 : 0 : case ACPI_RESOURCE_TYPE_ADDRESS64: 265 : : /* 266 : : * 64-Bit Address Resource: 267 : : * Add the size of the optional resource_source info 268 : : */ 269 : 0 : total_size = (acpi_rs_length)(total_size + 270 : 0 : acpi_rs_struct_option_length 271 : : (&resource->data. 272 : : address64. 273 : : resource_source)); 274 : 0 : break; 275 : : 276 : 21 : case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 277 : : /* 278 : : * Extended IRQ Resource: 279 : : * Add the size of each additional optional interrupt beyond the 280 : : * required 1 (4 bytes for each u32 interrupt number) 281 : : */ 282 : 21 : total_size = (acpi_rs_length)(total_size + 283 : : ((resource->data. 284 : 21 : extended_irq. 285 : 21 : interrupt_count - 286 : 21 : 1) * 4) + 287 : : /* Add the size of the optional resource_source info */ 288 : 21 : acpi_rs_struct_option_length 289 : : (&resource->data. 290 : : extended_irq. 291 : : resource_source)); 292 : 21 : break; 293 : : 294 : 0 : case ACPI_RESOURCE_TYPE_GPIO: 295 : : 296 : 0 : total_size = (acpi_rs_length)(total_size + 297 : 0 : (resource->data.gpio. 298 : 0 : pin_table_length * 2) + 299 : : resource->data.gpio. 300 : 0 : resource_source. 301 : 0 : string_length + 302 : 0 : resource->data.gpio. 303 : : vendor_length); 304 : : 305 : 0 : break; 306 : : 307 : 0 : case ACPI_RESOURCE_TYPE_PIN_FUNCTION: 308 : : 309 : 0 : total_size = (acpi_rs_length)(total_size + 310 : : (resource->data. 311 : 0 : pin_function. 312 : 0 : pin_table_length * 2) + 313 : : resource->data. 314 : : pin_function. 315 : 0 : resource_source. 316 : 0 : string_length + 317 : : resource->data. 318 : 0 : pin_function. 319 : : vendor_length); 320 : : 321 : 0 : break; 322 : : 323 : 0 : case ACPI_RESOURCE_TYPE_SERIAL_BUS: 324 : : 325 : 0 : total_size = 326 : 0 : acpi_gbl_aml_resource_serial_bus_sizes[resource-> 327 : : data. 328 : 0 : common_serial_bus. 329 : : type]; 330 : : 331 : 0 : total_size = (acpi_rs_length)(total_size + 332 : : resource->data. 333 : : i2c_serial_bus. 334 : 0 : resource_source. 335 : 0 : string_length + 336 : : resource->data. 337 : 0 : i2c_serial_bus. 338 : : vendor_length); 339 : : 340 : 0 : break; 341 : : 342 : 0 : case ACPI_RESOURCE_TYPE_PIN_CONFIG: 343 : : 344 : 0 : total_size = (acpi_rs_length)(total_size + 345 : : (resource->data. 346 : 0 : pin_config. 347 : 0 : pin_table_length * 2) + 348 : : resource->data.pin_config. 349 : 0 : resource_source. 350 : 0 : string_length + 351 : 0 : resource->data.pin_config. 352 : : vendor_length); 353 : : 354 : 0 : break; 355 : : 356 : 0 : case ACPI_RESOURCE_TYPE_PIN_GROUP: 357 : : 358 : 0 : total_size = (acpi_rs_length)(total_size + 359 : 0 : (resource->data.pin_group. 360 : 0 : pin_table_length * 2) + 361 : : resource->data.pin_group. 362 : 0 : resource_label. 363 : 0 : string_length + 364 : 0 : resource->data.pin_group. 365 : : vendor_length); 366 : : 367 : 0 : break; 368 : : 369 : 0 : case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION: 370 : : 371 : 0 : total_size = (acpi_rs_length)(total_size + 372 : : resource->data. 373 : : pin_group_function. 374 : 0 : resource_source. 375 : 0 : string_length + 376 : : resource->data. 377 : : pin_group_function. 378 : 0 : resource_source_label. 379 : 0 : string_length + 380 : : resource->data. 381 : 0 : pin_group_function. 382 : : vendor_length); 383 : : 384 : 0 : break; 385 : : 386 : 0 : case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG: 387 : : 388 : 0 : total_size = (acpi_rs_length)(total_size + 389 : : resource->data. 390 : : pin_group_config. 391 : 0 : resource_source. 392 : 0 : string_length + 393 : : resource->data. 394 : : pin_group_config. 395 : 0 : resource_source_label. 396 : 0 : string_length + 397 : : resource->data. 398 : 0 : pin_group_config. 399 : : vendor_length); 400 : : 401 : 0 : break; 402 : : 403 : : default: 404 : : 405 : : break; 406 : : } 407 : : 408 : : /* Update the total */ 409 : : 410 : 21 : aml_size_needed += total_size; 411 : : 412 : : /* Point to the next object */ 413 : : 414 : 21 : resource = 415 : 21 : ACPI_ADD_PTR(struct acpi_resource, resource, 416 : : resource->length); 417 : : } 418 : : 419 : : /* Did not find an end_tag resource descriptor */ 420 : : 421 : : return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); 422 : : } 423 : : 424 : : /******************************************************************************* 425 : : * 426 : : * FUNCTION: acpi_rs_get_list_length 427 : : * 428 : : * PARAMETERS: aml_buffer - Pointer to the resource byte stream 429 : : * aml_buffer_length - Size of aml_buffer 430 : : * size_needed - Where the size needed is returned 431 : : * 432 : : * RETURN: Status 433 : : * 434 : : * DESCRIPTION: Takes an external resource byte stream and calculates the size 435 : : * buffer needed to hold the corresponding internal resource 436 : : * descriptor linked list. 437 : : * 438 : : ******************************************************************************/ 439 : : 440 : : acpi_status 441 : 840 : acpi_rs_get_list_length(u8 *aml_buffer, 442 : : u32 aml_buffer_length, acpi_size *size_needed) 443 : : { 444 : 840 : acpi_status status; 445 : 840 : u8 *end_aml; 446 : 840 : u8 *buffer; 447 : 840 : u32 buffer_size; 448 : 840 : u16 temp16; 449 : 840 : u16 resource_length; 450 : 840 : u32 extra_struct_bytes; 451 : 840 : u8 resource_index; 452 : 840 : u8 minimum_aml_resource_length; 453 : 840 : union aml_resource *aml_resource; 454 : : 455 : 840 : ACPI_FUNCTION_TRACE(rs_get_list_length); 456 : : 457 : 840 : *size_needed = ACPI_RS_SIZE_MIN; /* Minimum size is one end_tag */ 458 : 840 : end_aml = aml_buffer + aml_buffer_length; 459 : : 460 : : /* Walk the list of AML resource descriptors */ 461 : : 462 [ + - ]: 2394 : while (aml_buffer < end_aml) { 463 : : 464 : : /* Validate the Resource Type and Resource Length */ 465 : : 466 : 2394 : status = 467 : 2394 : acpi_ut_validate_resource(NULL, aml_buffer, 468 : : &resource_index); 469 [ - + ]: 2394 : if (ACPI_FAILURE(status)) { 470 : : /* 471 : : * Exit on failure. Cannot continue because the descriptor length 472 : : * may be bogus also. 473 : : */ 474 : 0 : return_ACPI_STATUS(status); 475 : : } 476 : : 477 : 2394 : aml_resource = (void *)aml_buffer; 478 : : 479 : : /* Get the resource length and base (minimum) AML size */ 480 : : 481 : 2394 : resource_length = acpi_ut_get_resource_length(aml_buffer); 482 : 2394 : minimum_aml_resource_length = 483 : 2394 : acpi_gbl_resource_aml_sizes[resource_index]; 484 : : 485 : : /* 486 : : * Augment the size for descriptors with optional 487 : : * and/or variable length fields 488 : : */ 489 : 2394 : extra_struct_bytes = 0; 490 : 4788 : buffer = 491 : 2394 : aml_buffer + acpi_ut_get_resource_header_length(aml_buffer); 492 : : 493 [ + + - + : 2394 : switch (acpi_ut_get_resource_type(aml_buffer)) { + - - - - - - - + + ] 494 : 273 : case ACPI_RESOURCE_NAME_IRQ: 495 : : /* 496 : : * IRQ Resource: 497 : : * Get the number of bits set in the 16-bit IRQ mask 498 : : */ 499 : 273 : ACPI_MOVE_16_TO_16(&temp16, buffer); 500 : 273 : extra_struct_bytes = acpi_rs_count_set_bits(temp16); 501 : 273 : break; 502 : : 503 : 42 : case ACPI_RESOURCE_NAME_DMA: 504 : : /* 505 : : * DMA Resource: 506 : : * Get the number of bits set in the 8-bit DMA mask 507 : : */ 508 : 42 : extra_struct_bytes = acpi_rs_count_set_bits(*buffer); 509 : 42 : break; 510 : : 511 : 0 : case ACPI_RESOURCE_NAME_VENDOR_SMALL: 512 : : case ACPI_RESOURCE_NAME_VENDOR_LARGE: 513 : : /* 514 : : * Vendor Resource: 515 : : * Get the number of vendor data bytes 516 : : */ 517 : 0 : extra_struct_bytes = resource_length; 518 : : 519 : : /* 520 : : * There is already one byte included in the minimum 521 : : * descriptor size. If there are extra struct bytes, 522 : : * subtract one from the count. 523 : : */ 524 [ # # ]: 0 : if (extra_struct_bytes) { 525 : 0 : extra_struct_bytes--; 526 : : } 527 : : break; 528 : : 529 : : case ACPI_RESOURCE_NAME_END_TAG: 530 : : /* 531 : : * End Tag: This is the normal exit 532 : : */ 533 : : return_ACPI_STATUS(AE_OK); 534 : : 535 : 315 : case ACPI_RESOURCE_NAME_ADDRESS32: 536 : : case ACPI_RESOURCE_NAME_ADDRESS16: 537 : : case ACPI_RESOURCE_NAME_ADDRESS64: 538 : : /* 539 : : * Address Resource: 540 : : * Add the size of the optional resource_source 541 : : */ 542 : 315 : extra_struct_bytes = 543 : 315 : acpi_rs_stream_option_length(resource_length, 544 : : minimum_aml_resource_length); 545 : 315 : break; 546 : : 547 : 336 : case ACPI_RESOURCE_NAME_EXTENDED_IRQ: 548 : : /* 549 : : * Extended IRQ Resource: 550 : : * Using the interrupt_table_length, add 4 bytes for each additional 551 : : * interrupt. Note: at least one interrupt is required and is 552 : : * included in the minimum descriptor size (reason for the -1) 553 : : */ 554 : 336 : extra_struct_bytes = (buffer[1] - 1) * sizeof(u32); 555 : : 556 : : /* Add the size of the optional resource_source */ 557 : : 558 : 336 : extra_struct_bytes += 559 : 336 : acpi_rs_stream_option_length(resource_length - 560 : : extra_struct_bytes, 561 : : minimum_aml_resource_length); 562 : 336 : break; 563 : : 564 : 0 : case ACPI_RESOURCE_NAME_GPIO: 565 : : 566 : : /* Vendor data is optional */ 567 : : 568 [ # # ]: 0 : if (aml_resource->gpio.vendor_length) { 569 : 0 : extra_struct_bytes += 570 : 0 : aml_resource->gpio.vendor_offset - 571 : 0 : aml_resource->gpio.pin_table_offset + 572 : 0 : aml_resource->gpio.vendor_length; 573 : : } else { 574 : 0 : extra_struct_bytes += 575 : 0 : aml_resource->large_header.resource_length + 576 : 0 : sizeof(struct aml_resource_large_header) - 577 : 0 : aml_resource->gpio.pin_table_offset; 578 : : } 579 : : break; 580 : : 581 : 0 : case ACPI_RESOURCE_NAME_PIN_FUNCTION: 582 : : 583 : : /* Vendor data is optional */ 584 : : 585 [ # # ]: 0 : if (aml_resource->pin_function.vendor_length) { 586 : 0 : extra_struct_bytes += 587 : 0 : aml_resource->pin_function.vendor_offset - 588 : 0 : aml_resource->pin_function. 589 : 0 : pin_table_offset + 590 : 0 : aml_resource->pin_function.vendor_length; 591 : : } else { 592 : 0 : extra_struct_bytes += 593 : 0 : aml_resource->large_header.resource_length + 594 : 0 : sizeof(struct aml_resource_large_header) - 595 : 0 : aml_resource->pin_function.pin_table_offset; 596 : : } 597 : : break; 598 : : 599 : 0 : case ACPI_RESOURCE_NAME_SERIAL_BUS: 600 : : 601 : 0 : minimum_aml_resource_length = 602 : : acpi_gbl_resource_aml_serial_bus_sizes 603 : 0 : [aml_resource->common_serial_bus.type]; 604 : 0 : extra_struct_bytes += 605 : 0 : aml_resource->common_serial_bus.resource_length - 606 : : minimum_aml_resource_length; 607 : 0 : break; 608 : : 609 : 0 : case ACPI_RESOURCE_NAME_PIN_CONFIG: 610 : : 611 : : /* Vendor data is optional */ 612 : : 613 [ # # ]: 0 : if (aml_resource->pin_config.vendor_length) { 614 : 0 : extra_struct_bytes += 615 : 0 : aml_resource->pin_config.vendor_offset - 616 : 0 : aml_resource->pin_config.pin_table_offset + 617 : 0 : aml_resource->pin_config.vendor_length; 618 : : } else { 619 : 0 : extra_struct_bytes += 620 : 0 : aml_resource->large_header.resource_length + 621 : 0 : sizeof(struct aml_resource_large_header) - 622 : 0 : aml_resource->pin_config.pin_table_offset; 623 : : } 624 : : break; 625 : : 626 : 0 : case ACPI_RESOURCE_NAME_PIN_GROUP: 627 : : 628 : 0 : extra_struct_bytes += 629 : 0 : aml_resource->pin_group.vendor_offset - 630 : 0 : aml_resource->pin_group.pin_table_offset + 631 : 0 : aml_resource->pin_group.vendor_length; 632 : : 633 : 0 : break; 634 : : 635 : 0 : case ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION: 636 : : 637 : 0 : extra_struct_bytes += 638 : 0 : aml_resource->pin_group_function.vendor_offset - 639 : 0 : aml_resource->pin_group_function.res_source_offset + 640 : 0 : aml_resource->pin_group_function.vendor_length; 641 : : 642 : 0 : break; 643 : : 644 : 0 : case ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG: 645 : : 646 : 0 : extra_struct_bytes += 647 : 0 : aml_resource->pin_group_config.vendor_offset - 648 : 0 : aml_resource->pin_group_config.res_source_offset + 649 : 0 : aml_resource->pin_group_config.vendor_length; 650 : : 651 : 0 : break; 652 : : 653 : : default: 654 : : 655 : : break; 656 : : } 657 : : 658 : : /* 659 : : * Update the required buffer size for the internal descriptor structs 660 : : * 661 : : * Important: Round the size up for the appropriate alignment. This 662 : : * is a requirement on IA64. 663 : : */ 664 [ - + ]: 1554 : if (acpi_ut_get_resource_type(aml_buffer) == 665 : : ACPI_RESOURCE_NAME_SERIAL_BUS) { 666 : 0 : buffer_size = 667 : : acpi_gbl_resource_struct_serial_bus_sizes 668 : 0 : [aml_resource->common_serial_bus.type] + 669 : : extra_struct_bytes; 670 : : } else { 671 : 1554 : buffer_size = 672 : 1554 : acpi_gbl_resource_struct_sizes[resource_index] + 673 : : extra_struct_bytes; 674 : : } 675 : : 676 : 1554 : buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size); 677 : 1554 : *size_needed += buffer_size; 678 : : 679 : : ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 680 : : "Type %.2X, AmlLength %.2X InternalLength %.2X\n", 681 : : acpi_ut_get_resource_type(aml_buffer), 682 : : acpi_ut_get_descriptor_length(aml_buffer), 683 : 1554 : buffer_size)); 684 : : 685 : : /* 686 : : * Point to the next resource within the AML stream using the length 687 : : * contained in the resource descriptor header 688 : : */ 689 : 1554 : aml_buffer += acpi_ut_get_descriptor_length(aml_buffer); 690 : : } 691 : : 692 : : /* Did not find an end_tag resource descriptor */ 693 : : 694 : : return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); 695 : : } 696 : : 697 : : /******************************************************************************* 698 : : * 699 : : * FUNCTION: acpi_rs_get_pci_routing_table_length 700 : : * 701 : : * PARAMETERS: package_object - Pointer to the package object 702 : : * buffer_size_needed - u32 pointer of the size buffer 703 : : * needed to properly return the 704 : : * parsed data 705 : : * 706 : : * RETURN: Status 707 : : * 708 : : * DESCRIPTION: Given a package representing a PCI routing table, this 709 : : * calculates the size of the corresponding linked list of 710 : : * descriptions. 711 : : * 712 : : ******************************************************************************/ 713 : : 714 : : acpi_status 715 : 21 : acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, 716 : : acpi_size *buffer_size_needed) 717 : : { 718 : 21 : u32 number_of_elements; 719 : 21 : acpi_size temp_size_needed = 0; 720 : 21 : union acpi_operand_object **top_object_list; 721 : 21 : u32 index; 722 : 21 : union acpi_operand_object *package_element; 723 : 21 : union acpi_operand_object **sub_object_list; 724 : 21 : u8 name_found; 725 : 21 : u32 table_index; 726 : : 727 : 21 : ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length); 728 : : 729 : 21 : number_of_elements = package_object->package.count; 730 : : 731 : : /* 732 : : * Calculate the size of the return buffer. 733 : : * The base size is the number of elements * the sizes of the 734 : : * structures. Additional space for the strings is added below. 735 : : * The minus one is to subtract the size of the u8 Source[1] 736 : : * member because it is added below. 737 : : * 738 : : * But each PRT_ENTRY structure has a pointer to a string and 739 : : * the size of that string must be found. 740 : : */ 741 : 21 : top_object_list = package_object->package.elements; 742 : : 743 [ + + ]: 2709 : for (index = 0; index < number_of_elements; index++) { 744 : : 745 : : /* Dereference the subpackage */ 746 : : 747 : 2688 : package_element = *top_object_list; 748 : : 749 : : /* We must have a valid Package object */ 750 : : 751 [ + - ]: 2688 : if (!package_element || 752 [ + - ]: 2688 : (package_element->common.type != ACPI_TYPE_PACKAGE)) { 753 : : return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 754 : : } 755 : : 756 : : /* 757 : : * The sub_object_list will now point to an array of the 758 : : * four IRQ elements: Address, Pin, Source and source_index 759 : : */ 760 : 2688 : sub_object_list = package_element->package.elements; 761 : : 762 : : /* Scan the irq_table_elements for the Source Name String */ 763 : : 764 : 2688 : name_found = FALSE; 765 : : 766 : 2688 : for (table_index = 0; 767 [ + - ]: 10752 : table_index < package_element->package.count 768 [ + + ]: 18816 : && !name_found; table_index++) { 769 [ + - ]: 8064 : if (*sub_object_list && /* Null object allowed */ 770 : : ((ACPI_TYPE_STRING == 771 [ + - ]: 8064 : (*sub_object_list)->common.type) || 772 : : ((ACPI_TYPE_LOCAL_REFERENCE == 773 [ + + ]: 8064 : (*sub_object_list)->common.type) && 774 : : ((*sub_object_list)->reference.class == 775 : : ACPI_REFCLASS_NAME)))) { 776 : : name_found = TRUE; 777 : : } else { 778 : : /* Look at the next element */ 779 : : 780 : 5376 : sub_object_list++; 781 : : } 782 : : } 783 : : 784 : 2688 : temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4); 785 : : 786 : : /* Was a String type found? */ 787 : : 788 [ + - ]: 2688 : if (name_found) { 789 [ - + ]: 2688 : if ((*sub_object_list)->common.type == ACPI_TYPE_STRING) { 790 : : /* 791 : : * The length String.Length field does not include the 792 : : * terminating NULL, add 1 793 : : */ 794 : 0 : temp_size_needed += ((acpi_size) 795 : 0 : (*sub_object_list)->string. 796 : : length + 1); 797 : : } else { 798 : 2688 : temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node); 799 : : } 800 : : } else { 801 : : /* 802 : : * If no name was found, then this is a NULL, which is 803 : : * translated as a u32 zero. 804 : : */ 805 : 0 : temp_size_needed += sizeof(u32); 806 : : } 807 : : 808 : : /* Round up the size since each element must be aligned */ 809 : : 810 : 2688 : temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed); 811 : : 812 : : /* Point to the next union acpi_operand_object */ 813 : : 814 : 2688 : top_object_list++; 815 : : } 816 : : 817 : : /* 818 : : * Add an extra element to the end of the list, essentially a 819 : : * NULL terminator 820 : : */ 821 : 21 : *buffer_size_needed = 822 : 21 : temp_size_needed + sizeof(struct acpi_pci_routing_table); 823 : 21 : return_ACPI_STATUS(AE_OK); 824 : : }