From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../Universal/Acpi/AcpiTableDxe/AmlOption.c | 446 +++++++++++++++++++++ 1 file changed, 446 insertions(+) create mode 100644 roms/edk2/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AmlOption.c (limited to 'roms/edk2/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AmlOption.c') diff --git a/roms/edk2/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AmlOption.c b/roms/edk2/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AmlOption.c new file mode 100644 index 000000000..d0374c5de --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AmlOption.c @@ -0,0 +1,446 @@ +/** @file + ACPI Sdt Protocol Driver + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AcpiTable.h" + +/** + Retrieve option term according to AmlByteEncoding and Buffer. + + @param[in] AmlByteEncoding AML Byte Encoding. + @param[in] Buffer AML buffer. + @param[in] MaxBufferSize AML buffer MAX size. The parser can not parse any data exceed this region. + @param[in] TermIndex Index of the data to retrieve from the object. + @param[out] DataType Points to the returned data type or EFI_ACPI_DATA_TYPE_NONE if no data exists + for the specified index. + @param[out] Data Upon return, points to the pointer to the data. + @param[out] DataSize Upon return, points to the size of Data. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Buffer does not refer to a valid ACPI object. +**/ +EFI_STATUS +AmlParseOptionTerm ( + IN AML_BYTE_ENCODING *AmlByteEncoding, + IN UINT8 *Buffer, + IN UINTN MaxBufferSize, + IN AML_OP_PARSE_INDEX TermIndex, + OUT EFI_ACPI_DATA_TYPE *DataType, + OUT VOID **Data, + OUT UINTN *DataSize + ) +{ + AML_BYTE_ENCODING *ChildAmlByteEncoding; + EFI_STATUS Status; + + if (DataType != NULL) { + *DataType = AmlTypeToAcpiType (AmlByteEncoding->Format[TermIndex - 1]); + } + if (Data != NULL) { + *Data = Buffer; + } + // + // Parse term according to AML type + // + switch (AmlByteEncoding->Format[TermIndex - 1]) { + case AML_UINT8: + *DataSize = sizeof(UINT8); + break; + case AML_UINT16: + *DataSize = sizeof(UINT16); + break; + case AML_UINT32: + *DataSize = sizeof(UINT32); + break; + case AML_UINT64: + *DataSize = sizeof(UINT64); + break; + case AML_STRING: + *DataSize = AsciiStrSize((CHAR8 *)Buffer); + break; + case AML_NAME: + Status = AmlGetNameStringSize (Buffer, DataSize); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + break; + case AML_OBJECT: + ChildAmlByteEncoding = AmlSearchByOpByte (Buffer); + if (ChildAmlByteEncoding == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // NOTE: We need override DataType here, if there is a case the AML_OBJECT is AML_NAME. + // We need convert type from EFI_ACPI_DATA_TYPE_CHILD to EFI_ACPI_DATA_TYPE_NAME_STRING. + // We should not return CHILD because there is NO OpCode for NameString. + // + if ((ChildAmlByteEncoding->Attribute & AML_IS_NAME_CHAR) != 0) { + if (DataType != NULL) { + *DataType = AmlTypeToAcpiType (AML_NAME); + } + Status = AmlGetNameStringSize (Buffer, DataSize); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + break; + } + + // + // It is real AML_OBJECT + // + *DataSize = AmlGetObjectSize ( + ChildAmlByteEncoding, + Buffer, + MaxBufferSize + ); + if (*DataSize == 0) { + return EFI_INVALID_PARAMETER; + } + break; + case AML_NONE: + // + // No term + // + case AML_OPCODE: + default: + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + if (*DataSize > MaxBufferSize) { + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + +/** + Retrieve information according to AmlByteEncoding and Buffer. + + @param[in] AmlByteEncoding AML Byte Encoding. + @param[in] Buffer AML buffer. + @param[in] MaxBufferSize AML buffer MAX size. The parser can not parse any data exceed this region. + @param[in] Index Index of the data to retrieve from the object. In general, indexes read from left-to-right + in the ACPI encoding, with index 0 always being the ACPI opcode. + @param[out] DataType Points to the returned data type or EFI_ACPI_DATA_TYPE_NONE if no data exists + for the specified index. + @param[out] Data Upon return, points to the pointer to the data. + @param[out] DataSize Upon return, points to the size of Data. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Buffer does not refer to a valid ACPI object. +**/ +EFI_STATUS +AmlParseOptionCommon ( + IN AML_BYTE_ENCODING *AmlByteEncoding, + IN UINT8 *Buffer, + IN UINTN MaxBufferSize, + IN AML_OP_PARSE_INDEX Index, + OUT EFI_ACPI_DATA_TYPE *DataType, + OUT VOID **Data, + OUT UINTN *DataSize + ) +{ + UINT8 *CurrentBuffer; + UINTN PkgLength; + UINTN OpLength; + UINTN PkgOffset; + AML_OP_PARSE_INDEX TermIndex; + EFI_STATUS Status; + + ASSERT ((Index <= AmlByteEncoding->MaxIndex) || (Index == AML_OP_PARSE_INDEX_GET_SIZE)); + + // + // 0. Check if this is NAME string. + // + if ((AmlByteEncoding->Attribute & AML_IS_NAME_CHAR) != 0) { + // + // Only allow GET_SIZE + // + if (Index != AML_OP_PARSE_INDEX_GET_SIZE) { + return EFI_INVALID_PARAMETER; + } + // + // return NameString size + // + Status = AmlGetNameStringSize (Buffer, DataSize); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + if (*DataSize > MaxBufferSize) { + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; + } + + // + // Not NAME string, start parsing + // + CurrentBuffer = Buffer; + + // + // 1. Get OpCode + // + if (Index != AML_OP_PARSE_INDEX_GET_SIZE) { + *DataType = EFI_ACPI_DATA_TYPE_OPCODE; + *Data = (VOID *)CurrentBuffer; + } + if (*CurrentBuffer == AML_EXT_OP) { + OpLength = 2; + } else { + OpLength = 1; + } + *DataSize = OpLength; + if (Index == AML_OP_PARSE_INDEX_GET_OPCODE) { + return EFI_SUCCESS; + } + if (OpLength > MaxBufferSize) { + return EFI_INVALID_PARAMETER; + } + CurrentBuffer += OpLength; + + // + // 2. Skip PkgLength field, if have + // + if ((AmlByteEncoding->Attribute & AML_HAS_PKG_LENGTH) != 0) { + PkgOffset = AmlGetPkgLength(CurrentBuffer, &PkgLength); + // + // Override MaxBufferSize if it is valid PkgLength + // + if (OpLength + PkgLength > MaxBufferSize) { + return EFI_INVALID_PARAMETER; + } else { + MaxBufferSize = OpLength + PkgLength; + } + } else { + PkgOffset = 0; + PkgLength = 0; + } + CurrentBuffer += PkgOffset; + + // + // 3. Get Term one by one. + // + TermIndex = AML_OP_PARSE_INDEX_GET_TERM1; + while ((Index >= TermIndex) && (TermIndex <= AmlByteEncoding->MaxIndex) && ((UINTN)CurrentBuffer < (UINTN)Buffer + MaxBufferSize)) { + Status = AmlParseOptionTerm ( + AmlByteEncoding, + CurrentBuffer, + (UINTN)Buffer + MaxBufferSize - (UINTN)CurrentBuffer, + TermIndex, + DataType, + Data, + DataSize + ); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + if (Index == TermIndex) { + // + // Done + // + return EFI_SUCCESS; + } + + // + // Parse next one + // + CurrentBuffer += *DataSize; + TermIndex ++; + } + + // + // Finish all options, but no option found. + // + if ((UINTN)CurrentBuffer > (UINTN)Buffer + MaxBufferSize) { + return EFI_INVALID_PARAMETER; + } + if ((UINTN)CurrentBuffer == (UINTN)Buffer + MaxBufferSize) { + if (Index != AML_OP_PARSE_INDEX_GET_SIZE) { + return EFI_INVALID_PARAMETER; + } + } + + // + // 4. Finish parsing all node, return size + // + ASSERT (Index == AML_OP_PARSE_INDEX_GET_SIZE); + if ((AmlByteEncoding->Attribute & AML_HAS_PKG_LENGTH) != 0) { + *DataSize = OpLength + PkgLength; + } else { + *DataSize = (UINTN)CurrentBuffer - (UINTN)Buffer; + } + + return EFI_SUCCESS; +} + +/** + Return object size. + + @param[in] AmlByteEncoding AML Byte Encoding. + @param[in] Buffer AML object buffer. + @param[in] MaxBufferSize AML object buffer MAX size. The parser can not parse any data exceed this region. + + @return Size of the object. +**/ +UINTN +AmlGetObjectSize ( + IN AML_BYTE_ENCODING *AmlByteEncoding, + IN UINT8 *Buffer, + IN UINTN MaxBufferSize + ) +{ + EFI_STATUS Status; + UINTN DataSize; + + Status = AmlParseOptionCommon ( + AmlByteEncoding, + Buffer, + MaxBufferSize, + AML_OP_PARSE_INDEX_GET_SIZE, + NULL, + NULL, + &DataSize + ); + if (EFI_ERROR (Status)) { + return 0; + } else { + return DataSize; + } +} + +/** + Return object name. + + @param[in] AmlHandle AML handle. + + @return Name of the object. +**/ +CHAR8 * +AmlGetObjectName ( + IN EFI_AML_HANDLE *AmlHandle + ) +{ + AML_BYTE_ENCODING *AmlByteEncoding; + VOID *NameString; + UINTN NameSize; + AML_OP_PARSE_INDEX TermIndex; + EFI_STATUS Status; + EFI_ACPI_DATA_TYPE DataType; + + AmlByteEncoding = AmlHandle->AmlByteEncoding; + + ASSERT ((AmlByteEncoding->Attribute & AML_IN_NAMESPACE) != 0); + + // + // Find out Last Name index, according to OpCode table. + // The last name will be the node name by design. + // + TermIndex = AmlByteEncoding->MaxIndex; + for (TermIndex = AmlByteEncoding->MaxIndex; TermIndex > 0; TermIndex--) { + if (AmlByteEncoding->Format[TermIndex - 1] == AML_NAME) { + break; + } + } + ASSERT (TermIndex != 0); + + // + // Get Name for this node. + // + Status = AmlParseOptionHandleCommon ( + AmlHandle, + TermIndex, + &DataType, + &NameString, + &NameSize + ); + if (EFI_ERROR (Status)) { + return NULL; + } + ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING); + + return NameString; +} + +/** + Return offset of last option. + + @param[in] AmlHandle AML Handle. + @param[out] Buffer Upon return, points to the offset after last option. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER AmlHandle does not refer to a valid ACPI object. +**/ +EFI_STATUS +AmlGetOffsetAfterLastOption ( + IN EFI_AML_HANDLE *AmlHandle, + OUT UINT8 **Buffer + ) +{ + EFI_ACPI_DATA_TYPE DataType; + VOID *Data; + UINTN DataSize; + EFI_STATUS Status; + + Status = AmlParseOptionHandleCommon ( + AmlHandle, + AmlHandle->AmlByteEncoding->MaxIndex, + &DataType, + &Data, + &DataSize + ); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + // + // We need to parse the rest buffer after last node. + // + *Buffer = (UINT8 *)((UINTN)Data + DataSize); + + // + // We need skip PkgLength if no Option + // + if (DataType == EFI_ACPI_DATA_TYPE_OPCODE) { + *Buffer += AmlGetPkgLength (*Buffer, &DataSize); + } + return EFI_SUCCESS; +} + +/** + Retrieve information according to AmlHandle + + @param[in] AmlHandle AML handle. + @param[in] Index Index of the data to retrieve from the object. In general, indexes read from left-to-right + in the ACPI encoding, with index 0 always being the ACPI opcode. + @param[out] DataType Points to the returned data type or EFI_ACPI_DATA_TYPE_NONE if no data exists + for the specified index. + @param[out] Data Upon return, points to the pointer to the data. + @param[out] DataSize Upon return, points to the size of Data. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER AmlHandle does not refer to a valid ACPI object. +**/ +EFI_STATUS +AmlParseOptionHandleCommon ( + IN EFI_AML_HANDLE *AmlHandle, + IN AML_OP_PARSE_INDEX Index, + OUT EFI_ACPI_DATA_TYPE *DataType, + OUT VOID **Data, + OUT UINTN *DataSize + ) +{ + return AmlParseOptionCommon ( + AmlHandle->AmlByteEncoding, + AmlHandle->Buffer, + AmlHandle->Size, + Index, + DataType, + Data, + DataSize + ); +} -- cgit 1.2.3-korg