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