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