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