GNU Linux-libre 4.19.268-gnu1
[releases.git] / drivers / acpi / acpica / exfield.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: exfield - ACPI AML (p-code) execution - field manipulation
5  *
6  * Copyright (C) 2000 - 2018, Intel Corp.
7  *
8  *****************************************************************************/
9
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "acdispat.h"
13 #include "acinterp.h"
14 #include "amlcode.h"
15
16 #define _COMPONENT          ACPI_EXECUTER
17 ACPI_MODULE_NAME("exfield")
18
19 /* Local prototypes */
20 static u32
21 acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length);
22
23 /*******************************************************************************
24  *
25  * FUNCTION:    acpi_ex_get_serial_access_length
26  *
27  * PARAMETERS:  accessor_type   - The type of the protocol indicated by region
28  *                                field access attributes
29  *              access_length   - The access length of the region field
30  *
31  * RETURN:      Decoded access length
32  *
33  * DESCRIPTION: This routine returns the length of the generic_serial_bus
34  *              protocol bytes
35  *
36  ******************************************************************************/
37
38 static u32
39 acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length)
40 {
41         u32 length;
42
43         switch (accessor_type) {
44         case AML_FIELD_ATTRIB_QUICK:
45
46                 length = 0;
47                 break;
48
49         case AML_FIELD_ATTRIB_SEND_RCV:
50         case AML_FIELD_ATTRIB_BYTE:
51
52                 length = 1;
53                 break;
54
55         case AML_FIELD_ATTRIB_WORD:
56         case AML_FIELD_ATTRIB_WORD_CALL:
57
58                 length = 2;
59                 break;
60
61         case AML_FIELD_ATTRIB_MULTIBYTE:
62         case AML_FIELD_ATTRIB_RAW_BYTES:
63         case AML_FIELD_ATTRIB_RAW_PROCESS:
64
65                 length = access_length;
66                 break;
67
68         case AML_FIELD_ATTRIB_BLOCK:
69         case AML_FIELD_ATTRIB_BLOCK_CALL:
70         default:
71
72                 length = ACPI_GSBUS_BUFFER_SIZE - 2;
73                 break;
74         }
75
76         return (length);
77 }
78
79 /*******************************************************************************
80  *
81  * FUNCTION:    acpi_ex_read_data_from_field
82  *
83  * PARAMETERS:  walk_state          - Current execution state
84  *              obj_desc            - The named field
85  *              ret_buffer_desc     - Where the return data object is stored
86  *
87  * RETURN:      Status
88  *
89  * DESCRIPTION: Read from a named field. Returns either an Integer or a
90  *              Buffer, depending on the size of the field.
91  *
92  ******************************************************************************/
93
94 acpi_status
95 acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
96                              union acpi_operand_object *obj_desc,
97                              union acpi_operand_object **ret_buffer_desc)
98 {
99         acpi_status status;
100         union acpi_operand_object *buffer_desc;
101         acpi_size length;
102         void *buffer;
103         u32 function;
104         u16 accessor_type;
105
106         ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
107
108         /* Parameter validation */
109
110         if (!obj_desc) {
111                 return_ACPI_STATUS(AE_AML_NO_OPERAND);
112         }
113         if (!ret_buffer_desc) {
114                 return_ACPI_STATUS(AE_BAD_PARAMETER);
115         }
116
117         if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) {
118                 /*
119                  * If the buffer_field arguments have not been previously evaluated,
120                  * evaluate them now and save the results.
121                  */
122                 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
123                         status = acpi_ds_get_buffer_field_arguments(obj_desc);
124                         if (ACPI_FAILURE(status)) {
125                                 return_ACPI_STATUS(status);
126                         }
127                 }
128         } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
129                    (obj_desc->field.region_obj->region.space_id ==
130                     ACPI_ADR_SPACE_SMBUS
131                     || obj_desc->field.region_obj->region.space_id ==
132                     ACPI_ADR_SPACE_GSBUS
133                     || obj_desc->field.region_obj->region.space_id ==
134                     ACPI_ADR_SPACE_IPMI)) {
135                 /*
136                  * This is an SMBus, GSBus or IPMI read. We must create a buffer to
137                  * hold the data and then directly access the region handler.
138                  *
139                  * Note: SMBus and GSBus protocol value is passed in upper 16-bits
140                  * of Function
141                  */
142                 if (obj_desc->field.region_obj->region.space_id ==
143                     ACPI_ADR_SPACE_SMBUS) {
144                         length = ACPI_SMBUS_BUFFER_SIZE;
145                         function =
146                             ACPI_READ | (obj_desc->field.attribute << 16);
147                 } else if (obj_desc->field.region_obj->region.space_id ==
148                            ACPI_ADR_SPACE_GSBUS) {
149                         accessor_type = obj_desc->field.attribute;
150                         length =
151                             acpi_ex_get_serial_access_length(accessor_type,
152                                                              obj_desc->field.
153                                                              access_length);
154
155                         /*
156                          * Add additional 2 bytes for the generic_serial_bus data buffer:
157                          *
158                          *     Status;    (Byte 0 of the data buffer)
159                          *     Length;    (Byte 1 of the data buffer)
160                          *     Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
161                          */
162                         length += 2;
163                         function = ACPI_READ | (accessor_type << 16);
164                 } else {        /* IPMI */
165
166                         length = ACPI_IPMI_BUFFER_SIZE;
167                         function = ACPI_READ;
168                 }
169
170                 buffer_desc = acpi_ut_create_buffer_object(length);
171                 if (!buffer_desc) {
172                         return_ACPI_STATUS(AE_NO_MEMORY);
173                 }
174
175                 /* Lock entire transaction if requested */
176
177                 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
178
179                 /* Call the region handler for the read */
180
181                 status = acpi_ex_access_region(obj_desc, 0,
182                                                ACPI_CAST_PTR(u64,
183                                                              buffer_desc->
184                                                              buffer.pointer),
185                                                function);
186
187                 acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
188                 goto exit;
189         }
190
191         /*
192          * Allocate a buffer for the contents of the field.
193          *
194          * If the field is larger than the current integer width, create
195          * a BUFFER to hold it. Otherwise, use an INTEGER. This allows
196          * the use of arithmetic operators on the returned value if the
197          * field size is equal or smaller than an Integer.
198          *
199          * Note: Field.length is in bits.
200          */
201         length =
202             (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
203
204         if (length > acpi_gbl_integer_byte_width) {
205
206                 /* Field is too large for an Integer, create a Buffer instead */
207
208                 buffer_desc = acpi_ut_create_buffer_object(length);
209                 if (!buffer_desc) {
210                         return_ACPI_STATUS(AE_NO_MEMORY);
211                 }
212                 buffer = buffer_desc->buffer.pointer;
213         } else {
214                 /* Field will fit within an Integer (normal case) */
215
216                 buffer_desc = acpi_ut_create_integer_object((u64) 0);
217                 if (!buffer_desc) {
218                         return_ACPI_STATUS(AE_NO_MEMORY);
219                 }
220
221                 length = acpi_gbl_integer_byte_width;
222                 buffer = &buffer_desc->integer.value;
223         }
224
225         if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
226             (obj_desc->field.region_obj->region.space_id ==
227              ACPI_ADR_SPACE_GPIO)) {
228                 /*
229                  * For GPIO (general_purpose_io), the Address will be the bit offset
230                  * from the previous Connection() operator, making it effectively a
231                  * pin number index. The bit_length is the length of the field, which
232                  * is thus the number of pins.
233                  */
234                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
235                                   "GPIO FieldRead [FROM]:  Pin %u Bits %u\n",
236                                   obj_desc->field.pin_number_index,
237                                   obj_desc->field.bit_length));
238
239                 /* Lock entire transaction if requested */
240
241                 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
242
243                 /* Perform the write */
244
245                 status =
246                     acpi_ex_access_region(obj_desc, 0, (u64 *)buffer,
247                                           ACPI_READ);
248
249                 acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
250                 if (ACPI_FAILURE(status)) {
251                         acpi_ut_remove_reference(buffer_desc);
252                 } else {
253                         *ret_buffer_desc = buffer_desc;
254                 }
255                 return_ACPI_STATUS(status);
256         }
257
258         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
259                           "FieldRead [TO]:   Obj %p, Type %X, Buf %p, ByteLen %X\n",
260                           obj_desc, obj_desc->common.type, buffer,
261                           (u32) length));
262         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
263                           "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
264                           obj_desc->common_field.bit_length,
265                           obj_desc->common_field.start_field_bit_offset,
266                           obj_desc->common_field.base_byte_offset));
267
268         /* Lock entire transaction if requested */
269
270         acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
271
272         /* Read from the field */
273
274         status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length);
275         acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
276
277 exit:
278         if (ACPI_FAILURE(status)) {
279                 acpi_ut_remove_reference(buffer_desc);
280         } else {
281                 *ret_buffer_desc = buffer_desc;
282         }
283
284         return_ACPI_STATUS(status);
285 }
286
287 /*******************************************************************************
288  *
289  * FUNCTION:    acpi_ex_write_data_to_field
290  *
291  * PARAMETERS:  source_desc         - Contains data to write
292  *              obj_desc            - The named field
293  *              result_desc         - Where the return value is returned, if any
294  *
295  * RETURN:      Status
296  *
297  * DESCRIPTION: Write to a named field
298  *
299  ******************************************************************************/
300
301 acpi_status
302 acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
303                             union acpi_operand_object *obj_desc,
304                             union acpi_operand_object **result_desc)
305 {
306         acpi_status status;
307         u32 length;
308         void *buffer;
309         union acpi_operand_object *buffer_desc;
310         u32 function;
311         u16 accessor_type;
312
313         ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
314
315         /* Parameter validation */
316
317         if (!source_desc || !obj_desc) {
318                 return_ACPI_STATUS(AE_AML_NO_OPERAND);
319         }
320
321         if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) {
322                 /*
323                  * If the buffer_field arguments have not been previously evaluated,
324                  * evaluate them now and save the results.
325                  */
326                 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
327                         status = acpi_ds_get_buffer_field_arguments(obj_desc);
328                         if (ACPI_FAILURE(status)) {
329                                 return_ACPI_STATUS(status);
330                         }
331                 }
332         } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
333                    (obj_desc->field.region_obj->region.space_id ==
334                     ACPI_ADR_SPACE_SMBUS
335                     || obj_desc->field.region_obj->region.space_id ==
336                     ACPI_ADR_SPACE_GSBUS
337                     || obj_desc->field.region_obj->region.space_id ==
338                     ACPI_ADR_SPACE_IPMI)) {
339                 /*
340                  * This is an SMBus, GSBus or IPMI write. We will bypass the entire
341                  * field mechanism and handoff the buffer directly to the handler.
342                  * For these address spaces, the buffer is bi-directional; on a
343                  * write, return data is returned in the same buffer.
344                  *
345                  * Source must be a buffer of sufficient size:
346                  * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or
347                  * ACPI_IPMI_BUFFER_SIZE.
348                  *
349                  * Note: SMBus and GSBus protocol type is passed in upper 16-bits
350                  * of Function
351                  */
352                 if (source_desc->common.type != ACPI_TYPE_BUFFER) {
353                         ACPI_ERROR((AE_INFO,
354                                     "SMBus/IPMI/GenericSerialBus write requires "
355                                     "Buffer, found type %s",
356                                     acpi_ut_get_object_type_name(source_desc)));
357
358                         return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
359                 }
360
361                 if (obj_desc->field.region_obj->region.space_id ==
362                     ACPI_ADR_SPACE_SMBUS) {
363                         length = ACPI_SMBUS_BUFFER_SIZE;
364                         function =
365                             ACPI_WRITE | (obj_desc->field.attribute << 16);
366                 } else if (obj_desc->field.region_obj->region.space_id ==
367                            ACPI_ADR_SPACE_GSBUS) {
368                         accessor_type = obj_desc->field.attribute;
369                         length =
370                             acpi_ex_get_serial_access_length(accessor_type,
371                                                              obj_desc->field.
372                                                              access_length);
373
374                         /*
375                          * Add additional 2 bytes for the generic_serial_bus data buffer:
376                          *
377                          *     Status;    (Byte 0 of the data buffer)
378                          *     Length;    (Byte 1 of the data buffer)
379                          *     Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
380                          */
381                         length += 2;
382                         function = ACPI_WRITE | (accessor_type << 16);
383                 } else {        /* IPMI */
384
385                         length = ACPI_IPMI_BUFFER_SIZE;
386                         function = ACPI_WRITE;
387                 }
388
389                 if (source_desc->buffer.length < length) {
390                         ACPI_ERROR((AE_INFO,
391                                     "SMBus/IPMI/GenericSerialBus write requires "
392                                     "Buffer of length %u, found length %u",
393                                     length, source_desc->buffer.length));
394
395                         return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
396                 }
397
398                 /* Create the bi-directional buffer */
399
400                 buffer_desc = acpi_ut_create_buffer_object(length);
401                 if (!buffer_desc) {
402                         return_ACPI_STATUS(AE_NO_MEMORY);
403                 }
404
405                 buffer = buffer_desc->buffer.pointer;
406                 memcpy(buffer, source_desc->buffer.pointer, length);
407
408                 /* Lock entire transaction if requested */
409
410                 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
411
412                 /*
413                  * Perform the write (returns status and perhaps data in the
414                  * same buffer)
415                  */
416                 status =
417                     acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function);
418                 acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
419
420                 *result_desc = buffer_desc;
421                 return_ACPI_STATUS(status);
422         } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
423                    (obj_desc->field.region_obj->region.space_id ==
424                     ACPI_ADR_SPACE_GPIO)) {
425                 /*
426                  * For GPIO (general_purpose_io), we will bypass the entire field
427                  * mechanism and handoff the bit address and bit width directly to
428                  * the handler. The Address will be the bit offset
429                  * from the previous Connection() operator, making it effectively a
430                  * pin number index. The bit_length is the length of the field, which
431                  * is thus the number of pins.
432                  */
433                 if (source_desc->common.type != ACPI_TYPE_INTEGER) {
434                         return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
435                 }
436
437                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
438                                   "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X  [TO]: Pin %u Bits %u\n",
439                                   acpi_ut_get_type_name(source_desc->common.
440                                                         type),
441                                   source_desc->common.type,
442                                   (u32)source_desc->integer.value,
443                                   obj_desc->field.pin_number_index,
444                                   obj_desc->field.bit_length));
445
446                 buffer = &source_desc->integer.value;
447
448                 /* Lock entire transaction if requested */
449
450                 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
451
452                 /* Perform the write */
453
454                 status =
455                     acpi_ex_access_region(obj_desc, 0, (u64 *)buffer,
456                                           ACPI_WRITE);
457                 acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
458                 return_ACPI_STATUS(status);
459         }
460
461         /* Get a pointer to the data to be written */
462
463         switch (source_desc->common.type) {
464         case ACPI_TYPE_INTEGER:
465
466                 buffer = &source_desc->integer.value;
467                 length = sizeof(source_desc->integer.value);
468                 break;
469
470         case ACPI_TYPE_BUFFER:
471
472                 buffer = source_desc->buffer.pointer;
473                 length = source_desc->buffer.length;
474                 break;
475
476         case ACPI_TYPE_STRING:
477
478                 buffer = source_desc->string.pointer;
479                 length = source_desc->string.length;
480                 break;
481
482         default:
483
484                 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
485         }
486
487         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
488                           "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
489                           source_desc,
490                           acpi_ut_get_type_name(source_desc->common.type),
491                           source_desc->common.type, buffer, length));
492
493         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
494                           "FieldWrite [TO]:   Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
495                           obj_desc,
496                           acpi_ut_get_type_name(obj_desc->common.type),
497                           obj_desc->common.type,
498                           obj_desc->common_field.bit_length,
499                           obj_desc->common_field.start_field_bit_offset,
500                           obj_desc->common_field.base_byte_offset));
501
502         /* Lock entire transaction if requested */
503
504         acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
505
506         /* Write to the field */
507
508         status = acpi_ex_insert_into_field(obj_desc, buffer, length);
509         acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
510
511         return_ACPI_STATUS(status);
512 }