4 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include <Library/VarCheckLib.h>
10 #include <Library/BaseLib.h>
11 #include <Library/DebugLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/MemoryAllocationLib.h>
14 #include <Library/DxeServicesLib.h>
16 #include "VarCheckPcdStructure.h"
18 //#define DUMP_VAR_CHECK_PCD
20 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mVarCheckPcdHex
[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
23 Dump some hexadecimal data.
25 @param[in] Indent How many spaces to indent the output.
26 @param[in] Offset The offset of the dump.
27 @param[in] DataSize The size in bytes of UserData.
28 @param[in] UserData The data to dump.
32 VarCheckPcdInternalDumpHex (
50 while (DataSize
!= 0) {
52 if (Size
> DataSize
) {
56 for (Index
= 0; Index
< Size
; Index
+= 1) {
57 TempByte
= Data
[Index
];
58 Val
[Index
* 3 + 0] = mVarCheckPcdHex
[TempByte
>> 4];
59 Val
[Index
* 3 + 1] = mVarCheckPcdHex
[TempByte
& 0xF];
60 Val
[Index
* 3 + 2] = (CHAR8
) ((Index
== 7) ? '-' : ' ');
61 Str
[Index
] = (CHAR8
) ((TempByte
< ' ' || TempByte
> 'z') ? '.' : TempByte
);
66 DEBUG ((EFI_D_INFO
, "%*a%08X: %-48a *%a*\r\n", Indent
, "", Offset
, Val
, Str
));
75 Var Check Pcd ValidData.
77 @param[in] PcdValidData Pointer to Pcd ValidData
78 @param[in] Data Data pointer.
79 @param[in] DataSize Size of Data to set.
81 @retval TRUE Check pass
82 @retval FALSE Check fail.
86 VarCheckPcdValidData (
87 IN VAR_CHECK_PCD_VALID_DATA_HEADER
*PcdValidData
,
99 CopyMem (&OneData
, (UINT8
*) Data
+ PcdValidData
->VarOffset
, PcdValidData
->StorageWidth
);
101 switch (PcdValidData
->Type
) {
102 case VarCheckPcdValidList
:
103 Ptr
= (UINT8
*) ((VAR_CHECK_PCD_VALID_LIST
*) PcdValidData
+ 1);
104 while ((UINTN
) Ptr
< (UINTN
) PcdValidData
+ PcdValidData
->Length
) {
106 CopyMem (&OneValue
, Ptr
, PcdValidData
->StorageWidth
);
107 if (OneData
== OneValue
) {
113 Ptr
+= PcdValidData
->StorageWidth
;
115 if ((UINTN
) Ptr
>= ((UINTN
) PcdValidData
+ PcdValidData
->Length
)) {
119 DEBUG ((EFI_D_INFO
, "VarCheckPcdValidData fail: ValidList mismatch (0x%lx)\n", OneData
));
120 DEBUG_CODE (VarCheckPcdInternalDumpHex (2, 0, PcdValidData
->Length
, (UINT8
*) PcdValidData
););
125 case VarCheckPcdValidRange
:
128 Ptr
= (UINT8
*) ((VAR_CHECK_PCD_VALID_RANGE
*) PcdValidData
+ 1);
129 while ((UINTN
) Ptr
< (UINTN
) PcdValidData
+ PcdValidData
->Length
) {
130 CopyMem (&Minimum
, Ptr
, PcdValidData
->StorageWidth
);
131 Ptr
+= PcdValidData
->StorageWidth
;
132 CopyMem (&Maximum
, Ptr
, PcdValidData
->StorageWidth
);
133 Ptr
+= PcdValidData
->StorageWidth
;
135 if ((OneData
>= Minimum
) && (OneData
<= Maximum
)) {
139 DEBUG ((EFI_D_INFO
, "VarCheckPcdValidData fail: ValidRange mismatch (0x%lx)\n", OneData
));
140 DEBUG_CODE (VarCheckPcdInternalDumpHex (2, 0, PcdValidData
->Length
, (UINT8
*) PcdValidData
););
152 VAR_CHECK_PCD_VARIABLE_HEADER
*mVarCheckPcdBin
= NULL
;
153 UINTN mVarCheckPcdBinSize
= 0;
156 SetVariable check handler PCD.
158 @param[in] VariableName Name of Variable to set.
159 @param[in] VendorGuid Variable vendor GUID.
160 @param[in] Attributes Attribute value of the variable.
161 @param[in] DataSize Size of Data to set.
162 @param[in] Data Data pointer.
164 @retval EFI_SUCCESS The SetVariable check result was success.
165 @retval EFI_SECURITY_VIOLATION Check fail.
170 SetVariableCheckHandlerPcd (
171 IN CHAR16
*VariableName
,
172 IN EFI_GUID
*VendorGuid
,
173 IN UINT32 Attributes
,
178 VAR_CHECK_PCD_VARIABLE_HEADER
*PcdVariable
;
179 VAR_CHECK_PCD_VALID_DATA_HEADER
*PcdValidData
;
181 if (mVarCheckPcdBin
== NULL
) {
185 if ((((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0) && (DataSize
== 0)) || (Attributes
== 0)) {
187 // Do not check delete variable.
193 // For Pcd Variable header align.
195 PcdVariable
= (VAR_CHECK_PCD_VARIABLE_HEADER
*) HEADER_ALIGN (mVarCheckPcdBin
);
196 while ((UINTN
) PcdVariable
< ((UINTN
) mVarCheckPcdBin
+ mVarCheckPcdBinSize
)) {
197 if ((StrCmp ((CHAR16
*) (PcdVariable
+ 1), VariableName
) == 0) &&
198 (CompareGuid (&PcdVariable
->Guid
, VendorGuid
))) {
200 // Found the Pcd Variable that could be used to do check.
202 DEBUG ((EFI_D_INFO
, "VarCheckPcdVariable - %s:%g with Attributes = 0x%08x Size = 0x%x\n", VariableName
, VendorGuid
, Attributes
, DataSize
));
203 if ((PcdVariable
->Attributes
!= 0) && PcdVariable
->Attributes
!= Attributes
) {
204 DEBUG ((EFI_D_INFO
, "VarCheckPcdVariable fail for Attributes - 0x%08x\n", PcdVariable
->Attributes
));
205 return EFI_SECURITY_VIOLATION
;
209 DEBUG ((EFI_D_INFO
, "VarCheckPcdVariable - CHECK PASS with DataSize == 0 !\n"));
215 // For Pcd ValidData header align.
217 PcdValidData
= (VAR_CHECK_PCD_VALID_DATA_HEADER
*) HEADER_ALIGN (((UINTN
) PcdVariable
+ PcdVariable
->HeaderLength
));
218 while ((UINTN
) PcdValidData
< ((UINTN
) PcdVariable
+ PcdVariable
->Length
)) {
219 if (((UINTN
) PcdValidData
->VarOffset
+ PcdValidData
->StorageWidth
) <= DataSize
) {
220 if (!VarCheckPcdValidData (PcdValidData
, Data
, DataSize
)) {
221 return EFI_SECURITY_VIOLATION
;
225 // For Pcd ValidData header align.
227 PcdValidData
= (VAR_CHECK_PCD_VALID_DATA_HEADER
*) HEADER_ALIGN (((UINTN
) PcdValidData
+ PcdValidData
->Length
));
230 DEBUG ((EFI_D_INFO
, "VarCheckPcdVariable - ALL CHECK PASS!\n"));
234 // For Pcd Variable header align.
236 PcdVariable
= (VAR_CHECK_PCD_VARIABLE_HEADER
*) HEADER_ALIGN (((UINTN
) PcdVariable
+ PcdVariable
->Length
));
239 // Not found, so pass.
243 #ifdef DUMP_VAR_CHECK_PCD
247 @param[in] PcdValidData Pointer to Pcd ValidData.
252 IN VAR_CHECK_PCD_VALID_DATA_HEADER
*PcdValidData
260 DEBUG ((EFI_D_INFO
, " VAR_CHECK_PCD_VALID_DATA_HEADER\n"));
261 DEBUG ((EFI_D_INFO
, " Type - 0x%02x\n", PcdValidData
->Type
));
262 DEBUG ((EFI_D_INFO
, " Length - 0x%02x\n", PcdValidData
->Length
));
263 DEBUG ((EFI_D_INFO
, " VarOffset - 0x%04x\n", PcdValidData
->VarOffset
));
264 DEBUG ((EFI_D_INFO
, " StorageWidth - 0x%02x\n", PcdValidData
->StorageWidth
));
266 switch (PcdValidData
->Type
) {
267 case VarCheckPcdValidList
:
268 Ptr
= (UINT8
*) ((VAR_CHECK_PCD_VALID_LIST
*) PcdValidData
+ 1);
269 while ((UINTN
) Ptr
< ((UINTN
) PcdValidData
+ PcdValidData
->Length
)) {
271 CopyMem (&OneValue
, Ptr
, PcdValidData
->StorageWidth
);
272 switch (PcdValidData
->StorageWidth
) {
274 DEBUG ((EFI_D_INFO
, " ValidList - 0x%02x\n", OneValue
));
276 case sizeof (UINT16
):
277 DEBUG ((EFI_D_INFO
, " ValidList - 0x%04x\n", OneValue
));
279 case sizeof (UINT32
):
280 DEBUG ((EFI_D_INFO
, " ValidList - 0x%08x\n", OneValue
));
282 case sizeof (UINT64
):
283 DEBUG ((EFI_D_INFO
, " ValidList - 0x%016lx\n", OneValue
));
289 Ptr
+= PcdValidData
->StorageWidth
;
293 case VarCheckPcdValidRange
:
296 Ptr
= (UINT8
*) ((VAR_CHECK_PCD_VALID_RANGE
*) PcdValidData
+ 1);
297 while ((UINTN
) Ptr
< (UINTN
) PcdValidData
+ PcdValidData
->Length
) {
298 CopyMem (&Minimum
, Ptr
, PcdValidData
->StorageWidth
);
299 Ptr
+= PcdValidData
->StorageWidth
;
300 CopyMem (&Maximum
, Ptr
, PcdValidData
->StorageWidth
);
301 Ptr
+= PcdValidData
->StorageWidth
;
303 switch (PcdValidData
->StorageWidth
) {
305 DEBUG ((EFI_D_INFO
, " Minimum - 0x%02x\n", Minimum
));
306 DEBUG ((EFI_D_INFO
, " Maximum - 0x%02x\n", Maximum
));
308 case sizeof (UINT16
):
309 DEBUG ((EFI_D_INFO
, " Minimum - 0x%04x\n", Minimum
));
310 DEBUG ((EFI_D_INFO
, " Maximum - 0x%04x\n", Maximum
));
312 case sizeof (UINT32
):
313 DEBUG ((EFI_D_INFO
, " Minimum - 0x%08x\n", Minimum
));
314 DEBUG ((EFI_D_INFO
, " Maximum - 0x%08x\n", Maximum
));
316 case sizeof (UINT64
):
317 DEBUG ((EFI_D_INFO
, " Minimum - 0x%016lx\n", Minimum
));
318 DEBUG ((EFI_D_INFO
, " Maximum - 0x%016lx\n", Maximum
));
336 @param[in] PcdVariable Pointer to Pcd Variable.
341 IN VAR_CHECK_PCD_VARIABLE_HEADER
*PcdVariable
344 VAR_CHECK_PCD_VALID_DATA_HEADER
*PcdValidData
;
346 DEBUG ((EFI_D_INFO
, "VAR_CHECK_PCD_VARIABLE_HEADER\n"));
347 DEBUG ((EFI_D_INFO
, " Revision - 0x%04x\n", PcdVariable
->Revision
));
348 DEBUG ((EFI_D_INFO
, " HeaderLength - 0x%04x\n", PcdVariable
->HeaderLength
));
349 DEBUG ((EFI_D_INFO
, " Length - 0x%08x\n", PcdVariable
->Length
));
350 DEBUG ((EFI_D_INFO
, " Type - 0x%02x\n", PcdVariable
->Type
));
351 DEBUG ((EFI_D_INFO
, " Attributes - 0x%08x\n", PcdVariable
->Attributes
));
352 DEBUG ((EFI_D_INFO
, " Guid - %g\n", &PcdVariable
->Guid
));
353 DEBUG ((EFI_D_INFO
, " Name - %s\n", PcdVariable
+ 1));
356 // For Pcd ValidData header align.
358 PcdValidData
= (VAR_CHECK_PCD_VALID_DATA_HEADER
*) HEADER_ALIGN (((UINTN
) PcdVariable
+ PcdVariable
->HeaderLength
));
359 while ((UINTN
) PcdValidData
< ((UINTN
) PcdVariable
+ PcdVariable
->Length
)) {
361 // Dump Pcd ValidData related to the Pcd Variable.
363 DumpPcdValidData (PcdValidData
);
365 // For Pcd ValidData header align.
367 PcdValidData
= (VAR_CHECK_PCD_VALID_DATA_HEADER
*) HEADER_ALIGN (((UINTN
) PcdValidData
+ PcdValidData
->Length
));
374 @param[in] VarCheckPcdBin Pointer to VarCheckPcdBin.
375 @param[in] VarCheckPcdBinSize VarCheckPcdBin size.
380 IN VOID
*VarCheckPcdBin
,
381 IN UINTN VarCheckPcdBinSize
384 VAR_CHECK_PCD_VARIABLE_HEADER
*PcdVariable
;
386 DEBUG ((EFI_D_INFO
, "DumpVarCheckPcd\n"));
389 // For Pcd Variable header align.
391 PcdVariable
= (VAR_CHECK_PCD_VARIABLE_HEADER
*) HEADER_ALIGN (VarCheckPcdBin
);
392 while ((UINTN
) PcdVariable
< ((UINTN
) VarCheckPcdBin
+ VarCheckPcdBinSize
)) {
393 DumpPcdVariable (PcdVariable
);
395 // For Pcd Variable header align.
397 PcdVariable
= (VAR_CHECK_PCD_VARIABLE_HEADER
*) HEADER_ALIGN (((UINTN
) PcdVariable
+ PcdVariable
->Length
));
403 Locate VarCheckPcdBin.
408 LocateVarCheckPcdBin (
413 VAR_CHECK_PCD_VARIABLE_HEADER
*VarCheckPcdBin
;
414 UINTN VarCheckPcdBinSize
;
417 // Search the VarCheckPcdBin from the first RAW section of current FFS.
419 Status
= GetSectionFromFfs (
422 (VOID
**) &VarCheckPcdBin
,
425 if (!EFI_ERROR (Status
)) {
427 // AllocateRuntimeZeroPool () from MemoryAllocateLib is used for runtime access
428 // in SetVariable check handler.
430 mVarCheckPcdBin
= AllocateRuntimeCopyPool (VarCheckPcdBinSize
, VarCheckPcdBin
);
431 ASSERT (mVarCheckPcdBin
!= NULL
);
433 // Make sure the allocated buffer for VarCheckPcdBin at required alignment.
435 ASSERT ((((UINTN
) mVarCheckPcdBin
) & (HEADER_ALIGNMENT
- 1)) == 0);
436 mVarCheckPcdBinSize
= VarCheckPcdBinSize
;
437 FreePool (VarCheckPcdBin
);
439 DEBUG ((EFI_D_INFO
, "VarCheckPcdBin - at 0x%x size = 0x%x\n", mVarCheckPcdBin
, mVarCheckPcdBinSize
));
441 #ifdef DUMP_VAR_CHECK_PCD
443 DumpVarCheckPcd (mVarCheckPcdBin
, mVarCheckPcdBinSize
);
447 DEBUG ((EFI_D_INFO
, "[VarCheckPcd] No VarCheckPcdBin found at the first RAW section\n"));
452 Constructor function of VarCheckPcdLib to register var check PCD handler.
454 @param[in] ImageHandle The firmware allocated handle for the EFI image.
455 @param[in] SystemTable A pointer to the EFI System Table.
457 @retval EFI_SUCCESS The constructor executed correctly.
462 VarCheckPcdLibNullClassConstructor (
463 IN EFI_HANDLE ImageHandle
,
464 IN EFI_SYSTEM_TABLE
*SystemTable
467 LocateVarCheckPcdBin ();
468 VarCheckLibRegisterAddressPointer ((VOID
**) &mVarCheckPcdBin
);
469 VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerPcd
);