4 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "VarCheckHii.h"
11 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mVarCheckHiiHex
[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
14 Dump some hexadecimal data.
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.
23 VarCheckHiiInternalDumpHex (
41 while (DataSize
!= 0) {
43 if (Size
> DataSize
) {
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
);
57 DEBUG ((DEBUG_INFO
, "%*a%08X: %-48a *%a*\r\n", Indent
, "", Offset
, Val
, Str
));
66 Var Check Hii Question.
68 @param[in] HiiQuestion Pointer to Hii Question
69 @param[in] Data Data pointer.
70 @param[in] DataSize Size of Data to set.
72 @retval TRUE Check pass
73 @retval FALSE Check fail.
78 IN VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
,
93 UINT16 VarOffsetByteLevel
;
94 UINT8 StorageWidthByteLevel
;
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);
101 VarOffsetByteLevel
= HiiQuestion
->VarOffset
;
102 StorageWidthByteLevel
= HiiQuestion
->StorageWidth
;
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
));
111 CopyMem (&OneData
, (UINT8
*)Data
+ VarOffsetByteLevel
, StorageWidthByteLevel
);
112 if (HiiQuestion
->BitFieldStore
) {
114 // Get the value from the bit field.
116 StartBit
= HiiQuestion
->VarOffset
% 8;
117 EndBit
= StartBit
+ HiiQuestion
->StorageWidth
- 1;
118 OneData
= BitFieldRead64 (OneData
, StartBit
, EndBit
);
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
) {
126 if (HiiQuestion
->BitFieldStore
) {
128 // For OneOf stored in bit field, the value of options are saved as UINT32 type.
130 CopyMem (&OneValue
, Ptr
, sizeof (UINT32
));
132 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
135 if (OneData
== OneValue
) {
142 if (HiiQuestion
->BitFieldStore
) {
143 Ptr
+= sizeof (UINT32
);
145 Ptr
+= HiiQuestion
->StorageWidth
;
149 if ((UINTN
)Ptr
>= ((UINTN
)HiiQuestion
+ HiiQuestion
->Length
)) {
153 DEBUG ((DEBUG_INFO
, "VarCheckHiiQuestion fail: OneOf mismatch (0x%lx)\n", OneData
));
155 VarCheckHiiInternalDumpHex (2, 0, HiiQuestion
->Length
, (UINT8
*)HiiQuestion
);
162 case EFI_IFR_CHECKBOX_OP
:
163 if ((OneData
!= 0) && (OneData
!= 1)) {
164 DEBUG ((DEBUG_INFO
, "VarCheckHiiQuestion fail: CheckBox mismatch (0x%lx)\n", OneData
));
166 VarCheckHiiInternalDumpHex (2, 0, HiiQuestion
->Length
, (UINT8
*)HiiQuestion
);
173 case EFI_IFR_NUMERIC_OP
:
176 Ptr
= (UINT8
*)((VAR_CHECK_HII_QUESTION_NUMERIC
*)HiiQuestion
+ 1);
177 if (HiiQuestion
->BitFieldStore
) {
179 // For Numeric stored in bit field, the value of Maximum/Minimum are saved as UINT32 type.
181 CopyMem (&Minimum
, Ptr
, sizeof (UINT32
));
182 Ptr
+= sizeof (UINT32
);
183 CopyMem (&Maximum
, Ptr
, sizeof (UINT32
));
184 Ptr
+= sizeof (UINT32
);
186 CopyMem (&Minimum
, Ptr
, HiiQuestion
->StorageWidth
);
187 Ptr
+= HiiQuestion
->StorageWidth
;
188 CopyMem (&Maximum
, Ptr
, HiiQuestion
->StorageWidth
);
189 Ptr
+= HiiQuestion
->StorageWidth
;
193 // No need to check Step, because it is ONLY for UI.
195 if ((OneData
< Minimum
) || (OneData
> Maximum
)) {
196 DEBUG ((DEBUG_INFO
, "VarCheckHiiQuestion fail: Numeric mismatch (0x%lx)\n", OneData
));
198 VarCheckHiiInternalDumpHex (2, 0, HiiQuestion
->Length
, (UINT8
*)HiiQuestion
);
205 case EFI_IFR_ORDERED_LIST_OP
:
206 MaxContainers
= ((VAR_CHECK_HII_QUESTION_ORDEREDLIST
*)HiiQuestion
)->MaxContainers
;
207 if (((UINT32
)HiiQuestion
->VarOffset
+ HiiQuestion
->StorageWidth
* MaxContainers
) > DataSize
) {
208 DEBUG ((DEBUG_INFO
, "VarCheckHiiQuestion fail: (VarOffset(0x%04x) + StorageWidth(0x%02x) * MaxContainers(0x%02x)) > Size(0x%x)\n", HiiQuestion
->VarOffset
, HiiQuestion
->StorageWidth
, MaxContainers
, DataSize
));
212 for (Index
= 0; Index
< MaxContainers
; Index
++) {
214 CopyMem (&OneData
, (UINT8
*)Data
+ HiiQuestion
->VarOffset
+ HiiQuestion
->StorageWidth
* Index
, HiiQuestion
->StorageWidth
);
217 // The value of 0 is used to determine if a particular "slot" in the array is empty.
222 Ptr
= (UINT8
*)((VAR_CHECK_HII_QUESTION_ORDEREDLIST
*)HiiQuestion
+ 1);
223 while ((UINTN
)Ptr
< ((UINTN
)HiiQuestion
+ HiiQuestion
->Length
)) {
225 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
226 if (OneData
== OneValue
) {
233 Ptr
+= HiiQuestion
->StorageWidth
;
236 if ((UINTN
)Ptr
>= ((UINTN
)HiiQuestion
+ HiiQuestion
->Length
)) {
240 DEBUG ((DEBUG_INFO
, "VarCheckHiiQuestion fail: OrderedList mismatch\n"));
242 VarCheckHiiInternalDumpHex (2, 0, HiiQuestion
->StorageWidth
* MaxContainers
, (UINT8
*)Data
+ HiiQuestion
->VarOffset
);
245 VarCheckHiiInternalDumpHex (2, 0, HiiQuestion
->Length
, (UINT8
*)HiiQuestion
);
261 VAR_CHECK_HII_VARIABLE_HEADER
*mVarCheckHiiBin
= NULL
;
262 UINTN mVarCheckHiiBinSize
= 0;
265 SetVariable check handler HII.
267 @param[in] VariableName Name of Variable to set.
268 @param[in] VendorGuid Variable vendor GUID.
269 @param[in] Attributes Attribute value of the variable.
270 @param[in] DataSize Size of Data to set.
271 @param[in] Data Data pointer.
273 @retval EFI_SUCCESS The SetVariable check result was success.
274 @retval EFI_SECURITY_VIOLATION Check fail.
279 SetVariableCheckHandlerHii (
280 IN CHAR16
*VariableName
,
281 IN EFI_GUID
*VendorGuid
,
282 IN UINT32 Attributes
,
287 VAR_CHECK_HII_VARIABLE_HEADER
*HiiVariable
;
288 VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
;
290 if (mVarCheckHiiBin
== NULL
) {
294 if ((((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0) && (DataSize
== 0)) || (Attributes
== 0)) {
296 // Do not check delete variable.
302 // For Hii Variable header align.
304 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*)HEADER_ALIGN (mVarCheckHiiBin
);
305 while ((UINTN
)HiiVariable
< ((UINTN
)mVarCheckHiiBin
+ mVarCheckHiiBinSize
)) {
306 if ((StrCmp ((CHAR16
*)(HiiVariable
+ 1), VariableName
) == 0) &&
307 (CompareGuid (&HiiVariable
->Guid
, VendorGuid
)))
310 // Found the Hii Variable that could be used to do check.
312 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable - %s:%g with Attributes = 0x%08x Size = 0x%x\n", VariableName
, VendorGuid
, Attributes
, DataSize
));
313 if (HiiVariable
->Attributes
!= Attributes
) {
314 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable fail for Attributes - 0x%08x\n", HiiVariable
->Attributes
));
315 return EFI_SECURITY_VIOLATION
;
319 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable - CHECK PASS with DataSize == 0 !\n"));
323 if (HiiVariable
->Size
!= DataSize
) {
324 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable fail for Size - 0x%x\n", HiiVariable
->Size
));
325 return EFI_SECURITY_VIOLATION
;
330 // For Hii Question header align.
332 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*)HEADER_ALIGN (((UINTN
)HiiVariable
+ HiiVariable
->HeaderLength
));
333 while ((UINTN
)HiiQuestion
< ((UINTN
)HiiVariable
+ HiiVariable
->Length
)) {
334 if (!VarCheckHiiQuestion (HiiQuestion
, Data
, DataSize
)) {
335 return EFI_SECURITY_VIOLATION
;
339 // For Hii Question header align.
341 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*)HEADER_ALIGN (((UINTN
)HiiQuestion
+ HiiQuestion
->Length
));
344 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable - ALL CHECK PASS!\n"));
349 // For Hii Variable header align.
351 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*)HEADER_ALIGN (((UINTN
)HiiVariable
+ HiiVariable
->Length
));
354 // Not found, so pass.
358 #ifdef DUMP_VAR_CHECK_HII
359 GLOBAL_REMOVE_IF_UNREFERENCED VAR_CHECK_HII_OPCODE_STRING mHiiOpCodeStringTable
[] = {
360 { EFI_IFR_VARSTORE_EFI_OP
, "EfiVarStore" },
361 { EFI_IFR_ONE_OF_OP
, "OneOf" },
362 { EFI_IFR_CHECKBOX_OP
, "CheckBox" },
363 { EFI_IFR_NUMERIC_OP
, "Numeric" },
364 { EFI_IFR_ORDERED_LIST_OP
, "OrderedList" },
368 HII opcode to string.
370 @param[in] HiiOpCode Hii OpCode.
372 @return Pointer to string.
382 for (Index
= 0; Index
< ARRAY_SIZE (mHiiOpCodeStringTable
); Index
++) {
383 if (mHiiOpCodeStringTable
[Index
].HiiOpCode
== HiiOpCode
) {
384 return mHiiOpCodeStringTable
[Index
].HiiOpCodeStr
;
388 return "<UnknownHiiOpCode>";
394 @param[in] HiiQuestion Pointer to Hii Question.
399 IN VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
407 DEBUG ((DEBUG_INFO
, " VAR_CHECK_HII_QUESTION_HEADER\n"));
408 DEBUG ((DEBUG_INFO
, " OpCode - 0x%02x (%a) (%a)\n", HiiQuestion
->OpCode
, HiiOpCodeToStr (HiiQuestion
->OpCode
), (HiiQuestion
->BitFieldStore
? "bit level" : "byte level")));
409 DEBUG ((DEBUG_INFO
, " Length - 0x%02x\n", HiiQuestion
->Length
));
410 DEBUG ((DEBUG_INFO
, " VarOffset - 0x%04x (%a)\n", HiiQuestion
->VarOffset
, (HiiQuestion
->BitFieldStore
? "bit level" : "byte level")));
411 DEBUG ((DEBUG_INFO
, " StorageWidth - 0x%02x (%a)\n", HiiQuestion
->StorageWidth
, (HiiQuestion
->BitFieldStore
? "bit level" : "byte level")));
413 switch (HiiQuestion
->OpCode
) {
414 case EFI_IFR_ONE_OF_OP
:
415 Ptr
= (UINT8
*)((VAR_CHECK_HII_QUESTION_ONEOF
*)HiiQuestion
+ 1);
416 while ((UINTN
)Ptr
< ((UINTN
)HiiQuestion
+ HiiQuestion
->Length
)) {
418 if (HiiQuestion
->BitFieldStore
) {
420 // For OneOf stored in bit field, the value of options are saved as UINT32 type.
422 CopyMem (&OneValue
, Ptr
, sizeof (UINT32
));
423 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%08x\n", OneValue
));
425 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
426 switch (HiiQuestion
->StorageWidth
) {
428 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%02x\n", OneValue
));
430 case sizeof (UINT16
):
431 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%04x\n", OneValue
));
433 case sizeof (UINT32
):
434 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%08x\n", OneValue
));
436 case sizeof (UINT64
):
437 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%016lx\n", OneValue
));
445 if (HiiQuestion
->BitFieldStore
) {
446 Ptr
+= sizeof (UINT32
);
448 Ptr
+= HiiQuestion
->StorageWidth
;
454 case EFI_IFR_CHECKBOX_OP
:
457 case EFI_IFR_NUMERIC_OP
:
460 Ptr
= (UINT8
*)((VAR_CHECK_HII_QUESTION_NUMERIC
*)HiiQuestion
+ 1);
461 if (HiiQuestion
->BitFieldStore
) {
463 // For Numeric stored in bit field, the value of Maximum/Minimum are saved as UINT32 type.
465 CopyMem (&Minimum
, Ptr
, sizeof (UINT32
));
466 Ptr
+= sizeof (UINT32
);
467 CopyMem (&Maximum
, Ptr
, sizeof (UINT32
));
468 Ptr
+= sizeof (UINT32
);
470 DEBUG ((DEBUG_INFO
, " Minimum - 0x%08x\n", Minimum
));
471 DEBUG ((DEBUG_INFO
, " Maximum - 0x%08x\n", Maximum
));
473 CopyMem (&Minimum
, Ptr
, HiiQuestion
->StorageWidth
);
474 Ptr
+= HiiQuestion
->StorageWidth
;
475 CopyMem (&Maximum
, Ptr
, HiiQuestion
->StorageWidth
);
476 Ptr
+= HiiQuestion
->StorageWidth
;
478 switch (HiiQuestion
->StorageWidth
) {
480 DEBUG ((DEBUG_INFO
, " Minimum - 0x%02x\n", Minimum
));
481 DEBUG ((DEBUG_INFO
, " Maximum - 0x%02x\n", Maximum
));
483 case sizeof (UINT16
):
484 DEBUG ((DEBUG_INFO
, " Minimum - 0x%04x\n", Minimum
));
485 DEBUG ((DEBUG_INFO
, " Maximum - 0x%04x\n", Maximum
));
487 case sizeof (UINT32
):
488 DEBUG ((DEBUG_INFO
, " Minimum - 0x%08x\n", Minimum
));
489 DEBUG ((DEBUG_INFO
, " Maximum - 0x%08x\n", Maximum
));
491 case sizeof (UINT64
):
492 DEBUG ((DEBUG_INFO
, " Minimum - 0x%016lx\n", Minimum
));
493 DEBUG ((DEBUG_INFO
, " Maximum - 0x%016lx\n", Maximum
));
503 case EFI_IFR_ORDERED_LIST_OP
:
504 DEBUG ((DEBUG_INFO
, " MaxContainers - 0x%02x\n", ((VAR_CHECK_HII_QUESTION_ORDEREDLIST
*)HiiQuestion
)->MaxContainers
));
505 Ptr
= (UINT8
*)((VAR_CHECK_HII_QUESTION_ORDEREDLIST
*)HiiQuestion
+ 1);
506 while ((UINTN
)Ptr
< ((UINTN
)HiiQuestion
+ HiiQuestion
->Length
)) {
508 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
509 switch (HiiQuestion
->StorageWidth
) {
511 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%02x\n", OneValue
));
513 case sizeof (UINT16
):
514 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%04x\n", OneValue
));
516 case sizeof (UINT32
):
517 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%08x\n", OneValue
));
519 case sizeof (UINT64
):
520 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%016lx\n", OneValue
));
527 Ptr
+= HiiQuestion
->StorageWidth
;
541 @param[in] HiiVariable Pointer to Hii Variable.
546 IN VAR_CHECK_HII_VARIABLE_HEADER
*HiiVariable
549 VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
;
551 DEBUG ((DEBUG_INFO
, "VAR_CHECK_HII_VARIABLE_HEADER\n"));
552 DEBUG ((DEBUG_INFO
, " Revision - 0x%04x\n", HiiVariable
->Revision
));
553 DEBUG ((DEBUG_INFO
, " HeaderLength - 0x%04x\n", HiiVariable
->HeaderLength
));
554 DEBUG ((DEBUG_INFO
, " Length - 0x%08x\n", HiiVariable
->Length
));
555 DEBUG ((DEBUG_INFO
, " OpCode - 0x%02x (%a)\n", HiiVariable
->OpCode
, HiiOpCodeToStr (HiiVariable
->OpCode
)));
556 DEBUG ((DEBUG_INFO
, " Size - 0x%04x\n", HiiVariable
->Size
));
557 DEBUG ((DEBUG_INFO
, " Attributes - 0x%08x\n", HiiVariable
->Attributes
));
558 DEBUG ((DEBUG_INFO
, " Guid - %g\n", &HiiVariable
->Guid
));
559 DEBUG ((DEBUG_INFO
, " Name - %s\n", HiiVariable
+ 1));
562 // For Hii Question header align.
564 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*)HEADER_ALIGN (((UINTN
)HiiVariable
+ HiiVariable
->HeaderLength
));
565 while ((UINTN
)HiiQuestion
< ((UINTN
)HiiVariable
+ HiiVariable
->Length
)) {
567 // Dump Hii Question related to the Hii Variable.
569 DumpHiiQuestion (HiiQuestion
);
571 // For Hii Question header align.
573 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*)HEADER_ALIGN (((UINTN
)HiiQuestion
+ HiiQuestion
->Length
));
580 @param[in] VarCheckHiiBin Pointer to VarCheckHiiBin.
581 @param[in] VarCheckHiiBinSize VarCheckHiiBin size.
586 IN VOID
*VarCheckHiiBin
,
587 IN UINTN VarCheckHiiBinSize
590 VAR_CHECK_HII_VARIABLE_HEADER
*HiiVariable
;
592 DEBUG ((DEBUG_INFO
, "DumpVarCheckHii\n"));
595 // For Hii Variable header align.
597 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*)HEADER_ALIGN (VarCheckHiiBin
);
598 while ((UINTN
)HiiVariable
< ((UINTN
)VarCheckHiiBin
+ VarCheckHiiBinSize
)) {
599 DumpHiiVariable (HiiVariable
);
601 // For Hii Variable header align.
603 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*)HEADER_ALIGN (((UINTN
)HiiVariable
+ HiiVariable
->Length
));
610 Constructor function of VarCheckHiiLib to register var check HII handler.
612 @param[in] ImageHandle The firmware allocated handle for the EFI image.
613 @param[in] SystemTable A pointer to the EFI System Table.
615 @retval EFI_SUCCESS The constructor executed correctly.
620 VarCheckHiiLibNullClassConstructor (
621 IN EFI_HANDLE ImageHandle
,
622 IN EFI_SYSTEM_TABLE
*SystemTable
625 VarCheckLibRegisterEndOfDxeCallback (VarCheckHiiGen
);
626 VarCheckLibRegisterAddressPointer ((VOID
**)&mVarCheckHiiBin
);
627 VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerHii
);