nsxfname.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /******************************************************************************
  2. *
  3. * Module Name: nsxfname - Public interfaces to the ACPI subsystem
  4. * ACPI Namespace oriented interfaces
  5. *
  6. *****************************************************************************/
  7. /*
  8. * Copyright (C) 2000 - 2008, Intel Corp.
  9. * All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions, and the following disclaimer,
  16. * without modification.
  17. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18. * substantially similar to the "NO WARRANTY" disclaimer below
  19. * ("Disclaimer") and any redistribution must be conditioned upon
  20. * including a substantially similar Disclaimer requirement for further
  21. * binary redistribution.
  22. * 3. Neither the names of the above-listed copyright holders nor the names
  23. * of any contributors may be used to endorse or promote products derived
  24. * from this software without specific prior written permission.
  25. *
  26. * Alternatively, this software may be distributed under the terms of the
  27. * GNU General Public License ("GPL") version 2 as published by the Free
  28. * Software Foundation.
  29. *
  30. * NO WARRANTY
  31. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41. * POSSIBILITY OF SUCH DAMAGES.
  42. */
  43. #include <acpi/acpi.h>
  44. #include "accommon.h"
  45. #include "acnamesp.h"
  46. #include "acparser.h"
  47. #include "amlcode.h"
  48. #define _COMPONENT ACPI_NAMESPACE
  49. ACPI_MODULE_NAME("nsxfname")
  50. /******************************************************************************
  51. *
  52. * FUNCTION: acpi_get_handle
  53. *
  54. * PARAMETERS: Parent - Object to search under (search scope).
  55. * Pathname - Pointer to an asciiz string containing the
  56. * name
  57. * ret_handle - Where the return handle is returned
  58. *
  59. * RETURN: Status
  60. *
  61. * DESCRIPTION: This routine will search for a caller specified name in the
  62. * name space. The caller can restrict the search region by
  63. * specifying a non NULL parent. The parent value is itself a
  64. * namespace handle.
  65. *
  66. ******************************************************************************/
  67. acpi_status
  68. acpi_get_handle(acpi_handle parent,
  69. acpi_string pathname, acpi_handle * ret_handle)
  70. {
  71. acpi_status status;
  72. struct acpi_namespace_node *node = NULL;
  73. struct acpi_namespace_node *prefix_node = NULL;
  74. ACPI_FUNCTION_ENTRY();
  75. /* Parameter Validation */
  76. if (!ret_handle || !pathname) {
  77. return (AE_BAD_PARAMETER);
  78. }
  79. /* Convert a parent handle to a prefix node */
  80. if (parent) {
  81. prefix_node = acpi_ns_map_handle_to_node(parent);
  82. if (!prefix_node) {
  83. return (AE_BAD_PARAMETER);
  84. }
  85. }
  86. /*
  87. * Valid cases are:
  88. * 1) Fully qualified pathname
  89. * 2) Parent + Relative pathname
  90. *
  91. * Error for <null Parent + relative path>
  92. */
  93. if (acpi_ns_valid_root_prefix(pathname[0])) {
  94. /* Pathname is fully qualified (starts with '\') */
  95. /* Special case for root-only, since we can't search for it */
  96. if (!ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH)) {
  97. *ret_handle =
  98. acpi_ns_convert_entry_to_handle(acpi_gbl_root_node);
  99. return (AE_OK);
  100. }
  101. } else if (!prefix_node) {
  102. /* Relative path with null prefix is disallowed */
  103. return (AE_BAD_PARAMETER);
  104. }
  105. /* Find the Node and convert to a handle */
  106. status =
  107. acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node);
  108. if (ACPI_SUCCESS(status)) {
  109. *ret_handle = acpi_ns_convert_entry_to_handle(node);
  110. }
  111. return (status);
  112. }
  113. ACPI_EXPORT_SYMBOL(acpi_get_handle)
  114. /******************************************************************************
  115. *
  116. * FUNCTION: acpi_get_name
  117. *
  118. * PARAMETERS: Handle - Handle to be converted to a pathname
  119. * name_type - Full pathname or single segment
  120. * Buffer - Buffer for returned path
  121. *
  122. * RETURN: Pointer to a string containing the fully qualified Name.
  123. *
  124. * DESCRIPTION: This routine returns the fully qualified name associated with
  125. * the Handle parameter. This and the acpi_pathname_to_handle are
  126. * complementary functions.
  127. *
  128. ******************************************************************************/
  129. acpi_status
  130. acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
  131. {
  132. acpi_status status;
  133. struct acpi_namespace_node *node;
  134. /* Parameter validation */
  135. if (name_type > ACPI_NAME_TYPE_MAX) {
  136. return (AE_BAD_PARAMETER);
  137. }
  138. status = acpi_ut_validate_buffer(buffer);
  139. if (ACPI_FAILURE(status)) {
  140. return (status);
  141. }
  142. if (name_type == ACPI_FULL_PATHNAME) {
  143. /* Get the full pathname (From the namespace root) */
  144. status = acpi_ns_handle_to_pathname(handle, buffer);
  145. return (status);
  146. }
  147. /*
  148. * Wants the single segment ACPI name.
  149. * Validate handle and convert to a namespace Node
  150. */
  151. status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  152. if (ACPI_FAILURE(status)) {
  153. return (status);
  154. }
  155. node = acpi_ns_map_handle_to_node(handle);
  156. if (!node) {
  157. status = AE_BAD_PARAMETER;
  158. goto unlock_and_exit;
  159. }
  160. /* Validate/Allocate/Clear caller buffer */
  161. status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH);
  162. if (ACPI_FAILURE(status)) {
  163. goto unlock_and_exit;
  164. }
  165. /* Just copy the ACPI name from the Node and zero terminate it */
  166. ACPI_STRNCPY(buffer->pointer, acpi_ut_get_node_name(node),
  167. ACPI_NAME_SIZE);
  168. ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
  169. status = AE_OK;
  170. unlock_and_exit:
  171. (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  172. return (status);
  173. }
  174. ACPI_EXPORT_SYMBOL(acpi_get_name)
  175. /******************************************************************************
  176. *
  177. * FUNCTION: acpi_get_object_info
  178. *
  179. * PARAMETERS: Handle - Object Handle
  180. * Buffer - Where the info is returned
  181. *
  182. * RETURN: Status
  183. *
  184. * DESCRIPTION: Returns information about an object as gleaned from the
  185. * namespace node and possibly by running several standard
  186. * control methods (Such as in the case of a device.)
  187. *
  188. ******************************************************************************/
  189. acpi_status
  190. acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
  191. {
  192. acpi_status status;
  193. struct acpi_namespace_node *node;
  194. struct acpi_device_info *info;
  195. struct acpi_device_info *return_info;
  196. struct acpi_compatible_id_list *cid_list = NULL;
  197. acpi_size size;
  198. /* Parameter validation */
  199. if (!handle || !buffer) {
  200. return (AE_BAD_PARAMETER);
  201. }
  202. status = acpi_ut_validate_buffer(buffer);
  203. if (ACPI_FAILURE(status)) {
  204. return (status);
  205. }
  206. info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info));
  207. if (!info) {
  208. return (AE_NO_MEMORY);
  209. }
  210. status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  211. if (ACPI_FAILURE(status)) {
  212. goto cleanup;
  213. }
  214. node = acpi_ns_map_handle_to_node(handle);
  215. if (!node) {
  216. (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  217. status = AE_BAD_PARAMETER;
  218. goto cleanup;
  219. }
  220. /* Init return structure */
  221. size = sizeof(struct acpi_device_info);
  222. info->type = node->type;
  223. info->name = node->name.integer;
  224. info->valid = 0;
  225. if (node->type == ACPI_TYPE_METHOD) {
  226. info->param_count = node->object->method.param_count;
  227. }
  228. status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  229. if (ACPI_FAILURE(status)) {
  230. goto cleanup;
  231. }
  232. /* If not a device, we are all done */
  233. if (info->type == ACPI_TYPE_DEVICE) {
  234. /*
  235. * Get extra info for ACPI Devices objects only:
  236. * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods.
  237. *
  238. * Note: none of these methods are required, so they may or may
  239. * not be present for this device. The Info->Valid bitfield is used
  240. * to indicate which methods were found and ran successfully.
  241. */
  242. /* Execute the Device._HID method */
  243. status = acpi_ut_execute_HID(node, &info->hardware_id);
  244. if (ACPI_SUCCESS(status)) {
  245. info->valid |= ACPI_VALID_HID;
  246. }
  247. /* Execute the Device._UID method */
  248. status = acpi_ut_execute_UID(node, &info->unique_id);
  249. if (ACPI_SUCCESS(status)) {
  250. info->valid |= ACPI_VALID_UID;
  251. }
  252. /* Execute the Device._CID method */
  253. status = acpi_ut_execute_CID(node, &cid_list);
  254. if (ACPI_SUCCESS(status)) {
  255. size += cid_list->size;
  256. info->valid |= ACPI_VALID_CID;
  257. }
  258. /* Execute the Device._STA method */
  259. status = acpi_ut_execute_STA(node, &info->current_status);
  260. if (ACPI_SUCCESS(status)) {
  261. info->valid |= ACPI_VALID_STA;
  262. }
  263. /* Execute the Device._ADR method */
  264. status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node,
  265. &info->address);
  266. if (ACPI_SUCCESS(status)) {
  267. info->valid |= ACPI_VALID_ADR;
  268. }
  269. /* Execute the Device._sx_d methods */
  270. status = acpi_ut_execute_sxds(node, info->highest_dstates);
  271. if (ACPI_SUCCESS(status)) {
  272. info->valid |= ACPI_VALID_SXDS;
  273. }
  274. }
  275. /* Validate/Allocate/Clear caller buffer */
  276. status = acpi_ut_initialize_buffer(buffer, size);
  277. if (ACPI_FAILURE(status)) {
  278. goto cleanup;
  279. }
  280. /* Populate the return buffer */
  281. return_info = buffer->pointer;
  282. ACPI_MEMCPY(return_info, info, sizeof(struct acpi_device_info));
  283. if (cid_list) {
  284. ACPI_MEMCPY(&return_info->compatibility_id, cid_list,
  285. cid_list->size);
  286. }
  287. cleanup:
  288. ACPI_FREE(info);
  289. if (cid_list) {
  290. ACPI_FREE(cid_list);
  291. }
  292. return (status);
  293. }
  294. ACPI_EXPORT_SYMBOL(acpi_get_object_info)
  295. /******************************************************************************
  296. *
  297. * FUNCTION: acpi_install_method
  298. *
  299. * PARAMETERS: Buffer - An ACPI table containing one control method
  300. *
  301. * RETURN: Status
  302. *
  303. * DESCRIPTION: Install a control method into the namespace. If the method
  304. * name already exists in the namespace, it is overwritten. The
  305. * input buffer must contain a valid DSDT or SSDT containing a
  306. * single control method.
  307. *
  308. ******************************************************************************/
  309. acpi_status acpi_install_method(u8 *buffer)
  310. {
  311. struct acpi_table_header *table =
  312. ACPI_CAST_PTR(struct acpi_table_header, buffer);
  313. u8 *aml_buffer;
  314. u8 *aml_start;
  315. char *path;
  316. struct acpi_namespace_node *node;
  317. union acpi_operand_object *method_obj;
  318. struct acpi_parse_state parser_state;
  319. u32 aml_length;
  320. u16 opcode;
  321. u8 method_flags;
  322. acpi_status status;
  323. /* Parameter validation */
  324. if (!buffer) {
  325. return AE_BAD_PARAMETER;
  326. }
  327. /* Table must be a DSDT or SSDT */
  328. if (!ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) &&
  329. !ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) {
  330. return AE_BAD_HEADER;
  331. }
  332. /* First AML opcode in the table must be a control method */
  333. parser_state.aml = buffer + sizeof(struct acpi_table_header);
  334. opcode = acpi_ps_peek_opcode(&parser_state);
  335. if (opcode != AML_METHOD_OP) {
  336. return AE_BAD_PARAMETER;
  337. }
  338. /* Extract method information from the raw AML */
  339. parser_state.aml += acpi_ps_get_opcode_size(opcode);
  340. parser_state.pkg_end = acpi_ps_get_next_package_end(&parser_state);
  341. path = acpi_ps_get_next_namestring(&parser_state);
  342. method_flags = *parser_state.aml++;
  343. aml_start = parser_state.aml;
  344. aml_length = ACPI_PTR_DIFF(parser_state.pkg_end, aml_start);
  345. /*
  346. * Allocate resources up-front. We don't want to have to delete a new
  347. * node from the namespace if we cannot allocate memory.
  348. */
  349. aml_buffer = ACPI_ALLOCATE(aml_length);
  350. if (!aml_buffer) {
  351. return AE_NO_MEMORY;
  352. }
  353. method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
  354. if (!method_obj) {
  355. ACPI_FREE(aml_buffer);
  356. return AE_NO_MEMORY;
  357. }
  358. /* Lock namespace for acpi_ns_lookup, we may be creating a new node */
  359. status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  360. if (ACPI_FAILURE(status)) {
  361. goto error_exit;
  362. }
  363. /* The lookup either returns an existing node or creates a new one */
  364. status =
  365. acpi_ns_lookup(NULL, path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
  366. ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND,
  367. NULL, &node);
  368. (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  369. if (ACPI_FAILURE(status)) { /* ns_lookup */
  370. if (status != AE_ALREADY_EXISTS) {
  371. goto error_exit;
  372. }
  373. /* Node existed previously, make sure it is a method node */
  374. if (node->type != ACPI_TYPE_METHOD) {
  375. status = AE_TYPE;
  376. goto error_exit;
  377. }
  378. }
  379. /* Copy the method AML to the local buffer */
  380. ACPI_MEMCPY(aml_buffer, aml_start, aml_length);
  381. /* Initialize the method object with the new method's information */
  382. method_obj->method.aml_start = aml_buffer;
  383. method_obj->method.aml_length = aml_length;
  384. method_obj->method.param_count = (u8)
  385. (method_flags & AML_METHOD_ARG_COUNT);
  386. method_obj->method.method_flags = (u8)
  387. (method_flags & ~AML_METHOD_ARG_COUNT);
  388. if (method_flags & AML_METHOD_SERIALIZED) {
  389. method_obj->method.sync_level = (u8)
  390. ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
  391. }
  392. /*
  393. * Now that it is complete, we can attach the new method object to
  394. * the method Node (detaches/deletes any existing object)
  395. */
  396. status = acpi_ns_attach_object(node, method_obj, ACPI_TYPE_METHOD);
  397. /*
  398. * Flag indicates AML buffer is dynamic, must be deleted later.
  399. * Must be set only after attach above.
  400. */
  401. node->flags |= ANOBJ_ALLOCATED_BUFFER;
  402. /* Remove local reference to the method object */
  403. acpi_ut_remove_reference(method_obj);
  404. return status;
  405. error_exit:
  406. ACPI_FREE(aml_buffer);
  407. ACPI_FREE(method_obj);
  408. return status;
  409. }
  410. ACPI_EXPORT_SYMBOL(acpi_install_method)