]> git.proxmox.com Git - mirror_edk2.git/blame - FmpDevicePkg/FmpDxe/FmpDxe.c
FmpDevicePkg: Apply uncrustify changes
[mirror_edk2.git] / FmpDevicePkg / FmpDxe / FmpDxe.c
CommitLineData
a6d73269 1/** @file\r
b0bacc00
KM
2 Produces a Firmware Management Protocol that supports updates to a firmware\r
3 image stored in a firmware device with platform and firmware device specific\r
4 information provided through PCDs and libraries.\r
5\r
de6859ec 6 Copyright (c) Microsoft Corporation.<BR>\r
2ed845b3 7 Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>\r
b0bacc00 8\r
bcef758c 9 SPDX-License-Identifier: BSD-2-Clause-Patent\r
b0bacc00
KM
10\r
11**/\r
12\r
4f0544b1 13#include "FmpDxe.h"\r
67c1e5ee 14#include "VariableSupport.h"\r
b0bacc00
KM
15\r
16///\r
17/// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the\r
18/// FILE_GUID must always be overridden in the <Defines> section to provide\r
19/// the ESRT GUID value associated with the updatable firmware image. A\r
20/// check is made in this module's driver entry point to verify that a\r
21/// new FILE_GUID value has been defined.\r
22///\r
23const EFI_GUID mDefaultModuleFileGuid = {\r
24 0x78ef0a56, 0x1cf0, 0x4535, { 0xb5, 0xda, 0xf6, 0xfd, 0x2f, 0x40, 0x5a, 0x11 }\r
25};\r
26\r
b0bacc00 27///\r
4f0544b1 28/// TRUE if FmpDeviceLib manages a single firmware storage device.\r
b0bacc00 29///\r
4f0544b1 30BOOLEAN mFmpSingleInstance = FALSE;\r
b0bacc00 31\r
4f0544b1
EJ
32///\r
33/// Firmware Management Protocol instance that is initialized in the entry\r
34/// point from PCD settings.\r
35///\r
36EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL mFmpProgress;\r
b0bacc00 37\r
0760f5fe 38//\r
4f0544b1
EJ
39// Template of the private context structure for the Firmware Management\r
40// Protocol instance\r
0760f5fe 41//\r
4f0544b1 42const FIRMWARE_MANAGEMENT_PRIVATE_DATA mFirmwareManagementPrivateDataTemplate = {\r
45ce0a67
MK
43 FIRMWARE_MANAGEMENT_PRIVATE_DATA_SIGNATURE, // Signature\r
44 NULL, // Handle\r
4f0544b1
EJ
45 { // Fmp\r
46 GetTheImageInfo,\r
47 GetTheImage,\r
48 SetTheImage,\r
49 CheckTheImage,\r
50 GetPackageInfo,\r
51 SetPackageInfo\r
52 },\r
45ce0a67
MK
53 FALSE, // DescriptorPopulated\r
54 { // Desc\r
55 1, // ImageIndex\r
4f0544b1
EJ
56 //\r
57 // ImageTypeId\r
58 //\r
45ce0a67
MK
59 { 0x00000000, 0x0000,0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }\r
60 },\r
4f0544b1
EJ
61 1, // ImageId\r
62 NULL, // ImageIdName\r
63 0, // Version\r
64 NULL, // VersionName\r
65 0, // Size\r
66 0, // AttributesSupported\r
67 0, // AttributesSetting\r
68 0, // Compatibilities\r
69 0, // LowestSupportedImageVersion\r
70 0, // LastAttemptVersion\r
71 0, // LastAttemptStatus\r
72 0 // HardwareInstance\r
73 },\r
45ce0a67
MK
74 NULL, // ImageIdName\r
75 NULL, // VersionName\r
76 TRUE, // RuntimeVersionSupported\r
77 NULL, // FmpDeviceLockEvent\r
78 FALSE, // FmpDeviceLocked\r
79 NULL, // FmpDeviceContext\r
80 NULL, // VersionVariableName\r
81 NULL, // LsvVariableName\r
82 NULL, // LastAttemptStatusVariableName\r
83 NULL, // LastAttemptVersionVariableName\r
84 NULL, // FmpStateVariableName\r
85 TRUE // DependenciesSatisfied\r
4f0544b1
EJ
86};\r
87\r
88///\r
89/// GUID that is used to create event used to lock the firmware storage device.\r
90///\r
91EFI_GUID *mLockGuid = NULL;\r
92\r
93///\r
94/// Progress() function pointer passed into SetTheImage()\r
95///\r
96EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS mProgressFunc = NULL;\r
97\r
98///\r
99/// Null-terminated Unicode string retrieved from PcdFmpDeviceImageIdName.\r
100///\r
101CHAR16 *mImageIdName = NULL;\r
b0bacc00
KM
102\r
103/**\r
104 Callback function to report the process of the firmware updating.\r
105\r
106 Wrap the caller's version in this so that progress from the device lib is\r
107 within the expected range. Convert device lib 0% - 100% to 6% - 98%.\r
108\r
109 FmpDxe 1% - 5% for validation\r
110 FmpDeviceLib 6% - 98% for flashing/update\r
111 FmpDxe 99% - 100% finish\r
112\r
113 @param[in] Completion A value between 1 and 100 indicating the current\r
114 completion progress of the firmware update. Completion\r
115 progress is reported as from 1 to 100 percent. A value\r
116 of 0 is used by the driver to indicate that progress\r
117 reporting is not supported.\r
118\r
119 @retval EFI_SUCCESS The progress was updated.\r
120 @retval EFI_UNSUPPORTED Updating progress is not supported.\r
121\r
122**/\r
123EFI_STATUS\r
124EFIAPI\r
125FmpDxeProgress (\r
126 IN UINTN Completion\r
127 )\r
128{\r
45ce0a67 129 EFI_STATUS Status;\r
b0bacc00
KM
130\r
131 Status = EFI_UNSUPPORTED;\r
132\r
b0bacc00
KM
133 if (mProgressFunc == NULL) {\r
134 return Status;\r
135 }\r
136\r
137 //\r
138 // Reserve 6% - 98% for the FmpDeviceLib. Call the real progress function.\r
139 //\r
140 Status = mProgressFunc (((Completion * 92) / 100) + 6);\r
141\r
142 if (Status == EFI_UNSUPPORTED) {\r
b0bacc00
KM
143 mProgressFunc = NULL;\r
144 }\r
145\r
146 return Status;\r
147}\r
148\r
149/**\r
150 Returns a pointer to the ImageTypeId GUID value. An attempt is made to get\r
151 the GUID value from the FmpDeviceLib. If the FmpDeviceLib does not provide\r
278c3d48
EJ
152 a GUID value, then PcdFmpDeviceImageTypeIdGuid is used. If the size of\r
153 PcdFmpDeviceImageTypeIdGuid is not the size of EFI_GUID, then gEfiCallerIdGuid\r
154 is returned.\r
b0bacc00 155\r
67c1e5ee 156 @retval The ImageTypeId GUID\r
b0bacc00
KM
157\r
158**/\r
159EFI_GUID *\r
160GetImageTypeIdGuid (\r
161 VOID\r
162 )\r
163{\r
164 EFI_STATUS Status;\r
165 EFI_GUID *FmpDeviceLibGuid;\r
278c3d48 166 UINTN ImageTypeIdGuidSize;\r
b0bacc00
KM
167\r
168 FmpDeviceLibGuid = NULL;\r
45ce0a67 169 Status = FmpDeviceGetImageTypeIdGuidPtr (&FmpDeviceLibGuid);\r
b0bacc00
KM
170 if (EFI_ERROR (Status)) {\r
171 if (Status != EFI_UNSUPPORTED) {\r
e0961677 172 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", mImageIdName, Status));\r
b0bacc00 173 }\r
278c3d48 174 } else if (FmpDeviceLibGuid == NULL) {\r
e0961677 175 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n", mImageIdName));\r
278c3d48
EJ
176 Status = EFI_NOT_FOUND;\r
177 }\r
45ce0a67 178\r
278c3d48
EJ
179 if (EFI_ERROR (Status)) {\r
180 ImageTypeIdGuidSize = PcdGetSize (PcdFmpDeviceImageTypeIdGuid);\r
181 if (ImageTypeIdGuidSize == sizeof (EFI_GUID)) {\r
182 FmpDeviceLibGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceImageTypeIdGuid);\r
183 } else {\r
de6859ec 184 DEBUG ((DEBUG_WARN, "FmpDxe(%s): Fall back to ImageTypeIdGuid of gEfiCallerIdGuid\n", mImageIdName));\r
278c3d48
EJ
185 FmpDeviceLibGuid = &gEfiCallerIdGuid;\r
186 }\r
b0bacc00 187 }\r
45ce0a67 188\r
b0bacc00
KM
189 return FmpDeviceLibGuid;\r
190}\r
191\r
192/**\r
193 Returns a pointer to the Null-terminated Unicode ImageIdName string.\r
194\r
67c1e5ee 195 @retval Null-terminated Unicode ImageIdName string.\r
b0bacc00
KM
196\r
197**/\r
198CHAR16 *\r
199GetImageTypeNameString (\r
200 VOID\r
201 )\r
202{\r
203 return mImageIdName;\r
204}\r
205\r
206/**\r
207 Lowest supported version is a combo of three parts.\r
208 1. Check if the device lib has a lowest supported version\r
209 2. Check if we have a variable for lowest supported version (this will be updated with each capsule applied)\r
210 3. Check Fixed at build PCD\r
211\r
67c1e5ee
EJ
212 @param[in] Private Pointer to the private context structure for the\r
213 Firmware Management Protocol instance.\r
214\r
215 @retval The largest value\r
b0bacc00
KM
216\r
217**/\r
218UINT32\r
219GetLowestSupportedVersion (\r
67c1e5ee 220 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
b0bacc00
KM
221 )\r
222{\r
223 EFI_STATUS Status;\r
224 UINT32 DeviceLibLowestSupportedVersion;\r
225 UINT32 VariableLowestSupportedVersion;\r
226 UINT32 ReturnLsv;\r
227\r
228 //\r
229 // Get the LowestSupportedVersion.\r
230 //\r
231\r
b0bacc00 232 if (!IsLowestSupportedVersionCheckRequired ()) {\r
1bbb5126
SZ
233 //\r
234 // Any Version can pass the 0 LowestSupportedVersion check.\r
235 //\r
236 return 0;\r
b0bacc00
KM
237 }\r
238\r
1bbb5126
SZ
239 ReturnLsv = PcdGet32 (PcdFmpDeviceBuildTimeLowestSupportedVersion);\r
240\r
b0bacc00
KM
241 //\r
242 // Check the FmpDeviceLib\r
243 //\r
559b5d52 244 DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
45ce0a67 245 Status = FmpDeviceGetLowestSupportedVersion (&DeviceLibLowestSupportedVersion);\r
b0bacc00
KM
246 if (EFI_ERROR (Status)) {\r
247 DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
248 }\r
249\r
250 if (DeviceLibLowestSupportedVersion > ReturnLsv) {\r
251 ReturnLsv = DeviceLibLowestSupportedVersion;\r
252 }\r
253\r
254 //\r
255 // Check the lowest supported version UEFI variable for this device\r
256 //\r
67c1e5ee 257 VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable (Private);\r
b0bacc00
KM
258 if (VariableLowestSupportedVersion > ReturnLsv) {\r
259 ReturnLsv = VariableLowestSupportedVersion;\r
260 }\r
261\r
262 //\r
263 // Return the largest value\r
264 //\r
265 return ReturnLsv;\r
266}\r
267\r
268/**\r
4f0544b1
EJ
269 Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the private\r
270 context structure.\r
271\r
272 @param[in] Private Pointer to the private context structure for the\r
273 Firmware Management Protocol instance.\r
b0bacc00
KM
274\r
275**/\r
276VOID\r
277PopulateDescriptor (\r
4f0544b1 278 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
b0bacc00
KM
279 )\r
280{\r
281 EFI_STATUS Status;\r
0f30087b 282 UINT32 DependenciesSize;\r
b0bacc00 283\r
b4b9496b
MK
284 if (Private == NULL) {\r
285 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): PopulateDescriptor() - Private is NULL.\n", mImageIdName));\r
286 return;\r
287 }\r
288\r
4f0544b1
EJ
289 if (Private->DescriptorPopulated) {\r
290 return;\r
291 }\r
292\r
293 Private->Descriptor.ImageIndex = 1;\r
45ce0a67 294 CopyGuid (&Private->Descriptor.ImageTypeId, GetImageTypeIdGuid ());\r
4f0544b1 295 Private->Descriptor.ImageId = Private->Descriptor.ImageIndex;\r
45ce0a67 296 Private->Descriptor.ImageIdName = GetImageTypeNameString ();\r
b0bacc00 297\r
67c1e5ee
EJ
298 //\r
299 // Get the hardware instance from FmpDeviceLib\r
300 //\r
301 Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance);\r
302 if (Status == EFI_UNSUPPORTED) {\r
303 Private->Descriptor.HardwareInstance = 0;\r
304 }\r
305\r
306 //\r
307 // Generate UEFI Variable names used to store status information for this\r
308 // FMP instance.\r
309 //\r
310 GenerateFmpVariableNames (Private);\r
311\r
b0bacc00
KM
312 //\r
313 // Get the version. Some devices don't support getting the firmware version\r
314 // at runtime. If FmpDeviceLib does not support returning a version, then\r
315 // it is stored in a UEFI variable.\r
316 //\r
4f0544b1 317 Status = FmpDeviceGetVersion (&Private->Descriptor.Version);\r
b0bacc00 318 if (Status == EFI_UNSUPPORTED) {\r
4f0544b1 319 Private->RuntimeVersionSupported = FALSE;\r
45ce0a67 320 Private->Descriptor.Version = GetVersionFromVariable (Private);\r
b0bacc00
KM
321 } else if (EFI_ERROR (Status)) {\r
322 //\r
323 // Unexpected error. Use default version.\r
324 //\r
45ce0a67 325 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetVersion() from FmpDeviceLib (%s) returned %r\n", mImageIdName, GetImageTypeNameString (), Status));\r
4f0544b1 326 Private->Descriptor.Version = DEFAULT_VERSION;\r
b0bacc00
KM
327 }\r
328\r
329 //\r
330 // Free the current version name. Shouldn't really happen but this populate\r
331 // function could be called multiple times (to refresh).\r
332 //\r
4f0544b1
EJ
333 if (Private->Descriptor.VersionName != NULL) {\r
334 FreePool (Private->Descriptor.VersionName);\r
335 Private->Descriptor.VersionName = NULL;\r
b0bacc00
KM
336 }\r
337\r
338 //\r
339 // Attempt to get the version string from the FmpDeviceLib\r
340 //\r
4f0544b1 341 Status = FmpDeviceGetVersionString (&Private->Descriptor.VersionName);\r
b0bacc00 342 if (Status == EFI_UNSUPPORTED) {\r
e0961677 343 DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() unsupported in FmpDeviceLib.\n", mImageIdName));\r
4f0544b1
EJ
344 Private->Descriptor.VersionName = AllocateCopyPool (\r
345 sizeof (VERSION_STRING_NOT_SUPPORTED),\r
346 VERSION_STRING_NOT_SUPPORTED\r
347 );\r
b0bacc00 348 } else if (EFI_ERROR (Status)) {\r
e0961677 349 DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() not available in FmpDeviceLib.\n", mImageIdName));\r
4f0544b1
EJ
350 Private->Descriptor.VersionName = AllocateCopyPool (\r
351 sizeof (VERSION_STRING_NOT_AVAILABLE),\r
352 VERSION_STRING_NOT_AVAILABLE\r
353 );\r
b0bacc00
KM
354 }\r
355\r
67c1e5ee 356 Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion (Private);\r
b0bacc00
KM
357\r
358 //\r
359 // Get attributes from the FmpDeviceLib\r
360 //\r
4f0544b1
EJ
361 FmpDeviceGetAttributes (\r
362 &Private->Descriptor.AttributesSupported,\r
363 &Private->Descriptor.AttributesSetting\r
364 );\r
b0bacc00
KM
365\r
366 //\r
367 // Force set the updatable bits in the attributes;\r
368 //\r
4f0544b1
EJ
369 Private->Descriptor.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;\r
370 Private->Descriptor.AttributesSetting |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;\r
b0bacc00
KM
371\r
372 //\r
373 // Force set the authentication bits in the attributes;\r
374 //\r
4f0544b1
EJ
375 Private->Descriptor.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
376 Private->Descriptor.AttributesSetting |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
b0bacc00 377\r
4f0544b1 378 Private->Descriptor.Compatibilities = 0;\r
b0bacc00
KM
379\r
380 //\r
381 // Get the size of the firmware image from the FmpDeviceLib\r
382 //\r
4f0544b1 383 Status = FmpDeviceGetSize (&Private->Descriptor.Size);\r
b0bacc00 384 if (EFI_ERROR (Status)) {\r
4f0544b1 385 Private->Descriptor.Size = 0;\r
b0bacc00
KM
386 }\r
387\r
67c1e5ee
EJ
388 Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable (Private);\r
389 Private->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable (Private);\r
4f0544b1 390\r
2ed845b3 391 //\r
0f30087b 392 // Get the dependency from the FmpDependencyDeviceLib.\r
2ed845b3
WX
393 //\r
394 Private->Descriptor.Dependencies = NULL;\r
395\r
396 //\r
397 // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY\r
398 //\r
0f30087b
WX
399 if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {\r
400 Private->Descriptor.Dependencies = GetFmpDependency (&DependenciesSize);\r
2ed845b3
WX
401 }\r
402\r
4f0544b1 403 Private->DescriptorPopulated = TRUE;\r
b0bacc00
KM
404}\r
405\r
406/**\r
407 Returns information about the current firmware image(s) of the device.\r
408\r
409 This function allows a copy of the current firmware image to be created and saved.\r
410 The saved copy could later been used, for example, in firmware image recovery or rollback.\r
411\r
412 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
413 @param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.\r
414 On input, this is the size of the buffer allocated by the caller.\r
415 On output, it is the size of the buffer returned by the firmware\r
416 if the buffer was large enough, or the size of the buffer needed\r
417 to contain the image(s) information if the buffer was too small.\r
418 @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)\r
419 information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.\r
420 @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number\r
421 associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
422 @param[out] DescriptorCount A pointer to the location in which firmware returns the number of\r
423 descriptors or firmware images within this device.\r
424 @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,\r
425 of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
426 @param[out] PackageVersion A version number that represents all the firmware images in the device.\r
427 The format is vendor specific and new version must have a greater value\r
428 than the old version. If PackageVersion is not supported, the value is\r
429 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison\r
430 is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates\r
431 that package version update is in progress.\r
432 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the\r
433 package version name. The buffer is allocated by this function with\r
434 AllocatePool(), and it is the caller's responsibility to free it with a call\r
435 to FreePool().\r
436\r
437 @retval EFI_SUCCESS The device was successfully updated with the new image.\r
438 @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size\r
439 needed to hold the image(s) information is returned in ImageInfoSize.\r
440 @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.\r
441 @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.\r
442\r
443**/\r
444EFI_STATUS\r
445EFIAPI\r
446GetTheImageInfo (\r
447 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
448 IN OUT UINTN *ImageInfoSize,\r
449 IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,\r
450 OUT UINT32 *DescriptorVersion,\r
451 OUT UINT8 *DescriptorCount,\r
452 OUT UINTN *DescriptorSize,\r
453 OUT UINT32 *PackageVersion,\r
454 OUT CHAR16 **PackageVersionName\r
455 )\r
456{\r
4f0544b1
EJ
457 EFI_STATUS Status;\r
458 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
b0bacc00
KM
459\r
460 Status = EFI_SUCCESS;\r
461\r
b4b9496b
MK
462 if (This == NULL) {\r
463 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - This is NULL.\n", mImageIdName));\r
464 Status = EFI_INVALID_PARAMETER;\r
465 goto cleanup;\r
466 }\r
467\r
4f0544b1
EJ
468 //\r
469 // Retrieve the private context structure\r
470 //\r
471 Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
472 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
473\r
b0bacc00
KM
474 //\r
475 // Check for valid pointer\r
476 //\r
477 if (ImageInfoSize == NULL) {\r
e0961677 478 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is NULL.\n", mImageIdName));\r
b0bacc00
KM
479 Status = EFI_INVALID_PARAMETER;\r
480 goto cleanup;\r
481 }\r
482\r
483 //\r
484 // Check the buffer size\r
485 // NOTE: Check this first so caller can get the necessary memory size it must allocate.\r
486 //\r
487 if (*ImageInfoSize < (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR))) {\r
488 *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);\r
e0961677 489 DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is to small.\n", mImageIdName));\r
b0bacc00
KM
490 Status = EFI_BUFFER_TOO_SMALL;\r
491 goto cleanup;\r
492 }\r
493\r
494 //\r
495 // Confirm that buffer isn't null\r
496 //\r
45ce0a67
MK
497 if ( (ImageInfo == NULL) || (DescriptorVersion == NULL) || (DescriptorCount == NULL) || (DescriptorSize == NULL)\r
498 || (PackageVersion == NULL))\r
499 {\r
e0961677 500 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - Pointer Parameter is NULL.\n", mImageIdName));\r
b0bacc00
KM
501 Status = EFI_INVALID_PARAMETER;\r
502 goto cleanup;\r
503 }\r
504\r
505 //\r
506 // Set the size to whatever we need\r
507 //\r
508 *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);\r
509\r
4f0544b1 510 //\r
67c1e5ee 511 // Make sure the descriptor has already been loaded or refreshed\r
4f0544b1
EJ
512 //\r
513 PopulateDescriptor (Private);\r
b0bacc00
KM
514\r
515 //\r
516 // Copy the image descriptor\r
517 //\r
4f0544b1 518 CopyMem (ImageInfo, &Private->Descriptor, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR));\r
b0bacc00
KM
519\r
520 *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;\r
45ce0a67
MK
521 *DescriptorCount = 1;\r
522 *DescriptorSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);\r
b0bacc00
KM
523 //\r
524 // means unsupported\r
525 //\r
526 *PackageVersion = 0xFFFFFFFF;\r
527\r
528 //\r
529 // Do not update PackageVersionName since it is not supported in this instance.\r
530 //\r
531\r
532cleanup:\r
533\r
534 return Status;\r
535}\r
536\r
537/**\r
538 Retrieves a copy of the current firmware image of the device.\r
539\r
540 This function allows a copy of the current firmware image to be created and saved.\r
541 The saved copy could later been used, for example, in firmware image recovery or rollback.\r
542\r
a6d73269
SZ
543 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
544 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
b0bacc00 545 The number is between 1 and DescriptorCount.\r
a6d73269
SZ
546 @param[in, out] Image Points to the buffer where the current image is copied to.\r
547 @param[in, out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.\r
b0bacc00
KM
548 On return, points to the length of the image, in bytes.\r
549\r
550 @retval EFI_SUCCESS The device was successfully updated with the new image.\r
551 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the\r
552 image. The current buffer size needed to hold the image is returned\r
553 in ImageSize.\r
554 @retval EFI_INVALID_PARAMETER The Image was NULL.\r
555 @retval EFI_NOT_FOUND The current image is not copied to the buffer.\r
556 @retval EFI_UNSUPPORTED The operation is not supported.\r
5fc5867e 557 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
b0bacc00
KM
558\r
559**/\r
560EFI_STATUS\r
561EFIAPI\r
562GetTheImage (\r
563 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
564 IN UINT8 ImageIndex,\r
565 IN OUT VOID *Image,\r
566 IN OUT UINTN *ImageSize\r
567 )\r
568{\r
4f0544b1
EJ
569 EFI_STATUS Status;\r
570 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
571 UINTN Size;\r
b0bacc00 572\r
11d35494
EJ
573 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
574 return EFI_UNSUPPORTED;\r
575 }\r
576\r
0f30087b 577 Status = EFI_SUCCESS;\r
b0bacc00 578\r
b4b9496b
MK
579 if (This == NULL) {\r
580 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - This is NULL.\n", mImageIdName));\r
581 Status = EFI_INVALID_PARAMETER;\r
582 goto cleanup;\r
583 }\r
584\r
4f0544b1
EJ
585 //\r
586 // Retrieve the private context structure\r
587 //\r
588 Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
589 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
590\r
ebfac291
SZ
591 //\r
592 // Check to make sure index is 1 (only 1 image for this device)\r
593 //\r
594 if (ImageIndex != 1) {\r
e0961677 595 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Index Invalid.\n", mImageIdName));\r
ebfac291
SZ
596 Status = EFI_INVALID_PARAMETER;\r
597 goto cleanup;\r
598 }\r
599\r
03340683 600 if (ImageSize == NULL) {\r
e0961677 601 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - ImageSize Pointer Parameter is NULL.\n", mImageIdName));\r
b0bacc00
KM
602 Status = EFI_INVALID_PARAMETER;\r
603 goto cleanup;\r
604 }\r
605\r
606 //\r
607 // Check the buffer size\r
608 //\r
609 Status = FmpDeviceGetSize (&Size);\r
610 if (EFI_ERROR (Status)) {\r
611 Size = 0;\r
612 }\r
45ce0a67 613\r
0f30087b
WX
614 if (*ImageSize < Size) {\r
615 *ImageSize = Size;\r
e0961677 616 DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName));\r
b0bacc00
KM
617 Status = EFI_BUFFER_TOO_SMALL;\r
618 goto cleanup;\r
619 }\r
620\r
621 if (Image == NULL) {\r
e0961677 622 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Pointer Parameter is NULL.\n", mImageIdName));\r
b0bacc00
KM
623 Status = EFI_INVALID_PARAMETER;\r
624 goto cleanup;\r
625 }\r
626\r
0f30087b 627 Status = FmpDeviceGetImage (Image, ImageSize);\r
b0bacc00
KM
628cleanup:\r
629\r
630 return Status;\r
631}\r
632\r
633/**\r
634 Helper function to safely retrieve the FMP header from\r
635 within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.\r
636\r
0f30087b
WX
637 @param[in] Image Pointer to the image.\r
638 @param[in] ImageSize Size of the image.\r
639 @param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.\r
b4b9496b
MK
640 @param[out] PayloadSize An optional pointer to a UINTN that holds the size of the payload\r
641 (image size minus headers)\r
b0bacc00
KM
642\r
643 @retval !NULL Valid pointer to the header.\r
644 @retval NULL Structure is bad and pointer cannot be found.\r
645\r
646**/\r
647VOID *\r
648GetFmpHeader (\r
649 IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,\r
650 IN CONST UINTN ImageSize,\r
0f30087b 651 IN CONST UINTN AdditionalHeaderSize,\r
b4b9496b 652 OUT UINTN *PayloadSize OPTIONAL\r
b0bacc00
KM
653 )\r
654{\r
655 //\r
656 // Check to make sure that operation can be safely performed.\r
657 //\r
45ce0a67
MK
658 if ((((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize < (UINTN)Image) || \\r
659 (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize >= (UINTN)Image + ImageSize))\r
660 {\r
b0bacc00
KM
661 //\r
662 // Pointer overflow. Invalid image.\r
663 //\r
664 return NULL;\r
665 }\r
666\r
b4b9496b
MK
667 if (PayloadSize != NULL) {\r
668 *PayloadSize = ImageSize - (sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength + AdditionalHeaderSize);\r
669 }\r
670\r
0f30087b 671 return (VOID *)((UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength + AdditionalHeaderSize);\r
b0bacc00
KM
672}\r
673\r
674/**\r
675 Helper function to safely calculate the size of all headers\r
676 within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.\r
677\r
678 @param[in] Image Pointer to the image.\r
679 @param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.\r
680\r
681 @retval UINT32>0 Valid size of all the headers.\r
682 @retval 0 Structure is bad and size cannot be found.\r
683\r
684**/\r
685UINT32\r
686GetAllHeaderSize (\r
687 IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,\r
688 IN UINT32 AdditionalHeaderSize\r
689 )\r
690{\r
691 UINT32 CalculatedSize;\r
692\r
b4b9496b
MK
693 if (Image == NULL) {\r
694 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetAllHeaderSize() - Image is NULL.\n", mImageIdName));\r
695 return 0;\r
696 }\r
697\r
b0bacc00
KM
698 CalculatedSize = sizeof (Image->MonotonicCount) +\r
699 AdditionalHeaderSize +\r
700 Image->AuthInfo.Hdr.dwLength;\r
701\r
702 //\r
703 // Check to make sure that operation can be safely performed.\r
704 //\r
45ce0a67
MK
705 if ((CalculatedSize < sizeof (Image->MonotonicCount)) ||\r
706 (CalculatedSize < AdditionalHeaderSize) ||\r
707 (CalculatedSize < Image->AuthInfo.Hdr.dwLength))\r
708 {\r
b0bacc00
KM
709 //\r
710 // Integer overflow. Invalid image.\r
711 //\r
712 return 0;\r
713 }\r
714\r
715 return CalculatedSize;\r
716}\r
717\r
718/**\r
719 Checks if the firmware image is valid for the device.\r
720\r
721 This function allows firmware update application to validate the firmware image without\r
722 invoking the SetImage() first.\r
723\r
724 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
725 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
726 The number is between 1 and DescriptorCount.\r
727 @param[in] Image Points to the new image.\r
728 @param[in] ImageSize Size of the new image in bytes.\r
729 @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,\r
730 if available, additional information if the image is invalid.\r
5550f4d3
MK
731 @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt status to report\r
732 back to the ESRT table in case of error. If an error does not occur,\r
733 this function will set the value to LAST_ATTEMPT_STATUS_SUCCESS.\r
734\r
735 This function will return error codes that occur within this function\r
736 implementation within a driver range of last attempt error codes from\r
737 LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE_VALUE\r
738 to LAST_ATTEMPT_STATUS_DRIVER_MAX_ERROR_CODE_VALUE.\r
b0bacc00 739\r
207414cb
MK
740 This function might also return error codes that occur within libraries\r
741 linked against this module that return last attempt error codes such as:\r
742\r
743 LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MIN_ERROR_CODE_VALUE to\r
744 LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MAX_ERROR_CODE_VALUE\r
745\r
746 LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MIN_ERROR_CODE_VALUE to\r
747 LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MAX_ERROR_CODE_VALUE\r
748\r
b0bacc00 749 @retval EFI_SUCCESS The image was successfully checked.\r
4e61b8d0 750 @retval EFI_ABORTED The operation is aborted.\r
b0bacc00
KM
751 @retval EFI_INVALID_PARAMETER The Image was NULL.\r
752 @retval EFI_UNSUPPORTED The operation is not supported.\r
5fc5867e 753 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
b0bacc00
KM
754\r
755**/\r
756EFI_STATUS\r
757EFIAPI\r
5550f4d3 758CheckTheImageInternal (\r
b0bacc00
KM
759 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
760 IN UINT8 ImageIndex,\r
761 IN CONST VOID *Image,\r
762 IN UINTN ImageSize,\r
5550f4d3
MK
763 OUT UINT32 *ImageUpdatable,\r
764 OUT UINT32 *LastAttemptStatus\r
b0bacc00
KM
765 )\r
766{\r
4f0544b1 767 EFI_STATUS Status;\r
5550f4d3 768 UINT32 LocalLastAttemptStatus;\r
4f0544b1
EJ
769 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
770 UINTN RawSize;\r
771 VOID *FmpPayloadHeader;\r
772 UINTN FmpPayloadSize;\r
773 UINT32 Version;\r
774 UINT32 FmpHeaderSize;\r
775 UINTN AllHeaderSize;\r
776 UINT32 Index;\r
777 VOID *PublicKeyData;\r
778 UINTN PublicKeyDataLength;\r
779 UINT8 *PublicKeyDataXdr;\r
780 UINT8 *PublicKeyDataXdrEnd;\r
2ed845b3
WX
781 EFI_FIRMWARE_IMAGE_DEP *Dependencies;\r
782 UINT32 DependenciesSize;\r
b0bacc00 783\r
45ce0a67
MK
784 Status = EFI_SUCCESS;\r
785 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
786 RawSize = 0;\r
787 FmpPayloadHeader = NULL;\r
788 FmpPayloadSize = 0;\r
789 Version = 0;\r
790 FmpHeaderSize = 0;\r
791 AllHeaderSize = 0;\r
792 Dependencies = NULL;\r
793 DependenciesSize = 0;\r
b0bacc00 794\r
11d35494
EJ
795 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
796 return EFI_UNSUPPORTED;\r
797 }\r
798\r
5550f4d3
MK
799 if (LastAttemptStatus == NULL) {\r
800 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImageInternal() - LastAttemptStatus is NULL.\n", mImageIdName));\r
801 Status = EFI_INVALID_PARAMETER;\r
802 goto cleanup;\r
803 }\r
804\r
805 //\r
806 // A last attempt status error code will always override the success\r
807 // value before returning from the function\r
808 //\r
809 *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
810\r
b4b9496b
MK
811 if (This == NULL) {\r
812 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - This is NULL.\n", mImageIdName));\r
45ce0a67 813 Status = EFI_INVALID_PARAMETER;\r
5550f4d3 814 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;\r
b4b9496b
MK
815 goto cleanup;\r
816 }\r
817\r
4f0544b1
EJ
818 //\r
819 // Retrieve the private context structure\r
820 //\r
821 Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
822 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
823\r
b0bacc00 824 //\r
67c1e5ee 825 // Make sure the descriptor has already been loaded or refreshed\r
b0bacc00 826 //\r
4f0544b1 827 PopulateDescriptor (Private);\r
b0bacc00 828\r
a6d73269 829 if (ImageUpdatable == NULL) {\r
e0961677 830 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName));\r
45ce0a67 831 Status = EFI_INVALID_PARAMETER;\r
5550f4d3 832 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_UPDATABLE;\r
b0bacc00
KM
833 goto cleanup;\r
834 }\r
835\r
836 //\r
45ce0a67 837 // Set to valid and then if any tests fail it will update this flag.\r
b0bacc00 838 //\r
a6d73269 839 *ImageUpdatable = IMAGE_UPDATABLE_VALID;\r
b0bacc00 840\r
0f30087b
WX
841 //\r
842 // Set to satisfied and then if dependency evaluates to false it will update this flag.\r
843 //\r
844 Private->DependenciesSatisfied = TRUE;\r
845\r
b0bacc00 846 if (Image == NULL) {\r
e0961677 847 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName));\r
b0bacc00
KM
848 //\r
849 // not sure if this is needed\r
850 //\r
45ce0a67 851 *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
5550f4d3 852 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_PROVIDED;\r
b0bacc00
KM
853 return EFI_INVALID_PARAMETER;\r
854 }\r
855\r
856 PublicKeyDataXdr = PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr);\r
857 PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr);\r
858\r
45ce0a67 859 if ((PublicKeyDataXdr == NULL) || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {\r
e0961677 860 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName));\r
45ce0a67 861 Status = EFI_ABORTED;\r
5550f4d3 862 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_CERTIFICATE;\r
b0bacc00
KM
863 } else {\r
864 //\r
865 // Try each key from PcdFmpDevicePkcs7CertBufferXdr\r
866 //\r
867 for (Index = 1; PublicKeyDataXdr < PublicKeyDataXdrEnd; Index++) {\r
868 Index++;\r
869 DEBUG (\r
870 (DEBUG_INFO,\r
45ce0a67
MK
871 "FmpDxe(%s): Certificate #%d [%p..%p].\n",\r
872 mImageIdName,\r
873 Index,\r
874 PublicKeyDataXdr,\r
875 PublicKeyDataXdrEnd\r
b0bacc00
KM
876 )\r
877 );\r
878\r
879 if ((PublicKeyDataXdr + sizeof (UINT32)) > PublicKeyDataXdrEnd) {\r
880 //\r
881 // Key data extends beyond end of PCD\r
882 //\r
e0961677 883 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate size extends beyond end of PCD, skipping it.\n", mImageIdName));\r
45ce0a67 884 Status = EFI_ABORTED;\r
5550f4d3 885 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH_VALUE;\r
b0bacc00
KM
886 break;\r
887 }\r
45ce0a67 888\r
b0bacc00
KM
889 //\r
890 // Read key length stored in big-endian format\r
891 //\r
892 PublicKeyDataLength = SwapBytes32 (*(UINT32 *)(PublicKeyDataXdr));\r
893 //\r
894 // Point to the start of the key data\r
895 //\r
896 PublicKeyDataXdr += sizeof (UINT32);\r
897 if (PublicKeyDataXdr + PublicKeyDataLength > PublicKeyDataXdrEnd) {\r
898 //\r
899 // Key data extends beyond end of PCD\r
900 //\r
e0961677 901 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName));\r
45ce0a67 902 Status = EFI_ABORTED;\r
5550f4d3 903 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH;\r
b0bacc00
KM
904 break;\r
905 }\r
45ce0a67 906\r
b0bacc00 907 PublicKeyData = PublicKeyDataXdr;\r
45ce0a67
MK
908 Status = AuthenticateFmpImage (\r
909 (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image,\r
910 ImageSize,\r
911 PublicKeyData,\r
912 PublicKeyDataLength\r
913 );\r
b0bacc00
KM
914 if (!EFI_ERROR (Status)) {\r
915 break;\r
916 }\r
45ce0a67 917\r
b0bacc00 918 PublicKeyDataXdr += PublicKeyDataLength;\r
45ce0a67 919 PublicKeyDataXdr = (UINT8 *)ALIGN_POINTER (PublicKeyDataXdr, sizeof (UINT32));\r
b0bacc00
KM
920 }\r
921 }\r
922\r
923 if (EFI_ERROR (Status)) {\r
e0961677 924 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Authentication Failed %r.\n", mImageIdName, Status));\r
5550f4d3
MK
925 if (LocalLastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {\r
926 *LastAttemptStatus = LocalLastAttemptStatus;\r
927 } else {\r
928 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_AUTH_FAILURE;\r
929 }\r
45ce0a67 930\r
b0bacc00
KM
931 goto cleanup;\r
932 }\r
933\r
934 //\r
935 // Check to make sure index is 1\r
936 //\r
937 if (ImageIndex != 1) {\r
e0961677 938 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName));\r
45ce0a67
MK
939 *ImageUpdatable = IMAGE_UPDATABLE_INVALID_TYPE;\r
940 Status = EFI_INVALID_PARAMETER;\r
5550f4d3 941 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_IMAGE_INDEX;\r
b0bacc00
KM
942 goto cleanup;\r
943 }\r
944\r
0f30087b
WX
945 //\r
946 // Get the dependency from Image.\r
947 //\r
207414cb 948 Dependencies = GetImageDependency (\r
45ce0a67 949 (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image,\r
207414cb
MK
950 ImageSize,\r
951 &DependenciesSize,\r
952 LastAttemptStatus\r
953 );\r
954 if (*LastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {\r
955 Status = EFI_ABORTED;\r
956 goto cleanup;\r
957 }\r
b0bacc00
KM
958\r
959 //\r
960 // Check the FmpPayloadHeader\r
961 //\r
45ce0a67 962 FmpPayloadHeader = GetFmpHeader ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize);\r
b0bacc00 963 if (FmpPayloadHeader == NULL) {\r
e0961677 964 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));\r
45ce0a67 965 Status = EFI_ABORTED;\r
5550f4d3 966 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;\r
b0bacc00
KM
967 goto cleanup;\r
968 }\r
45ce0a67 969\r
b0bacc00
KM
970 Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);\r
971 if (EFI_ERROR (Status)) {\r
0f30087b 972 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));\r
45ce0a67
MK
973 *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
974 Status = EFI_SUCCESS;\r
5550f4d3 975 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_VERSION;\r
0f30087b 976 goto cleanup;\r
b0bacc00
KM
977 }\r
978\r
979 //\r
980 // Check the lowest supported version\r
981 //\r
4f0544b1 982 if (Version < Private->Descriptor.LowestSupportedImageVersion) {\r
b0bacc00
KM
983 DEBUG (\r
984 (DEBUG_ERROR,\r
45ce0a67
MK
985 "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",\r
986 mImageIdName, Version, Private->Descriptor.LowestSupportedImageVersion)\r
b0bacc00 987 );\r
45ce0a67
MK
988 *ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;\r
989 Status = EFI_SUCCESS;\r
5550f4d3 990 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_VERSION_TOO_LOW;\r
b0bacc00
KM
991 goto cleanup;\r
992 }\r
993\r
2ed845b3
WX
994 //\r
995 // Evaluate dependency expression\r
996 //\r
207414cb
MK
997 Private->DependenciesSatisfied = CheckFmpDependency (\r
998 Private->Descriptor.ImageTypeId,\r
999 Version,\r
1000 Dependencies,\r
1001 DependenciesSize,\r
1002 &LocalLastAttemptStatus\r
1003 );\r
0f30087b
WX
1004 if (!Private->DependenciesSatisfied) {\r
1005 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed.\n", mImageIdName));\r
45ce0a67
MK
1006 *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
1007 Status = EFI_SUCCESS;\r
207414cb 1008 *LastAttemptStatus = LocalLastAttemptStatus;\r
2ed845b3
WX
1009 goto cleanup;\r
1010 }\r
1011\r
b0bacc00
KM
1012 //\r
1013 // Get the FmpHeaderSize so we can determine the real payload size\r
1014 //\r
1015 Status = GetFmpPayloadHeaderSize (FmpPayloadHeader, FmpPayloadSize, &FmpHeaderSize);\r
1016 if (EFI_ERROR (Status)) {\r
1017 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));\r
45ce0a67
MK
1018 *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
1019 Status = EFI_SUCCESS;\r
5550f4d3 1020 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;\r
b0bacc00
KM
1021 goto cleanup;\r
1022 }\r
1023\r
1024 //\r
1025 // Call FmpDevice Lib Check Image on the\r
1026 // Raw payload. So all headers need stripped off\r
1027 //\r
45ce0a67 1028 AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);\r
b0bacc00 1029 if (AllHeaderSize == 0) {\r
e0961677 1030 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName));\r
45ce0a67 1031 Status = EFI_ABORTED;\r
5550f4d3 1032 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;\r
b0bacc00
KM
1033 goto cleanup;\r
1034 }\r
45ce0a67 1035\r
b0bacc00
KM
1036 RawSize = ImageSize - AllHeaderSize;\r
1037\r
1038 //\r
1039 // FmpDeviceLib CheckImage function to do any specific checks\r
1040 //\r
45ce0a67 1041 Status = FmpDeviceCheckImageWithStatus ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdatable, LastAttemptStatus);\r
b0bacc00 1042 if (EFI_ERROR (Status)) {\r
e0961677 1043 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName, Status));\r
b96b44fe
MK
1044\r
1045 //\r
1046 // LastAttemptStatus returned from the device library should fall within the designated error range\r
1047 // [LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE, LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE]\r
1048 //\r
1049 if ((*LastAttemptStatus < LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE) ||\r
45ce0a67
MK
1050 (*LastAttemptStatus > LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE))\r
1051 {\r
b96b44fe
MK
1052 DEBUG (\r
1053 (DEBUG_ERROR,\r
45ce0a67
MK
1054 "FmpDxe(%s): CheckTheImage() - LastAttemptStatus %d from FmpDeviceCheckImageWithStatus() is invalid.\n",\r
1055 mImageIdName,\r
1056 *LastAttemptStatus)\r
b96b44fe
MK
1057 );\r
1058 *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
1059 }\r
b0bacc00
KM
1060 }\r
1061\r
1062cleanup:\r
1063 return Status;\r
1064}\r
1065\r
5550f4d3
MK
1066/**\r
1067 Checks if the firmware image is valid for the device.\r
1068\r
1069 This function allows firmware update application to validate the firmware image without\r
1070 invoking the SetImage() first.\r
1071\r
1072 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
1073 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
1074 The number is between 1 and DescriptorCount.\r
1075 @param[in] Image Points to the new image.\r
1076 @param[in] ImageSize Size of the new image in bytes.\r
1077 @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,\r
1078 if available, additional information if the image is invalid.\r
1079\r
1080 @retval EFI_SUCCESS The image was successfully checked.\r
1081 @retval EFI_ABORTED The operation is aborted.\r
1082 @retval EFI_INVALID_PARAMETER The Image was NULL.\r
1083 @retval EFI_UNSUPPORTED The operation is not supported.\r
1084 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
1085\r
1086**/\r
1087EFI_STATUS\r
1088EFIAPI\r
1089CheckTheImage (\r
1090 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
1091 IN UINT8 ImageIndex,\r
1092 IN CONST VOID *Image,\r
1093 IN UINTN ImageSize,\r
1094 OUT UINT32 *ImageUpdatable\r
1095 )\r
1096{\r
1097 UINT32 LastAttemptStatus;\r
1098\r
1099 return CheckTheImageInternal (This, ImageIndex, Image, ImageSize, ImageUpdatable, &LastAttemptStatus);\r
1100}\r
1101\r
b0bacc00
KM
1102/**\r
1103 Updates the firmware image of the device.\r
1104\r
1105 This function updates the hardware with the new firmware image.\r
1106 This function returns EFI_UNSUPPORTED if the firmware image is not updatable.\r
1107 If the firmware image is updatable, the function should perform the following minimal validations\r
1108 before proceeding to do the firmware image update.\r
1109 - Validate the image authentication if image has attribute\r
1110 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns\r
1111 EFI_SECURITY_VIOLATION if the validation fails.\r
1112 - Validate the image is a supported image for this device. The function returns EFI_ABORTED if\r
1113 the image is unsupported. The function can optionally provide more detailed information on\r
1114 why the image is not a supported image.\r
1115 - Validate the data from VendorCode if not null. Image validation must be performed before\r
1116 VendorCode data validation. VendorCode data is ignored or considered invalid if image\r
1117 validation failed. The function returns EFI_ABORTED if the data is invalid.\r
1118\r
1119 VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if\r
1120 the caller did not specify the policy or use the default policy. As an example, vendor can implement\r
1121 a policy to allow an option to force a firmware image update when the abort reason is due to the new\r
1122 firmware image version is older than the current firmware image version or bad image checksum.\r
1123 Sensitive operations such as those wiping the entire firmware image and render the device to be\r
1124 non-functional should be encoded in the image itself rather than passed with the VendorCode.\r
1125 AbortReason enables vendor to have the option to provide a more detailed description of the abort\r
1126 reason to the caller.\r
1127\r
1128 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
1129 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
1130 The number is between 1 and DescriptorCount.\r
1131 @param[in] Image Points to the new image.\r
1132 @param[in] ImageSize Size of the new image in bytes.\r
1133 @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.\r
1134 Null indicates the caller did not specify the policy or use the default policy.\r
1135 @param[in] Progress A function used by the driver to report the progress of the firmware update.\r
1136 @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more\r
1137 details for the aborted operation. The buffer is allocated by this function\r
1138 with AllocatePool(), and it is the caller's responsibility to free it with a\r
1139 call to FreePool().\r
1140\r
1141 @retval EFI_SUCCESS The device was successfully updated with the new image.\r
1142 @retval EFI_ABORTED The operation is aborted.\r
1143 @retval EFI_INVALID_PARAMETER The Image was NULL.\r
1144 @retval EFI_UNSUPPORTED The operation is not supported.\r
5fc5867e 1145 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
b0bacc00
KM
1146\r
1147**/\r
1148EFI_STATUS\r
1149EFIAPI\r
1150SetTheImage (\r
1151 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
1152 IN UINT8 ImageIndex,\r
1153 IN CONST VOID *Image,\r
1154 IN UINTN ImageSize,\r
1155 IN CONST VOID *VendorCode,\r
1156 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,\r
1157 OUT CHAR16 **AbortReason\r
1158 )\r
1159{\r
4f0544b1
EJ
1160 EFI_STATUS Status;\r
1161 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
1162 UINT32 Updateable;\r
1163 BOOLEAN BooleanValue;\r
1164 UINT32 FmpHeaderSize;\r
1165 VOID *FmpHeader;\r
1166 UINTN FmpPayloadSize;\r
1167 UINT32 AllHeaderSize;\r
95d28836 1168 UINT32 IncomingFwVersion;\r
4f0544b1
EJ
1169 UINT32 LastAttemptStatus;\r
1170 UINT32 Version;\r
1171 UINT32 LowestSupportedVersion;\r
2ed845b3
WX
1172 EFI_FIRMWARE_IMAGE_DEP *Dependencies;\r
1173 UINT32 DependenciesSize;\r
b0bacc00 1174\r
45ce0a67
MK
1175 Status = EFI_SUCCESS;\r
1176 Private = NULL;\r
1177 Updateable = 0;\r
1178 BooleanValue = FALSE;\r
1179 FmpHeaderSize = 0;\r
1180 FmpHeader = NULL;\r
1181 FmpPayloadSize = 0;\r
1182 AllHeaderSize = 0;\r
1183 IncomingFwVersion = 0;\r
1184 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
1185 Dependencies = NULL;\r
1186 DependenciesSize = 0;\r
b0bacc00 1187\r
11d35494
EJ
1188 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
1189 return EFI_UNSUPPORTED;\r
1190 }\r
1191\r
b4b9496b
MK
1192 if (This == NULL) {\r
1193 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - This is NULL.\n", mImageIdName));\r
45ce0a67 1194 Status = EFI_INVALID_PARAMETER;\r
004ce0ab 1195 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;\r
b4b9496b
MK
1196 goto cleanup;\r
1197 }\r
1198\r
4f0544b1
EJ
1199 //\r
1200 // Retrieve the private context structure\r
1201 //\r
1202 Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
1203 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
b0bacc00 1204\r
67c1e5ee
EJ
1205 //\r
1206 // Make sure the descriptor has already been loaded or refreshed\r
1207 //\r
1208 PopulateDescriptor (Private);\r
1209\r
1210 //\r
1211 // Set to 0 to clear any previous results.\r
1212 //\r
95d28836 1213 SetLastAttemptVersionInVariable (Private, IncomingFwVersion);\r
b0bacc00
KM
1214\r
1215 //\r
1216 // if we have locked the device, then skip the set operation.\r
1217 // it should be blocked by hardware too but we can catch here even faster\r
1218 //\r
4f0544b1 1219 if (Private->FmpDeviceLocked) {\r
e0961677 1220 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Device is already locked. Can't update.\n", mImageIdName));\r
004ce0ab 1221 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_DEVICE_LOCKED;\r
45ce0a67 1222 Status = EFI_UNSUPPORTED;\r
b0bacc00
KM
1223 goto cleanup;\r
1224 }\r
1225\r
1226 //\r
1227 // Call check image to verify the image\r
1228 //\r
004ce0ab 1229 Status = CheckTheImageInternal (This, ImageIndex, Image, ImageSize, &Updateable, &LastAttemptStatus);\r
b0bacc00 1230 if (EFI_ERROR (Status)) {\r
e0961677 1231 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName, Status));\r
b0bacc00
KM
1232 goto cleanup;\r
1233 }\r
1234\r
0f30087b
WX
1235 //\r
1236 // Get the dependency from Image.\r
1237 //\r
207414cb 1238 Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize, &LastAttemptStatus);\r
0f30087b 1239\r
b0bacc00
KM
1240 //\r
1241 // No functional error in CheckTheImage. Attempt to get the Version to\r
1242 // support better error reporting.\r
1243 //\r
45ce0a67 1244 FmpHeader = GetFmpHeader ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize);\r
b0bacc00 1245 if (FmpHeader == NULL) {\r
e0961677 1246 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));\r
004ce0ab 1247 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;\r
45ce0a67 1248 Status = EFI_ABORTED;\r
b0bacc00
KM
1249 goto cleanup;\r
1250 }\r
45ce0a67 1251\r
95d28836 1252 Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);\r
b0bacc00
KM
1253 if (!EFI_ERROR (Status)) {\r
1254 //\r
1255 // Set to actual value\r
1256 //\r
95d28836 1257 SetLastAttemptVersionInVariable (Private, IncomingFwVersion);\r
b0bacc00
KM
1258 }\r
1259\r
b0bacc00
KM
1260 if (Updateable != IMAGE_UPDATABLE_VALID) {\r
1261 DEBUG (\r
1262 (DEBUG_ERROR,\r
45ce0a67
MK
1263 "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",\r
1264 mImageIdName, Updateable)\r
b0bacc00 1265 );\r
0f30087b 1266 if (Private->DependenciesSatisfied == FALSE) {\r
2ed845b3 1267 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;\r
2ed845b3 1268 }\r
45ce0a67 1269\r
b0bacc00
KM
1270 Status = EFI_ABORTED;\r
1271 goto cleanup;\r
1272 }\r
1273\r
1274 if (Progress == NULL) {\r
e0961677 1275 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName));\r
004ce0ab 1276 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROGRESS_CALLBACK_ERROR;\r
45ce0a67 1277 Status = EFI_INVALID_PARAMETER;\r
b0bacc00
KM
1278 goto cleanup;\r
1279 }\r
1280\r
1281 mProgressFunc = Progress;\r
b0bacc00
KM
1282\r
1283 //\r
1284 // Checking the image is at least 1%\r
1285 //\r
1286 Status = Progress (1);\r
1287 if (EFI_ERROR (Status)) {\r
e0961677 1288 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Progress Callback failed with Status %r.\n", mImageIdName, Status));\r
b0bacc00
KM
1289 }\r
1290\r
1291 //\r
45ce0a67 1292 // Check System Power\r
b0bacc00
KM
1293 //\r
1294 Status = CheckSystemPower (&BooleanValue);\r
1295 if (EFI_ERROR (Status)) {\r
e0961677 1296 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName, Status));\r
004ce0ab 1297 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_POWER_API;\r
b0bacc00
KM
1298 goto cleanup;\r
1299 }\r
45ce0a67 1300\r
b0bacc00
KM
1301 if (!BooleanValue) {\r
1302 Status = EFI_ABORTED;\r
1303 DEBUG (\r
1304 (DEBUG_ERROR,\r
45ce0a67 1305 "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n", mImageIdName)\r
b0bacc00
KM
1306 );\r
1307 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT;\r
1308 goto cleanup;\r
1309 }\r
1310\r
1311 Progress (2);\r
1312\r
1313 //\r
45ce0a67 1314 // Check System Thermal\r
b0bacc00
KM
1315 //\r
1316 Status = CheckSystemThermal (&BooleanValue);\r
1317 if (EFI_ERROR (Status)) {\r
e0961677 1318 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName, Status));\r
004ce0ab 1319 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_THERMAL_API;\r
b0bacc00
KM
1320 goto cleanup;\r
1321 }\r
45ce0a67 1322\r
b0bacc00 1323 if (!BooleanValue) {\r
45ce0a67 1324 Status = EFI_ABORTED;\r
004ce0ab 1325 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_THERMAL;\r
b0bacc00
KM
1326 DEBUG (\r
1327 (DEBUG_ERROR,\r
45ce0a67 1328 "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n", mImageIdName)\r
b0bacc00
KM
1329 );\r
1330 goto cleanup;\r
1331 }\r
1332\r
1333 Progress (3);\r
1334\r
1335 //\r
45ce0a67 1336 // Check System Environment\r
b0bacc00
KM
1337 //\r
1338 Status = CheckSystemEnvironment (&BooleanValue);\r
1339 if (EFI_ERROR (Status)) {\r
e0961677 1340 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName, Status));\r
004ce0ab 1341 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_ENV_API;\r
b0bacc00
KM
1342 goto cleanup;\r
1343 }\r
45ce0a67 1344\r
b0bacc00 1345 if (!BooleanValue) {\r
45ce0a67 1346 Status = EFI_ABORTED;\r
004ce0ab 1347 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_SYSTEM_ENV;\r
b0bacc00
KM
1348 DEBUG (\r
1349 (DEBUG_ERROR,\r
45ce0a67 1350 "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n", mImageIdName)\r
b0bacc00
KM
1351 );\r
1352 goto cleanup;\r
1353 }\r
1354\r
1355 Progress (4);\r
1356\r
1357 //\r
1358 // Save LastAttemptStatus as error so that if SetImage never returns the error\r
1359 // state is recorded.\r
1360 //\r
67c1e5ee 1361 SetLastAttemptStatusInVariable (Private, LastAttemptStatus);\r
b0bacc00
KM
1362\r
1363 //\r
1364 // Strip off all the headers so the device can process its firmware\r
1365 //\r
1366 Status = GetFmpPayloadHeaderSize (FmpHeader, FmpPayloadSize, &FmpHeaderSize);\r
1367 if (EFI_ERROR (Status)) {\r
e0961677 1368 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName, Status));\r
004ce0ab 1369 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;\r
b0bacc00
KM
1370 goto cleanup;\r
1371 }\r
1372\r
2ed845b3 1373 AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);\r
b0bacc00 1374 if (AllHeaderSize == 0) {\r
e0961677 1375 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName));\r
004ce0ab 1376 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;\r
45ce0a67 1377 Status = EFI_ABORTED;\r
b0bacc00
KM
1378 goto cleanup;\r
1379 }\r
1380\r
1381 //\r
1382 // Indicate that control is handed off to FmpDeviceLib\r
1383 //\r
1384 Progress (5);\r
1385\r
1386 //\r
45ce0a67 1387 // Copy the requested image to the firmware using the FmpDeviceLib\r
b0bacc00 1388 //\r
b96b44fe 1389 Status = FmpDeviceSetImageWithStatus (\r
45ce0a67 1390 (((UINT8 *)Image) + AllHeaderSize),\r
0f30087b 1391 ImageSize - AllHeaderSize,\r
b0bacc00
KM
1392 VendorCode,\r
1393 FmpDxeProgress,\r
95d28836 1394 IncomingFwVersion,\r
b96b44fe
MK
1395 AbortReason,\r
1396 &LastAttemptStatus\r
b0bacc00
KM
1397 );\r
1398 if (EFI_ERROR (Status)) {\r
e0961677 1399 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", mImageIdName, Status));\r
b96b44fe
MK
1400\r
1401 //\r
1402 // LastAttemptStatus returned from the device library should fall within the designated error range\r
1403 // [LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE, LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE]\r
1404 //\r
1405 if ((LastAttemptStatus < LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE) ||\r
45ce0a67
MK
1406 (LastAttemptStatus > LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE))\r
1407 {\r
b96b44fe
MK
1408 DEBUG (\r
1409 (DEBUG_ERROR,\r
45ce0a67
MK
1410 "FmpDxe(%s): SetTheImage() - LastAttemptStatus %d from FmpDeviceSetImageWithStatus() is invalid.\n",\r
1411 mImageIdName,\r
1412 LastAttemptStatus)\r
b96b44fe
MK
1413 );\r
1414 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
1415 }\r
1416\r
b0bacc00
KM
1417 goto cleanup;\r
1418 }\r
1419\r
0f30087b
WX
1420 //\r
1421 // Store the dependency\r
1422 //\r
1423 if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {\r
1424 Status = SaveFmpDependency (Dependencies, DependenciesSize);\r
1425 if (EFI_ERROR (Status)) {\r
1426 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SaveFmpDependency from FmpDependencyCheckLib failed. (%r)\n", mImageIdName, Status));\r
1427 }\r
45ce0a67 1428\r
0f30087b
WX
1429 Status = EFI_SUCCESS;\r
1430 }\r
b0bacc00
KM
1431\r
1432 //\r
1433 // Finished the update without error\r
1434 // Indicate that control has been returned from FmpDeviceLib\r
1435 //\r
1436 Progress (99);\r
1437\r
1438 //\r
1439 // Update the version stored in variable\r
1440 //\r
4f0544b1 1441 if (!Private->RuntimeVersionSupported) {\r
a6d73269 1442 Version = DEFAULT_VERSION;\r
b0bacc00 1443 GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);\r
67c1e5ee 1444 SetVersionInVariable (Private, Version);\r
b0bacc00
KM
1445 }\r
1446\r
1447 //\r
1448 // Update lowest supported variable\r
1449 //\r
67c1e5ee
EJ
1450 LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
1451 GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);\r
1452 SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion);\r
b0bacc00
KM
1453\r
1454 LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
1455\r
b0bacc00
KM
1456cleanup:\r
1457 mProgressFunc = NULL;\r
3633d530
MK
1458\r
1459 if (Private != NULL) {\r
004ce0ab 1460 DEBUG ((DEBUG_INFO, "FmpDxe(%s): SetTheImage() LastAttemptStatus: %u.\n", mImageIdName, LastAttemptStatus));\r
3633d530
MK
1461 SetLastAttemptStatusInVariable (Private, LastAttemptStatus);\r
1462 }\r
b0bacc00 1463\r
c6c18d87
SZ
1464 if (Progress != NULL) {\r
1465 //\r
1466 // Set progress to 100 after everything is done including recording Status.\r
1467 //\r
1468 Progress (100);\r
1469 }\r
b0bacc00 1470\r
27e42bf6
SZ
1471 //\r
1472 // Need repopulate after SetImage is called to\r
1473 // update LastAttemptVersion and LastAttemptStatus.\r
1474 //\r
3633d530
MK
1475 if (Private != NULL) {\r
1476 Private->DescriptorPopulated = FALSE;\r
1477 }\r
27e42bf6 1478\r
b0bacc00
KM
1479 return Status;\r
1480}\r
1481\r
1482/**\r
1483 Returns information about the firmware package.\r
1484\r
1485 This function returns package information.\r
1486\r
1487 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
1488 @param[out] PackageVersion A version number that represents all the firmware images in the device.\r
1489 The format is vendor specific and new version must have a greater value\r
1490 than the old version. If PackageVersion is not supported, the value is\r
1491 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version\r
1492 comparison is to be performed using PackageVersionName. A value of\r
1493 0xFFFFFFFD indicates that package version update is in progress.\r
1494 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing\r
1495 the package version name. The buffer is allocated by this function with\r
1496 AllocatePool(), and it is the caller's responsibility to free it with a\r
1497 call to FreePool().\r
1498 @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of\r
1499 package version name. A value of 0 indicates the device does not support\r
1500 update of package version name. Length is the number of Unicode characters,\r
1501 including the terminating null character.\r
1502 @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute\r
1503 Definitions' for possible returned values of this parameter. A value of 1\r
1504 indicates the attribute is supported and the current setting value is\r
1505 indicated in AttributesSetting. A value of 0 indicates the attribute is not\r
1506 supported and the current setting value in AttributesSetting is meaningless.\r
1507 @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned\r
1508 values of this parameter\r
1509\r
1510 @retval EFI_SUCCESS The package information was successfully returned.\r
1511 @retval EFI_UNSUPPORTED The operation is not supported.\r
1512\r
1513**/\r
1514EFI_STATUS\r
1515EFIAPI\r
1516GetPackageInfo (\r
1517 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
1518 OUT UINT32 *PackageVersion,\r
1519 OUT CHAR16 **PackageVersionName,\r
1520 OUT UINT32 *PackageVersionNameMaxLen,\r
1521 OUT UINT64 *AttributesSupported,\r
1522 OUT UINT64 *AttributesSetting\r
1523 )\r
1524{\r
1525 return EFI_UNSUPPORTED;\r
1526}\r
1527\r
1528/**\r
1529 Updates information about the firmware package.\r
1530\r
1531 This function updates package information.\r
1532 This function returns EFI_UNSUPPORTED if the package information is not updatable.\r
1533 VendorCode enables vendor to implement vendor-specific package information update policy.\r
1534 Null if the caller did not specify this policy or use the default policy.\r
1535\r
1536 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
1537 @param[in] Image Points to the authentication image.\r
1538 Null if authentication is not required.\r
1539 @param[in] ImageSize Size of the authentication image in bytes.\r
1540 0 if authentication is not required.\r
1541 @param[in] VendorCode This enables vendor to implement vendor-specific firmware\r
1542 image update policy.\r
1543 Null indicates the caller did not specify this policy or use\r
1544 the default policy.\r
1545 @param[in] PackageVersion The new package version.\r
1546 @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing\r
1547 the package version name.\r
1548 The string length is equal to or less than the value returned in\r
1549 PackageVersionNameMaxLen.\r
1550\r
1551 @retval EFI_SUCCESS The device was successfully updated with the new package\r
1552 information.\r
1553 @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value\r
1554 returned in PackageVersionNameMaxLen.\r
1555 @retval EFI_UNSUPPORTED The operation is not supported.\r
5fc5867e 1556 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
b0bacc00
KM
1557\r
1558**/\r
1559EFI_STATUS\r
1560EFIAPI\r
1561SetPackageInfo (\r
1562 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
1563 IN CONST VOID *Image,\r
1564 IN UINTN ImageSize,\r
1565 IN CONST VOID *VendorCode,\r
1566 IN UINT32 PackageVersion,\r
1567 IN CONST CHAR16 *PackageVersionName\r
1568 )\r
1569{\r
1570 return EFI_UNSUPPORTED;\r
1571}\r
1572\r
1573/**\r
1574 Event notification function that is invoked when the event GUID specified by\r
1575 PcdFmpDeviceLockEventGuid is signaled.\r
1576\r
1577 @param[in] Event Event whose notification function is being invoked.\r
1578 @param[in] Context The pointer to the notification function's context,\r
1579 which is implementation-dependent.\r
1580**/\r
1581VOID\r
1582EFIAPI\r
1583FmpDxeLockEventNotify (\r
1584 IN EFI_EVENT Event,\r
1585 IN VOID *Context\r
1586 )\r
1587{\r
4f0544b1
EJ
1588 EFI_STATUS Status;\r
1589 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
1590\r
b4b9496b
MK
1591 if (Context == NULL) {\r
1592 ASSERT (Context != NULL);\r
1593 return;\r
1594 }\r
1595\r
4f0544b1 1596 Private = (FIRMWARE_MANAGEMENT_PRIVATE_DATA *)Context;\r
b0bacc00 1597\r
4f0544b1 1598 if (!Private->FmpDeviceLocked) {\r
9e6c4f15
SZ
1599 //\r
1600 // Lock the firmware device\r
1601 //\r
4f0544b1 1602 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
45ce0a67 1603 Status = FmpDeviceLock ();\r
9e6c4f15
SZ
1604 if (EFI_ERROR (Status)) {\r
1605 if (Status != EFI_UNSUPPORTED) {\r
e0961677 1606 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));\r
b0bacc00 1607 } else {\r
e0961677 1608 DEBUG ((DEBUG_WARN, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));\r
b0bacc00 1609 }\r
b0bacc00 1610 }\r
45ce0a67 1611\r
4f0544b1 1612 Private->FmpDeviceLocked = TRUE;\r
b0bacc00
KM
1613 }\r
1614}\r
1615\r
1616/**\r
1617 Function to install FMP instance.\r
1618\r
1619 @param[in] Handle The device handle to install a FMP instance on.\r
1620\r
1621 @retval EFI_SUCCESS FMP Installed\r
1622 @retval EFI_INVALID_PARAMETER Handle was invalid\r
1623 @retval other Error installing FMP\r
1624\r
1625**/\r
1626EFI_STATUS\r
1627EFIAPI\r
1628InstallFmpInstance (\r
1629 IN EFI_HANDLE Handle\r
1630 )\r
1631{\r
4f0544b1
EJ
1632 EFI_STATUS Status;\r
1633 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
1634 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
b0bacc00 1635\r
b0bacc00
KM
1636 //\r
1637 // Only allow a single FMP Protocol instance to be installed\r
1638 //\r
4f0544b1
EJ
1639 Status = gBS->OpenProtocol (\r
1640 Handle,\r
1641 &gEfiFirmwareManagementProtocolGuid,\r
1642 (VOID **)&Fmp,\r
1643 NULL,\r
1644 NULL,\r
1645 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1646 );\r
1647 if (!EFI_ERROR (Status)) {\r
b0bacc00
KM
1648 return EFI_ALREADY_STARTED;\r
1649 }\r
1650\r
1651 //\r
1652 // Allocate FMP Protocol instance\r
1653 //\r
4f0544b1
EJ
1654 Private = AllocateCopyPool (\r
1655 sizeof (mFirmwareManagementPrivateDataTemplate),\r
1656 &mFirmwareManagementPrivateDataTemplate\r
1657 );\r
1658 if (Private == NULL) {\r
e0961677 1659 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to allocate memory for private structure.\n", mImageIdName));\r
b0bacc00
KM
1660 Status = EFI_OUT_OF_RESOURCES;\r
1661 goto cleanup;\r
1662 }\r
1663\r
1664 //\r
4f0544b1 1665 // Initialize private context data structure\r
b0bacc00 1666 //\r
45ce0a67 1667 Private->Handle = Handle;\r
4f0544b1 1668 Private->FmpDeviceContext = NULL;\r
45ce0a67 1669 Status = FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
4f0544b1
EJ
1670 if (Status == EFI_UNSUPPORTED) {\r
1671 Private->FmpDeviceContext = NULL;\r
1672 } else if (EFI_ERROR (Status)) {\r
b0bacc00
KM
1673 goto cleanup;\r
1674 }\r
1675\r
67c1e5ee
EJ
1676 //\r
1677 // Make sure the descriptor has already been loaded or refreshed\r
1678 //\r
1679 PopulateDescriptor (Private);\r
1680\r
4f0544b1
EJ
1681 if (IsLockFmpDeviceAtLockEventGuidRequired ()) {\r
1682 //\r
e0961677 1683 // Register all UEFI Variables used by this module to be locked.\r
4f0544b1 1684 //\r
67c1e5ee 1685 Status = LockAllFmpVariables (Private);\r
4f0544b1 1686 if (EFI_ERROR (Status)) {\r
e0961677 1687 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register variables to lock. Status = %r.\n", mImageIdName, Status));\r
4f0544b1 1688 } else {\r
e0961677 1689 DEBUG ((DEBUG_INFO, "FmpDxe(%s): All variables registered to lock\n", mImageIdName));\r
4f0544b1
EJ
1690 }\r
1691\r
1692 //\r
1693 // Create and register notify function to lock the FMP device.\r
1694 //\r
1695 Status = gBS->CreateEventEx (\r
1696 EVT_NOTIFY_SIGNAL,\r
1697 TPL_CALLBACK,\r
1698 FmpDxeLockEventNotify,\r
1699 Private,\r
1700 mLockGuid,\r
1701 &Private->FmpDeviceLockEvent\r
1702 );\r
1703 if (EFI_ERROR (Status)) {\r
e0961677 1704 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register notification. Status = %r\n", mImageIdName, Status));\r
4f0544b1 1705 }\r
45ce0a67 1706\r
4f0544b1
EJ
1707 ASSERT_EFI_ERROR (Status);\r
1708 } else {\r
e0961677 1709 DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): Not registering notification to call FmpDeviceLock() because mfg mode\n", mImageIdName));\r
4f0544b1 1710 }\r
b0bacc00
KM
1711\r
1712 //\r
1713 // Install FMP Protocol and FMP Progress Protocol\r
1714 //\r
1715 Status = gBS->InstallMultipleProtocolInterfaces (\r
4f0544b1 1716 &Private->Handle,\r
45ce0a67
MK
1717 &gEfiFirmwareManagementProtocolGuid,\r
1718 &Private->Fmp,\r
1719 &gEdkiiFirmwareManagementProgressProtocolGuid,\r
1720 &mFmpProgress,\r
b0bacc00
KM
1721 NULL\r
1722 );\r
b0bacc00 1723 if (EFI_ERROR (Status)) {\r
e0961677 1724 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol install error. Status = %r.\n", mImageIdName, Status));\r
b0bacc00
KM
1725 goto cleanup;\r
1726 }\r
1727\r
b0bacc00
KM
1728cleanup:\r
1729\r
4f0544b1
EJ
1730 if (EFI_ERROR (Status)) {\r
1731 if (Private != NULL) {\r
1732 if (Private->FmpDeviceLockEvent != NULL) {\r
1733 gBS->CloseEvent (Private->FmpDeviceLockEvent);\r
1734 }\r
45ce0a67 1735\r
67c1e5ee
EJ
1736 if (Private->Descriptor.VersionName != NULL) {\r
1737 FreePool (Private->Descriptor.VersionName);\r
1738 }\r
45ce0a67 1739\r
67c1e5ee
EJ
1740 if (Private->FmpDeviceContext != NULL) {\r
1741 FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
1742 }\r
45ce0a67 1743\r
67c1e5ee
EJ
1744 if (Private->VersionVariableName != NULL) {\r
1745 FreePool (Private->VersionVariableName);\r
1746 }\r
45ce0a67 1747\r
67c1e5ee
EJ
1748 if (Private->LsvVariableName != NULL) {\r
1749 FreePool (Private->LsvVariableName);\r
1750 }\r
45ce0a67 1751\r
67c1e5ee
EJ
1752 if (Private->LastAttemptStatusVariableName != NULL) {\r
1753 FreePool (Private->LastAttemptStatusVariableName);\r
1754 }\r
45ce0a67 1755\r
67c1e5ee
EJ
1756 if (Private->LastAttemptVersionVariableName != NULL) {\r
1757 FreePool (Private->LastAttemptVersionVariableName);\r
1758 }\r
45ce0a67 1759\r
67c1e5ee
EJ
1760 if (Private->FmpStateVariableName != NULL) {\r
1761 FreePool (Private->FmpStateVariableName);\r
1762 }\r
45ce0a67 1763\r
4f0544b1
EJ
1764 FreePool (Private);\r
1765 }\r
1766 }\r
1767\r
b0bacc00
KM
1768 return Status;\r
1769}\r
1770\r
4f0544b1
EJ
1771/**\r
1772 Function to uninstall FMP instance.\r
1773\r
1774 @param[in] Handle The device handle to install a FMP instance on.\r
1775\r
1776 @retval EFI_SUCCESS FMP Installed\r
1777 @retval EFI_INVALID_PARAMETER Handle was invalid\r
1778 @retval other Error installing FMP\r
1779\r
1780**/\r
1781EFI_STATUS\r
1782EFIAPI\r
1783UninstallFmpInstance (\r
1784 IN EFI_HANDLE Handle\r
1785 )\r
1786{\r
1787 EFI_STATUS Status;\r
1788 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
1789 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
1790\r
1791 Status = gBS->OpenProtocol (\r
1792 Handle,\r
1793 &gEfiFirmwareManagementProtocolGuid,\r
1794 (VOID **)&Fmp,\r
1795 NULL,\r
1796 NULL,\r
1797 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1798 );\r
1799 if (EFI_ERROR (Status)) {\r
e0961677 1800 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol open error. Status = %r.\n", mImageIdName, Status));\r
4f0544b1
EJ
1801 return Status;\r
1802 }\r
1803\r
1804 Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (Fmp);\r
1805 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
1806\r
1807 if (Private->FmpDeviceLockEvent != NULL) {\r
1808 gBS->CloseEvent (Private->FmpDeviceLockEvent);\r
1809 }\r
1810\r
1811 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1812 Private->Handle,\r
45ce0a67
MK
1813 &gEfiFirmwareManagementProtocolGuid,\r
1814 &Private->Fmp,\r
1815 &gEdkiiFirmwareManagementProgressProtocolGuid,\r
1816 &mFmpProgress,\r
4f0544b1
EJ
1817 NULL\r
1818 );\r
1819 if (EFI_ERROR (Status)) {\r
e0961677 1820 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol uninstall error. Status = %r.\n", mImageIdName, Status));\r
4f0544b1
EJ
1821 return Status;\r
1822 }\r
1823\r
67c1e5ee
EJ
1824 if (Private->Descriptor.VersionName != NULL) {\r
1825 FreePool (Private->Descriptor.VersionName);\r
1826 }\r
45ce0a67 1827\r
67c1e5ee
EJ
1828 if (Private->FmpDeviceContext != NULL) {\r
1829 FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
1830 }\r
45ce0a67 1831\r
67c1e5ee
EJ
1832 if (Private->VersionVariableName != NULL) {\r
1833 FreePool (Private->VersionVariableName);\r
1834 }\r
45ce0a67 1835\r
67c1e5ee
EJ
1836 if (Private->LsvVariableName != NULL) {\r
1837 FreePool (Private->LsvVariableName);\r
1838 }\r
45ce0a67 1839\r
67c1e5ee
EJ
1840 if (Private->LastAttemptStatusVariableName != NULL) {\r
1841 FreePool (Private->LastAttemptStatusVariableName);\r
1842 }\r
45ce0a67 1843\r
67c1e5ee
EJ
1844 if (Private->LastAttemptVersionVariableName != NULL) {\r
1845 FreePool (Private->LastAttemptVersionVariableName);\r
1846 }\r
45ce0a67 1847\r
67c1e5ee
EJ
1848 if (Private->FmpStateVariableName != NULL) {\r
1849 FreePool (Private->FmpStateVariableName);\r
1850 }\r
45ce0a67 1851\r
4f0544b1
EJ
1852 FreePool (Private);\r
1853\r
1854 return EFI_SUCCESS;\r
1855}\r
1856\r
1857/**\r
1858 Unloads the application and its installed protocol.\r
1859\r
1860 @param ImageHandle Handle that identifies the image to be unloaded.\r
1861 @param SystemTable The system table.\r
1862\r
1863 @retval EFI_SUCCESS The image has been unloaded.\r
1864\r
1865**/\r
1866EFI_STATUS\r
1867EFIAPI\r
1868FmpDxeLibDestructor (\r
1869 IN EFI_HANDLE ImageHandle,\r
1870 IN EFI_SYSTEM_TABLE *SystemTable\r
1871 )\r
1872{\r
1873 if (mFmpSingleInstance) {\r
1874 return UninstallFmpInstance (ImageHandle);\r
1875 }\r
45ce0a67 1876\r
4f0544b1
EJ
1877 return EFI_SUCCESS;\r
1878}\r
1879\r
b0bacc00 1880/**\r
e8619f82 1881 Main entry for this driver/library.\r
b0bacc00
KM
1882\r
1883 @param[in] ImageHandle Image handle this driver.\r
1884 @param[in] SystemTable Pointer to SystemTable.\r
1885\r
1886**/\r
1887EFI_STATUS\r
1888EFIAPI\r
1889FmpDxeEntryPoint (\r
1890 IN EFI_HANDLE ImageHandle,\r
1891 IN EFI_SYSTEM_TABLE *SystemTable\r
1892 )\r
1893{\r
1894 EFI_STATUS Status;\r
b0bacc00
KM
1895\r
1896 //\r
1897 // Verify that a new FILE_GUID value has been provided in the <Defines>\r
1898 // section of this module. The FILE_GUID is the ESRT GUID that must be\r
1899 // unique for each updatable firmware image.\r
1900 //\r
1901 if (CompareGuid (&mDefaultModuleFileGuid, &gEfiCallerIdGuid)) {\r
1902 DEBUG ((DEBUG_ERROR, "FmpDxe: Use of default FILE_GUID detected. FILE_GUID must be set to a unique value.\n"));\r
1903 ASSERT (FALSE);\r
1904 return EFI_UNSUPPORTED;\r
1905 }\r
1906\r
1907 //\r
1908 // Get the ImageIdName value for the EFI_FIRMWARE_IMAGE_DESCRIPTOR from a PCD.\r
1909 //\r
45ce0a67
MK
1910 mImageIdName = (CHAR16 *)PcdGetPtr (PcdFmpDeviceImageIdName);\r
1911 if ((PcdGetSize (PcdFmpDeviceImageIdName) <= 2) || (mImageIdName[0] == 0)) {\r
b0bacc00
KM
1912 //\r
1913 // PcdFmpDeviceImageIdName must be set to a non-empty Unicode string\r
1914 //\r
c9fa9762 1915 DEBUG ((DEBUG_ERROR, "FmpDxe(%g): PcdFmpDeviceImageIdName is an empty string.\n", &gEfiCallerIdGuid));\r
b0bacc00 1916 ASSERT (FALSE);\r
e0961677 1917 return EFI_UNSUPPORTED;\r
b0bacc00
KM
1918 }\r
1919\r
1920 //\r
1921 // Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.\r
1922 //\r
1923 DetectTestKey ();\r
1924\r
4f0544b1
EJ
1925 //\r
1926 // Fill in FMP Progress Protocol fields for Version 1\r
1927 //\r
1928 mFmpProgress.Version = 1;\r
1929 mFmpProgress.ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);\r
1930 mFmpProgress.WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);\r
9e6c4f15 1931\r
4f0544b1
EJ
1932 // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.\r
1933 // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then\r
1934 // gEfiEndOfDxeEventGroupGuid is used.\r
1935 //\r
1936 mLockGuid = &gEfiEndOfDxeEventGroupGuid;\r
1937 if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {\r
1938 mLockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);\r
9e6c4f15 1939 }\r
45ce0a67 1940\r
e0961677 1941 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Lock GUID: %g\n", mImageIdName, mLockGuid));\r
9e6c4f15 1942\r
b0bacc00
KM
1943 //\r
1944 // Register with library the install function so if the library uses\r
1945 // UEFI driver model/driver binding protocol it can install FMP on its device handle\r
1946 // If library is simple lib that does not use driver binding then it should return\r
1947 // unsupported and this will install the FMP instance on the ImageHandle\r
1948 //\r
1949 Status = RegisterFmpInstaller (InstallFmpInstance);\r
1950 if (Status == EFI_UNSUPPORTED) {\r
4f0544b1 1951 mFmpSingleInstance = TRUE;\r
e0961677 1952 DEBUG ((DEBUG_INFO, "FmpDxe(%s): FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n", mImageIdName));\r
4f0544b1
EJ
1953 Status = RegisterFmpUninstaller (UninstallFmpInstance);\r
1954 if (Status == EFI_UNSUPPORTED) {\r
1955 Status = InstallFmpInstance (ImageHandle);\r
1956 } else {\r
e0961677 1957 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));\r
4f0544b1
EJ
1958 Status = EFI_UNSUPPORTED;\r
1959 }\r
b0bacc00 1960 } else if (EFI_ERROR (Status)) {\r
e0961677 1961 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib registration returned %r. No FMP installed.\n", mImageIdName, Status));\r
b0bacc00
KM
1962 } else {\r
1963 DEBUG ((\r
1964 DEBUG_INFO,\r
e0961677
EJ
1965 "FmpDxe(%s): FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n",\r
1966 mImageIdName\r
b0bacc00 1967 ));\r
4f0544b1
EJ
1968 Status = RegisterFmpUninstaller (UninstallFmpInstance);\r
1969 if (EFI_ERROR (Status)) {\r
e0961677 1970 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));\r
4f0544b1 1971 }\r
b0bacc00
KM
1972 }\r
1973\r
b0bacc00
KM
1974 return Status;\r
1975}\r