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