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
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.
15 #include "VarCheckHii.h"
17 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mVarCheckHiiHex
[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
20 Dump some hexadecimal data.
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.
29 VarCheckHiiInternalDumpHex (
47 while (DataSize
!= 0) {
49 if (Size
> DataSize
) {
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
);
63 DEBUG ((DEBUG_INFO
, "%*a%08X: %-48a *%a*\r\n", Indent
, "", Offset
, Val
, Str
));
72 Var Check Hii Question.
74 @param[in] HiiQuestion Pointer to Hii Question
75 @param[in] Data Data pointer.
76 @param[in] DataSize Size of Data to set.
78 @retval TRUE Check pass
79 @retval FALSE Check fail.
84 IN VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
,
99 UINT16 VarOffsetByteLevel
;
100 UINT8 StorageWidthByteLevel
;
102 if (HiiQuestion
->BitFieldStore
) {
103 VarOffsetByteLevel
= HiiQuestion
->VarOffset
/ 8;
104 TotalBits
= HiiQuestion
->VarOffset
% 8 + HiiQuestion
->StorageWidth
;
105 StorageWidthByteLevel
= (TotalBits
% 8 == 0 ? TotalBits
/ 8: TotalBits
/ 8 + 1);
107 VarOffsetByteLevel
= HiiQuestion
->VarOffset
;
108 StorageWidthByteLevel
= HiiQuestion
->StorageWidth
;
111 if (((UINT32
) VarOffsetByteLevel
+ StorageWidthByteLevel
) > DataSize
) {
112 DEBUG ((DEBUG_INFO
, "VarCheckHiiQuestion fail: (VarOffset(0x%04x) + StorageWidth(0x%02x)) > Size(0x%x)\n", VarOffsetByteLevel
, StorageWidthByteLevel
, DataSize
));
117 CopyMem (&OneData
, (UINT8
*) Data
+ VarOffsetByteLevel
, StorageWidthByteLevel
);
118 if (HiiQuestion
->BitFieldStore
) {
120 // Get the value from the bit field.
122 StartBit
= HiiQuestion
->VarOffset
% 8;
123 EndBit
= StartBit
+ HiiQuestion
->StorageWidth
- 1;
124 OneData
= BitFieldRead64 (OneData
, StartBit
, EndBit
);
127 switch (HiiQuestion
->OpCode
) {
128 case EFI_IFR_ONE_OF_OP
:
129 Ptr
= (UINT8
*) ((VAR_CHECK_HII_QUESTION_ONEOF
*) HiiQuestion
+ 1);
130 while ((UINTN
) Ptr
< (UINTN
) HiiQuestion
+ HiiQuestion
->Length
) {
132 if (HiiQuestion
->BitFieldStore
) {
134 // For OneOf stored in bit field, the value of options are saved as UINT32 type.
136 CopyMem (&OneValue
, Ptr
, sizeof (UINT32
));
138 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
140 if (OneData
== OneValue
) {
146 if (HiiQuestion
->BitFieldStore
) {
147 Ptr
+= sizeof (UINT32
);
149 Ptr
+= HiiQuestion
->StorageWidth
;
152 if ((UINTN
) Ptr
>= ((UINTN
) HiiQuestion
+ HiiQuestion
->Length
)) {
156 DEBUG ((DEBUG_INFO
, "VarCheckHiiQuestion fail: OneOf mismatch (0x%lx)\n", OneData
));
157 DEBUG_CODE (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
));
165 DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion
->Length
, (UINT8
*) HiiQuestion
););
170 case EFI_IFR_NUMERIC_OP
:
173 Ptr
= (UINT8
*) ((VAR_CHECK_HII_QUESTION_NUMERIC
*) HiiQuestion
+ 1);
174 if (HiiQuestion
->BitFieldStore
) {
176 // For Numeric stored in bit field, the value of Maximum/Minimum are saved as UINT32 type.
178 CopyMem (&Minimum
, Ptr
, sizeof (UINT32
));
179 Ptr
+= sizeof (UINT32
);
180 CopyMem (&Maximum
, Ptr
, sizeof (UINT32
));
181 Ptr
+= sizeof (UINT32
);
183 CopyMem (&Minimum
, Ptr
, HiiQuestion
->StorageWidth
);
184 Ptr
+= HiiQuestion
->StorageWidth
;
185 CopyMem (&Maximum
, Ptr
, HiiQuestion
->StorageWidth
);
186 Ptr
+= HiiQuestion
->StorageWidth
;
190 // No need to check Step, because it is ONLY for UI.
192 if ((OneData
< Minimum
) || (OneData
> Maximum
)) {
193 DEBUG ((DEBUG_INFO
, "VarCheckHiiQuestion fail: Numeric mismatch (0x%lx)\n", OneData
));
194 DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion
->Length
, (UINT8
*) HiiQuestion
););
199 case EFI_IFR_ORDERED_LIST_OP
:
200 MaxContainers
= ((VAR_CHECK_HII_QUESTION_ORDEREDLIST
*) HiiQuestion
)->MaxContainers
;
201 if (((UINT32
) HiiQuestion
->VarOffset
+ HiiQuestion
->StorageWidth
* MaxContainers
) > DataSize
) {
202 DEBUG ((DEBUG_INFO
, "VarCheckHiiQuestion fail: (VarOffset(0x%04x) + StorageWidth(0x%02x) * MaxContainers(0x%02x)) > Size(0x%x)\n", HiiQuestion
->VarOffset
, HiiQuestion
->StorageWidth
, MaxContainers
, DataSize
));
205 for (Index
= 0; Index
< MaxContainers
; Index
++) {
207 CopyMem (&OneData
, (UINT8
*) Data
+ HiiQuestion
->VarOffset
+ HiiQuestion
->StorageWidth
* Index
, HiiQuestion
->StorageWidth
);
210 // The value of 0 is used to determine if a particular "slot" in the array is empty.
215 Ptr
= (UINT8
*) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST
*) HiiQuestion
+ 1);
216 while ((UINTN
) Ptr
< ((UINTN
) HiiQuestion
+ HiiQuestion
->Length
)) {
218 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
219 if (OneData
== OneValue
) {
225 Ptr
+= HiiQuestion
->StorageWidth
;
227 if ((UINTN
) Ptr
>= ((UINTN
) HiiQuestion
+ HiiQuestion
->Length
)) {
231 DEBUG ((DEBUG_INFO
, "VarCheckHiiQuestion fail: OrderedList mismatch\n"));
232 DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion
->StorageWidth
* MaxContainers
, (UINT8
*) Data
+ HiiQuestion
->VarOffset
););
233 DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion
->Length
, (UINT8
*) HiiQuestion
););
247 VAR_CHECK_HII_VARIABLE_HEADER
*mVarCheckHiiBin
= NULL
;
248 UINTN mVarCheckHiiBinSize
= 0;
251 SetVariable check handler HII.
253 @param[in] VariableName Name of Variable to set.
254 @param[in] VendorGuid Variable vendor GUID.
255 @param[in] Attributes Attribute value of the variable.
256 @param[in] DataSize Size of Data to set.
257 @param[in] Data Data pointer.
259 @retval EFI_SUCCESS The SetVariable check result was success.
260 @retval EFI_SECURITY_VIOLATION Check fail.
265 SetVariableCheckHandlerHii (
266 IN CHAR16
*VariableName
,
267 IN EFI_GUID
*VendorGuid
,
268 IN UINT32 Attributes
,
273 VAR_CHECK_HII_VARIABLE_HEADER
*HiiVariable
;
274 VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
;
276 if (mVarCheckHiiBin
== NULL
) {
280 if ((((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0) && (DataSize
== 0)) || (Attributes
== 0)) {
282 // Do not check delete variable.
288 // For Hii Variable header align.
290 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*) HEADER_ALIGN (mVarCheckHiiBin
);
291 while ((UINTN
) HiiVariable
< ((UINTN
) mVarCheckHiiBin
+ mVarCheckHiiBinSize
)) {
292 if ((StrCmp ((CHAR16
*) (HiiVariable
+ 1), VariableName
) == 0) &&
293 (CompareGuid (&HiiVariable
->Guid
, VendorGuid
))) {
295 // Found the Hii Variable that could be used to do check.
297 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable - %s:%g with Attributes = 0x%08x Size = 0x%x\n", VariableName
, VendorGuid
, Attributes
, DataSize
));
298 if (HiiVariable
->Attributes
!= Attributes
) {
299 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable fail for Attributes - 0x%08x\n", HiiVariable
->Attributes
));
300 return EFI_SECURITY_VIOLATION
;
304 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable - CHECK PASS with DataSize == 0 !\n"));
308 if (HiiVariable
->Size
!= DataSize
) {
309 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable fail for Size - 0x%x\n", HiiVariable
->Size
));
310 return EFI_SECURITY_VIOLATION
;
315 // For Hii Question header align.
317 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*) HEADER_ALIGN (((UINTN
) HiiVariable
+ HiiVariable
->HeaderLength
));
318 while ((UINTN
) HiiQuestion
< ((UINTN
) HiiVariable
+ HiiVariable
->Length
)) {
319 if (!VarCheckHiiQuestion (HiiQuestion
, Data
, DataSize
)) {
320 return EFI_SECURITY_VIOLATION
;
323 // For Hii Question header align.
325 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*) HEADER_ALIGN (((UINTN
) HiiQuestion
+ HiiQuestion
->Length
));
328 DEBUG ((DEBUG_INFO
, "VarCheckHiiVariable - ALL CHECK PASS!\n"));
332 // For Hii Variable header align.
334 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*) HEADER_ALIGN (((UINTN
) HiiVariable
+ HiiVariable
->Length
));
337 // Not found, so pass.
341 #ifdef DUMP_VAR_CHECK_HII
342 GLOBAL_REMOVE_IF_UNREFERENCED VAR_CHECK_HII_OPCODE_STRING mHiiOpCodeStringTable
[] = {
343 {EFI_IFR_VARSTORE_EFI_OP
, "EfiVarStore"},
344 {EFI_IFR_ONE_OF_OP
, "OneOf"},
345 {EFI_IFR_CHECKBOX_OP
, "CheckBox"},
346 {EFI_IFR_NUMERIC_OP
, "Numeric"},
347 {EFI_IFR_ORDERED_LIST_OP
, "OrderedList"},
351 HII opcode to string.
353 @param[in] HiiOpCode Hii OpCode.
355 @return Pointer to string.
364 for (Index
= 0; Index
< ARRAY_SIZE (mHiiOpCodeStringTable
); Index
++) {
365 if (mHiiOpCodeStringTable
[Index
].HiiOpCode
== HiiOpCode
) {
366 return mHiiOpCodeStringTable
[Index
].HiiOpCodeStr
;
370 return "<UnknownHiiOpCode>";
376 @param[in] HiiQuestion Pointer to Hii Question.
381 IN VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
389 DEBUG ((DEBUG_INFO
, " VAR_CHECK_HII_QUESTION_HEADER\n"));
390 DEBUG ((DEBUG_INFO
, " OpCode - 0x%02x (%a) (%a)\n", HiiQuestion
->OpCode
, HiiOpCodeToStr (HiiQuestion
->OpCode
), (HiiQuestion
->BitFieldStore
? "bit level": "byte level")));
391 DEBUG ((DEBUG_INFO
, " Length - 0x%02x\n", HiiQuestion
->Length
));
392 DEBUG ((DEBUG_INFO
, " VarOffset - 0x%04x (%a)\n", HiiQuestion
->VarOffset
, (HiiQuestion
->BitFieldStore
? "bit level": "byte level")));
393 DEBUG ((DEBUG_INFO
, " StorageWidth - 0x%02x (%a)\n", HiiQuestion
->StorageWidth
, (HiiQuestion
->BitFieldStore
? "bit level": "byte level")));
395 switch (HiiQuestion
->OpCode
) {
396 case EFI_IFR_ONE_OF_OP
:
397 Ptr
= (UINT8
*) ((VAR_CHECK_HII_QUESTION_ONEOF
*) HiiQuestion
+ 1);
398 while ((UINTN
) Ptr
< ((UINTN
) HiiQuestion
+ HiiQuestion
->Length
)) {
400 if (HiiQuestion
->BitFieldStore
) {
402 // For OneOf stored in bit field, the value of options are saved as UINT32 type.
404 CopyMem (&OneValue
, Ptr
, sizeof (UINT32
));
405 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%08x\n", OneValue
));
407 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
408 switch (HiiQuestion
->StorageWidth
) {
410 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%02x\n", OneValue
));
412 case sizeof (UINT16
):
413 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%04x\n", OneValue
));
415 case sizeof (UINT32
):
416 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%08x\n", OneValue
));
418 case sizeof (UINT64
):
419 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%016lx\n", OneValue
));
426 if (HiiQuestion
->BitFieldStore
) {
427 Ptr
+= sizeof (UINT32
);
429 Ptr
+= HiiQuestion
->StorageWidth
;
434 case EFI_IFR_CHECKBOX_OP
:
437 case EFI_IFR_NUMERIC_OP
:
440 Ptr
= (UINT8
*) ((VAR_CHECK_HII_QUESTION_NUMERIC
*) HiiQuestion
+ 1);
441 if(HiiQuestion
->BitFieldStore
) {
443 // For Numeric stored in bit field, the value of Maximum/Minimum are saved as UINT32 type.
445 CopyMem (&Minimum
, Ptr
, sizeof (UINT32
));
446 Ptr
+= sizeof (UINT32
);
447 CopyMem (&Maximum
, Ptr
, sizeof (UINT32
));
448 Ptr
+= sizeof (UINT32
);
450 DEBUG ((DEBUG_INFO
, " Minimum - 0x%08x\n", Minimum
));
451 DEBUG ((DEBUG_INFO
, " Maximum - 0x%08x\n", Maximum
));
453 CopyMem (&Minimum
, Ptr
, HiiQuestion
->StorageWidth
);
454 Ptr
+= HiiQuestion
->StorageWidth
;
455 CopyMem (&Maximum
, Ptr
, HiiQuestion
->StorageWidth
);
456 Ptr
+= HiiQuestion
->StorageWidth
;
458 switch (HiiQuestion
->StorageWidth
) {
460 DEBUG ((DEBUG_INFO
, " Minimum - 0x%02x\n", Minimum
));
461 DEBUG ((DEBUG_INFO
, " Maximum - 0x%02x\n", Maximum
));
463 case sizeof (UINT16
):
464 DEBUG ((DEBUG_INFO
, " Minimum - 0x%04x\n", Minimum
));
465 DEBUG ((DEBUG_INFO
, " Maximum - 0x%04x\n", Maximum
));
467 case sizeof (UINT32
):
468 DEBUG ((DEBUG_INFO
, " Minimum - 0x%08x\n", Minimum
));
469 DEBUG ((DEBUG_INFO
, " Maximum - 0x%08x\n", Maximum
));
471 case sizeof (UINT64
):
472 DEBUG ((DEBUG_INFO
, " Minimum - 0x%016lx\n", Minimum
));
473 DEBUG ((DEBUG_INFO
, " Maximum - 0x%016lx\n", Maximum
));
482 case EFI_IFR_ORDERED_LIST_OP
:
483 DEBUG ((DEBUG_INFO
, " MaxContainers - 0x%02x\n", ((VAR_CHECK_HII_QUESTION_ORDEREDLIST
*) HiiQuestion
)->MaxContainers
));
484 Ptr
= (UINT8
*) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST
*) HiiQuestion
+ 1);
485 while ((UINTN
) Ptr
< ((UINTN
) HiiQuestion
+ HiiQuestion
->Length
)) {
487 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
488 switch (HiiQuestion
->StorageWidth
) {
490 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%02x\n", OneValue
));
492 case sizeof (UINT16
):
493 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%04x\n", OneValue
));
495 case sizeof (UINT32
):
496 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%08x\n", OneValue
));
498 case sizeof (UINT64
):
499 DEBUG ((DEBUG_INFO
, " OneOfOption - 0x%016lx\n", OneValue
));
505 Ptr
+= HiiQuestion
->StorageWidth
;
518 @param[in] HiiVariable Pointer to Hii Variable.
523 IN VAR_CHECK_HII_VARIABLE_HEADER
*HiiVariable
526 VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
;
528 DEBUG ((DEBUG_INFO
, "VAR_CHECK_HII_VARIABLE_HEADER\n"));
529 DEBUG ((DEBUG_INFO
, " Revision - 0x%04x\n", HiiVariable
->Revision
));
530 DEBUG ((DEBUG_INFO
, " HeaderLength - 0x%04x\n", HiiVariable
->HeaderLength
));
531 DEBUG ((DEBUG_INFO
, " Length - 0x%08x\n", HiiVariable
->Length
));
532 DEBUG ((DEBUG_INFO
, " OpCode - 0x%02x (%a)\n", HiiVariable
->OpCode
, HiiOpCodeToStr (HiiVariable
->OpCode
)));
533 DEBUG ((DEBUG_INFO
, " Size - 0x%04x\n", HiiVariable
->Size
));
534 DEBUG ((DEBUG_INFO
, " Attributes - 0x%08x\n", HiiVariable
->Attributes
));
535 DEBUG ((DEBUG_INFO
, " Guid - %g\n", &HiiVariable
->Guid
));
536 DEBUG ((DEBUG_INFO
, " Name - %s\n", HiiVariable
+ 1));
539 // For Hii Question header align.
541 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*) HEADER_ALIGN (((UINTN
) HiiVariable
+ HiiVariable
->HeaderLength
));
542 while ((UINTN
) HiiQuestion
< ((UINTN
) HiiVariable
+ HiiVariable
->Length
)) {
544 // Dump Hii Question related to the Hii Variable.
546 DumpHiiQuestion (HiiQuestion
);
548 // For Hii Question header align.
550 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*) HEADER_ALIGN (((UINTN
) HiiQuestion
+ HiiQuestion
->Length
));
557 @param[in] VarCheckHiiBin Pointer to VarCheckHiiBin.
558 @param[in] VarCheckHiiBinSize VarCheckHiiBin size.
563 IN VOID
*VarCheckHiiBin
,
564 IN UINTN VarCheckHiiBinSize
567 VAR_CHECK_HII_VARIABLE_HEADER
*HiiVariable
;
569 DEBUG ((DEBUG_INFO
, "DumpVarCheckHii\n"));
572 // For Hii Variable header align.
574 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*) HEADER_ALIGN (VarCheckHiiBin
);
575 while ((UINTN
) HiiVariable
< ((UINTN
) VarCheckHiiBin
+ VarCheckHiiBinSize
)) {
576 DumpHiiVariable (HiiVariable
);
578 // For Hii Variable header align.
580 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*) HEADER_ALIGN (((UINTN
) HiiVariable
+ HiiVariable
->Length
));
586 Constructor function of VarCheckHiiLib to register var check HII handler.
588 @param[in] ImageHandle The firmware allocated handle for the EFI image.
589 @param[in] SystemTable A pointer to the EFI System Table.
591 @retval EFI_SUCCESS The constructor executed correctly.
596 VarCheckHiiLibNullClassConstructor (
597 IN EFI_HANDLE ImageHandle
,
598 IN EFI_SYSTEM_TABLE
*SystemTable
601 VarCheckLibRegisterEndOfDxeCallback (VarCheckHiiGen
);
602 VarCheckLibRegisterAddressPointer ((VOID
**) &mVarCheckHiiBin
);
603 VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerHii
);