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