--- /dev/null
+/** @file\r
+ Var Check Hii bin generation.\r
+\r
+Copyright (c) 2015, 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 "VarCheckHiiGen.h"\r
+\r
+LIST_ENTRY mVarCheckHiiList = INITIALIZE_LIST_HEAD_VARIABLE (mVarCheckHiiList);\r
+\r
+#define VAR_CHECK_HII_VARIABLE_NODE_SIGNATURE SIGNATURE_32 ('V', 'C', 'H', 'V')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+ VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable;\r
+ EFI_VARSTORE_ID VarStoreId;\r
+\r
+ VAR_CHECK_HII_QUESTION_HEADER **HiiQuestionArray;\r
+} VAR_CHECK_HII_VARIABLE_NODE;\r
+\r
+#define VAR_CHECK_HII_VARIABLE_FROM_LINK(a) CR (a, VAR_CHECK_HII_VARIABLE_NODE, Link, VAR_CHECK_HII_VARIABLE_NODE_SIGNATURE)\r
+\r
+CHAR16 *mVarName = NULL;\r
+UINTN mMaxVarNameSize = 0;\r
+\r
+#ifdef DUMP_HII_DATA\r
+GLOBAL_REMOVE_IF_UNREFERENCED VAR_CHECK_HII_OPCODE_STRING mIfrOpCodeStringTable[] = {\r
+ {EFI_IFR_VARSTORE_OP, "EFI_IFR_VARSTORE_OP"},\r
+ {EFI_IFR_VARSTORE_EFI_OP, "EFI_IFR_VARSTORE_EFI_OP"},\r
+ {EFI_IFR_ONE_OF_OP, "EFI_IFR_ONE_OF_OP"},\r
+ {EFI_IFR_CHECKBOX_OP, "EFI_IFR_CHECKBOX_OP"},\r
+ {EFI_IFR_NUMERIC_OP, "EFI_IFR_NUMERIC_OP"},\r
+ {EFI_IFR_ORDERED_LIST_OP, "EFI_IFR_ORDERED_LIST_OP"},\r
+ {EFI_IFR_ONE_OF_OPTION_OP, "EFI_IFR_ONE_OF_OPTION_OP"},\r
+};\r
+\r
+/**\r
+ Ifr opcode to string.\r
+\r
+ @param[in] IfrOpCode Ifr OpCode.\r
+\r
+ @return Pointer to string.\r
+\r
+**/\r
+CHAR8 *\r
+IfrOpCodeToStr (\r
+ IN UINT8 IfrOpCode\r
+ )\r
+{\r
+ UINTN Index;\r
+ for (Index = 0; Index < sizeof (mIfrOpCodeStringTable) / sizeof (mIfrOpCodeStringTable[0]); Index++) {\r
+ if (mIfrOpCodeStringTable[Index].HiiOpCode == IfrOpCode) {\r
+ return mIfrOpCodeStringTable[Index].HiiOpCodeStr;\r
+ }\r
+ }\r
+\r
+ return "<UnknownIfrOpCode>";\r
+}\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED VAR_CHECK_HII_PACKAGE_TYPE_STRING mPackageTypeStringTable[] = {\r
+ {EFI_HII_PACKAGE_TYPE_ALL, "EFI_HII_PACKAGE_TYPE_ALL"},\r
+ {EFI_HII_PACKAGE_TYPE_GUID, "EFI_HII_PACKAGE_TYPE_GUID"},\r
+ {EFI_HII_PACKAGE_FORMS, "EFI_HII_PACKAGE_FORMS"},\r
+ {EFI_HII_PACKAGE_STRINGS, "EFI_HII_PACKAGE_STRINGS"},\r
+ {EFI_HII_PACKAGE_FONTS, "EFI_HII_PACKAGE_FONTS"},\r
+ {EFI_HII_PACKAGE_IMAGES, "EFI_HII_PACKAGE_IMAGES"},\r
+ {EFI_HII_PACKAGE_SIMPLE_FONTS, "EFI_HII_PACKAGE_SIMPLE_FONTS"},\r
+ {EFI_HII_PACKAGE_DEVICE_PATH, "EFI_HII_PACKAGE_DEVICE_PATH"},\r
+ {EFI_HII_PACKAGE_KEYBOARD_LAYOUT, "EFI_HII_PACKAGE_KEYBOARD_LAYOUT"},\r
+ {EFI_HII_PACKAGE_ANIMATIONS, "EFI_HII_PACKAGE_ANIMATIONS"},\r
+ {EFI_HII_PACKAGE_END, "EFI_HII_PACKAGE_END"},\r
+ {EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN, "EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN"},\r
+ {EFI_HII_PACKAGE_TYPE_SYSTEM_END, "EFI_HII_PACKAGE_TYPE_SYSTEM_END"},\r
+};\r
+\r
+/**\r
+ Hii Package type to string.\r
+\r
+ @param[in] PackageType Package Type\r
+\r
+ @return Pointer to string.\r
+\r
+**/\r
+CHAR8 *\r
+HiiPackageTypeToStr (\r
+ IN UINT8 PackageType\r
+ )\r
+{\r
+ UINTN Index;\r
+ for (Index = 0; Index < sizeof (mPackageTypeStringTable) / sizeof (mPackageTypeStringTable[0]); Index++) {\r
+ if (mPackageTypeStringTable[Index].PackageType == PackageType) {\r
+ return mPackageTypeStringTable[Index].PackageTypeStr;\r
+ }\r
+ }\r
+\r
+ return "<UnknownPackageType>";\r
+}\r
+\r
+/**\r
+ Dump Hii Package.\r
+\r
+ @param[in] HiiPackage Pointer to Hii Package.\r
+\r
+**/\r
+VOID\r
+DumpHiiPackage (\r
+ IN VOID *HiiPackage\r
+ )\r
+{\r
+ EFI_HII_PACKAGE_HEADER *HiiPackageHeader;\r
+ EFI_IFR_OP_HEADER *IfrOpCodeHeader;\r
+ EFI_IFR_VARSTORE *IfrVarStore;\r
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
+\r
+ HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiPackage;\r
+\r
+ DEBUG ((EFI_D_INFO, " HiiPackageHeader->Type - 0x%02x (%a)\n", HiiPackageHeader->Type, HiiPackageTypeToStr ((UINT8) HiiPackageHeader->Type)));\r
+ DEBUG ((EFI_D_INFO, " HiiPackageHeader->Length - 0x%06x\n", HiiPackageHeader->Length));\r
+\r
+ switch (HiiPackageHeader->Type) {\r
+ case EFI_HII_PACKAGE_FORMS:\r
+ IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) (HiiPackageHeader + 1);\r
+\r
+ while ((UINTN) IfrOpCodeHeader < ((UINTN) HiiPackageHeader + HiiPackageHeader->Length)) {\r
+ switch (IfrOpCodeHeader->OpCode) {\r
+ case EFI_IFR_VARSTORE_OP:\r
+ IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpCodeHeader;\r
+ DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode)));\r
+ DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->Length - 0x%02x\n", IfrOpCodeHeader->Length));\r
+ DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->Scope - 0x%02x\n", IfrOpCodeHeader->Scope));\r
+ DEBUG ((EFI_D_INFO, " Guid - %g\n", &IfrVarStore->Guid));\r
+ DEBUG ((EFI_D_INFO, " VarStoreId - 0x%04x\n", IfrVarStore->VarStoreId));\r
+ DEBUG ((EFI_D_INFO, " Size - 0x%04x\n", IfrVarStore->Size));\r
+ DEBUG ((EFI_D_INFO, " Name - %a\n", IfrVarStore->Name));\r
+ break;\r
+\r
+ case EFI_IFR_VARSTORE_EFI_OP:\r
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpCodeHeader;\r
+ if (IfrEfiVarStore->Header.Length >= sizeof (EFI_IFR_VARSTORE_EFI)) {\r
+ DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode)));\r
+ DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->Length - 0x02%x\n", IfrOpCodeHeader->Length));\r
+ DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->Scope - 0x02%x\n", IfrOpCodeHeader->Scope));\r
+ DEBUG ((EFI_D_INFO, " Guid - %g\n", &IfrEfiVarStore->Guid));\r
+ DEBUG ((EFI_D_INFO, " VarStoreId - 0x%04x\n", IfrEfiVarStore->VarStoreId));\r
+ DEBUG ((EFI_D_INFO, " Size - 0x%04x\n", IfrEfiVarStore->Size));\r
+ DEBUG ((EFI_D_INFO, " Attributes - 0x%08x\n", IfrEfiVarStore->Attributes));\r
+ DEBUG ((EFI_D_INFO, " Name - %a\n", IfrEfiVarStore->Name));\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OP:\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ case EFI_IFR_NUMERIC_OP:\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode)));\r
+ DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->Length - 0x02%x\n", IfrOpCodeHeader->Length));\r
+ DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->Scope - 0x02%x\n", IfrOpCodeHeader->Scope));\r
+ DEBUG ((EFI_D_INFO, " Prompt - 0x%04x\n", ((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.Header.Prompt));\r
+ DEBUG ((EFI_D_INFO, " Help - 0x%04x\n", ((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.Header.Help));\r
+ DEBUG ((EFI_D_INFO, " QuestionId - 0x%04x\n", ((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.QuestionId));\r
+ DEBUG ((EFI_D_INFO, " VarStoreId - 0x%04x\n", ((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.VarStoreId));\r
+ DEBUG ((EFI_D_INFO, " VarStoreInfo - 0x%04x\n", ((EFI_IFR_ONE_OF * )IfrOpCodeHeader)->Question.VarStoreInfo.VarOffset));\r
+ {\r
+ EFI_IFR_ONE_OF *IfrOneOf;\r
+ EFI_IFR_CHECKBOX *IfrCheckBox;\r
+ EFI_IFR_NUMERIC *IfrNumeric;\r
+ EFI_IFR_ORDERED_LIST *IfrOrderedList;\r
+\r
+ switch (IfrOpCodeHeader->OpCode) {\r
+ case EFI_IFR_ONE_OF_OP:\r
+ IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpCodeHeader;\r
+ DEBUG ((EFI_D_INFO, " Flags - 0x%02x\n", IfrOneOf->Flags));\r
+ switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ DEBUG ((EFI_D_INFO, " MinValue - 0x%02x\n", IfrOneOf->data.u8.MinValue));\r
+ DEBUG ((EFI_D_INFO, " MaxValue - 0x%02x\n", IfrOneOf->data.u8.MaxValue));\r
+ DEBUG ((EFI_D_INFO, " Step - 0x%02x\n", IfrOneOf->data.u8.Step));\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ DEBUG ((EFI_D_INFO, " MinValue - 0x%04x\n", IfrOneOf->data.u16.MinValue));\r
+ DEBUG ((EFI_D_INFO, " MaxValue - 0x%04x\n", IfrOneOf->data.u16.MaxValue));\r
+ DEBUG ((EFI_D_INFO, " Step - 0x%04x\n", IfrOneOf->data.u16.Step));\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ DEBUG ((EFI_D_INFO, " MinValue - 0x%08x\n", IfrOneOf->data.u32.MinValue));\r
+ DEBUG ((EFI_D_INFO, " MaxValue - 0x%08x\n", IfrOneOf->data.u32.MaxValue));\r
+ DEBUG ((EFI_D_INFO, " Step - 0x%08x\n", IfrOneOf->data.u32.Step));\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ DEBUG ((EFI_D_INFO, " MinValue - 0x%016lx\n", IfrOneOf->data.u64.MinValue));\r
+ DEBUG ((EFI_D_INFO, " MaxValue - 0x%016lx\n", IfrOneOf->data.u64.MaxValue));\r
+ DEBUG ((EFI_D_INFO, " Step - 0x%016lx\n", IfrOneOf->data.u64.Step));\r
+ break;\r
+ }\r
+ break;\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpCodeHeader;\r
+ DEBUG ((EFI_D_INFO, " Flags - 0x%02x\n", IfrCheckBox->Flags));\r
+ break;\r
+ case EFI_IFR_NUMERIC_OP:\r
+ IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpCodeHeader;\r
+ DEBUG ((EFI_D_INFO, " Flags - 0x%02x\n", IfrNumeric->Flags));\r
+ switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ DEBUG ((EFI_D_INFO, " MinValue - 0x%02x\n", IfrNumeric->data.u8.MinValue));\r
+ DEBUG ((EFI_D_INFO, " MaxValue - 0x%02x\n", IfrNumeric->data.u8.MaxValue));\r
+ DEBUG ((EFI_D_INFO, " Step - 0x%02x\n", IfrNumeric->data.u8.Step));\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ DEBUG ((EFI_D_INFO, " MinValue - 0x%04x\n", IfrNumeric->data.u16.MinValue));\r
+ DEBUG ((EFI_D_INFO, " MaxValue - 0x%04x\n", IfrNumeric->data.u16.MaxValue));\r
+ DEBUG ((EFI_D_INFO, " Step - 0x%04x\n", IfrNumeric->data.u16.Step));\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ DEBUG ((EFI_D_INFO, " MinValue - 0x%08x\n", IfrNumeric->data.u32.MinValue));\r
+ DEBUG ((EFI_D_INFO, " MaxValue - 0x%08x\n", IfrNumeric->data.u32.MaxValue));\r
+ DEBUG ((EFI_D_INFO, " Step - 0x%08x\n", IfrNumeric->data.u32.Step));\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ DEBUG ((EFI_D_INFO, " MinValue - 0x%016lx\n", IfrNumeric->data.u64.MinValue));\r
+ DEBUG ((EFI_D_INFO, " MaxValue - 0x%016lx\n", IfrNumeric->data.u64.MaxValue));\r
+ DEBUG ((EFI_D_INFO, " Step - 0x%016lx\n", IfrNumeric->data.u64.Step));\r
+ break;\r
+ }\r
+ break;\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpCodeHeader;\r
+ DEBUG ((EFI_D_INFO, " MaxContainers - 0x%02x\n", IfrOrderedList->MaxContainers));\r
+ DEBUG ((EFI_D_INFO, " Flags - 0x%02x\n", IfrOrderedList->Flags));\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ if (IfrOpCodeHeader->Scope != 0) {\r
+ UINTN Scope;\r
+ EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
+\r
+ IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);\r
+ Scope = 1;\r
+ while (Scope != 0) {\r
+ switch (IfrOpCodeHeader->OpCode) {\r
+ case EFI_IFR_ONE_OF_OPTION_OP:\r
+ IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *)IfrOpCodeHeader;\r
+ DEBUG ((EFI_D_INFO, "!!!! IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", (UINTN)IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode)));\r
+ DEBUG ((EFI_D_INFO, "!!!! IfrOpCodeHeader->Scope - 0x%02x\n", IfrOpCodeHeader->Scope));\r
+ DEBUG ((EFI_D_INFO, "!!!! Option - 0x%04x\n", IfrOneOfOption->Option));\r
+ DEBUG ((EFI_D_INFO, "!!!! Flags - 0x%02x\n", IfrOneOfOption->Flags));\r
+ DEBUG ((EFI_D_INFO, "!!!! Type - 0x%02x\n", IfrOneOfOption->Type));\r
+ switch (IfrOneOfOption->Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ DEBUG ((EFI_D_INFO, "!!!! Value - 0x%02x\n", IfrOneOfOption->Value.u8));\r
+ break;\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ DEBUG ((EFI_D_INFO, "!!!! Value - 0x%04x\n", IfrOneOfOption->Value.u16));\r
+ break;\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ DEBUG ((EFI_D_INFO, "!!!! Value - 0x%08x\n", IfrOneOfOption->Value.u32));\r
+ break;\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ DEBUG ((EFI_D_INFO, "!!!! Value - 0x%016lx\n", IfrOneOfOption->Value.u64));\r
+ break;\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ DEBUG ((EFI_D_INFO, "!!!! Value - 0x%02x\n", IfrOneOfOption->Value.b));\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ break;\r
+ }\r
+\r
+ if (IfrOpCodeHeader->OpCode == EFI_IFR_END_OP) {\r
+ ASSERT (Scope > 0);\r
+ Scope--;\r
+ if (Scope == 0) {\r
+ break;\r
+ }\r
+ } else if (IfrOpCodeHeader->Scope != 0) {\r
+ Scope++;\r
+ }\r
+ IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);\r
+ }\r
+ }\r
+ }\r
+ default:\r
+ break;\r
+ }\r
+ IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Dump Hii Database.\r
+\r
+ @param[in] HiiDatabase Pointer to Hii Database.\r
+ @param[in] HiiDatabaseSize Hii Database size.\r
+\r
+**/\r
+VOID\r
+DumpHiiDatabase (\r
+ IN VOID *HiiDatabase,\r
+ IN UINTN HiiDatabaseSize\r
+ )\r
+{\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageListHeader;\r
+ EFI_HII_PACKAGE_HEADER *HiiPackageHeader;\r
+\r
+ DEBUG ((EFI_D_INFO, "HiiDatabaseSize - 0x%x\n", HiiDatabaseSize));\r
+ HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *) HiiDatabase;\r
+\r
+ while ((UINTN) HiiPackageListHeader < ((UINTN) HiiDatabase + HiiDatabaseSize)) {\r
+ DEBUG ((EFI_D_INFO, "HiiPackageListHeader->PackageListGuid - %g\n", &HiiPackageListHeader->PackageListGuid));\r
+ DEBUG ((EFI_D_INFO, "HiiPackageListHeader->PackageLength - 0x%x\n", (UINTN)HiiPackageListHeader->PackageLength));\r
+ HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *)(HiiPackageListHeader + 1);\r
+\r
+ while ((UINTN) HiiPackageHeader < (UINTN) HiiPackageListHeader + HiiPackageListHeader->PackageLength) {\r
+\r
+ DumpHiiPackage (HiiPackageHeader);\r
+\r
+ HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINTN) HiiPackageHeader + HiiPackageHeader->Length);\r
+ }\r
+\r
+ HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *) ((UINTN) HiiPackageListHeader + HiiPackageListHeader->PackageLength);\r
+ }\r
+\r
+ return ;\r
+}\r
+#endif\r
+\r
+/**\r
+ Allocates a buffer of a certain pool type.\r
+\r
+ Allocates the number bytes specified by AllocationSize of a certain pool type and returns a\r
+ pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
+ returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
+\r
+ @param MemoryType The type of memory to allocate.\r
+ @param AllocationSize The number of bytes to allocate.\r
+\r
+ @return A pointer to the allocated buffer or NULL if allocation fails.\r
+\r
+**/\r
+VOID *\r
+InternalVarCheckAllocatePool (\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN AllocationSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *Memory;\r
+\r
+ Status = gBS->AllocatePool (MemoryType, AllocationSize, &Memory);\r
+ if (EFI_ERROR (Status)) {\r
+ Memory = NULL;\r
+ }\r
+ return Memory;\r
+}\r
+\r
+/**\r
+ Allocates and zeros a buffer of type EfiBootServicesData.\r
+\r
+ Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the\r
+ buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
+ valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
+ request, then NULL is returned.\r
+\r
+ @param AllocationSize The number of bytes to allocate and zero.\r
+\r
+ @return A pointer to the allocated buffer or NULL if allocation fails.\r
+\r
+**/\r
+VOID *\r
+InternalVarCheckAllocateZeroPool (\r
+ IN UINTN AllocationSize\r
+ )\r
+{\r
+ VOID *Memory;\r
+\r
+ Memory = InternalVarCheckAllocatePool (EfiBootServicesData, AllocationSize);\r
+ if (Memory != NULL) {\r
+ Memory = ZeroMem (Memory, AllocationSize);\r
+ }\r
+ return Memory;\r
+}\r
+\r
+/**\r
+ Frees a buffer that was previously allocated with one of the pool allocation functions in the\r
+ Memory Allocation Library.\r
+\r
+ Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the\r
+ pool allocation services of the Memory Allocation Library. If it is not possible to free pool\r
+ resources, then this function will perform no actions.\r
+\r
+ If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,\r
+ then ASSERT().\r
+\r
+ @param Buffer The pointer to the buffer to free.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InternalVarCheckFreePool (\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->FreePool (Buffer);\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+ Reallocates a buffer of type EfiBootServicesData.\r
+\r
+ Allocates and zeros the number bytes specified by NewSize from memory of type\r
+ EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and\r
+ NewSize bytes are copied from OldBuffer to the newly allocated buffer, and\r
+ OldBuffer is freed. A pointer to the newly allocated buffer is returned.\r
+ If NewSize is 0, then a valid buffer of 0 size is returned. If there is not\r
+ enough memory remaining to satisfy the request, then NULL is returned.\r
+\r
+ If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
+ is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
+\r
+ @param OldSize The size, in bytes, of OldBuffer.\r
+ @param NewSize The size, in bytes, of the buffer to reallocate.\r
+ @param OldBuffer The buffer to copy to the allocated buffer. This is an optional\r
+ parameter that may be NULL.\r
+\r
+ @return A pointer to the allocated buffer or NULL if allocation fails.\r
+\r
+**/\r
+VOID *\r
+InternalVarCheckReallocatePool (\r
+ IN UINTN OldSize,\r
+ IN UINTN NewSize,\r
+ IN VOID *OldBuffer OPTIONAL\r
+ )\r
+{\r
+ VOID *NewBuffer;\r
+\r
+ NewBuffer = InternalVarCheckAllocateZeroPool (NewSize);\r
+ if (NewBuffer != NULL && OldBuffer != NULL) {\r
+ CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));\r
+ InternalVarCheckFreePool (OldBuffer);\r
+ }\r
+ return NewBuffer;\r
+}\r
+\r
+/**\r
+ Merge Hii Question.\r
+\r
+ @param[in, out] HiiVariableNode Pointer to Hii Variable node.\r
+ @param[in] HiiQuestion Pointer to Hii Question.\r
+ @param[in] FromFv Hii Question from FV.\r
+\r
+**/\r
+VOID\r
+MergeHiiQuestion (\r
+ IN OUT VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode,\r
+ IN VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion,\r
+ IN BOOLEAN FromFv\r
+ )\r
+{\r
+ VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion1;\r
+ VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion2;\r
+ VAR_CHECK_HII_QUESTION_HEADER *NewHiiQuestion;\r
+ UINT8 NewLength;\r
+ UINT64 Minimum1;\r
+ UINT64 Maximum1;\r
+ UINT64 OneValue1;\r
+ UINT64 Minimum2;\r
+ UINT64 Maximum2;\r
+ UINT64 OneValue2;\r
+ UINT8 *Ptr;\r
+ UINT8 *Ptr1;\r
+ UINT8 *Ptr2;\r
+\r
+ //\r
+ // Hii Question from Hii Database has high priority.\r
+ // Do not to merge Hii Question from Fv to Hii Question from Hii Database.\r
+ //\r
+ if (FromFv) {\r
+ InternalVarCheckFreePool (HiiQuestion);\r
+ return;\r
+ }\r
+\r
+ HiiQuestion1 = HiiVariableNode->HiiQuestionArray[HiiQuestion->VarOffset];\r
+ HiiQuestion2 = HiiQuestion;\r
+\r
+ ASSERT ((HiiQuestion1->OpCode == HiiQuestion2->OpCode) && (HiiQuestion1->StorageWidth == HiiQuestion2->StorageWidth));\r
+\r
+ switch (HiiQuestion1->OpCode) {\r
+ case EFI_IFR_ONE_OF_OP:\r
+ DEBUG ((EFI_D_INFO, "MergeHiiQuestion - EFI_IFR_ONE_OF_OP VarOffset = 0x%04x\n", HiiQuestion1->VarOffset));\r
+ //\r
+ // Get the length of Hii Question 1.\r
+ //\r
+ NewLength = HiiQuestion1->Length;\r
+\r
+ //\r
+ // Check if the one of options in Hii Question 2 have been in Hii Question 1.\r
+ //\r
+ Ptr2 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion2 + 1);\r
+ while ((UINTN) Ptr2 < (UINTN) HiiQuestion2 + HiiQuestion2->Length) {\r
+ OneValue2 = 0;\r
+ CopyMem (&OneValue2, Ptr2, HiiQuestion2->StorageWidth);\r
+\r
+ Ptr1 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion1 + 1);\r
+ while ((UINTN) Ptr1 < (UINTN) HiiQuestion1 + HiiQuestion1->Length) {\r
+ OneValue1 = 0;\r
+ CopyMem (&OneValue1, Ptr1, HiiQuestion1->StorageWidth);\r
+ if (OneValue2 == OneValue1) {\r
+ //\r
+ // Match\r
+ //\r
+ break;\r
+ }\r
+ Ptr1 += HiiQuestion1->StorageWidth;\r
+ }\r
+ if ((UINTN) Ptr1 >= ((UINTN) HiiQuestion1 + HiiQuestion1->Length)) {\r
+ //\r
+ // No match\r
+ //\r
+ NewLength = (UINT8) (NewLength + HiiQuestion1->StorageWidth);\r
+ }\r
+ Ptr2 += HiiQuestion2->StorageWidth;\r
+ }\r
+\r
+ if (NewLength > HiiQuestion1->Length) {\r
+ //\r
+ // Merge the one of options of Hii Question 2 and Hii Question 1.\r
+ //\r
+ NewHiiQuestion = InternalVarCheckAllocateZeroPool (NewLength);\r
+ ASSERT (NewHiiQuestion != NULL);\r
+ CopyMem (NewHiiQuestion, HiiQuestion1, HiiQuestion1->Length);\r
+ //\r
+ // Use the new length.\r
+ //\r
+ NewHiiQuestion->Length = NewLength;\r
+ Ptr = (UINT8 *) NewHiiQuestion + HiiQuestion1->Length;\r
+\r
+ Ptr2 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion2 + 1);\r
+ while ((UINTN) Ptr2 < (UINTN) HiiQuestion2 + HiiQuestion2->Length) {\r
+ OneValue2 = 0;\r
+ CopyMem (&OneValue2, Ptr2, HiiQuestion2->StorageWidth);\r
+\r
+ Ptr1 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion1 + 1);\r
+ while ((UINTN) Ptr1 < (UINTN) HiiQuestion1 + HiiQuestion1->Length) {\r
+ OneValue1 = 0;\r
+ CopyMem (&OneValue1, Ptr1, HiiQuestion1->StorageWidth);\r
+ if (OneValue2 == OneValue1) {\r
+ //\r
+ // Match\r
+ //\r
+ break;\r
+ }\r
+ Ptr1 += HiiQuestion1->StorageWidth;\r
+ }\r
+ if ((UINTN) Ptr1 >= ((UINTN) HiiQuestion1 + HiiQuestion1->Length)) {\r
+ //\r
+ // No match\r
+ //\r
+ CopyMem (Ptr, &OneValue2, HiiQuestion1->StorageWidth);\r
+ Ptr += HiiQuestion1->StorageWidth;\r
+ }\r
+ Ptr2 += HiiQuestion2->StorageWidth;\r
+ }\r
+\r
+ HiiVariableNode->HiiQuestionArray[HiiQuestion1->VarOffset] = NewHiiQuestion;\r
+ InternalVarCheckFreePool (HiiQuestion1);\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ DEBUG ((EFI_D_INFO, "MergeHiiQuestion - EFI_IFR_CHECKBOX_OP VarOffset = 0x%04x\n", HiiQuestion1->VarOffset));\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_OP:\r
+ DEBUG ((EFI_D_INFO, "MergeHiiQuestion - EFI_IFR_NUMERIC_OP VarOffset = 0x%04x\n", HiiQuestion1->VarOffset));\r
+ //\r
+ // Get minimum and maximum of Hii Question 1.\r
+ //\r
+ Minimum1 = 0;\r
+ Maximum1 = 0;\r
+ Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion1 + 1);\r
+ CopyMem (&Minimum1, Ptr, HiiQuestion1->StorageWidth);\r
+ Ptr += HiiQuestion1->StorageWidth;\r
+ CopyMem (&Maximum1, Ptr, HiiQuestion1->StorageWidth);\r
+\r
+ //\r
+ // Get minimum and maximum of Hii Question 2.\r
+ //\r
+ Minimum2 = 0;\r
+ Maximum2 = 0;\r
+ Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion2 + 1);\r
+ CopyMem (&Minimum2, Ptr, HiiQuestion2->StorageWidth);\r
+ Ptr += HiiQuestion2->StorageWidth;\r
+ CopyMem (&Maximum2, Ptr, HiiQuestion2->StorageWidth);\r
+\r
+ //\r
+ // Update minimum.\r
+ //\r
+ Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion1 + 1);\r
+ if (Minimum2 < Minimum1) {\r
+ Minimum1 = Minimum2;\r
+ CopyMem (Ptr, &Minimum1, HiiQuestion1->StorageWidth);\r
+ }\r
+ //\r
+ // Update maximum.\r
+ //\r
+ Ptr += HiiQuestion1->StorageWidth;\r
+ if (Maximum2 > Maximum1) {\r
+ Maximum1 = Maximum2;\r
+ CopyMem (Ptr, &Maximum1, HiiQuestion1->StorageWidth);\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ DEBUG ((EFI_D_INFO, "MergeHiiQuestion - EFI_IFR_ORDERED_LIST_OP VarOffset = 0x%04x\n", HiiQuestion1->VarOffset));\r
+ //\r
+ // Get the length of Hii Question 1.\r
+ //\r
+ NewLength = HiiQuestion1->Length;\r
+\r
+ //\r
+ // Check if the one of options in Hii Question 2 have been in Hii Question 1.\r
+ //\r
+ Ptr2 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion2 + 1);\r
+ while ((UINTN) Ptr2 < (UINTN) HiiQuestion2 + HiiQuestion2->Length) {\r
+ OneValue2 = 0;\r
+ CopyMem (&OneValue2, Ptr2, HiiQuestion2->StorageWidth);\r
+\r
+ Ptr1 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion1 + 1);\r
+ while ((UINTN) Ptr1 < (UINTN) HiiQuestion1 + HiiQuestion1->Length) {\r
+ OneValue1 = 0;\r
+ CopyMem (&OneValue1, Ptr1, HiiQuestion1->StorageWidth);\r
+ if (OneValue2 == OneValue1) {\r
+ //\r
+ // Match\r
+ //\r
+ break;\r
+ }\r
+ Ptr1 += HiiQuestion1->StorageWidth;\r
+ }\r
+ if ((UINTN) Ptr1 >= ((UINTN) HiiQuestion1 + HiiQuestion1->Length)) {\r
+ //\r
+ // No match\r
+ //\r
+ NewLength = (UINT8) (NewLength + HiiQuestion1->StorageWidth);\r
+ }\r
+ Ptr2 += HiiQuestion2->StorageWidth;\r
+ }\r
+\r
+ if (NewLength > HiiQuestion1->Length) {\r
+ //\r
+ // Merge the one of options of Hii Question 2 and Hii Question 1.\r
+ //\r
+ NewHiiQuestion = InternalVarCheckAllocateZeroPool (NewLength);\r
+ ASSERT (NewHiiQuestion != NULL);\r
+ CopyMem (NewHiiQuestion, HiiQuestion1, HiiQuestion1->Length);\r
+ //\r
+ // Use the new length.\r
+ //\r
+ NewHiiQuestion->Length = NewLength;\r
+ Ptr = (UINT8 *) NewHiiQuestion + HiiQuestion1->Length;\r
+\r
+ Ptr2 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion2 + 1);\r
+ while ((UINTN) Ptr2 < (UINTN) HiiQuestion2 + HiiQuestion2->Length) {\r
+ OneValue2 = 0;\r
+ CopyMem (&OneValue2, Ptr2, HiiQuestion2->StorageWidth);\r
+\r
+ Ptr1 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion1 + 1);\r
+ while ((UINTN) Ptr1 < (UINTN) HiiQuestion1 + HiiQuestion1->Length) {\r
+ OneValue1 = 0;\r
+ CopyMem (&OneValue1, Ptr1, HiiQuestion1->StorageWidth);\r
+ if (OneValue2 == OneValue1) {\r
+ //\r
+ // Match\r
+ //\r
+ break;\r
+ }\r
+ Ptr1 += HiiQuestion1->StorageWidth;\r
+ }\r
+ if ((UINTN) Ptr1 >= ((UINTN) HiiQuestion1 + HiiQuestion1->Length)) {\r
+ //\r
+ // No match\r
+ //\r
+ CopyMem (Ptr, &OneValue2, HiiQuestion1->StorageWidth);\r
+ Ptr += HiiQuestion1->StorageWidth;\r
+ }\r
+ Ptr2 += HiiQuestion2->StorageWidth;\r
+ }\r
+\r
+ HiiVariableNode->HiiQuestionArray[HiiQuestion1->VarOffset] = NewHiiQuestion;\r
+ InternalVarCheckFreePool (HiiQuestion1);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ return;\r
+ break;\r
+ }\r
+\r
+ //\r
+ //\r
+ // Hii Question 2 has been merged with Hii Question 1.\r
+ //\r
+ InternalVarCheckFreePool (HiiQuestion2);\r
+}\r
+\r
+/**\r
+ Get OneOf option data.\r
+\r
+ @param[in] IfrOpCodeHeader Pointer to Ifr OpCode header.\r
+ @param[out] Count Pointer to option count.\r
+ @param[out] Width Pointer to option width.\r
+ @param[out] OptionBuffer Pointer to option buffer.\r
+\r
+**/\r
+VOID\r
+GetOneOfOption (\r
+ IN EFI_IFR_OP_HEADER *IfrOpCodeHeader,\r
+ OUT UINTN *Count,\r
+ OUT UINT8 *Width,\r
+ OUT VOID *OptionBuffer OPTIONAL\r
+ )\r
+{\r
+ UINTN Scope;\r
+ EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
+\r
+ //\r
+ // Assume all OPTION has same Width.\r
+ //\r
+ *Count = 0;\r
+\r
+ if (IfrOpCodeHeader->Scope != 0) {\r
+ //\r
+ // Nested OpCode.\r
+ //\r
+ Scope = 1;\r
+ IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);\r
+ while (Scope != 0) {\r
+ switch (IfrOpCodeHeader->OpCode) {\r
+ case EFI_IFR_ONE_OF_OPTION_OP:\r
+ IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpCodeHeader;\r
+ switch (IfrOneOfOption->Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ *Count = *Count + 1;\r
+ *Width = sizeof (UINT8);\r
+ if (OptionBuffer != NULL) {\r
+ CopyMem (OptionBuffer, &IfrOneOfOption->Value.u8, sizeof (UINT8));\r
+ OptionBuffer = (UINT8 *) OptionBuffer + 1;\r
+ }\r
+ break;\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ *Count = *Count + 1;\r
+ *Width = sizeof (UINT16);\r
+ if (OptionBuffer != NULL) {\r
+ CopyMem (OptionBuffer, &IfrOneOfOption->Value.u16, sizeof (UINT16));\r
+ OptionBuffer = (UINT16 *) OptionBuffer + 1;\r
+ }\r
+ break;\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ *Count = *Count + 1;\r
+ *Width = sizeof (UINT32);\r
+ if (OptionBuffer != NULL) {\r
+ CopyMem (OptionBuffer, &IfrOneOfOption->Value.u32, sizeof (UINT32));\r
+ OptionBuffer = (UINT32 *) OptionBuffer + 1;\r
+ }\r
+ break;\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ *Count = *Count + 1;\r
+ *Width = sizeof (UINT64);\r
+ if (OptionBuffer != NULL) {\r
+ CopyMem (OptionBuffer, &IfrOneOfOption->Value.u64, sizeof (UINT64));\r
+ OptionBuffer = (UINT64 *) OptionBuffer + 1;\r
+ }\r
+ break;\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ *Count = *Count + 1;\r
+ *Width = sizeof (BOOLEAN);\r
+ if (OptionBuffer != NULL) {\r
+ CopyMem (OptionBuffer, &IfrOneOfOption->Value.b, sizeof (BOOLEAN));\r
+ OptionBuffer = (BOOLEAN *) OptionBuffer + 1;\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Until End OpCode.\r
+ //\r
+ if (IfrOpCodeHeader->OpCode == EFI_IFR_END_OP) {\r
+ ASSERT (Scope > 0);\r
+ Scope--;\r
+ if (Scope == 0) {\r
+ break;\r
+ }\r
+ } else if (IfrOpCodeHeader->Scope != 0) {\r
+ //\r
+ // Nested OpCode.\r
+ //\r
+ Scope++;\r
+ }\r
+ IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);\r
+ }\r
+ }\r
+\r
+ return ;\r
+}\r
+\r
+/**\r
+ Parse Hii Question Oneof.\r
+\r
+ @param[in] IfrOpCodeHeader Pointer to Ifr OpCode header.\r
+\r
+ return Pointer to Hii Question.\r
+\r
+**/\r
+VAR_CHECK_HII_QUESTION_HEADER *\r
+ParseHiiQuestionOneOf (\r
+ IN EFI_IFR_OP_HEADER *IfrOpCodeHeader\r
+ )\r
+{\r
+ EFI_IFR_ONE_OF *IfrOneOf;\r
+ VAR_CHECK_HII_QUESTION_ONEOF *OneOf;\r
+ UINTN Length;\r
+ UINT8 Width;\r
+ UINTN OptionCount;\r
+ UINT8 OptionWidth;\r
+\r
+ IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpCodeHeader;\r
+\r
+ Width = (UINT8) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
+\r
+ GetOneOfOption (IfrOpCodeHeader, &OptionCount, &OptionWidth, NULL);\r
+ ASSERT (Width == OptionWidth);\r
+\r
+ Length = sizeof (*OneOf) + OptionCount * Width;\r
+\r
+ OneOf = InternalVarCheckAllocateZeroPool (Length);\r
+ ASSERT (OneOf != NULL);\r
+ OneOf->OpCode = EFI_IFR_ONE_OF_OP;\r
+ OneOf->Length = (UINT8) Length;\r
+ OneOf->VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
+ OneOf->StorageWidth = Width;\r
+\r
+ GetOneOfOption (IfrOpCodeHeader, &OptionCount, &OptionWidth, OneOf + 1);\r
+\r
+ return (VAR_CHECK_HII_QUESTION_HEADER *) OneOf;\r
+}\r
+\r
+/**\r
+ Parse Hii Question CheckBox.\r
+\r
+ @param[in] IfrOpCodeHeader Pointer to Ifr OpCode header.\r
+\r
+ return Pointer to Hii Question.\r
+\r
+**/\r
+VAR_CHECK_HII_QUESTION_HEADER *\r
+ParseHiiQuestionCheckBox (\r
+ IN EFI_IFR_OP_HEADER *IfrOpCodeHeader\r
+ )\r
+{\r
+ EFI_IFR_CHECKBOX *IfrCheckBox;\r
+ VAR_CHECK_HII_QUESTION_CHECKBOX *CheckBox;\r
+\r
+ IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpCodeHeader;\r
+\r
+ CheckBox = InternalVarCheckAllocateZeroPool (sizeof (*CheckBox));\r
+ ASSERT (CheckBox != NULL);\r
+ CheckBox->OpCode = EFI_IFR_CHECKBOX_OP;\r
+ CheckBox->Length = (UINT8) sizeof (*CheckBox);;\r
+ CheckBox->VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
+ CheckBox->StorageWidth = (UINT8) sizeof (BOOLEAN);\r
+\r
+ return (VAR_CHECK_HII_QUESTION_HEADER *) CheckBox;\r
+}\r
+\r
+/**\r
+ Parse Hii Question Numeric.\r
+\r
+ @param[in] IfrOpCodeHeader Pointer to Ifr OpCode header.\r
+\r
+ return Pointer to Hii Question.\r
+\r
+**/\r
+VAR_CHECK_HII_QUESTION_HEADER *\r
+ParseHiiQuestionNumeric (\r
+ IN EFI_IFR_OP_HEADER *IfrOpCodeHeader\r
+ )\r
+{\r
+ EFI_IFR_NUMERIC *IfrNumeric;\r
+ VAR_CHECK_HII_QUESTION_NUMERIC *Numeric;\r
+ UINT8 Width;\r
+\r
+ IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpCodeHeader;\r
+\r
+ Numeric = InternalVarCheckAllocateZeroPool (sizeof (VAR_CHECK_HII_QUESTION_NUMERIC) + 2 * sizeof (UINT64));\r
+ ASSERT (Numeric != NULL);\r
+\r
+ Width = (UINT8) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));\r
+\r
+ Numeric->OpCode = EFI_IFR_NUMERIC_OP;\r
+ Numeric->Length = (UINT8) (sizeof (VAR_CHECK_HII_QUESTION_NUMERIC) + 2 * Width);\r
+ Numeric->VarOffset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
+ Numeric->StorageWidth = Width;\r
+\r
+ CopyMem (Numeric + 1, &IfrNumeric->data, Width * 2);\r
+\r
+ return (VAR_CHECK_HII_QUESTION_HEADER *) Numeric;\r
+}\r
+\r
+/**\r
+ Parse Hii Question OrderedList.\r
+\r
+ @param[in] IfrOpCodeHeader Pointer to Ifr OpCode header.\r
+\r
+ return Pointer to Hii Question.\r
+\r
+**/\r
+VAR_CHECK_HII_QUESTION_HEADER *\r
+ParseHiiQuestionOrderedList (\r
+ IN EFI_IFR_OP_HEADER *IfrOpCodeHeader\r
+ )\r
+{\r
+ EFI_IFR_ORDERED_LIST *IfrOrderedList;\r
+ VAR_CHECK_HII_QUESTION_ORDEREDLIST *OrderedList;\r
+ UINTN Length;\r
+ UINTN OptionCount;\r
+ UINT8 OptionWidth;\r
+\r
+ IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpCodeHeader;\r
+\r
+ GetOneOfOption (IfrOpCodeHeader, &OptionCount, &OptionWidth, NULL);\r
+\r
+ Length = sizeof (*OrderedList) + OptionCount * OptionWidth;\r
+\r
+ OrderedList = InternalVarCheckAllocateZeroPool (Length);\r
+ ASSERT (OrderedList != NULL);\r
+ OrderedList->OpCode = EFI_IFR_ORDERED_LIST_OP;\r
+ OrderedList->Length = (UINT8) Length;\r
+ OrderedList->VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset;\r
+ OrderedList->StorageWidth = OptionWidth;\r
+ OrderedList->MaxContainers = IfrOrderedList->MaxContainers;\r
+\r
+ GetOneOfOption (IfrOpCodeHeader, &OptionCount, &OptionWidth, OrderedList + 1);\r
+\r
+ return (VAR_CHECK_HII_QUESTION_HEADER *) OrderedList;\r
+}\r
+\r
+/**\r
+ Parse and create Hii Question node.\r
+\r
+ @param[in] HiiVariableNode Pointer to Hii Variable node.\r
+ @param[in] IfrOpCodeHeader Pointer to Ifr OpCode header.\r
+ @param[in] FromFv Hii Question from FV.\r
+\r
+**/\r
+VOID\r
+ParseHiiQuestion (\r
+ IN VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode,\r
+ IN EFI_IFR_OP_HEADER *IfrOpCodeHeader,\r
+ IN BOOLEAN FromFv\r
+ )\r
+{\r
+ VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion;\r
+\r
+ switch (IfrOpCodeHeader->OpCode) {\r
+ case EFI_IFR_ONE_OF_OP:\r
+ HiiQuestion = ParseHiiQuestionOneOf (IfrOpCodeHeader);\r
+ break;\r
+\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ HiiQuestion = ParseHiiQuestionCheckBox (IfrOpCodeHeader);\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_OP:\r
+ HiiQuestion = ParseHiiQuestionNumeric (IfrOpCodeHeader);\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ HiiQuestion = ParseHiiQuestionOrderedList (IfrOpCodeHeader);\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ return;\r
+ break;\r
+ }\r
+\r
+ if (HiiVariableNode->HiiQuestionArray[HiiQuestion->VarOffset] != NULL) {\r
+ MergeHiiQuestion (HiiVariableNode, HiiQuestion, FromFv);\r
+ } else {\r
+ HiiVariableNode->HiiQuestionArray[HiiQuestion->VarOffset] = HiiQuestion;\r
+ }\r
+}\r
+\r
+/**\r
+ Find Hii variable node by name and GUID.\r
+\r
+ @param[in] Name Pointer to variable name.\r
+ @param[in] Guid Pointer to vendor GUID.\r
+\r
+ @return Pointer to Hii Variable node.\r
+\r
+**/\r
+VAR_CHECK_HII_VARIABLE_NODE *\r
+FindHiiVariableNode (\r
+ IN CHAR16 *Name,\r
+ IN EFI_GUID *Guid\r
+ )\r
+{\r
+ VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode;\r
+ LIST_ENTRY *Link;\r
+\r
+ for (Link = mVarCheckHiiList.ForwardLink\r
+ ;Link != &mVarCheckHiiList\r
+ ;Link = Link->ForwardLink) {\r
+ HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (Link);\r
+\r
+ if ((StrCmp (Name, (CHAR16 *) (HiiVariableNode->HiiVariable + 1)) == 0) &&\r
+ CompareGuid (Guid, &HiiVariableNode->HiiVariable->Guid)) {\r
+ return HiiVariableNode;\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Find Hii variable node by var store id.\r
+\r
+ @param[in] VarStoreId Var store id.\r
+\r
+ @return Pointer to Hii Variable node.\r
+\r
+**/\r
+VAR_CHECK_HII_VARIABLE_NODE *\r
+FindHiiVariableNodeByVarStoreId (\r
+ IN EFI_VARSTORE_ID VarStoreId\r
+ )\r
+{\r
+ VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode;\r
+ LIST_ENTRY *Link;\r
+\r
+ if (VarStoreId == 0) {\r
+ //\r
+ // The variable store identifier, which is unique within the current form set.\r
+ // A value of zero is invalid.\r
+ //\r
+ return NULL;\r
+ }\r
+\r
+ for (Link = mVarCheckHiiList.ForwardLink\r
+ ;Link != &mVarCheckHiiList\r
+ ;Link = Link->ForwardLink) {\r
+ HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (Link);\r
+ //\r
+ // The variable store identifier, which is unique within the current form set.\r
+ //\r
+ if (VarStoreId == HiiVariableNode->VarStoreId) {\r
+ return HiiVariableNode;\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Destroy var store id in the Hii Variable node after parsing one Hii Package.\r
+\r
+**/\r
+VOID\r
+DestroyVarStoreId (\r
+ VOID\r
+ )\r
+{\r
+ VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode;\r
+ LIST_ENTRY *Link;\r
+\r
+ for (Link = mVarCheckHiiList.ForwardLink\r
+ ;Link != &mVarCheckHiiList\r
+ ;Link = Link->ForwardLink) {\r
+ HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (Link);\r
+ //\r
+ // The variable store identifier, which is unique within the current form set.\r
+ // A value of zero is invalid.\r
+ //\r
+ HiiVariableNode->VarStoreId = 0;\r
+ }\r
+}\r
+\r
+/**\r
+ Create Hii Variable node.\r
+\r
+ @param[in] IfrEfiVarStore Pointer to EFI VARSTORE.\r
+\r
+**/\r
+VOID\r
+CreateHiiVariableNode (\r
+ IN EFI_IFR_VARSTORE_EFI *IfrEfiVarStore\r
+ )\r
+{\r
+ VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode;\r
+ VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable;\r
+ UINTN HeaderLength;\r
+ CHAR16 *VarName;\r
+ UINTN VarNameSize;\r
+\r
+ //\r
+ // Get variable name.\r
+ //\r
+ VarNameSize = AsciiStrSize ((CHAR8 *) IfrEfiVarStore->Name) * 2;\r
+ if (VarNameSize > mMaxVarNameSize) {\r
+ mVarName = InternalVarCheckReallocatePool (mMaxVarNameSize, VarNameSize, mVarName);\r
+ ASSERT (mVarName != NULL);\r
+ mMaxVarNameSize = VarNameSize;\r
+ }\r
+ AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, mVarName);\r
+ VarName = mVarName;\r
+\r
+ HiiVariableNode = FindHiiVariableNode (\r
+ VarName,\r
+ &IfrEfiVarStore->Guid\r
+ );\r
+ if (HiiVariableNode == NULL) {\r
+ //\r
+ // Not found, then create new.\r
+ //\r
+ HeaderLength = sizeof (*HiiVariable) + VarNameSize;\r
+ HiiVariable = InternalVarCheckAllocateZeroPool (HeaderLength);\r
+ ASSERT (HiiVariable != NULL);\r
+ HiiVariable->Revision = VAR_CHECK_HII_REVISION;\r
+ HiiVariable->OpCode = EFI_IFR_VARSTORE_EFI_OP;\r
+ HiiVariable->HeaderLength = (UINT16) HeaderLength;\r
+ HiiVariable->Size = IfrEfiVarStore->Size;\r
+ HiiVariable->Attributes = IfrEfiVarStore->Attributes;\r
+ CopyGuid (&HiiVariable->Guid, &IfrEfiVarStore->Guid);\r
+ StrCpyS ((CHAR16 *) (HiiVariable + 1), VarNameSize / sizeof (CHAR16), VarName);\r
+\r
+ HiiVariableNode = InternalVarCheckAllocateZeroPool (sizeof (*HiiVariableNode));\r
+ ASSERT (HiiVariableNode != NULL);\r
+ HiiVariableNode->Signature = VAR_CHECK_HII_VARIABLE_NODE_SIGNATURE;\r
+ HiiVariableNode->HiiVariable = HiiVariable;\r
+ //\r
+ // The variable store identifier, which is unique within the current form set.\r
+ //\r
+ HiiVariableNode->VarStoreId = IfrEfiVarStore->VarStoreId;\r
+ HiiVariableNode->HiiQuestionArray = InternalVarCheckAllocateZeroPool (IfrEfiVarStore->Size * sizeof (VAR_CHECK_HII_QUESTION_HEADER *));\r
+\r
+ InsertTailList (&mVarCheckHiiList, &HiiVariableNode->Link);\r
+ } else {\r
+ HiiVariableNode->VarStoreId = IfrEfiVarStore->VarStoreId;\r
+ }\r
+}\r
+\r
+/**\r
+ Parse and create Hii Variable node list.\r
+\r
+ @param[in] HiiPackage Pointer to Hii Package.\r
+\r
+**/\r
+VOID\r
+ParseHiiVariable (\r
+ IN VOID *HiiPackage\r
+ )\r
+{\r
+ EFI_HII_PACKAGE_HEADER *HiiPackageHeader;\r
+ EFI_IFR_OP_HEADER *IfrOpCodeHeader;\r
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
+\r
+ HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiPackage;\r
+\r
+ switch (HiiPackageHeader->Type) {\r
+ case EFI_HII_PACKAGE_FORMS:\r
+ IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) (HiiPackageHeader + 1);\r
+\r
+ while ((UINTN) IfrOpCodeHeader < (UINTN) HiiPackageHeader + HiiPackageHeader->Length) {\r
+ switch (IfrOpCodeHeader->OpCode) {\r
+ case EFI_IFR_VARSTORE_EFI_OP:\r
+ //\r
+ // Come to EFI VARSTORE in Form Package.\r
+ //\r
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpCodeHeader;\r
+ if ((IfrEfiVarStore->Header.Length >= sizeof (EFI_IFR_VARSTORE_EFI)) &&\r
+ ((IfrEfiVarStore->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0)) {\r
+ //\r
+ // Only create node list for Hii Variable with NV attribute.\r
+ //\r
+ CreateHiiVariableNode (IfrEfiVarStore);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Var Check Parse Hii Package.\r
+\r
+ @param[in] HiiPackage Pointer to Hii Package.\r
+ @param[in] FromFv Hii Package from FV.\r
+\r
+**/\r
+VOID\r
+VarCheckParseHiiPackage (\r
+ IN VOID *HiiPackage,\r
+ IN BOOLEAN FromFv\r
+ )\r
+{\r
+ EFI_HII_PACKAGE_HEADER *HiiPackageHeader;\r
+ EFI_IFR_OP_HEADER *IfrOpCodeHeader;\r
+ VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode;\r
+\r
+ //\r
+ // Parse and create Hii Variable node list for this Hii Package.\r
+ //\r
+ ParseHiiVariable (HiiPackage);\r
+\r
+ HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiPackage;\r
+\r
+ switch (HiiPackageHeader->Type) {\r
+ case EFI_HII_PACKAGE_FORMS:\r
+ IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) (HiiPackageHeader + 1);\r
+\r
+ while ((UINTN) IfrOpCodeHeader < (UINTN) HiiPackageHeader + HiiPackageHeader->Length) {\r
+ switch (IfrOpCodeHeader->OpCode) {\r
+ case EFI_IFR_ONE_OF_OP:\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ case EFI_IFR_NUMERIC_OP:\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ HiiVariableNode = FindHiiVariableNodeByVarStoreId (((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.VarStoreId);\r
+ if ((HiiVariableNode == NULL) ||\r
+ //\r
+ // No related Hii Variable node found.\r
+ //\r
+ ((((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.Header.Prompt == 0) && (((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.Header.Help == 0))) {\r
+ //\r
+ // meanless IFR item introduced by ECP.\r
+ //\r
+ } else {\r
+ //\r
+ // Normal IFR\r
+ //\r
+ ParseHiiQuestion (HiiVariableNode, IfrOpCodeHeader, FromFv);\r
+ }\r
+ default:\r
+ break;\r
+ }\r
+ IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ DestroyVarStoreId ();\r
+}\r
+\r
+/**\r
+ Var Check Parse Hii Database.\r
+\r
+ @param[in] HiiDatabase Pointer to Hii Database.\r
+ @param[in] HiiDatabaseSize Hii Database size.\r
+\r
+**/\r
+VOID\r
+VarCheckParseHiiDatabase (\r
+ IN VOID *HiiDatabase,\r
+ IN UINTN HiiDatabaseSize\r
+ )\r
+{\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageListHeader;\r
+ EFI_HII_PACKAGE_HEADER *HiiPackageHeader;\r
+\r
+ HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *) HiiDatabase;\r
+\r
+ while ((UINTN) HiiPackageListHeader < ((UINTN) HiiDatabase + HiiDatabaseSize)) {\r
+ HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiPackageListHeader + 1);\r
+\r
+ while ((UINTN) HiiPackageHeader < ((UINTN) HiiPackageListHeader + HiiPackageListHeader->PackageLength)) {\r
+ //\r
+ // Parse Hii Pacakge.\r
+ //\r
+ VarCheckParseHiiPackage (HiiPackageHeader, FALSE);\r
+\r
+ HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINTN) HiiPackageHeader + HiiPackageHeader->Length);\r
+ }\r
+\r
+ HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *) ((UINTN) HiiPackageListHeader + HiiPackageListHeader->PackageLength);\r
+ }\r
+}\r
+\r
+/**\r
+ Destroy Hii Variable node.\r
+\r
+**/\r
+VOID\r
+DestroyHiiVariableNode (\r
+ VOID\r
+ )\r
+{\r
+ VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode;\r
+ LIST_ENTRY *HiiVariableLink;\r
+ UINTN Index;\r
+\r
+ while (mVarCheckHiiList.ForwardLink != &mVarCheckHiiList) {\r
+ HiiVariableLink = mVarCheckHiiList.ForwardLink;\r
+ HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (HiiVariableLink);\r
+\r
+ RemoveEntryList (&HiiVariableNode->Link);\r
+\r
+ //\r
+ // Free the allocated buffer.\r
+ //\r
+ for (Index = 0; Index < HiiVariableNode->HiiVariable->Size; Index++) {\r
+ if (HiiVariableNode->HiiQuestionArray[Index] != NULL) {\r
+ InternalVarCheckFreePool (HiiVariableNode->HiiQuestionArray[Index]);\r
+ }\r
+ }\r
+ InternalVarCheckFreePool (HiiVariableNode->HiiQuestionArray);\r
+ InternalVarCheckFreePool (HiiVariableNode->HiiVariable);\r
+ InternalVarCheckFreePool (HiiVariableNode);\r
+ }\r
+}\r
+\r
+/**\r
+ Build VarCheckHiiBin.\r
+\r
+ @param[out] Size Pointer to VarCheckHii size.\r
+\r
+ @return Pointer to VarCheckHiiBin.\r
+\r
+**/\r
+VOID *\r
+BuildVarCheckHiiBin (\r
+ OUT UINTN *Size\r
+ )\r
+{\r
+ VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode;\r
+ LIST_ENTRY *HiiVariableLink;\r
+ UINTN Index;\r
+ VOID *Data;\r
+ UINT8 *Ptr;\r
+ UINT32 BinSize;\r
+ UINT32 HiiVariableLength;\r
+\r
+ //\r
+ // Get Size\r
+ //\r
+ BinSize = 0;\r
+\r
+ for (HiiVariableLink = mVarCheckHiiList.ForwardLink\r
+ ;HiiVariableLink != &mVarCheckHiiList\r
+ ;HiiVariableLink = HiiVariableLink->ForwardLink) {\r
+ //\r
+ // For Hii Variable header align.\r
+ //\r
+ BinSize = (UINT32) HEADER_ALIGN (BinSize);\r
+\r
+ HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (HiiVariableLink);\r
+ HiiVariableLength = HiiVariableNode->HiiVariable->HeaderLength;\r
+\r
+ for (Index = 0; Index < HiiVariableNode->HiiVariable->Size; Index++) {\r
+ if (HiiVariableNode->HiiQuestionArray[Index] != NULL) {\r
+ //\r
+ // For Hii Question header align.\r
+ //\r
+ HiiVariableLength = (UINT32) HEADER_ALIGN (HiiVariableLength);\r
+ HiiVariableLength += HiiVariableNode->HiiQuestionArray[Index]->Length;\r
+ }\r
+ }\r
+\r
+ HiiVariableNode->HiiVariable->Length = HiiVariableLength;\r
+ BinSize += HiiVariableLength;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiBin - size = 0x%x\n", BinSize));\r
+ if (BinSize == 0) {\r
+ *Size = BinSize;\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // AllocatePages () and AllocatePool () from gBS are used for the process of VarCheckHiiBin generation.\r
+ // Only here AllocateRuntimeZeroPool () from MemoryAllocateLib is used for runtime access\r
+ // in SetVariable check handler.\r
+ //\r
+ Data = AllocateRuntimeZeroPool (BinSize);\r
+ ASSERT (Data != NULL);\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiBin - built at 0x%x\n", Data));\r
+\r
+ //\r
+ // Gen Data\r
+ //\r
+ Ptr = Data;\r
+ for (HiiVariableLink = mVarCheckHiiList.ForwardLink\r
+ ;HiiVariableLink != &mVarCheckHiiList\r
+ ;HiiVariableLink = HiiVariableLink->ForwardLink) {\r
+ //\r
+ // For Hii Variable header align.\r
+ //\r
+ Ptr = (UINT8 *) HEADER_ALIGN (Ptr);\r
+\r
+ HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (HiiVariableLink);\r
+ CopyMem (Ptr, HiiVariableNode->HiiVariable, HiiVariableNode->HiiVariable->HeaderLength);\r
+ Ptr += HiiVariableNode->HiiVariable->HeaderLength;\r
+\r
+ for (Index = 0; Index < HiiVariableNode->HiiVariable->Size; Index++) {\r
+ if (HiiVariableNode->HiiQuestionArray[Index] != NULL) {\r
+ //\r
+ // For Hii Question header align.\r
+ //\r
+ Ptr = (UINT8 *) HEADER_ALIGN (Ptr);\r
+ CopyMem (Ptr, HiiVariableNode->HiiQuestionArray[Index], HiiVariableNode->HiiQuestionArray[Index]->Length);\r
+ Ptr += HiiVariableNode->HiiQuestionArray[Index]->Length;\r
+ }\r
+ }\r
+ }\r
+\r
+ *Size = BinSize;\r
+ return Data;\r
+}\r
+\r
+/**\r
+ Generate VarCheckHiiBin from Hii Database and FV.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VarCheckHiiGen (\r
+ VOID\r
+ )\r
+{\r
+ VarCheckHiiGenFromHiiDatabase ();\r
+ VarCheckHiiGenFromFv ();\r
+\r
+ mVarCheckHiiBin = BuildVarCheckHiiBin (&mVarCheckHiiBinSize);\r
+ if (mVarCheckHiiBin == NULL) {\r
+ DEBUG ((EFI_D_INFO, "[VarCheckHii] This driver could be removed from *.dsc and *.fdf\n"));\r
+ return;\r
+ }\r
+\r
+ DestroyHiiVariableNode ();\r
+ if (mVarName != NULL) {\r
+ InternalVarCheckFreePool (mVarName);\r
+ }\r
+\r
+#ifdef DUMP_VAR_CHECK_HII\r
+ DEBUG_CODE (\r
+ DumpVarCheckHii (mVarCheckHiiBin, mVarCheckHiiBinSize);\r
+ );\r
+#endif\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Var Check Hii generation from FV.\r
+\r
+Copyright (c) 2015, 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 "VarCheckHiiGen.h"\r
+\r
+// {d0bc7cb4-6a47-495f-aa11-710746da06a2}\r
+#define EFI_VFR_ATTRACT_GUID \\r
+{ 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } }\r
+\r
+EFI_GUID gVfrArrayAttractGuid = EFI_VFR_ATTRACT_GUID;\r
+\r
+#define ALL_FF_GUID \\r
+{ 0xFFFFFFFF, 0xFFFF, 0xFFFF, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }\r
+\r
+EFI_GUID mAllFfGuid = ALL_FF_GUID;\r
+\r
+#define VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE SIGNATURE_32 ('V', 'D', 'R', 'I')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+ EFI_GUID *DriverGuid;\r
+} VAR_CHECK_VFR_DRIVER_INFO;\r
+\r
+LIST_ENTRY mVfrDriverList = INITIALIZE_LIST_HEAD_VARIABLE (mVfrDriverList);\r
+\r
+#define VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK(a) CR (a, VAR_CHECK_VFR_DRIVER_INFO, Link, VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE)\r
+\r
+#define MAX_MATCH_GUID_NUM 100\r
+\r
+/**\r
+ Get the address by Guid.\r
+\r
+ Parse the FFS and find the GUID address.\r
+ There may be multiple Guids matching the searched Guid.\r
+\r
+ @param Ffs Pointer to the FFS.\r
+ @param Guid Guid to find.\r
+ @param Length The length of FFS.\r
+ @param Offset Pointer to pointer to the offset.\r
+ @param NumOfMatchingGuid The number of matching Guid.\r
+\r
+ @retval EFI_SUCCESS One or multiple Guids matching the searched Guid.\r
+ @retval EFI_NOT_FOUND No Guid matching the searched Guid.\r
+\r
+**/\r
+EFI_STATUS\r
+GetAddressByGuid (\r
+ IN VOID *Ffs,\r
+ IN EFI_GUID *Guid,\r
+ IN UINTN Length,\r
+ OUT UINTN **Offset,\r
+ OUT UINT8 *NumOfMatchingGuid\r
+ )\r
+{\r
+ UINTN LoopControl;\r
+ BOOLEAN Found;\r
+\r
+ if((Ffs == NULL) || (Guid == NULL) || (Length == 0)){\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (NumOfMatchingGuid != NULL) {\r
+ *NumOfMatchingGuid = 0;\r
+ }\r
+\r
+ Found = FALSE;\r
+ for (LoopControl = 0; LoopControl < Length; LoopControl++) {\r
+ if (CompareGuid (Guid, (EFI_GUID *) ((UINT8 *) Ffs + LoopControl))) {\r
+ Found = TRUE;\r
+ //\r
+ // If NumOfMatchGuid or Offset are NULL, means user only want\r
+ // to check whether current FFS includes this Guid or not.\r
+ //\r
+ if ((NumOfMatchingGuid != NULL) && (Offset != NULL)) {\r
+ if (*NumOfMatchingGuid == 0) {\r
+ *Offset = InternalVarCheckAllocateZeroPool (sizeof (UINTN) * MAX_MATCH_GUID_NUM);\r
+ ASSERT (*Offset != NULL);\r
+ }\r
+ *(*Offset + *NumOfMatchingGuid) = LoopControl + sizeof (EFI_GUID);\r
+ (*NumOfMatchingGuid)++;\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);\r
+}\r
+\r
+/**\r
+ Search the VfrBin Base address.\r
+\r
+ According to the known GUID gVfrArrayAttractGuid to get the base address from FFS.\r
+\r
+ @param Ffs Pointer to the FFS.\r
+ @param EfiAddr Pointer to the EFI in FFS\r
+ @param Length The length of FFS.\r
+ @param Offset Pointer to pointer to the Addr (Offset).\r
+ @param NumOfMatchingOffset The number of Addr (Offset).\r
+\r
+ @retval EFI_SUCCESS Get the address successfully.\r
+ @retval EFI_NOT_FOUND No VfrBin found.\r
+\r
+**/\r
+EFI_STATUS\r
+SearchVfrBinInFfs (\r
+ IN VOID *Ffs,\r
+ IN VOID *EfiAddr,\r
+ IN UINTN Length,\r
+ OUT UINTN **Offset,\r
+ OUT UINT8 *NumOfMatchingOffset\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ UINTN VirOffValue;\r
+\r
+ if ((Ffs == NULL) || (Offset == NULL)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ Status = GetAddressByGuid (\r
+ Ffs,\r
+ &gVfrArrayAttractGuid,\r
+ Length,\r
+ Offset,\r
+ NumOfMatchingOffset\r
+ );\r
+ if (Status != EFI_SUCCESS) {\r
+ return Status;\r
+ }\r
+\r
+ for (Index = 0; Index < *NumOfMatchingOffset; Index++) {\r
+ //\r
+ // Got the virOffset after the GUID\r
+ //\r
+ VirOffValue = *(UINTN *) ((UINTN) Ffs + *(*Offset + Index));\r
+ //\r
+ // Transfer the offset to the VA address. One modules may own multiple VfrBin address.\r
+ //\r
+ *(*Offset + Index) = (UINTN) EfiAddr + VirOffValue;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Parse FFS.\r
+\r
+ @param[in] Fv2 Pointer to Fv2 protocol.\r
+ @param[in] DriverGuid Pointer to driver GUID.\r
+\r
+ @return Found the driver in the FV or not.\r
+\r
+**/\r
+BOOLEAN\r
+ParseFfs (\r
+ IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2,\r
+ IN EFI_GUID *DriverGuid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FV_FILETYPE FoundType;\r
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
+ UINT32 AuthenticationStatus;\r
+ UINTN Size;\r
+ VOID *Buffer;\r
+ UINTN SectionSize;\r
+ VOID *SectionBuffer;\r
+ UINTN VfrBinIndex;\r
+ UINT8 NumberofMatchingVfrBin;\r
+ UINTN *VfrBinBaseAddress;\r
+\r
+ Status = Fv2->ReadFile (\r
+ Fv2,\r
+ DriverGuid,\r
+ NULL,\r
+ &Size,\r
+ &FoundType,\r
+ &FileAttributes,\r
+ &AuthenticationStatus\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ Buffer = NULL;\r
+ Status = Fv2->ReadSection (\r
+ Fv2,\r
+ DriverGuid,\r
+ EFI_SECTION_RAW,\r
+ 0, // Instance\r
+ &Buffer,\r
+ &Size,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = SearchVfrBinInFfs (Buffer, 0, Size, &VfrBinBaseAddress, &NumberofMatchingVfrBin);\r
+ if (!EFI_ERROR (Status)) {\r
+ SectionBuffer = NULL;\r
+ Status = Fv2->ReadSection (\r
+ Fv2,\r
+ DriverGuid,\r
+ EFI_SECTION_PE32,\r
+ 0, // Instance\r
+ &SectionBuffer,\r
+ &SectionSize,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_INFO, "FfsNameGuid - %g\n", DriverGuid));\r
+ DEBUG ((EFI_D_INFO, "NumberofMatchingVfrBin - 0x%02x\n", NumberofMatchingVfrBin));\r
+\r
+ for (VfrBinIndex = 0; VfrBinIndex < NumberofMatchingVfrBin; VfrBinIndex++) {\r
+#ifdef DUMP_HII_DATA\r
+ DEBUG_CODE (\r
+ DumpHiiPackage ((UINT8 *) (UINTN) SectionBuffer + VfrBinBaseAddress[VfrBinIndex] + sizeof (UINT32));\r
+ );\r
+#endif\r
+ VarCheckParseHiiPackage ((UINT8 *) (UINTN) SectionBuffer + VfrBinBaseAddress[VfrBinIndex] + sizeof (UINT32), TRUE);\r
+ }\r
+\r
+ FreePool (SectionBuffer);\r
+ }\r
+\r
+ InternalVarCheckFreePool (VfrBinBaseAddress);\r
+ }\r
+\r
+ FreePool (Buffer);\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Parse FVs.\r
+\r
+ @param[in] ScanAll Scan all modules in all FVs or not.\r
+\r
+**/\r
+VOID\r
+ParseFv (\r
+ IN BOOLEAN ScanAll\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2;\r
+ VOID *Key;\r
+ EFI_FV_FILETYPE FileType;\r
+ EFI_GUID NameGuid;\r
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
+ UINTN Size;\r
+ UINTN FfsIndex;\r
+ VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;\r
+ LIST_ENTRY *VfrDriverLink;\r
+\r
+ HandleBuffer = NULL;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Search all FVs\r
+ //\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ DEBUG ((EFI_D_INFO, "FvIndex - %x\n", Index));\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ (VOID **) &Fv2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ DEBUG_CODE (\r
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *Fvb2;\r
+ EFI_PHYSICAL_ADDRESS FvAddress;\r
+ UINT64 FvSize;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiFirmwareVolumeBlock2ProtocolGuid,\r
+ (VOID **) &Fvb2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = Fvb2->GetPhysicalAddress (Fvb2, &FvAddress);\r
+ if (!EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_INFO, "FvAddress - 0x%08x\n", FvAddress));\r
+ FvSize = ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvAddress)->FvLength;\r
+ DEBUG ((EFI_D_INFO, "FvSize - 0x%08x\n", FvSize));\r
+ }\r
+ );\r
+\r
+ if (ScanAll) {\r
+ //\r
+ // Need to parse all modules in all FVs.\r
+ //\r
+ Key = InternalVarCheckAllocateZeroPool (Fv2->KeySize);\r
+ ASSERT (Key != NULL);\r
+\r
+ for (FfsIndex = 0; ; FfsIndex++) {\r
+ FileType = EFI_FV_FILETYPE_ALL;\r
+ Status = Fv2->GetNextFile (\r
+ Fv2,\r
+ Key,\r
+ &FileType,\r
+ &NameGuid,\r
+ &FileAttributes,\r
+ &Size\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ ParseFfs (Fv2, &NameGuid);\r
+ }\r
+\r
+ InternalVarCheckFreePool (Key);\r
+ } else {\r
+ //\r
+ // Only parse drivers in the VFR drivers list.\r
+ //\r
+ VfrDriverLink = mVfrDriverList.ForwardLink;\r
+ while (VfrDriverLink != &mVfrDriverList) {\r
+ VfrDriverInfo = VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK (VfrDriverLink);\r
+ VfrDriverLink = VfrDriverLink->ForwardLink;\r
+ if (ParseFfs (Fv2, VfrDriverInfo->DriverGuid)) {\r
+ //\r
+ // Found the driver in the FV.\r
+ //\r
+ RemoveEntryList (&VfrDriverInfo->Link);\r
+ InternalVarCheckFreePool (VfrDriverInfo);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ FreePool (HandleBuffer);\r
+}\r
+\r
+/**\r
+ Create Vfr Driver List.\r
+\r
+ @param[in] DriverGuidArray Driver Guid Array\r
+\r
+**/\r
+VOID\r
+CreateVfrDriverList (\r
+ IN EFI_GUID *DriverGuidArray\r
+ )\r
+{\r
+ UINTN Index;\r
+ VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;\r
+\r
+ for (Index = 0; !CompareGuid (&DriverGuidArray[Index], &gZeroGuid); Index++) {\r
+ DEBUG ((EFI_D_INFO, "CreateVfrDriverList: %g\n", &DriverGuidArray[Index]));\r
+ VfrDriverInfo = InternalVarCheckAllocateZeroPool (sizeof (*VfrDriverInfo));\r
+ ASSERT (VfrDriverInfo != NULL);\r
+ VfrDriverInfo->Signature = VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE;\r
+ VfrDriverInfo->DriverGuid = &DriverGuidArray[Index];\r
+ InsertTailList (&mVfrDriverList, &VfrDriverInfo->Link);\r
+ }\r
+}\r
+\r
+/**\r
+ Destroy Vfr Driver List.\r
+\r
+**/\r
+VOID\r
+DestroyVfrDriverList (\r
+ VOID\r
+ )\r
+{\r
+ VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;\r
+ LIST_ENTRY *VfrDriverLink;\r
+\r
+ while (mVfrDriverList.ForwardLink != &mVfrDriverList) {\r
+ VfrDriverLink = mVfrDriverList.ForwardLink;\r
+ VfrDriverInfo = VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK (VfrDriverLink);\r
+ RemoveEntryList (&VfrDriverInfo->Link);\r
+ InternalVarCheckFreePool (VfrDriverInfo);\r
+ }\r
+}\r
+\r
+/**\r
+ Generate from FV.\r
+\r
+**/\r
+VOID\r
+VarCheckHiiGenFromFv (\r
+ VOID\r
+ )\r
+{\r
+ EFI_GUID *DriverGuidArray;\r
+ BOOLEAN ScanAll;\r
+\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiGenDxeFromFv\n"));\r
+\r
+ //\r
+ // Get vfr driver guid array from PCD.\r
+ //\r
+ DriverGuidArray = (EFI_GUID *) PcdGetPtr (PcdVarCheckVfrDriverGuidArray);\r
+\r
+ if (CompareGuid (&DriverGuidArray[0], &gZeroGuid)) {\r
+ //\r
+ // No VFR driver will be parsed from FVs.\r
+ //\r
+ return;\r
+ }\r
+\r
+ if (CompareGuid (&DriverGuidArray[0], &mAllFfGuid)) {\r
+ ScanAll = TRUE;\r
+ } else {\r
+ ScanAll = FALSE;\r
+ CreateVfrDriverList (DriverGuidArray);\r
+ }\r
+\r
+ ParseFv (ScanAll);\r
+\r
+ if (!ScanAll) {\r
+ DestroyVfrDriverList ();\r
+ }\r
+}\r
--- /dev/null
+/** @file\r
+ Var Check Hii handler.\r
+\r
+Copyright (c) 2015, 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 "VarCheckHii.h"\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mVarCheckHiiHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};\r
+\r
+/**\r
+ Dump some hexadecimal data.\r
+\r
+ @param[in] Indent How many spaces to indent the output.\r
+ @param[in] Offset The offset of the dump.\r
+ @param[in] DataSize The size in bytes of UserData.\r
+ @param[in] UserData The data to dump.\r
+\r
+**/\r
+VOID\r
+VarCheckHiiInternalDumpHex (\r
+ IN UINTN Indent,\r
+ IN UINTN Offset,\r
+ IN UINTN DataSize,\r
+ IN VOID *UserData\r
+ )\r
+{\r
+ UINT8 *Data;\r
+\r
+ CHAR8 Val[50];\r
+\r
+ CHAR8 Str[20];\r
+\r
+ UINT8 TempByte;\r
+ UINTN Size;\r
+ UINTN Index;\r
+\r
+ Data = UserData;\r
+ while (DataSize != 0) {\r
+ Size = 16;\r
+ if (Size > DataSize) {\r
+ Size = DataSize;\r
+ }\r
+\r
+ for (Index = 0; Index < Size; Index += 1) {\r
+ TempByte = Data[Index];\r
+ Val[Index * 3 + 0] = mVarCheckHiiHex[TempByte >> 4];\r
+ Val[Index * 3 + 1] = mVarCheckHiiHex[TempByte & 0xF];\r
+ Val[Index * 3 + 2] = (CHAR8) ((Index == 7) ? '-' : ' ');\r
+ Str[Index] = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);\r
+ }\r
+\r
+ Val[Index * 3] = 0;\r
+ Str[Index] = 0;\r
+ DEBUG ((EFI_D_INFO, "%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str));\r
+\r
+ Data += Size;\r
+ Offset += Size;\r
+ DataSize -= Size;\r
+ }\r
+}\r
+\r
+/**\r
+ Var Check Hii Question.\r
+\r
+ @param[in] HiiQuestion Pointer to Hii Question\r
+ @param[in] Data Data pointer.\r
+ @param[in] DataSize Size of Data to set.\r
+\r
+ @retval TRUE Check pass\r
+ @retval FALSE Check fail.\r
+\r
+**/\r
+BOOLEAN\r
+VarCheckHiiQuestion (\r
+ IN VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion,\r
+ IN VOID *Data,\r
+ IN UINTN DataSize\r
+ )\r
+{\r
+ UINT64 OneData;\r
+ UINT64 Minimum;\r
+ UINT64 Maximum;\r
+ UINT64 OneValue;\r
+ UINT8 *Ptr;\r
+ UINT8 Index;\r
+ UINT8 MaxContainers;\r
+\r
+ if ((UINTN) (HiiQuestion->VarOffset + HiiQuestion->StorageWidth) > DataSize) {\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiQuestion fail: (VarOffset(0x%04x) + StorageWidth(0x%02x)) > Size(0x%x)\n", HiiQuestion->VarOffset, HiiQuestion->StorageWidth, DataSize));\r
+ return FALSE;\r
+ }\r
+\r
+ OneData = 0;\r
+ CopyMem (&OneData, (UINT8 *) Data + HiiQuestion->VarOffset, HiiQuestion->StorageWidth);\r
+\r
+ switch (HiiQuestion->OpCode) {\r
+ case EFI_IFR_ONE_OF_OP:\r
+ Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion + 1);\r
+ while ((UINTN) Ptr < (UINTN) HiiQuestion + HiiQuestion->Length) {\r
+ OneValue = 0;\r
+ CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);\r
+ if (OneData == OneValue) {\r
+ //\r
+ // Match\r
+ //\r
+ break;\r
+ }\r
+ Ptr += HiiQuestion->StorageWidth;\r
+ }\r
+ if ((UINTN) Ptr >= ((UINTN) HiiQuestion + HiiQuestion->Length)) {\r
+ //\r
+ // No match\r
+ //\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiQuestion fail: OneOf mismatch (0x%lx)\n", OneData));\r
+ DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *) HiiQuestion););\r
+ return FALSE;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ if ((OneData != 0) && (OneData != 1)) {\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiQuestion fail: CheckBox mismatch (0x%lx)\n", OneData));\r
+ DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *) HiiQuestion););\r
+ return FALSE;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_OP:\r
+ Minimum = 0;\r
+ Maximum = 0;\r
+ Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion + 1);\r
+ CopyMem (&Minimum, Ptr, HiiQuestion->StorageWidth);\r
+ Ptr += HiiQuestion->StorageWidth;\r
+ CopyMem (&Maximum, Ptr, HiiQuestion->StorageWidth);\r
+ Ptr += HiiQuestion->StorageWidth;\r
+\r
+ //\r
+ // No need to check Step, because it is ONLY for UI.\r
+ //\r
+ if ((OneData < Minimum) || (OneData > Maximum)) {\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiQuestion fail: Numeric mismatch (0x%lx)\n", OneData));\r
+ DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *) HiiQuestion););\r
+ return FALSE;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ MaxContainers = ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion)->MaxContainers;\r
+ if ((UINTN) (HiiQuestion->VarOffset + HiiQuestion->StorageWidth * MaxContainers) > DataSize) {\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiQuestion fail: (VarOffset(0x%04x) + StorageWidth(0x%02x) * MaxContainers(0x%02x)) > Size(0x%x)\n", HiiQuestion->VarOffset, HiiQuestion->StorageWidth, MaxContainers, DataSize));\r
+ return FALSE;\r
+ }\r
+ for (Index = 0; Index < MaxContainers; Index++) {\r
+ OneData = 0;\r
+ CopyMem (&OneData, (UINT8 *) Data + HiiQuestion->VarOffset + HiiQuestion->StorageWidth * Index, HiiQuestion->StorageWidth);\r
+ if (OneData == 0) {\r
+ //\r
+ // The value of 0 is used to determine if a particular "slot" in the array is empty.\r
+ //\r
+ continue;\r
+ }\r
+\r
+ Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion + 1);\r
+ while ((UINTN) Ptr < ((UINTN) HiiQuestion + HiiQuestion->Length)) {\r
+ OneValue = 0;\r
+ CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);\r
+ if (OneData == OneValue) {\r
+ //\r
+ // Match\r
+ //\r
+ break;\r
+ }\r
+ Ptr += HiiQuestion->StorageWidth;\r
+ }\r
+ if ((UINTN) Ptr >= ((UINTN) HiiQuestion + HiiQuestion->Length)) {\r
+ //\r
+ // No match\r
+ //\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiQuestion fail: OrderedList mismatch\n"));\r
+ DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->StorageWidth * MaxContainers, (UINT8 *) Data + HiiQuestion->VarOffset););\r
+ DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *) HiiQuestion););\r
+ return FALSE;\r
+ }\r
+ }\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+VAR_CHECK_HII_VARIABLE_HEADER *mVarCheckHiiBin = NULL;\r
+UINTN mVarCheckHiiBinSize = 0;\r
+\r
+/**\r
+ SetVariable check handler HII.\r
+\r
+ @param[in] VariableName Name of Variable to set.\r
+ @param[in] VendorGuid Variable vendor GUID.\r
+ @param[in] Attributes Attribute value of the variable.\r
+ @param[in] DataSize Size of Data to set.\r
+ @param[in] Data Data pointer.\r
+\r
+ @retval EFI_SUCCESS The SetVariable check result was success.\r
+ @retval EFI_SECURITY_VIOLATION Check fail.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetVariableCheckHandlerHii (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN UINT32 Attributes,\r
+ IN UINTN DataSize,\r
+ IN VOID *Data\r
+ )\r
+{\r
+ VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable;\r
+ VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion;\r
+\r
+ if (mVarCheckHiiBin == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0)) {\r
+ //\r
+ // Do not check delete variable.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // For Hii Variable header align.\r
+ //\r
+ HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *) HEADER_ALIGN (mVarCheckHiiBin);\r
+ while ((UINTN) HiiVariable < ((UINTN) mVarCheckHiiBin + mVarCheckHiiBinSize)) {\r
+ if ((StrCmp ((CHAR16 *) (HiiVariable + 1), VariableName) == 0) &&\r
+ (CompareGuid (&HiiVariable->Guid, VendorGuid))) {\r
+ //\r
+ // Found the Hii Variable that could be used to do check.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiVariable - %s:%g with Attributes = 0x%08x Size = 0x%x\n", VariableName, VendorGuid, Attributes, DataSize));\r
+ if (HiiVariable->Attributes != Attributes) {\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiVariable fail for Attributes - 0x%08x\n", HiiVariable->Attributes));\r
+ return EFI_SECURITY_VIOLATION;\r
+ }\r
+\r
+ if (DataSize == 0) {\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiVariable - CHECK PASS with DataSize == 0 !\n"));\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (HiiVariable->Size != DataSize) {\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiVariable fail for Size - 0x%x\n", HiiVariable->Size));\r
+ return EFI_SECURITY_VIOLATION;\r
+ }\r
+\r
+ //\r
+ // Do the check.\r
+ // For Hii Question header align.\r
+ //\r
+ HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *) HEADER_ALIGN (((UINTN) HiiVariable + HiiVariable->HeaderLength));\r
+ while ((UINTN) HiiQuestion < ((UINTN) HiiVariable + HiiVariable->Length)) {\r
+ if (!VarCheckHiiQuestion (HiiQuestion, Data, DataSize)) {\r
+ return EFI_SECURITY_VIOLATION;\r
+ }\r
+ //\r
+ // For Hii Question header align.\r
+ //\r
+ HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *) HEADER_ALIGN (((UINTN) HiiQuestion + HiiQuestion->Length));\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiVariable - ALL CHECK PASS!\n"));\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // For Hii Variable header align.\r
+ //\r
+ HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *) HEADER_ALIGN (((UINTN) HiiVariable + HiiVariable->Length));\r
+ }\r
+\r
+ // Not found, so pass.\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+#ifdef DUMP_VAR_CHECK_HII\r
+GLOBAL_REMOVE_IF_UNREFERENCED VAR_CHECK_HII_OPCODE_STRING mHiiOpCodeStringTable[] = {\r
+ {EFI_IFR_VARSTORE_EFI_OP, "EfiVarStore"},\r
+ {EFI_IFR_ONE_OF_OP, "OneOf"},\r
+ {EFI_IFR_CHECKBOX_OP, "CheckBox"},\r
+ {EFI_IFR_NUMERIC_OP, "Numeric"},\r
+ {EFI_IFR_ORDERED_LIST_OP, "OrderedList"},\r
+};\r
+\r
+/**\r
+ HII opcode to string.\r
+\r
+ @param[in] HiiOpCode Hii OpCode.\r
+\r
+ @return Pointer to string.\r
+\r
+**/\r
+CHAR8 *\r
+HiiOpCodeToStr (\r
+ IN UINT8 HiiOpCode\r
+ )\r
+{\r
+ UINTN Index;\r
+ for (Index = 0; Index < sizeof (mHiiOpCodeStringTable) / sizeof (mHiiOpCodeStringTable[0]); Index++) {\r
+ if (mHiiOpCodeStringTable[Index].HiiOpCode == HiiOpCode) {\r
+ return mHiiOpCodeStringTable[Index].HiiOpCodeStr;\r
+ }\r
+ }\r
+\r
+ return "<UnknownHiiOpCode>";\r
+}\r
+\r
+/**\r
+ Dump Hii Question.\r
+\r
+ @param[in] HiiQuestion Pointer to Hii Question.\r
+\r
+**/\r
+VOID\r
+DumpHiiQuestion (\r
+ IN VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion\r
+ )\r
+{\r
+ UINT64 Minimum;\r
+ UINT64 Maximum;\r
+ UINT64 OneValue;\r
+ UINT8 *Ptr;\r
+\r
+ DEBUG ((EFI_D_INFO, " VAR_CHECK_HII_QUESTION_HEADER\n"));\r
+ DEBUG ((EFI_D_INFO, " OpCode - 0x%02x (%a)\n", HiiQuestion->OpCode, HiiOpCodeToStr (HiiQuestion->OpCode)));\r
+ DEBUG ((EFI_D_INFO, " Length - 0x%02x\n", HiiQuestion->Length));\r
+ DEBUG ((EFI_D_INFO, " VarOffset - 0x%04x\n", HiiQuestion->VarOffset));\r
+ DEBUG ((EFI_D_INFO, " StorageWidth - 0x%02x\n", HiiQuestion->StorageWidth));\r
+\r
+ switch (HiiQuestion->OpCode) {\r
+ case EFI_IFR_ONE_OF_OP:\r
+ Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion + 1);\r
+ while ((UINTN) Ptr < ((UINTN) HiiQuestion + HiiQuestion->Length)) {\r
+ OneValue = 0;\r
+ CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);\r
+ switch (HiiQuestion->StorageWidth) {\r
+ case sizeof (UINT8):\r
+ DEBUG ((EFI_D_INFO, " OneOfOption - 0x%02x\n", OneValue));\r
+ break;\r
+ case sizeof (UINT16):\r
+ DEBUG ((EFI_D_INFO, " OneOfOption - 0x%04x\n", OneValue));\r
+ break;\r
+ case sizeof (UINT32):\r
+ DEBUG ((EFI_D_INFO, " OneOfOption - 0x%08x\n", OneValue));\r
+ break;\r
+ case sizeof (UINT64):\r
+ DEBUG ((EFI_D_INFO, " OneOfOption - 0x%016lx\n", OneValue));\r
+ break;\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+ Ptr += HiiQuestion->StorageWidth;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_OP:\r
+ Minimum = 0;\r
+ Maximum = 0;\r
+ Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion + 1);\r
+ CopyMem (&Minimum, Ptr, HiiQuestion->StorageWidth);\r
+ Ptr += HiiQuestion->StorageWidth;\r
+ CopyMem (&Maximum, Ptr, HiiQuestion->StorageWidth);\r
+ Ptr += HiiQuestion->StorageWidth;\r
+\r
+ switch (HiiQuestion->StorageWidth) {\r
+ case sizeof (UINT8):\r
+ DEBUG ((EFI_D_INFO, " Minimum - 0x%02x\n", Minimum));\r
+ DEBUG ((EFI_D_INFO, " Maximum - 0x%02x\n", Maximum));\r
+ break;\r
+ case sizeof (UINT16):\r
+ DEBUG ((EFI_D_INFO, " Minimum - 0x%04x\n", Minimum));\r
+ DEBUG ((EFI_D_INFO, " Maximum - 0x%04x\n", Maximum));\r
+ break;\r
+ case sizeof (UINT32):\r
+ DEBUG ((EFI_D_INFO, " Minimum - 0x%08x\n", Minimum));\r
+ DEBUG ((EFI_D_INFO, " Maximum - 0x%08x\n", Maximum));\r
+ break;\r
+ case sizeof (UINT64):\r
+ DEBUG ((EFI_D_INFO, " Minimum - 0x%016lx\n", Minimum));\r
+ DEBUG ((EFI_D_INFO, " Maximum - 0x%016lx\n", Maximum));\r
+ break;\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ DEBUG ((EFI_D_INFO, " MaxContainers - 0x%02x\n", ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion)->MaxContainers));\r
+ Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion + 1);\r
+ while ((UINTN) Ptr < ((UINTN) HiiQuestion + HiiQuestion->Length)) {\r
+ OneValue = 0;\r
+ CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);\r
+ switch (HiiQuestion->StorageWidth) {\r
+ case sizeof (UINT8):\r
+ DEBUG ((EFI_D_INFO, " OneOfOption - 0x%02x\n", OneValue));\r
+ break;\r
+ case sizeof (UINT16):\r
+ DEBUG ((EFI_D_INFO, " OneOfOption - 0x%04x\n", OneValue));\r
+ break;\r
+ case sizeof (UINT32):\r
+ DEBUG ((EFI_D_INFO, " OneOfOption - 0x%08x\n", OneValue));\r
+ break;\r
+ case sizeof (UINT64):\r
+ DEBUG ((EFI_D_INFO, " OneOfOption - 0x%016lx\n", OneValue));\r
+ break;\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+ Ptr += HiiQuestion->StorageWidth;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Dump Hii Variable.\r
+\r
+ @param[in] HiiVariable Pointer to Hii Variable.\r
+\r
+**/\r
+VOID\r
+DumpHiiVariable (\r
+ IN VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable\r
+ )\r
+{\r
+ VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion;\r
+\r
+ DEBUG ((EFI_D_INFO, "VAR_CHECK_HII_VARIABLE_HEADER\n"));\r
+ DEBUG ((EFI_D_INFO, " Revision - 0x%04x\n", HiiVariable->Revision));\r
+ DEBUG ((EFI_D_INFO, " HeaderLength - 0x%04x\n", HiiVariable->HeaderLength));\r
+ DEBUG ((EFI_D_INFO, " Length - 0x%08x\n", HiiVariable->Length));\r
+ DEBUG ((EFI_D_INFO, " OpCode - 0x%02x (%a)\n", HiiVariable->OpCode, HiiOpCodeToStr (HiiVariable->OpCode)));\r
+ DEBUG ((EFI_D_INFO, " Size - 0x%04x\n", HiiVariable->Size));\r
+ DEBUG ((EFI_D_INFO, " Attributes - 0x%08x\n", HiiVariable->Attributes));\r
+ DEBUG ((EFI_D_INFO, " Guid - %g\n", &HiiVariable->Guid));\r
+ DEBUG ((EFI_D_INFO, " Name - %s\n", HiiVariable + 1));\r
+\r
+ //\r
+ // For Hii Question header align.\r
+ //\r
+ HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *) HEADER_ALIGN (((UINTN) HiiVariable + HiiVariable->HeaderLength));\r
+ while ((UINTN) HiiQuestion < ((UINTN) HiiVariable + HiiVariable->Length)) {\r
+ //\r
+ // Dump Hii Question related to the Hii Variable.\r
+ //\r
+ DumpHiiQuestion (HiiQuestion);\r
+ //\r
+ // For Hii Question header align.\r
+ //\r
+ HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *) HEADER_ALIGN (((UINTN) HiiQuestion + HiiQuestion->Length));\r
+ }\r
+}\r
+\r
+/**\r
+ Dump Var Check HII.\r
+\r
+ @param[in] VarCheckHiiBin Pointer to VarCheckHiiBin.\r
+ @param[in] VarCheckHiiBinSize VarCheckHiiBin size.\r
+\r
+**/\r
+VOID\r
+DumpVarCheckHii (\r
+ IN VOID *VarCheckHiiBin,\r
+ IN UINTN VarCheckHiiBinSize\r
+ )\r
+{\r
+ VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable;\r
+\r
+ DEBUG ((EFI_D_INFO, "DumpVarCheckHii\n"));\r
+\r
+ //\r
+ // For Hii Variable header align.\r
+ //\r
+ HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *) HEADER_ALIGN (VarCheckHiiBin);\r
+ while ((UINTN) HiiVariable < ((UINTN) VarCheckHiiBin + VarCheckHiiBinSize)) {\r
+ DumpHiiVariable (HiiVariable);\r
+ //\r
+ // For Hii Variable header align.\r
+ //\r
+ HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *) HEADER_ALIGN (((UINTN) HiiVariable + HiiVariable->Length));\r
+ }\r
+}\r
+#endif\r
+\r
+/**\r
+ Constructor function of VarCheckHiiLib to register var check HII handler.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The constructor executed correctly.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VarCheckHiiLibNullClassConstructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ VarCheckLibRegisterEndOfDxeCallback (VarCheckHiiGen);\r
+ VarCheckLibRegisterAddressPointer ((VOID **) &mVarCheckHiiBin);\r
+ VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerHii);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r