nsload.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /******************************************************************************
  2. *
  3. * Module Name: nsload - namespace loading/expanding/contracting procedures
  4. *
  5. *****************************************************************************/
  6. /*
  7. * Copyright (C) 2000 - 2005, R. Byron Moore
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions, and the following disclaimer,
  15. * without modification.
  16. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  17. * substantially similar to the "NO WARRANTY" disclaimer below
  18. * ("Disclaimer") and any redistribution must be conditioned upon
  19. * including a substantially similar Disclaimer requirement for further
  20. * binary redistribution.
  21. * 3. Neither the names of the above-listed copyright holders nor the names
  22. * of any contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * Alternatively, this software may be distributed under the terms of the
  26. * GNU General Public License ("GPL") version 2 as published by the Free
  27. * Software Foundation.
  28. *
  29. * NO WARRANTY
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  33. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  34. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  38. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  39. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGES.
  41. */
  42. #include <acpi/acpi.h>
  43. #include <acpi/acnamesp.h>
  44. #include <acpi/acdispat.h>
  45. #define _COMPONENT ACPI_NAMESPACE
  46. ACPI_MODULE_NAME ("nsload")
  47. #ifndef ACPI_NO_METHOD_EXECUTION
  48. /*******************************************************************************
  49. *
  50. * FUNCTION: acpi_ns_load_table
  51. *
  52. * PARAMETERS: table_desc - Descriptor for table to be loaded
  53. * Node - Owning NS node
  54. *
  55. * RETURN: Status
  56. *
  57. * DESCRIPTION: Load one ACPI table into the namespace
  58. *
  59. ******************************************************************************/
  60. acpi_status
  61. acpi_ns_load_table (
  62. struct acpi_table_desc *table_desc,
  63. struct acpi_namespace_node *node)
  64. {
  65. acpi_status status;
  66. ACPI_FUNCTION_TRACE ("ns_load_table");
  67. /* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */
  68. if (!(acpi_gbl_table_data[table_desc->type].flags & ACPI_TABLE_EXECUTABLE)) {
  69. /* Just ignore this table */
  70. return_ACPI_STATUS (AE_OK);
  71. }
  72. /* Check validity of the AML start and length */
  73. if (!table_desc->aml_start) {
  74. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null AML pointer\n"));
  75. return_ACPI_STATUS (AE_BAD_PARAMETER);
  76. }
  77. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AML block at %p\n",
  78. table_desc->aml_start));
  79. /* Ignore table if there is no AML contained within */
  80. if (!table_desc->aml_length) {
  81. ACPI_REPORT_WARNING (("Zero-length AML block in table [%4.4s]\n",
  82. table_desc->pointer->signature));
  83. return_ACPI_STATUS (AE_OK);
  84. }
  85. /*
  86. * Parse the table and load the namespace with all named
  87. * objects found within. Control methods are NOT parsed
  88. * at this time. In fact, the control methods cannot be
  89. * parsed until the entire namespace is loaded, because
  90. * if a control method makes a forward reference (call)
  91. * to another control method, we can't continue parsing
  92. * because we don't know how many arguments to parse next!
  93. */
  94. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  95. "**** Loading table into namespace ****\n"));
  96. status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
  97. if (ACPI_FAILURE (status)) {
  98. return_ACPI_STATUS (status);
  99. }
  100. status = acpi_ns_parse_table (table_desc, node->child);
  101. (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
  102. if (ACPI_FAILURE (status)) {
  103. return_ACPI_STATUS (status);
  104. }
  105. /*
  106. * Now we can parse the control methods. We always parse
  107. * them here for a sanity check, and if configured for
  108. * just-in-time parsing, we delete the control method
  109. * parse trees.
  110. */
  111. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  112. "**** Begin Table Method Parsing and Object Initialization ****\n"));
  113. status = acpi_ds_initialize_objects (table_desc, node);
  114. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  115. "**** Completed Table Method Parsing and Object Initialization ****\n"));
  116. return_ACPI_STATUS (status);
  117. }
  118. /*******************************************************************************
  119. *
  120. * FUNCTION: acpi_ns_load_table_by_type
  121. *
  122. * PARAMETERS: table_type - Id of the table type to load
  123. *
  124. * RETURN: Status
  125. *
  126. * DESCRIPTION: Load an ACPI table or tables into the namespace. All tables
  127. * of the given type are loaded. The mechanism allows this
  128. * routine to be called repeatedly.
  129. *
  130. ******************************************************************************/
  131. acpi_status
  132. acpi_ns_load_table_by_type (
  133. acpi_table_type table_type)
  134. {
  135. u32 i;
  136. acpi_status status;
  137. struct acpi_table_desc *table_desc;
  138. ACPI_FUNCTION_TRACE ("ns_load_table_by_type");
  139. status = acpi_ut_acquire_mutex (ACPI_MTX_TABLES);
  140. if (ACPI_FAILURE (status)) {
  141. return_ACPI_STATUS (status);
  142. }
  143. /*
  144. * Table types supported are:
  145. * DSDT (one), SSDT/PSDT (multiple)
  146. */
  147. switch (table_type) {
  148. case ACPI_TABLE_DSDT:
  149. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading DSDT\n"));
  150. table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next;
  151. /* If table already loaded into namespace, just return */
  152. if (table_desc->loaded_into_namespace) {
  153. goto unlock_and_exit;
  154. }
  155. /* Now load the single DSDT */
  156. status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
  157. if (ACPI_SUCCESS (status)) {
  158. table_desc->loaded_into_namespace = TRUE;
  159. }
  160. break;
  161. case ACPI_TABLE_SSDT:
  162. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d SSDTs\n",
  163. acpi_gbl_table_lists[ACPI_TABLE_SSDT].count));
  164. /*
  165. * Traverse list of SSDT tables
  166. */
  167. table_desc = acpi_gbl_table_lists[ACPI_TABLE_SSDT].next;
  168. for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_SSDT].count; i++) {
  169. /*
  170. * Only attempt to load table if it is not
  171. * already loaded!
  172. */
  173. if (!table_desc->loaded_into_namespace) {
  174. status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
  175. if (ACPI_FAILURE (status)) {
  176. break;
  177. }
  178. table_desc->loaded_into_namespace = TRUE;
  179. }
  180. table_desc = table_desc->next;
  181. }
  182. break;
  183. case ACPI_TABLE_PSDT:
  184. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d PSDTs\n",
  185. acpi_gbl_table_lists[ACPI_TABLE_PSDT].count));
  186. /*
  187. * Traverse list of PSDT tables
  188. */
  189. table_desc = acpi_gbl_table_lists[ACPI_TABLE_PSDT].next;
  190. for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_PSDT].count; i++) {
  191. /* Only attempt to load table if it is not already loaded! */
  192. if (!table_desc->loaded_into_namespace) {
  193. status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
  194. if (ACPI_FAILURE (status)) {
  195. break;
  196. }
  197. table_desc->loaded_into_namespace = TRUE;
  198. }
  199. table_desc = table_desc->next;
  200. }
  201. break;
  202. default:
  203. status = AE_SUPPORT;
  204. break;
  205. }
  206. unlock_and_exit:
  207. (void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
  208. return_ACPI_STATUS (status);
  209. }
  210. /*******************************************************************************
  211. *
  212. * FUNCTION: acpi_load_namespace
  213. *
  214. * PARAMETERS: None
  215. *
  216. * RETURN: Status
  217. *
  218. * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
  219. * (DSDT points to either the BIOS or a buffer.)
  220. *
  221. ******************************************************************************/
  222. acpi_status
  223. acpi_ns_load_namespace (
  224. void)
  225. {
  226. acpi_status status;
  227. ACPI_FUNCTION_TRACE ("acpi_load_name_space");
  228. /* There must be at least a DSDT installed */
  229. if (acpi_gbl_DSDT == NULL) {
  230. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "DSDT is not in memory\n"));
  231. return_ACPI_STATUS (AE_NO_ACPI_TABLES);
  232. }
  233. /*
  234. * Load the namespace. The DSDT is required,
  235. * but the SSDT and PSDT tables are optional.
  236. */
  237. status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT);
  238. if (ACPI_FAILURE (status)) {
  239. return_ACPI_STATUS (status);
  240. }
  241. /* Ignore exceptions from these */
  242. (void) acpi_ns_load_table_by_type (ACPI_TABLE_SSDT);
  243. (void) acpi_ns_load_table_by_type (ACPI_TABLE_PSDT);
  244. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
  245. "ACPI Namespace successfully loaded at root %p\n",
  246. acpi_gbl_root_node));
  247. return_ACPI_STATUS (status);
  248. }
  249. #ifdef ACPI_FUTURE_USAGE
  250. /*******************************************************************************
  251. *
  252. * FUNCTION: acpi_ns_delete_subtree
  253. *
  254. * PARAMETERS: start_handle - Handle in namespace where search begins
  255. *
  256. * RETURNS Status
  257. *
  258. * DESCRIPTION: Walks the namespace starting at the given handle and deletes
  259. * all objects, entries, and scopes in the entire subtree.
  260. *
  261. * Namespace/Interpreter should be locked or the subsystem should
  262. * be in shutdown before this routine is called.
  263. *
  264. ******************************************************************************/
  265. acpi_status
  266. acpi_ns_delete_subtree (
  267. acpi_handle start_handle)
  268. {
  269. acpi_status status;
  270. acpi_handle child_handle;
  271. acpi_handle parent_handle;
  272. acpi_handle next_child_handle;
  273. acpi_handle dummy;
  274. u32 level;
  275. ACPI_FUNCTION_TRACE ("ns_delete_subtree");
  276. parent_handle = start_handle;
  277. child_handle = NULL;
  278. level = 1;
  279. /*
  280. * Traverse the tree of objects until we bubble back up
  281. * to where we started.
  282. */
  283. while (level > 0) {
  284. /* Attempt to get the next object in this scope */
  285. status = acpi_get_next_object (ACPI_TYPE_ANY, parent_handle,
  286. child_handle, &next_child_handle);
  287. child_handle = next_child_handle;
  288. /* Did we get a new object? */
  289. if (ACPI_SUCCESS (status)) {
  290. /* Check if this object has any children */
  291. if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, child_handle,
  292. NULL, &dummy))) {
  293. /*
  294. * There is at least one child of this object,
  295. * visit the object
  296. */
  297. level++;
  298. parent_handle = child_handle;
  299. child_handle = NULL;
  300. }
  301. }
  302. else {
  303. /*
  304. * No more children in this object, go back up to
  305. * the object's parent
  306. */
  307. level--;
  308. /* Delete all children now */
  309. acpi_ns_delete_children (child_handle);
  310. child_handle = parent_handle;
  311. status = acpi_get_parent (parent_handle, &parent_handle);
  312. if (ACPI_FAILURE (status)) {
  313. return_ACPI_STATUS (status);
  314. }
  315. }
  316. }
  317. /* Now delete the starting object, and we are done */
  318. acpi_ns_delete_node (child_handle);
  319. return_ACPI_STATUS (AE_OK);
  320. }
  321. /*******************************************************************************
  322. *
  323. * FUNCTION: acpi_ns_unload_name_space
  324. *
  325. * PARAMETERS: Handle - Root of namespace subtree to be deleted
  326. *
  327. * RETURN: Status
  328. *
  329. * DESCRIPTION: Shrinks the namespace, typically in response to an undocking
  330. * event. Deletes an entire subtree starting from (and
  331. * including) the given handle.
  332. *
  333. ******************************************************************************/
  334. acpi_status
  335. acpi_ns_unload_namespace (
  336. acpi_handle handle)
  337. {
  338. acpi_status status;
  339. ACPI_FUNCTION_TRACE ("ns_unload_name_space");
  340. /* Parameter validation */
  341. if (!acpi_gbl_root_node) {
  342. return_ACPI_STATUS (AE_NO_NAMESPACE);
  343. }
  344. if (!handle) {
  345. return_ACPI_STATUS (AE_BAD_PARAMETER);
  346. }
  347. /* This function does the real work */
  348. status = acpi_ns_delete_subtree (handle);
  349. return_ACPI_STATUS (status);
  350. }
  351. #endif /* ACPI_FUTURE_USAGE */
  352. #endif