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 ((DEBUG_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
) {
114 Ptr
+= PcdValidData
->StorageWidth
;
117 if ((UINTN
)Ptr
>= ((UINTN
)PcdValidData
+ PcdValidData
->Length
)) {
121 DEBUG ((DEBUG_INFO
, "VarCheckPcdValidData fail: ValidList mismatch (0x%lx)\n", OneData
));
123 VarCheckPcdInternalDumpHex (2, 0, PcdValidData
->Length
, (UINT8
*)PcdValidData
);
130 case VarCheckPcdValidRange
:
133 Ptr
= (UINT8
*)((VAR_CHECK_PCD_VALID_RANGE
*)PcdValidData
+ 1);
134 while ((UINTN
)Ptr
< (UINTN
)PcdValidData
+ PcdValidData
->Length
) {
135 CopyMem (&Minimum
, Ptr
, PcdValidData
->StorageWidth
);
136 Ptr
+= PcdValidData
->StorageWidth
;
137 CopyMem (&Maximum
, Ptr
, PcdValidData
->StorageWidth
);
138 Ptr
+= PcdValidData
->StorageWidth
;
140 if ((OneData
>= Minimum
) && (OneData
<= Maximum
)) {
145 DEBUG ((DEBUG_INFO
, "VarCheckPcdValidData fail: ValidRange mismatch (0x%lx)\n", OneData
));
147 VarCheckPcdInternalDumpHex (2, 0, PcdValidData
->Length
, (UINT8
*)PcdValidData
);
160 VAR_CHECK_PCD_VARIABLE_HEADER
*mVarCheckPcdBin
= NULL
;
161 UINTN mVarCheckPcdBinSize
= 0;
164 SetVariable check handler PCD.
166 @param[in] VariableName Name of Variable to set.
167 @param[in] VendorGuid Variable vendor GUID.
168 @param[in] Attributes Attribute value of the variable.
169 @param[in] DataSize Size of Data to set.
170 @param[in] Data Data pointer.
172 @retval EFI_SUCCESS The SetVariable check result was success.
173 @retval EFI_SECURITY_VIOLATION Check fail.
178 SetVariableCheckHandlerPcd (
179 IN CHAR16
*VariableName
,
180 IN EFI_GUID
*VendorGuid
,
181 IN UINT32 Attributes
,
186 VAR_CHECK_PCD_VARIABLE_HEADER
*PcdVariable
;
187 VAR_CHECK_PCD_VALID_DATA_HEADER
*PcdValidData
;
189 if (mVarCheckPcdBin
== NULL
) {
193 if ((((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0) && (DataSize
== 0)) || (Attributes
== 0)) {
195 // Do not check delete variable.
201 // For Pcd Variable header align.
203 PcdVariable
= (VAR_CHECK_PCD_VARIABLE_HEADER
*)HEADER_ALIGN (mVarCheckPcdBin
);
204 while ((UINTN
)PcdVariable
< ((UINTN
)mVarCheckPcdBin
+ mVarCheckPcdBinSize
)) {
205 if ((StrCmp ((CHAR16
*)(PcdVariable
+ 1), VariableName
) == 0) &&
206 (CompareGuid (&PcdVariable
->Guid
, VendorGuid
)))
209 // Found the Pcd Variable that could be used to do check.
211 DEBUG ((DEBUG_INFO
, "VarCheckPcdVariable - %s:%g with Attributes = 0x%08x Size = 0x%x\n", VariableName
, VendorGuid
, Attributes
, DataSize
));
212 if ((PcdVariable
->Attributes
!= 0) && (PcdVariable
->Attributes
!= Attributes
)) {
213 DEBUG ((DEBUG_INFO
, "VarCheckPcdVariable fail for Attributes - 0x%08x\n", PcdVariable
->Attributes
));
214 return EFI_SECURITY_VIOLATION
;
218 DEBUG ((DEBUG_INFO
, "VarCheckPcdVariable - CHECK PASS with DataSize == 0 !\n"));
224 // For Pcd ValidData header align.
226 PcdValidData
= (VAR_CHECK_PCD_VALID_DATA_HEADER
*)HEADER_ALIGN (((UINTN
)PcdVariable
+ PcdVariable
->HeaderLength
));
227 while ((UINTN
)PcdValidData
< ((UINTN
)PcdVariable
+ PcdVariable
->Length
)) {
228 if (((UINTN
)PcdValidData
->VarOffset
+ PcdValidData
->StorageWidth
) <= DataSize
) {
229 if (!VarCheckPcdValidData (PcdValidData
, Data
, DataSize
)) {
230 return EFI_SECURITY_VIOLATION
;
235 // For Pcd ValidData header align.
237 PcdValidData
= (VAR_CHECK_PCD_VALID_DATA_HEADER
*)HEADER_ALIGN (((UINTN
)PcdValidData
+ PcdValidData
->Length
));
240 DEBUG ((DEBUG_INFO
, "VarCheckPcdVariable - ALL CHECK PASS!\n"));
245 // For Pcd Variable header align.
247 PcdVariable
= (VAR_CHECK_PCD_VARIABLE_HEADER
*)HEADER_ALIGN (((UINTN
)PcdVariable
+ PcdVariable
->Length
));
250 // Not found, so pass.
254 #ifdef DUMP_VAR_CHECK_PCD
259 @param[in] PcdValidData Pointer to Pcd ValidData.
264 IN VAR_CHECK_PCD_VALID_DATA_HEADER
*PcdValidData
272 DEBUG ((DEBUG_INFO
, " VAR_CHECK_PCD_VALID_DATA_HEADER\n"));
273 DEBUG ((DEBUG_INFO
, " Type - 0x%02x\n", PcdValidData
->Type
));
274 DEBUG ((DEBUG_INFO
, " Length - 0x%02x\n", PcdValidData
->Length
));
275 DEBUG ((DEBUG_INFO
, " VarOffset - 0x%04x\n", PcdValidData
->VarOffset
));
276 DEBUG ((DEBUG_INFO
, " StorageWidth - 0x%02x\n", PcdValidData
->StorageWidth
));
278 switch (PcdValidData
->Type
) {
279 case VarCheckPcdValidList
:
280 Ptr
= (UINT8
*)((VAR_CHECK_PCD_VALID_LIST
*)PcdValidData
+ 1);
281 while ((UINTN
)Ptr
< ((UINTN
)PcdValidData
+ PcdValidData
->Length
)) {
283 CopyMem (&OneValue
, Ptr
, PcdValidData
->StorageWidth
);
284 switch (PcdValidData
->StorageWidth
) {
286 DEBUG ((DEBUG_INFO
, " ValidList - 0x%02x\n", OneValue
));
288 case sizeof (UINT16
):
289 DEBUG ((DEBUG_INFO
, " ValidList - 0x%04x\n", OneValue
));
291 case sizeof (UINT32
):
292 DEBUG ((DEBUG_INFO
, " ValidList - 0x%08x\n", OneValue
));
294 case sizeof (UINT64
):
295 DEBUG ((DEBUG_INFO
, " ValidList - 0x%016lx\n", OneValue
));
302 Ptr
+= PcdValidData
->StorageWidth
;
307 case VarCheckPcdValidRange
:
310 Ptr
= (UINT8
*)((VAR_CHECK_PCD_VALID_RANGE
*)PcdValidData
+ 1);
311 while ((UINTN
)Ptr
< (UINTN
)PcdValidData
+ PcdValidData
->Length
) {
312 CopyMem (&Minimum
, Ptr
, PcdValidData
->StorageWidth
);
313 Ptr
+= PcdValidData
->StorageWidth
;
314 CopyMem (&Maximum
, Ptr
, PcdValidData
->StorageWidth
);
315 Ptr
+= PcdValidData
->StorageWidth
;
317 switch (PcdValidData
->StorageWidth
) {
319 DEBUG ((DEBUG_INFO
, " Minimum - 0x%02x\n", Minimum
));
320 DEBUG ((DEBUG_INFO
, " Maximum - 0x%02x\n", Maximum
));
322 case sizeof (UINT16
):
323 DEBUG ((DEBUG_INFO
, " Minimum - 0x%04x\n", Minimum
));
324 DEBUG ((DEBUG_INFO
, " Maximum - 0x%04x\n", Maximum
));
326 case sizeof (UINT32
):
327 DEBUG ((DEBUG_INFO
, " Minimum - 0x%08x\n", Minimum
));
328 DEBUG ((DEBUG_INFO
, " Maximum - 0x%08x\n", Maximum
));
330 case sizeof (UINT64
):
331 DEBUG ((DEBUG_INFO
, " Minimum - 0x%016lx\n", Minimum
));
332 DEBUG ((DEBUG_INFO
, " Maximum - 0x%016lx\n", Maximum
));
351 @param[in] PcdVariable Pointer to Pcd Variable.
356 IN VAR_CHECK_PCD_VARIABLE_HEADER
*PcdVariable
359 VAR_CHECK_PCD_VALID_DATA_HEADER
*PcdValidData
;
361 DEBUG ((DEBUG_INFO
, "VAR_CHECK_PCD_VARIABLE_HEADER\n"));
362 DEBUG ((DEBUG_INFO
, " Revision - 0x%04x\n", PcdVariable
->Revision
));
363 DEBUG ((DEBUG_INFO
, " HeaderLength - 0x%04x\n", PcdVariable
->HeaderLength
));
364 DEBUG ((DEBUG_INFO
, " Length - 0x%08x\n", PcdVariable
->Length
));
365 DEBUG ((DEBUG_INFO
, " Type - 0x%02x\n", PcdVariable
->Type
));
366 DEBUG ((DEBUG_INFO
, " Attributes - 0x%08x\n", PcdVariable
->Attributes
));
367 DEBUG ((DEBUG_INFO
, " Guid - %g\n", &PcdVariable
->Guid
));
368 DEBUG ((DEBUG_INFO
, " Name - %s\n", PcdVariable
+ 1));
371 // For Pcd ValidData header align.
373 PcdValidData
= (VAR_CHECK_PCD_VALID_DATA_HEADER
*)HEADER_ALIGN (((UINTN
)PcdVariable
+ PcdVariable
->HeaderLength
));
374 while ((UINTN
)PcdValidData
< ((UINTN
)PcdVariable
+ PcdVariable
->Length
)) {
376 // Dump Pcd ValidData related to the Pcd Variable.
378 DumpPcdValidData (PcdValidData
);
380 // For Pcd ValidData header align.
382 PcdValidData
= (VAR_CHECK_PCD_VALID_DATA_HEADER
*)HEADER_ALIGN (((UINTN
)PcdValidData
+ PcdValidData
->Length
));
389 @param[in] VarCheckPcdBin Pointer to VarCheckPcdBin.
390 @param[in] VarCheckPcdBinSize VarCheckPcdBin size.
395 IN VOID
*VarCheckPcdBin
,
396 IN UINTN VarCheckPcdBinSize
399 VAR_CHECK_PCD_VARIABLE_HEADER
*PcdVariable
;
401 DEBUG ((DEBUG_INFO
, "DumpVarCheckPcd\n"));
404 // For Pcd Variable header align.
406 PcdVariable
= (VAR_CHECK_PCD_VARIABLE_HEADER
*)HEADER_ALIGN (VarCheckPcdBin
);
407 while ((UINTN
)PcdVariable
< ((UINTN
)VarCheckPcdBin
+ VarCheckPcdBinSize
)) {
408 DumpPcdVariable (PcdVariable
);
410 // For Pcd Variable header align.
412 PcdVariable
= (VAR_CHECK_PCD_VARIABLE_HEADER
*)HEADER_ALIGN (((UINTN
)PcdVariable
+ PcdVariable
->Length
));
419 Locate VarCheckPcdBin.
424 LocateVarCheckPcdBin (
429 VAR_CHECK_PCD_VARIABLE_HEADER
*VarCheckPcdBin
;
430 UINTN VarCheckPcdBinSize
;
433 // Search the VarCheckPcdBin from the first RAW section of current FFS.
435 Status
= GetSectionFromFfs (
438 (VOID
**)&VarCheckPcdBin
,
441 if (!EFI_ERROR (Status
)) {
443 // AllocateRuntimeZeroPool () from MemoryAllocateLib is used for runtime access
444 // in SetVariable check handler.
446 mVarCheckPcdBin
= AllocateRuntimeCopyPool (VarCheckPcdBinSize
, VarCheckPcdBin
);
447 ASSERT (mVarCheckPcdBin
!= NULL
);
449 // Make sure the allocated buffer for VarCheckPcdBin at required alignment.
451 ASSERT ((((UINTN
)mVarCheckPcdBin
) & (HEADER_ALIGNMENT
- 1)) == 0);
452 mVarCheckPcdBinSize
= VarCheckPcdBinSize
;
453 FreePool (VarCheckPcdBin
);
455 DEBUG ((DEBUG_INFO
, "VarCheckPcdBin - at 0x%x size = 0x%x\n", mVarCheckPcdBin
, mVarCheckPcdBinSize
));
457 #ifdef DUMP_VAR_CHECK_PCD
459 DumpVarCheckPcd (mVarCheckPcdBin
, mVarCheckPcdBinSize
);
463 DEBUG ((DEBUG_INFO
, "[VarCheckPcd] No VarCheckPcdBin found at the first RAW section\n"));
468 Constructor function of VarCheckPcdLib to register var check PCD handler.
470 @param[in] ImageHandle The firmware allocated handle for the EFI image.
471 @param[in] SystemTable A pointer to the EFI System Table.
473 @retval EFI_SUCCESS The constructor executed correctly.
478 VarCheckPcdLibNullClassConstructor (
479 IN EFI_HANDLE ImageHandle
,
480 IN EFI_SYSTEM_TABLE
*SystemTable
483 LocateVarCheckPcdBin ();
484 VarCheckLibRegisterAddressPointer ((VOID
**)&mVarCheckPcdBin
);
485 VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerPcd
);