| /** @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" | |
| /** | |
| 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 = AllocatePool (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) { | |
| SetMem (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); | |
| SetMem (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 | |
| ) | |
| { | |
| DEBUG ((DEBUG_ERROR, "%c", Buffer[0])); | |
| if ((Buffer[1] == '_') && (Buffer[2] == '_') && (Buffer[3] == '_')) { | |
| return; | |
| } | |
| DEBUG ((DEBUG_ERROR, "%c", Buffer[1])); | |
| if ((Buffer[2] == '_') && (Buffer[3] == '_')) { | |
| return; | |
| } | |
| DEBUG ((DEBUG_ERROR, "%c", Buffer[2])); | |
| if (Buffer[3] == '_') { | |
| return; | |
| } | |
| DEBUG ((DEBUG_ERROR, "%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++; | |
| DEBUG ((DEBUG_ERROR, "\\")); | |
| } else if (*Buffer == AML_PARENT_PREFIX_CHAR) { | |
| // | |
| // ParentPrefixChar | |
| // | |
| do { | |
| Buffer++; | |
| DEBUG ((DEBUG_ERROR, "^")); | |
| } 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++) { | |
| DEBUG ((DEBUG_ERROR, ".")); | |
| AmlPrintNameSeg (Buffer); | |
| Buffer += AML_NAME_SEG_SIZE; | |
| } | |
| return; | |
| } |