TianoCore EDK2 master
Loading...
Searching...
No Matches
AmlNodeInterface.c
Go to the documentation of this file.
1
9#include <AmlNodeDefines.h>
10
11#include <AmlCoreInterface.h>
13#include <String/AmlString.h>
14#include <Tree/AmlNode.h>
15#include <Tree/AmlTree.h>
16#include <Utils/AmlUtility.h>
17
26EFIAPI
29 )
30{
31 if (!IS_AML_NODE_VALID (Node)) {
32 ASSERT (0);
33 return EAmlNodeUnknown;
34 }
35
36 return Node->NodeType;
37}
38
49EFIAPI
51 IN AML_ROOT_NODE *RootNode,
52 OUT EFI_ACPI_DESCRIPTION_HEADER *SdtHeaderBuffer
53 )
54{
55 if (!IS_AML_ROOT_NODE (RootNode) ||
56 (SdtHeaderBuffer == NULL))
57 {
58 ASSERT (0);
59 return EFI_INVALID_PARAMETER;
60 }
61
62 CopyMem (
63 SdtHeaderBuffer,
64 RootNode->SdtHeader,
66 );
67
68 return EFI_SUCCESS;
69}
70
96EFIAPI
98 IN AML_OBJECT_NODE *ObjectNode,
99 OUT UINT8 *OpCode OPTIONAL,
100 OUT UINT8 *SubOpCode OPTIONAL,
101 OUT UINT32 *PkgLen OPTIONAL,
102 OUT BOOLEAN *IsNameSpaceNode OPTIONAL
103 )
104{
105 if (!IS_AML_OBJECT_NODE (ObjectNode)) {
106 ASSERT (0);
107 return EFI_INVALID_PARAMETER;
108 }
109
110 if (OpCode != NULL) {
111 *OpCode = ObjectNode->AmlByteEncoding->OpCode;
112 }
113
114 if (SubOpCode != NULL) {
115 *SubOpCode = ObjectNode->AmlByteEncoding->SubOpCode;
116 }
117
118 if (PkgLen != NULL) {
119 *PkgLen = ObjectNode->PkgLen;
120 }
121
122 if (IsNameSpaceNode != NULL) {
123 *IsNameSpaceNode = AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE);
124 }
125
126 return EFI_SUCCESS;
127}
128
136UINT8
138 IN AML_OBJECT_NODE *Node
139 )
140{
141 if (IS_AML_OBJECT_NODE (Node) &&
142 (Node->AmlByteEncoding != NULL))
143 {
144 return (UINT8)Node->AmlByteEncoding->MaxIndex;
145 }
146
147 return 0;
148}
149
160EFIAPI
162 IN AML_DATA_NODE *DataNode,
163 OUT EAML_NODE_DATA_TYPE *DataType
164 )
165{
166 if (!IS_AML_DATA_NODE (DataNode) ||
167 (DataType == NULL))
168 {
169 ASSERT (0);
170 return EFI_INVALID_PARAMETER;
171 }
172
173 *DataType = DataNode->DataType;
174
175 return EFI_SUCCESS;
176}
177
194EFIAPI
196 IN AML_DATA_NODE *DataNode,
197 OUT AML_RD_HEADER *ResourceDataType
198 )
199{
200 if (!IS_AML_DATA_NODE (DataNode) ||
201 (ResourceDataType == NULL) ||
202 (DataNode->DataType != EAmlNodeDataTypeResourceData))
203 {
204 ASSERT (0);
205 return EFI_INVALID_PARAMETER;
206 }
207
208 *ResourceDataType = AmlRdGetDescId (DataNode->Buffer);
209
210 return EFI_SUCCESS;
211}
212
235EFIAPI
237 IN AML_DATA_NODE *DataNode,
238 OUT UINT8 *Buffer OPTIONAL,
239 IN OUT UINT32 *BufferSize
240 )
241{
242 if (!IS_AML_DATA_NODE (DataNode) ||
243 (BufferSize == NULL))
244 {
245 ASSERT (0);
246 return EFI_INVALID_PARAMETER;
247 }
248
249 if ((*BufferSize >= DataNode->Size) &&
250 (Buffer != NULL))
251 {
252 CopyMem (Buffer, DataNode->Buffer, DataNode->Size);
253 }
254
255 *BufferSize = DataNode->Size;
256
257 return EFI_SUCCESS;
258}
259
273EFIAPI
275 IN AML_ROOT_NODE *RootNode,
277 )
278{
279 EFI_STATUS Status;
280 UINT32 Length;
281
282 if (!IS_AML_ROOT_NODE (RootNode) ||
283 (SdtHeader == NULL) ||
284 ((SdtHeader->Signature !=
286 (SdtHeader->Signature !=
288 {
289 ASSERT (0);
290 return EFI_INVALID_PARAMETER;
291 }
292
293 CopyMem (
294 RootNode->SdtHeader,
295 SdtHeader,
297 );
298
299 // Update the Length field.
300 Status = AmlComputeSize ((AML_NODE_HEADER *)RootNode, &Length);
301 if (EFI_ERROR (Status)) {
302 ASSERT (0);
303 return Status;
304 }
305
306 RootNode->SdtHeader->Length = Length +
307 (UINT32)sizeof (EFI_ACPI_DESCRIPTION_HEADER);
308
309 return Status;
310}
311
334EFIAPI
336 IN AML_OBJECT_NODE *IntegerOpNode,
337 IN UINT64 NewInteger
338 )
339{
340 EFI_STATUS Status;
341
342 INT8 ValueWidthDiff;
343
344 if (!IS_AML_OBJECT_NODE (IntegerOpNode) ||
345 (!IsIntegerNode (IntegerOpNode) &&
346 !IsSpecialIntegerNode (IntegerOpNode)) ||
347 AmlNodeCompareOpCode (IntegerOpNode, AML_ONES_OP, 0))
348 {
349 ASSERT (0);
350 return EFI_INVALID_PARAMETER;
351 }
352
353 Status = AmlNodeSetIntegerValue (IntegerOpNode, NewInteger, &ValueWidthDiff);
354 if (EFI_ERROR (Status)) {
355 ASSERT (0);
356 return Status;
357 }
358
359 // If the new size is different from the old size, propagate the new size.
360 if (ValueWidthDiff != 0) {
361 // Propagate the information.
362 Status = AmlPropagateInformation (
363 (AML_NODE_HEADER *)IntegerOpNode,
364 (ValueWidthDiff > 0) ? TRUE : FALSE,
365 ABS (ValueWidthDiff),
366 0
367 );
368 if (EFI_ERROR (Status)) {
369 ASSERT (0);
370 }
371 }
372
373 return Status;
374}
375
392EFIAPI
394 IN AML_DATA_NODE *DataNode,
395 IN EAML_NODE_DATA_TYPE DataType,
396 IN UINT8 *Buffer,
397 IN UINT32 Size
398 )
399{
400 EFI_STATUS Status;
401
402 UINT32 ExpectedSize;
403 AML_OBJECT_NODE *ParentNode;
404 EAML_NODE_DATA_TYPE ExpectedArgType;
405 EAML_PARSE_INDEX Index;
406
407 if (!IS_AML_DATA_NODE (DataNode) ||
408 (DataType > EAmlNodeDataTypeMax) ||
409 (Buffer == NULL) ||
410 (Size == 0))
411 {
412 ASSERT (0);
413 return EFI_INVALID_PARAMETER;
414 }
415
416 ParentNode = (AML_OBJECT_NODE *)AmlGetParent ((AML_NODE_HEADER *)DataNode);
417 if (!IS_AML_OBJECT_NODE (ParentNode)) {
418 ASSERT (0);
419 return EFI_INVALID_PARAMETER;
420 }
421
422 // The NewNode and OldNode must have the same type.
423 // We do not allow to change the argument type of a data node.
424 // If required, the initial ASL template should be modified
425 // accordingly.
426 // It is however possible to interchange a raw buffer and a
427 // resource data element, since raw data can be misinterpreted
428 // as a resource data element.
429 ExpectedArgType = DataNode->DataType;
430 if ((ExpectedArgType != DataType) &&
431 (((ExpectedArgType != EAmlNodeDataTypeRaw) &&
432 (ExpectedArgType != EAmlNodeDataTypeResourceData)) ||
433 ((DataType != EAmlNodeDataTypeRaw) &&
434 (DataType != EAmlNodeDataTypeResourceData))))
435 {
436 ASSERT (0);
437 return EFI_UNSUPPORTED;
438 }
439
440 // Perform some compatibility checks.
441 switch (DataType) {
443 {
444 // Check the name contained in the Buffer is an AML name
445 // with the right size.
446 Status = AmlGetNameStringSize ((CONST CHAR8 *)Buffer, &ExpectedSize);
447 if (EFI_ERROR (Status) ||
448 (Size != ExpectedSize))
449 {
450 ASSERT (0);
451 return Status;
452 }
453
454 break;
455 }
457 {
458 ExpectedSize = 0;
459 while (ExpectedSize < Size) {
460 // Cf ACPI 6.3 specification 20.2.3 Data Objects Encoding.
461 // AsciiCharList := Nothing | <AsciiChar AsciiCharList>
462 // AsciiChar := 0x01 - 0x7F
463 // NullChar := 0x00
464 if (Buffer[ExpectedSize] > 0x7F) {
465 ASSERT (0);
466 return EFI_INVALID_PARAMETER;
467 }
468
469 ExpectedSize++;
470 }
471
472 if (ExpectedSize != Size) {
473 ASSERT (0);
474 return EFI_INVALID_PARAMETER;
475 }
476
477 break;
478 }
480 {
481 if (AmlIsNodeFixedArgument ((CONST AML_NODE_HEADER *)DataNode, &Index)) {
482 if ((ParentNode->AmlByteEncoding == NULL) ||
483 (ParentNode->AmlByteEncoding->Format == NULL))
484 {
485 ASSERT (0);
486 return EFI_INVALID_PARAMETER;
487 }
488
489 // It is not possible to change the size of a fixed length UintX.
490 // E.g. for PackageOp the first fixed argument is of type EAmlUInt8
491 // and represents the count of elements. This type cannot be changed.
492 if ((ParentNode->AmlByteEncoding->Format[Index] != EAmlObject) &&
493 (DataNode->Size != Size))
494 {
495 ASSERT (0);
496 return EFI_UNSUPPORTED;
497 }
498 }
499
500 break;
501 }
503 {
504 // Check if the parent node has the byte list flag set.
505 if (!AmlNodeHasAttribute (ParentNode, AML_HAS_BYTE_LIST)) {
506 ASSERT (0);
507 return EFI_INVALID_PARAMETER;
508 }
509
510 break;
511 }
513 {
514 // The resource data can be either small or large resource data.
515 // Small resource data must be at least 1 byte.
516 // Large resource data must be at least as long as the header
517 // of a large resource data.
518 if (AML_RD_IS_LARGE (Buffer) &&
519 (Size < sizeof (ACPI_LARGE_RESOURCE_HEADER)))
520 {
521 ASSERT (0);
522 return EFI_INVALID_PARAMETER;
523 }
524
525 // Check if the parent node has the byte list flag set.
526 if (!AmlNodeHasAttribute (ParentNode, AML_HAS_BYTE_LIST)) {
527 ASSERT (0);
528 return EFI_INVALID_PARAMETER;
529 }
530
531 // Check the size of the buffer is equal to the resource data size
532 // encoded in the input buffer.
533 ExpectedSize = AmlRdGetSize (Buffer);
534 if (ExpectedSize != Size) {
535 ASSERT (0);
536 return EFI_INVALID_PARAMETER;
537 }
538
539 Status = AmlSetRdListCheckSum (ParentNode, 0);
540 if (EFI_ERROR (Status)) {
541 ASSERT (0);
542 return Status;
543 }
544
545 break;
546 }
548 {
549 // Check the parent is a FieldNamed field element.
550 if (!AmlNodeCompareOpCode (ParentNode, AML_FIELD_NAMED_OP, 0)) {
551 ASSERT (0);
552 return EFI_INVALID_PARAMETER;
553 }
554
555 break;
556 }
557 // None and reserved types.
558 default:
559 {
560 ASSERT (0);
561 return EFI_INVALID_PARAMETER;
562 break;
563 }
564 } // switch
565
566 // If the new size is different from the old size, propagate the new size.
567 if (DataNode->Size != Size) {
568 // Propagate the information.
569 Status = AmlPropagateInformation (
570 DataNode->NodeHeader.Parent,
571 (Size > DataNode->Size) ? TRUE : FALSE,
572 (Size > DataNode->Size) ?
573 (Size - DataNode->Size) :
574 (DataNode->Size - Size),
575 0
576 );
577 if (EFI_ERROR (Status)) {
578 ASSERT (0);
579 return Status;
580 }
581
582 // Free the old DataNode buffer and allocate a new buffer to store the
583 // new data.
584 FreePool (DataNode->Buffer);
585 DataNode->Buffer = AllocateZeroPool (Size);
586 if (DataNode->Buffer == NULL) {
587 ASSERT (0);
588 return EFI_OUT_OF_RESOURCES;
589 }
590
591 DataNode->Size = Size;
592 }
593
594 CopyMem (DataNode->Buffer, Buffer, Size);
595
596 return EFI_SUCCESS;
597}
#define EFI_ACPI_6_3_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
Definition: Acpi63.h:2716
#define EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
Definition: Acpi63.h:2831
#define AML_IN_NAMESPACE
Definition: Aml.h:98
#define AML_HAS_BYTE_LIST
Definition: Aml.h:82
@ EAmlObject
Definition: Aml.h:39
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
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
#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 AmlUpdateDataNode(IN AML_DATA_NODE *DataNode, IN EAML_NODE_DATA_TYPE DataType, IN UINT8 *Buffer, IN UINT32 Size)
EAML_NODE_TYPE EFIAPI AmlGetNodeType(IN AML_NODE_HEADER *Node)
EFI_STATUS EFIAPI AmlGetObjectNodeInfo(IN AML_OBJECT_NODE *ObjectNode, OUT UINT8 *OpCode OPTIONAL, OUT UINT8 *SubOpCode OPTIONAL, OUT UINT32 *PkgLen OPTIONAL, OUT BOOLEAN *IsNameSpaceNode OPTIONAL)
EFI_STATUS EFIAPI AmlGetRootNodeInfo(IN AML_ROOT_NODE *RootNode, OUT EFI_ACPI_DESCRIPTION_HEADER *SdtHeaderBuffer)
EFI_STATUS EFIAPI AmlUpdateRootNode(IN AML_ROOT_NODE *RootNode, IN CONST EFI_ACPI_DESCRIPTION_HEADER *SdtHeader)
EFI_STATUS EFIAPI AmlGetDataNodeBuffer(IN AML_DATA_NODE *DataNode, OUT UINT8 *Buffer OPTIONAL, IN OUT UINT32 *BufferSize)
UINT8 AmlGetFixedArgumentCount(IN AML_OBJECT_NODE *Node)
EFI_STATUS EFIAPI AmlUpdateInteger(IN AML_OBJECT_NODE *IntegerOpNode, IN UINT64 NewInteger)
EFI_STATUS EFIAPI AmlGetResourceDataType(IN AML_DATA_NODE *DataNode, OUT AML_RD_HEADER *ResourceDataType)
EFI_STATUS EFIAPI AmlGetNodeDataType(IN AML_DATA_NODE *DataNode, OUT EAML_NODE_DATA_TYPE *DataType)
UINT8 AML_RD_HEADER
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 AmlNodeSetIntegerValue(IN AML_OBJECT_NODE *Node, IN UINT64 NewValue, OUT INT8 *ValueWidthDiff)
Definition: AmlUtility.c:374
EFI_STATUS EFIAPI AmlPropagateInformation(IN AML_NODE_HEADER *Node, IN BOOLEAN IsIncrement, IN UINT32 Diff, IN UINT8 NodeCount)
Definition: AmlUtility.c:870
EFI_STATUS EFIAPI AmlComputeSize(IN CONST AML_NODE_HEADER *Node, IN OUT UINT32 *Size)
Definition: AmlUtility.c:169
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_STATUS EFIAPI AmlGetNameStringSize(IN CONST CHAR8 *AmlPath, OUT UINT32 *AmlPathSizePtr)
Definition: AmlString.c:547
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 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
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)
#define AML_RD_IS_LARGE(Header)
UINT32 EFIAPI AmlRdGetSize(IN CONST AML_RD_HEADER *Header)
AML_RD_HEADER EFIAPI AmlRdGetDescId(IN CONST AML_RD_HEADER *Header)
enum EAmlParseIndex EAML_PARSE_INDEX
#define AML_FIELD_NAMED_OP
Definition: AmlDefines.h:139
enum EAmlNodeType EAML_NODE_TYPE
enum EAmlNodeDataType EAML_NODE_DATA_TYPE
@ EAmlNodeUnknown
Unknown/Invalid AML Node Type.
Definition: AmlDefines.h:172
@ EAmlNodeDataTypeRaw
Raw bytes contained in a buffer.
Definition: AmlDefines.h:43
@ EAmlNodeDataTypeString
EAmlString, NULL terminated string.
Definition: AmlDefines.h:40
@ EAmlNodeDataTypeResourceData
Resource data element.
Definition: AmlDefines.h:44
@ EAmlNodeDataTypeMax
Max enum.
Definition: AmlDefines.h:50
@ EAmlNodeDataTypeUInt
Definition: AmlDefines.h:41
@ EAmlNodeDataTypeFieldPkgLen
Definition: AmlDefines.h:45
@ EAmlNodeDataTypeNameString
Definition: AmlDefines.h:37
AML_PARSE_FORMAT Format[EAmlParseIndexMax]
Type of each fixed argument.
Definition: Aml.h:142
CONST AML_BYTE_ENCODING * AmlByteEncoding