]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupLib.c
MdeModulePkg: Fix MSFT C4255 warning
[mirror_edk2.git] / MdeModulePkg / Library / PlatformVarCleanupLib / PlatVarCleanupLib.c
CommitLineData
c95d9ab8
SZ
1/** @file\r
2 Sample platform variable cleanup library implementation.\r
3\r
c103e09b 4Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
c95d9ab8
SZ
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 "PlatVarCleanup.h"\r
16\r
17VAR_ERROR_FLAG mLastVarErrorFlag = VAR_ERROR_FLAG_NO_ERROR;\r
18EDKII_VAR_CHECK_PROTOCOL *mVarCheck = NULL;\r
19\r
20///\r
21/// The flag to indicate whether the platform has left the DXE phase of execution.\r
22///\r
23BOOLEAN mEndOfDxe = FALSE;\r
24\r
c103e09b
HW
25EFI_EVENT mPlatVarCleanupLibEndOfDxeEvent = NULL;\r
26\r
c95d9ab8
SZ
27LIST_ENTRY mUserVariableList = INITIALIZE_LIST_HEAD_VARIABLE (mUserVariableList);\r
28UINT16 mUserVariableCount = 0;\r
29UINT16 mMarkedUserVariableCount = 0;\r
30\r
31EFI_GUID mVariableCleanupHiiGuid = VARIABLE_CLEANUP_HII_GUID;\r
32CHAR16 mVarStoreName[] = L"VariableCleanup";\r
33\r
34HII_VENDOR_DEVICE_PATH mVarCleanupHiiVendorDevicePath = {\r
35 {\r
36 {\r
37 HARDWARE_DEVICE_PATH,\r
38 HW_VENDOR_DP,\r
39 {\r
40 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
41 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
42 }\r
43 },\r
44 VARIABLE_CLEANUP_HII_GUID\r
45 },\r
46 {\r
47 END_DEVICE_PATH_TYPE,\r
48 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
49 {\r
50 (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)),\r
51 (UINT8) ((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8)\r
52 }\r
53 }\r
54};\r
55\r
56/**\r
57 Internal get variable error flag.\r
58\r
59 @return Variable error flag.\r
60\r
61**/\r
62VAR_ERROR_FLAG\r
63InternalGetVarErrorFlag (\r
64 VOID\r
65 )\r
66{\r
67 EFI_STATUS Status;\r
68 UINTN Size;\r
69 VAR_ERROR_FLAG ErrorFlag;\r
70\r
71 Size = sizeof (ErrorFlag);\r
72 Status = gRT->GetVariable (\r
73 VAR_ERROR_FLAG_NAME,\r
74 &gEdkiiVarErrorFlagGuid,\r
75 NULL,\r
76 &Size,\r
77 &ErrorFlag\r
78 );\r
79 if (EFI_ERROR (Status)) {\r
80 DEBUG ((EFI_D_INFO, "%s - not found\n", VAR_ERROR_FLAG_NAME));\r
81 return VAR_ERROR_FLAG_NO_ERROR;\r
82 }\r
83 return ErrorFlag;\r
84}\r
85\r
86/**\r
87 Is user variable?\r
88\r
89 @param[in] Name Pointer to variable name.\r
90 @param[in] Guid Pointer to vendor guid.\r
91\r
92 @retval TRUE User variable.\r
93 @retval FALSE System variable.\r
94\r
95**/\r
96BOOLEAN\r
97IsUserVariable (\r
98 IN CHAR16 *Name,\r
99 IN EFI_GUID *Guid\r
100 )\r
101{\r
102 EFI_STATUS Status;\r
103 VAR_CHECK_VARIABLE_PROPERTY Property;\r
104\r
58f025af
SZ
105 if (mVarCheck == NULL) {\r
106 gBS->LocateProtocol (\r
107 &gEdkiiVarCheckProtocolGuid,\r
108 NULL,\r
109 (VOID **) &mVarCheck\r
110 );\r
111 }\r
112 ASSERT (mVarCheck != NULL);\r
113\r
c95d9ab8
SZ
114 ZeroMem (&Property, sizeof (Property));\r
115 Status = mVarCheck->VariablePropertyGet (\r
116 Name,\r
117 Guid,\r
118 &Property\r
119 );\r
120 if (EFI_ERROR (Status)) {\r
121 //\r
122 // No property, it is user variable.\r
123 //\r
124 DEBUG ((EFI_D_INFO, "PlatformVarCleanup - User variable: %g:%s\n", Guid, Name));\r
125 return TRUE;\r
126 }\r
127\r
128// DEBUG ((EFI_D_INFO, "PlatformVarCleanup - Variable Property: %g:%s\n", Guid, Name));\r
129// DEBUG ((EFI_D_INFO, " Revision - 0x%04x\n", Property.Revision));\r
130// DEBUG ((EFI_D_INFO, " Property - 0x%04x\n", Property.Property));\r
131// DEBUG ((EFI_D_INFO, " Attribute - 0x%08x\n", Property.Attributes));\r
132// DEBUG ((EFI_D_INFO, " MinSize - 0x%x\n", Property.MinSize));\r
133// DEBUG ((EFI_D_INFO, " MaxSize - 0x%x\n", Property.MaxSize));\r
134\r
135 return FALSE;\r
136}\r
137\r
138/**\r
139 Find user variable node by variable GUID.\r
140\r
141 @param[in] Guid Pointer to vendor guid.\r
142\r
143 @return Pointer to user variable node.\r
144\r
145**/\r
146USER_VARIABLE_NODE *\r
147FindUserVariableNodeByGuid (\r
148 IN EFI_GUID *Guid\r
149 )\r
150{\r
151 USER_VARIABLE_NODE *UserVariableNode;\r
152 LIST_ENTRY *Link;\r
153\r
154 for (Link = mUserVariableList.ForwardLink\r
155 ;Link != &mUserVariableList\r
156 ;Link = Link->ForwardLink) {\r
157 UserVariableNode = USER_VARIABLE_FROM_LINK (Link);\r
158\r
159 if (CompareGuid (Guid, &UserVariableNode->Guid)) {\r
160 //\r
161 // Found it.\r
162 //\r
163 return UserVariableNode;\r
164 }\r
165 }\r
166\r
167 //\r
168 // Create new one if not found.\r
169 //\r
170 UserVariableNode = AllocateZeroPool (sizeof (*UserVariableNode));\r
171 ASSERT (UserVariableNode != NULL);\r
172 UserVariableNode->Signature = USER_VARIABLE_NODE_SIGNATURE;\r
173 CopyGuid (&UserVariableNode->Guid, Guid);\r
174 //\r
175 // (36 chars of "########-####-####-####-############" + 1 space + 1 terminator) * sizeof (CHAR16).\r
176 //\r
177 UserVariableNode->PromptString = AllocatePool ((36 + 2) * sizeof (CHAR16));\r
178 ASSERT (UserVariableNode->PromptString != NULL);\r
179 UnicodeSPrint (UserVariableNode->PromptString, (36 + 2) * sizeof (CHAR16), L" %g", &UserVariableNode->Guid);\r
180 InitializeListHead (&UserVariableNode->NameLink);\r
181 InsertTailList (&mUserVariableList, &UserVariableNode->Link);\r
182 return UserVariableNode;\r
183}\r
184\r
185/**\r
186 Create user variable node.\r
187\r
188**/\r
189VOID\r
190CreateUserVariableNode (\r
191 VOID\r
192 )\r
193{\r
194 EFI_STATUS Status;\r
195 EFI_STATUS GetVariableStatus;\r
196 CHAR16 *VarName;\r
197 UINTN MaxVarNameSize;\r
198 UINTN VarNameSize;\r
199 UINTN MaxDataSize;\r
200 UINTN DataSize;\r
201 VOID *Data;\r
202 UINT32 Attributes;\r
203 EFI_GUID Guid;\r
204 USER_VARIABLE_NODE *UserVariableNode;\r
205 USER_VARIABLE_NAME_NODE *UserVariableNameNode;\r
206 UINT16 Index;\r
207 UINTN StringSize;\r
208\r
209 //\r
210 // Initialize 128 * sizeof (CHAR16) variable name size.\r
211 //\r
212 MaxVarNameSize = 128 * sizeof (CHAR16);\r
213 VarName = AllocateZeroPool (MaxVarNameSize);\r
214 ASSERT (VarName != NULL);\r
215\r
216 //\r
217 // Initialize 0x1000 variable data size.\r
218 //\r
219 MaxDataSize = 0x1000;\r
220 Data = AllocateZeroPool (MaxDataSize);\r
221 ASSERT (Data != NULL);\r
222\r
223 Index = 0;\r
224 do {\r
225 VarNameSize = MaxVarNameSize;\r
226 Status = gRT->GetNextVariableName (&VarNameSize, VarName, &Guid);\r
227 if (Status == EFI_BUFFER_TOO_SMALL) {\r
228 VarName = ReallocatePool (MaxVarNameSize, VarNameSize, VarName);\r
229 ASSERT (VarName != NULL);\r
230 MaxVarNameSize = VarNameSize;\r
231 Status = gRT->GetNextVariableName (&VarNameSize, VarName, &Guid);\r
232 }\r
233\r
234 if (!EFI_ERROR (Status)) {\r
235 if (IsUserVariable (VarName, &Guid)) {\r
236 DataSize = MaxDataSize;\r
237 GetVariableStatus = gRT->GetVariable (VarName, &Guid, &Attributes, &DataSize, Data);\r
238 if (GetVariableStatus == EFI_BUFFER_TOO_SMALL) {\r
239 Data = ReallocatePool (MaxDataSize, DataSize, Data);\r
240 ASSERT (Data != NULL);\r
241 MaxDataSize = DataSize;\r
242 GetVariableStatus = gRT->GetVariable (VarName, &Guid, &Attributes, &DataSize, Data);\r
243 }\r
244 ASSERT_EFI_ERROR (GetVariableStatus);\r
245\r
246 if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
247 UserVariableNode = FindUserVariableNodeByGuid (&Guid);\r
248 ASSERT (UserVariableNode != NULL);\r
249\r
250 //\r
251 // Different variables that have same variable GUID share same user variable node.\r
252 //\r
253 UserVariableNameNode = AllocateZeroPool (sizeof (*UserVariableNameNode));\r
254 ASSERT (UserVariableNameNode != NULL);\r
255 UserVariableNameNode->Signature = USER_VARIABLE_NAME_NODE_SIGNATURE;\r
256 UserVariableNameNode->Name = AllocateCopyPool (VarNameSize, VarName);\r
257 UserVariableNameNode->Attributes = Attributes;\r
258 UserVariableNameNode->DataSize = DataSize;\r
259 UserVariableNameNode->Index = Index;\r
260 UserVariableNameNode->QuestionId = (EFI_QUESTION_ID) (USER_VARIABLE_QUESTION_ID + Index);\r
261 //\r
262 // 2 space * sizeof (CHAR16) + StrSize.\r
263 //\r
264 StringSize = 2 * sizeof (CHAR16) + StrSize (UserVariableNameNode->Name);\r
265 UserVariableNameNode->PromptString = AllocatePool (StringSize);\r
266 ASSERT (UserVariableNameNode->PromptString != NULL);\r
267 UnicodeSPrint (UserVariableNameNode->PromptString, StringSize, L" %s", UserVariableNameNode->Name);\r
268 //\r
269 // (33 chars of "Attribtues = 0x and DataSize = 0x" + 1 terminator + (sizeof (UINT32) + sizeof (UINTN)) * 2) * sizeof (CHAR16).\r
270 //\r
271 StringSize = (33 + 1 + (sizeof (UINT32) + sizeof (UINTN)) * 2) * sizeof (CHAR16);\r
272 UserVariableNameNode->HelpString = AllocatePool (StringSize);\r
273 ASSERT (UserVariableNameNode->HelpString != NULL);\r
274 UnicodeSPrint (UserVariableNameNode->HelpString, StringSize, L"Attribtues = 0x%08x and DataSize = 0x%x", UserVariableNameNode->Attributes, UserVariableNameNode->DataSize);\r
275 UserVariableNameNode->Deleted = FALSE;\r
276 InsertTailList (&UserVariableNode->NameLink, &UserVariableNameNode->Link);\r
277 Index++;\r
278 }\r
279 }\r
280 }\r
281 } while (Status != EFI_NOT_FOUND);\r
282\r
283 mUserVariableCount = Index;\r
284 ASSERT (mUserVariableCount <= MAX_USER_VARIABLE_COUNT);\r
285 DEBUG ((EFI_D_INFO, "PlatformVarCleanup - User variable count: 0x%04x\n", mUserVariableCount));\r
286\r
287 FreePool (VarName);\r
288 FreePool (Data);\r
289}\r
290\r
291/**\r
292 Destroy user variable nodes.\r
293\r
294**/\r
295VOID\r
296DestroyUserVariableNode (\r
297 VOID\r
298 )\r
299{\r
300 USER_VARIABLE_NODE *UserVariableNode;\r
301 LIST_ENTRY *Link;\r
302 USER_VARIABLE_NAME_NODE *UserVariableNameNode;\r
303 LIST_ENTRY *NameLink;\r
304\r
305 while (mUserVariableList.ForwardLink != &mUserVariableList) {\r
306 Link = mUserVariableList.ForwardLink;\r
307 UserVariableNode = USER_VARIABLE_FROM_LINK (Link);\r
308\r
309 RemoveEntryList (&UserVariableNode->Link);\r
310\r
311 while (UserVariableNode->NameLink.ForwardLink != &UserVariableNode->NameLink) {\r
312 NameLink = UserVariableNode->NameLink.ForwardLink;\r
313 UserVariableNameNode = USER_VARIABLE_NAME_FROM_LINK (NameLink);\r
314\r
315 RemoveEntryList (&UserVariableNameNode->Link);\r
316\r
317 FreePool (UserVariableNameNode->Name);\r
318 FreePool (UserVariableNameNode->PromptString);\r
319 FreePool (UserVariableNameNode->HelpString);\r
320 FreePool (UserVariableNameNode);\r
321 }\r
322\r
323 FreePool (UserVariableNode->PromptString);\r
324 FreePool (UserVariableNode);\r
325 }\r
326}\r
327\r
328/**\r
329 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2\r
330 descriptor with the input data. NO authentication is required in this function.\r
331\r
332 @param[in, out] DataSize On input, the size of Data buffer in bytes.\r
333 On output, the size of data returned in Data\r
334 buffer in bytes.\r
335 @param[in, out] Data On input, Pointer to data buffer to be wrapped or\r
336 pointer to NULL to wrap an empty payload.\r
337 On output, Pointer to the new payload date buffer allocated from pool,\r
338 it's caller's responsibility to free the memory after using it.\r
339\r
340 @retval EFI_SUCCESS Create time based payload successfully.\r
341 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.\r
342 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
343 @retval Others Unexpected error happens.\r
344\r
345**/\r
346EFI_STATUS\r
347CreateTimeBasedPayload (\r
348 IN OUT UINTN *DataSize,\r
349 IN OUT UINT8 **Data\r
350 )\r
351{\r
352 EFI_STATUS Status;\r
353 UINT8 *NewData;\r
354 UINT8 *Payload;\r
355 UINTN PayloadSize;\r
356 EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;\r
357 UINTN DescriptorSize;\r
358 EFI_TIME Time;\r
359\r
360 if (Data == NULL || DataSize == NULL) {\r
361 return EFI_INVALID_PARAMETER;\r
362 }\r
363\r
364 //\r
365 // At user physical presence, the variable does not need to be signed but the\r
366 // parameters to the SetVariable() call still need to be prepared as authenticated\r
367 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate\r
368 // data in it.\r
369 //\r
370 Payload = *Data;\r
371 PayloadSize = *DataSize;\r
372\r
373 DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);\r
374 NewData = (UINT8 *) AllocateZeroPool (DescriptorSize + PayloadSize);\r
375 if (NewData == NULL) {\r
376 return EFI_OUT_OF_RESOURCES;\r
377 }\r
378\r
379 if ((Payload != NULL) && (PayloadSize != 0)) {\r
380 CopyMem (NewData + DescriptorSize, Payload, PayloadSize);\r
381 }\r
382\r
383 DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);\r
384\r
385 ZeroMem (&Time, sizeof (EFI_TIME));\r
386 Status = gRT->GetTime (&Time, NULL);\r
387 if (EFI_ERROR (Status)) {\r
388 FreePool (NewData);\r
389 return Status;\r
390 }\r
391 Time.Pad1 = 0;\r
392 Time.Nanosecond = 0;\r
393 Time.TimeZone = 0;\r
394 Time.Daylight = 0;\r
395 Time.Pad2 = 0;\r
396 CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));\r
397\r
398 DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);\r
399 DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;\r
400 DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;\r
401 CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);\r
402\r
403 if (Payload != NULL) {\r
404 FreePool (Payload);\r
405 }\r
406\r
407 *DataSize = DescriptorSize + PayloadSize;\r
408 *Data = NewData;\r
409 return EFI_SUCCESS;\r
410}\r
411\r
412/**\r
413 Create a counter based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION\r
414 descriptor with the input data. NO authentication is required in this function.\r
415\r
416 @param[in, out] DataSize On input, the size of Data buffer in bytes.\r
417 On output, the size of data returned in Data\r
418 buffer in bytes.\r
419 @param[in, out] Data On input, Pointer to data buffer to be wrapped or\r
420 pointer to NULL to wrap an empty payload.\r
421 On output, Pointer to the new payload date buffer allocated from pool,\r
422 it's caller's responsibility to free the memory after using it.\r
423\r
424 @retval EFI_SUCCESS Create counter based payload successfully.\r
425 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.\r
426 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
427 @retval Others Unexpected error happens.\r
428\r
429**/\r
430EFI_STATUS\r
431CreateCounterBasedPayload (\r
432 IN OUT UINTN *DataSize,\r
433 IN OUT UINT8 **Data\r
434 )\r
435{\r
436 EFI_STATUS Status;\r
437 UINT8 *NewData;\r
438 UINT8 *Payload;\r
439 UINTN PayloadSize;\r
440 EFI_VARIABLE_AUTHENTICATION *DescriptorData;\r
441 UINTN DescriptorSize;\r
442 UINT64 MonotonicCount;\r
443\r
444 if (Data == NULL || DataSize == NULL) {\r
445 return EFI_INVALID_PARAMETER;\r
446 }\r
447\r
448 //\r
449 // At user physical presence, the variable does not need to be signed but the\r
450 // parameters to the SetVariable() call still need to be prepared as authenticated\r
451 // variable. So we create EFI_VARIABLE_AUTHENTICATED descriptor without certificate\r
452 // data in it.\r
453 //\r
454 Payload = *Data;\r
455 PayloadSize = *DataSize;\r
456\r
457 DescriptorSize = (OFFSET_OF (EFI_VARIABLE_AUTHENTICATION, AuthInfo)) + \\r
458 (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) + \\r
459 sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256);\r
460 NewData = (UINT8 *) AllocateZeroPool (DescriptorSize + PayloadSize);\r
461 if (NewData == NULL) {\r
462 return EFI_OUT_OF_RESOURCES;\r
463 }\r
464\r
465 if ((Payload != NULL) && (PayloadSize != 0)) {\r
466 CopyMem (NewData + DescriptorSize, Payload, PayloadSize);\r
467 }\r
468\r
469 DescriptorData = (EFI_VARIABLE_AUTHENTICATION *) (NewData);\r
470\r
471 Status = gBS->GetNextMonotonicCount (&MonotonicCount);\r
472 if (EFI_ERROR (Status)) {\r
473 FreePool (NewData);\r
474 return Status;\r
475 }\r
476 DescriptorData->MonotonicCount = MonotonicCount;\r
477\r
478 DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData) + sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256);\r
479 DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;\r
480 DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;\r
481 CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertTypeRsa2048Sha256Guid);\r
482\r
483 if (Payload != NULL) {\r
484 FreePool (Payload);\r
485 }\r
486\r
487 *DataSize = DescriptorSize + PayloadSize;\r
488 *Data = NewData;\r
489 return EFI_SUCCESS;\r
490}\r
491\r
492/**\r
493 Delete user variable.\r
494\r
495 @param[in] DeleteAll Delete all user variables.\r
496 @param[in] VariableCleanupData Pointer to variable cleanup data.\r
497\r
498**/\r
499VOID\r
500DeleteUserVariable (\r
501 IN BOOLEAN DeleteAll,\r
502 IN VARIABLE_CLEANUP_DATA *VariableCleanupData OPTIONAL\r
503 )\r
504{\r
505 EFI_STATUS Status;\r
506 USER_VARIABLE_NODE *UserVariableNode;\r
507 LIST_ENTRY *Link;\r
508 USER_VARIABLE_NAME_NODE *UserVariableNameNode;\r
509 LIST_ENTRY *NameLink;\r
510 UINTN DataSize;\r
511 UINT8 *Data;\r
512\r
513 for (Link = mUserVariableList.ForwardLink\r
514 ;Link != &mUserVariableList\r
515 ;Link = Link->ForwardLink) {\r
516 UserVariableNode = USER_VARIABLE_FROM_LINK (Link);\r
517\r
518 for (NameLink = UserVariableNode->NameLink.ForwardLink\r
519 ;NameLink != &UserVariableNode->NameLink\r
520 ;NameLink = NameLink->ForwardLink) {\r
521 UserVariableNameNode = USER_VARIABLE_NAME_FROM_LINK (NameLink);\r
522\r
523 if (!UserVariableNameNode->Deleted && (DeleteAll || ((VariableCleanupData != NULL) && (VariableCleanupData->UserVariable[UserVariableNameNode->Index] == TRUE)))) {\r
524 DEBUG ((EFI_D_INFO, "PlatformVarCleanup - Delete variable: %g:%s\n", &UserVariableNode->Guid, UserVariableNameNode->Name));\r
525 if ((UserVariableNameNode->Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
526 DataSize = 0;\r
527 Data = NULL;\r
528 Status = CreateTimeBasedPayload (&DataSize, &Data);\r
529 if (!EFI_ERROR (Status)) {\r
530 Status = gRT->SetVariable (UserVariableNameNode->Name, &UserVariableNode->Guid, UserVariableNameNode->Attributes, DataSize, Data);\r
531 FreePool (Data);\r
532 }\r
533 } else if ((UserVariableNameNode->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
534 DataSize = 0;\r
535 Data = NULL;\r
536 Status = CreateCounterBasedPayload (&DataSize, &Data);\r
537 if (!EFI_ERROR (Status)) {\r
538 Status = gRT->SetVariable (UserVariableNameNode->Name, &UserVariableNode->Guid, UserVariableNameNode->Attributes, DataSize, Data);\r
539 FreePool (Data);\r
540 }\r
541 } else {\r
542 Status = gRT->SetVariable (UserVariableNameNode->Name, &UserVariableNode->Guid, 0, 0, NULL);\r
543 }\r
544 if (!EFI_ERROR (Status)) {\r
545 UserVariableNameNode->Deleted = TRUE;\r
546 } else {\r
547 DEBUG ((EFI_D_INFO, "PlatformVarCleanup - Delete variable fail: %g:%s\n", &UserVariableNode->Guid, UserVariableNameNode->Name));\r
548 }\r
549 }\r
550 }\r
551 }\r
552}\r
553\r
554/**\r
555 This function allows a caller to extract the current configuration for one\r
556 or more named elements from the target driver.\r
557\r
558 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
559 @param[in] Request A null-terminated Unicode string in <ConfigRequest> format.\r
560 @param[out] Progress On return, points to a character in the Request string.\r
561 Points to the string's null terminator if request was successful.\r
562 Points to the most recent '&' before the first failing name/value\r
563 pair (or the beginning of the string if the failure is in the\r
564 first name/value pair) if the request was not successful.\r
565 @param[out] Results A null-terminated Unicode string in <ConfigAltResp> format which\r
566 has all values filled in for the names in the Request string.\r
567 String to be allocated by the called function.\r
568\r
569 @retval EFI_SUCCESS The Results is filled with the requested values.\r
570 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
571 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.\r
572 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
573\r
574**/\r
575EFI_STATUS\r
576EFIAPI\r
577VariableCleanupHiiExtractConfig (\r
578 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
579 IN CONST EFI_STRING Request,\r
580 OUT EFI_STRING *Progress,\r
581 OUT EFI_STRING *Results\r
582 )\r
583{\r
584 EFI_STATUS Status;\r
585 VARIABLE_CLEANUP_HII_PRIVATE_DATA *Private;\r
586 UINTN BufferSize;\r
587 EFI_STRING ConfigRequestHdr;\r
588 EFI_STRING ConfigRequest;\r
589 BOOLEAN AllocatedRequest;\r
590 UINTN Size;\r
591\r
592 if (Progress == NULL || Results == NULL) {\r
593 return EFI_INVALID_PARAMETER;\r
594 }\r
595\r
596 *Progress = Request;\r
597 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mVariableCleanupHiiGuid, mVarStoreName)) {\r
598 return EFI_NOT_FOUND;\r
599 }\r
600\r
601 ConfigRequestHdr = NULL;\r
602 ConfigRequest = NULL;\r
603 AllocatedRequest = FALSE;\r
604 Size = 0;\r
605\r
606 Private = VARIABLE_CLEANUP_HII_PRIVATE_FROM_THIS (This);\r
607 //\r
608 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().\r
609 //\r
610 BufferSize = sizeof (VARIABLE_CLEANUP_DATA);\r
611 ConfigRequest = Request;\r
612 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
613 //\r
614 // Request has no request element, construct full request string.\r
615 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
616 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator.\r
617 //\r
618 ConfigRequestHdr = HiiConstructConfigHdr (&mVariableCleanupHiiGuid, mVarStoreName, Private->HiiHandle);\r
619 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
620 ConfigRequest = AllocateZeroPool (Size);\r
621 ASSERT (ConfigRequest != NULL);\r
622 AllocatedRequest = TRUE;\r
623 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
624 FreePool (ConfigRequestHdr);\r
625 }\r
626\r
627 Status = Private->ConfigRouting->BlockToConfig (\r
628 Private->ConfigRouting,\r
629 ConfigRequest,\r
630 (UINT8 *) &Private->VariableCleanupData,\r
631 BufferSize,\r
632 Results,\r
633 Progress\r
634 );\r
635 ASSERT_EFI_ERROR (Status);\r
636\r
637 //\r
638 // Free the allocated config request string.\r
639 //\r
640 if (AllocatedRequest) {\r
641 FreePool (ConfigRequest);\r
642 ConfigRequest = NULL;\r
643 }\r
644 //\r
645 // Set Progress string to the original request string or the string's null terminator.\r
646 //\r
647 if (Request == NULL) {\r
648 *Progress = NULL;\r
649 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
650 *Progress = Request + StrLen (Request);\r
651 }\r
652\r
653 return Status;\r
654}\r
655\r
656/**\r
657 Update user variable form.\r
658\r
659 @param[in] Private Points to the VARIABLE_CLEANUP_HII_PRIVATE_DATA.\r
660\r
661**/\r
662VOID\r
663UpdateUserVariableForm (\r
664 IN VARIABLE_CLEANUP_HII_PRIVATE_DATA *Private\r
665 )\r
666{\r
667 EFI_STRING_ID PromptStringToken;\r
668 EFI_STRING_ID HelpStringToken;\r
669 VOID *StartOpCodeHandle;\r
670 VOID *EndOpCodeHandle;\r
671 EFI_IFR_GUID_LABEL *StartLabel;\r
672 EFI_IFR_GUID_LABEL *EndLabel;\r
673 USER_VARIABLE_NODE *UserVariableNode;\r
674 LIST_ENTRY *Link;\r
675 USER_VARIABLE_NAME_NODE *UserVariableNameNode;\r
676 LIST_ENTRY *NameLink;\r
677 BOOLEAN Created;\r
678\r
679 //\r
680 // Init OpCode Handle.\r
681 //\r
682 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
683 ASSERT (StartOpCodeHandle != NULL);\r
684\r
685 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
686 ASSERT (EndOpCodeHandle != NULL);\r
687\r
688 //\r
689 // Create Hii Extend Label OpCode as the start opcode.\r
690 //\r
691 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
692 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
693 StartLabel->Number = LABEL_START;\r
694\r
695 //\r
696 // Create Hii Extend Label OpCode as the end opcode.\r
697 //\r
698 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
699 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
700 EndLabel->Number = LABEL_END;\r
701\r
702 HiiUpdateForm (\r
703 Private->HiiHandle,\r
704 &mVariableCleanupHiiGuid,\r
705 FORM_ID_VARIABLE_CLEANUP,\r
706 StartOpCodeHandle, // LABEL_START\r
707 EndOpCodeHandle // LABEL_END\r
708 );\r
709\r
710 for (Link = mUserVariableList.ForwardLink\r
711 ;Link != &mUserVariableList\r
712 ;Link = Link->ForwardLink) {\r
713 UserVariableNode = USER_VARIABLE_FROM_LINK (Link);\r
714\r
715 //\r
716 // Create checkbox opcode for variables in the same variable GUID space.\r
717 //\r
718 Created = FALSE;\r
719 for (NameLink = UserVariableNode->NameLink.ForwardLink\r
720 ;NameLink != &UserVariableNode->NameLink\r
721 ;NameLink = NameLink->ForwardLink) {\r
722 UserVariableNameNode = USER_VARIABLE_NAME_FROM_LINK (NameLink);\r
723\r
724 if (!UserVariableNameNode->Deleted) {\r
725 if (!Created) {\r
726 //\r
727 // Create subtitle opcode for variable GUID.\r
728 //\r
729 PromptStringToken = HiiSetString (Private->HiiHandle, 0, UserVariableNode->PromptString, NULL);\r
730 HiiCreateSubTitleOpCode (StartOpCodeHandle, PromptStringToken, 0, 0, 0);\r
731 Created = TRUE;\r
732 }\r
733\r
734 //\r
735 // Only create opcode for the non-deleted variables.\r
736 //\r
737 PromptStringToken = HiiSetString (Private->HiiHandle, 0, UserVariableNameNode->PromptString, NULL);\r
738 HelpStringToken = HiiSetString (Private->HiiHandle, 0, UserVariableNameNode->HelpString, NULL);\r
739 HiiCreateCheckBoxOpCode (\r
740 StartOpCodeHandle,\r
741 UserVariableNameNode->QuestionId,\r
742 VARIABLE_CLEANUP_VARSTORE_ID,\r
743 (UINT16) (USER_VARIABLE_VAR_OFFSET + UserVariableNameNode->Index),\r
744 PromptStringToken,\r
745 HelpStringToken,\r
746 EFI_IFR_FLAG_CALLBACK,\r
747 Private->VariableCleanupData.UserVariable[UserVariableNameNode->Index],\r
748 NULL\r
749 );\r
750 }\r
751 }\r
752 }\r
753\r
754 HiiCreateSubTitleOpCode (\r
755 StartOpCodeHandle,\r
756 STRING_TOKEN (STR_NULL_STRING),\r
757 0,\r
758 0,\r
759 0\r
760 );\r
761\r
762 //\r
763 // Create the "Apply changes" and "Discard changes" tags.\r
764 //\r
765 HiiCreateActionOpCode (\r
766 StartOpCodeHandle,\r
767 SAVE_AND_EXIT_QUESTION_ID,\r
768 STRING_TOKEN (STR_SAVE_AND_EXIT),\r
769 STRING_TOKEN (STR_NULL_STRING),\r
770 EFI_IFR_FLAG_CALLBACK,\r
771 0\r
772 );\r
773 HiiCreateActionOpCode (\r
774 StartOpCodeHandle,\r
775 NO_SAVE_AND_EXIT_QUESTION_ID,\r
776 STRING_TOKEN (STR_NO_SAVE_AND_EXIT),\r
777 STRING_TOKEN (STR_NULL_STRING),\r
778 EFI_IFR_FLAG_CALLBACK,\r
779 0\r
780 );\r
781\r
782 HiiUpdateForm (\r
783 Private->HiiHandle,\r
784 &mVariableCleanupHiiGuid,\r
785 FORM_ID_VARIABLE_CLEANUP,\r
786 StartOpCodeHandle, // LABEL_START\r
787 EndOpCodeHandle // LABEL_END\r
788 );\r
789\r
790 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
791 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
792}\r
793\r
794/**\r
795 This function applies changes in a driver's configuration.\r
796 Input is a Configuration, which has the routing data for this\r
797 driver followed by name / value configuration pairs. The driver\r
798 must apply those pairs to its configurable storage. If the\r
799 driver's configuration is stored in a linear block of data\r
800 and the driver's name / value pairs are in <BlockConfig>\r
801 format, it may use the ConfigToBlock helper function (above) to\r
802 simplify the job. Currently not implemented.\r
803\r
804 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
805 @param[in] Configuration A null-terminated Unicode string in\r
806 <ConfigString> format.\r
807 @param[out] Progress A pointer to a string filled in with the\r
808 offset of the most recent '&' before the\r
809 first failing name / value pair (or the\r
810 beginn ing of the string if the failure\r
811 is in the first name / value pair) or\r
812 the terminating NULL if all was\r
813 successful.\r
814\r
815 @retval EFI_SUCCESS The results have been distributed or are\r
816 awaiting distribution.\r
817 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
818 parts of the results that must be\r
819 stored awaiting possible future\r
820 protocols.\r
821 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
822 Results parameter would result\r
823 in this type of error.\r
824 @retval EFI_NOT_FOUND Target for the specified routing data\r
825 was not found.\r
826\r
827**/\r
828EFI_STATUS\r
829EFIAPI\r
830VariableCleanupHiiRouteConfig (\r
831 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
832 IN CONST EFI_STRING Configuration,\r
833 OUT EFI_STRING *Progress\r
834 )\r
835{\r
836 EFI_STATUS Status;\r
837 VARIABLE_CLEANUP_HII_PRIVATE_DATA *Private;\r
838 UINTN BufferSize;\r
839\r
840 if (Progress == NULL) {\r
841 return EFI_INVALID_PARAMETER;\r
842 }\r
843 *Progress = Configuration;\r
844\r
845 if (Configuration == NULL) {\r
846 return EFI_INVALID_PARAMETER;\r
847 }\r
848\r
849 //\r
850 // Check routing data in <ConfigHdr>.\r
851 // Note: there is no name for Name/Value storage, only GUID will be checked.\r
852 //\r
853 if (!HiiIsConfigHdrMatch (Configuration, &mVariableCleanupHiiGuid, mVarStoreName)) {\r
854 return EFI_NOT_FOUND;\r
855 }\r
856\r
857 Private = VARIABLE_CLEANUP_HII_PRIVATE_FROM_THIS (This);\r
858 //\r
859 // Get Buffer Storage data.\r
860 //\r
861 BufferSize = sizeof (VARIABLE_CLEANUP_DATA);\r
862 //\r
863 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().\r
864 //\r
865 Status = Private->ConfigRouting->ConfigToBlock (\r
866 Private->ConfigRouting,\r
867 Configuration,\r
868 (UINT8 *) &Private->VariableCleanupData,\r
869 &BufferSize,\r
870 Progress\r
871 );\r
872 ASSERT_EFI_ERROR (Status);\r
873\r
874 DeleteUserVariable (FALSE, &Private->VariableCleanupData);\r
875 //\r
876 // For "F10" hotkey to refresh the form.\r
877 //\r
878// UpdateUserVariableForm (Private);\r
879\r
880 return EFI_SUCCESS;\r
881}\r
882\r
883/**\r
884 This function is called to provide results data to the driver.\r
885 This data consists of a unique key that is used to identify\r
886 which data is either being passed back or being asked for.\r
887\r
888 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
889 @param[in] Action Specifies the type of action taken by the browser.\r
890 @param[in] QuestionId A unique value which is sent to the original\r
891 exporting driver so that it can identify the type\r
892 of data to expect. The format of the data tends to\r
893 vary based on the opcode that generated the callback.\r
894 @param[in] Type The type of value for the question.\r
895 @param[in] Value A pointer to the data being sent to the original\r
896 exporting driver.\r
897 @param[out] ActionRequest On return, points to the action requested by the\r
898 callback function.\r
899\r
900 @retval EFI_SUCCESS The callback successfully handled the action.\r
901 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
902 variable and its data.\r
903 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
904 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
905 callback.\r
906**/\r
907EFI_STATUS\r
908EFIAPI\r
909VariableCleanupHiiCallback (\r
910 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
911 IN EFI_BROWSER_ACTION Action,\r
912 IN EFI_QUESTION_ID QuestionId,\r
913 IN UINT8 Type,\r
914 IN EFI_IFR_TYPE_VALUE *Value,\r
915 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
916 )\r
917{\r
918 VARIABLE_CLEANUP_HII_PRIVATE_DATA *Private;\r
919 VARIABLE_CLEANUP_DATA *VariableCleanupData;\r
920\r
921 Private = VARIABLE_CLEANUP_HII_PRIVATE_FROM_THIS (This);\r
922\r
923 if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {\r
924 //\r
925 // All other action return unsupported.\r
926 //\r
927 return EFI_UNSUPPORTED;\r
928 }\r
929\r
930 //\r
3b28e744 931 // Retrieve uncommitted data from Form Browser.\r
c95d9ab8
SZ
932 //\r
933 VariableCleanupData = &Private->VariableCleanupData;\r
934 HiiGetBrowserData (&mVariableCleanupHiiGuid, mVarStoreName, sizeof (VARIABLE_CLEANUP_DATA), (UINT8 *) VariableCleanupData);\r
935 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
936 if (Value == NULL) {\r
937 return EFI_INVALID_PARAMETER;\r
938 }\r
939 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
940 if ((Value == NULL) || (ActionRequest == NULL)) {\r
941 return EFI_INVALID_PARAMETER;\r
942 }\r
943 if ((QuestionId >= USER_VARIABLE_QUESTION_ID) && (QuestionId < USER_VARIABLE_QUESTION_ID + MAX_USER_VARIABLE_COUNT)) {\r
944 if (Value->b){\r
945 //\r
946 // Means one user variable checkbox is marked to delete but not press F10 or "Commit Changes and Exit" menu.\r
947 //\r
948 mMarkedUserVariableCount++;\r
949 ASSERT (mMarkedUserVariableCount <= mUserVariableCount);\r
950 if (mMarkedUserVariableCount == mUserVariableCount) {\r
951 //\r
952 // All user variables have been marked, then also mark the SelectAll checkbox.\r
953 //\r
954 VariableCleanupData->SelectAll = TRUE;\r
955 }\r
956 } else {\r
957 //\r
958 // Means one user variable checkbox is unmarked.\r
959 //\r
960 mMarkedUserVariableCount--;\r
961 //\r
962 // Also unmark the SelectAll checkbox.\r
963 //\r
964 VariableCleanupData->SelectAll = FALSE;\r
965 }\r
966 } else {\r
967 switch (QuestionId) {\r
968 case SELECT_ALL_QUESTION_ID:\r
969 if (Value->b){\r
970 //\r
971 // Means the SelectAll checkbox is marked to delete all user variables but not press F10 or "Commit Changes and Exit" menu.\r
972 //\r
973 SetMem (VariableCleanupData->UserVariable, sizeof (VariableCleanupData->UserVariable), TRUE);\r
974 mMarkedUserVariableCount = mUserVariableCount;\r
975 } else {\r
976 //\r
977 // Means the SelectAll checkbox is unmarked.\r
978 //\r
979 SetMem (VariableCleanupData->UserVariable, sizeof (VariableCleanupData->UserVariable), FALSE);\r
980 mMarkedUserVariableCount = 0;\r
981 }\r
982 break;\r
983 case SAVE_AND_EXIT_QUESTION_ID:\r
984 DeleteUserVariable (FALSE, VariableCleanupData);\r
985 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
986 break;\r
987\r
988 case NO_SAVE_AND_EXIT_QUESTION_ID:\r
989 //\r
990 // Restore local maintain data.\r
991 //\r
992 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
993 break;\r
994\r
995 default:\r
996 break;\r
997 }\r
998 }\r
999 }\r
1000\r
1001 //\r
1002 // Pass changed uncommitted data back to Form Browser.\r
1003 //\r
1004 HiiSetBrowserData (&mVariableCleanupHiiGuid, mVarStoreName, sizeof (VARIABLE_CLEANUP_DATA), (UINT8 *) VariableCleanupData, NULL);\r
1005 return EFI_SUCCESS;\r
1006}\r
1007\r
1008/**\r
1009 Platform variable cleanup.\r
1010\r
1011 @param[in] Flag Variable error flag.\r
1012 @param[in] Type Variable cleanup type.\r
1013 If it is VarCleanupManually, the interface must be called after console connected.\r
1014\r
1015 @retval EFI_SUCCESS No error or error processed.\r
1016 @retval EFI_UNSUPPORTED The specified Flag or Type is not supported.\r
1017 For example, system error may be not supported to process and Platform should have mechanism to reset system to manufacture mode.\r
1018 Another, if system and user variables are wanted to be distinguished to process, the interface must be called after EndOfDxe.\r
1019 @retval EFI_OUT_OF_RESOURCES Not enough resource to process the error.\r
1020 @retval EFI_INVALID_PARAMETER The specified Flag or Type is an invalid value.\r
1021 @retval Others Other failure occurs.\r
1022\r
1023**/\r
1024EFI_STATUS\r
1025EFIAPI\r
1026PlatformVarCleanup (\r
1027 IN VAR_ERROR_FLAG Flag,\r
1028 IN VAR_CLEANUP_TYPE Type\r
1029 )\r
1030{\r
1031 EFI_STATUS Status;\r
1032 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;\r
1033 VARIABLE_CLEANUP_HII_PRIVATE_DATA *Private;\r
1034\r
1035 if (!mEndOfDxe) {\r
1036 //\r
1037 // This implementation must be called after EndOfDxe.\r
1038 //\r
1039 return EFI_UNSUPPORTED;\r
1040 }\r
1041\r
1042 if ((Type >= VarCleanupMax) || ((Flag & ((VAR_ERROR_FLAG) (VAR_ERROR_FLAG_SYSTEM_ERROR & VAR_ERROR_FLAG_USER_ERROR))) == 0)) {\r
1043 return EFI_INVALID_PARAMETER;\r
1044 }\r
1045\r
1046 if (Flag == VAR_ERROR_FLAG_NO_ERROR) {\r
1047 //\r
1048 // Just return success if no error.\r
1049 //\r
1050 return EFI_SUCCESS;\r
1051 }\r
1052\r
1053 if ((Flag & (~((VAR_ERROR_FLAG) VAR_ERROR_FLAG_SYSTEM_ERROR))) == 0) {\r
1054 //\r
1055 // This sample does not support system variables cleanup.\r
1056 //\r
1057 DEBUG ((EFI_D_ERROR, "NOTICE - VAR_ERROR_FLAG_SYSTEM_ERROR\n"));\r
1058 DEBUG ((EFI_D_ERROR, "Platform should have mechanism to reset system to manufacture mode\n"));\r
1059 return EFI_UNSUPPORTED;\r
1060 }\r
1061\r
1062 //\r
1063 // Continue to process VAR_ERROR_FLAG_USER_ERROR.\r
1064 //\r
1065\r
1066 //\r
1067 // Create user variable nodes for the following processing.\r
1068 //\r
1069 CreateUserVariableNode ();\r
1070\r
1071 switch (Type) {\r
1072 case VarCleanupAll:\r
1073 DeleteUserVariable (TRUE, NULL);\r
1074 //\r
1075 // Destroyed the created user variable nodes\r
1076 //\r
1077 DestroyUserVariableNode ();\r
1078 return EFI_SUCCESS;\r
1079 break;\r
1080\r
1081 case VarCleanupManually:\r
1082 //\r
1083 // Locate FormBrowser2 protocol.\r
1084 //\r
1085 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);\r
1086 if (EFI_ERROR (Status)) {\r
1087 return Status;\r
1088 }\r
1089\r
1090 Private = AllocateZeroPool (sizeof (VARIABLE_CLEANUP_HII_PRIVATE_DATA));\r
1091 if (Private == NULL) {\r
1092 return EFI_OUT_OF_RESOURCES;\r
1093 }\r
1094\r
1095 Private->Signature = VARIABLE_CLEANUP_HII_PRIVATE_SIGNATURE;\r
1096 Private->ConfigAccess.ExtractConfig = VariableCleanupHiiExtractConfig;\r
1097 Private->ConfigAccess.RouteConfig = VariableCleanupHiiRouteConfig;\r
1098 Private->ConfigAccess.Callback = VariableCleanupHiiCallback;\r
1099\r
1100 Status = gBS->LocateProtocol (\r
1101 &gEfiHiiConfigRoutingProtocolGuid,\r
1102 NULL,\r
1103 (VOID **) &Private->ConfigRouting\r
1104 );\r
1105 if (EFI_ERROR (Status)) {\r
1106 goto Done;\r
1107 }\r
1108\r
1109 //\r
1110 // Install Device Path Protocol and Config Access protocol to driver handle.\r
1111 //\r
1112 Status = gBS->InstallMultipleProtocolInterfaces (\r
1113 &Private->DriverHandle,\r
1114 &gEfiDevicePathProtocolGuid,\r
1115 &mVarCleanupHiiVendorDevicePath,\r
1116 &gEfiHiiConfigAccessProtocolGuid,\r
1117 &Private->ConfigAccess,\r
1118 NULL\r
1119 );\r
1120 if (EFI_ERROR (Status)) {\r
1121 goto Done;\r
1122 }\r
1123\r
1124 //\r
1125 // Publish our HII data.\r
1126 //\r
1127 Private->HiiHandle = HiiAddPackages (\r
1128 &mVariableCleanupHiiGuid,\r
1129 Private->DriverHandle,\r
1130 PlatformVarCleanupLibStrings,\r
1131 PlatVarCleanupBin,\r
1132 NULL\r
1133 );\r
1134 if (Private->HiiHandle == NULL) {\r
1135 Status = EFI_OUT_OF_RESOURCES;\r
1136 goto Done;\r
1137 }\r
1138\r
1139 UpdateUserVariableForm (Private);\r
1140\r
1141 Status = FormBrowser2->SendForm (\r
1142 FormBrowser2,\r
1143 &Private->HiiHandle,\r
1144 1,\r
1145 NULL,\r
1146 0,\r
1147 NULL,\r
1148 NULL\r
1149 );\r
1150 break;\r
1151\r
1152 default:\r
1153 return EFI_UNSUPPORTED;\r
1154 break;\r
1155 }\r
1156\r
1157Done:\r
1158 if (Private->DriverHandle != NULL) {\r
1159 gBS->UninstallMultipleProtocolInterfaces (\r
1160 Private->DriverHandle,\r
1161 &gEfiDevicePathProtocolGuid,\r
1162 &mVarCleanupHiiVendorDevicePath,\r
1163 &gEfiHiiConfigAccessProtocolGuid,\r
1164 &Private->ConfigAccess,\r
1165 NULL\r
1166 );\r
1167 }\r
1168 if (Private->HiiHandle != NULL) {\r
1169 HiiRemovePackages (Private->HiiHandle);\r
1170 }\r
1171\r
1172 FreePool (Private);\r
1173\r
1174 //\r
1175 // Destroyed the created user variable nodes\r
1176 //\r
1177 DestroyUserVariableNode ();\r
1178 return Status;\r
1179}\r
1180\r
1181/**\r
1182 Get last boot variable error flag.\r
1183\r
1184 @return Last boot variable error flag.\r
1185\r
1186**/\r
1187VAR_ERROR_FLAG\r
1188EFIAPI\r
1189GetLastBootVarErrorFlag (\r
f826516d 1190 VOID\r
c95d9ab8
SZ
1191 )\r
1192{\r
1193 return mLastVarErrorFlag;\r
1194}\r
1195\r
1196/**\r
1197 Notification function of END_OF_DXE.\r
1198\r
1199 This is a notification function registered on END_OF_DXE event.\r
1200\r
1201 @param[in] Event Event whose notification function is being invoked.\r
1202 @param[in] Context Pointer to the notification function's context.\r
1203\r
1204**/\r
1205VOID\r
1206EFIAPI\r
1207PlatformVarCleanupEndOfDxeEvent (\r
1208 IN EFI_EVENT Event,\r
1209 IN VOID *Context\r
1210 )\r
1211{\r
1212 mEndOfDxe = TRUE;\r
1213}\r
1214\r
1215/**\r
1216 The constructor function caches the pointer to VarCheck protocol and last boot variable error flag.\r
1217\r
1218 The constructor function locates VarCheck protocol from protocol database.\r
1219 It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.\r
1220\r
1221 @param ImageHandle The firmware allocated handle for the EFI image.\r
1222 @param SystemTable A pointer to the EFI System Table.\r
1223\r
1224 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
1225\r
1226**/\r
1227EFI_STATUS\r
1228EFIAPI\r
1229PlatformVarCleanupLibConstructor (\r
1230 IN EFI_HANDLE ImageHandle,\r
1231 IN EFI_SYSTEM_TABLE *SystemTable\r
1232 )\r
1233{\r
1234 EFI_STATUS Status;\r
c95d9ab8
SZ
1235\r
1236 mLastVarErrorFlag = InternalGetVarErrorFlag ();\r
1237 DEBUG ((EFI_D_INFO, "mLastVarErrorFlag - 0x%02x\n", mLastVarErrorFlag));\r
1238\r
c95d9ab8
SZ
1239 //\r
1240 // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.\r
1241 //\r
1242 Status = gBS->CreateEventEx (\r
1243 EVT_NOTIFY_SIGNAL,\r
1244 TPL_CALLBACK,\r
1245 PlatformVarCleanupEndOfDxeEvent,\r
1246 NULL,\r
1247 &gEfiEndOfDxeEventGroupGuid,\r
c103e09b 1248 &mPlatVarCleanupLibEndOfDxeEvent\r
c95d9ab8
SZ
1249 );\r
1250 ASSERT_EFI_ERROR (Status);\r
1251\r
1252 return EFI_SUCCESS;\r
1253}\r
1254\r
c103e09b
HW
1255/**\r
1256 The destructor function closes the End of DXE event.\r
1257\r
1258 @param ImageHandle The firmware allocated handle for the EFI image.\r
1259 @param SystemTable A pointer to the EFI System Table.\r
1260\r
1261 @retval EFI_SUCCESS The destructor completed successfully.\r
1262\r
1263**/\r
1264EFI_STATUS\r
1265EFIAPI\r
1266PlatformVarCleanupLibDestructor (\r
1267 IN EFI_HANDLE ImageHandle,\r
1268 IN EFI_SYSTEM_TABLE *SystemTable\r
1269 )\r
1270{\r
1271 EFI_STATUS Status;\r
1272\r
1273 //\r
1274 // Close the End of DXE event.\r
1275 //\r
1276 Status = gBS->CloseEvent (mPlatVarCleanupLibEndOfDxeEvent);\r
1277 ASSERT_EFI_ERROR (Status);\r
1278\r
1279 return EFI_SUCCESS;\r
1280}\r