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