4 Copyright (c) 2015, 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 ((EFI_D_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
,
97 if ((UINTN
) (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
));
103 CopyMem (&OneData
, (UINT8
*) Data
+ HiiQuestion
->VarOffset
, HiiQuestion
->StorageWidth
);
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
) {
110 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
111 if (OneData
== OneValue
) {
117 Ptr
+= HiiQuestion
->StorageWidth
;
119 if ((UINTN
) Ptr
>= ((UINTN
) HiiQuestion
+ HiiQuestion
->Length
)) {
123 DEBUG ((EFI_D_INFO
, "VarCheckHiiQuestion fail: OneOf mismatch (0x%lx)\n", OneData
));
124 DEBUG_CODE (VarCheckHiiInternalDumpHex (2, 0, HiiQuestion
->Length
, (UINT8
*) HiiQuestion
););
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
););
137 case EFI_IFR_NUMERIC_OP
:
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
;
147 // No need to check Step, because it is ONLY for UI.
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
););
156 case EFI_IFR_ORDERED_LIST_OP
:
157 MaxContainers
= ((VAR_CHECK_HII_QUESTION_ORDEREDLIST
*) HiiQuestion
)->MaxContainers
;
158 if ((UINTN
) (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
));
162 for (Index
= 0; Index
< MaxContainers
; Index
++) {
164 CopyMem (&OneData
, (UINT8
*) Data
+ HiiQuestion
->VarOffset
+ HiiQuestion
->StorageWidth
* Index
, HiiQuestion
->StorageWidth
);
167 // The value of 0 is used to determine if a particular "slot" in the array is empty.
172 Ptr
= (UINT8
*) ((VAR_CHECK_HII_QUESTION_ORDEREDLIST
*) HiiQuestion
+ 1);
173 while ((UINTN
) Ptr
< ((UINTN
) HiiQuestion
+ HiiQuestion
->Length
)) {
175 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
176 if (OneData
== OneValue
) {
182 Ptr
+= HiiQuestion
->StorageWidth
;
184 if ((UINTN
) Ptr
>= ((UINTN
) HiiQuestion
+ HiiQuestion
->Length
)) {
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
););
204 VAR_CHECK_HII_VARIABLE_HEADER
*mVarCheckHiiBin
= NULL
;
205 UINTN mVarCheckHiiBinSize
= 0;
208 SetVariable check handler HII.
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.
216 @retval EFI_SUCCESS The SetVariable check result was success.
217 @retval EFI_SECURITY_VIOLATION Check fail.
222 SetVariableCheckHandlerHii (
223 IN CHAR16
*VariableName
,
224 IN EFI_GUID
*VendorGuid
,
225 IN UINT32 Attributes
,
230 VAR_CHECK_HII_VARIABLE_HEADER
*HiiVariable
;
231 VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
;
233 if (mVarCheckHiiBin
== NULL
) {
237 if ((((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0) && (DataSize
== 0)) || (Attributes
== 0)) {
239 // Do not check delete variable.
245 // For Hii Variable header align.
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
))) {
252 // Found the Hii Variable that could be used to do check.
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
;
261 DEBUG ((EFI_D_INFO
, "VarCheckHiiVariable - CHECK PASS with DataSize == 0 !\n"));
265 if (HiiVariable
->Size
!= DataSize
) {
266 DEBUG ((EFI_D_INFO
, "VarCheckHiiVariable fail for Size - 0x%x\n", HiiVariable
->Size
));
267 return EFI_SECURITY_VIOLATION
;
272 // For Hii Question header align.
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
;
280 // For Hii Question header align.
282 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*) HEADER_ALIGN (((UINTN
) HiiQuestion
+ HiiQuestion
->Length
));
285 DEBUG ((EFI_D_INFO
, "VarCheckHiiVariable - ALL CHECK PASS!\n"));
289 // For Hii Variable header align.
291 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*) HEADER_ALIGN (((UINTN
) HiiVariable
+ HiiVariable
->Length
));
294 // Not found, so pass.
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"},
308 HII opcode to string.
310 @param[in] HiiOpCode Hii OpCode.
312 @return Pointer to string.
321 for (Index
= 0; Index
< ARRAY_SIZE (mHiiOpCodeStringTable
); Index
++) {
322 if (mHiiOpCodeStringTable
[Index
].HiiOpCode
== HiiOpCode
) {
323 return mHiiOpCodeStringTable
[Index
].HiiOpCodeStr
;
327 return "<UnknownHiiOpCode>";
333 @param[in] HiiQuestion Pointer to Hii Question.
338 IN VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
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
));
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
)) {
357 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
358 switch (HiiQuestion
->StorageWidth
) {
360 DEBUG ((EFI_D_INFO
, " OneOfOption - 0x%02x\n", OneValue
));
362 case sizeof (UINT16
):
363 DEBUG ((EFI_D_INFO
, " OneOfOption - 0x%04x\n", OneValue
));
365 case sizeof (UINT32
):
366 DEBUG ((EFI_D_INFO
, " OneOfOption - 0x%08x\n", OneValue
));
368 case sizeof (UINT64
):
369 DEBUG ((EFI_D_INFO
, " OneOfOption - 0x%016lx\n", OneValue
));
375 Ptr
+= HiiQuestion
->StorageWidth
;
379 case EFI_IFR_CHECKBOX_OP
:
382 case EFI_IFR_NUMERIC_OP
:
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
;
391 switch (HiiQuestion
->StorageWidth
) {
393 DEBUG ((EFI_D_INFO
, " Minimum - 0x%02x\n", Minimum
));
394 DEBUG ((EFI_D_INFO
, " Maximum - 0x%02x\n", Maximum
));
396 case sizeof (UINT16
):
397 DEBUG ((EFI_D_INFO
, " Minimum - 0x%04x\n", Minimum
));
398 DEBUG ((EFI_D_INFO
, " Maximum - 0x%04x\n", Maximum
));
400 case sizeof (UINT32
):
401 DEBUG ((EFI_D_INFO
, " Minimum - 0x%08x\n", Minimum
));
402 DEBUG ((EFI_D_INFO
, " Maximum - 0x%08x\n", Maximum
));
404 case sizeof (UINT64
):
405 DEBUG ((EFI_D_INFO
, " Minimum - 0x%016lx\n", Minimum
));
406 DEBUG ((EFI_D_INFO
, " Maximum - 0x%016lx\n", Maximum
));
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
)) {
419 CopyMem (&OneValue
, Ptr
, HiiQuestion
->StorageWidth
);
420 switch (HiiQuestion
->StorageWidth
) {
422 DEBUG ((EFI_D_INFO
, " OneOfOption - 0x%02x\n", OneValue
));
424 case sizeof (UINT16
):
425 DEBUG ((EFI_D_INFO
, " OneOfOption - 0x%04x\n", OneValue
));
427 case sizeof (UINT32
):
428 DEBUG ((EFI_D_INFO
, " OneOfOption - 0x%08x\n", OneValue
));
430 case sizeof (UINT64
):
431 DEBUG ((EFI_D_INFO
, " OneOfOption - 0x%016lx\n", OneValue
));
437 Ptr
+= HiiQuestion
->StorageWidth
;
450 @param[in] HiiVariable Pointer to Hii Variable.
455 IN VAR_CHECK_HII_VARIABLE_HEADER
*HiiVariable
458 VAR_CHECK_HII_QUESTION_HEADER
*HiiQuestion
;
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));
471 // For Hii Question header align.
473 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*) HEADER_ALIGN (((UINTN
) HiiVariable
+ HiiVariable
->HeaderLength
));
474 while ((UINTN
) HiiQuestion
< ((UINTN
) HiiVariable
+ HiiVariable
->Length
)) {
476 // Dump Hii Question related to the Hii Variable.
478 DumpHiiQuestion (HiiQuestion
);
480 // For Hii Question header align.
482 HiiQuestion
= (VAR_CHECK_HII_QUESTION_HEADER
*) HEADER_ALIGN (((UINTN
) HiiQuestion
+ HiiQuestion
->Length
));
489 @param[in] VarCheckHiiBin Pointer to VarCheckHiiBin.
490 @param[in] VarCheckHiiBinSize VarCheckHiiBin size.
495 IN VOID
*VarCheckHiiBin
,
496 IN UINTN VarCheckHiiBinSize
499 VAR_CHECK_HII_VARIABLE_HEADER
*HiiVariable
;
501 DEBUG ((EFI_D_INFO
, "DumpVarCheckHii\n"));
504 // For Hii Variable header align.
506 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*) HEADER_ALIGN (VarCheckHiiBin
);
507 while ((UINTN
) HiiVariable
< ((UINTN
) VarCheckHiiBin
+ VarCheckHiiBinSize
)) {
508 DumpHiiVariable (HiiVariable
);
510 // For Hii Variable header align.
512 HiiVariable
= (VAR_CHECK_HII_VARIABLE_HEADER
*) HEADER_ALIGN (((UINTN
) HiiVariable
+ HiiVariable
->Length
));
518 Constructor function of VarCheckHiiLib to register var check HII handler.
520 @param[in] ImageHandle The firmware allocated handle for the EFI image.
521 @param[in] SystemTable A pointer to the EFI System Table.
523 @retval EFI_SUCCESS The constructor executed correctly.
528 VarCheckHiiLibNullClassConstructor (
529 IN EFI_HANDLE ImageHandle
,
530 IN EFI_SYSTEM_TABLE
*SystemTable
533 VarCheckLibRegisterEndOfDxeCallback (VarCheckHiiGen
);
534 VarCheckLibRegisterAddressPointer ((VOID
**) &mVarCheckHiiBin
);
535 VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerHii
);