mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-25 14:44:28 +02:00
DynamicTablesPkg: AML tree/node cloning
It is often desirable to clone an AML branch/tree or an AML node. An example of could be to clone an AML template before fixup so that the original AML template remains unmodified. Another example would be replicating a device branch in the AML tree and fixing up the device information. To facilitate such scenarios the AmlLib library provides functions that can be used to clone an AML branch/tree or an AML node. Signed-off-by: Pierre Gondois <pierre.gondois@arm.com> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com> Reviewed-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
This commit is contained in:
parent
e2c1104c50
commit
0414377c02
205
DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlClone.c
Normal file
205
DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlClone.c
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/** @file
|
||||||
|
AML Clone.
|
||||||
|
|
||||||
|
Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <AmlNodeDefines.h>
|
||||||
|
|
||||||
|
#include <AmlCoreInterface.h>
|
||||||
|
#include <Tree/AmlNode.h>
|
||||||
|
#include <Tree/AmlTree.h>
|
||||||
|
|
||||||
|
/** Clone a node.
|
||||||
|
|
||||||
|
This function does not clone the children nodes.
|
||||||
|
The cloned node returned is not attached to any tree.
|
||||||
|
|
||||||
|
@param [in] Node Pointer to a node.
|
||||||
|
@param [out] ClonedNode Pointer holding the cloned node.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The function completed successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Could not allocate memory.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
AmlCloneNode (
|
||||||
|
IN AML_NODE_HEADER * Node,
|
||||||
|
OUT AML_NODE_HEADER ** ClonedNode
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
AML_OBJECT_NODE * ObjectNode;
|
||||||
|
AML_DATA_NODE * DataNode;
|
||||||
|
AML_ROOT_NODE * RootNode;
|
||||||
|
|
||||||
|
if (!IS_AML_NODE_VALID (Node) ||
|
||||||
|
(ClonedNode == NULL)) {
|
||||||
|
ASSERT (0);
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ClonedNode = NULL;
|
||||||
|
|
||||||
|
if (IS_AML_DATA_NODE (Node)) {
|
||||||
|
DataNode = (AML_DATA_NODE*)Node;
|
||||||
|
Status = AmlCreateDataNode (
|
||||||
|
DataNode->DataType,
|
||||||
|
DataNode->Buffer,
|
||||||
|
DataNode->Size,
|
||||||
|
(AML_DATA_NODE**)ClonedNode
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
ASSERT (0);
|
||||||
|
}
|
||||||
|
} else if (IS_AML_OBJECT_NODE (Node)) {
|
||||||
|
ObjectNode = (AML_OBJECT_NODE*)Node;
|
||||||
|
|
||||||
|
Status = AmlCreateObjectNode (
|
||||||
|
ObjectNode->AmlByteEncoding,
|
||||||
|
ObjectNode->PkgLen,
|
||||||
|
(AML_OBJECT_NODE**)ClonedNode
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
ASSERT (0);
|
||||||
|
}
|
||||||
|
} else if (IS_AML_ROOT_NODE (Node)) {
|
||||||
|
RootNode = (AML_ROOT_NODE*)Node;
|
||||||
|
|
||||||
|
Status = AmlCreateRootNode (
|
||||||
|
RootNode->SdtHeader,
|
||||||
|
(AML_ROOT_NODE**)ClonedNode
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
ASSERT (0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ASSERT (0);
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Clone a node and its children (clone a tree branch).
|
||||||
|
|
||||||
|
The cloned branch returned is not attached to any tree.
|
||||||
|
|
||||||
|
@param [in] Node Pointer to a node.
|
||||||
|
Node is the head of the branch to clone.
|
||||||
|
@param [out] ClonedNode Pointer holding the head of the created cloned
|
||||||
|
branch.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The function completed successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Could not allocate memory.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
AmlCloneTree (
|
||||||
|
IN AML_NODE_HEADER * Node,
|
||||||
|
OUT AML_NODE_HEADER ** ClonedNode
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
AML_NODE_HEADER * HeadNode;
|
||||||
|
AML_NODE_HEADER * ClonedChildNode;
|
||||||
|
AML_NODE_HEADER * FixedArgNode;
|
||||||
|
|
||||||
|
EAML_PARSE_INDEX Index;
|
||||||
|
EAML_PARSE_INDEX MaxIndex;
|
||||||
|
|
||||||
|
LIST_ENTRY * StartLink;
|
||||||
|
LIST_ENTRY * CurrentLink;
|
||||||
|
|
||||||
|
if (!IS_AML_NODE_VALID (Node) ||
|
||||||
|
(ClonedNode == NULL)) {
|
||||||
|
ASSERT (0);
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = AmlCloneNode (Node, &HeadNode);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
ASSERT (0);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone the fixed arguments and bind them to their parent.
|
||||||
|
MaxIndex = (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (
|
||||||
|
(AML_OBJECT_NODE*)Node
|
||||||
|
);
|
||||||
|
for (Index = EAmlParseIndexTerm0; Index < MaxIndex; Index++) {
|
||||||
|
FixedArgNode = AmlGetFixedArgument ((AML_OBJECT_NODE*)Node, Index);
|
||||||
|
if (FixedArgNode == NULL) {
|
||||||
|
Status = EFI_INVALID_PARAMETER;
|
||||||
|
ASSERT (0);
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone child.
|
||||||
|
Status = AmlCloneTree (
|
||||||
|
FixedArgNode,
|
||||||
|
&ClonedChildNode
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
ASSERT (0);
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind child.
|
||||||
|
Status = AmlSetFixedArgument (
|
||||||
|
(AML_OBJECT_NODE*)HeadNode,
|
||||||
|
Index,
|
||||||
|
ClonedChildNode
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
AmlDeleteTree (ClonedChildNode);
|
||||||
|
ASSERT (0);
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
} // for
|
||||||
|
|
||||||
|
// Clone the variable arguments and bind them to their parent.
|
||||||
|
StartLink = AmlNodeGetVariableArgList (Node);
|
||||||
|
if (StartLink != NULL) {
|
||||||
|
CurrentLink = StartLink->ForwardLink;
|
||||||
|
while (CurrentLink != StartLink) {
|
||||||
|
// Clone child.
|
||||||
|
Status = AmlCloneTree ((AML_NODE_HEADER*)CurrentLink, &ClonedChildNode);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
ASSERT (0);
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind child.
|
||||||
|
Status = AmlVarListAddTailInternal (
|
||||||
|
HeadNode,
|
||||||
|
ClonedChildNode
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
AmlDeleteTree (ClonedChildNode);
|
||||||
|
ASSERT (0);
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentLink = CurrentLink->ForwardLink;
|
||||||
|
} // while
|
||||||
|
}
|
||||||
|
|
||||||
|
*ClonedNode = HeadNode;
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
error_handler:
|
||||||
|
*ClonedNode = NULL;
|
||||||
|
|
||||||
|
if (HeadNode != NULL) {
|
||||||
|
AmlDeleteTree (HeadNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user