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