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