linux/drivers/acpi/acpica/utresrc.c
<<
>>
Prefs
   1/*******************************************************************************
   2 *
   3 * Module Name: utresrc - Resource management utilities
   4 *
   5 ******************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2013, Intel Corp.
   9 * All rights reserved.
  10 *
  11 * Redistribution and use in source and binary forms, with or without
  12 * modification, are permitted provided that the following conditions
  13 * are met:
  14 * 1. Redistributions of source code must retain the above copyright
  15 *    notice, this list of conditions, and the following disclaimer,
  16 *    without modification.
  17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18 *    substantially similar to the "NO WARRANTY" disclaimer below
  19 *    ("Disclaimer") and any redistribution must be conditioned upon
  20 *    including a substantially similar Disclaimer requirement for further
  21 *    binary redistribution.
  22 * 3. Neither the names of the above-listed copyright holders nor the names
  23 *    of any contributors may be used to endorse or promote products derived
  24 *    from this software without specific prior written permission.
  25 *
  26 * Alternatively, this software may be distributed under the terms of the
  27 * GNU General Public License ("GPL") version 2 as published by the Free
  28 * Software Foundation.
  29 *
  30 * NO WARRANTY
  31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41 * POSSIBILITY OF SUCH DAMAGES.
  42 */
  43
  44#include <acpi/acpi.h>
  45#include "accommon.h"
  46#include "acresrc.h"
  47
  48#define _COMPONENT          ACPI_UTILITIES
  49ACPI_MODULE_NAME("utresrc")
  50#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
  51/*
  52 * Strings used to decode resource descriptors.
  53 * Used by both the disassembler and the debugger resource dump routines
  54 */
  55const char *acpi_gbl_bm_decode[] = {
  56        "NotBusMaster",
  57        "BusMaster"
  58};
  59
  60const char *acpi_gbl_config_decode[] = {
  61        "0 - Good Configuration",
  62        "1 - Acceptable Configuration",
  63        "2 - Suboptimal Configuration",
  64        "3 - ***Invalid Configuration***",
  65};
  66
  67const char *acpi_gbl_consume_decode[] = {
  68        "ResourceProducer",
  69        "ResourceConsumer"
  70};
  71
  72const char *acpi_gbl_dec_decode[] = {
  73        "PosDecode",
  74        "SubDecode"
  75};
  76
  77const char *acpi_gbl_he_decode[] = {
  78        "Level",
  79        "Edge"
  80};
  81
  82const char *acpi_gbl_io_decode[] = {
  83        "Decode10",
  84        "Decode16"
  85};
  86
  87const char *acpi_gbl_ll_decode[] = {
  88        "ActiveHigh",
  89        "ActiveLow"
  90};
  91
  92const char *acpi_gbl_max_decode[] = {
  93        "MaxNotFixed",
  94        "MaxFixed"
  95};
  96
  97const char *acpi_gbl_mem_decode[] = {
  98        "NonCacheable",
  99        "Cacheable",
 100        "WriteCombining",
 101        "Prefetchable"
 102};
 103
 104const char *acpi_gbl_min_decode[] = {
 105        "MinNotFixed",
 106        "MinFixed"
 107};
 108
 109const char *acpi_gbl_mtp_decode[] = {
 110        "AddressRangeMemory",
 111        "AddressRangeReserved",
 112        "AddressRangeACPI",
 113        "AddressRangeNVS"
 114};
 115
 116const char *acpi_gbl_rng_decode[] = {
 117        "InvalidRanges",
 118        "NonISAOnlyRanges",
 119        "ISAOnlyRanges",
 120        "EntireRange"
 121};
 122
 123const char *acpi_gbl_rw_decode[] = {
 124        "ReadOnly",
 125        "ReadWrite"
 126};
 127
 128const char *acpi_gbl_shr_decode[] = {
 129        "Exclusive",
 130        "Shared",
 131        "ExclusiveAndWake",     /* ACPI 5.0 */
 132        "SharedAndWake"         /* ACPI 5.0 */
 133};
 134
 135const char *acpi_gbl_siz_decode[] = {
 136        "Transfer8",
 137        "Transfer8_16",
 138        "Transfer16",
 139        "InvalidSize"
 140};
 141
 142const char *acpi_gbl_trs_decode[] = {
 143        "DenseTranslation",
 144        "SparseTranslation"
 145};
 146
 147const char *acpi_gbl_ttp_decode[] = {
 148        "TypeStatic",
 149        "TypeTranslation"
 150};
 151
 152const char *acpi_gbl_typ_decode[] = {
 153        "Compatibility",
 154        "TypeA",
 155        "TypeB",
 156        "TypeF"
 157};
 158
 159const char *acpi_gbl_ppc_decode[] = {
 160        "PullDefault",
 161        "PullUp",
 162        "PullDown",
 163        "PullNone"
 164};
 165
 166const char *acpi_gbl_ior_decode[] = {
 167        "IoRestrictionNone",
 168        "IoRestrictionInputOnly",
 169        "IoRestrictionOutputOnly",
 170        "IoRestrictionNoneAndPreserve"
 171};
 172
 173const char *acpi_gbl_dts_decode[] = {
 174        "Width8bit",
 175        "Width16bit",
 176        "Width32bit",
 177        "Width64bit",
 178        "Width128bit",
 179        "Width256bit",
 180};
 181
 182/* GPIO connection type */
 183
 184const char *acpi_gbl_ct_decode[] = {
 185        "Interrupt",
 186        "I/O"
 187};
 188
 189/* Serial bus type */
 190
 191const char *acpi_gbl_sbt_decode[] = {
 192        "/* UNKNOWN serial bus type */",
 193        "I2C",
 194        "SPI",
 195        "UART"
 196};
 197
 198/* I2C serial bus access mode */
 199
 200const char *acpi_gbl_am_decode[] = {
 201        "AddressingMode7Bit",
 202        "AddressingMode10Bit"
 203};
 204
 205/* I2C serial bus slave mode */
 206
 207const char *acpi_gbl_sm_decode[] = {
 208        "ControllerInitiated",
 209        "DeviceInitiated"
 210};
 211
 212/* SPI serial bus wire mode */
 213
 214const char *acpi_gbl_wm_decode[] = {
 215        "FourWireMode",
 216        "ThreeWireMode"
 217};
 218
 219/* SPI serial clock phase */
 220
 221const char *acpi_gbl_cph_decode[] = {
 222        "ClockPhaseFirst",
 223        "ClockPhaseSecond"
 224};
 225
 226/* SPI serial bus clock polarity */
 227
 228const char *acpi_gbl_cpo_decode[] = {
 229        "ClockPolarityLow",
 230        "ClockPolarityHigh"
 231};
 232
 233/* SPI serial bus device polarity */
 234
 235const char *acpi_gbl_dp_decode[] = {
 236        "PolarityLow",
 237        "PolarityHigh"
 238};
 239
 240/* UART serial bus endian */
 241
 242const char *acpi_gbl_ed_decode[] = {
 243        "LittleEndian",
 244        "BigEndian"
 245};
 246
 247/* UART serial bus bits per byte */
 248
 249const char *acpi_gbl_bpb_decode[] = {
 250        "DataBitsFive",
 251        "DataBitsSix",
 252        "DataBitsSeven",
 253        "DataBitsEight",
 254        "DataBitsNine",
 255        "/* UNKNOWN Bits per byte */",
 256        "/* UNKNOWN Bits per byte */",
 257        "/* UNKNOWN Bits per byte */"
 258};
 259
 260/* UART serial bus stop bits */
 261
 262const char *acpi_gbl_sb_decode[] = {
 263        "StopBitsNone",
 264        "StopBitsOne",
 265        "StopBitsOnePlusHalf",
 266        "StopBitsTwo"
 267};
 268
 269/* UART serial bus flow control */
 270
 271const char *acpi_gbl_fc_decode[] = {
 272        "FlowControlNone",
 273        "FlowControlHardware",
 274        "FlowControlXON",
 275        "/* UNKNOWN flow control keyword */"
 276};
 277
 278/* UART serial bus parity type */
 279
 280const char *acpi_gbl_pt_decode[] = {
 281        "ParityTypeNone",
 282        "ParityTypeEven",
 283        "ParityTypeOdd",
 284        "ParityTypeMark",
 285        "ParityTypeSpace",
 286        "/* UNKNOWN parity keyword */",
 287        "/* UNKNOWN parity keyword */",
 288        "/* UNKNOWN parity keyword */"
 289};
 290
 291#endif
 292
 293/*
 294 * Base sizes of the raw AML resource descriptors, indexed by resource type.
 295 * Zero indicates a reserved (and therefore invalid) resource type.
 296 */
 297const u8 acpi_gbl_resource_aml_sizes[] = {
 298        /* Small descriptors */
 299
 300        0,
 301        0,
 302        0,
 303        0,
 304        ACPI_AML_SIZE_SMALL(struct aml_resource_irq),
 305        ACPI_AML_SIZE_SMALL(struct aml_resource_dma),
 306        ACPI_AML_SIZE_SMALL(struct aml_resource_start_dependent),
 307        ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent),
 308        ACPI_AML_SIZE_SMALL(struct aml_resource_io),
 309        ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io),
 310        ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_dma),
 311        0,
 312        0,
 313        0,
 314        ACPI_AML_SIZE_SMALL(struct aml_resource_vendor_small),
 315        ACPI_AML_SIZE_SMALL(struct aml_resource_end_tag),
 316
 317        /* Large descriptors */
 318
 319        0,
 320        ACPI_AML_SIZE_LARGE(struct aml_resource_memory24),
 321        ACPI_AML_SIZE_LARGE(struct aml_resource_generic_register),
 322        0,
 323        ACPI_AML_SIZE_LARGE(struct aml_resource_vendor_large),
 324        ACPI_AML_SIZE_LARGE(struct aml_resource_memory32),
 325        ACPI_AML_SIZE_LARGE(struct aml_resource_fixed_memory32),
 326        ACPI_AML_SIZE_LARGE(struct aml_resource_address32),
 327        ACPI_AML_SIZE_LARGE(struct aml_resource_address16),
 328        ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq),
 329        ACPI_AML_SIZE_LARGE(struct aml_resource_address64),
 330        ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64),
 331        ACPI_AML_SIZE_LARGE(struct aml_resource_gpio),
 332        0,
 333        ACPI_AML_SIZE_LARGE(struct aml_resource_common_serialbus),
 334};
 335
 336const u8 acpi_gbl_resource_aml_serial_bus_sizes[] = {
 337        0,
 338        ACPI_AML_SIZE_LARGE(struct aml_resource_i2c_serialbus),
 339        ACPI_AML_SIZE_LARGE(struct aml_resource_spi_serialbus),
 340        ACPI_AML_SIZE_LARGE(struct aml_resource_uart_serialbus),
 341};
 342
 343/*
 344 * Resource types, used to validate the resource length field.
 345 * The length of fixed-length types must match exactly, variable
 346 * lengths must meet the minimum required length, etc.
 347 * Zero indicates a reserved (and therefore invalid) resource type.
 348 */
 349static const u8 acpi_gbl_resource_types[] = {
 350        /* Small descriptors */
 351
 352        0,
 353        0,
 354        0,
 355        0,
 356        ACPI_SMALL_VARIABLE_LENGTH,     /* 04 IRQ */
 357        ACPI_FIXED_LENGTH,      /* 05 DMA */
 358        ACPI_SMALL_VARIABLE_LENGTH,     /* 06 start_dependent_functions */
 359        ACPI_FIXED_LENGTH,      /* 07 end_dependent_functions */
 360        ACPI_FIXED_LENGTH,      /* 08 IO */
 361        ACPI_FIXED_LENGTH,      /* 09 fixed_IO */
 362        ACPI_FIXED_LENGTH,      /* 0A fixed_DMA */
 363        0,
 364        0,
 365        0,
 366        ACPI_VARIABLE_LENGTH,   /* 0E vendor_short */
 367        ACPI_FIXED_LENGTH,      /* 0F end_tag */
 368
 369        /* Large descriptors */
 370
 371        0,
 372        ACPI_FIXED_LENGTH,      /* 01 Memory24 */
 373        ACPI_FIXED_LENGTH,      /* 02 generic_register */
 374        0,
 375        ACPI_VARIABLE_LENGTH,   /* 04 vendor_long */
 376        ACPI_FIXED_LENGTH,      /* 05 Memory32 */
 377        ACPI_FIXED_LENGTH,      /* 06 memory32_fixed */
 378        ACPI_VARIABLE_LENGTH,   /* 07 Dword* address */
 379        ACPI_VARIABLE_LENGTH,   /* 08 Word* address */
 380        ACPI_VARIABLE_LENGTH,   /* 09 extended_IRQ */
 381        ACPI_VARIABLE_LENGTH,   /* 0A Qword* address */
 382        ACPI_FIXED_LENGTH,      /* 0B Extended* address */
 383        ACPI_VARIABLE_LENGTH,   /* 0C Gpio* */
 384        0,
 385        ACPI_VARIABLE_LENGTH    /* 0E *serial_bus */
 386};
 387
 388/*******************************************************************************
 389 *
 390 * FUNCTION:    acpi_ut_walk_aml_resources
 391 *
 392 * PARAMETERS:  walk_state          - Current walk info
 393 * PARAMETERS:  aml                 - Pointer to the raw AML resource template
 394 *              aml_length          - Length of the entire template
 395 *              user_function       - Called once for each descriptor found. If
 396 *                                    NULL, a pointer to the end_tag is returned
 397 *              context             - Passed to user_function
 398 *
 399 * RETURN:      Status
 400 *
 401 * DESCRIPTION: Walk a raw AML resource list(buffer). User function called
 402 *              once for each resource found.
 403 *
 404 ******************************************************************************/
 405
 406acpi_status
 407acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
 408                           u8 *aml,
 409                           acpi_size aml_length,
 410                           acpi_walk_aml_callback user_function, void **context)
 411{
 412        acpi_status status;
 413        u8 *end_aml;
 414        u8 resource_index;
 415        u32 length;
 416        u32 offset = 0;
 417        u8 end_tag[2] = { 0x79, 0x00 };
 418
 419        ACPI_FUNCTION_TRACE(ut_walk_aml_resources);
 420
 421        /* The absolute minimum resource template is one end_tag descriptor */
 422
 423        if (aml_length < sizeof(struct aml_resource_end_tag)) {
 424                return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
 425        }
 426
 427        /* Point to the end of the resource template buffer */
 428
 429        end_aml = aml + aml_length;
 430
 431        /* Walk the byte list, abort on any invalid descriptor type or length */
 432
 433        while (aml < end_aml) {
 434
 435                /* Validate the Resource Type and Resource Length */
 436
 437                status =
 438                    acpi_ut_validate_resource(walk_state, aml, &resource_index);
 439                if (ACPI_FAILURE(status)) {
 440                        /*
 441                         * Exit on failure. Cannot continue because the descriptor length
 442                         * may be bogus also.
 443                         */
 444                        return_ACPI_STATUS(status);
 445                }
 446
 447                /* Get the length of this descriptor */
 448
 449                length = acpi_ut_get_descriptor_length(aml);
 450
 451                /* Invoke the user function */
 452
 453                if (user_function) {
 454                        status =
 455                            user_function(aml, length, offset, resource_index,
 456                                          context);
 457                        if (ACPI_FAILURE(status)) {
 458                                return_ACPI_STATUS(status);
 459                        }
 460                }
 461
 462                /* An end_tag descriptor terminates this resource template */
 463
 464                if (acpi_ut_get_resource_type(aml) ==
 465                    ACPI_RESOURCE_NAME_END_TAG) {
 466                        /*
 467                         * There must be at least one more byte in the buffer for
 468                         * the 2nd byte of the end_tag
 469                         */
 470                        if ((aml + 1) >= end_aml) {
 471                                return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
 472                        }
 473
 474                        /* Return the pointer to the end_tag if requested */
 475
 476                        if (!user_function) {
 477                                *context = aml;
 478                        }
 479
 480                        /* Normal exit */
 481
 482                        return_ACPI_STATUS(AE_OK);
 483                }
 484
 485                aml += length;
 486                offset += length;
 487        }
 488
 489        /* Did not find an end_tag descriptor */
 490
 491        if (user_function) {
 492
 493                /* Insert an end_tag anyway. acpi_rs_get_list_length always leaves room */
 494
 495                (void)acpi_ut_validate_resource(walk_state, end_tag,
 496                                                &resource_index);
 497                status =
 498                    user_function(end_tag, 2, offset, resource_index, context);
 499                if (ACPI_FAILURE(status)) {
 500                        return_ACPI_STATUS(status);
 501                }
 502        }
 503
 504        return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
 505}
 506
 507/*******************************************************************************
 508 *
 509 * FUNCTION:    acpi_ut_validate_resource
 510 *
 511 * PARAMETERS:  walk_state          - Current walk info
 512 *              aml                 - Pointer to the raw AML resource descriptor
 513 *              return_index        - Where the resource index is returned. NULL
 514 *                                    if the index is not required.
 515 *
 516 * RETURN:      Status, and optionally the Index into the global resource tables
 517 *
 518 * DESCRIPTION: Validate an AML resource descriptor by checking the Resource
 519 *              Type and Resource Length. Returns an index into the global
 520 *              resource information/dispatch tables for later use.
 521 *
 522 ******************************************************************************/
 523
 524acpi_status
 525acpi_ut_validate_resource(struct acpi_walk_state *walk_state,
 526                          void *aml, u8 *return_index)
 527{
 528        union aml_resource *aml_resource;
 529        u8 resource_type;
 530        u8 resource_index;
 531        acpi_rs_length resource_length;
 532        acpi_rs_length minimum_resource_length;
 533
 534        ACPI_FUNCTION_ENTRY();
 535
 536        /*
 537         * 1) Validate the resource_type field (Byte 0)
 538         */
 539        resource_type = ACPI_GET8(aml);
 540
 541        /*
 542         * Byte 0 contains the descriptor name (Resource Type)
 543         * Examine the large/small bit in the resource header
 544         */
 545        if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
 546
 547                /* Verify the large resource type (name) against the max */
 548
 549                if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
 550                        goto invalid_resource;
 551                }
 552
 553                /*
 554                 * Large Resource Type -- bits 6:0 contain the name
 555                 * Translate range 0x80-0x8B to index range 0x10-0x1B
 556                 */
 557                resource_index = (u8) (resource_type - 0x70);
 558        } else {
 559                /*
 560                 * Small Resource Type -- bits 6:3 contain the name
 561                 * Shift range to index range 0x00-0x0F
 562                 */
 563                resource_index = (u8)
 564                    ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
 565        }
 566
 567        /*
 568         * Check validity of the resource type, via acpi_gbl_resource_types. Zero
 569         * indicates an invalid resource.
 570         */
 571        if (!acpi_gbl_resource_types[resource_index]) {
 572                goto invalid_resource;
 573        }
 574
 575        /*
 576         * Validate the resource_length field. This ensures that the length
 577         * is at least reasonable, and guarantees that it is non-zero.
 578         */
 579        resource_length = acpi_ut_get_resource_length(aml);
 580        minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index];
 581
 582        /* Validate based upon the type of resource - fixed length or variable */
 583
 584        switch (acpi_gbl_resource_types[resource_index]) {
 585        case ACPI_FIXED_LENGTH:
 586
 587                /* Fixed length resource, length must match exactly */
 588
 589                if (resource_length != minimum_resource_length) {
 590                        goto bad_resource_length;
 591                }
 592                break;
 593
 594        case ACPI_VARIABLE_LENGTH:
 595
 596                /* Variable length resource, length must be at least the minimum */
 597
 598                if (resource_length < minimum_resource_length) {
 599                        goto bad_resource_length;
 600                }
 601                break;
 602
 603        case ACPI_SMALL_VARIABLE_LENGTH:
 604
 605                /* Small variable length resource, length can be (Min) or (Min-1) */
 606
 607                if ((resource_length > minimum_resource_length) ||
 608                    (resource_length < (minimum_resource_length - 1))) {
 609                        goto bad_resource_length;
 610                }
 611                break;
 612
 613        default:
 614
 615                /* Shouldn't happen (because of validation earlier), but be sure */
 616
 617                goto invalid_resource;
 618        }
 619
 620        aml_resource = ACPI_CAST_PTR(union aml_resource, aml);
 621        if (resource_type == ACPI_RESOURCE_NAME_SERIAL_BUS) {
 622
 623                /* Validate the bus_type field */
 624
 625                if ((aml_resource->common_serial_bus.type == 0) ||
 626                    (aml_resource->common_serial_bus.type >
 627                     AML_RESOURCE_MAX_SERIALBUSTYPE)) {
 628                        if (walk_state) {
 629                                ACPI_ERROR((AE_INFO,
 630                                            "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X",
 631                                            aml_resource->common_serial_bus.
 632                                            type));
 633                        }
 634                        return (AE_AML_INVALID_RESOURCE_TYPE);
 635                }
 636        }
 637
 638        /* Optionally return the resource table index */
 639
 640        if (return_index) {
 641                *return_index = resource_index;
 642        }
 643
 644        return (AE_OK);
 645
 646      invalid_resource:
 647
 648        if (walk_state) {
 649                ACPI_ERROR((AE_INFO,
 650                            "Invalid/unsupported resource descriptor: Type 0x%2.2X",
 651                            resource_type));
 652        }
 653        return (AE_AML_INVALID_RESOURCE_TYPE);
 654
 655      bad_resource_length:
 656
 657        if (walk_state) {
 658                ACPI_ERROR((AE_INFO,
 659                            "Invalid resource descriptor length: Type "
 660                            "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X",
 661                            resource_type, resource_length,
 662                            minimum_resource_length));
 663        }
 664        return (AE_AML_BAD_RESOURCE_LENGTH);
 665}
 666
 667/*******************************************************************************
 668 *
 669 * FUNCTION:    acpi_ut_get_resource_type
 670 *
 671 * PARAMETERS:  aml             - Pointer to the raw AML resource descriptor
 672 *
 673 * RETURN:      The Resource Type with no extraneous bits (except the
 674 *              Large/Small descriptor bit -- this is left alone)
 675 *
 676 * DESCRIPTION: Extract the Resource Type/Name from the first byte of
 677 *              a resource descriptor.
 678 *
 679 ******************************************************************************/
 680
 681u8 acpi_ut_get_resource_type(void *aml)
 682{
 683        ACPI_FUNCTION_ENTRY();
 684
 685        /*
 686         * Byte 0 contains the descriptor name (Resource Type)
 687         * Examine the large/small bit in the resource header
 688         */
 689        if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
 690
 691                /* Large Resource Type -- bits 6:0 contain the name */
 692
 693                return (ACPI_GET8(aml));
 694        } else {
 695                /* Small Resource Type -- bits 6:3 contain the name */
 696
 697                return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK));
 698        }
 699}
 700
 701/*******************************************************************************
 702 *
 703 * FUNCTION:    acpi_ut_get_resource_length
 704 *
 705 * PARAMETERS:  aml             - Pointer to the raw AML resource descriptor
 706 *
 707 * RETURN:      Byte Length
 708 *
 709 * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By
 710 *              definition, this does not include the size of the descriptor
 711 *              header or the length field itself.
 712 *
 713 ******************************************************************************/
 714
 715u16 acpi_ut_get_resource_length(void *aml)
 716{
 717        acpi_rs_length resource_length;
 718
 719        ACPI_FUNCTION_ENTRY();
 720
 721        /*
 722         * Byte 0 contains the descriptor name (Resource Type)
 723         * Examine the large/small bit in the resource header
 724         */
 725        if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
 726
 727                /* Large Resource type -- bytes 1-2 contain the 16-bit length */
 728
 729                ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1));
 730
 731        } else {
 732                /* Small Resource type -- bits 2:0 of byte 0 contain the length */
 733
 734                resource_length = (u16) (ACPI_GET8(aml) &
 735                                         ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
 736        }
 737
 738        return (resource_length);
 739}
 740
 741/*******************************************************************************
 742 *
 743 * FUNCTION:    acpi_ut_get_resource_header_length
 744 *
 745 * PARAMETERS:  aml             - Pointer to the raw AML resource descriptor
 746 *
 747 * RETURN:      Length of the AML header (depends on large/small descriptor)
 748 *
 749 * DESCRIPTION: Get the length of the header for this resource.
 750 *
 751 ******************************************************************************/
 752
 753u8 acpi_ut_get_resource_header_length(void *aml)
 754{
 755        ACPI_FUNCTION_ENTRY();
 756
 757        /* Examine the large/small bit in the resource header */
 758
 759        if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
 760                return (sizeof(struct aml_resource_large_header));
 761        } else {
 762                return (sizeof(struct aml_resource_small_header));
 763        }
 764}
 765
 766/*******************************************************************************
 767 *
 768 * FUNCTION:    acpi_ut_get_descriptor_length
 769 *
 770 * PARAMETERS:  aml             - Pointer to the raw AML resource descriptor
 771 *
 772 * RETURN:      Byte length
 773 *
 774 * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the
 775 *              length of the descriptor header and the length field itself.
 776 *              Used to walk descriptor lists.
 777 *
 778 ******************************************************************************/
 779
 780u32 acpi_ut_get_descriptor_length(void *aml)
 781{
 782        ACPI_FUNCTION_ENTRY();
 783
 784        /*
 785         * Get the Resource Length (does not include header length) and add
 786         * the header length (depends on if this is a small or large resource)
 787         */
 788        return (acpi_ut_get_resource_length(aml) +
 789                acpi_ut_get_resource_header_length(aml));
 790}
 791
 792/*******************************************************************************
 793 *
 794 * FUNCTION:    acpi_ut_get_resource_end_tag
 795 *
 796 * PARAMETERS:  obj_desc        - The resource template buffer object
 797 *              end_tag         - Where the pointer to the end_tag is returned
 798 *
 799 * RETURN:      Status, pointer to the end tag
 800 *
 801 * DESCRIPTION: Find the end_tag resource descriptor in an AML resource template
 802 *              Note: allows a buffer length of zero.
 803 *
 804 ******************************************************************************/
 805
 806acpi_status
 807acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag)
 808{
 809        acpi_status status;
 810
 811        ACPI_FUNCTION_TRACE(ut_get_resource_end_tag);
 812
 813        /* Allow a buffer length of zero */
 814
 815        if (!obj_desc->buffer.length) {
 816                *end_tag = obj_desc->buffer.pointer;
 817                return_ACPI_STATUS(AE_OK);
 818        }
 819
 820        /* Validate the template and get a pointer to the end_tag */
 821
 822        status = acpi_ut_walk_aml_resources(NULL, obj_desc->buffer.pointer,
 823                                            obj_desc->buffer.length, NULL,
 824                                            (void **)end_tag);
 825
 826        return_ACPI_STATUS(status);
 827}
 828