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