]>
Commit | Line | Data |
---|---|---|
1 | /** @file\r | |
2 | UEFI variable support functions for Firmware Management Protocol based\r | |
3 | firmware updates.\r | |
4 | \r | |
5 | Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>\r | |
6 | Copyright (c) 2018 - 2021, Intel Corporation. All rights reserved.<BR>\r | |
7 | \r | |
8 | SPDX-License-Identifier: BSD-2-Clause-Patent\r | |
9 | \r | |
10 | **/\r | |
11 | \r | |
12 | #include "FmpDxe.h"\r | |
13 | #include "VariableSupport.h"\r | |
14 | \r | |
15 | /**\r | |
16 | Retrieve the value of a 32-bit UEFI Variable specified by VariableName and\r | |
17 | a GUID of gEfiCallerIdGuid.\r | |
18 | \r | |
19 | @param[in] VariableName Pointer to the UEFI Variable name to retrieve.\r | |
20 | @param[out] Valid Set to TRUE if UEFI Variable is present and the size\r | |
21 | of the UEFI Variable value is 32-bits. Otherwise\r | |
22 | FALSE.\r | |
23 | @param[out] Value If Valid is set to TRUE, then the 32-bit value of\r | |
24 | the UEFI Variable. Otherwise 0.\r | |
25 | **/\r | |
26 | static\r | |
27 | VOID\r | |
28 | GetFmpVariable (\r | |
29 | IN CHAR16 *VariableName,\r | |
30 | OUT BOOLEAN *Valid,\r | |
31 | OUT UINT32 *Value\r | |
32 | )\r | |
33 | {\r | |
34 | EFI_STATUS Status;\r | |
35 | UINTN Size;\r | |
36 | UINT32 *Buffer;\r | |
37 | \r | |
38 | *Valid = FALSE;\r | |
39 | *Value = 0;\r | |
40 | Size = 0;\r | |
41 | Buffer = NULL;\r | |
42 | Status = GetVariable2 (\r | |
43 | VariableName,\r | |
44 | &gEfiCallerIdGuid,\r | |
45 | (VOID **)&Buffer,\r | |
46 | &Size\r | |
47 | );\r | |
48 | if (!EFI_ERROR (Status) && (Size == sizeof (*Value)) && (Buffer != NULL)) {\r | |
49 | *Valid = TRUE;\r | |
50 | *Value = *Buffer;\r | |
51 | }\r | |
52 | \r | |
53 | if (Buffer != NULL) {\r | |
54 | FreePool (Buffer);\r | |
55 | }\r | |
56 | }\r | |
57 | \r | |
58 | /**\r | |
59 | Delete the UEFI Variable with name specified by VariableName and GUID of\r | |
60 | gEfiCallerIdGuid. If the variable can not be deleted, then print a\r | |
61 | DEBUG_ERROR message.\r | |
62 | \r | |
63 | @param[in] VariableName Pointer to the UEFI Variable name to delete.\r | |
64 | **/\r | |
65 | static\r | |
66 | VOID\r | |
67 | DeleteFmpVariable (\r | |
68 | IN CHAR16 *VariableName\r | |
69 | )\r | |
70 | {\r | |
71 | EFI_STATUS Status;\r | |
72 | BOOLEAN Valid;\r | |
73 | UINT32 Value;\r | |
74 | \r | |
75 | GetFmpVariable (VariableName, &Valid, &Value);\r | |
76 | if (Valid) {\r | |
77 | Status = gRT->SetVariable (VariableName, &gEfiCallerIdGuid, 0, 0, NULL);\r | |
78 | if (EFI_ERROR (Status)) {\r | |
79 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to delete variable %s. Status = %r\n", mImageIdName, VariableName, Status));\r | |
80 | } else {\r | |
81 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Deleted variable %s\n", mImageIdName, VariableName));\r | |
82 | }\r | |
83 | }\r | |
84 | }\r | |
85 | \r | |
86 | /**\r | |
87 | Retrieve the FMP Controller State UEFI Variable value. Return NULL if\r | |
88 | the variable does not exist or if the size of the UEFI Variable is not the\r | |
89 | size of FMP_CONTROLLER_STATE. The buffer for the UEFI Variable value\r | |
90 | if allocated using the UEFI Boot Service AllocatePool().\r | |
91 | \r | |
92 | @param[in] Private Private context structure for the managed controller.\r | |
93 | \r | |
94 | @return Pointer to the allocated FMP Controller State. Returns NULL\r | |
95 | if the variable does not exist or is a different size than expected.\r | |
96 | **/\r | |
97 | static\r | |
98 | FMP_CONTROLLER_STATE *\r | |
99 | GetFmpControllerState (\r | |
100 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r | |
101 | )\r | |
102 | {\r | |
103 | EFI_STATUS Status;\r | |
104 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
105 | UINTN Size;\r | |
106 | \r | |
107 | FmpControllerState = NULL;\r | |
108 | Size = 0;\r | |
109 | Status = GetVariable2 (\r | |
110 | Private->FmpStateVariableName,\r | |
111 | &gEfiCallerIdGuid,\r | |
112 | (VOID **)&FmpControllerState,\r | |
113 | &Size\r | |
114 | );\r | |
115 | if (EFI_ERROR (Status) || (FmpControllerState == NULL)) {\r | |
116 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to get the controller state. Status = %r\n", mImageIdName, Status));\r | |
117 | } else {\r | |
118 | if (Size == sizeof (*FmpControllerState)) {\r | |
119 | return FmpControllerState;\r | |
120 | }\r | |
121 | \r | |
122 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Getting controller state returned a size different than expected. Size = 0x%x\n", mImageIdName, Size));\r | |
123 | }\r | |
124 | \r | |
125 | if (FmpControllerState != NULL) {\r | |
126 | FreePool (FmpControllerState);\r | |
127 | }\r | |
128 | \r | |
129 | return NULL;\r | |
130 | }\r | |
131 | \r | |
132 | /**\r | |
133 | Generates a Null-terminated Unicode string UEFI Variable name from a base name\r | |
134 | and a hardware instance. If the hardware instance value is 0, then the base\r | |
135 | name is returned. If the hardware instance value is non-zero, then the 64-bit\r | |
136 | hardware instance value is converted to a 16 character hex string and appended\r | |
137 | to base name. The UEFI Variable name returned is allocated using the UEFI\r | |
138 | Boot Service AllocatePool().\r | |
139 | \r | |
140 | @param[in] HardwareInstance 64-bit hardware instance value.\r | |
141 | @param[in] BaseVariableName Null-terminated Unicode string that is the base\r | |
142 | name of the UEFI Variable.\r | |
143 | \r | |
144 | @return Pointer to the allocated UEFI Variable name. Returns NULL if the\r | |
145 | UEFI Variable can not be allocated.\r | |
146 | **/\r | |
147 | static\r | |
148 | CHAR16 *\r | |
149 | GenerateFmpVariableName (\r | |
150 | IN UINT64 HardwareInstance,\r | |
151 | IN CHAR16 *BaseVariableName\r | |
152 | )\r | |
153 | {\r | |
154 | UINTN Size;\r | |
155 | CHAR16 *VariableName;\r | |
156 | \r | |
157 | //\r | |
158 | // Allocate Unicode string with room for BaseVariableName and a 16 digit\r | |
159 | // hexadecimal value for the HardwareInstance value.\r | |
160 | //\r | |
161 | Size = StrSize (BaseVariableName) + 16 * sizeof (CHAR16);\r | |
162 | VariableName = AllocateCopyPool (Size, BaseVariableName);\r | |
163 | if (VariableName == NULL) {\r | |
164 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to generate variable name %s.\n", mImageIdName, BaseVariableName));\r | |
165 | return VariableName;\r | |
166 | }\r | |
167 | \r | |
168 | if (HardwareInstance == 0) {\r | |
169 | return VariableName;\r | |
170 | }\r | |
171 | \r | |
172 | UnicodeValueToStringS (\r | |
173 | &VariableName[StrLen (BaseVariableName)],\r | |
174 | Size,\r | |
175 | PREFIX_ZERO | RADIX_HEX,\r | |
176 | HardwareInstance,\r | |
177 | 16\r | |
178 | );\r | |
179 | return VariableName;\r | |
180 | }\r | |
181 | \r | |
182 | /**\r | |
183 | Generate the names of the UEFI Variables used to store state information for\r | |
184 | a managed controller. The UEFI Variables names are a combination of a base\r | |
185 | name and an optional hardware instance value as a 16 character hex value. If\r | |
186 | the hardware instance value is 0, then the 16 character hex value is not\r | |
187 | included. These storage for the UEFI Variable names are allocated using the\r | |
188 | UEFI Boot Service AllocatePool() and the pointers are stored in the Private.\r | |
189 | The following are examples of variable names produces for hardware instance\r | |
190 | value 0 and value 0x1234567812345678.\r | |
191 | \r | |
192 | FmpVersion\r | |
193 | FmpLsv\r | |
194 | LastAttemptStatus\r | |
195 | LastAttemptVersion\r | |
196 | FmpState\r | |
197 | \r | |
198 | FmpVersion1234567812345678\r | |
199 | FmpLsv1234567812345678\r | |
200 | LastAttemptStatus1234567812345678\r | |
201 | LastAttemptVersion1234567812345678\r | |
202 | FmpState1234567812345678\r | |
203 | \r | |
204 | @param[in,out] Private Private context structure for the managed controller.\r | |
205 | **/\r | |
206 | VOID\r | |
207 | GenerateFmpVariableNames (\r | |
208 | IN OUT FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r | |
209 | )\r | |
210 | {\r | |
211 | EFI_STATUS Status;\r | |
212 | VOID *Buffer;\r | |
213 | FMP_CONTROLLER_STATE FmpControllerState;\r | |
214 | \r | |
215 | if (Private->VersionVariableName != NULL) {\r | |
216 | FreePool (Private->VersionVariableName);\r | |
217 | }\r | |
218 | \r | |
219 | if (Private->LsvVariableName != NULL) {\r | |
220 | FreePool (Private->LsvVariableName);\r | |
221 | }\r | |
222 | \r | |
223 | if (Private->LastAttemptStatusVariableName != NULL) {\r | |
224 | FreePool (Private->LastAttemptStatusVariableName);\r | |
225 | }\r | |
226 | \r | |
227 | if (Private->LastAttemptVersionVariableName != NULL) {\r | |
228 | FreePool (Private->LastAttemptVersionVariableName);\r | |
229 | }\r | |
230 | \r | |
231 | if (Private->FmpStateVariableName != NULL) {\r | |
232 | FreePool (Private->FmpStateVariableName);\r | |
233 | }\r | |
234 | \r | |
235 | Private->VersionVariableName = GenerateFmpVariableName (\r | |
236 | Private->Descriptor.HardwareInstance,\r | |
237 | VARNAME_VERSION\r | |
238 | );\r | |
239 | Private->LsvVariableName = GenerateFmpVariableName (\r | |
240 | Private->Descriptor.HardwareInstance,\r | |
241 | VARNAME_LSV\r | |
242 | );\r | |
243 | Private->LastAttemptStatusVariableName = GenerateFmpVariableName (\r | |
244 | Private->Descriptor.HardwareInstance,\r | |
245 | VARNAME_LASTATTEMPTSTATUS\r | |
246 | );\r | |
247 | Private->LastAttemptVersionVariableName = GenerateFmpVariableName (\r | |
248 | Private->Descriptor.HardwareInstance,\r | |
249 | VARNAME_LASTATTEMPTVERSION\r | |
250 | );\r | |
251 | Private->FmpStateVariableName = GenerateFmpVariableName (\r | |
252 | Private->Descriptor.HardwareInstance,\r | |
253 | VARNAME_FMPSTATE\r | |
254 | );\r | |
255 | \r | |
256 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->VersionVariableName));\r | |
257 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LsvVariableName));\r | |
258 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LastAttemptStatusVariableName));\r | |
259 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LastAttemptVersionVariableName));\r | |
260 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->FmpStateVariableName));\r | |
261 | \r | |
262 | Buffer = GetFmpControllerState (Private);\r | |
263 | if (Buffer != NULL) {\r | |
264 | //\r | |
265 | // FMP Controller State was found with correct size.\r | |
266 | // Delete old variables if they exist.\r | |
267 | //\r | |
268 | FreePool (Buffer);\r | |
269 | DeleteFmpVariable (Private->VersionVariableName);\r | |
270 | DeleteFmpVariable (Private->LsvVariableName);\r | |
271 | DeleteFmpVariable (Private->LastAttemptStatusVariableName);\r | |
272 | DeleteFmpVariable (Private->LastAttemptVersionVariableName);\r | |
273 | return;\r | |
274 | }\r | |
275 | \r | |
276 | //\r | |
277 | // FMP Controller State was either not found or is wrong size.\r | |
278 | // Create a new FMP Controller State variable with the correct size.\r | |
279 | //\r | |
280 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Create controller state\n", mImageIdName));\r | |
281 | GetFmpVariable (\r | |
282 | Private->VersionVariableName,\r | |
283 | &FmpControllerState.VersionValid,\r | |
284 | &FmpControllerState.Version\r | |
285 | );\r | |
286 | GetFmpVariable (\r | |
287 | Private->LsvVariableName,\r | |
288 | &FmpControllerState.LsvValid,\r | |
289 | &FmpControllerState.Lsv\r | |
290 | );\r | |
291 | GetFmpVariable (\r | |
292 | Private->LastAttemptStatusVariableName,\r | |
293 | &FmpControllerState.LastAttemptStatusValid,\r | |
294 | &FmpControllerState.LastAttemptStatus\r | |
295 | );\r | |
296 | GetFmpVariable (\r | |
297 | Private->LastAttemptVersionVariableName,\r | |
298 | &FmpControllerState.LastAttemptVersionValid,\r | |
299 | &FmpControllerState.LastAttemptVersion\r | |
300 | );\r | |
301 | Status = gRT->SetVariable (\r | |
302 | Private->FmpStateVariableName,\r | |
303 | &gEfiCallerIdGuid,\r | |
304 | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r | |
305 | sizeof (FmpControllerState),\r | |
306 | &FmpControllerState\r | |
307 | );\r | |
308 | if (EFI_ERROR (Status)) {\r | |
309 | //\r | |
310 | // Failed to create FMP Controller State. In this case, do not\r | |
311 | // delete the individual variables. They can be used again on next boot\r | |
312 | // to create the FMP Controller State.\r | |
313 | //\r | |
314 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to create controller state. Status = %r\n", mImageIdName, Status));\r | |
315 | } else {\r | |
316 | DeleteFmpVariable (Private->VersionVariableName);\r | |
317 | DeleteFmpVariable (Private->LsvVariableName);\r | |
318 | DeleteFmpVariable (Private->LastAttemptStatusVariableName);\r | |
319 | DeleteFmpVariable (Private->LastAttemptVersionVariableName);\r | |
320 | }\r | |
321 | }\r | |
322 | \r | |
323 | /**\r | |
324 | Returns the value used to fill in the Version field of the\r | |
325 | EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r | |
326 | service of the Firmware Management Protocol. The value is read from a UEFI\r | |
327 | variable. If the UEFI variables does not exist, then a default version value\r | |
328 | is returned.\r | |
329 | \r | |
330 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r | |
331 | \r | |
332 | @param[in] Private Private context structure for the managed controller.\r | |
333 | \r | |
334 | @return The version of the firmware image in the firmware device.\r | |
335 | **/\r | |
336 | UINT32\r | |
337 | GetVersionFromVariable (\r | |
338 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r | |
339 | )\r | |
340 | {\r | |
341 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
342 | UINT32 Value;\r | |
343 | \r | |
344 | Value = DEFAULT_VERSION;\r | |
345 | FmpControllerState = GetFmpControllerState (Private);\r | |
346 | if (FmpControllerState != NULL) {\r | |
347 | if (FmpControllerState->VersionValid) {\r | |
348 | Value = FmpControllerState->Version;\r | |
349 | DEBUG ((\r | |
350 | DEBUG_INFO,\r | |
351 | "FmpDxe(%s): Get variable %g %s Version %08x\n",\r | |
352 | mImageIdName,\r | |
353 | &gEfiCallerIdGuid,\r | |
354 | Private->FmpStateVariableName,\r | |
355 | Value\r | |
356 | ));\r | |
357 | }\r | |
358 | \r | |
359 | FreePool (FmpControllerState);\r | |
360 | }\r | |
361 | \r | |
362 | return Value;\r | |
363 | }\r | |
364 | \r | |
365 | /**\r | |
366 | Returns the value used to fill in the LowestSupportedVersion field of the\r | |
367 | EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r | |
368 | service of the Firmware Management Protocol. The value is read from a UEFI\r | |
369 | variable. If the UEFI variables does not exist, then a default lowest\r | |
370 | supported version value is returned.\r | |
371 | \r | |
372 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r | |
373 | \r | |
374 | @param[in] Private Private context structure for the managed controller.\r | |
375 | \r | |
376 | @return The lowest supported version of the firmware image in the firmware\r | |
377 | device.\r | |
378 | **/\r | |
379 | UINT32\r | |
380 | GetLowestSupportedVersionFromVariable (\r | |
381 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r | |
382 | )\r | |
383 | {\r | |
384 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
385 | UINT32 Value;\r | |
386 | \r | |
387 | Value = DEFAULT_LOWESTSUPPORTEDVERSION;\r | |
388 | FmpControllerState = GetFmpControllerState (Private);\r | |
389 | if (FmpControllerState != NULL) {\r | |
390 | if (FmpControllerState->LsvValid) {\r | |
391 | Value = FmpControllerState->Lsv;\r | |
392 | DEBUG ((\r | |
393 | DEBUG_INFO,\r | |
394 | "FmpDxe(%s): Get variable %g %s LowestSupportedVersion %08x\n",\r | |
395 | mImageIdName,\r | |
396 | &gEfiCallerIdGuid,\r | |
397 | Private->FmpStateVariableName,\r | |
398 | Value\r | |
399 | ));\r | |
400 | }\r | |
401 | \r | |
402 | FreePool (FmpControllerState);\r | |
403 | }\r | |
404 | \r | |
405 | return Value;\r | |
406 | }\r | |
407 | \r | |
408 | /**\r | |
409 | Returns the value used to fill in the LastAttemptStatus field of the\r | |
410 | EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r | |
411 | service of the Firmware Management Protocol. The value is read from a UEFI\r | |
412 | variable. If the UEFI variables does not exist, then a default last attempt\r | |
413 | status value is returned.\r | |
414 | \r | |
415 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r | |
416 | \r | |
417 | @param[in] Private Private context structure for the managed controller.\r | |
418 | \r | |
419 | @return The last attempt status value for the most recent capsule update.\r | |
420 | **/\r | |
421 | UINT32\r | |
422 | GetLastAttemptStatusFromVariable (\r | |
423 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r | |
424 | )\r | |
425 | {\r | |
426 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
427 | UINT32 Value;\r | |
428 | \r | |
429 | Value = DEFAULT_LASTATTEMPTSTATUS;\r | |
430 | FmpControllerState = GetFmpControllerState (Private);\r | |
431 | if (FmpControllerState != NULL) {\r | |
432 | if (FmpControllerState->LastAttemptStatusValid) {\r | |
433 | Value = FmpControllerState->LastAttemptStatus;\r | |
434 | DEBUG ((\r | |
435 | DEBUG_INFO,\r | |
436 | "FmpDxe(%s): Get variable %g %s LastAttemptStatus %08x\n",\r | |
437 | mImageIdName,\r | |
438 | &gEfiCallerIdGuid,\r | |
439 | Private->FmpStateVariableName,\r | |
440 | Value\r | |
441 | ));\r | |
442 | }\r | |
443 | \r | |
444 | FreePool (FmpControllerState);\r | |
445 | }\r | |
446 | \r | |
447 | return Value;\r | |
448 | }\r | |
449 | \r | |
450 | /**\r | |
451 | Returns the value used to fill in the LastAttemptVersion field of the\r | |
452 | EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r | |
453 | service of the Firmware Management Protocol. The value is read from a UEFI\r | |
454 | variable. If the UEFI variables does not exist, then a default last attempt\r | |
455 | version value is returned.\r | |
456 | \r | |
457 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r | |
458 | \r | |
459 | @param[in] Private Private context structure for the managed controller.\r | |
460 | \r | |
461 | @return The last attempt version value for the most recent capsule update.\r | |
462 | **/\r | |
463 | UINT32\r | |
464 | GetLastAttemptVersionFromVariable (\r | |
465 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r | |
466 | )\r | |
467 | {\r | |
468 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
469 | UINT32 Value;\r | |
470 | \r | |
471 | Value = DEFAULT_LASTATTEMPTVERSION;\r | |
472 | FmpControllerState = GetFmpControllerState (Private);\r | |
473 | if (FmpControllerState != NULL) {\r | |
474 | if (FmpControllerState->LastAttemptVersionValid) {\r | |
475 | Value = FmpControllerState->LastAttemptVersion;\r | |
476 | DEBUG ((\r | |
477 | DEBUG_INFO,\r | |
478 | "FmpDxe(%s): Get variable %g %s LastAttemptVersion %08x\n",\r | |
479 | mImageIdName,\r | |
480 | &gEfiCallerIdGuid,\r | |
481 | Private->FmpStateVariableName,\r | |
482 | Value\r | |
483 | ));\r | |
484 | }\r | |
485 | \r | |
486 | FreePool (FmpControllerState);\r | |
487 | }\r | |
488 | \r | |
489 | return Value;\r | |
490 | }\r | |
491 | \r | |
492 | /**\r | |
493 | Saves the version current of the firmware image in the firmware device to a\r | |
494 | UEFI variable.\r | |
495 | \r | |
496 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r | |
497 | \r | |
498 | @param[in] Private Private context structure for the managed controller.\r | |
499 | @param[in] Version The version of the firmware image in the firmware device.\r | |
500 | **/\r | |
501 | VOID\r | |
502 | SetVersionInVariable (\r | |
503 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r | |
504 | IN UINT32 Version\r | |
505 | )\r | |
506 | {\r | |
507 | EFI_STATUS Status;\r | |
508 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
509 | BOOLEAN Update;\r | |
510 | \r | |
511 | FmpControllerState = GetFmpControllerState (Private);\r | |
512 | if (FmpControllerState == NULL) {\r | |
513 | //\r | |
514 | // Can not update value if FMP Controller State does not exist.\r | |
515 | // This variable is guaranteed to be created by GenerateFmpVariableNames().\r | |
516 | //\r | |
517 | return;\r | |
518 | }\r | |
519 | \r | |
520 | Update = FALSE;\r | |
521 | if (!FmpControllerState->VersionValid) {\r | |
522 | Update = TRUE;\r | |
523 | }\r | |
524 | \r | |
525 | if (FmpControllerState->Version != Version) {\r | |
526 | Update = TRUE;\r | |
527 | }\r | |
528 | \r | |
529 | if (!Update) {\r | |
530 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));\r | |
531 | } else {\r | |
532 | FmpControllerState->VersionValid = TRUE;\r | |
533 | FmpControllerState->Version = Version;\r | |
534 | Status = gRT->SetVariable (\r | |
535 | Private->FmpStateVariableName,\r | |
536 | &gEfiCallerIdGuid,\r | |
537 | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r | |
538 | sizeof (*FmpControllerState),\r | |
539 | FmpControllerState\r | |
540 | );\r | |
541 | if (EFI_ERROR (Status)) {\r | |
542 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));\r | |
543 | } else {\r | |
544 | DEBUG ((\r | |
545 | DEBUG_INFO,\r | |
546 | "FmpDxe(%s): Set variable %g %s Version %08x\n",\r | |
547 | mImageIdName,\r | |
548 | &gEfiCallerIdGuid,\r | |
549 | Private->FmpStateVariableName,\r | |
550 | Version\r | |
551 | ));\r | |
552 | }\r | |
553 | }\r | |
554 | \r | |
555 | FreePool (FmpControllerState);\r | |
556 | }\r | |
557 | \r | |
558 | /**\r | |
559 | Saves the lowest supported version current of the firmware image in the\r | |
560 | firmware device to a UEFI variable.\r | |
561 | \r | |
562 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r | |
563 | \r | |
564 | @param[in] Private Private context structure for the managed\r | |
565 | controller.\r | |
566 | @param[in] LowestSupportedVersion The lowest supported version of the\r | |
567 | firmware image in the firmware device.\r | |
568 | **/\r | |
569 | VOID\r | |
570 | SetLowestSupportedVersionInVariable (\r | |
571 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r | |
572 | IN UINT32 LowestSupportedVersion\r | |
573 | )\r | |
574 | {\r | |
575 | EFI_STATUS Status;\r | |
576 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
577 | BOOLEAN Update;\r | |
578 | \r | |
579 | FmpControllerState = GetFmpControllerState (Private);\r | |
580 | if (FmpControllerState == NULL) {\r | |
581 | //\r | |
582 | // Can not update value if FMP Controller State does not exist.\r | |
583 | // This variable is guaranteed to be created by GenerateFmpVariableNames().\r | |
584 | //\r | |
585 | return;\r | |
586 | }\r | |
587 | \r | |
588 | Update = FALSE;\r | |
589 | if (!FmpControllerState->LsvValid) {\r | |
590 | Update = TRUE;\r | |
591 | }\r | |
592 | \r | |
593 | if (FmpControllerState->Lsv < LowestSupportedVersion) {\r | |
594 | Update = TRUE;\r | |
595 | }\r | |
596 | \r | |
597 | if (!Update) {\r | |
598 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));\r | |
599 | } else {\r | |
600 | FmpControllerState->LsvValid = TRUE;\r | |
601 | FmpControllerState->Lsv = LowestSupportedVersion;\r | |
602 | Status = gRT->SetVariable (\r | |
603 | Private->FmpStateVariableName,\r | |
604 | &gEfiCallerIdGuid,\r | |
605 | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r | |
606 | sizeof (*FmpControllerState),\r | |
607 | FmpControllerState\r | |
608 | );\r | |
609 | if (EFI_ERROR (Status)) {\r | |
610 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));\r | |
611 | } else {\r | |
612 | DEBUG ((\r | |
613 | DEBUG_INFO,\r | |
614 | "FmpDxe(%s): Set variable %g %s LowestSupportedVersion %08x\n",\r | |
615 | mImageIdName,\r | |
616 | &gEfiCallerIdGuid,\r | |
617 | Private->FmpStateVariableName,\r | |
618 | LowestSupportedVersion\r | |
619 | ));\r | |
620 | }\r | |
621 | }\r | |
622 | \r | |
623 | FreePool (FmpControllerState);\r | |
624 | }\r | |
625 | \r | |
626 | /**\r | |
627 | Saves the last attempt status value of the most recent FMP capsule update to a\r | |
628 | UEFI variable.\r | |
629 | \r | |
630 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r | |
631 | \r | |
632 | @param[in] Private Private context structure for the managed\r | |
633 | controller.\r | |
634 | @param[in] LastAttemptStatus The last attempt status of the most recent FMP\r | |
635 | capsule update.\r | |
636 | **/\r | |
637 | VOID\r | |
638 | SetLastAttemptStatusInVariable (\r | |
639 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r | |
640 | IN UINT32 LastAttemptStatus\r | |
641 | )\r | |
642 | {\r | |
643 | EFI_STATUS Status;\r | |
644 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
645 | BOOLEAN Update;\r | |
646 | \r | |
647 | FmpControllerState = GetFmpControllerState (Private);\r | |
648 | if (FmpControllerState == NULL) {\r | |
649 | //\r | |
650 | // Can not update value if FMP Controller State does not exist.\r | |
651 | // This variable is guaranteed to be created by GenerateFmpVariableNames().\r | |
652 | //\r | |
653 | return;\r | |
654 | }\r | |
655 | \r | |
656 | Update = FALSE;\r | |
657 | if (!FmpControllerState->LastAttemptStatusValid) {\r | |
658 | Update = TRUE;\r | |
659 | }\r | |
660 | \r | |
661 | if (FmpControllerState->LastAttemptStatus != LastAttemptStatus) {\r | |
662 | Update = TRUE;\r | |
663 | }\r | |
664 | \r | |
665 | if (!Update) {\r | |
666 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));\r | |
667 | } else {\r | |
668 | FmpControllerState->LastAttemptStatusValid = TRUE;\r | |
669 | FmpControllerState->LastAttemptStatus = LastAttemptStatus;\r | |
670 | Status = gRT->SetVariable (\r | |
671 | Private->FmpStateVariableName,\r | |
672 | &gEfiCallerIdGuid,\r | |
673 | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r | |
674 | sizeof (*FmpControllerState),\r | |
675 | FmpControllerState\r | |
676 | );\r | |
677 | if (EFI_ERROR (Status)) {\r | |
678 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));\r | |
679 | } else {\r | |
680 | DEBUG ((\r | |
681 | DEBUG_INFO,\r | |
682 | "FmpDxe(%s): Set variable %g %s LastAttemptStatus %08x\n",\r | |
683 | mImageIdName,\r | |
684 | &gEfiCallerIdGuid,\r | |
685 | Private->FmpStateVariableName,\r | |
686 | LastAttemptStatus\r | |
687 | ));\r | |
688 | }\r | |
689 | }\r | |
690 | \r | |
691 | FreePool (FmpControllerState);\r | |
692 | }\r | |
693 | \r | |
694 | /**\r | |
695 | Saves the last attempt version value of the most recent FMP capsule update to\r | |
696 | a UEFI variable.\r | |
697 | \r | |
698 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r | |
699 | \r | |
700 | @param[in] Private Private context structure for the managed\r | |
701 | controller.\r | |
702 | @param[in] LastAttemptVersion The last attempt version value of the most\r | |
703 | recent FMP capsule update.\r | |
704 | **/\r | |
705 | VOID\r | |
706 | SetLastAttemptVersionInVariable (\r | |
707 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r | |
708 | IN UINT32 LastAttemptVersion\r | |
709 | )\r | |
710 | {\r | |
711 | EFI_STATUS Status;\r | |
712 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
713 | BOOLEAN Update;\r | |
714 | \r | |
715 | FmpControllerState = GetFmpControllerState (Private);\r | |
716 | if (FmpControllerState == NULL) {\r | |
717 | //\r | |
718 | // Can not update value if FMP Controller State does not exist.\r | |
719 | // This variable is guaranteed to be created by GenerateFmpVariableNames().\r | |
720 | //\r | |
721 | return;\r | |
722 | }\r | |
723 | \r | |
724 | Update = FALSE;\r | |
725 | if (!FmpControllerState->LastAttemptVersionValid) {\r | |
726 | Update = TRUE;\r | |
727 | }\r | |
728 | \r | |
729 | if (FmpControllerState->LastAttemptVersion != LastAttemptVersion) {\r | |
730 | Update = TRUE;\r | |
731 | }\r | |
732 | \r | |
733 | if (!Update) {\r | |
734 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));\r | |
735 | } else {\r | |
736 | FmpControllerState->LastAttemptVersionValid = TRUE;\r | |
737 | FmpControllerState->LastAttemptVersion = LastAttemptVersion;\r | |
738 | Status = gRT->SetVariable (\r | |
739 | Private->FmpStateVariableName,\r | |
740 | &gEfiCallerIdGuid,\r | |
741 | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r | |
742 | sizeof (*FmpControllerState),\r | |
743 | FmpControllerState\r | |
744 | );\r | |
745 | if (EFI_ERROR (Status)) {\r | |
746 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));\r | |
747 | } else {\r | |
748 | DEBUG ((\r | |
749 | DEBUG_INFO,\r | |
750 | "FmpDxe(%s): Set variable %g %s LastAttemptVersion %08x\n",\r | |
751 | mImageIdName,\r | |
752 | &gEfiCallerIdGuid,\r | |
753 | Private->FmpStateVariableName,\r | |
754 | LastAttemptVersion\r | |
755 | ));\r | |
756 | }\r | |
757 | }\r | |
758 | \r | |
759 | FreePool (FmpControllerState);\r | |
760 | }\r | |
761 | \r | |
762 | /**\r | |
763 | Attempts to lock a single UEFI Variable propagating the error state of the\r | |
764 | first lock attempt that fails. Uses gEfiCallerIdGuid as the variable GUID.\r | |
765 | \r | |
766 | @param[in] PreviousStatus The previous UEFI Variable lock attempt status.\r | |
767 | @param[in] VariableLock The EDK II Variable Lock Protocol instance.\r | |
768 | @param[in] VariableName The name of the UEFI Variable to lock.\r | |
769 | \r | |
770 | @retval EFI_SUCCESS The UEFI Variable was locked and the previous variable\r | |
771 | lock attempt also succeeded.\r | |
772 | @retval Other The UEFI Variable could not be locked or the previous\r | |
773 | variable lock attempt failed.\r | |
774 | **/\r | |
775 | static\r | |
776 | EFI_STATUS\r | |
777 | LockFmpVariable (\r | |
778 | IN EFI_STATUS PreviousStatus,\r | |
779 | IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy,\r | |
780 | IN CHAR16 *VariableName\r | |
781 | )\r | |
782 | {\r | |
783 | EFI_STATUS Status;\r | |
784 | \r | |
785 | // If success, go ahead and set the policies to protect the target variables.\r | |
786 | Status = RegisterBasicVariablePolicy (\r | |
787 | VariablePolicy,\r | |
788 | &gEfiCallerIdGuid,\r | |
789 | VariableName,\r | |
790 | VARIABLE_POLICY_NO_MIN_SIZE,\r | |
791 | VARIABLE_POLICY_NO_MAX_SIZE,\r | |
792 | VARIABLE_POLICY_NO_MUST_ATTR,\r | |
793 | VARIABLE_POLICY_NO_CANT_ATTR,\r | |
794 | VARIABLE_POLICY_TYPE_LOCK_NOW\r | |
795 | );\r | |
796 | if (EFI_ERROR (Status)) {\r | |
797 | DEBUG ((\r | |
798 | DEBUG_ERROR,\r | |
799 | "FmpDxe(%s): Failed to lock variable %g %s. Status = %r\n",\r | |
800 | mImageIdName,\r | |
801 | &gEfiCallerIdGuid,\r | |
802 | VariableName,\r | |
803 | Status\r | |
804 | ));\r | |
805 | }\r | |
806 | \r | |
807 | if (EFI_ERROR (PreviousStatus)) {\r | |
808 | return PreviousStatus;\r | |
809 | }\r | |
810 | \r | |
811 | return Status;\r | |
812 | }\r | |
813 | \r | |
814 | /**\r | |
815 | Locks all the UEFI Variables that use gEfiCallerIdGuid of the currently\r | |
816 | executing module.\r | |
817 | \r | |
818 | @param[in] Private Private context structure for the managed controller.\r | |
819 | \r | |
820 | @retval EFI_SUCCESS All UEFI variables are locked.\r | |
821 | @retval EFI_UNSUPPORTED Variable Lock Protocol not found.\r | |
822 | @retval Other One of the UEFI variables could not be locked.\r | |
823 | **/\r | |
824 | EFI_STATUS\r | |
825 | LockAllFmpVariables (\r | |
826 | FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r | |
827 | )\r | |
828 | {\r | |
829 | EFI_STATUS Status;\r | |
830 | EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy;\r | |
831 | \r | |
832 | // Locate the VariablePolicy protocol.\r | |
833 | Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicy);\r | |
834 | if (EFI_ERROR (Status)) {\r | |
835 | DEBUG ((DEBUG_ERROR, "FmpDxe %a - Could not locate VariablePolicy protocol! %r\n", __FUNCTION__, Status));\r | |
836 | return Status;\r | |
837 | }\r | |
838 | \r | |
839 | Status = EFI_SUCCESS;\r | |
840 | Status = LockFmpVariable (Status, VariablePolicy, Private->VersionVariableName);\r | |
841 | Status = LockFmpVariable (Status, VariablePolicy, Private->LsvVariableName);\r | |
842 | Status = LockFmpVariable (Status, VariablePolicy, Private->LastAttemptStatusVariableName);\r | |
843 | Status = LockFmpVariable (Status, VariablePolicy, Private->LastAttemptVersionVariableName);\r | |
844 | Status = LockFmpVariable (Status, VariablePolicy, Private->FmpStateVariableName);\r | |
845 | \r | |
846 | return Status;\r | |
847 | }\r |