utresrc.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /*******************************************************************************
  3. *
  4. * Module Name: utresrc - Resource management utilities
  5. *
  6. ******************************************************************************/
  7. #include <acpi/acpi.h>
  8. #include "accommon.h"
  9. #include "acresrc.h"
  10. #define _COMPONENT ACPI_UTILITIES
  11. ACPI_MODULE_NAME("utresrc")
  12. /*
  13. * Base sizes of the raw AML resource descriptors, indexed by resource type.
  14. * Zero indicates a reserved (and therefore invalid) resource type.
  15. */
  16. const u8 acpi_gbl_resource_aml_sizes[] = {
  17. /* Small descriptors */
  18. 0,
  19. 0,
  20. 0,
  21. 0,
  22. ACPI_AML_SIZE_SMALL(struct aml_resource_irq),
  23. ACPI_AML_SIZE_SMALL(struct aml_resource_dma),
  24. ACPI_AML_SIZE_SMALL(struct aml_resource_start_dependent),
  25. ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent),
  26. ACPI_AML_SIZE_SMALL(struct aml_resource_io),
  27. ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io),
  28. ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_dma),
  29. 0,
  30. 0,
  31. 0,
  32. ACPI_AML_SIZE_SMALL(struct aml_resource_vendor_small),
  33. ACPI_AML_SIZE_SMALL(struct aml_resource_end_tag),
  34. /* Large descriptors */
  35. 0,
  36. ACPI_AML_SIZE_LARGE(struct aml_resource_memory24),
  37. ACPI_AML_SIZE_LARGE(struct aml_resource_generic_register),
  38. 0,
  39. ACPI_AML_SIZE_LARGE(struct aml_resource_vendor_large),
  40. ACPI_AML_SIZE_LARGE(struct aml_resource_memory32),
  41. ACPI_AML_SIZE_LARGE(struct aml_resource_fixed_memory32),
  42. ACPI_AML_SIZE_LARGE(struct aml_resource_address32),
  43. ACPI_AML_SIZE_LARGE(struct aml_resource_address16),
  44. ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq),
  45. ACPI_AML_SIZE_LARGE(struct aml_resource_address64),
  46. ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64),
  47. ACPI_AML_SIZE_LARGE(struct aml_resource_gpio),
  48. ACPI_AML_SIZE_LARGE(struct aml_resource_pin_function),
  49. ACPI_AML_SIZE_LARGE(struct aml_resource_common_serialbus),
  50. ACPI_AML_SIZE_LARGE(struct aml_resource_pin_config),
  51. ACPI_AML_SIZE_LARGE(struct aml_resource_pin_group),
  52. ACPI_AML_SIZE_LARGE(struct aml_resource_pin_group_function),
  53. ACPI_AML_SIZE_LARGE(struct aml_resource_pin_group_config),
  54. };
  55. const u8 acpi_gbl_resource_aml_serial_bus_sizes[] = {
  56. 0,
  57. ACPI_AML_SIZE_LARGE(struct aml_resource_i2c_serialbus),
  58. ACPI_AML_SIZE_LARGE(struct aml_resource_spi_serialbus),
  59. ACPI_AML_SIZE_LARGE(struct aml_resource_uart_serialbus),
  60. ACPI_AML_SIZE_LARGE(struct aml_resource_csi2_serialbus),
  61. };
  62. /*
  63. * Resource types, used to validate the resource length field.
  64. * The length of fixed-length types must match exactly, variable
  65. * lengths must meet the minimum required length, etc.
  66. * Zero indicates a reserved (and therefore invalid) resource type.
  67. */
  68. static const u8 acpi_gbl_resource_types[] = {
  69. /* Small descriptors */
  70. 0,
  71. 0,
  72. 0,
  73. 0,
  74. ACPI_SMALL_VARIABLE_LENGTH, /* 04 IRQ */
  75. ACPI_FIXED_LENGTH, /* 05 DMA */
  76. ACPI_SMALL_VARIABLE_LENGTH, /* 06 start_dependent_functions */
  77. ACPI_FIXED_LENGTH, /* 07 end_dependent_functions */
  78. ACPI_FIXED_LENGTH, /* 08 IO */
  79. ACPI_FIXED_LENGTH, /* 09 fixed_IO */
  80. ACPI_FIXED_LENGTH, /* 0A fixed_DMA */
  81. 0,
  82. 0,
  83. 0,
  84. ACPI_VARIABLE_LENGTH, /* 0E vendor_short */
  85. ACPI_FIXED_LENGTH, /* 0F end_tag */
  86. /* Large descriptors */
  87. 0,
  88. ACPI_FIXED_LENGTH, /* 01 Memory24 */
  89. ACPI_FIXED_LENGTH, /* 02 generic_register */
  90. 0,
  91. ACPI_VARIABLE_LENGTH, /* 04 vendor_long */
  92. ACPI_FIXED_LENGTH, /* 05 Memory32 */
  93. ACPI_FIXED_LENGTH, /* 06 memory32_fixed */
  94. ACPI_VARIABLE_LENGTH, /* 07 Dword* address */
  95. ACPI_VARIABLE_LENGTH, /* 08 Word* address */
  96. ACPI_VARIABLE_LENGTH, /* 09 extended_IRQ */
  97. ACPI_VARIABLE_LENGTH, /* 0A Qword* address */
  98. ACPI_FIXED_LENGTH, /* 0B Extended* address */
  99. ACPI_VARIABLE_LENGTH, /* 0C Gpio* */
  100. ACPI_VARIABLE_LENGTH, /* 0D pin_function */
  101. ACPI_VARIABLE_LENGTH, /* 0E *serial_bus */
  102. ACPI_VARIABLE_LENGTH, /* 0F pin_config */
  103. ACPI_VARIABLE_LENGTH, /* 10 pin_group */
  104. ACPI_VARIABLE_LENGTH, /* 11 pin_group_function */
  105. ACPI_VARIABLE_LENGTH, /* 12 pin_group_config */
  106. };
  107. /*******************************************************************************
  108. *
  109. * FUNCTION: acpi_ut_walk_aml_resources
  110. *
  111. * PARAMETERS: walk_state - Current walk info
  112. * PARAMETERS: aml - Pointer to the raw AML resource template
  113. * aml_length - Length of the entire template
  114. * user_function - Called once for each descriptor found. If
  115. * NULL, a pointer to the end_tag is returned
  116. * context - Passed to user_function
  117. *
  118. * RETURN: Status
  119. *
  120. * DESCRIPTION: Walk a raw AML resource list(buffer). User function called
  121. * once for each resource found.
  122. *
  123. ******************************************************************************/
  124. acpi_status
  125. acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
  126. u8 *aml,
  127. acpi_size aml_length,
  128. acpi_walk_aml_callback user_function, void **context)
  129. {
  130. acpi_status status;
  131. u8 *end_aml;
  132. u8 resource_index;
  133. u32 length;
  134. u32 offset = 0;
  135. u8 end_tag[2] = { 0x79, 0x00 };
  136. ACPI_FUNCTION_TRACE(ut_walk_aml_resources);
  137. /* The absolute minimum resource template is one end_tag descriptor */
  138. if (aml_length < sizeof(struct aml_resource_end_tag)) {
  139. return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
  140. }
  141. /* Point to the end of the resource template buffer */
  142. end_aml = aml + aml_length;
  143. /* Walk the byte list, abort on any invalid descriptor type or length */
  144. while (aml < end_aml) {
  145. /* Validate the Resource Type and Resource Length */
  146. status =
  147. acpi_ut_validate_resource(walk_state, aml, &resource_index);
  148. if (ACPI_FAILURE(status)) {
  149. /*
  150. * Exit on failure. Cannot continue because the descriptor
  151. * length may be bogus also.
  152. */
  153. return_ACPI_STATUS(status);
  154. }
  155. /* Get the length of this descriptor */
  156. length = acpi_ut_get_descriptor_length(aml);
  157. /* Invoke the user function */
  158. if (user_function) {
  159. status =
  160. user_function(aml, length, offset, resource_index,
  161. context);
  162. if (ACPI_FAILURE(status)) {
  163. return_ACPI_STATUS(status);
  164. }
  165. }
  166. /* An end_tag descriptor terminates this resource template */
  167. if (acpi_ut_get_resource_type(aml) ==
  168. ACPI_RESOURCE_NAME_END_TAG) {
  169. /*
  170. * There must be at least one more byte in the buffer for
  171. * the 2nd byte of the end_tag
  172. */
  173. if ((aml + 1) >= end_aml) {
  174. return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
  175. }
  176. /*
  177. * Don't attempt to perform any validation on the 2nd byte.
  178. * Although all known ASL compilers insert a zero for the 2nd
  179. * byte, it can also be a checksum (as per the ACPI spec),
  180. * and this is occasionally seen in the field. July 2017.
  181. */
  182. /* Return the pointer to the end_tag if requested */
  183. if (!user_function) {
  184. *context = aml;
  185. }
  186. /* Normal exit */
  187. return_ACPI_STATUS(AE_OK);
  188. }
  189. aml += length;
  190. offset += length;
  191. }
  192. /* Did not find an end_tag descriptor */
  193. if (user_function) {
  194. /* Insert an end_tag anyway. acpi_rs_get_list_length always leaves room */
  195. (void)acpi_ut_validate_resource(walk_state, end_tag,
  196. &resource_index);
  197. status =
  198. user_function(end_tag, 2, offset, resource_index, context);
  199. if (ACPI_FAILURE(status)) {
  200. return_ACPI_STATUS(status);
  201. }
  202. }
  203. return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
  204. }
  205. /*******************************************************************************
  206. *
  207. * FUNCTION: acpi_ut_validate_resource
  208. *
  209. * PARAMETERS: walk_state - Current walk info
  210. * aml - Pointer to the raw AML resource descriptor
  211. * return_index - Where the resource index is returned. NULL
  212. * if the index is not required.
  213. *
  214. * RETURN: Status, and optionally the Index into the global resource tables
  215. *
  216. * DESCRIPTION: Validate an AML resource descriptor by checking the Resource
  217. * Type and Resource Length. Returns an index into the global
  218. * resource information/dispatch tables for later use.
  219. *
  220. ******************************************************************************/
  221. acpi_status
  222. acpi_ut_validate_resource(struct acpi_walk_state *walk_state,
  223. void *aml, u8 *return_index)
  224. {
  225. union aml_resource *aml_resource;
  226. u8 resource_type;
  227. u8 resource_index;
  228. acpi_rs_length resource_length;
  229. acpi_rs_length minimum_resource_length;
  230. ACPI_FUNCTION_ENTRY();
  231. /*
  232. * 1) Validate the resource_type field (Byte 0)
  233. */
  234. resource_type = ACPI_GET8(aml);
  235. /*
  236. * Byte 0 contains the descriptor name (Resource Type)
  237. * Examine the large/small bit in the resource header
  238. */
  239. if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
  240. /* Verify the large resource type (name) against the max */
  241. if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
  242. goto invalid_resource;
  243. }
  244. /*
  245. * Large Resource Type -- bits 6:0 contain the name
  246. * Translate range 0x80-0x8B to index range 0x10-0x1B
  247. */
  248. resource_index = (u8) (resource_type - 0x70);
  249. } else {
  250. /*
  251. * Small Resource Type -- bits 6:3 contain the name
  252. * Shift range to index range 0x00-0x0F
  253. */
  254. resource_index = (u8)
  255. ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
  256. }
  257. /*
  258. * Check validity of the resource type, via acpi_gbl_resource_types.
  259. * Zero indicates an invalid resource.
  260. */
  261. if (!acpi_gbl_resource_types[resource_index]) {
  262. goto invalid_resource;
  263. }
  264. /*
  265. * Validate the resource_length field. This ensures that the length
  266. * is at least reasonable, and guarantees that it is non-zero.
  267. */
  268. resource_length = acpi_ut_get_resource_length(aml);
  269. minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index];
  270. /* Validate based upon the type of resource - fixed length or variable */
  271. switch (acpi_gbl_resource_types[resource_index]) {
  272. case ACPI_FIXED_LENGTH:
  273. /* Fixed length resource, length must match exactly */
  274. if (resource_length != minimum_resource_length) {
  275. goto bad_resource_length;
  276. }
  277. break;
  278. case ACPI_VARIABLE_LENGTH:
  279. /* Variable length resource, length must be at least the minimum */
  280. if (resource_length < minimum_resource_length) {
  281. goto bad_resource_length;
  282. }
  283. break;
  284. case ACPI_SMALL_VARIABLE_LENGTH:
  285. /* Small variable length resource, length can be (Min) or (Min-1) */
  286. if ((resource_length > minimum_resource_length) ||
  287. (resource_length < (minimum_resource_length - 1))) {
  288. goto bad_resource_length;
  289. }
  290. break;
  291. default:
  292. /* Shouldn't happen (because of validation earlier), but be sure */
  293. goto invalid_resource;
  294. }
  295. aml_resource = ACPI_CAST_PTR(union aml_resource, aml);
  296. if (resource_type == ACPI_RESOURCE_NAME_SERIAL_BUS) {
  297. /* Validate the bus_type field */
  298. if ((aml_resource->common_serial_bus.type == 0) ||
  299. (aml_resource->common_serial_bus.type >
  300. AML_RESOURCE_MAX_SERIALBUSTYPE)) {
  301. if (walk_state) {
  302. ACPI_ERROR((AE_INFO,
  303. "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X",
  304. aml_resource->common_serial_bus.
  305. type));
  306. }
  307. return (AE_AML_INVALID_RESOURCE_TYPE);
  308. }
  309. }
  310. /* Optionally return the resource table index */
  311. if (return_index) {
  312. *return_index = resource_index;
  313. }
  314. return (AE_OK);
  315. invalid_resource:
  316. if (walk_state) {
  317. ACPI_ERROR((AE_INFO,
  318. "Invalid/unsupported resource descriptor: Type 0x%2.2X",
  319. resource_type));
  320. }
  321. return (AE_AML_INVALID_RESOURCE_TYPE);
  322. bad_resource_length:
  323. if (walk_state) {
  324. ACPI_ERROR((AE_INFO,
  325. "Invalid resource descriptor length: Type "
  326. "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X",
  327. resource_type, resource_length,
  328. minimum_resource_length));
  329. }
  330. return (AE_AML_BAD_RESOURCE_LENGTH);
  331. }
  332. /*******************************************************************************
  333. *
  334. * FUNCTION: acpi_ut_get_resource_type
  335. *
  336. * PARAMETERS: aml - Pointer to the raw AML resource descriptor
  337. *
  338. * RETURN: The Resource Type with no extraneous bits (except the
  339. * Large/Small descriptor bit -- this is left alone)
  340. *
  341. * DESCRIPTION: Extract the Resource Type/Name from the first byte of
  342. * a resource descriptor.
  343. *
  344. ******************************************************************************/
  345. u8 acpi_ut_get_resource_type(void *aml)
  346. {
  347. ACPI_FUNCTION_ENTRY();
  348. /*
  349. * Byte 0 contains the descriptor name (Resource Type)
  350. * Examine the large/small bit in the resource header
  351. */
  352. if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
  353. /* Large Resource Type -- bits 6:0 contain the name */
  354. return (ACPI_GET8(aml));
  355. } else {
  356. /* Small Resource Type -- bits 6:3 contain the name */
  357. return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK));
  358. }
  359. }
  360. /*******************************************************************************
  361. *
  362. * FUNCTION: acpi_ut_get_resource_length
  363. *
  364. * PARAMETERS: aml - Pointer to the raw AML resource descriptor
  365. *
  366. * RETURN: Byte Length
  367. *
  368. * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By
  369. * definition, this does not include the size of the descriptor
  370. * header or the length field itself.
  371. *
  372. ******************************************************************************/
  373. u16 acpi_ut_get_resource_length(void *aml)
  374. {
  375. acpi_rs_length resource_length;
  376. ACPI_FUNCTION_ENTRY();
  377. /*
  378. * Byte 0 contains the descriptor name (Resource Type)
  379. * Examine the large/small bit in the resource header
  380. */
  381. if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
  382. /* Large Resource type -- bytes 1-2 contain the 16-bit length */
  383. ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1));
  384. } else {
  385. /* Small Resource type -- bits 2:0 of byte 0 contain the length */
  386. resource_length = (u16) (ACPI_GET8(aml) &
  387. ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
  388. }
  389. return (resource_length);
  390. }
  391. /*******************************************************************************
  392. *
  393. * FUNCTION: acpi_ut_get_resource_header_length
  394. *
  395. * PARAMETERS: aml - Pointer to the raw AML resource descriptor
  396. *
  397. * RETURN: Length of the AML header (depends on large/small descriptor)
  398. *
  399. * DESCRIPTION: Get the length of the header for this resource.
  400. *
  401. ******************************************************************************/
  402. u8 acpi_ut_get_resource_header_length(void *aml)
  403. {
  404. ACPI_FUNCTION_ENTRY();
  405. /* Examine the large/small bit in the resource header */
  406. if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
  407. return (sizeof(struct aml_resource_large_header));
  408. } else {
  409. return (sizeof(struct aml_resource_small_header));
  410. }
  411. }
  412. /*******************************************************************************
  413. *
  414. * FUNCTION: acpi_ut_get_descriptor_length
  415. *
  416. * PARAMETERS: aml - Pointer to the raw AML resource descriptor
  417. *
  418. * RETURN: Byte length
  419. *
  420. * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the
  421. * length of the descriptor header and the length field itself.
  422. * Used to walk descriptor lists.
  423. *
  424. ******************************************************************************/
  425. u32 acpi_ut_get_descriptor_length(void *aml)
  426. {
  427. ACPI_FUNCTION_ENTRY();
  428. /*
  429. * Get the Resource Length (does not include header length) and add
  430. * the header length (depends on if this is a small or large resource)
  431. */
  432. return (acpi_ut_get_resource_length(aml) +
  433. acpi_ut_get_resource_header_length(aml));
  434. }
  435. /*******************************************************************************
  436. *
  437. * FUNCTION: acpi_ut_get_resource_end_tag
  438. *
  439. * PARAMETERS: obj_desc - The resource template buffer object
  440. * end_tag - Where the pointer to the end_tag is returned
  441. *
  442. * RETURN: Status, pointer to the end tag
  443. *
  444. * DESCRIPTION: Find the end_tag resource descriptor in an AML resource template
  445. * Note: allows a buffer length of zero.
  446. *
  447. ******************************************************************************/
  448. acpi_status
  449. acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag)
  450. {
  451. acpi_status status;
  452. ACPI_FUNCTION_TRACE(ut_get_resource_end_tag);
  453. /* Allow a buffer length of zero */
  454. if (!obj_desc->buffer.length) {
  455. *end_tag = obj_desc->buffer.pointer;
  456. return_ACPI_STATUS(AE_OK);
  457. }
  458. /* Validate the template and get a pointer to the end_tag */
  459. status = acpi_ut_walk_aml_resources(NULL, obj_desc->buffer.pointer,
  460. obj_desc->buffer.length, NULL,
  461. (void **)end_tag);
  462. return_ACPI_STATUS(status);
  463. }