1  // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2  /******************************************************************************
3   *
4   * Module Name: exfldio - Aml Field I/O
5   *
6   * Copyright (C) 2000 - 2023, Intel Corp.
7   *
8   *****************************************************************************/
9  
10  #include <acpi/acpi.h>
11  #include "accommon.h"
12  #include "acinterp.h"
13  #include "amlcode.h"
14  #include "acevents.h"
15  #include "acdispat.h"
16  
17  #define _COMPONENT          ACPI_EXECUTER
18  ACPI_MODULE_NAME("exfldio")
19  
20  /* Local prototypes */
21  static acpi_status
22  acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
23  		       u32 field_datum_byte_offset, u64 *value, u32 read_write);
24  
25  static u8
26  acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value);
27  
28  static acpi_status
29  acpi_ex_setup_region(union acpi_operand_object *obj_desc,
30  		     u32 field_datum_byte_offset);
31  
32  /*******************************************************************************
33   *
34   * FUNCTION:    acpi_ex_setup_region
35   *
36   * PARAMETERS:  obj_desc                - Field to be read or written
37   *              field_datum_byte_offset - Byte offset of this datum within the
38   *                                        parent field
39   *
40   * RETURN:      Status
41   *
42   * DESCRIPTION: Common processing for acpi_ex_extract_from_field and
43   *              acpi_ex_insert_into_field. Initialize the Region if necessary and
44   *              validate the request.
45   *
46   ******************************************************************************/
47  
48  static acpi_status
acpi_ex_setup_region(union acpi_operand_object * obj_desc,u32 field_datum_byte_offset)49  acpi_ex_setup_region(union acpi_operand_object *obj_desc,
50  		     u32 field_datum_byte_offset)
51  {
52  	acpi_status status = AE_OK;
53  	union acpi_operand_object *rgn_desc;
54  	u8 space_id;
55  
56  	ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset);
57  
58  	rgn_desc = obj_desc->common_field.region_obj;
59  
60  	/* We must have a valid region */
61  
62  	if (rgn_desc->common.type != ACPI_TYPE_REGION) {
63  		ACPI_ERROR((AE_INFO, "Needed Region, found type 0x%X (%s)",
64  			    rgn_desc->common.type,
65  			    acpi_ut_get_object_type_name(rgn_desc)));
66  
67  		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
68  	}
69  
70  	space_id = rgn_desc->region.space_id;
71  
72  	/* Validate the Space ID */
73  
74  	if (!acpi_is_valid_space_id(space_id)) {
75  		ACPI_ERROR((AE_INFO,
76  			    "Invalid/unknown Address Space ID: 0x%2.2X",
77  			    space_id));
78  		return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
79  	}
80  
81  	/*
82  	 * If the Region Address and Length have not been previously evaluated,
83  	 * evaluate them now and save the results.
84  	 */
85  	if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
86  		status = acpi_ds_get_region_arguments(rgn_desc);
87  		if (ACPI_FAILURE(status)) {
88  			return_ACPI_STATUS(status);
89  		}
90  	}
91  
92  	/*
93  	 * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear
94  	 * address space and the request cannot be directly validated
95  	 */
96  	if (space_id == ACPI_ADR_SPACE_SMBUS ||
97  	    space_id == ACPI_ADR_SPACE_GSBUS ||
98  	    space_id == ACPI_ADR_SPACE_IPMI) {
99  
100  		/* SMBus or IPMI has a non-linear address space */
101  
102  		return_ACPI_STATUS(AE_OK);
103  	}
104  #ifdef ACPI_UNDER_DEVELOPMENT
105  	/*
106  	 * If the Field access is any_acc, we can now compute the optimal
107  	 * access (because we know the length of the parent region)
108  	 */
109  	if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
110  		if (ACPI_FAILURE(status)) {
111  			return_ACPI_STATUS(status);
112  		}
113  	}
114  #endif
115  
116  	/*
117  	 * Validate the request. The entire request from the byte offset for a
118  	 * length of one field datum (access width) must fit within the region.
119  	 * (Region length is specified in bytes)
120  	 */
121  	if (rgn_desc->region.length <
122  	    (obj_desc->common_field.base_byte_offset + field_datum_byte_offset +
123  	     obj_desc->common_field.access_byte_width)) {
124  		if (acpi_gbl_enable_interpreter_slack) {
125  			/*
126  			 * Slack mode only:  We will go ahead and allow access to this
127  			 * field if it is within the region length rounded up to the next
128  			 * access width boundary. acpi_size cast for 64-bit compile.
129  			 */
130  			if (ACPI_ROUND_UP(rgn_desc->region.length,
131  					  obj_desc->common_field.
132  					  access_byte_width) >=
133  			    ((acpi_size)obj_desc->common_field.
134  			     base_byte_offset +
135  			     obj_desc->common_field.access_byte_width +
136  			     field_datum_byte_offset)) {
137  				return_ACPI_STATUS(AE_OK);
138  			}
139  		}
140  
141  		if (rgn_desc->region.length <
142  		    obj_desc->common_field.access_byte_width) {
143  			/*
144  			 * This is the case where the access_type (acc_word, etc.) is wider
145  			 * than the region itself. For example, a region of length one
146  			 * byte, and a field with Dword access specified.
147  			 */
148  			ACPI_ERROR((AE_INFO,
149  				    "Field [%4.4s] access width (%u bytes) "
150  				    "too large for region [%4.4s] (length %u)",
151  				    acpi_ut_get_node_name(obj_desc->
152  							  common_field.node),
153  				    obj_desc->common_field.access_byte_width,
154  				    acpi_ut_get_node_name(rgn_desc->region.
155  							  node),
156  				    rgn_desc->region.length));
157  		}
158  
159  		/*
160  		 * Offset rounded up to next multiple of field width
161  		 * exceeds region length, indicate an error
162  		 */
163  		ACPI_ERROR((AE_INFO,
164  			    "Field [%4.4s] Base+Offset+Width %u+%u+%u "
165  			    "is beyond end of region [%4.4s] (length %u)",
166  			    acpi_ut_get_node_name(obj_desc->common_field.node),
167  			    obj_desc->common_field.base_byte_offset,
168  			    field_datum_byte_offset,
169  			    obj_desc->common_field.access_byte_width,
170  			    acpi_ut_get_node_name(rgn_desc->region.node),
171  			    rgn_desc->region.length));
172  
173  		return_ACPI_STATUS(AE_AML_REGION_LIMIT);
174  	}
175  
176  	return_ACPI_STATUS(AE_OK);
177  }
178  
179  /*******************************************************************************
180   *
181   * FUNCTION:    acpi_ex_access_region
182   *
183   * PARAMETERS:  obj_desc                - Field to be read
184   *              field_datum_byte_offset - Byte offset of this datum within the
185   *                                        parent field
186   *              value                   - Where to store value (must at least
187   *                                        64 bits)
188   *              function                - Read or Write flag plus other region-
189   *                                        dependent flags
190   *
191   * RETURN:      Status
192   *
193   * DESCRIPTION: Read or Write a single field datum to an Operation Region.
194   *
195   ******************************************************************************/
196  
197  acpi_status
acpi_ex_access_region(union acpi_operand_object * obj_desc,u32 field_datum_byte_offset,u64 * value,u32 function)198  acpi_ex_access_region(union acpi_operand_object *obj_desc,
199  		      u32 field_datum_byte_offset, u64 *value, u32 function)
200  {
201  	acpi_status status;
202  	union acpi_operand_object *rgn_desc;
203  	u32 region_offset;
204  
205  	ACPI_FUNCTION_TRACE(ex_access_region);
206  
207  	/*
208  	 * Ensure that the region operands are fully evaluated and verify
209  	 * the validity of the request
210  	 */
211  	status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset);
212  	if (ACPI_FAILURE(status)) {
213  		return_ACPI_STATUS(status);
214  	}
215  
216  	/*
217  	 * The physical address of this field datum is:
218  	 *
219  	 * 1) The base of the region, plus
220  	 * 2) The base offset of the field, plus
221  	 * 3) The current offset into the field
222  	 */
223  	rgn_desc = obj_desc->common_field.region_obj;
224  	region_offset =
225  	    obj_desc->common_field.base_byte_offset + field_datum_byte_offset;
226  
227  	if ((function & ACPI_IO_MASK) == ACPI_READ) {
228  		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]"));
229  	} else {
230  		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]"));
231  	}
232  
233  	ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
234  			      " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
235  			      acpi_ut_get_region_name(rgn_desc->region.
236  						      space_id),
237  			      rgn_desc->region.space_id,
238  			      obj_desc->common_field.access_byte_width,
239  			      obj_desc->common_field.base_byte_offset,
240  			      field_datum_byte_offset,
241  			      ACPI_FORMAT_UINT64(rgn_desc->region.address +
242  						 region_offset)));
243  
244  	/* Invoke the appropriate address_space/op_region handler */
245  
246  	status = acpi_ev_address_space_dispatch(rgn_desc, obj_desc,
247  						function, region_offset,
248  						ACPI_MUL_8(obj_desc->
249  							   common_field.
250  							   access_byte_width),
251  						value);
252  
253  	if (ACPI_FAILURE(status)) {
254  		if (status == AE_NOT_IMPLEMENTED) {
255  			ACPI_ERROR((AE_INFO,
256  				    "Region %s (ID=%u) not implemented",
257  				    acpi_ut_get_region_name(rgn_desc->region.
258  							    space_id),
259  				    rgn_desc->region.space_id));
260  		} else if (status == AE_NOT_EXIST) {
261  			ACPI_ERROR((AE_INFO,
262  				    "Region %s (ID=%u) has no handler",
263  				    acpi_ut_get_region_name(rgn_desc->region.
264  							    space_id),
265  				    rgn_desc->region.space_id));
266  		}
267  	}
268  
269  	return_ACPI_STATUS(status);
270  }
271  
272  /*******************************************************************************
273   *
274   * FUNCTION:    acpi_ex_register_overflow
275   *
276   * PARAMETERS:  obj_desc                - Register(Field) to be written
277   *              value                   - Value to be stored
278   *
279   * RETURN:      TRUE if value overflows the field, FALSE otherwise
280   *
281   * DESCRIPTION: Check if a value is out of range of the field being written.
282   *              Used to check if the values written to Index and Bank registers
283   *              are out of range. Normally, the value is simply truncated
284   *              to fit the field, but this case is most likely a serious
285   *              coding error in the ASL.
286   *
287   ******************************************************************************/
288  
289  static u8
acpi_ex_register_overflow(union acpi_operand_object * obj_desc,u64 value)290  acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)
291  {
292  
293  	if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
294  		/*
295  		 * The field is large enough to hold the maximum integer, so we can
296  		 * never overflow it.
297  		 */
298  		return (FALSE);
299  	}
300  
301  	if (value >= ((u64) 1 << obj_desc->common_field.bit_length)) {
302  		/*
303  		 * The Value is larger than the maximum value that can fit into
304  		 * the register.
305  		 */
306  		ACPI_ERROR((AE_INFO,
307  			    "Index value 0x%8.8X%8.8X overflows field width 0x%X",
308  			    ACPI_FORMAT_UINT64(value),
309  			    obj_desc->common_field.bit_length));
310  
311  		return (TRUE);
312  	}
313  
314  	/* The Value will fit into the field with no truncation */
315  
316  	return (FALSE);
317  }
318  
319  /*******************************************************************************
320   *
321   * FUNCTION:    acpi_ex_field_datum_io
322   *
323   * PARAMETERS:  obj_desc                - Field to be read
324   *              field_datum_byte_offset - Byte offset of this datum within the
325   *                                        parent field
326   *              value                   - Where to store value (must be 64 bits)
327   *              read_write              - Read or Write flag
328   *
329   * RETURN:      Status
330   *
331   * DESCRIPTION: Read or Write a single datum of a field. The field_type is
332   *              demultiplexed here to handle the different types of fields
333   *              (buffer_field, region_field, index_field, bank_field)
334   *
335   ******************************************************************************/
336  
337  static acpi_status
acpi_ex_field_datum_io(union acpi_operand_object * obj_desc,u32 field_datum_byte_offset,u64 * value,u32 read_write)338  acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
339  		       u32 field_datum_byte_offset, u64 *value, u32 read_write)
340  {
341  	acpi_status status;
342  	u64 local_value;
343  
344  	ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset);
345  
346  	if (read_write == ACPI_READ) {
347  		if (!value) {
348  			local_value = 0;
349  
350  			/* To support reads without saving return value */
351  			value = &local_value;
352  		}
353  
354  		/* Clear the entire return buffer first, [Very Important!] */
355  
356  		*value = 0;
357  	}
358  
359  	/*
360  	 * The four types of fields are:
361  	 *
362  	 * buffer_field - Read/write from/to a Buffer
363  	 * region_field - Read/write from/to a Operation Region.
364  	 * bank_field  - Write to a Bank Register, then read/write from/to an
365  	 *               operation_region
366  	 * index_field - Write to an Index Register, then read/write from/to a
367  	 *               Data Register
368  	 */
369  	switch (obj_desc->common.type) {
370  	case ACPI_TYPE_BUFFER_FIELD:
371  		/*
372  		 * If the buffer_field arguments have not been previously evaluated,
373  		 * evaluate them now and save the results.
374  		 */
375  		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
376  			status = acpi_ds_get_buffer_field_arguments(obj_desc);
377  			if (ACPI_FAILURE(status)) {
378  				return_ACPI_STATUS(status);
379  			}
380  		}
381  
382  		if (read_write == ACPI_READ) {
383  			/*
384  			 * Copy the data from the source buffer.
385  			 * Length is the field width in bytes.
386  			 */
387  			memcpy(value,
388  			       (obj_desc->buffer_field.buffer_obj)->buffer.
389  			       pointer +
390  			       obj_desc->buffer_field.base_byte_offset +
391  			       field_datum_byte_offset,
392  			       obj_desc->common_field.access_byte_width);
393  		} else {
394  			/*
395  			 * Copy the data to the target buffer.
396  			 * Length is the field width in bytes.
397  			 */
398  			memcpy((obj_desc->buffer_field.buffer_obj)->buffer.
399  			       pointer +
400  			       obj_desc->buffer_field.base_byte_offset +
401  			       field_datum_byte_offset, value,
402  			       obj_desc->common_field.access_byte_width);
403  		}
404  
405  		status = AE_OK;
406  		break;
407  
408  	case ACPI_TYPE_LOCAL_BANK_FIELD:
409  		/*
410  		 * Ensure that the bank_value is not beyond the capacity of
411  		 * the register
412  		 */
413  		if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj,
414  					      (u64) obj_desc->bank_field.
415  					      value)) {
416  			return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
417  		}
418  
419  		/*
420  		 * For bank_fields, we must write the bank_value to the bank_register
421  		 * (itself a region_field) before we can access the data.
422  		 */
423  		status =
424  		    acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj,
425  					      &obj_desc->bank_field.value,
426  					      sizeof(obj_desc->bank_field.
427  						     value));
428  		if (ACPI_FAILURE(status)) {
429  			return_ACPI_STATUS(status);
430  		}
431  
432  		/*
433  		 * Now that the Bank has been selected, fall through to the
434  		 * region_field case and write the datum to the Operation Region
435  		 */
436  
437  		ACPI_FALLTHROUGH;
438  
439  	case ACPI_TYPE_LOCAL_REGION_FIELD:
440  		/*
441  		 * For simple region_fields, we just directly access the owning
442  		 * Operation Region.
443  		 */
444  		status =
445  		    acpi_ex_access_region(obj_desc, field_datum_byte_offset,
446  					  value, read_write);
447  		break;
448  
449  	case ACPI_TYPE_LOCAL_INDEX_FIELD:
450  		/*
451  		 * Ensure that the index_value is not beyond the capacity of
452  		 * the register
453  		 */
454  		if (acpi_ex_register_overflow(obj_desc->index_field.index_obj,
455  					      (u64) obj_desc->index_field.
456  					      value)) {
457  			return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
458  		}
459  
460  		/* Write the index value to the index_register (itself a region_field) */
461  
462  		field_datum_byte_offset += obj_desc->index_field.value;
463  
464  		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
465  				  "Write to Index Register: Value %8.8X\n",
466  				  field_datum_byte_offset));
467  
468  		status =
469  		    acpi_ex_insert_into_field(obj_desc->index_field.index_obj,
470  					      &field_datum_byte_offset,
471  					      sizeof(field_datum_byte_offset));
472  		if (ACPI_FAILURE(status)) {
473  			return_ACPI_STATUS(status);
474  		}
475  
476  		if (read_write == ACPI_READ) {
477  
478  			/* Read the datum from the data_register */
479  
480  			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
481  					  "Read from Data Register\n"));
482  
483  			status =
484  			    acpi_ex_extract_from_field(obj_desc->index_field.
485  						       data_obj, value,
486  						       sizeof(u64));
487  		} else {
488  			/* Write the datum to the data_register */
489  
490  			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
491  					  "Write to Data Register: Value %8.8X%8.8X\n",
492  					  ACPI_FORMAT_UINT64(*value)));
493  
494  			status =
495  			    acpi_ex_insert_into_field(obj_desc->index_field.
496  						      data_obj, value,
497  						      sizeof(u64));
498  		}
499  		break;
500  
501  	default:
502  
503  		ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %u",
504  			    obj_desc->common.type));
505  		status = AE_AML_INTERNAL;
506  		break;
507  	}
508  
509  	if (ACPI_SUCCESS(status)) {
510  		if (read_write == ACPI_READ) {
511  			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
512  					  "Value Read %8.8X%8.8X, Width %u\n",
513  					  ACPI_FORMAT_UINT64(*value),
514  					  obj_desc->common_field.
515  					  access_byte_width));
516  		} else {
517  			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
518  					  "Value Written %8.8X%8.8X, Width %u\n",
519  					  ACPI_FORMAT_UINT64(*value),
520  					  obj_desc->common_field.
521  					  access_byte_width));
522  		}
523  	}
524  
525  	return_ACPI_STATUS(status);
526  }
527  
528  /*******************************************************************************
529   *
530   * FUNCTION:    acpi_ex_write_with_update_rule
531   *
532   * PARAMETERS:  obj_desc                - Field to be written
533   *              mask                    - bitmask within field datum
534   *              field_value             - Value to write
535   *              field_datum_byte_offset - Offset of datum within field
536   *
537   * RETURN:      Status
538   *
539   * DESCRIPTION: Apply the field update rule to a field write
540   *
541   ******************************************************************************/
542  
543  acpi_status
acpi_ex_write_with_update_rule(union acpi_operand_object * obj_desc,u64 mask,u64 field_value,u32 field_datum_byte_offset)544  acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
545  			       u64 mask,
546  			       u64 field_value, u32 field_datum_byte_offset)
547  {
548  	acpi_status status = AE_OK;
549  	u64 merged_value;
550  	u64 current_value;
551  
552  	ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask);
553  
554  	/* Start with the new bits  */
555  
556  	merged_value = field_value;
557  
558  	/* If the mask is all ones, we don't need to worry about the update rule */
559  
560  	if (mask != ACPI_UINT64_MAX) {
561  
562  		/* Decode the update rule */
563  
564  		switch (obj_desc->common_field.
565  			field_flags & AML_FIELD_UPDATE_RULE_MASK) {
566  		case AML_FIELD_UPDATE_PRESERVE:
567  			/*
568  			 * Check if update rule needs to be applied (not if mask is all
569  			 * ones)  The left shift drops the bits we want to ignore.
570  			 */
571  			if ((~mask << (ACPI_MUL_8(sizeof(mask)) -
572  				       ACPI_MUL_8(obj_desc->common_field.
573  						  access_byte_width))) != 0) {
574  				/*
575  				 * Read the current contents of the byte/word/dword containing
576  				 * the field, and merge with the new field value.
577  				 */
578  				status =
579  				    acpi_ex_field_datum_io(obj_desc,
580  							   field_datum_byte_offset,
581  							   &current_value,
582  							   ACPI_READ);
583  				if (ACPI_FAILURE(status)) {
584  					return_ACPI_STATUS(status);
585  				}
586  
587  				merged_value |= (current_value & ~mask);
588  			}
589  			break;
590  
591  		case AML_FIELD_UPDATE_WRITE_AS_ONES:
592  
593  			/* Set positions outside the field to all ones */
594  
595  			merged_value |= ~mask;
596  			break;
597  
598  		case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
599  
600  			/* Set positions outside the field to all zeros */
601  
602  			merged_value &= mask;
603  			break;
604  
605  		default:
606  
607  			ACPI_ERROR((AE_INFO,
608  				    "Unknown UpdateRule value: 0x%X",
609  				    (obj_desc->common_field.field_flags &
610  				     AML_FIELD_UPDATE_RULE_MASK)));
611  			return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
612  		}
613  	}
614  
615  	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
616  			  "Mask %8.8X%8.8X, DatumOffset %X, Width %X, "
617  			  "Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
618  			  ACPI_FORMAT_UINT64(mask),
619  			  field_datum_byte_offset,
620  			  obj_desc->common_field.access_byte_width,
621  			  ACPI_FORMAT_UINT64(field_value),
622  			  ACPI_FORMAT_UINT64(merged_value)));
623  
624  	/* Write the merged value */
625  
626  	status =
627  	    acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
628  				   &merged_value, ACPI_WRITE);
629  
630  	return_ACPI_STATUS(status);
631  }
632  
633  /*******************************************************************************
634   *
635   * FUNCTION:    acpi_ex_extract_from_field
636   *
637   * PARAMETERS:  obj_desc            - Field to be read
638   *              buffer              - Where to store the field data
639   *              buffer_length       - Length of Buffer
640   *
641   * RETURN:      Status
642   *
643   * DESCRIPTION: Retrieve the current value of the given field
644   *
645   ******************************************************************************/
646  
647  acpi_status
acpi_ex_extract_from_field(union acpi_operand_object * obj_desc,void * buffer,u32 buffer_length)648  acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
649  			   void *buffer, u32 buffer_length)
650  {
651  	acpi_status status;
652  	u64 raw_datum;
653  	u64 merged_datum;
654  	u32 field_offset = 0;
655  	u32 buffer_offset = 0;
656  	u32 buffer_tail_bits;
657  	u32 datum_count;
658  	u32 field_datum_count;
659  	u32 access_bit_width;
660  	u32 i;
661  
662  	ACPI_FUNCTION_TRACE(ex_extract_from_field);
663  
664  	/* Validate target buffer and clear it */
665  
666  	if (buffer_length <
667  	    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
668  		ACPI_ERROR((AE_INFO,
669  			    "Field size %u (bits) is too large for buffer (%u)",
670  			    obj_desc->common_field.bit_length, buffer_length));
671  
672  		return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
673  	}
674  
675  	memset(buffer, 0, buffer_length);
676  	access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
677  
678  	/* Handle the simple case here */
679  
680  	if ((obj_desc->common_field.start_field_bit_offset == 0) &&
681  	    (obj_desc->common_field.bit_length == access_bit_width)) {
682  		if (buffer_length >= sizeof(u64)) {
683  			status =
684  			    acpi_ex_field_datum_io(obj_desc, 0, buffer,
685  						   ACPI_READ);
686  		} else {
687  			/* Use raw_datum (u64) to handle buffers < 64 bits */
688  
689  			status =
690  			    acpi_ex_field_datum_io(obj_desc, 0, &raw_datum,
691  						   ACPI_READ);
692  			memcpy(buffer, &raw_datum, buffer_length);
693  		}
694  
695  		return_ACPI_STATUS(status);
696  	}
697  
698  /* TBD: Move to common setup code */
699  
700  	/* Field algorithm is limited to sizeof(u64), truncate if needed */
701  
702  	if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
703  		obj_desc->common_field.access_byte_width = sizeof(u64);
704  		access_bit_width = sizeof(u64) * 8;
705  	}
706  
707  	/* Compute the number of datums (access width data items) */
708  
709  	datum_count =
710  	    ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
711  			     access_bit_width);
712  
713  	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
714  					     obj_desc->common_field.
715  					     start_field_bit_offset,
716  					     access_bit_width);
717  
718  	/* Priming read from the field */
719  
720  	status =
721  	    acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
722  				   ACPI_READ);
723  	if (ACPI_FAILURE(status)) {
724  		return_ACPI_STATUS(status);
725  	}
726  	merged_datum =
727  	    raw_datum >> obj_desc->common_field.start_field_bit_offset;
728  
729  	/* Read the rest of the field */
730  
731  	for (i = 1; i < field_datum_count; i++) {
732  
733  		/* Get next input datum from the field */
734  
735  		field_offset += obj_desc->common_field.access_byte_width;
736  		status =
737  		    acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
738  					   ACPI_READ);
739  		if (ACPI_FAILURE(status)) {
740  			return_ACPI_STATUS(status);
741  		}
742  
743  		/*
744  		 * Merge with previous datum if necessary.
745  		 *
746  		 * Note: Before the shift, check if the shift value will be larger than
747  		 * the integer size. If so, there is no need to perform the operation.
748  		 * This avoids the differences in behavior between different compilers
749  		 * concerning shift values larger than the target data width.
750  		 */
751  		if (access_bit_width -
752  		    obj_desc->common_field.start_field_bit_offset <
753  		    ACPI_INTEGER_BIT_SIZE) {
754  			merged_datum |=
755  			    raw_datum << (access_bit_width -
756  					  obj_desc->common_field.
757  					  start_field_bit_offset);
758  		}
759  
760  		if (i == datum_count) {
761  			break;
762  		}
763  
764  		/* Write merged datum to target buffer */
765  
766  		memcpy(((char *)buffer) + buffer_offset, &merged_datum,
767  		       ACPI_MIN(obj_desc->common_field.access_byte_width,
768  				buffer_length - buffer_offset));
769  
770  		buffer_offset += obj_desc->common_field.access_byte_width;
771  		merged_datum =
772  		    raw_datum >> obj_desc->common_field.start_field_bit_offset;
773  	}
774  
775  	/* Mask off any extra bits in the last datum */
776  
777  	buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
778  	if (buffer_tail_bits) {
779  		merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
780  	}
781  
782  	/* Write the last datum to the buffer */
783  
784  	memcpy(((char *)buffer) + buffer_offset, &merged_datum,
785  	       ACPI_MIN(obj_desc->common_field.access_byte_width,
786  			buffer_length - buffer_offset));
787  
788  	return_ACPI_STATUS(AE_OK);
789  }
790  
791  /*******************************************************************************
792   *
793   * FUNCTION:    acpi_ex_insert_into_field
794   *
795   * PARAMETERS:  obj_desc            - Field to be written
796   *              buffer              - Data to be written
797   *              buffer_length       - Length of Buffer
798   *
799   * RETURN:      Status
800   *
801   * DESCRIPTION: Store the Buffer contents into the given field
802   *
803   ******************************************************************************/
804  
805  acpi_status
acpi_ex_insert_into_field(union acpi_operand_object * obj_desc,void * buffer,u32 buffer_length)806  acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
807  			  void *buffer, u32 buffer_length)
808  {
809  	void *new_buffer;
810  	acpi_status status;
811  	u64 mask;
812  	u64 width_mask;
813  	u64 merged_datum;
814  	u64 raw_datum = 0;
815  	u32 field_offset = 0;
816  	u32 buffer_offset = 0;
817  	u32 buffer_tail_bits;
818  	u32 datum_count;
819  	u32 field_datum_count;
820  	u32 access_bit_width;
821  	u32 required_length;
822  	u32 i;
823  
824  	ACPI_FUNCTION_TRACE(ex_insert_into_field);
825  
826  	/* Validate input buffer */
827  
828  	new_buffer = NULL;
829  	required_length =
830  	    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
831  
832  	/*
833  	 * We must have a buffer that is at least as long as the field
834  	 * we are writing to. This is because individual fields are
835  	 * indivisible and partial writes are not supported -- as per
836  	 * the ACPI specification.
837  	 */
838  	if (buffer_length < required_length) {
839  
840  		/* We need to create a new buffer */
841  
842  		new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
843  		if (!new_buffer) {
844  			return_ACPI_STATUS(AE_NO_MEMORY);
845  		}
846  
847  		/*
848  		 * Copy the original data to the new buffer, starting
849  		 * at Byte zero. All unused (upper) bytes of the
850  		 * buffer will be 0.
851  		 */
852  		memcpy((char *)new_buffer, (char *)buffer, buffer_length);
853  		buffer = new_buffer;
854  		buffer_length = required_length;
855  	}
856  
857  /* TBD: Move to common setup code */
858  
859  	/* Algo is limited to sizeof(u64), so cut the access_byte_width */
860  	if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
861  		obj_desc->common_field.access_byte_width = sizeof(u64);
862  	}
863  
864  	access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
865  
866  	/* Create the bitmasks used for bit insertion */
867  
868  	width_mask = ACPI_MASK_BITS_ABOVE_64(access_bit_width);
869  	mask = width_mask &
870  	    ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);
871  
872  	/* Compute the number of datums (access width data items) */
873  
874  	datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
875  				       access_bit_width);
876  
877  	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
878  					     obj_desc->common_field.
879  					     start_field_bit_offset,
880  					     access_bit_width);
881  
882  	/* Get initial Datum from the input buffer */
883  
884  	memcpy(&raw_datum, buffer,
885  	       ACPI_MIN(obj_desc->common_field.access_byte_width,
886  			buffer_length - buffer_offset));
887  
888  	merged_datum =
889  	    raw_datum << obj_desc->common_field.start_field_bit_offset;
890  
891  	/* Write the entire field */
892  
893  	for (i = 1; i < field_datum_count; i++) {
894  
895  		/* Write merged datum to the target field */
896  
897  		merged_datum &= mask;
898  		status =
899  		    acpi_ex_write_with_update_rule(obj_desc, mask, merged_datum,
900  						   field_offset);
901  		if (ACPI_FAILURE(status)) {
902  			goto exit;
903  		}
904  
905  		field_offset += obj_desc->common_field.access_byte_width;
906  
907  		/*
908  		 * Start new output datum by merging with previous input datum
909  		 * if necessary.
910  		 *
911  		 * Note: Before the shift, check if the shift value will be larger than
912  		 * the integer size. If so, there is no need to perform the operation.
913  		 * This avoids the differences in behavior between different compilers
914  		 * concerning shift values larger than the target data width.
915  		 */
916  		if ((access_bit_width -
917  		     obj_desc->common_field.start_field_bit_offset) <
918  		    ACPI_INTEGER_BIT_SIZE) {
919  			merged_datum =
920  			    raw_datum >> (access_bit_width -
921  					  obj_desc->common_field.
922  					  start_field_bit_offset);
923  		} else {
924  			merged_datum = 0;
925  		}
926  
927  		mask = width_mask;
928  
929  		if (i == datum_count) {
930  			break;
931  		}
932  
933  		/* Get the next input datum from the buffer */
934  
935  		buffer_offset += obj_desc->common_field.access_byte_width;
936  		memcpy(&raw_datum, ((char *)buffer) + buffer_offset,
937  		       ACPI_MIN(obj_desc->common_field.access_byte_width,
938  				buffer_length - buffer_offset));
939  
940  		merged_datum |=
941  		    raw_datum << obj_desc->common_field.start_field_bit_offset;
942  	}
943  
944  	/* Mask off any extra bits in the last datum */
945  
946  	buffer_tail_bits = (obj_desc->common_field.bit_length +
947  			    obj_desc->common_field.start_field_bit_offset) %
948  	    access_bit_width;
949  	if (buffer_tail_bits) {
950  		mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
951  	}
952  
953  	/* Write the last datum to the field */
954  
955  	merged_datum &= mask;
956  	status =
957  	    acpi_ex_write_with_update_rule(obj_desc, mask, merged_datum,
958  					   field_offset);
959  
960  exit:
961  	/* Free temporary buffer if we used one */
962  
963  	if (new_buffer) {
964  		ACPI_FREE(new_buffer);
965  	}
966  	return_ACPI_STATUS(status);
967  }
968