dbdisasm.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:15k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*******************************************************************************
  2.  *
  3.  * Module Name: dbdisasm - parser op tree display routines
  4.  *              $Revision: 50 $
  5.  *
  6.  ******************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 R. Byron Moore
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. #include "acpi.h"
  25. #include "acparser.h"
  26. #include "amlcode.h"
  27. #include "acnamesp.h"
  28. #include "acdebug.h"
  29. #ifdef ENABLE_DEBUGGER
  30. #define _COMPONENT          ACPI_DEBUGGER
  31.  MODULE_NAME         ("dbdisasm")
  32. #define MAX_SHOW_ENTRY      128
  33. #define BLOCK_PAREN         1
  34. #define BLOCK_BRACE         2
  35. #define DB_NO_OP_INFO       "            [%2.2d]  "
  36. #define DB_FULL_OP_INFO     "%5.5X #%4.4X [%2.2d]  "
  37. NATIVE_CHAR                 *acpi_gbl_db_disasm_indent = "....";
  38. /*******************************************************************************
  39.  *
  40.  * FUNCTION:    Acpi_db_block_type
  41.  *
  42.  * PARAMETERS:  Op              - Object to be examined
  43.  *
  44.  * RETURN:      Status
  45.  *
  46.  * DESCRIPTION: Type of block for this op (parens or braces)
  47.  *
  48.  ******************************************************************************/
  49. u32
  50. acpi_db_block_type (
  51. acpi_parse_object       *op)
  52. {
  53. switch (op->opcode) {
  54. case AML_METHOD_OP:
  55. return (BLOCK_BRACE);
  56. break;
  57. default:
  58. break;
  59. }
  60. return (BLOCK_PAREN);
  61. }
  62. /*******************************************************************************
  63.  *
  64.  * FUNCTION:    Acpi_ps_display_object_pathname
  65.  *
  66.  * PARAMETERS:  Op              - Object whose pathname is to be obtained
  67.  *
  68.  * RETURN:      Status
  69.  *
  70.  * DESCRIPTION: Diplay the pathname associated with a named object.  Two
  71.  *              versions. One searches the parse tree (for parser-only
  72.  *              applications suchas Acpi_dump), and the other searches the
  73.  *              ACPI namespace (the parse tree is probably deleted)
  74.  *
  75.  ******************************************************************************/
  76. #ifdef PARSER_ONLY
  77. acpi_status
  78. acpi_ps_display_object_pathname (
  79. acpi_walk_state         *walk_state,
  80. acpi_parse_object       *op)
  81. {
  82. acpi_parse_object       *target_op;
  83. /* Search parent tree up to the root if necessary */
  84. target_op = acpi_ps_find (op, op->value.name, 0, 0);
  85. if (!target_op) {
  86. /*
  87.  * Didn't find the name in the parse tree.  This may be
  88.  * a problem, or it may simply be one of the predefined names
  89.  * (such as _OS_).  Rather than worry about looking up all
  90.  * the predefined names, just display the name as given
  91.  */
  92. acpi_os_printf (" **** Path not found in parse tree");
  93. }
  94. else {
  95. /* The target was found, print the name and complete path */
  96. acpi_os_printf (" (Path ");
  97. acpi_db_display_path (target_op);
  98. acpi_os_printf (")");
  99. }
  100. return (AE_OK);
  101. }
  102. #else
  103. acpi_status
  104. acpi_ps_display_object_pathname (
  105. acpi_walk_state         *walk_state,
  106. acpi_parse_object       *op)
  107. {
  108. acpi_status             status;
  109. acpi_namespace_node     *node;
  110. NATIVE_CHAR             buffer[MAX_SHOW_ENTRY];
  111. u32                     buffer_size = MAX_SHOW_ENTRY;
  112. u32                     debug_level;
  113. /* Save current debug level so we don't get extraneous debug output */
  114. debug_level = acpi_dbg_level;
  115. acpi_dbg_level = 0;
  116. /* Just get the Node out of the Op object */
  117. node = op->node;
  118. if (!node) {
  119. /* Node not defined in this scope, look it up */
  120. status = acpi_ns_lookup (walk_state->scope_info, op->value.string, ACPI_TYPE_ANY,
  121.   IMODE_EXECUTE, NS_SEARCH_PARENT, walk_state, &(node));
  122. if (ACPI_FAILURE (status)) {
  123. /*
  124.  * We can't get the pathname since the object
  125.  * is not in the namespace.  This can happen during single
  126.  * stepping where a dynamic named object is *about* to be created.
  127.  */
  128. acpi_os_printf (" [Path not found]");
  129. goto exit;
  130. }
  131. /* Save it for next time. */
  132. op->node = node;
  133. }
  134. /* Convert Named_desc/handle to a full pathname */
  135. status = acpi_ns_handle_to_pathname (node, &buffer_size, buffer);
  136. if (ACPI_FAILURE (status)) {
  137. acpi_os_printf ("****Could not get pathname****)");
  138. goto exit;
  139. }
  140. acpi_os_printf (" (Path %s)", buffer);
  141. exit:
  142. /* Restore the debug level */
  143. acpi_dbg_level = debug_level;
  144. return (status);
  145. }
  146. #endif
  147. /*******************************************************************************
  148.  *
  149.  * FUNCTION:    Acpi_db_display_op
  150.  *
  151.  * PARAMETERS:  Origin          - Starting object
  152.  *              Num_opcodes     - Max number of opcodes to be displayed
  153.  *
  154.  * RETURN:      None
  155.  *
  156.  * DESCRIPTION: Display parser object and its children
  157.  *
  158.  ******************************************************************************/
  159. void
  160. acpi_db_display_op (
  161. acpi_walk_state         *walk_state,
  162. acpi_parse_object       *origin,
  163. u32                     num_opcodes)
  164. {
  165. acpi_parse_object       *op = origin;
  166. acpi_parse_object       *arg;
  167. acpi_parse_object       *depth;
  168. u32                     depth_count = 0;
  169. u32                     last_depth = 0;
  170. u32                     i;
  171. u32                     j;
  172. if (op) {
  173. while (op) {
  174. /* indentation */
  175. depth_count = 0;
  176. if (!acpi_gbl_db_opt_verbose) {
  177. depth_count++;
  178. }
  179. /* Determine the nesting depth of this argument */
  180. for (depth = op->parent; depth; depth = depth->parent) {
  181. arg = acpi_ps_get_arg (depth, 0);
  182. while (arg && arg != origin) {
  183. arg = arg->next;
  184. }
  185. if (arg) {
  186. break;
  187. }
  188. depth_count++;
  189. }
  190. /* Open a new block if we are nested further than last time */
  191. if (depth_count > last_depth) {
  192. VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth));
  193. for (i = 0; i < last_depth; i++) {
  194. acpi_os_printf ("%s", acpi_gbl_db_disasm_indent);
  195. }
  196. if (acpi_db_block_type (op) == BLOCK_PAREN) {
  197. acpi_os_printf ("(n");
  198. }
  199. else {
  200. acpi_os_printf ("{n");
  201. }
  202. }
  203. /* Close a block if we are nested less than last time */
  204. else if (depth_count < last_depth) {
  205. for (j = 0; j < (last_depth - depth_count); j++) {
  206. VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth - j));
  207. for (i = 0; i < (last_depth - j - 1); i++) {
  208. acpi_os_printf ("%s", acpi_gbl_db_disasm_indent);
  209. }
  210. if (acpi_db_block_type (op) == BLOCK_PAREN) {
  211. acpi_os_printf (")n");
  212. }
  213. else {
  214. acpi_os_printf ("}n");
  215. }
  216. }
  217. }
  218. /* In verbose mode, print the AML offset, opcode and depth count */
  219. VERBOSE_PRINT ((DB_FULL_OP_INFO, (unsigned) op->aml_offset, op->opcode, depth_count));
  220. /* Indent the output according to the depth count */
  221. for (i = 0; i < depth_count; i++) {
  222. acpi_os_printf ("%s", acpi_gbl_db_disasm_indent);
  223. }
  224. /* Now print the opcode */
  225. acpi_db_display_opcode (walk_state, op);
  226. /* Resolve a name reference */
  227. if ((op->opcode == AML_INT_NAMEPATH_OP && op->value.name)  &&
  228. (op->parent) &&
  229. (acpi_gbl_db_opt_verbose)) {
  230. acpi_ps_display_object_pathname (walk_state, op);
  231. }
  232. acpi_os_printf ("n");
  233. /* Get the next node in the tree */
  234. op = acpi_ps_get_depth_next (origin, op);
  235. last_depth = depth_count;
  236. num_opcodes--;
  237. if (!num_opcodes) {
  238. op = NULL;
  239. }
  240. }
  241. /* Close the last block(s) */
  242. depth_count = last_depth -1;
  243. for (i = 0; i < last_depth; i++) {
  244. VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth - i));
  245. for (j = 0; j < depth_count; j++) {
  246. acpi_os_printf ("%s", acpi_gbl_db_disasm_indent);
  247. }
  248. acpi_os_printf ("}n");
  249. depth_count--;
  250. }
  251. }
  252. else {
  253. acpi_db_display_opcode (walk_state, op);
  254. }
  255. }
  256. /*******************************************************************************
  257.  *
  258.  * FUNCTION:    Acpi_db_display_namestring
  259.  *
  260.  * PARAMETERS:  Name                - ACPI Name string to store
  261.  *
  262.  * RETURN:      None
  263.  *
  264.  * DESCRIPTION: Display namestring. Handles prefix characters
  265.  *
  266.  ******************************************************************************/
  267. void
  268. acpi_db_display_namestring (
  269. NATIVE_CHAR             *name)
  270. {
  271. u32                     seg_count;
  272. u8                      do_dot = FALSE;
  273. if (!name) {
  274. acpi_os_printf ("<NULL NAME PTR>");
  275. return;
  276. }
  277. if (acpi_ps_is_prefix_char (GET8 (name))) {
  278. /* append prefix character */
  279. acpi_os_printf ("%1c", GET8 (name));
  280. name++;
  281. }
  282. switch (GET8 (name)) {
  283. case AML_DUAL_NAME_PREFIX:
  284. seg_count = 2;
  285. name++;
  286. break;
  287. case AML_MULTI_NAME_PREFIX_OP:
  288. seg_count = (u32) GET8 (name + 1);
  289. name += 2;
  290. break;
  291. default:
  292. seg_count = 1;
  293. break;
  294. }
  295. while (seg_count--) {
  296. /* append Name segment */
  297. if (do_dot) {
  298. /* append dot */
  299. acpi_os_printf (".");
  300. }
  301. acpi_os_printf ("%4.4s", name);
  302. do_dot = TRUE;
  303. name += 4;
  304. }
  305. }
  306. /*******************************************************************************
  307.  *
  308.  * FUNCTION:    Acpi_db_display_path
  309.  *
  310.  * PARAMETERS:  Op                  - Named Op whose path is to be constructed
  311.  *
  312.  * RETURN:      None
  313.  *
  314.  * DESCRIPTION: Walk backwards from current scope and display the name
  315.  *              of each previous level of scope up to the root scope
  316.  *              (like "pwd" does with file systems)
  317.  *
  318.  ******************************************************************************/
  319. void
  320. acpi_db_display_path (
  321. acpi_parse_object       *op)
  322. {
  323. acpi_parse_object       *prev;
  324. acpi_parse_object       *search;
  325. u32                     name;
  326. u8                      do_dot = FALSE;
  327. acpi_parse_object       *name_path;
  328. const acpi_opcode_info  *op_info;
  329. /* We are only interested in named objects */
  330. op_info = acpi_ps_get_opcode_info (op->opcode);
  331. if (!(op_info->flags & AML_NSNODE)) {
  332. return;
  333. }
  334. if (op_info->flags & AML_CREATE) {
  335. /* Field creation - check for a fully qualified namepath */
  336. if (op->opcode == AML_CREATE_FIELD_OP) {
  337. name_path = acpi_ps_get_arg (op, 3);
  338. }
  339. else {
  340. name_path = acpi_ps_get_arg (op, 2);
  341. }
  342. if ((name_path) &&
  343. (name_path->value.string) &&
  344. (name_path->value.string[0] == '\')) {
  345. acpi_db_display_namestring (name_path->value.string);
  346. return;
  347. }
  348. }
  349. prev = NULL;            /* Start with Root Node */
  350. while (prev != op) {
  351. /* Search upwards in the tree to find scope with "prev" as its parent */
  352. search = op;
  353. for (; ;) {
  354. if (search->parent == prev) {
  355. break;
  356. }
  357. /* Go up one level */
  358. search = search->parent;
  359. }
  360. if (prev) {
  361. op_info = acpi_ps_get_opcode_info (search->opcode);
  362. if (!(op_info->flags & AML_FIELD)) {
  363. /* below root scope, append scope name */
  364. if (do_dot) {
  365. /* append dot */
  366. acpi_os_printf (".");
  367. }
  368. if (op_info->flags & AML_CREATE) {
  369. if (op->opcode == AML_CREATE_FIELD_OP) {
  370. name_path = acpi_ps_get_arg (op, 3);
  371. }
  372. else {
  373. name_path = acpi_ps_get_arg (op, 2);
  374. }
  375. if ((name_path) &&
  376. (name_path->value.string)) {
  377. acpi_os_printf ("%4.4s", name_path->value.string);
  378. }
  379. }
  380. else {
  381. name = acpi_ps_get_name (search);
  382. acpi_os_printf ("%4.4s", &name);
  383. }
  384. do_dot = TRUE;
  385. }
  386. }
  387. prev = search;
  388. }
  389. }
  390. /*******************************************************************************
  391.  *
  392.  * FUNCTION:    Acpi_db_display_opcode
  393.  *
  394.  * PARAMETERS:  Op                  - Op that is to be printed
  395.  *
  396.  * RETURN:      Status
  397.  *
  398.  * DESCRIPTION: Store printed op in a Buffer and return its length
  399.  *              (or -1 if out of space)
  400.  *
  401.  * NOTE: Terse mode prints out ASL-like code.  Verbose mode adds more info.
  402.  *
  403.  ******************************************************************************/
  404. void
  405. acpi_db_display_opcode (
  406. acpi_walk_state         *walk_state,
  407. acpi_parse_object       *op)
  408. {
  409. u8                      *byte_data;
  410. u32                     byte_count;
  411. u32                     i;
  412. const acpi_opcode_info  *op_info = NULL;
  413. u32                     name;
  414. if (!op) {
  415. acpi_os_printf ("<NULL OP PTR>");
  416. }
  417. /* op and arguments */
  418. switch (op->opcode) {
  419. case AML_BYTE_OP:
  420. if (acpi_gbl_db_opt_verbose) {
  421. acpi_os_printf ("(u8) 0x%2.2X", op->value.integer8);
  422. }
  423. else {
  424. acpi_os_printf ("0x%2.2X", op->value.integer8);
  425. }
  426. break;
  427. case AML_WORD_OP:
  428. if (acpi_gbl_db_opt_verbose) {
  429. acpi_os_printf ("(u16) 0x%4.4X", op->value.integer16);
  430. }
  431. else {
  432. acpi_os_printf ("0x%4.4X", op->value.integer16);
  433. }
  434. break;
  435. case AML_DWORD_OP:
  436. if (acpi_gbl_db_opt_verbose) {
  437. acpi_os_printf ("(u32) 0x%8.8X", op->value.integer32);
  438. }
  439. else {
  440. acpi_os_printf ("0x%8.8X", op->value.integer32);
  441. }
  442. break;
  443. case AML_QWORD_OP:
  444. if (acpi_gbl_db_opt_verbose) {
  445. acpi_os_printf ("(u64) 0x%8.8X%8.8X", op->value.integer64.hi,
  446.  op->value.integer64.lo);
  447. }
  448. else {
  449. acpi_os_printf ("0x%8.8X%8.8X", op->value.integer64.hi,
  450.  op->value.integer64.lo);
  451. }
  452. break;
  453. case AML_STRING_OP:
  454. if (op->value.string) {
  455. acpi_os_printf (""%s"", op->value.string);
  456. }
  457. else {
  458. acpi_os_printf ("<"NULL STRING PTR">");
  459. }
  460. break;
  461. case AML_INT_STATICSTRING_OP:
  462. if (op->value.string) {
  463. acpi_os_printf (""%s"", op->value.string);
  464. }
  465. else {
  466. acpi_os_printf (""<NULL STATIC STRING PTR>"");
  467. }
  468. break;
  469. case AML_INT_NAMEPATH_OP:
  470. acpi_db_display_namestring (op->value.name);
  471. break;
  472. case AML_INT_NAMEDFIELD_OP:
  473. acpi_os_printf ("Named_field (Length 0x%8.8X)  ", op->value.integer32);
  474. break;
  475. case AML_INT_RESERVEDFIELD_OP:
  476. acpi_os_printf ("Reserved_field (Length 0x%8.8X) ", op->value.integer32);
  477. break;
  478. case AML_INT_ACCESSFIELD_OP:
  479. acpi_os_printf ("Access_field (Length 0x%8.8X) ", op->value.integer32);
  480. break;
  481. case AML_INT_BYTELIST_OP:
  482. if (acpi_gbl_db_opt_verbose) {
  483. acpi_os_printf ("Byte_list   (Length 0x%8.8X)  ", op->value.integer32);
  484. }
  485. else {
  486. acpi_os_printf ("0x%2.2X", op->value.integer32);
  487. byte_count = op->value.integer32;
  488. byte_data = ((acpi_parse2_object *) op)->data;
  489. for (i = 0; i < byte_count; i++) {
  490. acpi_os_printf (", 0x%2.2X", byte_data[i]);
  491. }
  492. }
  493. break;
  494. default:
  495. /* Just get the opcode name and print it */
  496. op_info = acpi_ps_get_opcode_info (op->opcode);
  497. acpi_os_printf ("%s", op_info->name);
  498. #ifndef PARSER_ONLY
  499. if ((op->opcode == AML_INT_RETURN_VALUE_OP) &&
  500. (walk_state->results) &&
  501. (walk_state->results->results.num_results)) {
  502. acpi_db_decode_internal_object (walk_state->results->results.obj_desc [walk_state->results->results.num_results-1]);
  503. }
  504. #endif
  505. break;
  506. }
  507. if (!op_info) {
  508. /* If there is another element in the list, add a comma */
  509. if (op->next) {
  510. acpi_os_printf (",");
  511. }
  512. }
  513. /*
  514.  * If this is a named opcode, print the associated name value
  515.  */
  516. op_info = acpi_ps_get_opcode_info (op->opcode);
  517. if (op && (op_info->flags & AML_NAMED)) {
  518. name = acpi_ps_get_name (op);
  519. acpi_os_printf (" %4.4s", &name);
  520. if (acpi_gbl_db_opt_verbose) {
  521. acpi_os_printf (" (Path \");
  522. acpi_db_display_path (op);
  523. acpi_os_printf (")");
  524. }
  525. }
  526. }
  527. #endif  /* ENABLE_DEBUGGER */