Leaked source code of windows server 2003
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.

2005 lines
40 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. unasm.c
  5. Abstract:
  6. This unassembles an AML file
  7. Author:
  8. Based on code by Mike Tsang (MikeTs)
  9. Stephane Plante (Splante)
  10. Environment:
  11. User mode only
  12. Revision History:
  13. --*/
  14. #include "pch.h"
  15. ULONG DSDTLoaded = FALSE;
  16. UCHAR
  17. LOCAL
  18. ComputeDataCheckSum(
  19. PUCHAR OpCode,
  20. ULONG Length
  21. )
  22. /*++
  23. Routine Description:
  24. This routine performs a data check sum on the supplied opcode pointer
  25. Arguments:
  26. OpCode - Data Buffer
  27. Length - Number of bytes in buffer
  28. Return Value:
  29. UCHAR
  30. --*/
  31. {
  32. UCHAR checkSum = 0;
  33. while (Length > 0) {
  34. checkSum += *OpCode;
  35. OpCode++;
  36. Length--;
  37. }
  38. return checkSum;
  39. }
  40. DllInit(
  41. HANDLE Module,
  42. ULONG Reason,
  43. ULONG Reserved
  44. )
  45. /*++
  46. Routine Description:
  47. This routine is called to initialize the DLL
  48. Arguments:
  49. Return Value:
  50. --*/
  51. {
  52. switch (Reason) {
  53. case DLL_THREAD_ATTACH:
  54. case DLL_THREAD_DETACH:
  55. case DLL_PROCESS_ATTACH:
  56. case DLL_PROCESS_DETACH:
  57. break;
  58. }
  59. return TRUE;
  60. }
  61. VOID
  62. LOCAL
  63. DumpCode(
  64. PUCHAR *Opcode,
  65. PUNASM_PRINT PrintFunction,
  66. ULONG_PTR BaseAddress,
  67. ULONG IndentLevel
  68. )
  69. /*++
  70. Routine Description:
  71. This routine doesn't do much right now, but it is the point where
  72. raw bytes should be displayed as well as the unassembly
  73. Arguments:
  74. OpCode - Pointer to the OpCode
  75. PrintFunction - Function to call to print information
  76. BaseAddress - Where the start of the scope lies, in memory
  77. IndentLevel - How much white space to leave on the left
  78. Return Value:
  79. NTSTATUS
  80. --*/
  81. {
  82. if (PrintFunction != NULL) {
  83. PrintFunction("\n");
  84. }
  85. }
  86. PASLTERM
  87. LOCAL
  88. FindKeywordTerm(
  89. UCHAR KeyWordGroup,
  90. UCHAR Data
  91. )
  92. /*++
  93. Routine Description:
  94. Find a Keyword within the TermTable
  95. Arguments:
  96. KeyWordGroup - What to search for
  97. Data - Data to match keyword
  98. Return Value:
  99. PASLTERM
  100. --*/
  101. {
  102. PASLTERM term = NULL;
  103. ULONG i;
  104. for (i = 0; TermTable[i].ID != NULL; i++) {
  105. if ((TermTable[i].TermClass == TC_KEYWORD) &&
  106. (TermTable[i].ArgActions[0] == KeyWordGroup) &&
  107. ((Data & (UCHAR)(TermTable[i].TermData >> 8)) ==
  108. (UCHAR)(TermTable[i].TermData & 0xff))) {
  109. break;
  110. }
  111. }
  112. if (TermTable[i].ID != NULL) {
  113. term = &TermTable[i];
  114. }
  115. return term;
  116. }
  117. UCHAR
  118. LOCAL
  119. FindOpClass(
  120. UCHAR OpCode,
  121. POPMAP OpCodeTable
  122. )
  123. /*++
  124. Routine Description:
  125. Find opcode class of extended opcode
  126. Arguments:
  127. OpCode - The Opcode to look up
  128. OpCodeTable - The table to look in
  129. Return Value:
  130. UCHAR
  131. --*/
  132. {
  133. UCHAR opCodeClass = OPCLASS_INVALID;
  134. while (OpCodeTable->OpCodeClass != 0) {
  135. if (OpCode == OpCodeTable->ExtendedOpCode) {
  136. opCodeClass = OpCodeTable->OpCodeClass;
  137. break;
  138. }
  139. OpCodeTable++;
  140. }
  141. return opCodeClass;
  142. }
  143. PASLTERM
  144. LOCAL
  145. FindOpTerm(
  146. ULONG OpCode
  147. )
  148. /*++
  149. Routine Description:
  150. Find an OpCode within the TermTable
  151. Arguments:
  152. OpCode - What to look for in the TermTable
  153. Return Value:
  154. PASLTERM
  155. --*/
  156. {
  157. PASLTERM term = NULL;
  158. ULONG i;
  159. for (i = 0; TermTable[i].ID != NULL; i++) {
  160. if ( (TermTable[i].OpCode == OpCode) &&
  161. (TermTable[i].TermClass & TC_OPCODE_TERM) ) {
  162. break;
  163. }
  164. }
  165. if (TermTable[i].ID != NULL) {
  166. term = &TermTable[i];
  167. }
  168. return term;
  169. }
  170. ULONG
  171. EXPORT
  172. IsDSDTLoaded(
  173. VOID
  174. )
  175. /*++
  176. Routine Description:
  177. This routine returns wether or not we have loaded a DSDT image
  178. Arguments:
  179. None
  180. Return:
  181. ULONG
  182. --*/
  183. {
  184. return DSDTLoaded;
  185. }
  186. NTSTATUS
  187. LOCAL
  188. ParseNameTail(
  189. PUCHAR *OpCode,
  190. PUCHAR Buffer,
  191. ULONG Length
  192. )
  193. /*++
  194. Routine Description:
  195. Parse AML name tail
  196. Arguments:
  197. OpCode - Pointer to the OpCode
  198. Buffer - Where to hold the parsed named
  199. Length - Index to the tail of Buffer
  200. Return Value:
  201. NTSTATUS
  202. --*/
  203. {
  204. NTSTATUS status = STATUS_SUCCESS;
  205. ULONG numSegments = 0;
  206. //
  207. // We do not check for invalid NameSeg characters here and assume that
  208. // the compiler does its job not generating it.
  209. //
  210. if (**OpCode == '\0'){
  211. //
  212. // There is no NameTail (i.e. either NULL name or name with just
  213. // prefixes.
  214. //
  215. (*OpCode)++;
  216. } else if (**OpCode == OP_MULTI_NAME_PREFIX) {
  217. (*OpCode)++;
  218. numSegments = (ULONG)**OpCode;
  219. (*OpCode)++;
  220. } else if (**OpCode == OP_DUAL_NAME_PREFIX) {
  221. (*OpCode)++;
  222. numSegments = 2;
  223. } else {
  224. numSegments = 1;
  225. }
  226. while ((numSegments > 0) && (Length + sizeof(NAMESEG) < MAX_NAME_LEN)) {
  227. strncpy(&Buffer[Length], (PUCHAR)(*OpCode), sizeof(NAMESEG));
  228. Length += sizeof(NAMESEG);
  229. *OpCode += sizeof(NAMESEG);
  230. numSegments--;
  231. if ((numSegments > 0) && (Length + 1 < MAX_NAME_LEN)) {
  232. Buffer[Length] = '.';
  233. Length++;
  234. }
  235. }
  236. if (numSegments > 0) {
  237. status = STATUS_NAME_TOO_LONG;
  238. } else {
  239. Buffer[Length] = '\0';
  240. }
  241. return status;
  242. }
  243. ULONG
  244. LOCAL
  245. ParsePackageLen(
  246. PUCHAR *OpCode,
  247. PUCHAR *OpCodeNext
  248. )
  249. /*++
  250. Routine Description:
  251. Parses the packages length
  252. Arguments:
  253. OpCode - Pointer to the current instruction
  254. OpCodeNode - Where to hold a pointer to the next instruction
  255. Return Value:
  256. ULONG - Package Length
  257. --*/
  258. {
  259. UCHAR noBytes;
  260. UCHAR i;
  261. ULONG length;
  262. if (OpCodeNext != NULL) {
  263. *OpCodeNext = *OpCode;
  264. }
  265. length = (ULONG)(**OpCode);
  266. (*OpCode)++;
  267. noBytes = (UCHAR)((length & 0xc0) >> 6);
  268. if (noBytes != 0) {
  269. length &= 0x0000000f;
  270. for (i = 0; i < noBytes; i++) {
  271. length |= (ULONG)(**OpCode) << (i*8 + 4);
  272. (*OpCode)++;
  273. }
  274. }
  275. if (OpCodeNext != NULL) {
  276. *OpCodeNext += length;
  277. }
  278. return length;
  279. }
  280. VOID
  281. LOCAL
  282. PrintIndent(
  283. PUNASM_PRINT PrintFunction,
  284. ULONG IndentLevel
  285. )
  286. /*++
  287. Routine Description:
  288. Does the indenting required
  289. Arguments:
  290. PrintFunction - Function to call to indent
  291. IndentLevel - How many levels to indent
  292. Return Value:
  293. VOID
  294. --*/
  295. {
  296. ULONG i;
  297. for (i = 0; i < IndentLevel; i++) {
  298. PrintFunction(" ");
  299. }
  300. }
  301. NTSTATUS
  302. LOCAL
  303. UnAsmArgs(
  304. PUCHAR UnAsmArgTypes,
  305. PUCHAR ArgActions,
  306. PUCHAR *OpCode,
  307. PNSOBJ *NameObject,
  308. PUNASM_PRINT PrintFunction,
  309. ULONG_PTR BaseAddress,
  310. ULONG IndentLevel
  311. )
  312. /*++
  313. Routine Description:
  314. Unassemble Arguments:
  315. Arguments:
  316. UnAsmArgTypes - UnAsm ArgTypes String
  317. ArgActions - Arg Action Types
  318. OpCode - Pointer to the OpCode
  319. NameObject - To hold created object
  320. PrintFunction - Function to call to print information
  321. BaseAddress - Where the start of the scope lies, in memory
  322. IndentLevel - How much white space to leave on the left
  323. Return Value:
  324. NTSTATUS
  325. --*/
  326. {
  327. NTSTATUS status = STATUS_SUCCESS;
  328. PASLTERM term;
  329. static UCHAR argData = 0;
  330. ULONG i;
  331. ULONG numArgs;
  332. numArgs = strlen(UnAsmArgTypes);
  333. if (PrintFunction != NULL) {
  334. PrintFunction("(");
  335. }
  336. for (i = 0; i < numArgs; i++){
  337. if ((i != 0) && (PrintFunction != NULL)) {
  338. PrintFunction(", ");
  339. }
  340. switch (UnAsmArgTypes[i]) {
  341. case 'N':
  342. ASSERT(ArgActions != NULL);
  343. status = UnAsmNameObj(
  344. OpCode,
  345. (islower(ArgActions[i])? NameObject: NULL),
  346. ArgActions[i],
  347. PrintFunction,
  348. BaseAddress,
  349. IndentLevel
  350. );
  351. break;
  352. case 'O':
  353. if ((**OpCode == OP_BUFFER) || (**OpCode == OP_PACKAGE) ||
  354. (OpClassTable[**OpCode] == OPCLASS_CONST_OBJ)) {
  355. term = FindOpTerm( (ULONG)(**OpCode) );
  356. ASSERT(term != NULL);
  357. (*OpCode)++;
  358. status = UnAsmTermObj(
  359. term,
  360. OpCode,
  361. PrintFunction,
  362. BaseAddress,
  363. IndentLevel
  364. );
  365. } else {
  366. status = UnAsmDataObj(
  367. OpCode,
  368. PrintFunction,
  369. BaseAddress,
  370. IndentLevel);
  371. }
  372. break;
  373. case 'C':
  374. status = UnAsmOpcode(
  375. OpCode,
  376. PrintFunction,
  377. BaseAddress,
  378. IndentLevel
  379. );
  380. break;
  381. case 'B':
  382. if (PrintFunction != NULL) {
  383. PrintFunction("0x%x", **OpCode);
  384. }
  385. *OpCode += sizeof(UCHAR);
  386. break;
  387. case 'K':
  388. case 'k':
  389. if (UnAsmArgTypes[i] == 'K') {
  390. argData = **OpCode;
  391. }
  392. if ((ArgActions != NULL) && (ArgActions[i] == '!')) {
  393. if (*NameObject != NULL) {
  394. (*NameObject)->ObjectData.DataValue =
  395. (ULONG)(**OpCode & 0x07);
  396. }
  397. if (PrintFunction != NULL) {
  398. PrintFunction("0x%x", **OpCode & 0x07);
  399. }
  400. } else if (PrintFunction != NULL) {
  401. term = FindKeywordTerm(ArgActions[i], argData);
  402. ASSERT(term != NULL);
  403. PrintFunction("%s", term->ID);
  404. }
  405. if (UnAsmArgTypes[i] == 'K') {
  406. *OpCode += sizeof(UCHAR);
  407. }
  408. break;
  409. case 'W':
  410. if (PrintFunction != NULL) {
  411. PrintFunction("0x%x", *( (PUSHORT)*OpCode ) );
  412. }
  413. *OpCode += sizeof(USHORT);
  414. break;
  415. case 'D':
  416. if (PrintFunction != NULL) {
  417. PrintFunction("0x%x", *( (PULONG)*OpCode ) );
  418. }
  419. *OpCode += sizeof(ULONG);
  420. break;
  421. case 'S':
  422. ASSERT(ArgActions != NULL);
  423. status = UnAsmSuperName(
  424. OpCode,
  425. PrintFunction,
  426. BaseAddress,
  427. IndentLevel
  428. );
  429. break;
  430. default:
  431. status = STATUS_ACPI_INVALID_ARGTYPE;
  432. }
  433. }
  434. if (PrintFunction != NULL) {
  435. PrintFunction(")");
  436. }
  437. return status;
  438. }
  439. NTSTATUS
  440. LOCAL
  441. UnAsmDataList(
  442. PUCHAR *OpCode,
  443. PUCHAR OpCodeEnd,
  444. PUNASM_PRINT PrintFunction,
  445. ULONG_PTR BaseAddress,
  446. ULONG IndentLevel
  447. )
  448. /*++
  449. Routine Description:
  450. Unassemble Data List
  451. Arguments:
  452. OpCode - Pointer to the OpCode
  453. OpCodeEnd - End of List
  454. PrintFunction - Function to call to print information
  455. BaseAddress - Where the start of the scope lies, in memory
  456. IndentLevel - How much white space to leave on the left
  457. Return Value:
  458. NTSTATUS
  459. --*/
  460. {
  461. NTSTATUS status = STATUS_SUCCESS;
  462. ULONG i;
  463. //
  464. // This is another place that DumpCode() was being called from
  465. //
  466. DumpCode(
  467. OpCode,
  468. PrintFunction,
  469. BaseAddress,
  470. IndentLevel
  471. );
  472. if (PrintFunction != NULL) {
  473. PrintIndent(PrintFunction, IndentLevel);
  474. PrintFunction("{\n");
  475. }
  476. while (*OpCode < OpCodeEnd) {
  477. if (PrintFunction != NULL) {
  478. PrintFunction("\t0x%02x", **OpCode);
  479. }
  480. (*OpCode)++;
  481. for (i = 1; (*OpCode < OpCodeEnd) && (i < 12); ++i) {
  482. if (PrintFunction != NULL) {
  483. PrintFunction(", 0x%02x", **OpCode);
  484. }
  485. (*OpCode)++;
  486. }
  487. if (PrintFunction != NULL) {
  488. if (*OpCode < OpCodeEnd) {
  489. PrintFunction(",");
  490. }
  491. PrintFunction("\n");
  492. }
  493. }
  494. if (PrintFunction != NULL) {
  495. PrintIndent(PrintFunction, IndentLevel);
  496. PrintFunction("}");
  497. }
  498. return status;
  499. }
  500. NTSTATUS
  501. LOCAL
  502. UnAsmDataObj(
  503. PUCHAR *OpCode,
  504. PUNASM_PRINT PrintFunction,
  505. ULONG_PTR BaseAddress,
  506. ULONG IndentLevel
  507. )
  508. /*++
  509. Routine Description:
  510. Unassembles a data object
  511. Arguments:
  512. OpCode - Pointer to the OpCode
  513. PrintFunction - Function to call to print information
  514. BaseAddress - Where the start of the scope lies, in memory
  515. IndentLevel - How much white space to leave on the left
  516. Return Value:
  517. NTSTATUS
  518. --*/
  519. {
  520. NTSTATUS status = STATUS_SUCCESS;
  521. UCHAR localOpcode = **OpCode;
  522. (*OpCode)++;
  523. switch (localOpcode)
  524. {
  525. case OP_BYTE:
  526. if (PrintFunction != NULL)
  527. {
  528. PrintFunction("0x%x", **OpCode);
  529. }
  530. *OpCode += sizeof(UCHAR);
  531. break;
  532. case OP_WORD:
  533. if (PrintFunction != NULL)
  534. {
  535. PrintFunction("0x%x", *((PUSHORT)*OpCode));
  536. }
  537. *OpCode += sizeof(USHORT);
  538. break;
  539. case OP_DWORD:
  540. if (PrintFunction != NULL)
  541. {
  542. PrintFunction("0x%x", *((PULONG)*OpCode));
  543. }
  544. *OpCode += sizeof(ULONG);
  545. break;
  546. case OP_STRING:
  547. if (PrintFunction != NULL)
  548. {
  549. PrintFunction("\"%s\"", *OpCode);
  550. }
  551. *OpCode += strlen((PUCHAR)*OpCode) + 1;
  552. break;
  553. default:
  554. status = STATUS_ACPI_INVALID_OPCODE;
  555. }
  556. return status;
  557. }
  558. NTSTATUS
  559. EXPORT
  560. UnAsmDSDT(
  561. PUCHAR DSDT,
  562. PUNASM_PRINT PrintFunction,
  563. ULONG_PTR DsdtLocation,
  564. ULONG IndentLevel
  565. )
  566. /*++
  567. Routine Description:
  568. This routine unassembles an entire DSDT table
  569. Arguments:
  570. DSDT - Where the DSDT is located in memory
  571. PrintFunction - What function to call to print to the user
  572. DsdtLocation - Where the DSDT is located in memory
  573. IndentLevel - How much space to indent from the left margin
  574. Return Value:
  575. NTSTATUS
  576. --*/
  577. {
  578. NTSTATUS status = STATUS_SUCCESS;
  579. PDESCRIPTION_HEADER header = (PDESCRIPTION_HEADER) DSDT;
  580. ASSERT(RootNameSpaceObject != NULL);
  581. CurrentOwnerNameSpaceObject = NULL;
  582. CurrentScopeNameSpaceObject = RootNameSpaceObject;
  583. TopOpcode = CurrentOpcode = DSDT;
  584. //
  585. // Dump the header
  586. //
  587. status = UnAsmHeader( header, PrintFunction, DsdtLocation, IndentLevel );
  588. if (NT_SUCCESS(status)) {
  589. DSDT += sizeof(DESCRIPTION_HEADER);
  590. status = UnAsmScope(
  591. &DSDT,
  592. (PUCHAR) (DSDT + header->Length - sizeof(DESCRIPTION_HEADER)),
  593. PrintFunction,
  594. DsdtLocation,
  595. IndentLevel
  596. );
  597. }
  598. return status;
  599. }
  600. NTSTATUS
  601. LOCAL
  602. UnAsmField(
  603. PUCHAR *OpCode,
  604. PULONG BitPos,
  605. PUNASM_PRINT PrintFunction,
  606. ULONG_PTR BaseAddress,
  607. ULONG IndentLevel
  608. )
  609. /*++
  610. Routine Description:
  611. Unassemble field
  612. Arguments:
  613. OpCode - Pointer to the OpCode
  614. OpCodeEnd - End of List
  615. PrintFunction - Function to call to print information
  616. BaseAddress - Where the start of the scope lies, in memory
  617. IndentLevel - How much white space to leave on the left
  618. Return Value:
  619. NTSTATUS
  620. --*/
  621. {
  622. NTSTATUS status = STATUS_SUCCESS;
  623. if (**OpCode == 0x01) {
  624. (*OpCode)++;
  625. if (PrintFunction != NULL) {
  626. PASLTERM term;
  627. term = FindKeywordTerm('A', **OpCode);
  628. PrintFunction(
  629. "AccessAs(%s, 0x%x)",
  630. term->ID,
  631. *(*OpCode + 1)
  632. );
  633. }
  634. *OpCode += 2;
  635. } else {
  636. UCHAR nameSeg[sizeof(NAMESEG) + 1];
  637. ULONG length;
  638. if (**OpCode == 0) {
  639. nameSeg[0] = '\0';
  640. (*OpCode)++;
  641. } else {
  642. strncpy(nameSeg, (PUCHAR)*OpCode, sizeof(NAMESEG));
  643. nameSeg[sizeof(NAMESEG)] = '\0';
  644. *OpCode += sizeof(NAMESEG);
  645. }
  646. length = ParsePackageLen(
  647. OpCode,
  648. NULL
  649. );
  650. if (nameSeg[0] == '\0') {
  651. if (PrintFunction != NULL) {
  652. if ((length > 32) && (((*BitPos + length) % 8) == 0)) {
  653. PrintFunction(
  654. "Offset(0x%x)",
  655. (*BitPos + length)/8
  656. );
  657. } else {
  658. PrintFunction(
  659. ", %d",
  660. length
  661. );
  662. }
  663. }
  664. } else {
  665. if (PrintFunction != NULL) {
  666. PrintFunction(
  667. "%s, %d",
  668. nameSeg,
  669. length
  670. );
  671. }
  672. if (PrintFunction == NULL) {
  673. status = CreateObject(
  674. nameSeg,
  675. NSTYPE_FIELDUNIT,
  676. NULL
  677. );
  678. }
  679. }
  680. *BitPos += length;
  681. }
  682. return status;
  683. }
  684. NTSTATUS
  685. LOCAL
  686. UnAsmFieldList(
  687. PUCHAR *OpCode,
  688. PUCHAR OpCodeEnd,
  689. PUNASM_PRINT PrintFunction,
  690. ULONG_PTR BaseAddress,
  691. ULONG IndentLevel
  692. )
  693. /*++
  694. Routine Description:
  695. Unassemble field list
  696. Arguments:
  697. OpCode - Pointer to the OpCode
  698. OpCodeEnd - End of List
  699. PrintFunction - Function to call to print information
  700. BaseAddress - Where the start of the scope lies, in memory
  701. IndentLevel - How much white space to leave on the left
  702. Return Value:
  703. NTSTATUS
  704. --*/
  705. {
  706. NTSTATUS status = STATUS_SUCCESS;
  707. ULONG bitPos = 0;
  708. //
  709. // This is another place that DumpCode() was being called from
  710. //
  711. DumpCode(
  712. OpCode,
  713. PrintFunction,
  714. BaseAddress,
  715. IndentLevel
  716. );
  717. if (PrintFunction != NULL) {
  718. PrintIndent(PrintFunction, IndentLevel);
  719. PrintFunction("{\n");
  720. }
  721. IndentLevel++;
  722. while ((*OpCode < OpCodeEnd) && NT_SUCCESS(status)) {
  723. if (PrintFunction != NULL) {
  724. PrintIndent(PrintFunction, IndentLevel);
  725. }
  726. status = UnAsmField(
  727. OpCode,
  728. &bitPos,
  729. PrintFunction,
  730. BaseAddress,
  731. IndentLevel
  732. );
  733. if (NT_SUCCESS(status) && (*OpCode < OpCodeEnd) &&
  734. (PrintFunction != NULL) ) {
  735. PrintFunction(",");
  736. }
  737. //
  738. // This is another place that DumpCode() was being called from
  739. //
  740. DumpCode(
  741. OpCode,
  742. PrintFunction,
  743. BaseAddress,
  744. IndentLevel
  745. );
  746. }
  747. IndentLevel--;
  748. if (PrintFunction != NULL) {
  749. PrintIndent(PrintFunction, IndentLevel);
  750. PrintFunction("}");
  751. }
  752. return status;
  753. }
  754. NTSTATUS
  755. LOCAL
  756. UnAsmHeader(
  757. PDESCRIPTION_HEADER DsdtHeader,
  758. PUNASM_PRINT PrintFunction,
  759. ULONG_PTR DsdtLocation,
  760. ULONG IndentLevel
  761. )
  762. /*++
  763. Routine Description:
  764. Unassembles the DSDT header
  765. Arguments:
  766. DsdtHeader - Header to unassemble
  767. PrintFunction - Function to call to display information
  768. DsdtLocation - Where in memory the DSDT Lives
  769. IndentLevel - How much space to indent from the left margin
  770. Return Value:
  771. NTSTATUS
  772. --*/
  773. {
  774. NTSTATUS status = STATUS_SUCCESS;
  775. UCHAR signature[sizeof(DsdtHeader->Signature) + 1] = {0};
  776. UCHAR oemID[sizeof(DsdtHeader->OEMID) + 1] = {0};
  777. UCHAR oemTableID[sizeof(DsdtHeader->OEMTableID) + 1] = {0};
  778. UCHAR creatorID[sizeof(DsdtHeader->CreatorID) + 1] = {0};
  779. UCHAR checkSum;
  780. //
  781. // Lets do a checksump on the entire table
  782. //
  783. checkSum = ComputeDataCheckSum(
  784. (PUCHAR) DsdtHeader,
  785. DsdtHeader->Length
  786. );
  787. if (checkSum != 0) {
  788. status = STATUS_ACPI_INVALID_TABLE;
  789. }
  790. strncpy(
  791. signature,
  792. (PUCHAR)&DsdtHeader->Signature,
  793. sizeof(DsdtHeader->Signature)
  794. );
  795. strncpy(
  796. oemID,
  797. (PUCHAR) DsdtHeader->OEMID,
  798. sizeof(DsdtHeader->OEMID)
  799. );
  800. strncpy(
  801. oemTableID,
  802. (PUCHAR) DsdtHeader->OEMTableID,
  803. sizeof(DsdtHeader->OEMTableID)
  804. );
  805. strncpy(
  806. creatorID,
  807. (PUCHAR) DsdtHeader->CreatorID,
  808. sizeof(DsdtHeader->CreatorID)
  809. );
  810. if (PrintFunction != NULL) {
  811. PrintIndent( PrintFunction, IndentLevel );
  812. PrintFunction(
  813. "// CreatorID = %s\tCreatorRevision =%x.%x.%d\n",
  814. creatorID,
  815. DsdtHeader->CreatorRev >> 24,
  816. ( (DsdtHeader->CreatorRev >> 16) & 0xFF),
  817. (DsdtHeader->CreatorRev & 0xFFFF)
  818. );
  819. PrintIndent( PrintFunction, IndentLevel );
  820. PrintFunction(
  821. "// TableLength = %d\tTableChkSum=0x%x\n\n",
  822. DsdtHeader->Length,
  823. DsdtHeader->Checksum
  824. );
  825. PrintIndent( PrintFunction, IndentLevel );
  826. PrintFunction(
  827. "DefinitionBlock(\"%s.AML\", \"%s\", 0x%02x, \"%s\", \"%s\", 0x%08x)",
  828. signature,
  829. signature,
  830. DsdtHeader->Revision,
  831. oemID,
  832. oemTableID,
  833. DsdtHeader->OEMRevision
  834. );
  835. }
  836. return status;
  837. }
  838. NTSTATUS
  839. EXPORT
  840. UnAsmLoadDSDT(
  841. PUCHAR DSDT
  842. )
  843. /*++
  844. Routine Description:
  845. This routine causes the unassmebler to initialize itself with the
  846. given DSDT
  847. Arguments:
  848. DSDT - Where the DSDT is located in memory
  849. PrintFunction - What function to call to print to the user
  850. DsdtLocation - Where the DSDT is located in memory
  851. IndentLevel - How much space to indent from the left margin
  852. Return Value:
  853. NTSTATUS
  854. --*/
  855. {
  856. NTSTATUS status = STATUS_SUCCESS;
  857. PDESCRIPTION_HEADER header = (PDESCRIPTION_HEADER) DSDT;
  858. PUCHAR localDSDT;
  859. ENTER( (1, "UnAsmLoadDSDT(%08lx)\n", DSDT) );
  860. //
  861. // Step 1: Create the root namespace
  862. //
  863. status = CreateNameSpaceObject( "\\", NULL, NULL, NULL, NSF_EXIST_ERR );
  864. if (NT_SUCCESS(status)) {
  865. static struct _defobj {
  866. PUCHAR Name;
  867. ULONG ObjectType;
  868. } DefinedRootObjects[] = {
  869. "_GPE", OBJTYPE_UNKNOWN,
  870. "_PR", OBJTYPE_UNKNOWN,
  871. "_SB", OBJTYPE_UNKNOWN,
  872. "_SI", OBJTYPE_UNKNOWN,
  873. "_TZ", OBJTYPE_UNKNOWN,
  874. "_REV", OBJTYPE_INTDATA,
  875. "_OS", OBJTYPE_STRDATA,
  876. "_GL", OBJTYPE_MUTEX,
  877. NULL, 0
  878. };
  879. ULONG i;
  880. PNSOBJ nameObject;
  881. CurrentScopeNameSpaceObject = RootNameSpaceObject;
  882. for (i = 0; DefinedRootObjects[i].Name != NULL; i++) {
  883. //
  884. // Step 2: Create the fixed objects
  885. //
  886. status = CreateNameSpaceObject(
  887. DefinedRootObjects[i].Name,
  888. NULL,
  889. NULL,
  890. &nameObject,
  891. NSF_EXIST_ERR
  892. );
  893. if (NT_SUCCESS(status)) {
  894. nameObject->ObjectData.DataType =
  895. DefinedRootObjects[i].ObjectType;
  896. } else {
  897. break;
  898. }
  899. }
  900. if (NT_SUCCESS(status)) {
  901. ASSERT(RootNameSpaceObject != NULL);
  902. CurrentOwnerNameSpaceObject = NULL;
  903. CurrentScopeNameSpaceObject = RootNameSpaceObject;
  904. TopOpcode = CurrentOpcode = DSDT;
  905. //
  906. // Step 3: Dump the header
  907. //
  908. status = UnAsmHeader( header, NULL, 0, 0 );
  909. if (NT_SUCCESS(status)) {
  910. //
  911. // Step 4: Dump the scope
  912. //
  913. localDSDT = DSDT + sizeof(DESCRIPTION_HEADER);
  914. status = UnAsmScope(
  915. &localDSDT,
  916. (PUCHAR) (DSDT + header->Length),
  917. NULL,
  918. 0,
  919. 0
  920. );
  921. }
  922. }
  923. }
  924. if (NT_SUCCESS(status)) {
  925. DSDTLoaded = 1;
  926. }
  927. EXIT( (1, "UnAsmLoadDSDT=%08lx\n", status ) );
  928. return status;
  929. }
  930. NTSTATUS
  931. LOCAL
  932. UnAsmNameObj(
  933. PUCHAR *OpCode,
  934. PNSOBJ *NameObject,
  935. UCHAR ObjectType,
  936. PUNASM_PRINT PrintFunction,
  937. ULONG_PTR BaseAddress,
  938. ULONG IndentLevel
  939. )
  940. /*++
  941. Routine Description:
  942. Unassemble name object
  943. Arguments:
  944. OpCode - Pointer to the OpCode
  945. NameObject - Where to store the NS object if one is found/created
  946. ObjecType - Type of NS object
  947. PrintFunction - Function to call to print information
  948. BaseAddress - Where the start of the scope lies, in memory
  949. IndentLevel - How much white space to leave on the left
  950. Return Value:
  951. NTSTATUS
  952. --*/
  953. {
  954. NTSTATUS status = STATUS_SUCCESS;
  955. UCHAR name[MAX_NAME_LEN + 1];
  956. ULONG length = 0;
  957. name[0] = '\0';
  958. if (**OpCode == OP_ROOT_PREFIX){
  959. name[length] = '\\';
  960. length++;
  961. (*OpCode)++;
  962. status = ParseNameTail(OpCode, name, length);
  963. } else if (**OpCode == OP_PARENT_PREFIX) {
  964. name[length] = '^';
  965. length++;
  966. (*OpCode)++;
  967. while ((**OpCode == OP_PARENT_PREFIX) && (length < MAX_NAME_LEN)) {
  968. name[length] = '^';
  969. length++;
  970. (*OpCode)++;
  971. }
  972. if (**OpCode == OP_PARENT_PREFIX) {
  973. status = STATUS_OBJECT_NAME_INVALID;
  974. } else {
  975. status = ParseNameTail(OpCode, name, length);
  976. }
  977. } else {
  978. status = ParseNameTail(OpCode, name, length);
  979. }
  980. if (NT_SUCCESS(status)) {
  981. PNSOBJ localObject = NULL;
  982. if (PrintFunction != NULL) {
  983. PrintFunction("%s", name);
  984. }
  985. if (isupper(ObjectType) || (PrintFunction != NULL)) {
  986. status = GetNameSpaceObject(
  987. name,
  988. CurrentScopeNameSpaceObject,
  989. &localObject,
  990. 0
  991. );
  992. if (!NT_SUCCESS(status)) {
  993. status = STATUS_SUCCESS;
  994. }
  995. } else {
  996. status = CreateObject(
  997. name,
  998. (UCHAR) _toupper(ObjectType),
  999. &localObject
  1000. );
  1001. }
  1002. if (NT_SUCCESS(status)) {
  1003. if ((ObjectType == NSTYPE_SCOPE) && (localObject != NULL)) {
  1004. CurrentScopeNameSpaceObject = localObject;
  1005. }
  1006. if (NameObject != NULL) {
  1007. *NameObject = localObject;
  1008. }
  1009. }
  1010. }
  1011. return status;
  1012. }
  1013. NTSTATUS
  1014. LOCAL
  1015. UnAsmOpcode(
  1016. PUCHAR *OpCode,
  1017. PUNASM_PRINT PrintFunction,
  1018. ULONG_PTR BaseAddress,
  1019. ULONG IndentLevel
  1020. )
  1021. /*++
  1022. Routine Description:
  1023. Unassemble an Opcode
  1024. Arguments:
  1025. OpCode - Pointer to the OpCode
  1026. PrintFunction - Function to call to print information
  1027. BaseAddress - Where the start of the scope lies, in memory
  1028. IndentLevel - How much white space to leave on the left
  1029. Return Value:
  1030. NTSTATUS
  1031. --*/
  1032. {
  1033. NTSTATUS status = STATUS_SUCCESS;
  1034. PASLTERM term;
  1035. PNSOBJ nameObject;
  1036. UCHAR opCodeClass;
  1037. UCHAR unAsmArgTypes[MAX_ARGS+1];
  1038. ULONG i;
  1039. ULONG localOpCode;
  1040. if (**OpCode == OP_EXT_PREFIX) {
  1041. (*OpCode)++;
  1042. localOpCode = ( ( (ULONG) **OpCode) << 8) | OP_EXT_PREFIX;
  1043. opCodeClass = FindOpClass(**OpCode, ExOpClassTable);
  1044. } else {
  1045. localOpCode = (ULONG)(**OpCode);
  1046. opCodeClass = OpClassTable[**OpCode];
  1047. }
  1048. switch (opCodeClass) {
  1049. case OPCLASS_DATA_OBJ:
  1050. status = UnAsmDataObj(
  1051. OpCode,
  1052. PrintFunction,
  1053. BaseAddress,
  1054. IndentLevel
  1055. );
  1056. break;
  1057. case OPCLASS_NAME_OBJ:
  1058. status = UnAsmNameObj(
  1059. OpCode,
  1060. &nameObject,
  1061. NSTYPE_UNKNOWN,
  1062. PrintFunction,
  1063. BaseAddress,
  1064. IndentLevel
  1065. );
  1066. if (NT_SUCCESS(status) && nameObject != NULL &&
  1067. nameObject->ObjectData.DataType == OBJTYPE_METHOD) {
  1068. for (i = 0; i < nameObject->ObjectData.DataValue; i++) {
  1069. unAsmArgTypes[i] = 'C';
  1070. }
  1071. unAsmArgTypes[i] = '\0';
  1072. status = UnAsmArgs(
  1073. unAsmArgTypes,
  1074. NULL,
  1075. OpCode,
  1076. NULL,
  1077. PrintFunction,
  1078. BaseAddress,
  1079. IndentLevel
  1080. );
  1081. }
  1082. break;
  1083. case OPCLASS_ARG_OBJ:
  1084. case OPCLASS_LOCAL_OBJ:
  1085. case OPCLASS_CODE_OBJ:
  1086. case OPCLASS_CONST_OBJ:
  1087. term = FindOpTerm( localOpCode );
  1088. if (term == NULL) {
  1089. status = STATUS_ACPI_INVALID_OPCODE;
  1090. } else {
  1091. (*OpCode)++;
  1092. status = UnAsmTermObj(
  1093. term,
  1094. OpCode,
  1095. PrintFunction,
  1096. BaseAddress,
  1097. IndentLevel
  1098. );
  1099. }
  1100. break;
  1101. default:
  1102. status = STATUS_ACPI_INVALID_OPCODE;
  1103. }
  1104. return status;
  1105. }
  1106. NTSTATUS
  1107. LOCAL
  1108. UnAsmPkgList(
  1109. PUCHAR *OpCode,
  1110. PUCHAR OpCodeEnd,
  1111. PUNASM_PRINT PrintFunction,
  1112. ULONG_PTR BaseAddress,
  1113. ULONG IndentLevel
  1114. )
  1115. /*++
  1116. Routine Description:
  1117. Unassemble Package List
  1118. Arguments:
  1119. OpCode - Pointer to the OpCode
  1120. OpCodeEnd - End of List
  1121. PrintFunction - Function to call to print information
  1122. BaseAddress - Where the start of the scope lies, in memory
  1123. IndentLevel - How much white space to leave on the left
  1124. Return Value:
  1125. NTSTATUS
  1126. --*/
  1127. {
  1128. NTSTATUS status = STATUS_SUCCESS;
  1129. PASLTERM term;
  1130. //
  1131. // This is another place that DumpCode() was being called from
  1132. //
  1133. DumpCode(
  1134. OpCode,
  1135. PrintFunction,
  1136. BaseAddress,
  1137. IndentLevel
  1138. );
  1139. if (PrintFunction != NULL) {
  1140. PrintIndent(PrintFunction, IndentLevel);
  1141. PrintFunction("{\n");
  1142. }
  1143. IndentLevel++;
  1144. while ((*OpCode < OpCodeEnd) && NT_SUCCESS(status)) {
  1145. if (PrintFunction != NULL) {
  1146. PrintIndent(PrintFunction, IndentLevel);
  1147. }
  1148. if ((**OpCode == OP_BUFFER) ||
  1149. (**OpCode == OP_PACKAGE) ||
  1150. (OpClassTable[**OpCode] == OPCLASS_CONST_OBJ) ) {
  1151. term = FindOpTerm( (ULONG)(**OpCode) );
  1152. ASSERT(term != NULL);
  1153. (*OpCode)++;
  1154. status = UnAsmTermObj(
  1155. term,
  1156. OpCode,
  1157. PrintFunction,
  1158. BaseAddress,
  1159. IndentLevel
  1160. );
  1161. } else if (OpClassTable[**OpCode] == OPCLASS_NAME_OBJ) {
  1162. status = UnAsmNameObj(
  1163. OpCode,
  1164. NULL,
  1165. NSTYPE_UNKNOWN,
  1166. PrintFunction,
  1167. BaseAddress,
  1168. IndentLevel
  1169. );
  1170. } else {
  1171. status = UnAsmDataObj(
  1172. OpCode,
  1173. PrintFunction,
  1174. BaseAddress,
  1175. IndentLevel
  1176. );
  1177. }
  1178. if ((*OpCode < OpCodeEnd) && NT_SUCCESS(status) &&
  1179. (PrintFunction != NULL) ) {
  1180. PrintFunction(",");
  1181. }
  1182. //
  1183. // This is another place that DumpCode() was being called from
  1184. //
  1185. DumpCode(
  1186. OpCode,
  1187. PrintFunction,
  1188. BaseAddress,
  1189. IndentLevel
  1190. );
  1191. }
  1192. IndentLevel--;
  1193. if (PrintFunction != NULL) {
  1194. PrintIndent(PrintFunction, IndentLevel);
  1195. PrintFunction("}");
  1196. }
  1197. return status;
  1198. }
  1199. NTSTATUS
  1200. LOCAL
  1201. UnAsmScope(
  1202. PUCHAR *OpCode,
  1203. PUCHAR OpCodeEnd,
  1204. PUNASM_PRINT PrintFunction,
  1205. ULONG_PTR BaseAddress,
  1206. ULONG IndentLevel
  1207. )
  1208. /*++
  1209. Routine Description:
  1210. OpCode - Pointer to the current Opcode
  1211. OpCodeEnd - End of Scope
  1212. PrintFunction - Function to call to print information
  1213. BaseAddress - Where the start of the scope lies, in memory
  1214. IndentLevel - How much white space to leave on the left
  1215. Return Value:
  1216. NTSTATUS
  1217. --*/
  1218. {
  1219. NTSTATUS status = STATUS_SUCCESS;
  1220. //
  1221. // Note: This is where DumpCode used to be called, so if this code
  1222. // is ever changed to dump the by bytes of the previous whatever, then
  1223. // this is where it needs to be done from
  1224. //
  1225. DumpCode(
  1226. OpCode,
  1227. PrintFunction,
  1228. BaseAddress,
  1229. IndentLevel
  1230. );
  1231. //
  1232. // Indent to the proper amount and dump opening brace
  1233. //
  1234. if (PrintFunction != NULL) {
  1235. PrintIndent(PrintFunction, IndentLevel);
  1236. PrintFunction("{\n");
  1237. }
  1238. //
  1239. // Increase the indent level for future recursion
  1240. //
  1241. IndentLevel++;
  1242. //
  1243. // Loop while there are bytes in the scope
  1244. //
  1245. while ((NT_SUCCESS(status)) && (*OpCode < OpCodeEnd)) {
  1246. //
  1247. // Indent Again
  1248. //
  1249. if (PrintFunction != NULL) {
  1250. PrintIndent(PrintFunction, IndentLevel);
  1251. }
  1252. //
  1253. // Unassemble
  1254. //
  1255. status = UnAsmOpcode(
  1256. OpCode,
  1257. PrintFunction,
  1258. BaseAddress,
  1259. IndentLevel
  1260. );
  1261. //
  1262. // This is another place where DumpCode was being called from
  1263. //
  1264. if ( StartOpcode != *OpCode) {
  1265. DumpCode(
  1266. OpCode,
  1267. PrintFunction,
  1268. BaseAddress,
  1269. IndentLevel
  1270. );
  1271. } else if (PrintFunction != NULL) {
  1272. PrintFunction("\n");
  1273. }
  1274. }
  1275. //
  1276. // Return the IndentLevel to its proper value
  1277. //
  1278. IndentLevel--;
  1279. //
  1280. // Print the trailing brace
  1281. //
  1282. if (PrintFunction != NULL) {
  1283. PrintIndent(PrintFunction, IndentLevel);
  1284. PrintFunction("}");
  1285. }
  1286. //
  1287. // Done
  1288. //
  1289. return status;
  1290. }
  1291. NTSTATUS
  1292. LOCAL
  1293. UnAsmSuperName(
  1294. PUCHAR *OpCode,
  1295. PUNASM_PRINT PrintFunction,
  1296. ULONG_PTR BaseAddress,
  1297. ULONG IndentLevel
  1298. )
  1299. /*++
  1300. Routine Description:
  1301. Unassemble supernames
  1302. Arguments:
  1303. OpCode - Pointer to the OpCode
  1304. PrintFunction - Function to call to print information
  1305. BaseAddress - Where the start of the scope lies, in memory
  1306. IndentLevel - How much white space to leave on the left
  1307. Return Value:
  1308. NTSTATUS
  1309. --*/
  1310. {
  1311. NTSTATUS status = STATUS_SUCCESS;
  1312. if (**OpCode == 0) {
  1313. (*OpCode)++;
  1314. } else if ((**OpCode == OP_EXT_PREFIX) && (*(*OpCode + 1) == EXOP_DEBUG)) {
  1315. if (PrintFunction != NULL) {
  1316. PrintFunction("Debug");
  1317. }
  1318. *OpCode += 2;
  1319. } else if (OpClassTable[**OpCode] == OPCLASS_NAME_OBJ) {
  1320. status = UnAsmNameObj(
  1321. OpCode,
  1322. NULL,
  1323. NSTYPE_UNKNOWN,
  1324. PrintFunction,
  1325. BaseAddress,
  1326. IndentLevel
  1327. );
  1328. } else if ((**OpCode == OP_INDEX) ||
  1329. (OpClassTable[**OpCode] == OPCLASS_ARG_OBJ) ||
  1330. (OpClassTable[**OpCode] == OPCLASS_LOCAL_OBJ)) {
  1331. status = UnAsmOpcode(
  1332. OpCode,
  1333. PrintFunction,
  1334. BaseAddress,
  1335. IndentLevel
  1336. );
  1337. } else {
  1338. status = STATUS_ACPI_INVALID_SUPERNAME;
  1339. }
  1340. return status;
  1341. }
  1342. NTSTATUS
  1343. LOCAL
  1344. UnAsmTermObj(
  1345. PASLTERM Term,
  1346. PUCHAR *OpCode,
  1347. PUNASM_PRINT PrintFunction,
  1348. ULONG_PTR BaseAddress,
  1349. ULONG IndentLevel
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. Unassemble term object
  1354. Arguments:
  1355. Term - Term Table Entry
  1356. OpCode - Pointer to the OpCode
  1357. PrintFunction - Function to call to print information
  1358. BaseAddress - Where the start of the scope lies, in memory
  1359. IndentLevel - How much white space to leave on the left
  1360. Return Value:
  1361. NTSTATUS
  1362. --*/
  1363. {
  1364. NTSTATUS status = STATUS_SUCCESS;
  1365. PNSOBJ scopeObject = CurrentScopeNameSpaceObject;
  1366. PNSOBJ nameObject = NULL;
  1367. PUCHAR opCodeEnd = NULL;
  1368. if (PrintFunction != NULL) {
  1369. PrintFunction("%s", Term->ID);
  1370. }
  1371. if (Term->Flags & TF_PACKAGE_LEN) {
  1372. ParsePackageLen(OpCode, &opCodeEnd);
  1373. }
  1374. if (Term->UnAsmArgTypes != NULL) {
  1375. status = UnAsmArgs(
  1376. Term->UnAsmArgTypes,
  1377. Term->ArgActions,
  1378. OpCode,
  1379. &nameObject,
  1380. PrintFunction,
  1381. BaseAddress,
  1382. IndentLevel
  1383. );
  1384. }
  1385. if (NT_SUCCESS(status)) {
  1386. if (Term->Flags & TF_DATA_LIST) {
  1387. status = UnAsmDataList(
  1388. OpCode,
  1389. opCodeEnd,
  1390. PrintFunction,
  1391. BaseAddress,
  1392. IndentLevel
  1393. );
  1394. } else if (Term->Flags & TF_PACKAGE_LIST) {
  1395. status = UnAsmPkgList(
  1396. OpCode,
  1397. opCodeEnd,
  1398. PrintFunction,
  1399. BaseAddress,
  1400. IndentLevel
  1401. );
  1402. } else if (Term->Flags & TF_FIELD_LIST) {
  1403. status = UnAsmFieldList(
  1404. OpCode,
  1405. opCodeEnd,
  1406. PrintFunction,
  1407. BaseAddress,
  1408. IndentLevel
  1409. );
  1410. } else if (Term->Flags & TF_PACKAGE_LEN) {
  1411. if (nameObject != NULL) {
  1412. CurrentScopeNameSpaceObject = nameObject;
  1413. }
  1414. status = UnAsmScope(
  1415. OpCode,
  1416. opCodeEnd,
  1417. PrintFunction,
  1418. BaseAddress,
  1419. IndentLevel
  1420. );
  1421. }
  1422. }
  1423. CurrentScopeNameSpaceObject = scopeObject;
  1424. return status;
  1425. }