]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLibNullClass.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 ((DEBUG_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
114 Ptr += PcdValidData->StorageWidth;
115 }
116
117 if ((UINTN)Ptr >= ((UINTN)PcdValidData + PcdValidData->Length)) {
118 //
119 // No match
120 //
121 DEBUG ((DEBUG_INFO, "VarCheckPcdValidData fail: ValidList mismatch (0x%lx)\n", OneData));
122 DEBUG_CODE (
123 VarCheckPcdInternalDumpHex (2, 0, PcdValidData->Length, (UINT8 *)PcdValidData);
124 );
125 return FALSE;
126 }
127
128 break;
129
130 case VarCheckPcdValidRange:
131 Minimum = 0;
132 Maximum = 0;
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;
139
140 if ((OneData >= Minimum) && (OneData <= Maximum)) {
141 return TRUE;
142 }
143 }
144
145 DEBUG ((DEBUG_INFO, "VarCheckPcdValidData fail: ValidRange mismatch (0x%lx)\n", OneData));
146 DEBUG_CODE (
147 VarCheckPcdInternalDumpHex (2, 0, PcdValidData->Length, (UINT8 *)PcdValidData);
148 );
149 return FALSE;
150 break;
151
152 default:
153 ASSERT (FALSE);
154 break;
155 }
156
157 return TRUE;
158 }
159
160 VAR_CHECK_PCD_VARIABLE_HEADER *mVarCheckPcdBin = NULL;
161 UINTN mVarCheckPcdBinSize = 0;
162
163 /**
164 SetVariable check handler PCD.
165
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.
171
172 @retval EFI_SUCCESS The SetVariable check result was success.
173 @retval EFI_SECURITY_VIOLATION Check fail.
174
175 **/
176 EFI_STATUS
177 EFIAPI
178 SetVariableCheckHandlerPcd (
179 IN CHAR16 *VariableName,
180 IN EFI_GUID *VendorGuid,
181 IN UINT32 Attributes,
182 IN UINTN DataSize,
183 IN VOID *Data
184 )
185 {
186 VAR_CHECK_PCD_VARIABLE_HEADER *PcdVariable;
187 VAR_CHECK_PCD_VALID_DATA_HEADER *PcdValidData;
188
189 if (mVarCheckPcdBin == NULL) {
190 return EFI_SUCCESS;
191 }
192
193 if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0)) {
194 //
195 // Do not check delete variable.
196 //
197 return EFI_SUCCESS;
198 }
199
200 //
201 // For Pcd Variable header align.
202 //
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)))
207 {
208 //
209 // Found the Pcd Variable that could be used to do check.
210 //
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;
215 }
216
217 if (DataSize == 0) {
218 DEBUG ((DEBUG_INFO, "VarCheckPcdVariable - CHECK PASS with DataSize == 0 !\n"));
219 return EFI_SUCCESS;
220 }
221
222 //
223 // Do the check.
224 // For Pcd ValidData header align.
225 //
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;
231 }
232 }
233
234 //
235 // For Pcd ValidData header align.
236 //
237 PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *)HEADER_ALIGN (((UINTN)PcdValidData + PcdValidData->Length));
238 }
239
240 DEBUG ((DEBUG_INFO, "VarCheckPcdVariable - ALL CHECK PASS!\n"));
241 return EFI_SUCCESS;
242 }
243
244 //
245 // For Pcd Variable header align.
246 //
247 PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *)HEADER_ALIGN (((UINTN)PcdVariable + PcdVariable->Length));
248 }
249
250 // Not found, so pass.
251 return EFI_SUCCESS;
252 }
253
254 #ifdef DUMP_VAR_CHECK_PCD
255
256 /**
257 Dump Pcd ValidData.
258
259 @param[in] PcdValidData Pointer to Pcd ValidData.
260
261 **/
262 VOID
263 DumpPcdValidData (
264 IN VAR_CHECK_PCD_VALID_DATA_HEADER *PcdValidData
265 )
266 {
267 UINT64 Minimum;
268 UINT64 Maximum;
269 UINT64 OneValue;
270 UINT8 *Ptr;
271
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));
277
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)) {
282 OneValue = 0;
283 CopyMem (&OneValue, Ptr, PcdValidData->StorageWidth);
284 switch (PcdValidData->StorageWidth) {
285 case sizeof (UINT8):
286 DEBUG ((DEBUG_INFO, " ValidList - 0x%02x\n", OneValue));
287 break;
288 case sizeof (UINT16):
289 DEBUG ((DEBUG_INFO, " ValidList - 0x%04x\n", OneValue));
290 break;
291 case sizeof (UINT32):
292 DEBUG ((DEBUG_INFO, " ValidList - 0x%08x\n", OneValue));
293 break;
294 case sizeof (UINT64):
295 DEBUG ((DEBUG_INFO, " ValidList - 0x%016lx\n", OneValue));
296 break;
297 default:
298 ASSERT (FALSE);
299 break;
300 }
301
302 Ptr += PcdValidData->StorageWidth;
303 }
304
305 break;
306
307 case VarCheckPcdValidRange:
308 Minimum = 0;
309 Maximum = 0;
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;
316
317 switch (PcdValidData->StorageWidth) {
318 case sizeof (UINT8):
319 DEBUG ((DEBUG_INFO, " Minimum - 0x%02x\n", Minimum));
320 DEBUG ((DEBUG_INFO, " Maximum - 0x%02x\n", Maximum));
321 break;
322 case sizeof (UINT16):
323 DEBUG ((DEBUG_INFO, " Minimum - 0x%04x\n", Minimum));
324 DEBUG ((DEBUG_INFO, " Maximum - 0x%04x\n", Maximum));
325 break;
326 case sizeof (UINT32):
327 DEBUG ((DEBUG_INFO, " Minimum - 0x%08x\n", Minimum));
328 DEBUG ((DEBUG_INFO, " Maximum - 0x%08x\n", Maximum));
329 break;
330 case sizeof (UINT64):
331 DEBUG ((DEBUG_INFO, " Minimum - 0x%016lx\n", Minimum));
332 DEBUG ((DEBUG_INFO, " Maximum - 0x%016lx\n", Maximum));
333 break;
334 default:
335 ASSERT (FALSE);
336 break;
337 }
338 }
339
340 break;
341
342 default:
343 ASSERT (FALSE);
344 break;
345 }
346 }
347
348 /**
349 Dump Pcd Variable.
350
351 @param[in] PcdVariable Pointer to Pcd Variable.
352
353 **/
354 VOID
355 DumpPcdVariable (
356 IN VAR_CHECK_PCD_VARIABLE_HEADER *PcdVariable
357 )
358 {
359 VAR_CHECK_PCD_VALID_DATA_HEADER *PcdValidData;
360
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));
369
370 //
371 // For Pcd ValidData header align.
372 //
373 PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *)HEADER_ALIGN (((UINTN)PcdVariable + PcdVariable->HeaderLength));
374 while ((UINTN)PcdValidData < ((UINTN)PcdVariable + PcdVariable->Length)) {
375 //
376 // Dump Pcd ValidData related to the Pcd Variable.
377 //
378 DumpPcdValidData (PcdValidData);
379 //
380 // For Pcd ValidData header align.
381 //
382 PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *)HEADER_ALIGN (((UINTN)PcdValidData + PcdValidData->Length));
383 }
384 }
385
386 /**
387 Dump Var Check PCD.
388
389 @param[in] VarCheckPcdBin Pointer to VarCheckPcdBin.
390 @param[in] VarCheckPcdBinSize VarCheckPcdBin size.
391
392 **/
393 VOID
394 DumpVarCheckPcd (
395 IN VOID *VarCheckPcdBin,
396 IN UINTN VarCheckPcdBinSize
397 )
398 {
399 VAR_CHECK_PCD_VARIABLE_HEADER *PcdVariable;
400
401 DEBUG ((DEBUG_INFO, "DumpVarCheckPcd\n"));
402
403 //
404 // For Pcd Variable header align.
405 //
406 PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *)HEADER_ALIGN (VarCheckPcdBin);
407 while ((UINTN)PcdVariable < ((UINTN)VarCheckPcdBin + VarCheckPcdBinSize)) {
408 DumpPcdVariable (PcdVariable);
409 //
410 // For Pcd Variable header align.
411 //
412 PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *)HEADER_ALIGN (((UINTN)PcdVariable + PcdVariable->Length));
413 }
414 }
415
416 #endif
417
418 /**
419 Locate VarCheckPcdBin.
420
421 **/
422 VOID
423 EFIAPI
424 LocateVarCheckPcdBin (
425 VOID
426 )
427 {
428 EFI_STATUS Status;
429 VAR_CHECK_PCD_VARIABLE_HEADER *VarCheckPcdBin;
430 UINTN VarCheckPcdBinSize;
431
432 //
433 // Search the VarCheckPcdBin from the first RAW section of current FFS.
434 //
435 Status = GetSectionFromFfs (
436 EFI_SECTION_RAW,
437 0,
438 (VOID **)&VarCheckPcdBin,
439 &VarCheckPcdBinSize
440 );
441 if (!EFI_ERROR (Status)) {
442 //
443 // AllocateRuntimeZeroPool () from MemoryAllocateLib is used for runtime access
444 // in SetVariable check handler.
445 //
446 mVarCheckPcdBin = AllocateRuntimeCopyPool (VarCheckPcdBinSize, VarCheckPcdBin);
447 ASSERT (mVarCheckPcdBin != NULL);
448 //
449 // Make sure the allocated buffer for VarCheckPcdBin at required alignment.
450 //
451 ASSERT ((((UINTN)mVarCheckPcdBin) & (HEADER_ALIGNMENT - 1)) == 0);
452 mVarCheckPcdBinSize = VarCheckPcdBinSize;
453 FreePool (VarCheckPcdBin);
454
455 DEBUG ((DEBUG_INFO, "VarCheckPcdBin - at 0x%x size = 0x%x\n", mVarCheckPcdBin, mVarCheckPcdBinSize));
456
457 #ifdef DUMP_VAR_CHECK_PCD
458 DEBUG_CODE (
459 DumpVarCheckPcd (mVarCheckPcdBin, mVarCheckPcdBinSize);
460 );
461 #endif
462 } else {
463 DEBUG ((DEBUG_INFO, "[VarCheckPcd] No VarCheckPcdBin found at the first RAW section\n"));
464 }
465 }
466
467 /**
468 Constructor function of VarCheckPcdLib to register var check PCD handler.
469
470 @param[in] ImageHandle The firmware allocated handle for the EFI image.
471 @param[in] SystemTable A pointer to the EFI System Table.
472
473 @retval EFI_SUCCESS The constructor executed correctly.
474
475 **/
476 EFI_STATUS
477 EFIAPI
478 VarCheckPcdLibNullClassConstructor (
479 IN EFI_HANDLE ImageHandle,
480 IN EFI_SYSTEM_TABLE *SystemTable
481 )
482 {
483 LocateVarCheckPcdBin ();
484 VarCheckLibRegisterAddressPointer ((VOID **)&mVarCheckPcdBin);
485 VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerPcd);
486
487 return EFI_SUCCESS;
488 }