blob: 9f6777057847347fb6256c7137d4ef1d3aa366dd [file] [log] [blame]
/** @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;
}