1 /******************************************************************************* 2 * 3 * Module Name: utresrc - Resource management utilities 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2026, 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 MERCHANTABILITY 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.h" 45 #include "accommon.h" 46 #include "acresrc.h" 47 48 49 #define _COMPONENT ACPI_UTILITIES 50 ACPI_MODULE_NAME ("utresrc") 51 52 53 /* 54 * Base sizes of the raw AML resource descriptors, indexed by resource type. 55 * Zero indicates a reserved (and therefore invalid) resource type. 56 */ 57 const UINT8 AcpiGbl_ResourceAmlSizes[] = 58 { 59 /* Small descriptors */ 60 61 0, 62 0, 63 0, 64 0, 65 ACPI_AML_SIZE_SMALL (AML_RESOURCE_IRQ), 66 ACPI_AML_SIZE_SMALL (AML_RESOURCE_DMA), 67 ACPI_AML_SIZE_SMALL (AML_RESOURCE_START_DEPENDENT), 68 ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_DEPENDENT), 69 ACPI_AML_SIZE_SMALL (AML_RESOURCE_IO), 70 ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_IO), 71 ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_DMA), 72 0, 73 0, 74 0, 75 ACPI_AML_SIZE_SMALL (AML_RESOURCE_VENDOR_SMALL), 76 ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_TAG), 77 78 /* Large descriptors */ 79 80 0, 81 ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY24), 82 ACPI_AML_SIZE_LARGE (AML_RESOURCE_GENERIC_REGISTER), 83 0, 84 ACPI_AML_SIZE_LARGE (AML_RESOURCE_VENDOR_LARGE), 85 ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY32), 86 ACPI_AML_SIZE_LARGE (AML_RESOURCE_FIXED_MEMORY32), 87 ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS32), 88 ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS16), 89 ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_IRQ), 90 ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS64), 91 ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_ADDRESS64), 92 ACPI_AML_SIZE_LARGE (AML_RESOURCE_GPIO), 93 ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_FUNCTION), 94 ACPI_AML_SIZE_LARGE (AML_RESOURCE_COMMON_SERIALBUS), 95 ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_CONFIG), 96 ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_GROUP), 97 ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_GROUP_FUNCTION), 98 ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_GROUP_CONFIG), 99 ACPI_AML_SIZE_LARGE (AML_RESOURCE_CLOCK_INPUT), 100 101 }; 102 103 const UINT8 AcpiGbl_ResourceAmlSerialBusSizes[] = 104 { 105 0, 106 ACPI_AML_SIZE_LARGE (AML_RESOURCE_I2C_SERIALBUS), 107 ACPI_AML_SIZE_LARGE (AML_RESOURCE_SPI_SERIALBUS), 108 ACPI_AML_SIZE_LARGE (AML_RESOURCE_UART_SERIALBUS), 109 ACPI_AML_SIZE_LARGE (AML_RESOURCE_CSI2_SERIALBUS), 110 }; 111 112 113 /* 114 * Resource types, used to validate the resource length field. 115 * The length of fixed-length types must match exactly, variable 116 * lengths must meet the minimum required length, etc. 117 * Zero indicates a reserved (and therefore invalid) resource type. 118 */ 119 static const UINT8 AcpiGbl_ResourceTypes[] = 120 { 121 /* Small descriptors */ 122 123 0, 124 0, 125 0, 126 0, 127 ACPI_SMALL_VARIABLE_LENGTH, /* 04 IRQ */ 128 ACPI_FIXED_LENGTH, /* 05 DMA */ 129 ACPI_SMALL_VARIABLE_LENGTH, /* 06 StartDependentFunctions */ 130 ACPI_FIXED_LENGTH, /* 07 EndDependentFunctions */ 131 ACPI_FIXED_LENGTH, /* 08 IO */ 132 ACPI_FIXED_LENGTH, /* 09 FixedIO */ 133 ACPI_FIXED_LENGTH, /* 0A FixedDMA */ 134 0, 135 0, 136 0, 137 ACPI_VARIABLE_LENGTH, /* 0E VendorShort */ 138 ACPI_FIXED_LENGTH, /* 0F EndTag */ 139 140 /* Large descriptors */ 141 142 0, 143 ACPI_FIXED_LENGTH, /* 01 Memory24 */ 144 ACPI_FIXED_LENGTH, /* 02 GenericRegister */ 145 0, 146 ACPI_VARIABLE_LENGTH, /* 04 VendorLong */ 147 ACPI_FIXED_LENGTH, /* 05 Memory32 */ 148 ACPI_FIXED_LENGTH, /* 06 Memory32Fixed */ 149 ACPI_VARIABLE_LENGTH, /* 07 Dword* address */ 150 ACPI_VARIABLE_LENGTH, /* 08 Word* address */ 151 ACPI_VARIABLE_LENGTH, /* 09 ExtendedIRQ */ 152 ACPI_VARIABLE_LENGTH, /* 0A Qword* address */ 153 ACPI_FIXED_LENGTH, /* 0B Extended* address */ 154 ACPI_VARIABLE_LENGTH, /* 0C Gpio* */ 155 ACPI_VARIABLE_LENGTH, /* 0D PinFunction */ 156 ACPI_VARIABLE_LENGTH, /* 0E *SerialBus */ 157 ACPI_VARIABLE_LENGTH, /* 0F PinConfig */ 158 ACPI_VARIABLE_LENGTH, /* 10 PinGroup */ 159 ACPI_VARIABLE_LENGTH, /* 11 PinGroupFunction */ 160 ACPI_VARIABLE_LENGTH, /* 12 PinGroupConfig */ 161 ACPI_VARIABLE_LENGTH, /* 13 ClockInput */ 162 }; 163 164 165 /******************************************************************************* 166 * 167 * FUNCTION: AcpiUtWalkAmlResources 168 * 169 * PARAMETERS: WalkState - Current walk info 170 * PARAMETERS: Aml - Pointer to the raw AML resource template 171 * AmlLength - Length of the entire template 172 * UserFunction - Called once for each descriptor found. If 173 * NULL, a pointer to the EndTag is returned 174 * Context - Passed to UserFunction 175 * 176 * RETURN: Status 177 * 178 * DESCRIPTION: Walk a raw AML resource list(buffer). User function called 179 * once for each resource found. 180 * 181 ******************************************************************************/ 182 183 ACPI_STATUS 184 AcpiUtWalkAmlResources ( 185 ACPI_WALK_STATE *WalkState, 186 UINT8 *Aml, 187 ACPI_SIZE AmlLength, 188 ACPI_WALK_AML_CALLBACK UserFunction, 189 void **Context) 190 { 191 ACPI_STATUS Status; 192 UINT8 *EndAml; 193 UINT8 ResourceIndex; 194 UINT32 Length; 195 UINT32 Offset = 0; 196 UINT8 EndTag[2] = {0x79, 0x00}; 197 198 199 ACPI_FUNCTION_TRACE (UtWalkAmlResources); 200 201 202 /* The absolute minimum resource template is one EndTag descriptor */ 203 204 if (AmlLength < sizeof (AML_RESOURCE_END_TAG)) 205 { 206 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); 207 } 208 209 /* Point to the end of the resource template buffer */ 210 211 EndAml = Aml + AmlLength; 212 213 /* Walk the byte list, abort on any invalid descriptor type or length */ 214 215 while (Aml < EndAml) 216 { 217 /* 218 * Validate that the remaining buffer space can hold enough 219 * bytes to safely access fields during validation. 220 * For large resource descriptors (bit 7 set), we need enough 221 * bytes to access the Type field in SerialBus resources. 222 * Small resource descriptors only need sizeof(AML_RESOURCE_END_TAG). 223 */ 224 if ((ACPI_SIZE) (EndAml - Aml) < sizeof (AML_RESOURCE_END_TAG)) 225 { 226 return_ACPI_STATUS (AE_AML_BUFFER_LENGTH); 227 } 228 229 /* 230 * For large resource descriptors, ensure enough space for 231 * the header plus SerialBus Type field access. 232 */ 233 if ((ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) && 234 ((ACPI_SIZE) (EndAml - Aml) < 235 ACPI_OFFSET (AML_RESOURCE_COMMON_SERIALBUS, Type) + 1)) 236 { 237 return_ACPI_STATUS (AE_AML_BUFFER_LENGTH); 238 } 239 240 /* Validate the Resource Type and Resource Length */ 241 242 Status = AcpiUtValidateResource (WalkState, Aml, &ResourceIndex); 243 if (ACPI_FAILURE (Status)) 244 { 245 /* 246 * Exit on failure. Cannot continue because the descriptor 247 * length may be bogus also. 248 */ 249 return_ACPI_STATUS (Status); 250 } 251 252 /* Get the length of this descriptor */ 253 254 Length = AcpiUtGetDescriptorLength (Aml); 255 256 /* 257 * Validate that the descriptor length doesn't exceed the 258 * remaining buffer size to prevent reading beyond the end. 259 */ 260 if (Length > (ACPI_SIZE) (EndAml - Aml)) 261 { 262 return_ACPI_STATUS (AE_AML_BUFFER_LENGTH); 263 } 264 265 /* Invoke the user function */ 266 267 if (UserFunction) 268 { 269 Status = UserFunction ( 270 Aml, Length, Offset, ResourceIndex, Context); 271 if (ACPI_FAILURE (Status)) 272 { 273 return_ACPI_STATUS (Status); 274 } 275 } 276 277 /* An EndTag descriptor terminates this resource template */ 278 279 if (AcpiUtGetResourceType (Aml) == ACPI_RESOURCE_NAME_END_TAG) 280 { 281 /* 282 * There must be at least one more byte in the buffer for 283 * the 2nd byte of the EndTag 284 */ 285 if ((Aml + 1) >= EndAml) 286 { 287 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); 288 } 289 290 /* 291 * Don't attempt to perform any validation on the 2nd byte. 292 * Although all known ASL compilers insert a zero for the 2nd 293 * byte, it can also be a checksum (as per the ACPI spec), 294 * and this is occasionally seen in the field. July 2017. 295 */ 296 297 /* Return the pointer to the EndTag if requested */ 298 299 if (!UserFunction) 300 { 301 *Context = Aml; 302 } 303 304 /* Normal exit */ 305 306 return_ACPI_STATUS (AE_OK); 307 } 308 309 Aml += Length; 310 Offset += Length; 311 } 312 313 /* Did not find an EndTag descriptor */ 314 315 if (UserFunction) 316 { 317 /* Insert an EndTag anyway. AcpiRsGetListLength always leaves room */ 318 319 (void) AcpiUtValidateResource (WalkState, EndTag, &ResourceIndex); 320 Status = UserFunction (EndTag, 2, Offset, ResourceIndex, Context); 321 if (ACPI_FAILURE (Status)) 322 { 323 return_ACPI_STATUS (Status); 324 } 325 } 326 327 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); 328 } 329 330 331 /******************************************************************************* 332 * 333 * FUNCTION: AcpiUtValidateResource 334 * 335 * PARAMETERS: WalkState - Current walk info 336 * Aml - Pointer to the raw AML resource descriptor 337 * ReturnIndex - Where the resource index is returned. NULL 338 * if the index is not required. 339 * 340 * RETURN: Status, and optionally the Index into the global resource tables 341 * 342 * DESCRIPTION: Validate an AML resource descriptor by checking the Resource 343 * Type and Resource Length. Returns an index into the global 344 * resource information/dispatch tables for later use. 345 * 346 ******************************************************************************/ 347 348 ACPI_STATUS 349 AcpiUtValidateResource ( 350 ACPI_WALK_STATE *WalkState, 351 void *Aml, 352 UINT8 *ReturnIndex) 353 { 354 AML_RESOURCE *AmlResource; 355 UINT8 ResourceType; 356 UINT8 ResourceIndex; 357 ACPI_RS_LENGTH ResourceLength; 358 ACPI_RS_LENGTH MinimumResourceLength; 359 360 361 ACPI_FUNCTION_ENTRY (); 362 363 364 /* 365 * 1) Validate the ResourceType field (Byte 0) 366 */ 367 ResourceType = ACPI_GET8 (Aml); 368 369 /* 370 * Byte 0 contains the descriptor name (Resource Type) 371 * Examine the large/small bit in the resource header 372 */ 373 if (ResourceType & ACPI_RESOURCE_NAME_LARGE) 374 { 375 /* Verify the large resource type (name) against the max */ 376 377 if (ResourceType > ACPI_RESOURCE_NAME_LARGE_MAX) 378 { 379 goto InvalidResource; 380 } 381 382 /* 383 * Large Resource Type -- bits 6:0 contain the name 384 * Translate range 0x80-0x8B to index range 0x10-0x1B 385 */ 386 ResourceIndex = (UINT8) (ResourceType - 0x70); 387 } 388 else 389 { 390 /* 391 * Small Resource Type -- bits 6:3 contain the name 392 * Shift range to index range 0x00-0x0F 393 */ 394 ResourceIndex = (UINT8) 395 ((ResourceType & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3); 396 } 397 398 /* 399 * Check validity of the resource type, via AcpiGbl_ResourceTypes. 400 * Zero indicates an invalid resource. 401 */ 402 if (!AcpiGbl_ResourceTypes[ResourceIndex]) 403 { 404 goto InvalidResource; 405 } 406 407 /* 408 * Validate the ResourceLength field. This ensures that the length 409 * is at least reasonable, and guarantees that it is non-zero. 410 */ 411 ResourceLength = AcpiUtGetResourceLength (Aml); 412 MinimumResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex]; 413 414 /* Validate based upon the type of resource - fixed length or variable */ 415 416 switch (AcpiGbl_ResourceTypes[ResourceIndex]) 417 { 418 case ACPI_FIXED_LENGTH: 419 420 /* Fixed length resource, length must match exactly */ 421 422 if (ResourceLength != MinimumResourceLength) 423 { 424 goto BadResourceLength; 425 } 426 break; 427 428 case ACPI_VARIABLE_LENGTH: 429 430 /* Variable length resource, length must be at least the minimum */ 431 432 if (ResourceLength < MinimumResourceLength) 433 { 434 goto BadResourceLength; 435 } 436 break; 437 438 case ACPI_SMALL_VARIABLE_LENGTH: 439 440 /* Small variable length resource, length can be (Min) or (Min-1) */ 441 442 if ((ResourceLength > MinimumResourceLength) || 443 (ResourceLength < (MinimumResourceLength - 1))) 444 { 445 goto BadResourceLength; 446 } 447 break; 448 449 default: 450 451 /* Shouldn't happen (because of validation earlier), but be sure */ 452 453 goto InvalidResource; 454 } 455 456 AmlResource = ACPI_CAST_PTR (AML_RESOURCE, Aml); 457 if (ResourceType == ACPI_RESOURCE_NAME_SERIAL_BUS) 458 { 459 /* Validate the BusType field */ 460 461 if ((AmlResource->CommonSerialBus.Type == 0) || 462 (AmlResource->CommonSerialBus.Type > AML_RESOURCE_MAX_SERIALBUSTYPE)) 463 { 464 if (WalkState) 465 { 466 ACPI_ERROR ((AE_INFO, 467 "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X", 468 AmlResource->CommonSerialBus.Type)); 469 } 470 return (AE_AML_INVALID_RESOURCE_TYPE); 471 } 472 } 473 474 /* Optionally return the resource table index */ 475 476 if (ReturnIndex) 477 { 478 *ReturnIndex = ResourceIndex; 479 } 480 481 return (AE_OK); 482 483 484 InvalidResource: 485 486 if (WalkState) 487 { 488 ACPI_ERROR ((AE_INFO, 489 "Invalid/unsupported resource descriptor: Type 0x%2.2X", 490 ResourceType)); 491 } 492 return (AE_AML_INVALID_RESOURCE_TYPE); 493 494 BadResourceLength: 495 496 if (WalkState) 497 { 498 ACPI_ERROR ((AE_INFO, 499 "Invalid resource descriptor length: Type " 500 "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X", 501 ResourceType, ResourceLength, MinimumResourceLength)); 502 } 503 return (AE_AML_BAD_RESOURCE_LENGTH); 504 } 505 506 507 /******************************************************************************* 508 * 509 * FUNCTION: AcpiUtGetResourceType 510 * 511 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 512 * 513 * RETURN: The Resource Type with no extraneous bits (except the 514 * Large/Small descriptor bit -- this is left alone) 515 * 516 * DESCRIPTION: Extract the Resource Type/Name from the first byte of 517 * a resource descriptor. 518 * 519 ******************************************************************************/ 520 521 UINT8 522 AcpiUtGetResourceType ( 523 void *Aml) 524 { 525 ACPI_FUNCTION_ENTRY (); 526 527 528 /* 529 * Byte 0 contains the descriptor name (Resource Type) 530 * Examine the large/small bit in the resource header 531 */ 532 if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) 533 { 534 /* Large Resource Type -- bits 6:0 contain the name */ 535 536 return (ACPI_GET8 (Aml)); 537 } 538 else 539 { 540 /* Small Resource Type -- bits 6:3 contain the name */ 541 542 return ((UINT8) (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_SMALL_MASK)); 543 } 544 } 545 546 547 /******************************************************************************* 548 * 549 * FUNCTION: AcpiUtGetResourceLength 550 * 551 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 552 * 553 * RETURN: Byte Length 554 * 555 * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By 556 * definition, this does not include the size of the descriptor 557 * header or the length field itself. 558 * 559 ******************************************************************************/ 560 561 UINT16 562 AcpiUtGetResourceLength ( 563 void *Aml) 564 { 565 ACPI_RS_LENGTH ResourceLength; 566 567 568 ACPI_FUNCTION_ENTRY (); 569 570 571 /* 572 * Byte 0 contains the descriptor name (Resource Type) 573 * Examine the large/small bit in the resource header 574 */ 575 if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) 576 { 577 /* Large Resource type -- bytes 1-2 contain the 16-bit length */ 578 579 ACPI_MOVE_16_TO_16 (&ResourceLength, ACPI_ADD_PTR (UINT8, Aml, 1)); 580 581 } 582 else 583 { 584 /* Small Resource type -- bits 2:0 of byte 0 contain the length */ 585 586 ResourceLength = (UINT16) (ACPI_GET8 (Aml) & 587 ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK); 588 } 589 590 return (ResourceLength); 591 } 592 593 594 /******************************************************************************* 595 * 596 * FUNCTION: AcpiUtGetResourceHeaderLength 597 * 598 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 599 * 600 * RETURN: Length of the AML header (depends on large/small descriptor) 601 * 602 * DESCRIPTION: Get the length of the header for this resource. 603 * 604 ******************************************************************************/ 605 606 UINT8 607 AcpiUtGetResourceHeaderLength ( 608 void *Aml) 609 { 610 ACPI_FUNCTION_ENTRY (); 611 612 613 /* Examine the large/small bit in the resource header */ 614 615 if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) 616 { 617 return (sizeof (AML_RESOURCE_LARGE_HEADER)); 618 } 619 else 620 { 621 return (sizeof (AML_RESOURCE_SMALL_HEADER)); 622 } 623 } 624 625 626 /******************************************************************************* 627 * 628 * FUNCTION: AcpiUtGetDescriptorLength 629 * 630 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 631 * 632 * RETURN: Byte length 633 * 634 * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the 635 * length of the descriptor header and the length field itself. 636 * Used to walk descriptor lists. 637 * 638 ******************************************************************************/ 639 640 UINT32 641 AcpiUtGetDescriptorLength ( 642 void *Aml) 643 { 644 ACPI_FUNCTION_ENTRY (); 645 646 647 /* 648 * Get the Resource Length (does not include header length) and add 649 * the header length (depends on if this is a small or large resource) 650 */ 651 return (AcpiUtGetResourceLength (Aml) + 652 AcpiUtGetResourceHeaderLength (Aml)); 653 } 654 655 656 /******************************************************************************* 657 * 658 * FUNCTION: AcpiUtGetResourceEndTag 659 * 660 * PARAMETERS: ObjDesc - The resource template buffer object 661 * EndTag - Where the pointer to the EndTag is returned 662 * 663 * RETURN: Status, pointer to the end tag 664 * 665 * DESCRIPTION: Find the EndTag resource descriptor in an AML resource template 666 * Note: allows a buffer length of zero. 667 * 668 ******************************************************************************/ 669 670 ACPI_STATUS 671 AcpiUtGetResourceEndTag ( 672 ACPI_OPERAND_OBJECT *ObjDesc, 673 UINT8 **EndTag) 674 { 675 ACPI_STATUS Status; 676 677 678 ACPI_FUNCTION_TRACE (UtGetResourceEndTag); 679 680 681 /* Allow a buffer length of zero */ 682 683 if (!ObjDesc->Buffer.Length) 684 { 685 *EndTag = ObjDesc->Buffer.Pointer; 686 return_ACPI_STATUS (AE_OK); 687 } 688 689 /* Validate the template and get a pointer to the EndTag */ 690 691 Status = AcpiUtWalkAmlResources (NULL, ObjDesc->Buffer.Pointer, 692 ObjDesc->Buffer.Length, NULL, (void **) EndTag); 693 694 return_ACPI_STATUS (Status); 695 } 696