]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/VarCheckLib/VarCheckLib.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Library / VarCheckLib / VarCheckLib.c
CommitLineData
31b183bc
SZ
1/** @file\r
2 Implementation functions and structures for var check services.\r
3\r
248d08c5 4Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
31b183bc
SZ
6\r
7**/\r
8\r
9#include <Library/VarCheckLib.h>\r
10#include <Library/BaseLib.h>\r
11#include <Library/BaseMemoryLib.h>\r
12#include <Library/DebugLib.h>\r
13#include <Library/MemoryAllocationLib.h>\r
14\r
15#include <Guid/GlobalVariable.h>\r
16#include <Guid/HardwareErrorVariable.h>\r
17\r
1436aea4 18BOOLEAN mVarCheckLibEndOfDxe = FALSE;\r
31b183bc 19\r
1436aea4 20#define VAR_CHECK_TABLE_SIZE 0x8\r
31b183bc 21\r
1436aea4
MK
22UINTN mVarCheckLibEndOfDxeCallbackCount = 0;\r
23UINTN mVarCheckLibEndOfDxeCallbackMaxCount = 0;\r
24VAR_CHECK_END_OF_DXE_CALLBACK *mVarCheckLibEndOfDxeCallback = NULL;\r
31b183bc 25\r
1436aea4
MK
26UINTN mVarCheckLibAddressPointerCount = 0;\r
27UINTN mVarCheckLibAddressPointerMaxCount = 0;\r
28VOID ***mVarCheckLibAddressPointer = NULL;\r
31b183bc 29\r
1436aea4
MK
30UINTN mNumberOfVarCheckHandler = 0;\r
31UINTN mMaxNumberOfVarCheckHandler = 0;\r
32VAR_CHECK_SET_VARIABLE_CHECK_HANDLER *mVarCheckHandlerTable = NULL;\r
31b183bc
SZ
33\r
34typedef struct {\r
1436aea4
MK
35 EFI_GUID Guid;\r
36 VAR_CHECK_VARIABLE_PROPERTY VariableProperty;\r
37 // CHAR16 *Name;\r
31b183bc
SZ
38} VAR_CHECK_VARIABLE_ENTRY;\r
39\r
1436aea4
MK
40UINTN mNumberOfVarCheckVariable = 0;\r
41UINTN mMaxNumberOfVarCheckVariable = 0;\r
42VARIABLE_ENTRY_PROPERTY **mVarCheckVariableTable = NULL;\r
31b183bc
SZ
43\r
44//\r
45// Handle variables with wildcard name specially.\r
46//\r
1436aea4 47VARIABLE_ENTRY_PROPERTY mVarCheckVariableWithWildcardName[] = {\r
31b183bc
SZ
48 {\r
49 &gEfiGlobalVariableGuid,\r
50 L"Boot####",\r
51 {\r
52 0\r
53 },\r
54 },\r
55 {\r
56 &gEfiGlobalVariableGuid,\r
57 L"Driver####",\r
58 {\r
59 0\r
60 },\r
61 },\r
62 {\r
63 &gEfiGlobalVariableGuid,\r
64 L"SysPrep####",\r
65 {\r
66 0\r
67 },\r
68 },\r
69 {\r
70 &gEfiGlobalVariableGuid,\r
71 L"Key####",\r
72 {\r
73 0\r
74 },\r
75 },\r
51b655a8
RN
76 {\r
77 &gEfiGlobalVariableGuid,\r
78 L"PlatformRecovery####",\r
79 {\r
80 0\r
81 },\r
82 },\r
31b183bc
SZ
83 {\r
84 &gEfiHardwareErrorVariableGuid,\r
85 L"HwErrRec####",\r
86 {\r
87 0\r
88 },\r
89 },\r
90};\r
91\r
92/**\r
6c59c7c2 93 Check if a Unicode character is an upper case hexadecimal character.\r
31b183bc 94\r
6c59c7c2
SZ
95 This function checks if a Unicode character is an upper case\r
96 hexadecimal character. The valid upper case hexadecimal character is\r
97 L'0' to L'9', or L'A' to L'F'.\r
31b183bc
SZ
98\r
99\r
100 @param[in] Char The character to check against.\r
101\r
6c59c7c2
SZ
102 @retval TRUE If the Char is an upper case hexadecmial character.\r
103 @retval FALSE If the Char is not an upper case hexadecmial character.\r
31b183bc
SZ
104\r
105**/\r
106BOOLEAN\r
107EFIAPI\r
108VarCheckInternalIsHexaDecimalDigitCharacter (\r
1436aea4 109 IN CHAR16 Char\r
31b183bc
SZ
110 )\r
111{\r
1436aea4 112 return (BOOLEAN)((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F'));\r
31b183bc
SZ
113}\r
114\r
115/**\r
116 Variable property get with wildcard name.\r
117\r
118 @param[in] VariableName Pointer to variable name.\r
119 @param[in] VendorGuid Pointer to variable vendor GUID.\r
120 @param[in] WildcardMatch Try wildcard match or not.\r
121\r
122 @return Pointer to variable property.\r
123\r
124**/\r
125VAR_CHECK_VARIABLE_PROPERTY *\r
126VariablePropertyGetWithWildcardName (\r
1436aea4
MK
127 IN CHAR16 *VariableName,\r
128 IN EFI_GUID *VendorGuid,\r
129 IN BOOLEAN WildcardMatch\r
31b183bc
SZ
130 )\r
131{\r
1436aea4
MK
132 UINTN Index;\r
133 UINTN NameLength;\r
31b183bc
SZ
134\r
135 NameLength = StrLen (VariableName) - 4;\r
136 for (Index = 0; Index < sizeof (mVarCheckVariableWithWildcardName)/sizeof (mVarCheckVariableWithWildcardName[0]); Index++) {\r
1436aea4 137 if (CompareGuid (mVarCheckVariableWithWildcardName[Index].Guid, VendorGuid)) {\r
31b183bc
SZ
138 if (WildcardMatch) {\r
139 if ((StrLen (VariableName) == StrLen (mVarCheckVariableWithWildcardName[Index].Name)) &&\r
140 (StrnCmp (VariableName, mVarCheckVariableWithWildcardName[Index].Name, NameLength) == 0) &&\r
141 VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength]) &&\r
142 VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength + 1]) &&\r
143 VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength + 2]) &&\r
1436aea4
MK
144 VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength + 3]))\r
145 {\r
d2dbe5b7 146 return &mVarCheckVariableWithWildcardName[Index].VariableProperty;\r
31b183bc
SZ
147 }\r
148 }\r
1436aea4 149\r
31b183bc 150 if (StrCmp (mVarCheckVariableWithWildcardName[Index].Name, VariableName) == 0) {\r
1436aea4 151 return &mVarCheckVariableWithWildcardName[Index].VariableProperty;\r
31b183bc
SZ
152 }\r
153 }\r
154 }\r
155\r
156 return NULL;\r
157}\r
158\r
159/**\r
160 Variable property get function.\r
161\r
162 @param[in] Name Pointer to the variable name.\r
163 @param[in] Guid Pointer to the vendor GUID.\r
164 @param[in] WildcardMatch Try wildcard match or not.\r
165\r
166 @return Pointer to the property of variable specified by the Name and Guid.\r
167\r
168**/\r
169VAR_CHECK_VARIABLE_PROPERTY *\r
170VariablePropertyGetFunction (\r
1436aea4
MK
171 IN CHAR16 *Name,\r
172 IN EFI_GUID *Guid,\r
173 IN BOOLEAN WildcardMatch\r
31b183bc
SZ
174 )\r
175{\r
176 UINTN Index;\r
177 VAR_CHECK_VARIABLE_ENTRY *Entry;\r
178 CHAR16 *VariableName;\r
179\r
180 for (Index = 0; Index < mNumberOfVarCheckVariable; Index++) {\r
1436aea4
MK
181 Entry = (VAR_CHECK_VARIABLE_ENTRY *)mVarCheckVariableTable[Index];\r
182 VariableName = (CHAR16 *)((UINTN)Entry + sizeof (*Entry));\r
31b183bc
SZ
183 if (CompareGuid (&Entry->Guid, Guid) && (StrCmp (VariableName, Name) == 0)) {\r
184 return &Entry->VariableProperty;\r
185 }\r
186 }\r
187\r
188 return VariablePropertyGetWithWildcardName (Name, Guid, WildcardMatch);\r
189}\r
190\r
191/**\r
192 Var check add table entry.\r
193\r
194 @param[in, out] Table Pointer to table buffer.\r
195 @param[in, out] MaxNumber Pointer to maximum number of entry in the table.\r
196 @param[in, out] CurrentNumber Pointer to current number of entry in the table.\r
197 @param[in] Entry Entry will be added to the table.\r
198\r
199 @retval EFI_SUCCESS Reallocate memory successfully.\r
200 @retval EFI_OUT_OF_RESOURCES No enough memory to allocate.\r
201\r
202**/\r
203EFI_STATUS\r
204VarCheckAddTableEntry (\r
1436aea4
MK
205 IN OUT UINTN **Table,\r
206 IN OUT UINTN *MaxNumber,\r
207 IN OUT UINTN *CurrentNumber,\r
208 IN UINTN Entry\r
31b183bc
SZ
209 )\r
210{\r
1436aea4 211 UINTN *TempTable;\r
31b183bc
SZ
212\r
213 //\r
214 // Check whether the table is enough to store new entry.\r
215 //\r
216 if (*CurrentNumber == *MaxNumber) {\r
217 //\r
218 // Reallocate memory for the table.\r
219 //\r
220 TempTable = ReallocateRuntimePool (\r
221 *MaxNumber * sizeof (UINTN),\r
222 (*MaxNumber + VAR_CHECK_TABLE_SIZE) * sizeof (UINTN),\r
223 *Table\r
224 );\r
225\r
226 //\r
227 // No enough resource to allocate.\r
228 //\r
229 if (TempTable == NULL) {\r
230 return EFI_OUT_OF_RESOURCES;\r
231 }\r
232\r
233 *Table = TempTable;\r
234 //\r
235 // Increase max number.\r
236 //\r
237 *MaxNumber += VAR_CHECK_TABLE_SIZE;\r
238 }\r
239\r
240 //\r
241 // Add entry to the table.\r
242 //\r
243 (*Table)[*CurrentNumber] = Entry;\r
244 (*CurrentNumber)++;\r
245\r
246 return EFI_SUCCESS;\r
247}\r
248\r
249/**\r
250 Register END_OF_DXE callback.\r
251 The callback will be invoked by VarCheckLibInitializeAtEndOfDxe().\r
252\r
253 @param[in] Callback END_OF_DXE callback.\r
254\r
255 @retval EFI_SUCCESS The callback was registered successfully.\r
256 @retval EFI_INVALID_PARAMETER Callback is NULL.\r
257 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
258 already been signaled.\r
259 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the callback register request.\r
260\r
261**/\r
262EFI_STATUS\r
263EFIAPI\r
264VarCheckLibRegisterEndOfDxeCallback (\r
265 IN VAR_CHECK_END_OF_DXE_CALLBACK Callback\r
266 )\r
267{\r
1436aea4 268 EFI_STATUS Status;\r
31b183bc
SZ
269\r
270 if (Callback == NULL) {\r
271 return EFI_INVALID_PARAMETER;\r
272 }\r
273\r
274 if (mVarCheckLibEndOfDxe) {\r
275 return EFI_ACCESS_DENIED;\r
276 }\r
277\r
278 Status = VarCheckAddTableEntry (\r
1436aea4
MK
279 (UINTN **)&mVarCheckLibEndOfDxeCallback,\r
280 &mVarCheckLibEndOfDxeCallbackMaxCount,\r
281 &mVarCheckLibEndOfDxeCallbackCount,\r
282 (UINTN)Callback\r
283 );\r
31b183bc 284\r
87000d77 285 DEBUG ((DEBUG_INFO, "VarCheckLibRegisterEndOfDxeCallback - 0x%x %r\n", Callback, Status));\r
31b183bc
SZ
286\r
287 return Status;\r
288}\r
289\r
290/**\r
291 Var check initialize at END_OF_DXE.\r
292\r
293 This function needs to be called at END_OF_DXE.\r
294 Address pointers may be returned,\r
295 and caller needs to ConvertPointer() for the pointers.\r
296\r
297 @param[in, out] AddressPointerCount Output pointer to address pointer count.\r
298\r
299 @return Address pointer buffer, NULL if input AddressPointerCount is NULL.\r
300\r
301**/\r
302VOID ***\r
303EFIAPI\r
304VarCheckLibInitializeAtEndOfDxe (\r
1436aea4 305 IN OUT UINTN *AddressPointerCount OPTIONAL\r
31b183bc
SZ
306 )\r
307{\r
1436aea4
MK
308 VOID *TempTable;\r
309 UINTN TotalCount;\r
310 UINTN Index;\r
31b183bc
SZ
311\r
312 for (Index = 0; Index < mVarCheckLibEndOfDxeCallbackCount; Index++) {\r
313 //\r
314 // Invoke the callback registered by VarCheckLibRegisterEndOfDxeCallback().\r
315 //\r
1436aea4 316 mVarCheckLibEndOfDxeCallback[Index]();\r
31b183bc 317 }\r
1436aea4 318\r
31b183bc
SZ
319 if (mVarCheckLibEndOfDxeCallback != NULL) {\r
320 //\r
321 // Free the callback buffer.\r
322 //\r
1436aea4 323 mVarCheckLibEndOfDxeCallbackCount = 0;\r
31b183bc 324 mVarCheckLibEndOfDxeCallbackMaxCount = 0;\r
1436aea4 325 FreePool ((VOID *)mVarCheckLibEndOfDxeCallback);\r
31b183bc
SZ
326 mVarCheckLibEndOfDxeCallback = NULL;\r
327 }\r
328\r
329 mVarCheckLibEndOfDxe = TRUE;\r
330\r
331 if (AddressPointerCount == NULL) {\r
332 if (mVarCheckLibAddressPointer != NULL) {\r
333 //\r
334 // Free the address pointer buffer.\r
335 //\r
1436aea4 336 mVarCheckLibAddressPointerCount = 0;\r
31b183bc 337 mVarCheckLibAddressPointerMaxCount = 0;\r
1436aea4 338 FreePool ((VOID *)mVarCheckLibAddressPointer);\r
31b183bc
SZ
339 mVarCheckLibAddressPointer = NULL;\r
340 }\r
1436aea4 341\r
31b183bc
SZ
342 return NULL;\r
343 }\r
344\r
345 //\r
346 // Get the total count needed.\r
347 // Also cover VarCheckHandler and the entries, and VarCheckVariable and the entries.\r
348 //\r
349 TotalCount = mVarCheckLibAddressPointerCount + (mNumberOfVarCheckHandler + 1) + (mNumberOfVarCheckVariable + 1);\r
1436aea4
MK
350 TempTable = ReallocateRuntimePool (\r
351 mVarCheckLibAddressPointerMaxCount * sizeof (VOID **),\r
352 TotalCount * sizeof (VOID **),\r
353 (VOID *)mVarCheckLibAddressPointer\r
354 );\r
31b183bc
SZ
355\r
356 if (TempTable != NULL) {\r
1436aea4 357 mVarCheckLibAddressPointer = (VOID ***)TempTable;\r
31b183bc
SZ
358\r
359 //\r
360 // Cover VarCheckHandler and the entries.\r
361 //\r
1436aea4 362 mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **)&mVarCheckHandlerTable;\r
31b183bc 363 for (Index = 0; Index < mNumberOfVarCheckHandler; Index++) {\r
1436aea4 364 mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **)&mVarCheckHandlerTable[Index];\r
31b183bc
SZ
365 }\r
366\r
367 //\r
368 // Cover VarCheckVariable and the entries.\r
369 //\r
1436aea4 370 mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **)&mVarCheckVariableTable;\r
31b183bc 371 for (Index = 0; Index < mNumberOfVarCheckVariable; Index++) {\r
1436aea4 372 mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **)&mVarCheckVariableTable[Index];\r
31b183bc
SZ
373 }\r
374\r
375 ASSERT (mVarCheckLibAddressPointerCount == TotalCount);\r
376 mVarCheckLibAddressPointerMaxCount = mVarCheckLibAddressPointerCount;\r
377 }\r
378\r
379 *AddressPointerCount = mVarCheckLibAddressPointerCount;\r
380 return mVarCheckLibAddressPointer;\r
381}\r
382\r
383/**\r
384 Register address pointer.\r
385 The AddressPointer may be returned by VarCheckLibInitializeAtEndOfDxe().\r
386\r
387 @param[in] AddressPointer Address pointer.\r
388\r
389 @retval EFI_SUCCESS The address pointer was registered successfully.\r
390 @retval EFI_INVALID_PARAMETER AddressPointer is NULL.\r
391 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
392 already been signaled.\r
393 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the address pointer register request.\r
394\r
395**/\r
396EFI_STATUS\r
397EFIAPI\r
398VarCheckLibRegisterAddressPointer (\r
1436aea4 399 IN VOID **AddressPointer\r
31b183bc
SZ
400 )\r
401{\r
1436aea4 402 EFI_STATUS Status;\r
31b183bc
SZ
403\r
404 if (AddressPointer == NULL) {\r
405 return EFI_INVALID_PARAMETER;\r
406 }\r
407\r
408 if (mVarCheckLibEndOfDxe) {\r
409 return EFI_ACCESS_DENIED;\r
410 }\r
411\r
1436aea4
MK
412 Status = VarCheckAddTableEntry (\r
413 (UINTN **)&mVarCheckLibAddressPointer,\r
414 &mVarCheckLibAddressPointerMaxCount,\r
415 &mVarCheckLibAddressPointerCount,\r
416 (UINTN)AddressPointer\r
417 );\r
31b183bc 418\r
87000d77 419 DEBUG ((DEBUG_INFO, "VarCheckLibRegisterAddressPointer - 0x%x %r\n", AddressPointer, Status));\r
31b183bc
SZ
420\r
421 return Status;\r
422}\r
423\r
424/**\r
425 Register SetVariable check handler.\r
426\r
427 @param[in] Handler Pointer to check handler.\r
428\r
429 @retval EFI_SUCCESS The SetVariable check handler was registered successfully.\r
430 @retval EFI_INVALID_PARAMETER Handler is NULL.\r
431 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
432 already been signaled.\r
433 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the SetVariable check handler register request.\r
434 @retval EFI_UNSUPPORTED This interface is not implemented.\r
435 For example, it is unsupported in VarCheck protocol if both VarCheck and SmmVarCheck protocols are present.\r
436\r
437**/\r
438EFI_STATUS\r
439EFIAPI\r
440VarCheckLibRegisterSetVariableCheckHandler (\r
1436aea4 441 IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER Handler\r
31b183bc
SZ
442 )\r
443{\r
1436aea4 444 EFI_STATUS Status;\r
31b183bc
SZ
445\r
446 if (Handler == NULL) {\r
447 return EFI_INVALID_PARAMETER;\r
448 }\r
449\r
450 if (mVarCheckLibEndOfDxe) {\r
451 return EFI_ACCESS_DENIED;\r
452 }\r
453\r
1436aea4
MK
454 Status = VarCheckAddTableEntry (\r
455 (UINTN **)&mVarCheckHandlerTable,\r
456 &mMaxNumberOfVarCheckHandler,\r
457 &mNumberOfVarCheckHandler,\r
458 (UINTN)Handler\r
459 );\r
31b183bc 460\r
87000d77 461 DEBUG ((DEBUG_INFO, "VarCheckLibRegisterSetVariableCheckHandler - 0x%x %r\n", Handler, Status));\r
31b183bc
SZ
462\r
463 return Status;\r
464}\r
465\r
466/**\r
467 Variable property set.\r
468\r
469 @param[in] Name Pointer to the variable name.\r
470 @param[in] Guid Pointer to the vendor GUID.\r
471 @param[in] VariableProperty Pointer to the input variable property.\r
472\r
473 @retval EFI_SUCCESS The property of variable specified by the Name and Guid was set successfully.\r
474 @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string,\r
475 or the fields of VariableProperty are not valid.\r
476 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
477 already been signaled.\r
478 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the variable property set request.\r
479\r
480**/\r
481EFI_STATUS\r
482EFIAPI\r
483VarCheckLibVariablePropertySet (\r
1436aea4
MK
484 IN CHAR16 *Name,\r
485 IN EFI_GUID *Guid,\r
486 IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty\r
31b183bc
SZ
487 )\r
488{\r
1436aea4
MK
489 EFI_STATUS Status;\r
490 VAR_CHECK_VARIABLE_ENTRY *Entry;\r
491 CHAR16 *VariableName;\r
492 VAR_CHECK_VARIABLE_PROPERTY *Property;\r
31b183bc 493\r
1436aea4 494 if ((Name == NULL) || (Name[0] == 0) || (Guid == NULL)) {\r
31b183bc
SZ
495 return EFI_INVALID_PARAMETER;\r
496 }\r
497\r
498 if (VariableProperty == NULL) {\r
499 return EFI_INVALID_PARAMETER;\r
500 }\r
501\r
502 if (VariableProperty->Revision != VAR_CHECK_VARIABLE_PROPERTY_REVISION) {\r
503 return EFI_INVALID_PARAMETER;\r
504 }\r
505\r
506 if (mVarCheckLibEndOfDxe) {\r
507 return EFI_ACCESS_DENIED;\r
508 }\r
509\r
510 Status = EFI_SUCCESS;\r
511\r
d2dbe5b7
SZ
512 //\r
513 // Get the pointer of property data for set.\r
514 //\r
31b183bc
SZ
515 Property = VariablePropertyGetFunction (Name, Guid, FALSE);\r
516 if (Property != NULL) {\r
517 CopyMem (Property, VariableProperty, sizeof (*VariableProperty));\r
518 } else {\r
519 Entry = AllocateRuntimeZeroPool (sizeof (*Entry) + StrSize (Name));\r
520 if (Entry == NULL) {\r
521 return EFI_OUT_OF_RESOURCES;\r
522 }\r
1436aea4
MK
523\r
524 VariableName = (CHAR16 *)((UINTN)Entry + sizeof (*Entry));\r
31b183bc
SZ
525 StrCpyS (VariableName, StrSize (Name)/sizeof (CHAR16), Name);\r
526 CopyGuid (&Entry->Guid, Guid);\r
527 CopyMem (&Entry->VariableProperty, VariableProperty, sizeof (*VariableProperty));\r
528\r
1436aea4
MK
529 Status = VarCheckAddTableEntry (\r
530 (UINTN **)&mVarCheckVariableTable,\r
31b183bc
SZ
531 &mMaxNumberOfVarCheckVariable,\r
532 &mNumberOfVarCheckVariable,\r
1436aea4 533 (UINTN)Entry\r
31b183bc
SZ
534 );\r
535\r
536 if (EFI_ERROR (Status)) {\r
537 FreePool (Entry);\r
538 }\r
539 }\r
540\r
541 return Status;\r
542}\r
543\r
544/**\r
545 Variable property get.\r
546\r
547 @param[in] Name Pointer to the variable name.\r
548 @param[in] Guid Pointer to the vendor GUID.\r
549 @param[out] VariableProperty Pointer to the output variable property.\r
550\r
551 @retval EFI_SUCCESS The property of variable specified by the Name and Guid was got successfully.\r
552 @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string.\r
553 @retval EFI_NOT_FOUND The property of variable specified by the Name and Guid was not found.\r
554\r
555**/\r
556EFI_STATUS\r
557EFIAPI\r
558VarCheckLibVariablePropertyGet (\r
1436aea4
MK
559 IN CHAR16 *Name,\r
560 IN EFI_GUID *Guid,\r
561 OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty\r
31b183bc
SZ
562 )\r
563{\r
1436aea4 564 VAR_CHECK_VARIABLE_PROPERTY *Property;\r
31b183bc 565\r
1436aea4 566 if ((Name == NULL) || (Name[0] == 0) || (Guid == NULL)) {\r
31b183bc
SZ
567 return EFI_INVALID_PARAMETER;\r
568 }\r
569\r
570 if (VariableProperty == NULL) {\r
571 return EFI_INVALID_PARAMETER;\r
572 }\r
573\r
574 Property = VariablePropertyGetFunction (Name, Guid, TRUE);\r
d2dbe5b7
SZ
575 //\r
576 // Also check the property revision before using the property data.\r
577 // There is no property set to this variable(wildcard name)\r
578 // if the revision is not VAR_CHECK_VARIABLE_PROPERTY_REVISION.\r
579 //\r
580 if ((Property != NULL) && (Property->Revision == VAR_CHECK_VARIABLE_PROPERTY_REVISION)) {\r
31b183bc
SZ
581 CopyMem (VariableProperty, Property, sizeof (*VariableProperty));\r
582 return EFI_SUCCESS;\r
583 }\r
584\r
585 return EFI_NOT_FOUND;\r
586}\r
587\r
588/**\r
589 SetVariable check.\r
590\r
591 @param[in] VariableName Name of Variable to set.\r
592 @param[in] VendorGuid Variable vendor GUID.\r
593 @param[in] Attributes Attribute value of the variable.\r
594 @param[in] DataSize Size of Data to set.\r
595 @param[in] Data Data pointer.\r
596 @param[in] RequestSource Request source.\r
597\r
598 @retval EFI_SUCCESS The SetVariable check result was success.\r
599 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, GUID,\r
600 DataSize and Data value was supplied.\r
601 @retval EFI_WRITE_PROTECTED The variable in question is read-only.\r
602 @retval Others The other return status from check handler.\r
603\r
604**/\r
605EFI_STATUS\r
606EFIAPI\r
607VarCheckLibSetVariableCheck (\r
1436aea4
MK
608 IN CHAR16 *VariableName,\r
609 IN EFI_GUID *VendorGuid,\r
610 IN UINT32 Attributes,\r
611 IN UINTN DataSize,\r
612 IN VOID *Data,\r
613 IN VAR_CHECK_REQUEST_SOURCE RequestSource\r
31b183bc
SZ
614 )\r
615{\r
1436aea4
MK
616 EFI_STATUS Status;\r
617 UINTN Index;\r
618 VAR_CHECK_VARIABLE_PROPERTY *Property;\r
31b183bc
SZ
619\r
620 if (!mVarCheckLibEndOfDxe) {\r
621 //\r
622 // Only do check after End Of Dxe.\r
623 //\r
624 return EFI_SUCCESS;\r
625 }\r
626\r
627 Property = VariablePropertyGetFunction (VariableName, VendorGuid, TRUE);\r
d2dbe5b7
SZ
628 //\r
629 // Also check the property revision before using the property data.\r
630 // There is no property set to this variable(wildcard name)\r
631 // if the revision is not VAR_CHECK_VARIABLE_PROPERTY_REVISION.\r
632 //\r
633 if ((Property != NULL) && (Property->Revision == VAR_CHECK_VARIABLE_PROPERTY_REVISION)) {\r
31b183bc 634 if ((RequestSource != VarCheckFromTrusted) && ((Property->Property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) != 0)) {\r
87000d77 635 DEBUG ((DEBUG_INFO, "Variable Check ReadOnly variable fail %r - %g:%s\n", EFI_WRITE_PROTECTED, VendorGuid, VariableName));\r
31b183bc
SZ
636 return EFI_WRITE_PROTECTED;\r
637 }\r
1436aea4 638\r
31b183bc
SZ
639 if (!((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0))) {\r
640 //\r
641 // Not to delete variable.\r
642 //\r
643 if ((Property->Attributes != 0) && ((Attributes & (~EFI_VARIABLE_APPEND_WRITE)) != Property->Attributes)) {\r
87000d77 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));\r
31b183bc
SZ
645 return EFI_INVALID_PARAMETER;\r
646 }\r
1436aea4 647\r
31b183bc
SZ
648 if (DataSize != 0) {\r
649 if ((DataSize < Property->MinSize) || (DataSize > Property->MaxSize)) {\r
87000d77 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));\r
31b183bc
SZ
651 return EFI_INVALID_PARAMETER;\r
652 }\r
653 }\r
654 }\r
655 }\r
656\r
657 for (Index = 0; Index < mNumberOfVarCheckHandler; Index++) {\r
1436aea4
MK
658 Status = mVarCheckHandlerTable[Index](\r
659 VariableName,\r
660 VendorGuid,\r
661 Attributes,\r
662 DataSize,\r
663 Data\r
664 );\r
665 if ((Status == EFI_WRITE_PROTECTED) && (RequestSource == VarCheckFromTrusted)) {\r
248d08c5
MK
666 //\r
667 // If RequestSource is trusted, then allow variable to be set even if it\r
668 // is write protected.\r
669 //\r
670 continue;\r
671 }\r
1436aea4 672\r
31b183bc 673 if (EFI_ERROR (Status)) {\r
87000d77 674 DEBUG ((DEBUG_INFO, "Variable Check handler fail %r - %g:%s\n", Status, VendorGuid, VariableName));\r
31b183bc
SZ
675 return Status;\r
676 }\r
677 }\r
1436aea4 678\r
31b183bc
SZ
679 return EFI_SUCCESS;\r
680}\r