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