1 /** @file 2 Var Check Hii bin generation. 3 4 Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "VarCheckHiiGen.h" 16 17 LIST_ENTRY mVarCheckHiiList = INITIALIZE_LIST_HEAD_VARIABLE (mVarCheckHiiList); 18 19 #define VAR_CHECK_HII_VARIABLE_NODE_SIGNATURE SIGNATURE_32 ('V', 'C', 'H', 'V') 20 21 typedef struct { 22 UINTN Signature; 23 LIST_ENTRY Link; 24 VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable; 25 EFI_VARSTORE_ID VarStoreId; 26 27 VAR_CHECK_HII_QUESTION_HEADER **HiiQuestionArray; 28 } VAR_CHECK_HII_VARIABLE_NODE; 29 30 #define VAR_CHECK_HII_VARIABLE_FROM_LINK(a) CR (a, VAR_CHECK_HII_VARIABLE_NODE, Link, VAR_CHECK_HII_VARIABLE_NODE_SIGNATURE) 31 32 CHAR16 *mVarName = NULL; 33 UINTN mMaxVarNameSize = 0; 34 35 #ifdef DUMP_HII_DATA 36 GLOBAL_REMOVE_IF_UNREFERENCED VAR_CHECK_HII_OPCODE_STRING mIfrOpCodeStringTable[] = { 37 {EFI_IFR_VARSTORE_OP, "EFI_IFR_VARSTORE_OP"}, 38 {EFI_IFR_VARSTORE_EFI_OP, "EFI_IFR_VARSTORE_EFI_OP"}, 39 {EFI_IFR_ONE_OF_OP, "EFI_IFR_ONE_OF_OP"}, 40 {EFI_IFR_CHECKBOX_OP, "EFI_IFR_CHECKBOX_OP"}, 41 {EFI_IFR_NUMERIC_OP, "EFI_IFR_NUMERIC_OP"}, 42 {EFI_IFR_ORDERED_LIST_OP, "EFI_IFR_ORDERED_LIST_OP"}, 43 {EFI_IFR_ONE_OF_OPTION_OP, "EFI_IFR_ONE_OF_OPTION_OP"}, 44 }; 45 46 /** 47 Ifr opcode to string. 48 49 @param[in] IfrOpCode Ifr OpCode. 50 51 @return Pointer to string. 52 53 **/ 54 CHAR8 * 55 IfrOpCodeToStr ( 56 IN UINT8 IfrOpCode 57 ) 58 { 59 UINTN Index; 60 for (Index = 0; Index < ARRAY_SIZE (mIfrOpCodeStringTable); Index++) { 61 if (mIfrOpCodeStringTable[Index].HiiOpCode == IfrOpCode) { 62 return mIfrOpCodeStringTable[Index].HiiOpCodeStr; 63 } 64 } 65 66 return "<UnknownIfrOpCode>"; 67 } 68 69 GLOBAL_REMOVE_IF_UNREFERENCED VAR_CHECK_HII_PACKAGE_TYPE_STRING mPackageTypeStringTable[] = { 70 {EFI_HII_PACKAGE_TYPE_ALL, "EFI_HII_PACKAGE_TYPE_ALL"}, 71 {EFI_HII_PACKAGE_TYPE_GUID, "EFI_HII_PACKAGE_TYPE_GUID"}, 72 {EFI_HII_PACKAGE_FORMS, "EFI_HII_PACKAGE_FORMS"}, 73 {EFI_HII_PACKAGE_STRINGS, "EFI_HII_PACKAGE_STRINGS"}, 74 {EFI_HII_PACKAGE_FONTS, "EFI_HII_PACKAGE_FONTS"}, 75 {EFI_HII_PACKAGE_IMAGES, "EFI_HII_PACKAGE_IMAGES"}, 76 {EFI_HII_PACKAGE_SIMPLE_FONTS, "EFI_HII_PACKAGE_SIMPLE_FONTS"}, 77 {EFI_HII_PACKAGE_DEVICE_PATH, "EFI_HII_PACKAGE_DEVICE_PATH"}, 78 {EFI_HII_PACKAGE_KEYBOARD_LAYOUT, "EFI_HII_PACKAGE_KEYBOARD_LAYOUT"}, 79 {EFI_HII_PACKAGE_ANIMATIONS, "EFI_HII_PACKAGE_ANIMATIONS"}, 80 {EFI_HII_PACKAGE_END, "EFI_HII_PACKAGE_END"}, 81 {EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN, "EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN"}, 82 {EFI_HII_PACKAGE_TYPE_SYSTEM_END, "EFI_HII_PACKAGE_TYPE_SYSTEM_END"}, 83 }; 84 85 /** 86 Hii Package type to string. 87 88 @param[in] PackageType Package Type 89 90 @return Pointer to string. 91 92 **/ 93 CHAR8 * 94 HiiPackageTypeToStr ( 95 IN UINT8 PackageType 96 ) 97 { 98 UINTN Index; 99 for (Index = 0; Index < ARRAY_SIZE (mPackageTypeStringTable); Index++) { 100 if (mPackageTypeStringTable[Index].PackageType == PackageType) { 101 return mPackageTypeStringTable[Index].PackageTypeStr; 102 } 103 } 104 105 return "<UnknownPackageType>"; 106 } 107 108 /** 109 Dump Hii Package. 110 111 @param[in] HiiPackage Pointer to Hii Package. 112 113 **/ 114 VOID 115 DumpHiiPackage ( 116 IN VOID *HiiPackage 117 ) 118 { 119 EFI_HII_PACKAGE_HEADER *HiiPackageHeader; 120 EFI_IFR_OP_HEADER *IfrOpCodeHeader; 121 EFI_IFR_VARSTORE *IfrVarStore; 122 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore; 123 124 HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiPackage; 125 126 DEBUG ((EFI_D_INFO, " HiiPackageHeader->Type - 0x%02x (%a)\n", HiiPackageHeader->Type, HiiPackageTypeToStr ((UINT8) HiiPackageHeader->Type))); 127 DEBUG ((EFI_D_INFO, " HiiPackageHeader->Length - 0x%06x\n", HiiPackageHeader->Length)); 128 129 switch (HiiPackageHeader->Type) { 130 case EFI_HII_PACKAGE_FORMS: 131 IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) (HiiPackageHeader + 1); 132 133 while ((UINTN) IfrOpCodeHeader < ((UINTN) HiiPackageHeader + HiiPackageHeader->Length)) { 134 switch (IfrOpCodeHeader->OpCode) { 135 case EFI_IFR_VARSTORE_OP: 136 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpCodeHeader; 137 DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode))); 138 DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->Length - 0x%02x\n", IfrOpCodeHeader->Length)); 139 DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->Scope - 0x%02x\n", IfrOpCodeHeader->Scope)); 140 DEBUG ((EFI_D_INFO, " Guid - %g\n", &IfrVarStore->Guid)); 141 DEBUG ((EFI_D_INFO, " VarStoreId - 0x%04x\n", IfrVarStore->VarStoreId)); 142 DEBUG ((EFI_D_INFO, " Size - 0x%04x\n", IfrVarStore->Size)); 143 DEBUG ((EFI_D_INFO, " Name - %a\n", IfrVarStore->Name)); 144 break; 145 146 case EFI_IFR_VARSTORE_EFI_OP: 147 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpCodeHeader; 148 if (IfrEfiVarStore->Header.Length >= sizeof (EFI_IFR_VARSTORE_EFI)) { 149 DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode))); 150 DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->Length - 0x02%x\n", IfrOpCodeHeader->Length)); 151 DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->Scope - 0x02%x\n", IfrOpCodeHeader->Scope)); 152 DEBUG ((EFI_D_INFO, " Guid - %g\n", &IfrEfiVarStore->Guid)); 153 DEBUG ((EFI_D_INFO, " VarStoreId - 0x%04x\n", IfrEfiVarStore->VarStoreId)); 154 DEBUG ((EFI_D_INFO, " Size - 0x%04x\n", IfrEfiVarStore->Size)); 155 DEBUG ((EFI_D_INFO, " Attributes - 0x%08x\n", IfrEfiVarStore->Attributes)); 156 DEBUG ((EFI_D_INFO, " Name - %a\n", IfrEfiVarStore->Name)); 157 } 158 break; 159 160 case EFI_IFR_ONE_OF_OP: 161 case EFI_IFR_CHECKBOX_OP: 162 case EFI_IFR_NUMERIC_OP: 163 case EFI_IFR_ORDERED_LIST_OP: 164 DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode))); 165 DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->Length - 0x02%x\n", IfrOpCodeHeader->Length)); 166 DEBUG ((EFI_D_INFO, " IfrOpCodeHeader->Scope - 0x02%x\n", IfrOpCodeHeader->Scope)); 167 DEBUG ((EFI_D_INFO, " Prompt - 0x%04x\n", ((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.Header.Prompt)); 168 DEBUG ((EFI_D_INFO, " Help - 0x%04x\n", ((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.Header.Help)); 169 DEBUG ((EFI_D_INFO, " QuestionId - 0x%04x\n", ((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.QuestionId)); 170 DEBUG ((EFI_D_INFO, " VarStoreId - 0x%04x\n", ((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.VarStoreId)); 171 DEBUG ((EFI_D_INFO, " VarStoreInfo - 0x%04x\n", ((EFI_IFR_ONE_OF * )IfrOpCodeHeader)->Question.VarStoreInfo.VarOffset)); 172 { 173 EFI_IFR_ONE_OF *IfrOneOf; 174 EFI_IFR_CHECKBOX *IfrCheckBox; 175 EFI_IFR_NUMERIC *IfrNumeric; 176 EFI_IFR_ORDERED_LIST *IfrOrderedList; 177 178 switch (IfrOpCodeHeader->OpCode) { 179 case EFI_IFR_ONE_OF_OP: 180 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpCodeHeader; 181 DEBUG ((EFI_D_INFO, " Flags - 0x%02x\n", IfrOneOf->Flags)); 182 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) { 183 case EFI_IFR_NUMERIC_SIZE_1: 184 DEBUG ((EFI_D_INFO, " MinValue - 0x%02x\n", IfrOneOf->data.u8.MinValue)); 185 DEBUG ((EFI_D_INFO, " MaxValue - 0x%02x\n", IfrOneOf->data.u8.MaxValue)); 186 DEBUG ((EFI_D_INFO, " Step - 0x%02x\n", IfrOneOf->data.u8.Step)); 187 break; 188 case EFI_IFR_NUMERIC_SIZE_2: 189 DEBUG ((EFI_D_INFO, " MinValue - 0x%04x\n", IfrOneOf->data.u16.MinValue)); 190 DEBUG ((EFI_D_INFO, " MaxValue - 0x%04x\n", IfrOneOf->data.u16.MaxValue)); 191 DEBUG ((EFI_D_INFO, " Step - 0x%04x\n", IfrOneOf->data.u16.Step)); 192 break; 193 case EFI_IFR_NUMERIC_SIZE_4: 194 DEBUG ((EFI_D_INFO, " MinValue - 0x%08x\n", IfrOneOf->data.u32.MinValue)); 195 DEBUG ((EFI_D_INFO, " MaxValue - 0x%08x\n", IfrOneOf->data.u32.MaxValue)); 196 DEBUG ((EFI_D_INFO, " Step - 0x%08x\n", IfrOneOf->data.u32.Step)); 197 break; 198 case EFI_IFR_NUMERIC_SIZE_8: 199 DEBUG ((EFI_D_INFO, " MinValue - 0x%016lx\n", IfrOneOf->data.u64.MinValue)); 200 DEBUG ((EFI_D_INFO, " MaxValue - 0x%016lx\n", IfrOneOf->data.u64.MaxValue)); 201 DEBUG ((EFI_D_INFO, " Step - 0x%016lx\n", IfrOneOf->data.u64.Step)); 202 break; 203 } 204 break; 205 case EFI_IFR_CHECKBOX_OP: 206 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpCodeHeader; 207 DEBUG ((EFI_D_INFO, " Flags - 0x%02x\n", IfrCheckBox->Flags)); 208 break; 209 case EFI_IFR_NUMERIC_OP: 210 IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpCodeHeader; 211 DEBUG ((EFI_D_INFO, " Flags - 0x%02x\n", IfrNumeric->Flags)); 212 switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) { 213 case EFI_IFR_NUMERIC_SIZE_1: 214 DEBUG ((EFI_D_INFO, " MinValue - 0x%02x\n", IfrNumeric->data.u8.MinValue)); 215 DEBUG ((EFI_D_INFO, " MaxValue - 0x%02x\n", IfrNumeric->data.u8.MaxValue)); 216 DEBUG ((EFI_D_INFO, " Step - 0x%02x\n", IfrNumeric->data.u8.Step)); 217 break; 218 case EFI_IFR_NUMERIC_SIZE_2: 219 DEBUG ((EFI_D_INFO, " MinValue - 0x%04x\n", IfrNumeric->data.u16.MinValue)); 220 DEBUG ((EFI_D_INFO, " MaxValue - 0x%04x\n", IfrNumeric->data.u16.MaxValue)); 221 DEBUG ((EFI_D_INFO, " Step - 0x%04x\n", IfrNumeric->data.u16.Step)); 222 break; 223 case EFI_IFR_NUMERIC_SIZE_4: 224 DEBUG ((EFI_D_INFO, " MinValue - 0x%08x\n", IfrNumeric->data.u32.MinValue)); 225 DEBUG ((EFI_D_INFO, " MaxValue - 0x%08x\n", IfrNumeric->data.u32.MaxValue)); 226 DEBUG ((EFI_D_INFO, " Step - 0x%08x\n", IfrNumeric->data.u32.Step)); 227 break; 228 case EFI_IFR_NUMERIC_SIZE_8: 229 DEBUG ((EFI_D_INFO, " MinValue - 0x%016lx\n", IfrNumeric->data.u64.MinValue)); 230 DEBUG ((EFI_D_INFO, " MaxValue - 0x%016lx\n", IfrNumeric->data.u64.MaxValue)); 231 DEBUG ((EFI_D_INFO, " Step - 0x%016lx\n", IfrNumeric->data.u64.Step)); 232 break; 233 } 234 break; 235 case EFI_IFR_ORDERED_LIST_OP: 236 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpCodeHeader; 237 DEBUG ((EFI_D_INFO, " MaxContainers - 0x%02x\n", IfrOrderedList->MaxContainers)); 238 DEBUG ((EFI_D_INFO, " Flags - 0x%02x\n", IfrOrderedList->Flags)); 239 break; 240 default: 241 break; 242 } 243 244 if (IfrOpCodeHeader->Scope != 0) { 245 UINTN Scope; 246 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption; 247 248 IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length); 249 Scope = 1; 250 while (Scope != 0) { 251 switch (IfrOpCodeHeader->OpCode) { 252 case EFI_IFR_ONE_OF_OPTION_OP: 253 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *)IfrOpCodeHeader; 254 DEBUG ((EFI_D_INFO, "!!!! IfrOpCodeHeader->OpCode - 0x%02x (%a)\n", (UINTN)IfrOpCodeHeader->OpCode, IfrOpCodeToStr (IfrOpCodeHeader->OpCode))); 255 DEBUG ((EFI_D_INFO, "!!!! IfrOpCodeHeader->Scope - 0x%02x\n", IfrOpCodeHeader->Scope)); 256 DEBUG ((EFI_D_INFO, "!!!! Option - 0x%04x\n", IfrOneOfOption->Option)); 257 DEBUG ((EFI_D_INFO, "!!!! Flags - 0x%02x\n", IfrOneOfOption->Flags)); 258 DEBUG ((EFI_D_INFO, "!!!! Type - 0x%02x\n", IfrOneOfOption->Type)); 259 switch (IfrOneOfOption->Type) { 260 case EFI_IFR_TYPE_NUM_SIZE_8: 261 DEBUG ((EFI_D_INFO, "!!!! Value - 0x%02x\n", IfrOneOfOption->Value.u8)); 262 break; 263 case EFI_IFR_TYPE_NUM_SIZE_16: 264 DEBUG ((EFI_D_INFO, "!!!! Value - 0x%04x\n", IfrOneOfOption->Value.u16)); 265 break; 266 case EFI_IFR_TYPE_NUM_SIZE_32: 267 DEBUG ((EFI_D_INFO, "!!!! Value - 0x%08x\n", IfrOneOfOption->Value.u32)); 268 break; 269 case EFI_IFR_TYPE_NUM_SIZE_64: 270 DEBUG ((EFI_D_INFO, "!!!! Value - 0x%016lx\n", IfrOneOfOption->Value.u64)); 271 break; 272 case EFI_IFR_TYPE_BOOLEAN: 273 DEBUG ((EFI_D_INFO, "!!!! Value - 0x%02x\n", IfrOneOfOption->Value.b)); 274 break; 275 default: 276 break; 277 } 278 break; 279 } 280 281 if (IfrOpCodeHeader->OpCode == EFI_IFR_END_OP) { 282 ASSERT (Scope > 0); 283 Scope--; 284 if (Scope == 0) { 285 break; 286 } 287 } else if (IfrOpCodeHeader->Scope != 0) { 288 Scope++; 289 } 290 IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length); 291 } 292 } 293 } 294 default: 295 break; 296 } 297 IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length); 298 } 299 break; 300 default: 301 break; 302 } 303 } 304 305 /** 306 Dump Hii Database. 307 308 @param[in] HiiDatabase Pointer to Hii Database. 309 @param[in] HiiDatabaseSize Hii Database size. 310 311 **/ 312 VOID 313 DumpHiiDatabase ( 314 IN VOID *HiiDatabase, 315 IN UINTN HiiDatabaseSize 316 ) 317 { 318 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageListHeader; 319 EFI_HII_PACKAGE_HEADER *HiiPackageHeader; 320 321 DEBUG ((EFI_D_INFO, "HiiDatabaseSize - 0x%x\n", HiiDatabaseSize)); 322 HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *) HiiDatabase; 323 324 while ((UINTN) HiiPackageListHeader < ((UINTN) HiiDatabase + HiiDatabaseSize)) { 325 DEBUG ((EFI_D_INFO, "HiiPackageListHeader->PackageListGuid - %g\n", &HiiPackageListHeader->PackageListGuid)); 326 DEBUG ((EFI_D_INFO, "HiiPackageListHeader->PackageLength - 0x%x\n", (UINTN)HiiPackageListHeader->PackageLength)); 327 HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *)(HiiPackageListHeader + 1); 328 329 while ((UINTN) HiiPackageHeader < (UINTN) HiiPackageListHeader + HiiPackageListHeader->PackageLength) { 330 331 DumpHiiPackage (HiiPackageHeader); 332 333 HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINTN) HiiPackageHeader + HiiPackageHeader->Length); 334 } 335 336 HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *) ((UINTN) HiiPackageListHeader + HiiPackageListHeader->PackageLength); 337 } 338 339 return ; 340 } 341 #endif 342 343 /** 344 Allocates a buffer of a certain pool type. 345 346 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a 347 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is 348 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. 349 350 @param MemoryType The type of memory to allocate. 351 @param AllocationSize The number of bytes to allocate. 352 353 @return A pointer to the allocated buffer or NULL if allocation fails. 354 355 **/ 356 VOID * 357 InternalVarCheckAllocatePool ( 358 IN EFI_MEMORY_TYPE MemoryType, 359 IN UINTN AllocationSize 360 ) 361 { 362 EFI_STATUS Status; 363 VOID *Memory; 364 365 Status = gBS->AllocatePool (MemoryType, AllocationSize, &Memory); 366 if (EFI_ERROR (Status)) { 367 Memory = NULL; 368 } 369 return Memory; 370 } 371 372 /** 373 Allocates and zeros a buffer of type EfiBootServicesData. 374 375 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the 376 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a 377 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the 378 request, then NULL is returned. 379 380 @param AllocationSize The number of bytes to allocate and zero. 381 382 @return A pointer to the allocated buffer or NULL if allocation fails. 383 384 **/ 385 VOID * 386 InternalVarCheckAllocateZeroPool ( 387 IN UINTN AllocationSize 388 ) 389 { 390 VOID *Memory; 391 392 Memory = InternalVarCheckAllocatePool (EfiBootServicesData, AllocationSize); 393 if (Memory != NULL) { 394 Memory = ZeroMem (Memory, AllocationSize); 395 } 396 return Memory; 397 } 398 399 /** 400 Frees a buffer that was previously allocated with one of the pool allocation functions in the 401 Memory Allocation Library. 402 403 Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the 404 pool allocation services of the Memory Allocation Library. If it is not possible to free pool 405 resources, then this function will perform no actions. 406 407 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library, 408 then ASSERT(). 409 410 @param Buffer The pointer to the buffer to free. 411 412 **/ 413 VOID 414 EFIAPI 415 InternalVarCheckFreePool ( 416 IN VOID *Buffer 417 ) 418 { 419 EFI_STATUS Status; 420 421 Status = gBS->FreePool (Buffer); 422 ASSERT_EFI_ERROR (Status); 423 } 424 425 /** 426 Reallocates a buffer of type EfiBootServicesData. 427 428 Allocates and zeros the number bytes specified by NewSize from memory of type 429 EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and 430 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and 431 OldBuffer is freed. A pointer to the newly allocated buffer is returned. 432 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not 433 enough memory remaining to satisfy the request, then NULL is returned. 434 435 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize 436 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). 437 438 @param OldSize The size, in bytes, of OldBuffer. 439 @param NewSize The size, in bytes, of the buffer to reallocate. 440 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional 441 parameter that may be NULL. 442 443 @return A pointer to the allocated buffer or NULL if allocation fails. 444 445 **/ 446 VOID * 447 InternalVarCheckReallocatePool ( 448 IN UINTN OldSize, 449 IN UINTN NewSize, 450 IN VOID *OldBuffer OPTIONAL 451 ) 452 { 453 VOID *NewBuffer; 454 455 NewBuffer = InternalVarCheckAllocateZeroPool (NewSize); 456 if (NewBuffer != NULL && OldBuffer != NULL) { 457 CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize)); 458 InternalVarCheckFreePool (OldBuffer); 459 } 460 return NewBuffer; 461 } 462 463 /** 464 Merge Hii Question. 465 466 @param[in, out] HiiVariableNode Pointer to Hii Variable node. 467 @param[in] HiiQuestion Pointer to Hii Question. 468 @param[in] FromFv Hii Question from FV. 469 470 **/ 471 VOID 472 MergeHiiQuestion ( 473 IN OUT VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode, 474 IN VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion, 475 IN BOOLEAN FromFv 476 ) 477 { 478 VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion1; 479 VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion2; 480 VAR_CHECK_HII_QUESTION_HEADER *NewHiiQuestion; 481 UINT8 NewLength; 482 UINT64 Minimum1; 483 UINT64 Maximum1; 484 UINT64 OneValue1; 485 UINT64 Minimum2; 486 UINT64 Maximum2; 487 UINT64 OneValue2; 488 UINT8 *Ptr; 489 UINT8 *Ptr1; 490 UINT8 *Ptr2; 491 492 // 493 // Hii Question from Hii Database has high priority. 494 // Do not to merge Hii Question from Fv to Hii Question from Hii Database. 495 // 496 if (FromFv) { 497 InternalVarCheckFreePool (HiiQuestion); 498 return; 499 } 500 501 HiiQuestion1 = HiiVariableNode->HiiQuestionArray[HiiQuestion->VarOffset]; 502 HiiQuestion2 = HiiQuestion; 503 504 ASSERT ((HiiQuestion1->OpCode == HiiQuestion2->OpCode) && (HiiQuestion1->StorageWidth == HiiQuestion2->StorageWidth)); 505 506 switch (HiiQuestion1->OpCode) { 507 case EFI_IFR_ONE_OF_OP: 508 DEBUG ((EFI_D_INFO, "MergeHiiQuestion - EFI_IFR_ONE_OF_OP VarOffset = 0x%04x\n", HiiQuestion1->VarOffset)); 509 // 510 // Get the length of Hii Question 1. 511 // 512 NewLength = HiiQuestion1->Length; 513 514 // 515 // Check if the one of options in Hii Question 2 have been in Hii Question 1. 516 // 517 Ptr2 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion2 + 1); 518 while ((UINTN) Ptr2 < (UINTN) HiiQuestion2 + HiiQuestion2->Length) { 519 OneValue2 = 0; 520 CopyMem (&OneValue2, Ptr2, HiiQuestion2->StorageWidth); 521 522 Ptr1 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion1 + 1); 523 while ((UINTN) Ptr1 < (UINTN) HiiQuestion1 + HiiQuestion1->Length) { 524 OneValue1 = 0; 525 CopyMem (&OneValue1, Ptr1, HiiQuestion1->StorageWidth); 526 if (OneValue2 == OneValue1) { 527 // 528 // Match 529 // 530 break; 531 } 532 Ptr1 += HiiQuestion1->StorageWidth; 533 } 534 if ((UINTN) Ptr1 >= ((UINTN) HiiQuestion1 + HiiQuestion1->Length)) { 535 // 536 // No match 537 // 538 NewLength = (UINT8) (NewLength + HiiQuestion1->StorageWidth); 539 } 540 Ptr2 += HiiQuestion2->StorageWidth; 541 } 542 543 if (NewLength > HiiQuestion1->Length) { 544 // 545 // Merge the one of options of Hii Question 2 and Hii Question 1. 546 // 547 NewHiiQuestion = InternalVarCheckAllocateZeroPool (NewLength); 548 ASSERT (NewHiiQuestion != NULL); 549 CopyMem (NewHiiQuestion, HiiQuestion1, HiiQuestion1->Length); 550 // 551 // Use the new length. 552 // 553 NewHiiQuestion->Length = NewLength; 554 Ptr = (UINT8 *) NewHiiQuestion + HiiQuestion1->Length; 555 556 Ptr2 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion2 + 1); 557 while ((UINTN) Ptr2 < (UINTN) HiiQuestion2 + HiiQuestion2->Length) { 558 OneValue2 = 0; 559 CopyMem (&OneValue2, Ptr2, HiiQuestion2->StorageWidth); 560 561 Ptr1 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion1 + 1); 562 while ((UINTN) Ptr1 < (UINTN) HiiQuestion1 + HiiQuestion1->Length) { 563 OneValue1 = 0; 564 CopyMem (&OneValue1, Ptr1, HiiQuestion1->StorageWidth); 565 if (OneValue2 == OneValue1) { 566 // 567 // Match 568 // 569 break; 570 } 571 Ptr1 += HiiQuestion1->StorageWidth; 572 } 573 if ((UINTN) Ptr1 >= ((UINTN) HiiQuestion1 + HiiQuestion1->Length)) { 574 // 575 // No match 576 // 577 CopyMem (Ptr, &OneValue2, HiiQuestion1->StorageWidth); 578 Ptr += HiiQuestion1->StorageWidth; 579 } 580 Ptr2 += HiiQuestion2->StorageWidth; 581 } 582 583 HiiVariableNode->HiiQuestionArray[HiiQuestion1->VarOffset] = NewHiiQuestion; 584 InternalVarCheckFreePool (HiiQuestion1); 585 } 586 break; 587 588 case EFI_IFR_CHECKBOX_OP: 589 DEBUG ((EFI_D_INFO, "MergeHiiQuestion - EFI_IFR_CHECKBOX_OP VarOffset = 0x%04x\n", HiiQuestion1->VarOffset)); 590 break; 591 592 case EFI_IFR_NUMERIC_OP: 593 DEBUG ((EFI_D_INFO, "MergeHiiQuestion - EFI_IFR_NUMERIC_OP VarOffset = 0x%04x\n", HiiQuestion1->VarOffset)); 594 // 595 // Get minimum and maximum of Hii Question 1. 596 // 597 Minimum1 = 0; 598 Maximum1 = 0; 599 Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion1 + 1); 600 CopyMem (&Minimum1, Ptr, HiiQuestion1->StorageWidth); 601 Ptr += HiiQuestion1->StorageWidth; 602 CopyMem (&Maximum1, Ptr, HiiQuestion1->StorageWidth); 603 604 // 605 // Get minimum and maximum of Hii Question 2. 606 // 607 Minimum2 = 0; 608 Maximum2 = 0; 609 Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion2 + 1); 610 CopyMem (&Minimum2, Ptr, HiiQuestion2->StorageWidth); 611 Ptr += HiiQuestion2->StorageWidth; 612 CopyMem (&Maximum2, Ptr, HiiQuestion2->StorageWidth); 613 614 // 615 // Update minimum. 616 // 617 Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion1 + 1); 618 if (Minimum2 < Minimum1) { 619 Minimum1 = Minimum2; 620 CopyMem (Ptr, &Minimum1, HiiQuestion1->StorageWidth); 621 } 622 // 623 // Update maximum. 624 // 625 Ptr += HiiQuestion1->StorageWidth; 626 if (Maximum2 > Maximum1) { 627 Maximum1 = Maximum2; 628 CopyMem (Ptr, &Maximum1, HiiQuestion1->StorageWidth); 629 } 630 break; 631 632 case EFI_IFR_ORDERED_LIST_OP: 633 DEBUG ((EFI_D_INFO, "MergeHiiQuestion - EFI_IFR_ORDERED_LIST_OP VarOffset = 0x%04x\n", HiiQuestion1->VarOffset)); 634 // 635 // Get the length of Hii Question 1. 636 // 637 NewLength = HiiQuestion1->Length; 638 639 // 640 // Check if the one of options in Hii Question 2 have been in Hii Question 1. 641 // 642 Ptr2 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion2 + 1); 643 while ((UINTN) Ptr2 < (UINTN) HiiQuestion2 + HiiQuestion2->Length) { 644 OneValue2 = 0; 645 CopyMem (&OneValue2, Ptr2, HiiQuestion2->StorageWidth); 646 647 Ptr1 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion1 + 1); 648 while ((UINTN) Ptr1 < (UINTN) HiiQuestion1 + HiiQuestion1->Length) { 649 OneValue1 = 0; 650 CopyMem (&OneValue1, Ptr1, HiiQuestion1->StorageWidth); 651 if (OneValue2 == OneValue1) { 652 // 653 // Match 654 // 655 break; 656 } 657 Ptr1 += HiiQuestion1->StorageWidth; 658 } 659 if ((UINTN) Ptr1 >= ((UINTN) HiiQuestion1 + HiiQuestion1->Length)) { 660 // 661 // No match 662 // 663 NewLength = (UINT8) (NewLength + HiiQuestion1->StorageWidth); 664 } 665 Ptr2 += HiiQuestion2->StorageWidth; 666 } 667 668 if (NewLength > HiiQuestion1->Length) { 669 // 670 // Merge the one of options of Hii Question 2 and Hii Question 1. 671 // 672 NewHiiQuestion = InternalVarCheckAllocateZeroPool (NewLength); 673 ASSERT (NewHiiQuestion != NULL); 674 CopyMem (NewHiiQuestion, HiiQuestion1, HiiQuestion1->Length); 675 // 676 // Use the new length. 677 // 678 NewHiiQuestion->Length = NewLength; 679 Ptr = (UINT8 *) NewHiiQuestion + HiiQuestion1->Length; 680 681 Ptr2 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion2 + 1); 682 while ((UINTN) Ptr2 < (UINTN) HiiQuestion2 + HiiQuestion2->Length) { 683 OneValue2 = 0; 684 CopyMem (&OneValue2, Ptr2, HiiQuestion2->StorageWidth); 685 686 Ptr1 = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion1 + 1); 687 while ((UINTN) Ptr1 < (UINTN) HiiQuestion1 + HiiQuestion1->Length) { 688 OneValue1 = 0; 689 CopyMem (&OneValue1, Ptr1, HiiQuestion1->StorageWidth); 690 if (OneValue2 == OneValue1) { 691 // 692 // Match 693 // 694 break; 695 } 696 Ptr1 += HiiQuestion1->StorageWidth; 697 } 698 if ((UINTN) Ptr1 >= ((UINTN) HiiQuestion1 + HiiQuestion1->Length)) { 699 // 700 // No match 701 // 702 CopyMem (Ptr, &OneValue2, HiiQuestion1->StorageWidth); 703 Ptr += HiiQuestion1->StorageWidth; 704 } 705 Ptr2 += HiiQuestion2->StorageWidth; 706 } 707 708 HiiVariableNode->HiiQuestionArray[HiiQuestion1->VarOffset] = NewHiiQuestion; 709 InternalVarCheckFreePool (HiiQuestion1); 710 } 711 break; 712 713 default: 714 ASSERT (FALSE); 715 return; 716 break; 717 } 718 719 // 720 // 721 // Hii Question 2 has been merged with Hii Question 1. 722 // 723 InternalVarCheckFreePool (HiiQuestion2); 724 } 725 726 /** 727 Get OneOf option data. 728 729 @param[in] IfrOpCodeHeader Pointer to Ifr OpCode header. 730 @param[out] Count Pointer to option count. 731 @param[out] Width Pointer to option width. 732 @param[out] OptionBuffer Pointer to option buffer. 733 734 **/ 735 VOID 736 GetOneOfOption ( 737 IN EFI_IFR_OP_HEADER *IfrOpCodeHeader, 738 OUT UINTN *Count, 739 OUT UINT8 *Width, 740 OUT VOID *OptionBuffer OPTIONAL 741 ) 742 { 743 UINTN Scope; 744 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption; 745 746 // 747 // Assume all OPTION has same Width. 748 // 749 *Count = 0; 750 751 if (IfrOpCodeHeader->Scope != 0) { 752 // 753 // Nested OpCode. 754 // 755 Scope = 1; 756 IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length); 757 while (Scope != 0) { 758 switch (IfrOpCodeHeader->OpCode) { 759 case EFI_IFR_ONE_OF_OPTION_OP: 760 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpCodeHeader; 761 switch (IfrOneOfOption->Type) { 762 case EFI_IFR_TYPE_NUM_SIZE_8: 763 *Count = *Count + 1; 764 *Width = sizeof (UINT8); 765 if (OptionBuffer != NULL) { 766 CopyMem (OptionBuffer, &IfrOneOfOption->Value.u8, sizeof (UINT8)); 767 OptionBuffer = (UINT8 *) OptionBuffer + 1; 768 } 769 break; 770 case EFI_IFR_TYPE_NUM_SIZE_16: 771 *Count = *Count + 1; 772 *Width = sizeof (UINT16); 773 if (OptionBuffer != NULL) { 774 CopyMem (OptionBuffer, &IfrOneOfOption->Value.u16, sizeof (UINT16)); 775 OptionBuffer = (UINT16 *) OptionBuffer + 1; 776 } 777 break; 778 case EFI_IFR_TYPE_NUM_SIZE_32: 779 *Count = *Count + 1; 780 *Width = sizeof (UINT32); 781 if (OptionBuffer != NULL) { 782 CopyMem (OptionBuffer, &IfrOneOfOption->Value.u32, sizeof (UINT32)); 783 OptionBuffer = (UINT32 *) OptionBuffer + 1; 784 } 785 break; 786 case EFI_IFR_TYPE_NUM_SIZE_64: 787 *Count = *Count + 1; 788 *Width = sizeof (UINT64); 789 if (OptionBuffer != NULL) { 790 CopyMem (OptionBuffer, &IfrOneOfOption->Value.u64, sizeof (UINT64)); 791 OptionBuffer = (UINT64 *) OptionBuffer + 1; 792 } 793 break; 794 case EFI_IFR_TYPE_BOOLEAN: 795 *Count = *Count + 1; 796 *Width = sizeof (BOOLEAN); 797 if (OptionBuffer != NULL) { 798 CopyMem (OptionBuffer, &IfrOneOfOption->Value.b, sizeof (BOOLEAN)); 799 OptionBuffer = (BOOLEAN *) OptionBuffer + 1; 800 } 801 break; 802 default: 803 break; 804 } 805 break; 806 } 807 808 // 809 // Until End OpCode. 810 // 811 if (IfrOpCodeHeader->OpCode == EFI_IFR_END_OP) { 812 ASSERT (Scope > 0); 813 Scope--; 814 if (Scope == 0) { 815 break; 816 } 817 } else if (IfrOpCodeHeader->Scope != 0) { 818 // 819 // Nested OpCode. 820 // 821 Scope++; 822 } 823 IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length); 824 } 825 } 826 827 return ; 828 } 829 830 /** 831 Parse Hii Question Oneof. 832 833 @param[in] IfrOpCodeHeader Pointer to Ifr OpCode header. 834 835 return Pointer to Hii Question. 836 837 **/ 838 VAR_CHECK_HII_QUESTION_HEADER * 839 ParseHiiQuestionOneOf ( 840 IN EFI_IFR_OP_HEADER *IfrOpCodeHeader 841 ) 842 { 843 EFI_IFR_ONE_OF *IfrOneOf; 844 VAR_CHECK_HII_QUESTION_ONEOF *OneOf; 845 UINTN Length; 846 UINT8 Width; 847 UINTN OptionCount; 848 UINT8 OptionWidth; 849 850 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpCodeHeader; 851 852 Width = (UINT8) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE)); 853 854 GetOneOfOption (IfrOpCodeHeader, &OptionCount, &OptionWidth, NULL); 855 ASSERT (Width == OptionWidth); 856 857 Length = sizeof (*OneOf) + OptionCount * Width; 858 859 OneOf = InternalVarCheckAllocateZeroPool (Length); 860 ASSERT (OneOf != NULL); 861 OneOf->OpCode = EFI_IFR_ONE_OF_OP; 862 OneOf->Length = (UINT8) Length; 863 OneOf->VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset; 864 OneOf->StorageWidth = Width; 865 866 GetOneOfOption (IfrOpCodeHeader, &OptionCount, &OptionWidth, OneOf + 1); 867 868 return (VAR_CHECK_HII_QUESTION_HEADER *) OneOf; 869 } 870 871 /** 872 Parse Hii Question CheckBox. 873 874 @param[in] IfrOpCodeHeader Pointer to Ifr OpCode header. 875 876 return Pointer to Hii Question. 877 878 **/ 879 VAR_CHECK_HII_QUESTION_HEADER * 880 ParseHiiQuestionCheckBox ( 881 IN EFI_IFR_OP_HEADER *IfrOpCodeHeader 882 ) 883 { 884 EFI_IFR_CHECKBOX *IfrCheckBox; 885 VAR_CHECK_HII_QUESTION_CHECKBOX *CheckBox; 886 887 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpCodeHeader; 888 889 CheckBox = InternalVarCheckAllocateZeroPool (sizeof (*CheckBox)); 890 ASSERT (CheckBox != NULL); 891 CheckBox->OpCode = EFI_IFR_CHECKBOX_OP; 892 CheckBox->Length = (UINT8) sizeof (*CheckBox);; 893 CheckBox->VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset; 894 CheckBox->StorageWidth = (UINT8) sizeof (BOOLEAN); 895 896 return (VAR_CHECK_HII_QUESTION_HEADER *) CheckBox; 897 } 898 899 /** 900 Parse Hii Question Numeric. 901 902 @param[in] IfrOpCodeHeader Pointer to Ifr OpCode header. 903 904 return Pointer to Hii Question. 905 906 **/ 907 VAR_CHECK_HII_QUESTION_HEADER * 908 ParseHiiQuestionNumeric ( 909 IN EFI_IFR_OP_HEADER *IfrOpCodeHeader 910 ) 911 { 912 EFI_IFR_NUMERIC *IfrNumeric; 913 VAR_CHECK_HII_QUESTION_NUMERIC *Numeric; 914 UINT8 Width; 915 916 IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpCodeHeader; 917 918 Numeric = InternalVarCheckAllocateZeroPool (sizeof (VAR_CHECK_HII_QUESTION_NUMERIC) + 2 * sizeof (UINT64)); 919 ASSERT (Numeric != NULL); 920 921 Width = (UINT8) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE)); 922 923 Numeric->OpCode = EFI_IFR_NUMERIC_OP; 924 Numeric->Length = (UINT8) (sizeof (VAR_CHECK_HII_QUESTION_NUMERIC) + 2 * Width); 925 Numeric->VarOffset = IfrNumeric->Question.VarStoreInfo.VarOffset; 926 Numeric->StorageWidth = Width; 927 928 CopyMem (Numeric + 1, &IfrNumeric->data, Width * 2); 929 930 return (VAR_CHECK_HII_QUESTION_HEADER *) Numeric; 931 } 932 933 /** 934 Parse Hii Question OrderedList. 935 936 @param[in] IfrOpCodeHeader Pointer to Ifr OpCode header. 937 938 return Pointer to Hii Question. 939 940 **/ 941 VAR_CHECK_HII_QUESTION_HEADER * 942 ParseHiiQuestionOrderedList ( 943 IN EFI_IFR_OP_HEADER *IfrOpCodeHeader 944 ) 945 { 946 EFI_IFR_ORDERED_LIST *IfrOrderedList; 947 VAR_CHECK_HII_QUESTION_ORDEREDLIST *OrderedList; 948 UINTN Length; 949 UINTN OptionCount; 950 UINT8 OptionWidth; 951 952 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpCodeHeader; 953 954 GetOneOfOption (IfrOpCodeHeader, &OptionCount, &OptionWidth, NULL); 955 956 Length = sizeof (*OrderedList) + OptionCount * OptionWidth; 957 958 OrderedList = InternalVarCheckAllocateZeroPool (Length); 959 ASSERT (OrderedList != NULL); 960 OrderedList->OpCode = EFI_IFR_ORDERED_LIST_OP; 961 OrderedList->Length = (UINT8) Length; 962 OrderedList->VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset; 963 OrderedList->StorageWidth = OptionWidth; 964 OrderedList->MaxContainers = IfrOrderedList->MaxContainers; 965 966 GetOneOfOption (IfrOpCodeHeader, &OptionCount, &OptionWidth, OrderedList + 1); 967 968 return (VAR_CHECK_HII_QUESTION_HEADER *) OrderedList; 969 } 970 971 /** 972 Parse and create Hii Question node. 973 974 @param[in] HiiVariableNode Pointer to Hii Variable node. 975 @param[in] IfrOpCodeHeader Pointer to Ifr OpCode header. 976 @param[in] FromFv Hii Question from FV. 977 978 **/ 979 VOID 980 ParseHiiQuestion ( 981 IN VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode, 982 IN EFI_IFR_OP_HEADER *IfrOpCodeHeader, 983 IN BOOLEAN FromFv 984 ) 985 { 986 VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion; 987 988 switch (IfrOpCodeHeader->OpCode) { 989 case EFI_IFR_ONE_OF_OP: 990 HiiQuestion = ParseHiiQuestionOneOf (IfrOpCodeHeader); 991 break; 992 993 case EFI_IFR_CHECKBOX_OP: 994 HiiQuestion = ParseHiiQuestionCheckBox (IfrOpCodeHeader); 995 break; 996 997 case EFI_IFR_NUMERIC_OP: 998 HiiQuestion = ParseHiiQuestionNumeric (IfrOpCodeHeader); 999 break; 1000 1001 case EFI_IFR_ORDERED_LIST_OP: 1002 HiiQuestion = ParseHiiQuestionOrderedList (IfrOpCodeHeader); 1003 break; 1004 1005 default: 1006 ASSERT (FALSE); 1007 return; 1008 break; 1009 } 1010 1011 if (HiiVariableNode->HiiQuestionArray[HiiQuestion->VarOffset] != NULL) { 1012 MergeHiiQuestion (HiiVariableNode, HiiQuestion, FromFv); 1013 } else { 1014 HiiVariableNode->HiiQuestionArray[HiiQuestion->VarOffset] = HiiQuestion; 1015 } 1016 } 1017 1018 /** 1019 Find Hii variable node by name and GUID. 1020 1021 @param[in] Name Pointer to variable name. 1022 @param[in] Guid Pointer to vendor GUID. 1023 1024 @return Pointer to Hii Variable node. 1025 1026 **/ 1027 VAR_CHECK_HII_VARIABLE_NODE * 1028 FindHiiVariableNode ( 1029 IN CHAR16 *Name, 1030 IN EFI_GUID *Guid 1031 ) 1032 { 1033 VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode; 1034 LIST_ENTRY *Link; 1035 1036 for (Link = mVarCheckHiiList.ForwardLink 1037 ;Link != &mVarCheckHiiList 1038 ;Link = Link->ForwardLink) { 1039 HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (Link); 1040 1041 if ((StrCmp (Name, (CHAR16 *) (HiiVariableNode->HiiVariable + 1)) == 0) && 1042 CompareGuid (Guid, &HiiVariableNode->HiiVariable->Guid)) { 1043 return HiiVariableNode; 1044 } 1045 } 1046 1047 return NULL; 1048 } 1049 1050 /** 1051 Find Hii variable node by var store id. 1052 1053 @param[in] VarStoreId Var store id. 1054 1055 @return Pointer to Hii Variable node. 1056 1057 **/ 1058 VAR_CHECK_HII_VARIABLE_NODE * 1059 FindHiiVariableNodeByVarStoreId ( 1060 IN EFI_VARSTORE_ID VarStoreId 1061 ) 1062 { 1063 VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode; 1064 LIST_ENTRY *Link; 1065 1066 if (VarStoreId == 0) { 1067 // 1068 // The variable store identifier, which is unique within the current form set. 1069 // A value of zero is invalid. 1070 // 1071 return NULL; 1072 } 1073 1074 for (Link = mVarCheckHiiList.ForwardLink 1075 ;Link != &mVarCheckHiiList 1076 ;Link = Link->ForwardLink) { 1077 HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (Link); 1078 // 1079 // The variable store identifier, which is unique within the current form set. 1080 // 1081 if (VarStoreId == HiiVariableNode->VarStoreId) { 1082 return HiiVariableNode; 1083 } 1084 } 1085 1086 return NULL; 1087 } 1088 1089 /** 1090 Destroy var store id in the Hii Variable node after parsing one Hii Package. 1091 1092 **/ 1093 VOID 1094 DestroyVarStoreId ( 1095 VOID 1096 ) 1097 { 1098 VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode; 1099 LIST_ENTRY *Link; 1100 1101 for (Link = mVarCheckHiiList.ForwardLink 1102 ;Link != &mVarCheckHiiList 1103 ;Link = Link->ForwardLink) { 1104 HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (Link); 1105 // 1106 // The variable store identifier, which is unique within the current form set. 1107 // A value of zero is invalid. 1108 // 1109 HiiVariableNode->VarStoreId = 0; 1110 } 1111 } 1112 1113 /** 1114 Create Hii Variable node. 1115 1116 @param[in] IfrEfiVarStore Pointer to EFI VARSTORE. 1117 1118 **/ 1119 VOID 1120 CreateHiiVariableNode ( 1121 IN EFI_IFR_VARSTORE_EFI *IfrEfiVarStore 1122 ) 1123 { 1124 VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode; 1125 VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable; 1126 UINTN HeaderLength; 1127 CHAR16 *VarName; 1128 UINTN VarNameSize; 1129 1130 // 1131 // Get variable name. 1132 // 1133 VarNameSize = AsciiStrSize ((CHAR8 *) IfrEfiVarStore->Name) * sizeof (CHAR16); 1134 if (VarNameSize > mMaxVarNameSize) { 1135 mVarName = InternalVarCheckReallocatePool (mMaxVarNameSize, VarNameSize, mVarName); 1136 ASSERT (mVarName != NULL); 1137 mMaxVarNameSize = VarNameSize; 1138 } 1139 AsciiStrToUnicodeStrS ((CHAR8 *) IfrEfiVarStore->Name, mVarName, mMaxVarNameSize / sizeof (CHAR16)); 1140 VarName = mVarName; 1141 1142 HiiVariableNode = FindHiiVariableNode ( 1143 VarName, 1144 &IfrEfiVarStore->Guid 1145 ); 1146 if (HiiVariableNode == NULL) { 1147 // 1148 // Not found, then create new. 1149 // 1150 HeaderLength = sizeof (*HiiVariable) + VarNameSize; 1151 HiiVariable = InternalVarCheckAllocateZeroPool (HeaderLength); 1152 ASSERT (HiiVariable != NULL); 1153 HiiVariable->Revision = VAR_CHECK_HII_REVISION; 1154 HiiVariable->OpCode = EFI_IFR_VARSTORE_EFI_OP; 1155 HiiVariable->HeaderLength = (UINT16) HeaderLength; 1156 HiiVariable->Size = IfrEfiVarStore->Size; 1157 HiiVariable->Attributes = IfrEfiVarStore->Attributes; 1158 CopyGuid (&HiiVariable->Guid, &IfrEfiVarStore->Guid); 1159 StrCpyS ((CHAR16 *) (HiiVariable + 1), VarNameSize / sizeof (CHAR16), VarName); 1160 1161 HiiVariableNode = InternalVarCheckAllocateZeroPool (sizeof (*HiiVariableNode)); 1162 ASSERT (HiiVariableNode != NULL); 1163 HiiVariableNode->Signature = VAR_CHECK_HII_VARIABLE_NODE_SIGNATURE; 1164 HiiVariableNode->HiiVariable = HiiVariable; 1165 // 1166 // The variable store identifier, which is unique within the current form set. 1167 // 1168 HiiVariableNode->VarStoreId = IfrEfiVarStore->VarStoreId; 1169 HiiVariableNode->HiiQuestionArray = InternalVarCheckAllocateZeroPool (IfrEfiVarStore->Size * sizeof (VAR_CHECK_HII_QUESTION_HEADER *)); 1170 1171 InsertTailList (&mVarCheckHiiList, &HiiVariableNode->Link); 1172 } else { 1173 HiiVariableNode->VarStoreId = IfrEfiVarStore->VarStoreId; 1174 } 1175 } 1176 1177 /** 1178 Parse and create Hii Variable node list. 1179 1180 @param[in] HiiPackage Pointer to Hii Package. 1181 1182 **/ 1183 VOID 1184 ParseHiiVariable ( 1185 IN VOID *HiiPackage 1186 ) 1187 { 1188 EFI_HII_PACKAGE_HEADER *HiiPackageHeader; 1189 EFI_IFR_OP_HEADER *IfrOpCodeHeader; 1190 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore; 1191 1192 HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiPackage; 1193 1194 switch (HiiPackageHeader->Type) { 1195 case EFI_HII_PACKAGE_FORMS: 1196 IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) (HiiPackageHeader + 1); 1197 1198 while ((UINTN) IfrOpCodeHeader < (UINTN) HiiPackageHeader + HiiPackageHeader->Length) { 1199 switch (IfrOpCodeHeader->OpCode) { 1200 case EFI_IFR_VARSTORE_EFI_OP: 1201 // 1202 // Come to EFI VARSTORE in Form Package. 1203 // 1204 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpCodeHeader; 1205 if ((IfrEfiVarStore->Header.Length >= sizeof (EFI_IFR_VARSTORE_EFI)) && 1206 ((IfrEfiVarStore->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0)) { 1207 // 1208 // Only create node list for Hii Variable with NV attribute. 1209 // 1210 CreateHiiVariableNode (IfrEfiVarStore); 1211 } 1212 break; 1213 1214 default: 1215 break; 1216 } 1217 IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length); 1218 } 1219 break; 1220 1221 default: 1222 break; 1223 } 1224 } 1225 1226 /** 1227 Var Check Parse Hii Package. 1228 1229 @param[in] HiiPackage Pointer to Hii Package. 1230 @param[in] FromFv Hii Package from FV. 1231 1232 **/ 1233 VOID 1234 VarCheckParseHiiPackage ( 1235 IN VOID *HiiPackage, 1236 IN BOOLEAN FromFv 1237 ) 1238 { 1239 EFI_HII_PACKAGE_HEADER *HiiPackageHeader; 1240 EFI_IFR_OP_HEADER *IfrOpCodeHeader; 1241 VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode; 1242 1243 // 1244 // Parse and create Hii Variable node list for this Hii Package. 1245 // 1246 ParseHiiVariable (HiiPackage); 1247 1248 HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiPackage; 1249 1250 switch (HiiPackageHeader->Type) { 1251 case EFI_HII_PACKAGE_FORMS: 1252 IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) (HiiPackageHeader + 1); 1253 1254 while ((UINTN) IfrOpCodeHeader < (UINTN) HiiPackageHeader + HiiPackageHeader->Length) { 1255 switch (IfrOpCodeHeader->OpCode) { 1256 case EFI_IFR_ONE_OF_OP: 1257 case EFI_IFR_CHECKBOX_OP: 1258 case EFI_IFR_NUMERIC_OP: 1259 case EFI_IFR_ORDERED_LIST_OP: 1260 HiiVariableNode = FindHiiVariableNodeByVarStoreId (((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.VarStoreId); 1261 if ((HiiVariableNode == NULL) || 1262 // 1263 // No related Hii Variable node found. 1264 // 1265 ((((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.Header.Prompt == 0) && (((EFI_IFR_ONE_OF *) IfrOpCodeHeader)->Question.Header.Help == 0))) { 1266 // 1267 // meanless IFR item introduced by ECP. 1268 // 1269 } else { 1270 // 1271 // Normal IFR 1272 // 1273 ParseHiiQuestion (HiiVariableNode, IfrOpCodeHeader, FromFv); 1274 } 1275 default: 1276 break; 1277 } 1278 IfrOpCodeHeader = (EFI_IFR_OP_HEADER *) ((UINTN) IfrOpCodeHeader + IfrOpCodeHeader->Length); 1279 } 1280 break; 1281 1282 default: 1283 break; 1284 } 1285 DestroyVarStoreId (); 1286 } 1287 1288 /** 1289 Var Check Parse Hii Database. 1290 1291 @param[in] HiiDatabase Pointer to Hii Database. 1292 @param[in] HiiDatabaseSize Hii Database size. 1293 1294 **/ 1295 VOID 1296 VarCheckParseHiiDatabase ( 1297 IN VOID *HiiDatabase, 1298 IN UINTN HiiDatabaseSize 1299 ) 1300 { 1301 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageListHeader; 1302 EFI_HII_PACKAGE_HEADER *HiiPackageHeader; 1303 1304 HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *) HiiDatabase; 1305 1306 while ((UINTN) HiiPackageListHeader < ((UINTN) HiiDatabase + HiiDatabaseSize)) { 1307 HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiPackageListHeader + 1); 1308 1309 while ((UINTN) HiiPackageHeader < ((UINTN) HiiPackageListHeader + HiiPackageListHeader->PackageLength)) { 1310 // 1311 // Parse Hii Package. 1312 // 1313 VarCheckParseHiiPackage (HiiPackageHeader, FALSE); 1314 1315 HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINTN) HiiPackageHeader + HiiPackageHeader->Length); 1316 } 1317 1318 HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *) ((UINTN) HiiPackageListHeader + HiiPackageListHeader->PackageLength); 1319 } 1320 } 1321 1322 /** 1323 Destroy Hii Variable node. 1324 1325 **/ 1326 VOID 1327 DestroyHiiVariableNode ( 1328 VOID 1329 ) 1330 { 1331 VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode; 1332 LIST_ENTRY *HiiVariableLink; 1333 UINTN Index; 1334 1335 while (mVarCheckHiiList.ForwardLink != &mVarCheckHiiList) { 1336 HiiVariableLink = mVarCheckHiiList.ForwardLink; 1337 HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (HiiVariableLink); 1338 1339 RemoveEntryList (&HiiVariableNode->Link); 1340 1341 // 1342 // Free the allocated buffer. 1343 // 1344 for (Index = 0; Index < HiiVariableNode->HiiVariable->Size; Index++) { 1345 if (HiiVariableNode->HiiQuestionArray[Index] != NULL) { 1346 InternalVarCheckFreePool (HiiVariableNode->HiiQuestionArray[Index]); 1347 } 1348 } 1349 InternalVarCheckFreePool (HiiVariableNode->HiiQuestionArray); 1350 InternalVarCheckFreePool (HiiVariableNode->HiiVariable); 1351 InternalVarCheckFreePool (HiiVariableNode); 1352 } 1353 } 1354 1355 /** 1356 Build VarCheckHiiBin. 1357 1358 @param[out] Size Pointer to VarCheckHii size. 1359 1360 @return Pointer to VarCheckHiiBin. 1361 1362 **/ 1363 VOID * 1364 BuildVarCheckHiiBin ( 1365 OUT UINTN *Size 1366 ) 1367 { 1368 VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode; 1369 LIST_ENTRY *HiiVariableLink; 1370 UINTN Index; 1371 VOID *Data; 1372 UINT8 *Ptr; 1373 UINT32 BinSize; 1374 UINT32 HiiVariableLength; 1375 1376 // 1377 // Get Size 1378 // 1379 BinSize = 0; 1380 1381 for (HiiVariableLink = mVarCheckHiiList.ForwardLink 1382 ;HiiVariableLink != &mVarCheckHiiList 1383 ;HiiVariableLink = HiiVariableLink->ForwardLink) { 1384 // 1385 // For Hii Variable header align. 1386 // 1387 BinSize = (UINT32) HEADER_ALIGN (BinSize); 1388 1389 HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (HiiVariableLink); 1390 HiiVariableLength = HiiVariableNode->HiiVariable->HeaderLength; 1391 1392 for (Index = 0; Index < HiiVariableNode->HiiVariable->Size; Index++) { 1393 if (HiiVariableNode->HiiQuestionArray[Index] != NULL) { 1394 // 1395 // For Hii Question header align. 1396 // 1397 HiiVariableLength = (UINT32) HEADER_ALIGN (HiiVariableLength); 1398 HiiVariableLength += HiiVariableNode->HiiQuestionArray[Index]->Length; 1399 } 1400 } 1401 1402 HiiVariableNode->HiiVariable->Length = HiiVariableLength; 1403 BinSize += HiiVariableLength; 1404 } 1405 1406 DEBUG ((EFI_D_INFO, "VarCheckHiiBin - size = 0x%x\n", BinSize)); 1407 if (BinSize == 0) { 1408 *Size = BinSize; 1409 return NULL; 1410 } 1411 1412 // 1413 // AllocatePages () and AllocatePool () from gBS are used for the process of VarCheckHiiBin generation. 1414 // Only here AllocateRuntimeZeroPool () from MemoryAllocateLib is used for runtime access 1415 // in SetVariable check handler. 1416 // 1417 Data = AllocateRuntimeZeroPool (BinSize); 1418 ASSERT (Data != NULL); 1419 DEBUG ((EFI_D_INFO, "VarCheckHiiBin - built at 0x%x\n", Data)); 1420 1421 // 1422 // Gen Data 1423 // 1424 Ptr = Data; 1425 for (HiiVariableLink = mVarCheckHiiList.ForwardLink 1426 ;HiiVariableLink != &mVarCheckHiiList 1427 ;HiiVariableLink = HiiVariableLink->ForwardLink) { 1428 // 1429 // For Hii Variable header align. 1430 // 1431 Ptr = (UINT8 *) HEADER_ALIGN (Ptr); 1432 1433 HiiVariableNode = VAR_CHECK_HII_VARIABLE_FROM_LINK (HiiVariableLink); 1434 CopyMem (Ptr, HiiVariableNode->HiiVariable, HiiVariableNode->HiiVariable->HeaderLength); 1435 Ptr += HiiVariableNode->HiiVariable->HeaderLength; 1436 1437 for (Index = 0; Index < HiiVariableNode->HiiVariable->Size; Index++) { 1438 if (HiiVariableNode->HiiQuestionArray[Index] != NULL) { 1439 // 1440 // For Hii Question header align. 1441 // 1442 Ptr = (UINT8 *) HEADER_ALIGN (Ptr); 1443 CopyMem (Ptr, HiiVariableNode->HiiQuestionArray[Index], HiiVariableNode->HiiQuestionArray[Index]->Length); 1444 Ptr += HiiVariableNode->HiiQuestionArray[Index]->Length; 1445 } 1446 } 1447 } 1448 1449 *Size = BinSize; 1450 return Data; 1451 } 1452 1453 /** 1454 Generate VarCheckHiiBin from Hii Database and FV. 1455 1456 **/ 1457 VOID 1458 EFIAPI 1459 VarCheckHiiGen ( 1460 VOID 1461 ) 1462 { 1463 VarCheckHiiGenFromHiiDatabase (); 1464 VarCheckHiiGenFromFv (); 1465 1466 mVarCheckHiiBin = BuildVarCheckHiiBin (&mVarCheckHiiBinSize); 1467 if (mVarCheckHiiBin == NULL) { 1468 DEBUG ((EFI_D_INFO, "[VarCheckHii] This driver could be removed from *.dsc and *.fdf\n")); 1469 return; 1470 } 1471 1472 DestroyHiiVariableNode (); 1473 if (mVarName != NULL) { 1474 InternalVarCheckFreePool (mVarName); 1475 } 1476 1477 #ifdef DUMP_VAR_CHECK_HII 1478 DEBUG_CODE ( 1479 DumpVarCheckHii (mVarCheckHiiBin, mVarCheckHiiBinSize); 1480 ); 1481 #endif 1482 } 1483 1484