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