Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2249 lines
43 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. parser.c
  5. Abstract:
  6. The aml parser
  7. Author:
  8. Michael Tsang
  9. Stephane Plante
  10. Environment:
  11. Any
  12. Revision History:
  13. --*/
  14. #include "pch.h"
  15. //
  16. // This is a dispatch table
  17. //
  18. typedef NTSTATUS (*PARSE_STATE_FUNCTION) (PSTACK *Stack);
  19. PARSE_STATE_FUNCTION ScopeStates[] = {
  20. ParseFunctionHandler,
  21. ParseArgument,
  22. ParseArgumentObject,
  23. ParseBuffer,
  24. ParseByte,
  25. ParseCodeObject,
  26. ParseConstObject,
  27. ParseData,
  28. ParseDelimiter,
  29. ParseDWord,
  30. ParseField,
  31. ParseLocalObject,
  32. ParseName,
  33. ParseNameObject,
  34. ParseOpcode,
  35. ParsePackage,
  36. ParsePop,
  37. ParsePush,
  38. ParseSuperName,
  39. ParseTrailingArgument,
  40. ParseTrailingBuffer,
  41. ParseTrailingPackage,
  42. ParseVariableObject,
  43. ParseWord
  44. };
  45. NTSTATUS
  46. ParseArgument(
  47. IN PSTACK *Stack
  48. )
  49. /*++
  50. Routine Description:
  51. This routine parses the arguments to a function
  52. Arguments:
  53. Stack - The stack for the current thread
  54. Return Value:
  55. NTSTATUS
  56. --*/
  57. {
  58. NTSTATUS status;
  59. PUNASM_AMLTERM amlTerm;
  60. PUNASM_SCOPE localScope;
  61. PUNASM_SCOPE rootScope;
  62. UCHAR action;
  63. ASSERT( Stack != NULL && *Stack != NULL);
  64. //
  65. // Step 1: Get the current scopes
  66. //
  67. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  68. //
  69. // Step 2: Check to see if we still need to process arguments?
  70. //
  71. amlTerm = localScope->AmlTerm;
  72. if ( localScope->Context1 == 0) {
  73. UCHAR actionList[2] = {
  74. SC_PARSE_ARGUMENT,
  75. SC_PARSE_DELIMITER
  76. };
  77. ULONG i;
  78. //
  79. // Step 2.1.1: Push an opening "(" onto the stack
  80. //
  81. StringStackPush( &(rootScope->StringStack), 1, "(" );
  82. //
  83. // Step 2.1.2: Make sure to call the thing to handle the trailing
  84. // argument
  85. //
  86. action = SC_PARSE_TRAILING_ARGUMENT;
  87. StringStackPush( &(rootScope->ParseStack), 1, &action );
  88. //
  89. // Step 2.1.3: This is the first that we have seen of the argument
  90. // Determine the number of bytes to process
  91. //
  92. localScope->Context2 = STRING_LENGTH( amlTerm->ArgumentTypes );
  93. //
  94. // Step 2.1.4: Setup the stack with the appropriate number of
  95. // calls to this function.
  96. //
  97. if (localScope->Context2 >= 2) {
  98. for (i = 0; i < localScope->Context2 - 1; i++) {
  99. StringStackPush( &(rootScope->ParseStack), 2, actionList );
  100. }
  101. }
  102. } else if ( localScope->Context1 >= localScope->Context2 ) {
  103. //
  104. // Step 2.2.1: BAD!!
  105. //
  106. return STATUS_UNSUCCESSFUL;
  107. }
  108. //
  109. // Step 3: Handle the current argument
  110. //
  111. switch( amlTerm->ArgumentTypes[ localScope->Context1 ] ) {
  112. case ARGTYPE_NAME:
  113. action = SC_PARSE_NAME;
  114. break;
  115. case ARGTYPE_DATAOBJECT:
  116. action = SC_PARSE_DATA;
  117. break;
  118. case ARGTYPE_WORD:
  119. action = SC_PARSE_WORD;
  120. break;
  121. case ARGTYPE_DWORD:
  122. action = SC_PARSE_DWORD;
  123. break;
  124. case ARGTYPE_BYTE:
  125. action = SC_PARSE_BYTE;
  126. break;
  127. case ARGTYPE_SUPERNAME:
  128. action = SC_PARSE_SUPER_NAME;
  129. break;
  130. case ARGTYPE_OPCODE: {
  131. UCHAR actionList[2] = {
  132. SC_PARSE_POP,
  133. SC_PARSE_OPCODE
  134. };
  135. //
  136. // Step 3.1: Increment the argument count
  137. //
  138. localScope->Context1++;
  139. //
  140. // Step 3.2: Set up what wee need next
  141. //
  142. StringStackPush( &(rootScope->ParseStack), 2, actionList );
  143. //
  144. // Step 3.3: Push a new scope
  145. //
  146. status = ParsePush( Stack );
  147. if (!NT_SUCCESS(status) ) {
  148. return status;
  149. }
  150. //
  151. // Step 3.4: Make sure to note that we are now nesting things
  152. //
  153. status = StackTop( Stack, &localScope );
  154. if (!NT_SUCCESS( status ) ) {
  155. return status;
  156. }
  157. localScope->Flags |= SC_FLAG_NESTED;
  158. //
  159. // Step 3.5: Done
  160. //
  161. return STATUS_SUCCESS;
  162. }
  163. default:
  164. return STATUS_INVALID_PARAMETER;
  165. }
  166. //
  167. // Step 4: Push the action onto the stack and setup for the next call
  168. //
  169. StringStackPush( &(rootScope->ParseStack), 1, &action );
  170. localScope->Context1++;
  171. //
  172. // Step 5: Done
  173. //
  174. return STATUS_SUCCESS;
  175. }
  176. NTSTATUS
  177. ParseArgumentObject(
  178. IN PSTACK *Stack
  179. )
  180. /*++
  181. Routine Description:
  182. This parses and executes the ArgX instruction
  183. Arguments:
  184. Stack - The stack for the current thread
  185. Return Value:
  186. NTSTATUS
  187. --*/
  188. {
  189. CHAR i;
  190. NTSTATUS status;
  191. PUNASM_SCOPE localScope;
  192. PUNASM_SCOPE rootScope;
  193. PSTRING_STACK *stringStack;
  194. UCHAR buffer[5];
  195. ASSERT( Stack != NULL && *Stack != NULL );
  196. //
  197. // Step 1: Grab the current and root scope
  198. //
  199. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  200. //
  201. // Step 2: Find the string stack to use
  202. //
  203. stringStack = &(rootScope->StringStack);
  204. //
  205. // Step 3: Determine which argument we are looking at
  206. //
  207. i = *(localScope->CurrentByte) - OP_ARG0;
  208. if (i < 0 || i > 7) {
  209. return STATUS_INVALID_PARAMETER;
  210. }
  211. //
  212. // Step 4: Show the argument number to the user
  213. //
  214. STRING_PRINT( buffer, "Arg%1d", i );
  215. StringStackPush( stringStack, 4, buffer );
  216. //
  217. // Step 5: Setup for next state
  218. //
  219. localScope->CurrentByte++;
  220. //
  221. // Step 6: Done
  222. //
  223. return STATUS_SUCCESS;
  224. }
  225. NTSTATUS
  226. ParseBuffer(
  227. IN PSTACK *Stack
  228. )
  229. /*++
  230. Routine Description:
  231. This routine handles buffers
  232. Arguments:
  233. Stack - The stack for the current thread
  234. Return Value:
  235. NTSTATUS;
  236. --*/
  237. {
  238. NTSTATUS status;
  239. PUNASM_SCOPE localScope;
  240. PUNASM_SCOPE rootScope;
  241. UCHAR actionList[2] = { SC_PARSE_BYTE, SC_PARSE_TRAILING_BUFFER };
  242. ULONG numBytes;
  243. ULONG i;
  244. //
  245. // Step 1: Grab the current scopes
  246. //
  247. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  248. //
  249. // Step 2: Determine the number of bytes that we have
  250. //
  251. numBytes = localScope->LastByte - localScope->CurrentByte + 1;
  252. if (numBytes) {
  253. //
  254. // Step 3: Push the leading delimiter
  255. //
  256. StringStackPush( &(rootScope->StringStack), 2, " {" );
  257. //
  258. // Step 4: This handles the last byte in the stream. We assume that
  259. // we have at least one byte otherwise we would not be here
  260. //
  261. StringStackPush( &(rootScope->ParseStack), 1, &(actionList[1]) );
  262. //
  263. // Make sure that we process the right number of bytes
  264. //
  265. actionList[1] = SC_PARSE_DELIMITER;
  266. if (numBytes > 1) {
  267. for (i = 0; i < numBytes - 1; i++) {
  268. StringStackPush( &(rootScope->ParseStack), 2, actionList );
  269. }
  270. }
  271. StringStackPush( &(rootScope->ParseStack),1, actionList );
  272. }
  273. //
  274. // Step 4: Done
  275. //
  276. return STATUS_SUCCESS;
  277. }
  278. NTSTATUS
  279. ParseByte(
  280. IN PSTACK *Stack
  281. )
  282. /*++
  283. Routine Description:
  284. This routine handles bytes
  285. Arguments:
  286. Stack - The stack for the current thread
  287. Return Value:
  288. NTSTATUS
  289. --*/
  290. {
  291. NTSTATUS status;
  292. PUNASM_SCOPE localScope;
  293. PUNASM_SCOPE rootScope;
  294. UCHAR localBuffer[6];
  295. ASSERT( Stack != NULL && *Stack != NULL );
  296. //
  297. // Step 1: Grab the current and root scope
  298. //
  299. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  300. //
  301. // Step 2: Build the string
  302. //
  303. STRING_PRINT( localBuffer, "0x%02x", *(localScope->CurrentByte) );
  304. //
  305. // Step 3: Move the instruction pointer as appropriate, and setup
  306. // for the next instructions
  307. //
  308. localScope->CurrentByte += 1;
  309. //
  310. // Step 4: Now push the byte onto the string stack
  311. //
  312. StringStackPush(
  313. &(rootScope->StringStack),
  314. STRING_LENGTH( localBuffer ),
  315. localBuffer
  316. );
  317. //
  318. // Step 5: Done
  319. //
  320. return status;
  321. }
  322. NTSTATUS
  323. ParseCodeObject(
  324. IN PSTACK *Stack
  325. )
  326. /*++
  327. Routine Description:
  328. This parses code
  329. Arguments:
  330. Stack - The stack for the current thread
  331. Return Value:
  332. NTSTATUS
  333. --*/
  334. {
  335. NTSTATUS status;
  336. PUNASM_SCOPE localScope;
  337. PUNASM_SCOPE rootScope;
  338. PSTRING_STACK *stringStack;
  339. UCHAR action;
  340. ULONG i;
  341. ULONG len;
  342. ASSERT( Stack != NULL && *Stack != NULL);
  343. //
  344. // Step 1: Grab the scope that we will process
  345. //
  346. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  347. //
  348. // Step 2: Push a token onto the string stack to present the term
  349. // name
  350. //
  351. StringStackPush(
  352. &(rootScope->StringStack),
  353. STRING_LENGTH( localScope->AmlTerm->TermName ),
  354. localScope->AmlTerm->TermName
  355. );
  356. //
  357. // Step 3: This is guaranteed to be called after all arguments are
  358. // parsed
  359. //
  360. action = SC_FUNCTION_HANDLER;
  361. StringStackPush( &(rootScope->ParseStack), 1, &action );
  362. //
  363. // Step 4: Determine if we have any arguments
  364. //
  365. if (localScope->AmlTerm->ArgumentTypes != NULL) {
  366. //
  367. // Step 4.1.1: Parse the Arguments
  368. //
  369. action = SC_PARSE_ARGUMENT;
  370. StringStackPush( &(rootScope->ParseStack), 1, &action );
  371. //
  372. // Step 4.1.2: Make sure to start the argument index at zero
  373. //
  374. localScope->Context1 = localScope->Context2 = 0;
  375. }
  376. //
  377. // Step 5: Done
  378. //
  379. return STATUS_SUCCESS;
  380. }
  381. NTSTATUS
  382. ParseConstObject(
  383. IN PSTACK *Stack
  384. )
  385. /*++
  386. Routine Description:
  387. This parses constants
  388. Arguments:
  389. Stack - The stack for the current thread
  390. Return Value:
  391. NTSTATUS
  392. --*/
  393. {
  394. NTSTATUS status;
  395. PUNASM_SCOPE localScope;
  396. PUNASM_SCOPE rootScope;
  397. PSTRING_STACK *stringStack;
  398. ASSERT( Stack != NULL && *Stack != NULL );
  399. //
  400. // Step 1: Grab the current and root scope
  401. //
  402. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  403. //
  404. // Step 2: Find the string stack to use
  405. //
  406. stringStack = &(rootScope->StringStack);
  407. //
  408. // Step 3: Action depends on what the current byte value is:
  409. //
  410. switch ( *(localScope->CurrentByte) ) {
  411. case OP_ZERO:
  412. StringStackPush( stringStack, 4, "Zero" );
  413. break;
  414. case OP_ONE:
  415. StringStackPush( stringStack, 3, "One" );
  416. break;
  417. case OP_ONES:
  418. StringStackPush( stringStack, 4, "Ones" );
  419. break;
  420. case OP_REVISION:
  421. StringStackPush( stringStack, 8, "Revision" );
  422. break;
  423. default:
  424. return STATUS_INVALID_PARAMETER;
  425. }
  426. //
  427. // Step 4: Done with the current byte
  428. //
  429. localScope->CurrentByte++;
  430. //
  431. // Step 5: Done
  432. //
  433. return status;
  434. }
  435. NTSTATUS
  436. ParseData(
  437. IN PSTACK *Stack
  438. )
  439. /*++
  440. Routine Description:
  441. This routine handles data arguments
  442. Arguments:
  443. Stack - The stack for the current thread
  444. Return Value:
  445. NTSTATUS
  446. --*/
  447. {
  448. NTSTATUS status;
  449. PUNASM_SCOPE localScope;
  450. PUNASM_SCOPE rootScope;
  451. UCHAR action;
  452. UCHAR currentDataType;
  453. ULONG i;
  454. ULONG num;
  455. ASSERT( Stack != NULL && *Stack != NULL );
  456. //
  457. // Step 1: Grab the current scopes
  458. //
  459. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  460. //
  461. // Step 2: Grab the current byte and decide what type of
  462. // data we are looking at based on that value
  463. //
  464. currentDataType = *(localScope->CurrentByte);
  465. localScope->CurrentByte++;
  466. switch( currentDataType ) {
  467. case OP_BYTE:
  468. action = SC_PARSE_BYTE;
  469. break;
  470. case OP_WORD:
  471. action = SC_PARSE_WORD;
  472. break;
  473. case OP_DWORD:
  474. action = SC_PARSE_DWORD;
  475. break;
  476. case OP_STRING:
  477. //
  478. // Step 2.2.1: Determine how long the string is
  479. //
  480. num = STRING_LENGTH( localScope->CurrentByte );
  481. //
  482. // Step 2.2.2: Push that number of bytes onto the string stack
  483. //
  484. StringStackPush( &(rootScope->StringStack), 1, "\"" );
  485. StringStackPush(
  486. &(rootScope->StringStack),
  487. num,
  488. localScope->CurrentByte
  489. );
  490. StringStackPush( &(rootScope->StringStack), 1, "\"" );
  491. //
  492. // Step 2.2.3: Update the current byte pointer and prepare for
  493. // next instructions
  494. //
  495. localScope->CurrentByte += (num + 1);
  496. //
  497. // Step 2.2.4: we don't have a next step, so we just return here
  498. //
  499. return STATUS_SUCCESS;
  500. case OP_BUFFER: {
  501. //
  502. // Step 2.1.1: This is an array of actions that we are about to
  503. // undertake. This reduces the number of calls to StringStackPush
  504. //
  505. UCHAR actionList[4] = {
  506. SC_PARSE_POP,
  507. SC_PARSE_BUFFER,
  508. SC_PARSE_OPCODE,
  509. SC_PARSE_VARIABLE_OBJECT
  510. };
  511. //
  512. // Step 2.1.2: Push this array onto the stack
  513. //
  514. StringStackPush( &(rootScope->ParseStack), 4, actionList );
  515. //
  516. // Step 2.1.3: Display a name
  517. //
  518. StringStackPush( &(rootScope->StringStack), 7, "Buffer=");
  519. //
  520. // Step 2.1.3: Done
  521. //
  522. return STATUS_SUCCESS;
  523. }
  524. case OP_PACKAGE: {
  525. //
  526. // Step 2.3.1: Array of instructions to execute
  527. //
  528. UCHAR actionList[3] = {
  529. SC_PARSE_POP,
  530. SC_PARSE_PACKAGE,
  531. SC_PARSE_VARIABLE_OBJECT
  532. };
  533. //
  534. // Step 2.3.2: Push those instructions onto the stack
  535. StringStackPush( &(rootScope->ParseStack), 3, actionList );
  536. //
  537. //
  538. // Step 2.3.3: Done
  539. //
  540. return STATUS_SUCCESS;
  541. }
  542. default:
  543. localScope->CurrentByte--;
  544. return STATUS_ILLEGAL_INSTRUCTION;
  545. } // switch
  546. //
  547. // Step 3: Push action onto the stack
  548. //
  549. StringStackPush( &(rootScope->ParseStack), 1, &action);
  550. //
  551. // Step 4: done
  552. //
  553. return STATUS_SUCCESS;
  554. }
  555. NTSTATUS
  556. ParseDelimiter(
  557. IN PSTACK *Stack
  558. )
  559. /*--
  560. Routine Description:
  561. This routine is between elements. It is responsible for adding commas
  562. on the string stack
  563. Arguments:
  564. Stack - The current thread of execution
  565. Return Value:
  566. NTSTATUS
  567. --*/
  568. {
  569. NTSTATUS status;
  570. PUNASM_SCOPE rootScope;
  571. //
  572. // Step 1: Get the scope
  573. //
  574. status = StackRoot( Stack, &rootScope );
  575. if (!NT_SUCCESS(status)) {
  576. return status;
  577. }
  578. //
  579. // Step 2: Push the trailer
  580. //
  581. StringStackPush( &(rootScope->StringStack), 1, "," );
  582. //
  583. // Step 3: Done
  584. //
  585. return status;
  586. }
  587. NTSTATUS
  588. ParseDWord(
  589. IN PSTACK *Stack
  590. )
  591. /*++
  592. Routine Description:
  593. This routine handles double words
  594. Arguments:
  595. Stack - The stack for the current thread
  596. Return Value:
  597. NTSTATUS
  598. --*/
  599. {
  600. NTSTATUS status;
  601. PUNASM_SCOPE localScope;
  602. PUNASM_SCOPE rootScope;
  603. UCHAR localBuffer[12];
  604. ASSERT( Stack != NULL && *Stack != NULL );
  605. //
  606. // Step 1: Grab the current and root scope
  607. //
  608. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  609. //
  610. // Step 2: Build the string
  611. //
  612. STRING_PRINT( localBuffer, "0x%08x", *((PULONG)localScope->CurrentByte));
  613. //
  614. // Step 3: Move the instruction pointer as appropriate, and setup
  615. // for the next instructions
  616. //
  617. localScope->CurrentByte += 4;
  618. //
  619. // Step 4: Now push the byte onto the string stack
  620. //
  621. StringStackPush(
  622. &(rootScope->StringStack),
  623. STRING_LENGTH( localBuffer ),
  624. localBuffer
  625. );
  626. //
  627. // Step 5: Done
  628. //
  629. return status;
  630. }
  631. NTSTATUS
  632. ParseField(
  633. IN PSTACK *Stack
  634. )
  635. /*++
  636. Routine Description:
  637. This is the code that actually parses a field
  638. Arguments:
  639. The current thread's stack
  640. Return Value:
  641. None:
  642. --*/
  643. {
  644. NTSTATUS status;
  645. PUNASM_SCOPE localScope;
  646. PUNASM_SCOPE rootScope;
  647. UCHAR action;
  648. UCHAR followBits;
  649. UCHAR i;
  650. UCHAR buffer[32];
  651. ULONG size;
  652. //
  653. // Step 1: Grab the current scopes
  654. //
  655. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  656. //
  657. // Step 2: Make sure that we still have some room to work with
  658. //
  659. if (localScope->CurrentByte > localScope->LastByte) {
  660. return STATUS_SUCCESS;
  661. }
  662. //
  663. // Step 3: This is the first byte in something that we will print out
  664. // And lets increment the count so that we have an idea of how many
  665. // items we have processed
  666. //
  667. localScope->TermByte = localScope->CurrentByte;
  668. localScope->Context1 += 1;
  669. //
  670. // Step 4: Action depends on current byte
  671. //
  672. if ( *(localScope->CurrentByte) == 0x01) {
  673. UCHAR b1;
  674. UCHAR b2;
  675. //
  676. // Step 4.1.1: Get the two bytes that we are going to use
  677. //
  678. localScope->CurrentByte++;
  679. b1 = *(localScope->CurrentByte++);
  680. b2 = *(localScope->CurrentByte++);
  681. //
  682. // Step 4.1.2: Make the string
  683. //
  684. STRING_PRINT( buffer,"AccessAs: (0x%2x,0x%2x)\n", b1, b2 );
  685. //
  686. // Step 4.1.3: Dump this to the string stack
  687. //
  688. StringStackPush(
  689. &(rootScope->StringStack),
  690. STRING_LENGTH( buffer ),
  691. buffer
  692. );
  693. } else {
  694. //
  695. // Step 4.2.1: Otherwise we have an encoded name
  696. //
  697. if ( *(localScope->CurrentByte) == 0x00 ) {
  698. StringStackPush(
  699. &(rootScope->StringStack),
  700. 10,
  701. "(Reserved)"
  702. );
  703. localScope->CurrentByte++;
  704. } else {
  705. StringStackPush(
  706. &(rootScope->StringStack),
  707. sizeof(NAMESEG),
  708. localScope->CurrentByte
  709. );
  710. localScope->CurrentByte += sizeof(NAMESEG);
  711. }
  712. //
  713. // Step 4.2.2: Dump a seperator
  714. //
  715. StringStackPush(
  716. &(rootScope->StringStack),
  717. 4,
  718. ": 0x"
  719. );
  720. //
  721. // Step 4.2.3: Calculate the size of the field
  722. //
  723. size = (ULONG) *(localScope->CurrentByte);
  724. localScope->CurrentByte++;
  725. followBits = (UCHAR) ( (size & 0xc0) >> 6);
  726. if (followBits) {
  727. size &= 0xf;
  728. for (i = 0; i < followBits; i++) {
  729. size |= (ULONG) *(localScope->CurrentByte) << (i * 8 + 4);
  730. localScope->CurrentByte++;
  731. }
  732. }
  733. //
  734. // Step 4.2.4: Dump a string that is correspondent to the size
  735. // of the number
  736. //
  737. STRING_PRINT( buffer,"%x", size );
  738. //
  739. // Step 4.2.5: Dump the length of the thing
  740. //
  741. StringStackPush(
  742. &(rootScope->StringStack),
  743. STRING_LENGTH( buffer ),
  744. buffer
  745. );
  746. //
  747. // Step 5.4: Print the string out
  748. //
  749. StringStackPush( &(rootScope->StringStack), 1, "\n" );
  750. }
  751. //
  752. // Step 5: Dump the string we generated
  753. //
  754. ScopePrint( Stack );
  755. //
  756. // Step 6: If there are still more thing to processe, we should
  757. // call this function again
  758. //
  759. if (localScope->CurrentByte <= localScope->LastByte) {
  760. action = SC_PARSE_FIELD;
  761. StringStackPush( &(rootScope->ParseStack), 1, &action );
  762. }
  763. //
  764. // Step 7: Done
  765. //
  766. return STATUS_SUCCESS;
  767. }
  768. NTSTATUS
  769. ParseFunctionHandler(
  770. IN PSTACK *Stack
  771. )
  772. /*++
  773. Routine Description:
  774. This code is actually something that transfers control to the term
  775. specific handler
  776. Arguments:
  777. The current thread's stack
  778. Return Value:
  779. None
  780. --*/
  781. {
  782. NTSTATUS status;
  783. PUNASM_SCOPE localScope;
  784. PUNASM_SCOPE rootScope;
  785. //
  786. // Step 1: Grab the current scopes
  787. //
  788. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  789. //
  790. // Step 2: Check to see if we are at the end of the current nest
  791. //
  792. if (!(localScope->Flags & SC_FLAG_NESTED) ) {
  793. //
  794. // Step 2.1: Dump the string
  795. //
  796. StringStackPush( &(rootScope->StringStack), 2, "\n" );
  797. ScopePrint( Stack );
  798. }
  799. //
  800. // Step 4: Call the function handler if there is one
  801. //
  802. if ( localScope->AmlTerm->FunctionHandler != NULL) {
  803. status = (localScope->AmlTerm->FunctionHandler)( Stack );
  804. }
  805. //
  806. // Step 5: Done
  807. //
  808. return status;
  809. }
  810. NTSTATUS
  811. ParseLocalObject(
  812. IN PSTACK *Stack
  813. )
  814. /*++
  815. Routine Description:
  816. This routine handles the LocalX instruction
  817. Arguments:
  818. Stack - The stack for the current thread
  819. Return Value:
  820. NTSTATUS
  821. --*/
  822. {
  823. CHAR i;
  824. NTSTATUS status;
  825. PUNASM_SCOPE localScope;
  826. PUNASM_SCOPE rootScope;
  827. UCHAR buffer[7];
  828. ASSERT( Stack != NULL && *Stack != NULL );
  829. //
  830. // Step 1: Grab the current and root scope
  831. //
  832. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  833. //
  834. // Step 2: Which local are we talking about
  835. //
  836. i = *(localScope->CurrentByte) - OP_LOCAL0;
  837. if ( i < 0 || i > 7) {
  838. return STATUS_INVALID_PARAMETER;
  839. }
  840. //
  841. // Step 3: Display this to the user
  842. //
  843. STRING_PRINT( buffer, "Local%1d", i );
  844. StringStackPush( &(rootScope->StringStack), 6, buffer );
  845. //
  846. // Step 4: Setup for next state
  847. //
  848. localScope->CurrentByte++;
  849. //
  850. // Step 5: Done
  851. //
  852. return status;
  853. }
  854. NTSTATUS
  855. ParseName(
  856. IN PSTACK *Stack
  857. )
  858. /*++
  859. Routine Description:
  860. This routine handles generating the argument name
  861. Arguments:
  862. Stack - The Stack for the current thread
  863. Return Value:
  864. NTSTATUS
  865. --*/
  866. {
  867. NTSTATUS status;
  868. PUNASM_SCOPE localScope;
  869. PUNASM_SCOPE rootScope;
  870. PSTRING_STACK *stringStack;
  871. ULONG nameSegmentCount = 1;
  872. ASSERT( Stack != NULL && *Stack != NULL );
  873. //
  874. // Step 1: Grab the current and local scope
  875. //
  876. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  877. //
  878. // Step 2: Delimit the String
  879. //
  880. stringStack = &(rootScope->StringStack);
  881. StringStackPush( stringStack, 1, "\"");
  882. //
  883. // Step 3: Action depends on what the current byte value is:
  884. //
  885. switch ( *(localScope->CurrentByte) ) {
  886. case OP_ROOT_PREFIX:
  887. StringStackPush( stringStack, 1, "\\" );
  888. localScope->CurrentByte++;
  889. break;
  890. case OP_PARENT_PREFIX:
  891. while ( *(localScope->CurrentByte) == OP_PARENT_PREFIX ) {
  892. StringStackPush( stringStack, 1, "^" );
  893. localScope->CurrentByte++;
  894. }
  895. break;
  896. }
  897. //
  898. // Step 4: Determine the number of Name segments we are adding
  899. //
  900. switch ( *(localScope->CurrentByte) ) {
  901. case '\0':
  902. nameSegmentCount = 0;
  903. localScope->CurrentByte++;
  904. break;
  905. case OP_MULTI_NAME_PREFIX:
  906. //
  907. // The next byte contains the number of name segments
  908. //
  909. localScope->CurrentByte++;
  910. nameSegmentCount = (ULONG) *(localScope->CurrentByte);
  911. localScope->CurrentByte++;
  912. break;
  913. case OP_DUAL_NAME_PREFIX:
  914. //
  915. // There are two name segments
  916. //
  917. nameSegmentCount = 2;
  918. localScope->CurrentByte++;
  919. break;
  920. }
  921. //
  922. // Step 5: Push the name segments onto the stack
  923. //
  924. while (nameSegmentCount > 0) {
  925. //
  926. // Step 5.1 Add the segment onto the stack
  927. //
  928. StringStackPush(
  929. stringStack,
  930. sizeof( NAMESEG ),
  931. localScope->CurrentByte
  932. );
  933. //
  934. // Step 5.2: Decrement the number of remaining segments and
  935. // move the current byte pointer to point to the next
  936. // interesting thing
  937. //
  938. nameSegmentCount--;
  939. localScope->CurrentByte += sizeof(NAMESEG);
  940. //
  941. // Step 5.3: Check to see if we should add a seperator
  942. //
  943. if (nameSegmentCount) {
  944. StringStackPush( stringStack, 1, "." );
  945. }
  946. }
  947. //
  948. // Step 6: Push the closing delimiter
  949. //
  950. StringStackPush( stringStack, 1, "\"" );
  951. //
  952. // Step 7: done
  953. //
  954. return STATUS_SUCCESS;
  955. }
  956. NTSTATUS
  957. ParseNameObject(
  958. IN PSTACK *Stack
  959. )
  960. /*++
  961. Routine Description:
  962. This routine handles name objects
  963. Arguments:
  964. Stack - The stack for the current thread
  965. Return Value:
  966. NTSTATUS
  967. --*/
  968. {
  969. //
  970. // Note: at this time, this function is just a wrapper for
  971. // ParseName(). If that was an assembler, it would have to execute
  972. // something here
  973. //
  974. return ParseName( Stack );
  975. }
  976. NTSTATUS
  977. ParseOpcode(
  978. IN PSTACK *Stack
  979. )
  980. /*++
  981. Routine Description:
  982. This routine is the main parsing point for AML opcode
  983. Arguments:
  984. Stack - The stack for the current thread
  985. Return Value:
  986. NTSTATUS
  987. --*/
  988. {
  989. NTSTATUS status;
  990. PUNASM_AMLTERM amlTerm;
  991. PUNASM_SCOPE localScope;
  992. PUNASM_SCOPE rootScope;
  993. UCHAR action;
  994. ULONG termGroup;
  995. ASSERT( Stack != NULL && *Stack != NULL );
  996. //
  997. // Step 1: Grab the current scopes
  998. //
  999. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  1000. //
  1001. // Step 2: Check to see if we are past the end byte?
  1002. //
  1003. if (localScope->CurrentByte > localScope->LastByte) {
  1004. return STATUS_SUCCESS;
  1005. }
  1006. //
  1007. // Step 3: Remember which byte demarked the start of the
  1008. // instruction
  1009. //
  1010. localScope->TermByte = localScope->CurrentByte;
  1011. //
  1012. // Step 4: Check to see if this is an extended instruction
  1013. //
  1014. if ( *(localScope->CurrentByte) == OP_EXT_PREFIX) {
  1015. //
  1016. // Step 4.1.1: Extended opcode. Next instruction will let us find the
  1017. // AML term to use for the evaluation
  1018. //
  1019. localScope->CurrentByte++;
  1020. //
  1021. // Step 4.1.2: Grab the AML term for the extended operation
  1022. //
  1023. amlTerm = localScope->AmlTerm = ScopeFindExtendedOpcode( Stack );
  1024. } else {
  1025. //
  1026. // Step 4.2.1: Grab the AML term for the current operation
  1027. //
  1028. amlTerm = localScope->AmlTerm =
  1029. OpcodeTable[ *(localScope->CurrentByte) ];
  1030. }
  1031. localScope->Context1 = localScope->Context2 = 0;
  1032. //
  1033. // Step 5: Check to see if we have a valid AML term
  1034. //
  1035. if (localScope->AmlTerm == NULL) {
  1036. return STATUS_UNSUCCESSFUL;
  1037. }
  1038. //
  1039. // Step 6: Farm out the real work to functions that are better capable
  1040. // of handling the current AML term
  1041. //
  1042. termGroup = (amlTerm->OpCodeFlags & 0xFF);
  1043. switch( termGroup ) {
  1044. case OF_NORMAL_OBJECT:
  1045. case OF_VARIABLE_LIST:
  1046. case OF_REF_OBJECT:
  1047. //
  1048. // Step 6.1: If we are going to handle a variable length instruction
  1049. // than we must also pop it from the stack
  1050. //
  1051. if (amlTerm->OpCodeFlags == OF_VARIABLE_LIST) {
  1052. UCHAR actionList[5] = {
  1053. SC_PARSE_OPCODE,
  1054. SC_PARSE_POP,
  1055. SC_PARSE_OPCODE,
  1056. SC_PARSE_CODE_OBJECT,
  1057. SC_PARSE_VARIABLE_OBJECT
  1058. };
  1059. StringStackPush( &(rootScope->ParseStack), 5, actionList );
  1060. } else {
  1061. //
  1062. // If we are already nested, we know that there is an ParseOpcode
  1063. // just waiting for us...
  1064. //
  1065. if (!(localScope->Flags & SC_FLAG_NESTED)) {
  1066. action = SC_PARSE_OPCODE;
  1067. StringStackPush( &(rootScope->ParseStack), 1, &action);
  1068. }
  1069. action = SC_PARSE_CODE_OBJECT;
  1070. StringStackPush( &(rootScope->ParseStack), 1, &action);
  1071. }
  1072. //
  1073. // Step 6.2: This is a code byte. Ergo we eat it since we just
  1074. // processed it
  1075. //
  1076. localScope->CurrentByte++;
  1077. //
  1078. // Step 6.3: Done
  1079. //
  1080. return STATUS_SUCCESS;
  1081. case OF_NAME_OBJECT:
  1082. action = SC_PARSE_NAME_OBJECT;
  1083. break;
  1084. case OF_DATA_OBJECT:
  1085. action = SC_PARSE_DATA;
  1086. break;
  1087. case OF_CONST_OBJECT:
  1088. action = SC_PARSE_CONST_OBJECT;
  1089. break;
  1090. case OF_ARG_OBJECT:
  1091. action = SC_PARSE_ARGUMENT_OBJECT;
  1092. break;
  1093. case OF_LOCAL_OBJECT:
  1094. action = SC_PARSE_LOCAL_OBJECT;
  1095. break;
  1096. default:
  1097. return STATUS_NOT_SUPPORTED;
  1098. }
  1099. //
  1100. // Step 7: Actually push the action to execute next on to the stack
  1101. //
  1102. StringStackPush( &(rootScope->ParseStack), 1, &action );
  1103. //
  1104. // Step 8: Done
  1105. //
  1106. return STATUS_SUCCESS;
  1107. }
  1108. NTSTATUS
  1109. ParsePackage(
  1110. IN PSTACK *Stack
  1111. )
  1112. /*++
  1113. Routine Description:
  1114. This routine parses the stages of a package
  1115. Arguments:
  1116. The current thread's stack
  1117. Note: Caller needs to push a stack location before calling this and they
  1118. have to pop it when it finishes
  1119. Return Value:
  1120. NTSTATUS:
  1121. --*/
  1122. {
  1123. NTSTATUS status;
  1124. PUNASM_SCOPE localScope;
  1125. PUNASM_SCOPE rootScope;
  1126. UCHAR action;
  1127. //
  1128. // Step 1: Grab the current scopes
  1129. //
  1130. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  1131. //
  1132. // Step 2: Context1 is the current index in the package...
  1133. //
  1134. if (localScope->Context1 == 0) {
  1135. UCHAR actionList[2] = {
  1136. SC_PARSE_PACKAGE,
  1137. SC_PARSE_DELIMITER
  1138. };
  1139. ULONG i;
  1140. //
  1141. // Step 2.1.1: This is the first call to parse package...
  1142. // What we need to do here is handle the first argument here,
  1143. // and make sure that we get called again for the remaining
  1144. // arguments
  1145. //
  1146. StringStackPush( &(rootScope->StringStack), 1, "[" );
  1147. //
  1148. // Step 2.1.2: This byte contains the number of arguments to handle
  1149. //
  1150. localScope->Context2 = *(localScope->CurrentByte);
  1151. localScope->CurrentByte++;
  1152. //
  1153. // Step 2.1.3: Make sure that we close that bracket above
  1154. //
  1155. action = SC_PARSE_TRAILING_PACKAGE;
  1156. StringStackPush( &(rootScope->ParseStack), 1, &action );
  1157. //
  1158. // Step 2.1.3: Setup all the remaining calls to this function
  1159. //
  1160. if (localScope->Context2 >= 2) {
  1161. for (i=0; i < localScope->Context2 - 1; i++) {
  1162. StringStackPush( &(rootScope->ParseStack), 2, actionList );
  1163. }
  1164. }
  1165. } else if (localScope->Context1 >= localScope->Context2) {
  1166. //
  1167. // Step 2.2.1: We are at the end of the package
  1168. //
  1169. return STATUS_UNSUCCESSFUL;
  1170. }
  1171. //
  1172. // Step 3: Farm out the work depending on what the current byte is
  1173. // This looks a lot like ParseData, but note the new default case
  1174. //
  1175. switch ( *(localScope->CurrentByte) ) {
  1176. case OP_BYTE:
  1177. case OP_WORD:
  1178. case OP_DWORD:
  1179. case OP_BUFFER:
  1180. case OP_STRING:
  1181. case OP_PACKAGE:
  1182. action = SC_PARSE_DATA;
  1183. break;
  1184. default:
  1185. action = SC_PARSE_NAME;
  1186. }
  1187. //
  1188. // Step 4: Push the next action onto the stack
  1189. //
  1190. StringStackPush( &(rootScope->ParseStack), 1, &action );
  1191. localScope->Context1++;
  1192. //
  1193. // Step 5: done
  1194. //
  1195. return STATUS_SUCCESS;
  1196. }
  1197. NTSTATUS
  1198. ParsePop(
  1199. IN PSTACK *Stack
  1200. )
  1201. /*++
  1202. Routine Description:
  1203. This routine removes the top level of the stack and updates the
  1204. current byte as appropriate
  1205. Arguments:
  1206. The current thread's stack
  1207. Return Value:
  1208. NTSTATUS
  1209. --*/
  1210. {
  1211. NTSTATUS status;
  1212. PUNASM_SCOPE topScope;
  1213. PUNASM_SCOPE prevScope;
  1214. //
  1215. // Step 1: Get the top scope
  1216. //
  1217. status = StackTop( Stack, &topScope );
  1218. if (!NT_SUCCESS(status)) {
  1219. return status;
  1220. }
  1221. //
  1222. // Step 2: Get the previous scope
  1223. //
  1224. status = StackParent( Stack, topScope, &prevScope );
  1225. if (!NT_SUCCESS(status)) {
  1226. //
  1227. // Step 2.1: There is actually no parent to this function ...
  1228. // Just pop the top and return
  1229. //
  1230. return StackPop( Stack );
  1231. }
  1232. //
  1233. // Step 3: Make sure to update the prevScope's current byte
  1234. //
  1235. if (topScope->CurrentByte > prevScope->CurrentByte) {
  1236. prevScope->CurrentByte = topScope->CurrentByte;
  1237. }
  1238. //
  1239. // Step 4: Pop the top stack and return
  1240. //
  1241. return StackPop( Stack );
  1242. }
  1243. NTSTATUS
  1244. ParsePush(
  1245. IN PSTACK *Stack
  1246. )
  1247. /*++
  1248. Routine Description:
  1249. This routine handles adding a level to the stack
  1250. Arguments:
  1251. The thread's current stack
  1252. Return Value:
  1253. NTSTATUS
  1254. --*/
  1255. {
  1256. NTSTATUS status;
  1257. PUNASM_SCOPE curScope;
  1258. PUNASM_SCOPE newScope;
  1259. //
  1260. // Step 1: Create a new scope on the stack
  1261. //
  1262. status = StackPush( Stack, &newScope );
  1263. if (!NT_SUCCESS(status)) {
  1264. return status;
  1265. }
  1266. //
  1267. // Step 2: Grab the parent from the stack
  1268. //
  1269. status = StackParent( Stack, newScope, &curScope );
  1270. if (!NT_SUCCESS(status)) {
  1271. return status;
  1272. }
  1273. //
  1274. // Step 3: Copy the important values
  1275. //
  1276. newScope->CurrentByte = curScope->CurrentByte;
  1277. newScope->TermByte = curScope->TermByte;
  1278. newScope->LastByte = curScope->LastByte;
  1279. newScope->StringStack = curScope->StringStack;
  1280. newScope->IndentLevel = curScope->IndentLevel;
  1281. newScope->AmlTerm = curScope->AmlTerm;
  1282. newScope->Flags = curScope->Flags;
  1283. //
  1284. // Step 4: Done
  1285. //
  1286. return STATUS_SUCCESS;
  1287. }
  1288. NTSTATUS
  1289. ParseScope(
  1290. IN PSTACK *Stack
  1291. )
  1292. /*++
  1293. Routine Description:
  1294. This routine handles super names
  1295. Arguments:
  1296. Stack - The current thread of execution
  1297. Return Value:
  1298. NTSTATUS
  1299. --*/
  1300. {
  1301. NTSTATUS status;
  1302. PUNASM_SCOPE localScope;
  1303. PUNASM_SCOPE rootScope;
  1304. PUCHAR action;
  1305. UCHAR defAction = SC_PARSE_OPCODE;
  1306. ASSERT( Stack != NULL && *Stack != NULL);
  1307. //
  1308. // Step 1: Loop forever
  1309. //
  1310. while (1) {
  1311. //
  1312. // Step 2: Get the top of stack, and while it exits, process
  1313. // the current operation
  1314. //
  1315. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  1316. //
  1317. // Step 3: We are done if we are in the root scope and the
  1318. // current byte exceeds the last byte
  1319. //
  1320. if (localScope == rootScope &&
  1321. localScope->CurrentByte > localScope->LastByte) {
  1322. //
  1323. // Step 3.1 Done!
  1324. //
  1325. return STATUS_SUCCESS;
  1326. }
  1327. //
  1328. // Step 4: Fetch thing to execute
  1329. //
  1330. status = StringStackPop( &(rootScope->ParseStack), 1, &action );
  1331. if (!NT_SUCCESS(status)) {
  1332. //
  1333. // Step 4.1.1: This is fixed in the look up table
  1334. //
  1335. status = (ScopeStates[ SC_PARSE_OPCODE ])( Stack );
  1336. } else {
  1337. //
  1338. // Step 4.1.2: Determine what to execute
  1339. //
  1340. ASSERT( *action <= SC_MAX_TABLE );
  1341. status = (ScopeStates[ *action ])( Stack );
  1342. }
  1343. if (!NT_SUCCESS(status)) {
  1344. break;
  1345. }
  1346. }
  1347. //
  1348. // Step 5: Show the user the error
  1349. //
  1350. PRINTF("Error Code: %x\n", status );
  1351. return status;
  1352. }
  1353. NTSTATUS
  1354. ParseSuperName(
  1355. IN PSTACK *Stack
  1356. )
  1357. /*++
  1358. Routine Description:
  1359. This routine handles super names
  1360. Arguments:
  1361. Stack - The current thread of execution
  1362. Return Value:
  1363. NTSTATUS
  1364. --*/
  1365. {
  1366. NTSTATUS status;
  1367. PUNASM_AMLTERM amlTerm;
  1368. PUNASM_SCOPE localScope;
  1369. PUNASM_SCOPE rootScope;
  1370. UCHAR action;
  1371. ASSERT( Stack != NULL && *Stack != NULL);
  1372. //
  1373. // Step 1: Get the scopes
  1374. //
  1375. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  1376. //
  1377. // Step 2: What we do next depend on the current byte
  1378. //
  1379. if ( *(localScope->CurrentByte) == 0) {
  1380. //
  1381. // Unknown
  1382. //
  1383. localScope->CurrentByte++;
  1384. return STATUS_SUCCESS;
  1385. } else if ( *(localScope->CurrentByte) == OP_EXT_PREFIX &&
  1386. *(localScope->CurrentByte + 1) == EXOP_DEBUG) {
  1387. //
  1388. // Debug Object
  1389. //
  1390. localScope->CurrentByte += 2;
  1391. return STATUS_SUCCESS;
  1392. } else if ( OpcodeTable[ *(localScope->CurrentByte) ] == NULL) {
  1393. return STATUS_INVALID_PARAMETER;
  1394. }
  1395. //
  1396. // Step 3: Now, our action depends on the current AML Term
  1397. //
  1398. amlTerm = OpcodeTable[ *(localScope->CurrentByte) ];
  1399. if ( amlTerm->OpCodeFlags == OF_NAME_OBJECT) {
  1400. //
  1401. // We have a name to parse
  1402. //
  1403. action = SC_PARSE_NAME;
  1404. } else if ( amlTerm->OpCodeFlags == OF_ARG_OBJECT) {
  1405. //
  1406. // We have an argument to parse
  1407. //
  1408. action = SC_PARSE_ARGUMENT_OBJECT;
  1409. } else if ( amlTerm->OpCodeFlags == OF_LOCAL_OBJECT) {
  1410. //
  1411. // We have a local object...
  1412. //
  1413. action = SC_PARSE_LOCAL_OBJECT;
  1414. } else if ( amlTerm->OpCodeFlags == OF_REF_OBJECT) {
  1415. UCHAR actionList[3] = {
  1416. SC_PARSE_OPCODE,
  1417. SC_PARSE_POP,
  1418. SC_PARSE_OPCODE
  1419. };
  1420. //
  1421. // Step 3.1: Set up the initial task of the new scope
  1422. //
  1423. StringStackPush( &(rootScope->ParseStack), 3, actionList );
  1424. //
  1425. // Step 3.2: Push a new scope
  1426. //
  1427. status = ParsePush( Stack );
  1428. if (!NT_SUCCESS(status) ) {
  1429. return status;
  1430. }
  1431. //
  1432. // Step 3.3: Done
  1433. //
  1434. return STATUS_SUCCESS;
  1435. } else {
  1436. return STATUS_INVALID_PARAMETER;
  1437. }
  1438. //
  1439. // Step 4: Push the action onto the stack
  1440. //
  1441. StringStackPush( &(rootScope->ParseStack), 1, &action );
  1442. //
  1443. // Step 5: Done
  1444. //
  1445. return STATUS_SUCCESS;
  1446. }
  1447. NTSTATUS
  1448. ParseTrailingArgument(
  1449. IN PSTACK *Stack
  1450. )
  1451. /*--
  1452. Routine Description:
  1453. This routine is run at after all arguments are parsed. It is responsible
  1454. for placing a trailing parentheses on the string stack
  1455. Arguments:
  1456. Stack - The current thread of execution
  1457. Return Value:
  1458. NTSTATUS
  1459. --*/
  1460. {
  1461. NTSTATUS status;
  1462. PUNASM_SCOPE rootScope;
  1463. //
  1464. // Step 1: Get the scope
  1465. //
  1466. status = StackRoot( Stack, &rootScope );
  1467. if (!NT_SUCCESS(status)) {
  1468. return status;
  1469. }
  1470. //
  1471. // Step 2: Push the trailer
  1472. //
  1473. StringStackPush( &(rootScope->StringStack), 1, ")" );
  1474. //
  1475. // Step 3: Done
  1476. //
  1477. return status;
  1478. }
  1479. NTSTATUS
  1480. ParseTrailingBuffer(
  1481. IN PSTACK *Stack
  1482. )
  1483. /*--
  1484. Routine Description:
  1485. This routine is run at after the buffer is parsed. It is responsible
  1486. for placing a trailing curly brace on the string stack
  1487. Arguments:
  1488. Stack - The current thread of execution
  1489. Return Value:
  1490. NTSTATUS
  1491. --*/
  1492. {
  1493. NTSTATUS status;
  1494. PUNASM_SCOPE rootScope;
  1495. //
  1496. // Step 1: Get the scope
  1497. //
  1498. status = StackRoot( Stack, &rootScope );
  1499. if (!NT_SUCCESS(status)) {
  1500. return status;
  1501. }
  1502. //
  1503. // Step 2: Push the trailer
  1504. //
  1505. StringStackPush( &(rootScope->StringStack), 1, "}" );
  1506. //
  1507. // Step 3: Done
  1508. //
  1509. return status;
  1510. }
  1511. NTSTATUS
  1512. ParseTrailingPackage(
  1513. IN PSTACK *Stack
  1514. )
  1515. /*--
  1516. Routine Description:
  1517. This routine is run at after all elements are parsed. It is responsible
  1518. for placing a trailing brace on the string stack
  1519. Arguments:
  1520. Stack - The current thread of execution
  1521. Return Value:
  1522. NTSTATUS
  1523. --*/
  1524. {
  1525. NTSTATUS status;
  1526. PUNASM_SCOPE rootScope;
  1527. //
  1528. // Step 1: Get the scope
  1529. //
  1530. status = StackRoot( Stack, &rootScope );
  1531. if (!NT_SUCCESS(status)) {
  1532. return status;
  1533. }
  1534. //
  1535. // Step 2: Push the trailer
  1536. //
  1537. StringStackPush( &(rootScope->StringStack), 1, "]" );
  1538. //
  1539. // Step 3: Done
  1540. //
  1541. return status;
  1542. }
  1543. NTSTATUS
  1544. ParseVariableObject(
  1545. IN PSTACK *Stack
  1546. )
  1547. /*++
  1548. Routine Description:
  1549. This routine creates another scope level on the stack to process the
  1550. current variable length instruction. It modifies the current scope
  1551. to (correctly) point to the next instruction
  1552. Note: Callers of this function are expected to pop off the stack
  1553. when it is no longer required!!!
  1554. Arguments:
  1555. Stack - The current thread of execution
  1556. Return Value:
  1557. NTSTATUS
  1558. --*/
  1559. {
  1560. NTSTATUS status;
  1561. PUNASM_SCOPE newScope;
  1562. PUNASM_SCOPE oldScope;
  1563. PUCHAR nextOpcode;
  1564. UCHAR i;
  1565. UCHAR lengthBytes;
  1566. ULONG packageLength;
  1567. ASSERT( Stack != NULL && *Stack != NULL);
  1568. //
  1569. // Step 1: Create a new scope on the stack
  1570. //
  1571. status = ParsePush( Stack );
  1572. if (!NT_SUCCESS(status)) {
  1573. return status;
  1574. }
  1575. //
  1576. // Step 2: Get the new top scope and its parent
  1577. //
  1578. status = StackTop( Stack, &newScope );
  1579. if (!NT_SUCCESS( status ) ) {
  1580. return status;
  1581. }
  1582. status = StackParent( Stack, newScope, &oldScope );
  1583. if (!NT_SUCCESS( status ) ) {
  1584. return status;
  1585. }
  1586. //
  1587. // Step 3: Determine how bytes the current instruction takes
  1588. //
  1589. packageLength = (ULONG) *(newScope->CurrentByte);
  1590. newScope->CurrentByte++;
  1591. //
  1592. // Step 4: If the the high 2 bits are set, this indicates that some
  1593. // follow on bits are also used in calculating the length
  1594. //
  1595. lengthBytes = (UCHAR) ( ( packageLength & 0xC0) >> 6);
  1596. if (lengthBytes) {
  1597. //
  1598. // Step 4.1: Mask off the non-length bits in the packageLength
  1599. //
  1600. packageLength &= 0xF;
  1601. //
  1602. // Step 4.2: Add the follow-on lengths
  1603. //
  1604. for (i = 0; i < lengthBytes; i++) {
  1605. packageLength |= ( (ULONG) *(newScope->CurrentByte) << (i*8 + 4) );
  1606. newScope->CurrentByte++;
  1607. }
  1608. }
  1609. //
  1610. // Step 5: We can calculate the start of the next opcode as the
  1611. // opcode in the old scope plus the calculated length. The end of
  1612. // new scope is the byte previous to this one
  1613. //
  1614. oldScope->CurrentByte += packageLength;
  1615. newScope->LastByte = oldScope->CurrentByte - 1;
  1616. //
  1617. // Step 6: Done
  1618. //
  1619. return STATUS_SUCCESS;
  1620. }
  1621. NTSTATUS
  1622. ParseWord(
  1623. IN PSTACK *Stack
  1624. )
  1625. /*++
  1626. Routine Description:
  1627. This routine handles words
  1628. Arguments:
  1629. Stack - The stack for the current thread
  1630. Return Value:
  1631. NTSTATUS
  1632. --*/
  1633. {
  1634. NTSTATUS status;
  1635. PUNASM_SCOPE localScope;
  1636. PUNASM_SCOPE rootScope;
  1637. UCHAR localBuffer[8];
  1638. ASSERT( Stack != NULL && *Stack != NULL );
  1639. //
  1640. // Step 1: Grab the current and root scope
  1641. //
  1642. ScopeFindLocalScope( Stack, &localScope, &rootScope, status );
  1643. //
  1644. // Step 2: Build the string
  1645. //
  1646. STRING_PRINT( localBuffer, "0x%04x", *((PUSHORT)localScope->CurrentByte));
  1647. //
  1648. // Step 3: Move the instruction pointer as appropriate, and setup
  1649. // for the next instructions
  1650. //
  1651. localScope->CurrentByte += 2;
  1652. //
  1653. // Step 4: Now push the byte onto the string stack
  1654. //
  1655. StringStackPush(
  1656. &(rootScope->StringStack),
  1657. STRING_LENGTH( localBuffer ),
  1658. localBuffer
  1659. );
  1660. //
  1661. // Step 5: Done
  1662. //
  1663. return status;
  1664. }