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