TianoCore EDK2 master
Loading...
Searching...
No Matches
DxeCapsuleReportLib.c
Go to the documentation of this file.
1
9#include <PiDxe.h>
11#include <Guid/CapsuleReport.h>
12#include <Guid/FmpCapsule.h>
13#include <Guid/CapsuleVendor.h>
14
15#include <Library/BaseLib.h>
16#include <Library/DebugLib.h>
21#include <Library/UefiLib.h>
22#include <Library/PcdLib.h>
23#include <Library/HobLib.h>
24#include <Library/PrintLib.h>
27#include <Library/CapsuleLib.h>
28#include <Library/VariablePolicyHelperLib.h>
29
31
41 VOID
42 );
43
50INTN
52 VOID
53 )
54{
55 UINTN Size;
56 CHAR16 CapsuleLastStr[sizeof ("Capsule####")];
57 EFI_STATUS Status;
58 UINT16 CurrentIndex;
59
60 Size = sizeof (L"Capsule####") - sizeof (CHAR16); // no zero terminator
61 Status = gRT->GetVariable (
62 L"CapsuleLast",
63 &gEfiCapsuleReportGuid,
64 NULL,
65 &Size,
66 CapsuleLastStr
67 );
68 if (EFI_ERROR (Status)) {
69 return -1;
70 }
71
72 CurrentIndex = (UINT16)StrHexToUintn (&CapsuleLastStr[sizeof ("Capsule") - 1]);
73 return CurrentIndex;
74}
75
82INTN
84 VOID
85 )
86{
87 INTN CurrentIndex;
88
89 CurrentIndex = GetCurrentCapsuleLastIndex ();
90 if (CurrentIndex >= PcdGet16 (PcdCapsuleMax)) {
91 DEBUG ((DEBUG_INFO, " CapsuleResult variable Rolling Over!\n"));
92 return 0;
93 }
94
95 return CurrentIndex + 1;
96}
97
105VOID
107 IN CONST EFI_GUID VariableGuid,
108 IN CHAR16 *VariableName,
109 IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy
110 )
111{
112 EFI_STATUS Status;
113
114 // Set the policies to protect the target variables
115 Status = RegisterBasicVariablePolicy (
116 VariablePolicy,
117 &VariableGuid,
118 VariableName,
119 VARIABLE_POLICY_NO_MIN_SIZE,
120 VARIABLE_POLICY_NO_MAX_SIZE,
121 VARIABLE_POLICY_NO_MUST_ATTR,
122 VARIABLE_POLICY_NO_CANT_ATTR,
123 VARIABLE_POLICY_TYPE_LOCK_NOW
124 );
125 if (EFI_ERROR (Status)) {
126 DEBUG ((
127 DEBUG_ERROR,
128 "DxeCapsuleLibFmp: Failed to lock variable %g %s. Status = %r\n",
129 &VariableGuid,
130 VariableName,
131 Status
132 ));
133 ASSERT_EFI_ERROR (Status);
134 }
135}
136
148 IN VOID *CapsuleResult,
149 IN UINTN CapsuleResultSize
150 )
151{
152 INTN CapsuleResultIndex;
153 CHAR16 CapsuleResultStr[sizeof ("Capsule####")];
154 UINTN Size;
155 EFI_STATUS Status;
156
157 CapsuleResultIndex = GetNewCapsuleResultIndex ();
158 DEBUG ((DEBUG_INFO, "New CapsuleResultIndex - 0x%x\n", CapsuleResultIndex));
159
161 CapsuleResultStr,
162 sizeof (CapsuleResultStr),
163 L"Capsule%04x",
164 CapsuleResultIndex
165 );
166
167 Status = gRT->SetVariable (
168 CapsuleResultStr,
169 &gEfiCapsuleReportGuid,
170 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
171 CapsuleResultSize,
172 CapsuleResult
173 );
174 if (!EFI_ERROR (Status)) {
175 Size = sizeof (L"Capsule####") - sizeof (CHAR16); // no zero terminator
176 DEBUG ((DEBUG_INFO, "Set CapsuleLast - %s\n", CapsuleResultStr));
177 Status = gRT->SetVariable (
178 L"CapsuleLast",
179 &gEfiCapsuleReportGuid,
180 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
181 Size,
182 CapsuleResultStr
183 );
184 }
185
186 return Status;
187}
188
200 IN EFI_CAPSULE_HEADER *CapsuleHeader,
201 IN EFI_STATUS CapsuleStatus
202 )
203{
204 EFI_CAPSULE_RESULT_VARIABLE_HEADER CapsuleResultVariable;
205 EFI_STATUS Status;
206
207 CapsuleResultVariable.VariableTotalSize = sizeof (CapsuleResultVariable);
208 CapsuleResultVariable.Reserved = 0;
209 CopyGuid (&CapsuleResultVariable.CapsuleGuid, &CapsuleHeader->CapsuleGuid);
210 ZeroMem (&CapsuleResultVariable.CapsuleProcessed, sizeof (CapsuleResultVariable.CapsuleProcessed));
211 gRT->GetTime (&CapsuleResultVariable.CapsuleProcessed, NULL);
212 CapsuleResultVariable.CapsuleStatus = CapsuleStatus;
213
214 Status = EFI_SUCCESS;
215 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
216 Status = WriteNewCapsuleResultVariable (&CapsuleResultVariable, sizeof (CapsuleResultVariable));
217 }
218
219 return Status;
220}
221
237 IN EFI_CAPSULE_HEADER *CapsuleHeader,
238 IN EFI_STATUS CapsuleStatus,
239 IN UINTN PayloadIndex,
241 IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL,
242 IN CHAR16 *CapFileName OPTIONAL
243 )
244{
245 EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResultVariableHeader;
246 EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultVariableFmp;
247 EFI_STATUS Status;
248 UINT8 *CapsuleResultVariable;
249 UINTN CapsuleResultVariableSize;
250 CHAR16 *DevicePathStr;
251 UINTN DevicePathStrSize;
252 UINTN CapFileNameSize;
253
254 DevicePathStr = NULL;
255 CapFileNameSize = sizeof (CHAR16);
256
257 if (FmpDevicePath != NULL) {
258 DevicePathStr = ConvertDevicePathToText (FmpDevicePath, FALSE, FALSE);
259 }
260
261 if (DevicePathStr != NULL) {
262 DevicePathStrSize = StrSize (DevicePathStr);
263 } else {
264 DevicePathStrSize = sizeof (CHAR16);
265 }
266
267 if (CapFileName != NULL) {
268 CapFileNameSize = StrSize (CapFileName);
269 }
270
271 //
272 // Allocate room for CapsuleFileName.
273 //
274 CapsuleResultVariableSize = sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize + DevicePathStrSize;
275
276 CapsuleResultVariable = AllocateZeroPool (CapsuleResultVariableSize);
277 if (CapsuleResultVariable == NULL) {
278 return EFI_OUT_OF_RESOURCES;
279 }
280
281 CapsuleResultVariableHeader = (VOID *)CapsuleResultVariable;
282 CapsuleResultVariableHeader->VariableTotalSize = (UINT32)CapsuleResultVariableSize;
283 CapsuleResultVariableHeader->Reserved = 0;
284 CopyGuid (&CapsuleResultVariableHeader->CapsuleGuid, &CapsuleHeader->CapsuleGuid);
285 ZeroMem (&CapsuleResultVariableHeader->CapsuleProcessed, sizeof (CapsuleResultVariableHeader->CapsuleProcessed));
286 gRT->GetTime (&CapsuleResultVariableHeader->CapsuleProcessed, NULL);
287 CapsuleResultVariableHeader->CapsuleStatus = CapsuleStatus;
288
289 CapsuleResultVariableFmp = (VOID *)(CapsuleResultVariable + sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER));
290 CapsuleResultVariableFmp->Version = 0x1;
291 CapsuleResultVariableFmp->PayloadIndex = (UINT8)PayloadIndex;
292 CapsuleResultVariableFmp->UpdateImageIndex = ImageHeader->UpdateImageIndex;
293 CopyGuid (&CapsuleResultVariableFmp->UpdateImageTypeId, &ImageHeader->UpdateImageTypeId);
294
295 if (CapFileName != NULL) {
296 CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP), CapFileName, CapFileNameSize);
297 }
298
299 if (DevicePathStr != NULL) {
300 CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize, DevicePathStr, DevicePathStrSize);
301 FreePool (DevicePathStr);
302 DevicePathStr = NULL;
303 }
304
305 Status = EFI_SUCCESS;
306 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
307 Status = WriteNewCapsuleResultVariable (CapsuleResultVariable, CapsuleResultVariableSize);
308 }
309
310 FreePool (CapsuleResultVariable);
311 return Status;
312}
313
319VOID
321 EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy
322 )
323{
324 EFI_STATUS Status;
325 UINTN Size;
326 CHAR16 CapsuleMaxStr[sizeof ("Capsule####")];
327
329 CapsuleMaxStr,
330 sizeof (CapsuleMaxStr),
331 L"Capsule%04x",
332 PcdGet16 (PcdCapsuleMax)
333 );
334
335 Size = sizeof (L"Capsule####") - sizeof (CHAR16); // no zero terminator
336 Status = gRT->SetVariable (
337 L"CapsuleMax",
338 &gEfiCapsuleReportGuid,
339 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
340 Size,
341 CapsuleMaxStr
342 );
343 if (!EFI_ERROR (Status)) {
344 // Lock it per UEFI spec.
345 LockVariable (gEfiCapsuleReportGuid, L"CapsuleMax", VariablePolicy);
346 }
347}
348
354VOID
356 EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy
357 )
358{
359 EFI_STATUS Status;
360 EFI_BOOT_MODE BootMode;
361 VOID *CapsuleResult;
362 UINTN Size;
363 CHAR16 CapsuleLastStr[sizeof ("Capsule####")];
364
365 BootMode = GetBootModeHob ();
366 if (BootMode == BOOT_ON_FLASH_UPDATE) {
367 Status = gRT->SetVariable (
368 L"CapsuleLast",
369 &gEfiCapsuleReportGuid,
370 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
371 0,
372 NULL
373 );
374 // Do not lock it because it will be updated later.
375 } else {
376 //
377 // Check if OS/APP cleared L"Capsule####"
378 //
379 ZeroMem (CapsuleLastStr, sizeof (CapsuleLastStr));
380 Size = sizeof (L"Capsule####") - sizeof (CHAR16); // no zero terminator
381 Status = gRT->GetVariable (
382 L"CapsuleLast",
383 &gEfiCapsuleReportGuid,
384 NULL,
385 &Size,
386 CapsuleLastStr
387 );
388 if (!EFI_ERROR (Status)) {
389 //
390 // L"CapsuleLast" is got, check if data is there.
391 //
392 Status = GetVariable2 (
393 CapsuleLastStr,
394 &gEfiCapsuleReportGuid,
395 (VOID **)&CapsuleResult,
396 NULL
397 );
398 if (EFI_ERROR (Status)) {
399 //
400 // If no data, delete L"CapsuleLast"
401 //
402 Status = gRT->SetVariable (
403 L"CapsuleLast",
404 &gEfiCapsuleReportGuid,
405 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
406 0,
407 NULL
408 );
409 } else {
410 if (CapsuleResult != NULL) {
411 FreePool (CapsuleResult);
412 }
413 }
414 }
415
416 // Lock it in normal boot path per UEFI spec.
417 LockVariable (gEfiCapsuleReportGuid, L"CapsuleLast", VariablePolicy);
418 }
419}
420
424VOID
426 VOID
427 )
428{
429 EFI_STATUS Status;
430 UINTN Index;
431 CHAR16 CapsuleVarName[30];
432 CHAR16 *TempVarName;
433
434 //
435 // Clear all the capsule variables CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
436 // as early as possible which will avoid the next time boot after the capsule update
437 // will still into the capsule loop
438 //
439 StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CapsuleVarName[0]), EFI_CAPSULE_VARIABLE_NAME);
440 TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
441 Index = 0;
442 while (TRUE) {
443 if (Index > 0) {
445 TempVarName,
446 sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),
447 0,
448 Index,
449 0
450 );
451 }
452
453 Status = gRT->SetVariable (
454 CapsuleVarName,
455 &gEfiCapsuleVendorGuid,
456 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
457 0,
458 (VOID *)NULL
459 );
460 if (EFI_ERROR (Status)) {
461 //
462 // There is no capsule variables, quit
463 //
464 break;
465 }
466
467 Index++;
468 }
469}
470
476VOID
478 EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy
479 )
480{
482
483 //
484 // Unlock Capsule On Disk relocation Info variable only when Capsule On Disk flag is enabled
485 //
487 LockVariable (gEfiCapsuleVendorGuid, COD_RELOCATION_INFO_VAR_NAME, VariablePolicy);
488 }
489}
490
494VOID
496 VOID
497 )
498{
499 EFI_STATUS Status;
500 EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy;
501
502 // Locate the VariablePolicy protocol
503 Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicy);
504 if (EFI_ERROR (Status)) {
505 DEBUG ((DEBUG_ERROR, "DxeCapsuleReportLib %a - Could not locate VariablePolicy protocol! %r\n", __func__, Status));
506 ASSERT_EFI_ERROR (Status);
507 }
508
510 InitCapsuleMaxVariable (VariablePolicy);
511 InitCapsuleLastVariable (VariablePolicy);
512 InitCapsuleRelocationInfo (VariablePolicy);
513
514 //
515 // No need to clear L"Capsule####", because OS/APP should refer L"CapsuleLast"
516 // to check status and delete them.
517 //
518}
UINT64 UINTN
INT64 INTN
EFI_BOOT_MODE EFIAPI GetBootModeHob(VOID)
Definition: HobLib.c:240
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
RETURN_STATUS EFIAPI StrCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:226
UINTN EFIAPI StrHexToUintn(IN CONST CHAR16 *String)
Definition: String.c:508
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
BOOLEAN EFIAPI CoDCheckCapsuleOnDiskFlag(VOID)
#define EFI_CAPSULE_VARIABLE_NAME
Definition: CapsuleVendor.h:33
CHAR16 *EFIAPI ConvertDevicePathToText(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN BOOLEAN DisplayOnly, IN BOOLEAN AllowShortcuts)
INTN GetCurrentCapsuleLastIndex(VOID)
VOID InitCapsuleUpdateVariable(VOID)
INTN GetNewCapsuleResultIndex(VOID)
EFI_STATUS RecordCapsuleStatusVariable(IN EFI_CAPSULE_HEADER *CapsuleHeader, IN EFI_STATUS CapsuleStatus)
VOID LockVariable(IN CONST EFI_GUID VariableGuid, IN CHAR16 *VariableName, IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy)
EFI_STATUS CoDClearCapsuleRelocationInfo(VOID)
VOID InitCapsuleLastVariable(EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy)
EFI_STATUS WriteNewCapsuleResultVariable(IN VOID *CapsuleResult, IN UINTN CapsuleResultSize)
VOID InitCapsuleRelocationInfo(EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy)
EFI_STATUS RecordFmpCapsuleStatusVariable(IN EFI_CAPSULE_HEADER *CapsuleHeader, IN EFI_STATUS CapsuleStatus, IN UINTN PayloadIndex, IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader, IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL, IN CHAR16 *CapFileName OPTIONAL)
VOID InitCapsuleMaxVariable(EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy)
VOID InitCapsuleVariable(VOID)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
RETURN_STATUS EFIAPI UnicodeValueToStringS(IN OUT CHAR16 *Buffer, IN UINTN BufferSize, IN UINTN Flags, IN INT64 Value, IN UINTN Width)
Definition: PrintLib.c:652
UINTN EFIAPI UnicodeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
Definition: PrintLib.c:408
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet16(TokenName)
Definition: PcdLib.h:349
UINT32 EFI_BOOT_MODE
Definition: PiBootMode.h:18
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI GetVariable2(IN CONST CHAR16 *Name, IN CONST EFI_GUID *Guid, OUT VOID **Value, OUT UINTN *Size OPTIONAL)
Definition: UefiLib.c:1317
#define EFI_VARIABLE_NON_VOLATILE
Definition: Base.h:213