]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
MdeModulePkg/CapsuleLib: Fix runtime issue
[mirror_edk2.git] / MdeModulePkg / Library / DxeCapsuleLibFmp / DxeCapsuleProcessLib.c
CommitLineData
d2a16030
JY
1/** @file\r
2 DXE capsule process.\r
3\r
4 Caution: This module requires additional review when modified.\r
5 This module will have external input - capsule image.\r
6 This external input must be validated carefully to avoid security issue like\r
7 buffer overflow, integer overflow.\r
8\r
9 ProcessCapsules(), ProcessTheseCapsules() will receive untrusted\r
10 input and do basic validation.\r
11\r
12 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
13 This program and the accompanying materials\r
14 are licensed and made available under the terms and conditions of the BSD License\r
15 which accompanies this distribution. The full text of the license may be found at\r
16 http://opensource.org/licenses/bsd-license.php\r
17\r
18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
20\r
21**/\r
22\r
23#include <PiDxe.h>\r
24#include <Protocol/EsrtManagement.h>\r
25\r
26#include <Library/BaseLib.h>\r
27#include <Library/DebugLib.h>\r
28#include <Library/BaseMemoryLib.h>\r
29#include <Library/UefiBootServicesTableLib.h>\r
30#include <Library/UefiRuntimeServicesTableLib.h>\r
31#include <Library/MemoryAllocationLib.h>\r
32#include <Library/UefiLib.h>\r
33#include <Library/PcdLib.h>\r
34#include <Library/HobLib.h>\r
35#include <Library/ReportStatusCodeLib.h>\r
36#include <Library/CapsuleLib.h>\r
37\r
38#include <IndustryStandard/WindowsUxCapsule.h>\r
39\r
40/**\r
41 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.\r
42\r
43 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER\r
44\r
45 @retval TRUE It is a system FMP.\r
46 @retval FALSE It is a device FMP.\r
47**/\r
48BOOLEAN\r
49IsFmpCapsule (\r
50 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
51 );\r
52\r
53/**\r
54 Validate Fmp capsules layout.\r
55\r
56 Caution: This function may receive untrusted input.\r
57\r
58 This function assumes the caller validated the capsule by using\r
59 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.\r
60 The capsule buffer size is CapsuleHeader->CapsuleImageSize.\r
61\r
62 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\r
63 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.\r
64\r
65 This function need support nested FMP capsule.\r
66\r
67 @param[in] CapsuleHeader Points to a capsule header.\r
68 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.\r
69\r
70 @retval EFI_SUCESS Input capsule is a correct FMP capsule.\r
71 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.\r
72**/\r
73EFI_STATUS\r
74ValidateFmpCapsule (\r
75 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
76 OUT UINT16 *EmbeddedDriverCount OPTIONAL\r
77 );\r
78\r
79/**\r
80 Validate if it is valid capsule header\r
81\r
82 This function assumes the caller provided correct CapsuleHeader pointer\r
83 and CapsuleSize.\r
84\r
85 This function validates the fields in EFI_CAPSULE_HEADER.\r
86\r
87 @param[in] CapsuleHeader Points to a capsule header.\r
88 @param[in] CapsuleSize Size of the whole capsule image.\r
89\r
90**/\r
91BOOLEAN\r
92IsValidCapsuleHeader (\r
93 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
94 IN UINT64 CapsuleSize\r
95 );\r
96\r
97extern BOOLEAN mDxeCapsuleLibEndOfDxe;\r
d2a16030
JY
98BOOLEAN mNeedReset;\r
99\r
3f31ea1b
JY
100VOID **mCapsulePtr;\r
101EFI_STATUS *mCapsuleStatusArray;\r
102UINT32 mCapsuleTotalNumber;\r
d2a16030 103\r
3f31ea1b
JY
104/**\r
105 This function initializes the mCapsulePtr, mCapsuleStatusArray and mCapsuleTotalNumber.\r
d2a16030 106**/\r
3f31ea1b
JY
107VOID\r
108InitCapsulePtr (\r
109 VOID\r
d2a16030
JY
110 )\r
111{\r
d2a16030 112 EFI_PEI_HOB_POINTERS HobPointer;\r
3f31ea1b 113 UINTN Index;\r
d2a16030 114\r
d2a16030
JY
115 //\r
116 // Find all capsule images from hob\r
117 //\r
118 HobPointer.Raw = GetHobList ();\r
119 while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {\r
120 if (!IsValidCapsuleHeader((VOID *)(UINTN)HobPointer.Capsule->BaseAddress, HobPointer.Capsule->Length)) {\r
121 HobPointer.Header->HobType = EFI_HOB_TYPE_UNUSED; // Mark this hob as invalid\r
122 } else {\r
3f31ea1b 123 mCapsuleTotalNumber++;\r
d2a16030
JY
124 }\r
125 HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
126 }\r
127\r
3f31ea1b
JY
128 DEBUG ((DEBUG_INFO, "mCapsuleTotalNumber - 0x%x\n", mCapsuleTotalNumber));\r
129\r
130 if (mCapsuleTotalNumber == 0) {\r
131 return ;\r
d2a16030
JY
132 }\r
133\r
134 //\r
135 // Init temp Capsule Data table.\r
136 //\r
3f31ea1b
JY
137 mCapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * mCapsuleTotalNumber);\r
138 if (mCapsulePtr == NULL) {\r
139 DEBUG ((DEBUG_ERROR, "Allocate mCapsulePtr fail!\n"));\r
140 mCapsuleTotalNumber = 0;\r
141 return ;\r
d2a16030 142 }\r
3f31ea1b
JY
143 mCapsuleStatusArray = (EFI_STATUS *) AllocateZeroPool (sizeof (EFI_STATUS) * mCapsuleTotalNumber);\r
144 if (mCapsuleStatusArray == NULL) {\r
145 DEBUG ((DEBUG_ERROR, "Allocate mCapsuleStatusArray fail!\n"));\r
146 FreePool (mCapsulePtr);\r
147 mCapsulePtr = NULL;\r
148 mCapsuleTotalNumber = 0;\r
149 return ;\r
d2a16030 150 }\r
3f31ea1b 151 SetMemN (mCapsuleStatusArray, sizeof (EFI_STATUS) * mCapsuleTotalNumber, EFI_NOT_READY);\r
d2a16030
JY
152\r
153 //\r
154 // Find all capsule images from hob\r
155 //\r
156 HobPointer.Raw = GetHobList ();\r
3f31ea1b 157 Index = 0;\r
d2a16030 158 while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {\r
3f31ea1b 159 mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;\r
d2a16030
JY
160 HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
161 }\r
3f31ea1b 162}\r
d2a16030 163\r
3f31ea1b
JY
164/**\r
165 This function returns if all capsule images are processed.\r
166\r
167 @retval TRUE All capsule images are processed.\r
168 @retval FALSE Not all capsule images are processed.\r
169**/\r
170BOOLEAN\r
171AreAllImagesProcessed (\r
172 VOID\r
173 )\r
174{\r
175 UINTN Index;\r
176\r
177 for (Index = 0; Index < mCapsuleTotalNumber; Index++) {\r
178 if (mCapsuleStatusArray[Index] == EFI_NOT_READY) {\r
179 return FALSE;\r
180 }\r
181 }\r
182\r
183 return TRUE;\r
184}\r
185\r
186/**\r
187 This function populates capsule in the configuration table.\r
188**/\r
189VOID\r
190PopulateCapsuleInConfigurationTable (\r
191 VOID\r
192 )\r
193{\r
194 VOID **CapsulePtrCache;\r
195 EFI_GUID *CapsuleGuidCache;\r
196 EFI_CAPSULE_HEADER *CapsuleHeader;\r
197 EFI_CAPSULE_TABLE *CapsuleTable;\r
198 UINT32 CacheIndex;\r
199 UINT32 CacheNumber;\r
200 UINT32 CapsuleNumber;\r
201 UINTN Index;\r
202 UINTN Size;\r
203 EFI_STATUS Status;\r
204\r
205 if (mCapsuleTotalNumber == 0) {\r
206 return ;\r
207 }\r
208\r
209 CapsulePtrCache = NULL;\r
210 CapsuleGuidCache = NULL;\r
211 CacheIndex = 0;\r
212 CacheNumber = 0;\r
213\r
214 CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * mCapsuleTotalNumber);\r
215 if (CapsulePtrCache == NULL) {\r
216 DEBUG ((DEBUG_ERROR, "Allocate CapsulePtrCache fail!\n"));\r
217 return ;\r
218 }\r
219 CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * mCapsuleTotalNumber);\r
220 if (CapsuleGuidCache == NULL) {\r
221 DEBUG ((DEBUG_ERROR, "Allocate CapsuleGuidCache fail!\n"));\r
222 FreePool (CapsulePtrCache);\r
223 return ;\r
224 }\r
d2a16030
JY
225\r
226 //\r
227 // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating\r
228 // System to have information persist across a system reset. EFI System Table must\r
229 // point to an array of capsules that contains the same CapsuleGuid value. And agents\r
230 // searching for this type capsule will look in EFI System Table and search for the\r
231 // capsule's Guid and associated pointer to retrieve the data. Two steps below describes\r
232 // how to sorting the capsules by the unique guid and install the array to EFI System Table.\r
233 // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an\r
234 // array for later sorting capsules by CapsuleGuid.\r
235 //\r
3f31ea1b
JY
236 for (Index = 0; Index < mCapsuleTotalNumber; Index++) {\r
237 CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];\r
d2a16030
JY
238 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
239 //\r
240 // For each capsule, we compare it with known CapsuleGuid in the CacheArray.\r
241 // If already has the Guid, skip it. Whereas, record it in the CacheArray as\r
242 // an additional one.\r
243 //\r
244 CacheIndex = 0;\r
245 while (CacheIndex < CacheNumber) {\r
246 if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {\r
247 break;\r
248 }\r
249 CacheIndex++;\r
250 }\r
251 if (CacheIndex == CacheNumber) {\r
252 CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));\r
253 }\r
254 }\r
255 }\r
256\r
257 //\r
258 // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules\r
259 // whose guid is the same as it, and malloc memory for an array which preceding\r
260 // with UINT32. The array fills with entry point of capsules that have the same\r
261 // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install\r
262 // this array into EFI System Table, so that agents searching for this type capsule\r
263 // will look in EFI System Table and search for the capsule's Guid and associated\r
264 // pointer to retrieve the data.\r
265 //\r
3f31ea1b 266 for (CacheIndex = 0; CacheIndex < CacheNumber; CacheIndex++) {\r
d2a16030 267 CapsuleNumber = 0;\r
3f31ea1b
JY
268 for (Index = 0; Index < mCapsuleTotalNumber; Index++) {\r
269 CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];\r
d2a16030
JY
270 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
271 if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {\r
272 //\r
273 // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.\r
274 //\r
275 CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;\r
d2a16030
JY
276 }\r
277 }\r
278 }\r
279 if (CapsuleNumber != 0) {\r
280 Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*);\r
281 CapsuleTable = AllocateRuntimePool (Size);\r
d2a16030 282 if (CapsuleTable == NULL) {\r
3f31ea1b
JY
283 DEBUG ((DEBUG_ERROR, "Allocate CapsuleTable (%g) fail!\n", &CapsuleGuidCache[CacheIndex]));\r
284 continue;\r
d2a16030
JY
285 }\r
286 CapsuleTable->CapsuleArrayNumber = CapsuleNumber;\r
287 CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));\r
288 Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);\r
3f31ea1b
JY
289 if (EFI_ERROR (Status)) {\r
290 DEBUG ((DEBUG_ERROR, "InstallConfigurationTable (%g) fail!\n", &CapsuleGuidCache[CacheIndex]));\r
291 }\r
d2a16030 292 }\r
3f31ea1b
JY
293 }\r
294\r
295 FreePool(CapsuleGuidCache);\r
296 FreePool(CapsulePtrCache);\r
297}\r
298\r
299/**\r
300\r
301 This routine is called to process capsules.\r
302\r
303 Caution: This function may receive untrusted input.\r
304\r
305 Each individual capsule result is recorded in capsule record variable.\r
306\r
307 @param[in] FirstRound TRUE: First round. Need skip the FMP capsules with non zero EmbeddedDriverCount.\r
308 FALSE: Process rest FMP capsules.\r
309\r
310 @retval EFI_SUCCESS There is no error when processing capsules.\r
311 @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.\r
312\r
313**/\r
314EFI_STATUS\r
315ProcessTheseCapsules (\r
316 IN BOOLEAN FirstRound\r
317 )\r
318{\r
319 EFI_STATUS Status;\r
320 EFI_CAPSULE_HEADER *CapsuleHeader;\r
321 UINT32 Index;\r
322 BOOLEAN DisplayCapsuleExist;\r
323 ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;\r
324 UINT16 EmbeddedDriverCount;\r
325\r
326 REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin)));\r
327\r
328 if (FirstRound) {\r
329 InitCapsulePtr ();\r
330 }\r
331\r
332 if (mCapsuleTotalNumber == 0) {\r
333 //\r
334 // We didn't find a hob, so had no errors.\r
335 //\r
336 DEBUG ((DEBUG_ERROR, "We can not find capsule data in capsule update boot mode.\n"));\r
337 return EFI_SUCCESS;\r
338 }\r
339\r
340 if (AreAllImagesProcessed ()) {\r
341 return EFI_SUCCESS;\r
342 }\r
343\r
344 //\r
345 // Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install\r
346 // capsuleTable to configure table with EFI_CAPSULE_GUID\r
347 //\r
348 if (FirstRound) {\r
349 PopulateCapsuleInConfigurationTable ();\r
d2a16030
JY
350 }\r
351\r
352 REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdatingFirmware)));\r
353\r
354 //\r
355 // If Windows UX capsule exist, process it first\r
356 //\r
3f31ea1b
JY
357 DisplayCapsuleExist = FALSE;\r
358 for (Index = 0; Index < mCapsuleTotalNumber; Index++) {\r
359 CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];\r
360 if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {\r
d2a16030
JY
361 DEBUG ((DEBUG_INFO, "ProcessCapsuleImage (Ux) - 0x%x\n", CapsuleHeader));\r
362 DisplayCapsuleExist = TRUE;\r
363 DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n"));\r
364 Status = ProcessCapsuleImage (CapsuleHeader);\r
3f31ea1b 365 mCapsuleStatusArray [Index] = EFI_SUCCESS;\r
d2a16030 366 DEBUG((DEBUG_INFO, "ProcessCapsuleImage (Ux) - %r\n", Status));\r
d2a16030
JY
367 break;\r
368 }\r
369 }\r
370\r
371 if (!DisplayCapsuleExist) {\r
372 //\r
373 // Display Capsule not found. Display the default string.\r
374 //\r
375 Print (L"Updating the firmware ......\r\n");\r
376 }\r
377\r
378 //\r
379 // All capsules left are recognized by platform.\r
380 //\r
3f31ea1b
JY
381 for (Index = 0; Index < mCapsuleTotalNumber; Index++) {\r
382 if (mCapsuleStatusArray [Index] != EFI_NOT_READY) {\r
383 // already processed\r
384 continue;\r
385 }\r
386 CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];\r
387 if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {\r
d2a16030
JY
388 //\r
389 // Call capsule library to process capsule image.\r
390 //\r
391 EmbeddedDriverCount = 0;\r
392 if (IsFmpCapsule(CapsuleHeader)) {\r
3f31ea1b 393 Status = ValidateFmpCapsule (CapsuleHeader, &EmbeddedDriverCount);\r
d2a16030
JY
394 if (EFI_ERROR(Status)) {\r
395 DEBUG((DEBUG_ERROR, "ValidateFmpCapsule failed. Ignore!\n"));\r
3f31ea1b 396 mCapsuleStatusArray [Index] = EFI_ABORTED;\r
d2a16030
JY
397 continue;\r
398 }\r
3f31ea1b
JY
399 } else {\r
400 mCapsuleStatusArray [Index] = EFI_ABORTED;\r
401 continue;\r
d2a16030
JY
402 }\r
403\r
3f31ea1b 404 if ((!FirstRound) || (EmbeddedDriverCount == 0)) {\r
d2a16030
JY
405 DEBUG((DEBUG_INFO, "ProcessCapsuleImage - 0x%x\n", CapsuleHeader));\r
406 Status = ProcessCapsuleImage (CapsuleHeader);\r
3f31ea1b 407 mCapsuleStatusArray [Index] = Status;\r
d2a16030
JY
408 DEBUG((DEBUG_INFO, "ProcessCapsuleImage - %r\n", Status));\r
409\r
3f31ea1b
JY
410 if (Status != EFI_NOT_READY) {\r
411 if (EFI_ERROR(Status)) {\r
412 REPORT_STATUS_CODE(EFI_ERROR_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareFailed)));\r
413 DEBUG ((DEBUG_ERROR, "Capsule process failed!\n"));\r
414 Print (L"Firmware update failed...\r\n");\r
415 } else {\r
416 REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareSuccess)));\r
417 }\r
418\r
419 if ((CapsuleHeader->Flags & PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag)) != 0 ||\r
420 IsFmpCapsule(CapsuleHeader)) {\r
421 mNeedReset = TRUE;\r
422 }\r
d2a16030
JY
423 }\r
424 }\r
425 }\r
426 }\r
427\r
428 Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);\r
429 //\r
430 // Always sync ESRT Cache from FMP Instance\r
431 //\r
432 if (!EFI_ERROR(Status)) {\r
433 EsrtManagement->SyncEsrtFmp();\r
434 }\r
435 Status = EFI_SUCCESS;\r
436\r
d2a16030
JY
437 REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesEnd)));\r
438\r
439 return Status;\r
440}\r
441\r
442/**\r
443 Do reset system.\r
444**/\r
445VOID\r
446DoResetSystem (\r
447 VOID\r
448 )\r
449{\r
450 UINTN Index;\r
451\r
452 REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeResettingSystem)));\r
453\r
454 Print(L"Capsule Request Cold Reboot.\n");\r
455 DEBUG((DEBUG_INFO, "Capsule Request Cold Reboot."));\r
456\r
457 for (Index = 5; Index > 0; Index--) {\r
458 Print(L"\rResetting system in %d seconds ...", Index);\r
459 DEBUG((DEBUG_INFO, "\rResetting system in %d seconds ...", Index));\r
460 gBS->Stall(1000000);\r
461 }\r
462\r
463 gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);\r
464\r
465 CpuDeadLoop();\r
466}\r
467\r
468/**\r
469\r
470 This routine is called to process capsules.\r
471\r
472 Caution: This function may receive untrusted input.\r
473\r
474 The capsules reported in EFI_HOB_UEFI_CAPSULE are processed.\r
475 If there is no EFI_HOB_UEFI_CAPSULE, this routine does nothing.\r
476\r
477 This routine should be called twice in BDS.\r
478 1) The first call must be before EndOfDxe. The system capsules is processed.\r
479 If device capsule FMP protocols are exposted at this time and device FMP\r
480 capsule has zero EmbeddedDriverCount, the device capsules are processed.\r
481 Each individual capsule result is recorded in capsule record variable.\r
482 System may reset in this function, if reset is required by capsule and\r
483 all capsules are processed.\r
484 If not all capsules are processed, reset will be defered to second call.\r
485\r
486 2) The second call must be after EndOfDxe and after ConnectAll, so that all\r
487 device capsule FMP protocols are exposed.\r
488 The system capsules are skipped. If the device capsules are NOT processed\r
489 in first call, they are processed here.\r
490 Each individual capsule result is recorded in capsule record variable.\r
491 System may reset in this function, if reset is required by capsule\r
492 processed in first call and second call.\r
493\r
494 @retval EFI_SUCCESS There is no error when processing capsules.\r
495 @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.\r
496\r
497**/\r
498EFI_STATUS\r
499EFIAPI\r
500ProcessCapsules (\r
501 VOID\r
502 )\r
503{\r
504 EFI_STATUS Status;\r
505\r
506 if (!mDxeCapsuleLibEndOfDxe) {\r
d2a16030 507 Status = ProcessTheseCapsules(TRUE);\r
3f31ea1b 508\r
d2a16030
JY
509 //\r
510 // Reboot System if and only if all capsule processed.\r
511 // If not, defer reset to 2nd process.\r
512 //\r
3f31ea1b 513 if (mNeedReset && AreAllImagesProcessed()) {\r
d2a16030
JY
514 DoResetSystem();\r
515 }\r
516 } else {\r
517 Status = ProcessTheseCapsules(FALSE);\r
518 //\r
519 // Reboot System if required after all capsule processed\r
520 //\r
521 if (mNeedReset) {\r
522 DoResetSystem();\r
523 }\r
524 }\r
525 return Status;\r
526}\r