]> git.proxmox.com Git - mirror_edk2.git/blob - FmpDevicePkg/FmpDxe/FmpDxe.c
FmpDevicePkg/FmpDxe: Improve set image path Last Attempt Status granularity
[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 @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt status to report
725 back to the ESRT table in case of error. If an error does not occur,
726 this function will set the value to LAST_ATTEMPT_STATUS_SUCCESS.
727
728 This function will return error codes that occur within this function
729 implementation within a driver range of last attempt error codes from
730 LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE_VALUE
731 to LAST_ATTEMPT_STATUS_DRIVER_MAX_ERROR_CODE_VALUE.
732
733 @retval EFI_SUCCESS The image was successfully checked.
734 @retval EFI_ABORTED The operation is aborted.
735 @retval EFI_INVALID_PARAMETER The Image was NULL.
736 @retval EFI_UNSUPPORTED The operation is not supported.
737 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
738
739 **/
740 EFI_STATUS
741 EFIAPI
742 CheckTheImageInternal (
743 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
744 IN UINT8 ImageIndex,
745 IN CONST VOID *Image,
746 IN UINTN ImageSize,
747 OUT UINT32 *ImageUpdatable,
748 OUT UINT32 *LastAttemptStatus
749 )
750 {
751 EFI_STATUS Status;
752 UINT32 LocalLastAttemptStatus;
753 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
754 UINTN RawSize;
755 VOID *FmpPayloadHeader;
756 UINTN FmpPayloadSize;
757 UINT32 Version;
758 UINT32 FmpHeaderSize;
759 UINTN AllHeaderSize;
760 UINT32 Index;
761 VOID *PublicKeyData;
762 UINTN PublicKeyDataLength;
763 UINT8 *PublicKeyDataXdr;
764 UINT8 *PublicKeyDataXdrEnd;
765 EFI_FIRMWARE_IMAGE_DEP *Dependencies;
766 UINT32 DependenciesSize;
767
768 Status = EFI_SUCCESS;
769 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
770 RawSize = 0;
771 FmpPayloadHeader = NULL;
772 FmpPayloadSize = 0;
773 Version = 0;
774 FmpHeaderSize = 0;
775 AllHeaderSize = 0;
776 Dependencies = NULL;
777 DependenciesSize = 0;
778
779 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
780 return EFI_UNSUPPORTED;
781 }
782
783 if (LastAttemptStatus == NULL) {
784 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImageInternal() - LastAttemptStatus is NULL.\n", mImageIdName));
785 Status = EFI_INVALID_PARAMETER;
786 goto cleanup;
787 }
788
789 //
790 // A last attempt status error code will always override the success
791 // value before returning from the function
792 //
793 *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
794
795 if (This == NULL) {
796 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - This is NULL.\n", mImageIdName));
797 Status = EFI_INVALID_PARAMETER;
798 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;
799 goto cleanup;
800 }
801
802 //
803 // Retrieve the private context structure
804 //
805 Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
806 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
807
808 //
809 // Make sure the descriptor has already been loaded or refreshed
810 //
811 PopulateDescriptor (Private);
812
813 if (ImageUpdatable == NULL) {
814 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName));
815 Status = EFI_INVALID_PARAMETER;
816 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_UPDATABLE;
817 goto cleanup;
818 }
819
820 //
821 //Set to valid and then if any tests fail it will update this flag.
822 //
823 *ImageUpdatable = IMAGE_UPDATABLE_VALID;
824
825 //
826 // Set to satisfied and then if dependency evaluates to false it will update this flag.
827 //
828 Private->DependenciesSatisfied = TRUE;
829
830 if (Image == NULL) {
831 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName));
832 //
833 // not sure if this is needed
834 //
835 *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
836 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_PROVIDED;
837 return EFI_INVALID_PARAMETER;
838 }
839
840 PublicKeyDataXdr = PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr);
841 PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr);
842
843 if (PublicKeyDataXdr == NULL || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {
844 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName));
845 Status = EFI_ABORTED;
846 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_CERTIFICATE;
847 } else {
848 //
849 // Try each key from PcdFmpDevicePkcs7CertBufferXdr
850 //
851 for (Index = 1; PublicKeyDataXdr < PublicKeyDataXdrEnd; Index++) {
852 Index++;
853 DEBUG (
854 (DEBUG_INFO,
855 "FmpDxe(%s): Certificate #%d [%p..%p].\n",
856 mImageIdName,
857 Index,
858 PublicKeyDataXdr,
859 PublicKeyDataXdrEnd
860 )
861 );
862
863 if ((PublicKeyDataXdr + sizeof (UINT32)) > PublicKeyDataXdrEnd) {
864 //
865 // Key data extends beyond end of PCD
866 //
867 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate size extends beyond end of PCD, skipping it.\n", mImageIdName));
868 Status = EFI_ABORTED;
869 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH_VALUE;
870 break;
871 }
872 //
873 // Read key length stored in big-endian format
874 //
875 PublicKeyDataLength = SwapBytes32 (*(UINT32 *)(PublicKeyDataXdr));
876 //
877 // Point to the start of the key data
878 //
879 PublicKeyDataXdr += sizeof (UINT32);
880 if (PublicKeyDataXdr + PublicKeyDataLength > PublicKeyDataXdrEnd) {
881 //
882 // Key data extends beyond end of PCD
883 //
884 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName));
885 Status = EFI_ABORTED;
886 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH;
887 break;
888 }
889 PublicKeyData = PublicKeyDataXdr;
890 Status = AuthenticateFmpImage (
891 (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image,
892 ImageSize,
893 PublicKeyData,
894 PublicKeyDataLength
895 );
896 if (!EFI_ERROR (Status)) {
897 break;
898 }
899 PublicKeyDataXdr += PublicKeyDataLength;
900 PublicKeyDataXdr = (UINT8 *)ALIGN_POINTER (PublicKeyDataXdr, sizeof (UINT32));
901 }
902 }
903
904 if (EFI_ERROR (Status)) {
905 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Authentication Failed %r.\n", mImageIdName, Status));
906 if (LocalLastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {
907 *LastAttemptStatus = LocalLastAttemptStatus;
908 } else {
909 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_AUTH_FAILURE;
910 }
911 goto cleanup;
912 }
913
914 //
915 // Check to make sure index is 1
916 //
917 if (ImageIndex != 1) {
918 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName));
919 *ImageUpdatable = IMAGE_UPDATABLE_INVALID_TYPE;
920 Status = EFI_INVALID_PARAMETER;
921 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_IMAGE_INDEX;
922 goto cleanup;
923 }
924
925 //
926 // Get the dependency from Image.
927 //
928 Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);
929
930 //
931 // Check the FmpPayloadHeader
932 //
933 FmpPayloadHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize );
934 if (FmpPayloadHeader == NULL) {
935 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));
936 Status = EFI_ABORTED;
937 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;
938 goto cleanup;
939 }
940 Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
941 if (EFI_ERROR (Status)) {
942 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));
943 *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
944 Status = EFI_SUCCESS;
945 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_VERSION;
946 goto cleanup;
947 }
948
949 //
950 // Check the lowest supported version
951 //
952 if (Version < Private->Descriptor.LowestSupportedImageVersion) {
953 DEBUG (
954 (DEBUG_ERROR,
955 "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",
956 mImageIdName, Version, Private->Descriptor.LowestSupportedImageVersion)
957 );
958 *ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;
959 Status = EFI_SUCCESS;
960 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_VERSION_TOO_LOW;
961 goto cleanup;
962 }
963
964 //
965 // Evaluate dependency expression
966 //
967 Private->DependenciesSatisfied = CheckFmpDependency (Private->Descriptor.ImageTypeId, Version, Dependencies, DependenciesSize);
968 if (!Private->DependenciesSatisfied) {
969 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed.\n", mImageIdName));
970 *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
971 Status = EFI_SUCCESS;
972 goto cleanup;
973 }
974
975 //
976 // Get the FmpHeaderSize so we can determine the real payload size
977 //
978 Status = GetFmpPayloadHeaderSize (FmpPayloadHeader, FmpPayloadSize, &FmpHeaderSize);
979 if (EFI_ERROR (Status)) {
980 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));
981 *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
982 Status = EFI_SUCCESS;
983 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;
984 goto cleanup;
985 }
986
987 //
988 // Call FmpDevice Lib Check Image on the
989 // Raw payload. So all headers need stripped off
990 //
991 AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);
992 if (AllHeaderSize == 0) {
993 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName));
994 Status = EFI_ABORTED;
995 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;
996 goto cleanup;
997 }
998 RawSize = ImageSize - AllHeaderSize;
999
1000 //
1001 // FmpDeviceLib CheckImage function to do any specific checks
1002 //
1003 Status = FmpDeviceCheckImage ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdatable);
1004 if (EFI_ERROR (Status)) {
1005 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName, Status));
1006 }
1007
1008 cleanup:
1009 return Status;
1010 }
1011
1012 /**
1013 Checks if the firmware image is valid for the device.
1014
1015 This function allows firmware update application to validate the firmware image without
1016 invoking the SetImage() first.
1017
1018 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1019 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
1020 The number is between 1 and DescriptorCount.
1021 @param[in] Image Points to the new image.
1022 @param[in] ImageSize Size of the new image in bytes.
1023 @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
1024 if available, additional information if the image is invalid.
1025
1026 @retval EFI_SUCCESS The image was successfully checked.
1027 @retval EFI_ABORTED The operation is aborted.
1028 @retval EFI_INVALID_PARAMETER The Image was NULL.
1029 @retval EFI_UNSUPPORTED The operation is not supported.
1030 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
1031
1032 **/
1033 EFI_STATUS
1034 EFIAPI
1035 CheckTheImage (
1036 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
1037 IN UINT8 ImageIndex,
1038 IN CONST VOID *Image,
1039 IN UINTN ImageSize,
1040 OUT UINT32 *ImageUpdatable
1041 )
1042 {
1043 UINT32 LastAttemptStatus;
1044
1045 return CheckTheImageInternal (This, ImageIndex, Image, ImageSize, ImageUpdatable, &LastAttemptStatus);
1046 }
1047
1048 /**
1049 Updates the firmware image of the device.
1050
1051 This function updates the hardware with the new firmware image.
1052 This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
1053 If the firmware image is updatable, the function should perform the following minimal validations
1054 before proceeding to do the firmware image update.
1055 - Validate the image authentication if image has attribute
1056 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
1057 EFI_SECURITY_VIOLATION if the validation fails.
1058 - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
1059 the image is unsupported. The function can optionally provide more detailed information on
1060 why the image is not a supported image.
1061 - Validate the data from VendorCode if not null. Image validation must be performed before
1062 VendorCode data validation. VendorCode data is ignored or considered invalid if image
1063 validation failed. The function returns EFI_ABORTED if the data is invalid.
1064
1065 VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
1066 the caller did not specify the policy or use the default policy. As an example, vendor can implement
1067 a policy to allow an option to force a firmware image update when the abort reason is due to the new
1068 firmware image version is older than the current firmware image version or bad image checksum.
1069 Sensitive operations such as those wiping the entire firmware image and render the device to be
1070 non-functional should be encoded in the image itself rather than passed with the VendorCode.
1071 AbortReason enables vendor to have the option to provide a more detailed description of the abort
1072 reason to the caller.
1073
1074 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1075 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
1076 The number is between 1 and DescriptorCount.
1077 @param[in] Image Points to the new image.
1078 @param[in] ImageSize Size of the new image in bytes.
1079 @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
1080 Null indicates the caller did not specify the policy or use the default policy.
1081 @param[in] Progress A function used by the driver to report the progress of the firmware update.
1082 @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
1083 details for the aborted operation. The buffer is allocated by this function
1084 with AllocatePool(), and it is the caller's responsibility to free it with a
1085 call to FreePool().
1086
1087 @retval EFI_SUCCESS The device was successfully updated with the new image.
1088 @retval EFI_ABORTED The operation is aborted.
1089 @retval EFI_INVALID_PARAMETER The Image was NULL.
1090 @retval EFI_UNSUPPORTED The operation is not supported.
1091 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
1092
1093 **/
1094 EFI_STATUS
1095 EFIAPI
1096 SetTheImage (
1097 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
1098 IN UINT8 ImageIndex,
1099 IN CONST VOID *Image,
1100 IN UINTN ImageSize,
1101 IN CONST VOID *VendorCode,
1102 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,
1103 OUT CHAR16 **AbortReason
1104 )
1105 {
1106 EFI_STATUS Status;
1107 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
1108 UINT32 Updateable;
1109 BOOLEAN BooleanValue;
1110 UINT32 FmpHeaderSize;
1111 VOID *FmpHeader;
1112 UINTN FmpPayloadSize;
1113 UINT32 AllHeaderSize;
1114 UINT32 IncomingFwVersion;
1115 UINT32 LastAttemptStatus;
1116 UINT32 Version;
1117 UINT32 LowestSupportedVersion;
1118 EFI_FIRMWARE_IMAGE_DEP *Dependencies;
1119 UINT32 DependenciesSize;
1120
1121 Status = EFI_SUCCESS;
1122 Private = NULL;
1123 Updateable = 0;
1124 BooleanValue = FALSE;
1125 FmpHeaderSize = 0;
1126 FmpHeader = NULL;
1127 FmpPayloadSize = 0;
1128 AllHeaderSize = 0;
1129 IncomingFwVersion = 0;
1130 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
1131 Dependencies = NULL;
1132 DependenciesSize = 0;
1133
1134 if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
1135 return EFI_UNSUPPORTED;
1136 }
1137
1138 if (This == NULL) {
1139 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - This is NULL.\n", mImageIdName));
1140 Status = EFI_INVALID_PARAMETER;
1141 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;
1142 goto cleanup;
1143 }
1144
1145 //
1146 // Retrieve the private context structure
1147 //
1148 Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
1149 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
1150
1151 //
1152 // Make sure the descriptor has already been loaded or refreshed
1153 //
1154 PopulateDescriptor (Private);
1155
1156 //
1157 // Set to 0 to clear any previous results.
1158 //
1159 SetLastAttemptVersionInVariable (Private, IncomingFwVersion);
1160
1161 //
1162 // if we have locked the device, then skip the set operation.
1163 // it should be blocked by hardware too but we can catch here even faster
1164 //
1165 if (Private->FmpDeviceLocked) {
1166 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Device is already locked. Can't update.\n", mImageIdName));
1167 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_DEVICE_LOCKED;
1168 Status = EFI_UNSUPPORTED;
1169 goto cleanup;
1170 }
1171
1172 //
1173 // Call check image to verify the image
1174 //
1175 Status = CheckTheImageInternal (This, ImageIndex, Image, ImageSize, &Updateable, &LastAttemptStatus);
1176 if (EFI_ERROR (Status)) {
1177 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName, Status));
1178 goto cleanup;
1179 }
1180
1181 //
1182 // Get the dependency from Image.
1183 //
1184 Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);
1185
1186 //
1187 // No functional error in CheckTheImage. Attempt to get the Version to
1188 // support better error reporting.
1189 //
1190 FmpHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize );
1191 if (FmpHeader == NULL) {
1192 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));
1193 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;
1194 Status = EFI_ABORTED;
1195 goto cleanup;
1196 }
1197 Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);
1198 if (!EFI_ERROR (Status)) {
1199 //
1200 // Set to actual value
1201 //
1202 SetLastAttemptVersionInVariable (Private, IncomingFwVersion);
1203 }
1204
1205
1206 if (Updateable != IMAGE_UPDATABLE_VALID) {
1207 DEBUG (
1208 (DEBUG_ERROR,
1209 "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",
1210 mImageIdName, Updateable)
1211 );
1212 if (Private->DependenciesSatisfied == FALSE) {
1213 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;
1214 }
1215 Status = EFI_ABORTED;
1216 goto cleanup;
1217 }
1218
1219 if (Progress == NULL) {
1220 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName));
1221 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROGRESS_CALLBACK_ERROR;
1222 Status = EFI_INVALID_PARAMETER;
1223 goto cleanup;
1224 }
1225
1226 mProgressFunc = Progress;
1227
1228 //
1229 // Checking the image is at least 1%
1230 //
1231 Status = Progress (1);
1232 if (EFI_ERROR (Status)) {
1233 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Progress Callback failed with Status %r.\n", mImageIdName, Status));
1234 }
1235
1236 //
1237 //Check System Power
1238 //
1239 Status = CheckSystemPower (&BooleanValue);
1240 if (EFI_ERROR (Status)) {
1241 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName, Status));
1242 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_POWER_API;
1243 goto cleanup;
1244 }
1245 if (!BooleanValue) {
1246 Status = EFI_ABORTED;
1247 DEBUG (
1248 (DEBUG_ERROR,
1249 "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n", mImageIdName)
1250 );
1251 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT;
1252 goto cleanup;
1253 }
1254
1255 Progress (2);
1256
1257 //
1258 //Check System Thermal
1259 //
1260 Status = CheckSystemThermal (&BooleanValue);
1261 if (EFI_ERROR (Status)) {
1262 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName, Status));
1263 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_THERMAL_API;
1264 goto cleanup;
1265 }
1266 if (!BooleanValue) {
1267 Status = EFI_ABORTED;
1268 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_THERMAL;
1269 DEBUG (
1270 (DEBUG_ERROR,
1271 "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n", mImageIdName)
1272 );
1273 goto cleanup;
1274 }
1275
1276 Progress (3);
1277
1278 //
1279 //Check System Environment
1280 //
1281 Status = CheckSystemEnvironment (&BooleanValue);
1282 if (EFI_ERROR (Status)) {
1283 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName, Status));
1284 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_ENV_API;
1285 goto cleanup;
1286 }
1287 if (!BooleanValue) {
1288 Status = EFI_ABORTED;
1289 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_SYSTEM_ENV;
1290 DEBUG (
1291 (DEBUG_ERROR,
1292 "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n", mImageIdName)
1293 );
1294 goto cleanup;
1295 }
1296
1297 Progress (4);
1298
1299 //
1300 // Save LastAttemptStatus as error so that if SetImage never returns the error
1301 // state is recorded.
1302 //
1303 SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
1304
1305 //
1306 // Strip off all the headers so the device can process its firmware
1307 //
1308 Status = GetFmpPayloadHeaderSize (FmpHeader, FmpPayloadSize, &FmpHeaderSize);
1309 if (EFI_ERROR (Status)) {
1310 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName, Status));
1311 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;
1312 goto cleanup;
1313 }
1314
1315 AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);
1316 if (AllHeaderSize == 0) {
1317 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName));
1318 LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;
1319 Status = EFI_ABORTED;
1320 goto cleanup;
1321 }
1322
1323 //
1324 // Indicate that control is handed off to FmpDeviceLib
1325 //
1326 Progress (5);
1327
1328 //
1329 //Copy the requested image to the firmware using the FmpDeviceLib
1330 //
1331 Status = FmpDeviceSetImage (
1332 (((UINT8 *)Image) + AllHeaderSize),
1333 ImageSize - AllHeaderSize,
1334 VendorCode,
1335 FmpDxeProgress,
1336 IncomingFwVersion,
1337 AbortReason
1338 );
1339 if (EFI_ERROR (Status)) {
1340 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", mImageIdName, Status));
1341 goto cleanup;
1342 }
1343
1344 //
1345 // Store the dependency
1346 //
1347 if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
1348 Status = SaveFmpDependency (Dependencies, DependenciesSize);
1349 if (EFI_ERROR (Status)) {
1350 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SaveFmpDependency from FmpDependencyCheckLib failed. (%r)\n", mImageIdName, Status));
1351 }
1352 Status = EFI_SUCCESS;
1353 }
1354
1355 //
1356 // Finished the update without error
1357 // Indicate that control has been returned from FmpDeviceLib
1358 //
1359 Progress (99);
1360
1361 //
1362 // Update the version stored in variable
1363 //
1364 if (!Private->RuntimeVersionSupported) {
1365 Version = DEFAULT_VERSION;
1366 GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);
1367 SetVersionInVariable (Private, Version);
1368 }
1369
1370 //
1371 // Update lowest supported variable
1372 //
1373 LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
1374 GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);
1375 SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion);
1376
1377 LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
1378
1379 cleanup:
1380 mProgressFunc = NULL;
1381
1382 if (Private != NULL) {
1383 DEBUG ((DEBUG_INFO, "FmpDxe(%s): SetTheImage() LastAttemptStatus: %u.\n", mImageIdName, LastAttemptStatus));
1384 SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
1385 }
1386
1387 if (Progress != NULL) {
1388 //
1389 // Set progress to 100 after everything is done including recording Status.
1390 //
1391 Progress (100);
1392 }
1393
1394 //
1395 // Need repopulate after SetImage is called to
1396 // update LastAttemptVersion and LastAttemptStatus.
1397 //
1398 if (Private != NULL) {
1399 Private->DescriptorPopulated = FALSE;
1400 }
1401
1402 return Status;
1403 }
1404
1405 /**
1406 Returns information about the firmware package.
1407
1408 This function returns package information.
1409
1410 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1411 @param[out] PackageVersion A version number that represents all the firmware images in the device.
1412 The format is vendor specific and new version must have a greater value
1413 than the old version. If PackageVersion is not supported, the value is
1414 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
1415 comparison is to be performed using PackageVersionName. A value of
1416 0xFFFFFFFD indicates that package version update is in progress.
1417 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing
1418 the package version name. The buffer is allocated by this function with
1419 AllocatePool(), and it is the caller's responsibility to free it with a
1420 call to FreePool().
1421 @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
1422 package version name. A value of 0 indicates the device does not support
1423 update of package version name. Length is the number of Unicode characters,
1424 including the terminating null character.
1425 @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute
1426 Definitions' for possible returned values of this parameter. A value of 1
1427 indicates the attribute is supported and the current setting value is
1428 indicated in AttributesSetting. A value of 0 indicates the attribute is not
1429 supported and the current setting value in AttributesSetting is meaningless.
1430 @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned
1431 values of this parameter
1432
1433 @retval EFI_SUCCESS The package information was successfully returned.
1434 @retval EFI_UNSUPPORTED The operation is not supported.
1435
1436 **/
1437 EFI_STATUS
1438 EFIAPI
1439 GetPackageInfo (
1440 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
1441 OUT UINT32 *PackageVersion,
1442 OUT CHAR16 **PackageVersionName,
1443 OUT UINT32 *PackageVersionNameMaxLen,
1444 OUT UINT64 *AttributesSupported,
1445 OUT UINT64 *AttributesSetting
1446 )
1447 {
1448 return EFI_UNSUPPORTED;
1449 }
1450
1451 /**
1452 Updates information about the firmware package.
1453
1454 This function updates package information.
1455 This function returns EFI_UNSUPPORTED if the package information is not updatable.
1456 VendorCode enables vendor to implement vendor-specific package information update policy.
1457 Null if the caller did not specify this policy or use the default policy.
1458
1459 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1460 @param[in] Image Points to the authentication image.
1461 Null if authentication is not required.
1462 @param[in] ImageSize Size of the authentication image in bytes.
1463 0 if authentication is not required.
1464 @param[in] VendorCode This enables vendor to implement vendor-specific firmware
1465 image update policy.
1466 Null indicates the caller did not specify this policy or use
1467 the default policy.
1468 @param[in] PackageVersion The new package version.
1469 @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing
1470 the package version name.
1471 The string length is equal to or less than the value returned in
1472 PackageVersionNameMaxLen.
1473
1474 @retval EFI_SUCCESS The device was successfully updated with the new package
1475 information.
1476 @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
1477 returned in PackageVersionNameMaxLen.
1478 @retval EFI_UNSUPPORTED The operation is not supported.
1479 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
1480
1481 **/
1482 EFI_STATUS
1483 EFIAPI
1484 SetPackageInfo (
1485 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
1486 IN CONST VOID *Image,
1487 IN UINTN ImageSize,
1488 IN CONST VOID *VendorCode,
1489 IN UINT32 PackageVersion,
1490 IN CONST CHAR16 *PackageVersionName
1491 )
1492 {
1493 return EFI_UNSUPPORTED;
1494 }
1495
1496 /**
1497 Event notification function that is invoked when the event GUID specified by
1498 PcdFmpDeviceLockEventGuid is signaled.
1499
1500 @param[in] Event Event whose notification function is being invoked.
1501 @param[in] Context The pointer to the notification function's context,
1502 which is implementation-dependent.
1503 **/
1504 VOID
1505 EFIAPI
1506 FmpDxeLockEventNotify (
1507 IN EFI_EVENT Event,
1508 IN VOID *Context
1509 )
1510 {
1511 EFI_STATUS Status;
1512 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
1513
1514 if (Context == NULL) {
1515 ASSERT (Context != NULL);
1516 return;
1517 }
1518
1519 Private = (FIRMWARE_MANAGEMENT_PRIVATE_DATA *)Context;
1520
1521 if (!Private->FmpDeviceLocked) {
1522 //
1523 // Lock the firmware device
1524 //
1525 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
1526 Status = FmpDeviceLock();
1527 if (EFI_ERROR (Status)) {
1528 if (Status != EFI_UNSUPPORTED) {
1529 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));
1530 } else {
1531 DEBUG ((DEBUG_WARN, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));
1532 }
1533 }
1534 Private->FmpDeviceLocked = TRUE;
1535 }
1536 }
1537
1538 /**
1539 Function to install FMP instance.
1540
1541 @param[in] Handle The device handle to install a FMP instance on.
1542
1543 @retval EFI_SUCCESS FMP Installed
1544 @retval EFI_INVALID_PARAMETER Handle was invalid
1545 @retval other Error installing FMP
1546
1547 **/
1548 EFI_STATUS
1549 EFIAPI
1550 InstallFmpInstance (
1551 IN EFI_HANDLE Handle
1552 )
1553 {
1554 EFI_STATUS Status;
1555 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
1556 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
1557
1558 //
1559 // Only allow a single FMP Protocol instance to be installed
1560 //
1561 Status = gBS->OpenProtocol (
1562 Handle,
1563 &gEfiFirmwareManagementProtocolGuid,
1564 (VOID **)&Fmp,
1565 NULL,
1566 NULL,
1567 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1568 );
1569 if (!EFI_ERROR (Status)) {
1570 return EFI_ALREADY_STARTED;
1571 }
1572
1573 //
1574 // Allocate FMP Protocol instance
1575 //
1576 Private = AllocateCopyPool (
1577 sizeof (mFirmwareManagementPrivateDataTemplate),
1578 &mFirmwareManagementPrivateDataTemplate
1579 );
1580 if (Private == NULL) {
1581 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to allocate memory for private structure.\n", mImageIdName));
1582 Status = EFI_OUT_OF_RESOURCES;
1583 goto cleanup;
1584 }
1585
1586 //
1587 // Initialize private context data structure
1588 //
1589 Private->Handle = Handle;
1590 Private->FmpDeviceContext = NULL;
1591 Status = FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
1592 if (Status == EFI_UNSUPPORTED) {
1593 Private->FmpDeviceContext = NULL;
1594 } else if (EFI_ERROR (Status)) {
1595 goto cleanup;
1596 }
1597
1598 //
1599 // Make sure the descriptor has already been loaded or refreshed
1600 //
1601 PopulateDescriptor (Private);
1602
1603 if (IsLockFmpDeviceAtLockEventGuidRequired ()) {
1604 //
1605 // Register all UEFI Variables used by this module to be locked.
1606 //
1607 Status = LockAllFmpVariables (Private);
1608 if (EFI_ERROR (Status)) {
1609 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register variables to lock. Status = %r.\n", mImageIdName, Status));
1610 } else {
1611 DEBUG ((DEBUG_INFO, "FmpDxe(%s): All variables registered to lock\n", mImageIdName));
1612 }
1613
1614 //
1615 // Create and register notify function to lock the FMP device.
1616 //
1617 Status = gBS->CreateEventEx (
1618 EVT_NOTIFY_SIGNAL,
1619 TPL_CALLBACK,
1620 FmpDxeLockEventNotify,
1621 Private,
1622 mLockGuid,
1623 &Private->FmpDeviceLockEvent
1624 );
1625 if (EFI_ERROR (Status)) {
1626 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register notification. Status = %r\n", mImageIdName, Status));
1627 }
1628 ASSERT_EFI_ERROR (Status);
1629 } else {
1630 DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): Not registering notification to call FmpDeviceLock() because mfg mode\n", mImageIdName));
1631 }
1632
1633 //
1634 // Install FMP Protocol and FMP Progress Protocol
1635 //
1636 Status = gBS->InstallMultipleProtocolInterfaces (
1637 &Private->Handle,
1638 &gEfiFirmwareManagementProtocolGuid, &Private->Fmp,
1639 &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress,
1640 NULL
1641 );
1642 if (EFI_ERROR (Status)) {
1643 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol install error. Status = %r.\n", mImageIdName, Status));
1644 goto cleanup;
1645 }
1646
1647 cleanup:
1648
1649 if (EFI_ERROR (Status)) {
1650 if (Private != NULL) {
1651 if (Private->FmpDeviceLockEvent != NULL) {
1652 gBS->CloseEvent (Private->FmpDeviceLockEvent);
1653 }
1654 if (Private->Descriptor.VersionName != NULL) {
1655 FreePool (Private->Descriptor.VersionName);
1656 }
1657 if (Private->FmpDeviceContext != NULL) {
1658 FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);
1659 }
1660 if (Private->VersionVariableName != NULL) {
1661 FreePool (Private->VersionVariableName);
1662 }
1663 if (Private->LsvVariableName != NULL) {
1664 FreePool (Private->LsvVariableName);
1665 }
1666 if (Private->LastAttemptStatusVariableName != NULL) {
1667 FreePool (Private->LastAttemptStatusVariableName);
1668 }
1669 if (Private->LastAttemptVersionVariableName != NULL) {
1670 FreePool (Private->LastAttemptVersionVariableName);
1671 }
1672 if (Private->FmpStateVariableName != NULL) {
1673 FreePool (Private->FmpStateVariableName);
1674 }
1675 FreePool (Private);
1676 }
1677 }
1678
1679 return Status;
1680 }
1681
1682 /**
1683 Function to uninstall FMP instance.
1684
1685 @param[in] Handle The device handle to install a FMP instance on.
1686
1687 @retval EFI_SUCCESS FMP Installed
1688 @retval EFI_INVALID_PARAMETER Handle was invalid
1689 @retval other Error installing FMP
1690
1691 **/
1692 EFI_STATUS
1693 EFIAPI
1694 UninstallFmpInstance (
1695 IN EFI_HANDLE Handle
1696 )
1697 {
1698 EFI_STATUS Status;
1699 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
1700 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
1701
1702 Status = gBS->OpenProtocol (
1703 Handle,
1704 &gEfiFirmwareManagementProtocolGuid,
1705 (VOID **)&Fmp,
1706 NULL,
1707 NULL,
1708 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1709 );
1710 if (EFI_ERROR (Status)) {
1711 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol open error. Status = %r.\n", mImageIdName, Status));
1712 return Status;
1713 }
1714
1715 Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (Fmp);
1716 FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
1717
1718 if (Private->FmpDeviceLockEvent != NULL) {
1719 gBS->CloseEvent (Private->FmpDeviceLockEvent);
1720 }
1721
1722 Status = gBS->UninstallMultipleProtocolInterfaces (
1723 Private->Handle,
1724 &gEfiFirmwareManagementProtocolGuid, &Private->Fmp,
1725 &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress,
1726 NULL
1727 );
1728 if (EFI_ERROR (Status)) {
1729 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol uninstall error. Status = %r.\n", mImageIdName, Status));
1730 return Status;
1731 }
1732
1733 if (Private->Descriptor.VersionName != NULL) {
1734 FreePool (Private->Descriptor.VersionName);
1735 }
1736 if (Private->FmpDeviceContext != NULL) {
1737 FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);
1738 }
1739 if (Private->VersionVariableName != NULL) {
1740 FreePool (Private->VersionVariableName);
1741 }
1742 if (Private->LsvVariableName != NULL) {
1743 FreePool (Private->LsvVariableName);
1744 }
1745 if (Private->LastAttemptStatusVariableName != NULL) {
1746 FreePool (Private->LastAttemptStatusVariableName);
1747 }
1748 if (Private->LastAttemptVersionVariableName != NULL) {
1749 FreePool (Private->LastAttemptVersionVariableName);
1750 }
1751 if (Private->FmpStateVariableName != NULL) {
1752 FreePool (Private->FmpStateVariableName);
1753 }
1754 FreePool (Private);
1755
1756 return EFI_SUCCESS;
1757 }
1758
1759 /**
1760 Unloads the application and its installed protocol.
1761
1762 @param ImageHandle Handle that identifies the image to be unloaded.
1763 @param SystemTable The system table.
1764
1765 @retval EFI_SUCCESS The image has been unloaded.
1766
1767 **/
1768 EFI_STATUS
1769 EFIAPI
1770 FmpDxeLibDestructor (
1771 IN EFI_HANDLE ImageHandle,
1772 IN EFI_SYSTEM_TABLE *SystemTable
1773 )
1774 {
1775 if (mFmpSingleInstance) {
1776 return UninstallFmpInstance (ImageHandle);
1777 }
1778 return EFI_SUCCESS;
1779 }
1780
1781 /**
1782 Main entry for this driver/library.
1783
1784 @param[in] ImageHandle Image handle this driver.
1785 @param[in] SystemTable Pointer to SystemTable.
1786
1787 **/
1788 EFI_STATUS
1789 EFIAPI
1790 FmpDxeEntryPoint (
1791 IN EFI_HANDLE ImageHandle,
1792 IN EFI_SYSTEM_TABLE *SystemTable
1793 )
1794 {
1795 EFI_STATUS Status;
1796
1797 //
1798 // Verify that a new FILE_GUID value has been provided in the <Defines>
1799 // section of this module. The FILE_GUID is the ESRT GUID that must be
1800 // unique for each updatable firmware image.
1801 //
1802 if (CompareGuid (&mDefaultModuleFileGuid, &gEfiCallerIdGuid)) {
1803 DEBUG ((DEBUG_ERROR, "FmpDxe: Use of default FILE_GUID detected. FILE_GUID must be set to a unique value.\n"));
1804 ASSERT (FALSE);
1805 return EFI_UNSUPPORTED;
1806 }
1807
1808 //
1809 // Get the ImageIdName value for the EFI_FIRMWARE_IMAGE_DESCRIPTOR from a PCD.
1810 //
1811 mImageIdName = (CHAR16 *) PcdGetPtr (PcdFmpDeviceImageIdName);
1812 if (PcdGetSize (PcdFmpDeviceImageIdName) <= 2 || mImageIdName[0] == 0) {
1813 //
1814 // PcdFmpDeviceImageIdName must be set to a non-empty Unicode string
1815 //
1816 DEBUG ((DEBUG_ERROR, "FmpDxe(%g): PcdFmpDeviceImageIdName is an empty string.\n", &gEfiCallerIdGuid));
1817 ASSERT (FALSE);
1818 return EFI_UNSUPPORTED;
1819 }
1820
1821 //
1822 // Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.
1823 //
1824 DetectTestKey ();
1825
1826 //
1827 // Fill in FMP Progress Protocol fields for Version 1
1828 //
1829 mFmpProgress.Version = 1;
1830 mFmpProgress.ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);
1831 mFmpProgress.WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);
1832
1833 // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.
1834 // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then
1835 // gEfiEndOfDxeEventGroupGuid is used.
1836 //
1837 mLockGuid = &gEfiEndOfDxeEventGroupGuid;
1838 if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {
1839 mLockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);
1840 }
1841 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Lock GUID: %g\n", mImageIdName, mLockGuid));
1842
1843 //
1844 // Register with library the install function so if the library uses
1845 // UEFI driver model/driver binding protocol it can install FMP on its device handle
1846 // If library is simple lib that does not use driver binding then it should return
1847 // unsupported and this will install the FMP instance on the ImageHandle
1848 //
1849 Status = RegisterFmpInstaller (InstallFmpInstance);
1850 if (Status == EFI_UNSUPPORTED) {
1851 mFmpSingleInstance = TRUE;
1852 DEBUG ((DEBUG_INFO, "FmpDxe(%s): FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n", mImageIdName));
1853 Status = RegisterFmpUninstaller (UninstallFmpInstance);
1854 if (Status == EFI_UNSUPPORTED) {
1855 Status = InstallFmpInstance (ImageHandle);
1856 } else {
1857 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));
1858 Status = EFI_UNSUPPORTED;
1859 }
1860 } else if (EFI_ERROR (Status)) {
1861 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib registration returned %r. No FMP installed.\n", mImageIdName, Status));
1862 } else {
1863 DEBUG ((
1864 DEBUG_INFO,
1865 "FmpDxe(%s): FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n",
1866 mImageIdName
1867 ));
1868 Status = RegisterFmpUninstaller (UninstallFmpInstance);
1869 if (EFI_ERROR (Status)) {
1870 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));
1871 }
1872 }
1873
1874 return Status;
1875 }