nsnames.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /*******************************************************************************
  3. *
  4. * Module Name: nsnames - Name manipulation and search
  5. *
  6. ******************************************************************************/
  7. #include <acpi/acpi.h>
  8. #include "accommon.h"
  9. #include "amlcode.h"
  10. #include "acnamesp.h"
  11. #define _COMPONENT ACPI_NAMESPACE
  12. ACPI_MODULE_NAME("nsnames")
  13. /*******************************************************************************
  14. *
  15. * FUNCTION: acpi_ns_get_external_pathname
  16. *
  17. * PARAMETERS: node - Namespace node whose pathname is needed
  18. *
  19. * RETURN: Pointer to storage containing the fully qualified name of
  20. * the node, In external format (name segments separated by path
  21. * separators.)
  22. *
  23. * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
  24. * for error and debug statements.
  25. *
  26. ******************************************************************************/
  27. char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
  28. {
  29. char *name_buffer;
  30. ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node);
  31. name_buffer = acpi_ns_get_normalized_pathname(node, FALSE);
  32. return_PTR(name_buffer);
  33. }
  34. /*******************************************************************************
  35. *
  36. * FUNCTION: acpi_ns_get_pathname_length
  37. *
  38. * PARAMETERS: node - Namespace node
  39. *
  40. * RETURN: Length of path, including prefix
  41. *
  42. * DESCRIPTION: Get the length of the pathname string for this node
  43. *
  44. ******************************************************************************/
  45. acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
  46. {
  47. acpi_size size;
  48. /* Validate the Node */
  49. if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
  50. ACPI_ERROR((AE_INFO,
  51. "Invalid/cached reference target node: %p, descriptor type %d",
  52. node, ACPI_GET_DESCRIPTOR_TYPE(node)));
  53. return (0);
  54. }
  55. size = acpi_ns_build_normalized_path(node, NULL, 0, FALSE);
  56. return (size);
  57. }
  58. /*******************************************************************************
  59. *
  60. * FUNCTION: acpi_ns_handle_to_name
  61. *
  62. * PARAMETERS: target_handle - Handle of named object whose name is
  63. * to be found
  64. * buffer - Where the name is returned
  65. *
  66. * RETURN: Status, Buffer is filled with name if status is AE_OK
  67. *
  68. * DESCRIPTION: Build and return a full namespace name
  69. *
  70. ******************************************************************************/
  71. acpi_status
  72. acpi_ns_handle_to_name(acpi_handle target_handle, struct acpi_buffer *buffer)
  73. {
  74. acpi_status status;
  75. struct acpi_namespace_node *node;
  76. const char *node_name;
  77. ACPI_FUNCTION_TRACE_PTR(ns_handle_to_name, target_handle);
  78. node = acpi_ns_validate_handle(target_handle);
  79. if (!node) {
  80. return_ACPI_STATUS(AE_BAD_PARAMETER);
  81. }
  82. /* Validate/Allocate/Clear caller buffer */
  83. status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH);
  84. if (ACPI_FAILURE(status)) {
  85. return_ACPI_STATUS(status);
  86. }
  87. /* Just copy the ACPI name from the Node and zero terminate it */
  88. node_name = acpi_ut_get_node_name(node);
  89. ACPI_COPY_NAMESEG(buffer->pointer, node_name);
  90. ((char *)buffer->pointer)[ACPI_NAMESEG_SIZE] = 0;
  91. ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%4.4s\n", (char *)buffer->pointer));
  92. return_ACPI_STATUS(AE_OK);
  93. }
  94. /*******************************************************************************
  95. *
  96. * FUNCTION: acpi_ns_handle_to_pathname
  97. *
  98. * PARAMETERS: target_handle - Handle of named object whose name is
  99. * to be found
  100. * buffer - Where the pathname is returned
  101. * no_trailing - Remove trailing '_' for each name
  102. * segment
  103. *
  104. * RETURN: Status, Buffer is filled with pathname if status is AE_OK
  105. *
  106. * DESCRIPTION: Build and return a full namespace pathname
  107. *
  108. ******************************************************************************/
  109. acpi_status
  110. acpi_ns_handle_to_pathname(acpi_handle target_handle,
  111. struct acpi_buffer *buffer, u8 no_trailing)
  112. {
  113. acpi_status status;
  114. struct acpi_namespace_node *node;
  115. acpi_size required_size;
  116. ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle);
  117. node = acpi_ns_validate_handle(target_handle);
  118. if (!node) {
  119. return_ACPI_STATUS(AE_BAD_PARAMETER);
  120. }
  121. /* Determine size required for the caller buffer */
  122. required_size =
  123. acpi_ns_build_normalized_path(node, NULL, 0, no_trailing);
  124. if (!required_size) {
  125. return_ACPI_STATUS(AE_BAD_PARAMETER);
  126. }
  127. /* Validate/Allocate/Clear caller buffer */
  128. status = acpi_ut_initialize_buffer(buffer, required_size);
  129. if (ACPI_FAILURE(status)) {
  130. return_ACPI_STATUS(status);
  131. }
  132. /* Build the path in the caller buffer */
  133. (void)acpi_ns_build_normalized_path(node, buffer->pointer,
  134. (u32)required_size, no_trailing);
  135. ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n",
  136. (char *)buffer->pointer, (u32) required_size));
  137. return_ACPI_STATUS(AE_OK);
  138. }
  139. /*******************************************************************************
  140. *
  141. * FUNCTION: acpi_ns_build_normalized_path
  142. *
  143. * PARAMETERS: node - Namespace node
  144. * full_path - Where the path name is returned
  145. * path_size - Size of returned path name buffer
  146. * no_trailing - Remove trailing '_' from each name segment
  147. *
  148. * RETURN: Return 1 if the AML path is empty, otherwise returning (length
  149. * of pathname + 1) which means the 'FullPath' contains a trailing
  150. * null.
  151. *
  152. * DESCRIPTION: Build and return a full namespace pathname.
  153. * Note that if the size of 'FullPath' isn't large enough to
  154. * contain the namespace node's path name, the actual required
  155. * buffer length is returned, and it should be greater than
  156. * 'PathSize'. So callers are able to check the returning value
  157. * to determine the buffer size of 'FullPath'.
  158. *
  159. ******************************************************************************/
  160. u32
  161. acpi_ns_build_normalized_path(struct acpi_namespace_node *node,
  162. char *full_path, u32 path_size, u8 no_trailing)
  163. {
  164. u32 length = 0, i;
  165. char name[ACPI_NAMESEG_SIZE];
  166. u8 do_no_trailing;
  167. char c, *left, *right;
  168. struct acpi_namespace_node *next_node;
  169. ACPI_FUNCTION_TRACE_PTR(ns_build_normalized_path, node);
  170. #define ACPI_PATH_PUT8(path, size, byte, length) \
  171. do { \
  172. if ((length) < (size)) \
  173. { \
  174. (path)[(length)] = (byte); \
  175. } \
  176. (length)++; \
  177. } while (0)
  178. /*
  179. * Make sure the path_size is correct, so that we don't need to
  180. * validate both full_path and path_size.
  181. */
  182. if (!full_path) {
  183. path_size = 0;
  184. }
  185. if (!node) {
  186. goto build_trailing_null;
  187. }
  188. next_node = node;
  189. while (next_node && next_node != acpi_gbl_root_node) {
  190. if (next_node != node) {
  191. ACPI_PATH_PUT8(full_path, path_size,
  192. AML_DUAL_NAME_PREFIX, length);
  193. }
  194. ACPI_MOVE_32_TO_32(name, &next_node->name);
  195. do_no_trailing = no_trailing;
  196. for (i = 0; i < 4; i++) {
  197. c = name[4 - i - 1];
  198. if (do_no_trailing && c != '_') {
  199. do_no_trailing = FALSE;
  200. }
  201. if (!do_no_trailing) {
  202. ACPI_PATH_PUT8(full_path, path_size, c, length);
  203. }
  204. }
  205. next_node = next_node->parent;
  206. }
  207. ACPI_PATH_PUT8(full_path, path_size, AML_ROOT_PREFIX, length);
  208. /* Reverse the path string */
  209. if (length <= path_size) {
  210. left = full_path;
  211. right = full_path + length - 1;
  212. while (left < right) {
  213. c = *left;
  214. *left++ = *right;
  215. *right-- = c;
  216. }
  217. }
  218. /* Append the trailing null */
  219. build_trailing_null:
  220. ACPI_PATH_PUT8(full_path, path_size, '\0', length);
  221. #undef ACPI_PATH_PUT8
  222. return_UINT32(length);
  223. }
  224. /*******************************************************************************
  225. *
  226. * FUNCTION: acpi_ns_get_normalized_pathname
  227. *
  228. * PARAMETERS: node - Namespace node whose pathname is needed
  229. * no_trailing - Remove trailing '_' from each name segment
  230. *
  231. * RETURN: Pointer to storage containing the fully qualified name of
  232. * the node, In external format (name segments separated by path
  233. * separators.)
  234. *
  235. * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
  236. * for error and debug statements. All trailing '_' will be
  237. * removed from the full pathname if 'NoTrailing' is specified..
  238. *
  239. ******************************************************************************/
  240. char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node,
  241. u8 no_trailing)
  242. {
  243. char *name_buffer;
  244. acpi_size size;
  245. ACPI_FUNCTION_TRACE_PTR(ns_get_normalized_pathname, node);
  246. /* Calculate required buffer size based on depth below root */
  247. size = acpi_ns_build_normalized_path(node, NULL, 0, no_trailing);
  248. if (!size) {
  249. return_PTR(NULL);
  250. }
  251. /* Allocate a buffer to be returned to caller */
  252. name_buffer = ACPI_ALLOCATE_ZEROED(size);
  253. if (!name_buffer) {
  254. ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size));
  255. return_PTR(NULL);
  256. }
  257. /* Build the path in the allocated buffer */
  258. (void)acpi_ns_build_normalized_path(node, name_buffer, (u32)size,
  259. no_trailing);
  260. ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES, "%s: Path \"%s\"\n",
  261. ACPI_GET_FUNCTION_NAME, name_buffer));
  262. return_PTR(name_buffer);
  263. }
  264. /*******************************************************************************
  265. *
  266. * FUNCTION: acpi_ns_build_prefixed_pathname
  267. *
  268. * PARAMETERS: prefix_scope - Scope/Path that prefixes the internal path
  269. * internal_path - Name or path of the namespace node
  270. *
  271. * RETURN: None
  272. *
  273. * DESCRIPTION: Construct a fully qualified pathname from a concatenation of:
  274. * 1) Path associated with the prefix_scope namespace node
  275. * 2) External path representation of the Internal path
  276. *
  277. ******************************************************************************/
  278. char *acpi_ns_build_prefixed_pathname(union acpi_generic_state *prefix_scope,
  279. const char *internal_path)
  280. {
  281. acpi_status status;
  282. char *full_path = NULL;
  283. char *external_path = NULL;
  284. char *prefix_path = NULL;
  285. acpi_size prefix_path_length = 0;
  286. /* If there is a prefix, get the pathname to it */
  287. if (prefix_scope && prefix_scope->scope.node) {
  288. prefix_path =
  289. acpi_ns_get_normalized_pathname(prefix_scope->scope.node,
  290. TRUE);
  291. if (prefix_path) {
  292. prefix_path_length = strlen(prefix_path);
  293. }
  294. }
  295. status = acpi_ns_externalize_name(ACPI_UINT32_MAX, internal_path,
  296. NULL, &external_path);
  297. if (ACPI_FAILURE(status)) {
  298. goto cleanup;
  299. }
  300. /* Merge the prefix path and the path. 2 is for one dot and trailing null */
  301. full_path =
  302. ACPI_ALLOCATE_ZEROED(prefix_path_length + strlen(external_path) +
  303. 2);
  304. if (!full_path) {
  305. goto cleanup;
  306. }
  307. /* Don't merge if the External path is already fully qualified */
  308. if (prefix_path && (*external_path != '\\') && (*external_path != '^')) {
  309. strcat(full_path, prefix_path);
  310. if (prefix_path[1]) {
  311. strcat(full_path, ".");
  312. }
  313. }
  314. acpi_ns_normalize_pathname(external_path);
  315. strcat(full_path, external_path);
  316. cleanup:
  317. if (prefix_path) {
  318. ACPI_FREE(prefix_path);
  319. }
  320. if (external_path) {
  321. ACPI_FREE(external_path);
  322. }
  323. return (full_path);
  324. }
  325. /*******************************************************************************
  326. *
  327. * FUNCTION: acpi_ns_normalize_pathname
  328. *
  329. * PARAMETERS: original_path - Path to be normalized, in External format
  330. *
  331. * RETURN: The original path is processed in-place
  332. *
  333. * DESCRIPTION: Remove trailing underscores from each element of a path.
  334. *
  335. * For example: \A___.B___.C___ becomes \A.B.C
  336. *
  337. ******************************************************************************/
  338. void acpi_ns_normalize_pathname(char *original_path)
  339. {
  340. char *input_path = original_path;
  341. char *new_path_buffer;
  342. char *new_path;
  343. u32 i;
  344. /* Allocate a temp buffer in which to construct the new path */
  345. new_path_buffer = ACPI_ALLOCATE_ZEROED(strlen(input_path) + 1);
  346. new_path = new_path_buffer;
  347. if (!new_path_buffer) {
  348. return;
  349. }
  350. /* Special characters may appear at the beginning of the path */
  351. if (*input_path == '\\') {
  352. *new_path = *input_path;
  353. new_path++;
  354. input_path++;
  355. }
  356. while (*input_path == '^') {
  357. *new_path = *input_path;
  358. new_path++;
  359. input_path++;
  360. }
  361. /* Remainder of the path */
  362. while (*input_path) {
  363. /* Do one nameseg at a time */
  364. for (i = 0; (i < ACPI_NAMESEG_SIZE) && *input_path; i++) {
  365. if ((i == 0) || (*input_path != '_')) { /* First char is allowed to be underscore */
  366. *new_path = *input_path;
  367. new_path++;
  368. }
  369. input_path++;
  370. }
  371. /* Dot means that there are more namesegs to come */
  372. if (*input_path == '.') {
  373. *new_path = *input_path;
  374. new_path++;
  375. input_path++;
  376. }
  377. }
  378. *new_path = 0;
  379. strcpy(original_path, new_path_buffer);
  380. ACPI_FREE(new_path_buffer);
  381. }