TianoCore EDK2 master
Loading...
Searching...
No Matches
VarCheckLib.c
Go to the documentation of this file.
1
10#include <Library/BaseLib.h>
12#include <Library/DebugLib.h>
14
15#include <Guid/GlobalVariable.h>
17
18BOOLEAN mVarCheckLibEndOfDxe = FALSE;
19
20#define VAR_CHECK_TABLE_SIZE 0x8
21
22UINTN mVarCheckLibEndOfDxeCallbackCount = 0;
23UINTN mVarCheckLibEndOfDxeCallbackMaxCount = 0;
24VAR_CHECK_END_OF_DXE_CALLBACK *mVarCheckLibEndOfDxeCallback = NULL;
25
26UINTN mVarCheckLibAddressPointerCount = 0;
27UINTN mVarCheckLibAddressPointerMaxCount = 0;
28VOID ***mVarCheckLibAddressPointer = NULL;
29
30UINTN mNumberOfVarCheckHandler = 0;
31UINTN mMaxNumberOfVarCheckHandler = 0;
32VAR_CHECK_SET_VARIABLE_CHECK_HANDLER *mVarCheckHandlerTable = NULL;
33
34typedef struct {
35 EFI_GUID Guid;
36 VAR_CHECK_VARIABLE_PROPERTY VariableProperty;
37 // CHAR16 *Name;
39
40UINTN mNumberOfVarCheckVariable = 0;
41UINTN mMaxNumberOfVarCheckVariable = 0;
42VARIABLE_ENTRY_PROPERTY **mVarCheckVariableTable = NULL;
43
44//
45// Handle variables with wildcard name specially.
46//
47VARIABLE_ENTRY_PROPERTY mVarCheckVariableWithWildcardName[] = {
48 {
49 &gEfiGlobalVariableGuid,
50 L"Boot####",
51 {
52 0
53 },
54 },
55 {
56 &gEfiGlobalVariableGuid,
57 L"Driver####",
58 {
59 0
60 },
61 },
62 {
63 &gEfiGlobalVariableGuid,
64 L"SysPrep####",
65 {
66 0
67 },
68 },
69 {
70 &gEfiGlobalVariableGuid,
71 L"Key####",
72 {
73 0
74 },
75 },
76 {
77 &gEfiGlobalVariableGuid,
78 L"PlatformRecovery####",
79 {
80 0
81 },
82 },
83 {
84 &gEfiHardwareErrorVariableGuid,
85 L"HwErrRec####",
86 {
87 0
88 },
89 },
90};
91
106BOOLEAN
107EFIAPI
109 IN CHAR16 Char
110 )
111{
112 return (BOOLEAN)((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F'));
113}
114
127 IN CHAR16 *VariableName,
128 IN EFI_GUID *VendorGuid,
129 IN BOOLEAN WildcardMatch
130 )
131{
132 UINTN Index;
133 UINTN NameLength;
134
135 NameLength = StrLen (VariableName) - 4;
136 for (Index = 0; Index < sizeof (mVarCheckVariableWithWildcardName)/sizeof (mVarCheckVariableWithWildcardName[0]); Index++) {
137 if (CompareGuid (mVarCheckVariableWithWildcardName[Index].Guid, VendorGuid)) {
138 if (WildcardMatch) {
139 if ((StrLen (VariableName) == StrLen (mVarCheckVariableWithWildcardName[Index].Name)) &&
140 (StrnCmp (VariableName, mVarCheckVariableWithWildcardName[Index].Name, NameLength) == 0) &&
141 VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength]) &&
142 VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength + 1]) &&
143 VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength + 2]) &&
144 VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength + 3]))
145 {
146 return &mVarCheckVariableWithWildcardName[Index].VariableProperty;
147 }
148 }
149
150 if (StrCmp (mVarCheckVariableWithWildcardName[Index].Name, VariableName) == 0) {
151 return &mVarCheckVariableWithWildcardName[Index].VariableProperty;
152 }
153 }
154 }
155
156 return NULL;
157}
158
171 IN CHAR16 *Name,
172 IN EFI_GUID *Guid,
173 IN BOOLEAN WildcardMatch
174 )
175{
176 UINTN Index;
178 CHAR16 *VariableName;
179
180 for (Index = 0; Index < mNumberOfVarCheckVariable; Index++) {
181 Entry = (VAR_CHECK_VARIABLE_ENTRY *)mVarCheckVariableTable[Index];
182 VariableName = (CHAR16 *)((UINTN)Entry + sizeof (*Entry));
183 if (CompareGuid (&Entry->Guid, Guid) && (StrCmp (VariableName, Name) == 0)) {
184 return &Entry->VariableProperty;
185 }
186 }
187
188 return VariablePropertyGetWithWildcardName (Name, Guid, WildcardMatch);
189}
190
205 IN OUT UINTN **Table,
206 IN OUT UINTN *MaxNumber,
207 IN OUT UINTN *CurrentNumber,
208 IN UINTN Entry
209 )
210{
211 UINTN *TempTable;
212
213 //
214 // Check whether the table is enough to store new entry.
215 //
216 if (*CurrentNumber == *MaxNumber) {
217 //
218 // Reallocate memory for the table.
219 //
220 TempTable = ReallocateRuntimePool (
221 *MaxNumber * sizeof (UINTN),
222 (*MaxNumber + VAR_CHECK_TABLE_SIZE) * sizeof (UINTN),
223 *Table
224 );
225
226 //
227 // No enough resource to allocate.
228 //
229 if (TempTable == NULL) {
230 return EFI_OUT_OF_RESOURCES;
231 }
232
233 *Table = TempTable;
234 //
235 // Increase max number.
236 //
237 *MaxNumber += VAR_CHECK_TABLE_SIZE;
238 }
239
240 //
241 // Add entry to the table.
242 //
243 (*Table)[*CurrentNumber] = Entry;
244 (*CurrentNumber)++;
245
246 return EFI_SUCCESS;
247}
248
263EFIAPI
265 IN VAR_CHECK_END_OF_DXE_CALLBACK Callback
266 )
267{
268 EFI_STATUS Status;
269
270 if (Callback == NULL) {
271 return EFI_INVALID_PARAMETER;
272 }
273
274 if (mVarCheckLibEndOfDxe) {
275 return EFI_ACCESS_DENIED;
276 }
277
278 Status = VarCheckAddTableEntry (
279 (UINTN **)&mVarCheckLibEndOfDxeCallback,
280 &mVarCheckLibEndOfDxeCallbackMaxCount,
281 &mVarCheckLibEndOfDxeCallbackCount,
282 (UINTN)Callback
283 );
284
285 DEBUG ((DEBUG_INFO, "VarCheckLibRegisterEndOfDxeCallback - 0x%x %r\n", Callback, Status));
286
287 return Status;
288}
289
302VOID ***
303EFIAPI
305 IN OUT UINTN *AddressPointerCount OPTIONAL
306 )
307{
308 VOID *TempTable;
309 UINTN TotalCount;
310 UINTN Index;
311
312 for (Index = 0; Index < mVarCheckLibEndOfDxeCallbackCount; Index++) {
313 //
314 // Invoke the callback registered by VarCheckLibRegisterEndOfDxeCallback().
315 //
316 mVarCheckLibEndOfDxeCallback[Index]();
317 }
318
319 if (mVarCheckLibEndOfDxeCallback != NULL) {
320 //
321 // Free the callback buffer.
322 //
323 mVarCheckLibEndOfDxeCallbackCount = 0;
324 mVarCheckLibEndOfDxeCallbackMaxCount = 0;
325 FreePool ((VOID *)mVarCheckLibEndOfDxeCallback);
326 mVarCheckLibEndOfDxeCallback = NULL;
327 }
328
329 mVarCheckLibEndOfDxe = TRUE;
330
331 if (AddressPointerCount == NULL) {
332 if (mVarCheckLibAddressPointer != NULL) {
333 //
334 // Free the address pointer buffer.
335 //
336 mVarCheckLibAddressPointerCount = 0;
337 mVarCheckLibAddressPointerMaxCount = 0;
338 FreePool ((VOID *)mVarCheckLibAddressPointer);
339 mVarCheckLibAddressPointer = NULL;
340 }
341
342 return NULL;
343 }
344
345 //
346 // Get the total count needed.
347 // Also cover VarCheckHandler and the entries, and VarCheckVariable and the entries.
348 //
349 TotalCount = mVarCheckLibAddressPointerCount + (mNumberOfVarCheckHandler + 1) + (mNumberOfVarCheckVariable + 1);
350 TempTable = ReallocateRuntimePool (
351 mVarCheckLibAddressPointerMaxCount * sizeof (VOID **),
352 TotalCount * sizeof (VOID **),
353 (VOID *)mVarCheckLibAddressPointer
354 );
355
356 if (TempTable != NULL) {
357 mVarCheckLibAddressPointer = (VOID ***)TempTable;
358
359 //
360 // Cover VarCheckHandler and the entries.
361 //
362 mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **)&mVarCheckHandlerTable;
363 for (Index = 0; Index < mNumberOfVarCheckHandler; Index++) {
364 mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **)&mVarCheckHandlerTable[Index];
365 }
366
367 //
368 // Cover VarCheckVariable and the entries.
369 //
370 mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **)&mVarCheckVariableTable;
371 for (Index = 0; Index < mNumberOfVarCheckVariable; Index++) {
372 mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **)&mVarCheckVariableTable[Index];
373 }
374
375 ASSERT (mVarCheckLibAddressPointerCount == TotalCount);
376 mVarCheckLibAddressPointerMaxCount = mVarCheckLibAddressPointerCount;
377 }
378
379 *AddressPointerCount = mVarCheckLibAddressPointerCount;
380 return mVarCheckLibAddressPointer;
381}
382
397EFIAPI
399 IN VOID **AddressPointer
400 )
401{
402 EFI_STATUS Status;
403
404 if (AddressPointer == NULL) {
405 return EFI_INVALID_PARAMETER;
406 }
407
408 if (mVarCheckLibEndOfDxe) {
409 return EFI_ACCESS_DENIED;
410 }
411
412 Status = VarCheckAddTableEntry (
413 (UINTN **)&mVarCheckLibAddressPointer,
414 &mVarCheckLibAddressPointerMaxCount,
415 &mVarCheckLibAddressPointerCount,
416 (UINTN)AddressPointer
417 );
418
419 DEBUG ((DEBUG_INFO, "VarCheckLibRegisterAddressPointer - 0x%x %r\n", AddressPointer, Status));
420
421 return Status;
422}
423
439EFIAPI
441 IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER Handler
442 )
443{
444 EFI_STATUS Status;
445
446 if (Handler == NULL) {
447 return EFI_INVALID_PARAMETER;
448 }
449
450 if (mVarCheckLibEndOfDxe) {
451 return EFI_ACCESS_DENIED;
452 }
453
454 Status = VarCheckAddTableEntry (
455 (UINTN **)&mVarCheckHandlerTable,
456 &mMaxNumberOfVarCheckHandler,
457 &mNumberOfVarCheckHandler,
458 (UINTN)Handler
459 );
460
461 DEBUG ((DEBUG_INFO, "VarCheckLibRegisterSetVariableCheckHandler - 0x%x %r\n", Handler, Status));
462
463 return Status;
464}
465
482EFIAPI
484 IN CHAR16 *Name,
485 IN EFI_GUID *Guid,
486 IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty
487 )
488{
489 EFI_STATUS Status;
491 CHAR16 *VariableName;
493
494 if ((Name == NULL) || (Name[0] == 0) || (Guid == NULL)) {
495 return EFI_INVALID_PARAMETER;
496 }
497
498 if (VariableProperty == NULL) {
499 return EFI_INVALID_PARAMETER;
500 }
501
502 if (VariableProperty->Revision != VAR_CHECK_VARIABLE_PROPERTY_REVISION) {
503 return EFI_INVALID_PARAMETER;
504 }
505
506 if (mVarCheckLibEndOfDxe) {
507 return EFI_ACCESS_DENIED;
508 }
509
510 Status = EFI_SUCCESS;
511
512 //
513 // Get the pointer of property data for set.
514 //
515 Property = VariablePropertyGetFunction (Name, Guid, FALSE);
516 if (Property != NULL) {
517 CopyMem (Property, VariableProperty, sizeof (*VariableProperty));
518 } else {
519 Entry = AllocateRuntimeZeroPool (sizeof (*Entry) + StrSize (Name));
520 if (Entry == NULL) {
521 return EFI_OUT_OF_RESOURCES;
522 }
523
524 VariableName = (CHAR16 *)((UINTN)Entry + sizeof (*Entry));
525 StrCpyS (VariableName, StrSize (Name)/sizeof (CHAR16), Name);
526 CopyGuid (&Entry->Guid, Guid);
527 CopyMem (&Entry->VariableProperty, VariableProperty, sizeof (*VariableProperty));
528
529 Status = VarCheckAddTableEntry (
530 (UINTN **)&mVarCheckVariableTable,
531 &mMaxNumberOfVarCheckVariable,
532 &mNumberOfVarCheckVariable,
533 (UINTN)Entry
534 );
535
536 if (EFI_ERROR (Status)) {
537 FreePool (Entry);
538 }
539 }
540
541 return Status;
542}
543
557EFIAPI
559 IN CHAR16 *Name,
560 IN EFI_GUID *Guid,
561 OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty
562 )
563{
565
566 if ((Name == NULL) || (Name[0] == 0) || (Guid == NULL)) {
567 return EFI_INVALID_PARAMETER;
568 }
569
570 if (VariableProperty == NULL) {
571 return EFI_INVALID_PARAMETER;
572 }
573
574 Property = VariablePropertyGetFunction (Name, Guid, TRUE);
575 //
576 // Also check the property revision before using the property data.
577 // There is no property set to this variable(wildcard name)
578 // if the revision is not VAR_CHECK_VARIABLE_PROPERTY_REVISION.
579 //
580 if ((Property != NULL) && (Property->Revision == VAR_CHECK_VARIABLE_PROPERTY_REVISION)) {
581 CopyMem (VariableProperty, Property, sizeof (*VariableProperty));
582 return EFI_SUCCESS;
583 }
584
585 return EFI_NOT_FOUND;
586}
587
606EFIAPI
608 IN CHAR16 *VariableName,
609 IN EFI_GUID *VendorGuid,
610 IN UINT32 Attributes,
611 IN UINTN DataSize,
612 IN VOID *Data,
613 IN VAR_CHECK_REQUEST_SOURCE RequestSource
614 )
615{
616 EFI_STATUS Status;
617 UINTN Index;
619
620 if (!mVarCheckLibEndOfDxe) {
621 //
622 // Only do check after End Of Dxe.
623 //
624 return EFI_SUCCESS;
625 }
626
627 Property = VariablePropertyGetFunction (VariableName, VendorGuid, TRUE);
628 //
629 // Also check the property revision before using the property data.
630 // There is no property set to this variable(wildcard name)
631 // if the revision is not VAR_CHECK_VARIABLE_PROPERTY_REVISION.
632 //
633 if ((Property != NULL) && (Property->Revision == VAR_CHECK_VARIABLE_PROPERTY_REVISION)) {
634 if ((RequestSource != VarCheckFromTrusted) && ((Property->Property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) != 0)) {
635 DEBUG ((DEBUG_INFO, "Variable Check ReadOnly variable fail %r - %g:%s\n", EFI_WRITE_PROTECTED, VendorGuid, VariableName));
636 return EFI_WRITE_PROTECTED;
637 }
638
639 if (!((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0))) {
640 //
641 // Not to delete variable.
642 //
643 if ((Property->Attributes != 0) && ((Attributes & (~EFI_VARIABLE_APPEND_WRITE)) != Property->Attributes)) {
644 DEBUG ((DEBUG_INFO, "Variable Check Attributes(0x%08x to 0x%08x) fail %r - %g:%s\n", Property->Attributes, Attributes, EFI_INVALID_PARAMETER, VendorGuid, VariableName));
645 return EFI_INVALID_PARAMETER;
646 }
647
648 if (DataSize != 0) {
649 if ((DataSize < Property->MinSize) || (DataSize > Property->MaxSize)) {
650 DEBUG ((DEBUG_INFO, "Variable Check DataSize fail(0x%x not in 0x%x - 0x%x) %r - %g:%s\n", DataSize, Property->MinSize, Property->MaxSize, EFI_INVALID_PARAMETER, VendorGuid, VariableName));
651 return EFI_INVALID_PARAMETER;
652 }
653 }
654 }
655 }
656
657 for (Index = 0; Index < mNumberOfVarCheckHandler; Index++) {
658 Status = mVarCheckHandlerTable[Index](
659 VariableName,
660 VendorGuid,
661 Attributes,
662 DataSize,
663 Data
664 );
665 if ((Status == EFI_WRITE_PROTECTED) && (RequestSource == VarCheckFromTrusted)) {
666 //
667 // If RequestSource is trusted, then allow variable to be set even if it
668 // is write protected.
669 //
670 continue;
671 }
672
673 if (EFI_ERROR (Status)) {
674 DEBUG ((DEBUG_INFO, "Variable Check handler fail %r - %g:%s\n", Status, VendorGuid, VariableName));
675 return Status;
676 }
677 }
678
679 return EFI_SUCCESS;
680}
UINT64 UINTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
RETURN_STATUS EFIAPI StrCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:226
INTN EFIAPI StrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
Definition: String.c:109
INTN EFIAPI StrnCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString, IN UINTN Length)
Definition: String.c:162
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI ReallocateRuntimePool(IN UINTN OldSize, IN UINTN NewSize, IN VOID *OldBuffer OPTIONAL)
VOID *EFIAPI AllocateRuntimeZeroPool(IN UINTN AllocationSize)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
VAR_CHECK_VARIABLE_PROPERTY * VariablePropertyGetWithWildcardName(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN BOOLEAN WildcardMatch)
Definition: VarCheckLib.c:126
VOID ***EFIAPI VarCheckLibInitializeAtEndOfDxe(IN OUT UINTN *AddressPointerCount OPTIONAL)
Definition: VarCheckLib.c:304
EFI_STATUS EFIAPI VarCheckLibRegisterAddressPointer(IN VOID **AddressPointer)
Definition: VarCheckLib.c:398
VAR_CHECK_VARIABLE_PROPERTY * VariablePropertyGetFunction(IN CHAR16 *Name, IN EFI_GUID *Guid, IN BOOLEAN WildcardMatch)
Definition: VarCheckLib.c:170
EFI_STATUS EFIAPI VarCheckLibRegisterSetVariableCheckHandler(IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER Handler)
Definition: VarCheckLib.c:440
EFI_STATUS EFIAPI VarCheckLibRegisterEndOfDxeCallback(IN VAR_CHECK_END_OF_DXE_CALLBACK Callback)
Definition: VarCheckLib.c:264
EFI_STATUS EFIAPI VarCheckLibVariablePropertySet(IN CHAR16 *Name, IN EFI_GUID *Guid, IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty)
Definition: VarCheckLib.c:483
BOOLEAN EFIAPI VarCheckInternalIsHexaDecimalDigitCharacter(IN CHAR16 Char)
Definition: VarCheckLib.c:108
EFI_STATUS VarCheckAddTableEntry(IN OUT UINTN **Table, IN OUT UINTN *MaxNumber, IN OUT UINTN *CurrentNumber, IN UINTN Entry)
Definition: VarCheckLib.c:204
EFI_STATUS EFIAPI VarCheckLibSetVariableCheck(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data, IN VAR_CHECK_REQUEST_SOURCE RequestSource)
Definition: VarCheckLib.c:607
EFI_STATUS EFIAPI VarCheckLibVariablePropertyGet(IN CHAR16 *Name, IN EFI_GUID *Guid, OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty)
Definition: VarCheckLib.c:558
Definition: Base.h:213