]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLibNullClass.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Library / VarCheckPcdLib / VarCheckPcdLibNullClass.c
1 /** @file
2 Var Check PCD handler.
3
4 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
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>
15
16 #include "VarCheckPcdStructure.h"
17
18 //#define DUMP_VAR_CHECK_PCD
19
20 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mVarCheckPcdHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
21
22 /**
23 Dump some hexadecimal data.
24
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.
29
30 **/
31 VOID
32 VarCheckPcdInternalDumpHex (
33 IN UINTN Indent,
34 IN UINTN Offset,
35 IN UINTN DataSize,
36 IN VOID *UserData
37 )
38 {
39 UINT8 *Data;
40
41 CHAR8 Val[50];
42
43 CHAR8 Str[20];
44
45 UINT8 TempByte;
46 UINTN Size;
47 UINTN Index;
48
49 Data = UserData;
50 while (DataSize != 0) {
51 Size = 16;
52 if (Size > DataSize) {
53 Size = DataSize;
54 }
55
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);
62 }
63
64 Val[Index * 3] = 0;
65 Str[Index] = 0;
66 DEBUG ((EFI_D_INFO, "%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str));
67
68 Data += Size;
69 Offset += Size;
70 DataSize -= Size;
71 }
72 }
73
74 /**
75 Var Check Pcd ValidData.
76
77 @param[in] PcdValidData Pointer to Pcd ValidData
78 @param[in] Data Data pointer.
79 @param[in] DataSize Size of Data to set.
80
81 @retval TRUE Check pass
82 @retval FALSE Check fail.
83
84 **/
85 BOOLEAN
86 VarCheckPcdValidData (
87 IN VAR_CHECK_PCD_VALID_DATA_HEADER *PcdValidData,
88 IN VOID *Data,
89 IN UINTN DataSize
90 )
91 {
92 UINT64 OneData;
93 UINT64 Minimum;
94 UINT64 Maximum;
95 UINT64 OneValue;
96 UINT8 *Ptr;
97
98 OneData = 0;
99 CopyMem (&OneData, (UINT8 *) Data + PcdValidData->VarOffset, PcdValidData->StorageWidth);
100
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) {
105 OneValue = 0;
106 CopyMem (&OneValue, Ptr, PcdValidData->StorageWidth);
107 if (OneData == OneValue) {
108 //
109 // Match
110 //
111 break;
112 }
113 Ptr += PcdValidData->StorageWidth;
114 }
115 if ((UINTN) Ptr >= ((UINTN) PcdValidData + PcdValidData->Length)) {
116 //
117 // No match
118 //
119 DEBUG ((EFI_D_INFO, "VarCheckPcdValidData fail: ValidList mismatch (0x%lx)\n", OneData));
120 DEBUG_CODE (VarCheckPcdInternalDumpHex (2, 0, PcdValidData->Length, (UINT8 *) PcdValidData););
121 return FALSE;
122 }
123 break;
124
125 case VarCheckPcdValidRange:
126 Minimum = 0;
127 Maximum = 0;
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;
134
135 if ((OneData >= Minimum) && (OneData <= Maximum)) {
136 return TRUE;
137 }
138 }
139 DEBUG ((EFI_D_INFO, "VarCheckPcdValidData fail: ValidRange mismatch (0x%lx)\n", OneData));
140 DEBUG_CODE (VarCheckPcdInternalDumpHex (2, 0, PcdValidData->Length, (UINT8 *) PcdValidData););
141 return FALSE;
142 break;
143
144 default:
145 ASSERT (FALSE);
146 break;
147 }
148
149 return TRUE;
150 }
151
152 VAR_CHECK_PCD_VARIABLE_HEADER *mVarCheckPcdBin = NULL;
153 UINTN mVarCheckPcdBinSize = 0;
154
155 /**
156 SetVariable check handler PCD.
157
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.
163
164 @retval EFI_SUCCESS The SetVariable check result was success.
165 @retval EFI_SECURITY_VIOLATION Check fail.
166
167 **/
168 EFI_STATUS
169 EFIAPI
170 SetVariableCheckHandlerPcd (
171 IN CHAR16 *VariableName,
172 IN EFI_GUID *VendorGuid,
173 IN UINT32 Attributes,
174 IN UINTN DataSize,
175 IN VOID *Data
176 )
177 {
178 VAR_CHECK_PCD_VARIABLE_HEADER *PcdVariable;
179 VAR_CHECK_PCD_VALID_DATA_HEADER *PcdValidData;
180
181 if (mVarCheckPcdBin == NULL) {
182 return EFI_SUCCESS;
183 }
184
185 if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0)) {
186 //
187 // Do not check delete variable.
188 //
189 return EFI_SUCCESS;
190 }
191
192 //
193 // For Pcd Variable header align.
194 //
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))) {
199 //
200 // Found the Pcd Variable that could be used to do check.
201 //
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;
206 }
207
208 if (DataSize == 0) {
209 DEBUG ((EFI_D_INFO, "VarCheckPcdVariable - CHECK PASS with DataSize == 0 !\n"));
210 return EFI_SUCCESS;
211 }
212
213 //
214 // Do the check.
215 // For Pcd ValidData header align.
216 //
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;
222 }
223 }
224 //
225 // For Pcd ValidData header align.
226 //
227 PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *) HEADER_ALIGN (((UINTN) PcdValidData + PcdValidData->Length));
228 }
229
230 DEBUG ((EFI_D_INFO, "VarCheckPcdVariable - ALL CHECK PASS!\n"));
231 return EFI_SUCCESS;
232 }
233 //
234 // For Pcd Variable header align.
235 //
236 PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *) HEADER_ALIGN (((UINTN) PcdVariable + PcdVariable->Length));
237 }
238
239 // Not found, so pass.
240 return EFI_SUCCESS;
241 }
242
243 #ifdef DUMP_VAR_CHECK_PCD
244 /**
245 Dump Pcd ValidData.
246
247 @param[in] PcdValidData Pointer to Pcd ValidData.
248
249 **/
250 VOID
251 DumpPcdValidData (
252 IN VAR_CHECK_PCD_VALID_DATA_HEADER *PcdValidData
253 )
254 {
255 UINT64 Minimum;
256 UINT64 Maximum;
257 UINT64 OneValue;
258 UINT8 *Ptr;
259
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));
265
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)) {
270 OneValue = 0;
271 CopyMem (&OneValue, Ptr, PcdValidData->StorageWidth);
272 switch (PcdValidData->StorageWidth) {
273 case sizeof (UINT8):
274 DEBUG ((EFI_D_INFO, " ValidList - 0x%02x\n", OneValue));
275 break;
276 case sizeof (UINT16):
277 DEBUG ((EFI_D_INFO, " ValidList - 0x%04x\n", OneValue));
278 break;
279 case sizeof (UINT32):
280 DEBUG ((EFI_D_INFO, " ValidList - 0x%08x\n", OneValue));
281 break;
282 case sizeof (UINT64):
283 DEBUG ((EFI_D_INFO, " ValidList - 0x%016lx\n", OneValue));
284 break;
285 default:
286 ASSERT (FALSE);
287 break;
288 }
289 Ptr += PcdValidData->StorageWidth;
290 }
291 break;
292
293 case VarCheckPcdValidRange:
294 Minimum = 0;
295 Maximum = 0;
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;
302
303 switch (PcdValidData->StorageWidth) {
304 case sizeof (UINT8):
305 DEBUG ((EFI_D_INFO, " Minimum - 0x%02x\n", Minimum));
306 DEBUG ((EFI_D_INFO, " Maximum - 0x%02x\n", Maximum));
307 break;
308 case sizeof (UINT16):
309 DEBUG ((EFI_D_INFO, " Minimum - 0x%04x\n", Minimum));
310 DEBUG ((EFI_D_INFO, " Maximum - 0x%04x\n", Maximum));
311 break;
312 case sizeof (UINT32):
313 DEBUG ((EFI_D_INFO, " Minimum - 0x%08x\n", Minimum));
314 DEBUG ((EFI_D_INFO, " Maximum - 0x%08x\n", Maximum));
315 break;
316 case sizeof (UINT64):
317 DEBUG ((EFI_D_INFO, " Minimum - 0x%016lx\n", Minimum));
318 DEBUG ((EFI_D_INFO, " Maximum - 0x%016lx\n", Maximum));
319 break;
320 default:
321 ASSERT (FALSE);
322 break;
323 }
324 }
325 break;
326
327 default:
328 ASSERT (FALSE);
329 break;
330 }
331 }
332
333 /**
334 Dump Pcd Variable.
335
336 @param[in] PcdVariable Pointer to Pcd Variable.
337
338 **/
339 VOID
340 DumpPcdVariable (
341 IN VAR_CHECK_PCD_VARIABLE_HEADER *PcdVariable
342 )
343 {
344 VAR_CHECK_PCD_VALID_DATA_HEADER *PcdValidData;
345
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));
354
355 //
356 // For Pcd ValidData header align.
357 //
358 PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *) HEADER_ALIGN (((UINTN) PcdVariable + PcdVariable->HeaderLength));
359 while ((UINTN) PcdValidData < ((UINTN) PcdVariable + PcdVariable->Length)) {
360 //
361 // Dump Pcd ValidData related to the Pcd Variable.
362 //
363 DumpPcdValidData (PcdValidData);
364 //
365 // For Pcd ValidData header align.
366 //
367 PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *) HEADER_ALIGN (((UINTN) PcdValidData + PcdValidData->Length));
368 }
369 }
370
371 /**
372 Dump Var Check PCD.
373
374 @param[in] VarCheckPcdBin Pointer to VarCheckPcdBin.
375 @param[in] VarCheckPcdBinSize VarCheckPcdBin size.
376
377 **/
378 VOID
379 DumpVarCheckPcd (
380 IN VOID *VarCheckPcdBin,
381 IN UINTN VarCheckPcdBinSize
382 )
383 {
384 VAR_CHECK_PCD_VARIABLE_HEADER *PcdVariable;
385
386 DEBUG ((EFI_D_INFO, "DumpVarCheckPcd\n"));
387
388 //
389 // For Pcd Variable header align.
390 //
391 PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *) HEADER_ALIGN (VarCheckPcdBin);
392 while ((UINTN) PcdVariable < ((UINTN) VarCheckPcdBin + VarCheckPcdBinSize)) {
393 DumpPcdVariable (PcdVariable);
394 //
395 // For Pcd Variable header align.
396 //
397 PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *) HEADER_ALIGN (((UINTN) PcdVariable + PcdVariable->Length));
398 }
399 }
400 #endif
401
402 /**
403 Locate VarCheckPcdBin.
404
405 **/
406 VOID
407 EFIAPI
408 LocateVarCheckPcdBin (
409 VOID
410 )
411 {
412 EFI_STATUS Status;
413 VAR_CHECK_PCD_VARIABLE_HEADER *VarCheckPcdBin;
414 UINTN VarCheckPcdBinSize;
415
416 //
417 // Search the VarCheckPcdBin from the first RAW section of current FFS.
418 //
419 Status = GetSectionFromFfs (
420 EFI_SECTION_RAW,
421 0,
422 (VOID **) &VarCheckPcdBin,
423 &VarCheckPcdBinSize
424 );
425 if (!EFI_ERROR (Status)) {
426 //
427 // AllocateRuntimeZeroPool () from MemoryAllocateLib is used for runtime access
428 // in SetVariable check handler.
429 //
430 mVarCheckPcdBin = AllocateRuntimeCopyPool (VarCheckPcdBinSize, VarCheckPcdBin);
431 ASSERT (mVarCheckPcdBin != NULL);
432 //
433 // Make sure the allocated buffer for VarCheckPcdBin at required alignment.
434 //
435 ASSERT ((((UINTN) mVarCheckPcdBin) & (HEADER_ALIGNMENT - 1)) == 0);
436 mVarCheckPcdBinSize = VarCheckPcdBinSize;
437 FreePool (VarCheckPcdBin);
438
439 DEBUG ((EFI_D_INFO, "VarCheckPcdBin - at 0x%x size = 0x%x\n", mVarCheckPcdBin, mVarCheckPcdBinSize));
440
441 #ifdef DUMP_VAR_CHECK_PCD
442 DEBUG_CODE (
443 DumpVarCheckPcd (mVarCheckPcdBin, mVarCheckPcdBinSize);
444 );
445 #endif
446 } else {
447 DEBUG ((EFI_D_INFO, "[VarCheckPcd] No VarCheckPcdBin found at the first RAW section\n"));
448 }
449 }
450
451 /**
452 Constructor function of VarCheckPcdLib to register var check PCD handler.
453
454 @param[in] ImageHandle The firmware allocated handle for the EFI image.
455 @param[in] SystemTable A pointer to the EFI System Table.
456
457 @retval EFI_SUCCESS The constructor executed correctly.
458
459 **/
460 EFI_STATUS
461 EFIAPI
462 VarCheckPcdLibNullClassConstructor (
463 IN EFI_HANDLE ImageHandle,
464 IN EFI_SYSTEM_TABLE *SystemTable
465 )
466 {
467 LocateVarCheckPcdBin ();
468 VarCheckLibRegisterAddressPointer ((VOID **) &mVarCheckPcdBin);
469 VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerPcd);
470
471 return EFI_SUCCESS;
472 }