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