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