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