diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/ACPI/AmlString.c | |
download | zprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz |
Diffstat (limited to 'Core/EM/ACPI/AmlString.c')
-rw-r--r-- | Core/EM/ACPI/AmlString.c | 600 |
1 files changed, 600 insertions, 0 deletions
diff --git a/Core/EM/ACPI/AmlString.c b/Core/EM/ACPI/AmlString.c new file mode 100644 index 0000000..b3640f3 --- /dev/null +++ b/Core/EM/ACPI/AmlString.c @@ -0,0 +1,600 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/AmlString.c 3 12/13/12 12:00p Oleksiyy $ +// +// $Revision: 3 $ +// +// $Date: 12/13/12 12:00p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/BIN/Modules/ACPI/Template/Core/AmlString.c $ +// +// 3 12/13/12 12:00p Oleksiyy +// [TAG] EIP109290 +// [Category] Improvement +// [Description] Issues found by CppCheck in ACPI eModule +// [Files] AcpiCore.c, mptable.c, AmlString.c, BootScriptSave.c and +// BootScriptExecuter.c +// +// 2 5/14/11 2:13p 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: AmlString.c +// +// Description: +// ACPI AML Name space parsing/manipulation functions for ACPI SDT. +// +//<AMI_FHDR_END> +//********************************************************************** + +#include "AcpiCore.h" + +/** + Check if it is AML Root name + + @param[in] Buffer AML path. + + @retval TRUE AML path is root. + @retval FALSE AML path is not root. +**/ +BOOLEAN +AmlIsRootPath ( + IN UINT8 *Buffer + ) +{ + if ((Buffer[0] == AML_ROOT_CHAR) && (Buffer[1] == 0)) { + return TRUE; + } else { + return FALSE; + } +} + +/** + Check if it is AML LeadName. + + @param[in] Ch Char. + + @retval TRUE Char is AML LeadName. + @retval FALSE Char is not AML LeadName. +**/ +BOOLEAN +AmlIsLeadName ( + IN CHAR8 Ch + ) +{ + if ((Ch == '_') || (Ch >= 'A' && Ch <= 'Z')) { + return TRUE; + } else { + return FALSE; + } +} + +/** + Check if it is AML Name. + + @param[in] Ch Char. + + @retval TRUE Char is AML Name. + @retval FALSE Char is not AML Name. +**/ +BOOLEAN +AmlIsName ( + IN CHAR8 Ch + ) +{ + if (AmlIsLeadName (Ch) || (Ch >= '0' && Ch <= '9')) { + return TRUE; + } else { + return FALSE; + } +} + +/** + Return is buffer is AML NameSeg. + + @param[in] Buffer AML NameSement. + + @retval TRUE It is AML NameSegment. + @retval FALSE It is not AML NameSegment. +**/ +BOOLEAN +AmlIsNameSeg ( + IN UINT8 *Buffer + ) +{ + UINTN Index; + if (!AmlIsLeadName (Buffer[0])) { + return FALSE; + } + for (Index = 1; Index < AML_NAME_SEG_SIZE; Index++) { + if (!AmlIsName (Buffer[Index])) { + return FALSE; + } + } + return TRUE; +} + +/** + Get AML NameString size. + + @param[in] Buffer AML NameString. + @param[out] BufferSize AML NameString size + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Buffer does not refer to a valid AML NameString. +**/ +EFI_STATUS +AmlGetNameStringSize ( + IN UINT8 *Buffer, + OUT UINTN *BufferSize + ) +{ + UINTN SegCount; + UINTN Length; + UINTN Index; + + Length = 0; + + // + // Parse root or parent prefix + // + if (*Buffer == AML_ROOT_CHAR) { + Buffer ++; + Length ++; + } else if (*Buffer == AML_PARENT_PREFIX_CHAR) { + do { + Buffer ++; + Length ++; + } while (*Buffer == AML_PARENT_PREFIX_CHAR); + } + + // + // Parse name segment + // + if (*Buffer == AML_DUAL_NAME_PREFIX) { + Buffer ++; + Length ++; + SegCount = 2; + } else if (*Buffer == AML_MULTI_NAME_PREFIX) { + Buffer ++; + Length ++; + SegCount = *Buffer; + Buffer ++; + Length ++; + } else if (*Buffer == 0) { + // + // NULL Name, only for Root + // + SegCount = 0; + Buffer --; + if ((Length == 1) && (*Buffer == AML_ROOT_CHAR)) { + *BufferSize = 2; + return EFI_SUCCESS; + } else { + return EFI_INVALID_PARAMETER; + } + } else { + // + // NameSeg + // + SegCount = 1; + } + + Index = 0; + do { + if (!AmlIsNameSeg (Buffer)) { + return EFI_INVALID_PARAMETER; + } + Buffer += AML_NAME_SEG_SIZE; + Length += AML_NAME_SEG_SIZE; + Index ++; + } while (Index < SegCount); + + *BufferSize = Length; + return EFI_SUCCESS; +} + +/** + Check if it is ASL LeadName. + + @param[in] Ch Char. + + @retval TRUE Char is ASL LeadName. + @retval FALSE Char is not ASL LeadName. +**/ +BOOLEAN +AmlIsAslLeadName ( + IN CHAR8 Ch + ) +{ + if (AmlIsLeadName (Ch) || (Ch >= 'a' && Ch <= 'z')) { + return TRUE; + } else { + return FALSE; + } +} + +/** + Check if it is ASL Name. + + @param[in] Ch Char. + + @retval TRUE Char is ASL Name. + @retval FALSE Char is not ASL Name. +**/ +BOOLEAN +AmlIsAslName ( + IN CHAR8 Ch + ) +{ + if (AmlIsAslLeadName (Ch) || (Ch >= '0' && Ch <= '9')) { + return TRUE; + } else { + return FALSE; + } +} + +/** + Get ASL NameString size. + + @param[in] Buffer ASL NameString. + + @return ASL NameString size. +**/ +UINTN +AmlGetAslNameSegLength ( + IN UINT8 *Buffer + ) +{ + UINTN Length; + UINTN Index; + + if (*Buffer == 0) { + return 0; + } + + Length = 0; + // + // 1st + // + if (AmlIsAslLeadName (*Buffer)) { + Length ++; + Buffer ++; + } + if ((*Buffer == 0) || (*Buffer == '.')) { + return Length; + } + // + // 2, 3, 4 name char + // + for (Index = 0; Index < 3; Index++) { + if (AmlIsAslName (*Buffer)) { + Length ++; + Buffer ++; + } + if ((*Buffer == 0) || (*Buffer == '.')) { + return Length; + } + } + + // + // Invalid ASL name + // + return 0; +} + +/** + Get ASL NameString size. + + @param[in] Buffer ASL NameString. + @param[out] Root On return, points to Root char number. + @param[out] Parent On return, points to Parent char number. + @param[out] SegCount On return, points to Segment count. + + @return ASL NameString size. +**/ +UINTN +AmlGetAslNameStringSize ( + IN UINT8 *Buffer, + OUT UINTN *Root, + OUT UINTN *Parent, + OUT UINTN *SegCount + ) +{ + UINTN NameLength; + UINTN TotalLength; + + *Root = 0; + *Parent = 0; + *SegCount = 0; + TotalLength = 0; + NameLength = 0; + if (*Buffer == AML_ROOT_CHAR) { + *Root = 1; + Buffer ++; + } else if (*Buffer == AML_PARENT_PREFIX_CHAR) { + do { + Buffer ++; + (*Parent) ++; + } while (*Buffer == AML_PARENT_PREFIX_CHAR); + } + + // + // Now parse name + // + while (*Buffer != 0) { + NameLength = AmlGetAslNameSegLength (Buffer); + if ((NameLength == 0) || (NameLength > AML_NAME_SEG_SIZE)) { + return 0; + } + (*SegCount) ++; + Buffer += NameLength; + if (*Buffer == 0) { + break; + } + Buffer ++; + } + + // + // Check SegCoount + // + if (*SegCount > 0xFF) { + return 0; + } + + // + // Calculate total length + // + TotalLength = *Root + *Parent + (*SegCount) * AML_NAME_SEG_SIZE; + if (*SegCount > 2) { + TotalLength += 2; + } else if (*SegCount == 2) { + TotalLength += 1; + } + + // + // Add NULL char + // + TotalLength ++; + + return TotalLength; +} + +/** + Copy mem, and cast all the char in dest to be upper case. + + @param[in] DstBuffer Destination buffer. + @param[in] SrcBuffer Source buffer. + @param[in] Length Buffer length. +**/ +VOID +AmlUpperCaseCopyMem ( + IN UINT8 *DstBuffer, + IN UINT8 *SrcBuffer, + IN UINTN Length + ) +{ + UINTN Index; + + for (Index = 0; Index < Length; Index++) { + if (SrcBuffer[Index] >= 'a' && SrcBuffer[Index] <= 'z') { + DstBuffer[Index] = (UINT8)(SrcBuffer[Index] - 'a' + 'A'); + } else { + DstBuffer[Index] = SrcBuffer[Index]; + } + } +} + +/** + Return AML name according to ASL name. + The caller need free the AmlName returned. + + @param[in] AslPath ASL name. + + @return AmlName +**/ +UINT8 * +AmlNameFromAslName ( + IN UINT8 *AslPath + ) +{ + UINTN Root; + UINTN Parent; + UINTN SegCount; + UINTN TotalLength; + UINTN NameLength; + UINT8 *Buffer; + UINT8 *AmlPath; + UINT8 *AmlBuffer; + + TotalLength = AmlGetAslNameStringSize (AslPath, &Root, &Parent, &SegCount); + if (TotalLength == 0) { + return NULL; + } + + AmlPath = Malloc (TotalLength); + ASSERT (AmlPath != NULL); + + AmlBuffer = AmlPath; + Buffer = AslPath; + + // + // Handle Root and Parent + // + if (Root == 1) { + *AmlBuffer = AML_ROOT_CHAR; + AmlBuffer ++; + Buffer ++; + } else if (Parent > 0) { + MemSet (AmlBuffer, Parent, AML_PARENT_PREFIX_CHAR); + AmlBuffer += Parent; + Buffer += Parent; + } + + // + // Handle SegCount + // + if (SegCount > 2) { + *AmlBuffer = AML_MULTI_NAME_PREFIX; + AmlBuffer ++; + *AmlBuffer = (UINT8)SegCount; + AmlBuffer ++; + } else if (SegCount == 2) { + *AmlBuffer = AML_DUAL_NAME_PREFIX; + AmlBuffer ++; + } + + // + // Now to name + // + while (*Buffer != 0) { + NameLength = AmlGetAslNameSegLength (Buffer); + ASSERT ((NameLength != 0) && (NameLength <= AML_NAME_SEG_SIZE)); + AmlUpperCaseCopyMem (AmlBuffer, Buffer, NameLength); + MemSet (AmlBuffer + NameLength, AML_NAME_SEG_SIZE - NameLength, AML_NAME_CHAR__); + Buffer += NameLength; + AmlBuffer += AML_NAME_SEG_SIZE; + if (*Buffer == 0) { + break; + } + Buffer ++; + } + + // + // Add NULL + // + AmlPath[TotalLength - 1] = 0; + + return AmlPath; +} + +/** + Print AML NameSeg. + + @param[in] Buffer AML NameSeg. +**/ +VOID +AmlPrintNameSeg ( + IN UINT8 *Buffer + ) +{ + TRACE ((-1, "%c", Buffer[0])); + if ((Buffer[1] == '_') && (Buffer[2] == '_') && (Buffer[3] == '_')) { + return ; + } + TRACE ((-1, "%c", Buffer[1])); + if ((Buffer[2] == '_') && (Buffer[3] == '_')) { + return ; + } + TRACE ((-1, "%c", Buffer[2])); + if (Buffer[3] == '_') { + return ; + } + TRACE ((-1, "%c", Buffer[3])); + return ; +} + +/** + Print AML NameString. + + @param[in] Buffer AML NameString. +**/ +VOID +AmlPrintNameString ( + IN UINT8 *Buffer + ) +{ + UINT8 SegCount; + UINT8 Index; + + if (*Buffer == AML_ROOT_CHAR) { + // + // RootChar + // + Buffer ++; + TRACE ((-1, "\\")); + } else if (*Buffer == AML_PARENT_PREFIX_CHAR) { + // + // ParentPrefixChar + // + do { + Buffer ++; + TRACE ((-1, "^")); + } while (*Buffer == AML_PARENT_PREFIX_CHAR); + } + + if (*Buffer == AML_DUAL_NAME_PREFIX) { + // + // DualName + // + Buffer ++; + SegCount = 2; + } else if (*Buffer == AML_MULTI_NAME_PREFIX) { + // + // MultiName + // + Buffer ++; + SegCount = *Buffer; + Buffer ++; + } else if (*Buffer == 0) { + // + // NULL Name + // + return ; + } else { + // + // NameSeg + // + SegCount = 1; + } + + AmlPrintNameSeg (Buffer); + Buffer += AML_NAME_SEG_SIZE; + for (Index = 0; Index < SegCount - 1; Index++) { + TRACE ((-1, ".")); + AmlPrintNameSeg (Buffer); + Buffer += AML_NAME_SEG_SIZE; + } + + return ; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |