1 /****************************************************************************** 2 * 3 * Module Name: aslxref - Namespace cross-reference 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 45 #include <contrib/dev/acpica/compiler/aslcompiler.h> 46 #include "aslcompiler.y.h" 47 #include <contrib/dev/acpica/include/acparser.h> 48 #include <contrib/dev/acpica/include/amlcode.h> 49 #include <contrib/dev/acpica/include/acnamesp.h> 50 #include <contrib/dev/acpica/include/acdispat.h> 51 52 53 #define _COMPONENT ACPI_COMPILER 54 ACPI_MODULE_NAME ("aslxref") 55 56 /* Local prototypes */ 57 58 static ACPI_STATUS 59 XfNamespaceLocateBegin ( 60 ACPI_PARSE_OBJECT *Op, 61 UINT32 Level, 62 void *Context); 63 64 static ACPI_STATUS 65 XfNamespaceLocateEnd ( 66 ACPI_PARSE_OBJECT *Op, 67 UINT32 Level, 68 void *Context); 69 70 static BOOLEAN 71 XfObjectExists ( 72 char *Name); 73 74 static ACPI_STATUS 75 XfCompareOneNamespaceObject ( 76 ACPI_HANDLE ObjHandle, 77 UINT32 Level, 78 void *Context, 79 void **ReturnValue); 80 81 static void 82 XfCheckFieldRange ( 83 ACPI_PARSE_OBJECT *Op, 84 UINT32 RegionBitLength, 85 UINT32 FieldBitOffset, 86 UINT32 FieldBitLength, 87 UINT32 AccessBitWidth); 88 89 90 /******************************************************************************* 91 * 92 * FUNCTION: XfCrossReferenceNamespace 93 * 94 * PARAMETERS: None 95 * 96 * RETURN: Status 97 * 98 * DESCRIPTION: Perform a cross reference check of the parse tree against the 99 * namespace. Every named referenced within the parse tree 100 * should be get resolved with a namespace lookup. If not, the 101 * original reference in the ASL code is invalid -- i.e., refers 102 * to a non-existent object. 103 * 104 * NOTE: The ASL "External" operator causes the name to be inserted into the 105 * namespace so that references to the external name will be resolved 106 * correctly here. 107 * 108 ******************************************************************************/ 109 110 ACPI_STATUS 111 XfCrossReferenceNamespace ( 112 void) 113 { 114 ACPI_WALK_STATE *WalkState; 115 116 117 DbgPrint (ASL_DEBUG_OUTPUT, "\nCross referencing namespace\n\n"); 118 119 /* 120 * Create a new walk state for use when looking up names 121 * within the namespace (Passed as context to the callbacks) 122 */ 123 WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); 124 if (!WalkState) 125 { 126 return (AE_NO_MEMORY); 127 } 128 129 /* Walk the entire parse tree */ 130 131 TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, XfNamespaceLocateBegin, 132 XfNamespaceLocateEnd, WalkState); 133 return (AE_OK); 134 } 135 136 137 /******************************************************************************* 138 * 139 * FUNCTION: XfObjectExists 140 * 141 * PARAMETERS: Name - 4 char ACPI name 142 * 143 * RETURN: TRUE if name exists in namespace 144 * 145 * DESCRIPTION: Walk the namespace to find an object 146 * 147 ******************************************************************************/ 148 149 static BOOLEAN 150 XfObjectExists ( 151 char *Name) 152 { 153 ACPI_STATUS Status; 154 155 156 /* Walk entire namespace from the supplied root */ 157 158 Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 159 ACPI_UINT32_MAX, FALSE, XfCompareOneNamespaceObject, NULL, 160 Name, NULL); 161 if (Status == AE_CTRL_TRUE) 162 { 163 /* At least one instance of the name was found */ 164 165 return (TRUE); 166 } 167 168 return (FALSE); 169 } 170 171 172 /******************************************************************************* 173 * 174 * FUNCTION: XfCompareOneNamespaceObject 175 * 176 * PARAMETERS: ACPI_WALK_CALLBACK 177 * 178 * RETURN: Status 179 * 180 * DESCRIPTION: Compare name of one object. 181 * 182 ******************************************************************************/ 183 184 static ACPI_STATUS 185 XfCompareOneNamespaceObject ( 186 ACPI_HANDLE ObjHandle, 187 UINT32 Level, 188 void *Context, 189 void **ReturnValue) 190 { 191 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 192 193 194 /* Simply check the name */ 195 196 if (*((UINT32 *) (Context)) == Node->Name.Integer) 197 { 198 /* Abort walk if we found one instance */ 199 200 return (AE_CTRL_TRUE); 201 } 202 203 return (AE_OK); 204 } 205 206 207 /******************************************************************************* 208 * 209 * FUNCTION: XfCheckFieldRange 210 * 211 * PARAMETERS: RegionBitLength - Length of entire parent region 212 * FieldBitOffset - Start of the field unit (within region) 213 * FieldBitLength - Entire length of field unit 214 * AccessBitWidth - Access width of the field unit 215 * 216 * RETURN: None 217 * 218 * DESCRIPTION: Check one field unit to make sure it fits in the parent 219 * op region. 220 * 221 * Note: AccessBitWidth must be either 8,16,32, or 64 222 * 223 ******************************************************************************/ 224 225 static void 226 XfCheckFieldRange ( 227 ACPI_PARSE_OBJECT *Op, 228 UINT32 RegionBitLength, 229 UINT32 FieldBitOffset, 230 UINT32 FieldBitLength, 231 UINT32 AccessBitWidth) 232 { 233 UINT32 FieldEndBitOffset; 234 235 236 /* 237 * Check each field unit against the region size. The entire 238 * field unit (start offset plus length) must fit within the 239 * region. 240 */ 241 FieldEndBitOffset = FieldBitOffset + FieldBitLength; 242 243 if (FieldEndBitOffset > RegionBitLength) 244 { 245 /* Field definition itself is beyond the end-of-region */ 246 247 AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL); 248 return; 249 } 250 251 /* 252 * Now check that the field plus AccessWidth doesn't go beyond 253 * the end-of-region. Assumes AccessBitWidth is a power of 2 254 */ 255 FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth); 256 257 if (FieldEndBitOffset > RegionBitLength) 258 { 259 /* Field definition combined with the access is beyond EOR */ 260 261 AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL); 262 } 263 } 264 265 /******************************************************************************* 266 * 267 * FUNCTION: XfNamespaceLocateBegin 268 * 269 * PARAMETERS: ASL_WALK_CALLBACK 270 * 271 * RETURN: Status 272 * 273 * DESCRIPTION: Descending callback used during cross-reference. For named 274 * object references, attempt to locate the name in the 275 * namespace. 276 * 277 * NOTE: ASL references to named fields within resource descriptors are 278 * resolved to integer values here. Therefore, this step is an 279 * important part of the code generation. We don't know that the 280 * name refers to a resource descriptor until now. 281 * 282 ******************************************************************************/ 283 284 static ACPI_STATUS 285 XfNamespaceLocateBegin ( 286 ACPI_PARSE_OBJECT *Op, 287 UINT32 Level, 288 void *Context) 289 { 290 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 291 ACPI_NAMESPACE_NODE *Node; 292 ACPI_STATUS Status; 293 ACPI_OBJECT_TYPE ObjectType; 294 char *Path; 295 UINT8 PassedArgs; 296 ACPI_PARSE_OBJECT *NextOp; 297 ACPI_PARSE_OBJECT *OwningOp; 298 ACPI_PARSE_OBJECT *SpaceIdOp; 299 UINT32 MinimumLength; 300 UINT32 Offset; 301 UINT32 FieldBitLength; 302 UINT32 TagBitLength; 303 UINT8 Message = 0; 304 const ACPI_OPCODE_INFO *OpInfo; 305 UINT32 Flags; 306 307 308 ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op); 309 310 /* 311 * If this node is the actual declaration of a name 312 * [such as the XXXX name in "Method (XXXX)"], 313 * we are not interested in it here. We only care about names that are 314 * references to other objects within the namespace and the parent objects 315 * of name declarations 316 */ 317 if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION) 318 { 319 return (AE_OK); 320 } 321 322 /* We are only interested in opcodes that have an associated name */ 323 324 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 325 326 if ((!(OpInfo->Flags & AML_NAMED)) && 327 (!(OpInfo->Flags & AML_CREATE)) && 328 (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) && 329 (Op->Asl.ParseOpcode != PARSEOP_NAMESEG) && 330 (Op->Asl.ParseOpcode != PARSEOP_METHODCALL)) 331 { 332 return (AE_OK); 333 } 334 335 /* 336 * One special case: CondRefOf operator - we don't care if the name exists 337 * or not at this point, just ignore it, the point of the operator is to 338 * determine if the name exists at runtime. 339 */ 340 if ((Op->Asl.Parent) && 341 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)) 342 { 343 return (AE_OK); 344 } 345 346 /* 347 * We must enable the "search-to-root" for single NameSegs, but 348 * we have to be very careful about opening up scopes 349 */ 350 Flags = ACPI_NS_SEARCH_PARENT; 351 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 352 (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 353 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 354 { 355 /* 356 * These are name references, do not push the scope stack 357 * for them. 358 */ 359 Flags |= ACPI_NS_DONT_OPEN_SCOPE; 360 } 361 362 /* Get the NamePath from the appropriate place */ 363 364 if (OpInfo->Flags & AML_NAMED) 365 { 366 /* For nearly all NAMED operators, the name reference is the first child */ 367 368 Path = Op->Asl.Child->Asl.Value.String; 369 if (Op->Asl.AmlOpcode == AML_ALIAS_OP) 370 { 371 /* 372 * ALIAS is the only oddball opcode, the name declaration 373 * (alias name) is the second operand 374 */ 375 Path = Op->Asl.Child->Asl.Next->Asl.Value.String; 376 } 377 } 378 else if (OpInfo->Flags & AML_CREATE) 379 { 380 /* Name must appear as the last parameter */ 381 382 NextOp = Op->Asl.Child; 383 while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)) 384 { 385 NextOp = NextOp->Asl.Next; 386 } 387 Path = NextOp->Asl.Value.String; 388 } 389 else 390 { 391 Path = Op->Asl.Value.String; 392 } 393 394 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 395 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 396 "Type=%s\n", AcpiUtGetTypeName (ObjectType))); 397 398 /* 399 * Lookup the name in the namespace. Name must exist at this point, or it 400 * is an invalid reference. 401 * 402 * The namespace is also used as a lookup table for references to resource 403 * descriptors and the fields within them. 404 */ 405 Gbl_NsLookupCount++; 406 407 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 408 ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node)); 409 if (ACPI_FAILURE (Status)) 410 { 411 if (Status == AE_NOT_FOUND) 412 { 413 /* 414 * We didn't find the name reference by path -- we can qualify this 415 * a little better before we print an error message 416 */ 417 if (strlen (Path) == ACPI_NAME_SIZE) 418 { 419 /* A simple, one-segment ACPI name */ 420 421 if (XfObjectExists (Path)) 422 { 423 /* 424 * There exists such a name, but we couldn't get to it 425 * from this scope 426 */ 427 AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op, 428 Op->Asl.ExternalName); 429 } 430 else 431 { 432 /* The name doesn't exist, period */ 433 434 AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, 435 Op, Op->Asl.ExternalName); 436 } 437 } 438 else 439 { 440 /* Check for a fully qualified path */ 441 442 if (Path[0] == AML_ROOT_PREFIX) 443 { 444 /* Gave full path, the object does not exist */ 445 446 AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op, 447 Op->Asl.ExternalName); 448 } 449 else 450 { 451 /* 452 * We can't tell whether it doesn't exist or just 453 * can't be reached. 454 */ 455 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 456 Op->Asl.ExternalName); 457 } 458 } 459 460 Status = AE_OK; 461 } 462 return (Status); 463 } 464 465 /* Check for a reference vs. name declaration */ 466 467 if (!(OpInfo->Flags & AML_NAMED) && 468 !(OpInfo->Flags & AML_CREATE)) 469 { 470 /* This node has been referenced, mark it for reference check */ 471 472 Node->Flags |= ANOBJ_IS_REFERENCED; 473 } 474 475 /* Attempt to optimize the NamePath */ 476 477 OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node); 478 479 /* 480 * 1) Dereference an alias (A name reference that is an alias) 481 * Aliases are not nested, the alias always points to the final object 482 */ 483 if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) && 484 (Node->Type == ACPI_TYPE_LOCAL_ALIAS)) 485 { 486 /* This node points back to the original PARSEOP_ALIAS */ 487 488 NextOp = Node->Op; 489 490 /* The first child is the alias target op */ 491 492 NextOp = NextOp->Asl.Child; 493 494 /* That in turn points back to original target alias node */ 495 496 if (NextOp->Asl.Node) 497 { 498 Node = NextOp->Asl.Node; 499 } 500 501 /* Else - forward reference to alias, will be resolved later */ 502 } 503 504 /* 2) Check for a reference to a resource descriptor */ 505 506 if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 507 (Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 508 { 509 /* 510 * This was a reference to a field within a resource descriptor. 511 * Extract the associated field offset (either a bit or byte 512 * offset depending on the field type) and change the named 513 * reference into an integer for AML code generation 514 */ 515 Offset = Node->Value; 516 TagBitLength = Node->Length; 517 518 /* 519 * If a field is being created, generate the length (in bits) of 520 * the field. Note: Opcodes other than CreateXxxField and Index 521 * can come through here. For other opcodes, we just need to 522 * convert the resource tag reference to an integer offset. 523 */ 524 switch (Op->Asl.Parent->Asl.AmlOpcode) 525 { 526 case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */ 527 /* 528 * We know the length operand is an integer constant because 529 * we know that it contains a reference to a resource 530 * descriptor tag. 531 */ 532 FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer; 533 break; 534 535 case AML_CREATE_BIT_FIELD_OP: 536 537 FieldBitLength = 1; 538 break; 539 540 case AML_CREATE_BYTE_FIELD_OP: 541 case AML_INDEX_OP: 542 543 FieldBitLength = 8; 544 break; 545 546 case AML_CREATE_WORD_FIELD_OP: 547 548 FieldBitLength = 16; 549 break; 550 551 case AML_CREATE_DWORD_FIELD_OP: 552 553 FieldBitLength = 32; 554 break; 555 556 case AML_CREATE_QWORD_FIELD_OP: 557 558 FieldBitLength = 64; 559 break; 560 561 default: 562 563 FieldBitLength = 0; 564 break; 565 } 566 567 /* Check the field length against the length of the resource tag */ 568 569 if (FieldBitLength) 570 { 571 if (TagBitLength < FieldBitLength) 572 { 573 Message = ASL_MSG_TAG_SMALLER; 574 } 575 else if (TagBitLength > FieldBitLength) 576 { 577 Message = ASL_MSG_TAG_LARGER; 578 } 579 580 if (Message) 581 { 582 sprintf (MsgBuffer, "Size mismatch, Tag: %u bit%s, Field: %u bit%s", 583 TagBitLength, (TagBitLength > 1) ? "s" : "", 584 FieldBitLength, (FieldBitLength > 1) ? "s" : ""); 585 586 AslError (ASL_WARNING, Message, Op, MsgBuffer); 587 } 588 } 589 590 /* Convert the BitOffset to a ByteOffset for certain opcodes */ 591 592 switch (Op->Asl.Parent->Asl.AmlOpcode) 593 { 594 case AML_CREATE_BYTE_FIELD_OP: 595 case AML_CREATE_WORD_FIELD_OP: 596 case AML_CREATE_DWORD_FIELD_OP: 597 case AML_CREATE_QWORD_FIELD_OP: 598 case AML_INDEX_OP: 599 600 Offset = ACPI_DIV_8 (Offset); 601 break; 602 603 default: 604 605 break; 606 } 607 608 /* Now convert this node to an integer whose value is the field offset */ 609 610 Op->Asl.AmlLength = 0; 611 Op->Asl.ParseOpcode = PARSEOP_INTEGER; 612 Op->Asl.Value.Integer = (UINT64) Offset; 613 Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD; 614 615 OpcGenerateAmlOpcode (Op); 616 } 617 618 /* 3) Check for a method invocation */ 619 620 else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) && 621 (Node->Type == ACPI_TYPE_METHOD) && 622 (Op->Asl.Parent) && 623 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD)) || 624 625 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 626 { 627 628 /* 629 * A reference to a method within one of these opcodes is not an 630 * invocation of the method, it is simply a reference to the method. 631 */ 632 if ((Op->Asl.Parent) && 633 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) || 634 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF) || 635 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE))) 636 { 637 return (AE_OK); 638 } 639 /* 640 * There are two types of method invocation: 641 * 1) Invocation with arguments -- the parser recognizes this 642 * as a METHODCALL. 643 * 2) Invocation with no arguments --the parser cannot determine that 644 * this is a method invocation, therefore we have to figure it out 645 * here. 646 */ 647 if (Node->Type != ACPI_TYPE_METHOD) 648 { 649 sprintf (MsgBuffer, "%s is a %s", 650 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); 651 652 AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer); 653 return (AE_OK); 654 } 655 656 /* Save the method node in the caller's op */ 657 658 Op->Asl.Node = Node; 659 if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF) 660 { 661 return (AE_OK); 662 } 663 664 /* 665 * This is a method invocation, with or without arguments. 666 * Count the number of arguments, each appears as a child 667 * under the parent node 668 */ 669 Op->Asl.ParseOpcode = PARSEOP_METHODCALL; 670 UtSetParseOpName (Op); 671 672 PassedArgs = 0; 673 NextOp = Op->Asl.Child; 674 675 while (NextOp) 676 { 677 PassedArgs++; 678 NextOp = NextOp->Asl.Next; 679 } 680 681 if (Node->Value != ASL_EXTERNAL_METHOD) 682 { 683 /* 684 * Check the parsed arguments with the number expected by the 685 * method declaration itself 686 */ 687 if (PassedArgs != Node->Value) 688 { 689 sprintf (MsgBuffer, "%s requires %u", Op->Asl.ExternalName, 690 Node->Value); 691 692 if (PassedArgs < Node->Value) 693 { 694 AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer); 695 } 696 else 697 { 698 AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer); 699 } 700 } 701 } 702 } 703 704 /* 4) Check for an ASL Field definition */ 705 706 else if ((Op->Asl.Parent) && 707 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD) || 708 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD))) 709 { 710 /* 711 * Offset checking for fields. If the parent operation region has a 712 * constant length (known at compile time), we can check fields 713 * defined in that region against the region length. This will catch 714 * fields and field units that cannot possibly fit within the region. 715 * 716 * Note: Index fields do not directly reference an operation region, 717 * thus they are not included in this check. 718 */ 719 if (Op == Op->Asl.Parent->Asl.Child) 720 { 721 /* 722 * This is the first child of the field node, which is 723 * the name of the region. Get the parse node for the 724 * region -- which contains the length of the region. 725 */ 726 OwningOp = Node->Op; 727 Op->Asl.Parent->Asl.ExtraValue = 728 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer); 729 730 /* Examine the field access width */ 731 732 switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer) 733 { 734 case AML_FIELD_ACCESS_ANY: 735 case AML_FIELD_ACCESS_BYTE: 736 case AML_FIELD_ACCESS_BUFFER: 737 default: 738 739 MinimumLength = 1; 740 break; 741 742 case AML_FIELD_ACCESS_WORD: 743 744 MinimumLength = 2; 745 break; 746 747 case AML_FIELD_ACCESS_DWORD: 748 749 MinimumLength = 4; 750 break; 751 752 case AML_FIELD_ACCESS_QWORD: 753 754 MinimumLength = 8; 755 break; 756 } 757 758 /* 759 * Is the region at least as big as the access width? 760 * Note: DataTableRegions have 0 length 761 */ 762 if (((UINT32) OwningOp->Asl.Value.Integer) && 763 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength)) 764 { 765 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL); 766 } 767 768 /* 769 * Check EC/CMOS/SMBUS fields to make sure that the correct 770 * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS) 771 */ 772 SpaceIdOp = OwningOp->Asl.Child->Asl.Next; 773 switch ((UINT32) SpaceIdOp->Asl.Value.Integer) 774 { 775 case ACPI_ADR_SPACE_EC: 776 case ACPI_ADR_SPACE_CMOS: 777 case ACPI_ADR_SPACE_GPIO: 778 779 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE) 780 { 781 AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL); 782 } 783 break; 784 785 case ACPI_ADR_SPACE_SMBUS: 786 case ACPI_ADR_SPACE_IPMI: 787 case ACPI_ADR_SPACE_GSBUS: 788 789 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER) 790 { 791 AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL); 792 } 793 break; 794 795 default: 796 797 /* Nothing to do for other address spaces */ 798 799 break; 800 } 801 } 802 else 803 { 804 /* 805 * This is one element of the field list. Check to make sure 806 * that it does not go beyond the end of the parent operation region. 807 * 808 * In the code below: 809 * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits) 810 * Op->Asl.ExtraValue - Field start offset (bits) 811 * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits) 812 * Op->Asl.Child->Asl.ExtraValue - Field access width (bits) 813 */ 814 if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child) 815 { 816 XfCheckFieldRange (Op, 817 Op->Asl.Parent->Asl.ExtraValue, 818 Op->Asl.ExtraValue, 819 (UINT32) Op->Asl.Child->Asl.Value.Integer, 820 Op->Asl.Child->Asl.ExtraValue); 821 } 822 } 823 } 824 825 Op->Asl.Node = Node; 826 return (Status); 827 } 828 829 830 /******************************************************************************* 831 * 832 * FUNCTION: XfNamespaceLocateEnd 833 * 834 * PARAMETERS: ASL_WALK_CALLBACK 835 * 836 * RETURN: Status 837 * 838 * DESCRIPTION: Ascending callback used during cross reference. We only 839 * need to worry about scope management here. 840 * 841 ******************************************************************************/ 842 843 static ACPI_STATUS 844 XfNamespaceLocateEnd ( 845 ACPI_PARSE_OBJECT *Op, 846 UINT32 Level, 847 void *Context) 848 { 849 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 850 const ACPI_OPCODE_INFO *OpInfo; 851 852 853 ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd); 854 855 856 /* We are only interested in opcodes that have an associated name */ 857 858 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 859 if (!(OpInfo->Flags & AML_NAMED)) 860 { 861 return (AE_OK); 862 } 863 864 /* Not interested in name references, we did not open a scope for them */ 865 866 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 867 (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 868 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 869 { 870 return (AE_OK); 871 } 872 873 /* Pop the scope stack if necessary */ 874 875 if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode))) 876 { 877 878 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 879 "%s: Popping scope for Op %p\n", 880 AcpiUtGetTypeName (OpInfo->ObjectType), Op)); 881 882 (void) AcpiDsScopeStackPop (WalkState); 883 } 884 885 return (AE_OK); 886 } 887