root/drivers/acpi/acpica/rscalc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_rs_struct_option_length
  3. acpi_rs_stream_option_length
  4. acpi_rs_get_aml_length
  5. acpi_rs_get_list_length
  6. acpi_rs_get_pci_routing_table_length

   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 static u8 acpi_rs_count_set_bits(u16 bit_field)
  39 {
  40         u8 bits_set;
  41 
  42         ACPI_FUNCTION_ENTRY();
  43 
  44         for (bits_set = 0; bit_field; bits_set++) {
  45 
  46                 /* Zero the least significant bit that is set */
  47 
  48                 bit_field &= (u16) (bit_field - 1);
  49         }
  50 
  51         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 acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
  70 {
  71         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         if (resource_source->string_ptr) {
  79                 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 acpi_rs_stream_option_length(u32 resource_length,
 103                              u32 minimum_aml_resource_length)
 104 {
 105         u32 string_length = 0;
 106 
 107         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         if (resource_length > minimum_aml_resource_length) {
 123 
 124                 /* Compute the length of the optional string */
 125 
 126                 string_length =
 127                     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         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 acpi_rs_get_aml_length(struct acpi_resource *resource,
 155                        acpi_size resource_list_size, acpi_size *size_needed)
 156 {
 157         acpi_size aml_size_needed = 0;
 158         struct acpi_resource *resource_end;
 159         acpi_rs_length total_size;
 160 
 161         ACPI_FUNCTION_TRACE(rs_get_aml_length);
 162 
 163         /* Traverse entire list of internal resource descriptors */
 164 
 165         resource_end =
 166             ACPI_ADD_PTR(struct acpi_resource, resource, resource_list_size);
 167         while (resource < resource_end) {
 168 
 169                 /* Validate the descriptor type */
 170 
 171                 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                 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                 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                 switch (resource->type) {
 190                 case ACPI_RESOURCE_TYPE_IRQ:
 191 
 192                         /* Length can be 3 or 2 */
 193 
 194                         if (resource->data.irq.descriptor_length == 2) {
 195                                 total_size--;
 196                         }
 197                         break;
 198 
 199                 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 200 
 201                         /* Length can be 1 or 0 */
 202 
 203                         if (resource->data.irq.descriptor_length == 0) {
 204                                 total_size--;
 205                         }
 206                         break;
 207 
 208                 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                         if (resource->data.vendor.byte_length > 7) {
 216 
 217                                 /* Base size of a Large resource descriptor */
 218 
 219                                 total_size =
 220                                     sizeof(struct aml_resource_large_header);
 221                         }
 222 
 223                         /* Add the size of the vendor-specific data */
 224 
 225                         total_size = (acpi_rs_length)
 226                             (total_size + resource->data.vendor.byte_length);
 227                         break;
 228 
 229                 case ACPI_RESOURCE_TYPE_END_TAG:
 230                         /*
 231                          * End Tag:
 232                          * We are done -- return the accumulated total size.
 233                          */
 234                         *size_needed = aml_size_needed + total_size;
 235 
 236                         /* Normal exit */
 237 
 238                         return_ACPI_STATUS(AE_OK);
 239 
 240                 case ACPI_RESOURCE_TYPE_ADDRESS16:
 241                         /*
 242                          * 16-Bit Address Resource:
 243                          * Add the size of the optional resource_source info
 244                          */
 245                         total_size = (acpi_rs_length)(total_size +
 246                                                       acpi_rs_struct_option_length
 247                                                       (&resource->data.
 248                                                        address16.
 249                                                        resource_source));
 250                         break;
 251 
 252                 case ACPI_RESOURCE_TYPE_ADDRESS32:
 253                         /*
 254                          * 32-Bit Address Resource:
 255                          * Add the size of the optional resource_source info
 256                          */
 257                         total_size = (acpi_rs_length)(total_size +
 258                                                       acpi_rs_struct_option_length
 259                                                       (&resource->data.
 260                                                        address32.
 261                                                        resource_source));
 262                         break;
 263 
 264                 case ACPI_RESOURCE_TYPE_ADDRESS64:
 265                         /*
 266                          * 64-Bit Address Resource:
 267                          * Add the size of the optional resource_source info
 268                          */
 269                         total_size = (acpi_rs_length)(total_size +
 270                                                       acpi_rs_struct_option_length
 271                                                       (&resource->data.
 272                                                        address64.
 273                                                        resource_source));
 274                         break;
 275 
 276                 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                         total_size = (acpi_rs_length)(total_size +
 283                                                       ((resource->data.
 284                                                         extended_irq.
 285                                                         interrupt_count -
 286                                                         1) * 4) +
 287                                                       /* Add the size of the optional resource_source info */
 288                                                       acpi_rs_struct_option_length
 289                                                       (&resource->data.
 290                                                        extended_irq.
 291                                                        resource_source));
 292                         break;
 293 
 294                 case ACPI_RESOURCE_TYPE_GPIO:
 295 
 296                         total_size = (acpi_rs_length)(total_size +
 297                                                       (resource->data.gpio.
 298                                                        pin_table_length * 2) +
 299                                                       resource->data.gpio.
 300                                                       resource_source.
 301                                                       string_length +
 302                                                       resource->data.gpio.
 303                                                       vendor_length);
 304 
 305                         break;
 306 
 307                 case ACPI_RESOURCE_TYPE_PIN_FUNCTION:
 308 
 309                         total_size = (acpi_rs_length)(total_size +
 310                                                       (resource->data.
 311                                                        pin_function.
 312                                                        pin_table_length * 2) +
 313                                                       resource->data.
 314                                                       pin_function.
 315                                                       resource_source.
 316                                                       string_length +
 317                                                       resource->data.
 318                                                       pin_function.
 319                                                       vendor_length);
 320 
 321                         break;
 322 
 323                 case ACPI_RESOURCE_TYPE_SERIAL_BUS:
 324 
 325                         total_size =
 326                             acpi_gbl_aml_resource_serial_bus_sizes[resource->
 327                                                                    data.
 328                                                                    common_serial_bus.
 329                                                                    type];
 330 
 331                         total_size = (acpi_rs_length)(total_size +
 332                                                       resource->data.
 333                                                       i2c_serial_bus.
 334                                                       resource_source.
 335                                                       string_length +
 336                                                       resource->data.
 337                                                       i2c_serial_bus.
 338                                                       vendor_length);
 339 
 340                         break;
 341 
 342                 case ACPI_RESOURCE_TYPE_PIN_CONFIG:
 343 
 344                         total_size = (acpi_rs_length)(total_size +
 345                                                       (resource->data.
 346                                                        pin_config.
 347                                                        pin_table_length * 2) +
 348                                                       resource->data.pin_config.
 349                                                       resource_source.
 350                                                       string_length +
 351                                                       resource->data.pin_config.
 352                                                       vendor_length);
 353 
 354                         break;
 355 
 356                 case ACPI_RESOURCE_TYPE_PIN_GROUP:
 357 
 358                         total_size = (acpi_rs_length)(total_size +
 359                                                       (resource->data.pin_group.
 360                                                        pin_table_length * 2) +
 361                                                       resource->data.pin_group.
 362                                                       resource_label.
 363                                                       string_length +
 364                                                       resource->data.pin_group.
 365                                                       vendor_length);
 366 
 367                         break;
 368 
 369                 case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION:
 370 
 371                         total_size = (acpi_rs_length)(total_size +
 372                                                       resource->data.
 373                                                       pin_group_function.
 374                                                       resource_source.
 375                                                       string_length +
 376                                                       resource->data.
 377                                                       pin_group_function.
 378                                                       resource_source_label.
 379                                                       string_length +
 380                                                       resource->data.
 381                                                       pin_group_function.
 382                                                       vendor_length);
 383 
 384                         break;
 385 
 386                 case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG:
 387 
 388                         total_size = (acpi_rs_length)(total_size +
 389                                                       resource->data.
 390                                                       pin_group_config.
 391                                                       resource_source.
 392                                                       string_length +
 393                                                       resource->data.
 394                                                       pin_group_config.
 395                                                       resource_source_label.
 396                                                       string_length +
 397                                                       resource->data.
 398                                                       pin_group_config.
 399                                                       vendor_length);
 400 
 401                         break;
 402 
 403                 default:
 404 
 405                         break;
 406                 }
 407 
 408                 /* Update the total */
 409 
 410                 aml_size_needed += total_size;
 411 
 412                 /* Point to the next object */
 413 
 414                 resource =
 415                     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 acpi_rs_get_list_length(u8 *aml_buffer,
 442                         u32 aml_buffer_length, acpi_size *size_needed)
 443 {
 444         acpi_status status;
 445         u8 *end_aml;
 446         u8 *buffer;
 447         u32 buffer_size;
 448         u16 temp16;
 449         u16 resource_length;
 450         u32 extra_struct_bytes;
 451         u8 resource_index;
 452         u8 minimum_aml_resource_length;
 453         union aml_resource *aml_resource;
 454 
 455         ACPI_FUNCTION_TRACE(rs_get_list_length);
 456 
 457         *size_needed = ACPI_RS_SIZE_MIN;        /* Minimum size is one end_tag */
 458         end_aml = aml_buffer + aml_buffer_length;
 459 
 460         /* Walk the list of AML resource descriptors */
 461 
 462         while (aml_buffer < end_aml) {
 463 
 464                 /* Validate the Resource Type and Resource Length */
 465 
 466                 status =
 467                     acpi_ut_validate_resource(NULL, aml_buffer,
 468                                               &resource_index);
 469                 if (ACPI_FAILURE(status)) {
 470                         /*
 471                          * Exit on failure. Cannot continue because the descriptor length
 472                          * may be bogus also.
 473                          */
 474                         return_ACPI_STATUS(status);
 475                 }
 476 
 477                 aml_resource = (void *)aml_buffer;
 478 
 479                 /* Get the resource length and base (minimum) AML size */
 480 
 481                 resource_length = acpi_ut_get_resource_length(aml_buffer);
 482                 minimum_aml_resource_length =
 483                     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                 extra_struct_bytes = 0;
 490                 buffer =
 491                     aml_buffer + acpi_ut_get_resource_header_length(aml_buffer);
 492 
 493                 switch (acpi_ut_get_resource_type(aml_buffer)) {
 494                 case ACPI_RESOURCE_NAME_IRQ:
 495                         /*
 496                          * IRQ Resource:
 497                          * Get the number of bits set in the 16-bit IRQ mask
 498                          */
 499                         ACPI_MOVE_16_TO_16(&temp16, buffer);
 500                         extra_struct_bytes = acpi_rs_count_set_bits(temp16);
 501                         break;
 502 
 503                 case ACPI_RESOURCE_NAME_DMA:
 504                         /*
 505                          * DMA Resource:
 506                          * Get the number of bits set in the 8-bit DMA mask
 507                          */
 508                         extra_struct_bytes = acpi_rs_count_set_bits(*buffer);
 509                         break;
 510 
 511                 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                         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                         if (extra_struct_bytes) {
 525                                 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                 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                         extra_struct_bytes =
 543                             acpi_rs_stream_option_length(resource_length,
 544                                                          minimum_aml_resource_length);
 545                         break;
 546 
 547                 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                         extra_struct_bytes = (buffer[1] - 1) * sizeof(u32);
 555 
 556                         /* Add the size of the optional resource_source */
 557 
 558                         extra_struct_bytes +=
 559                             acpi_rs_stream_option_length(resource_length -
 560                                                          extra_struct_bytes,
 561                                                          minimum_aml_resource_length);
 562                         break;
 563 
 564                 case ACPI_RESOURCE_NAME_GPIO:
 565 
 566                         /* Vendor data is optional */
 567 
 568                         if (aml_resource->gpio.vendor_length) {
 569                                 extra_struct_bytes +=
 570                                     aml_resource->gpio.vendor_offset -
 571                                     aml_resource->gpio.pin_table_offset +
 572                                     aml_resource->gpio.vendor_length;
 573                         } else {
 574                                 extra_struct_bytes +=
 575                                     aml_resource->large_header.resource_length +
 576                                     sizeof(struct aml_resource_large_header) -
 577                                     aml_resource->gpio.pin_table_offset;
 578                         }
 579                         break;
 580 
 581                 case ACPI_RESOURCE_NAME_PIN_FUNCTION:
 582 
 583                         /* Vendor data is optional */
 584 
 585                         if (aml_resource->pin_function.vendor_length) {
 586                                 extra_struct_bytes +=
 587                                     aml_resource->pin_function.vendor_offset -
 588                                     aml_resource->pin_function.
 589                                     pin_table_offset +
 590                                     aml_resource->pin_function.vendor_length;
 591                         } else {
 592                                 extra_struct_bytes +=
 593                                     aml_resource->large_header.resource_length +
 594                                     sizeof(struct aml_resource_large_header) -
 595                                     aml_resource->pin_function.pin_table_offset;
 596                         }
 597                         break;
 598 
 599                 case ACPI_RESOURCE_NAME_SERIAL_BUS:
 600 
 601                         minimum_aml_resource_length =
 602                             acpi_gbl_resource_aml_serial_bus_sizes
 603                             [aml_resource->common_serial_bus.type];
 604                         extra_struct_bytes +=
 605                             aml_resource->common_serial_bus.resource_length -
 606                             minimum_aml_resource_length;
 607                         break;
 608 
 609                 case ACPI_RESOURCE_NAME_PIN_CONFIG:
 610 
 611                         /* Vendor data is optional */
 612 
 613                         if (aml_resource->pin_config.vendor_length) {
 614                                 extra_struct_bytes +=
 615                                     aml_resource->pin_config.vendor_offset -
 616                                     aml_resource->pin_config.pin_table_offset +
 617                                     aml_resource->pin_config.vendor_length;
 618                         } else {
 619                                 extra_struct_bytes +=
 620                                     aml_resource->large_header.resource_length +
 621                                     sizeof(struct aml_resource_large_header) -
 622                                     aml_resource->pin_config.pin_table_offset;
 623                         }
 624                         break;
 625 
 626                 case ACPI_RESOURCE_NAME_PIN_GROUP:
 627 
 628                         extra_struct_bytes +=
 629                             aml_resource->pin_group.vendor_offset -
 630                             aml_resource->pin_group.pin_table_offset +
 631                             aml_resource->pin_group.vendor_length;
 632 
 633                         break;
 634 
 635                 case ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION:
 636 
 637                         extra_struct_bytes +=
 638                             aml_resource->pin_group_function.vendor_offset -
 639                             aml_resource->pin_group_function.res_source_offset +
 640                             aml_resource->pin_group_function.vendor_length;
 641 
 642                         break;
 643 
 644                 case ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG:
 645 
 646                         extra_struct_bytes +=
 647                             aml_resource->pin_group_config.vendor_offset -
 648                             aml_resource->pin_group_config.res_source_offset +
 649                             aml_resource->pin_group_config.vendor_length;
 650 
 651                         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                 if (acpi_ut_get_resource_type(aml_buffer) ==
 665                     ACPI_RESOURCE_NAME_SERIAL_BUS) {
 666                         buffer_size =
 667                             acpi_gbl_resource_struct_serial_bus_sizes
 668                             [aml_resource->common_serial_bus.type] +
 669                             extra_struct_bytes;
 670                 } else {
 671                         buffer_size =
 672                             acpi_gbl_resource_struct_sizes[resource_index] +
 673                             extra_struct_bytes;
 674                 }
 675 
 676                 buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
 677                 *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                                   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                 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 acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
 716                                      acpi_size *buffer_size_needed)
 717 {
 718         u32 number_of_elements;
 719         acpi_size temp_size_needed = 0;
 720         union acpi_operand_object **top_object_list;
 721         u32 index;
 722         union acpi_operand_object *package_element;
 723         union acpi_operand_object **sub_object_list;
 724         u8 name_found;
 725         u32 table_index;
 726 
 727         ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length);
 728 
 729         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         top_object_list = package_object->package.elements;
 742 
 743         for (index = 0; index < number_of_elements; index++) {
 744 
 745                 /* Dereference the subpackage */
 746 
 747                 package_element = *top_object_list;
 748 
 749                 /* We must have a valid Package object */
 750 
 751                 if (!package_element ||
 752                     (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                 sub_object_list = package_element->package.elements;
 761 
 762                 /* Scan the irq_table_elements for the Source Name String */
 763 
 764                 name_found = FALSE;
 765 
 766                 for (table_index = 0;
 767                      table_index < package_element->package.count
 768                      && !name_found; table_index++) {
 769                         if (*sub_object_list && /* Null object allowed */
 770                             ((ACPI_TYPE_STRING ==
 771                               (*sub_object_list)->common.type) ||
 772                              ((ACPI_TYPE_LOCAL_REFERENCE ==
 773                                (*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                                 sub_object_list++;
 781                         }
 782                 }
 783 
 784                 temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);
 785 
 786                 /* Was a String type found? */
 787 
 788                 if (name_found) {
 789                         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                                 temp_size_needed += ((acpi_size)
 795                                                      (*sub_object_list)->string.
 796                                                      length + 1);
 797                         } else {
 798                                 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                         temp_size_needed += sizeof(u32);
 806                 }
 807 
 808                 /* Round up the size since each element must be aligned */
 809 
 810                 temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed);
 811 
 812                 /* Point to the next union acpi_operand_object */
 813 
 814                 top_object_list++;
 815         }
 816 
 817         /*
 818          * Add an extra element to the end of the list, essentially a
 819          * NULL terminator
 820          */
 821         *buffer_size_needed =
 822             temp_size_needed + sizeof(struct acpi_pci_routing_table);
 823         return_ACPI_STATUS(AE_OK);
 824 }

/* [<][>][^][v][top][bottom][index][help] */