/** @file | |
ACPI Sdt Protocol Driver | |
Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "AcpiTable.h" | |
/** | |
Return the child objects buffer from AML Handle's buffer. | |
@param[in] AmlParentHandle Parent handle. | |
@param[in] CurrentBuffer The current child buffer. | |
@param[out] Buffer On return, points to the next returned child buffer or NULL if there are no | |
child buffer. | |
@retval EFI_SUCCESS Success | |
@retval EFI_INVALID_PARAMETER AmlParentHandle does not refer to a valid ACPI object. | |
**/ | |
EFI_STATUS | |
AmlGetChildFromObjectBuffer ( | |
IN EFI_AML_HANDLE *AmlParentHandle, | |
IN UINT8 *CurrentBuffer, | |
OUT VOID **Buffer | |
) | |
{ | |
AML_BYTE_ENCODING *AmlByteEncoding; | |
UINTN DataSize; | |
// | |
// Root is considered as SCOPE, which has TermList. | |
// We need return only Object in TermList. | |
// | |
while ((UINTN)CurrentBuffer < (UINTN)(AmlParentHandle->Buffer + AmlParentHandle->Size)) { | |
AmlByteEncoding = AmlSearchByOpByte (CurrentBuffer); | |
if (AmlByteEncoding == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// NOTE: We need return everything, because user might need parse the returned object. | |
// | |
if ((AmlByteEncoding->Attribute & AML_IS_NAME_CHAR) == 0) { | |
*Buffer = CurrentBuffer; | |
return EFI_SUCCESS; | |
} | |
DataSize = AmlGetObjectSize ( | |
AmlByteEncoding, | |
CurrentBuffer, | |
(UINTN)AmlParentHandle->Buffer + AmlParentHandle->Size - (UINTN)CurrentBuffer | |
); | |
if (DataSize == 0) { | |
return EFI_INVALID_PARAMETER; | |
} | |
CurrentBuffer += DataSize; | |
} | |
// | |
// No more | |
// | |
*Buffer = NULL; | |
return EFI_SUCCESS; | |
} | |
/** | |
Return the child ACPI objects from Root Handle. | |
@param[in] AmlParentHandle Parent handle. It is Root Handle. | |
@param[in] AmlHandle The previously returned handle or NULL to start with the first handle. | |
@param[out] Buffer On return, points to the next returned ACPI handle or NULL if there are no | |
child objects. | |
@retval EFI_SUCCESS Success | |
@retval EFI_INVALID_PARAMETER ParentHandle is NULL or does not refer to a valid ACPI object. | |
**/ | |
EFI_STATUS | |
AmlGetChildFromRoot ( | |
IN EFI_AML_HANDLE *AmlParentHandle, | |
IN EFI_AML_HANDLE *AmlHandle, | |
OUT VOID **Buffer | |
) | |
{ | |
UINT8 *CurrentBuffer; | |
if (AmlHandle == NULL) { | |
// | |
// First One | |
// | |
CurrentBuffer = (VOID *)AmlParentHandle->Buffer; | |
} else { | |
CurrentBuffer = (VOID *)(AmlHandle->Buffer + AmlHandle->Size); | |
} | |
return AmlGetChildFromObjectBuffer (AmlParentHandle, CurrentBuffer, Buffer); | |
} | |
/** | |
Return the child objects buffer from AML Handle's option list. | |
@param[in] AmlParentHandle Parent handle. | |
@param[in] AmlHandle The current child handle. | |
@param[out] Buffer On return, points to the next returned child buffer or NULL if there are no | |
child buffer. | |
@retval EFI_SUCCESS Success | |
@retval EFI_INVALID_PARAMETER AmlParentHandle does not refer to a valid ACPI object. | |
**/ | |
EFI_STATUS | |
AmlGetChildFromOptionList ( | |
IN EFI_AML_HANDLE *AmlParentHandle, | |
IN EFI_AML_HANDLE *AmlHandle, | |
OUT VOID **Buffer | |
) | |
{ | |
EFI_ACPI_DATA_TYPE DataType; | |
VOID *Data; | |
UINTN DataSize; | |
AML_OP_PARSE_INDEX Index; | |
EFI_STATUS Status; | |
AML_OP_PARSE_INDEX MaxTerm; | |
Index = AML_OP_PARSE_INDEX_GET_TERM1; | |
MaxTerm = AmlParentHandle->AmlByteEncoding->MaxIndex; | |
while (Index <= MaxTerm) { | |
Status = AmlParseOptionHandleCommon ( | |
AmlParentHandle, | |
(AML_OP_PARSE_INDEX)Index, | |
&DataType, | |
(VOID **)&Data, | |
&DataSize | |
); | |
if (EFI_ERROR (Status)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (DataType == EFI_ACPI_DATA_TYPE_NONE) { | |
// | |
// Not found | |
// | |
break; | |
} | |
// | |
// Find it, and Check Data | |
// | |
if ((DataType == EFI_ACPI_DATA_TYPE_CHILD) && | |
((UINTN)AmlHandle->Buffer < (UINTN)Data)) | |
{ | |
// | |
// Buffer < Data means current node is next one | |
// | |
*Buffer = Data; | |
return EFI_SUCCESS; | |
} | |
// | |
// Not Child | |
// | |
Index++; | |
} | |
*Buffer = NULL; | |
return EFI_SUCCESS; | |
} | |
/** | |
Return the child objects buffer from AML Handle's object child list. | |
@param[in] AmlParentHandle Parent handle. | |
@param[in] AmlHandle The current child handle. | |
@param[out] Buffer On return, points to the next returned child buffer or NULL if there are no | |
child buffer. | |
@retval EFI_SUCCESS Success | |
@retval EFI_INVALID_PARAMETER AmlParentHandle does not refer to a valid ACPI object. | |
**/ | |
EFI_STATUS | |
AmlGetChildFromObjectChildList ( | |
IN EFI_AML_HANDLE *AmlParentHandle, | |
IN EFI_AML_HANDLE *AmlHandle, | |
OUT VOID **Buffer | |
) | |
{ | |
EFI_STATUS Status; | |
UINT8 *CurrentBuffer; | |
CurrentBuffer = NULL; | |
if ((AmlParentHandle->AmlByteEncoding->Attribute & AML_HAS_CHILD_OBJ) == 0) { | |
// | |
// No ObjectList | |
// | |
*Buffer = NULL; | |
return EFI_SUCCESS; | |
} | |
// | |
// Do we need add node within METHOD? | |
// Yes, just add Object is OK. But we need filter NameString for METHOD invoke. | |
// | |
// | |
// Now, we get the last node. | |
// | |
Status = AmlGetOffsetAfterLastOption (AmlParentHandle, &CurrentBuffer); | |
if (EFI_ERROR (Status)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// Go through all the reset buffer. | |
// | |
if ((UINTN)AmlHandle->Buffer < (UINTN)CurrentBuffer) { | |
// | |
// Buffer < Data means next node is first object | |
// | |
} else if ((UINTN)AmlHandle->Buffer + AmlHandle->Size < (UINTN)AmlParentHandle->Buffer + AmlParentHandle->Size) { | |
// | |
// There is still more node | |
// | |
CurrentBuffer = AmlHandle->Buffer + AmlHandle->Size; | |
} else { | |
// | |
// No more data | |
// | |
*Buffer = NULL; | |
return EFI_SUCCESS; | |
} | |
return AmlGetChildFromObjectBuffer (AmlParentHandle, CurrentBuffer, Buffer); | |
} | |
/** | |
Return the child ACPI objects from Non-Root Handle. | |
@param[in] AmlParentHandle Parent handle. It is Non-Root Handle. | |
@param[in] AmlHandle The previously returned handle or NULL to start with the first handle. | |
@param[out] Buffer On return, points to the next returned ACPI handle or NULL if there are no | |
child objects. | |
@retval EFI_SUCCESS Success | |
@retval EFI_INVALID_PARAMETER ParentHandle is NULL or does not refer to a valid ACPI object. | |
**/ | |
EFI_STATUS | |
AmlGetChildFromNonRoot ( | |
IN EFI_AML_HANDLE *AmlParentHandle, | |
IN EFI_AML_HANDLE *AmlHandle, | |
OUT VOID **Buffer | |
) | |
{ | |
EFI_STATUS Status; | |
if (AmlHandle == NULL) { | |
// | |
// NULL means first one | |
// | |
AmlHandle = AmlParentHandle; | |
} | |
// | |
// 1. Get Option | |
// | |
Status = AmlGetChildFromOptionList (AmlParentHandle, AmlHandle, Buffer); | |
if (EFI_ERROR (Status)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (*Buffer != NULL) { | |
return EFI_SUCCESS; | |
} | |
// | |
// 2. search ObjectList | |
// | |
return AmlGetChildFromObjectChildList (AmlParentHandle, AmlHandle, Buffer); | |
} |