]> git.proxmox.com Git - mirror_edk2.git/blame - FmpDevicePkg/FmpDxe/FmpDxe.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
772c5bb8
MK
1043 // The image cannot be valid if an error occurred checking the image\r
1044 if (*ImageUpdatable == IMAGE_UPDATABLE_VALID) {\r
1045 *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
1046 }\r
1047\r
e0961677 1048 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName, Status));\r
772c5bb8 1049 }\r
b96b44fe 1050\r
772c5bb8
MK
1051 //\r
1052 // Only validate the library last attempt status code if the image is not updatable.\r
1053 // This specifically avoids converting LAST_ATTEMPT_STATUS_SUCCESS if it set for an updatable image.\r
1054 //\r
1055 if (*ImageUpdatable != IMAGE_UPDATABLE_VALID) {\r
b96b44fe
MK
1056 //\r
1057 // LastAttemptStatus returned from the device library should fall within the designated error range\r
1058 // [LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE, LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE]\r
1059 //\r
1060 if ((*LastAttemptStatus < LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE) ||\r
45ce0a67
MK
1061 (*LastAttemptStatus > LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE))\r
1062 {\r
772c5bb8
MK
1063 DEBUG ((\r
1064 DEBUG_ERROR,\r
1065 "FmpDxe(%s): CheckTheImage() - LastAttemptStatus %d from FmpDeviceCheckImageWithStatus() is invalid.\n",\r
1066 mImageIdName,\r
1067 *LastAttemptStatus\r
1068 ));\r
b96b44fe
MK
1069 *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
1070 }\r
b0bacc00
KM
1071 }\r
1072\r
1073cleanup:\r
1074 return Status;\r
1075}\r
1076\r
5550f4d3
MK
1077/**\r
1078 Checks if the firmware image is valid for the device.\r
1079\r
1080 This function allows firmware update application to validate the firmware image without\r
1081 invoking the SetImage() first.\r
1082\r
1083 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
1084 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
1085 The number is between 1 and DescriptorCount.\r
1086 @param[in] Image Points to the new image.\r
1087 @param[in] ImageSize Size of the new image in bytes.\r
1088 @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,\r
1089 if available, additional information if the image is invalid.\r
1090\r
1091 @retval EFI_SUCCESS The image was successfully checked.\r
1092 @retval EFI_ABORTED The operation is aborted.\r
1093 @retval EFI_INVALID_PARAMETER The Image was NULL.\r
1094 @retval EFI_UNSUPPORTED The operation is not supported.\r
1095 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
1096\r
1097**/\r
1098EFI_STATUS\r
1099EFIAPI\r
1100CheckTheImage (\r
1101 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
1102 IN UINT8 ImageIndex,\r
1103 IN CONST VOID *Image,\r
1104 IN UINTN ImageSize,\r
1105 OUT UINT32 *ImageUpdatable\r
1106 )\r
1107{\r
1108 UINT32 LastAttemptStatus;\r
1109\r
1110 return CheckTheImageInternal (This, ImageIndex, Image, ImageSize, ImageUpdatable, &LastAttemptStatus);\r
1111}\r
1112\r
b0bacc00
KM
1113/**\r
1114 Updates the firmware image of the device.\r
1115\r
1116 This function updates the hardware with the new firmware image.\r
1117 This function returns EFI_UNSUPPORTED if the firmware image is not updatable.\r
1118 If the firmware image is updatable, the function should perform the following minimal validations\r
1119 before proceeding to do the firmware image update.\r
1120 - Validate the image authentication if image has attribute\r
1121 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns\r
1122 EFI_SECURITY_VIOLATION if the validation fails.\r
1123 - Validate the image is a supported image for this device. The function returns EFI_ABORTED if\r
1124 the image is unsupported. The function can optionally provide more detailed information on\r
1125 why the image is not a supported image.\r
1126 - Validate the data from VendorCode if not null. Image validation must be performed before\r
1127 VendorCode data validation. VendorCode data is ignored or considered invalid if image\r
1128 validation failed. The function returns EFI_ABORTED if the data is invalid.\r
1129\r
1130 VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if\r
1131 the caller did not specify the policy or use the default policy. As an example, vendor can implement\r
1132 a policy to allow an option to force a firmware image update when the abort reason is due to the new\r
1133 firmware image version is older than the current firmware image version or bad image checksum.\r
1134 Sensitive operations such as those wiping the entire firmware image and render the device to be\r
1135 non-functional should be encoded in the image itself rather than passed with the VendorCode.\r
1136 AbortReason enables vendor to have the option to provide a more detailed description of the abort\r
1137 reason to the caller.\r
1138\r
1139 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
1140 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
1141 The number is between 1 and DescriptorCount.\r
1142 @param[in] Image Points to the new image.\r
1143 @param[in] ImageSize Size of the new image in bytes.\r
1144 @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.\r
1145 Null indicates the caller did not specify the policy or use the default policy.\r
1146 @param[in] Progress A function used by the driver to report the progress of the firmware update.\r
1147 @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more\r
1148 details for the aborted operation. The buffer is allocated by this function\r
1149 with AllocatePool(), and it is the caller's responsibility to free it with a\r
1150 call to FreePool().\r
1151\r
1152 @retval EFI_SUCCESS The device was successfully updated with the new image.\r
1153 @retval EFI_ABORTED The operation is aborted.\r
1154 @retval EFI_INVALID_PARAMETER The Image was NULL.\r
1155 @retval EFI_UNSUPPORTED The operation is not supported.\r
5fc5867e 1156 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
b0bacc00
KM
1157\r
1158**/\r
1159EFI_STATUS\r
1160EFIAPI\r
1161SetTheImage (\r
1162 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
1163 IN UINT8 ImageIndex,\r
1164 IN CONST VOID *Image,\r
1165 IN UINTN ImageSize,\r
1166 IN CONST VOID *VendorCode,\r
1167 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,\r
1168 OUT CHAR16 **AbortReason\r
1169 )\r
1170{\r
4f0544b1
EJ
1171 EFI_STATUS Status;\r
1172 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
1173 UINT32 Updateable;\r
1174 BOOLEAN BooleanValue;\r
1175 UINT32 FmpHeaderSize;\r
1176 VOID *FmpHeader;\r
1177 UINTN FmpPayloadSize;\r
1178 UINT32 AllHeaderSize;\r
95d28836 1179 UINT32 IncomingFwVersion;\r
4f0544b1
EJ
1180 UINT32 LastAttemptStatus;\r
1181 UINT32 Version;\r
1182 UINT32 LowestSupportedVersion;\r
2ed845b3
WX
1183 EFI_FIRMWARE_IMAGE_DEP *Dependencies;\r
1184 UINT32 DependenciesSize;\r
b0bacc00 1185\r
45ce0a67
MK
1186 Status = EFI_SUCCESS;\r
1187 Private = NULL;\r
1188 Updateable = 0;\r
1189 BooleanValue = FALSE;\r
1190 FmpHeaderSize = 0;\r
1191 FmpHeader = NULL;\r
1192 FmpPayloadSize = 0;\r
1193 AllHeaderSize = 0;\r
1194 IncomingFwVersion = 0;\r
1195 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
1196 Dependencies = NULL;\r
1197 DependenciesSize = 0;\r
b0bacc00 1198\r
11d35494
EJ
1199 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
1200 return EFI_UNSUPPORTED;\r
1201 }\r
1202\r
b4b9496b
MK
1203 if (This == NULL) {\r
1204 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - This is NULL.\n", mImageIdName));\r
45ce0a67 1205 Status = EFI_INVALID_PARAMETER;\r
004ce0ab 1206 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;\r
b4b9496b
MK
1207 goto cleanup;\r
1208 }\r
1209\r
4f0544b1
EJ
1210 //\r
1211 // Retrieve the private context structure\r
1212 //\r
1213 Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
1214 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
b0bacc00 1215\r
67c1e5ee
EJ
1216 //\r
1217 // Make sure the descriptor has already been loaded or refreshed\r
1218 //\r
1219 PopulateDescriptor (Private);\r
1220\r
1221 //\r
1222 // Set to 0 to clear any previous results.\r
1223 //\r
95d28836 1224 SetLastAttemptVersionInVariable (Private, IncomingFwVersion);\r
b0bacc00
KM
1225\r
1226 //\r
1227 // if we have locked the device, then skip the set operation.\r
1228 // it should be blocked by hardware too but we can catch here even faster\r
1229 //\r
4f0544b1 1230 if (Private->FmpDeviceLocked) {\r
e0961677 1231 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Device is already locked. Can't update.\n", mImageIdName));\r
004ce0ab 1232 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_DEVICE_LOCKED;\r
45ce0a67 1233 Status = EFI_UNSUPPORTED;\r
b0bacc00
KM
1234 goto cleanup;\r
1235 }\r
1236\r
1237 //\r
1238 // Call check image to verify the image\r
1239 //\r
004ce0ab 1240 Status = CheckTheImageInternal (This, ImageIndex, Image, ImageSize, &Updateable, &LastAttemptStatus);\r
b0bacc00 1241 if (EFI_ERROR (Status)) {\r
e0961677 1242 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName, Status));\r
b0bacc00
KM
1243 goto cleanup;\r
1244 }\r
1245\r
0f30087b
WX
1246 //\r
1247 // Get the dependency from Image.\r
1248 //\r
207414cb 1249 Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize, &LastAttemptStatus);\r
0f30087b 1250\r
b0bacc00
KM
1251 //\r
1252 // No functional error in CheckTheImage. Attempt to get the Version to\r
1253 // support better error reporting.\r
1254 //\r
45ce0a67 1255 FmpHeader = GetFmpHeader ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize);\r
b0bacc00 1256 if (FmpHeader == NULL) {\r
e0961677 1257 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));\r
004ce0ab 1258 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;\r
45ce0a67 1259 Status = EFI_ABORTED;\r
b0bacc00
KM
1260 goto cleanup;\r
1261 }\r
45ce0a67 1262\r
95d28836 1263 Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);\r
b0bacc00
KM
1264 if (!EFI_ERROR (Status)) {\r
1265 //\r
1266 // Set to actual value\r
1267 //\r
95d28836 1268 SetLastAttemptVersionInVariable (Private, IncomingFwVersion);\r
b0bacc00
KM
1269 }\r
1270\r
b0bacc00
KM
1271 if (Updateable != IMAGE_UPDATABLE_VALID) {\r
1272 DEBUG (\r
1273 (DEBUG_ERROR,\r
45ce0a67
MK
1274 "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",\r
1275 mImageIdName, Updateable)\r
b0bacc00 1276 );\r
0f30087b 1277 if (Private->DependenciesSatisfied == FALSE) {\r
2ed845b3 1278 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;\r
2ed845b3 1279 }\r
45ce0a67 1280\r
b0bacc00
KM
1281 Status = EFI_ABORTED;\r
1282 goto cleanup;\r
1283 }\r
1284\r
1285 if (Progress == NULL) {\r
e0961677 1286 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName));\r
004ce0ab 1287 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROGRESS_CALLBACK_ERROR;\r
45ce0a67 1288 Status = EFI_INVALID_PARAMETER;\r
b0bacc00
KM
1289 goto cleanup;\r
1290 }\r
1291\r
1292 mProgressFunc = Progress;\r
b0bacc00
KM
1293\r
1294 //\r
1295 // Checking the image is at least 1%\r
1296 //\r
1297 Status = Progress (1);\r
1298 if (EFI_ERROR (Status)) {\r
e0961677 1299 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Progress Callback failed with Status %r.\n", mImageIdName, Status));\r
b0bacc00
KM
1300 }\r
1301\r
1302 //\r
45ce0a67 1303 // Check System Power\r
b0bacc00
KM
1304 //\r
1305 Status = CheckSystemPower (&BooleanValue);\r
1306 if (EFI_ERROR (Status)) {\r
e0961677 1307 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName, Status));\r
004ce0ab 1308 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_POWER_API;\r
b0bacc00
KM
1309 goto cleanup;\r
1310 }\r
45ce0a67 1311\r
b0bacc00
KM
1312 if (!BooleanValue) {\r
1313 Status = EFI_ABORTED;\r
1314 DEBUG (\r
1315 (DEBUG_ERROR,\r
45ce0a67 1316 "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n", mImageIdName)\r
b0bacc00
KM
1317 );\r
1318 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT;\r
1319 goto cleanup;\r
1320 }\r
1321\r
1322 Progress (2);\r
1323\r
1324 //\r
45ce0a67 1325 // Check System Thermal\r
b0bacc00
KM
1326 //\r
1327 Status = CheckSystemThermal (&BooleanValue);\r
1328 if (EFI_ERROR (Status)) {\r
e0961677 1329 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName, Status));\r
004ce0ab 1330 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_THERMAL_API;\r
b0bacc00
KM
1331 goto cleanup;\r
1332 }\r
45ce0a67 1333\r
b0bacc00 1334 if (!BooleanValue) {\r
45ce0a67 1335 Status = EFI_ABORTED;\r
004ce0ab 1336 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_THERMAL;\r
b0bacc00
KM
1337 DEBUG (\r
1338 (DEBUG_ERROR,\r
45ce0a67 1339 "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n", mImageIdName)\r
b0bacc00
KM
1340 );\r
1341 goto cleanup;\r
1342 }\r
1343\r
1344 Progress (3);\r
1345\r
1346 //\r
45ce0a67 1347 // Check System Environment\r
b0bacc00
KM
1348 //\r
1349 Status = CheckSystemEnvironment (&BooleanValue);\r
1350 if (EFI_ERROR (Status)) {\r
e0961677 1351 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName, Status));\r
004ce0ab 1352 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_ENV_API;\r
b0bacc00
KM
1353 goto cleanup;\r
1354 }\r
45ce0a67 1355\r
b0bacc00 1356 if (!BooleanValue) {\r
45ce0a67 1357 Status = EFI_ABORTED;\r
004ce0ab 1358 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_SYSTEM_ENV;\r
b0bacc00
KM
1359 DEBUG (\r
1360 (DEBUG_ERROR,\r
45ce0a67 1361 "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n", mImageIdName)\r
b0bacc00
KM
1362 );\r
1363 goto cleanup;\r
1364 }\r
1365\r
1366 Progress (4);\r
1367\r
1368 //\r
1369 // Save LastAttemptStatus as error so that if SetImage never returns the error\r
1370 // state is recorded.\r
1371 //\r
67c1e5ee 1372 SetLastAttemptStatusInVariable (Private, LastAttemptStatus);\r
b0bacc00
KM
1373\r
1374 //\r
1375 // Strip off all the headers so the device can process its firmware\r
1376 //\r
1377 Status = GetFmpPayloadHeaderSize (FmpHeader, FmpPayloadSize, &FmpHeaderSize);\r
1378 if (EFI_ERROR (Status)) {\r
e0961677 1379 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName, Status));\r
004ce0ab 1380 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;\r
b0bacc00
KM
1381 goto cleanup;\r
1382 }\r
1383\r
2ed845b3 1384 AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);\r
b0bacc00 1385 if (AllHeaderSize == 0) {\r
e0961677 1386 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName));\r
004ce0ab 1387 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;\r
45ce0a67 1388 Status = EFI_ABORTED;\r
b0bacc00
KM
1389 goto cleanup;\r
1390 }\r
1391\r
1392 //\r
1393 // Indicate that control is handed off to FmpDeviceLib\r
1394 //\r
1395 Progress (5);\r
1396\r
1397 //\r
45ce0a67 1398 // Copy the requested image to the firmware using the FmpDeviceLib\r
b0bacc00 1399 //\r
b96b44fe 1400 Status = FmpDeviceSetImageWithStatus (\r
45ce0a67 1401 (((UINT8 *)Image) + AllHeaderSize),\r
0f30087b 1402 ImageSize - AllHeaderSize,\r
b0bacc00
KM
1403 VendorCode,\r
1404 FmpDxeProgress,\r
95d28836 1405 IncomingFwVersion,\r
b96b44fe
MK
1406 AbortReason,\r
1407 &LastAttemptStatus\r
b0bacc00
KM
1408 );\r
1409 if (EFI_ERROR (Status)) {\r
e0961677 1410 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", mImageIdName, Status));\r
b96b44fe
MK
1411\r
1412 //\r
1413 // LastAttemptStatus returned from the device library should fall within the designated error range\r
1414 // [LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE, LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE]\r
1415 //\r
1416 if ((LastAttemptStatus < LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE) ||\r
45ce0a67
MK
1417 (LastAttemptStatus > LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE))\r
1418 {\r
b96b44fe
MK
1419 DEBUG (\r
1420 (DEBUG_ERROR,\r
45ce0a67
MK
1421 "FmpDxe(%s): SetTheImage() - LastAttemptStatus %d from FmpDeviceSetImageWithStatus() is invalid.\n",\r
1422 mImageIdName,\r
1423 LastAttemptStatus)\r
b96b44fe
MK
1424 );\r
1425 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
1426 }\r
1427\r
b0bacc00
KM
1428 goto cleanup;\r
1429 }\r
1430\r
0f30087b
WX
1431 //\r
1432 // Store the dependency\r
1433 //\r
1434 if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {\r
1435 Status = SaveFmpDependency (Dependencies, DependenciesSize);\r
1436 if (EFI_ERROR (Status)) {\r
1437 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SaveFmpDependency from FmpDependencyCheckLib failed. (%r)\n", mImageIdName, Status));\r
1438 }\r
45ce0a67 1439\r
0f30087b
WX
1440 Status = EFI_SUCCESS;\r
1441 }\r
b0bacc00
KM
1442\r
1443 //\r
1444 // Finished the update without error\r
1445 // Indicate that control has been returned from FmpDeviceLib\r
1446 //\r
1447 Progress (99);\r
1448\r
1449 //\r
1450 // Update the version stored in variable\r
1451 //\r
4f0544b1 1452 if (!Private->RuntimeVersionSupported) {\r
a6d73269 1453 Version = DEFAULT_VERSION;\r
b0bacc00 1454 GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);\r
67c1e5ee 1455 SetVersionInVariable (Private, Version);\r
b0bacc00
KM
1456 }\r
1457\r
1458 //\r
1459 // Update lowest supported variable\r
1460 //\r
67c1e5ee
EJ
1461 LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
1462 GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);\r
1463 SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion);\r
b0bacc00
KM
1464\r
1465 LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
1466\r
b0bacc00
KM
1467cleanup:\r
1468 mProgressFunc = NULL;\r
3633d530
MK
1469\r
1470 if (Private != NULL) {\r
004ce0ab 1471 DEBUG ((DEBUG_INFO, "FmpDxe(%s): SetTheImage() LastAttemptStatus: %u.\n", mImageIdName, LastAttemptStatus));\r
3633d530
MK
1472 SetLastAttemptStatusInVariable (Private, LastAttemptStatus);\r
1473 }\r
b0bacc00 1474\r
c6c18d87
SZ
1475 if (Progress != NULL) {\r
1476 //\r
1477 // Set progress to 100 after everything is done including recording Status.\r
1478 //\r
1479 Progress (100);\r
1480 }\r
b0bacc00 1481\r
27e42bf6
SZ
1482 //\r
1483 // Need repopulate after SetImage is called to\r
1484 // update LastAttemptVersion and LastAttemptStatus.\r
1485 //\r
3633d530
MK
1486 if (Private != NULL) {\r
1487 Private->DescriptorPopulated = FALSE;\r
1488 }\r
27e42bf6 1489\r
b0bacc00
KM
1490 return Status;\r
1491}\r
1492\r
1493/**\r
1494 Returns information about the firmware package.\r
1495\r
1496 This function returns package information.\r
1497\r
1498 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
1499 @param[out] PackageVersion A version number that represents all the firmware images in the device.\r
1500 The format is vendor specific and new version must have a greater value\r
1501 than the old version. If PackageVersion is not supported, the value is\r
1502 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version\r
1503 comparison is to be performed using PackageVersionName. A value of\r
1504 0xFFFFFFFD indicates that package version update is in progress.\r
1505 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing\r
1506 the package version name. The buffer is allocated by this function with\r
1507 AllocatePool(), and it is the caller's responsibility to free it with a\r
1508 call to FreePool().\r
1509 @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of\r
1510 package version name. A value of 0 indicates the device does not support\r
1511 update of package version name. Length is the number of Unicode characters,\r
1512 including the terminating null character.\r
1513 @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute\r
1514 Definitions' for possible returned values of this parameter. A value of 1\r
1515 indicates the attribute is supported and the current setting value is\r
1516 indicated in AttributesSetting. A value of 0 indicates the attribute is not\r
1517 supported and the current setting value in AttributesSetting is meaningless.\r
1518 @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned\r
1519 values of this parameter\r
1520\r
1521 @retval EFI_SUCCESS The package information was successfully returned.\r
1522 @retval EFI_UNSUPPORTED The operation is not supported.\r
1523\r
1524**/\r
1525EFI_STATUS\r
1526EFIAPI\r
1527GetPackageInfo (\r
1528 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
1529 OUT UINT32 *PackageVersion,\r
1530 OUT CHAR16 **PackageVersionName,\r
1531 OUT UINT32 *PackageVersionNameMaxLen,\r
1532 OUT UINT64 *AttributesSupported,\r
1533 OUT UINT64 *AttributesSetting\r
1534 )\r
1535{\r
1536 return EFI_UNSUPPORTED;\r
1537}\r
1538\r
1539/**\r
1540 Updates information about the firmware package.\r
1541\r
1542 This function updates package information.\r
1543 This function returns EFI_UNSUPPORTED if the package information is not updatable.\r
1544 VendorCode enables vendor to implement vendor-specific package information update policy.\r
1545 Null if the caller did not specify this policy or use the default policy.\r
1546\r
1547 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
1548 @param[in] Image Points to the authentication image.\r
1549 Null if authentication is not required.\r
1550 @param[in] ImageSize Size of the authentication image in bytes.\r
1551 0 if authentication is not required.\r
1552 @param[in] VendorCode This enables vendor to implement vendor-specific firmware\r
1553 image update policy.\r
1554 Null indicates the caller did not specify this policy or use\r
1555 the default policy.\r
1556 @param[in] PackageVersion The new package version.\r
1557 @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing\r
1558 the package version name.\r
1559 The string length is equal to or less than the value returned in\r
1560 PackageVersionNameMaxLen.\r
1561\r
1562 @retval EFI_SUCCESS The device was successfully updated with the new package\r
1563 information.\r
1564 @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value\r
1565 returned in PackageVersionNameMaxLen.\r
1566 @retval EFI_UNSUPPORTED The operation is not supported.\r
5fc5867e 1567 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
b0bacc00
KM
1568\r
1569**/\r
1570EFI_STATUS\r
1571EFIAPI\r
1572SetPackageInfo (\r
1573 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
1574 IN CONST VOID *Image,\r
1575 IN UINTN ImageSize,\r
1576 IN CONST VOID *VendorCode,\r
1577 IN UINT32 PackageVersion,\r
1578 IN CONST CHAR16 *PackageVersionName\r
1579 )\r
1580{\r
1581 return EFI_UNSUPPORTED;\r
1582}\r
1583\r
1584/**\r
1585 Event notification function that is invoked when the event GUID specified by\r
1586 PcdFmpDeviceLockEventGuid is signaled.\r
1587\r
1588 @param[in] Event Event whose notification function is being invoked.\r
1589 @param[in] Context The pointer to the notification function's context,\r
1590 which is implementation-dependent.\r
1591**/\r
1592VOID\r
1593EFIAPI\r
1594FmpDxeLockEventNotify (\r
1595 IN EFI_EVENT Event,\r
1596 IN VOID *Context\r
1597 )\r
1598{\r
4f0544b1
EJ
1599 EFI_STATUS Status;\r
1600 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
1601\r
b4b9496b
MK
1602 if (Context == NULL) {\r
1603 ASSERT (Context != NULL);\r
1604 return;\r
1605 }\r
1606\r
4f0544b1 1607 Private = (FIRMWARE_MANAGEMENT_PRIVATE_DATA *)Context;\r
b0bacc00 1608\r
4f0544b1 1609 if (!Private->FmpDeviceLocked) {\r
9e6c4f15
SZ
1610 //\r
1611 // Lock the firmware device\r
1612 //\r
4f0544b1 1613 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
45ce0a67 1614 Status = FmpDeviceLock ();\r
9e6c4f15
SZ
1615 if (EFI_ERROR (Status)) {\r
1616 if (Status != EFI_UNSUPPORTED) {\r
e0961677 1617 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));\r
b0bacc00 1618 } else {\r
e0961677 1619 DEBUG ((DEBUG_WARN, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));\r
b0bacc00 1620 }\r
b0bacc00 1621 }\r
45ce0a67 1622\r
4f0544b1 1623 Private->FmpDeviceLocked = TRUE;\r
b0bacc00
KM
1624 }\r
1625}\r
1626\r
1627/**\r
1628 Function to install FMP instance.\r
1629\r
1630 @param[in] Handle The device handle to install a FMP instance on.\r
1631\r
1632 @retval EFI_SUCCESS FMP Installed\r
1633 @retval EFI_INVALID_PARAMETER Handle was invalid\r
1634 @retval other Error installing FMP\r
1635\r
1636**/\r
1637EFI_STATUS\r
1638EFIAPI\r
1639InstallFmpInstance (\r
1640 IN EFI_HANDLE Handle\r
1641 )\r
1642{\r
4f0544b1
EJ
1643 EFI_STATUS Status;\r
1644 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
1645 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
b0bacc00 1646\r
b0bacc00
KM
1647 //\r
1648 // Only allow a single FMP Protocol instance to be installed\r
1649 //\r
4f0544b1
EJ
1650 Status = gBS->OpenProtocol (\r
1651 Handle,\r
1652 &gEfiFirmwareManagementProtocolGuid,\r
1653 (VOID **)&Fmp,\r
1654 NULL,\r
1655 NULL,\r
1656 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1657 );\r
1658 if (!EFI_ERROR (Status)) {\r
b0bacc00
KM
1659 return EFI_ALREADY_STARTED;\r
1660 }\r
1661\r
1662 //\r
1663 // Allocate FMP Protocol instance\r
1664 //\r
4f0544b1
EJ
1665 Private = AllocateCopyPool (\r
1666 sizeof (mFirmwareManagementPrivateDataTemplate),\r
1667 &mFirmwareManagementPrivateDataTemplate\r
1668 );\r
1669 if (Private == NULL) {\r
e0961677 1670 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to allocate memory for private structure.\n", mImageIdName));\r
b0bacc00
KM
1671 Status = EFI_OUT_OF_RESOURCES;\r
1672 goto cleanup;\r
1673 }\r
1674\r
1675 //\r
4f0544b1 1676 // Initialize private context data structure\r
b0bacc00 1677 //\r
45ce0a67 1678 Private->Handle = Handle;\r
4f0544b1 1679 Private->FmpDeviceContext = NULL;\r
45ce0a67 1680 Status = FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
4f0544b1
EJ
1681 if (Status == EFI_UNSUPPORTED) {\r
1682 Private->FmpDeviceContext = NULL;\r
1683 } else if (EFI_ERROR (Status)) {\r
b0bacc00
KM
1684 goto cleanup;\r
1685 }\r
1686\r
67c1e5ee
EJ
1687 //\r
1688 // Make sure the descriptor has already been loaded or refreshed\r
1689 //\r
1690 PopulateDescriptor (Private);\r
1691\r
4f0544b1
EJ
1692 if (IsLockFmpDeviceAtLockEventGuidRequired ()) {\r
1693 //\r
e0961677 1694 // Register all UEFI Variables used by this module to be locked.\r
4f0544b1 1695 //\r
67c1e5ee 1696 Status = LockAllFmpVariables (Private);\r
4f0544b1 1697 if (EFI_ERROR (Status)) {\r
e0961677 1698 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register variables to lock. Status = %r.\n", mImageIdName, Status));\r
4f0544b1 1699 } else {\r
e0961677 1700 DEBUG ((DEBUG_INFO, "FmpDxe(%s): All variables registered to lock\n", mImageIdName));\r
4f0544b1
EJ
1701 }\r
1702\r
1703 //\r
1704 // Create and register notify function to lock the FMP device.\r
1705 //\r
1706 Status = gBS->CreateEventEx (\r
1707 EVT_NOTIFY_SIGNAL,\r
1708 TPL_CALLBACK,\r
1709 FmpDxeLockEventNotify,\r
1710 Private,\r
1711 mLockGuid,\r
1712 &Private->FmpDeviceLockEvent\r
1713 );\r
1714 if (EFI_ERROR (Status)) {\r
e0961677 1715 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register notification. Status = %r\n", mImageIdName, Status));\r
4f0544b1 1716 }\r
45ce0a67 1717\r
4f0544b1
EJ
1718 ASSERT_EFI_ERROR (Status);\r
1719 } else {\r
e0961677 1720 DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): Not registering notification to call FmpDeviceLock() because mfg mode\n", mImageIdName));\r
4f0544b1 1721 }\r
b0bacc00
KM
1722\r
1723 //\r
1724 // Install FMP Protocol and FMP Progress Protocol\r
1725 //\r
1726 Status = gBS->InstallMultipleProtocolInterfaces (\r
4f0544b1 1727 &Private->Handle,\r
45ce0a67
MK
1728 &gEfiFirmwareManagementProtocolGuid,\r
1729 &Private->Fmp,\r
1730 &gEdkiiFirmwareManagementProgressProtocolGuid,\r
1731 &mFmpProgress,\r
b0bacc00
KM
1732 NULL\r
1733 );\r
b0bacc00 1734 if (EFI_ERROR (Status)) {\r
e0961677 1735 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol install error. Status = %r.\n", mImageIdName, Status));\r
b0bacc00
KM
1736 goto cleanup;\r
1737 }\r
1738\r
b0bacc00
KM
1739cleanup:\r
1740\r
4f0544b1
EJ
1741 if (EFI_ERROR (Status)) {\r
1742 if (Private != NULL) {\r
1743 if (Private->FmpDeviceLockEvent != NULL) {\r
1744 gBS->CloseEvent (Private->FmpDeviceLockEvent);\r
1745 }\r
45ce0a67 1746\r
67c1e5ee
EJ
1747 if (Private->Descriptor.VersionName != NULL) {\r
1748 FreePool (Private->Descriptor.VersionName);\r
1749 }\r
45ce0a67 1750\r
67c1e5ee
EJ
1751 if (Private->FmpDeviceContext != NULL) {\r
1752 FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
1753 }\r
45ce0a67 1754\r
67c1e5ee
EJ
1755 if (Private->VersionVariableName != NULL) {\r
1756 FreePool (Private->VersionVariableName);\r
1757 }\r
45ce0a67 1758\r
67c1e5ee
EJ
1759 if (Private->LsvVariableName != NULL) {\r
1760 FreePool (Private->LsvVariableName);\r
1761 }\r
45ce0a67 1762\r
67c1e5ee
EJ
1763 if (Private->LastAttemptStatusVariableName != NULL) {\r
1764 FreePool (Private->LastAttemptStatusVariableName);\r
1765 }\r
45ce0a67 1766\r
67c1e5ee
EJ
1767 if (Private->LastAttemptVersionVariableName != NULL) {\r
1768 FreePool (Private->LastAttemptVersionVariableName);\r
1769 }\r
45ce0a67 1770\r
67c1e5ee
EJ
1771 if (Private->FmpStateVariableName != NULL) {\r
1772 FreePool (Private->FmpStateVariableName);\r
1773 }\r
45ce0a67 1774\r
4f0544b1
EJ
1775 FreePool (Private);\r
1776 }\r
1777 }\r
1778\r
b0bacc00
KM
1779 return Status;\r
1780}\r
1781\r
4f0544b1
EJ
1782/**\r
1783 Function to uninstall FMP instance.\r
1784\r
1785 @param[in] Handle The device handle to install a FMP instance on.\r
1786\r
1787 @retval EFI_SUCCESS FMP Installed\r
1788 @retval EFI_INVALID_PARAMETER Handle was invalid\r
1789 @retval other Error installing FMP\r
1790\r
1791**/\r
1792EFI_STATUS\r
1793EFIAPI\r
1794UninstallFmpInstance (\r
1795 IN EFI_HANDLE Handle\r
1796 )\r
1797{\r
1798 EFI_STATUS Status;\r
1799 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
1800 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
1801\r
1802 Status = gBS->OpenProtocol (\r
1803 Handle,\r
1804 &gEfiFirmwareManagementProtocolGuid,\r
1805 (VOID **)&Fmp,\r
1806 NULL,\r
1807 NULL,\r
1808 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1809 );\r
1810 if (EFI_ERROR (Status)) {\r
e0961677 1811 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol open error. Status = %r.\n", mImageIdName, Status));\r
4f0544b1
EJ
1812 return Status;\r
1813 }\r
1814\r
1815 Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (Fmp);\r
1816 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
1817\r
1818 if (Private->FmpDeviceLockEvent != NULL) {\r
1819 gBS->CloseEvent (Private->FmpDeviceLockEvent);\r
1820 }\r
1821\r
1822 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1823 Private->Handle,\r
45ce0a67
MK
1824 &gEfiFirmwareManagementProtocolGuid,\r
1825 &Private->Fmp,\r
1826 &gEdkiiFirmwareManagementProgressProtocolGuid,\r
1827 &mFmpProgress,\r
4f0544b1
EJ
1828 NULL\r
1829 );\r
1830 if (EFI_ERROR (Status)) {\r
e0961677 1831 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol uninstall error. Status = %r.\n", mImageIdName, Status));\r
4f0544b1
EJ
1832 return Status;\r
1833 }\r
1834\r
67c1e5ee
EJ
1835 if (Private->Descriptor.VersionName != NULL) {\r
1836 FreePool (Private->Descriptor.VersionName);\r
1837 }\r
45ce0a67 1838\r
67c1e5ee
EJ
1839 if (Private->FmpDeviceContext != NULL) {\r
1840 FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
1841 }\r
45ce0a67 1842\r
67c1e5ee
EJ
1843 if (Private->VersionVariableName != NULL) {\r
1844 FreePool (Private->VersionVariableName);\r
1845 }\r
45ce0a67 1846\r
67c1e5ee
EJ
1847 if (Private->LsvVariableName != NULL) {\r
1848 FreePool (Private->LsvVariableName);\r
1849 }\r
45ce0a67 1850\r
67c1e5ee
EJ
1851 if (Private->LastAttemptStatusVariableName != NULL) {\r
1852 FreePool (Private->LastAttemptStatusVariableName);\r
1853 }\r
45ce0a67 1854\r
67c1e5ee
EJ
1855 if (Private->LastAttemptVersionVariableName != NULL) {\r
1856 FreePool (Private->LastAttemptVersionVariableName);\r
1857 }\r
45ce0a67 1858\r
67c1e5ee
EJ
1859 if (Private->FmpStateVariableName != NULL) {\r
1860 FreePool (Private->FmpStateVariableName);\r
1861 }\r
45ce0a67 1862\r
4f0544b1
EJ
1863 FreePool (Private);\r
1864\r
1865 return EFI_SUCCESS;\r
1866}\r
1867\r
1868/**\r
1869 Unloads the application and its installed protocol.\r
1870\r
1871 @param ImageHandle Handle that identifies the image to be unloaded.\r
1872 @param SystemTable The system table.\r
1873\r
1874 @retval EFI_SUCCESS The image has been unloaded.\r
1875\r
1876**/\r
1877EFI_STATUS\r
1878EFIAPI\r
1879FmpDxeLibDestructor (\r
1880 IN EFI_HANDLE ImageHandle,\r
1881 IN EFI_SYSTEM_TABLE *SystemTable\r
1882 )\r
1883{\r
1884 if (mFmpSingleInstance) {\r
1885 return UninstallFmpInstance (ImageHandle);\r
1886 }\r
45ce0a67 1887\r
4f0544b1
EJ
1888 return EFI_SUCCESS;\r
1889}\r
1890\r
b0bacc00 1891/**\r
e8619f82 1892 Main entry for this driver/library.\r
b0bacc00
KM
1893\r
1894 @param[in] ImageHandle Image handle this driver.\r
1895 @param[in] SystemTable Pointer to SystemTable.\r
1896\r
1897**/\r
1898EFI_STATUS\r
1899EFIAPI\r
1900FmpDxeEntryPoint (\r
1901 IN EFI_HANDLE ImageHandle,\r
1902 IN EFI_SYSTEM_TABLE *SystemTable\r
1903 )\r
1904{\r
1905 EFI_STATUS Status;\r
b0bacc00
KM
1906\r
1907 //\r
1908 // Verify that a new FILE_GUID value has been provided in the <Defines>\r
1909 // section of this module. The FILE_GUID is the ESRT GUID that must be\r
1910 // unique for each updatable firmware image.\r
1911 //\r
1912 if (CompareGuid (&mDefaultModuleFileGuid, &gEfiCallerIdGuid)) {\r
1913 DEBUG ((DEBUG_ERROR, "FmpDxe: Use of default FILE_GUID detected. FILE_GUID must be set to a unique value.\n"));\r
1914 ASSERT (FALSE);\r
1915 return EFI_UNSUPPORTED;\r
1916 }\r
1917\r
1918 //\r
1919 // Get the ImageIdName value for the EFI_FIRMWARE_IMAGE_DESCRIPTOR from a PCD.\r
1920 //\r
45ce0a67
MK
1921 mImageIdName = (CHAR16 *)PcdGetPtr (PcdFmpDeviceImageIdName);\r
1922 if ((PcdGetSize (PcdFmpDeviceImageIdName) <= 2) || (mImageIdName[0] == 0)) {\r
b0bacc00
KM
1923 //\r
1924 // PcdFmpDeviceImageIdName must be set to a non-empty Unicode string\r
1925 //\r
c9fa9762 1926 DEBUG ((DEBUG_ERROR, "FmpDxe(%g): PcdFmpDeviceImageIdName is an empty string.\n", &gEfiCallerIdGuid));\r
b0bacc00 1927 ASSERT (FALSE);\r
e0961677 1928 return EFI_UNSUPPORTED;\r
b0bacc00
KM
1929 }\r
1930\r
1931 //\r
1932 // Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.\r
1933 //\r
1934 DetectTestKey ();\r
1935\r
4f0544b1
EJ
1936 //\r
1937 // Fill in FMP Progress Protocol fields for Version 1\r
1938 //\r
1939 mFmpProgress.Version = 1;\r
1940 mFmpProgress.ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);\r
1941 mFmpProgress.WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);\r
9e6c4f15 1942\r
4f0544b1
EJ
1943 // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.\r
1944 // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then\r
1945 // gEfiEndOfDxeEventGroupGuid is used.\r
1946 //\r
1947 mLockGuid = &gEfiEndOfDxeEventGroupGuid;\r
1948 if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {\r
1949 mLockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);\r
9e6c4f15 1950 }\r
45ce0a67 1951\r
e0961677 1952 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Lock GUID: %g\n", mImageIdName, mLockGuid));\r
9e6c4f15 1953\r
b0bacc00
KM
1954 //\r
1955 // Register with library the install function so if the library uses\r
1956 // UEFI driver model/driver binding protocol it can install FMP on its device handle\r
1957 // If library is simple lib that does not use driver binding then it should return\r
1958 // unsupported and this will install the FMP instance on the ImageHandle\r
1959 //\r
1960 Status = RegisterFmpInstaller (InstallFmpInstance);\r
1961 if (Status == EFI_UNSUPPORTED) {\r
4f0544b1 1962 mFmpSingleInstance = TRUE;\r
e0961677 1963 DEBUG ((DEBUG_INFO, "FmpDxe(%s): FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n", mImageIdName));\r
4f0544b1
EJ
1964 Status = RegisterFmpUninstaller (UninstallFmpInstance);\r
1965 if (Status == EFI_UNSUPPORTED) {\r
1966 Status = InstallFmpInstance (ImageHandle);\r
1967 } else {\r
e0961677 1968 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));\r
4f0544b1
EJ
1969 Status = EFI_UNSUPPORTED;\r
1970 }\r
b0bacc00 1971 } else if (EFI_ERROR (Status)) {\r
e0961677 1972 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib registration returned %r. No FMP installed.\n", mImageIdName, Status));\r
b0bacc00
KM
1973 } else {\r
1974 DEBUG ((\r
1975 DEBUG_INFO,\r
e0961677
EJ
1976 "FmpDxe(%s): FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n",\r
1977 mImageIdName\r
b0bacc00 1978 ));\r
4f0544b1
EJ
1979 Status = RegisterFmpUninstaller (UninstallFmpInstance);\r
1980 if (EFI_ERROR (Status)) {\r
e0961677 1981 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));\r
4f0544b1 1982 }\r
b0bacc00
KM
1983 }\r
1984\r
b0bacc00
KM
1985 return Status;\r
1986}\r