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