]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
MdeModulePkg/CapsuleLib: Add CapsuleTarget support.
[mirror_edk2.git] / MdeModulePkg / Library / DxeCapsuleLibFmp / DxeCapsuleReportLib.c
CommitLineData
d2a16030
JY
1/** @file\r
2 DXE capsule report related function.\r
3\r
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <PiDxe.h>\r
16#include <Protocol/FirmwareManagement.h>\r
17#include <Protocol/VariableLock.h>\r
18#include <Guid/CapsuleReport.h>\r
19#include <Guid/FmpCapsule.h>\r
20#include <Guid/CapsuleVendor.h>\r
21\r
22#include <Library/BaseLib.h>\r
23#include <Library/DebugLib.h>\r
24#include <Library/BaseMemoryLib.h>\r
25#include <Library/UefiBootServicesTableLib.h>\r
26#include <Library/UefiRuntimeServicesTableLib.h>\r
27#include <Library/MemoryAllocationLib.h>\r
28#include <Library/UefiLib.h>\r
29#include <Library/PcdLib.h>\r
30#include <Library/HobLib.h>\r
31#include <Library/PrintLib.h>\r
32#include <Library/ReportStatusCodeLib.h>\r
8f6db161 33#include <Library/DevicePathLib.h>\r
d2a16030
JY
34#include <Library/CapsuleLib.h>\r
35\r
36#include <IndustryStandard/WindowsUxCapsule.h>\r
37\r
38typedef struct {\r
39 EFI_CAPSULE_RESULT_VARIABLE_HEADER CapsuleResultHeader;\r
40 EFI_CAPSULE_RESULT_VARIABLE_FMP CapsuleResultFmp;\r
41} CAPSULE_RESULT_VARIABLE_CACHE;\r
42\r
43#define CAPSULE_RESULT_VARIABLE_CACHE_COUNT 0x10\r
44\r
45CAPSULE_RESULT_VARIABLE_CACHE *mCapsuleResultVariableCache;\r
46UINTN mCapsuleResultVariableCacheMaxCount;\r
47UINTN mCapsuleResultVariableCacheCount;\r
48\r
49/**\r
50 Get current capsule last variable index.\r
51\r
52 @return Current capsule last variable index.\r
53 @retval -1 No current capsule last variable.\r
54**/\r
55INTN\r
56GetCurrentCapsuleLastIndex (\r
57 VOID\r
58 )\r
59{\r
60 UINTN Size;\r
61 CHAR16 CapsuleLastStr[sizeof("Capsule####")];\r
62 EFI_STATUS Status;\r
63 UINT16 CurrentIndex;\r
64\r
65 Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator\r
66 Status = gRT->GetVariable(\r
67 L"CapsuleLast",\r
68 &gEfiCapsuleReportGuid,\r
69 NULL,\r
70 &Size,\r
71 CapsuleLastStr\r
72 );\r
73 if (EFI_ERROR(Status)) {\r
74 return -1;\r
75 }\r
76 CurrentIndex = (UINT16)StrHexToUintn(&CapsuleLastStr[sizeof("Capsule") - 1]);\r
77 return CurrentIndex;\r
78}\r
79\r
80/**\r
81 Check if this FMP capsule is processed.\r
82\r
83 @param[in] CapsuleHeader The capsule image header\r
84 @param[in] PayloadIndex FMP payload index\r
85 @param[in] ImageHeader FMP image header\r
86\r
87 @retval TRUE This FMP capsule is processed.\r
88 @retval FALSE This FMP capsule is not processed.\r
89**/\r
90BOOLEAN\r
91IsFmpCapsuleProcessed (\r
92 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
93 IN UINTN PayloadIndex,\r
94 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader\r
95 )\r
96{\r
97 UINTN Index;\r
98 EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResult;\r
99 EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultFmp;\r
100\r
101 for (Index = 0; Index < mCapsuleResultVariableCacheCount; Index++) {\r
102 //\r
103 // Check\r
104 //\r
105 CapsuleResult = &mCapsuleResultVariableCache[Index].CapsuleResultHeader;\r
106 if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {\r
107 if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {\r
d8487a34 108 if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) * 2) {\r
d2a16030
JY
109 CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);\r
110 if (CompareGuid(&CapsuleResultFmp->UpdateImageTypeId, &ImageHeader->UpdateImageTypeId) &&\r
111 (CapsuleResultFmp->UpdateImageIndex == ImageHeader->UpdateImageIndex) &&\r
112 (CapsuleResultFmp->PayloadIndex == PayloadIndex) ) {\r
113 return TRUE;\r
114 }\r
115 }\r
116 }\r
117 }\r
118 }\r
119\r
120 return FALSE;\r
121}\r
122\r
123/**\r
124 Write a new capsule status variable cache.\r
125\r
126 @param[in] CapsuleResult The capsule status variable\r
127 @param[in] CapsuleResultSize The size of the capsule stauts variable in bytes\r
128\r
129 @retval EFI_SUCCESS The capsule status variable is cached.\r
130 @retval EFI_OUT_OF_RESOURCES No resource to cache the capsule status variable.\r
131**/\r
132EFI_STATUS\r
133WriteNewCapsuleResultVariableCache (\r
134 IN VOID *CapsuleResult,\r
135 IN UINTN CapsuleResultSize\r
136 )\r
137{\r
138 if (CapsuleResultSize > sizeof(CAPSULE_RESULT_VARIABLE_CACHE)) {\r
139 CapsuleResultSize = sizeof(CAPSULE_RESULT_VARIABLE_CACHE);\r
140 }\r
141\r
142 if (mCapsuleResultVariableCacheCount == mCapsuleResultVariableCacheMaxCount) {\r
143 mCapsuleResultVariableCache = ReallocatePool(\r
144 mCapsuleResultVariableCacheMaxCount * sizeof(CAPSULE_RESULT_VARIABLE_CACHE),\r
145 (mCapsuleResultVariableCacheMaxCount + CAPSULE_RESULT_VARIABLE_CACHE_COUNT) * sizeof(CAPSULE_RESULT_VARIABLE_CACHE),\r
146 mCapsuleResultVariableCache\r
147 );\r
148 if (mCapsuleResultVariableCache == NULL) {\r
149 return EFI_OUT_OF_RESOURCES;\r
150 }\r
151 mCapsuleResultVariableCacheMaxCount += CAPSULE_RESULT_VARIABLE_CACHE_COUNT;\r
152 }\r
153\r
154 ASSERT(mCapsuleResultVariableCacheCount < mCapsuleResultVariableCacheMaxCount);\r
155 ASSERT(mCapsuleResultVariableCache != NULL);\r
156 CopyMem(\r
157 &mCapsuleResultVariableCache[mCapsuleResultVariableCacheCount],\r
158 CapsuleResult,\r
159 CapsuleResultSize\r
160 );\r
161 mCapsuleResultVariableCacheCount++;\r
162\r
163 return EFI_SUCCESS;\r
164}\r
165\r
166/**\r
167 Get a new capsule status variable index.\r
168\r
169 @return A new capsule status variable index.\r
170 @retval -1 No new capsule status variable index.\r
171**/\r
172INTN\r
173GetNewCapsuleResultIndex (\r
174 VOID\r
175 )\r
176{\r
177 INTN CurrentIndex;\r
178\r
179 CurrentIndex = GetCurrentCapsuleLastIndex();\r
180 if (CurrentIndex >= PcdGet16(PcdCapsuleMax)) {\r
181 return -1;\r
182 }\r
183\r
184 return CurrentIndex + 1;\r
185}\r
186\r
187/**\r
188 Write a new capsule status variable.\r
189\r
190 @param[in] CapsuleResult The capsule status variable\r
191 @param[in] CapsuleResultSize The size of the capsule stauts variable in bytes\r
192\r
193 @retval EFI_SUCCESS The capsule status variable is recorded.\r
194 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.\r
195**/\r
196EFI_STATUS\r
197WriteNewCapsuleResultVariable (\r
198 IN VOID *CapsuleResult,\r
199 IN UINTN CapsuleResultSize\r
200 )\r
201{\r
202 INTN CapsuleResultIndex;\r
203 CHAR16 CapsuleResultStr[sizeof("Capsule####")];\r
204 UINTN Size;\r
205 EFI_STATUS Status;\r
206\r
207 CapsuleResultIndex = GetNewCapsuleResultIndex();\r
208 DEBUG((DEBUG_INFO, "New CapsuleResultIndex - 0x%x\n", CapsuleResultIndex));\r
209 if (CapsuleResultIndex == -1) {\r
210 return EFI_OUT_OF_RESOURCES;\r
211 }\r
212 UnicodeSPrint(\r
213 CapsuleResultStr,\r
214 sizeof(CapsuleResultStr),\r
215 L"Capsule%04x",\r
216 CapsuleResultIndex\r
217 );\r
218\r
219 Status = gRT->SetVariable(\r
220 CapsuleResultStr,\r
221 &gEfiCapsuleReportGuid,\r
222 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
223 CapsuleResultSize,\r
224 CapsuleResult\r
225 );\r
226 if (!EFI_ERROR(Status)) {\r
227 Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator\r
228 DEBUG((DEBUG_INFO, "Set CapsuleLast - %s\n", CapsuleResultStr));\r
229 Status = gRT->SetVariable(\r
230 L"CapsuleLast",\r
231 &gEfiCapsuleReportGuid,\r
232 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
233 Size,\r
234 CapsuleResultStr\r
235 );\r
236 }\r
237\r
238 return Status;\r
239}\r
240\r
241/**\r
242 Record capsule status variable and to local cache.\r
243\r
244 @param[in] CapsuleHeader The capsule image header\r
245 @param[in] CapsuleStatus The capsule process stauts\r
246\r
247 @retval EFI_SUCCESS The capsule status variable is recorded.\r
248 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.\r
249**/\r
250EFI_STATUS\r
251RecordCapsuleStatusVariable (\r
252 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
253 IN EFI_STATUS CapsuleStatus\r
254 )\r
255{\r
256 EFI_CAPSULE_RESULT_VARIABLE_HEADER CapsuleResultVariable;\r
257 EFI_STATUS Status;\r
258\r
259 CapsuleResultVariable.VariableTotalSize = sizeof(CapsuleResultVariable);\r
d8487a34 260 CapsuleResultVariable.Reserved = 0;\r
d2a16030
JY
261 CopyGuid (&CapsuleResultVariable.CapsuleGuid, &CapsuleHeader->CapsuleGuid);\r
262 ZeroMem(&CapsuleResultVariable.CapsuleProcessed, sizeof(CapsuleResultVariable.CapsuleProcessed));\r
263 gRT->GetTime(&CapsuleResultVariable.CapsuleProcessed, NULL);\r
264 CapsuleResultVariable.CapsuleStatus = CapsuleStatus;\r
265\r
266 //\r
267 // Save Local Cache\r
268 //\r
269 Status = WriteNewCapsuleResultVariableCache(&CapsuleResultVariable, sizeof(CapsuleResultVariable));\r
270\r
271 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {\r
272 Status = WriteNewCapsuleResultVariable(&CapsuleResultVariable, sizeof(CapsuleResultVariable));\r
273 }\r
274 return Status;\r
275}\r
276\r
277/**\r
278 Record FMP capsule status variable and to local cache.\r
279\r
280 @param[in] CapsuleHeader The capsule image header\r
281 @param[in] CapsuleStatus The capsule process stauts\r
282 @param[in] PayloadIndex FMP payload index\r
283 @param[in] ImageHeader FMP image header\r
8f6db161 284 @param[in] FmpDevicePath DevicePath associated with the FMP producer\r
d2a16030
JY
285\r
286 @retval EFI_SUCCESS The capsule status variable is recorded.\r
287 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.\r
288**/\r
289EFI_STATUS\r
290RecordFmpCapsuleStatusVariable (\r
291 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
292 IN EFI_STATUS CapsuleStatus,\r
293 IN UINTN PayloadIndex,\r
8f6db161
JY
294 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,\r
295 IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL\r
d2a16030
JY
296 )\r
297{\r
d2a16030
JY
298 EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResultVariableHeader;\r
299 EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultVariableFmp;\r
300 EFI_STATUS Status;\r
b857bf48 301 UINT8 *CapsuleResultVariable;\r
8f6db161
JY
302 UINTN CapsuleResultVariableSize;\r
303 CHAR16 *DevicePathStr;\r
304 UINTN DevicePathStrSize;\r
d2a16030 305\r
8f6db161
JY
306 DevicePathStr = NULL;\r
307 if (FmpDevicePath != NULL) {\r
308 DevicePathStr = ConvertDevicePathToText (FmpDevicePath, FALSE, FALSE);\r
309 }\r
310 if (DevicePathStr != NULL) {\r
311 DevicePathStrSize = StrSize(DevicePathStr);\r
312 } else {\r
313 DevicePathStrSize = sizeof(CHAR16);\r
314 }\r
d8487a34 315 //\r
8f6db161 316 // Allocate zero CHAR16 for CapsuleFileName.\r
d8487a34 317 //\r
8f6db161 318 CapsuleResultVariableSize = sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) + DevicePathStrSize;\r
d8487a34 319 CapsuleResultVariable = AllocateZeroPool (CapsuleResultVariableSize);\r
b857bf48
DB
320 if (CapsuleResultVariable == NULL) {\r
321 return EFI_OUT_OF_RESOURCES;\r
322 }\r
323 CapsuleResultVariableHeader = (VOID *)CapsuleResultVariable;\r
8f6db161 324 CapsuleResultVariableHeader->VariableTotalSize = (UINT32)CapsuleResultVariableSize;\r
d8487a34 325 CapsuleResultVariableHeader->Reserved = 0;\r
d2a16030
JY
326 CopyGuid(&CapsuleResultVariableHeader->CapsuleGuid, &CapsuleHeader->CapsuleGuid);\r
327 ZeroMem(&CapsuleResultVariableHeader->CapsuleProcessed, sizeof(CapsuleResultVariableHeader->CapsuleProcessed));\r
328 gRT->GetTime(&CapsuleResultVariableHeader->CapsuleProcessed, NULL);\r
329 CapsuleResultVariableHeader->CapsuleStatus = CapsuleStatus;\r
330\r
b857bf48 331 CapsuleResultVariableFmp = (VOID *)(CapsuleResultVariable + sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER));\r
d2a16030
JY
332 CapsuleResultVariableFmp->Version = 0x1;\r
333 CapsuleResultVariableFmp->PayloadIndex = (UINT8)PayloadIndex;\r
334 CapsuleResultVariableFmp->UpdateImageIndex = ImageHeader->UpdateImageIndex;\r
335 CopyGuid (&CapsuleResultVariableFmp->UpdateImageTypeId, &ImageHeader->UpdateImageTypeId);\r
8f6db161
JY
336 if (DevicePathStr != NULL) {\r
337 CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16), DevicePathStr, DevicePathStrSize);\r
338 FreePool (DevicePathStr);\r
339 DevicePathStr = NULL;\r
340 }\r
d2a16030
JY
341\r
342 //\r
343 // Save Local Cache\r
344 //\r
b857bf48 345 Status = WriteNewCapsuleResultVariableCache(CapsuleResultVariable, CapsuleResultVariableSize);\r
d2a16030
JY
346\r
347 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {\r
b857bf48 348 Status = WriteNewCapsuleResultVariable(CapsuleResultVariable, CapsuleResultVariableSize);\r
d2a16030 349 }\r
b857bf48 350 FreePool (CapsuleResultVariable);\r
d2a16030
JY
351 return Status;\r
352}\r
353\r
354/**\r
355 Initialize CapsuleMax variables.\r
356**/\r
357VOID\r
358InitCapsuleMaxVariable (\r
359 VOID\r
360 )\r
361{\r
362 EFI_STATUS Status;\r
363 UINTN Size;\r
364 CHAR16 CapsuleMaxStr[sizeof("Capsule####")];\r
365 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
366\r
367 UnicodeSPrint(\r
368 CapsuleMaxStr,\r
369 sizeof(CapsuleMaxStr),\r
370 L"Capsule%04x",\r
371 PcdGet16(PcdCapsuleMax)\r
372 );\r
373\r
374 Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator\r
375 Status = gRT->SetVariable(\r
376 L"CapsuleMax",\r
377 &gEfiCapsuleReportGuid,\r
378 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
379 Size,\r
380 CapsuleMaxStr\r
381 );\r
382 if (!EFI_ERROR(Status)) {\r
383 // Lock it per UEFI spec.\r
384 Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);\r
385 if (!EFI_ERROR(Status)) {\r
386 Status = VariableLock->RequestToLock(VariableLock, L"CapsuleMax", &gEfiCapsuleReportGuid);\r
387 ASSERT_EFI_ERROR(Status);\r
388 }\r
389 }\r
390}\r
391\r
392/**\r
393 Initialize CapsuleLast variables.\r
394**/\r
395VOID\r
396InitCapsuleLastVariable (\r
397 VOID\r
398 )\r
399{\r
400 EFI_STATUS Status;\r
401 EFI_BOOT_MODE BootMode;\r
402 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
403 VOID *CapsuleResult;\r
404 UINTN Size;\r
405 CHAR16 CapsuleLastStr[sizeof("Capsule####")];\r
406\r
407 BootMode = GetBootModeHob();\r
408 if (BootMode == BOOT_ON_FLASH_UPDATE) {\r
409 Status = gRT->SetVariable(\r
410 L"CapsuleLast",\r
411 &gEfiCapsuleReportGuid,\r
412 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
413 0,\r
414 NULL\r
415 );\r
416 // Do not lock it because it will be updated later.\r
417 } else {\r
418 //\r
419 // Check if OS/APP cleared L"Capsule####"\r
420 //\r
421 ZeroMem(CapsuleLastStr, sizeof(CapsuleLastStr));\r
422 Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator\r
423 Status = gRT->GetVariable(\r
424 L"CapsuleLast",\r
425 &gEfiCapsuleReportGuid,\r
426 NULL,\r
427 &Size,\r
428 CapsuleLastStr\r
429 );\r
430 if (!EFI_ERROR(Status)) {\r
431 //\r
432 // L"CapsuleLast" is got, check if data is there.\r
433 //\r
434 Status = GetVariable2 (\r
435 CapsuleLastStr,\r
436 &gEfiCapsuleReportGuid,\r
437 (VOID **) &CapsuleResult,\r
438 NULL\r
439 );\r
440 if (EFI_ERROR(Status)) {\r
441 //\r
442 // If no data, delete L"CapsuleLast"\r
443 //\r
444 Status = gRT->SetVariable(\r
445 L"CapsuleLast",\r
446 &gEfiCapsuleReportGuid,\r
447 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
448 0,\r
449 NULL\r
450 );\r
451 }\r
452 }\r
453\r
454 // Lock it in normal boot path per UEFI spec.\r
455 Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);\r
456 if (!EFI_ERROR(Status)) {\r
457 Status = VariableLock->RequestToLock(VariableLock, L"CapsuleLast", &gEfiCapsuleReportGuid);\r
458 ASSERT_EFI_ERROR(Status);\r
459 }\r
460 }\r
461}\r
462\r
463/**\r
464 Initialize capsule update variables.\r
465**/\r
466VOID\r
467InitCapsuleUpdateVariable (\r
468 VOID\r
469 )\r
470{\r
471 EFI_STATUS Status;\r
472 UINTN Index;\r
473 CHAR16 CapsuleVarName[30];\r
474 CHAR16 *TempVarName;\r
475\r
476 //\r
477 // Clear all the capsule variables CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...\r
478 // as early as possible which will avoid the next time boot after the capsule update\r
479 // will still into the capsule loop\r
480 //\r
481 StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]), EFI_CAPSULE_VARIABLE_NAME);\r
482 TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
483 Index = 0;\r
484 while (TRUE) {\r
485 if (Index > 0) {\r
486 UnicodeValueToString (TempVarName, 0, Index, 0);\r
487 }\r
488 Status = gRT->SetVariable (\r
489 CapsuleVarName,\r
490 &gEfiCapsuleVendorGuid,\r
491 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
492 0,\r
493 (VOID *)NULL\r
494 );\r
495 if (EFI_ERROR (Status)) {\r
496 //\r
497 // There is no capsule variables, quit\r
498 //\r
499 break;\r
500 }\r
501 Index++;\r
502 }\r
503}\r
504\r
505/**\r
506 Initialize capsule related variables.\r
507**/\r
508VOID\r
509InitCapsuleVariable (\r
510 VOID\r
511 )\r
512{\r
513 InitCapsuleUpdateVariable();\r
514 InitCapsuleMaxVariable();\r
515 InitCapsuleLastVariable();\r
516 //\r
517 // No need to clear L"Capsule####", because OS/APP should refer L"CapsuleLast"\r
518 // to check status and delete them.\r
519 //\r
520}\r