TianoCore EDK2 master
Loading...
Searching...
No Matches
AmlNode.c
Go to the documentation of this file.
1
9#include <Tree/AmlNode.h>
10
11#include <AmlCoreInterface.h>
12#include <Tree/AmlTree.h>
13
25EFIAPI
27 IN AML_NODE_HEADER *Node,
28 IN EAML_NODE_TYPE NodeType
29 )
30{
31 if (Node == NULL) {
32 ASSERT (0);
33 return EFI_INVALID_PARAMETER;
34 }
35
36 InitializeListHead (&Node->Link);
37
38 Node->Parent = NULL;
39 Node->NodeType = NodeType;
40
41 return EFI_SUCCESS;
42}
43
56EFIAPI
58 IN AML_ROOT_NODE *RootNode
59 )
60{
61 if (!IS_AML_ROOT_NODE (RootNode)) {
62 ASSERT (0);
63 return EFI_INVALID_PARAMETER;
64 }
65
66 if ((RootNode->SdtHeader != NULL)) {
67 FreePool (RootNode->SdtHeader);
68 } else {
69 ASSERT (0);
70 return EFI_INVALID_PARAMETER;
71 }
72
73 FreePool (RootNode);
74 return EFI_SUCCESS;
75}
76
91EFIAPI
94 OUT AML_ROOT_NODE **NewRootNodePtr
95 )
96{
97 EFI_STATUS Status;
98 AML_ROOT_NODE *RootNode;
99
100 if ((SdtHeader == NULL) ||
101 (NewRootNodePtr == NULL))
102 {
103 ASSERT (0);
104 return EFI_INVALID_PARAMETER;
105 }
106
107 *NewRootNodePtr = NULL;
108
109 RootNode = AllocateZeroPool (sizeof (AML_ROOT_NODE));
110 if (RootNode == NULL) {
111 ASSERT (0);
112 return EFI_OUT_OF_RESOURCES;
113 }
114
115 Status = AmlInitializeNodeHeader (&RootNode->NodeHeader, EAmlNodeRoot);
116 if (EFI_ERROR (Status)) {
117 FreePool (RootNode);
118 ASSERT (0);
119 return Status;
120 }
121
122 InitializeListHead (&RootNode->VariableArgs);
123
124 RootNode->SdtHeader = AllocateCopyPool (
126 SdtHeader
127 );
128 if (RootNode->SdtHeader == NULL) {
129 ASSERT (0);
130 AmlDeleteRootNode (RootNode);
131 return EFI_OUT_OF_RESOURCES;
132 }
133
134 *NewRootNodePtr = RootNode;
135
136 return EFI_SUCCESS;
137}
138
149STATIC
151EFIAPI
153 IN AML_OBJECT_NODE *ObjectNode
154 )
155{
156 if (!IS_AML_OBJECT_NODE (ObjectNode)) {
157 ASSERT (0);
158 return EFI_INVALID_PARAMETER;
159 }
160
161 FreePool (ObjectNode);
162 return EFI_SUCCESS;
163}
164
180EFIAPI
182 IN CONST AML_BYTE_ENCODING *AmlByteEncoding,
183 IN UINT32 PkgLength,
184 OUT AML_OBJECT_NODE **NewObjectNodePtr
185 )
186{
187 EFI_STATUS Status;
188 AML_OBJECT_NODE *ObjectNode;
189
190 if ((AmlByteEncoding == NULL) ||
191 (NewObjectNodePtr == NULL))
192 {
193 ASSERT (0);
194 return EFI_INVALID_PARAMETER;
195 }
196
197 *NewObjectNodePtr = NULL;
198
199 ObjectNode = AllocateZeroPool (sizeof (AML_OBJECT_NODE));
200 if (ObjectNode == NULL) {
201 ASSERT (0);
202 return EFI_OUT_OF_RESOURCES;
203 }
204
205 Status = AmlInitializeNodeHeader (&ObjectNode->NodeHeader, EAmlNodeObject);
206 if (EFI_ERROR (Status)) {
207 FreePool (ObjectNode);
208 ASSERT (0);
209 return Status;
210 }
211
212 InitializeListHead (&ObjectNode->VariableArgs);
213
214 // ObjectNode->FixedArgs[...] is already initialised to NULL as the
215 // ObjectNode is Zero allocated.
216 ObjectNode->AmlByteEncoding = AmlByteEncoding;
217 ObjectNode->PkgLen = PkgLength;
218
219 *NewObjectNodePtr = ObjectNode;
220
221 return EFI_SUCCESS;
222}
223
235STATIC
237EFIAPI
239 IN AML_DATA_NODE *DataNode
240 )
241{
242 if (!IS_AML_DATA_NODE (DataNode)) {
243 ASSERT (0);
244 return EFI_INVALID_PARAMETER;
245 }
246
247 if (DataNode->Buffer != NULL) {
248 FreePool (DataNode->Buffer);
249 } else {
250 ASSERT (0);
251 return EFI_INVALID_PARAMETER;
252 }
253
254 FreePool (DataNode);
255 return EFI_SUCCESS;
256}
257
274EFIAPI
276 IN EAML_NODE_DATA_TYPE DataType,
277 IN CONST UINT8 *Data,
278 IN UINT32 DataSize,
279 OUT AML_DATA_NODE **NewDataNodePtr
280 )
281{
282 EFI_STATUS Status;
283 AML_DATA_NODE *DataNode;
284
285 // A data node must not be created for certain data types.
286 if ((DataType == EAmlNodeDataTypeNone) ||
287 (DataType == EAmlNodeDataTypeReserved1) ||
288 (DataType == EAmlNodeDataTypeReserved2) ||
289 (DataType == EAmlNodeDataTypeReserved3) ||
290 (DataType == EAmlNodeDataTypeReserved4) ||
291 (DataType == EAmlNodeDataTypeReserved5) ||
292 (Data == NULL) ||
293 (DataSize == 0) ||
294 (NewDataNodePtr == NULL))
295 {
296 ASSERT (0);
297 return EFI_INVALID_PARAMETER;
298 }
299
300 *NewDataNodePtr = NULL;
301
302 DataNode = AllocateZeroPool (sizeof (AML_DATA_NODE));
303 if (DataNode == NULL) {
304 ASSERT (0);
305 return EFI_OUT_OF_RESOURCES;
306 }
307
308 Status = AmlInitializeNodeHeader (&DataNode->NodeHeader, EAmlNodeData);
309 if (EFI_ERROR (Status)) {
310 FreePool (DataNode);
311 ASSERT (0);
312 return Status;
313 }
314
315 DataNode->Buffer = AllocateCopyPool (DataSize, Data);
316 if (DataNode->Buffer == NULL) {
317 AmlDeleteDataNode (DataNode);
318 ASSERT (0);
319 return EFI_OUT_OF_RESOURCES;
320 }
321
322 DataNode->DataType = DataType;
323 DataNode->Size = DataSize;
324
325 *NewDataNodePtr = DataNode;
326
327 return EFI_SUCCESS;
328}
329
338EFIAPI
340 IN AML_NODE_HEADER *Node
341 )
342{
343 EFI_STATUS Status;
344 EAML_PARSE_INDEX Index;
345
346 // Check that the node being deleted is unlinked.
347 // When removing the node, its parent and list are reset
348 // with InitializeListHead. Thus it must be empty.
349 if (!IS_AML_NODE_VALID (Node) ||
350 !AML_NODE_IS_DETACHED (Node))
351 {
352 ASSERT (0);
353 return EFI_INVALID_PARAMETER;
354 }
355
356 switch (Node->NodeType) {
357 case EAmlNodeRoot:
358 {
359 // Check the variable list of arguments has been cleaned.
361 ASSERT (0);
362 return EFI_INVALID_PARAMETER;
363 }
364
365 Status = AmlDeleteRootNode ((AML_ROOT_NODE *)Node);
366 if (EFI_ERROR (Status)) {
367 ASSERT (0);
368 }
369
370 break;
371 }
372
373 case EAmlNodeObject:
374 {
375 // Check the variable list of arguments has been cleaned.
377 ASSERT (0);
378 return EFI_INVALID_PARAMETER;
379 }
380
381 // Check the fixed argument list has been cleaned.
382 for (Index = EAmlParseIndexTerm0; Index < EAmlParseIndexMax; Index++) {
383 if (((AML_OBJECT_NODE *)Node)->FixedArgs[Index] != NULL) {
384 ASSERT (0);
385 return EFI_INVALID_PARAMETER;
386 }
387 }
388
389 Status = AmlDeleteObjectNode ((AML_OBJECT_NODE *)Node);
390 if (EFI_ERROR (Status)) {
391 ASSERT (0);
392 }
393
394 break;
395 }
396
397 case EAmlNodeData:
398 {
399 Status = AmlDeleteDataNode ((AML_DATA_NODE *)Node);
400 if (EFI_ERROR (Status)) {
401 ASSERT (0);
402 }
403
404 break;
405 }
406
407 default:
408 {
409 ASSERT (0);
410 Status = EFI_INVALID_PARAMETER;
411 break;
412 }
413 } // switch
414
415 return Status;
416}
417
428BOOLEAN
429EFIAPI
431 IN CONST AML_OBJECT_NODE *ObjectNode,
432 IN AML_OP_ATTRIBUTE Attribute
433 )
434{
435 if (!IS_AML_OBJECT_NODE (ObjectNode) ||
436 (ObjectNode->AmlByteEncoding == NULL))
437 {
438 return FALSE;
439 }
440
441 return ((ObjectNode->AmlByteEncoding->Attribute &
442 Attribute) == 0 ? FALSE : TRUE);
443}
444
455BOOLEAN
456EFIAPI
458 IN CONST AML_OBJECT_NODE *ObjectNode,
459 IN UINT8 OpCode,
460 IN UINT8 SubOpCode
461 )
462{
463 if (!IS_AML_OBJECT_NODE (ObjectNode) ||
464 (ObjectNode->AmlByteEncoding == NULL))
465 {
466 return FALSE;
467 }
468
469 ASSERT (AmlIsOpCodeValid (OpCode, SubOpCode));
470
471 return ((ObjectNode->AmlByteEncoding->OpCode == OpCode) &&
472 (ObjectNode->AmlByteEncoding->SubOpCode == SubOpCode)) ?
473 TRUE : FALSE;
474}
475
489BOOLEAN
490EFIAPI
492 IN AML_OBJECT_NODE *Node
493 )
494{
495 UINT8 OpCode;
496
497 if (!IS_AML_OBJECT_NODE (Node) ||
498 (Node->AmlByteEncoding == NULL))
499 {
500 return FALSE;
501 }
502
503 // Check Node is an integer node.
504 OpCode = Node->AmlByteEncoding->OpCode;
505 if ((OpCode != AML_BYTE_PREFIX) &&
506 (OpCode != AML_WORD_PREFIX) &&
507 (OpCode != AML_DWORD_PREFIX) &&
508 (OpCode != AML_QWORD_PREFIX))
509 {
510 return FALSE;
511 }
512
513 return TRUE;
514}
515
526BOOLEAN
527EFIAPI
529 IN AML_OBJECT_NODE *Node
530 )
531{
532 UINT8 OpCode;
533
534 if (!IS_AML_OBJECT_NODE (Node) ||
535 (Node->AmlByteEncoding == NULL))
536 {
537 return FALSE;
538 }
539
540 OpCode = Node->AmlByteEncoding->OpCode;
541
542 if ((OpCode != AML_ZERO_OP) &&
543 (OpCode != AML_ONE_OP) &&
544 (OpCode != AML_ONES_OP))
545 {
546 return FALSE;
547 }
548
549 return TRUE;
550}
551
568BOOLEAN
569EFIAPI
572 )
573{
574 AML_DATA_NODE *ObjectType;
575
576 // Node is checked to be an object node as well.
577 if (AmlNodeCompareOpCode (Node, AML_METHOD_OP, 0)) {
578 return TRUE;
579 } else if (AmlNodeCompareOpCode (Node, AML_EXTERNAL_OP, 0)) {
580 // If the node is an external definition, check this is a method.
581 // DefExternal := ExternalOp NameString ObjectType ArgumentCount
582 // ExternalOp := 0x15
583 // ObjectType := ByteData
584 // ArgumentCount := ByteData (0 - 7)
585 ObjectType = (AML_DATA_NODE *)AmlGetFixedArgument (
586 (AML_OBJECT_NODE *)Node,
588 );
589 if (IS_AML_DATA_NODE (ObjectType) &&
590 (ObjectType->DataType == EAmlNodeDataTypeUInt) &&
591 ((ObjectType->Size == 1)))
592 {
593 if (*((UINT8 *)ObjectType->Buffer) == (UINT8)EAmlObjTypeMethodObj) {
594 // The external definition is a method.
595 return TRUE;
596 } else {
597 // The external definition is not a method.
598 return FALSE;
599 }
600 } else {
601 // The tree is inconsistent.
602 ASSERT (0);
603 return FALSE;
604 }
605 }
606
607 // This is not a method definition.
608 return FALSE;
609}
610
622 IN CONST AML_OBJECT_NODE *ObjectNode,
623 OUT EAML_PARSE_INDEX *Index
624 )
625{
626 EAML_PARSE_INDEX NameIndex;
627
628 if (!AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE) ||
629 (ObjectNode->AmlByteEncoding == NULL) ||
630 (Index == NULL))
631 {
632 ASSERT (0);
633 return EFI_INVALID_PARAMETER;
634 }
635
636 NameIndex = ObjectNode->AmlByteEncoding->NameIndex;
637
638 if ((NameIndex > ObjectNode->AmlByteEncoding->MaxIndex) ||
639 (ObjectNode->AmlByteEncoding->Format[NameIndex] != EAmlName))
640 {
641 ASSERT (0);
642 return EFI_INVALID_PARAMETER;
643 }
644
645 *Index = NameIndex;
646
647 return EFI_SUCCESS;
648}
649
661CHAR8 *
662EFIAPI
664 IN CONST AML_OBJECT_NODE *ObjectNode
665 )
666{
667 EFI_STATUS Status;
668 EAML_PARSE_INDEX NameIndex;
669 AML_DATA_NODE *DataNode;
670
671 if (!AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE)) {
672 ASSERT (0);
673 return NULL;
674 }
675
676 // Get the index at which the name is stored in the fixed arguments list.
677 Status = AmlNodeGetNameIndex (ObjectNode, &NameIndex);
678 if (EFI_ERROR (Status)) {
679 ASSERT (0);
680 return NULL;
681 }
682
683 // The name is stored in a Data node.
684 DataNode = (AML_DATA_NODE *)ObjectNode->FixedArgs[NameIndex];
685 if (IS_AML_DATA_NODE (DataNode) &&
687 {
688 return (CHAR8 *)DataNode->Buffer;
689 }
690
691 /* Return NULL if no name is found.
692 This can occur if the name of a node is defined as a further
693 fixed argument.
694 E.g.: CreateField (BD03, 0x28, Add (ID03 + 0x08), BF33)
695 ^
696 The parser is here.
697 The parent of the Add statement is the CreateField statement. This
698 statement defines a name in the AML namespace. This name defined as
699 the fourth fixed argument. It hasn't been parsed yet.
700 */
701 return NULL;
702}
#define AML_IN_NAMESPACE
Definition: Aml.h:98
UINT32 AML_OP_ATTRIBUTE
Definition: Aml.h:59
@ EAmlName
Definition: Aml.h:44
BOOLEAN EFIAPI IsIntegerNode(IN AML_OBJECT_NODE *Node)
Definition: AmlNode.c:491
BOOLEAN EFIAPI AmlIsMethodDefinitionNode(IN CONST AML_OBJECT_NODE *Node)
Definition: AmlNode.c:570
BOOLEAN EFIAPI AmlNodeCompareOpCode(IN CONST AML_OBJECT_NODE *ObjectNode, IN UINT8 OpCode, IN UINT8 SubOpCode)
Definition: AmlNode.c:457
EFI_STATUS EFIAPI AmlCreateObjectNode(IN CONST AML_BYTE_ENCODING *AmlByteEncoding, IN UINT32 PkgLength, OUT AML_OBJECT_NODE **NewObjectNodePtr)
Definition: AmlNode.c:181
EFI_STATUS EFIAPI AmlDeleteNode(IN AML_NODE_HEADER *Node)
Definition: AmlNode.c:339
STATIC EFI_STATUS EFIAPI AmlDeleteRootNode(IN AML_ROOT_NODE *RootNode)
Definition: AmlNode.c:57
BOOLEAN EFIAPI AmlNodeHasAttribute(IN CONST AML_OBJECT_NODE *ObjectNode, IN AML_OP_ATTRIBUTE Attribute)
Definition: AmlNode.c:430
CHAR8 *EFIAPI AmlNodeGetName(IN CONST AML_OBJECT_NODE *ObjectNode)
Definition: AmlNode.c:663
STATIC EFI_STATUS EFIAPI AmlDeleteObjectNode(IN AML_OBJECT_NODE *ObjectNode)
Definition: AmlNode.c:152
STATIC EFI_STATUS EFIAPI AmlDeleteDataNode(IN AML_DATA_NODE *DataNode)
Definition: AmlNode.c:238
EFI_STATUS EFIAPI AmlCreateRootNode(IN CONST EFI_ACPI_DESCRIPTION_HEADER *SdtHeader, OUT AML_ROOT_NODE **NewRootNodePtr)
Definition: AmlNode.c:92
STATIC EFI_STATUS EFIAPI AmlInitializeNodeHeader(IN AML_NODE_HEADER *Node, IN EAML_NODE_TYPE NodeType)
Definition: AmlNode.c:26
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
EFI_STATUS AmlNodeGetNameIndex(IN CONST AML_OBJECT_NODE *ObjectNode, OUT EAML_PARSE_INDEX *Index)
Definition: AmlNode.c:621
#define IS_AML_ROOT_NODE(Node)
#define IS_AML_OBJECT_NODE(Node)
#define IS_AML_DATA_NODE(Node)
#define IS_AML_NODE_VALID(Node)
#define AML_NODE_IS_DETACHED(Node)
LIST_ENTRY *EFIAPI AmlNodeGetVariableArgList(IN CONST AML_NODE_HEADER *Node)
Definition: AmlTree.c:205
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
BOOLEAN EFIAPI AmlIsOpCodeValid(IN UINT8 OpCode, IN UINT8 SubOpCode)
Definition: Aml.c:543
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST 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 OUT
Definition: Base.h:284
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
AML_NODE_HANDLE EFIAPI AmlGetFixedArgument(IN AML_OBJECT_NODE_HANDLE ObjectNode, IN EAML_PARSE_INDEX Index)
enum EAmlParseIndex EAML_PARSE_INDEX
enum EAmlNodeType EAML_NODE_TYPE
enum EAmlNodeDataType EAML_NODE_DATA_TYPE
@ EAmlParseIndexMax
Maximum fixed argument index (=6).
Definition: AmlDefines.h:71
@ EAmlParseIndexTerm1
Second fixed argument index.
Definition: AmlDefines.h:66
@ EAmlParseIndexTerm0
First fixed argument index.
Definition: AmlDefines.h:65
@ EAmlNodeData
Definition: AmlDefines.h:176
@ EAmlNodeRoot
AML Root Node, typically represents a DefinitionBlock.
Definition: AmlDefines.h:173
@ EAmlNodeObject
Definition: AmlDefines.h:174
@ EAmlNodeDataTypeReserved4
EAmlUInt64, converted to the UInt type.
Definition: AmlDefines.h:35
@ EAmlNodeDataTypeReserved1
EAmlUInt8, converted to the UInt type.
Definition: AmlDefines.h:32
@ EAmlNodeDataTypeNone
EAmlNone, not accessible.
Definition: AmlDefines.h:31
@ EAmlNodeDataTypeReserved5
EAmlObject, not accessible.
Definition: AmlDefines.h:36
@ EAmlNodeDataTypeReserved3
EAmlUInt32, converted to the UInt type.
Definition: AmlDefines.h:34
@ EAmlNodeDataTypeReserved2
EAmlUInt16, converted to the UInt type.
Definition: AmlDefines.h:33
@ EAmlNodeDataTypeUInt
Definition: AmlDefines.h:41
@ EAmlNodeDataTypeNameString
Definition: AmlDefines.h:37
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.
LIST_ENTRY VariableArgs
CONST AML_BYTE_ENCODING * AmlByteEncoding
AML_NODE_HEADER NodeHeader
Header information. Must be the first field of the struct.
AML_NODE_HEADER NodeHeader
Header information. Must be the first field of the struct.
LIST_ENTRY VariableArgs
EFI_ACPI_DESCRIPTION_HEADER * SdtHeader
ACPI DSDT/SSDT header.