File indexing completed on 2025-05-11 08:24:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152 #include "acpi.h"
0153 #include "accommon.h"
0154 #include "acinterp.h"
0155 #include "amlcode.h"
0156 #include "acevents.h"
0157 #include "acdispat.h"
0158
0159
0160 #define _COMPONENT ACPI_EXECUTER
0161 ACPI_MODULE_NAME ("exfldio")
0162
0163
0164
0165 static ACPI_STATUS
0166 AcpiExFieldDatumIo (
0167 ACPI_OPERAND_OBJECT *ObjDesc,
0168 UINT32 FieldDatumByteOffset,
0169 UINT64 *Value,
0170 UINT32 ReadWrite);
0171
0172 static BOOLEAN
0173 AcpiExRegisterOverflow (
0174 ACPI_OPERAND_OBJECT *ObjDesc,
0175 UINT64 Value);
0176
0177 static ACPI_STATUS
0178 AcpiExSetupRegion (
0179 ACPI_OPERAND_OBJECT *ObjDesc,
0180 UINT32 FieldDatumByteOffset);
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199 static ACPI_STATUS
0200 AcpiExSetupRegion (
0201 ACPI_OPERAND_OBJECT *ObjDesc,
0202 UINT32 FieldDatumByteOffset)
0203 {
0204 ACPI_STATUS Status = AE_OK;
0205 ACPI_OPERAND_OBJECT *RgnDesc;
0206 UINT8 SpaceId;
0207
0208
0209 ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset);
0210
0211
0212 RgnDesc = ObjDesc->CommonField.RegionObj;
0213
0214
0215
0216 if (RgnDesc->Common.Type != ACPI_TYPE_REGION)
0217 {
0218 ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
0219 RgnDesc->Common.Type,
0220 AcpiUtGetObjectTypeName (RgnDesc)));
0221
0222 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
0223 }
0224
0225 SpaceId = RgnDesc->Region.SpaceId;
0226
0227
0228
0229 if (!AcpiIsValidSpaceId (SpaceId))
0230 {
0231 ACPI_ERROR ((AE_INFO,
0232 "Invalid/unknown Address Space ID: 0x%2.2X", SpaceId));
0233 return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID);
0234 }
0235
0236
0237
0238
0239
0240 if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
0241 {
0242 Status = AcpiDsGetRegionArguments (RgnDesc);
0243 if (ACPI_FAILURE (Status))
0244 {
0245 return_ACPI_STATUS (Status);
0246 }
0247 }
0248
0249
0250
0251
0252
0253 if (SpaceId == ACPI_ADR_SPACE_SMBUS ||
0254 SpaceId == ACPI_ADR_SPACE_GSBUS ||
0255 SpaceId == ACPI_ADR_SPACE_IPMI)
0256 {
0257
0258
0259 return_ACPI_STATUS (AE_OK);
0260 }
0261
0262 #ifdef ACPI_UNDER_DEVELOPMENT
0263
0264
0265
0266
0267 if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
0268 {
0269 if (ACPI_FAILURE (Status))
0270 {
0271 return_ACPI_STATUS (Status);
0272 }
0273 }
0274 #endif
0275
0276
0277
0278
0279
0280
0281 if (RgnDesc->Region.Length <
0282 (ObjDesc->CommonField.BaseByteOffset + FieldDatumByteOffset +
0283 ObjDesc->CommonField.AccessByteWidth))
0284 {
0285 if (AcpiGbl_EnableInterpreterSlack)
0286 {
0287
0288
0289
0290
0291
0292 if (ACPI_ROUND_UP (RgnDesc->Region.Length,
0293 ObjDesc->CommonField.AccessByteWidth) >=
0294 ((ACPI_SIZE) ObjDesc->CommonField.BaseByteOffset +
0295 ObjDesc->CommonField.AccessByteWidth +
0296 FieldDatumByteOffset))
0297 {
0298 return_ACPI_STATUS (AE_OK);
0299 }
0300 }
0301
0302 if (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth)
0303 {
0304
0305
0306
0307
0308
0309 ACPI_ERROR ((AE_INFO,
0310 "Field [%4.4s] access width (%u bytes) "
0311 "too large for region [%4.4s] (length %u)",
0312 AcpiUtGetNodeName (ObjDesc->CommonField.Node),
0313 ObjDesc->CommonField.AccessByteWidth,
0314 AcpiUtGetNodeName (RgnDesc->Region.Node),
0315 RgnDesc->Region.Length));
0316 }
0317
0318
0319
0320
0321
0322 ACPI_ERROR ((AE_INFO,
0323 "Field [%4.4s] Base+Offset+Width %u+%u+%u "
0324 "is beyond end of region [%4.4s] (length %u)",
0325 AcpiUtGetNodeName (ObjDesc->CommonField.Node),
0326 ObjDesc->CommonField.BaseByteOffset,
0327 FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
0328 AcpiUtGetNodeName (RgnDesc->Region.Node),
0329 RgnDesc->Region.Length));
0330
0331 return_ACPI_STATUS (AE_AML_REGION_LIMIT);
0332 }
0333
0334 return_ACPI_STATUS (AE_OK);
0335 }
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356 ACPI_STATUS
0357 AcpiExAccessRegion (
0358 ACPI_OPERAND_OBJECT *ObjDesc,
0359 UINT32 FieldDatumByteOffset,
0360 UINT64 *Value,
0361 UINT32 Function)
0362 {
0363 ACPI_STATUS Status;
0364 ACPI_OPERAND_OBJECT *RgnDesc;
0365 UINT32 RegionOffset;
0366
0367
0368 ACPI_FUNCTION_TRACE (ExAccessRegion);
0369
0370
0371
0372
0373
0374
0375 Status = AcpiExSetupRegion (ObjDesc, FieldDatumByteOffset);
0376 if (ACPI_FAILURE (Status))
0377 {
0378 return_ACPI_STATUS (Status);
0379 }
0380
0381
0382
0383
0384
0385
0386
0387
0388 RgnDesc = ObjDesc->CommonField.RegionObj;
0389 RegionOffset =
0390 ObjDesc->CommonField.BaseByteOffset +
0391 FieldDatumByteOffset;
0392
0393 if ((Function & ACPI_IO_MASK) == ACPI_READ)
0394 {
0395 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
0396 }
0397 else
0398 {
0399 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
0400 }
0401
0402 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
0403 " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
0404 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
0405 RgnDesc->Region.SpaceId,
0406 ObjDesc->CommonField.AccessByteWidth,
0407 ObjDesc->CommonField.BaseByteOffset,
0408 FieldDatumByteOffset,
0409 ACPI_FORMAT_UINT64 (RgnDesc->Region.Address + RegionOffset)));
0410
0411
0412
0413 Status = AcpiEvAddressSpaceDispatch (RgnDesc, ObjDesc,
0414 Function, RegionOffset,
0415 ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value);
0416
0417 if (ACPI_FAILURE (Status))
0418 {
0419 if (Status == AE_NOT_IMPLEMENTED)
0420 {
0421 ACPI_ERROR ((AE_INFO,
0422 "Region %s (ID=%u) not implemented",
0423 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
0424 RgnDesc->Region.SpaceId));
0425 }
0426 else if (Status == AE_NOT_EXIST)
0427 {
0428 ACPI_ERROR ((AE_INFO,
0429 "Region %s (ID=%u) has no handler",
0430 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
0431 RgnDesc->Region.SpaceId));
0432 }
0433 }
0434
0435 return_ACPI_STATUS (Status);
0436 }
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456 static BOOLEAN
0457 AcpiExRegisterOverflow (
0458 ACPI_OPERAND_OBJECT *ObjDesc,
0459 UINT64 Value)
0460 {
0461
0462 if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE)
0463 {
0464
0465
0466
0467
0468 return (FALSE);
0469 }
0470
0471 if (Value >= ((UINT64) 1 << ObjDesc->CommonField.BitLength))
0472 {
0473
0474
0475
0476
0477 ACPI_ERROR ((AE_INFO,
0478 "Index value 0x%8.8X%8.8X overflows field width 0x%X",
0479 ACPI_FORMAT_UINT64 (Value),
0480 ObjDesc->CommonField.BitLength));
0481
0482 return (TRUE);
0483 }
0484
0485
0486
0487 return (FALSE);
0488 }
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509 static ACPI_STATUS
0510 AcpiExFieldDatumIo (
0511 ACPI_OPERAND_OBJECT *ObjDesc,
0512 UINT32 FieldDatumByteOffset,
0513 UINT64 *Value,
0514 UINT32 ReadWrite)
0515 {
0516 ACPI_STATUS Status;
0517 UINT64 LocalValue;
0518
0519
0520 ACPI_FUNCTION_TRACE_U32 (ExFieldDatumIo, FieldDatumByteOffset);
0521
0522
0523 if (ReadWrite == ACPI_READ)
0524 {
0525 if (!Value)
0526 {
0527 LocalValue = 0;
0528
0529
0530 Value = &LocalValue;
0531 }
0532
0533
0534
0535 *Value = 0;
0536 }
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548 switch (ObjDesc->Common.Type)
0549 {
0550 case ACPI_TYPE_BUFFER_FIELD:
0551
0552
0553
0554
0555 if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
0556 {
0557 Status = AcpiDsGetBufferFieldArguments (ObjDesc);
0558 if (ACPI_FAILURE (Status))
0559 {
0560 return_ACPI_STATUS (Status);
0561 }
0562 }
0563
0564 if (ReadWrite == ACPI_READ)
0565 {
0566
0567
0568
0569
0570 memcpy (Value,
0571 (ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
0572 ObjDesc->BufferField.BaseByteOffset +
0573 FieldDatumByteOffset,
0574 ObjDesc->CommonField.AccessByteWidth);
0575 }
0576 else
0577 {
0578
0579
0580
0581
0582 memcpy ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
0583 ObjDesc->BufferField.BaseByteOffset +
0584 FieldDatumByteOffset,
0585 Value, ObjDesc->CommonField.AccessByteWidth);
0586 }
0587
0588 Status = AE_OK;
0589 break;
0590
0591 case ACPI_TYPE_LOCAL_BANK_FIELD:
0592
0593
0594
0595
0596 if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj,
0597 (UINT64) ObjDesc->BankField.Value))
0598 {
0599 return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
0600 }
0601
0602
0603
0604
0605
0606 Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj,
0607 &ObjDesc->BankField.Value,
0608 sizeof (ObjDesc->BankField.Value));
0609 if (ACPI_FAILURE (Status))
0610 {
0611 return_ACPI_STATUS (Status);
0612 }
0613
0614
0615
0616
0617
0618
0619 ACPI_FALLTHROUGH;
0620
0621 case ACPI_TYPE_LOCAL_REGION_FIELD:
0622
0623
0624
0625
0626 Status = AcpiExAccessRegion (
0627 ObjDesc, FieldDatumByteOffset, Value, ReadWrite);
0628 break;
0629
0630 case ACPI_TYPE_LOCAL_INDEX_FIELD:
0631
0632
0633
0634
0635 if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj,
0636 (UINT64) ObjDesc->IndexField.Value))
0637 {
0638 return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
0639 }
0640
0641
0642
0643 FieldDatumByteOffset += ObjDesc->IndexField.Value;
0644
0645 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
0646 "Write to Index Register: Value %8.8X\n",
0647 FieldDatumByteOffset));
0648
0649 Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj,
0650 &FieldDatumByteOffset, sizeof (FieldDatumByteOffset));
0651 if (ACPI_FAILURE (Status))
0652 {
0653 return_ACPI_STATUS (Status);
0654 }
0655
0656 if (ReadWrite == ACPI_READ)
0657 {
0658
0659
0660 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
0661 "Read from Data Register\n"));
0662
0663 Status = AcpiExExtractFromField (
0664 ObjDesc->IndexField.DataObj, Value, sizeof (UINT64));
0665 }
0666 else
0667 {
0668
0669
0670 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
0671 "Write to Data Register: Value %8.8X%8.8X\n",
0672 ACPI_FORMAT_UINT64 (*Value)));
0673
0674 Status = AcpiExInsertIntoField (
0675 ObjDesc->IndexField.DataObj, Value, sizeof (UINT64));
0676 }
0677 break;
0678
0679 default:
0680
0681 ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %u",
0682 ObjDesc->Common.Type));
0683 Status = AE_AML_INTERNAL;
0684 break;
0685 }
0686
0687 if (ACPI_SUCCESS (Status))
0688 {
0689 if (ReadWrite == ACPI_READ)
0690 {
0691 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
0692 "Value Read %8.8X%8.8X, Width %u\n",
0693 ACPI_FORMAT_UINT64 (*Value),
0694 ObjDesc->CommonField.AccessByteWidth));
0695 }
0696 else
0697 {
0698 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
0699 "Value Written %8.8X%8.8X, Width %u\n",
0700 ACPI_FORMAT_UINT64 (*Value),
0701 ObjDesc->CommonField.AccessByteWidth));
0702 }
0703 }
0704
0705 return_ACPI_STATUS (Status);
0706 }
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724 ACPI_STATUS
0725 AcpiExWriteWithUpdateRule (
0726 ACPI_OPERAND_OBJECT *ObjDesc,
0727 UINT64 Mask,
0728 UINT64 FieldValue,
0729 UINT32 FieldDatumByteOffset)
0730 {
0731 ACPI_STATUS Status = AE_OK;
0732 UINT64 MergedValue;
0733 UINT64 CurrentValue;
0734
0735
0736 ACPI_FUNCTION_TRACE_U32 (ExWriteWithUpdateRule, Mask);
0737
0738
0739
0740
0741 MergedValue = FieldValue;
0742
0743
0744
0745 if (Mask != ACPI_UINT64_MAX)
0746 {
0747
0748
0749 switch (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)
0750 {
0751 case AML_FIELD_UPDATE_PRESERVE:
0752
0753
0754
0755
0756 if ((~Mask << (ACPI_MUL_8 (sizeof (Mask)) -
0757 ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth))) != 0)
0758 {
0759
0760
0761
0762
0763 Status = AcpiExFieldDatumIo (
0764 ObjDesc, FieldDatumByteOffset, &CurrentValue, ACPI_READ);
0765 if (ACPI_FAILURE (Status))
0766 {
0767 return_ACPI_STATUS (Status);
0768 }
0769
0770 MergedValue |= (CurrentValue & ~Mask);
0771 }
0772 break;
0773
0774 case AML_FIELD_UPDATE_WRITE_AS_ONES:
0775
0776
0777
0778 MergedValue |= ~Mask;
0779 break;
0780
0781 case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
0782
0783
0784
0785 MergedValue &= Mask;
0786 break;
0787
0788 default:
0789
0790 ACPI_ERROR ((AE_INFO,
0791 "Unknown UpdateRule value: 0x%X",
0792 (ObjDesc->CommonField.FieldFlags &
0793 AML_FIELD_UPDATE_RULE_MASK)));
0794 return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
0795 }
0796 }
0797
0798 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
0799 "Mask %8.8X%8.8X, DatumOffset %X, Width %X, "
0800 "Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
0801 ACPI_FORMAT_UINT64 (Mask),
0802 FieldDatumByteOffset,
0803 ObjDesc->CommonField.AccessByteWidth,
0804 ACPI_FORMAT_UINT64 (FieldValue),
0805 ACPI_FORMAT_UINT64 (MergedValue)));
0806
0807
0808
0809 Status = AcpiExFieldDatumIo (
0810 ObjDesc, FieldDatumByteOffset, &MergedValue, ACPI_WRITE);
0811
0812 return_ACPI_STATUS (Status);
0813 }
0814
0815
0816
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830 ACPI_STATUS
0831 AcpiExExtractFromField (
0832 ACPI_OPERAND_OBJECT *ObjDesc,
0833 void *Buffer,
0834 UINT32 BufferLength)
0835 {
0836 ACPI_STATUS Status;
0837 UINT64 RawDatum;
0838 UINT64 MergedDatum;
0839 UINT32 FieldOffset = 0;
0840 UINT32 BufferOffset = 0;
0841 UINT32 BufferTailBits;
0842 UINT32 DatumCount;
0843 UINT32 FieldDatumCount;
0844 UINT32 AccessBitWidth;
0845 UINT32 i;
0846
0847
0848 ACPI_FUNCTION_TRACE (ExExtractFromField);
0849
0850
0851
0852
0853 if (BufferLength <
0854 ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
0855 {
0856 ACPI_ERROR ((AE_INFO,
0857 "Field size %u (bits) is too large for buffer (%u)",
0858 ObjDesc->CommonField.BitLength, BufferLength));
0859
0860 return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
0861 }
0862
0863 memset (Buffer, 0, BufferLength);
0864 AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
0865
0866
0867
0868 if ((ObjDesc->CommonField.StartFieldBitOffset == 0) &&
0869 (ObjDesc->CommonField.BitLength == AccessBitWidth))
0870 {
0871 if (BufferLength >= sizeof (UINT64))
0872 {
0873 Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ);
0874 }
0875 else
0876 {
0877
0878
0879 Status = AcpiExFieldDatumIo (ObjDesc, 0, &RawDatum, ACPI_READ);
0880 memcpy (Buffer, &RawDatum, BufferLength);
0881 }
0882
0883 return_ACPI_STATUS (Status);
0884 }
0885
0886
0887
0888
0889
0890 if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
0891 {
0892 ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
0893 AccessBitWidth = sizeof (UINT64) * 8;
0894 }
0895
0896
0897
0898 DatumCount = ACPI_ROUND_UP_TO (
0899 ObjDesc->CommonField.BitLength, AccessBitWidth);
0900
0901 FieldDatumCount = ACPI_ROUND_UP_TO (
0902 ObjDesc->CommonField.BitLength +
0903 ObjDesc->CommonField.StartFieldBitOffset, AccessBitWidth);
0904
0905
0906
0907 Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
0908 if (ACPI_FAILURE (Status))
0909 {
0910 return_ACPI_STATUS (Status);
0911 }
0912 MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
0913
0914
0915
0916 for (i = 1; i < FieldDatumCount; i++)
0917 {
0918
0919
0920 FieldOffset += ObjDesc->CommonField.AccessByteWidth;
0921 Status = AcpiExFieldDatumIo (
0922 ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
0923 if (ACPI_FAILURE (Status))
0924 {
0925 return_ACPI_STATUS (Status);
0926 }
0927
0928
0929
0930
0931
0932
0933
0934
0935
0936 if (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset <
0937 ACPI_INTEGER_BIT_SIZE)
0938 {
0939 MergedDatum |= RawDatum <<
0940 (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
0941 }
0942
0943 if (i == DatumCount)
0944 {
0945 break;
0946 }
0947
0948
0949
0950 memcpy (((char *) Buffer) + BufferOffset, &MergedDatum,
0951 ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
0952 BufferLength - BufferOffset));
0953
0954 BufferOffset += ObjDesc->CommonField.AccessByteWidth;
0955 MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
0956 }
0957
0958
0959
0960 BufferTailBits = ObjDesc->CommonField.BitLength % AccessBitWidth;
0961 if (BufferTailBits)
0962 {
0963 MergedDatum &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
0964 }
0965
0966
0967
0968 memcpy (((char *) Buffer) + BufferOffset, &MergedDatum,
0969 ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
0970 BufferLength - BufferOffset));
0971
0972 return_ACPI_STATUS (AE_OK);
0973 }
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990 ACPI_STATUS
0991 AcpiExInsertIntoField (
0992 ACPI_OPERAND_OBJECT *ObjDesc,
0993 void *Buffer,
0994 UINT32 BufferLength)
0995 {
0996 void *NewBuffer;
0997 ACPI_STATUS Status;
0998 UINT64 Mask;
0999 UINT64 WidthMask;
1000 UINT64 MergedDatum;
1001 UINT64 RawDatum = 0;
1002 UINT32 FieldOffset = 0;
1003 UINT32 BufferOffset = 0;
1004 UINT32 BufferTailBits;
1005 UINT32 DatumCount;
1006 UINT32 FieldDatumCount;
1007 UINT32 AccessBitWidth;
1008 UINT32 RequiredLength;
1009 UINT32 i;
1010
1011
1012 ACPI_FUNCTION_TRACE (ExInsertIntoField);
1013
1014
1015
1016
1017 NewBuffer = NULL;
1018 RequiredLength = ACPI_ROUND_BITS_UP_TO_BYTES (
1019 ObjDesc->CommonField.BitLength);
1020
1021
1022
1023
1024
1025
1026
1027 if (BufferLength < RequiredLength)
1028 {
1029
1030
1031 NewBuffer = ACPI_ALLOCATE_ZEROED (RequiredLength);
1032 if (!NewBuffer)
1033 {
1034 return_ACPI_STATUS (AE_NO_MEMORY);
1035 }
1036
1037
1038
1039
1040
1041
1042 memcpy ((char *) NewBuffer, (char *) Buffer, BufferLength);
1043 Buffer = NewBuffer;
1044 BufferLength = RequiredLength;
1045 }
1046
1047
1048
1049
1050 if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
1051 {
1052 ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
1053 }
1054
1055 AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
1056
1057
1058
1059 WidthMask = ACPI_MASK_BITS_ABOVE_64 (AccessBitWidth);
1060 Mask = WidthMask &
1061 ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset);
1062
1063
1064
1065 DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength,
1066 AccessBitWidth);
1067
1068 FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength +
1069 ObjDesc->CommonField.StartFieldBitOffset,
1070 AccessBitWidth);
1071
1072
1073
1074 memcpy (&RawDatum, Buffer,
1075 ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
1076 BufferLength - BufferOffset));
1077
1078 MergedDatum = RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
1079
1080
1081
1082 for (i = 1; i < FieldDatumCount; i++)
1083 {
1084
1085
1086 MergedDatum &= Mask;
1087 Status = AcpiExWriteWithUpdateRule (
1088 ObjDesc, Mask, MergedDatum, FieldOffset);
1089 if (ACPI_FAILURE (Status))
1090 {
1091 goto Exit;
1092 }
1093
1094 FieldOffset += ObjDesc->CommonField.AccessByteWidth;
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105 if ((AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset) <
1106 ACPI_INTEGER_BIT_SIZE)
1107 {
1108 MergedDatum = RawDatum >>
1109 (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
1110 }
1111 else
1112 {
1113 MergedDatum = 0;
1114 }
1115
1116 Mask = WidthMask;
1117
1118 if (i == DatumCount)
1119 {
1120 break;
1121 }
1122
1123
1124
1125 BufferOffset += ObjDesc->CommonField.AccessByteWidth;
1126 memcpy (&RawDatum, ((char *) Buffer) + BufferOffset,
1127 ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
1128 BufferLength - BufferOffset));
1129
1130 MergedDatum |= RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
1131 }
1132
1133
1134
1135 BufferTailBits = (ObjDesc->CommonField.BitLength +
1136 ObjDesc->CommonField.StartFieldBitOffset) % AccessBitWidth;
1137 if (BufferTailBits)
1138 {
1139 Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
1140 }
1141
1142
1143
1144 MergedDatum &= Mask;
1145 Status = AcpiExWriteWithUpdateRule (
1146 ObjDesc, Mask, MergedDatum, FieldOffset);
1147
1148 Exit:
1149
1150
1151 if (NewBuffer)
1152 {
1153 ACPI_FREE (NewBuffer);
1154 }
1155 return_ACPI_STATUS (Status);
1156 }