TianoCore EDK2 master
Loading...
Searching...
No Matches
AmlUtility.c
Go to the documentation of this file.
1
9#include <Utils/AmlUtility.h>
10
11#include <AmlCoreInterface.h>
12#include <Tree/AmlNode.h>
13#include <Tree/AmlTree.h>
14
23EFIAPI
26 )
27{
28 UINT8 *Ptr;
29 UINT8 Sum;
30 UINT32 Size;
31
32 if (AcpiTable == NULL) {
33 ASSERT (0);
34 return EFI_INVALID_PARAMETER;
35 }
36
37 Ptr = (UINT8 *)AcpiTable;
38 Size = AcpiTable->Length;
39 Sum = 0;
40
41 // Set the checksum field to 0 first.
42 AcpiTable->Checksum = 0;
43
44 // Compute the checksum.
45 while ((Size--) != 0) {
46 Sum = (UINT8)(Sum + (*Ptr++));
47 }
48
49 // Set the checksum.
50 AcpiTable->Checksum = (UINT8)(0xFF - Sum + 1);
51
52 return EFI_SUCCESS;
53}
54
76BOOLEAN
77EFIAPI
79 IN AML_NODE_HEADER *Node,
80 IN OUT VOID *Context,
81 IN OUT EFI_STATUS *Status OPTIONAL
82 )
83{
84 UINT32 Size;
85 EAML_PARSE_INDEX IndexPtr;
86 CONST AML_OBJECT_NODE *ParentNode;
87
88 if (!IS_AML_NODE_VALID (Node) ||
89 (Context == NULL))
90 {
91 ASSERT (0);
92 if (Status != NULL) {
93 *Status = EFI_INVALID_PARAMETER;
94 }
95
96 return FALSE;
97 }
98
99 // Ignore the second fixed argument of method invocation nodes
100 // as the information stored there (the argument count) is not in the
101 // ACPI specification.
102 ParentNode = (CONST AML_OBJECT_NODE *)AmlGetParent (Node);
103 if (IS_AML_OBJECT_NODE (ParentNode) &&
104 AmlNodeCompareOpCode (ParentNode, AML_METHOD_INVOC_OP, 0) &&
105 AmlIsNodeFixedArgument (Node, &IndexPtr))
106 {
107 if (IndexPtr == EAmlParseIndexTerm1) {
108 if (Status != NULL) {
109 *Status = EFI_SUCCESS;
110 }
111
112 return TRUE;
113 }
114 }
115
116 Size = *((UINT32 *)Context);
117
118 if (IS_AML_DATA_NODE (Node)) {
119 Size += ((AML_DATA_NODE *)Node)->Size;
120 } else if (IS_AML_OBJECT_NODE (Node) &&
122 (CONST AML_OBJECT_NODE *)Node,
124 ))
125 {
126 // Ignore pseudo-opcodes as they are not part of the
127 // ACPI specification.
128
129 Size += (((AML_OBJECT_NODE *)Node)->AmlByteEncoding->OpCode ==
130 AML_EXT_OP) ? 2 : 1;
131
132 // Add the size of the PkgLen.
134 (AML_OBJECT_NODE *)Node,
136 ))
137 {
138 Size += AmlComputePkgLengthWidth (((AML_OBJECT_NODE *)Node)->PkgLen);
139 }
140 }
141
142 // Check for overflow.
143 // The root node has a null size, thus the strict comparison.
144 if (*((UINT32 *)Context) > Size) {
145 ASSERT (0);
146 *Status = EFI_INVALID_PARAMETER;
147 return FALSE;
148 }
149
150 *((UINT32 *)Context) = Size;
151
152 if (Status != NULL) {
153 *Status = EFI_SUCCESS;
154 }
155
156 return TRUE;
157}
158
168EFIAPI
171 IN OUT UINT32 *Size
172 )
173{
174 EFI_STATUS Status;
175
176 if (!IS_AML_NODE_VALID (Node) ||
177 (Size == NULL))
178 {
179 ASSERT (0);
180 return EFI_INVALID_PARAMETER;
181 }
182
183 *Size = 0;
184
186 (AML_NODE_HEADER *)Node,
188 (VOID *)Size,
189 &Status
190 );
191
192 return Status;
193}
194
205EFIAPI
207 IN AML_OBJECT_NODE *Node,
208 OUT UINT64 *Value
209 )
210{
211 AML_DATA_NODE *DataNode;
212
213 if ((!IsIntegerNode (Node) &&
214 !IsSpecialIntegerNode (Node)) ||
215 (Value == NULL))
216 {
217 ASSERT (0);
218 return EFI_INVALID_PARAMETER;
219 }
220
221 // For ZeroOp and OneOp, there is no data node.
222 if (IsSpecialIntegerNode (Node)) {
223 if (AmlNodeCompareOpCode (Node, AML_ZERO_OP, 0)) {
224 *Value = 0;
225 } else if (AmlNodeCompareOpCode (Node, AML_ONE_OP, 0)) {
226 *Value = 1;
227 } else {
228 // OnesOp cannot be handled: it represents a maximum value.
229 ASSERT (0);
230 return EFI_INVALID_PARAMETER;
231 }
232
233 return EFI_SUCCESS;
234 }
235
236 // For integer nodes, the value is in the first fixed argument.
237 DataNode = (AML_DATA_NODE *)Node->FixedArgs[EAmlParseIndexTerm0];
238 if (!IS_AML_DATA_NODE (DataNode) ||
239 (DataNode->DataType != EAmlNodeDataTypeUInt))
240 {
241 ASSERT (0);
242 return EFI_INVALID_PARAMETER;
243 }
244
245 switch (DataNode->Size) {
246 case 1:
247 {
248 *Value = *((UINT8 *)(DataNode->Buffer));
249 break;
250 }
251 case 2:
252 {
253 *Value = *((UINT16 *)(DataNode->Buffer));
254 break;
255 }
256 case 4:
257 {
258 *Value = *((UINT32 *)(DataNode->Buffer));
259 break;
260 }
261 case 8:
262 {
263 *Value = *((UINT64 *)(DataNode->Buffer));
264 break;
265 }
266 default:
267 {
268 ASSERT (0);
269 return EFI_INVALID_PARAMETER;
270 }
271 } // switch
272
273 return EFI_SUCCESS;
274}
275
285STATIC
287EFIAPI
289 IN AML_OBJECT_NODE *Node
290 )
291{
292 EFI_STATUS Status;
293
294 AML_DATA_NODE *NewDataNode;
295 UINT8 Value;
296 CONST AML_BYTE_ENCODING *ByteEncoding;
297
298 if (!IsSpecialIntegerNode (Node)) {
299 ASSERT (0);
300 return EFI_INVALID_PARAMETER;
301 }
302
303 // Find the value.
304 if (AmlNodeCompareOpCode (Node, AML_ZERO_OP, 0)) {
305 Value = 0;
306 } else if (AmlNodeCompareOpCode (Node, AML_ONE_OP, 0)) {
307 Value = 1;
308 } else {
309 // OnesOp cannot be handled: it represents a maximum value.
310 ASSERT (0);
311 return EFI_INVALID_PARAMETER;
312 }
313
314 Status = AmlCreateDataNode (
316 &Value,
317 sizeof (UINT8),
318 (AML_DATA_NODE **)&NewDataNode
319 );
320 if (EFI_ERROR (Status)) {
321 ASSERT (0);
322 return Status;
323 }
324
325 // Change the encoding of the special node to a ByteOp encoding.
326 ByteEncoding = AmlGetByteEncodingByOpCode (AML_BYTE_PREFIX, 0);
327 if (ByteEncoding == NULL) {
328 ASSERT (0);
329 Status = EFI_INVALID_PARAMETER;
330 goto error_handler;
331 }
332
333 // Update the ByteEncoding from ZERO_OP/ONE_OP to AML_BYTE_PREFIX.
334 Node->AmlByteEncoding = ByteEncoding;
335
336 // Add the data node as the first fixed argument of the ByteOp object.
337 Status = AmlSetFixedArgument (
338 (AML_OBJECT_NODE *)Node,
340 (AML_NODE_HEADER *)NewDataNode
341 );
342 if (EFI_ERROR (Status)) {
343 ASSERT (0);
344 goto error_handler;
345 }
346
347 return Status;
348
349error_handler:
350 AmlDeleteTree ((AML_NODE_HEADER *)NewDataNode);
351 return Status;
352}
353
373EFIAPI
375 IN AML_OBJECT_NODE *Node,
376 IN UINT64 NewValue,
377 OUT INT8 *ValueWidthDiff
378 )
379{
380 EFI_STATUS Status;
381 AML_DATA_NODE *DataNode;
382
383 UINT8 NewOpCode;
384 UINT8 NumberOfBytes;
385
386 if ((!IsIntegerNode (Node) &&
387 !IsSpecialIntegerNode (Node)) ||
388 (ValueWidthDiff == NULL))
389 {
390 ASSERT (0);
391 return EFI_INVALID_PARAMETER;
392 }
393
394 *ValueWidthDiff = 0;
395 // For ZeroOp and OneOp, there is no data node.
396 // Thus the object node is converted to a byte object node holding 0 or 1.
397 if (IsSpecialIntegerNode (Node)) {
398 switch (NewValue) {
399 case AML_ZERO_OP:
400 Node->AmlByteEncoding = AmlGetByteEncodingByOpCode (AML_ZERO_OP, 0);
401 return EFI_SUCCESS;
402 case AML_ONE_OP:
403 Node->AmlByteEncoding = AmlGetByteEncodingByOpCode (AML_ONE_OP, 0);
404 return EFI_SUCCESS;
405 default:
406 {
407 Status = AmlUnwindSpecialInteger (Node);
408 if (EFI_ERROR (Status)) {
409 ASSERT (0);
410 return Status;
411 }
412
413 // The AmlUnwindSpecialInteger functions converts a special integer
414 // node to a UInt8/Byte data node. Thus, the size increments by one:
415 // special integer are encoded as one byte (the opcode only) while byte
416 // integers are encoded as two bytes (the opcode + the value).
417 *ValueWidthDiff += sizeof (UINT8);
418 }
419 } // switch
420 } // IsSpecialIntegerNode (Node)
421
422 // For integer nodes, the value is in the first fixed argument.
423 DataNode = (AML_DATA_NODE *)Node->FixedArgs[EAmlParseIndexTerm0];
424 if (!IS_AML_DATA_NODE (DataNode) ||
425 (DataNode->DataType != EAmlNodeDataTypeUInt))
426 {
427 ASSERT (0);
428 return EFI_INVALID_PARAMETER;
429 }
430
431 // The value can be encoded with a special 0 or 1 OpCode.
432 // The AML_ONES_OP is not handled.
433 if (NewValue <= 1) {
434 NewOpCode = (NewValue == 0) ? AML_ZERO_OP : AML_ONE_OP;
435 Node->AmlByteEncoding = AmlGetByteEncodingByOpCode (NewOpCode, 0);
436
437 // The value is encoded with a AML_ZERO_OP or AML_ONE_OP.
438 // This means there is no need for a DataNode containing the value.
439 // The change in size is equal to the size of the DataNode's buffer.
440 *ValueWidthDiff = -((INT8)DataNode->Size);
441
442 // Detach and free the DataNode containing the integer value.
443 DataNode->NodeHeader.Parent = NULL;
444 Node->FixedArgs[EAmlParseIndexTerm0] = NULL;
445 Status = AmlDeleteNode ((AML_NODE_HEADER *)DataNode);
446 if (EFI_ERROR (Status)) {
447 ASSERT (0);
448 return Status;
449 }
450
451 return EFI_SUCCESS;
452 }
453
454 // Check the number of bits needed to represent the value.
455 if (NewValue > MAX_UINT32) {
456 // Value is 64 bits.
457 NewOpCode = AML_QWORD_PREFIX;
458 NumberOfBytes = 8;
459 } else if (NewValue > MAX_UINT16) {
460 // Value is 32 bits.
461 NewOpCode = AML_DWORD_PREFIX;
462 NumberOfBytes = 4;
463 } else if (NewValue > MAX_UINT8) {
464 // Value is 16 bits.
465 NewOpCode = AML_WORD_PREFIX;
466 NumberOfBytes = 2;
467 } else {
468 // Value is 8 bits.
469 NewOpCode = AML_BYTE_PREFIX;
470 NumberOfBytes = 1;
471 }
472
473 *ValueWidthDiff += (INT8)(NumberOfBytes - DataNode->Size);
474
475 // Update the ByteEncoding as it may have changed between [8 .. 64] bits.
476 Node->AmlByteEncoding = AmlGetByteEncodingByOpCode (NewOpCode, 0);
477 if (Node->AmlByteEncoding == NULL) {
478 ASSERT (0);
479 return EFI_INVALID_PARAMETER;
480 }
481
482 // Free the old DataNode buffer and allocate a buffer with the right size
483 // to store the new data.
484 if (*ValueWidthDiff != 0) {
485 FreePool (DataNode->Buffer);
486 DataNode->Buffer = AllocateZeroPool (NumberOfBytes);
487 if (DataNode->Buffer == NULL) {
488 ASSERT (0);
489 return EFI_OUT_OF_RESOURCES;
490 }
491
492 DataNode->Size = NumberOfBytes;
493 }
494
495 // Write the new value.
496 CopyMem (DataNode->Buffer, &NewValue, NumberOfBytes);
497
498 return EFI_SUCCESS;
499}
500
519STATIC
521EFIAPI
523 IN AML_OBJECT_NODE *IntegerNode,
524 IN BOOLEAN IsIncrement,
525 IN UINT64 Diff,
526 OUT INT8 *ValueWidthDiff
527 )
528{
529 EFI_STATUS Status;
530 UINT64 Value;
531
532 if (ValueWidthDiff == NULL) {
533 ASSERT (0);
534 return EFI_INVALID_PARAMETER;
535 }
536
537 // Get the current value.
538 // Checks on the IntegerNode are done in the call.
539 Status = AmlNodeGetIntegerValue (IntegerNode, &Value);
540 if (EFI_ERROR (Status)) {
541 ASSERT (0);
542 return Status;
543 }
544
545 // Check for UINT64 over/underflow.
546 if ((IsIncrement && (Value > (MAX_UINT64 - Diff))) ||
547 (!IsIncrement && (Value < Diff)))
548 {
549 ASSERT (0);
550 return EFI_INVALID_PARAMETER;
551 }
552
553 // Compute the new value.
554 if (IsIncrement) {
555 Value += Diff;
556 } else {
557 Value -= Diff;
558 }
559
560 Status = AmlNodeSetIntegerValue (
561 IntegerNode,
562 Value,
563 ValueWidthDiff
564 );
565 ASSERT_EFI_ERROR (Status);
566 return Status;
567}
568
586STATIC
588EFIAPI
590 IN AML_NODE_HEADER *Node,
591 IN BOOLEAN IsIncrement,
592 IN UINT32 *Diff
593 )
594{
595 EFI_STATUS Status;
596 AML_OBJECT_NODE *ObjectNode;
597 AML_NODE_HEADER *ParentNode;
598
599 UINT32 Value;
600 UINT32 InitialPkgLenWidth;
601 UINT32 NewPkgLenWidth;
602 UINT32 ReComputedPkgLenWidth;
603 INT8 FieldWidthChange;
604
605 if (!IS_AML_OBJECT_NODE (Node) &&
606 !IS_AML_ROOT_NODE (Node))
607 {
608 ASSERT (0);
609 return EFI_INVALID_PARAMETER;
610 }
611
612 if (IS_AML_OBJECT_NODE (Node)) {
613 ObjectNode = (AML_OBJECT_NODE *)Node;
614
615 // For BufferOp, the buffer size is stored in BufferSize. Therefore,
616 // BufferOp needs special handling to update the BufferSize.
617 // BufferSize must be updated before the PkgLen to accommodate any
618 // increment resulting from the update of the BufferSize.
619 // DefBuffer := BufferOp PkgLength BufferSize ByteList
620 // BufferOp := 0x11
621 // BufferSize := TermArg => Integer
622 if (AmlNodeCompareOpCode (ObjectNode, AML_BUFFER_OP, 0)) {
623 // First fixed argument of BufferOp is an integer (BufferSize)
624 // (can be a BYTE, WORD, DWORD or QWORD).
625 // BufferSize is an object node.
628 ObjectNode,
630 ),
631 IsIncrement,
632 (UINT64)(*Diff),
633 &FieldWidthChange
634 );
635 if (EFI_ERROR (Status)) {
636 ASSERT (0);
637 return Status;
638 }
639
640 // FieldWidthChange is an integer.
641 // It must be positive if IsIncrement is TRUE, negative otherwise.
642 if ((IsIncrement &&
643 (FieldWidthChange < 0)) ||
644 (!IsIncrement &&
645 (FieldWidthChange > 0)))
646 {
647 ASSERT (0);
648 return EFI_INVALID_PARAMETER;
649 }
650
651 // Check for UINT32 overflow.
652 if (*Diff > (MAX_UINT32 - (UINT32)ABS (FieldWidthChange))) {
653 ASSERT (0);
654 return EFI_INVALID_PARAMETER;
655 }
656
657 // Update Diff if the field width changed.
658 *Diff = (UINT32)(*Diff + ABS (FieldWidthChange));
659 } // AML_BUFFER_OP node.
660
661 // Update the PgkLen.
662 // Needs to be done at last to reflect the potential field width changes.
663 if (AmlNodeHasAttribute (ObjectNode, AML_HAS_PKG_LENGTH)) {
664 Value = ObjectNode->PkgLen;
665
666 // Subtract the size of the PkgLen encoding. The size of the PkgLen
667 // encoding must be computed after having updated Value.
668 InitialPkgLenWidth = AmlComputePkgLengthWidth (Value);
669 Value -= InitialPkgLenWidth;
670
671 // Check for an over/underflows.
672 // PkgLen is a 28 bit value, cf 20.2.4 Package Length Encoding
673 // i.e. the maximum value is (2^28 - 1) = ((BIT0 << 28) - 1).
674 if ((IsIncrement && ((((BIT0 << 28) - 1) - Value) < *Diff)) ||
675 (!IsIncrement && (Value < *Diff)))
676 {
677 ASSERT (0);
678 return EFI_INVALID_PARAMETER;
679 }
680
681 // Update the size.
682 if (IsIncrement) {
683 Value += *Diff;
684 } else {
685 Value -= *Diff;
686 }
687
688 // Compute the new PkgLenWidth.
689 NewPkgLenWidth = AmlComputePkgLengthWidth (Value);
690 if (NewPkgLenWidth == 0) {
691 ASSERT (0);
692 return EFI_INVALID_PARAMETER;
693 }
694
695 // Add it to the Value.
696 Value += NewPkgLenWidth;
697
698 // Check that adding the PkgLenWidth didn't trigger a domino effect,
699 // increasing the encoding width of the PkgLen again.
700 // The PkgLen is encoded on at most 4 bytes. It is possible to increase
701 // the PkgLen width if its encoding is on less than 3 bytes.
702 ReComputedPkgLenWidth = AmlComputePkgLengthWidth (Value);
703 if (ReComputedPkgLenWidth != NewPkgLenWidth) {
704 if ((ReComputedPkgLenWidth != 0) &&
705 (ReComputedPkgLenWidth < 4))
706 {
707 // No need to recompute the PkgLen since a new threshold cannot
708 // be reached by incrementing the value by one.
709 Value += 1;
710 } else {
711 ASSERT (0);
712 return EFI_INVALID_PARAMETER;
713 }
714 }
715
716 *Diff += (InitialPkgLenWidth > ReComputedPkgLenWidth) ?
717 (InitialPkgLenWidth - ReComputedPkgLenWidth) :
718 (ReComputedPkgLenWidth - InitialPkgLenWidth);
719 ObjectNode->PkgLen = Value;
720 } // PkgLen update.
721
722 // During CodeGeneration, the tree is incomplete and
723 // there is no root node at the top of the tree. Stop
724 // propagating the new size when finding a root node
725 // OR when a NULL parent is found.
726 ParentNode = AmlGetParent ((AML_NODE_HEADER *)Node);
727 if (ParentNode != NULL) {
728 // Propagate the size up the tree.
729 Status = AmlPropagateSize (
730 Node->Parent,
731 IsIncrement,
732 Diff
733 );
734 if (EFI_ERROR (Status)) {
735 ASSERT (0);
736 return Status;
737 }
738 }
739 } else if (IS_AML_ROOT_NODE (Node)) {
740 // Update the length field in the SDT header.
741 Value = ((AML_ROOT_NODE *)Node)->SdtHeader->Length;
742
743 // Check for an over/underflows.
744 if ((IsIncrement && (Value > (MAX_UINT32 - *Diff))) ||
745 (!IsIncrement && (Value < *Diff)))
746 {
747 ASSERT (0);
748 return EFI_INVALID_PARAMETER;
749 }
750
751 // Update the size.
752 if (IsIncrement) {
753 Value += *Diff;
754 } else {
755 Value -= *Diff;
756 }
757
758 ((AML_ROOT_NODE *)Node)->SdtHeader->Length = Value;
759 }
760
761 return EFI_SUCCESS;
762}
763
782STATIC
784EFIAPI
786 IN AML_OBJECT_NODE *ObjectNode,
787 IN BOOLEAN IsIncrement,
788 IN UINT8 NodeCount,
789 OUT INT8 *FieldWidthChange
790 )
791{
792 EFI_STATUS Status;
793
794 AML_NODE_HEADER *NodeCountArg;
795 UINT8 CurrNodeCount;
796
797 // Currently there is no use case where (NodeCount > 1).
798 if (!IS_AML_OBJECT_NODE (ObjectNode) ||
799 (FieldWidthChange == NULL) ||
800 (NodeCount > 1))
801 {
802 ASSERT (0);
803 return EFI_INVALID_PARAMETER;
804 }
805
806 *FieldWidthChange = 0;
807
808 // Update the number of elements stored in PackageOp and VarPackageOp.
809 // The number of elements is stored as the first fixed argument.
810 // DefPackage := PackageOp PkgLength NumElements PackageElementList
811 // PackageOp := 0x12
812 // DefVarPackage := VarPackageOp PkgLength VarNumElements PackageElementList
813 // VarPackageOp := 0x13
814 // NumElements := ByteData
815 // VarNumElements := TermArg => Integer
816 NodeCountArg = AmlGetFixedArgument (ObjectNode, EAmlParseIndexTerm0);
817 if (AmlNodeCompareOpCode (ObjectNode, AML_PACKAGE_OP, 0)) {
818 // First fixed argument of PackageOp stores the number of elements
819 // in the package. It is an UINT8.
820
821 // Check for over/underflow.
822 CurrNodeCount = *(((AML_DATA_NODE *)NodeCountArg)->Buffer);
823 if ((IsIncrement && (CurrNodeCount == MAX_UINT8)) ||
824 (!IsIncrement && (CurrNodeCount == 0)))
825 {
826 ASSERT (0);
827 return EFI_INVALID_PARAMETER;
828 }
829
830 // Update the node count in the DataNode.
831 CurrNodeCount = IsIncrement ? (CurrNodeCount + 1) : (CurrNodeCount - 1);
832 *(((AML_DATA_NODE *)NodeCountArg)->Buffer) = CurrNodeCount;
833 } else if (AmlNodeCompareOpCode (ObjectNode, AML_VAR_PACKAGE_OP, 0)) {
834 // First fixed argument of PackageOp stores the number of elements
835 // in the package. It is an integer (can be a BYTE, WORD, DWORD, QWORD).
837 (AML_OBJECT_NODE *)NodeCountArg,
838 IsIncrement,
839 NodeCount,
840 FieldWidthChange
841 );
842 if (EFI_ERROR (Status)) {
843 ASSERT (0);
844 return Status;
845 }
846 }
847
848 return EFI_SUCCESS;
849}
850
869EFIAPI
871 IN AML_NODE_HEADER *Node,
872 IN BOOLEAN IsIncrement,
873 IN UINT32 Diff,
874 IN UINT8 NodeCount
875 )
876{
877 EFI_STATUS Status;
878 INT8 FieldWidthChange;
879
880 // Currently there is no use case where (NodeCount > 1).
881 if ((!IS_AML_ROOT_NODE (Node) &&
882 !IS_AML_OBJECT_NODE (Node)) ||
883 (NodeCount > 1))
884 {
885 ASSERT (0);
886 return EFI_INVALID_PARAMETER;
887 }
888
889 // Propagate the node count first as it may change the number of bytes
890 // needed to store the node count, and then impact FieldWidthChange.
891 if ((NodeCount != 0) &&
892 IS_AML_OBJECT_NODE (Node))
893 {
894 Status = AmlPropagateNodeCount (
895 (AML_OBJECT_NODE *)Node,
896 IsIncrement,
897 NodeCount,
898 &FieldWidthChange
899 );
900 if (EFI_ERROR (Status)) {
901 ASSERT (0);
902 return Status;
903 }
904
905 // Propagate the potential field width change.
906 // Maximum change is between UINT8/UINT64: 8 bytes.
907 if ((ABS (FieldWidthChange) > 8) ||
908 (IsIncrement &&
909 ((FieldWidthChange < 0) ||
910 ((Diff + (UINT8)FieldWidthChange) > MAX_UINT32))) ||
911 (!IsIncrement &&
912 ((FieldWidthChange > 0) ||
913 (Diff < (UINT32)ABS (FieldWidthChange)))))
914 {
915 ASSERT (0);
916 return EFI_INVALID_PARAMETER;
917 }
918
919 Diff = (UINT32)(Diff + (UINT8)ABS (FieldWidthChange));
920 }
921
922 // Diff can be zero if some data is updated without modifying the data size.
923 if (Diff != 0) {
924 Status = AmlPropagateSize (Node, IsIncrement, &Diff);
925 if (EFI_ERROR (Status)) {
926 ASSERT (0);
927 return Status;
928 }
929 }
930
931 return EFI_SUCCESS;
932}
933
960EFIAPI
962 IN AML_OBJECT_NODE *BufferOpNode,
963 IN UINT8 CheckSum
964 )
965{
966 EFI_STATUS Status;
967 AML_DATA_NODE *LastRdNode;
968 AML_RD_HEADER RdDataType;
969
970 if (!AmlNodeCompareOpCode (BufferOpNode, AML_BUFFER_OP, 0)) {
971 ASSERT (0);
972 return EFI_INVALID_PARAMETER;
973 }
974
975 // Get the last Resource data node in the variable list of
976 // argument of the BufferOp node.
978 (AML_NODE_HEADER *)BufferOpNode,
979 NULL
980 );
981 if ((LastRdNode == NULL) ||
982 !IS_AML_DATA_NODE (LastRdNode) ||
983 (LastRdNode->DataType != EAmlNodeDataTypeResourceData))
984 {
985 ASSERT (0);
986 return EFI_INVALID_PARAMETER;
987 }
988
989 Status = AmlGetResourceDataType (LastRdNode, &RdDataType);
990 if (EFI_ERROR (Status)) {
991 ASSERT (0);
992 return Status;
993 }
994
995 // Check the LastRdNode is an EndTag.
996 // It is possible to have only one Resource Data in a BufferOp with
997 // no EndTag. Return EFI_NOT_FOUND is such case.
998 if (!AmlRdCompareDescId (
999 &RdDataType,
1000 AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME)
1001 ))
1002 {
1003 ASSERT (0);
1004 return EFI_NOT_FOUND;
1005 }
1006
1007 Status = AmlRdSetEndTagChecksum (LastRdNode->Buffer, CheckSum);
1008 ASSERT_EFI_ERROR (Status);
1009
1010 return Status;
1011}
#define AML_HAS_PKG_LENGTH
Definition: Aml.h:64
#define AML_IS_PSEUDO_OPCODE
Definition: Aml.h:103
BOOLEAN EFIAPI IsIntegerNode(IN AML_OBJECT_NODE *Node)
Definition: AmlNode.c:491
BOOLEAN EFIAPI AmlNodeCompareOpCode(IN CONST AML_OBJECT_NODE *ObjectNode, IN UINT8 OpCode, IN UINT8 SubOpCode)
Definition: AmlNode.c:457
EFI_STATUS EFIAPI AmlDeleteNode(IN AML_NODE_HEADER *Node)
Definition: AmlNode.c:339
BOOLEAN EFIAPI AmlNodeHasAttribute(IN CONST AML_OBJECT_NODE *ObjectNode, IN AML_OP_ATTRIBUTE Attribute)
Definition: AmlNode.c:430
BOOLEAN EFIAPI IsSpecialIntegerNode(IN AML_OBJECT_NODE *Node)
Definition: AmlNode.c:528
EFI_STATUS EFIAPI AmlCreateDataNode(IN EAML_NODE_DATA_TYPE DataType, IN CONST UINT8 *Data, IN UINT32 DataSize, OUT AML_DATA_NODE **NewDataNodePtr)
Definition: AmlNode.c:275
#define IS_AML_ROOT_NODE(Node)
#define IS_AML_OBJECT_NODE(Node)
#define IS_AML_DATA_NODE(Node)
#define IS_AML_NODE_VALID(Node)
EFI_STATUS EFIAPI AmlRdSetEndTagChecksum(IN CONST AML_RD_HEADER *Header, IN UINT8 CheckSum)
UINT8 AML_RD_HEADER
EFI_STATUS EFIAPI AmlSetFixedArgument(IN AML_OBJECT_NODE *ObjectNode, IN EAML_PARSE_INDEX Index, IN AML_NODE_HEADER *NewNode)
Definition: AmlTree.c:168
BOOLEAN EFIAPI AmlIsNodeFixedArgument(IN CONST AML_NODE_HEADER *Node, OUT EAML_PARSE_INDEX *IndexPtr)
Definition: AmlTree.c:110
EFI_STATUS EFIAPI AmlSetRdListCheckSum(IN AML_OBJECT_NODE *BufferOpNode, IN UINT8 CheckSum)
Definition: AmlUtility.c:961
EFI_STATUS EFIAPI AmlNodeGetIntegerValue(IN AML_OBJECT_NODE *Node, OUT UINT64 *Value)
Definition: AmlUtility.c:206
EFI_STATUS EFIAPI AmlNodeSetIntegerValue(IN AML_OBJECT_NODE *Node, IN UINT64 NewValue, OUT INT8 *ValueWidthDiff)
Definition: AmlUtility.c:374
EFI_STATUS EFIAPI AcpiPlatformChecksum(IN EFI_ACPI_DESCRIPTION_HEADER *AcpiTable)
Definition: AmlUtility.c:24
STATIC EFI_STATUS EFIAPI AmlPropagateSize(IN AML_NODE_HEADER *Node, IN BOOLEAN IsIncrement, IN UINT32 *Diff)
Definition: AmlUtility.c:589
EFI_STATUS EFIAPI AmlPropagateInformation(IN AML_NODE_HEADER *Node, IN BOOLEAN IsIncrement, IN UINT32 Diff, IN UINT8 NodeCount)
Definition: AmlUtility.c:870
STATIC EFI_STATUS EFIAPI AmlPropagateNodeCount(IN AML_OBJECT_NODE *ObjectNode, IN BOOLEAN IsIncrement, IN UINT8 NodeCount, OUT INT8 *FieldWidthChange)
Definition: AmlUtility.c:785
STATIC BOOLEAN EFIAPI AmlComputeSizeCallback(IN AML_NODE_HEADER *Node, IN OUT VOID *Context, IN OUT EFI_STATUS *Status OPTIONAL)
Definition: AmlUtility.c:78
EFI_STATUS EFIAPI AmlComputeSize(IN CONST AML_NODE_HEADER *Node, IN OUT UINT32 *Size)
Definition: AmlUtility.c:169
STATIC EFI_STATUS EFIAPI AmlNodeUpdateIntegerValue(IN AML_OBJECT_NODE *IntegerNode, IN BOOLEAN IsIncrement, IN UINT64 Diff, OUT INT8 *ValueWidthDiff)
Definition: AmlUtility.c:522
STATIC EFI_STATUS EFIAPI AmlUnwindSpecialInteger(IN AML_OBJECT_NODE *Node)
Definition: AmlUtility.c:288
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
CONST AML_BYTE_ENCODING *EFIAPI AmlGetByteEncodingByOpCode(IN UINT8 OpCode, IN UINT8 SubOpCode)
Definition: Aml.c:347
UINT8 EFIAPI AmlComputePkgLengthWidth(IN UINT32 Length)
Definition: Aml.c:799
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define ABS(a)
Definition: Base.h:1020
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
AML_NODE_HANDLE EFIAPI AmlGetParent(IN AML_NODE_HANDLE Node)
AML_NODE_HANDLE EFIAPI AmlGetFixedArgument(IN AML_OBJECT_NODE_HANDLE ObjectNode, IN EAML_PARSE_INDEX Index)
AML_NODE_HANDLE EFIAPI AmlGetPreviousVariableArgument(IN AML_NODE_HANDLE Node, IN AML_NODE_HANDLE CurrVarArg)
BOOLEAN EFIAPI AmlEnumTree(IN AML_NODE_HANDLE Node, IN EDKII_AML_TREE_ENUM_CALLBACK CallBack, IN OUT VOID *Context OPTIONAL, OUT EFI_STATUS *Status OPTIONAL)
EFI_STATUS EFIAPI AmlGetResourceDataType(IN AML_DATA_NODE_HANDLE DataNode, OUT AML_RD_HEADER *ResourceDataType)
BOOLEAN EFIAPI AmlRdCompareDescId(IN CONST AML_RD_HEADER *Header, IN AML_RD_HEADER DescriptorId)
#define AML_RD_BUILD_SMALL_DESC_ID(Id)
#define AML_METHOD_INVOC_OP
Definition: AmlDefines.h:120
enum EAmlParseIndex EAML_PARSE_INDEX
@ EAmlParseIndexTerm1
Second fixed argument index.
Definition: AmlDefines.h:66
@ EAmlParseIndexTerm0
First fixed argument index.
Definition: AmlDefines.h:65
@ EAmlNodeDataTypeResourceData
Resource data element.
Definition: AmlDefines.h:44
@ EAmlNodeDataTypeUInt
Definition: AmlDefines.h:41
EFI_STATUS EFIAPI AmlDeleteTree(IN AML_NODE_HANDLE Node)
AML_NODE_HEADER NodeHeader
Header information. Must be the first field of the struct.
EAML_NODE_DATA_TYPE DataType
UINT8 * Buffer
Buffer containing the data stored by this node.
UINT32 Size
Size of the Buffer.
struct AmlNodeHeader * Parent
Parent of this node. NULL for the root node.