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