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