summaryrefslogtreecommitdiff
path: root/Core/EM/ACPI/AmlOption.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/ACPI/AmlOption.c')
-rw-r--r--Core/EM/ACPI/AmlOption.c500
1 files changed, 500 insertions, 0 deletions
diff --git a/Core/EM/ACPI/AmlOption.c b/Core/EM/ACPI/AmlOption.c
new file mode 100644
index 0000000..55ef7f7
--- /dev/null
+++ b/Core/EM/ACPI/AmlOption.c
@@ -0,0 +1,500 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/BIN/Modules/ACPI/Template/Core/AmlOption.c 2 5/14/11 2:12p Yakovlevs $
+//
+// $Revision: 2 $
+//
+// $Date: 5/14/11 2:12p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Modules/ACPI/Template/Core/AmlOption.c $
+//
+// 2 5/14/11 2:12p Yakovlevs
+// [TAG] EIP 56526
+// [Category] New Feature
+// [Description] ACPI Manipulation Protocol. PI 1.2 Spec Vol 5 Section
+// 9. Initial checkin.
+// [Files] AcpiCore.c; AcpiCore.h; AcpiSdtPrivate.h; Aml.c; AmlChild.c;
+// AmlNamespace.c; AmlOption.c; AmlString.c AcpiSdt.c;
+// Protocol\AcpiSdt.h.
+//
+//**********************************************************************
+
+
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AmlOption.c
+//
+// Description:
+// ACPI AML Name space parsing/manipulation functions for ACPI SDT.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include "AcpiCore.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 = (Strlen((CHAR8 *)Buffer)+1);
+ 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, accroding 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
+ );
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************