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