]> git.proxmox.com Git - mirror_edk2.git/blob - FmpDevicePkg/FmpDxe/FmpDxe.c
FmpDevicePkg FmpDxe: Return UNSUPPORTED if device has been locked
[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 Status = FmpDeviceGetLowestSupportedVersion (&DeviceLibLowestSupportedVersion);
233 if (EFI_ERROR (Status)) {
234 DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
235 }
236
237 if (DeviceLibLowestSupportedVersion > ReturnLsv) {
238 ReturnLsv = DeviceLibLowestSupportedVersion;
239 }
240
241 //
242 // Check the lowest supported version UEFI variable for this device
243 //
244 VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable();
245 if (VariableLowestSupportedVersion > ReturnLsv) {
246 ReturnLsv = VariableLowestSupportedVersion;
247 }
248
249 //
250 // Return the largest value
251 //
252 return ReturnLsv;
253 }
254
255 /**
256 Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the module global
257 variable mDesc.
258
259 **/
260 VOID
261 PopulateDescriptor (
262 VOID
263 )
264 {
265 EFI_STATUS Status;
266
267 mDesc.ImageIndex = 1;
268 CopyGuid (&mDesc.ImageTypeId, GetImageTypeIdGuid());
269 mDesc.ImageId = mImageId;
270 mDesc.ImageIdName = GetImageTypeNameString();
271
272 //
273 // Get the version. Some devices don't support getting the firmware version
274 // at runtime. If FmpDeviceLib does not support returning a version, then
275 // it is stored in a UEFI variable.
276 //
277 Status = FmpDeviceGetVersion (&mDesc.Version);
278 if (Status == EFI_UNSUPPORTED) {
279 mRuntimeVersionSupported = FALSE;
280 mDesc.Version = GetVersionFromVariable();
281 } else if (EFI_ERROR (Status)) {
282 //
283 // Unexpected error. Use default version.
284 //
285 DEBUG ((DEBUG_ERROR, "FmpDxe: GetVersion() from FmpDeviceLib (%s) returned %r\n", GetImageTypeNameString(), Status));
286 mDesc.Version = DEFAULT_VERSION;
287 }
288
289 //
290 // Free the current version name. Shouldn't really happen but this populate
291 // function could be called multiple times (to refresh).
292 //
293 if (mVersionName != NULL) {
294 FreePool (mVersionName);
295 mVersionName = NULL;
296 }
297
298 //
299 // Attempt to get the version string from the FmpDeviceLib
300 //
301 Status = FmpDeviceGetVersionString (&mVersionName);
302 if (Status == EFI_UNSUPPORTED) {
303 DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() unsupported in FmpDeviceLib.\n"));
304 mVersionName = AllocateCopyPool (
305 sizeof (VERSION_STRING_NOT_SUPPORTED),
306 VERSION_STRING_NOT_SUPPORTED
307 );
308 } else if (EFI_ERROR (Status)) {
309 DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() not available in FmpDeviceLib.\n"));
310 mVersionName = AllocateCopyPool (
311 sizeof (VERSION_STRING_NOT_AVAILABLE),
312 VERSION_STRING_NOT_AVAILABLE
313 );
314 }
315
316 mDesc.VersionName = mVersionName;
317
318 mDesc.LowestSupportedImageVersion = GetLowestSupportedVersion();
319
320 //
321 // Get attributes from the FmpDeviceLib
322 //
323 FmpDeviceGetAttributes (&mDesc.AttributesSupported, &mDesc.AttributesSetting);
324
325 //
326 // Force set the updatable bits in the attributes;
327 //
328 mDesc.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
329 mDesc.AttributesSetting |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
330
331 //
332 // Force set the authentication bits in the attributes;
333 //
334 mDesc.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
335 mDesc.AttributesSetting |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
336
337 mDesc.Compatibilities = 0;
338
339 //
340 // Get the size of the firmware image from the FmpDeviceLib
341 //
342 Status = FmpDeviceGetSize (&mDesc.Size);
343 if (EFI_ERROR (Status)) {
344 mDesc.Size = 0;
345 }
346
347 mDesc.LastAttemptVersion = GetLastAttemptVersionFromVariable ();
348 mDesc.LastAttemptStatus = GetLastAttemptStatusFromVariable ();
349
350 mDescriptorPopulated = TRUE;
351 }
352
353 /**
354 Returns information about the current firmware image(s) of the device.
355
356 This function allows a copy of the current firmware image to be created and saved.
357 The saved copy could later been used, for example, in firmware image recovery or rollback.
358
359 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
360 @param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.
361 On input, this is the size of the buffer allocated by the caller.
362 On output, it is the size of the buffer returned by the firmware
363 if the buffer was large enough, or the size of the buffer needed
364 to contain the image(s) information if the buffer was too small.
365 @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)
366 information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
367 @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number
368 associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
369 @param[out] DescriptorCount A pointer to the location in which firmware returns the number of
370 descriptors or firmware images within this device.
371 @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,
372 of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
373 @param[out] PackageVersion A version number that represents all the firmware images in the device.
374 The format is vendor specific and new version must have a greater value
375 than the old version. If PackageVersion is not supported, the value is
376 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
377 is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
378 that package version update is in progress.
379 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the
380 package version name. The buffer is allocated by this function with
381 AllocatePool(), and it is the caller's responsibility to free it with a call
382 to FreePool().
383
384 @retval EFI_SUCCESS The device was successfully updated with the new image.
385 @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size
386 needed to hold the image(s) information is returned in ImageInfoSize.
387 @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.
388 @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.
389
390 **/
391 EFI_STATUS
392 EFIAPI
393 GetTheImageInfo (
394 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
395 IN OUT UINTN *ImageInfoSize,
396 IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
397 OUT UINT32 *DescriptorVersion,
398 OUT UINT8 *DescriptorCount,
399 OUT UINTN *DescriptorSize,
400 OUT UINT32 *PackageVersion,
401 OUT CHAR16 **PackageVersionName
402 )
403 {
404 EFI_STATUS Status;
405
406 Status = EFI_SUCCESS;
407
408 //
409 // Check for valid pointer
410 //
411 if (ImageInfoSize == NULL) {
412 DEBUG ((DEBUG_ERROR, "FmpDxe: GetImageInfo() - ImageInfoSize is NULL.\n"));
413 Status = EFI_INVALID_PARAMETER;
414 goto cleanup;
415 }
416
417 //
418 // Check the buffer size
419 // NOTE: Check this first so caller can get the necessary memory size it must allocate.
420 //
421 if (*ImageInfoSize < (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR))) {
422 *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
423 DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImageInfo() - ImageInfoSize is to small.\n"));
424 Status = EFI_BUFFER_TOO_SMALL;
425 goto cleanup;
426 }
427
428 //
429 // Confirm that buffer isn't null
430 //
431 if ( (ImageInfo == NULL) || (DescriptorVersion == NULL) || (DescriptorCount == NULL) || (DescriptorSize == NULL)
432 || (PackageVersion == NULL)) {
433 DEBUG ((DEBUG_ERROR, "FmpDxe: GetImageInfo() - Pointer Parameter is NULL.\n"));
434 Status = EFI_INVALID_PARAMETER;
435 goto cleanup;
436 }
437
438 //
439 // Set the size to whatever we need
440 //
441 *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
442
443
444 if (!mDescriptorPopulated) {
445 PopulateDescriptor();
446 }
447
448 //
449 // Copy the image descriptor
450 //
451 CopyMem (ImageInfo, &mDesc, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR));
452
453 *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
454 *DescriptorCount = 1;
455 *DescriptorSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
456 //
457 // means unsupported
458 //
459 *PackageVersion = 0xFFFFFFFF;
460
461 //
462 // Do not update PackageVersionName since it is not supported in this instance.
463 //
464
465 cleanup:
466
467 return Status;
468 }
469
470 /**
471 Retrieves a copy of the current firmware image of the device.
472
473 This function allows a copy of the current firmware image to be created and saved.
474 The saved copy could later been used, for example, in firmware image recovery or rollback.
475
476 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
477 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
478 The number is between 1 and DescriptorCount.
479 @param[out] Image Points to the buffer where the current image is copied to.
480 @param[out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.
481 On return, points to the length of the image, in bytes.
482
483 @retval EFI_SUCCESS The device was successfully updated with the new image.
484 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the
485 image. The current buffer size needed to hold the image is returned
486 in ImageSize.
487 @retval EFI_INVALID_PARAMETER The Image was NULL.
488 @retval EFI_NOT_FOUND The current image is not copied to the buffer.
489 @retval EFI_UNSUPPORTED The operation is not supported.
490 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
491
492 **/
493 EFI_STATUS
494 EFIAPI
495 GetTheImage (
496 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
497 IN UINT8 ImageIndex,
498 IN OUT VOID *Image,
499 IN OUT UINTN *ImageSize
500 )
501 {
502 EFI_STATUS Status;
503 UINTN Size;
504
505 Status = EFI_SUCCESS;
506
507 //
508 // Check to make sure index is 1 (only 1 image for this device)
509 //
510 if (ImageIndex != 1) {
511 DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - Image Index Invalid.\n"));
512 Status = EFI_INVALID_PARAMETER;
513 goto cleanup;
514 }
515
516 if ((ImageSize == NULL)) {
517 DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - ImageSize Pointer Parameter is NULL.\n"));
518 Status = EFI_INVALID_PARAMETER;
519 goto cleanup;
520 }
521
522 //
523 // Check the buffer size
524 //
525 Status = FmpDeviceGetSize (&Size);
526 if (EFI_ERROR (Status)) {
527 Size = 0;
528 }
529 if (*ImageSize < Size) {
530 *ImageSize = Size;
531 DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImage() - ImageSize is to small.\n"));
532 Status = EFI_BUFFER_TOO_SMALL;
533 goto cleanup;
534 }
535
536 if (Image == NULL) {
537 DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - Image Pointer Parameter is NULL.\n"));
538 Status = EFI_INVALID_PARAMETER;
539 goto cleanup;
540 }
541
542 Status = FmpDeviceGetImage (Image, ImageSize);
543 cleanup:
544
545 return Status;
546 }
547
548 /**
549 Helper function to safely retrieve the FMP header from
550 within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
551
552 @param[in] Image Pointer to the image.
553 @param[in] ImageSize Size of the image.
554 @param[out] PayloadSize
555
556 @retval !NULL Valid pointer to the header.
557 @retval NULL Structure is bad and pointer cannot be found.
558
559 **/
560 VOID *
561 GetFmpHeader (
562 IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
563 IN CONST UINTN ImageSize,
564 OUT UINTN *PayloadSize
565 )
566 {
567 //
568 // Check to make sure that operation can be safely performed.
569 //
570 if (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) < (UINTN)Image || \
571 ((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) >= (UINTN)Image + ImageSize) {
572 //
573 // Pointer overflow. Invalid image.
574 //
575 return NULL;
576 }
577
578 *PayloadSize = ImageSize - (sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength);
579 return (VOID *)((UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength);
580 }
581
582 /**
583 Helper function to safely calculate the size of all headers
584 within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
585
586 @param[in] Image Pointer to the image.
587 @param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.
588
589 @retval UINT32>0 Valid size of all the headers.
590 @retval 0 Structure is bad and size cannot be found.
591
592 **/
593 UINT32
594 GetAllHeaderSize (
595 IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
596 IN UINT32 AdditionalHeaderSize
597 )
598 {
599 UINT32 CalculatedSize;
600
601 CalculatedSize = sizeof (Image->MonotonicCount) +
602 AdditionalHeaderSize +
603 Image->AuthInfo.Hdr.dwLength;
604
605 //
606 // Check to make sure that operation can be safely performed.
607 //
608 if (CalculatedSize < sizeof (Image->MonotonicCount) ||
609 CalculatedSize < AdditionalHeaderSize ||
610 CalculatedSize < Image->AuthInfo.Hdr.dwLength ) {
611 //
612 // Integer overflow. Invalid image.
613 //
614 return 0;
615 }
616
617 return CalculatedSize;
618 }
619
620 /**
621 Checks if the firmware image is valid for the device.
622
623 This function allows firmware update application to validate the firmware image without
624 invoking the SetImage() first.
625
626 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
627 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
628 The number is between 1 and DescriptorCount.
629 @param[in] Image Points to the new image.
630 @param[in] ImageSize Size of the new image in bytes.
631 @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
632 if available, additional information if the image is invalid.
633
634 @retval EFI_SUCCESS The image was successfully checked.
635 @retval EFI_ABORTED The operation is aborted.
636 @retval EFI_INVALID_PARAMETER The Image was NULL.
637 @retval EFI_UNSUPPORTED The operation is not supported.
638 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
639
640 **/
641 EFI_STATUS
642 EFIAPI
643 CheckTheImage (
644 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
645 IN UINT8 ImageIndex,
646 IN CONST VOID *Image,
647 IN UINTN ImageSize,
648 OUT UINT32 *ImageUpdateable
649 )
650 {
651 EFI_STATUS Status;
652 UINTN RawSize;
653 VOID *FmpPayloadHeader;
654 UINTN FmpPayloadSize;
655 UINT32 Version;
656 UINT32 FmpHeaderSize;
657 UINTN AllHeaderSize;
658 UINT32 Index;
659 VOID *PublicKeyData;
660 UINTN PublicKeyDataLength;
661 UINT8 *PublicKeyDataXdr;
662 UINT8 *PublicKeyDataXdrEnd;
663
664 Status = EFI_SUCCESS;
665 RawSize = 0;
666 FmpPayloadHeader = NULL;
667 FmpPayloadSize = 0;
668 Version = 0;
669 FmpHeaderSize = 0;
670 AllHeaderSize = 0;
671
672 //
673 // make sure the descriptor has already been loaded
674 //
675 if (!mDescriptorPopulated) {
676 PopulateDescriptor();
677 }
678
679 if (ImageUpdateable == NULL) {
680 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - ImageUpdateable Pointer Parameter is NULL.\n"));
681 Status = EFI_INVALID_PARAMETER;
682 goto cleanup;
683 }
684
685 //
686 //Set to valid and then if any tests fail it will update this flag.
687 //
688 *ImageUpdateable = IMAGE_UPDATABLE_VALID;
689
690 if (Image == NULL) {
691 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - Image Pointer Parameter is NULL.\n"));
692 //
693 // not sure if this is needed
694 //
695 *ImageUpdateable = IMAGE_UPDATABLE_INVALID;
696 return EFI_INVALID_PARAMETER;
697 }
698
699 PublicKeyDataXdr = PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr);
700 PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr);
701
702 if (PublicKeyDataXdr == NULL || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {
703 DEBUG ((DEBUG_ERROR, "FmpDxe: Invalid certificate, skipping it.\n"));
704 Status = EFI_ABORTED;
705 } else {
706 //
707 // Try each key from PcdFmpDevicePkcs7CertBufferXdr
708 //
709 for (Index = 1; PublicKeyDataXdr < PublicKeyDataXdrEnd; Index++) {
710 Index++;
711 DEBUG (
712 (DEBUG_INFO,
713 "FmpDxe: Certificate #%d [%p..%p].\n",
714 Index,
715 PublicKeyDataXdr,
716 PublicKeyDataXdrEnd
717 )
718 );
719
720 if ((PublicKeyDataXdr + sizeof (UINT32)) > PublicKeyDataXdrEnd) {
721 //
722 // Key data extends beyond end of PCD
723 //
724 DEBUG ((DEBUG_ERROR, "FmpDxe: Certificate size extends beyond end of PCD, skipping it.\n"));
725 Status = EFI_ABORTED;
726 break;
727 }
728 //
729 // Read key length stored in big-endian format
730 //
731 PublicKeyDataLength = SwapBytes32 (*(UINT32 *)(PublicKeyDataXdr));
732 //
733 // Point to the start of the key data
734 //
735 PublicKeyDataXdr += sizeof (UINT32);
736 if (PublicKeyDataXdr + PublicKeyDataLength > PublicKeyDataXdrEnd) {
737 //
738 // Key data extends beyond end of PCD
739 //
740 DEBUG ((DEBUG_ERROR, "FmpDxe: Certificate extends beyond end of PCD, skipping it.\n"));
741 Status = EFI_ABORTED;
742 break;
743 }
744 PublicKeyData = PublicKeyDataXdr;
745 Status = AuthenticateFmpImage (
746 (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image,
747 ImageSize,
748 PublicKeyData,
749 PublicKeyDataLength
750 );
751 if (!EFI_ERROR (Status)) {
752 break;
753 }
754 PublicKeyDataXdr += PublicKeyDataLength;
755 PublicKeyDataXdr = (UINT8 *)ALIGN_POINTER (PublicKeyDataXdr, sizeof (UINT32));
756 }
757 }
758
759 if (EFI_ERROR (Status)) {
760 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - Authentication Failed %r.\n", Status));
761 goto cleanup;
762 }
763
764 //
765 // Check to make sure index is 1
766 //
767 if (ImageIndex != 1) {
768 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - Image Index Invalid.\n"));
769 *ImageUpdateable = IMAGE_UPDATABLE_INVALID_TYPE;
770 Status = EFI_SUCCESS;
771 goto cleanup;
772 }
773
774
775 //
776 // Check the FmpPayloadHeader
777 //
778 FmpPayloadHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize );
779 if (FmpPayloadHeader == NULL) {
780 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpHeader failed.\n"));
781 Status = EFI_ABORTED;
782 goto cleanup;
783 }
784 Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
785 if (EFI_ERROR (Status)) {
786 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", Status));
787 *ImageUpdateable = IMAGE_UPDATABLE_INVALID;
788 Status = EFI_SUCCESS;
789 goto cleanup;
790 }
791
792 //
793 // Check the lowest supported version
794 //
795 if (Version < mDesc.LowestSupportedImageVersion) {
796 DEBUG (
797 (DEBUG_ERROR,
798 "FmpDxe: CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",
799 Version, mDesc.LowestSupportedImageVersion)
800 );
801 *ImageUpdateable = IMAGE_UPDATABLE_INVALID_OLD;
802 Status = EFI_SUCCESS;
803 goto cleanup;
804 }
805
806 //
807 // Get the FmpHeaderSize so we can determine the real payload size
808 //
809 Status = GetFmpPayloadHeaderSize (FmpPayloadHeader, FmpPayloadSize, &FmpHeaderSize);
810 if (EFI_ERROR (Status)) {
811 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));
812 *ImageUpdateable = IMAGE_UPDATABLE_INVALID;
813 Status = EFI_SUCCESS;
814 goto cleanup;
815 }
816
817 //
818 // Call FmpDevice Lib Check Image on the
819 // Raw payload. So all headers need stripped off
820 //
821 AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize );
822 if (AllHeaderSize == 0) {
823 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetAllHeaderSize failed.\n"));
824 Status = EFI_ABORTED;
825 goto cleanup;
826 }
827 RawSize = ImageSize - AllHeaderSize;
828
829 //
830 // FmpDeviceLib CheckImage function to do any specific checks
831 //
832 Status = FmpDeviceCheckImage ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdateable);
833 if (EFI_ERROR (Status)) {
834 DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", Status));
835 }
836
837 cleanup:
838 return Status;
839 }
840
841 /**
842 Updates the firmware image of the device.
843
844 This function updates the hardware with the new firmware image.
845 This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
846 If the firmware image is updatable, the function should perform the following minimal validations
847 before proceeding to do the firmware image update.
848 - Validate the image authentication if image has attribute
849 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
850 EFI_SECURITY_VIOLATION if the validation fails.
851 - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
852 the image is unsupported. The function can optionally provide more detailed information on
853 why the image is not a supported image.
854 - Validate the data from VendorCode if not null. Image validation must be performed before
855 VendorCode data validation. VendorCode data is ignored or considered invalid if image
856 validation failed. The function returns EFI_ABORTED if the data is invalid.
857
858 VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
859 the caller did not specify the policy or use the default policy. As an example, vendor can implement
860 a policy to allow an option to force a firmware image update when the abort reason is due to the new
861 firmware image version is older than the current firmware image version or bad image checksum.
862 Sensitive operations such as those wiping the entire firmware image and render the device to be
863 non-functional should be encoded in the image itself rather than passed with the VendorCode.
864 AbortReason enables vendor to have the option to provide a more detailed description of the abort
865 reason to the caller.
866
867 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
868 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
869 The number is between 1 and DescriptorCount.
870 @param[in] Image Points to the new image.
871 @param[in] ImageSize Size of the new image in bytes.
872 @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
873 Null indicates the caller did not specify the policy or use the default policy.
874 @param[in] Progress A function used by the driver to report the progress of the firmware update.
875 @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
876 details for the aborted operation. The buffer is allocated by this function
877 with AllocatePool(), and it is the caller's responsibility to free it with a
878 call to FreePool().
879
880 @retval EFI_SUCCESS The device was successfully updated with the new image.
881 @retval EFI_ABORTED The operation is aborted.
882 @retval EFI_INVALID_PARAMETER The Image was NULL.
883 @retval EFI_UNSUPPORTED The operation is not supported.
884 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
885
886 **/
887 EFI_STATUS
888 EFIAPI
889 SetTheImage (
890 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
891 IN UINT8 ImageIndex,
892 IN CONST VOID *Image,
893 IN UINTN ImageSize,
894 IN CONST VOID *VendorCode,
895 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,
896 OUT CHAR16 **AbortReason
897 )
898 {
899 EFI_STATUS Status;
900 UINT32 Updateable;
901 BOOLEAN BooleanValue;
902 UINT32 FmpHeaderSize;
903 VOID *FmpHeader;
904 UINTN FmpPayloadSize;
905 UINT32 AllHeaderSize;
906 UINT32 IncommingFwVersion;
907 UINT32 LastAttemptStatus;
908 EFI_STATUS GetAttributesStatus;
909 UINT64 AttributesSupported;
910 UINT64 AttributesSetting;
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 UINT32 Version = DEFAULT_VERSION;
1106 GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);
1107 SetVersionInVariable (Version);
1108 }
1109
1110 //
1111 // Update lowest supported variable
1112 //
1113 {
1114 UINT32 Version = DEFAULT_LOWESTSUPPORTEDVERSION;
1115 GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &Version);
1116 SetLowestSupportedVersionInVariable (Version);
1117 }
1118
1119 LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
1120
1121 //
1122 // Set flag so the descriptor is repopulated
1123 // This is only applied to devices that do not require reset
1124 //
1125 GetAttributesStatus = FmpDeviceGetAttributes (&AttributesSupported, &AttributesSetting);
1126 if (!EFI_ERROR (GetAttributesStatus)) {
1127 if (((AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED) == 0) ||
1128 ((AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED) == 0)) {
1129 mDescriptorPopulated = FALSE;
1130 }
1131 }
1132
1133 cleanup:
1134 mProgressFunc = NULL;
1135 mProgressSupported = FALSE;
1136 SetLastAttemptStatusInVariable (LastAttemptStatus);
1137
1138 if (Progress != NULL) {
1139 //
1140 // Set progress to 100 after everything is done including recording Status.
1141 //
1142 Progress (100);
1143 }
1144
1145 return Status;
1146 }
1147
1148 /**
1149 Returns information about the firmware package.
1150
1151 This function returns package information.
1152
1153 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1154 @param[out] PackageVersion A version number that represents all the firmware images in the device.
1155 The format is vendor specific and new version must have a greater value
1156 than the old version. If PackageVersion is not supported, the value is
1157 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
1158 comparison is to be performed using PackageVersionName. A value of
1159 0xFFFFFFFD indicates that package version update is in progress.
1160 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing
1161 the package version name. The buffer is allocated by this function with
1162 AllocatePool(), and it is the caller's responsibility to free it with a
1163 call to FreePool().
1164 @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
1165 package version name. A value of 0 indicates the device does not support
1166 update of package version name. Length is the number of Unicode characters,
1167 including the terminating null character.
1168 @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute
1169 Definitions' for possible returned values of this parameter. A value of 1
1170 indicates the attribute is supported and the current setting value is
1171 indicated in AttributesSetting. A value of 0 indicates the attribute is not
1172 supported and the current setting value in AttributesSetting is meaningless.
1173 @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned
1174 values of this parameter
1175
1176 @retval EFI_SUCCESS The package information was successfully returned.
1177 @retval EFI_UNSUPPORTED The operation is not supported.
1178
1179 **/
1180 EFI_STATUS
1181 EFIAPI
1182 GetPackageInfo (
1183 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
1184 OUT UINT32 *PackageVersion,
1185 OUT CHAR16 **PackageVersionName,
1186 OUT UINT32 *PackageVersionNameMaxLen,
1187 OUT UINT64 *AttributesSupported,
1188 OUT UINT64 *AttributesSetting
1189 )
1190 {
1191 return EFI_UNSUPPORTED;
1192 }
1193
1194 /**
1195 Updates information about the firmware package.
1196
1197 This function updates package information.
1198 This function returns EFI_UNSUPPORTED if the package information is not updatable.
1199 VendorCode enables vendor to implement vendor-specific package information update policy.
1200 Null if the caller did not specify this policy or use the default policy.
1201
1202 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
1203 @param[in] Image Points to the authentication image.
1204 Null if authentication is not required.
1205 @param[in] ImageSize Size of the authentication image in bytes.
1206 0 if authentication is not required.
1207 @param[in] VendorCode This enables vendor to implement vendor-specific firmware
1208 image update policy.
1209 Null indicates the caller did not specify this policy or use
1210 the default policy.
1211 @param[in] PackageVersion The new package version.
1212 @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing
1213 the package version name.
1214 The string length is equal to or less than the value returned in
1215 PackageVersionNameMaxLen.
1216
1217 @retval EFI_SUCCESS The device was successfully updated with the new package
1218 information.
1219 @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
1220 returned in PackageVersionNameMaxLen.
1221 @retval EFI_UNSUPPORTED The operation is not supported.
1222 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
1223
1224 **/
1225 EFI_STATUS
1226 EFIAPI
1227 SetPackageInfo (
1228 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
1229 IN CONST VOID *Image,
1230 IN UINTN ImageSize,
1231 IN CONST VOID *VendorCode,
1232 IN UINT32 PackageVersion,
1233 IN CONST CHAR16 *PackageVersionName
1234 )
1235 {
1236 return EFI_UNSUPPORTED;
1237 }
1238
1239 /**
1240 Event notification function that is invoked when the event GUID specified by
1241 PcdFmpDeviceLockEventGuid is signaled.
1242
1243 @param[in] Event Event whose notification function is being invoked.
1244 @param[in] Context The pointer to the notification function's context,
1245 which is implementation-dependent.
1246 **/
1247 VOID
1248 EFIAPI
1249 FmpDxeLockEventNotify (
1250 IN EFI_EVENT Event,
1251 IN VOID *Context
1252 )
1253 {
1254 EFI_STATUS Status;
1255
1256 if (!mFmpDeviceLocked) {
1257 if (IsLockFmpDeviceAtLockEventGuidRequired ()) {
1258 //
1259 // Lock all UEFI Variables used by this module.
1260 //
1261 Status = LockAllFmpVariables ();
1262 if (EFI_ERROR (Status)) {
1263 DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variables. Status = %r.\n"));
1264 } else {
1265 DEBUG ((DEBUG_INFO, "FmpDxe: All variables locked\n"));
1266 }
1267
1268 //
1269 // Lock the firmware device
1270 //
1271 Status = FmpDeviceLock();
1272 if (EFI_ERROR (Status)) {
1273 if (Status != EFI_UNSUPPORTED) {
1274 DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status));
1275 } else {
1276 DEBUG ((DEBUG_WARN, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status));
1277 }
1278 }
1279 mFmpDeviceLocked = TRUE;
1280 } else {
1281 DEBUG ((DEBUG_VERBOSE, "FmpDxe: Not calling FmpDeviceLock() because mfg mode\n"));
1282 }
1283 }
1284 }
1285
1286 /**
1287 Function to install FMP instance.
1288
1289 @param[in] Handle The device handle to install a FMP instance on.
1290
1291 @retval EFI_SUCCESS FMP Installed
1292 @retval EFI_INVALID_PARAMETER Handle was invalid
1293 @retval other Error installing FMP
1294
1295 **/
1296 EFI_STATUS
1297 EFIAPI
1298 InstallFmpInstance (
1299 IN EFI_HANDLE Handle
1300 )
1301 {
1302 EFI_STATUS Status;
1303 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
1304 EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *FmpProgress;
1305
1306 Status = EFI_SUCCESS;
1307 Fmp = NULL;
1308 FmpProgress = NULL;
1309
1310 //
1311 // Only allow a single FMP Protocol instance to be installed
1312 //
1313 if (mFmpInstalled) {
1314 return EFI_ALREADY_STARTED;
1315 }
1316
1317 //
1318 // Allocate FMP Protocol instance
1319 //
1320 Fmp = AllocateZeroPool (sizeof (EFI_FIRMWARE_MANAGEMENT_PROTOCOL));
1321 if (Fmp == NULL) {
1322 DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for FMP Protocol instance.\n"));
1323 Status = EFI_OUT_OF_RESOURCES;
1324 goto cleanup;
1325 }
1326
1327 //
1328 // Allocate FMP Progress Protocol instance
1329 //
1330 FmpProgress = AllocateZeroPool (sizeof (EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL));
1331 if (FmpProgress == NULL) {
1332 DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for FMP Progress Protocol instance.\n"));
1333 Status = EFI_OUT_OF_RESOURCES;
1334 FreePool (Fmp);
1335 goto cleanup;
1336 }
1337
1338 //
1339 // Set up FMP Protocol function pointers
1340 //
1341 Fmp->GetImageInfo = GetTheImageInfo;
1342 Fmp->GetImage = GetTheImage;
1343 Fmp->SetImage = SetTheImage;
1344 Fmp->CheckImage = CheckTheImage;
1345 Fmp->GetPackageInfo = GetPackageInfo;
1346 Fmp->SetPackageInfo = SetPackageInfo;
1347
1348 //
1349 // Fill in FMP Progress Protocol fields for Version 1
1350 //
1351 FmpProgress->Version = 1;
1352 FmpProgress->ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);
1353 FmpProgress->WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);
1354
1355 //
1356 // Install FMP Protocol and FMP Progress Protocol
1357 //
1358 Status = gBS->InstallMultipleProtocolInterfaces (
1359 &Handle,
1360 &gEfiFirmwareManagementProtocolGuid,
1361 Fmp,
1362 &gEdkiiFirmwareManagementProgressProtocolGuid,
1363 FmpProgress,
1364 NULL
1365 );
1366
1367 if (EFI_ERROR (Status)) {
1368 DEBUG ((DEBUG_ERROR, "FmpDxe: FMP Protocol install error. Status = %r.\n", Status));
1369 FreePool (Fmp);
1370 goto cleanup;
1371 }
1372
1373 DEBUG ((DEBUG_INFO, "FmpDxe: FMP Protocol Installed!\n"));
1374 mFmpInstalled = TRUE;
1375
1376 cleanup:
1377
1378 return Status;
1379 }
1380
1381 /**
1382 Main entry for this driver/library.
1383
1384 @param[in] ImageHandle Image handle this driver.
1385 @param[in] SystemTable Pointer to SystemTable.
1386
1387 **/
1388 EFI_STATUS
1389 EFIAPI
1390 FmpDxeEntryPoint (
1391 IN EFI_HANDLE ImageHandle,
1392 IN EFI_SYSTEM_TABLE *SystemTable
1393 )
1394 {
1395 EFI_STATUS Status;
1396 EFI_GUID *LockGuid;
1397
1398 //
1399 // Verify that a new FILE_GUID value has been provided in the <Defines>
1400 // section of this module. The FILE_GUID is the ESRT GUID that must be
1401 // unique for each updatable firmware image.
1402 //
1403 if (CompareGuid (&mDefaultModuleFileGuid, &gEfiCallerIdGuid)) {
1404 DEBUG ((DEBUG_ERROR, "FmpDxe: Use of default FILE_GUID detected. FILE_GUID must be set to a unique value.\n"));
1405 ASSERT (FALSE);
1406 return EFI_UNSUPPORTED;
1407 }
1408
1409 //
1410 // Get the ImageIdName value for the EFI_FIRMWARE_IMAGE_DESCRIPTOR from a PCD.
1411 //
1412 mImageIdName = (CHAR16 *) PcdGetPtr (PcdFmpDeviceImageIdName);
1413 if (PcdGetSize (PcdFmpDeviceImageIdName) <= 2 || mImageIdName[0] == 0) {
1414 //
1415 // PcdFmpDeviceImageIdName must be set to a non-empty Unicode string
1416 //
1417 DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib PcdFmpDeviceImageIdName is an empty string.\n"));
1418 ASSERT (FALSE);
1419 }
1420
1421 //
1422 // Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.
1423 //
1424 DetectTestKey ();
1425
1426 //
1427 // Register with library the install function so if the library uses
1428 // UEFI driver model/driver binding protocol it can install FMP on its device handle
1429 // If library is simple lib that does not use driver binding then it should return
1430 // unsupported and this will install the FMP instance on the ImageHandle
1431 //
1432 Status = RegisterFmpInstaller (InstallFmpInstance);
1433 if (Status == EFI_UNSUPPORTED) {
1434 DEBUG ((DEBUG_INFO, "FmpDxe: FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n"));
1435 Status = InstallFmpInstance (ImageHandle);
1436 } else if (EFI_ERROR (Status)) {
1437 DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib registration returned %r. No FMP installed.\n", Status));
1438 } else {
1439 DEBUG ((
1440 DEBUG_INFO,
1441 "FmpDxe: FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n"
1442 ));
1443 }
1444
1445 //
1446 // Register notify function to lock the FMP device.
1447 // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.
1448 // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then
1449 // gEfiEndOfDxeEventGroupGuid is used.
1450 //
1451 LockGuid = &gEfiEndOfDxeEventGroupGuid;
1452 if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {
1453 LockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);
1454 }
1455 DEBUG ((DEBUG_INFO, "FmpDxe: Lock GUID: %g\n", LockGuid));
1456
1457 Status = gBS->CreateEventEx (
1458 EVT_NOTIFY_SIGNAL,
1459 TPL_CALLBACK,
1460 FmpDxeLockEventNotify,
1461 NULL,
1462 LockGuid,
1463 &mFmpDeviceLockEvent
1464 );
1465 if (EFI_ERROR (Status)) {
1466 DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to register for ready to boot. Status = %r\n", Status));
1467 }
1468 ASSERT_EFI_ERROR (Status);
1469
1470 return Status;
1471 }