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