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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: nsload - namespace loading/expanding/contracting procedures
  4.  *              $Revision: 47 $
  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 "acinterp.h"
  26. #include "acnamesp.h"
  27. #include "amlcode.h"
  28. #include "acparser.h"
  29. #include "acdispat.h"
  30. #include "acdebug.h"
  31. #define _COMPONENT          ACPI_NAMESPACE
  32.  MODULE_NAME         ("nsload")
  33. /*******************************************************************************
  34.  *
  35.  * FUNCTION:    Acpi_load_namespace
  36.  *
  37.  * PARAMETERS:  Display_aml_during_load
  38.  *
  39.  * RETURN:      Status
  40.  *
  41.  * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
  42.  *              (DSDT points to either the BIOS or a buffer.)
  43.  *
  44.  ******************************************************************************/
  45. acpi_status
  46. acpi_ns_load_namespace (
  47. void)
  48. {
  49. acpi_status             status;
  50. FUNCTION_TRACE ("Acpi_load_name_space");
  51. /* There must be at least a DSDT installed */
  52. if (acpi_gbl_DSDT == NULL) {
  53. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "DSDT is not in memoryn"));
  54. return_ACPI_STATUS (AE_NO_ACPI_TABLES);
  55. }
  56. /*
  57.  * Load the namespace.  The DSDT is required,
  58.  * but the SSDT and PSDT tables are optional.
  59.  */
  60. status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT);
  61. if (ACPI_FAILURE (status)) {
  62. return_ACPI_STATUS (status);
  63. }
  64. /* Ignore exceptions from these */
  65. acpi_ns_load_table_by_type (ACPI_TABLE_SSDT);
  66. acpi_ns_load_table_by_type (ACPI_TABLE_PSDT);
  67. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK,
  68. "ACPI Namespace successfully loaded at root %pn",
  69. acpi_gbl_root_node));
  70. return_ACPI_STATUS (status);
  71. }
  72. /*******************************************************************************
  73.  *
  74.  * FUNCTION:    Acpi_ns_one_parse_pass
  75.  *
  76.  * PARAMETERS:
  77.  *
  78.  * RETURN:      Status
  79.  *
  80.  * DESCRIPTION:
  81.  *
  82.  ******************************************************************************/
  83. acpi_status
  84. acpi_ns_one_complete_parse (
  85. u32                     pass_number,
  86. acpi_table_desc         *table_desc)
  87. {
  88. acpi_parse_object       *parse_root;
  89. acpi_status             status;
  90. acpi_walk_state         *walk_state;
  91. FUNCTION_TRACE ("Ns_one_complete_parse");
  92. /* Create and init a Root Node */
  93. parse_root = acpi_ps_alloc_op (AML_SCOPE_OP);
  94. if (!parse_root) {
  95. return_ACPI_STATUS (AE_NO_MEMORY);
  96. }
  97. ((acpi_parse2_object *) parse_root)->name = ACPI_ROOT_NAME;
  98. /* Create and initialize a new walk state */
  99. walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT,
  100.    NULL, NULL, NULL);
  101. if (!walk_state) {
  102. acpi_ps_free_op (parse_root);
  103. return_ACPI_STATUS (AE_NO_MEMORY);
  104. }
  105. status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL, table_desc->aml_start,
  106.   table_desc->aml_length, NULL, NULL, pass_number);
  107. if (ACPI_FAILURE (status)) {
  108. acpi_ds_delete_walk_state (walk_state);
  109. return_ACPI_STATUS (status);
  110. }
  111. /* Parse the AML */
  112. ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "*PARSE* pass %d parsen", pass_number));
  113. status = acpi_ps_parse_aml (walk_state);
  114. acpi_ps_delete_parse_tree (parse_root);
  115. return_ACPI_STATUS (status);
  116. }
  117. /*******************************************************************************
  118.  *
  119.  * FUNCTION:    Acpi_ns_parse_table
  120.  *
  121.  * PARAMETERS:  Table_desc      - An ACPI table descriptor for table to parse
  122.  *              Start_node      - Where to enter the table into the namespace
  123.  *
  124.  * RETURN:      Status
  125.  *
  126.  * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
  127.  *
  128.  ******************************************************************************/
  129. acpi_status
  130. acpi_ns_parse_table (
  131. acpi_table_desc         *table_desc,
  132. acpi_namespace_node     *start_node)
  133. {
  134. acpi_status             status;
  135. FUNCTION_TRACE ("Ns_parse_table");
  136. /*
  137.  * AML Parse, pass 1
  138.  *
  139.  * In this pass, we load most of the namespace.  Control methods
  140.  * are not parsed until later.  A parse tree is not created.  Instead,
  141.  * each Parser Op subtree is deleted when it is finished.  This saves
  142.  * a great deal of memory, and allows a small cache of parse objects
  143.  * to service the entire parse.  The second pass of the parse then
  144.  * performs another complete parse of the AML..
  145.  */
  146. status = acpi_ns_one_complete_parse (1, table_desc);
  147. if (ACPI_FAILURE (status)) {
  148. return_ACPI_STATUS (status);
  149. }
  150. /*
  151.  * AML Parse, pass 2
  152.  *
  153.  * In this pass, we resolve forward references and other things
  154.  * that could not be completed during the first pass.
  155.  * Another complete parse of the AML is performed, but the
  156.  * overhead of this is compensated for by the fact that the
  157.  * parse objects are all cached.
  158.  */
  159. status = acpi_ns_one_complete_parse (2, table_desc);
  160. if (ACPI_FAILURE (status)) {
  161. return_ACPI_STATUS (status);
  162. }
  163. return_ACPI_STATUS (status);
  164. }
  165. /*******************************************************************************
  166.  *
  167.  * FUNCTION:    Acpi_ns_load_table
  168.  *
  169.  * PARAMETERS:  Table_desc      - Descriptor for table to be loaded
  170.  *              Node            - Owning NS node
  171.  *
  172.  * RETURN:      Status
  173.  *
  174.  * DESCRIPTION: Load one ACPI table into the namespace
  175.  *
  176.  ******************************************************************************/
  177. acpi_status
  178. acpi_ns_load_table (
  179. acpi_table_desc         *table_desc,
  180. acpi_namespace_node     *node)
  181. {
  182. acpi_status             status;
  183. FUNCTION_TRACE ("Ns_load_table");
  184. if (!table_desc->aml_start) {
  185. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null AML pointern"));
  186. return_ACPI_STATUS (AE_BAD_PARAMETER);
  187. }
  188. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AML block at %pn", table_desc->aml_start));
  189. if (!table_desc->aml_length) {
  190. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Zero-length AML blockn"));
  191. return_ACPI_STATUS (AE_BAD_PARAMETER);
  192. }
  193. /*
  194.  * Parse the table and load the namespace with all named
  195.  * objects found within.  Control methods are NOT parsed
  196.  * at this time.  In fact, the control methods cannot be
  197.  * parsed until the entire namespace is loaded, because
  198.  * if a control method makes a forward reference (call)
  199.  * to another control method, we can't continue parsing
  200.  * because we don't know how many arguments to parse next!
  201.  */
  202. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Loading table into namespace ****n"));
  203. acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
  204. status = acpi_ns_parse_table (table_desc, node->child);
  205. acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
  206. if (ACPI_FAILURE (status)) {
  207. return_ACPI_STATUS (status);
  208. }
  209. /*
  210.  * Now we can parse the control methods.  We always parse
  211.  * them here for a sanity check, and if configured for
  212.  * just-in-time parsing, we delete the control method
  213.  * parse trees.
  214.  */
  215. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  216. "**** Begin Table Method Parsing and Object Initialization ****n"));
  217. status = acpi_ds_initialize_objects (table_desc, node);
  218. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  219. "**** Completed Table Method Parsing and Object Initialization ****n"));
  220. return_ACPI_STATUS (status);
  221. }
  222. /*******************************************************************************
  223.  *
  224.  * FUNCTION:    Acpi_ns_load_table_by_type
  225.  *
  226.  * PARAMETERS:  Table_type          - Id of the table type to load
  227.  *
  228.  * RETURN:      Status
  229.  *
  230.  * DESCRIPTION: Load an ACPI table or tables into the namespace.  All tables
  231.  *              of the given type are loaded.  The mechanism allows this
  232.  *              routine to be called repeatedly.
  233.  *
  234.  ******************************************************************************/
  235. acpi_status
  236. acpi_ns_load_table_by_type (
  237. acpi_table_type         table_type)
  238. {
  239. u32                     i;
  240. acpi_status             status = AE_OK;
  241. acpi_table_desc         *table_desc;
  242. FUNCTION_TRACE ("Ns_load_table_by_type");
  243. acpi_ut_acquire_mutex (ACPI_MTX_TABLES);
  244. /*
  245.  * Table types supported are:
  246.  * DSDT (one), SSDT/PSDT (multiple)
  247.  */
  248. switch (table_type) {
  249. case ACPI_TABLE_DSDT:
  250. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading DSDTn"));
  251. table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_DSDT];
  252. /* If table already loaded into namespace, just return */
  253. if (table_desc->loaded_into_namespace) {
  254. goto unlock_and_exit;
  255. }
  256. table_desc->table_id = TABLE_ID_DSDT;
  257. /* Now load the single DSDT */
  258. status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
  259. if (ACPI_SUCCESS (status)) {
  260. table_desc->loaded_into_namespace = TRUE;
  261. }
  262. break;
  263. case ACPI_TABLE_SSDT:
  264. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d SSDTsn",
  265. acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count));
  266. /*
  267.  * Traverse list of SSDT tables
  268.  */
  269. table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_SSDT];
  270. for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count; i++) {
  271. /*
  272.  * Only attempt to load table if it is not
  273.  * already loaded!
  274.  */
  275. if (!table_desc->loaded_into_namespace) {
  276. status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
  277. if (ACPI_FAILURE (status)) {
  278. break;
  279. }
  280. table_desc->loaded_into_namespace = TRUE;
  281. }
  282. table_desc = table_desc->next;
  283. }
  284. break;
  285. case ACPI_TABLE_PSDT:
  286. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d PSDTsn",
  287. acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count));
  288. /*
  289.  * Traverse list of PSDT tables
  290.  */
  291. table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_PSDT];
  292. for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count; i++) {
  293. /* Only attempt to load table if it is not already loaded! */
  294. if (!table_desc->loaded_into_namespace) {
  295. status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
  296. if (ACPI_FAILURE (status)) {
  297. break;
  298. }
  299. table_desc->loaded_into_namespace = TRUE;
  300. }
  301. table_desc = table_desc->next;
  302. }
  303. break;
  304. default:
  305. status = AE_SUPPORT;
  306. break;
  307. }
  308. unlock_and_exit:
  309. acpi_ut_release_mutex (ACPI_MTX_TABLES);
  310. return_ACPI_STATUS (status);
  311. }
  312. /*******************************************************************************
  313.  *
  314.  * FUNCTION:    Acpi_ns_delete_subtree
  315.  *
  316.  * PARAMETERS:  Start_handle        - Handle in namespace where search begins
  317.  *
  318.  * RETURNS      Status
  319.  *
  320.  * DESCRIPTION: Walks the namespace starting at the given handle and deletes
  321.  *              all objects, entries, and scopes in the entire subtree.
  322.  *
  323.  *              TBD: [Investigate] What if any part of this subtree is in use?
  324.  *              (i.e. on one of the object stacks?)
  325.  *
  326.  ******************************************************************************/
  327. acpi_status
  328. acpi_ns_delete_subtree (
  329. acpi_handle             start_handle)
  330. {
  331. acpi_status             status;
  332. acpi_handle             child_handle;
  333. acpi_handle             parent_handle;
  334. acpi_handle             next_child_handle;
  335. acpi_handle             dummy;
  336. u32                     level;
  337. FUNCTION_TRACE ("Ns_delete_subtree");
  338. parent_handle = start_handle;
  339. child_handle = 0;
  340. level        = 1;
  341. /*
  342.  * Traverse the tree of objects until we bubble back up
  343.  * to where we started.
  344.  */
  345. while (level > 0) {
  346. /* Attempt to get the next object in this scope */
  347. status = acpi_get_next_object (ACPI_TYPE_ANY, parent_handle,
  348.   child_handle, &next_child_handle);
  349. child_handle = next_child_handle;
  350. /* Did we get a new object? */
  351. if (ACPI_SUCCESS (status)) {
  352. /* Check if this object has any children */
  353. if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, child_handle,
  354.  0, &dummy))) {
  355. /*
  356.  * There is at least one child of this object,
  357.  * visit the object
  358.  */
  359. level++;
  360. parent_handle = child_handle;
  361. child_handle = 0;
  362. }
  363. }
  364. else {
  365. /*
  366.  * No more children in this object, go back up to
  367.  * the object's parent
  368.  */
  369. level--;
  370. /* Delete all children now */
  371. acpi_ns_delete_children (child_handle);
  372. child_handle = parent_handle;
  373. acpi_get_parent (parent_handle, &parent_handle);
  374. }
  375. }
  376. /* Now delete the starting object, and we are done */
  377. acpi_ns_delete_node (child_handle);
  378. return_ACPI_STATUS (AE_OK);
  379. }
  380. /*******************************************************************************
  381.  *
  382.  *  FUNCTION:       Acpi_ns_unload_name_space
  383.  *
  384.  *  PARAMETERS:     Handle          - Root of namespace subtree to be deleted
  385.  *
  386.  *  RETURN:         Status
  387.  *
  388.  *  DESCRIPTION:    Shrinks the namespace, typically in response to an undocking
  389.  *                  event.  Deletes an entire subtree starting from (and
  390.  *                  including) the given handle.
  391.  *
  392.  ******************************************************************************/
  393. acpi_status
  394. acpi_ns_unload_namespace (
  395. acpi_handle             handle)
  396. {
  397. acpi_status             status;
  398. FUNCTION_TRACE ("Ns_unload_name_space");
  399. /* Parameter validation */
  400. if (!acpi_gbl_root_node) {
  401. return_ACPI_STATUS (AE_NO_NAMESPACE);
  402. }
  403. if (!handle) {
  404. return_ACPI_STATUS (AE_BAD_PARAMETER);
  405. }
  406. /* This function does the real work */
  407. status = acpi_ns_delete_subtree (handle);
  408. return_ACPI_STATUS (status);
  409. }