rsxface.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /*******************************************************************************
  3. *
  4. * Module Name: rsxface - Public interfaces to the resource manager
  5. *
  6. ******************************************************************************/
  7. #define EXPORT_ACPI_INTERFACES
  8. #include <acpi/acpi.h>
  9. #include "accommon.h"
  10. #include "acresrc.h"
  11. #include "acnamesp.h"
  12. #define _COMPONENT ACPI_RESOURCES
  13. ACPI_MODULE_NAME("rsxface")
  14. /* Local macros for 16,32-bit to 64-bit conversion */
  15. #define ACPI_COPY_FIELD(out, in, field) ((out)->field = (in)->field)
  16. #define ACPI_COPY_ADDRESS(out, in) \
  17. ACPI_COPY_FIELD(out, in, resource_type); \
  18. ACPI_COPY_FIELD(out, in, producer_consumer); \
  19. ACPI_COPY_FIELD(out, in, decode); \
  20. ACPI_COPY_FIELD(out, in, min_address_fixed); \
  21. ACPI_COPY_FIELD(out, in, max_address_fixed); \
  22. ACPI_COPY_FIELD(out, in, info); \
  23. ACPI_COPY_FIELD(out, in, address.granularity); \
  24. ACPI_COPY_FIELD(out, in, address.minimum); \
  25. ACPI_COPY_FIELD(out, in, address.maximum); \
  26. ACPI_COPY_FIELD(out, in, address.translation_offset); \
  27. ACPI_COPY_FIELD(out, in, address.address_length); \
  28. ACPI_COPY_FIELD(out, in, resource_source);
  29. /* Local prototypes */
  30. static acpi_status
  31. acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context);
  32. static acpi_status
  33. acpi_rs_validate_parameters(acpi_handle device_handle,
  34. struct acpi_buffer *buffer,
  35. struct acpi_namespace_node **return_node);
  36. /*******************************************************************************
  37. *
  38. * FUNCTION: acpi_rs_validate_parameters
  39. *
  40. * PARAMETERS: device_handle - Handle to a device
  41. * buffer - Pointer to a data buffer
  42. * return_node - Pointer to where the device node is returned
  43. *
  44. * RETURN: Status
  45. *
  46. * DESCRIPTION: Common parameter validation for resource interfaces
  47. *
  48. ******************************************************************************/
  49. static acpi_status
  50. acpi_rs_validate_parameters(acpi_handle device_handle,
  51. struct acpi_buffer *buffer,
  52. struct acpi_namespace_node **return_node)
  53. {
  54. acpi_status status;
  55. struct acpi_namespace_node *node;
  56. ACPI_FUNCTION_TRACE(rs_validate_parameters);
  57. /*
  58. * Must have a valid handle to an ACPI device
  59. */
  60. if (!device_handle) {
  61. return_ACPI_STATUS(AE_BAD_PARAMETER);
  62. }
  63. node = acpi_ns_validate_handle(device_handle);
  64. if (!node) {
  65. return_ACPI_STATUS(AE_BAD_PARAMETER);
  66. }
  67. if (node->type != ACPI_TYPE_DEVICE) {
  68. return_ACPI_STATUS(AE_TYPE);
  69. }
  70. /*
  71. * Validate the user buffer object
  72. *
  73. * if there is a non-zero buffer length we also need a valid pointer in
  74. * the buffer. If it's a zero buffer length, we'll be returning the
  75. * needed buffer size (later), so keep going.
  76. */
  77. status = acpi_ut_validate_buffer(buffer);
  78. if (ACPI_FAILURE(status)) {
  79. return_ACPI_STATUS(status);
  80. }
  81. *return_node = node;
  82. return_ACPI_STATUS(AE_OK);
  83. }
  84. /*******************************************************************************
  85. *
  86. * FUNCTION: acpi_get_irq_routing_table
  87. *
  88. * PARAMETERS: device_handle - Handle to the Bus device we are querying
  89. * ret_buffer - Pointer to a buffer to receive the
  90. * current resources for the device
  91. *
  92. * RETURN: Status
  93. *
  94. * DESCRIPTION: This function is called to get the IRQ routing table for a
  95. * specific bus. The caller must first acquire a handle for the
  96. * desired bus. The routine table is placed in the buffer pointed
  97. * to by the ret_buffer variable parameter.
  98. *
  99. * If the function fails an appropriate status will be returned
  100. * and the value of ret_buffer is undefined.
  101. *
  102. * This function attempts to execute the _PRT method contained in
  103. * the object indicated by the passed device_handle.
  104. *
  105. ******************************************************************************/
  106. acpi_status
  107. acpi_get_irq_routing_table(acpi_handle device_handle,
  108. struct acpi_buffer *ret_buffer)
  109. {
  110. acpi_status status;
  111. struct acpi_namespace_node *node;
  112. ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table);
  113. /* Validate parameters then dispatch to internal routine */
  114. status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
  115. if (ACPI_FAILURE(status)) {
  116. return_ACPI_STATUS(status);
  117. }
  118. status = acpi_rs_get_prt_method_data(node, ret_buffer);
  119. return_ACPI_STATUS(status);
  120. }
  121. ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table)
  122. /*******************************************************************************
  123. *
  124. * FUNCTION: acpi_get_current_resources
  125. *
  126. * PARAMETERS: device_handle - Handle to the device object for the
  127. * device we are querying
  128. * ret_buffer - Pointer to a buffer to receive the
  129. * current resources for the device
  130. *
  131. * RETURN: Status
  132. *
  133. * DESCRIPTION: This function is called to get the current resources for a
  134. * specific device. The caller must first acquire a handle for
  135. * the desired device. The resource data is placed in the buffer
  136. * pointed to by the ret_buffer variable parameter.
  137. *
  138. * If the function fails an appropriate status will be returned
  139. * and the value of ret_buffer is undefined.
  140. *
  141. * This function attempts to execute the _CRS method contained in
  142. * the object indicated by the passed device_handle.
  143. *
  144. ******************************************************************************/
  145. acpi_status
  146. acpi_get_current_resources(acpi_handle device_handle,
  147. struct acpi_buffer *ret_buffer)
  148. {
  149. acpi_status status;
  150. struct acpi_namespace_node *node;
  151. ACPI_FUNCTION_TRACE(acpi_get_current_resources);
  152. /* Validate parameters then dispatch to internal routine */
  153. status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
  154. if (ACPI_FAILURE(status)) {
  155. return_ACPI_STATUS(status);
  156. }
  157. status = acpi_rs_get_crs_method_data(node, ret_buffer);
  158. return_ACPI_STATUS(status);
  159. }
  160. ACPI_EXPORT_SYMBOL(acpi_get_current_resources)
  161. /*******************************************************************************
  162. *
  163. * FUNCTION: acpi_get_possible_resources
  164. *
  165. * PARAMETERS: device_handle - Handle to the device object for the
  166. * device we are querying
  167. * ret_buffer - Pointer to a buffer to receive the
  168. * resources for the device
  169. *
  170. * RETURN: Status
  171. *
  172. * DESCRIPTION: This function is called to get a list of the possible resources
  173. * for a specific device. The caller must first acquire a handle
  174. * for the desired device. The resource data is placed in the
  175. * buffer pointed to by the ret_buffer variable.
  176. *
  177. * If the function fails an appropriate status will be returned
  178. * and the value of ret_buffer is undefined.
  179. *
  180. ******************************************************************************/
  181. acpi_status
  182. acpi_get_possible_resources(acpi_handle device_handle,
  183. struct acpi_buffer *ret_buffer)
  184. {
  185. acpi_status status;
  186. struct acpi_namespace_node *node;
  187. ACPI_FUNCTION_TRACE(acpi_get_possible_resources);
  188. /* Validate parameters then dispatch to internal routine */
  189. status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
  190. if (ACPI_FAILURE(status)) {
  191. return_ACPI_STATUS(status);
  192. }
  193. status = acpi_rs_get_prs_method_data(node, ret_buffer);
  194. return_ACPI_STATUS(status);
  195. }
  196. ACPI_EXPORT_SYMBOL(acpi_get_possible_resources)
  197. /*******************************************************************************
  198. *
  199. * FUNCTION: acpi_set_current_resources
  200. *
  201. * PARAMETERS: device_handle - Handle to the device object for the
  202. * device we are setting resources
  203. * in_buffer - Pointer to a buffer containing the
  204. * resources to be set for the device
  205. *
  206. * RETURN: Status
  207. *
  208. * DESCRIPTION: This function is called to set the current resources for a
  209. * specific device. The caller must first acquire a handle for
  210. * the desired device. The resource data is passed to the routine
  211. * the buffer pointed to by the in_buffer variable.
  212. *
  213. ******************************************************************************/
  214. acpi_status
  215. acpi_set_current_resources(acpi_handle device_handle,
  216. struct acpi_buffer *in_buffer)
  217. {
  218. acpi_status status;
  219. struct acpi_namespace_node *node;
  220. ACPI_FUNCTION_TRACE(acpi_set_current_resources);
  221. /* Validate the buffer, don't allow zero length */
  222. if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) {
  223. return_ACPI_STATUS(AE_BAD_PARAMETER);
  224. }
  225. /* Validate parameters then dispatch to internal routine */
  226. status = acpi_rs_validate_parameters(device_handle, in_buffer, &node);
  227. if (ACPI_FAILURE(status)) {
  228. return_ACPI_STATUS(status);
  229. }
  230. status = acpi_rs_set_srs_method_data(node, in_buffer);
  231. return_ACPI_STATUS(status);
  232. }
  233. ACPI_EXPORT_SYMBOL(acpi_set_current_resources)
  234. /*******************************************************************************
  235. *
  236. * FUNCTION: acpi_get_event_resources
  237. *
  238. * PARAMETERS: device_handle - Handle to the device object for the
  239. * device we are getting resources
  240. * in_buffer - Pointer to a buffer containing the
  241. * resources to be set for the device
  242. *
  243. * RETURN: Status
  244. *
  245. * DESCRIPTION: This function is called to get the event resources for a
  246. * specific device. The caller must first acquire a handle for
  247. * the desired device. The resource data is passed to the routine
  248. * the buffer pointed to by the in_buffer variable. Uses the
  249. * _AEI method.
  250. *
  251. ******************************************************************************/
  252. acpi_status
  253. acpi_get_event_resources(acpi_handle device_handle,
  254. struct acpi_buffer *ret_buffer)
  255. {
  256. acpi_status status;
  257. struct acpi_namespace_node *node;
  258. ACPI_FUNCTION_TRACE(acpi_get_event_resources);
  259. /* Validate parameters then dispatch to internal routine */
  260. status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
  261. if (ACPI_FAILURE(status)) {
  262. return_ACPI_STATUS(status);
  263. }
  264. status = acpi_rs_get_aei_method_data(node, ret_buffer);
  265. return_ACPI_STATUS(status);
  266. }
  267. ACPI_EXPORT_SYMBOL(acpi_get_event_resources)
  268. /******************************************************************************
  269. *
  270. * FUNCTION: acpi_resource_to_address64
  271. *
  272. * PARAMETERS: resource - Pointer to a resource
  273. * out - Pointer to the users's return buffer
  274. * (a struct acpi_resource_address64)
  275. *
  276. * RETURN: Status
  277. *
  278. * DESCRIPTION: If the resource is an address16, address32, or address64,
  279. * copy it to the address64 return buffer. This saves the
  280. * caller from having to duplicate code for different-sized
  281. * addresses.
  282. *
  283. ******************************************************************************/
  284. acpi_status
  285. acpi_resource_to_address64(struct acpi_resource *resource,
  286. struct acpi_resource_address64 *out)
  287. {
  288. struct acpi_resource_address16 *address16;
  289. struct acpi_resource_address32 *address32;
  290. if (!resource || !out) {
  291. return (AE_BAD_PARAMETER);
  292. }
  293. /* Convert 16 or 32 address descriptor to 64 */
  294. switch (resource->type) {
  295. case ACPI_RESOURCE_TYPE_ADDRESS16:
  296. address16 =
  297. ACPI_CAST_PTR(struct acpi_resource_address16,
  298. &resource->data);
  299. ACPI_COPY_ADDRESS(out, address16);
  300. break;
  301. case ACPI_RESOURCE_TYPE_ADDRESS32:
  302. address32 =
  303. ACPI_CAST_PTR(struct acpi_resource_address32,
  304. &resource->data);
  305. ACPI_COPY_ADDRESS(out, address32);
  306. break;
  307. case ACPI_RESOURCE_TYPE_ADDRESS64:
  308. /* Simple copy for 64 bit source */
  309. memcpy(out, &resource->data,
  310. sizeof(struct acpi_resource_address64));
  311. break;
  312. default:
  313. return (AE_BAD_PARAMETER);
  314. }
  315. return (AE_OK);
  316. }
  317. ACPI_EXPORT_SYMBOL(acpi_resource_to_address64)
  318. /*******************************************************************************
  319. *
  320. * FUNCTION: acpi_get_vendor_resource
  321. *
  322. * PARAMETERS: device_handle - Handle for the parent device object
  323. * name - Method name for the parent resource
  324. * (METHOD_NAME__CRS or METHOD_NAME__PRS)
  325. * uuid - Pointer to the UUID to be matched.
  326. * includes both subtype and 16-byte UUID
  327. * ret_buffer - Where the vendor resource is returned
  328. *
  329. * RETURN: Status
  330. *
  331. * DESCRIPTION: Walk a resource template for the specified device to find a
  332. * vendor-defined resource that matches the supplied UUID and
  333. * UUID subtype. Returns a struct acpi_resource of type Vendor.
  334. *
  335. ******************************************************************************/
  336. acpi_status
  337. acpi_get_vendor_resource(acpi_handle device_handle,
  338. char *name,
  339. struct acpi_vendor_uuid *uuid,
  340. struct acpi_buffer *ret_buffer)
  341. {
  342. struct acpi_vendor_walk_info info;
  343. acpi_status status;
  344. /* Other parameters are validated by acpi_walk_resources */
  345. if (!uuid || !ret_buffer) {
  346. return (AE_BAD_PARAMETER);
  347. }
  348. info.uuid = uuid;
  349. info.buffer = ret_buffer;
  350. info.status = AE_NOT_EXIST;
  351. /* Walk the _CRS or _PRS resource list for this device */
  352. status =
  353. acpi_walk_resources(device_handle, name,
  354. acpi_rs_match_vendor_resource, &info);
  355. if (ACPI_FAILURE(status)) {
  356. return (status);
  357. }
  358. return (info.status);
  359. }
  360. ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource)
  361. /*******************************************************************************
  362. *
  363. * FUNCTION: acpi_rs_match_vendor_resource
  364. *
  365. * PARAMETERS: acpi_walk_resource_callback
  366. *
  367. * RETURN: Status
  368. *
  369. * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID
  370. *
  371. ******************************************************************************/
  372. static acpi_status
  373. acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
  374. {
  375. struct acpi_vendor_walk_info *info = context;
  376. struct acpi_resource_vendor_typed *vendor;
  377. struct acpi_buffer *buffer;
  378. acpi_status status;
  379. /* Ignore all descriptors except Vendor */
  380. if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) {
  381. return (AE_OK);
  382. }
  383. vendor = &resource->data.vendor_typed;
  384. /*
  385. * For a valid match, these conditions must hold:
  386. *
  387. * 1) Length of descriptor data must be at least as long as a UUID struct
  388. * 2) The UUID subtypes must match
  389. * 3) The UUID data must match
  390. */
  391. if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) ||
  392. (vendor->uuid_subtype != info->uuid->subtype) ||
  393. (memcmp(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) {
  394. return (AE_OK);
  395. }
  396. /* Validate/Allocate/Clear caller buffer */
  397. buffer = info->buffer;
  398. status = acpi_ut_initialize_buffer(buffer, resource->length);
  399. if (ACPI_FAILURE(status)) {
  400. return (status);
  401. }
  402. /* Found the correct resource, copy and return it */
  403. memcpy(buffer->pointer, resource, resource->length);
  404. buffer->length = resource->length;
  405. /* Found the desired descriptor, terminate resource walk */
  406. info->status = AE_OK;
  407. return (AE_CTRL_TERMINATE);
  408. }
  409. /*******************************************************************************
  410. *
  411. * FUNCTION: acpi_walk_resource_buffer
  412. *
  413. * PARAMETERS: buffer - Formatted buffer returned by one of the
  414. * various Get*Resource functions
  415. * user_function - Called for each resource
  416. * context - Passed to user_function
  417. *
  418. * RETURN: Status
  419. *
  420. * DESCRIPTION: Walks the input resource template. The user_function is called
  421. * once for each resource in the list.
  422. *
  423. ******************************************************************************/
  424. acpi_status
  425. acpi_walk_resource_buffer(struct acpi_buffer *buffer,
  426. acpi_walk_resource_callback user_function,
  427. void *context)
  428. {
  429. acpi_status status = AE_OK;
  430. struct acpi_resource *resource;
  431. struct acpi_resource *resource_end;
  432. ACPI_FUNCTION_TRACE(acpi_walk_resource_buffer);
  433. /* Parameter validation */
  434. if (!buffer || !buffer->pointer || !user_function) {
  435. return_ACPI_STATUS(AE_BAD_PARAMETER);
  436. }
  437. /* Buffer contains the resource list and length */
  438. resource = ACPI_CAST_PTR(struct acpi_resource, buffer->pointer);
  439. resource_end =
  440. ACPI_ADD_PTR(struct acpi_resource, buffer->pointer, buffer->length);
  441. /* Walk the resource list until the end_tag is found (or buffer end) */
  442. while (resource < resource_end) {
  443. /* Sanity check the resource type */
  444. if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
  445. status = AE_AML_INVALID_RESOURCE_TYPE;
  446. break;
  447. }
  448. /* Sanity check the length. It must not be zero, or we loop forever */
  449. if (!resource->length) {
  450. return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
  451. }
  452. /* Invoke the user function, abort on any error returned */
  453. status = user_function(resource, context);
  454. if (ACPI_FAILURE(status)) {
  455. if (status == AE_CTRL_TERMINATE) {
  456. /* This is an OK termination by the user function */
  457. status = AE_OK;
  458. }
  459. break;
  460. }
  461. /* end_tag indicates end-of-list */
  462. if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
  463. break;
  464. }
  465. /* Get the next resource descriptor */
  466. resource = ACPI_NEXT_RESOURCE(resource);
  467. }
  468. return_ACPI_STATUS(status);
  469. }
  470. ACPI_EXPORT_SYMBOL(acpi_walk_resource_buffer)
  471. /*******************************************************************************
  472. *
  473. * FUNCTION: acpi_walk_resources
  474. *
  475. * PARAMETERS: device_handle - Handle to the device object for the
  476. * device we are querying
  477. * name - Method name of the resources we want.
  478. * (METHOD_NAME__CRS, METHOD_NAME__PRS, or
  479. * METHOD_NAME__AEI or METHOD_NAME__DMA)
  480. * user_function - Called for each resource
  481. * context - Passed to user_function
  482. *
  483. * RETURN: Status
  484. *
  485. * DESCRIPTION: Retrieves the current or possible resource list for the
  486. * specified device. The user_function is called once for
  487. * each resource in the list.
  488. *
  489. ******************************************************************************/
  490. acpi_status
  491. acpi_walk_resources(acpi_handle device_handle,
  492. char *name,
  493. acpi_walk_resource_callback user_function, void *context)
  494. {
  495. acpi_status status;
  496. struct acpi_buffer buffer;
  497. ACPI_FUNCTION_TRACE(acpi_walk_resources);
  498. /* Parameter validation */
  499. if (!device_handle || !user_function || !name ||
  500. (!ACPI_COMPARE_NAMESEG(name, METHOD_NAME__CRS) &&
  501. !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__PRS) &&
  502. !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__AEI) &&
  503. !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__DMA))) {
  504. return_ACPI_STATUS(AE_BAD_PARAMETER);
  505. }
  506. /* Get the _CRS/_PRS/_AEI/_DMA resource list */
  507. buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
  508. status = acpi_rs_get_method_data(device_handle, name, &buffer);
  509. if (ACPI_FAILURE(status)) {
  510. return_ACPI_STATUS(status);
  511. }
  512. /* Walk the resource list and cleanup */
  513. status = acpi_walk_resource_buffer(&buffer, user_function, context);
  514. ACPI_FREE(buffer.pointer);
  515. return_ACPI_STATUS(status);
  516. }
  517. ACPI_EXPORT_SYMBOL(acpi_walk_resources)