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