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 <Library/VarCheckLib.h>
16 #include <Library/BaseLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include <Library/DxeServicesLib.h>
22 #include "VarCheckPcdStructure.h"
24 //#define DUMP_VAR_CHECK_PCD
26 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mVarCheckPcdHex
[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
29 Dump some hexadecimal data.
31 @param[in] Indent How many spaces to indent the output.
32 @param[in] Offset The offset of the dump.
33 @param[in] DataSize The size in bytes of UserData.
34 @param[in] UserData The data to dump.
38 VarCheckPcdInternalDumpHex (
56 while (DataSize
!= 0) {
58 if (Size
> DataSize
) {
62 for (Index
= 0; Index
< Size
; Index
+= 1) {
63 TempByte
= Data
[Index
];
64 Val
[Index
* 3 + 0] = mVarCheckPcdHex
[TempByte
>> 4];
65 Val
[Index
* 3 + 1] = mVarCheckPcdHex
[TempByte
& 0xF];
66 Val
[Index
* 3 + 2] = (CHAR8
) ((Index
== 7) ? '-' : ' ');
67 Str
[Index
] = (CHAR8
) ((TempByte
< ' ' || TempByte
> 'z') ? '.' : TempByte
);
72 DEBUG ((EFI_D_INFO
, "%*a%08X: %-48a *%a*\r\n", Indent
, "", Offset
, Val
, Str
));
81 Var Check Pcd ValidData.
83 @param[in] PcdValidData Pointer to Pcd ValidData
84 @param[in] Data Data pointer.
85 @param[in] DataSize Size of Data to set.
87 @retval TRUE Check pass
88 @retval FALSE Check fail.
92 VarCheckPcdValidData (
93 IN VAR_CHECK_PCD_VALID_DATA_HEADER
*PcdValidData
,
105 CopyMem (&OneData
, (UINT8
*) Data
+ PcdValidData
->VarOffset
, PcdValidData
->StorageWidth
);
107 switch (PcdValidData
->Type
) {
108 case VarCheckPcdValidList
:
109 Ptr
= (UINT8
*) ((VAR_CHECK_PCD_VALID_LIST
*) PcdValidData
+ 1);
110 while ((UINTN
) Ptr
< (UINTN
) PcdValidData
+ PcdValidData
->Length
) {
112 CopyMem (&OneValue
, Ptr
, PcdValidData
->StorageWidth
);
113 if (OneData
== OneValue
) {
119 Ptr
+= PcdValidData
->StorageWidth
;
121 if ((UINTN
) Ptr
>= ((UINTN
) PcdValidData
+ PcdValidData
->Length
)) {
125 DEBUG ((EFI_D_INFO
, "VarCheckPcdValidData fail: ValidList mismatch (0x%lx)\n", OneData
));
126 DEBUG_CODE (VarCheckPcdInternalDumpHex (2, 0, PcdValidData
->Length
, (UINT8
*) PcdValidData
););
131 case VarCheckPcdValidRange
:
134 Ptr
= (UINT8
*) ((VAR_CHECK_PCD_VALID_RANGE
*) PcdValidData
+ 1);
135 while ((UINTN
) Ptr
< (UINTN
) PcdValidData
+ PcdValidData
->Length
) {
136 CopyMem (&Minimum
, Ptr
, PcdValidData
->StorageWidth
);
137 Ptr
+= PcdValidData
->StorageWidth
;
138 CopyMem (&Maximum
, Ptr
, PcdValidData
->StorageWidth
);
139 Ptr
+= PcdValidData
->StorageWidth
;
141 if ((OneData
>= Minimum
) && (OneData
<= Maximum
)) {
145 DEBUG ((EFI_D_INFO
, "VarCheckPcdValidData fail: ValidRange mismatch (0x%lx)\n", OneData
));
146 DEBUG_CODE (VarCheckPcdInternalDumpHex (2, 0, PcdValidData
->Length
, (UINT8
*) PcdValidData
););
158 VAR_CHECK_PCD_VARIABLE_HEADER
*mVarCheckPcdBin
= NULL
;
159 UINTN mVarCheckPcdBinSize
= 0;
162 SetVariable check handler PCD.
164 @param[in] VariableName Name of Variable to set.
165 @param[in] VendorGuid Variable vendor GUID.
166 @param[in] Attributes Attribute value of the variable.
167 @param[in] DataSize Size of Data to set.
168 @param[in] Data Data pointer.
170 @retval EFI_SUCCESS The SetVariable check result was success.
171 @retval EFI_SECURITY_VIOLATION Check fail.
176 SetVariableCheckHandlerPcd (
177 IN CHAR16
*VariableName
,
178 IN EFI_GUID
*VendorGuid
,
179 IN UINT32 Attributes
,
184 VAR_CHECK_PCD_VARIABLE_HEADER
*PcdVariable
;
185 VAR_CHECK_PCD_VALID_DATA_HEADER
*PcdValidData
;
187 if (mVarCheckPcdBin
== NULL
) {
191 if ((((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0) && (DataSize
== 0)) || (Attributes
== 0)) {
193 // Do not check delete variable.
199 // For Pcd Variable header align.
201 PcdVariable
= (VAR_CHECK_PCD_VARIABLE_HEADER
*) HEADER_ALIGN (mVarCheckPcdBin
);
202 while ((UINTN
) PcdVariable
< ((UINTN
) mVarCheckPcdBin
+ mVarCheckPcdBinSize
)) {
203 if ((StrCmp ((CHAR16
*) (PcdVariable
+ 1), VariableName
) == 0) &&
204 (CompareGuid (&PcdVariable
->Guid
, VendorGuid
))) {
206 // Found the Pcd Variable that could be used to do check.
208 DEBUG ((EFI_D_INFO
, "VarCheckPcdVariable - %s:%g with Attributes = 0x%08x Size = 0x%x\n", VariableName
, VendorGuid
, Attributes
, DataSize
));
209 if ((PcdVariable
->Attributes
!= 0) && PcdVariable
->Attributes
!= Attributes
) {
210 DEBUG ((EFI_D_INFO
, "VarCheckPcdVariable fail for Attributes - 0x%08x\n", PcdVariable
->Attributes
));
211 return EFI_SECURITY_VIOLATION
;
215 DEBUG ((EFI_D_INFO
, "VarCheckPcdVariable - CHECK PASS with DataSize == 0 !\n"));
221 // For Pcd ValidData header align.
223 PcdValidData
= (VAR_CHECK_PCD_VALID_DATA_HEADER
*) HEADER_ALIGN (((UINTN
) PcdVariable
+ PcdVariable
->HeaderLength
));
224 while ((UINTN
) PcdValidData
< ((UINTN
) PcdVariable
+ PcdVariable
->Length
)) {
225 if (((UINTN
) PcdValidData
->VarOffset
+ PcdValidData
->StorageWidth
) <= DataSize
) {
226 if (!VarCheckPcdValidData (PcdValidData
, Data
, DataSize
)) {
227 return EFI_SECURITY_VIOLATION
;
231 // For Pcd ValidData header align.
233 PcdValidData
= (VAR_CHECK_PCD_VALID_DATA_HEADER
*) HEADER_ALIGN (((UINTN
) PcdValidData
+ PcdValidData
->Length
));
236 DEBUG ((EFI_D_INFO
, "VarCheckPcdVariable - ALL CHECK PASS!\n"));
240 // For Pcd Variable header align.
242 PcdVariable
= (VAR_CHECK_PCD_VARIABLE_HEADER
*) HEADER_ALIGN (((UINTN
) PcdVariable
+ PcdVariable
->Length
));
245 // Not found, so pass.
249 #ifdef DUMP_VAR_CHECK_PCD
253 @param[in] PcdValidData Pointer to Pcd ValidData.
258 IN VAR_CHECK_PCD_VALID_DATA_HEADER
*PcdValidData
266 DEBUG ((EFI_D_INFO
, " VAR_CHECK_PCD_VALID_DATA_HEADER\n"));
267 DEBUG ((EFI_D_INFO
, " Type - 0x%02x\n", PcdValidData
->Type
));
268 DEBUG ((EFI_D_INFO
, " Length - 0x%02x\n", PcdValidData
->Length
));
269 DEBUG ((EFI_D_INFO
, " VarOffset - 0x%04x\n", PcdValidData
->VarOffset
));
270 DEBUG ((EFI_D_INFO
, " StorageWidth - 0x%02x\n", PcdValidData
->StorageWidth
));
272 switch (PcdValidData
->Type
) {
273 case VarCheckPcdValidList
:
274 Ptr
= (UINT8
*) ((VAR_CHECK_PCD_VALID_LIST
*) PcdValidData
+ 1);
275 while ((UINTN
) Ptr
< ((UINTN
) PcdValidData
+ PcdValidData
->Length
)) {
277 CopyMem (&OneValue
, Ptr
, PcdValidData
->StorageWidth
);
278 switch (PcdValidData
->StorageWidth
) {
280 DEBUG ((EFI_D_INFO
, " ValidList - 0x%02x\n", OneValue
));
282 case sizeof (UINT16
):
283 DEBUG ((EFI_D_INFO
, " ValidList - 0x%04x\n", OneValue
));
285 case sizeof (UINT32
):
286 DEBUG ((EFI_D_INFO
, " ValidList - 0x%08x\n", OneValue
));
288 case sizeof (UINT64
):
289 DEBUG ((EFI_D_INFO
, " ValidList - 0x%016lx\n", OneValue
));
295 Ptr
+= PcdValidData
->StorageWidth
;
299 case VarCheckPcdValidRange
:
302 Ptr
= (UINT8
*) ((VAR_CHECK_PCD_VALID_RANGE
*) PcdValidData
+ 1);
303 while ((UINTN
) Ptr
< (UINTN
) PcdValidData
+ PcdValidData
->Length
) {
304 CopyMem (&Minimum
, Ptr
, PcdValidData
->StorageWidth
);
305 Ptr
+= PcdValidData
->StorageWidth
;
306 CopyMem (&Maximum
, Ptr
, PcdValidData
->StorageWidth
);
307 Ptr
+= PcdValidData
->StorageWidth
;
309 switch (PcdValidData
->StorageWidth
) {
311 DEBUG ((EFI_D_INFO
, " Minimum - 0x%02x\n", Minimum
));
312 DEBUG ((EFI_D_INFO
, " Maximum - 0x%02x\n", Maximum
));
314 case sizeof (UINT16
):
315 DEBUG ((EFI_D_INFO
, " Minimum - 0x%04x\n", Minimum
));
316 DEBUG ((EFI_D_INFO
, " Maximum - 0x%04x\n", Maximum
));
318 case sizeof (UINT32
):
319 DEBUG ((EFI_D_INFO
, " Minimum - 0x%08x\n", Minimum
));
320 DEBUG ((EFI_D_INFO
, " Maximum - 0x%08x\n", Maximum
));
322 case sizeof (UINT64
):
323 DEBUG ((EFI_D_INFO
, " Minimum - 0x%016lx\n", Minimum
));
324 DEBUG ((EFI_D_INFO
, " Maximum - 0x%016lx\n", Maximum
));
342 @param[in] PcdVariable Pointer to Pcd Variable.
347 IN VAR_CHECK_PCD_VARIABLE_HEADER
*PcdVariable
350 VAR_CHECK_PCD_VALID_DATA_HEADER
*PcdValidData
;
352 DEBUG ((EFI_D_INFO
, "VAR_CHECK_PCD_VARIABLE_HEADER\n"));
353 DEBUG ((EFI_D_INFO
, " Revision - 0x%04x\n", PcdVariable
->Revision
));
354 DEBUG ((EFI_D_INFO
, " HeaderLength - 0x%04x\n", PcdVariable
->HeaderLength
));
355 DEBUG ((EFI_D_INFO
, " Length - 0x%08x\n", PcdVariable
->Length
));
356 DEBUG ((EFI_D_INFO
, " Type - 0x%02x\n", PcdVariable
->Type
));
357 DEBUG ((EFI_D_INFO
, " Attributes - 0x%08x\n", PcdVariable
->Attributes
));
358 DEBUG ((EFI_D_INFO
, " Guid - %g\n", &PcdVariable
->Guid
));
359 DEBUG ((EFI_D_INFO
, " Name - %s\n", PcdVariable
+ 1));
362 // For Pcd ValidData header align.
364 PcdValidData
= (VAR_CHECK_PCD_VALID_DATA_HEADER
*) HEADER_ALIGN (((UINTN
) PcdVariable
+ PcdVariable
->HeaderLength
));
365 while ((UINTN
) PcdValidData
< ((UINTN
) PcdVariable
+ PcdVariable
->Length
)) {
367 // Dump Pcd ValidData related to the Pcd Variable.
369 DumpPcdValidData (PcdValidData
);
371 // For Pcd ValidData header align.
373 PcdValidData
= (VAR_CHECK_PCD_VALID_DATA_HEADER
*) HEADER_ALIGN (((UINTN
) PcdValidData
+ PcdValidData
->Length
));
380 @param[in] VarCheckPcdBin Pointer to VarCheckPcdBin.
381 @param[in] VarCheckPcdBinSize VarCheckPcdBin size.
386 IN VOID
*VarCheckPcdBin
,
387 IN UINTN VarCheckPcdBinSize
390 VAR_CHECK_PCD_VARIABLE_HEADER
*PcdVariable
;
392 DEBUG ((EFI_D_INFO
, "DumpVarCheckPcd\n"));
395 // For Pcd Variable header align.
397 PcdVariable
= (VAR_CHECK_PCD_VARIABLE_HEADER
*) HEADER_ALIGN (VarCheckPcdBin
);
398 while ((UINTN
) PcdVariable
< ((UINTN
) VarCheckPcdBin
+ VarCheckPcdBinSize
)) {
399 DumpPcdVariable (PcdVariable
);
401 // For Pcd Variable header align.
403 PcdVariable
= (VAR_CHECK_PCD_VARIABLE_HEADER
*) HEADER_ALIGN (((UINTN
) PcdVariable
+ PcdVariable
->Length
));
409 Locate VarCheckPcdBin.
414 LocateVarCheckPcdBin (
419 VAR_CHECK_PCD_VARIABLE_HEADER
*VarCheckPcdBin
;
420 UINTN VarCheckPcdBinSize
;
423 // Search the VarCheckPcdBin from the first RAW section of current FFS.
425 Status
= GetSectionFromFfs (
428 (VOID
**) &VarCheckPcdBin
,
431 if (!EFI_ERROR (Status
)) {
433 // AllocateRuntimeZeroPool () from MemoryAllocateLib is used for runtime access
434 // in SetVariable check handler.
436 mVarCheckPcdBin
= AllocateRuntimeCopyPool (VarCheckPcdBinSize
, VarCheckPcdBin
);
437 ASSERT (mVarCheckPcdBin
!= NULL
);
438 mVarCheckPcdBinSize
= VarCheckPcdBinSize
;
439 FreePool (VarCheckPcdBin
);
441 DEBUG ((EFI_D_INFO
, "VarCheckPcdBin - at 0x%x size = 0x%x\n", mVarCheckPcdBin
, mVarCheckPcdBinSize
));
443 #ifdef DUMP_VAR_CHECK_PCD
445 DumpVarCheckPcd (mVarCheckPcdBin
, mVarCheckPcdBinSize
);
449 DEBUG ((EFI_D_INFO
, "[VarCheckPcd] No VarCheckPcdBin found at the first RAW section\n"));
454 Constructor function of VarCheckPcdLib to register var check PCD handler.
456 @param[in] ImageHandle The firmware allocated handle for the EFI image.
457 @param[in] SystemTable A pointer to the EFI System Table.
459 @retval EFI_SUCCESS The constructor executed correctly.
464 VarCheckPcdLibNullClassConstructor (
465 IN EFI_HANDLE ImageHandle
,
466 IN EFI_SYSTEM_TABLE
*SystemTable
469 LocateVarCheckPcdBin ();
470 VarCheckLibRegisterAddressPointer ((VOID
**) &mVarCheckPcdBin
);
471 VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerPcd
);