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