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
);
134 if (OneData
== OneValue
) {
140 if (HiiQuestion
->BitFieldStore
) {
141 Ptr
+= sizeof (UINT32
);
143 Ptr
+= HiiQuestion
->StorageWidth
;
146 if ((UINTN
) Ptr
>= ((UINTN
) HiiQuestion
+ HiiQuestion
->Length
)) {
150 DEBUG ((DEBUG_INFO
, "VarCheckHiiQuestion fail: OneOf mismatch (0x%lx)\n", OneData
));
151 DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion
->Length
, (UINT8
*) HiiQuestion
););
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
););
164 case EFI_IFR_NUMERIC_OP
:
167 Ptr
= (UINT8
*) ((VAR_CHECK_HII_QUESTION_NUMERIC
*) HiiQuestion
+ 1);
168 if (HiiQuestion
->BitFieldStore
) {
170 // For Numeric stored in bit field, the value of Maximum/Minimum are saved as UINT32 type.
172 CopyMem (&Minimum
, Ptr
, sizeof (UINT32
));
173 Ptr
+= sizeof (UINT32
);
174 CopyMem (&Maximum
, Ptr
, sizeof (UINT32
));
175 Ptr
+= sizeof (UINT32
);
177 CopyMem (&Minimum
, Ptr
, HiiQuestion
->StorageWidth
);
178 Ptr
+= HiiQuestion
->StorageWidth
;
179 CopyMem (&Maximum
, Ptr
, HiiQuestion
->StorageWidth
);
180 Ptr
+= HiiQuestion
->StorageWidth
;
184 // No need to check Step, because it is ONLY for UI.
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
););
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
));
199 for (Index
= 0; Index
< MaxContainers
; Index
++) {
201 CopyMem (&OneData
, (UINT8
*) Data
+ HiiQuestion
->VarOffset
+ HiiQuestion
->StorageWidth
* Index
, HiiQuestion
->StorageWidth
);
204 // The value of 0 is used to determine if a particular "slot" in the array is empty.
209 Ptr
= (UINT8
*) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST
*) HiiQuestion
+ 1);
210 while ((UINTN
) Ptr
< ((UINTN
) HiiQuestion
+ HiiQuestion
->Length
)) {
212 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
213 if (OneData
== OneValue
) {
219 Ptr
+= HiiQuestion
->StorageWidth
;
221 if ((UINTN
) Ptr
>= ((UINTN
) HiiQuestion
+ HiiQuestion
->Length
)) {
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
););
241 VAR_CHECK_HII_VARIABLE_HEADER
*mVarCheckHiiBin
= NULL
;
242 UINTN mVarCheckHiiBinSize
= 0;
245 SetVariable check handler HII.
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.
253 @retval EFI_SUCCESS The SetVariable check result was success.
254 @retval EFI_SECURITY_VIOLATION Check fail.
259 SetVariableCheckHandlerHii (
260 IN CHAR16
*VariableName
,
261 IN EFI_GUID
*VendorGuid
,
262 IN UINT32 Attributes
,
267 VAR_CHECK_HII_VARIABLE_HEADER
*HiiVariable
;
268 VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
;
270 if (mVarCheckHiiBin
== NULL
) {
274 if ((((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0) && (DataSize
== 0)) || (Attributes
== 0)) {
276 // Do not check delete variable.
282 // For Hii Variable header align.
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
))) {
289 // Found the Hii Variable that could be used to do check.
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
;
298 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable - CHECK PASS with DataSize == 0 !\n"));
302 if (HiiVariable
->Size
!= DataSize
) {
303 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable fail for Size - 0x%x\n", HiiVariable
->Size
));
304 return EFI_SECURITY_VIOLATION
;
309 // For Hii Question header align.
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
;
317 // For Hii Question header align.
319 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*) HEADER_ALIGN (((UINTN
) HiiQuestion
+ HiiQuestion
->Length
));
322 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable - ALL CHECK PASS!\n"));
326 // For Hii Variable header align.
328 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*) HEADER_ALIGN (((UINTN
) HiiVariable
+ HiiVariable
->Length
));
331 // Not found, so pass.
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"},
345 HII opcode to string.
347 @param[in] HiiOpCode Hii OpCode.
349 @return Pointer to string.
358 for (Index
= 0; Index
< ARRAY_SIZE (mHiiOpCodeStringTable
); Index
++) {
359 if (mHiiOpCodeStringTable
[Index
].HiiOpCode
== HiiOpCode
) {
360 return mHiiOpCodeStringTable
[Index
].HiiOpCodeStr
;
364 return "<UnknownHiiOpCode>";
370 @param[in] HiiQuestion Pointer to Hii Question.
375 IN VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
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")));
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
)) {
394 if (HiiQuestion
->BitFieldStore
) {
396 // For OneOf stored in bit field, the value of options are saved as UINT32 type.
398 CopyMem (&OneValue
, Ptr
, sizeof (UINT32
));
399 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%08x\n", OneValue
));
401 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
402 switch (HiiQuestion
->StorageWidth
) {
404 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%02x\n", OneValue
));
406 case sizeof (UINT16
):
407 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%04x\n", OneValue
));
409 case sizeof (UINT32
):
410 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%08x\n", OneValue
));
412 case sizeof (UINT64
):
413 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%016lx\n", OneValue
));
420 if (HiiQuestion
->BitFieldStore
) {
421 Ptr
+= sizeof (UINT32
);
423 Ptr
+= HiiQuestion
->StorageWidth
;
428 case EFI_IFR_CHECKBOX_OP
:
431 case EFI_IFR_NUMERIC_OP
:
434 Ptr
= (UINT8
*) ((VAR_CHECK_HII_QUESTION_NUMERIC
*) HiiQuestion
+ 1);
435 if(HiiQuestion
->BitFieldStore
) {
437 // For Numeric stored in bit field, the value of Maximum/Minimum are saved as UINT32 type.
439 CopyMem (&Minimum
, Ptr
, sizeof (UINT32
));
440 Ptr
+= sizeof (UINT32
);
441 CopyMem (&Maximum
, Ptr
, sizeof (UINT32
));
442 Ptr
+= sizeof (UINT32
);
444 DEBUG ((DEBUG_INFO
, " Minimum - 0x%08x\n", Minimum
));
445 DEBUG ((DEBUG_INFO
, " Maximum - 0x%08x\n", Maximum
));
447 CopyMem (&Minimum
, Ptr
, HiiQuestion
->StorageWidth
);
448 Ptr
+= HiiQuestion
->StorageWidth
;
449 CopyMem (&Maximum
, Ptr
, HiiQuestion
->StorageWidth
);
450 Ptr
+= HiiQuestion
->StorageWidth
;
452 switch (HiiQuestion
->StorageWidth
) {
454 DEBUG ((DEBUG_INFO
, " Minimum - 0x%02x\n", Minimum
));
455 DEBUG ((DEBUG_INFO
, " Maximum - 0x%02x\n", Maximum
));
457 case sizeof (UINT16
):
458 DEBUG ((DEBUG_INFO
, " Minimum - 0x%04x\n", Minimum
));
459 DEBUG ((DEBUG_INFO
, " Maximum - 0x%04x\n", Maximum
));
461 case sizeof (UINT32
):
462 DEBUG ((DEBUG_INFO
, " Minimum - 0x%08x\n", Minimum
));
463 DEBUG ((DEBUG_INFO
, " Maximum - 0x%08x\n", Maximum
));
465 case sizeof (UINT64
):
466 DEBUG ((DEBUG_INFO
, " Minimum - 0x%016lx\n", Minimum
));
467 DEBUG ((DEBUG_INFO
, " Maximum - 0x%016lx\n", Maximum
));
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
)) {
481 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
482 switch (HiiQuestion
->StorageWidth
) {
484 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%02x\n", OneValue
));
486 case sizeof (UINT16
):
487 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%04x\n", OneValue
));
489 case sizeof (UINT32
):
490 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%08x\n", OneValue
));
492 case sizeof (UINT64
):
493 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%016lx\n", OneValue
));
499 Ptr
+= HiiQuestion
->StorageWidth
;
512 @param[in] HiiVariable Pointer to Hii Variable.
517 IN VAR_CHECK_HII_VARIABLE_HEADER
*HiiVariable
520 VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
;
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));
533 // For Hii Question header align.
535 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*) HEADER_ALIGN (((UINTN
) HiiVariable
+ HiiVariable
->HeaderLength
));
536 while ((UINTN
) HiiQuestion
< ((UINTN
) HiiVariable
+ HiiVariable
->Length
)) {
538 // Dump Hii Question related to the Hii Variable.
540 DumpHiiQuestion (HiiQuestion
);
542 // For Hii Question header align.
544 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*) HEADER_ALIGN (((UINTN
) HiiQuestion
+ HiiQuestion
->Length
));
551 @param[in] VarCheckHiiBin Pointer to VarCheckHiiBin.
552 @param[in] VarCheckHiiBinSize VarCheckHiiBin size.
557 IN VOID
*VarCheckHiiBin
,
558 IN UINTN VarCheckHiiBinSize
561 VAR_CHECK_HII_VARIABLE_HEADER
*HiiVariable
;
563 DEBUG ((DEBUG_INFO
, "DumpVarCheckHii\n"));
566 // For Hii Variable header align.
568 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*) HEADER_ALIGN (VarCheckHiiBin
);
569 while ((UINTN
) HiiVariable
< ((UINTN
) VarCheckHiiBin
+ VarCheckHiiBinSize
)) {
570 DumpHiiVariable (HiiVariable
);
572 // For Hii Variable header align.
574 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*) HEADER_ALIGN (((UINTN
) HiiVariable
+ HiiVariable
->Length
));
580 Constructor function of VarCheckHiiLib to register var check HII handler.
582 @param[in] ImageHandle The firmware allocated handle for the EFI image.
583 @param[in] SystemTable A pointer to the EFI System Table.
585 @retval EFI_SUCCESS The constructor executed correctly.
590 VarCheckHiiLibNullClassConstructor (
591 IN EFI_HANDLE ImageHandle
,
592 IN EFI_SYSTEM_TABLE
*SystemTable
595 VarCheckLibRegisterEndOfDxeCallback (VarCheckHiiGen
);
596 VarCheckLibRegisterAddressPointer ((VOID
**) &mVarCheckHiiBin
);
597 VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerHii
);