exnames.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Module Name: exnames - interpreter/scanner name load/execute
  5. *
  6. * Copyright (C) 2000 - 2022, Intel Corp.
  7. *
  8. *****************************************************************************/
  9. #include <acpi/acpi.h>
  10. #include "accommon.h"
  11. #include "acinterp.h"
  12. #include "amlcode.h"
  13. #define _COMPONENT ACPI_EXECUTER
  14. ACPI_MODULE_NAME("exnames")
  15. /* Local prototypes */
  16. static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs);
  17. static acpi_status acpi_ex_name_segment(u8 **in_aml_address, char *name_string);
  18. /*******************************************************************************
  19. *
  20. * FUNCTION: acpi_ex_allocate_name_string
  21. *
  22. * PARAMETERS: prefix_count - Count of parent levels. Special cases:
  23. * (-1)==root, 0==none
  24. * num_name_segs - count of 4-character name segments
  25. *
  26. * RETURN: A pointer to the allocated string segment. This segment must
  27. * be deleted by the caller.
  28. *
  29. * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
  30. * string is long enough, and set up prefix if any.
  31. *
  32. ******************************************************************************/
  33. static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
  34. {
  35. char *temp_ptr;
  36. char *name_string;
  37. u32 size_needed;
  38. ACPI_FUNCTION_TRACE(ex_allocate_name_string);
  39. /*
  40. * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix.
  41. * Also, one byte for the null terminator.
  42. * This may actually be somewhat longer than needed.
  43. */
  44. if (prefix_count == ACPI_UINT32_MAX) {
  45. /* Special case for root */
  46. size_needed = 1 + (ACPI_NAMESEG_SIZE * num_name_segs) + 2 + 1;
  47. } else {
  48. size_needed =
  49. prefix_count + (ACPI_NAMESEG_SIZE * num_name_segs) + 2 + 1;
  50. }
  51. /*
  52. * Allocate a buffer for the name.
  53. * This buffer must be deleted by the caller!
  54. */
  55. name_string = ACPI_ALLOCATE(size_needed);
  56. if (!name_string) {
  57. ACPI_ERROR((AE_INFO,
  58. "Could not allocate size %u", size_needed));
  59. return_PTR(NULL);
  60. }
  61. temp_ptr = name_string;
  62. /* Set up Root or Parent prefixes if needed */
  63. if (prefix_count == ACPI_UINT32_MAX) {
  64. *temp_ptr++ = AML_ROOT_PREFIX;
  65. } else {
  66. while (prefix_count--) {
  67. *temp_ptr++ = AML_PARENT_PREFIX;
  68. }
  69. }
  70. /* Set up Dual or Multi prefixes if needed */
  71. if (num_name_segs > 2) {
  72. /* Set up multi prefixes */
  73. *temp_ptr++ = AML_MULTI_NAME_PREFIX;
  74. *temp_ptr++ = (char)num_name_segs;
  75. } else if (2 == num_name_segs) {
  76. /* Set up dual prefixes */
  77. *temp_ptr++ = AML_DUAL_NAME_PREFIX;
  78. }
  79. /*
  80. * Terminate string following prefixes. acpi_ex_name_segment() will
  81. * append the segment(s)
  82. */
  83. *temp_ptr = 0;
  84. return_PTR(name_string);
  85. }
  86. /*******************************************************************************
  87. *
  88. * FUNCTION: acpi_ex_name_segment
  89. *
  90. * PARAMETERS: in_aml_address - Pointer to the name in the AML code
  91. * name_string - Where to return the name. The name is appended
  92. * to any existing string to form a namepath
  93. *
  94. * RETURN: Status
  95. *
  96. * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream
  97. *
  98. ******************************************************************************/
  99. static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
  100. {
  101. char *aml_address = (void *)*in_aml_address;
  102. acpi_status status = AE_OK;
  103. u32 index;
  104. char char_buf[5];
  105. ACPI_FUNCTION_TRACE(ex_name_segment);
  106. /*
  107. * If first character is a digit, then we know that we aren't looking
  108. * at a valid name segment
  109. */
  110. char_buf[0] = *aml_address;
  111. if ('0' <= char_buf[0] && char_buf[0] <= '9') {
  112. ACPI_ERROR((AE_INFO, "Invalid leading digit: %c", char_buf[0]));
  113. return_ACPI_STATUS(AE_CTRL_PENDING);
  114. }
  115. for (index = 0;
  116. (index < ACPI_NAMESEG_SIZE)
  117. && (acpi_ut_valid_name_char(*aml_address, 0)); index++) {
  118. char_buf[index] = *aml_address++;
  119. }
  120. /* Valid name segment */
  121. if (index == 4) {
  122. /* Found 4 valid characters */
  123. char_buf[4] = '\0';
  124. if (name_string) {
  125. ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
  126. "Appending NameSeg %s\n", char_buf));
  127. strcat(name_string, char_buf);
  128. } else {
  129. ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
  130. "No Name string - %s\n", char_buf));
  131. }
  132. } else if (index == 0) {
  133. /*
  134. * First character was not a valid name character,
  135. * so we are looking at something other than a name.
  136. */
  137. ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  138. "Leading character is not alpha: %02Xh (not a name)\n",
  139. char_buf[0]));
  140. status = AE_CTRL_PENDING;
  141. } else {
  142. /*
  143. * Segment started with one or more valid characters, but fewer than
  144. * the required 4
  145. */
  146. status = AE_AML_BAD_NAME;
  147. ACPI_ERROR((AE_INFO,
  148. "Bad character 0x%02x in name, at %p",
  149. *aml_address, aml_address));
  150. }
  151. *in_aml_address = ACPI_CAST_PTR(u8, aml_address);
  152. return_ACPI_STATUS(status);
  153. }
  154. /*******************************************************************************
  155. *
  156. * FUNCTION: acpi_ex_get_name_string
  157. *
  158. * PARAMETERS: data_type - Object type to be associated with this
  159. * name
  160. * in_aml_address - Pointer to the namestring in the AML code
  161. * out_name_string - Where the namestring is returned
  162. * out_name_length - Length of the returned string
  163. *
  164. * RETURN: Status, namestring and length
  165. *
  166. * DESCRIPTION: Extract a full namepath from the AML byte stream,
  167. * including any prefixes.
  168. *
  169. ******************************************************************************/
  170. acpi_status
  171. acpi_ex_get_name_string(acpi_object_type data_type,
  172. u8 * in_aml_address,
  173. char **out_name_string, u32 * out_name_length)
  174. {
  175. acpi_status status = AE_OK;
  176. u8 *aml_address = in_aml_address;
  177. char *name_string = NULL;
  178. u32 num_segments;
  179. u32 prefix_count = 0;
  180. u8 has_prefix = FALSE;
  181. ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address);
  182. if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type ||
  183. ACPI_TYPE_LOCAL_BANK_FIELD == data_type ||
  184. ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
  185. /* Disallow prefixes for types associated with field_unit names */
  186. name_string = acpi_ex_allocate_name_string(0, 1);
  187. if (!name_string) {
  188. status = AE_NO_MEMORY;
  189. } else {
  190. status =
  191. acpi_ex_name_segment(&aml_address, name_string);
  192. }
  193. } else {
  194. /*
  195. * data_type is not a field name.
  196. * Examine first character of name for root or parent prefix operators
  197. */
  198. switch (*aml_address) {
  199. case AML_ROOT_PREFIX:
  200. ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
  201. "RootPrefix(\\) at %p\n",
  202. aml_address));
  203. /*
  204. * Remember that we have a root_prefix --
  205. * see comment in acpi_ex_allocate_name_string()
  206. */
  207. aml_address++;
  208. prefix_count = ACPI_UINT32_MAX;
  209. has_prefix = TRUE;
  210. break;
  211. case AML_PARENT_PREFIX:
  212. /* Increment past possibly multiple parent prefixes */
  213. do {
  214. ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
  215. "ParentPrefix (^) at %p\n",
  216. aml_address));
  217. aml_address++;
  218. prefix_count++;
  219. } while (*aml_address == AML_PARENT_PREFIX);
  220. has_prefix = TRUE;
  221. break;
  222. default:
  223. /* Not a prefix character */
  224. break;
  225. }
  226. /* Examine first character of name for name segment prefix operator */
  227. switch (*aml_address) {
  228. case AML_DUAL_NAME_PREFIX:
  229. ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
  230. "DualNamePrefix at %p\n",
  231. aml_address));
  232. aml_address++;
  233. name_string =
  234. acpi_ex_allocate_name_string(prefix_count, 2);
  235. if (!name_string) {
  236. status = AE_NO_MEMORY;
  237. break;
  238. }
  239. /* Indicate that we processed a prefix */
  240. has_prefix = TRUE;
  241. status =
  242. acpi_ex_name_segment(&aml_address, name_string);
  243. if (ACPI_SUCCESS(status)) {
  244. status =
  245. acpi_ex_name_segment(&aml_address,
  246. name_string);
  247. }
  248. break;
  249. case AML_MULTI_NAME_PREFIX:
  250. ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
  251. "MultiNamePrefix at %p\n",
  252. aml_address));
  253. /* Fetch count of segments remaining in name path */
  254. aml_address++;
  255. num_segments = *aml_address;
  256. name_string =
  257. acpi_ex_allocate_name_string(prefix_count,
  258. num_segments);
  259. if (!name_string) {
  260. status = AE_NO_MEMORY;
  261. break;
  262. }
  263. /* Indicate that we processed a prefix */
  264. aml_address++;
  265. has_prefix = TRUE;
  266. while (num_segments &&
  267. (status =
  268. acpi_ex_name_segment(&aml_address,
  269. name_string)) == AE_OK) {
  270. num_segments--;
  271. }
  272. break;
  273. case 0:
  274. /* null_name valid as of 8-12-98 ASL/AML Grammar Update */
  275. if (prefix_count == ACPI_UINT32_MAX) {
  276. ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
  277. "NameSeg is \"\\\" followed by NULL\n"));
  278. }
  279. /* Consume the NULL byte */
  280. aml_address++;
  281. name_string =
  282. acpi_ex_allocate_name_string(prefix_count, 0);
  283. if (!name_string) {
  284. status = AE_NO_MEMORY;
  285. break;
  286. }
  287. break;
  288. default:
  289. /* Name segment string */
  290. name_string =
  291. acpi_ex_allocate_name_string(prefix_count, 1);
  292. if (!name_string) {
  293. status = AE_NO_MEMORY;
  294. break;
  295. }
  296. status =
  297. acpi_ex_name_segment(&aml_address, name_string);
  298. break;
  299. }
  300. }
  301. if (AE_CTRL_PENDING == status && has_prefix) {
  302. /* Ran out of segments after processing a prefix */
  303. ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string));
  304. status = AE_AML_BAD_NAME;
  305. }
  306. if (ACPI_FAILURE(status)) {
  307. if (name_string) {
  308. ACPI_FREE(name_string);
  309. }
  310. return_ACPI_STATUS(status);
  311. }
  312. *out_name_string = name_string;
  313. *out_name_length = (u32) (aml_address - in_aml_address);
  314. return_ACPI_STATUS(status);
  315. }