/** @file ACPI Sdt Protocol Driver Copyright (c) 2010, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #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; UINT8 *Name; Name = Buffer; 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 ((EFI_D_ERROR, "%c", Buffer[0])); if ((Buffer[1] == '_') && (Buffer[2] == '_') && (Buffer[3] == '_')) { return ; } DEBUG ((EFI_D_ERROR, "%c", Buffer[1])); if ((Buffer[2] == '_') && (Buffer[3] == '_')) { return ; } DEBUG ((EFI_D_ERROR, "%c", Buffer[2])); if (Buffer[3] == '_') { return ; } DEBUG ((EFI_D_ERROR, "%c", Buffer[3])); return ; } /** Print AML NameString. @param[in] Buffer AML NameString. **/ VOID AmlPrintNameString ( IN UINT8 *Buffer ) { UINT8 SegCount; UINT8 Index; UINT8 *Name; Name = Buffer; if (*Buffer == AML_ROOT_CHAR) { // // RootChar // Buffer ++; DEBUG ((EFI_D_ERROR, "\\")); } else if (*Buffer == AML_PARENT_PREFIX_CHAR) { // // ParentPrefixChar // do { Buffer ++; DEBUG ((EFI_D_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 ((EFI_D_ERROR, ".")); AmlPrintNameSeg (Buffer); Buffer += AML_NAME_SEG_SIZE; } return ; }