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