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
		
			
				
	
	
		
			1484 lines
		
	
	
		
			52 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1484 lines
		
	
	
		
			52 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Var Check Hii bin generation.
 | |
| 
 | |
| Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "VarCheckHiiGen.h"
 | |
| 
 | |
| LIST_ENTRY mVarCheckHiiList = INITIALIZE_LIST_HEAD_VARIABLE (mVarCheckHiiList);
 | |
| 
 | |
| #define VAR_CHECK_HII_VARIABLE_NODE_SIGNATURE   SIGNATURE_32 ('V', 'C', 'H', 'V')
 | |
| 
 | |
| typedef struct {
 | |
|   UINTN                         Signature;
 | |
|   LIST_ENTRY                    Link;
 | |
|   VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable;
 | |
|   EFI_VARSTORE_ID               VarStoreId;
 | |
| 
 | |
|   VAR_CHECK_HII_QUESTION_HEADER **HiiQuestionArray;
 | |
| } VAR_CHECK_HII_VARIABLE_NODE;
 | |
| 
 | |
| #define VAR_CHECK_HII_VARIABLE_FROM_LINK(a) CR (a, VAR_CHECK_HII_VARIABLE_NODE, Link, VAR_CHECK_HII_VARIABLE_NODE_SIGNATURE)
 | |
| 
 | |
| CHAR16 *mVarName = NULL;
 | |
| UINTN  mMaxVarNameSize = 0;
 | |
| 
 | |
