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