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