--- /dev/null
+/** @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