]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibNullClass.c
93ff9340e90c86f68284826f66ece4909cf96bf0
[mirror_edk2.git] / MdeModulePkg / Library / VarCheckHiiLib / VarCheckHiiLibNullClass.c
1 /** @file
2 Var Check Hii handler.
3
4 Copyright (c) 2015 - 2017, 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 "VarCheckHii.h"
16
17 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mVarCheckHiiHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
18
19 /**
20 Dump some hexadecimal data.
21
22 @param[in] Indent How many spaces to indent the output.
23 @param[in] Offset The offset of the dump.
24 @param[in] DataSize The size in bytes of UserData.
25 @param[in] UserData The data to dump.
26
27 **/
28 VOID
29 VarCheckHiiInternalDumpHex (
30 IN UINTN Indent,
31 IN UINTN Offset,
32 IN UINTN DataSize,
33 IN VOID *UserData
34 )
35 {
36 UINT8 *Data;
37
38 CHAR8 Val[50];
39
40 CHAR8 Str[20];
41
42 UINT8 TempByte;
43 UINTN Size;
44 UINTN Index;
45
46 Data = UserData;
47 while (DataSize != 0) {
48 Size = 16;
49 if (Size > DataSize) {
50 Size = DataSize;
51 }
52
53 for (Index = 0; Index < Size; Index += 1) {
54 TempByte = Data[Index];
55 Val[Index * 3 + 0] = mVarCheckHiiHex[TempByte >> 4];
56 Val[Index * 3 + 1] = mVarCheckHiiHex[TempByte & 0xF];
57 Val[Index * 3 + 2] = (CHAR8) ((Index == 7) ? '-' : ' ');
58 Str[Index] = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);
59 }
60
61 Val[Index * 3] = 0;
62 Str[Index] = 0;
63 DEBUG ((EFI_D_INFO, "%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str));
64
65 Data += Size;
66 Offset += Size;
67 DataSize -= Size;
68 }
69 }
70
71 /**
72 Var Check Hii Question.
73
74 @param[in] HiiQuestion Pointer to Hii Question
75 @param[in] Data Data pointer.
76 @param[in] DataSize Size of Data to set.
77
78 @retval TRUE Check pass
79 @retval FALSE Check fail.
80
81 **/
82 BOOLEAN
83 VarCheckHiiQuestion (
84 IN VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion,
85 IN VOID *Data,
86 IN UINTN DataSize
87 )
88 {
89 UINT64 OneData;
90 UINT64 Minimum;
91 UINT64 Maximum;
92 UINT64 OneValue;
93 UINT8 *Ptr;
94 UINT8 Index;
95 UINT8 MaxContainers;
96
97 if (((UINT32) HiiQuestion->VarOffset + HiiQuestion->StorageWidth) > DataSize) {
98 DEBUG ((EFI_D_INFO, "VarCheckHiiQuestion fail: (VarOffset(0x%04x) + StorageWidth(0x%02x)) > Size(0x%x)\n", HiiQuestion->VarOffset, HiiQuestion->StorageWidth, DataSize));
99 return FALSE;
100 }
101
102 OneData = 0;
103 CopyMem (&OneData, (UINT8 *) Data + HiiQuestion->VarOffset, HiiQuestion->StorageWidth);
104
105 switch (HiiQuestion->OpCode) {
106 case EFI_IFR_ONE_OF_OP:
107 Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion + 1);
108 while ((UINTN) Ptr < (UINTN) HiiQuestion + HiiQuestion->Length) {
109 OneValue = 0;
110 CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);
111 if (OneData == OneValue) {
112 //
113 // Match
114 //
115 break;
116 }
117 Ptr += HiiQuestion->StorageWidth;
118 }
119 if ((UINTN) Ptr >= ((UINTN) HiiQuestion + HiiQuestion->Length)) {
120 //
121 // No match
122 //
123 DEBUG ((EFI_D_INFO, "VarCheckHiiQuestion fail: OneOf mismatch (0x%lx)\n", OneData));
124 DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *) HiiQuestion););
125 return FALSE;
126 }
127 break;
128
129 case EFI_IFR_CHECKBOX_OP:
130 if ((OneData != 0) && (OneData != 1)) {
131 DEBUG ((EFI_D_INFO, "VarCheckHiiQuestion fail: CheckBox mismatch (0x%lx)\n", OneData));
132 DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *) HiiQuestion););
133 return FALSE;
134 }
135 break;
136
137 case EFI_IFR_NUMERIC_OP:
138 Minimum = 0;
139 Maximum = 0;
140 Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion + 1);
141 CopyMem (&Minimum, Ptr, HiiQuestion->StorageWidth);
142 Ptr += HiiQuestion->StorageWidth;
143 CopyMem (&Maximum, Ptr, HiiQuestion->StorageWidth);
144 Ptr += HiiQuestion->StorageWidth;
145
146 //
147 // No need to check Step, because it is ONLY for UI.
148 //
149 if ((OneData < Minimum) || (OneData > Maximum)) {
150 DEBUG ((EFI_D_INFO, "VarCheckHiiQuestion fail: Numeric mismatch (0x%lx)\n", OneData));
151 DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *) HiiQuestion););
152 return FALSE;
153 }
154 break;
155
156 case EFI_IFR_ORDERED_LIST_OP:
157 MaxContainers = ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion)->MaxContainers;
158 if (((UINT32) HiiQuestion->VarOffset + HiiQuestion->StorageWidth * MaxContainers) > DataSize) {
159 DEBUG ((EFI_D_INFO, "VarCheckHiiQuestion fail: (VarOffset(0x%04x) + StorageWidth(0x%02x) * MaxContainers(0x%02x)) > Size(0x%x)\n", HiiQuestion->VarOffset, HiiQuestion->StorageWidth, MaxContainers, DataSize));
160 return FALSE;
161 }
162 for (Index = 0; Index < MaxContainers; Index++) {
163 OneData = 0;
164 CopyMem (&OneData, (UINT8 *) Data + HiiQuestion->VarOffset + HiiQuestion->StorageWidth * Index, HiiQuestion->StorageWidth);
165 if (OneData == 0) {
166 //
167 // The value of 0 is used to determine if a particular "slot" in the array is empty.
168 //
169 continue;
170 }
171
172 Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion + 1);
173 while ((UINTN) Ptr < ((UINTN) HiiQuestion + HiiQuestion->Length)) {
174 OneValue = 0;
175 CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);
176 if (OneData == OneValue) {
177 //
178 // Match
179 //
180 break;
181 }
182 Ptr += HiiQuestion->StorageWidth;
183 }
184 if ((UINTN) Ptr >= ((UINTN) HiiQuestion + HiiQuestion->Length)) {
185 //
186 // No match
187 //
188 DEBUG ((EFI_D_INFO, "VarCheckHiiQuestion fail: OrderedList mismatch\n"));
189 DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->StorageWidth * MaxContainers, (UINT8 *) Data + HiiQuestion->VarOffset););
190 DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *) HiiQuestion););
191 return FALSE;
192 }
193 }
194 break;
195
196 default:
197 ASSERT (FALSE);
198 break;
199 }
200
201 return TRUE;
202 }
203
204 VAR_CHECK_HII_VARIABLE_HEADER *mVarCheckHiiBin = NULL;
205 UINTN mVarCheckHiiBinSize = 0;
206
207 /**
208 SetVariable check handler HII.
209
210 @param[in] VariableName Name of Variable to set.
211 @param[in] VendorGuid Variable vendor GUID.
212 @param[in] Attributes Attribute value of the variable.
213 @param[in] DataSize Size of Data to set.
214 @param[in] Data Data pointer.
215
216 @retval EFI_SUCCESS The SetVariable check result was success.
217 @retval EFI_SECURITY_VIOLATION Check fail.
218
219 **/
220 EFI_STATUS
221 EFIAPI
222 SetVariableCheckHandlerHii (
223 IN CHAR16 *VariableName,
224 IN EFI_GUID *VendorGuid,
225 IN UINT32 Attributes,
226 IN UINTN DataSize,
227 IN VOID *Data
228 )
229 {
230 VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable;
231 VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion;
232
233 if (mVarCheckHiiBin == NULL) {
234 return EFI_SUCCESS;
235 }
236
237 if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0)) {
238 //
239 // Do not check delete variable.
240 //
241 return EFI_SUCCESS;
242 }
243
244 //
245 // For Hii Variable header align.
246 //
247 HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *) HEADER_ALIGN (mVarCheckHiiBin);
248 while ((UINTN) HiiVariable < ((UINTN) mVarCheckHiiBin + mVarCheckHiiBinSize)) {
249 if ((StrCmp ((CHAR16 *) (HiiVariable + 1), VariableName) == 0) &&
250 (CompareGuid (&HiiVariable->Guid, VendorGuid))) {
251 //
252 // Found the Hii Variable that could be used to do check.
253 //
254 DEBUG ((EFI_D_INFO, "VarCheckHiiVariable - %s:%g with Attributes = 0x%08x Size = 0x%x\n", VariableName, VendorGuid, Attributes, DataSize));
255 if (HiiVariable->Attributes != Attributes) {
256 DEBUG ((EFI_D_INFO, "VarCheckHiiVariable fail for Attributes - 0x%08x\n", HiiVariable->Attributes));
257 return EFI_SECURITY_VIOLATION;
258 }
259
260 if (DataSize == 0) {
261 DEBUG ((EFI_D_INFO, "VarCheckHiiVariable - CHECK PASS with DataSize == 0 !\n"));
262 return EFI_SUCCESS;
263 }
264
265 if (HiiVariable->Size != DataSize) {
266 DEBUG ((EFI_D_INFO, "VarCheckHiiVariable fail for Size - 0x%x\n", HiiVariable->Size));
267 return EFI_SECURITY_VIOLATION;
268 }
269
270 //
271 // Do the check.
272 // For Hii Question header align.
273 //
274 HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *) HEADER_ALIGN (((UINTN) HiiVariable + HiiVariable->HeaderLength));
275 while ((UINTN) HiiQuestion < ((UINTN) HiiVariable + HiiVariable->Length)) {
276 if (!VarCheckHiiQuestion (HiiQuestion, Data, DataSize)) {
277 return EFI_SECURITY_VIOLATION;
278 }
279 //
280 // For Hii Question header align.
281 //
282 HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *) HEADER_ALIGN (((UINTN) HiiQuestion + HiiQuestion->Length));
283 }
284
285 DEBUG ((EFI_D_INFO, "VarCheckHiiVariable - ALL CHECK PASS!\n"));
286 return EFI_SUCCESS;
287 }
288 //
289 // For Hii Variable header align.
290 //
291 HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *) HEADER_ALIGN (((UINTN) HiiVariable + HiiVariable->Length));
292 }
293
294 // Not found, so pass.
295 return EFI_SUCCESS;
296 }
297
298 #ifdef DUMP_VAR_CHECK_HII
299 GLOBAL_REMOVE_IF_UNREFERENCED VAR_CHECK_HII_OPCODE_STRING mHiiOpCodeStringTable[] = {
300 {EFI_IFR_VARSTORE_EFI_OP, "EfiVarStore"},
301 {EFI_IFR_ONE_OF_OP, "OneOf"},
302 {EFI_IFR_CHECKBOX_OP, "CheckBox"},
303 {EFI_IFR_NUMERIC_OP, "Numeric"},
304 {EFI_IFR_ORDERED_LIST_OP, "OrderedList"},
305 };
306
307 /**
308 HII opcode to string.
309
310 @param[in] HiiOpCode Hii OpCode.
311
312 @return Pointer to string.
313
314 **/
315 CHAR8 *
316 HiiOpCodeToStr (
317 IN UINT8 HiiOpCode
318 )
319 {
320 UINTN Index;
321 for (Index = 0; Index < ARRAY_SIZE (mHiiOpCodeStringTable); Index++) {
322 if (mHiiOpCodeStringTable[Index].HiiOpCode == HiiOpCode) {
323 return mHiiOpCodeStringTable[Index].HiiOpCodeStr;
324 }
325 }
326
327 return "<UnknownHiiOpCode>";
328 }
329
330 /**
331 Dump Hii Question.
332
333 @param[in] HiiQuestion Pointer to Hii Question.
334
335 **/
336 VOID
337 DumpHiiQuestion (
338 IN VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion
339 )
340 {
341 UINT64 Minimum;
342 UINT64 Maximum;
343 UINT64 OneValue;
344 UINT8 *Ptr;
345
346 DEBUG ((EFI_D_INFO, " VAR_CHECK_HII_QUESTION_HEADER\n"));
347 DEBUG ((EFI_D_INFO, " OpCode - 0x%02x (%a)\n", HiiQuestion->OpCode, HiiOpCodeToStr (HiiQuestion->OpCode)));
348 DEBUG ((EFI_D_INFO, " Length - 0x%02x\n", HiiQuestion->Length));
349 DEBUG ((EFI_D_INFO, " VarOffset - 0x%04x\n", HiiQuestion->VarOffset));
350 DEBUG ((EFI_D_INFO, " StorageWidth - 0x%02x\n", HiiQuestion->StorageWidth));
351
352 switch (HiiQuestion->OpCode) {
353 case EFI_IFR_ONE_OF_OP:
354 Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ONEOF *) HiiQuestion + 1);
355 while ((UINTN) Ptr < ((UINTN) HiiQuestion + HiiQuestion->Length)) {
356 OneValue = 0;
357 CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);
358 switch (HiiQuestion->StorageWidth) {
359 case sizeof (UINT8):
360 DEBUG ((EFI_D_INFO, " OneOfOption - 0x%02x\n", OneValue));
361 break;
362 case sizeof (UINT16):
363 DEBUG ((EFI_D_INFO, " OneOfOption - 0x%04x\n", OneValue));
364 break;
365 case sizeof (UINT32):
366 DEBUG ((EFI_D_INFO, " OneOfOption - 0x%08x\n", OneValue));
367 break;
368 case sizeof (UINT64):
369 DEBUG ((EFI_D_INFO, " OneOfOption - 0x%016lx\n", OneValue));
370 break;
371 default:
372 ASSERT (FALSE);
373 break;
374 }
375 Ptr += HiiQuestion->StorageWidth;
376 }
377 break;
378
379 case EFI_IFR_CHECKBOX_OP:
380 break;
381
382 case EFI_IFR_NUMERIC_OP:
383 Minimum = 0;
384 Maximum = 0;
385 Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_NUMERIC *) HiiQuestion + 1);
386 CopyMem (&Minimum, Ptr, HiiQuestion->StorageWidth);
387 Ptr += HiiQuestion->StorageWidth;
388 CopyMem (&Maximum, Ptr, HiiQuestion->StorageWidth);
389 Ptr += HiiQuestion->StorageWidth;
390
391 switch (HiiQuestion->StorageWidth) {
392 case sizeof (UINT8):
393 DEBUG ((EFI_D_INFO, " Minimum - 0x%02x\n", Minimum));
394 DEBUG ((EFI_D_INFO, " Maximum - 0x%02x\n", Maximum));
395 break;
396 case sizeof (UINT16):
397 DEBUG ((EFI_D_INFO, " Minimum - 0x%04x\n", Minimum));
398 DEBUG ((EFI_D_INFO, " Maximum - 0x%04x\n", Maximum));
399 break;
400 case sizeof (UINT32):
401 DEBUG ((EFI_D_INFO, " Minimum - 0x%08x\n", Minimum));
402 DEBUG ((EFI_D_INFO, " Maximum - 0x%08x\n", Maximum));
403 break;
404 case sizeof (UINT64):
405 DEBUG ((EFI_D_INFO, " Minimum - 0x%016lx\n", Minimum));
406 DEBUG ((EFI_D_INFO, " Maximum - 0x%016lx\n", Maximum));
407 break;
408 default:
409 ASSERT (FALSE);
410 break;
411 }
412 break;
413
414 case EFI_IFR_ORDERED_LIST_OP:
415 DEBUG ((EFI_D_INFO, " MaxContainers - 0x%02x\n", ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion)->MaxContainers));
416 Ptr = (UINT8 *) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *) HiiQuestion + 1);
417 while ((UINTN) Ptr < ((UINTN) HiiQuestion + HiiQuestion->Length)) {
418 OneValue = 0;
419 CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);
420 switch (HiiQuestion->StorageWidth) {
421 case sizeof (UINT8):
422 DEBUG ((EFI_D_INFO, " OneOfOption - 0x%02x\n", OneValue));
423 break;
424 case sizeof (UINT16):
425 DEBUG ((EFI_D_INFO, " OneOfOption - 0x%04x\n", OneValue));
426 break;
427 case sizeof (UINT32):
428 DEBUG ((EFI_D_INFO, " OneOfOption - 0x%08x\n", OneValue));
429 break;
430 case sizeof (UINT64):
431 DEBUG ((EFI_D_INFO, " OneOfOption - 0x%016lx\n", OneValue));
432 break;
433 default:
434 ASSERT (FALSE);
435 break;
436 }
437 Ptr += HiiQuestion->StorageWidth;
438 }
439 break;
440
441 default:
442 ASSERT (FALSE);
443 break;
444 }
445 }
446
447 /**
448 Dump Hii Variable.
449
450 @param[in] HiiVariable Pointer to Hii Variable.
451
452 **/
453 VOID
454 DumpHiiVariable (
455 IN VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable
456 )
457 {
458 VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion;
459
460 DEBUG ((EFI_D_INFO, "VAR_CHECK_HII_VARIABLE_HEADER\n"));
461 DEBUG ((EFI_D_INFO, " Revision - 0x%04x\n", HiiVariable->Revision));
462 DEBUG ((EFI_D_INFO, " HeaderLength - 0x%04x\n", HiiVariable->HeaderLength));
463 DEBUG ((EFI_D_INFO, " Length - 0x%08x\n", HiiVariable->Length));
464 DEBUG ((EFI_D_INFO, " OpCode - 0x%02x (%a)\n", HiiVariable->OpCode, HiiOpCodeToStr (HiiVariable->OpCode)));
465 DEBUG ((EFI_D_INFO, " Size - 0x%04x\n", HiiVariable->Size));
466 DEBUG ((EFI_D_INFO, " Attributes - 0x%08x\n", HiiVariable->Attributes));
467 DEBUG ((EFI_D_INFO, " Guid - %g\n", &HiiVariable->Guid));
468 DEBUG ((EFI_D_INFO, " Name - %s\n", HiiVariable + 1));
469
470 //
471 // For Hii Question header align.
472 //
473 HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *) HEADER_ALIGN (((UINTN) HiiVariable + HiiVariable->HeaderLength));
474 while ((UINTN) HiiQuestion < ((UINTN) HiiVariable + HiiVariable->Length)) {
475 //
476 // Dump Hii Question related to the Hii Variable.
477 //
478 DumpHiiQuestion (HiiQuestion);
479 //
480 // For Hii Question header align.
481 //
482 HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *) HEADER_ALIGN (((UINTN) HiiQuestion + HiiQuestion->Length));
483 }
484 }
485
486 /**
487 Dump Var Check HII.
488
489 @param[in] VarCheckHiiBin Pointer to VarCheckHiiBin.
490 @param[in] VarCheckHiiBinSize VarCheckHiiBin size.
491
492 **/
493 VOID
494 DumpVarCheckHii (
495 IN VOID *VarCheckHiiBin,
496 IN UINTN VarCheckHiiBinSize
497 )
498 {
499 VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable;
500
501 DEBUG ((EFI_D_INFO, "DumpVarCheckHii\n"));
502
503 //
504 // For Hii Variable header align.
505 //
506 HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *) HEADER_ALIGN (VarCheckHiiBin);
507 while ((UINTN) HiiVariable < ((UINTN) VarCheckHiiBin + VarCheckHiiBinSize)) {
508 DumpHiiVariable (HiiVariable);
509 //
510 // For Hii Variable header align.
511 //
512 HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *) HEADER_ALIGN (((UINTN) HiiVariable + HiiVariable->Length));
513 }
514 }
515 #endif
516
517 /**
518 Constructor function of VarCheckHiiLib to register var check HII handler.
519
520 @param[in] ImageHandle The firmware allocated handle for the EFI image.
521 @param[in] SystemTable A pointer to the EFI System Table.
522
523 @retval EFI_SUCCESS The constructor executed correctly.
524
525 **/
526 EFI_STATUS
527 EFIAPI
528 VarCheckHiiLibNullClassConstructor (
529 IN EFI_HANDLE ImageHandle,
530 IN EFI_SYSTEM_TABLE *SystemTable
531 )
532 {
533 VarCheckLibRegisterEndOfDxeCallback (VarCheckHiiGen);
534 VarCheckLibRegisterAddressPointer ((VOID **) &mVarCheckHiiBin);
535 VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerHii);
536
537 return EFI_SUCCESS;
538 }
539