Changeset 108029 in vbox for trunk/src/VBox/Runtime/common/acpi/acpi-compiler.cpp
- Timestamp:
- Feb 3, 2025 3:58:01 PM (3 weeks ago)
- svn:sync-xref-src-repo-rev:
- 167302
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/acpi/acpi-compiler.cpp
r108021 r108029 73 73 { 74 74 RTACPIASLTERMINAL_INVALID = 0, 75 76 /** Keyword terminals, must come first as they are used for indexing into a table later on. */ 75 77 RTACPIASLTERMINAL_KEYWORD_DEFINITION_BLOCK, 76 78 RTACPIASLTERMINAL_KEYWORD_SCOPE, … … 99 101 /** Error information. */ 100 102 PRTERRINFO pErrInfo; 103 /** List of AST nodes for the DefinitionBlock() scope. */ 104 RTLISTANCHOR LstStmts; 101 105 } RTACPIASLCU; 102 106 /** Pointer to an ACPI ASL compilation unit state. */ … … 104 108 /** Pointer to a constant ACPI ASL compilation unit state. */ 105 109 typedef const RTACPIASLCU *PCRTACPIASLCU; 110 111 112 /** 113 * ASL keyword encoding entry. 114 */ 115 typedef struct RTACPIASLKEYWORD 116 { 117 /** Name of the opcode. */ 118 const char *pszOpc; 119 /** The opcode AML value. */ 120 uint8_t bOpc; 121 /** Number of arguments required. */ 122 uint8_t cArgsReq; 123 /** Number of optional arguments. */ 124 uint8_t cArgsOpt; 125 /** Flags for the opcode. */ 126 uint32_t fFlags; 127 /** Argument type for the required arguments. */ 128 RTACPIASTARGTYPE aenmTypes[5]; 129 /** Arguments for optional arguments, including the default value if absent. */ 130 RTACPIASTARG aArgsOpt[3]; 131 } RTACPIASLKEYWORD; 132 /** Pointer to a ASL keyword encoding entry. */ 133 typedef RTACPIASLKEYWORD *PRTACPIASLKEYWORD; 134 /** Pointer to a const ASL keyword encoding entry. */ 135 typedef const RTACPIASLKEYWORD *PCRTACPIASLKEYWORD; 106 136 107 137 … … 155 185 { 156 186 { '\"', '\"', RTSCRIPT_LEX_RULE_CONSUME, RTScriptLexScanStringLiteralC, NULL}, 157 { '0', '9', RTSCRIPT_LEX_RULE_ CONSUME, rtAcpiAslLexerParseNumber, NULL},158 { 'A', 'Z', RTSCRIPT_LEX_RULE_ CONSUME, rtAcpiAslLexerParseNameString, NULL},159 { '_', '_', RTSCRIPT_LEX_RULE_ CONSUME, rtAcpiAslLexerParseNameString, NULL},160 { '^', '^', RTSCRIPT_LEX_RULE_ CONSUME, rtAcpiAslLexerParseNameString, NULL},161 { '\\', '\\', RTSCRIPT_LEX_RULE_ CONSUME, rtAcpiAslLexerParseNameString, NULL},187 { '0', '9', RTSCRIPT_LEX_RULE_DEFAULT, rtAcpiAslLexerParseNumber, NULL}, 188 { 'A', 'Z', RTSCRIPT_LEX_RULE_DEFAULT, rtAcpiAslLexerParseNameString, NULL}, 189 { '_', '_', RTSCRIPT_LEX_RULE_DEFAULT, rtAcpiAslLexerParseNameString, NULL}, 190 { '^', '^', RTSCRIPT_LEX_RULE_DEFAULT, rtAcpiAslLexerParseNameString, NULL}, 191 { '\\', '\\', RTSCRIPT_LEX_RULE_DEFAULT, rtAcpiAslLexerParseNameString, NULL}, 162 192 163 193 { '\0', '\0', RTSCRIPT_LEX_RULE_DEFAULT, NULL, NULL} … … 249 279 char aszIde[513]; RT_ZERO(aszIde); 250 280 unsigned idx = 0; 251 aszIde[idx++] = ch;252 281 253 282 if (ch == '^') /* PrefixPath */ 254 283 { 284 aszIde[idx++] = '^'; 285 RTScriptLexConsumeCh(hScriptLex); 286 255 287 ch = RTScriptLexGetCh(hScriptLex); 256 288 while ( idx < sizeof(aszIde) - 1 … … 264 296 if (idx == sizeof(aszIde) - 1) 265 297 return RTScriptLexProduceTokError(hScriptLex, pTok, VERR_BUFFER_OVERFLOW, "Lexer: PrefixPath exceeds the allowed length"); 298 } 299 else if (ch == '\\') 300 { 301 aszIde[idx++] = '\\'; 302 RTScriptLexConsumeCh(hScriptLex); 266 303 } 267 304 … … 310 347 311 348 349 #if 0 350 DECLINLINE(bool) rtAcpiAslLexerIsKeyword(PCRTACPIASLCU pThis, RTACPIASLTERMINAL enmTerm) 351 { 352 PCRTSCRIPTLEXTOKEN pTok; 353 int rc = RTScriptLexQueryToken(pThis->hLexSource, &pTok); 354 if (RT_FAILURE(rc)) 355 return false; 356 357 if ( pTok->enmType == RTSCRIPTLEXTOKTYPE_KEYWORD 358 && pTok->Type.Keyword.pKeyword->u64Val == (uint64_t)enmTerm) 359 return true; 360 361 return false; 362 } 363 #endif 364 365 366 DECLINLINE(bool) rtAcpiAslLexerIsPunctuator(PCRTACPIASLCU pThis, RTACPIASLTERMINAL enmTerm) 367 { 368 PCRTSCRIPTLEXTOKEN pTok; 369 int rc = RTScriptLexQueryToken(pThis->hLexSource, &pTok); 370 if (RT_FAILURE(rc)) 371 return false; 372 373 if ( pTok->enmType == RTSCRIPTLEXTOKTYPE_PUNCTUATOR 374 && pTok->Type.Keyword.pKeyword->u64Val == (uint64_t)enmTerm) 375 return true; 376 377 return false; 378 } 379 380 312 381 static int rtAcpiAslLexerConsumeIfKeyword(PCRTACPIASLCU pThis, RTACPIASLTERMINAL enmTerm, bool *pfConsumed) 313 382 { … … 396 465 && pTok->Type.Number.enmType == RTSCRIPTLEXTOKNUMTYPE_NATURAL) 397 466 { 398 RTScriptLexConsumeToken(pThis->hLexSource);399 467 *pfConsumed = true; 400 468 *pu64 = pTok->Type.Number.Type.u64; 469 RTScriptLexConsumeToken(pThis->hLexSource); 401 470 return VINF_SUCCESS; 402 471 } … … 477 546 } while(0) 478 547 479 static int rtAcpiTblAslParseInner(PRTACPIASLCU pThis); 480 481 static int rtAcpiTblAslParseTerminal(PRTACPIASLCU pThis, RTACPIASLTERMINAL enmTerminal) 548 #define RTACPIASL_SKIP_CURRENT_TOKEN() \ 549 RTScriptLexConsumeToken(pThis->hLexSource); 550 551 552 static int rtAcpiTblAslParseInner(PRTACPIASLCU pThis, PRTLISTANCHOR pLstStmts); 553 554 /** 555 * Keyword encoding table, indexed by RTACPIASLTERMINAL_XXX. 556 */ 557 static const RTACPIASLKEYWORD g_aAslKeywords[] = 558 { 559 /* RTACPIASLTERMINAL_INVALID */ { 560 NULL, 0, 0, 0, RTACPI_AST_NODE_F_DEFAULT, 561 { kAcpiAstArgType_Invalid, 562 kAcpiAstArgType_Invalid, 563 kAcpiAstArgType_Invalid, 564 kAcpiAstArgType_Invalid, 565 kAcpiAstArgType_Invalid}, 566 { 567 { kAcpiAstArgType_Invalid, { 0 } }, 568 { kAcpiAstArgType_Invalid, { 0 } }, 569 { kAcpiAstArgType_Invalid, { 0 } } 570 } 571 }, 572 /* RTACPIASLTERMINAL_DEFINITION_BLOCK */ { 573 NULL, 0, 0, 0, RTACPI_AST_NODE_F_DEFAULT, 574 { kAcpiAstArgType_Invalid, 575 kAcpiAstArgType_Invalid, 576 kAcpiAstArgType_Invalid, 577 kAcpiAstArgType_Invalid, 578 kAcpiAstArgType_Invalid}, 579 { 580 { kAcpiAstArgType_Invalid, { 0 } }, 581 { kAcpiAstArgType_Invalid, { 0 } }, 582 { kAcpiAstArgType_Invalid, { 0 } } 583 } 584 }, 585 /* RTACPIASLTERMINAL_SCOPE */ { 586 "Scope", ACPI_AML_BYTE_CODE_OP_SCOPE, 1, 0, RTACPI_AST_NODE_F_NEW_SCOPE, 587 { kAcpiAstArgType_NameString, 588 kAcpiAstArgType_Invalid, 589 kAcpiAstArgType_Invalid, 590 kAcpiAstArgType_Invalid, 591 kAcpiAstArgType_Invalid 592 }, 593 { 594 { kAcpiAstArgType_Invalid, { 0 } }, 595 { kAcpiAstArgType_Invalid, { 0 } }, 596 { kAcpiAstArgType_Invalid, { 0 } } 597 } 598 }, 599 /* RTACPIASLTERMINAL_PROCESSOR */ { 600 "Processor", ACPI_AML_BYTE_CODE_EXT_OP_PROCESSOR, 2, 2, RTACPI_AST_NODE_F_NEW_SCOPE | RTACPI_AST_NODE_F_EXT_OPC, 601 { kAcpiAstArgType_NameString, 602 kAcpiAstArgType_U8, 603 kAcpiAstArgType_Invalid, 604 kAcpiAstArgType_Invalid, 605 kAcpiAstArgType_Invalid 606 }, 607 { 608 { kAcpiAstArgType_U32, { 0 } }, 609 { kAcpiAstArgType_U8, { 0 } }, 610 { kAcpiAstArgType_Invalid, { 0 } } 611 } 612 }, 613 }; 614 615 static int rtAcpiTblAslParseArgument(PRTACPIASLCU pThis, const char *pszKeyword, uint8_t iArg, RTACPIASTARGTYPE enmArgType, PRTACPIASTARG pArg) 616 { 617 switch (enmArgType) 618 { 619 case kAcpiAstArgType_AstNode: 620 { 621 //rtAcpiTblAslParseTerminal(pThis, RTACPIASLTERMINAL enmTerminal, PRTACPIASTNODE *ppAstNd) 622 break; 623 } 624 case kAcpiAstArgType_NameString: 625 { 626 RTACPIASL_PARSE_NAME_STRING(pszNameString); 627 pArg->enmType = kAcpiAstArgType_NameString; 628 pArg->u.pszNameString = pszNameString; 629 break; 630 } 631 case kAcpiAstArgType_U8: 632 { 633 RTACPIASL_PARSE_NATURAL(u64); 634 if (u64 > UINT8_MAX) 635 return RTErrInfoSetF(pThis->pErrInfo, VERR_INVALID_PARAMETER, 636 "Value for byte parameter %u is out of range (%#RX64) while processing keyword '%s'", 637 iArg, u64, pszKeyword); 638 639 pArg->enmType = kAcpiAstArgType_U8; 640 pArg->u.u8 = (uint8_t)u64; 641 break; 642 } 643 case kAcpiAstArgType_U16: 644 { 645 RTACPIASL_PARSE_NATURAL(u64); 646 if (u64 > UINT16_MAX) 647 return RTErrInfoSetF(pThis->pErrInfo, VERR_INVALID_PARAMETER, 648 "Value for word parameter %u is out of range (%#RX64) while processing keyword '%s'", 649 iArg, u64, pszKeyword); 650 651 pArg->enmType = kAcpiAstArgType_U16; 652 pArg->u.u16 = (uint16_t)u64; 653 break; 654 } 655 case kAcpiAstArgType_U32: 656 { 657 RTACPIASL_PARSE_NATURAL(u64); 658 if (u64 > UINT32_MAX) 659 return RTErrInfoSetF(pThis->pErrInfo, VERR_INVALID_PARAMETER, 660 "Value for 32-bit parameter %u is out of range (%#RX64) while processing keyword '%s'", 661 iArg, u64, pszKeyword); 662 663 pArg->enmType = kAcpiAstArgType_U32; 664 pArg->u.u32 = (uint32_t)u64; 665 break; 666 } 667 case kAcpiAstArgType_U64: 668 { 669 RTACPIASL_PARSE_NATURAL(u64); 670 pArg->enmType = kAcpiAstArgType_U64; 671 pArg->u.u64 = u64; 672 break; 673 } 674 default: 675 AssertReleaseFailed(); 676 } 677 678 return VINF_SUCCESS; 679 } 680 681 682 static int rtAcpiTblAslParseTerminal(PRTACPIASLCU pThis, RTACPIASLTERMINAL enmTerminal, PRTACPIASTNODE *ppAstNd) 482 683 { 483 684 int rc = VINF_SUCCESS; 484 685 485 switch (enmTerminal) 486 { 487 case RTACPIASLTERMINAL_KEYWORD_SCOPE: 488 { 489 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_OPEN_BRACKET, '('); 490 RTACPIASL_PARSE_NAME_STRING(pszName); 491 RT_NOREF(pszName); 492 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_CLOSE_BRACKET, ')'); 493 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_OPEN_CURLY_BRACKET, '{'); 494 rc = rtAcpiTblAslParseInner(pThis); 686 AssertReturn(enmTerminal > RTACPIASLTERMINAL_INVALID && enmTerminal < RT_ELEMENTS(g_aAslKeywords), VERR_INTERNAL_ERROR); 687 688 *ppAstNd = NULL; 689 690 PCRTACPIASLKEYWORD pAslKeyword = &g_aAslKeywords[enmTerminal]; 691 PRTACPIASTNODE pAstNd = rtAcpiAstNodeAlloc(pAslKeyword->bOpc, pAslKeyword->fFlags, pAslKeyword->cArgsReq + pAslKeyword->cArgsOpt); 692 if (!pAstNd) 693 return RTErrInfoSetF(pThis->pErrInfo, VERR_NO_MEMORY, "Failed to allocate ACPI AST node when processing keyword '%s'", pAslKeyword->pszOpc); 694 695 *ppAstNd = pAstNd; 696 697 if (pAslKeyword->cArgsReq || pAslKeyword->cArgsOpt) 698 { 699 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_OPEN_BRACKET, '('); 700 701 /* Process any required arguments. */ 702 for (uint32_t i = 0; i < pAslKeyword->cArgsReq; i++) 703 { 704 rc = rtAcpiTblAslParseArgument(pThis, pAslKeyword->pszOpc, i, pAslKeyword->aenmTypes[i], &pAstNd->aArgs[i]); 705 if (RT_FAILURE(rc)) 706 return rc; 707 708 /* There must be a "," between required arguments, not counting the last required argument because it can be closed with ")". */ 709 if (i < pAslKeyword->cArgsReq - 1) 710 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_COMMA, ','); 711 } 712 713 /* Process any optional arguments, this is a bit ugly. */ 714 uint8_t iArg = 0; 715 while (iArg < pAslKeyword->cArgsOpt) 716 { 717 if (rtAcpiAslLexerIsPunctuator(pThis, RTACPIASLTERMINAL_PUNCTUATOR_CLOSE_BRACKET)) 718 break; /* The end of the argument list was reached. */ 719 720 /* 721 * It is possible to have empty arguments in the list by having nothing to parse between the "," or something like ",)" 722 * (like "Method(NAM, 0,,)" for example). 723 */ 724 if (rtAcpiAslLexerIsPunctuator(pThis, RTACPIASLTERMINAL_PUNCTUATOR_COMMA)) 725 { 726 RTACPIASL_SKIP_CURRENT_TOKEN(); /* Skip "," */ 727 728 /* 729 * If the next token is also a "," there is a hole in the argument list and we have to fill in the default, 730 * if it is ")" we reached the end. 731 */ 732 if (rtAcpiAslLexerIsPunctuator(pThis, RTACPIASLTERMINAL_PUNCTUATOR_CLOSE_BRACKET)) 733 break; 734 else if (rtAcpiAslLexerIsPunctuator(pThis, RTACPIASLTERMINAL_PUNCTUATOR_COMMA)) 735 { 736 pAstNd->aArgs[pAslKeyword->cArgsReq + iArg] = pAslKeyword->aArgsOpt[iArg]; 737 iArg++; 738 continue; /* Continue with the next argument. */ 739 } 740 741 /* So there is an argument we need to parse. */ 742 rc = rtAcpiTblAslParseArgument(pThis, pAslKeyword->pszOpc, iArg, pAslKeyword->aArgsOpt[iArg].enmType, &pAstNd->aArgs[pAslKeyword->cArgsReq + iArg]); 743 if (RT_FAILURE(rc)) 744 return rc; 745 746 iArg++; 747 } 748 } 749 750 /* Fill remaining optional arguments with the defaults. */ 751 for (; iArg < pAslKeyword->cArgsOpt; iArg++) 752 pAstNd->aArgs[pAslKeyword->cArgsReq + iArg] = pAslKeyword->aArgsOpt[iArg]; 753 754 /* Now there must be a closing ) */ 755 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_CLOSE_BRACKET, ')'); 756 } 757 758 /* For keywords opening a new scope do the parsing now. */ 759 if (pAslKeyword->fFlags & RTACPI_AST_NODE_F_NEW_SCOPE) 760 { 761 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_OPEN_CURLY_BRACKET, '{'); 762 rc = rtAcpiTblAslParseInner(pThis, &pAstNd->LstScopeNodes); 763 if (RT_SUCCESS(rc)) 495 764 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_CLOSE_CURLY_BRACKET, '}'); 496 break;497 }498 case RTACPIASLTERMINAL_KEYWORD_PROCESSOR:499 {500 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_OPEN_BRACKET, '(');501 RTACPIASL_PARSE_NAME_STRING(pszName);502 RT_NOREF(pszName);503 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_COMMA, ',');504 AssertFailed();505 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_CLOSE_BRACKET, ')');506 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_OPEN_CURLY_BRACKET, '{');507 rc = rtAcpiTblAslParseInner(pThis);508 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_CLOSE_CURLY_BRACKET, '}');509 break;510 }511 default:512 rc = RTErrInfoSetF(pThis->pErrInfo, VERR_INVALID_PARAMETER, "Parser: Unexpected keyword encountered");513 break;514 765 } 515 766 … … 518 769 519 770 520 static int rtAcpiTblAslParseInner(PRTACPIASLCU pThis )771 static int rtAcpiTblAslParseInner(PRTACPIASLCU pThis, PRTLISTANCHOR pLstStmts) 521 772 { 522 773 for (;;) … … 537 788 538 789 RTACPIASLTERMINAL enmKeyword = (RTACPIASLTERMINAL)pTok->Type.Keyword.pKeyword->u64Val; 539 RTScriptLexConsumeToken(pThis->hLexSource); 540 541 rc = rtAcpiTblAslParseTerminal(pThis, enmKeyword); 790 RTScriptLexConsumeToken(pThis->hLexSource); /* This must come here as rtAcpiTblAslParseTerminal() will continue parsing. */ 791 792 PRTACPIASTNODE pAstNd = NULL; 793 rc = rtAcpiTblAslParseTerminal(pThis, enmKeyword, &pAstNd); 542 794 if (RT_FAILURE(rc)) 795 { 796 if (pAstNd) 797 rtAcpiAstNodeFree(pAstNd); 543 798 return rc; 799 } 800 801 RTListAppend(pLstStmts, &pAstNd->NdAst); 544 802 } 545 803 } … … 596 854 { 597 855 RTACPIASL_PARSE_PUNCTUATOR(RTACPIASLTERMINAL_PUNCTUATOR_OPEN_CURLY_BRACKET, '{'); 598 rc = rtAcpiTblAslParseInner(pThis );856 rc = rtAcpiTblAslParseInner(pThis, &pThis->LstStmts); 599 857 if (RT_SUCCESS(rc)) 600 858 { … … 603 861 } 604 862 } 863 else 864 rc = RTErrInfoSetF(pThis->pErrInfo, rc, "Call to RTAcpiTblCreate() failed"); 605 865 606 866 return rc; … … 616 876 pThis->hVfsIosIn = hVfsIosIn; 617 877 pThis->pErrInfo = pErrInfo; 878 RTListInit(&pThis->LstStmts); 618 879 619 880 rc = RTScriptLexCreateFromReader(&pThis->hLexSource, rtAcpiAslLexerRead, … … 627 888 { 628 889 /* 2. - Optimize AST (constant folding, etc). */ 890 /** @todo */ 891 629 892 /* 3. - Traverse AST and output table. */ 630 RT_NOREF(hVfsIosOut); 893 PRTACPIASTNODE pIt; 894 RTListForEach(&pThis->LstStmts, pIt, RTACPIASTNODE, NdAst) 895 { 896 rc = rtAcpiAstDumpToTbl(pIt, pThis->hAcpiTbl); 897 if (RT_FAILURE(rc)) 898 break; 899 } 900 901 /* Finalize and write to the VFS I/O stream. */ 902 if (RT_SUCCESS(rc)) 903 { 904 rc = RTAcpiTblFinalize(pThis->hAcpiTbl); 905 if (RT_SUCCESS(rc)) 906 { 907 rc = RTAcpiTblDumpToVfsIoStrm(pThis->hAcpiTbl, RTACPITBLTYPE_AML, hVfsIosOut); 908 if (RT_FAILURE(rc)) 909 rc = RTErrInfoSetF(pErrInfo, rc, "Writing the ACPI table failed with %Rrc", rc); 910 } 911 else 912 rc = RTErrInfoSetF(pErrInfo, rc, "Finalizing the ACPI table failed with %Rrc", rc); 913 } 914 else 915 rc = RTErrInfoSetF(pErrInfo, rc, "Dumping AST to ACPI table failed with %Rrc", rc); 631 916 } 632 917 633 /** @todo Destroy AST. */634 918 RTScriptLexDestroy(pThis->hLexSource); 635 919 } … … 637 921 rc = RTErrInfoSetF(pErrInfo, rc, "Creating the ASL lexer failed with %Rrc", rc); 638 922 923 /* Destroy the AST nodes. */ 924 PRTACPIASTNODE pIt, pItNext; 925 RTListForEachSafe(&pThis->LstStmts, pIt, pItNext, RTACPIASTNODE, NdAst) 926 { 927 RTListNodeRemove(&pIt->NdAst); 928 rtAcpiAstNodeFree(pIt); 929 } 930 639 931 RTMemFree(pThis); 640 932 }
Note:
See TracChangeset
for help on using the changeset viewer.