| #ifdef DUMP_HII_DATA
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED VAR_CHECK_HII_OPCODE_STRING   mIfrOpCodeStringTable[] = {
 | |
|   {EFI_IFR_VARSTORE_OP,             "EFI_IFR_VARSTORE_OP"},
 | |
|   {EFI_IFR_VARSTORE_EFI_OP,         "EFI_IFR_VARSTORE_EFI_OP"},
 | |
|   {EFI_IFR_ONE_OF_OP,               "EFI_IFR_ONE_OF_OP"},
 | |
|   {EFI_IFR_CHECKBOX_OP,             "EFI_IFR_CHECKBOX_OP"},
 | |
|   {EFI_IFR_NUMERIC_OP,              "EFI_IFR_NUMERIC_OP"},
 | |
|   {EFI_IFR_ORDERED_LIST_OP,         "EFI_IFR_ORDERED_LIST_OP"},
 | |
|   {EFI_IFR_ONE_OF_OPTION_OP,        "EFI_IFR_ONE_OF_OPTION_OP"},
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Ifr opcode to string.
 | |
| 
 | |
|   @param[in] IfrOpCode  Ifr OpCode.
 | |
| 
 | |
|   @return Pointer to string.
 | |
| 
 | |
| **/
 | |
| CHAR8 *
 | |
| IfrOpCodeToStr (
 | |
|   IN UINT8  IfrOpCode
 | |
|   )
 | |
| {
 | |
|   UINTN  Index;
 | |
|   for (Index = 0; Index < sizeof (mIfrOpCodeStringTable) / sizeof (mIfrOpCodeStringTable[0]); Index++) {
 | |
|     if (mIfrOpCodeStringTable[Index].HiiOpCode == IfrOpCode) {
 | |
|       return mIfrOpCodeStringTable[Index].HiiOpCodeStr;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return "<UnknownIfrOpCode>";
 | |
| }
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED VAR_CHECK_HII_PACKAGE_TYPE_STRING  mPackageTypeStringTable[] = {
 | |
|   {EFI_HII_PACKAGE_TYPE_ALL,            "EFI_HII_PACKAGE_TYPE_ALL"},
 | |
|   {EFI_HII_PACKAGE_TYPE_GUID,           "EFI_HII_PACKAGE_TYPE_GUID"},
 | |
|   {EFI_HII_PACKAGE_FORMS,               "EFI_HII_PACKAGE_FORMS"},
 | |
|   {EFI_HII_PACKAGE_STRINGS,             "EFI_HII_PACKAGE_STRINGS"},
 | |
|   {EFI_HII_PACKAGE_FONTS,               "EFI_HII_PACKAGE_FONTS"},
 | |
|   {EFI_HII_PACKAGE_IMAGES,              "EFI_HII_PACKAGE_IMAGES"},
 | |
|   {EFI_HII_PACKAGE_SIMPLE_FONTS,        "EFI_HII_PACKAGE_SIMPLE_FONTS"},
 | |
|   {EFI_HII_PACKAGE_DEVICE_PATH,         "EFI_HII_PACKAGE_DEVICE_PATH"},
 | |
|   {EFI_HII_PACKAGE_KEYBOARD_LAYOUT,     "EFI_HII_PACKAGE_KEYBOARD_LAYOUT"},
 | |
|   {EFI_HII_PACKAGE_ANIMATIONS,          "EFI_HII_PACKAGE_ANIMATIONS"},
 | |
|   {EFI_HII_PACKAGE_END,                 "EFI_HII_PACKAGE_END"},
 | |
|   {EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN,   "EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN"},
 | |
|   {EFI_HII_PACKAGE_TYPE_SYSTEM_END,     "EFI_HII_PACKAGE_TYPE_SYSTEM_END"},
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Hii Package type to string.
 | |
| 
 | |
|   @param[in] PackageType    Package Type
 | |
| 
 | |
|   @return Pointer to string.
 | |
| 
 | |
| **/
 | |
| CHAR8 *
 | |
| HiiPackageTypeToStr (
 | |
|   IN UINT8  PackageType
 | |
|   )
 | |
| {
 | |
|   UINTN     Index;
 | |
|   for (Index = 0; Index < sizeof (mPackageTypeStringTable) / sizeof (mPackageTypeStringTable[0]); Index++) {
 | |
|     if (mPackageTypeStringTable[Index].PackageType == PackageType) {
 | |
|       return mPackageTypeStringTable[Index].PackageTypeStr;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return "<UnknownPackageType>";
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump Hii Package.
 | |
| 
 | |
|   @param[in] HiiPackage         Pointer to Hii Package.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DumpHiiPackage (
 | |
|   IN VOID       *HiiPackage
 | |
|   )
 | |
| {
 | |
|   EFI_HII_PACKAGE_HEADER        *HiiPackageHeader;
 | |
|   EFI_IFR_OP_HEADER             *IfrOpCodeHeader;
 | |
|   EFI_IFR_VARSTORE              *IfrVarStore;
 | |
|   EFI_IFR_VARSTORE_EFI          *IfrEfiVarStore;
 | |
| 
 | |
|   HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiPackage;
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "  HiiPackageHeader->Type   - 0x%02x (%a)\n", HiiPackageHeader->Type, HiiPackageTypeToStr ((UINT8) HiiPackageHeader->Type)));
 | |
|   DEBUG ((EFI_D_INFO, "  HiiPackageHeader->Length - 0x%06x\n", HiiPackageHeader->Length));
 | |
| 
 | |
|   switch (HiiPackageHeader->Type) {
 | |
|     case EFI_HII_PACKAGE_FORMS:
 | |
|       IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) (HiiPackageHeader + 1);
 | |
| 
 | |
|       while ((UINTN) IfrOpCodeHeader < ((UINTN) HiiPackageHeader + HiiPackageHeader->Length)) {
 | |
|         switch (IfrOpCodeHeader->OpCode) {
 | |
|           case EFI_IFR_VARSTORE_OP:
 | |
|             IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpCodeHeader;
 | |
|             DEBUG ((EFI_D_INFO, "    IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode)));
 | |
|             DEBUG ((EFI_D_INFO, "    IfrOpCodeHeader->Length - 0x%02x\n", IfrOpCodeHeader->Length));
 | |
|             DEBUG ((EFI_D_INFO, "    IfrOpCodeHeader->Scope  - 0x%02x\n", IfrOpCodeHeader->Scope));
 | |
|             DEBUG ((EFI_D_INFO, "      Guid       - %g\n", &IfrVarStore->Guid));
 | |
|             DEBUG ((EFI_D_INFO, "      VarStoreId - 0x%04x\n", IfrVarStore->VarStoreId));
 | |
|             DEBUG ((EFI_D_INFO, "      Size       - 0x%04x\n", IfrVarStore->Size));
 | |
|             DEBUG ((EFI_D_INFO, "      Name       - %a\n", IfrVarStore->Name));
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_VARSTORE_EFI_OP:
 | |
|             IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpCodeHeader;
 | |
|             if (IfrEfiVarStore->Header.Length >= sizeof (EFI_IFR_VARSTORE_EFI)) {
 | |
|               DEBUG ((EFI_D_INFO, "    IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode)));
 | |
|               DEBUG ((EFI_D_INFO, "    IfrOpCodeHeader->Length - 0x02%x\n", IfrOpCodeHeader->Length));
 | |
|               DEBUG ((EFI_D_INFO, "    IfrOpCodeHeader->Scope  - 0x02%x\n", IfrOpCodeHeader->Scope));
 | |
|               DEBUG ((EFI_D_INFO, "      Guid       - %g\n", &IfrEfiVarStore->Guid));
 | |
|               DEBUG ((EFI_D_INFO, "      VarStoreId - 0x%04x\n", IfrEfiVarStore->VarStoreId));
 | |
|               DEBUG ((EFI_D_INFO, "      Size       - 0x%04x\n", IfrEfiVarStore->Size));
 | |
|               DEBUG ((EFI_D_INFO, "      Attributes - 0x%08x\n", IfrEfiVarStore->Attributes));
 | |
|               DEBUG ((EFI_D_INFO, "      Name       - %a\n", IfrEfiVarStore->Name));
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_ONE_OF_OP:
 | |
|           case EFI_IFR_CHECKBOX_OP:
 | |
|           case EFI_IFR_NUMERIC_OP:
 | |
|           case EFI_IFR_ORDERED_LIST_OP:
 | |
|             DEBUG ((EFI_D_INFO, "    IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode)));
 | |
|             DEBUG ((EFI_D_INFO, "    IfrOpCodeHeader->Length - 0x02%x\n", IfrOpCodeHeader->Length));
 | |
|             DEBUG ((EFI_D_INFO, "    IfrOpCodeHeader->Scope  - 0x02%x\n", IfrOpCodeHeader->Scope));
 | |
|             DEBUG ((EFI_D_INFO, "      Prompt       - 0x%04x\n", ((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.Header.Prompt));
 | |
|             DEBUG ((EFI_D_INFO, "      Help         - 0x%04x\n", ((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.Header.Help));
 | |
|             DEBUG ((EFI_D_INFO, "      QuestionId   - 0x%04x\n", ((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.QuestionId));
 | |
|             DEBUG ((EFI_D_INFO, "      VarStoreId   - 0x%04x\n", ((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.VarStoreId));
 | |
|             DEBUG ((EFI_D_INFO, "      VarStoreInfo - 0x%04x\n", ((EFI_IFR_ONE_OF * )IfrOpCodeHeader)->Question.VarStoreInfo.VarOffset));
 | |
|             {
 | |
|               EFI_IFR_ONE_OF            *IfrOneOf;
 | |
|               EFI_IFR_CHECKBOX          *IfrCheckBox;
 | |
|               EFI_IFR_NUMERIC           *IfrNumeric;
 | |
|               EFI_IFR_ORDERED_LIST      *IfrOrderedList;
 | |
| 
 | |
|               switch (IfrOpCodeHeader->OpCode) {
 | |
|                 case EFI_IFR_ONE_OF_OP:
 | |
|                   IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpCodeHeader;
 | |
|                   DEBUG ((EFI_D_INFO, "      Flags         - 0x%02x\n", IfrOneOf->Flags));
 | |
|                   switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
 | |
|                   case EFI_IFR_NUMERIC_SIZE_1:
 | |
|                     DEBUG ((EFI_D_INFO, "      MinValue      - 0x%02x\n", IfrOneOf->data.u8.MinValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      MaxValue      - 0x%02x\n", IfrOneOf->data.u8.MaxValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      Step          - 0x%02x\n", IfrOneOf->data.u8.Step));
 | |
|                     break;
 | |
|                   case EFI_IFR_NUMERIC_SIZE_2:
 | |
|                     DEBUG ((EFI_D_INFO, "      MinValue      - 0x%04x\n", IfrOneOf->data.u16.MinValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      MaxValue      - 0x%04x\n", IfrOneOf->data.u16.MaxValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      Step          - 0x%04x\n", IfrOneOf->data.u16.Step));
 | |
|                     break;
 | |
|                   case EFI_IFR_NUMERIC_SIZE_4:
 | |
|                     DEBUG ((EFI_D_INFO, "      MinValue      - 0x%08x\n", IfrOneOf->data.u32.MinValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      MaxValue      - 0x%08x\n", IfrOneOf->data.u32.MaxValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      Step          - 0x%08x\n", IfrOneOf->data.u32.Step));
 | |
|                     break;
 | |
|                   case EFI_IFR_NUMERIC_SIZE_8:
 | |
|                     DEBUG ((EFI_D_INFO, "      MinValue      - 0x%016lx\n", IfrOneOf->data.u64.MinValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      MaxValue      - 0x%016lx\n", IfrOneOf->data.u64.MaxValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      Step          - 0x%016lx\n", IfrOneOf->data.u64.Step));
 | |
|                     break;
 | |
|                   }
 | |
|                   break;
 | |
|                 case EFI_IFR_CHECKBOX_OP:
 | |
|                   IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpCodeHeader;
 | |
|                   DEBUG ((EFI_D_INFO, "      Flags         - 0x%02x\n", IfrCheckBox->Flags));
 | |
|                   break;
 | |
|                 case EFI_IFR_NUMERIC_OP:
 | |
|                   IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpCodeHeader;
 | |
|                   DEBUG ((EFI_D_INFO, "      Flags         - 0x%02x\n", IfrNumeric->Flags));
 | |
|                   switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {
 | |
|                   case EFI_IFR_NUMERIC_SIZE_1:
 | |
|                     DEBUG ((EFI_D_INFO, "      MinValue      - 0x%02x\n", IfrNumeric->data.u8.MinValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      MaxValue      - 0x%02x\n", IfrNumeric->data.u8.MaxValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      Step          - 0x%02x\n", IfrNumeric->data.u8.Step));
 | |
|                     break;
 | |
|                   case EFI_IFR_NUMERIC_SIZE_2:
 | |
|                     DEBUG ((EFI_D_INFO, "      MinValue      - 0x%04x\n", IfrNumeric->data.u16.MinValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      MaxValue      - 0x%04x\n", IfrNumeric->data.u16.MaxValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      Step          - 0x%04x\n", IfrNumeric->data.u16.Step));
 | |
|                     break;
 | |
|                   case EFI_IFR_NUMERIC_SIZE_4:
 | |
|                     DEBUG ((EFI_D_INFO, "      MinValue      - 0x%08x\n", IfrNumeric->data.u32.MinValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      MaxValue      - 0x%08x\n", IfrNumeric->data.u32.MaxValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      Step          - 0x%08x\n", IfrNumeric->data.u32.Step));
 | |
|                     break;
 | |
|                   case EFI_IFR_NUMERIC_SIZE_8:
 | |
|                     DEBUG ((EFI_D_INFO, "      MinValue      - 0x%016lx\n", IfrNumeric->data.u64.MinValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      MaxValue      - 0x%016lx\n", IfrNumeric->data.u64.MaxValue));
 | |
|                     DEBUG ((EFI_D_INFO, "      Step          - 0x%016lx\n", IfrNumeric->data.u64.Step));
 | |
|                     break;
 | |
|                   }
 | |
|                   break;
 | |
|                 case EFI_IFR_ORDERED_LIST_OP:
 | |
|                   IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpCodeHeader;
 | |
|                   DEBUG ((EFI_D_INFO, "      MaxContainers - 0x%02x\n", IfrOrderedList->MaxContainers));
 | |
|                   DEBUG ((EFI_D_INFO, "      Flags         - 0x%02x\n", IfrOrderedList->Flags));
 | |
|                   break;
 | |
|                 default:
 | |
|                   break;
 | |
|               }
 | |
| 
 | |
|               if (IfrOpCodeHeader->Scope != 0) {
 | |
|                 UINTN                       Scope;
 | |
|                 EFI_IFR_ONE_OF_OPTION       *IfrOneOfOption;
 | |
| 
 | |
|                 IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);
 | |
|                 Scope = 1;
 | |
|                 while (Scope != 0) {
 | |
|                   switch (IfrOpCodeHeader->OpCode) {
 | |
|                     case EFI_IFR_ONE_OF_OPTION_OP:
 | |
|                       IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *)IfrOpCodeHeader;
 | |
|                       DEBUG ((EFI_D_INFO, "!!!!    IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", (UINTN)IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode)));
 | |
|                       DEBUG ((EFI_D_INFO, "!!!!    IfrOpCodeHeader->Scope  - 0x%02x\n", IfrOpCodeHeader->Scope));
 | |
|                       DEBUG ((EFI_D_INFO, "!!!!      Option                - 0x%04x\n", IfrOneOfOption->Option));
 | |
|                       DEBUG ((EFI_D_INFO, "!!!!      Flags                 - 0x%02x\n", IfrOneOfOption->Flags));
 | |
|                       DEBUG ((EFI_D_INFO, "!!!!      Type                  - 0x%02x\n", IfrOneOfOption->Type));
 | |
|                       switch (IfrOneOfOption->Type) {
 | |
|                         case EFI_IFR_TYPE_NUM_SIZE_8:
 | |
|                           DEBUG ((EFI_D_INFO, "!!!!      Value                 - 0x%02x\n", IfrOneOfOption->Value.u8));
 | |
|                           break;
 | |
|                         case EFI_IFR_TYPE_NUM_SIZE_16:
 | |
|                           DEBUG ((EFI_D_INFO, "!!!!      Value                 - 0x%04x\n", IfrOneOfOption->Value.u16));
 | |
|                           break;
 | |
|                         case EFI_IFR_TYPE_NUM_SIZE_32:
 | |
|                           DEBUG ((EFI_D_INFO, "!!!!      Value                 - 0x%08x\n", IfrOneOfOption->Value.u32));
 | |
|                           break;
 | |
|                         case EFI_IFR_TYPE_NUM_SIZE_64:
 | |
|                           DEBUG ((EFI_D_INFO, "!!!!      Value                 - 0x%016lx\n", IfrOneOfOption->Value.u64));
 | |
|                           break;
 | |
|                         case EFI_IFR_TYPE_BOOLEAN:
 | |
|                           DEBUG ((EFI_D_INFO, "!!!!      Value                 - 0x%02x\n", IfrOneOfOption->Value.b));
 | |
|                           break;
 | |
|                         default:
 | |
|                           break;
 | |
|                       }
 | |
|                       break;
 | |
|                   }
 | |
| 
 | |
|                   if (IfrOpCodeHeader->OpCode == EFI_IFR_END_OP) {
 | |
|                     ASSERT (Scope > 0);
 | |
|                     Scope--;
 | |
|                     if (Scope == 0) {
 | |
|                       break;
 | |
|                     }
 | |
|                   } else if (IfrOpCodeHeader->Scope != 0) {
 | |
|                     Scope++;
 | |
|                   }
 | |
|                   IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
|           default:
 | |
|             break;
 | |
|         }
 | |
|         IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);
 | |
|       }
 | |
|       break;
 | |
|     default:
 | |
|       break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump Hii Database.
 | |
| 
 | |
|   @param[in] HiiDatabase        Pointer to Hii Database.
 | |
|   @param[in] HiiDatabaseSize    Hii Database size.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DumpHiiDatabase (
 | |
|   IN VOID       *HiiDatabase,
 | |
|   IN UINTN      HiiDatabaseSize
 | |
|   )
 | |
| {
 | |
|   EFI_HII_PACKAGE_LIST_HEADER   *HiiPackageListHeader;
 | |
|   EFI_HII_PACKAGE_HEADER        *HiiPackageHeader;
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "HiiDatabaseSize - 0x%x\n", HiiDatabaseSize));
 | |
|   HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *) HiiDatabase;
 | |
| 
 | |
|   while ((UINTN) HiiPackageListHeader < ((UINTN) HiiDatabase + HiiDatabaseSize)) {
 | |
|     DEBUG ((EFI_D_INFO, "HiiPackageListHeader->PackageListGuid - %g\n", &HiiPackageListHeader->PackageListGuid));
 | |
|     DEBUG ((EFI_D_INFO, "HiiPackageListHeader->PackageLength   - 0x%x\n", (UINTN)HiiPackageListHeader->PackageLength));
 | |
|     HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *)(HiiPackageListHeader + 1);
 | |
| 
 | |
|     while ((UINTN) HiiPackageHeader < (UINTN) HiiPackageListHeader + HiiPackageListHeader->PackageLength) {
 | |
| 
 | |
|       DumpHiiPackage (HiiPackageHeader);
 | |
| 
 | |
|       HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINTN) HiiPackageHeader + HiiPackageHeader->Length);
 | |
|     }
 | |
| 
 | |
|     HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *) ((UINTN) HiiPackageListHeader + HiiPackageListHeader->PackageLength);
 | |
|   }
 | |
| 
 | |
|   return ;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|   Allocates a buffer of a certain pool type.
 | |
| 
 | |
|   Allocates the number bytes specified by AllocationSize of a certain pool type and returns a
 | |
|   pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
 | |
|   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
 | |
| 
 | |
|   @param  MemoryType            The type of memory to allocate.
 | |
|   @param  AllocationSize        The number of bytes to allocate.
 | |
| 
 | |
|   @return A pointer to the allocated buffer or NULL if allocation fails.
 | |
| 
 | |
| **/
 | |
| VOID *
 | |
| InternalVarCheckAllocatePool (
 | |
|   IN EFI_MEMORY_TYPE  MemoryType,
 | |
|   IN UINTN            AllocationSize
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   VOID        *Memory;
 | |
| 
 | |
|   Status = gBS->AllocatePool (MemoryType, AllocationSize, &Memory);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Memory = NULL;
 | |
|   }
 | |
|   return Memory;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Allocates and zeros a buffer of type EfiBootServicesData.
 | |
| 
 | |
|   Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
 | |
|   buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
 | |
|   valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
 | |
|   request, then NULL is returned.
 | |
| 
 | |
|   @param  AllocationSize        The number of bytes to allocate and zero.
 | |
| 
 | |
|   @return A pointer to the allocated buffer or NULL if allocation fails.
 | |
| 
 | |
| **/
 | |
| VOID *
 | |
| InternalVarCheckAllocateZeroPool (
 | |
|   IN UINTN            AllocationSize
 | |
|   )
 | |
| {
 | |
|   VOID  *Memory;
 | |
| 
 | |
|   Memory = InternalVarCheckAllocatePool (EfiBootServicesData, AllocationSize);
 | |
|   if (Memory != NULL) {
 | |
|     Memory = ZeroMem (Memory, AllocationSize);
 | |
|   }
 | |
|   return Memory;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Frees a buffer that was previously allocated with one of the pool allocation functions in the
 | |
|   Memory Allocation Library.
 | |
| 
 | |
|   Frees the buffer specified by Buffer.  Buffer must have been allocated on a previous call to the
 | |
|   pool allocation services of the Memory Allocation Library.  If it is not possible to free pool
 | |
|   resources, then this function will perform no actions.
 | |
| 
 | |
|   If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
 | |
|   then ASSERT().
 | |
| 
 | |
|   @param  Buffer                The pointer to the buffer to free.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| InternalVarCheckFreePool (
 | |
|   IN VOID   *Buffer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS    Status;
 | |
| 
 | |
|   Status = gBS->FreePool (Buffer);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Reallocates a buffer of type EfiBootServicesData.
 | |
| 
 | |
|   Allocates and zeros the number bytes specified by NewSize from memory of type
 | |
|   EfiBootServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and
 | |
|   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
 | |
|   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
 | |
|   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
 | |
|   enough memory remaining to satisfy the request, then NULL is returned.
 | |
| 
 | |
|   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
 | |
|   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
 | |
| 
 | |
|   @param  OldSize        The size, in bytes, of OldBuffer.
 | |
|   @param  NewSize        The size, in bytes, of the buffer to reallocate.
 | |
|   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
 | |
|                          parameter that may be NULL.
 | |
| 
 | |
|   @return A pointer to the allocated buffer or NULL if allocation fails.
 | |
| 
 | |
| **/
 | |
| VOID *
 | |
| InternalVarCheckReallocatePool (
 | |
|   IN UINTN            OldSize,
 | |
|   IN UINTN            NewSize,
 | |
|   IN VOID             *OldBuffer  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   VOID  *NewBuffer;
 | |
| 
 | |
|   NewBuffer = InternalVarCheckAllocateZeroPool (NewSize);
 | |
|   if (NewBuffer != NULL && OldBuffer != NULL) {
 | |
|     CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
 | |
|     InternalVarCheckFreePool (OldBuffer);
 | |
|   }
 | |
|   return NewBuffer;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Merge Hii Question.
 | |
| 
 | |
|   @param[in, out] HiiVariableNode   Pointer to Hii Variable node.
 | |
|   @param[in]      HiiQuestion       Pointer to Hii Question.
 | |
|   @param[in]      FromFv            Hii Question from FV.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| MergeHiiQuestion (
 | |
|   IN OUT VAR_CHECK_HII_VARIABLE_NODE    *HiiVariableNode,
 | |
|   IN VAR_CHECK_HII_QUESTION_HEADER      *HiiQuestion,
 | |
|   IN BOOLEAN                            FromFv
 | |
|   )
 | |
| {
 | |
|   VAR_CHECK_HII_QUESTION_HEADER     *HiiQuestion1;
 | |
|   VAR_CHECK_HII_QUESTION_HEADER     *HiiQuestion2;
 | |
|   VAR_CHECK_HII_QUESTION_HEADER     *NewHiiQuestion;
 | |
|   UINT8                             NewLength;
 | |
|   UINT64                            Minimum1;
 | |
|   UINT64                            Maximum1;
 | |
|   UINT64                            OneValue1;
 | |
|   UINT64                            Minimum2;
 | |
|   UINT64                            Maximum2;
 | |
|   UINT64                            OneValue2;
 | |
|   UINT8                             *Ptr;
 | |
|   UINT8                             *Ptr1;
 | |
|   UINT8                             *Ptr2;
 | |
| 
 | |
|   //
 | |
|   // Hii Question from Hii Database has high priority.
 | |
|   // Do not to merge Hii Question from Fv to Hii Question from Hii Database.
 | |
|   //
 | |
|   if (FromFv) {
 | |
|     InternalVarCheckFreePool (HiiQuestion);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   HiiQuestion1 = HiiVariableNode->HiiQuestionArray[HiiQuestion->VarOffset];
 | |
|   HiiQuestion2 = HiiQuestion;
 | |
| 
 | |
|   ASSERT ((HiiQuestion1->OpCode == HiiQuestion2->OpCode) && (HiiQuestion1->StorageWidth == HiiQuestion2->StorageWidth));
 | |
| 
 | |
|   switch (HiiQuestion1->OpCode) {
 | |
|     case EFI_IFR_ONE_OF_OP:
 | |
|       DEBUG ((EFI_D_INFO, "MergeHiiQuestion - EFI_IFR_ONE_OF_OP VarOffset = 0x%04x\n", HiiQuestion1->VarOffset));
 | |
|       //
 | |
|       // Get the length of Hii Question 1.
 | |
|       //
 | |
|       NewLength = HiiQuestion1->Length;
 | |
| 
 | |
|       //
 | |
|       // Check if the one of options in Hii Question 2 have been in Hii Question 1.
 | |
|       //
 | |
|       Ptr2 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion2 + 1);
 | |
|       while ((UINTN) Ptr2 < (UINTN) HiiQuestion2 + HiiQuestion2->Length) {
 | |
|         OneValue2 = 0;
 | |
|         CopyMem (&OneValue2, Ptr2, HiiQuestion2->StorageWidth);
 | |
| 
 | |
|         Ptr1 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion1 + 1);
 | |
|         while ((UINTN) Ptr1 < (UINTN) HiiQuestion1 + HiiQuestion1->Length) {
 | |
|           OneValue1 = 0;
 | |
|           CopyMem (&OneValue1, Ptr1, HiiQuestion1->StorageWidth);
 | |
|           if (OneValue2 == OneValue1) {
 | |
|             //
 | |
|             // Match
 | |
|             //
 | |
|             break;
 | |
|           }
 | |
|           Ptr1 += HiiQuestion1->StorageWidth;
 | |
|         }
 | |
|         if ((UINTN) Ptr1 >= ((UINTN) HiiQuestion1 + HiiQuestion1->Length)) {
 | |
|           //
 | |
|           // No match
 | |
|           //
 | |
|           NewLength = (UINT8) (NewLength + HiiQuestion1->StorageWidth);
 | |
|         }
 | |
|         Ptr2 += HiiQuestion2->StorageWidth;
 | |
|       }
 | |
| 
 | |
|       if (NewLength > HiiQuestion1->Length) {
 | |
|         //
 | |
|         // Merge the one of options of Hii Question 2 and Hii Question 1.
 | |
|         //
 | |
|         NewHiiQuestion = InternalVarCheckAllocateZeroPool (NewLength);
 | |
|         ASSERT (NewHiiQuestion != NULL);
 | |
|         CopyMem (NewHiiQuestion, HiiQuestion1, HiiQuestion1->Length);
 | |
|         //
 | |
|         // Use the new length.
 | |
|         //
 | |
|         NewHiiQuestion->Length = NewLength;
 | |
|         Ptr = (UINT8 *) NewHiiQuestion + HiiQuestion1->Length;
 | |
| 
 | |
|         Ptr2 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion2 + 1);
 | |
|         while ((UINTN) Ptr2 < (UINTN) HiiQuestion2 + HiiQuestion2->Length) {
 | |
|           OneValue2 = 0;
 | |
|           CopyMem (&OneValue2, Ptr2, HiiQuestion2->StorageWidth);
 | |
| 
 | |
|           Ptr1 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion1 + 1);
 | |
|           while ((UINTN) Ptr1 < (UINTN) HiiQuestion1 + HiiQuestion1->Length) {
 | |
|             OneValue1 = 0;
 | |
|             CopyMem (&OneValue1, Ptr1, HiiQuestion1->StorageWidth);
 | |
|             if (OneValue2 == OneValue1) {
 | |
|               //
 | |
|               // Match
 | |
|               //
 | |
|               break;
 | |
|             }
 | |
|             Ptr1 += HiiQuestion1->StorageWidth;
 | |
|           }
 | |
|           if ((UINTN) Ptr1 >= ((UINTN) HiiQuestion1 + HiiQuestion1->Length)) {
 | |
|             //
 | |
|             // No match
 | |
|             //
 | |
|             CopyMem (Ptr, &OneValue2, HiiQuestion1->StorageWidth);
 | |
|             Ptr += HiiQuestion1->StorageWidth;
 | |
|           }
 | |
|           Ptr2 += HiiQuestion2->StorageWidth;
 | |
|         }
 | |
| 
 | |
|         HiiVariableNode->HiiQuestionArray[HiiQuestion1->VarOffset] = NewHiiQuestion;
 | |
|         InternalVarCheckFreePool (HiiQuestion1);
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_CHECKBOX_OP:
 | |
|       DEBUG ((EFI_D_INFO, "MergeHiiQuestion - EFI_IFR_CHECKBOX_OP VarOffset = 0x%04x\n", HiiQuestion1->VarOffset));
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_NUMERIC_OP:
 | |
|       DEBUG ((EFI_D_INFO, "MergeHiiQuestion - EFI_IFR_NUMERIC_OP VarOffset = 0x%04x\n", HiiQuestion1->VarOffset));
 | |
|       //
 | |
|       // Get minimum and maximum of Hii Question 1.
 | |
|       //
 | |
|       Minimum1 = 0;
 | |
|       Maximum1 = 0;
 | |
|       Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion1 + 1);
 | |
|       CopyMem (&Minimum1, Ptr, HiiQuestion1->StorageWidth);
 | |
|       Ptr += HiiQuestion1->StorageWidth;
 | |
|       CopyMem (&Maximum1, Ptr, HiiQuestion1->StorageWidth);
 | |
| 
 | |
|       //
 | |
|       // Get minimum and maximum of Hii Question 2.
 | |
|       //
 | |
|       Minimum2 = 0;
 | |
|       Maximum2 = 0;
 | |
|       Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion2 + 1);
 | |
|       CopyMem (&Minimum2, Ptr, HiiQuestion2->StorageWidth);
 | |
|       Ptr += HiiQuestion2->StorageWidth;
 | |
|       CopyMem (&Maximum2, Ptr, HiiQuestion2->StorageWidth);
 | |
| 
 | |
|       //
 | |
|       // Update minimum.
 | |
|       //
 | |
|       Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion1 + 1);
 | |
|       if (Minimum2 < Minimum1) {
 | |
|         Minimum1 = Minimum2;
 | |
|         CopyMem (Ptr, &Minimum1, HiiQuestion1->StorageWidth);
 | |
|       }
 | |
|       //
 | |
|       // Update maximum.
 | |
|       //
 | |
|       Ptr += HiiQuestion1->StorageWidth;
 | |
|       if (Maximum2 > Maximum1) {
 | |
|         Maximum1 = Maximum2;
 | |
|         CopyMem (Ptr, &Maximum1, HiiQuestion1->StorageWidth);
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_ORDERED_LIST_OP:
 | |
|       DEBUG ((EFI_D_INFO, "MergeHiiQuestion - EFI_IFR_ORDERED_LIST_OP VarOffset = 0x%04x\n", HiiQuestion1->VarOffset));
 | |
|       //
 | |
|       // Get the length of Hii Question 1.
 | |
|       //
 | |
|       NewLength = HiiQuestion1->Length;
 | |
| 
 | |
|       //
 | |
|       // Check if the one of options in Hii Question 2 have been in Hii Question 1.
 | |
|       //
 | |
|       Ptr2 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion2 + 1);
 | |
|       while ((UINTN) Ptr2 < (UINTN) HiiQuestion2 + HiiQuestion2->Length) {
 | |
|         OneValue2 = 0;
 | |
|         CopyMem (&OneValue2, Ptr2, HiiQuestion2->StorageWidth);
 | |
| 
 | |
|         Ptr1 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion1 + 1);
 | |
|         while ((UINTN) Ptr1 < (UINTN) HiiQuestion1 + HiiQuestion1->Length) {
 | |
|           OneValue1 = 0;
 | |
|           CopyMem (&OneValue1, Ptr1, HiiQuestion1->StorageWidth);
 | |
|           if (OneValue2 == OneValue1) {
 | |
|             //
 | |
|             // Match
 | |
|             //
 | |
|             break;
 | |
|           }
 | |
|           Ptr1 += HiiQuestion1->StorageWidth;
 | |
|         }
 | |
|         if ((UINTN) Ptr1 >= ((UINTN) HiiQuestion1 + HiiQuestion1->Length)) {
 | |
|           //
 | |
|           // No match
 | |
|           //
 | |
|           NewLength = (UINT8) (NewLength + HiiQuestion1->StorageWidth);
 | |
|         }
 | |
|         Ptr2 += HiiQuestion2->StorageWidth;
 | |
|       }
 | |
| 
 | |
|       if (NewLength > HiiQuestion1->Length) {
 | |
|         //
 | |
|         // Merge the one of options of Hii Question 2 and Hii Question 1.
 | |
|         //
 | |
|         NewHiiQuestion = InternalVarCheckAllocateZeroPool (NewLength);
 | |
|         ASSERT (NewHiiQuestion != NULL);
 | |
|         CopyMem (NewHiiQuestion, HiiQuestion1, HiiQuestion1->Length);
 | |
|         //
 | |
|         // Use the new length.
 | |
|         //
 | |
|         NewHiiQuestion->Length = NewLength;
 | |
|         Ptr = (UINT8 *) NewHiiQuestion + HiiQuestion1->Length;
 | |
| 
 | |
|         Ptr2 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion2 + 1);
 | |
|         while ((UINTN) Ptr2 < (UINTN) HiiQuestion2 + HiiQuestion2->Length) {
 | |
|           OneValue2 = 0;
 | |
|           CopyMem (&OneValue2, Ptr2, HiiQuestion2->StorageWidth);
 | |
| 
 | |
|           Ptr1 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion1 + 1);
 | |
|           while ((UINTN) Ptr1 < (UINTN) HiiQuestion1 + HiiQuestion1->Length) {
 | |
|             OneValue1 = 0;
 | |
|             CopyMem (&OneValue1, Ptr1, HiiQuestion1->StorageWidth);
 | |
|             if (OneValue2 == OneValue1) {
 | |
|               //
 | |
|               // Match
 | |
|               //
 | |
|               break;
 | |
|             }
 | |
|             Ptr1 += HiiQuestion1->StorageWidth;
 | |
|           }
 | |
|           if ((UINTN) Ptr1 >= ((UINTN) HiiQuestion1 + HiiQuestion1->Length)) {
 | |
|             //
 | |
|             // No match
 | |
|             //
 | |
|             CopyMem (Ptr, &OneValue2, HiiQuestion1->StorageWidth);
 | |
|             Ptr += HiiQuestion1->StorageWidth;
 | |
|           }
 | |
|           Ptr2 += HiiQuestion2->StorageWidth;
 | |
|         }
 | |
| 
 | |
|         HiiVariableNode->HiiQuestionArray[HiiQuestion1->VarOffset] = NewHiiQuestion;
 | |
|         InternalVarCheckFreePool (HiiQuestion1);
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       ASSERT (FALSE);
 | |
|       return;
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //
 | |
|   // Hii Question 2 has been merged with Hii Question 1.
 | |
|   //
 | |
|   InternalVarCheckFreePool (HiiQuestion2);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get OneOf option data.
 | |
| 
 | |
|   @param[in]  IfrOpCodeHeader   Pointer to Ifr OpCode header.
 | |
|   @param[out] Count             Pointer to option count.
 | |
|   @param[out] Width             Pointer to option width.
 | |
|   @param[out] OptionBuffer      Pointer to option buffer.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| GetOneOfOption (
 | |
|   IN  EFI_IFR_OP_HEADER     *IfrOpCodeHeader,
 | |
|   OUT UINTN                 *Count,
 | |
|   OUT UINT8                 *Width,
 | |
|   OUT VOID                  *OptionBuffer OPTIONAL
 | |
|   )
 | |
| {
 | |
|   UINTN                     Scope;
 | |
|   EFI_IFR_ONE_OF_OPTION     *IfrOneOfOption;
 | |
| 
 | |
|   //
 | |
|   // Assume all OPTION has same Width.
 | |
|   //
 | |
|   *Count = 0;
 | |
| 
 | |
|   if (IfrOpCodeHeader->Scope != 0) {
 | |
|     //
 | |
|     // Nested OpCode.
 | |
|     //
 | |
|     Scope = 1;
 | |
|     IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);
 | |
|     while (Scope != 0) {
 | |
|       switch (IfrOpCodeHeader->OpCode) {
 | |
|         case EFI_IFR_ONE_OF_OPTION_OP:
 | |
|           IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpCodeHeader;
 | |
|           switch (IfrOneOfOption->Type) {
 | |
|             case EFI_IFR_TYPE_NUM_SIZE_8:
 | |
|               *Count = *Count + 1;
 | |
|               *Width = sizeof (UINT8);
 | |
|               if (OptionBuffer != NULL) {
 | |
|                 CopyMem (OptionBuffer, &IfrOneOfOption->Value.u8, sizeof (UINT8));
 | |
|                 OptionBuffer = (UINT8 *) OptionBuffer + 1;
 | |
|               }
 | |
|               break;
 | |
|             case EFI_IFR_TYPE_NUM_SIZE_16:
 | |
|               *Count = *Count + 1;
 | |
|               *Width = sizeof (UINT16);
 | |
|               if (OptionBuffer != NULL) {
 | |
|                 CopyMem (OptionBuffer, &IfrOneOfOption->Value.u16, sizeof (UINT16));
 | |
|                 OptionBuffer = (UINT16 *) OptionBuffer + 1;
 | |
|               }
 | |
|               break;
 | |
|             case EFI_IFR_TYPE_NUM_SIZE_32:
 | |
|               *Count = *Count + 1;
 | |
|               *Width = sizeof (UINT32);
 | |
|               if (OptionBuffer != NULL) {
 | |
|                 CopyMem (OptionBuffer, &IfrOneOfOption->Value.u32, sizeof (UINT32));
 | |
|                 OptionBuffer = (UINT32 *) OptionBuffer + 1;
 | |
|               }
 | |
|               break;
 | |
|             case EFI_IFR_TYPE_NUM_SIZE_64:
 | |
|               *Count = *Count + 1;
 | |
|               *Width = sizeof (UINT64);
 | |
|               if (OptionBuffer != NULL) {
 | |
|                 CopyMem (OptionBuffer, &IfrOneOfOption->Value.u64, sizeof (UINT64));
 | |
|                 OptionBuffer = (UINT64 *) OptionBuffer + 1;
 | |
|               }
 | |
|               break;
 | |
|             case EFI_IFR_TYPE_BOOLEAN:
 | |
|               *Count = *Count + 1;
 | |
|               *Width = sizeof (BOOLEAN);
 | |
|               if (OptionBuffer != NULL) {
 | |
|                 CopyMem (OptionBuffer, &IfrOneOfOption->Value.b, sizeof (BOOLEAN));
 | |
|                 OptionBuffer = (BOOLEAN *) OptionBuffer + 1;
 | |
|               }
 | |
|               break;
 | |
|             default:
 | |
|               break;
 | |
|           }
 | |
|           break;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Until End OpCode.
 | |
|       //
 | |
|       if (IfrOpCodeHeader->OpCode == EFI_IFR_END_OP) {
 | |
|         ASSERT (Scope > 0);
 | |
|         Scope--;
 | |
|         if (Scope == 0) {
 | |
|           break;
 | |
|         }
 | |
|       } else if (IfrOpCodeHeader->Scope != 0) {
 | |
|         //
 | |
|         // Nested OpCode.
 | |
|         //
 | |
|         Scope++;
 | |
|       }
 | |
|       IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parse Hii Question Oneof.
 | |
| 
 | |
|   @param[in] IfrOpCodeHeader    Pointer to Ifr OpCode header.
 | |
| 
 | |
|   return Pointer to Hii Question.
 | |
| 
 | |
| **/
 | |
| VAR_CHECK_HII_QUESTION_HEADER *
 | |
| ParseHiiQuestionOneOf (
 | |
|   IN EFI_IFR_OP_HEADER  *IfrOpCodeHeader
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_ONE_OF                *IfrOneOf;
 | |
|   VAR_CHECK_HII_QUESTION_ONEOF  *OneOf;
 | |
|   UINTN                         Length;
 | |
|   UINT8                         Width;
 | |
|   UINTN                         OptionCount;
 | |
|   UINT8                         OptionWidth;
 | |
| 
 | |
|   IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpCodeHeader;
 | |
| 
 | |
|   Width = (UINT8) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
 | |
| 
 | |
|   GetOneOfOption (IfrOpCodeHeader, &OptionCount, &OptionWidth, NULL);
 | |
|   ASSERT (Width == OptionWidth);
 | |
| 
 | |
|   Length = sizeof (*OneOf) + OptionCount * Width;
 | |
| 
 | |
|   OneOf = InternalVarCheckAllocateZeroPool (Length);
 | |
|   ASSERT (OneOf != NULL);
 | |
|   OneOf->OpCode       = EFI_IFR_ONE_OF_OP;
 | |
|   OneOf->Length       = (UINT8) Length;
 | |
|   OneOf->VarOffset    = IfrOneOf->Question.VarStoreInfo.VarOffset;
 | |
|   OneOf->StorageWidth = Width;
 | |
| 
 | |
|   GetOneOfOption (IfrOpCodeHeader, &OptionCount, &OptionWidth, OneOf + 1);
 | |
| 
 | |
|   return (VAR_CHECK_HII_QUESTION_HEADER *) OneOf;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parse Hii Question CheckBox.
 | |
| 
 | |
|   @param[in] IfrOpCodeHeader    Pointer to Ifr OpCode header.
 | |
| 
 | |
|   return Pointer to Hii Question.
 | |
| 
 | |
| **/
 | |
| VAR_CHECK_HII_QUESTION_HEADER *
 | |
| ParseHiiQuestionCheckBox (
 | |
|   IN EFI_IFR_OP_HEADER  *IfrOpCodeHeader
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_CHECKBOX                  *IfrCheckBox;
 | |
|   VAR_CHECK_HII_QUESTION_CHECKBOX   *CheckBox;
 | |
| 
 | |
|   IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpCodeHeader;
 | |
| 
 | |
|   CheckBox = InternalVarCheckAllocateZeroPool (sizeof (*CheckBox));
 | |
|   ASSERT (CheckBox != NULL);
 | |
|   CheckBox->OpCode       = EFI_IFR_CHECKBOX_OP;
 | |
|   CheckBox->Length       = (UINT8) sizeof (*CheckBox);;
 | |
|   CheckBox->VarOffset    = IfrCheckBox->Question.VarStoreInfo.VarOffset;
 | |
|   CheckBox->StorageWidth = (UINT8) sizeof (BOOLEAN);
 | |
| 
 | |
|   return (VAR_CHECK_HII_QUESTION_HEADER *) CheckBox;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parse Hii Question Numeric.
 | |
| 
 | |
|   @param[in] IfrOpCodeHeader    Pointer to Ifr OpCode header.
 | |
| 
 | |
|   return Pointer to Hii Question.
 | |
| 
 | |
| **/
 | |
| VAR_CHECK_HII_QUESTION_HEADER *
 | |
| ParseHiiQuestionNumeric (
 | |
|   IN EFI_IFR_OP_HEADER  *IfrOpCodeHeader
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_NUMERIC                   *IfrNumeric;
 | |
|   VAR_CHECK_HII_QUESTION_NUMERIC    *Numeric;
 | |
|   UINT8                             Width;
 | |
| 
 | |
|   IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpCodeHeader;
 | |
| 
 | |
|   Numeric = InternalVarCheckAllocateZeroPool (sizeof (VAR_CHECK_HII_QUESTION_NUMERIC) + 2 * sizeof (UINT64));
 | |
|   ASSERT (Numeric != NULL);
 | |
| 
 | |
|   Width = (UINT8) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));
 | |
| 
 | |
|   Numeric->OpCode       = EFI_IFR_NUMERIC_OP;
 | |
|   Numeric->Length       = (UINT8) (sizeof (VAR_CHECK_HII_QUESTION_NUMERIC) + 2 * Width);
 | |
|   Numeric->VarOffset    = IfrNumeric->Question.VarStoreInfo.VarOffset;
 | |
|   Numeric->StorageWidth = Width;
 | |
| 
 | |
|   CopyMem (Numeric + 1, &IfrNumeric->data, Width * 2);
 | |
| 
 | |
|   return (VAR_CHECK_HII_QUESTION_HEADER *) Numeric;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parse Hii Question OrderedList.
 | |
| 
 | |
|   @param[in] IfrOpCodeHeader    Pointer to Ifr OpCode header.
 | |
| 
 | |
|   return Pointer to Hii Question.
 | |
| 
 | |
| **/
 | |
| VAR_CHECK_HII_QUESTION_HEADER *
 | |
| ParseHiiQuestionOrderedList (
 | |
|   IN EFI_IFR_OP_HEADER  *IfrOpCodeHeader
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_ORDERED_LIST                  *IfrOrderedList;
 | |
|   VAR_CHECK_HII_QUESTION_ORDEREDLIST    *OrderedList;
 | |
|   UINTN                                 Length;
 | |
|   UINTN                                 OptionCount;
 | |
|   UINT8                                 OptionWidth;
 | |
| 
 | |
|   IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpCodeHeader;
 | |
| 
 | |
|   GetOneOfOption (IfrOpCodeHeader, &OptionCount, &OptionWidth, NULL);
 | |
| 
 | |
|   Length = sizeof (*OrderedList) + OptionCount * OptionWidth;
 | |
| 
 | |
|   OrderedList = InternalVarCheckAllocateZeroPool (Length);
 | |
|   ASSERT (OrderedList != NULL);
 | |
|   OrderedList->OpCode        = EFI_IFR_ORDERED_LIST_OP;
 | |
|   OrderedList->Length        = (UINT8) Length;
 | |
|   OrderedList->VarOffset     = IfrOrderedList->Question.VarStoreInfo.VarOffset;
 | |
|   OrderedList->StorageWidth  = OptionWidth;
 | |
|   OrderedList->MaxContainers = IfrOrderedList->MaxContainers;
 | |
| 
 | |
|   GetOneOfOption (IfrOpCodeHeader, &OptionCount, &OptionWidth, OrderedList + 1);
 | |
| 
 | |
|   return (VAR_CHECK_HII_QUESTION_HEADER *) OrderedList;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parse and create Hii Question node.
 | |
| 
 | |
|   @param[in] HiiVariableNode    Pointer to Hii Variable node.
 | |
|   @param[in] IfrOpCodeHeader    Pointer to Ifr OpCode header.
 | |
|   @param[in] FromFv             Hii Question from FV.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| ParseHiiQuestion (
 | |
|   IN VAR_CHECK_HII_VARIABLE_NODE    *HiiVariableNode,
 | |
|   IN  EFI_IFR_OP_HEADER             *IfrOpCodeHeader,
 | |
|   IN BOOLEAN                        FromFv
 | |
|   )
 | |
| {
 | |
|   VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion;
 | |
| 
 | |
|   switch (IfrOpCodeHeader->OpCode) {
 | |
|     case EFI_IFR_ONE_OF_OP:
 | |
|       HiiQuestion = ParseHiiQuestionOneOf (IfrOpCodeHeader);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_CHECKBOX_OP:
 | |
|       HiiQuestion = ParseHiiQuestionCheckBox (IfrOpCodeHeader);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_NUMERIC_OP:
 | |
|       HiiQuestion = ParseHiiQuestionNumeric (IfrOpCodeHeader);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_ORDERED_LIST_OP:
 | |
|       HiiQuestion = ParseHiiQuestionOrderedList (IfrOpCodeHeader);
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       ASSERT (FALSE);
 | |
|       return;
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   if (HiiVariableNode->HiiQuestionArray[HiiQuestion->VarOffset] != NULL) {
 | |
|     MergeHiiQuestion (HiiVariableNode, HiiQuestion, FromFv);
 | |
|   } else {
 | |
|     HiiVariableNode->HiiQuestionArray[HiiQuestion->VarOffset] = HiiQuestion;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Find Hii variable node by name and GUID.
 | |
| 
 | |
|   @param[in] Name   Pointer to variable name.
 | |
|   @param[in] Guid   Pointer to vendor GUID.
 | |
| 
 | |
|   @return Pointer to Hii Variable node.
 | |
| 
 | |
| **/
 | |
| VAR_CHECK_HII_VARIABLE_NODE *
 | |
| FindHiiVariableNode (
 | |
|   IN CHAR16     *Name,
 | |
|   IN EFI_GUID   *Guid
 | |
|   )
 | |
| {
 | |
|   VAR_CHECK_HII_VARIABLE_NODE   *HiiVariableNode;
 | |
|   LIST_ENTRY                    *Link;
 | |
| 
 | |
|   for (Link = mVarCheckHiiList.ForwardLink
 | |
|       ;Link != &mVarCheckHiiList
 | |
|       ;Link = Link->ForwardLink) {
 | |
|     HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (Link);
 | |
| 
 | |
|     if ((StrCmp (Name, (CHAR16 *) (HiiVariableNode->HiiVariable + 1)) == 0) &&
 | |
|         CompareGuid (Guid, &HiiVariableNode->HiiVariable->Guid)) {
 | |
|       return HiiVariableNode;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Find Hii variable node by var store id.
 | |
| 
 | |
|   @param[in] VarStoreId         Var store id.
 | |
| 
 | |
|   @return Pointer to Hii Variable node.
 | |
| 
 | |
| **/
 | |
| VAR_CHECK_HII_VARIABLE_NODE *
 | |
| FindHiiVariableNodeByVarStoreId (
 | |
|   IN EFI_VARSTORE_ID            VarStoreId
 | |
|   )
 | |
| {
 | |
|   VAR_CHECK_HII_VARIABLE_NODE   *HiiVariableNode;
 | |
|   LIST_ENTRY                    *Link;
 | |
| 
 | |
|   if (VarStoreId == 0) {
 | |
|     //
 | |
|     // The variable store identifier, which is unique within the current form set.
 | |
|     // A value of zero is invalid.
 | |
|     //
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   for (Link = mVarCheckHiiList.ForwardLink
 | |
|       ;Link != &mVarCheckHiiList
 | |
|       ;Link = Link->ForwardLink) {
 | |
|     HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (Link);
 | |
|     //
 | |
|     // The variable store identifier, which is unique within the current form set.
 | |
|     //
 | |
|     if (VarStoreId == HiiVariableNode->VarStoreId) {
 | |
|       return HiiVariableNode;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Destroy var store id in the Hii Variable node after parsing one Hii Package.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DestroyVarStoreId (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   VAR_CHECK_HII_VARIABLE_NODE   *HiiVariableNode;
 | |
|   LIST_ENTRY                    *Link;
 | |
| 
 | |
|   for (Link = mVarCheckHiiList.ForwardLink
 | |
|       ;Link != &mVarCheckHiiList
 | |
|       ;Link = Link->ForwardLink) {
 | |
|     HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (Link);
 | |
|     //
 | |
|     // The variable store identifier, which is unique within the current form set.
 | |
|     // A value of zero is invalid.
 | |
|     //
 | |
|     HiiVariableNode->VarStoreId = 0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create Hii Variable node.
 | |
| 
 | |
|   @param[in] IfrEfiVarStore  Pointer to EFI VARSTORE.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| CreateHiiVariableNode (
 | |
|   IN EFI_IFR_VARSTORE_EFI   *IfrEfiVarStore
 | |
|   )
 | |
| {
 | |
|   VAR_CHECK_HII_VARIABLE_NODE   *HiiVariableNode;
 | |
|   VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable;
 | |
|   UINTN                         HeaderLength;
 | |
|   CHAR16                        *VarName;
 | |
|   UINTN                         VarNameSize;
 | |
| 
 | |
|   //
 | |
|   // Get variable name.
 | |
|   //
 | |
|   VarNameSize = AsciiStrSize ((CHAR8 *) IfrEfiVarStore->Name) * 2;
 | |
|   if (VarNameSize > mMaxVarNameSize) {
 | |
|     mVarName = InternalVarCheckReallocatePool (mMaxVarNameSize, VarNameSize, mVarName);
 | |
|     ASSERT (mVarName != NULL);
 | |
|     mMaxVarNameSize = VarNameSize;
 | |
|   }
 | |
|   AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, mVarName);
 | |
|   VarName = mVarName;
 | |
| 
 | |
|   HiiVariableNode = FindHiiVariableNode (
 | |
|                       VarName,
 | |
|                       &IfrEfiVarStore->Guid
 | |
|                       );
 | |
|   if (HiiVariableNode == NULL) {
 | |
|     //
 | |
|     // Not found, then create new.
 | |
|     //
 | |
|     HeaderLength = sizeof (*HiiVariable) + VarNameSize;
 | |
|     HiiVariable = InternalVarCheckAllocateZeroPool (HeaderLength);
 | |
|     ASSERT (HiiVariable != NULL);
 | |
|     HiiVariable->Revision = VAR_CHECK_HII_REVISION;
 | |
|     HiiVariable->OpCode = EFI_IFR_VARSTORE_EFI_OP;
 | |
|     HiiVariable->HeaderLength = (UINT16) HeaderLength;
 | |
|     HiiVariable->Size = IfrEfiVarStore->Size;
 | |
|     HiiVariable->Attributes = IfrEfiVarStore->Attributes;
 | |
|     CopyGuid (&HiiVariable->Guid, &IfrEfiVarStore->Guid);
 | |
|     StrCpyS ((CHAR16 *) (HiiVariable + 1), VarNameSize / sizeof (CHAR16), VarName);
 | |
| 
 | |
|     HiiVariableNode = InternalVarCheckAllocateZeroPool (sizeof (*HiiVariableNode));
 | |
|     ASSERT (HiiVariableNode != NULL);
 | |
|     HiiVariableNode->Signature = VAR_CHECK_HII_VARIABLE_NODE_SIGNATURE;
 | |
|     HiiVariableNode->HiiVariable = HiiVariable;
 | |
|     //
 | |
|     // The variable store identifier, which is unique within the current form set.
 | |
|     //
 | |
|     HiiVariableNode->VarStoreId = IfrEfiVarStore->VarStoreId;
 | |
|     HiiVariableNode->HiiQuestionArray = InternalVarCheckAllocateZeroPool (IfrEfiVarStore->Size * sizeof (VAR_CHECK_HII_QUESTION_HEADER *));
 | |
| 
 | |
|     InsertTailList (&mVarCheckHiiList, &HiiVariableNode->Link);
 | |
|   } else {
 | |
|     HiiVariableNode->VarStoreId = IfrEfiVarStore->VarStoreId;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parse and create Hii Variable node list.
 | |
| 
 | |
|   @param[in] HiiPackage         Pointer to Hii Package.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| ParseHiiVariable (
 | |
|   IN VOID       *HiiPackage
 | |
|   )
 | |
| {
 | |
|   EFI_HII_PACKAGE_HEADER    *HiiPackageHeader;
 | |
|   EFI_IFR_OP_HEADER         *IfrOpCodeHeader;
 | |
|   EFI_IFR_VARSTORE_EFI      *IfrEfiVarStore;
 | |
| 
 | |
|   HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiPackage;
 | |
| 
 | |
|   switch (HiiPackageHeader->Type) {
 | |
|     case EFI_HII_PACKAGE_FORMS:
 | |
|       IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) (HiiPackageHeader + 1);
 | |
| 
 | |
|       while ((UINTN) IfrOpCodeHeader < (UINTN) HiiPackageHeader + HiiPackageHeader->Length) {
 | |
|         switch (IfrOpCodeHeader->OpCode) {
 | |
|           case EFI_IFR_VARSTORE_EFI_OP:
 | |
|             //
 | |
|             // Come to EFI VARSTORE in Form Package.
 | |
|             //
 | |
|             IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpCodeHeader;
 | |
|             if ((IfrEfiVarStore->Header.Length >= sizeof (EFI_IFR_VARSTORE_EFI)) &&
 | |
|                 ((IfrEfiVarStore->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0)) {
 | |
|               //
 | |
|               // Only create node list for Hii Variable with NV attribute.
 | |
|               //
 | |
|               CreateHiiVariableNode (IfrEfiVarStore);
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|           default:
 | |
|             break;
 | |
|         }
 | |
|       IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Var Check Parse Hii Package.
 | |
| 
 | |
|   @param[in] HiiPackage         Pointer to Hii Package.
 | |
|   @param[in] FromFv             Hii Package from FV.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| VarCheckParseHiiPackage (
 | |
|   IN VOID       *HiiPackage,
 | |
|   IN BOOLEAN    FromFv
 | |
|   )
 | |
| {
 | |
|   EFI_HII_PACKAGE_HEADER        *HiiPackageHeader;
 | |
|   EFI_IFR_OP_HEADER             *IfrOpCodeHeader;
 | |
|   VAR_CHECK_HII_VARIABLE_NODE   *HiiVariableNode;
 | |
| 
 | |
|   //
 | |
|   // Parse and create Hii Variable node list for this Hii Package.
 | |
|   //
 | |
|   ParseHiiVariable (HiiPackage);
 | |
| 
 | |
|   HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiPackage;
 | |
| 
 | |
|   switch (HiiPackageHeader->Type) {
 | |
|     case EFI_HII_PACKAGE_FORMS:
 | |
|       IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) (HiiPackageHeader + 1);
 | |
| 
 | |
|       while ((UINTN) IfrOpCodeHeader < (UINTN) HiiPackageHeader + HiiPackageHeader->Length) {
 | |
|         switch (IfrOpCodeHeader->OpCode) {
 | |
|           case EFI_IFR_ONE_OF_OP:
 | |
|           case EFI_IFR_CHECKBOX_OP:
 | |
|           case EFI_IFR_NUMERIC_OP:
 | |
|           case EFI_IFR_ORDERED_LIST_OP:
 | |
|             HiiVariableNode = FindHiiVariableNodeByVarStoreId (((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.VarStoreId);
 | |
|             if ((HiiVariableNode == NULL) ||
 | |
|                 //
 | |
|                 // No related Hii Variable node found.
 | |
|                 //
 | |
|                 ((((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.Header.Prompt == 0) && (((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.Header.Help == 0))) {
 | |
|                 //
 | |
|                 // meanless IFR item introduced by ECP.
 | |
|                 //
 | |
|             } else {
 | |
|               //
 | |
|               // Normal IFR
 | |
|               //
 | |
|               ParseHiiQuestion (HiiVariableNode, IfrOpCodeHeader, FromFv);
 | |
|             }
 | |
|           default:
 | |
|             break;
 | |
|         }
 | |
|         IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length);
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       break;
 | |
|   }
 | |
|   DestroyVarStoreId ();
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Var Check Parse Hii Database.
 | |
| 
 | |
|   @param[in] HiiDatabase        Pointer to Hii Database.
 | |
|   @param[in] HiiDatabaseSize    Hii Database size.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| VarCheckParseHiiDatabase (
 | |
|   IN VOID       *HiiDatabase,
 | |
|   IN UINTN      HiiDatabaseSize
 | |
|   )
 | |
| {
 | |
|   EFI_HII_PACKAGE_LIST_HEADER   *HiiPackageListHeader;
 | |
|   EFI_HII_PACKAGE_HEADER        *HiiPackageHeader;
 | |
| 
 | |
|   HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *) HiiDatabase;
 | |
| 
 | |
|   while ((UINTN) HiiPackageListHeader < ((UINTN) HiiDatabase + HiiDatabaseSize)) {
 | |
|     HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiPackageListHeader + 1);
 | |
| 
 | |
|     while ((UINTN) HiiPackageHeader < ((UINTN) HiiPackageListHeader + HiiPackageListHeader->PackageLength)) {
 | |
|       //
 | |
|       // Parse Hii Pacakge.
 | |
|       //
 | |
|       VarCheckParseHiiPackage (HiiPackageHeader, FALSE);
 | |
| 
 | |
|       HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINTN) HiiPackageHeader + HiiPackageHeader->Length);
 | |
|     }
 | |
| 
 | |
|     HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *) ((UINTN) HiiPackageListHeader + HiiPackageListHeader->PackageLength);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Destroy Hii Variable node.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DestroyHiiVariableNode (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   VAR_CHECK_HII_VARIABLE_NODE   *HiiVariableNode;
 | |
|   LIST_ENTRY                    *HiiVariableLink;
 | |
|   UINTN                         Index;
 | |
| 
 | |
|   while (mVarCheckHiiList.ForwardLink != &mVarCheckHiiList) {
 | |
|     HiiVariableLink = mVarCheckHiiList.ForwardLink;
 | |
|     HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (HiiVariableLink);
 | |
| 
 | |
|     RemoveEntryList (&HiiVariableNode->Link);
 | |
| 
 | |
|     //
 | |
|     // Free the allocated buffer.
 | |
|     //
 | |
|     for (Index = 0; Index < HiiVariableNode->HiiVariable->Size; Index++) {
 | |
|       if (HiiVariableNode->HiiQuestionArray[Index] != NULL) {
 | |
|         InternalVarCheckFreePool (HiiVariableNode->HiiQuestionArray[Index]);
 | |
|       }
 | |
|     }
 | |
|     InternalVarCheckFreePool (HiiVariableNode->HiiQuestionArray);
 | |
|     InternalVarCheckFreePool (HiiVariableNode->HiiVariable);
 | |
|     InternalVarCheckFreePool (HiiVariableNode);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Build VarCheckHiiBin.
 | |
| 
 | |
|   @param[out] Size      Pointer to VarCheckHii size.
 | |
| 
 | |
|   @return Pointer to VarCheckHiiBin.
 | |
| 
 | |
| **/
 | |
| VOID *
 | |
| BuildVarCheckHiiBin (
 | |
|   OUT UINTN  *Size
 | |
|   )
 | |
| {
 | |
|   VAR_CHECK_HII_VARIABLE_NODE   *HiiVariableNode;
 | |
|   LIST_ENTRY                    *HiiVariableLink;
 | |
|   UINTN                         Index;
 | |
|   VOID                          *Data;
 | |
|   UINT8                         *Ptr;
 | |
|   UINT32                        BinSize;
 | |
|   UINT32                        HiiVariableLength;
 | |
| 
 | |
|   //
 | |
|   // Get Size
 | |
|   //
 | |
|   BinSize = 0;
 | |
| 
 | |
|   for (HiiVariableLink = mVarCheckHiiList.ForwardLink
 | |
|       ;HiiVariableLink != &mVarCheckHiiList
 | |
|       ;HiiVariableLink = HiiVariableLink->ForwardLink) {
 | |
|     //
 | |
|     // For Hii Variable header align.
 | |
|     //
 | |
|     BinSize = (UINT32) HEADER_ALIGN (BinSize);
 | |
| 
 | |
|     HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (HiiVariableLink);
 | |
|     HiiVariableLength = HiiVariableNode->HiiVariable->HeaderLength;
 | |
| 
 | |
|     for (Index = 0; Index < HiiVariableNode->HiiVariable->Size; Index++) {
 | |
|       if (HiiVariableNode->HiiQuestionArray[Index] != NULL) {
 | |
|         //
 | |
|         // For Hii Question header align.
 | |
|         //
 | |
|         HiiVariableLength = (UINT32) HEADER_ALIGN (HiiVariableLength);
 | |
|         HiiVariableLength += HiiVariableNode->HiiQuestionArray[Index]->Length;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     HiiVariableNode->HiiVariable->Length = HiiVariableLength;
 | |
|     BinSize += HiiVariableLength;
 | |
|   }
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "VarCheckHiiBin - size = 0x%x\n", BinSize));
 | |
|   if (BinSize == 0) {
 | |
|     *Size = BinSize;
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // AllocatePages () and AllocatePool () from gBS are used for the process of VarCheckHiiBin generation.
 | |
|   // Only here AllocateRuntimeZeroPool () from MemoryAllocateLib is used for runtime access
 | |
|   // in SetVariable check handler.
 | |
|   //
 | |
|   Data = AllocateRuntimeZeroPool (BinSize);
 | |
|   ASSERT (Data != NULL);
 | |
|   DEBUG ((EFI_D_INFO, "VarCheckHiiBin - built at 0x%x\n", Data));
 | |
| 
 | |
|   //
 | |
|   // Gen Data
 | |
|   //
 | |
|   Ptr = Data;
 | |
|   for (HiiVariableLink = mVarCheckHiiList.ForwardLink
 | |
|       ;HiiVariableLink != &mVarCheckHiiList
 | |
|       ;HiiVariableLink = HiiVariableLink->ForwardLink) {
 | |
|     //
 | |
|     // For Hii Variable header align.
 | |
|     //
 | |
|     Ptr = (UINT8 *) HEADER_ALIGN (Ptr);
 | |
| 
 | |
|     HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (HiiVariableLink);
 | |
|     CopyMem (Ptr, HiiVariableNode->HiiVariable, HiiVariableNode->HiiVariable->HeaderLength);
 | |
|     Ptr += HiiVariableNode->HiiVariable->HeaderLength;
 | |
| 
 | |
|     for (Index = 0; Index < HiiVariableNode->HiiVariable->Size; Index++) {
 | |
|       if (HiiVariableNode->HiiQuestionArray[Index] != NULL) {
 | |
|         //
 | |
|         // For Hii Question header align.
 | |
|         //
 | |
|         Ptr = (UINT8 *) HEADER_ALIGN (Ptr);
 | |
|         CopyMem (Ptr, HiiVariableNode->HiiQuestionArray[Index], HiiVariableNode->HiiQuestionArray[Index]->Length);
 | |
|         Ptr += HiiVariableNode->HiiQuestionArray[Index]->Length;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   *Size = BinSize;
 | |
|   return Data;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Generate VarCheckHiiBin from Hii Database and FV.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| VarCheckHiiGen (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   VarCheckHiiGenFromHiiDatabase ();
 | |
|   VarCheckHiiGenFromFv ();
 | |
| 
 | |
|   mVarCheckHiiBin = BuildVarCheckHiiBin (&mVarCheckHiiBinSize);
 | |
|   if (mVarCheckHiiBin == NULL) {
 | |
|     DEBUG ((EFI_D_INFO, "[VarCheckHii] This driver could be removed from *.dsc and *.fdf\n"));
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   DestroyHiiVariableNode ();
 | |
|   if (mVarName != NULL) {
 | |
|     InternalVarCheckFreePool (mVarName);
 | |
|   }
 | |
| 
 | |
| #ifdef DUMP_VAR_CHECK_HII
 | |
|   DEBUG_CODE (
 | |
|     DumpVarCheckHii (mVarCheckHiiBin, mVarCheckHiiBinSize);
 | |
|   );
 | |
| #endif
 | |
| }
 | |
| 
 |