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