From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../Library/Common/AmlLib/Parser/AmlMethodParser.c | 1458 ++++++++++++++++++++ 1 file changed, 1458 insertions(+) create mode 100644 src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.c (limited to 'src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.c') diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.c new file mode 100644 index 00000000..28fe51b2 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.c @@ -0,0 +1,1458 @@ +/** @file + AML Method Parser. + + Copyright (c) 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +/** Delete a namespace reference node and its pathname. + + It is the caller's responsibility to check the NameSpaceRefNode has been + removed from any list the node is part of. + + @param [in] NameSpaceRefNode Pointer to an AML_NAMESPACE_REF_NODE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlDeleteNameSpaceRefNode ( + IN AML_NAMESPACE_REF_NODE * NameSpaceRefNode + ) +{ + if (NameSpaceRefNode == NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (NameSpaceRefNode->RawAbsolutePath != NULL) { + FreePool ((CHAR8*)NameSpaceRefNode->RawAbsolutePath); + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + FreePool (NameSpaceRefNode); + return EFI_SUCCESS; +} + +/** Delete a list of namespace reference nodes. + + @param [in] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDeleteNameSpaceRefList ( + IN LIST_ENTRY * NameSpaceRefList + ) +{ + EFI_STATUS Status; + LIST_ENTRY * CurrentLink; + + if (NameSpaceRefList == NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + while (!IsListEmpty (NameSpaceRefList)) { + CurrentLink = NameSpaceRefList->ForwardLink; + RemoveEntryList (CurrentLink); + Status = AmlDeleteNameSpaceRefNode ( + (AML_NAMESPACE_REF_NODE*)CurrentLink + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } // while + + return EFI_SUCCESS; +} + +/** Create an AML_NAMESPACE_REF_NODE. + + A Buffer is allocated to store the raw AML absolute path. + + @param [in] ObjectNode Node being part of the namespace. + Must be have the AML_IN_NAMESPACE + attribute. + @param [in] RawAbsolutePath AML raw absolute path of the ObjectNode. + A raw NameString is a concatenated list + of 4 chars long names. + @param [in] RawAbsolutePathSize Size of the RawAbsolutePath buffer. + @param [out] NameSpaceRefNodePtr The created AML_METHOD_REF_NODE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlCreateMethodRefNode ( + IN CONST AML_OBJECT_NODE * ObjectNode, + IN CONST CHAR8 * RawAbsolutePath, + IN UINT32 RawAbsolutePathSize, + OUT AML_NAMESPACE_REF_NODE ** NameSpaceRefNodePtr + ) +{ + AML_NAMESPACE_REF_NODE * NameSpaceRefNode; + + if (!AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE) || + (RawAbsolutePath == NULL) || + (RawAbsolutePathSize == 0) || + (NameSpaceRefNodePtr == NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + NameSpaceRefNode = AllocateZeroPool (sizeof (AML_NAMESPACE_REF_NODE)); + if (NameSpaceRefNode == NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + NameSpaceRefNode->RawAbsolutePathSize = RawAbsolutePathSize; + NameSpaceRefNode->RawAbsolutePath = AllocateCopyPool ( + RawAbsolutePathSize, + RawAbsolutePath + ); + if (NameSpaceRefNode->RawAbsolutePath == NULL) { + FreePool (NameSpaceRefNode); + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + InitializeListHead (&NameSpaceRefNode->Link); + + NameSpaceRefNode->NodeRef = ObjectNode; + *NameSpaceRefNodePtr = NameSpaceRefNode; + + return EFI_SUCCESS; +} + +#if !defined (MDEPKG_NDEBUG) + +/** Print the list of raw absolute paths of the NameSpace reference list. + + @param [in] NameSpaceRefList List of NameSpace reference nodes. +**/ +VOID +EFIAPI +AmlDbgPrintNameSpaceRefList ( + IN CONST LIST_ENTRY * NameSpaceRefList + ) +{ + LIST_ENTRY * CurrLink; + AML_NAMESPACE_REF_NODE * CurrNameSpaceNode; + + if (NameSpaceRefList == NULL) { + ASSERT (0); + return; + } + + DEBUG ((DEBUG_INFO, "AmlMethodParser: List of available raw AML paths:\n")); + + CurrLink = NameSpaceRefList->ForwardLink; + while (CurrLink != NameSpaceRefList) { + CurrNameSpaceNode = (AML_NAMESPACE_REF_NODE*)CurrLink; + + AMLDBG_PRINT_CHARS ( + DEBUG_INFO, + CurrNameSpaceNode->RawAbsolutePath, + CurrNameSpaceNode->RawAbsolutePathSize + ); + DEBUG ((DEBUG_INFO, "\n")); + + CurrLink = CurrLink->ForwardLink; + } + + DEBUG ((DEBUG_INFO, "\n")); +} + +#endif // MDEPKG_NDEBUG + +/** From a forward stream pointing to a NameString, + initialize a raw backward stream. + + StartOfStream + Fstream: CurrPos EndOfStream + v v + +-----------------------------------------+ + |^^^[Multi-name prefix]AAAA.BBBB.CCCC | + +-----------------------------------------+ + ^ ^ + RawPathNameBStream: EndOfStream CurrPos + StartOfStream + + No memory is allocated when initializing the stream. + + @param [in] FStream Forward stream pointing to a NameString. + The stream must not be at its end. + @param [out] RawPathNameBStream Backward stream containing the + raw AML path. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlInitRawPathBStream ( + IN CONST AML_STREAM * FStream, + OUT AML_STREAM * RawPathNameBStream + ) +{ + EFI_STATUS Status; + + UINT8 * RawPathBuffer; + CONST CHAR8 * Buffer; + + UINT32 Root; + UINT32 ParentPrefix; + UINT32 SegCount; + + if (!IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (RawPathNameBStream == NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Buffer = (CONST CHAR8*)AmlStreamGetCurrPos (FStream); + if (Buffer == NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Parse the NameString information. + Status = AmlParseNameStringInfo ( + Buffer, + &Root, + &ParentPrefix, + &SegCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Get the beginning of the raw NameString. + RawPathBuffer = (UINT8*)AmlGetFirstNameSeg ( + Buffer, + Root, + ParentPrefix + ); + if (RawPathBuffer == NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Initialize a backward stream containing the raw path. + Status = AmlStreamInit ( + RawPathNameBStream, + RawPathBuffer, + (SegCount * AML_NAME_SEG_SIZE), + EAmlStreamDirectionBackward + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Get the first node in the ParentNode branch that is part of the + AML namespace and has its name defined. + + This is different from getting the first namespace node. This function is + necessary because an absolute path is built while the tree is not complete + yet. The parsing is ongoing. + + For instance, the ASL statement "CreateXXXField ()" adds a field in the + AML namespace, but the name it defines is the last fixed argument of the + corresponding object. + If an AML path is referenced in its first fixed argument, it is not + possible to resolve the name of the CreateXXXField object. However, the AML + path is not part of the scope created by the CreateXXXField object, so this + scope can be skipped. + + In the following ASL code, the method invocation to MET0 is done in the + "CreateField" statement. The "CreateField" statement defines the "FIEL" + path in the AML namespace. However, MET0 must be not be resolved in the + "CreateField" object scope. It needs to be resolved in its parent. + ASL code: + Method (MET0, 0,,, BuffObj) { + Return (Buffer (0x1000) {}) + } + CreateField (MET0(), 0x100, 0x4, FIEL) + + @param [in] Node Node to get the first named node from, in + its hierarchy. + @param [out] OutNamedNode First named node in Node's hierarchy. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlGetFirstNamedAncestorNode ( + IN CONST AML_NODE_HEADER * Node, + OUT AML_NODE_HEADER ** OutNamedNode + ) +{ + EFI_STATUS Status; + CONST AML_NODE_HEADER * NameSpaceNode; + + if ((!IS_AML_OBJECT_NODE (Node) && + !IS_AML_ROOT_NODE (Node)) || + (OutNamedNode == NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // If Node is not the root node and doesn't have a name defined yet, + // get the ancestor NameSpace node. + while (!IS_AML_ROOT_NODE (Node) && + !(AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)Node, + AML_IN_NAMESPACE) && + AmlNodeGetName ((CONST AML_OBJECT_NODE*)Node) != NULL)) { + Status = AmlGetFirstAncestorNameSpaceNode ( + Node, + (AML_NODE_HEADER**)&NameSpaceNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + // The NameSpaceNode may not have its name defined as yet. In this + // case get the next ancestor node. + Node = NameSpaceNode; + } + + *OutNamedNode = (AML_NODE_HEADER*)Node; + + return EFI_SUCCESS; +} + +/** From a ParentNode and a forward stream pointing to a relative path, + build a raw AML absolute path and return it in a backward stream. + + No memory is allocated in this function, the out stream must be initialized + with a buffer long enough to hold any raw absolute AML path. + + @param [in] ParentNode Parent node of the namespace + node from which the absolute + path is built. ParentNode isn't + necessarily a namespace node. + Must be a root or an object node. + @param [in] PathnameFStream Forward stream pointing to the + beginning of a pathname (any + NameString). + The stream must not be at its end. + @param [in, out] AbsolutePathBStream Backward stream where the raw + absolute path is written. The + stream must be already initialized. + The stream must not be at its end. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlBuildRawMethodAbsolutePath ( + IN CONST AML_NODE_HEADER * ParentNode, + IN CONST AML_STREAM * PathnameFStream, + IN OUT AML_STREAM * AbsolutePathBStream + ) +{ + EFI_STATUS Status; + + AML_NODE_HEADER * NamedParentNode; + UINT8 * RawPathBuffer; + CONST CHAR8 * CurrPos; + + UINT32 Root; + UINT32 ParentPrefix; + UINT32 SegCount; + + if ((!IS_AML_OBJECT_NODE (ParentNode) && + !IS_AML_ROOT_NODE (ParentNode)) || + !IS_STREAM (PathnameFStream) || + IS_END_OF_STREAM (PathnameFStream) || + !IS_STREAM_FORWARD (PathnameFStream) || + !IS_STREAM (AbsolutePathBStream) || + IS_END_OF_STREAM (AbsolutePathBStream) || + !IS_STREAM_BACKWARD (AbsolutePathBStream)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + CurrPos = (CONST CHAR8*)AmlStreamGetCurrPos (PathnameFStream); + if (CurrPos == NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Parse the NameString information. + Status = AmlParseNameStringInfo ( + CurrPos, + &Root, + &ParentPrefix, + &SegCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Copy the method invocation raw relative path at the end of the Stream. + if (SegCount != 0) { + // Get the beginning of the raw NameString. + RawPathBuffer = (UINT8*)AmlGetFirstNameSeg ( + CurrPos, + Root, + ParentPrefix + ); + + Status = AmlStreamWrite ( + AbsolutePathBStream, + RawPathBuffer, + SegCount * AML_NAME_SEG_SIZE + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + // If the pathname contained an absolute path, this is finished, return. + if (Root) { + return Status; + } + + // Get the first named node of the parent node in its hierarchy. + Status = AmlGetFirstNamedAncestorNode (ParentNode, &NamedParentNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Build the raw absolute path of the namespace node. + Status = AmlGetRawNameSpacePath ( + NamedParentNode, + ParentPrefix, + AbsolutePathBStream + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Compare two raw NameStrings stored in forward streams. + Compare them NameSeg by NameSeg (a NameSeg is 4 bytes long). + + The two raw NameStrings can be of different size. + + @param [in] RawFStream1 First forward stream to compare. + Points to the beginning of the raw NameString. + @param [in] RawFStream2 Second forward stream to compare. + Points to the beginning of the raw NameString. + @param [out] CompareCount Count of identic bytes. + Must be a multiple of 4 (size of a NameSeg). + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlCompareRawNameString ( + IN CONST AML_STREAM * RawFStream1, + IN CONST AML_STREAM * RawFStream2, + OUT UINT32 * CompareCount + ) +{ + EFI_STATUS Status; + UINT32 Index; + + AML_STREAM RawFStream1Clone; + AML_STREAM RawFStream2Clone; + UINT32 Stream1Size; + UINT32 Stream2Size; + UINT32 CompareLen; + + // Raw NameStrings have a size that is a multiple of the size of NameSegs. + if (!IS_STREAM (RawFStream1) || + IS_END_OF_STREAM (RawFStream1) || + !IS_STREAM_FORWARD (RawFStream1) || + !IS_STREAM (RawFStream2) || + IS_END_OF_STREAM (RawFStream2) || + (CompareCount == NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Stream1Size = AmlStreamGetFreeSpace (RawFStream1); + if ((Stream1Size & (AML_NAME_SEG_SIZE - 1)) != 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Stream2Size = AmlStreamGetFreeSpace (RawFStream2); + if ((Stream2Size & (AML_NAME_SEG_SIZE - 1)) != 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status = AmlStreamClone (RawFStream1, &RawFStream1Clone); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlStreamClone (RawFStream2, &RawFStream2Clone); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + CompareLen = MIN (Stream1Size, Stream2Size); + Index = 0; + // Check there is enough space for a NameSeg in both Stream1 and Stream2. + while (Index < CompareLen) { + if (!AmlStreamCmp ( + &RawFStream1Clone, + &RawFStream2Clone, + AML_NAME_SEG_SIZE) + ) { + // NameSegs are different. Break. + break; + } + + Status = AmlStreamProgress (&RawFStream1Clone, AML_NAME_SEG_SIZE); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + Status = AmlStreamProgress (&RawFStream2Clone, AML_NAME_SEG_SIZE); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Index += AML_NAME_SEG_SIZE; + } + + *CompareCount = Index; + + return EFI_SUCCESS; +} + +/** Check whether an alias can be resolved to a method definition. + + Indeed, the following ASL code must be handled: + Method (MET0, 1) { + Return (0x9) + } + Alias (\MET0, \ALI0) + Alias (\ALI0, \ALI1) + \ALI1(0x5) + When searching for \ALI1 in the AML NameSpace, it resolves to \ALI0. + When searching for \ALI0 in the AML NameSpace, it resolves to \MET0. + When searching for \MET0 in the AML NameSpace, it resolves to a method + definition. + + This method is a wrapper to recursively call AmlFindMethodDefinition. + + @param [in] AliasNode Pointer to an Alias object node. + @param [in] NameSpaceRefList List of NameSpaceRef nodes. + @param [out] OutNameSpaceRefNode If success, and if the alias is resolved + to a method definition (this can go + through other alias indirections), + containing the corresponding + NameSpaceRef node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlResolveAliasMethod ( + IN CONST AML_OBJECT_NODE * AliasNode, + IN CONST LIST_ENTRY * NameSpaceRefList, + OUT AML_NAMESPACE_REF_NODE ** OutNameSpaceRefNode + ) +{ + EFI_STATUS Status; + AML_STREAM SourceAliasFStream; + CONST AML_DATA_NODE * DataNode; + + if (!AmlNodeCompareOpCode (AliasNode, AML_ALIAS_OP, 0) || + (NameSpaceRefList == NULL) || + (OutNameSpaceRefNode == NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // The aliased NameString (the source name) is the first fixed argument, + // cf. ACPI6.3 spec, s19.6.4: Alias (SourceObject, AliasObject) + DataNode = (CONST AML_DATA_NODE*)AmlGetFixedArgument ( + (AML_OBJECT_NODE*)AliasNode, + EAmlParseIndexTerm0 + ); + if (DataNode == NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Initialize a stream on the source alias NameString. + Status = AmlStreamInit ( + &SourceAliasFStream, + DataNode->Buffer, + DataNode->Size, + EAmlStreamDirectionForward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Recursively check whether the source alias NameString + // is a method invocation. + Status = AmlIsMethodInvocation ( + AmlGetParent ((AML_NODE_HEADER*)AliasNode), + &SourceAliasFStream, + NameSpaceRefList, + OutNameSpaceRefNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + + return Status; +} + +/** Iterate through the MethodList to find the best namespace resolution. + If the pathname resolves to a method definition, returns it. + + For instance, if the AML namespace is: + \ + \-MET0 <- Device definition, absolute path: \MET0 + \-AAAA + \-MET0 <- Method definition, absolute path: \AAAA.MET0 + \-MET1 <- Method definition, absolute path: \AAAA.MET1 + \-BBBB + \-CCCC + \-DDDD + \-MET0 <- Method definition, absolute path: \AAAA.BBBB.CCCC.DDDD.MET0 + + The list of the available pathnames is: + [NameSpaceRefList] + - \MET0 <- Device definition + - \AAAA + - \AAAA.MET0 <- Method definition + - \AAAA.MET1 <- Method definition + - \AAAA.BBBB + - \AAAA.BBBB.CCCC + - \AAAA.BBBB.CCCC.DDDD + - \AAAA.BBBB.CCCC.DDDD.MET0 <- Method definition + + Depending on where the method invocation is done, the method definition + referenced changes. If the method call "MET0" is done from + \AAAA.BBBB.CCCC: + 1. Identify which pathnames end with "MET0": + - \MET0 <- Device definition + - \AAAA.MET0 <- Method definition + - \AAAA.BBBB.CCCC.DDDD.MET0 <- Method definition + 2. Resolve the method invocation: + - \AAAA.MET0 <- Method definition + 3. \AAAA.MET0 is a method definition, so return the corresponding + reference node. + + @param [in] RawAbsolutePathFStream Forward stream pointing to a raw + absolute path. + The stream must not be at its end. + @param [in] RawPathNameBStream Backward stream pointing to a raw + pathname. This raw pathname is the + raw NameString of namespace node. + The stream must not be at its end. + @param [in] NameSpaceRefList List of NameSpaceRef nodes. + @param [out] OutNameSpaceRefNode If the two input paths are + referencing a method definition, + returns the corresponding + NameSpaceRef node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlFindMethodDefinition ( + IN CONST AML_STREAM * RawAbsolutePathFStream, + IN CONST AML_STREAM * RawPathNameBStream, + IN CONST LIST_ENTRY * NameSpaceRefList, + OUT AML_NAMESPACE_REF_NODE ** OutNameSpaceRefNode + ) +{ + EFI_STATUS Status; + + LIST_ENTRY * NextLink; + + // To resolve a pathname, scope levels need to be compared. + UINT32 NameSegScopeCount; + UINT32 PathNameSegScopeCount; + UINT32 ProbedScopeCount; + UINT32 BestScopeCount; + + AML_STREAM ProbedRawAbsoluteFStream; + AML_STREAM ProbedRawAbsoluteBStream; + + AML_NAMESPACE_REF_NODE * ProbedNameSpaceRefNode; + AML_NAMESPACE_REF_NODE * BestNameSpaceRefNode; + + if (!IS_STREAM (RawAbsolutePathFStream) || + IS_END_OF_STREAM (RawAbsolutePathFStream) || + !IS_STREAM_FORWARD (RawAbsolutePathFStream) || + ((AmlStreamGetIndex (RawAbsolutePathFStream) & + (AML_NAME_SEG_SIZE - 1)) != 0) || + !IS_STREAM (RawPathNameBStream) || + IS_END_OF_STREAM (RawPathNameBStream) || + !IS_STREAM_BACKWARD (RawPathNameBStream) || + ((AmlStreamGetIndex (RawPathNameBStream) & + (AML_NAME_SEG_SIZE - 1)) != 0) || + (NameSpaceRefList == NULL) || + (OutNameSpaceRefNode == NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + DEBUG ((DEBUG_VERBOSE, "AmlMethodParser: Checking absolute name: ")); + AMLDBG_PRINT_CHARS ( + DEBUG_VERBOSE, + (CONST CHAR8*)AmlStreamGetCurrPos (RawAbsolutePathFStream), + AmlStreamGetMaxBufferSize (RawAbsolutePathFStream) + ); + DEBUG ((DEBUG_VERBOSE, ".\n")); + + BestNameSpaceRefNode = NULL; + BestScopeCount = 0; + NameSegScopeCount = AmlStreamGetMaxBufferSize (RawAbsolutePathFStream); + PathNameSegScopeCount = AmlStreamGetMaxBufferSize (RawPathNameBStream); + + // Iterate through the raw AML absolute path to find the best match. + DEBUG ((DEBUG_VERBOSE, "AmlMethodParser: Comparing with: ")); + NextLink = NameSpaceRefList->ForwardLink; + while (NextLink != NameSpaceRefList) { + ProbedNameSpaceRefNode = (AML_NAMESPACE_REF_NODE*)NextLink; + + // Print the raw absolute path of the probed node. + AMLDBG_PRINT_CHARS ( + DEBUG_VERBOSE, + ProbedNameSpaceRefNode->RawAbsolutePath, + ProbedNameSpaceRefNode->RawAbsolutePathSize + ); + DEBUG ((DEBUG_VERBOSE, "; ")); + + // If the raw AML absolute path of the probed node is longer than the + // searched pathname, continue. + // E.g.: The method call \MET0 cannot resolve to a method defined at + // \AAAA.MET0. The method definition is out of scope. + if (PathNameSegScopeCount > ProbedNameSpaceRefNode->RawAbsolutePathSize) { + NextLink = NextLink->ForwardLink; + continue; + } + + // Initialize a backward stream for the probed node. + // This stream is used to compare the ending of the pathnames. + // E.g. if the method searched ends with "MET0", pathnames not ending with + // "MET0" should be skipped. + Status = AmlStreamInit ( + &ProbedRawAbsoluteBStream, + (UINT8*)ProbedNameSpaceRefNode->RawAbsolutePath, + ProbedNameSpaceRefNode->RawAbsolutePathSize, + EAmlStreamDirectionBackward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Compare the pathname endings. If they don't match, continue. + if (!AmlStreamCmp ( + RawPathNameBStream, + &ProbedRawAbsoluteBStream, + AmlStreamGetMaxBufferSize (RawPathNameBStream))) { + NextLink = NextLink->ForwardLink; + continue; + } + + // Initialize a forward stream for the probed node. + // This stream is used to count how many scope levels from the root + // are common with the probed node. The more there are, the better it is. + // E.g.: For the method invocation \AAAA.BBBB.MET0, if there are 2 + // pathnames ending with MET0: + // - \AAAA.MET0 has 1 NameSeg in common with \AAAA.BBBB.MET0 + // from the root (this is "AAAA"); + // - \MET0 has 0 NameSeg in common with \AAAA.BBBB.MET0 + // from the root; + // Thus, the best match is \AAAA.MET0. + Status = AmlStreamInit ( + &ProbedRawAbsoluteFStream, + (UINT8*)ProbedNameSpaceRefNode->RawAbsolutePath, + ProbedNameSpaceRefNode->RawAbsolutePathSize, + EAmlStreamDirectionForward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Count how many namespace levels are in common from the root. + Status = AmlCompareRawNameString ( + RawAbsolutePathFStream, + &ProbedRawAbsoluteFStream, + &ProbedScopeCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (ProbedScopeCount == NameSegScopeCount) { + // This is a perfect match. Exit the loop. + BestNameSpaceRefNode = ProbedNameSpaceRefNode; + break; + } else if (ProbedScopeCount > BestScopeCount) { + // The probed node has more scope levels in common than the + // last best match. Update the best match. + BestScopeCount = ProbedScopeCount; + BestNameSpaceRefNode = ProbedNameSpaceRefNode; + } else if (ProbedScopeCount == BestScopeCount) { + // The probed node has the same number of scope levels in + // common as the last best match. + if (ProbedScopeCount == 0) { + // There was not best match previously. Set it. + BestNameSpaceRefNode = ProbedNameSpaceRefNode; + } else { + // (ProbedScopeCount != 0) + // If there is an equivalent candidate, the best has the shortest + // absolute path. Indeed, a similar ProbedScopeCount and a longer + // path means the definition is out of the scope. + // E.g.: For the method invocation \AAAA.BBBB.MET0, if there are 2 + // pathnames ending with MET0: + // - \AAAA.MET0 has 1 NameSegs in common with \AAAA.BBBB.MET0 + // from the root (this is "AAAA"); + // - \AAAA.CCCC.MET0 has 1 NameSegs in common with + // \AAAA.BBBB.MET0 from the root (this is "AAAA"); + // As \AAAA.CCCC.MET0 is longer than \AAAA.MET0, it means that + // the pathname could have matched on more NameSegs, but it + // didn't because it is out of scope. + // Thus, the best match is \AAAA.MET0. + if (AmlStreamGetIndex (&ProbedRawAbsoluteFStream) < + BestNameSpaceRefNode->RawAbsolutePathSize) { + BestScopeCount = ProbedScopeCount; + BestNameSpaceRefNode = ProbedNameSpaceRefNode; + } else if (AmlStreamGetIndex (&ProbedRawAbsoluteFStream) == + BestNameSpaceRefNode->RawAbsolutePathSize) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } + } + + NextLink = NextLink->ForwardLink; + } + + DEBUG ((DEBUG_VERBOSE, "\n")); + + // Check whether the BestNameSpaceRefNode is a method definition. + if (BestNameSpaceRefNode != NULL) { + if (AmlIsMethodDefinitionNode (BestNameSpaceRefNode->NodeRef)) { + *OutNameSpaceRefNode = BestNameSpaceRefNode; + } else if (AmlNodeCompareOpCode ( + BestNameSpaceRefNode->NodeRef, + AML_ALIAS_OP, 0)) { + // The path matches an alias. Resolve the alias and check whether + // this is a method defintion. + Status = AmlResolveAliasMethod ( + BestNameSpaceRefNode->NodeRef, + NameSpaceRefList, + OutNameSpaceRefNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + } else { + // If no, return NULL, even if a matching pathname has been found. + *OutNameSpaceRefNode = NULL; + } + + return EFI_SUCCESS; +} + +/** Check whether a pathname is a method invocation. + + If there is a matching method definition, returns the corresponding + NameSpaceRef node. + + To do so, the NameSpaceRefList is keeping track of every namespace node + and its raw AML absolute path. + To check whether a pathname is a method invocation, a corresponding raw + absolute pathname is built. This raw absolute pathname is then compared + to the list of available pathnames. If a pathname defining a method + matches the scope of the input pathname, return. + + @param [in] ParentNode Parent node. Node to which the node to be + created will be attached. + @param [in] FStream Forward stream pointing to the NameString + to find. + @param [in] NameSpaceRefList List of NameSpaceRef nodes. + @param [out] OutNameSpaceRefNode If the NameString pointed by FStream is + a method invocation, OutNameSpaceRefNode + contains the NameSpaceRef corresponding + to the method definition. + NULL otherwise. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlIsMethodInvocation ( + IN CONST AML_NODE_HEADER * ParentNode, + IN CONST AML_STREAM * FStream, + IN CONST LIST_ENTRY * NameSpaceRefList, + OUT AML_NAMESPACE_REF_NODE ** OutNameSpaceRefNode + ) +{ + EFI_STATUS Status; + + AML_STREAM RawPathNameBStream; + AML_STREAM RawAbsolutePathFStream; + + AML_STREAM RawAbsolutePathBStream; + UINT8 * RawAbsolutePathBuffer; + UINT32 RawAbsolutePathBufferSize; + + AML_NAMESPACE_REF_NODE * NameSpaceRefNode; + + if ((!IS_AML_OBJECT_NODE (ParentNode) && + !IS_AML_ROOT_NODE (ParentNode)) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (NameSpaceRefList == NULL) || + (OutNameSpaceRefNode == NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // There cannot be a method invocation in a field list. Return. + if (AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)ParentNode, + AML_HAS_FIELD_LIST)) { + *OutNameSpaceRefNode = NULL; + return EFI_SUCCESS; + } + + // Allocate memory for the raw absolute path. + RawAbsolutePathBufferSize = MAX_AML_NAMESTRING_SIZE; + RawAbsolutePathBuffer = AllocateZeroPool (RawAbsolutePathBufferSize); + if (RawAbsolutePathBuffer == NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + // Initialize a backward stream to get the raw absolute path. + Status = AmlStreamInit ( + &RawAbsolutePathBStream, + RawAbsolutePathBuffer, + RawAbsolutePathBufferSize, + EAmlStreamDirectionBackward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Build the raw AML absolute path of the namespace node. + Status = AmlBuildRawMethodAbsolutePath ( + ParentNode, + FStream, + &RawAbsolutePathBStream + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // If this is the root path: it cannot be a method invocation. Just return. + if (AmlStreamGetIndex (&RawAbsolutePathBStream) == 0) { + DEBUG (( + DEBUG_VERBOSE, + "AmlMethodParser: " + "Root node cannot be a method invocation\n" + )); + *OutNameSpaceRefNode = NULL; + Status = EFI_SUCCESS; + goto exit_handler; + } + + // Create a forward stream for the raw absolute path. + // This forward stream only contains the raw absolute path with + // no extra free space. + Status = AmlStreamInit ( + &RawAbsolutePathFStream, + AmlStreamGetCurrPos (&RawAbsolutePathBStream), + AmlStreamGetIndex (&RawAbsolutePathBStream), + EAmlStreamDirectionForward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Create a backward stream for the node name. + Status = AmlInitRawPathBStream ( + FStream, + &RawPathNameBStream + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Go through the NameSpaceRefList elements to check for + // a corresponding method definition. + NameSpaceRefNode = NULL; + Status = AmlFindMethodDefinition ( + &RawAbsolutePathFStream, + &RawPathNameBStream, + NameSpaceRefList, + &NameSpaceRefNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + +#if !defined(MDEPKG_NDEBUG) + // Print whether a method definition has been found. + if (NameSpaceRefNode != NULL) { + DEBUG (( + DEBUG_VERBOSE, + "AmlMethodParser: Corresponding method definition: " + )); + AMLDBG_PRINT_CHARS ( + DEBUG_VERBOSE, + NameSpaceRefNode->RawAbsolutePath, + NameSpaceRefNode->RawAbsolutePathSize + ); + DEBUG ((DEBUG_VERBOSE, ".\n")); + + } else { + DEBUG ((DEBUG_VERBOSE, "AmlMethodParser: No method definition found.\n")); + } +#endif // MDEPKG_NDEBUG + + *OutNameSpaceRefNode = NameSpaceRefNode; + +exit_handler: + // Free allocated memory. + FreePool (RawAbsolutePathBuffer); + return Status; +} + +/** Create a namespace reference node and add it to the NameSpaceRefList. + + When a namespace node is encountered, the namespace it defines must be + associated to the node. This allow to keep track of the nature of each + name present in the AML namespace. + + In the end, this allows to recognize method invocations and parse the right + number of arguments after the method name. + + @param [in] Node Namespace node. + @param [in, out] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlAddNameSpaceReference ( + IN CONST AML_OBJECT_NODE * Node, + IN OUT LIST_ENTRY * NameSpaceRefList + ) +{ + EFI_STATUS Status; + AML_NAMESPACE_REF_NODE * NameSpaceRefNode; + + AML_STREAM NodeNameFStream; + EAML_PARSE_INDEX NameIndex; + CONST AML_DATA_NODE * NameNode; + + AML_STREAM RawAbsolutePathBStream; + UINT32 RawAbsolutePathBStreamSize; + + CHAR8 * AbsolutePathBuffer; + UINT32 AbsolutePathBufferSize; + + CONST AML_NODE_HEADER * ParentNode; + + if (!AmlNodeHasAttribute (Node, AML_IN_NAMESPACE) || + (NameSpaceRefList == NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Allocate a buffer to get the raw AML absolute pathname of the + // namespace node. + AbsolutePathBufferSize = MAX_AML_NAMESTRING_SIZE; + AbsolutePathBuffer = AllocateZeroPool (AbsolutePathBufferSize); + if (AbsolutePathBuffer == NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + Status = AmlStreamInit ( + &RawAbsolutePathBStream, + (UINT8*)AbsolutePathBuffer, + AbsolutePathBufferSize, + EAmlStreamDirectionBackward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + Status = EFI_INVALID_PARAMETER; + goto exit_handler; + } + + // Get the index where the name of the Node is stored in its + // fixed list of arguments. + Status = AmlNodeGetNameIndex (Node, &NameIndex); + if (EFI_ERROR (Status)) { + ASSERT (0); + Status = EFI_INVALID_PARAMETER; + goto exit_handler; + } + + // Get the Node name. + NameNode = (CONST AML_DATA_NODE*)AmlGetFixedArgument ( + (AML_OBJECT_NODE*)Node, + NameIndex + ); + if (!IS_AML_DATA_NODE (NameNode) || + (NameNode->DataType != EAmlNodeDataTypeNameString)) { + ASSERT (0); + Status = EFI_INVALID_PARAMETER; + goto exit_handler; + } + + // Initialize a stream on the node name of the namespace node. + // This is an AML NameString. + Status = AmlStreamInit ( + &NodeNameFStream, + NameNode->Buffer, + NameNode->Size, + EAmlStreamDirectionForward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + Status = EFI_INVALID_PARAMETER; + goto exit_handler; + } + + ParentNode = AmlGetParent ((AML_NODE_HEADER*)Node); + if (ParentNode == NULL) { + ASSERT (0); + Status = EFI_INVALID_PARAMETER; + goto exit_handler; + } + + // Build the raw AML absolute path of the namespace node. + Status = AmlBuildRawMethodAbsolutePath ( + ParentNode, + &NodeNameFStream, + &RawAbsolutePathBStream + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + RawAbsolutePathBStreamSize = AmlStreamGetIndex (&RawAbsolutePathBStream); + // This is the root path: this cannot be a method invocation. + if (RawAbsolutePathBStreamSize == 0) { + Status = EFI_SUCCESS; + goto exit_handler; + } + + // Create a NameSpace reference node. + Status = AmlCreateMethodRefNode ( + Node, + (CONST CHAR8*)AmlStreamGetCurrPos (&RawAbsolutePathBStream), + RawAbsolutePathBStreamSize, + &NameSpaceRefNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Add the created NameSpaceRefNode to the list. + InsertTailList (NameSpaceRefList, &NameSpaceRefNode->Link); + + DEBUG (( + DEBUG_VERBOSE, + "AmlMethodParser: Adding namespace reference with name:\n" + )); + AMLDBG_PRINT_CHARS ( + DEBUG_VERBOSE, + (CONST CHAR8*)AmlStreamGetCurrPos (&RawAbsolutePathBStream), + AmlStreamGetIndex (&RawAbsolutePathBStream) + ); + DEBUG ((DEBUG_VERBOSE, "\n")); + +exit_handler: + // Free allocated memory. + FreePool (AbsolutePathBuffer); + + return Status; +} + +/** Create a method invocation node. + + The AML grammar does not attribute an OpCode/SubOpCode couple for + method invocations. This library is representing method invocations + as if they had one. + + The AML encoding for method invocations in the ACPI specification 6.3 is: + MethodInvocation := NameString TermArgList + In this library, it is: + MethodInvocation := MethodInvocationOp NameString ArgumentCount TermArgList + ArgumentCount := ByteData + + When computing the size of a tree or serializing it, the additional data is + not taken into account (i.e. the MethodInvocationOp and the ArgumentCount). + + Method invocation nodes have the AML_METHOD_INVOVATION attribute. + + @param [in] NameSpaceRefNode NameSpaceRef node pointing to the + the definition of the invoked + method. + @param [in] MethodInvocationName Data node containing the method + invocation name. + @param [out] MethodInvocationNodePtr Created method invocation 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 +AmlCreateMethodInvocationNode ( + IN CONST AML_NAMESPACE_REF_NODE * NameSpaceRefNode, + IN AML_DATA_NODE * MethodInvocationName, + OUT AML_OBJECT_NODE ** MethodInvocationNodePtr + ) +{ + EFI_STATUS Status; + + UINT8 ArgCount; + AML_DATA_NODE * ArgCountNode; + AML_NODE_HEADER ** FixedArgs; + AML_OBJECT_NODE * MethodDefinitionNode; + AML_OBJECT_NODE * MethodInvocationNode; + + if ((NameSpaceRefNode == NULL) || + !AmlIsMethodDefinitionNode (NameSpaceRefNode->NodeRef) || + !IS_AML_DATA_NODE (MethodInvocationName) || + (MethodInvocationName->DataType != EAmlNodeDataTypeNameString) || + (MethodInvocationNodePtr == NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the number of arguments of the method. + MethodDefinitionNode = (AML_OBJECT_NODE*)NameSpaceRefNode->NodeRef; + FixedArgs = MethodDefinitionNode->FixedArgs; + // The method definition is an actual method definition. + if (AmlNodeCompareOpCode (MethodDefinitionNode, AML_METHOD_OP, 0)) { + // Cf ACPI 6.3 specification: + // DefMethod := MethodOp PkgLength NameString MethodFlags TermList + // MethodOp := 0x14 + // MethodFlags := ByteData bit 0-2: ArgCount (0-7) + // bit 3: SerializeFlag + // 0 NotSerialized + // 1 Serialized + // bit 4-7: SyncLevel (0x00-0x0f) + + // Read the MethodFlags to decode the ArgCount. + ArgCountNode = (AML_DATA_NODE*)FixedArgs[EAmlParseIndexTerm1]; + ArgCount = *((UINT8*)ArgCountNode->Buffer) & 0x7; + } else if (AmlNodeCompareOpCode (MethodDefinitionNode, AML_EXTERNAL_OP, 0)) { + // The method definition is an external statement. + // Cf ACPI 6.3 specification: + // DefExternal := ExternalOp NameString ObjectType ArgumentCount + // ExternalOp := 0x15 + // ObjectType := ByteData + // ArgumentCount := ByteData (0 - 7) + + // Read the ArgumentCount. + ArgCountNode = (AML_DATA_NODE*)FixedArgs[EAmlParseIndexTerm2]; + ArgCount = *((UINT8*)ArgCountNode->Buffer); + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Create the object node for the method invocation. + // MethodInvocation := MethodInvocationOp NameString ArgumentCount + // MethodInvocationOp := Pseudo Opcode for Method Invocation + // NameString := Method Name + // ArgumentCount := ByteData (0 - 7) + Status = AmlCreateObjectNode ( + AmlGetByteEncodingByOpCode (AML_METHOD_INVOC_OP, 0), + 0, + &MethodInvocationNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // The first fixed argument is the method name. + Status = AmlSetFixedArgument ( + MethodInvocationNode, + EAmlParseIndexTerm0, + (AML_NODE_HEADER*)MethodInvocationName + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + // Create a data node holding the number of arguments + // of the method invocation. + ArgCountNode = NULL; + Status = AmlCreateDataNode ( + EAmlNodeDataTypeUInt, + &ArgCount, + sizeof (UINT8), + &ArgCountNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + // The second fixed argument is the number of arguments. + Status = AmlSetFixedArgument ( + MethodInvocationNode, + EAmlParseIndexTerm1, + (AML_NODE_HEADER*)ArgCountNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + *MethodInvocationNodePtr = MethodInvocationNode; + return Status; + +error_handler: + // Delete the sub-tree: the method invocation name is already attached. + AmlDeleteTree ((AML_NODE_HEADER*)MethodInvocationNode); + if (ArgCountNode != NULL) { + AmlDeleteNode ((AML_NODE_HEADER*)ArgCountNode); + } + + return Status; +} + +/** Get the number of arguments of a method invocation node. + + This function also allow to identify whether a node is a method invocation + node. If the input node is not a method invocation node, just return. + + @param [in] MethodInvocationNode Method invocation node. + @param [out] IsMethodInvocation Boolean stating whether the input + node is a method invocation. + @param [out] ArgCount Number of arguments of the method + invocation. + Set to 0 if MethodInvocationNode + is not a method invocation. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlGetMethodInvocationArgCount ( + IN CONST AML_OBJECT_NODE * MethodInvocationNode, + OUT BOOLEAN * IsMethodInvocation, + OUT UINT8 * ArgCount + ) +{ + AML_DATA_NODE * NumArgsNode; + + if (!IS_AML_NODE_VALID (MethodInvocationNode) || + (IsMethodInvocation == NULL) || + (ArgCount == NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Check whether MethodInvocationNode is a method invocation. + if (!AmlNodeCompareOpCode (MethodInvocationNode, AML_METHOD_INVOC_OP, 0)) { + *IsMethodInvocation = FALSE; + *ArgCount = 0; + return EFI_SUCCESS; + } + + // MethodInvocation := MethodInvocationOp NameString ArgumentCount + // MethodInvocationOp := Pseudo Opcode for Method Invocation + // NameString := Method Name + // ArgumentCount := ByteData (0 - 7) + NumArgsNode = (AML_DATA_NODE*)AmlGetFixedArgument ( + (AML_OBJECT_NODE*)MethodInvocationNode, + EAmlParseIndexTerm1 + ); + if (!IS_AML_NODE_VALID (NumArgsNode) || + (NumArgsNode->Buffer == NULL) || + (NumArgsNode->DataType != EAmlNodeDataTypeUInt) || + (NumArgsNode->Size != 1)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + *ArgCount = *NumArgsNode->Buffer; + + *IsMethodInvocation = TRUE; + return EFI_SUCCESS; +} -- cgit v1.2.3