REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			1638 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1638 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Var Check Hii bin generation.
 | |
| 
 | |
| Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #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 < ARRAY_SIZE (mIfrOpCodeStringTable); 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 < ARRAY_SIZE (mPackageTypeStringTable); 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;
 | |
|   BOOLEAN                 QuestionStoredInBitField;
 | |
| 
 | |
|   HiiPackageHeader         = (EFI_HII_PACKAGE_HEADER *)HiiPackage;
 | |
|   QuestionStoredInBitField = FALSE;
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO, "  HiiPackageHeader->Type   - 0x%02x (%a)\n", HiiPackageHeader->Type, HiiPackageTypeToStr ((UINT8)HiiPackageHeader->Type)));
 | |
|   DEBUG ((DEBUG_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 ((DEBUG_INFO, "    IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode)));
 | |
|             DEBUG ((DEBUG_INFO, "    IfrOpCodeHeader->Length - 0x%02x\n", IfrOpCodeHeader->Length));
 | |
|             DEBUG ((DEBUG_INFO, "    IfrOpCodeHeader->Scope  - 0x%02x\n", IfrOpCodeHeader->Scope));
 | |
|             DEBUG ((DEBUG_INFO, "      Guid       - %g\n", &IfrVarStore->Guid));
 | |
|             DEBUG ((DEBUG_INFO, "      VarStoreId - 0x%04x\n", IfrVarStore->VarStoreId));
 | |
|             DEBUG ((DEBUG_INFO, "      Size       - 0x%04x\n", IfrVarStore->Size));
 | |
|             DEBUG ((DEBUG_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 ((DEBUG_INFO, "    IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode)));
 | |
|               DEBUG ((DEBUG_INFO, "    IfrOpCodeHeader->Length - 0x%02x\n", IfrOpCodeHeader->Length));
 | |
|               DEBUG ((DEBUG_INFO, "    IfrOpCodeHeader->Scope  - 0x%02x\n", IfrOpCodeHeader->Scope));
 | |
|               DEBUG ((DEBUG_INFO, "      Guid       - %g\n", &IfrEfiVarStore->Guid));
 | |
|               DEBUG ((DEBUG_INFO, "      VarStoreId - 0x%04x\n", IfrEfiVarStore->VarStoreId));
 | |
|               DEBUG ((DEBUG_INFO, "      Size       - 0x%04x\n", IfrEfiVarStore->Size));
 | |
|               DEBUG ((DEBUG_INFO, "      Attributes - 0x%08x\n", IfrEfiVarStore->Attributes));
 | |
|               DEBUG ((DEBUG_INFO, "      Name       - %a\n", IfrEfiVarStore->Name));
 | |
|             }
 | |
| 
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_GUID_OP:
 | |
|             if (CompareGuid ((EFI_GUID *)((UINTN)IfrOpCodeHeader + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {
 | |
|               QuestionStoredInBitField = TRUE;
 | |
|             }
 | |
| 
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_ONE_OF_OP:
 | |
|           case EFI_IFR_CHECKBOX_OP:
 | |
|           case EFI_IFR_NUMERIC_OP:
 | |
|           case EFI_IFR_ORDERED_LIST_OP:
 | |
|             DEBUG ((DEBUG_INFO, "    IfrOpCodeHeader->OpCode - 0x%02x (%a) (%a)\n", IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode), (QuestionStoredInBitField ? "bit level" : "byte level")));
 | |
|             DEBUG ((DEBUG_INFO, "    IfrOpCodeHeader->Length - 0x%02x\n", IfrOpCodeHeader->Length));
 | |
|             DEBUG ((DEBUG_INFO, "    IfrOpCodeHeader->Scope  - 0x%02x\n", IfrOpCodeHeader->Scope));
 | |
|             DEBUG ((DEBUG_INFO, "      Prompt       - 0x%04x\n", ((EFI_IFR_ONE_OF *)IfrOpCodeHeader)->Question.Header.Prompt));
 | |
|             DEBUG ((DEBUG_INFO, "      Help         - 0x%04x\n", ((EFI_IFR_ONE_OF *)IfrOpCodeHeader)->Question.Header.Help));
 | |
|             DEBUG ((DEBUG_INFO, "      QuestionId   - 0x%04x\n", ((EFI_IFR_ONE_OF *)IfrOpCodeHeader)->Question.QuestionId));
 | |
|             DEBUG ((DEBUG_INFO, "      VarStoreId   - 0x%04x\n", ((EFI_IFR_ONE_OF *)IfrOpCodeHeader)->Question.VarStoreId));
 | |
|             DEBUG ((DEBUG_INFO, "      VarStoreInfo - 0x%04x (%a)\n", ((EFI_IFR_ONE_OF *)IfrOpCodeHeader)->Question.VarStoreInfo.VarOffset, (QuestionStoredInBitField ? "bit level" : "byte level")));
 | |
|             {
 | |
|               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 ((DEBUG_INFO, "      Flags         - 0x%02x\n", IfrOneOf->Flags));
 | |
|                   if (QuestionStoredInBitField) {
 | |
|                     //
 | |
|                     // For OneOf stored in bit field, the option value are saved as UINT32 type.
 | |
|                     //
 | |
|                     DEBUG ((DEBUG_INFO, "      MinValue      - 0x%08x\n", IfrOneOf->data.u32.MinValue));
 | |
|                     DEBUG ((DEBUG_INFO, "      MaxValue      - 0x%08x\n", IfrOneOf->data.u32.MaxValue));
 | |
|                     DEBUG ((DEBUG_INFO, "      Step          - 0x%08x\n", IfrOneOf->data.u32.Step));
 | |
|                   } else {
 | |
|                     switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
 | |
|                       case EFI_IFR_NUMERIC_SIZE_1:
 | |
|                         DEBUG ((DEBUG_INFO, "      MinValue      - 0x%02x\n", IfrOneOf->data.u8.MinValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      MaxValue      - 0x%02x\n", IfrOneOf->data.u8.MaxValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      Step          - 0x%02x\n", IfrOneOf->data.u8.Step));
 | |
|                         break;
 | |
|                       case EFI_IFR_NUMERIC_SIZE_2:
 | |
|                         DEBUG ((DEBUG_INFO, "      MinValue      - 0x%04x\n", IfrOneOf->data.u16.MinValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      MaxValue      - 0x%04x\n", IfrOneOf->data.u16.MaxValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      Step          - 0x%04x\n", IfrOneOf->data.u16.Step));
 | |
|                         break;
 | |
|                       case EFI_IFR_NUMERIC_SIZE_4:
 | |
|                         DEBUG ((DEBUG_INFO, "      MinValue      - 0x%08x\n", IfrOneOf->data.u32.MinValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      MaxValue      - 0x%08x\n", IfrOneOf->data.u32.MaxValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      Step          - 0x%08x\n", IfrOneOf->data.u32.Step));
 | |
|                         break;
 | |
|                       case EFI_IFR_NUMERIC_SIZE_8:
 | |
|                         DEBUG ((DEBUG_INFO, "      MinValue      - 0x%016lx\n", IfrOneOf->data.u64.MinValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      MaxValue      - 0x%016lx\n", IfrOneOf->data.u64.MaxValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      Step          - 0x%016lx\n", IfrOneOf->data.u64.Step));
 | |
|                         break;
 | |
|                     }
 | |
|                   }
 | |
| 
 | |
|                   break;
 | |
|                 case EFI_IFR_CHECKBOX_OP:
 | |
|                   IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpCodeHeader;
 | |
|                   DEBUG ((DEBUG_INFO, "      Flags         - 0x%02x\n", IfrCheckBox->Flags));
 | |
|                   break;
 | |
|                 case EFI_IFR_NUMERIC_OP:
 | |
|                   IfrNumeric = (EFI_IFR_NUMERIC *)IfrOpCodeHeader;
 | |
|                   DEBUG ((DEBUG_INFO, "      Flags         - 0x%02x\n", IfrNumeric->Flags));
 | |
|                   if (QuestionStoredInBitField) {
 | |
|                     //
 | |
|                     // For Numeric stored in bit field, the MinValue,MaxValue and Step are saved as UINT32 type.
 | |
|                     //
 | |
|                     DEBUG ((DEBUG_INFO, "      MinValue      - 0x%08x\n", IfrNumeric->data.u32.MinValue));
 | |
|                     DEBUG ((DEBUG_INFO, "      MaxValue      - 0x%08x\n", IfrNumeric->data.u32.MaxValue));
 | |
|                     DEBUG ((DEBUG_INFO, "      Step          - 0x%08x\n", IfrNumeric->data.u32.Step));
 | |
|                   } else {
 | |
|                     switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {
 | |
|                       case EFI_IFR_NUMERIC_SIZE_1:
 | |
|                         DEBUG ((DEBUG_INFO, "      MinValue      - 0x%02x\n", IfrNumeric->data.u8.MinValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      MaxValue      - 0x%02x\n", IfrNumeric->data.u8.MaxValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      Step          - 0x%02x\n", IfrNumeric->data.u8.Step));
 | |
|                         break;
 | |
|                       case EFI_IFR_NUMERIC_SIZE_2:
 | |
|                         DEBUG ((DEBUG_INFO, "      MinValue      - 0x%04x\n", IfrNumeric->data.u16.MinValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      MaxValue      - 0x%04x\n", IfrNumeric->data.u16.MaxValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      Step          - 0x%04x\n", IfrNumeric->data.u16.Step));
 | |
|                         break;
 | |
|                       case EFI_IFR_NUMERIC_SIZE_4:
 | |
|                         DEBUG ((DEBUG_INFO, "      MinValue      - 0x%08x\n", IfrNumeric->data.u32.MinValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      MaxValue      - 0x%08x\n", IfrNumeric->data.u32.MaxValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      Step          - 0x%08x\n", IfrNumeric->data.u32.Step));
 | |
|                         break;
 | |
|                       case EFI_IFR_NUMERIC_SIZE_8:
 | |
|                         DEBUG ((DEBUG_INFO, "      MinValue      - 0x%016lx\n", IfrNumeric->data.u64.MinValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      MaxValue      - 0x%016lx\n", IfrNumeric->data.u64.MaxValue));
 | |
|                         DEBUG ((DEBUG_INFO, "      Step          - 0x%016lx\n", IfrNumeric->data.u64.Step));
 | |
|                         break;
 | |
|                     }
 | |
|                   }
 | |
| 
 | |
|                   break;
 | |
|                 case EFI_IFR_ORDERED_LIST_OP:
 | |
|                   IfrOrderedList = (EFI_IFR_ORDERED_LIST *)IfrOpCodeHeader;
 | |
|                   DEBUG ((DEBUG_INFO, "      MaxContainers - 0x%02x\n", IfrOrderedList->MaxContainers));
 | |
|                   DEBUG ((DEBUG_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 ((DEBUG_INFO, "!!!!    IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", (UINTN)IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode)));
 | |
|                       DEBUG ((DEBUG_INFO, "!!!!    IfrOpCodeHeader->Scope  - 0x%02x\n", IfrOpCodeHeader->Scope));
 | |
|                       DEBUG ((DEBUG_INFO, "!!!!      Option                - 0x%04x\n", IfrOneOfOption->Option));
 | |
|                       DEBUG ((DEBUG_INFO, "!!!!      Flags                 - 0x%02x\n", IfrOneOfOption->Flags));
 | |
|                       DEBUG ((DEBUG_INFO, "!!!!      Type                  - 0x%02x\n", IfrOneOfOption->Type));
 | |
|                       switch (IfrOneOfOption->Type) {
 | |
|                         case EFI_IFR_TYPE_NUM_SIZE_8:
 | |
|                           DEBUG ((DEBUG_INFO, "!!!!      Value                 - 0x%02x\n", IfrOneOfOption->Value.u8));
 | |
|                           break;
 | |
|                         case EFI_IFR_TYPE_NUM_SIZE_16:
 | |
|                           DEBUG ((DEBUG_INFO, "!!!!      Value                 - 0x%04x\n", IfrOneOfOption->Value.u16));
 | |
|                           break;
 | |
|                         case EFI_IFR_TYPE_NUM_SIZE_32:
 | |
|                           DEBUG ((DEBUG_INFO, "!!!!      Value                 - 0x%08x\n", IfrOneOfOption->Value.u32));
 | |
|                           break;
 | |
|                         case EFI_IFR_TYPE_NUM_SIZE_64:
 | |
|                           DEBUG ((DEBUG_INFO, "!!!!      Value                 - 0x%016lx\n", IfrOneOfOption->Value.u64));
 | |
|                           break;
 | |
|                         case EFI_IFR_TYPE_BOOLEAN:
 | |
|                           DEBUG ((DEBUG_INFO, "!!!!      Value                 - 0x%02x\n", IfrOneOfOption->Value.b));
 | |
|                           break;
 | |
|                         default:
 | |
|                           break;
 | |
|                       }
 | |
| 
 | |
|                       break;
 | |
|                   }
 | |
| 
 | |
|                   if (IfrOpCodeHeader->OpCode == EFI_IFR_END_OP) {
 | |
|                     QuestionStoredInBitField = FALSE;
 | |
|                     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 ((DEBUG_INFO, "HiiDatabaseSize - 0x%x\n", HiiDatabaseSize));
 | |
|   HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *)HiiDatabase;
 | |
| 
 | |
|   while ((UINTN)HiiPackageListHeader < ((UINTN)HiiDatabase + HiiDatabaseSize)) {
 | |
|     DEBUG ((DEBUG_INFO, "HiiPackageListHeader->PackageListGuid - %g\n", &HiiPackageListHeader->PackageListGuid));
 | |
|     DEBUG ((DEBUG_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;
 | |
|   UINTN                          ArrayIndex;
 | |
| 
 | |
|   //
 | |
|   // 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;
 | |
|   }
 | |
| 
 | |
|   if (HiiQuestion->BitFieldStore) {
 | |
|     ArrayIndex = HiiQuestion->VarOffset;
 | |
|   } else {
 | |
|     ArrayIndex = HiiQuestion->VarOffset * 8;
 | |
|   }
 | |
| 
 | |
|   HiiQuestion1 = HiiVariableNode->HiiQuestionArray[ArrayIndex];
 | |
|   HiiQuestion2 = HiiQuestion;
 | |
| 
 | |
|   ASSERT ((HiiQuestion1->OpCode == HiiQuestion2->OpCode) && (HiiQuestion1->StorageWidth == HiiQuestion2->StorageWidth));
 | |
| 
 | |
|   switch (HiiQuestion1->OpCode) {
 | |
|     case EFI_IFR_ONE_OF_OP:
 | |
|       DEBUG ((DEBUG_INFO, "MergeHiiQuestion - EFI_IFR_ONE_OF_OP VarOffset = 0x%04x (%a)\n", HiiQuestion1->VarOffset, (HiiQuestion1->BitFieldStore ? "bit level" : "byte level")));
 | |
|       //
 | |
|       // 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[ArrayIndex] = NewHiiQuestion;
 | |
|         InternalVarCheckFreePool (HiiQuestion1);
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_CHECKBOX_OP:
 | |
|       DEBUG ((DEBUG_INFO, "MergeHiiQuestion - EFI_IFR_CHECKBOX_OP VarOffset = 0x%04x (%a)\n", HiiQuestion1->VarOffset, (HiiQuestion1->BitFieldStore ? "bit level" : "byte level")));
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_NUMERIC_OP:
 | |
|       DEBUG ((DEBUG_INFO, "MergeHiiQuestion - EFI_IFR_NUMERIC_OP VarOffset = 0x%04x (%a)\n", HiiQuestion1->VarOffset, (HiiQuestion1->BitFieldStore ? "bit level" : "byte level")));
 | |
|       //
 | |
|       // 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 ((DEBUG_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[ArrayIndex] = 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.
 | |
|   @param[in] StoredInBitField   Whether the OneOf is stored in bit field Storage.
 | |
| 
 | |
|   return Pointer to Hii Question.
 | |
| 
 | |
| **/
 | |
| VAR_CHECK_HII_QUESTION_HEADER *
 | |
| ParseHiiQuestionOneOf (
 | |
|   IN EFI_IFR_OP_HEADER  *IfrOpCodeHeader,
 | |
|   IN BOOLEAN            StoredInBitField
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_ONE_OF                *IfrOneOf;
 | |
|   VAR_CHECK_HII_QUESTION_ONEOF  *OneOf;
 | |
|   UINTN                         Length;
 | |
|   UINT8                         Width;
 | |
|   UINTN                         OptionCount;
 | |
|   UINT8                         OptionWidth;
 | |
|   UINT8                         BitWidth;
 | |
| 
 | |
|   IfrOneOf = (EFI_IFR_ONE_OF *)IfrOpCodeHeader;
 | |
|   BitWidth = 0;
 | |
| 
 | |
|   if (StoredInBitField) {
 | |
|     //
 | |
|     // When OneOf stored in bit field, the bit width is saved in the lower six bits of the flag.
 | |
|     // And the options in the OneOf is saved as UINT32 type.
 | |
|     //
 | |
|     BitWidth = IfrOneOf->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;
 | |
|     Width    = sizeof (UINT32);
 | |
|   } else {
 | |
|     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->BitFieldStore = StoredInBitField;
 | |
|   if (StoredInBitField) {
 | |
|     OneOf->StorageWidth = BitWidth;
 | |
|   } else {
 | |
|     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.
 | |
|   @param[in] StoredInBitField   Whether the CheckBox is stored in bit field Storage.
 | |
| 
 | |
|   return Pointer to Hii Question.
 | |
| 
 | |
| **/
 | |
| VAR_CHECK_HII_QUESTION_HEADER *
 | |
| ParseHiiQuestionCheckBox (
 | |
|   IN EFI_IFR_OP_HEADER  *IfrOpCodeHeader,
 | |
|   IN BOOLEAN            StoredInBitField
 | |
|   )
 | |
| {
 | |
|   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->BitFieldStore = StoredInBitField;
 | |
|   if (StoredInBitField) {
 | |
|     CheckBox->StorageWidth = 1;
 | |
|   } else {
 | |
|     CheckBox->StorageWidth = (UINT8)sizeof (BOOLEAN);
 | |
|   }
 | |
| 
 | |
|   return (VAR_CHECK_HII_QUESTION_HEADER *)CheckBox;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parse Hii Question Numeric.
 | |
| 
 | |
|   @param[in] IfrOpCodeHeader    Pointer to Ifr OpCode header.
 | |
|   @param[in] StoredInBitField   Whether the Numeric is stored in bit field Storage.
 | |
| 
 | |
|   return Pointer to Hii Question.
 | |
| 
 | |
| **/
 | |
| VAR_CHECK_HII_QUESTION_HEADER *
 | |
| ParseHiiQuestionNumeric (
 | |
|   IN EFI_IFR_OP_HEADER  *IfrOpCodeHeader,
 | |
|   IN BOOLEAN            StoredInBitField
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_NUMERIC                 *IfrNumeric;
 | |
|   VAR_CHECK_HII_QUESTION_NUMERIC  *Numeric;
 | |
|   UINT8                           Width;
 | |
|   UINT8                           BitWidth;
 | |
| 
 | |
|   IfrNumeric = (EFI_IFR_NUMERIC *)IfrOpCodeHeader;
 | |
|   BitWidth   = 0;
 | |
| 
 | |
|   Numeric = InternalVarCheckAllocateZeroPool (sizeof (VAR_CHECK_HII_QUESTION_NUMERIC) + 2 * sizeof (UINT64));
 | |
|   ASSERT (Numeric != NULL);
 | |
| 
 | |
|   if (StoredInBitField) {
 | |
|     //
 | |
|     // When Numeric stored in bit field, the bit field width is saved in the lower six bits of the flag.
 | |
|     // And the Minimum Maximum of Numeric is saved as UINT32 type.
 | |
|     //
 | |
|     BitWidth = IfrNumeric->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;
 | |
|     Width    = sizeof (UINT32);
 | |
|   } else {
 | |
|     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->BitFieldStore = StoredInBitField;
 | |
|   if (StoredInBitField) {
 | |
|     Numeric->StorageWidth = BitWidth;
 | |
|   } else {
 | |
|     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;
 | |
|   OrderedList->BitFieldStore = FALSE;
 | |
| 
 | |
|   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.
 | |
|   @param[in] StoredInBitField   Whether the Question is stored in bit field Storage.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| ParseHiiQuestion (
 | |
|   IN VAR_CHECK_HII_VARIABLE_NODE  *HiiVariableNode,
 | |
|   IN  EFI_IFR_OP_HEADER           *IfrOpCodeHeader,
 | |
|   IN BOOLEAN                      FromFv,
 | |
|   IN BOOLEAN                      StoredInBitField
 | |
|   )
 | |
| {
 | |
|   VAR_CHECK_HII_QUESTION_HEADER  *HiiQuestion;
 | |
|   UINTN                          ArrayIndex;
 | |
| 
 | |
|   //
 | |
|   // Currently only OneOf, CheckBox and Numeric can be stored in bit field.
 | |
|   //
 | |
|   switch (IfrOpCodeHeader->OpCode) {
 | |
|     case EFI_IFR_ONE_OF_OP:
 | |
|       HiiQuestion = ParseHiiQuestionOneOf (IfrOpCodeHeader, StoredInBitField);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_CHECKBOX_OP:
 | |
|       HiiQuestion = ParseHiiQuestionCheckBox (IfrOpCodeHeader, StoredInBitField);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_NUMERIC_OP:
 | |
|       HiiQuestion = ParseHiiQuestionNumeric (IfrOpCodeHeader, StoredInBitField);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_ORDERED_LIST_OP:
 | |
|       HiiQuestion = ParseHiiQuestionOrderedList (IfrOpCodeHeader);
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       ASSERT (FALSE);
 | |
|       return;
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   if (StoredInBitField) {
 | |
|     ArrayIndex = HiiQuestion->VarOffset;
 | |
|   } else {
 | |
|     ArrayIndex = HiiQuestion->VarOffset * 8;
 | |
|   }
 | |
| 
 | |
|   if (HiiVariableNode->HiiQuestionArray[ArrayIndex] != NULL) {
 | |
|     MergeHiiQuestion (HiiVariableNode, HiiQuestion, FromFv);
 | |
|   } else {
 | |
|     HiiVariableNode->HiiQuestionArray[ArrayIndex] = 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) * sizeof (CHAR16);
 | |
|   if (VarNameSize > mMaxVarNameSize) {
 | |
|     mVarName = InternalVarCheckReallocatePool (mMaxVarNameSize, VarNameSize, mVarName);
 | |
|     ASSERT (mVarName != NULL);
 | |
|     mMaxVarNameSize = VarNameSize;
 | |
|   }
 | |
| 
 | |
|   AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, mVarName, mMaxVarNameSize / sizeof (CHAR16));
 | |
|   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 * 8 * 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;
 | |
|   BOOLEAN                      QuestionStoredInBitField;
 | |
| 
 | |
|   //
 | |
|   // Parse and create Hii Variable node list for this Hii Package.
 | |
|   //
 | |
|   ParseHiiVariable (HiiPackage);
 | |
| 
 | |
|   HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *)HiiPackage;
 | |
| 
 | |
|   QuestionStoredInBitField = FALSE;
 | |
| 
 | |
|   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_GUID_OP:
 | |
|             if (CompareGuid ((EFI_GUID *)((UINTN)IfrOpCodeHeader + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {
 | |
|               QuestionStoredInBitField = TRUE;
 | |
|             }
 | |
| 
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_END_OP:
 | |
|             QuestionStoredInBitField = FALSE;
 | |
|             break;
 | |
| 
 | |
|           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, QuestionStoredInBitField);
 | |
|             }
 | |
| 
 | |
|           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 Package.
 | |
|       //
 | |
|       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 * (UINTN)8; 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 * (UINTN)8; 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 ((DEBUG_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);
 | |
|   //
 | |
|   // Make sure the allocated buffer for VarCheckHiiBin at required alignment.
 | |
|   //
 | |
|   ASSERT ((((UINTN)Data) & (HEADER_ALIGNMENT - 1)) == 0);
 | |
|   DEBUG ((DEBUG_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 * (UINTN)8; 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 ((DEBUG_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
 | |
| }
 |