/** @file | |
ACPI Sdt Protocol Driver | |
Copyright (c) 2010, Intel Corporation. All rights reserved. <BR> | |
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 ; | |
} |