]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Acpi/AcpiTableDxe/AmlString.c
MdeModulePkg:
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / AcpiTableDxe / AmlString.c
diff --git a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AmlString.c b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AmlString.c
new file mode 100644 (file)
index 0000000..fe2c761
--- /dev/null
@@ -0,0 +1,549 @@
+/** @file\r
+  ACPI Sdt Protocol Driver\r
+\r
+  Copyright (c) 2010, Intel Corporation. All rights reserved. <BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "AcpiTable.h"\r
+\r
+/**\r
+  Check if it is AML Root name\r
+\r
+  @param[in]    Buffer AML path.\r
+  \r
+  @retval       TRUE  AML path is root.\r
+  @retval       FALSE AML path is not root.\r
+**/\r
+BOOLEAN\r
+AmlIsRootPath (\r
+  IN UINT8              *Buffer\r
+  )\r
+{\r
+  if ((Buffer[0] == AML_ROOT_CHAR) && (Buffer[1] == 0)) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Check if it is AML LeadName.\r
+\r
+  @param[in]    Ch   Char.\r
+  \r
+  @retval       TRUE  Char is AML LeadName.\r
+  @retval       FALSE Char is not AML LeadName.\r
+**/\r
+BOOLEAN\r
+AmlIsLeadName (\r
+  IN CHAR8 Ch\r
+  )\r
+{\r
+  if ((Ch == '_') || (Ch >= 'A' && Ch <= 'Z')) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Check if it is AML Name.\r
+\r
+  @param[in]    Ch   Char.\r
+  \r
+  @retval       TRUE  Char is AML Name.\r
+  @retval       FALSE Char is not AML Name.\r
+**/\r
+BOOLEAN\r
+AmlIsName (\r
+  IN CHAR8 Ch\r
+  )\r
+{\r
+  if (AmlIsLeadName (Ch) || (Ch >= '0' && Ch <= '9')) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Return is buffer is AML NameSeg.\r
+\r
+  @param[in]    Buffer     AML NameSement.\r
+  \r
+  @retval       TRUE       It is AML NameSegment.\r
+  @retval       FALSE      It is not AML NameSegment.\r
+**/\r
+BOOLEAN\r
+AmlIsNameSeg (\r
+  IN  UINT8              *Buffer\r
+  )\r
+{\r
+  UINTN  Index;\r
+  if (!AmlIsLeadName (Buffer[0])) {\r
+    return FALSE;\r
+  }\r
+  for (Index = 1; Index < AML_NAME_SEG_SIZE; Index++) {\r
+    if (!AmlIsName (Buffer[Index])) {\r
+      return FALSE;\r
+    }\r
+  }\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Get AML NameString size.\r
+\r
+  @param[in]    Buffer     AML NameString.\r
+  @param[out]   BufferSize AML NameString size \r
+  \r
+  @retval       EFI_SUCCESS           Success.\r
+  @retval       EFI_INVALID_PARAMETER Buffer does not refer to a valid AML NameString.\r
+**/\r
+EFI_STATUS\r
+AmlGetNameStringSize (\r
+  IN  UINT8              *Buffer,\r
+  OUT UINTN              *BufferSize\r
+  )\r
+{\r
+  UINTN                 SegCount;\r
+  UINTN                 Length;\r
+  UINTN                 Index;\r
+  UINT8                 *Name;\r
+\r
+  Name = Buffer;\r
+  Length = 0;\r
+\r
+  //\r
+  // Parse root or parent prefix\r
+  //\r
+  if (*Buffer == AML_ROOT_CHAR) {\r
+    Buffer ++;\r
+    Length ++;\r
+  } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {\r
+    do {\r
+      Buffer ++;\r
+      Length ++;\r
+    } while (*Buffer == AML_PARENT_PREFIX_CHAR);\r
+  }\r
+\r
+  //\r
+  // Parse name segment\r
+  //\r
+  if (*Buffer == AML_DUAL_NAME_PREFIX) {\r
+    Buffer ++;\r
+    Length ++;\r
+    SegCount = 2;\r
+  } else if (*Buffer == AML_MULTI_NAME_PREFIX) {\r
+    Buffer ++;\r
+    Length ++;\r
+    SegCount = *Buffer;\r
+    Buffer ++;\r
+    Length ++;\r
+  } else if (*Buffer == 0) {\r
+    //\r
+    // NULL Name, only for Root\r
+    //\r
+    SegCount = 0;\r
+    Buffer --;\r
+    if ((Length == 1) && (*Buffer == AML_ROOT_CHAR)) {\r
+      *BufferSize = 2;\r
+      return EFI_SUCCESS;\r
+    } else {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  } else {\r
+    //\r
+    // NameSeg\r
+    //\r
+    SegCount = 1;\r
+  }\r
+\r
+  Index = 0;\r
+  do {\r
+    if (!AmlIsNameSeg (Buffer)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    Buffer += AML_NAME_SEG_SIZE;\r
+    Length += AML_NAME_SEG_SIZE;\r
+    Index ++;\r
+  } while (Index < SegCount);\r
+\r
+  *BufferSize = Length;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Check if it is ASL LeadName.\r
+\r
+  @param[in]    Ch   Char.\r
+  \r
+  @retval       TRUE  Char is ASL LeadName.\r
+  @retval       FALSE Char is not ASL LeadName.\r
+**/\r
+BOOLEAN\r
+AmlIsAslLeadName (\r
+  IN CHAR8 Ch\r
+  )\r
+{\r
+  if (AmlIsLeadName (Ch) || (Ch >= 'a' && Ch <= 'z')) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Check if it is ASL Name.\r
+\r
+  @param[in]    Ch   Char.\r
+  \r
+  @retval       TRUE  Char is ASL Name.\r
+  @retval       FALSE Char is not ASL Name.\r
+**/\r
+BOOLEAN\r
+AmlIsAslName (\r
+  IN CHAR8 Ch\r
+  )\r
+{\r
+  if (AmlIsAslLeadName (Ch) || (Ch >= '0' && Ch <= '9')) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Get ASL NameString size.\r
+\r
+  @param[in]    Buffer   ASL NameString.\r
+  \r
+  @return       ASL NameString size.\r
+**/\r
+UINTN\r
+AmlGetAslNameSegLength (\r
+  IN UINT8 *Buffer\r
+  )\r
+{\r
+  UINTN Length;\r
+  UINTN Index;\r
+\r
+  if (*Buffer == 0) {\r
+    return 0;\r
+  }\r
+  \r
+  Length = 0;\r
+  //\r
+  // 1st\r
+  //\r
+  if (AmlIsAslLeadName (*Buffer)) {\r
+    Length ++;\r
+    Buffer ++;\r
+  }\r
+  if ((*Buffer == 0) || (*Buffer == '.')) {\r
+    return Length;\r
+  }\r
+  //\r
+  // 2, 3, 4 name char\r
+  //\r
+  for (Index = 0; Index < 3; Index++) {\r
+    if (AmlIsAslName (*Buffer)) {\r
+      Length ++;\r
+      Buffer ++;\r
+    }\r
+    if ((*Buffer == 0) || (*Buffer == '.')) {\r
+      return Length;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Invalid ASL name\r
+  //\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Get ASL NameString size.\r
+\r
+  @param[in]    Buffer   ASL NameString.\r
+  @param[out]   Root     On return, points to Root char number.\r
+  @param[out]   Parent   On return, points to Parent char number.\r
+  @param[out]   SegCount On return, points to Segment count.\r
+  \r
+  @return       ASL NameString size.\r
+**/\r
+UINTN\r
+AmlGetAslNameStringSize (\r
+  IN UINT8              *Buffer,\r
+  OUT UINTN             *Root,\r
+  OUT UINTN             *Parent,\r
+  OUT UINTN             *SegCount\r
+  )\r
+{\r
+  UINTN NameLength;\r
+  UINTN TotalLength;\r
+\r
+  *Root   = 0;\r
+  *Parent = 0;\r
+  *SegCount = 0;\r
+  TotalLength = 0;\r
+  NameLength = 0;\r
+  if (*Buffer == AML_ROOT_CHAR) {\r
+    *Root = 1;\r
+    Buffer ++;\r
+  } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {\r
+    do {\r
+      Buffer ++;\r
+      (*Parent) ++;\r
+    } while (*Buffer == AML_PARENT_PREFIX_CHAR);\r
+  }\r
+\r
+  //\r
+  // Now parse name\r
+  //\r
+  while (*Buffer != 0) {\r
+    NameLength = AmlGetAslNameSegLength (Buffer);\r
+    if ((NameLength == 0) || (NameLength > AML_NAME_SEG_SIZE)) {\r
+      return 0;\r
+    }\r
+    (*SegCount) ++;\r
+    Buffer += NameLength;\r
+    if (*Buffer == 0) {\r
+      break;\r
+    }\r
+    Buffer ++;\r
+  }\r
+\r
+  //\r
+  // Check SegCoount\r
+  //\r
+  if (*SegCount > 0xFF) {\r
+    return 0;\r
+  }\r
+\r
+  //\r
+  // Calculate total length\r
+  //\r
+  TotalLength = *Root + *Parent + (*SegCount) * AML_NAME_SEG_SIZE;\r
+  if (*SegCount > 2) {\r
+    TotalLength += 2;\r
+  } else if (*SegCount == 2) {\r
+    TotalLength += 1;\r
+  }\r
+\r
+  //\r
+  // Add NULL char\r
+  //\r
+  TotalLength ++;\r
+\r
+  return TotalLength;\r
+}\r
+\r
+/**\r
+  Copy mem, and cast all the char in dest to be upper case.\r
+\r
+  @param[in]    DstBuffer   Destination buffer.\r
+  @param[in]    SrcBuffer   Source buffer.\r
+  @param[in]    Length      Buffer length.\r
+**/\r
+VOID\r
+AmlUpperCaseCopyMem (\r
+  IN UINT8 *DstBuffer,\r
+  IN UINT8 *SrcBuffer,\r
+  IN UINTN Length\r
+  )\r
+{\r
+  UINTN Index;\r
+\r
+  for (Index = 0; Index < Length; Index++) {\r
+    if (SrcBuffer[Index] >= 'a' && SrcBuffer[Index] <= 'z') {\r
+      DstBuffer[Index] = (UINT8)(SrcBuffer[Index] - 'a' + 'A');\r
+    } else {\r
+      DstBuffer[Index] = SrcBuffer[Index];\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Return AML name according to ASL name.\r
+  The caller need free the AmlName returned.\r
+\r
+  @param[in]    AslPath     ASL name.\r
+\r
+  @return AmlName\r
+**/\r
+UINT8 *\r
+AmlNameFromAslName (\r
+  IN UINT8 *AslPath\r
+  )\r
+{\r
+  UINTN Root;\r
+  UINTN Parent;\r
+  UINTN SegCount;\r
+  UINTN TotalLength;\r
+  UINTN NameLength;\r
+  UINT8 *Buffer;\r
+  UINT8 *AmlPath;\r
+  UINT8 *AmlBuffer;\r
+\r
+  TotalLength = AmlGetAslNameStringSize (AslPath, &Root, &Parent, &SegCount);\r
+  if (TotalLength == 0) {\r
+    return NULL;\r
+  }\r
+\r
+  AmlPath = AllocatePool (TotalLength);\r
+  ASSERT (AmlPath != NULL);\r
+\r
+  AmlBuffer = AmlPath;\r
+  Buffer = AslPath;\r
+\r
+  //\r
+  // Handle Root and Parent\r
+  //\r
+  if (Root == 1) {\r
+    *AmlBuffer = AML_ROOT_CHAR;\r
+    AmlBuffer ++;\r
+    Buffer ++;\r
+  } else if (Parent > 0) {\r
+    SetMem (AmlBuffer, Parent, AML_PARENT_PREFIX_CHAR);\r
+    AmlBuffer += Parent;\r
+    Buffer += Parent;\r
+  }\r
+\r
+  //\r
+  // Handle SegCount\r
+  //\r
+  if (SegCount > 2) {\r
+    *AmlBuffer = AML_MULTI_NAME_PREFIX;\r
+    AmlBuffer ++;\r
+    *AmlBuffer = (UINT8)SegCount;\r
+    AmlBuffer ++;\r
+  } else if (SegCount == 2) {\r
+    *AmlBuffer = AML_DUAL_NAME_PREFIX;\r
+    AmlBuffer ++;\r
+  }\r
+\r
+  //\r
+  // Now to name\r
+  //\r
+  while (*Buffer != 0) {\r
+    NameLength = AmlGetAslNameSegLength (Buffer);\r
+    ASSERT ((NameLength != 0) && (NameLength <= AML_NAME_SEG_SIZE));\r
+    AmlUpperCaseCopyMem (AmlBuffer, Buffer, NameLength);\r
+    SetMem (AmlBuffer + NameLength, AML_NAME_SEG_SIZE - NameLength, AML_NAME_CHAR__);\r
+    Buffer += NameLength;\r
+    AmlBuffer += AML_NAME_SEG_SIZE;\r
+    if (*Buffer == 0) {\r
+      break;\r
+    }\r
+    Buffer ++;\r
+  }\r
+\r
+  //\r
+  // Add NULL\r
+  //\r
+  AmlPath[TotalLength - 1] = 0;\r
+\r
+  return AmlPath;\r
+}\r
+\r
+/**\r
+  Print AML NameSeg.\r
+\r
+  @param[in] Buffer AML NameSeg.\r
+**/\r
+VOID\r
+AmlPrintNameSeg (\r
+  IN UINT8              *Buffer\r
+  )\r
+{\r
+  DEBUG ((EFI_D_ERROR, "%c", Buffer[0]));\r
+  if ((Buffer[1] == '_') && (Buffer[2] == '_') && (Buffer[3] == '_')) {\r
+    return ;\r
+  }\r
+  DEBUG ((EFI_D_ERROR, "%c", Buffer[1]));\r
+  if ((Buffer[2] == '_') && (Buffer[3] == '_')) {\r
+    return ;\r
+  }\r
+  DEBUG ((EFI_D_ERROR, "%c", Buffer[2]));\r
+  if (Buffer[3] == '_') {\r
+    return ;\r
+  }\r
+  DEBUG ((EFI_D_ERROR, "%c", Buffer[3]));\r
+  return ;\r
+}\r
+\r
+/**\r
+  Print AML NameString.\r
+\r
+  @param[in] Buffer AML NameString.\r
+**/\r
+VOID\r
+AmlPrintNameString (\r
+  IN UINT8              *Buffer\r
+  )\r
+{\r
+  UINT8                 SegCount;\r
+  UINT8                 Index;\r
+  UINT8                 *Name;\r
\r
+  Name = Buffer;\r
+  if (*Buffer == AML_ROOT_CHAR) {\r
+    //\r
+    // RootChar\r
+    //\r
+    Buffer ++;\r
+    DEBUG ((EFI_D_ERROR, "\\"));\r
+  } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {\r
+    //\r
+    // ParentPrefixChar\r
+    //\r
+    do {\r
+      Buffer ++;\r
+      DEBUG ((EFI_D_ERROR, "^"));\r
+    } while (*Buffer == AML_PARENT_PREFIX_CHAR);\r
+  }\r
+\r
+  if (*Buffer == AML_DUAL_NAME_PREFIX) {\r
+    //\r
+    // DualName\r
+    //\r
+    Buffer ++;\r
+    SegCount = 2;\r
+  } else if (*Buffer == AML_MULTI_NAME_PREFIX) {\r
+    //\r
+    // MultiName\r
+    //\r
+    Buffer ++;\r
+    SegCount = *Buffer;\r
+    Buffer ++;\r
+  } else if (*Buffer == 0) {\r
+    //\r
+    // NULL Name\r
+    //\r
+    return ;\r
+  } else {\r
+    //\r
+    // NameSeg\r
+    //\r
+    SegCount = 1;\r
+  }\r
+  \r
+  AmlPrintNameSeg (Buffer);\r
+  Buffer += AML_NAME_SEG_SIZE;\r
+  for (Index = 0; Index < SegCount - 1; Index++) {\r
+    DEBUG ((EFI_D_ERROR, "."));\r
+    AmlPrintNameSeg (Buffer);\r
+    Buffer += AML_NAME_SEG_SIZE;\r
+  }\r
+\r
+  return ;\r
+}\r