Linux-libre 5.7.6-gnu
[librecmc/linux-libre.git] / drivers / acpi / acpica / rsutils.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /*******************************************************************************
3  *
4  * Module Name: rsutils - Utilities for the resource manager
5  *
6  ******************************************************************************/
7
8 #include <acpi/acpi.h>
9 #include "accommon.h"
10 #include "acnamesp.h"
11 #include "acresrc.h"
12
13 #define _COMPONENT          ACPI_RESOURCES
14 ACPI_MODULE_NAME("rsutils")
15
16 /*******************************************************************************
17  *
18  * FUNCTION:    acpi_rs_decode_bitmask
19  *
20  * PARAMETERS:  mask            - Bitmask to decode
21  *              list            - Where the converted list is returned
22  *
23  * RETURN:      Count of bits set (length of list)
24  *
25  * DESCRIPTION: Convert a bit mask into a list of values
26  *
27  ******************************************************************************/
28 u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
29 {
30         u8 i;
31         u8 bit_count;
32
33         ACPI_FUNCTION_ENTRY();
34
35         /* Decode the mask bits */
36
37         for (i = 0, bit_count = 0; mask; i++) {
38                 if (mask & 0x0001) {
39                         list[bit_count] = i;
40                         bit_count++;
41                 }
42
43                 mask >>= 1;
44         }
45
46         return (bit_count);
47 }
48
49 /*******************************************************************************
50  *
51  * FUNCTION:    acpi_rs_encode_bitmask
52  *
53  * PARAMETERS:  list            - List of values to encode
54  *              count           - Length of list
55  *
56  * RETURN:      Encoded bitmask
57  *
58  * DESCRIPTION: Convert a list of values to an encoded bitmask
59  *
60  ******************************************************************************/
61
62 u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
63 {
64         u32 i;
65         u16 mask;
66
67         ACPI_FUNCTION_ENTRY();
68
69         /* Encode the list into a single bitmask */
70
71         for (i = 0, mask = 0; i < count; i++) {
72                 mask |= (0x1 << list[i]);
73         }
74
75         return (mask);
76 }
77
78 /*******************************************************************************
79  *
80  * FUNCTION:    acpi_rs_move_data
81  *
82  * PARAMETERS:  destination         - Pointer to the destination descriptor
83  *              source              - Pointer to the source descriptor
84  *              item_count          - How many items to move
85  *              move_type           - Byte width
86  *
87  * RETURN:      None
88  *
89  * DESCRIPTION: Move multiple data items from one descriptor to another. Handles
90  *              alignment issues and endian issues if necessary, as configured
91  *              via the ACPI_MOVE_* macros. (This is why a memcpy is not used)
92  *
93  ******************************************************************************/
94
95 void
96 acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
97 {
98         u32 i;
99
100         ACPI_FUNCTION_ENTRY();
101
102         /* One move per item */
103
104         for (i = 0; i < item_count; i++) {
105                 switch (move_type) {
106                         /*
107                          * For the 8-bit case, we can perform the move all at once
108                          * since there are no alignment or endian issues
109                          */
110                 case ACPI_RSC_MOVE8:
111                 case ACPI_RSC_MOVE_GPIO_RES:
112                 case ACPI_RSC_MOVE_SERIAL_VEN:
113                 case ACPI_RSC_MOVE_SERIAL_RES:
114
115                         memcpy(destination, source, item_count);
116                         return;
117
118                         /*
119                          * 16-, 32-, and 64-bit cases must use the move macros that perform
120                          * endian conversion and/or accommodate hardware that cannot perform
121                          * misaligned memory transfers
122                          */
123                 case ACPI_RSC_MOVE16:
124                 case ACPI_RSC_MOVE_GPIO_PIN:
125
126                         ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i],
127                                            &ACPI_CAST_PTR(u16, source)[i]);
128                         break;
129
130                 case ACPI_RSC_MOVE32:
131
132                         ACPI_MOVE_32_TO_32(&ACPI_CAST_PTR(u32, destination)[i],
133                                            &ACPI_CAST_PTR(u32, source)[i]);
134                         break;
135
136                 case ACPI_RSC_MOVE64:
137
138                         ACPI_MOVE_64_TO_64(&ACPI_CAST_PTR(u64, destination)[i],
139                                            &ACPI_CAST_PTR(u64, source)[i]);
140                         break;
141
142                 default:
143
144                         return;
145                 }
146         }
147 }
148
149 /*******************************************************************************
150  *
151  * FUNCTION:    acpi_rs_set_resource_length
152  *
153  * PARAMETERS:  total_length        - Length of the AML descriptor, including
154  *                                    the header and length fields.
155  *              aml                 - Pointer to the raw AML descriptor
156  *
157  * RETURN:      None
158  *
159  * DESCRIPTION: Set the resource_length field of an AML
160  *              resource descriptor, both Large and Small descriptors are
161  *              supported automatically. Note: Descriptor Type field must
162  *              be valid.
163  *
164  ******************************************************************************/
165
166 void
167 acpi_rs_set_resource_length(acpi_rsdesc_size total_length,
168                             union aml_resource *aml)
169 {
170         acpi_rs_length resource_length;
171
172         ACPI_FUNCTION_ENTRY();
173
174         /* Length is the total descriptor length minus the header length */
175
176         resource_length = (acpi_rs_length)
177             (total_length - acpi_ut_get_resource_header_length(aml));
178
179         /* Length is stored differently for large and small descriptors */
180
181         if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) {
182
183                 /* Large descriptor -- bytes 1-2 contain the 16-bit length */
184
185                 ACPI_MOVE_16_TO_16(&aml->large_header.resource_length,
186                                    &resource_length);
187         } else {
188                 /*
189                  * Small descriptor -- bits 2:0 of byte 0 contain the length
190                  * Clear any existing length, preserving descriptor type bits
191                  */
192                 aml->small_header.descriptor_type = (u8)
193                     ((aml->small_header.descriptor_type &
194                       ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK)
195                      | resource_length);
196         }
197 }
198
199 /*******************************************************************************
200  *
201  * FUNCTION:    acpi_rs_set_resource_header
202  *
203  * PARAMETERS:  descriptor_type     - Byte to be inserted as the type
204  *              total_length        - Length of the AML descriptor, including
205  *                                    the header and length fields.
206  *              aml                 - Pointer to the raw AML descriptor
207  *
208  * RETURN:      None
209  *
210  * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML
211  *              resource descriptor, both Large and Small descriptors are
212  *              supported automatically
213  *
214  ******************************************************************************/
215
216 void
217 acpi_rs_set_resource_header(u8 descriptor_type,
218                             acpi_rsdesc_size total_length,
219                             union aml_resource *aml)
220 {
221         ACPI_FUNCTION_ENTRY();
222
223         /* Set the Resource Type */
224
225         aml->small_header.descriptor_type = descriptor_type;
226
227         /* Set the Resource Length */
228
229         acpi_rs_set_resource_length(total_length, aml);
230 }
231
232 /*******************************************************************************
233  *
234  * FUNCTION:    acpi_rs_strcpy
235  *
236  * PARAMETERS:  destination         - Pointer to the destination string
237  *              source              - Pointer to the source string
238  *
239  * RETURN:      String length, including NULL terminator
240  *
241  * DESCRIPTION: Local string copy that returns the string length, saving a
242  *              strcpy followed by a strlen.
243  *
244  ******************************************************************************/
245
246 static u16 acpi_rs_strcpy(char *destination, char *source)
247 {
248         u16 i;
249
250         ACPI_FUNCTION_ENTRY();
251
252         for (i = 0; source[i]; i++) {
253                 destination[i] = source[i];
254         }
255
256         destination[i] = 0;
257
258         /* Return string length including the NULL terminator */
259
260         return ((u16) (i + 1));
261 }
262
263 /*******************************************************************************
264  *
265  * FUNCTION:    acpi_rs_get_resource_source
266  *
267  * PARAMETERS:  resource_length     - Length field of the descriptor
268  *              minimum_length      - Minimum length of the descriptor (minus
269  *                                    any optional fields)
270  *              resource_source     - Where the resource_source is returned
271  *              aml                 - Pointer to the raw AML descriptor
272  *              string_ptr          - (optional) where to store the actual
273  *                                    resource_source string
274  *
275  * RETURN:      Length of the string plus NULL terminator, rounded up to native
276  *              word boundary
277  *
278  * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor
279  *              to an internal resource descriptor
280  *
281  ******************************************************************************/
282
283 acpi_rs_length
284 acpi_rs_get_resource_source(acpi_rs_length resource_length,
285                             acpi_rs_length minimum_length,
286                             struct acpi_resource_source * resource_source,
287                             union aml_resource * aml, char *string_ptr)
288 {
289         acpi_rsdesc_size total_length;
290         u8 *aml_resource_source;
291
292         ACPI_FUNCTION_ENTRY();
293
294         total_length =
295             resource_length + sizeof(struct aml_resource_large_header);
296         aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
297
298         /*
299          * resource_source is present if the length of the descriptor is longer
300          * than the minimum length.
301          *
302          * Note: Some resource descriptors will have an additional null, so
303          * we add 1 to the minimum length.
304          */
305         if (total_length > (acpi_rsdesc_size)(minimum_length + 1)) {
306
307                 /* Get the resource_source_index */
308
309                 resource_source->index = aml_resource_source[0];
310
311                 resource_source->string_ptr = string_ptr;
312                 if (!string_ptr) {
313                         /*
314                          * String destination pointer is not specified; Set the String
315                          * pointer to the end of the current resource_source structure.
316                          */
317                         resource_source->string_ptr =
318                             ACPI_ADD_PTR(char, resource_source,
319                                          sizeof(struct acpi_resource_source));
320                 }
321
322                 /*
323                  * In order for the Resource length to be a multiple of the native
324                  * word, calculate the length of the string (+1 for NULL terminator)
325                  * and expand to the next word multiple.
326                  *
327                  * Zero the entire area of the buffer.
328                  */
329                 total_length =
330                     (u32)strlen(ACPI_CAST_PTR(char, &aml_resource_source[1])) +
331                     1;
332
333                 total_length = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(total_length);
334
335                 memset(resource_source->string_ptr, 0, total_length);
336
337                 /* Copy the resource_source string to the destination */
338
339                 resource_source->string_length =
340                     acpi_rs_strcpy(resource_source->string_ptr,
341                                    ACPI_CAST_PTR(char,
342                                                  &aml_resource_source[1]));
343
344                 return ((acpi_rs_length)total_length);
345         }
346
347         /* resource_source is not present */
348
349         resource_source->index = 0;
350         resource_source->string_length = 0;
351         resource_source->string_ptr = NULL;
352         return (0);
353 }
354
355 /*******************************************************************************
356  *
357  * FUNCTION:    acpi_rs_set_resource_source
358  *
359  * PARAMETERS:  aml                 - Pointer to the raw AML descriptor
360  *              minimum_length      - Minimum length of the descriptor (minus
361  *                                    any optional fields)
362  *              resource_source     - Internal resource_source
363
364  *
365  * RETURN:      Total length of the AML descriptor
366  *
367  * DESCRIPTION: Convert an optional resource_source from internal format to a
368  *              raw AML resource descriptor
369  *
370  ******************************************************************************/
371
372 acpi_rsdesc_size
373 acpi_rs_set_resource_source(union aml_resource *aml,
374                             acpi_rs_length minimum_length,
375                             struct acpi_resource_source *resource_source)
376 {
377         u8 *aml_resource_source;
378         acpi_rsdesc_size descriptor_length;
379
380         ACPI_FUNCTION_ENTRY();
381
382         descriptor_length = minimum_length;
383
384         /* Non-zero string length indicates presence of a resource_source */
385
386         if (resource_source->string_length) {
387
388                 /* Point to the end of the AML descriptor */
389
390                 aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
391
392                 /* Copy the resource_source_index */
393
394                 aml_resource_source[0] = (u8) resource_source->index;
395
396                 /* Copy the resource_source string */
397
398                 strcpy(ACPI_CAST_PTR(char, &aml_resource_source[1]),
399                        resource_source->string_ptr);
400
401                 /*
402                  * Add the length of the string (+ 1 for null terminator) to the
403                  * final descriptor length
404                  */
405                 descriptor_length += ((acpi_rsdesc_size)
406                                       resource_source->string_length + 1);
407         }
408
409         /* Return the new total length of the AML descriptor */
410
411         return (descriptor_length);
412 }
413
414 /*******************************************************************************
415  *
416  * FUNCTION:    acpi_rs_get_prt_method_data
417  *
418  * PARAMETERS:  node            - Device node
419  *              ret_buffer      - Pointer to a buffer structure for the
420  *                                results
421  *
422  * RETURN:      Status
423  *
424  * DESCRIPTION: This function is called to get the _PRT value of an object
425  *              contained in an object specified by the handle passed in
426  *
427  *              If the function fails an appropriate status will be returned
428  *              and the contents of the callers buffer is undefined.
429  *
430  ******************************************************************************/
431
432 acpi_status
433 acpi_rs_get_prt_method_data(struct acpi_namespace_node *node,
434                             struct acpi_buffer *ret_buffer)
435 {
436         union acpi_operand_object *obj_desc;
437         acpi_status status;
438
439         ACPI_FUNCTION_TRACE(rs_get_prt_method_data);
440
441         /* Parameters guaranteed valid by caller */
442
443         /* Execute the method, no parameters */
444
445         status =
446             acpi_ut_evaluate_object(node, METHOD_NAME__PRT, ACPI_BTYPE_PACKAGE,
447                                     &obj_desc);
448         if (ACPI_FAILURE(status)) {
449                 return_ACPI_STATUS(status);
450         }
451
452         /*
453          * Create a resource linked list from the byte stream buffer that comes
454          * back from the _CRS method execution.
455          */
456         status = acpi_rs_create_pci_routing_table(obj_desc, ret_buffer);
457
458         /* On exit, we must delete the object returned by evaluate_object */
459
460         acpi_ut_remove_reference(obj_desc);
461         return_ACPI_STATUS(status);
462 }
463
464 /*******************************************************************************
465  *
466  * FUNCTION:    acpi_rs_get_crs_method_data
467  *
468  * PARAMETERS:  node            - Device node
469  *              ret_buffer      - Pointer to a buffer structure for the
470  *                                results
471  *
472  * RETURN:      Status
473  *
474  * DESCRIPTION: This function is called to get the _CRS value of an object
475  *              contained in an object specified by the handle passed in
476  *
477  *              If the function fails an appropriate status will be returned
478  *              and the contents of the callers buffer is undefined.
479  *
480  ******************************************************************************/
481
482 acpi_status
483 acpi_rs_get_crs_method_data(struct acpi_namespace_node *node,
484                             struct acpi_buffer *ret_buffer)
485 {
486         union acpi_operand_object *obj_desc;
487         acpi_status status;
488
489         ACPI_FUNCTION_TRACE(rs_get_crs_method_data);
490
491         /* Parameters guaranteed valid by caller */
492
493         /* Execute the method, no parameters */
494
495         status =
496             acpi_ut_evaluate_object(node, METHOD_NAME__CRS, ACPI_BTYPE_BUFFER,
497                                     &obj_desc);
498         if (ACPI_FAILURE(status)) {
499                 return_ACPI_STATUS(status);
500         }
501
502         /*
503          * Make the call to create a resource linked list from the
504          * byte stream buffer that comes back from the _CRS method
505          * execution.
506          */
507         status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
508
509         /* On exit, we must delete the object returned by evaluateObject */
510
511         acpi_ut_remove_reference(obj_desc);
512         return_ACPI_STATUS(status);
513 }
514
515 /*******************************************************************************
516  *
517  * FUNCTION:    acpi_rs_get_prs_method_data
518  *
519  * PARAMETERS:  node            - Device node
520  *              ret_buffer      - Pointer to a buffer structure for the
521  *                                results
522  *
523  * RETURN:      Status
524  *
525  * DESCRIPTION: This function is called to get the _PRS value of an object
526  *              contained in an object specified by the handle passed in
527  *
528  *              If the function fails an appropriate status will be returned
529  *              and the contents of the callers buffer is undefined.
530  *
531  ******************************************************************************/
532
533 acpi_status
534 acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,
535                             struct acpi_buffer *ret_buffer)
536 {
537         union acpi_operand_object *obj_desc;
538         acpi_status status;
539
540         ACPI_FUNCTION_TRACE(rs_get_prs_method_data);
541
542         /* Parameters guaranteed valid by caller */
543
544         /* Execute the method, no parameters */
545
546         status =
547             acpi_ut_evaluate_object(node, METHOD_NAME__PRS, ACPI_BTYPE_BUFFER,
548                                     &obj_desc);
549         if (ACPI_FAILURE(status)) {
550                 return_ACPI_STATUS(status);
551         }
552
553         /*
554          * Make the call to create a resource linked list from the
555          * byte stream buffer that comes back from the _CRS method
556          * execution.
557          */
558         status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
559
560         /* On exit, we must delete the object returned by evaluateObject */
561
562         acpi_ut_remove_reference(obj_desc);
563         return_ACPI_STATUS(status);
564 }
565
566 /*******************************************************************************
567  *
568  * FUNCTION:    acpi_rs_get_aei_method_data
569  *
570  * PARAMETERS:  node            - Device node
571  *              ret_buffer      - Pointer to a buffer structure for the
572  *                                results
573  *
574  * RETURN:      Status
575  *
576  * DESCRIPTION: This function is called to get the _AEI value of an object
577  *              contained in an object specified by the handle passed in
578  *
579  *              If the function fails an appropriate status will be returned
580  *              and the contents of the callers buffer is undefined.
581  *
582  ******************************************************************************/
583
584 acpi_status
585 acpi_rs_get_aei_method_data(struct acpi_namespace_node *node,
586                             struct acpi_buffer *ret_buffer)
587 {
588         union acpi_operand_object *obj_desc;
589         acpi_status status;
590
591         ACPI_FUNCTION_TRACE(rs_get_aei_method_data);
592
593         /* Parameters guaranteed valid by caller */
594
595         /* Execute the method, no parameters */
596
597         status =
598             acpi_ut_evaluate_object(node, METHOD_NAME__AEI, ACPI_BTYPE_BUFFER,
599                                     &obj_desc);
600         if (ACPI_FAILURE(status)) {
601                 return_ACPI_STATUS(status);
602         }
603
604         /*
605          * Make the call to create a resource linked list from the
606          * byte stream buffer that comes back from the _CRS method
607          * execution.
608          */
609         status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
610
611         /* On exit, we must delete the object returned by evaluateObject */
612
613         acpi_ut_remove_reference(obj_desc);
614         return_ACPI_STATUS(status);
615 }
616
617 /*******************************************************************************
618  *
619  * FUNCTION:    acpi_rs_get_method_data
620  *
621  * PARAMETERS:  handle          - Handle to the containing object
622  *              path            - Path to method, relative to Handle
623  *              ret_buffer      - Pointer to a buffer structure for the
624  *                                results
625  *
626  * RETURN:      Status
627  *
628  * DESCRIPTION: This function is called to get the _CRS or _PRS value of an
629  *              object contained in an object specified by the handle passed in
630  *
631  *              If the function fails an appropriate status will be returned
632  *              and the contents of the callers buffer is undefined.
633  *
634  ******************************************************************************/
635
636 acpi_status
637 acpi_rs_get_method_data(acpi_handle handle,
638                         const char *path, struct acpi_buffer *ret_buffer)
639 {
640         union acpi_operand_object *obj_desc;
641         acpi_status status;
642
643         ACPI_FUNCTION_TRACE(rs_get_method_data);
644
645         /* Parameters guaranteed valid by caller */
646
647         /* Execute the method, no parameters */
648
649         status =
650             acpi_ut_evaluate_object(ACPI_CAST_PTR
651                                     (struct acpi_namespace_node, handle), path,
652                                     ACPI_BTYPE_BUFFER, &obj_desc);
653         if (ACPI_FAILURE(status)) {
654                 return_ACPI_STATUS(status);
655         }
656
657         /*
658          * Make the call to create a resource linked list from the
659          * byte stream buffer that comes back from the method
660          * execution.
661          */
662         status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
663
664         /* On exit, we must delete the object returned by evaluate_object */
665
666         acpi_ut_remove_reference(obj_desc);
667         return_ACPI_STATUS(status);
668 }
669
670 /*******************************************************************************
671  *
672  * FUNCTION:    acpi_rs_set_srs_method_data
673  *
674  * PARAMETERS:  node            - Device node
675  *              in_buffer       - Pointer to a buffer structure of the
676  *                                parameter
677  *
678  * RETURN:      Status
679  *
680  * DESCRIPTION: This function is called to set the _SRS of an object contained
681  *              in an object specified by the handle passed in
682  *
683  *              If the function fails an appropriate status will be returned
684  *              and the contents of the callers buffer is undefined.
685  *
686  * Note: Parameters guaranteed valid by caller
687  *
688  ******************************************************************************/
689
690 acpi_status
691 acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
692                             struct acpi_buffer *in_buffer)
693 {
694         struct acpi_evaluate_info *info;
695         union acpi_operand_object *args[2];
696         acpi_status status;
697         struct acpi_buffer buffer;
698
699         ACPI_FUNCTION_TRACE(rs_set_srs_method_data);
700
701         /* Allocate and initialize the evaluation information block */
702
703         info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
704         if (!info) {
705                 return_ACPI_STATUS(AE_NO_MEMORY);
706         }
707
708         info->prefix_node = node;
709         info->relative_pathname = METHOD_NAME__SRS;
710         info->parameters = args;
711         info->flags = ACPI_IGNORE_RETURN_VALUE;
712
713         /*
714          * The in_buffer parameter will point to a linked list of
715          * resource parameters. It needs to be formatted into a
716          * byte stream to be sent in as an input parameter to _SRS
717          *
718          * Convert the linked list into a byte stream
719          */
720         buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
721         status = acpi_rs_create_aml_resources(in_buffer, &buffer);
722         if (ACPI_FAILURE(status)) {
723                 goto cleanup;
724         }
725
726         /* Create and initialize the method parameter object */
727
728         args[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
729         if (!args[0]) {
730                 /*
731                  * Must free the buffer allocated above (otherwise it is freed
732                  * later)
733                  */
734                 ACPI_FREE(buffer.pointer);
735                 status = AE_NO_MEMORY;
736                 goto cleanup;
737         }
738
739         args[0]->buffer.length = (u32) buffer.length;
740         args[0]->buffer.pointer = buffer.pointer;
741         args[0]->common.flags = AOPOBJ_DATA_VALID;
742         args[1] = NULL;
743
744         /* Execute the method, no return value is expected */
745
746         status = acpi_ns_evaluate(info);
747
748         /* Clean up and return the status from acpi_ns_evaluate */
749
750         acpi_ut_remove_reference(args[0]);
751
752 cleanup:
753         ACPI_FREE(info);
754         return_ACPI_STATUS(status);
755 }