ReactOS  0.4.15-dev-1033-gd7d716a
exfldio.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * Module Name: exfldio - Aml Field I/O
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2020, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  * notice, this list of conditions, and the following disclaimer,
16  * without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  * substantially similar to the "NO WARRANTY" disclaimer below
19  * ("Disclaimer") and any redistribution must be conditioned upon
20  * including a substantially similar Disclaimer requirement for further
21  * binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  * of any contributors may be used to endorse or promote products derived
24  * from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acinterp.h"
47 #include "amlcode.h"
48 #include "acevents.h"
49 #include "acdispat.h"
50 
51 
52 #define _COMPONENT ACPI_EXECUTER
53  ACPI_MODULE_NAME ("exfldio")
54 
55 /* Local prototypes */
56 
57 static ACPI_STATUS
59  ACPI_OPERAND_OBJECT *ObjDesc,
60  UINT32 FieldDatumByteOffset,
61  UINT64 *Value,
63 
64 static BOOLEAN
66  ACPI_OPERAND_OBJECT *ObjDesc,
67  UINT64 Value);
68 
69 static ACPI_STATUS
71  ACPI_OPERAND_OBJECT *ObjDesc,
72  UINT32 FieldDatumByteOffset);
73 
74 
75 /*******************************************************************************
76  *
77  * FUNCTION: AcpiExSetupRegion
78  *
79  * PARAMETERS: ObjDesc - Field to be read or written
80  * FieldDatumByteOffset - Byte offset of this datum within the
81  * parent field
82  *
83  * RETURN: Status
84  *
85  * DESCRIPTION: Common processing for AcpiExExtractFromField and
86  * AcpiExInsertIntoField. Initialize the Region if necessary and
87  * validate the request.
88  *
89  ******************************************************************************/
90 
91 static ACPI_STATUS
93  ACPI_OPERAND_OBJECT *ObjDesc,
94  UINT32 FieldDatumByteOffset)
95 {
97  ACPI_OPERAND_OBJECT *RgnDesc;
98  UINT8 SpaceId;
99 
100 
101  ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset);
102 
103 
104  RgnDesc = ObjDesc->CommonField.RegionObj;
105 
106  /* We must have a valid region */
107 
108  if (RgnDesc->Common.Type != ACPI_TYPE_REGION)
109  {
110  ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
111  RgnDesc->Common.Type,
112  AcpiUtGetObjectTypeName (RgnDesc)));
113 
115  }
116 
117  SpaceId = RgnDesc->Region.SpaceId;
118 
119  /* Validate the Space ID */
120 
122  {
124  "Invalid/unknown Address Space ID: 0x%2.2X", SpaceId));
126  }
127 
128  /*
129  * If the Region Address and Length have not been previously evaluated,
130  * evaluate them now and save the results.
131  */
132  if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
133  {
134  Status = AcpiDsGetRegionArguments (RgnDesc);
135  if (ACPI_FAILURE (Status))
136  {
138  }
139  }
140 
141  /*
142  * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear
143  * address space and the request cannot be directly validated
144  */
145  if (SpaceId == ACPI_ADR_SPACE_SMBUS ||
148  {
149  /* SMBus or IPMI has a non-linear address space */
150 
152  }
153 
154 #ifdef ACPI_UNDER_DEVELOPMENT
155  /*
156  * If the Field access is AnyAcc, we can now compute the optimal
157  * access (because we know know the length of the parent region)
158  */
159  if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
160  {
161  if (ACPI_FAILURE (Status))
162  {
164  }
165  }
166 #endif
167 
168  /*
169  * Validate the request. The entire request from the byte offset for a
170  * length of one field datum (access width) must fit within the region.
171  * (Region length is specified in bytes)
172  */
173  if (RgnDesc->Region.Length <
174  (ObjDesc->CommonField.BaseByteOffset + FieldDatumByteOffset +
175  ObjDesc->CommonField.AccessByteWidth))
176  {
177  if (AcpiGbl_EnableInterpreterSlack)
178  {
179  /*
180  * Slack mode only: We will go ahead and allow access to this
181  * field if it is within the region length rounded up to the next
182  * access width boundary. ACPI_SIZE cast for 64-bit compile.
183  */
184  if (ACPI_ROUND_UP (RgnDesc->Region.Length,
185  ObjDesc->CommonField.AccessByteWidth) >=
186  ((ACPI_SIZE) ObjDesc->CommonField.BaseByteOffset +
187  ObjDesc->CommonField.AccessByteWidth +
188  FieldDatumByteOffset))
189  {
191  }
192  }
193 
194  if (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth)
195  {
196  /*
197  * This is the case where the AccessType (AccWord, etc.) is wider
198  * than the region itself. For example, a region of length one
199  * byte, and a field with Dword access specified.
200  */
202  "Field [%4.4s] access width (%u bytes) "
203  "too large for region [%4.4s] (length %u)",
204  AcpiUtGetNodeName (ObjDesc->CommonField.Node),
205  ObjDesc->CommonField.AccessByteWidth,
206  AcpiUtGetNodeName (RgnDesc->Region.Node),
207  RgnDesc->Region.Length));
208  }
209 
210  /*
211  * Offset rounded up to next multiple of field width
212  * exceeds region length, indicate an error
213  */
215  "Field [%4.4s] Base+Offset+Width %u+%u+%u "
216  "is beyond end of region [%4.4s] (length %u)",
217  AcpiUtGetNodeName (ObjDesc->CommonField.Node),
218  ObjDesc->CommonField.BaseByteOffset,
219  FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
220  AcpiUtGetNodeName (RgnDesc->Region.Node),
221  RgnDesc->Region.Length));
222 
224  }
225 
227 }
228 
229 
230 /*******************************************************************************
231  *
232  * FUNCTION: AcpiExAccessRegion
233  *
234  * PARAMETERS: ObjDesc - Field to be read
235  * FieldDatumByteOffset - Byte offset of this datum within the
236  * parent field
237  * Value - Where to store value (must at least
238  * 64 bits)
239  * Function - Read or Write flag plus other region-
240  * dependent flags
241  *
242  * RETURN: Status
243  *
244  * DESCRIPTION: Read or Write a single field datum to an Operation Region.
245  *
246  ******************************************************************************/
247 
250  ACPI_OPERAND_OBJECT *ObjDesc,
251  UINT32 FieldDatumByteOffset,
252  UINT64 *Value,
254 {
256  ACPI_OPERAND_OBJECT *RgnDesc;
257  UINT32 RegionOffset;
258 
259 
260  ACPI_FUNCTION_TRACE (ExAccessRegion);
261 
262 
263  /*
264  * Ensure that the region operands are fully evaluated and verify
265  * the validity of the request
266  */
267  Status = AcpiExSetupRegion (ObjDesc, FieldDatumByteOffset);
268  if (ACPI_FAILURE (Status))
269  {
271  }
272 
273  /*
274  * The physical address of this field datum is:
275  *
276  * 1) The base of the region, plus
277  * 2) The base offset of the field, plus
278  * 3) The current offset into the field
279  */
280  RgnDesc = ObjDesc->CommonField.RegionObj;
281  RegionOffset =
282  ObjDesc->CommonField.BaseByteOffset +
283  FieldDatumByteOffset;
284 
285  if ((Function & ACPI_IO_MASK) == ACPI_READ)
286  {
287  ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
288  }
289  else
290  {
291  ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
292  }
293 
295  " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
297  RgnDesc->Region.SpaceId,
298  ObjDesc->CommonField.AccessByteWidth,
299  ObjDesc->CommonField.BaseByteOffset,
300  FieldDatumByteOffset,
301  ACPI_FORMAT_UINT64 (RgnDesc->Region.Address + RegionOffset)));
302 
303  /* Invoke the appropriate AddressSpace/OpRegion handler */
304 
305  Status = AcpiEvAddressSpaceDispatch (RgnDesc, ObjDesc,
306  Function, RegionOffset,
307  ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value);
308 
309  if (ACPI_FAILURE (Status))
310  {
311  if (Status == AE_NOT_IMPLEMENTED)
312  {
314  "Region %s (ID=%u) not implemented",
316  RgnDesc->Region.SpaceId));
317  }
318  else if (Status == AE_NOT_EXIST)
319  {
321  "Region %s (ID=%u) has no handler",
323  RgnDesc->Region.SpaceId));
324  }
325  }
326 
328 }
329 
330 
331 /*******************************************************************************
332  *
333  * FUNCTION: AcpiExRegisterOverflow
334  *
335  * PARAMETERS: ObjDesc - Register(Field) to be written
336  * Value - Value to be stored
337  *
338  * RETURN: TRUE if value overflows the field, FALSE otherwise
339  *
340  * DESCRIPTION: Check if a value is out of range of the field being written.
341  * Used to check if the values written to Index and Bank registers
342  * are out of range. Normally, the value is simply truncated
343  * to fit the field, but this case is most likely a serious
344  * coding error in the ASL.
345  *
346  ******************************************************************************/
347 
348 static BOOLEAN
350  ACPI_OPERAND_OBJECT *ObjDesc,
351  UINT64 Value)
352 {
353 
354  if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE)
355  {
356  /*
357  * The field is large enough to hold the maximum integer, so we can
358  * never overflow it.
359  */
360  return (FALSE);
361  }
362 
363  if (Value >= ((UINT64) 1 << ObjDesc->CommonField.BitLength))
364  {
365  /*
366  * The Value is larger than the maximum value that can fit into
367  * the register.
368  */
370  "Index value 0x%8.8X%8.8X overflows field width 0x%X",
372  ObjDesc->CommonField.BitLength));
373 
374  return (TRUE);
375  }
376 
377  /* The Value will fit into the field with no truncation */
378 
379  return (FALSE);
380 }
381 
382 
383 /*******************************************************************************
384  *
385  * FUNCTION: AcpiExFieldDatumIo
386  *
387  * PARAMETERS: ObjDesc - Field to be read
388  * FieldDatumByteOffset - Byte offset of this datum within the
389  * parent field
390  * Value - Where to store value (must be 64 bits)
391  * ReadWrite - Read or Write flag
392  *
393  * RETURN: Status
394  *
395  * DESCRIPTION: Read or Write a single datum of a field. The FieldType is
396  * demultiplexed here to handle the different types of fields
397  * (BufferField, RegionField, IndexField, BankField)
398  *
399  ******************************************************************************/
400 
401 static ACPI_STATUS
403  ACPI_OPERAND_OBJECT *ObjDesc,
404  UINT32 FieldDatumByteOffset,
405  UINT64 *Value,
407 {
409  UINT64 LocalValue;
410 
411 
412  ACPI_FUNCTION_TRACE_U32 (ExFieldDatumIo, FieldDatumByteOffset);
413 
414 
415  if (ReadWrite == ACPI_READ)
416  {
417  if (!Value)
418  {
419  LocalValue = 0;
420 
421  /* To support reads without saving return value */
422  Value = &LocalValue;
423  }
424 
425  /* Clear the entire return buffer first, [Very Important!] */
426 
427  *Value = 0;
428  }
429 
430  /*
431  * The four types of fields are:
432  *
433  * BufferField - Read/write from/to a Buffer
434  * RegionField - Read/write from/to a Operation Region.
435  * BankField - Write to a Bank Register, then read/write from/to an
436  * OperationRegion
437  * IndexField - Write to an Index Register, then read/write from/to a
438  * Data Register
439  */
440  switch (ObjDesc->Common.Type)
441  {
443  /*
444  * If the BufferField arguments have not been previously evaluated,
445  * evaluate them now and save the results.
446  */
447  if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
448  {
450  if (ACPI_FAILURE (Status))
451  {
453  }
454  }
455 
456  if (ReadWrite == ACPI_READ)
457  {
458  /*
459  * Copy the data from the source buffer.
460  * Length is the field width in bytes.
461  */
462  memcpy (Value,
463  (ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
464  ObjDesc->BufferField.BaseByteOffset +
465  FieldDatumByteOffset,
466  ObjDesc->CommonField.AccessByteWidth);
467  }
468  else
469  {
470  /*
471  * Copy the data to the target buffer.
472  * Length is the field width in bytes.
473  */
474  memcpy ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
475  ObjDesc->BufferField.BaseByteOffset +
476  FieldDatumByteOffset,
477  Value, ObjDesc->CommonField.AccessByteWidth);
478  }
479 
480  Status = AE_OK;
481  break;
482 
484  /*
485  * Ensure that the BankValue is not beyond the capacity of
486  * the register
487  */
489  (UINT64) ObjDesc->BankField.Value))
490  {
492  }
493 
494  /*
495  * For BankFields, we must write the BankValue to the BankRegister
496  * (itself a RegionField) before we can access the data.
497  */
499  &ObjDesc->BankField.Value,
500  sizeof (ObjDesc->BankField.Value));
501  if (ACPI_FAILURE (Status))
502  {
504  }
505 
506  /*
507  * Now that the Bank has been selected, fall through to the
508  * RegionField case and write the datum to the Operation Region
509  */
510 
511  /*lint -fallthrough */
512 
514  /*
515  * For simple RegionFields, we just directly access the owning
516  * Operation Region.
517  */
519  ObjDesc, FieldDatumByteOffset, Value, ReadWrite);
520  break;
521 
523  /*
524  * Ensure that the IndexValue is not beyond the capacity of
525  * the register
526  */
528  (UINT64) ObjDesc->IndexField.Value))
529  {
531  }
532 
533  /* Write the index value to the IndexRegister (itself a RegionField) */
534 
535  FieldDatumByteOffset += ObjDesc->IndexField.Value;
536 
538  "Write to Index Register: Value %8.8X\n",
539  FieldDatumByteOffset));
540 
542  &FieldDatumByteOffset, sizeof (FieldDatumByteOffset));
543  if (ACPI_FAILURE (Status))
544  {
546  }
547 
548  if (ReadWrite == ACPI_READ)
549  {
550  /* Read the datum from the DataRegister */
551 
553  "Read from Data Register\n"));
554 
556  ObjDesc->IndexField.DataObj, Value, sizeof (UINT64));
557  }
558  else
559  {
560  /* Write the datum to the DataRegister */
561 
563  "Write to Data Register: Value %8.8X%8.8X\n",
565 
567  ObjDesc->IndexField.DataObj, Value, sizeof (UINT64));
568  }
569  break;
570 
571  default:
572 
573  ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %u",
574  ObjDesc->Common.Type));
576  break;
577  }
578 
579  if (ACPI_SUCCESS (Status))
580  {
581  if (ReadWrite == ACPI_READ)
582  {
584  "Value Read %8.8X%8.8X, Width %u\n",
586  ObjDesc->CommonField.AccessByteWidth));
587  }
588  else
589  {
591  "Value Written %8.8X%8.8X, Width %u\n",
593  ObjDesc->CommonField.AccessByteWidth));
594  }
595  }
596 
598 }
599 
600 
601 /*******************************************************************************
602  *
603  * FUNCTION: AcpiExWriteWithUpdateRule
604  *
605  * PARAMETERS: ObjDesc - Field to be written
606  * Mask - bitmask within field datum
607  * FieldValue - Value to write
608  * FieldDatumByteOffset - Offset of datum within field
609  *
610  * RETURN: Status
611  *
612  * DESCRIPTION: Apply the field update rule to a field write
613  *
614  ******************************************************************************/
615 
618  ACPI_OPERAND_OBJECT *ObjDesc,
619  UINT64 Mask,
620  UINT64 FieldValue,
621  UINT32 FieldDatumByteOffset)
622 {
624  UINT64 MergedValue;
625  UINT64 CurrentValue;
626 
627 
628  ACPI_FUNCTION_TRACE_U32 (ExWriteWithUpdateRule, Mask);
629 
630 
631  /* Start with the new bits */
632 
633  MergedValue = FieldValue;
634 
635  /* If the mask is all ones, we don't need to worry about the update rule */
636 
637  if (Mask != ACPI_UINT64_MAX)
638  {
639  /* Decode the update rule */
640 
641  switch (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)
642  {
644  /*
645  * Check if update rule needs to be applied (not if mask is all
646  * ones) The left shift drops the bits we want to ignore.
647  */
648  if ((~Mask << (ACPI_MUL_8 (sizeof (Mask)) -
649  ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth))) != 0)
650  {
651  /*
652  * Read the current contents of the byte/word/dword containing
653  * the field, and merge with the new field value.
654  */
656  ObjDesc, FieldDatumByteOffset, &CurrentValue, ACPI_READ);
657  if (ACPI_FAILURE (Status))
658  {
660  }
661 
662  MergedValue |= (CurrentValue & ~Mask);
663  }
664  break;
665 
667 
668  /* Set positions outside the field to all ones */
669 
670  MergedValue |= ~Mask;
671  break;
672 
674 
675  /* Set positions outside the field to all zeros */
676 
677  MergedValue &= Mask;
678  break;
679 
680  default:
681 
683  "Unknown UpdateRule value: 0x%X",
684  (ObjDesc->CommonField.FieldFlags &
687  }
688  }
689 
691  "Mask %8.8X%8.8X, DatumOffset %X, Width %X, "
692  "Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
693  ACPI_FORMAT_UINT64 (Mask),
694  FieldDatumByteOffset,
695  ObjDesc->CommonField.AccessByteWidth,
696  ACPI_FORMAT_UINT64 (FieldValue),
697  ACPI_FORMAT_UINT64 (MergedValue)));
698 
699  /* Write the merged value */
700 
702  ObjDesc, FieldDatumByteOffset, &MergedValue, ACPI_WRITE);
703 
705 }
706 
707 
708 /*******************************************************************************
709  *
710  * FUNCTION: AcpiExExtractFromField
711  *
712  * PARAMETERS: ObjDesc - Field to be read
713  * Buffer - Where to store the field data
714  * BufferLength - Length of Buffer
715  *
716  * RETURN: Status
717  *
718  * DESCRIPTION: Retrieve the current value of the given field
719  *
720  ******************************************************************************/
721 
724  ACPI_OPERAND_OBJECT *ObjDesc,
725  void *Buffer,
727 {
729  UINT64 RawDatum;
730  UINT64 MergedDatum;
731  UINT32 FieldOffset = 0;
732  UINT32 BufferOffset = 0;
733  UINT32 BufferTailBits;
734  UINT32 DatumCount;
735  UINT32 FieldDatumCount;
736  UINT32 AccessBitWidth;
737  UINT32 i;
738 
739 
740  ACPI_FUNCTION_TRACE (ExExtractFromField);
741 
742 
743  /* Validate target buffer and clear it */
744 
745  if (BufferLength <
746  ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
747  {
749  "Field size %u (bits) is too large for buffer (%u)",
750  ObjDesc->CommonField.BitLength, BufferLength));
751 
753  }
754 
755  memset (Buffer, 0, BufferLength);
756  AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
757 
758  /* Handle the simple case here */
759 
760  if ((ObjDesc->CommonField.StartFieldBitOffset == 0) &&
761  (ObjDesc->CommonField.BitLength == AccessBitWidth))
762  {
763  if (BufferLength >= sizeof (UINT64))
764  {
765  Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ);
766  }
767  else
768  {
769  /* Use RawDatum (UINT64) to handle buffers < 64 bits */
770 
771  Status = AcpiExFieldDatumIo (ObjDesc, 0, &RawDatum, ACPI_READ);
772  memcpy (Buffer, &RawDatum, BufferLength);
773  }
774 
776  }
777 
778 /* TBD: Move to common setup code */
779 
780  /* Field algorithm is limited to sizeof(UINT64), truncate if needed */
781 
782  if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
783  {
784  ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
785  AccessBitWidth = sizeof (UINT64) * 8;
786  }
787 
788  /* Compute the number of datums (access width data items) */
789 
790  DatumCount = ACPI_ROUND_UP_TO (
791  ObjDesc->CommonField.BitLength, AccessBitWidth);
792 
793  FieldDatumCount = ACPI_ROUND_UP_TO (
794  ObjDesc->CommonField.BitLength +
795  ObjDesc->CommonField.StartFieldBitOffset, AccessBitWidth);
796 
797  /* Priming read from the field */
798 
799  Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
800  if (ACPI_FAILURE (Status))
801  {
803  }
804  MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
805 
806  /* Read the rest of the field */
807 
808  for (i = 1; i < FieldDatumCount; i++)
809  {
810  /* Get next input datum from the field */
811 
812  FieldOffset += ObjDesc->CommonField.AccessByteWidth;
814  ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
815  if (ACPI_FAILURE (Status))
816  {
818  }
819 
820  /*
821  * Merge with previous datum if necessary.
822  *
823  * Note: Before the shift, check if the shift value will be larger than
824  * the integer size. If so, there is no need to perform the operation.
825  * This avoids the differences in behavior between different compilers
826  * concerning shift values larger than the target data width.
827  */
828  if (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset <
830  {
831  MergedDatum |= RawDatum <<
832  (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
833  }
834 
835  if (i == DatumCount)
836  {
837  break;
838  }
839 
840  /* Write merged datum to target buffer */
841 
842  memcpy (((char *) Buffer) + BufferOffset, &MergedDatum,
843  ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
844  BufferLength - BufferOffset));
845 
846  BufferOffset += ObjDesc->CommonField.AccessByteWidth;
847  MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
848  }
849 
850  /* Mask off any extra bits in the last datum */
851 
852  BufferTailBits = ObjDesc->CommonField.BitLength % AccessBitWidth;
853  if (BufferTailBits)
854  {
855  MergedDatum &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
856  }
857 
858  /* Write the last datum to the buffer */
859 
860  memcpy (((char *) Buffer) + BufferOffset, &MergedDatum,
861  ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
862  BufferLength - BufferOffset));
863 
865 }
866 
867 
868 /*******************************************************************************
869  *
870  * FUNCTION: AcpiExInsertIntoField
871  *
872  * PARAMETERS: ObjDesc - Field to be written
873  * Buffer - Data to be written
874  * BufferLength - Length of Buffer
875  *
876  * RETURN: Status
877  *
878  * DESCRIPTION: Store the Buffer contents into the given field
879  *
880  ******************************************************************************/
881 
884  ACPI_OPERAND_OBJECT *ObjDesc,
885  void *Buffer,
887 {
888  void *NewBuffer;
890  UINT64 Mask;
891  UINT64 WidthMask;
892  UINT64 MergedDatum;
893  UINT64 RawDatum = 0;
894  UINT32 FieldOffset = 0;
895  UINT32 BufferOffset = 0;
896  UINT32 BufferTailBits;
897  UINT32 DatumCount;
898  UINT32 FieldDatumCount;
899  UINT32 AccessBitWidth;
901  UINT32 i;
902 
903 
904  ACPI_FUNCTION_TRACE (ExInsertIntoField);
905 
906 
907  /* Validate input buffer */
908 
909  NewBuffer = NULL;
911  ObjDesc->CommonField.BitLength);
912 
913  /*
914  * We must have a buffer that is at least as long as the field
915  * we are writing to. This is because individual fields are
916  * indivisible and partial writes are not supported -- as per
917  * the ACPI specification.
918  */
920  {
921  /* We need to create a new buffer */
922 
923  NewBuffer = ACPI_ALLOCATE_ZEROED (RequiredLength);
924  if (!NewBuffer)
925  {
927  }
928 
929  /*
930  * Copy the original data to the new buffer, starting
931  * at Byte zero. All unused (upper) bytes of the
932  * buffer will be 0.
933  */
934  memcpy ((char *) NewBuffer, (char *) Buffer, BufferLength);
935  Buffer = NewBuffer;
937  }
938 
939 /* TBD: Move to common setup code */
940 
941  /* Algo is limited to sizeof(UINT64), so cut the AccessByteWidth */
942  if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
943  {
944  ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
945  }
946 
947  AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
948 
949  /* Create the bitmasks used for bit insertion */
950 
951  WidthMask = ACPI_MASK_BITS_ABOVE_64 (AccessBitWidth);
952  Mask = WidthMask &
953  ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset);
954 
955  /* Compute the number of datums (access width data items) */
956 
957  DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength,
958  AccessBitWidth);
959 
960  FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength +
961  ObjDesc->CommonField.StartFieldBitOffset,
962  AccessBitWidth);
963 
964  /* Get initial Datum from the input buffer */
965 
966  memcpy (&RawDatum, Buffer,
967  ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
968  BufferLength - BufferOffset));
969 
970  MergedDatum = RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
971 
972  /* Write the entire field */
973 
974  for (i = 1; i < FieldDatumCount; i++)
975  {
976  /* Write merged datum to the target field */
977 
978  MergedDatum &= Mask;
980  ObjDesc, Mask, MergedDatum, FieldOffset);
981  if (ACPI_FAILURE (Status))
982  {
983  goto Exit;
984  }
985 
986  FieldOffset += ObjDesc->CommonField.AccessByteWidth;
987 
988  /*
989  * Start new output datum by merging with previous input datum
990  * if necessary.
991  *
992  * Note: Before the shift, check if the shift value will be larger than
993  * the integer size. If so, there is no need to perform the operation.
994  * This avoids the differences in behavior between different compilers
995  * concerning shift values larger than the target data width.
996  */
997  if ((AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset) <
999  {
1000  MergedDatum = RawDatum >>
1001  (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
1002  }
1003  else
1004  {
1005  MergedDatum = 0;
1006  }
1007 
1008  Mask = WidthMask;
1009 
1010  if (i == DatumCount)
1011  {
1012  break;
1013  }
1014 
1015  /* Get the next input datum from the buffer */
1016 
1017  BufferOffset += ObjDesc->CommonField.AccessByteWidth;
1018  memcpy (&RawDatum, ((char *) Buffer) + BufferOffset,
1019  ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
1020  BufferLength - BufferOffset));
1021 
1022  MergedDatum |= RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
1023  }
1024 
1025  /* Mask off any extra bits in the last datum */
1026 
1027  BufferTailBits = (ObjDesc->CommonField.BitLength +
1028  ObjDesc->CommonField.StartFieldBitOffset) % AccessBitWidth;
1029  if (BufferTailBits)
1030  {
1031  Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
1032  }
1033 
1034  /* Write the last datum to the field */
1035 
1036  MergedDatum &= Mask;
1038  ObjDesc, Mask, MergedDatum, FieldOffset);
1039 
1040 Exit:
1041  /* Free temporary buffer if we used one */
1042 
1043  if (NewBuffer)
1044  {
1045  ACPI_FREE (NewBuffer);
1046  }
1048 }
#define ACPI_DEBUG_PRINT_RAW(pl)
Definition: acoutput.h:476
#define AE_AML_REGION_LIMIT
Definition: acexcep.h:188
#define ACPI_FREE(a)
Definition: actypes.h:386
#define ACPI_DB_BFIELD
Definition: acoutput.h:168
ACPI_STATUS AcpiDsGetBufferFieldArguments(ACPI_OPERAND_OBJECT *ObjDesc)
Definition: dsargs.c:196
#define ACPI_ALLOCATE_ZEROED(a)
Definition: actypes.h:385
static ACPI_STATUS AcpiExSetupRegion(ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset)
Definition: exfldio.c:92
#define ACPI_SUCCESS(a)
Definition: acexcep.h:94
#define ACPI_READ
Definition: actypes.h:743
#define AE_NO_MEMORY
Definition: acexcep.h:112
ACPI_NAMESPACE_NODE * Node
Definition: acobject.h:203
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
#define TRUE
Definition: types.h:120
#define AE_AML_OPERAND_VALUE
Definition: acexcep.h:183
BOOLEAN AcpiIsValidSpaceId(UINT8 SpaceId)
Definition: exutils.c:494
ACPI_OBJECT_FIELD_COMMON CommonField
Definition: acobject.h:531
#define AE_AML_INTERNAL
Definition: acexcep.h:194
#define ACPI_MUL_8(a)
Definition: acmacros.h:215
UINT32 ACPI_STATUS
Definition: actypes.h:460
#define ACPI_MASK_BITS_ABOVE_64(width)
Definition: acmacros.h:348
union acpi_operand_object * BankObj
Definition: acobject.h:358
#define ACPI_FUNCTION_TRACE_U32(a, b)
Definition: acoutput.h:482
static ACPI_STATUS AcpiExFieldDatumIo(ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset, UINT64 *Value, UINT32 ReadWrite)
Definition: exfldio.c:402
ACPI_OBJECT_COMMON_HEADER UINT8 SpaceId
Definition: acobject.h:202
#define AE_AML_OPERAND_TYPE
Definition: acexcep.h:182
#define ACPI_TYPE_LOCAL_INDEX_FIELD
Definition: actypes.h:710
IN UCHAR Value
Definition: halp.h:394
#define AE_NOT_IMPLEMENTED
Definition: acexcep.h:122
#define AE_AML_REGISTER_LIMIT
Definition: acexcep.h:204
#define ACPI_MIN(a, b)
Definition: actypes.h:535
#define ACPI_INTEGER_BIT_SIZE
Definition: actypes.h:490
#define AML_FIELD_UPDATE_RULE_MASK
Definition: amlcode.h:444
#define ACPI_FAILURE(a)
Definition: acexcep.h:95
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ACPI_STATUS AcpiEvAddressSpaceDispatch(ACPI_OPERAND_OBJECT *RegionObj, ACPI_OPERAND_OBJECT *FieldObj, UINT32 Function, UINT32 RegionOffset, UINT32 BitWidth, UINT64 *Value)
Definition: evregion.c:148
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn BOOLEAN Physical UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE ACPI_HANDLE ACPI_HANDLE *OutHandle ACPI_HANDLE *OutHandle void *Context void *Context ACPI_EVENT_HANDLER Handler UINT32 UINT32 ACPI_GPE_HANDLER void *Context UINT32 ACPI_NOTIFY_HANDLER void *Context ACPI_ADR_SPACE_TYPE SpaceId
Definition: acpixf.h:828
ACPI_OBJECT_BANK_FIELD BankField
Definition: acobject.h:534
#define AE_BUFFER_OVERFLOW
Definition: acexcep.h:119
const char * AcpiUtGetRegionName(UINT8 SpaceId)
Definition: utdecode.c:125
#define FALSE
Definition: types.h:117
static LPOVERLAPPED_COMPLETION_ROUTINE Function
Definition: sync.c:681
unsigned int UINT32
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object * RegionObj
Definition: acobject.h:335
#define AE_AML_INVALID_SPACE_ID
Definition: acexcep.h:195
#define ACPI_MODULE_NAME(Name)
Definition: acoutput.h:216
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define AE_INFO
Definition: acoutput.h:230
#define ACPI_MASK_BITS_ABOVE(position)
Definition: acmacros.h:344
Definition: bufpool.h:45
ACPI_OBJECT_REGION Region
Definition: acobject.h:525
ACPI_STATUS AcpiExExtractFromField(ACPI_OPERAND_OBJECT *ObjDesc, void *Buffer, UINT32 BufferLength)
Definition: exfldio.c:723
union acpi_operand_object * DataObj
Definition: acobject.h:373
_In_ UCHAR BufferLength
Definition: scsi.h:4067
#define ACPI_MASK_BITS_BELOW(position)
Definition: acmacros.h:345
static void Exit(void)
Definition: sock.c:1331
#define ACPI_ROUND_UP(value, boundary)
Definition: acmacros.h:242
#define ACPI_DEBUG_PRINT(pl)
Definition: acoutput.h:475
#define ACPI_ADR_SPACE_IPMI
Definition: actypes.h:859
ACPI_OBJECT_INDEX_FIELD IndexField
Definition: acobject.h:535
#define ACPI_TYPE_LOCAL_REGION_FIELD
Definition: actypes.h:708
#define ACPI_ADR_SPACE_GSBUS
Definition: actypes.h:861
Status
Definition: gdiplustypes.h:24
#define AE_NOT_EXIST
Definition: acexcep.h:114
ACPI_STATUS AcpiExWriteWithUpdateRule(ACPI_OPERAND_OBJECT *ObjDesc, UINT64 Mask, UINT64 FieldValue, UINT32 FieldDatumByteOffset)
Definition: exfldio.c:617
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
union acpi_operand_object * BufferObj
Definition: acobject.h:385
#define ACPI_IO_MASK
Definition: actypes.h:745
#define return_ACPI_STATUS(s)
Definition: acoutput.h:496
ACPI_STATUS AcpiDsGetRegionArguments(ACPI_OPERAND_OBJECT *ObjDesc)
Definition: dsargs.c:395
#define ACPI_FUNCTION_TRACE(a)
Definition: acoutput.h:480
#define ACPI_FORMAT_UINT64(i)
Definition: acmacros.h:71
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:29
#define ACPI_TYPE_BUFFER_FIELD
Definition: actypes.h:693
ACPI_OBJECT_COMMON Common
Definition: acobject.h:517
#define ACPI_ROUND_UP_TO(value, boundary)
Definition: acmacros.h:263
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object * IndexObj
Definition: acobject.h:372
#define ACPI_ERROR(plist)
Definition: acoutput.h:240
const char * AcpiUtGetNodeName(void *Object)
Definition: utdecode.c:306
#define AOPOBJ_DATA_VALID
Definition: acobject.h:96
ACPI_PHYSICAL_ADDRESS Address
Definition: acobject.h:206
#define ACPI_TYPE_REGION
Definition: actypes.h:689
#define ACPI_TYPE_LOCAL_BANK_FIELD
Definition: actypes.h:709
#define ACPI_ADR_SPACE_SMBUS
Definition: actypes.h:856
#define ACPI_UINT64_MAX
Definition: actypes.h:67
DRIVER_DISPATCH ReadWrite
Definition: readwrite.h:29
#define ACPI_ROUND_BITS_UP_TO_BYTES(a)
Definition: acmacros.h:256
ACPI_STATUS AcpiExInsertIntoField(ACPI_OPERAND_OBJECT *ObjDesc, void *Buffer, UINT32 BufferLength)
Definition: exfldio.c:883
ACPI_OBJECT_BUFFER_FIELD BufferField
Definition: acobject.h:533
unsigned long long UINT64
ACPI_STATUS AcpiExAccessRegion(ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset, UINT64 *Value, UINT32 Function)
Definition: exfldio.c:249
unsigned char UINT8
#define memset(x, y, z)
Definition: compat.h:39
const char * AcpiUtGetObjectTypeName(ACPI_OPERAND_OBJECT *ObjDesc)
Definition: utdecode.c:264
#define AE_OK
Definition: acexcep.h:97
#define ACPI_WRITE
Definition: actypes.h:744
static BOOLEAN AcpiExRegisterOverflow(ACPI_OPERAND_OBJECT *ObjDesc, UINT64 Value)
Definition: exfldio.c:349