]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg: Add VarCheckHiiLib NULL class library
authorStar Zeng <star.zeng@intel.com>
Tue, 25 Aug 2015 03:10:04 +0000 (03:10 +0000)
committerlzeng14 <lzeng14@Edk2>
Tue, 25 Aug 2015 03:10:04 +0000 (03:10 +0000)
The check will be based on VarCheckHiiBin that generated
from FV and Hii Database.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18293 6f19259b-4bc3-4df7-8a09-765794883524

12 files changed:
MdeModulePkg/Library/VarCheckHiiLib/InternalVarCheckStructure.h [new file with mode: 0644]
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHii.h [new file with mode: 0644]
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.c [new file with mode: 0644]
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.h [new file with mode: 0644]
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c [new file with mode: 0644]
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromHii.c [new file with mode: 0644]
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf [new file with mode: 0644]
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.uni [new file with mode: 0644]
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibNullClass.c [new file with mode: 0644]
MdeModulePkg/MdeModulePkg.dec
MdeModulePkg/MdeModulePkg.dsc
MdeModulePkg/MdeModulePkg.uni

diff --git a/MdeModulePkg/Library/VarCheckHiiLib/InternalVarCheckStructure.h b/MdeModulePkg/Library/VarCheckHiiLib/InternalVarCheckStructure.h
new file mode 100644 (file)
index 0000000..a9faed4
--- /dev/null
@@ -0,0 +1,82 @@
+/** @file\r
+  Internal structure for Var Check Hii.\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
+#ifndef _VAR_CHECK_STRUCTURE_H_\r
+#define _VAR_CHECK_STRUCTURE_H_\r
+\r
+//\r
+// Alignment for Hii Variable and Question header.\r
+//\r
+#define HEADER_ALIGNMENT  4\r
+#define HEADER_ALIGN(Header)  (((UINTN) (Header) + HEADER_ALIGNMENT - 1) & (~(HEADER_ALIGNMENT - 1)))\r
+\r
+#pragma pack (1)\r
+\r
+#define VAR_CHECK_HII_REVISION  0x0001\r
+\r
+typedef struct {\r
+  UINT16            Revision;\r
+  UINT16            HeaderLength;\r
+  UINT32            Length; // Length include this header\r
+  UINT8             OpCode;\r
+  UINT8             Reserved;\r
+  UINT16            Size;\r
+  UINT32            Attributes;\r
+  EFI_GUID          Guid;\r
+//CHAR16              Name[];\r
+} VAR_CHECK_HII_VARIABLE_HEADER;\r
+\r
+typedef struct {\r
+  UINT8             OpCode;\r
+  UINT8             Length; // Length include this header\r
+  UINT16            VarOffset;\r
+  UINT8             StorageWidth;\r
+} VAR_CHECK_HII_QUESTION_HEADER;\r
+\r
+typedef struct {\r
+  UINT8             OpCode;\r
+  UINT8             Length; // Length include this header\r
+  UINT16            VarOffset;\r
+  UINT8             StorageWidth;\r
+//UINTx               Data[]; // x = UINT8/UINT16/UINT32/UINT64;\r
+} VAR_CHECK_HII_QUESTION_ONEOF;\r
+\r
+typedef struct {\r
+  UINT8             OpCode;\r
+  UINT8             Length; // Length include this header\r
+  UINT16            VarOffset;\r
+  UINT8             StorageWidth;\r
+} VAR_CHECK_HII_QUESTION_CHECKBOX;\r
+\r
+typedef struct {\r
+  UINT8             OpCode;\r
+  UINT8             Length; // Length include this header\r
+  UINT16            VarOffset;\r
+  UINT8             StorageWidth;\r
+//UINTx               Minimum; // x = UINT8/UINT16/UINT32/UINT64;\r
+//UINTx               Maximum; // x = UINT8/UINT16/UINT32/UINT64;\r
+} VAR_CHECK_HII_QUESTION_NUMERIC;\r
+\r
+typedef struct {\r
+  UINT8             OpCode;\r
+  UINT8             Length; // Length include this header\r
+  UINT16            VarOffset;\r
+  UINT8             StorageWidth;\r
+  UINT8             MaxContainers;\r
+//UINTx               Data[]; // x = UINT8/UINT16/UINT32/UINT64;\r
+} VAR_CHECK_HII_QUESTION_ORDEREDLIST;\r
+\r
+#pragma pack ()\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHii.h b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHii.h
new file mode 100644 (file)
index 0000000..d770785
--- /dev/null
@@ -0,0 +1,63 @@
+/** @file\r
+  Include file for Var Check Hii handler and bin.\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
+#ifndef _VAR_CHECK_HII_H_\r
+#define _VAR_CHECK_HII_H_\r
+\r
+#include <Library/VarCheckLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+\r
+#include <Guid/ZeroGuid.h>\r
+\r
+#include <Protocol/HiiDatabase.h>\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/FirmwareVolumeBlock.h>\r
+\r
+#include "InternalVarCheckStructure.h"\r
+#include "VarCheckHiiGen.h"\r
+\r
+//#define DUMP_VAR_CHECK_HII\r
+//#define DUMP_HII_DATA\r
+\r
+typedef struct {\r
+  UINT8     HiiOpCode;\r
+  CHAR8     *HiiOpCodeStr;\r
+} VAR_CHECK_HII_OPCODE_STRING;\r
+\r
+typedef struct {\r
+  UINT8     PackageType;\r
+  CHAR8     *PackageTypeStr;\r
+} VAR_CHECK_HII_PACKAGE_TYPE_STRING;\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
+extern VAR_CHECK_HII_VARIABLE_HEADER    *mVarCheckHiiBin;\r
+extern UINTN                            mVarCheckHiiBinSize;\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.c b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.c
new file mode 100644 (file)
index 0000000..725ccc7
--- /dev/null
@@ -0,0 +1,1483 @@
+/** @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
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.h b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.h
new file mode 100644 (file)
index 0000000..f81be2e
--- /dev/null
@@ -0,0 +1,136 @@
+/** @file\r
+  Include file for 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
+#ifndef _VAR_CHECK_HII_GEN_H_\r
+#define _VAR_CHECK_HII_GEN_H_\r
+\r
+#include "VarCheckHii.h"\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
+/**\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
+/**\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
+/**\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
+/**\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
+/**\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
+/**\r
+  Generate from FV.\r
+\r
+**/\r
+VOID\r
+VarCheckHiiGenFromFv (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Generate from Hii Database.\r
+\r
+**/\r
+VOID\r
+VarCheckHiiGenFromHiiDatabase (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Generate VarCheckHiiBin from Hii Database and FV.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VarCheckHiiGen (\r
+  VOID\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c
new file mode 100644 (file)
index 0000000..21fc80e
--- /dev/null
@@ -0,0 +1,443 @@
+/** @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
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromHii.c b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromHii.c
new file mode 100644 (file)
index 0000000..41cde34
--- /dev/null
@@ -0,0 +1,73 @@
+/** @file\r
+  Var Check Hii generation from Hii Database.\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
+/**\r
+  Generate from Hii Database.\r
+\r
+**/\r
+VOID\r
+VarCheckHiiGenFromHiiDatabase (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UINTN                         BufferSize;\r
+  VOID                          *Buffer;\r
+  EFI_PHYSICAL_ADDRESS          BufferAddress;\r
+  EFI_HII_DATABASE_PROTOCOL     *HiiDatabase;\r
+\r
+  //\r
+  // Locate HII Database protocol\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Call first time with zero buffer length.\r
+  // Should fail with EFI_BUFFER_TOO_SMALL.\r
+  //\r
+  BufferSize = 0;\r
+  Buffer = NULL;\r
+  Status = HiiDatabase->ExportPackageLists (HiiDatabase, 0, &BufferSize, Buffer);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    //\r
+    // Allocate buffer to hold the HII Database.\r
+    //\r
+    Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES (BufferSize), &BufferAddress);\r
+    ASSERT_EFI_ERROR (Status);\r
+    Buffer = (VOID *) (UINTN) BufferAddress;\r
+\r
+    //\r
+    // Export HII Database into the buffer.\r
+    //\r
+    Status = HiiDatabase->ExportPackageLists (HiiDatabase, 0, &BufferSize, Buffer);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    DEBUG ((EFI_D_INFO, "VarCheckHiiGenDxeFromHii - HII Database exported at 0x%x, size = 0x%x\n", Buffer, BufferSize));\r
+\r
+#ifdef DUMP_HII_DATA\r
+    DEBUG_CODE (\r
+      DumpHiiDatabase (Buffer, BufferSize);\r
+      );\r
+#endif\r
+\r
+    VarCheckParseHiiDatabase (Buffer, BufferSize);\r
+\r
+    gBS->FreePages (BufferAddress, EFI_SIZE_TO_PAGES (BufferSize));\r
+  }\r
+}\r
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
new file mode 100644 (file)
index 0000000..24d24c5
--- /dev/null
@@ -0,0 +1,58 @@
+## @file\r
+#  NULL class library to register var check HII handler.\r
+#\r
+#  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+#\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions\r
+#  of the BSD License which accompanies this distribution.  The\r
+#  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
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = VarCheckHiiLib\r
+  MODULE_UNI_FILE                = VarCheckHiiLib.uni\r
+  FILE_GUID                      = A34FBDD0-05D3-4AF7-A720-560E91AC8CDF\r
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = NULL|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER\r
+  CONSTRUCTOR                    = VarCheckHiiLibNullClassConstructor\r
+\r
+[Sources]\r
+  VarCheckHiiLibNullClass.c\r
+  VarCheckHii.h\r
+  VarCheckHiiGenFromFv.c\r
+  VarCheckHiiGenFromHii.c\r
+  VarCheckHiiGen.c\r
+  VarCheckHiiGen.h\r
+  InternalVarCheckStructure.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  DebugLib\r
+  BaseMemoryLib\r
+  UefiBootServicesTableLib\r
+  MemoryAllocationLib\r
+  PcdLib\r
+  VarCheckLib\r
+\r
+[Guids]\r
+  gZeroGuid                                 ## SOMETIMES_CONSUMES   ## GUID\r
+\r
+[Protocols]\r
+  gEfiFirmwareVolume2ProtocolGuid           ## SOMETIMES_CONSUMES\r
+  gEfiFirmwareVolumeBlock2ProtocolGuid      ## SOMETIMES_CONSUMES\r
+  gEfiHiiDatabaseProtocolGuid               ## SOMETIMES_CONSUMES\r
+\r
+[Pcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVarCheckVfrDriverGuidArray   ## SOMETIMES_CONSUMES\r
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.uni b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.uni
new file mode 100644 (file)
index 0000000..e4a0deb
Binary files /dev/null and b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.uni differ
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibNullClass.c b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibNullClass.c
new file mode 100644 (file)
index 0000000..3afa796
--- /dev/null
@@ -0,0 +1,539 @@
+/** @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
index 4cd9c4dd89b8a0d8ede415f1601dddf01d3aaaca..c0e9d32e04ab611272ca5334a72bab35afd0579b 100644 (file)
   # @Prompt Set NX for stack.\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack|FALSE|BOOLEAN|0x0001006f\r
 \r
+  ## This PCD to include the driver guid of VFR drivers for VarCheckHiiBin generation.<BR><BR>\r
+  # Default is gZeroGuid that means no VFR driver will be parsed for VarCheckHiiBin generation.<BR>\r
+  # If it is set to an all FFs GUID, it means all modules in all FVs will be parsed for VarCheckHiiBin generation.<BR>\r
+  # @Prompt Driver guid array of VFR drivers for VarCheckHiiBin generation.\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVarCheckVfrDriverGuidArray|{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }|VOID*|0x3000103A\r
+\r
 [PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]\r
   ## This PCD defines the Console output row. The default value is 25 according to UEFI spec.\r
   #  This PCD could be set to 0 then console output would be at max column and max row.\r
index ee928989cad38749bde4ad06eed8e718a39af4d1..c211d7f0eda4259c68d0289a17f0efc7cbcd5db7 100644 (file)
   MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf\r
   MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf\r
   MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf\r
+  MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf\r
 \r
   MdeModulePkg/Universal/BdsDxe/BdsDxe.inf\r
   MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf\r
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {\r
     <LibraryClasses>\r
       NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf\r
+      NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf\r
   }\r
   MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf\r
   \r
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {\r
     <LibraryClasses>\r
       NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf\r
+      NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf\r
   }\r
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf\r
   MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf\r
index 27c0db73afe95aca106ace7a24d843a4d805e7b7..9db6e58e165898f02e3dbad097d0fd84f3f8ea03 100644 (file)
Binary files a/MdeModulePkg/MdeModulePkg.uni and b/MdeModulePkg/MdeModulePkg.uni differ