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