]> git.proxmox.com Git - mirror_edk2.git/blob - FmpDevicePkg/FmpDxe/FmpDxe.c
FmpDevicePkg FmpDxe: Lock variables in entrypoint instead of callback
[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, Intel Corporation. All rights reserved.<BR>
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
11 1. Redistributions of source code must retain the above copyright notice,
12 this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright notice,
14 this list of conditions and the following disclaimer in the documentation
15 and/or other materials provided with the distribution.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 **/
29
30 #include <PiDxe.h>
31 #include <Library/DebugLib.h>
32 #include <Library/BaseLib.h>
33 #include <Library/BaseMemoryLib.h>
34 #include <Library/UefiBootServicesTableLib.h>
35 #include <Library/MemoryAllocationLib.h>
36 #include <Library/UefiLib.h>
37 #include <Library/FmpAuthenticationLib.h>
38 #include <Library/FmpDeviceLib.h>
39 #include <Library/FmpPayloadHeaderLib.h>
40 #include <Library/CapsuleUpdatePolicyLib.h>
41 #include <Protocol/FirmwareManagement.h>
42 #include <Protocol/FirmwareManagementProgress.h>
43 #include <Guid/SystemResourceTable.h>
44 #include <Guid/EventGroup.h>
45 #include "VariableSupport.h"
46
47 #define VERSION_STRING_NOT_SUPPORTED L"VERSION STRING NOT SUPPORTED"
48 #define VERSION_STRING_NOT_AVAILABLE L"VERSION STRING NOT AVAILABLE"
49
50 /**
51 Check to see if any of the keys in PcdFmpDevicePkcs7CertBufferXdr matches
52 the test key. PcdFmpDeviceTestKeySha256Digest contains the SHA256 hash of
53 the test key. For each key in PcdFmpDevicePkcs7CertBufferXdr, compute the
54 SHA256 hash and compare it to PcdFmpDeviceTestKeySha256Digest. If the
55 SHA256 hash matches or there is then error computing the SHA256 hash, then
56 set PcdTestKeyUsed to TRUE. Skip this check if PcdTestKeyUsed is already
57 TRUE or PcdFmpDeviceTestKeySha256Digest is not exactly SHA256_DIGEST_SIZE
58 bytes.
59 **/
60 VOID
61 DetectTestKey (
62 VOID
63 );
64
65 ///
66 /// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the
67 /// FILE_GUID must always be overridden in the <Defines> section to provide
68 /// the ESRT GUID value associated with the updatable firmware image. A
69 /// check is made in this module's driver entry point to verify that a
70 /// new FILE_GUID value has been defined.
71 ///
72 const EFI_GUID mDefaultModuleFileGuid = {
73 0x78ef0a56, 0x1cf0, 0x4535, { 0xb5, 0xda, 0xf6, 0xfd, 0x2f, 0x40, 0x5a, 0x11 }
74 };
75
76 EFI_FIRMWARE_IMAGE_DESCRIPTOR mDesc;
77 BOOLEAN mDescriptorPopulated = FALSE;
78 BOOLEAN mRuntimeVersionSupported = TRUE;
79 BOOLEAN mFmpInstalled = FALSE;
80
81 ///
82 /// Function pointer to progress function
83 ///
84 EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS mProgressFunc = NULL;
85 BOOLEAN mProgressSupported = FALSE;
86
87 CHAR16 *mImageIdName = NULL;
88 UINT64 mImageId = 0x1;
89 CHAR16 *mVersionName = NULL;
90
91 EFI_EVENT mFmpDeviceLockEvent;
92 //
93 // Indicates if an attempt has been made to lock a
94 // FLASH storage device by calling FmpDeviceLock().
95 // A FLASH storage device may not support being locked,
96 // so this variable is set to TRUE even if FmpDeviceLock()
97 // returns an error.
98 //
99 BOOLEAN mFmpDeviceLocked = FALSE;
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 (!mProgressSupported) {
132 return Status;
133 }
134
135 if (mProgressFunc == NULL) {
136 return Status;
137 }
138
139 //
140 // Reserve 6% - 98% for the FmpDeviceLib. Call the real progress function.
141 //
142 Status = mProgressFunc (((Completion * 92) / 100) + 6);
143
144 if (Status == EFI_UNSUPPORTED) {
145 mProgressSupported = FALSE;
146 mProgressFunc = NULL;
147 }
148
149 return Status;
150 }
151
152 /**
153 Returns a pointer to the ImageTypeId GUID value. An attempt is made to get
154 the GUID value from the FmpDeviceLib. If the FmpDeviceLib does not provide
155 a GUID value, then gEfiCallerIdGuid is returned.
156
157 @return The ImageTypeId GUID
158
159 **/
160 EFI_GUID *
161 GetImageTypeIdGuid (
162 VOID
163 )
164 {
165 EFI_STATUS Status;
166 EFI_GUID *FmpDeviceLibGuid;
167
168 FmpDeviceLibGuid = NULL;
169 Status = FmpDeviceGetImageTypeIdGuidPtr (&FmpDeviceLibGuid);
170 if (EFI_ERROR (Status)) {
171 if (Status != EFI_UNSUPPORTED) {
172 DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", Status));
173 }
174 return &gEfiCallerIdGuid;
175 }
176 if (FmpDeviceLibGuid == NULL) {
177 DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n"));
178 return &gEfiCallerIdGuid;
179 }
180 return FmpDeviceLibGuid;
181 }
182
183 /**
184 Returns a pointer to the Null-terminated Unicode ImageIdName string.
185
186 @return Null-terminated Unicode ImageIdName string.
187
188 **/
189 CHAR16 *
190 GetImageTypeNameString (
191 VOID
192 )
193 {
194 return mImageIdName;
195 }
196
197 /**
198 Lowest supported version is a combo of three parts.
199 1. Check if the device lib has a lowest supported version
200 2. Check if we have a variable for lowest supported version (this will be updated with each capsule applied)
201 3. Check Fixed at build PCD
202
203 Take the largest value
204
205 **/
206 UINT32
207 GetLowestSupportedVersion (
208 VOID
209 )
210 {
211 EFI_STATUS Status;
212 UINT32 DeviceLibLowestSupportedVersion;
213 UINT32 VariableLowestSupportedVersion;
214 UINT32 ReturnLsv;
215
216 //
217 // Get the LowestSupportedVersion.
218 //
219
220 if (!IsLowestSupportedVersionCheckRequired ()) {
221 //
222 // Any Version can pass the 0 LowestSupportedVersion check.
223 //
224 return 0;
225 }
226
227 ReturnLsv = PcdGet32 (PcdFmpDeviceBuildTimeLowestSupportedVersion);
228
229 //
230 // Check the FmpDeviceLib
231 //
232 DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
233 Status = FmpDeviceGetLowestSupportedVersion (&DeviceLibLowestSupportedVersion);
234 if (EFI_ERROR (Status)) {
235 DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
236 }
237
238 if (DeviceLibLowestSupportedVersion > ReturnLsv) {
239 ReturnLsv = DeviceLibLowestSupportedVersion;
240 }
241
242 //
243 // Check the lowest supported version UEFI variable for this device
244 //
245 VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable();
246 if (VariableLowestSupportedVersion > ReturnLsv) {
247 ReturnLsv = VariableLowestSupportedVersion;
248 }
249
250 //
251 // Return the largest value
252 //
253 return ReturnLsv;
254 }
255
256 /**
257 Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the module global
258 variable mDesc.
259
260 **/
261 VOID
262 PopulateDescriptor (
263 VOID
264 )
265 {
266 EFI_STATUS Status;
267
268 mDesc.ImageIndex = 1;
269 CopyGuid (&mDesc.ImageTypeId, GetImageTypeIdGuid());
270 mDesc.ImageId = mImageId;
271 mDesc.ImageIdName = GetImageTypeNameString();
272
273 //
274 // Get the version. Some devices don't support getting the firmware version
275 // at runtime. If FmpDeviceLib does not support returning a version, then
276 // it is stored in a UEFI variable.
277 //
278 Status = FmpDeviceGetVersion (&mDesc.Version);
279 if (Status == EFI_UNSUPPORTED) {
280 mRuntimeVersionSupported = FALSE;
281 mDesc.Version = GetVersionFromVariable();
282 } else if (EFI_ERROR (Status)) {
283 //
284 // Unexpected error. Use default version.
285 //
286 DEBUG ((DEBUG_ERROR, "FmpDxe: GetVersion() from FmpDeviceLib (%s) returned %r\n", GetImageTypeNameString(), Status));
287 mDesc.Version = DEFAULT_VERSION;
288 }
289
290 //
291 // Free the current version name. Shouldn't really happen but this populate
292 // function could be called multiple times (to refresh).
293 //
294 if (mVersionName != NULL) {
295 FreePool (mVersionName);
296 mVersionName = NULL;
297 }
298
299 //
300 // Attempt to get the version string from the FmpDeviceLib
301 //
302 Status = FmpDeviceGetVersionString (&mVersionName);
303 if (Status == EFI_UNSUPPORTED) {
304 DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() unsupported in FmpDeviceLib.\n"));
305 mVersionName = AllocateCopyPool (
306 sizeof (VERSION_STRING_NOT_SUPPORTED),
307 VERSION_STRING_NOT_SUPPORTED
308 );
309 } else if (EFI_ERROR (Status)) {
310 DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() not available in FmpDeviceLib.\n"));
311 mVersionName = AllocateCopyPool (
312 sizeof (VERSION_STRING_NOT_AVAILABLE),
313 VERSION_STRING_NOT_AVAILABLE
314 );
315 }
316
317 mDesc.VersionName = mVersionName;
318
319 mDesc.LowestSupportedImageVersion = GetLowestSupportedVersion();
320
321 //
322 // Get attributes from the FmpDeviceLib
323 //
324 FmpDeviceGetAttributes (&mDesc.AttributesSupported, &mDesc.AttributesSetting);
325
326 //
327 // Force set the updatable bits in the attributes;
328 //
329 mDesc.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
330 mDesc.AttributesSetting |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
331
332 //
333 // Force set the authentication bits in the attributes;
334 //
335 mDesc.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
336 mDesc.AttributesSetting |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
337
338 mDesc.Compatibilities = 0;
339
340 //
341 // Get the size of the firmware image from the FmpDeviceLib
342 //
343 Status = FmpDeviceGetSize (&mDesc.Size);
344 if (EFI_ERROR (Status)) {
345 mDesc.Size = 0;
346 }
347
348 mDesc.LastAttemptVersion = GetLastAttemptVersionFromVariable ();
349 mDesc.LastAttemptStatus = GetLastAttemptStatusFromVariable ();
350
351 mDescriptorPopulated = TRUE;
352 }
353
354 /**
355 Returns information about the current firmware image(s) of the device.
356
357 This function allows a copy of the current firmware image to be created and saved.
358 The saved copy could later been used, for example, in firmware image recovery or rollback.
359
360 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
361 @param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.
362 On input, this is the size of the buffer allocated by the caller.
363 On output, it is the size of the buffer returned by the firmware
364 if the buffer was large enough, or the size of the buffer needed
365 to contain the image(s) information if the buffer was too small.
366 @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)
367 information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
368 @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number
369 associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
370 @param[out] DescriptorCount A pointer to the location in which firmware returns the number of
371 descriptors or firmware images within this device.
372 @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,
373 of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
374 @param[out] PackageVersion A version number that represents all the firmware images in the device.
375 The format is vendor specific and new version must have a greater value
376 than the old version. If PackageVersion is not supported, the value is
377 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
378 is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
379 that package version update is in progress.
380 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the
381 package version name. The buffer is allocated by this function with
382 AllocatePool(), and it is the caller's responsibility to free it with a call
383 to FreePool().
384
385 @retval EFI_SUCCESS The device was successfully updated with the new image.
386 @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size
387 needed to hold the image(s) information is returned in ImageInfoSize.
388 @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.
389 @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.
390
391 **/
392 EFI_STATUS
393 EFIAPI
394 GetTheImageInfo (
395 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
396 IN OUT UINTN *ImageInfoSize,
397 IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
398 OUT UINT32 *DescriptorVersion,
399 OUT UINT8 *DescriptorCount,
400 OUT UINTN *DescriptorSize,
401 OUT UINT32 *PackageVersion,
402 OUT CHAR16 **PackageVersionName
403 )
404 {
405 EFI_STATUS Status;
406
407 Status = EFI_SUCCESS;
408
409 //
410 // Check for valid pointer
411 //
412 if (ImageInfoSize == NULL) {
413 DEBUG ((DEBUG_ERROR, "FmpDxe: GetImageInfo() - ImageInfoSize is NULL.\n"));
414 Status = EFI_INVALID_PARAMETER;
415 goto cleanup;
416 }
417
418 //
419 // Check the buffer size
420 // NOTE: Check this first so caller can get the necessary memory size it must allocate.
421 //
422 if (*ImageInfoSize < (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR))) {
423 *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
424 DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImageInfo() - ImageInfoSize is to small.\n"));
425 Status = EFI_BUFFER_TOO_SMALL;
426 goto cleanup;
427 }
428
429 //
430 // Confirm that buffer isn't null
431 //
432 if ( (ImageInfo == NULL) || (DescriptorVersion == NULL) || (DescriptorCount == NULL) || (DescriptorSize == NULL)
433 || (PackageVersion == NULL)) {
434 DEBUG ((DEBUG_ERROR, "FmpDxe: GetImageInfo() - Pointer Parameter is NULL.\n"));
435 Status = EFI_INVALID_PARAMETER;
436 goto cleanup;
437 }
438
439 //
440 // Set the size to whatever we need
441 //
442 *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
443
444
445 if (!mDescriptorPopulated) {
446 PopulateDescriptor();
447 }
448
449 //
450 // Copy the image descriptor
451 //
452 CopyMem (ImageInfo, &mDesc, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR));
453
454 *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
455 *DescriptorCount = 1;
456 *DescriptorSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
457 //
458 // means unsupported
459 //
460 *PackageVersion = 0xFFFFFFFF;
461
462 //
463 // Do not update PackageVersionName since it is not supported in this instance.
464 //
465
466 cleanup:
467
468 return Status;
469 }
470
471 /**
472 Retrieves a copy of the current firmware image of the device.
473
474 This function allows a copy of the current firmware image to be created and saved.
475 The saved copy could later been used, for example, in firmware image recovery or rollback.
476
477 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
478 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
479 The number is between 1 and DescriptorCount.
480 @param[in, out] Image Points to the buffer where the current image is copied to.
481 @param[in, out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.
482 On return, points to the length of the image, in bytes.
483
484 @retval EFI_SUCCESS The device was successfully updated with the new image.
485 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the
486 image. The current buffer size needed to hold the image is returned
487 in ImageSize.
488 @retval EFI_INVALID_PARAMETER The Image was NULL.
489 @retval EFI_NOT_FOUND The current image is not copied to the buffer.
490 @retval EFI_UNSUPPORTED The operation is not supported.
491 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
492
493 **/
494 EFI_STATUS
495 EFIAPI
496 GetTheImage (
497 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
498 IN UINT8 ImageIndex,
499 IN OUT VOID *Image,
500 IN OUT UINTN *ImageSize
501 )
502 {
503 EFI_STATUS Status;
504 UINTN Size;
505
506 Status = EFI_SUCCESS;
507
508 //
509 // Check to make sure index is 1 (only 1 image for this device)
510 //
511 if (ImageIndex != 1) {
512 DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - Image Index Invalid.\n"));
513 Status = EFI_INVALID_PARAMETER;
514 goto cleanup;
515 }
516
517 if (ImageSize == NULL) {
518 DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - ImageSize Pointer Parameter is NULL.\n"));
519 Status = EFI_INVALID_PARAMETER;
520 goto cleanup;
521 }
522
523 //
524 // Check the buffer size
525 //
526 Status = FmpDeviceGetSize (&Size);
527 if (EFI_ERROR (Status)) {
528 Size = 0;
529 }
530 if (*ImageSize < Size) {
531 *ImageSize = Size;
532 DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImage() - ImageSize is to small.\n"));
533 Status = EFI_BUFFER_TOO_SMALL;
534 goto cleanup;
535 }
536
537 if (Image == NULL) {
538 DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - Image Pointer Parameter is NULL.\n"));
539 Status = EFI_INVALID_PARAMETER;
540 goto cleanup;
541 }
542
543 Status = FmpDeviceGetImage (Image, ImageSize);
544 cleanup:
545
546 return Status;
547 }
548
549 /**
550 Helper function to safely retrieve the FMP header from
551 within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
552
553 @param[in] Image Pointer to the image.
554 @param[in] ImageSize Size of the image.
555 @param[out] PayloadSize
556
557 @retval !NULL Valid pointer to the header.
558 @retval NULL Structure is bad and pointer cannot be found.
559
560 **/
561 VOID *
562 GetFmpHeader (
563 IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
564 IN CONST UINTN ImageSize,
565 OUT UINTN *PayloadSize
566 )
567 {
568 //
569 // Check to make sure that operation can be safely performed.
570 //
571 if (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) < (UINTN)Image || \
572 ((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) >= (UINTN)Image + ImageSize) {
573 //
574 // Pointer overflow. Invalid image.
575 //
576 return NULL;
577 }
578
579 *PayloadSize = ImageSize - (sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength);
580 return (VOID *)((UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength);
581 }
582
583 /**
584 Helper function to safely calculate the size of all headers
585 within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
586
587 @param[in] Image Pointer to the image.
588 @param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.
589
590 @retval UINT32>0 Valid size of all the headers.
591 @retval 0 Structure is bad and size cannot be found.
592
593 **/
594 UINT32
595 GetAllHeaderSize (
596 IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
597 IN UINT32 AdditionalHeaderSize
598 )
599 {
600 UINT32 CalculatedSize;
601
602 CalculatedSize = sizeof (Image->MonotonicCount) +
603 AdditionalHeaderSize +
604 Image->AuthInfo.Hdr.dwLength;
605
606 //
607 // Check to make sure that operation can be safely performed.
608 //
609 if (CalculatedSize < sizeof (Image->MonotonicCount) ||
610 CalculatedSize < AdditionalHeaderSize ||
611 CalculatedSize < Image->AuthInfo.Hdr.dwLength ) {
612 //
613 // Integer overflow. Invalid image.
614 //
615 return 0;
616 }
617
618 return CalculatedSize;
619 }
620
621 /**
622 Checks if the firmware image is valid for the device.
623
624 This function allows firmware update application to validate the firmware image without
625 invoking the SetImage() first.
626
627 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
628 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
629 The number is between 1 and DescriptorCount.
630 @param[in] Image Points to the new image.
631 @param[in] ImageSize Size of the new image in bytes.
632 @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
633 if available, additional information if the image is invalid.
634
635 @retval EFI_SUCCESS The image was successfully checked.
636 @retval EFI_ABORTED The operation is aborted.
637 @retval EFI_INVALID_PARAMETER The Image was NULL.
638 @retval EFI_UNSUPPORTED The operation is not supported.
639 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
640
641 **/
642 EFI_STATUS
643 EFIAPI
644 CheckTheImage (
645 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
646 IN UINT8 ImageIndex,
647 IN CONST VOID *Image,
648 IN UINTN ImageSize,
649 OUT UINT32 *ImageUpdatable
650 )
651 {
652 EFI_STATUS Status;
653 UINTN RawSize;
654 VOID *FmpPayloadHeader;
655 UINTN FmpPayloadSize;
656 UINT32 Version;
657 UINT32 FmpHeaderSize;
658 UINTN AllHeaderSize;
659 UINT32 Index;
660 VOID *PublicKeyData;
661 UINTN PublicKeyDataLength;
662 UINT8 *PublicKeyDataXdr;
663 UINT8 *PublicKeyDataXdrEnd;
664
665 Status = EFI_SUCCESS;
666 RawSize = 0;
667 FmpPayloadHeader = NULL;
668 FmpPayloadSize = 0;
669 Version = 0;
670 FmpHeaderSize = 0;
671 AllHeaderSize = 0;
672
673 //
674 // make sure the descriptor has already been loaded
675 //
676 if (!mDescriptorPopulated) {
677 PopulateDescriptor();
678 }
679
680 if (ImageUpdatable == NULL) {
681 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n"));
682 Status = EFI_INVALID_PARAMETER;
683 goto cleanup;
684 }
685
686 //
687 //Set to valid and then if any tests fail it will update this flag.
688 //
689 *ImageUpdatable = IMAGE_UPDATABLE_VALID;
690
691 if (Image == NULL) {
692 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - Image Pointer Parameter is NULL.\n"));
693 //
694 // not sure if this is needed
695 //
696 *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
697 return EFI_INVALID_PARAMETER;
698 }
699
700 PublicKeyDataXdr = PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr);
701 PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr);
702
703 if (PublicKeyDataXdr == NULL || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {
704 DEBUG ((DEBUG_ERROR, "FmpDxe: Invalid certificate, skipping it.\n"));
705 Status = EFI_ABORTED;
706 } else {
707 //
708 // Try each key from PcdFmpDevicePkcs7CertBufferXdr
709 //
710 for (Index = 1; PublicKeyDataXdr < PublicKeyDataXdrEnd; Index++) {
711 Index++;
712 DEBUG (
713 (DEBUG_INFO,
714 "FmpDxe: Certificate #%d [%p..%p].\n",
715 Index,
716 PublicKeyDataXdr,
717 PublicKeyDataXdrEnd
718 )
719 );
720
721 if ((PublicKeyDataXdr + sizeof (UINT32)) > PublicKeyDataXdrEnd) {
722 //
723 // Key data extends beyond end of PCD
724 //
725 DEBUG ((DEBUG_ERROR, "FmpDxe: Certificate size extends beyond end of PCD, skipping it.\n"));
726 Status = EFI_ABORTED;
727 break;
728 }
729 //
730 // Read key length stored in big-endian format
731 //
732 PublicKeyDataLength = SwapBytes32 (*(UINT32 *)(PublicKeyDataXdr));
733 //
734 // Point to the start of the key data
735 //
736 PublicKeyDataXdr += sizeof (UINT32);
737 if (PublicKeyDataXdr + PublicKeyDataLength > PublicKeyDataXdrEnd) {
738 //
739 // Key data extends beyond end of PCD
740 //
741 DEBUG ((DEBUG_ERROR, "FmpDxe: Certificate extends beyond end of PCD, skipping it.\n"));
742 Status = EFI_ABORTED;
743 break;
744 }
745 PublicKeyData = PublicKeyDataXdr;
746 Status = AuthenticateFmpImage (
747 (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image,
748 ImageSize,
749 PublicKeyData,
750 PublicKeyDataLength
751 );
752 if (!EFI_ERROR (Status)) {
753 break;
754 }
755 PublicKeyDataXdr += PublicKeyDataLength;
756 PublicKeyDataXdr = (UINT8 *)ALIGN_POINTER (PublicKeyDataXdr, sizeof (UINT32));
757 }
758 }
759
760 if (EFI_ERROR (Status)) {
761 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - Authentication Failed %r.\n", Status));
762 goto cleanup;
763 }
764
765 //
766 // Check to make sure index is 1
767 //
768 if (ImageIndex != 1) {
769 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - Image Index Invalid.\n"));
770 *ImageUpdatable = IMAGE_UPDATABLE_INVALID_TYPE;
771 Status = EFI_SUCCESS;
772 goto cleanup;
773 }
774
775
776 //
777 // Check the FmpPayloadHeader
778 //
779 FmpPayloadHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize );
780 if (FmpPayloadHeader == NULL) {
781 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpHeader failed.\n"));
782 Status = EFI_ABORTED;
783 goto cleanup;
784 }
785 Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
786 if (EFI_ERROR (Status)) {
787 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", Status));
788 *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
789 Status = EFI_SUCCESS;
790 goto cleanup;
791 }
792
793 //
794 // Check the lowest supported version
795 //
796 if (Version < mDesc.LowestSupportedImageVersion) {
797 DEBUG (
798 (DEBUG_ERROR,
799 "FmpDxe: CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",
800 Version, mDesc.LowestSupportedImageVersion)
801 );
802 *ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;
803 Status = EFI_SUCCESS;
804 goto cleanup;
805 }
806
807 //
808 // Get the FmpHeaderSize so we can determine the real payload size
809 //
810 Status = GetFmpPayloadHeaderSize (FmpPayloadHeader, FmpPayloadSize, &FmpHeaderSize);
811 if (EFI_ERROR (Status)) {
812 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));
813 *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
814 Status = EFI_SUCCESS;
815 goto cleanup;
816 }
817
818 //
819 // Call FmpDevice Lib Check Image on the
820 // Raw payload. So all headers need stripped off
821 //
822 AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize );
823 if (AllHeaderSize == 0) {
824 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetAllHeaderSize failed.\n"));
825 Status = EFI_ABORTED;
826 goto cleanup;
827 }
828 RawSize = ImageSize - AllHeaderSize;
829
830 //
831 // FmpDeviceLib CheckImage function to do any specific checks
832 //
833 Status = FmpDeviceCheckImage ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdatable);
834 if (EFI_ERROR (Status)) {
835 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", Status));
836 }
837
838 cleanup:
839 return Status;
840 }
841
842 /**
843 Updates the firmware image of the device.
844
845 This function updates the hardware with the new firmware image.
846 This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
847 If the firmware image is updatable, the function should perform the following minimal validations
848 before proceeding to do the firmware image update.
849 - Validate the image authentication if image has attribute
850 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
851 EFI_SECURITY_VIOLATION if the validation fails.
852 - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
853 the image is unsupported. The function can optionally provide more detailed information on
854 why the image is not a supported image.
855 - Validate the data from VendorCode if not null. Image validation must be performed before
856 VendorCode data validation. VendorCode data is ignored or considered invalid if image
857 validation failed. The function returns EFI_ABORTED if the data is invalid.
858
859 VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
860 the caller did not specify the policy or use the default policy. As an example, vendor can implement
861 a policy to allow an option to force a firmware image update when the abort reason is due to the new
862 firmware image version is older than the current firmware image version or bad image checksum.
863 Sensitive operations such as those wiping the entire firmware image and render the device to be
864 non-functional should be encoded in the image itself rather than passed with the VendorCode.
865 AbortReason enables vendor to have the option to provide a more detailed description of the abort
866 reason to the caller.
867
868 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
869 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
870 The number is between 1 and DescriptorCount.
871 @param[in] Image Points to the new image.
872 @param[in] ImageSize Size of the new image in bytes.
873 @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
874 Null indicates the caller did not specify the policy or use the default policy.
875 @param[in] Progress A function used by the driver to report the progress of the firmware update.
876 @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
877 details for the aborted operation. The buffer is allocated by this function
878 with AllocatePool(), and it is the caller's responsibility to free it with a
879 call to FreePool().
880
881 @retval EFI_SUCCESS The device was successfully updated with the new image.
882 @retval EFI_ABORTED The operation is aborted.
883 @retval EFI_INVALID_PARAMETER The Image was NULL.
884 @retval EFI_UNSUPPORTED The operation is not supported.
885 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
886
887 **/
888 EFI_STATUS
889 EFIAPI
890 SetTheImage (
891 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
892 IN UINT8 ImageIndex,
893 IN CONST VOID *Image,
894 IN UINTN ImageSize,
895 IN CONST VOID *VendorCode,
896 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,
897 OUT CHAR16 **AbortReason
898 )
899 {
900 EFI_STATUS Status;
901 UINT32 Updateable;
902 BOOLEAN BooleanValue;
903 UINT32 FmpHeaderSize;
904 VOID *FmpHeader;
905 UINTN FmpPayloadSize;
906 UINT32 AllHeaderSize;
907 UINT32 IncommingFwVersion;
908 UINT32 LastAttemptStatus;
909 UINT32 Version;
910 UINT32 LowestSupportedVersion;
911
912 Status = EFI_SUCCESS;
913 Updateable = 0;
914 BooleanValue = FALSE;
915 FmpHeaderSize = 0;
916 FmpHeader = NULL;
917 FmpPayloadSize = 0;
918 AllHeaderSize = 0;
919 IncommingFwVersion = 0;
920 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
921
922
923 SetLastAttemptVersionInVariable (IncommingFwVersion); //set to 0 to clear any previous results.
924
925 //
926 // if we have locked the device, then skip the set operation.
927 // it should be blocked by hardware too but we can catch here even faster
928 //
929 if (mFmpDeviceLocked) {
930 DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Device is already locked. Can't update.\n"));
931 Status = EFI_UNSUPPORTED;
932 goto cleanup;
933 }
934
935 //
936 // Call check image to verify the image
937 //
938 Status = CheckTheImage (This, ImageIndex, Image, ImageSize, &Updateable);
939 if (EFI_ERROR (Status)) {
940 DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Check The Image failed with %r.\n", Status));
941 if (Status == EFI_SECURITY_VIOLATION) {
942 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
943 }
944 goto cleanup;
945 }
946
947 //
948 // No functional error in CheckTheImage. Attempt to get the Version to
949 // support better error reporting.
950 //
951 FmpHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize );
952 if (FmpHeader == NULL) {
953 DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetFmpHeader failed.\n"));
954 Status = EFI_ABORTED;
955 goto cleanup;
956 }
957 Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncommingFwVersion);
958 if (!EFI_ERROR (Status)) {
959 //
960 // Set to actual value
961 //
962 SetLastAttemptVersionInVariable (IncommingFwVersion);
963 }
964
965
966 if (Updateable != IMAGE_UPDATABLE_VALID) {
967 DEBUG (
968 (DEBUG_ERROR,
969 "FmpDxed: SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",
970 Updateable)
971 );
972 Status = EFI_ABORTED;
973 goto cleanup;
974 }
975
976 if (Progress == NULL) {
977 DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Invalid progress callback\n"));
978 Status = EFI_INVALID_PARAMETER;
979 goto cleanup;
980 }
981
982 mProgressFunc = Progress;
983 mProgressSupported = TRUE;
984
985 //
986 // Checking the image is at least 1%
987 //
988 Status = Progress (1);
989 if (EFI_ERROR (Status)) {
990 DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Progress Callback failed with Status %r.\n", Status));
991 }
992
993 //
994 //Check System Power
995 //
996 Status = CheckSystemPower (&BooleanValue);
997 if (EFI_ERROR (Status)) {
998 DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemPower - API call failed %r.\n", Status));
999 goto cleanup;
1000 }
1001 if (!BooleanValue) {
1002 Status = EFI_ABORTED;
1003 DEBUG (
1004 (DEBUG_ERROR,
1005 "FmpDxe: SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n")
1006 );
1007 LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT;
1008 goto cleanup;
1009 }
1010
1011 Progress (2);
1012
1013 //
1014 //Check System Thermal
1015 //
1016 Status = CheckSystemThermal (&BooleanValue);
1017 if (EFI_ERROR (Status)) {
1018 DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemThermal - API call failed %r.\n", Status));
1019 goto cleanup;
1020 }
1021 if (!BooleanValue) {
1022 Status = EFI_ABORTED;
1023 DEBUG (
1024 (DEBUG_ERROR,
1025 "FmpDxe: SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n")
1026 );
1027 goto cleanup;
1028 }
1029
1030 Progress (3);
1031
1032 //
1033 //Check System Environment
1034 //
1035 Status = CheckSystemEnvironment (&BooleanValue);
1036 if (EFI_ERROR (Status)) {
1037 DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", Status));
1038 goto cleanup;
1039 }
1040 if (!BooleanValue) {
1041 Status = EFI_ABORTED;
1042 DEBUG (
1043 (DEBUG_ERROR,
1044 "FmpDxe: SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n")
1045 );
1046 goto cleanup;
1047 }
1048
1049 Progress (4);
1050
1051 //
1052 // Save LastAttemptStatus as error so that if SetImage never returns the error
1053 // state is recorded.
1054 //
1055 SetLastAttemptStatusInVariable (LastAttemptStatus);
1056
1057 //
1058 // Strip off all the headers so the device can process its firmware
1059 //
1060 Status = GetFmpPayloadHeaderSize (FmpHeader, FmpPayloadSize, &FmpHeaderSize);
1061 if (EFI_ERROR (Status)) {
1062 DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));
1063 goto cleanup;
1064 }
1065
1066 AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize );
1067 if (AllHeaderSize == 0) {
1068 DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetAllHeaderSize failed.\n"));
1069 Status = EFI_ABORTED;
1070 goto cleanup;
1071 }
1072
1073 //
1074 // Indicate that control is handed off to FmpDeviceLib
1075 //
1076 Progress (5);
1077
1078 //
1079 //Copy the requested image to the firmware using the FmpDeviceLib
1080 //
1081 Status = FmpDeviceSetImage (
1082 (((UINT8 *)Image) + AllHeaderSize),
1083 ImageSize - AllHeaderSize,
1084 VendorCode,
1085 FmpDxeProgress,
1086 IncommingFwVersion,
1087 AbortReason
1088 );
1089 if (EFI_ERROR (Status)) {
1090 DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", Status));
1091 goto cleanup;
1092 }
1093
1094
1095 //
1096 // Finished the update without error
1097 // Indicate that control has been returned from FmpDeviceLib
1098 //
1099 Progress (99);
1100
1101 //
1102 // Update the version stored in variable
1103 //
1104 if (!mRuntimeVersionSupported) {
1105 Version = DEFAULT_VERSION;
1106 GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);
1107 SetVersionInVariable (Version);
1108 }
1109
1110 //
1111 // Update lowest supported variable
1112 //
1113 {
1114 LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
1115 GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);
1116 SetLowestSupportedVersionInVariable (LowestSupportedVersion);
1117 }
1118
1119 LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
1120
1121 cleanup:
1122 mProgressFunc = NULL;
1123 mProgressSupported = FALSE;
1124 SetLastAttemptStatusInVariable (LastAttemptStatus);
1125
1126 if (Progress != NULL) {
1127 //
1128 // Set progress to 100 after everything is done including recording Status.
1129 //
1130 Progress (100);
1131 }
1132
1133 //
1134 // Need repopulate after SetImage is called to
1135 // update LastAttemptVersion and LastAttemptStatus.
1136 //
1137 mDescriptorPopulated = FALSE;
1138
1139 return Status;
1140 }
1141
1142 /**
1143 Returns information about the firmware package.
1144
1145 This function returns package information.
1146
1147 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1148 @param[out] PackageVersion A version number that represents all the firmware images in the device.
1149 The format is vendor specific and new version must have a greater value
1150 than the old version. If PackageVersion is not supported, the value is
1151 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
1152 comparison is to be performed using PackageVersionName. A value of
1153 0xFFFFFFFD indicates that package version update is in progress.
1154 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing
1155 the package version name. The buffer is allocated by this function with
1156 AllocatePool(), and it is the caller's responsibility to free it with a
1157 call to FreePool().
1158 @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
1159 package version name. A value of 0 indicates the device does not support
1160 update of package version name. Length is the number of Unicode characters,
1161 including the terminating null character.
1162 @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute
1163 Definitions' for possible returned values of this parameter. A value of 1
1164 indicates the attribute is supported and the current setting value is
1165 indicated in AttributesSetting. A value of 0 indicates the attribute is not
1166 supported and the current setting value in AttributesSetting is meaningless.
1167 @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned
1168 values of this parameter
1169
1170 @retval EFI_SUCCESS The package information was successfully returned.
1171 @retval EFI_UNSUPPORTED The operation is not supported.
1172
1173 **/
1174 EFI_STATUS
1175 EFIAPI
1176 GetPackageInfo (
1177 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
1178 OUT UINT32 *PackageVersion,
1179 OUT CHAR16 **PackageVersionName,
1180 OUT UINT32 *PackageVersionNameMaxLen,
1181 OUT UINT64 *AttributesSupported,
1182 OUT UINT64 *AttributesSetting
1183 )
1184 {
1185 return EFI_UNSUPPORTED;
1186 }
1187
1188 /**
1189 Updates information about the firmware package.
1190
1191 This function updates package information.
1192 This function returns EFI_UNSUPPORTED if the package information is not updatable.
1193 VendorCode enables vendor to implement vendor-specific package information update policy.
1194 Null if the caller did not specify this policy or use the default policy.
1195
1196 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1197 @param[in] Image Points to the authentication image.
1198 Null if authentication is not required.
1199 @param[in] ImageSize Size of the authentication image in bytes.
1200 0 if authentication is not required.
1201 @param[in] VendorCode This enables vendor to implement vendor-specific firmware
1202 image update policy.
1203 Null indicates the caller did not specify this policy or use
1204 the default policy.
1205 @param[in] PackageVersion The new package version.
1206 @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing
1207 the package version name.
1208 The string length is equal to or less than the value returned in
1209 PackageVersionNameMaxLen.
1210
1211 @retval EFI_SUCCESS The device was successfully updated with the new package
1212 information.
1213 @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
1214 returned in PackageVersionNameMaxLen.
1215 @retval EFI_UNSUPPORTED The operation is not supported.
1216 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
1217
1218 **/
1219 EFI_STATUS
1220 EFIAPI
1221 SetPackageInfo (
1222 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
1223 IN CONST VOID *Image,
1224 IN UINTN ImageSize,
1225 IN CONST VOID *VendorCode,
1226 IN UINT32 PackageVersion,
1227 IN CONST CHAR16 *PackageVersionName
1228 )
1229 {
1230 return EFI_UNSUPPORTED;
1231 }
1232
1233 /**
1234 Event notification function that is invoked when the event GUID specified by
1235 PcdFmpDeviceLockEventGuid is signaled.
1236
1237 @param[in] Event Event whose notification function is being invoked.
1238 @param[in] Context The pointer to the notification function's context,
1239 which is implementation-dependent.
1240 **/
1241 VOID
1242 EFIAPI
1243 FmpDxeLockEventNotify (
1244 IN EFI_EVENT Event,
1245 IN VOID *Context
1246 )
1247 {
1248 EFI_STATUS Status;
1249
1250 if (!mFmpDeviceLocked) {
1251 //
1252 // Lock the firmware device
1253 //
1254 Status = FmpDeviceLock();
1255 if (EFI_ERROR (Status)) {
1256 if (Status != EFI_UNSUPPORTED) {
1257 DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status));
1258 } else {
1259 DEBUG ((DEBUG_WARN, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status));
1260 }
1261 }
1262 mFmpDeviceLocked = TRUE;
1263 }
1264 }
1265
1266 /**
1267 Function to install FMP instance.
1268
1269 @param[in] Handle The device handle to install a FMP instance on.
1270
1271 @retval EFI_SUCCESS FMP Installed
1272 @retval EFI_INVALID_PARAMETER Handle was invalid
1273 @retval other Error installing FMP
1274
1275 **/
1276 EFI_STATUS
1277 EFIAPI
1278 InstallFmpInstance (
1279 IN EFI_HANDLE Handle
1280 )
1281 {
1282 EFI_STATUS Status;
1283 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
1284 EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *FmpProgress;
1285
1286 Status = EFI_SUCCESS;
1287 Fmp = NULL;
1288 FmpProgress = NULL;
1289
1290 //
1291 // Only allow a single FMP Protocol instance to be installed
1292 //
1293 if (mFmpInstalled) {
1294 return EFI_ALREADY_STARTED;
1295 }
1296
1297 //
1298 // Allocate FMP Protocol instance
1299 //
1300 Fmp = AllocateZeroPool (sizeof (EFI_FIRMWARE_MANAGEMENT_PROTOCOL));
1301 if (Fmp == NULL) {
1302 DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for FMP Protocol instance.\n"));
1303 Status = EFI_OUT_OF_RESOURCES;
1304 goto cleanup;
1305 }
1306
1307 //
1308 // Allocate FMP Progress Protocol instance
1309 //
1310 FmpProgress = AllocateZeroPool (sizeof (EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL));
1311 if (FmpProgress == NULL) {
1312 DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for FMP Progress Protocol instance.\n"));
1313 Status = EFI_OUT_OF_RESOURCES;
1314 FreePool (Fmp);
1315 goto cleanup;
1316 }
1317
1318 //
1319 // Set up FMP Protocol function pointers
1320 //
1321 Fmp->GetImageInfo = GetTheImageInfo;
1322 Fmp->GetImage = GetTheImage;
1323 Fmp->SetImage = SetTheImage;
1324 Fmp->CheckImage = CheckTheImage;
1325 Fmp->GetPackageInfo = GetPackageInfo;
1326 Fmp->SetPackageInfo = SetPackageInfo;
1327
1328 //
1329 // Fill in FMP Progress Protocol fields for Version 1
1330 //
1331 FmpProgress->Version = 1;
1332 FmpProgress->ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);
1333 FmpProgress->WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);
1334
1335 //
1336 // Install FMP Protocol and FMP Progress Protocol
1337 //
1338 Status = gBS->InstallMultipleProtocolInterfaces (
1339 &Handle,
1340 &gEfiFirmwareManagementProtocolGuid,
1341 Fmp,
1342 &gEdkiiFirmwareManagementProgressProtocolGuid,
1343 FmpProgress,
1344 NULL
1345 );
1346
1347 if (EFI_ERROR (Status)) {
1348 DEBUG ((DEBUG_ERROR, "FmpDxe: FMP Protocol install error. Status = %r.\n", Status));
1349 FreePool (Fmp);
1350 goto cleanup;
1351 }
1352
1353 DEBUG ((DEBUG_INFO, "FmpDxe: FMP Protocol Installed!\n"));
1354 mFmpInstalled = TRUE;
1355
1356 cleanup:
1357
1358 return Status;
1359 }
1360
1361 /**
1362 Main entry for this driver/library.
1363
1364 @param[in] ImageHandle Image handle this driver.
1365 @param[in] SystemTable Pointer to SystemTable.
1366
1367 **/
1368 EFI_STATUS
1369 EFIAPI
1370 FmpDxeEntryPoint (
1371 IN EFI_HANDLE ImageHandle,
1372 IN EFI_SYSTEM_TABLE *SystemTable
1373 )
1374 {
1375 EFI_STATUS Status;
1376 EFI_GUID *LockGuid;
1377
1378 //
1379 // Verify that a new FILE_GUID value has been provided in the <Defines>
1380 // section of this module. The FILE_GUID is the ESRT GUID that must be
1381 // unique for each updatable firmware image.
1382 //
1383 if (CompareGuid (&mDefaultModuleFileGuid, &gEfiCallerIdGuid)) {
1384 DEBUG ((DEBUG_ERROR, "FmpDxe: Use of default FILE_GUID detected. FILE_GUID must be set to a unique value.\n"));
1385 ASSERT (FALSE);
1386 return EFI_UNSUPPORTED;
1387 }
1388
1389 //
1390 // Get the ImageIdName value for the EFI_FIRMWARE_IMAGE_DESCRIPTOR from a PCD.
1391 //
1392 mImageIdName = (CHAR16 *) PcdGetPtr (PcdFmpDeviceImageIdName);
1393 if (PcdGetSize (PcdFmpDeviceImageIdName) <= 2 || mImageIdName[0] == 0) {
1394 //
1395 // PcdFmpDeviceImageIdName must be set to a non-empty Unicode string
1396 //
1397 DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib PcdFmpDeviceImageIdName is an empty string.\n"));
1398 ASSERT (FALSE);
1399 }
1400
1401 //
1402 // Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.
1403 //
1404 DetectTestKey ();
1405
1406 if (IsLockFmpDeviceAtLockEventGuidRequired ()) {
1407 //
1408 // Lock all UEFI Variables used by this module.
1409 //
1410 Status = LockAllFmpVariables ();
1411 if (EFI_ERROR (Status)) {
1412 DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variables. Status = %r.\n", Status));
1413 } else {
1414 DEBUG ((DEBUG_INFO, "FmpDxe: All variables locked\n"));
1415 }
1416
1417 //
1418 // Register notify function to lock the FMP device.
1419 // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.
1420 // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then
1421 // gEfiEndOfDxeEventGroupGuid is used.
1422 //
1423 LockGuid = &gEfiEndOfDxeEventGroupGuid;
1424 if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {
1425 LockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);
1426 }
1427 DEBUG ((DEBUG_INFO, "FmpDxe: Lock GUID: %g\n", LockGuid));
1428
1429 Status = gBS->CreateEventEx (
1430 EVT_NOTIFY_SIGNAL,
1431 TPL_CALLBACK,
1432 FmpDxeLockEventNotify,
1433 NULL,
1434 LockGuid,
1435 &mFmpDeviceLockEvent
1436 );
1437 if (EFI_ERROR (Status)) {
1438 DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to register notification. Status = %r\n", Status));
1439 }
1440 ASSERT_EFI_ERROR (Status);
1441 } else {
1442 DEBUG ((DEBUG_VERBOSE, "FmpDxe: Not registering notification to call FmpDeviceLock() because mfg mode\n"));
1443 }
1444
1445 //
1446 // Register with library the install function so if the library uses
1447 // UEFI driver model/driver binding protocol it can install FMP on its device handle
1448 // If library is simple lib that does not use driver binding then it should return
1449 // unsupported and this will install the FMP instance on the ImageHandle
1450 //
1451 Status = RegisterFmpInstaller (InstallFmpInstance);
1452 if (Status == EFI_UNSUPPORTED) {
1453 DEBUG ((DEBUG_INFO, "FmpDxe: FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n"));
1454 Status = InstallFmpInstance (ImageHandle);
1455 } else if (EFI_ERROR (Status)) {
1456 DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib registration returned %r. No FMP installed.\n", Status));
1457 } else {
1458 DEBUG ((
1459 DEBUG_INFO,
1460 "FmpDxe: FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n"
1461 ));
1462 }
1463
1464 return Status;
1465 }