-/** @file\r
+/** @file\r
Produces a Firmware Management Protocol that supports updates to a firmware\r
image stored in a firmware device with platform and firmware device specific\r
information provided through PCDs and libraries.\r
\r
Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>\r
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
-\r
- Redistribution and use in source and binary forms, with or without\r
- modification, are permitted provided that the following conditions are met:\r
- 1. Redistributions of source code must retain the above copyright notice,\r
- this list of conditions and the following disclaimer.\r
- 2. Redistributions in binary form must reproduce the above copyright notice,\r
- this list of conditions and the following disclaimer in the documentation\r
- and/or other materials provided with the distribution.\r
-\r
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\r
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
- OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-#include <PiDxe.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/FmpAuthenticationLib.h>\r
-#include <Library/FmpDeviceLib.h>\r
-#include <Library/FmpPayloadHeaderLib.h>\r
-#include <Library/CapsuleUpdatePolicyLib.h>\r
-#include <Protocol/FirmwareManagement.h>\r
-#include <Protocol/FirmwareManagementProgress.h>\r
-#include <Guid/SystemResourceTable.h>\r
-#include <Guid/EventGroup.h>\r
+#include "FmpDxe.h"\r
#include "VariableSupport.h"\r
-\r
-#define VERSION_STRING_NOT_SUPPORTED L"VERSION STRING NOT SUPPORTED"\r
-#define VERSION_STRING_NOT_AVAILABLE L"VERSION STRING NOT AVAILABLE"\r
-\r
-/**\r
- Check to see if any of the keys in PcdFmpDevicePkcs7CertBufferXdr matches\r
- the test key. PcdFmpDeviceTestKeySha256Digest contains the SHA256 hash of\r
- the test key. For each key in PcdFmpDevicePkcs7CertBufferXdr, compute the\r
- SHA256 hash and compare it to PcdFmpDeviceTestKeySha256Digest. If the\r
- SHA256 hash matches or there is then error computing the SHA256 hash, then\r
- set PcdTestKeyUsed to TRUE. Skip this check if PcdTestKeyUsed is already\r
- TRUE or PcdFmpDeviceTestKeySha256Digest is not exactly SHA256_DIGEST_SIZE\r
- bytes.\r
-**/\r
-VOID\r
-DetectTestKey (\r
- VOID\r
- );\r
+#include "Dependency.h"\r
\r
///\r
/// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the\r
0x78ef0a56, 0x1cf0, 0x4535, { 0xb5, 0xda, 0xf6, 0xfd, 0x2f, 0x40, 0x5a, 0x11 }\r
};\r
\r
-EFI_FIRMWARE_IMAGE_DESCRIPTOR mDesc;\r
-BOOLEAN mDescriptorPopulated = FALSE;\r
-BOOLEAN mRuntimeVersionSupported = TRUE;\r
-BOOLEAN mFmpInstalled = FALSE;\r
-\r
///\r
-/// Function pointer to progress function\r
+/// TRUE if FmpDeviceLib manages a single firmware storage device.\r
///\r
-EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS mProgressFunc = NULL;\r
-BOOLEAN mProgressSupported = FALSE;\r
+BOOLEAN mFmpSingleInstance = FALSE;\r
\r
-CHAR16 *mImageIdName = NULL;\r
-UINT64 mImageId = 0x1;\r
-CHAR16 *mVersionName = NULL;\r
+///\r
+/// Firmware Management Protocol instance that is initialized in the entry\r
+/// point from PCD settings.\r
+///\r
+EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL mFmpProgress;\r
\r
-EFI_EVENT mFmpDeviceLockEvent;\r
//\r
-// Indicates if an attempt has been made to lock a \r
-// FLASH storage device by calling FmpDeviceLock().\r
-// A FLASH storage device may not support being locked,\r
-// so this variable is set to TRUE even if FmpDeviceLock()\r
-// returns an error.\r
+// Template of the private context structure for the Firmware Management\r
+// Protocol instance\r
//\r
-BOOLEAN mFmpDeviceLocked = FALSE;\r
+const FIRMWARE_MANAGEMENT_PRIVATE_DATA mFirmwareManagementPrivateDataTemplate = {\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA_SIGNATURE, // Signature\r
+ NULL, // Handle\r
+ { // Fmp\r
+ GetTheImageInfo,\r
+ GetTheImage,\r
+ SetTheImage,\r
+ CheckTheImage,\r
+ GetPackageInfo,\r
+ SetPackageInfo\r
+ },\r
+ FALSE, // DescriptorPopulated\r
+ { // Desc\r
+ 1, // ImageIndex\r
+ //\r
+ // ImageTypeId\r
+ //\r
+ { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },\r
+ 1, // ImageId\r
+ NULL, // ImageIdName\r
+ 0, // Version\r
+ NULL, // VersionName\r
+ 0, // Size\r
+ 0, // AttributesSupported\r
+ 0, // AttributesSetting\r
+ 0, // Compatibilities\r
+ 0, // LowestSupportedImageVersion\r
+ 0, // LastAttemptVersion\r
+ 0, // LastAttemptStatus\r
+ 0 // HardwareInstance\r
+ },\r
+ NULL, // ImageIdName\r
+ NULL, // VersionName\r
+ TRUE, // RuntimeVersionSupported\r
+ NULL, // FmpDeviceLockEvent\r
+ FALSE, // FmpDeviceLocked\r
+ NULL, // FmpDeviceContext\r
+ NULL, // VersionVariableName\r
+ NULL, // LsvVariableName\r
+ NULL, // LastAttemptStatusVariableName\r
+ NULL, // LastAttemptVersionVariableName\r
+ NULL // FmpStateVariableName\r
+};\r
+\r
+///\r
+/// GUID that is used to create event used to lock the firmware storage device.\r
+///\r
+EFI_GUID *mLockGuid = NULL;\r
+\r
+///\r
+/// Progress() function pointer passed into SetTheImage()\r
+///\r
+EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS mProgressFunc = NULL;\r
+\r
+///\r
+/// Null-terminated Unicode string retrieved from PcdFmpDeviceImageIdName.\r
+///\r
+CHAR16 *mImageIdName = NULL;\r
\r
/**\r
Callback function to report the process of the firmware updating.\r
\r
Status = EFI_UNSUPPORTED;\r
\r
- if (!mProgressSupported) {\r
- return Status;\r
- }\r
-\r
if (mProgressFunc == NULL) {\r
return Status;\r
}\r
Status = mProgressFunc (((Completion * 92) / 100) + 6);\r
\r
if (Status == EFI_UNSUPPORTED) {\r
- mProgressSupported = FALSE;\r
mProgressFunc = NULL;\r
}\r
\r
/**\r
Returns a pointer to the ImageTypeId GUID value. An attempt is made to get\r
the GUID value from the FmpDeviceLib. If the FmpDeviceLib does not provide\r
- a GUID value, then gEfiCallerIdGuid is returned.\r
+ a GUID value, then PcdFmpDeviceImageTypeIdGuid is used. If the size of\r
+ PcdFmpDeviceImageTypeIdGuid is not the size of EFI_GUID, then gEfiCallerIdGuid\r
+ is returned.\r
\r
- @return The ImageTypeId GUID\r
+ @retval The ImageTypeId GUID\r
\r
**/\r
EFI_GUID *\r
{\r
EFI_STATUS Status;\r
EFI_GUID *FmpDeviceLibGuid;\r
+ UINTN ImageTypeIdGuidSize;\r
\r
FmpDeviceLibGuid = NULL;\r
Status = FmpDeviceGetImageTypeIdGuidPtr (&FmpDeviceLibGuid);\r
if (EFI_ERROR (Status)) {\r
if (Status != EFI_UNSUPPORTED) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", mImageIdName, Status));\r
}\r
- return &gEfiCallerIdGuid;\r
+ } else if (FmpDeviceLibGuid == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n", mImageIdName));\r
+ Status = EFI_NOT_FOUND;\r
}\r
- if (FmpDeviceLibGuid == NULL) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n"));\r
- return &gEfiCallerIdGuid;\r
+ if (EFI_ERROR (Status)) {\r
+ ImageTypeIdGuidSize = PcdGetSize (PcdFmpDeviceImageTypeIdGuid);\r
+ if (ImageTypeIdGuidSize == sizeof (EFI_GUID)) {\r
+ FmpDeviceLibGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceImageTypeIdGuid);\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): Fall back to ImageTypeIdGuid of gEfiCallerIdGuid\n", mImageIdName));\r
+ FmpDeviceLibGuid = &gEfiCallerIdGuid;\r
+ }\r
}\r
return FmpDeviceLibGuid;\r
}\r
/**\r
Returns a pointer to the Null-terminated Unicode ImageIdName string.\r
\r
- @return Null-terminated Unicode ImageIdName string.\r
+ @retval Null-terminated Unicode ImageIdName string.\r
\r
**/\r
CHAR16 *\r
2. Check if we have a variable for lowest supported version (this will be updated with each capsule applied)\r
3. Check Fixed at build PCD\r
\r
- Take the largest value\r
+ @param[in] Private Pointer to the private context structure for the\r
+ Firmware Management Protocol instance.\r
+\r
+ @retval The largest value\r
\r
**/\r
UINT32\r
GetLowestSupportedVersion (\r
- VOID\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
)\r
{\r
EFI_STATUS Status;\r
//\r
// Check the FmpDeviceLib\r
//\r
+ DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
Status = FmpDeviceGetLowestSupportedVersion (&DeviceLibLowestSupportedVersion);\r
if (EFI_ERROR (Status)) {\r
DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
//\r
// Check the lowest supported version UEFI variable for this device\r
//\r
- VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable();\r
+ VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable (Private);\r
if (VariableLowestSupportedVersion > ReturnLsv) {\r
ReturnLsv = VariableLowestSupportedVersion;\r
}\r
}\r
\r
/**\r
- Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the module global\r
- variable mDesc.\r
+ Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the private\r
+ context structure.\r
+\r
+ @param[in] Private Pointer to the private context structure for the\r
+ Firmware Management Protocol instance.\r
\r
**/\r
VOID\r
PopulateDescriptor (\r
- VOID\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
)\r
{\r
EFI_STATUS Status;\r
+ VOID *Image;\r
+ UINTN ImageSize;\r
+ BOOLEAN IsDepexValid;\r
+ UINT32 DepexSize;\r
+\r
+ Image = NULL;\r
+ ImageSize = 0;\r
+\r
+ if (Private->DescriptorPopulated) {\r
+ return;\r
+ }\r
+\r
+ Private->Descriptor.ImageIndex = 1;\r
+ CopyGuid (&Private->Descriptor.ImageTypeId, GetImageTypeIdGuid());\r
+ Private->Descriptor.ImageId = Private->Descriptor.ImageIndex;\r
+ Private->Descriptor.ImageIdName = GetImageTypeNameString();\r
\r
- mDesc.ImageIndex = 1;\r
- CopyGuid (&mDesc.ImageTypeId, GetImageTypeIdGuid());\r
- mDesc.ImageId = mImageId;\r
- mDesc.ImageIdName = GetImageTypeNameString();\r
+ //\r
+ // Get the hardware instance from FmpDeviceLib\r
+ //\r
+ Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance);\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ Private->Descriptor.HardwareInstance = 0;\r
+ }\r
+\r
+ //\r
+ // Generate UEFI Variable names used to store status information for this\r
+ // FMP instance.\r
+ //\r
+ GenerateFmpVariableNames (Private);\r
\r
//\r
// Get the version. Some devices don't support getting the firmware version\r
// at runtime. If FmpDeviceLib does not support returning a version, then\r
// it is stored in a UEFI variable.\r
//\r
- Status = FmpDeviceGetVersion (&mDesc.Version);\r
+ Status = FmpDeviceGetVersion (&Private->Descriptor.Version);\r
if (Status == EFI_UNSUPPORTED) {\r
- mRuntimeVersionSupported = FALSE;\r
- mDesc.Version = GetVersionFromVariable();\r
+ Private->RuntimeVersionSupported = FALSE;\r
+ Private->Descriptor.Version = GetVersionFromVariable (Private);\r
} else if (EFI_ERROR (Status)) {\r
//\r
// Unexpected error. Use default version.\r
//\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: GetVersion() from FmpDeviceLib (%s) returned %r\n", GetImageTypeNameString(), Status));\r
- mDesc.Version = DEFAULT_VERSION;\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetVersion() from FmpDeviceLib (%s) returned %r\n", mImageIdName, GetImageTypeNameString(), Status));\r
+ Private->Descriptor.Version = DEFAULT_VERSION;\r
}\r
\r
//\r
// Free the current version name. Shouldn't really happen but this populate\r
// function could be called multiple times (to refresh).\r
//\r
- if (mVersionName != NULL) {\r
- FreePool (mVersionName);\r
- mVersionName = NULL;\r
+ if (Private->Descriptor.VersionName != NULL) {\r
+ FreePool (Private->Descriptor.VersionName);\r
+ Private->Descriptor.VersionName = NULL;\r
}\r
\r
//\r
// Attempt to get the version string from the FmpDeviceLib\r
//\r
- Status = FmpDeviceGetVersionString (&mVersionName);\r
+ Status = FmpDeviceGetVersionString (&Private->Descriptor.VersionName);\r
if (Status == EFI_UNSUPPORTED) {\r
- DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() unsupported in FmpDeviceLib.\n"));\r
- mVersionName = AllocateCopyPool (\r
- sizeof (VERSION_STRING_NOT_SUPPORTED),\r
- VERSION_STRING_NOT_SUPPORTED\r
- );\r
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() unsupported in FmpDeviceLib.\n", mImageIdName));\r
+ Private->Descriptor.VersionName = AllocateCopyPool (\r
+ sizeof (VERSION_STRING_NOT_SUPPORTED),\r
+ VERSION_STRING_NOT_SUPPORTED\r
+ );\r
} else if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() not available in FmpDeviceLib.\n"));\r
- mVersionName = AllocateCopyPool (\r
- sizeof (VERSION_STRING_NOT_AVAILABLE),\r
- VERSION_STRING_NOT_AVAILABLE\r
- );\r
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() not available in FmpDeviceLib.\n", mImageIdName));\r
+ Private->Descriptor.VersionName = AllocateCopyPool (\r
+ sizeof (VERSION_STRING_NOT_AVAILABLE),\r
+ VERSION_STRING_NOT_AVAILABLE\r
+ );\r
}\r
\r
- mDesc.VersionName = mVersionName;\r
-\r
- mDesc.LowestSupportedImageVersion = GetLowestSupportedVersion();\r
+ Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion (Private);\r
\r
//\r
// Get attributes from the FmpDeviceLib\r
//\r
- FmpDeviceGetAttributes (&mDesc.AttributesSupported, &mDesc.AttributesSetting);\r
+ FmpDeviceGetAttributes (\r
+ &Private->Descriptor.AttributesSupported,\r
+ &Private->Descriptor.AttributesSetting\r
+ );\r
\r
//\r
// Force set the updatable bits in the attributes;\r
//\r
- mDesc.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;\r
- mDesc.AttributesSetting |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;\r
+ Private->Descriptor.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;\r
+ Private->Descriptor.AttributesSetting |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;\r
\r
//\r
// Force set the authentication bits in the attributes;\r
//\r
- mDesc.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
- mDesc.AttributesSetting |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
+ Private->Descriptor.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
+ Private->Descriptor.AttributesSetting |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
\r
- mDesc.Compatibilities = 0;\r
+ Private->Descriptor.Compatibilities = 0;\r
\r
//\r
// Get the size of the firmware image from the FmpDeviceLib\r
//\r
- Status = FmpDeviceGetSize (&mDesc.Size);\r
+ Status = FmpDeviceGetSize (&Private->Descriptor.Size);\r
if (EFI_ERROR (Status)) {\r
- mDesc.Size = 0;\r
+ Private->Descriptor.Size = 0;\r
+ }\r
+\r
+ Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable (Private);\r
+ Private->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable (Private);\r
+\r
+ //\r
+ // Get the dependency from the FmpDeviceLib and populate it to the descriptor.\r
+ //\r
+ Private->Descriptor.Dependencies = NULL;\r
+\r
+ //\r
+ // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY\r
+ //\r
+ if (Private->Descriptor.AttributesSupported & IMAGE_ATTRIBUTE_DEPENDENCY) {\r
+ //\r
+ // The parameter "Image" of FmpDeviceGetImage() is extended to contain the dependency.\r
+ // Get the dependency from the Image.\r
+ //\r
+ ImageSize = Private->Descriptor.Size;\r
+ Image = AllocatePool (ImageSize);\r
+ if (Image != NULL) {\r
+ Status = FmpDeviceGetImage (Image, &ImageSize);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ FreePool (Image);\r
+ Image = AllocatePool (ImageSize);\r
+ if (Image != NULL) {\r
+ Status = FmpDeviceGetImage (Image, &ImageSize);\r
+ }\r
+ }\r
+ }\r
+ if (!EFI_ERROR (Status) && Image != NULL) {\r
+ IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP *) Image, ImageSize, &DepexSize);\r
+ if (IsDepexValid == TRUE) {\r
+ Private->Descriptor.Dependencies = AllocatePool (DepexSize);\r
+ if (Private->Descriptor.Dependencies != NULL) {\r
+ CopyMem (Private->Descriptor.Dependencies->Dependencies, Image, DepexSize);\r
+ }\r
+ }\r
+ }\r
}\r
\r
- mDesc.LastAttemptVersion = GetLastAttemptVersionFromVariable ();\r
- mDesc.LastAttemptStatus = GetLastAttemptStatusFromVariable ();\r
+ Private->DescriptorPopulated = TRUE;\r
\r
- mDescriptorPopulated = TRUE;\r
+ if (Image != NULL) {\r
+ FreePool (Image);\r
+ }\r
}\r
\r
/**\r
OUT CHAR16 **PackageVersionName\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
\r
Status = EFI_SUCCESS;\r
\r
+ //\r
+ // Retrieve the private context structure\r
+ //\r
+ Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+\r
//\r
// Check for valid pointer\r
//\r
if (ImageInfoSize == NULL) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: GetImageInfo() - ImageInfoSize is NULL.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is NULL.\n", mImageIdName));\r
Status = EFI_INVALID_PARAMETER;\r
goto cleanup;\r
}\r
//\r
if (*ImageInfoSize < (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR))) {\r
*ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);\r
- DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImageInfo() - ImageInfoSize is to small.\n"));\r
+ DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is to small.\n", mImageIdName));\r
Status = EFI_BUFFER_TOO_SMALL;\r
goto cleanup;\r
}\r
//\r
if ( (ImageInfo == NULL) || (DescriptorVersion == NULL) || (DescriptorCount == NULL) || (DescriptorSize == NULL)\r
|| (PackageVersion == NULL)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: GetImageInfo() - Pointer Parameter is NULL.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - Pointer Parameter is NULL.\n", mImageIdName));\r
Status = EFI_INVALID_PARAMETER;\r
goto cleanup;\r
}\r
//\r
*ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);\r
\r
-\r
- if (!mDescriptorPopulated) {\r
- PopulateDescriptor();\r
- }\r
+ //\r
+ // Make sure the descriptor has already been loaded or refreshed\r
+ //\r
+ PopulateDescriptor (Private);\r
\r
//\r
// Copy the image descriptor\r
//\r
- CopyMem (ImageInfo, &mDesc, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR));\r
+ CopyMem (ImageInfo, &Private->Descriptor, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR));\r
\r
*DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;\r
*DescriptorCount = 1;\r
This function allows a copy of the current firmware image to be created and saved.\r
The saved copy could later been used, for example, in firmware image recovery or rollback.\r
\r
- @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
- @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
+ @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
The number is between 1 and DescriptorCount.\r
- @param[out] Image Points to the buffer where the current image is copied to.\r
- @param[out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.\r
+ @param[in, out] Image Points to the buffer where the current image is copied to.\r
+ @param[in, out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.\r
On return, points to the length of the image, in bytes.\r
\r
@retval EFI_SUCCESS The device was successfully updated with the new image.\r
IN OUT UINTN *ImageSize\r
)\r
{\r
- EFI_STATUS Status;\r
- UINTN Size;\r
+ EFI_STATUS Status;\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
+ UINTN Size;\r
+ UINT8 *ImageBuffer;\r
+ UINTN ImageBufferSize;\r
+ UINT32 DepexSize;\r
+\r
+ if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
\r
- Status = EFI_SUCCESS;\r
+ Status = EFI_SUCCESS;\r
+ ImageBuffer = NULL;\r
+ DepexSize = 0;\r
+\r
+ //\r
+ // Retrieve the private context structure\r
+ //\r
+ Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
\r
//\r
// Check to make sure index is 1 (only 1 image for this device)\r
//\r
if (ImageIndex != 1) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - Image Index Invalid.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Index Invalid.\n", mImageIdName));\r
Status = EFI_INVALID_PARAMETER;\r
goto cleanup;\r
}\r
\r
- if ((ImageSize == NULL)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - ImageSize Pointer Parameter is NULL.\n"));\r
+ if (ImageSize == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - ImageSize Pointer Parameter is NULL.\n", mImageIdName));\r
Status = EFI_INVALID_PARAMETER;\r
goto cleanup;\r
}\r
if (EFI_ERROR (Status)) {\r
Size = 0;\r
}\r
- if (*ImageSize < Size) {\r
- *ImageSize = Size;\r
- DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImage() - ImageSize is to small.\n"));\r
+\r
+ //\r
+ // The parameter "Image" of FmpDeviceGetImage() is extended to contain the dependency.\r
+ // Get the Fmp Payload from the Image.\r
+ //\r
+ ImageBufferSize = Size;\r
+ ImageBuffer = AllocatePool (ImageBufferSize);\r
+ if (ImageBuffer == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - AllocatePool fails.\n", mImageIdName));\r
+ Status = EFI_NOT_FOUND;\r
+ goto cleanup;\r
+ }\r
+ Status = FmpDeviceGetImage (ImageBuffer, &ImageBufferSize);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ FreePool (ImageBuffer);\r
+ ImageBuffer = AllocatePool (ImageBufferSize);\r
+ if (ImageBuffer == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - AllocatePool fails.\n", mImageIdName));\r
+ Status = EFI_NOT_FOUND;\r
+ goto cleanup;\r
+ }\r
+ Status = FmpDeviceGetImage (ImageBuffer, &ImageBufferSize);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ goto cleanup;\r
+ }\r
+\r
+ //\r
+ // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY\r
+ //\r
+ if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {\r
+ //\r
+ // Validate the dependency to get its size.\r
+ //\r
+ ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP *) ImageBuffer, ImageBufferSize, &DepexSize);\r
+ }\r
+\r
+ if (*ImageSize < ImageBufferSize - DepexSize) {\r
+ *ImageSize = ImageBufferSize - DepexSize;\r
+ DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName));\r
Status = EFI_BUFFER_TOO_SMALL;\r
goto cleanup;\r
}\r
\r
if (Image == NULL) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - Image Pointer Parameter is NULL.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Pointer Parameter is NULL.\n", mImageIdName));\r
Status = EFI_INVALID_PARAMETER;\r
goto cleanup;\r
}\r
\r
- Status = FmpDeviceGetImage (Image, ImageSize);\r
+ //\r
+ // Image is after the dependency expression.\r
+ //\r
+ *ImageSize = ImageBufferSize - DepexSize;\r
+ CopyMem (Image, ImageBuffer + DepexSize, *ImageSize);\r
+ Status = EFI_SUCCESS;\r
+\r
cleanup:\r
+ if (ImageBuffer != NULL) {\r
+ FreePool (ImageBuffer);\r
+ }\r
\r
return Status;\r
}\r
IN UINT8 ImageIndex,\r
IN CONST VOID *Image,\r
IN UINTN ImageSize,\r
- OUT UINT32 *ImageUpdateable\r
+ OUT UINT32 *ImageUpdatable\r
)\r
{\r
- EFI_STATUS Status;\r
- UINTN RawSize;\r
- VOID *FmpPayloadHeader;\r
- UINTN FmpPayloadSize;\r
- UINT32 Version;\r
- UINT32 FmpHeaderSize;\r
- UINTN AllHeaderSize;\r
- UINT32 Index;\r
- VOID *PublicKeyData;\r
- UINTN PublicKeyDataLength;\r
- UINT8 *PublicKeyDataXdr;\r
- UINT8 *PublicKeyDataXdrEnd;\r
+ EFI_STATUS Status;\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
+ UINTN RawSize;\r
+ VOID *FmpPayloadHeader;\r
+ UINTN FmpPayloadSize;\r
+ UINT32 Version;\r
+ UINT32 FmpHeaderSize;\r
+ UINTN AllHeaderSize;\r
+ UINT32 Index;\r
+ VOID *PublicKeyData;\r
+ UINTN PublicKeyDataLength;\r
+ UINT8 *PublicKeyDataXdr;\r
+ UINT8 *PublicKeyDataXdrEnd;\r
+ EFI_FIRMWARE_IMAGE_DEP *Dependencies;\r
+ UINT32 DependenciesSize;\r
+ BOOLEAN IsDepexValid;\r
+ BOOLEAN IsDepexSatisfied;\r
\r
Status = EFI_SUCCESS;\r
RawSize = 0;\r
Version = 0;\r
FmpHeaderSize = 0;\r
AllHeaderSize = 0;\r
+ Dependencies = NULL;\r
+ DependenciesSize = 0;\r
+\r
+ if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
\r
//\r
- // make sure the descriptor has already been loaded\r
+ // Retrieve the private context structure\r
//\r
- if (!mDescriptorPopulated) {\r
- PopulateDescriptor();\r
- }\r
+ Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+\r
+ //\r
+ // Make sure the descriptor has already been loaded or refreshed\r
+ //\r
+ PopulateDescriptor (Private);\r
\r
- if (ImageUpdateable == NULL) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - ImageUpdateable Pointer Parameter is NULL.\n"));\r
+ if (ImageUpdatable == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName));\r
Status = EFI_INVALID_PARAMETER;\r
goto cleanup;\r
}\r
//\r
//Set to valid and then if any tests fail it will update this flag.\r
//\r
- *ImageUpdateable = IMAGE_UPDATABLE_VALID;\r
+ *ImageUpdatable = IMAGE_UPDATABLE_VALID;\r
\r
if (Image == NULL) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - Image Pointer Parameter is NULL.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName));\r
//\r
// not sure if this is needed\r
//\r
- *ImageUpdateable = IMAGE_UPDATABLE_INVALID;\r
+ *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr);\r
\r
if (PublicKeyDataXdr == NULL || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: Invalid certificate, skipping it.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName));\r
Status = EFI_ABORTED;\r
} else {\r
//\r
Index++;\r
DEBUG (\r
(DEBUG_INFO,\r
- "FmpDxe: Certificate #%d [%p..%p].\n",\r
+ "FmpDxe(%s): Certificate #%d [%p..%p].\n",\r
+ mImageIdName,\r
Index,\r
PublicKeyDataXdr,\r
PublicKeyDataXdrEnd\r
//\r
// Key data extends beyond end of PCD\r
//\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: Certificate size extends beyond end of PCD, skipping it.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate size extends beyond end of PCD, skipping it.\n", mImageIdName));\r
Status = EFI_ABORTED;\r
break;\r
}\r
//\r
// Key data extends beyond end of PCD\r
//\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: Certificate extends beyond end of PCD, skipping it.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName));\r
Status = EFI_ABORTED;\r
break;\r
}\r
}\r
\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - Authentication Failed %r.\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Authentication Failed %r.\n", mImageIdName, Status));\r
goto cleanup;\r
}\r
\r
// Check to make sure index is 1\r
//\r
if (ImageIndex != 1) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - Image Index Invalid.\n"));\r
- *ImageUpdateable = IMAGE_UPDATABLE_INVALID_TYPE;\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName));\r
+ *ImageUpdatable = IMAGE_UPDATABLE_INVALID_TYPE;\r
Status = EFI_SUCCESS;\r
goto cleanup;\r
}\r
//\r
FmpPayloadHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize );\r
if (FmpPayloadHeader == NULL) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpHeader failed.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));\r
Status = EFI_ABORTED;\r
goto cleanup;\r
}\r
Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", Status));\r
- *ImageUpdateable = IMAGE_UPDATABLE_INVALID;\r
- Status = EFI_SUCCESS;\r
- goto cleanup;\r
+ //\r
+ // Check if there is dependency expression\r
+ //\r
+ IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP*) FmpPayloadHeader, FmpPayloadSize, &DependenciesSize);\r
+ if (IsDepexValid && (DependenciesSize < FmpPayloadSize)) {\r
+ //\r
+ // Fmp payload is after dependency expression\r
+ //\r
+ Dependencies = (EFI_FIRMWARE_IMAGE_DEP*) FmpPayloadHeader;\r
+ FmpPayloadHeader = (UINT8 *) Dependencies + DependenciesSize;\r
+ FmpPayloadSize = FmpPayloadSize - DependenciesSize;\r
+ Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));\r
+ *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
+ Status = EFI_SUCCESS;\r
+ goto cleanup;\r
+ }\r
+ } else {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency is invalid.\n", mImageIdName));\r
+ mDependenciesCheckStatus = DEPENDENCIES_INVALID;\r
+ *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
+ Status = EFI_SUCCESS;\r
+ goto cleanup;\r
+ }\r
+ } else {\r
+ DEBUG ((DEBUG_WARN, "FmpDxe(%s): CheckTheImage() - No dependency associated in image.\n", mImageIdName));\r
}\r
\r
//\r
// Check the lowest supported version\r
//\r
- if (Version < mDesc.LowestSupportedImageVersion) {\r
+ if (Version < Private->Descriptor.LowestSupportedImageVersion) {\r
DEBUG (\r
(DEBUG_ERROR,\r
- "FmpDxe: CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",\r
- Version, mDesc.LowestSupportedImageVersion)\r
+ "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",\r
+ mImageIdName, Version, Private->Descriptor.LowestSupportedImageVersion)\r
);\r
- *ImageUpdateable = IMAGE_UPDATABLE_INVALID_OLD;\r
+ *ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;\r
+ Status = EFI_SUCCESS;\r
+ goto cleanup;\r
+ }\r
+\r
+ //\r
+ // Evaluate dependency expression\r
+ //\r
+ Status = EvaluateImageDependencies (Private->Descriptor.ImageTypeId, Version, Dependencies, DependenciesSize, &IsDepexSatisfied);\r
+ if (!IsDepexSatisfied || EFI_ERROR (Status)) {\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed %r.\n", mImageIdName, Status));\r
+ } else {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency is not satisfied.\n", mImageIdName));\r
+ }\r
+ mDependenciesCheckStatus = DEPENDENCIES_UNSATISFIED;\r
+ *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
Status = EFI_SUCCESS;\r
goto cleanup;\r
}\r
Status = GetFmpPayloadHeaderSize (FmpPayloadHeader, FmpPayloadSize, &FmpHeaderSize);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));\r
- *ImageUpdateable = IMAGE_UPDATABLE_INVALID;\r
+ *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
Status = EFI_SUCCESS;\r
goto cleanup;\r
}\r
// Call FmpDevice Lib Check Image on the\r
// Raw payload. So all headers need stripped off\r
//\r
- AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize );\r
+ AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);\r
if (AllHeaderSize == 0) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetAllHeaderSize failed.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName));\r
Status = EFI_ABORTED;\r
goto cleanup;\r
}\r
//\r
// FmpDeviceLib CheckImage function to do any specific checks\r
//\r
- Status = FmpDeviceCheckImage ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdateable);\r
+ Status = FmpDeviceCheckImage ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdatable);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName, Status));\r
}\r
\r
cleanup:\r
OUT CHAR16 **AbortReason\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 Updateable;\r
- BOOLEAN BooleanValue;\r
- UINT32 FmpHeaderSize;\r
- VOID *FmpHeader;\r
- UINTN FmpPayloadSize;\r
- UINT32 AllHeaderSize;\r
- UINT32 IncommingFwVersion;\r
- UINT32 LastAttemptStatus;\r
- EFI_STATUS GetAttributesStatus;\r
- UINT64 AttributesSupported;\r
- UINT64 AttributesSetting;\r
+ EFI_STATUS Status;\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
+ UINT32 Updateable;\r
+ BOOLEAN BooleanValue;\r
+ UINT32 FmpHeaderSize;\r
+ VOID *FmpHeader;\r
+ UINTN FmpPayloadSize;\r
+ UINT32 AllHeaderSize;\r
+ UINT32 IncomingFwVersion;\r
+ UINT32 LastAttemptStatus;\r
+ UINT32 Version;\r
+ UINT32 LowestSupportedVersion;\r
+ EFI_FIRMWARE_IMAGE_DEP *Dependencies;\r
+ UINT32 DependenciesSize;\r
+ BOOLEAN IsDepexValid;\r
+ UINT8 *ImageBuffer;\r
+ UINTN ImageBufferSize;\r
\r
Status = EFI_SUCCESS;\r
Updateable = 0;\r
FmpHeader = NULL;\r
FmpPayloadSize = 0;\r
AllHeaderSize = 0;\r
- IncommingFwVersion = 0;\r
+ IncomingFwVersion = 0;\r
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
+ Dependencies = NULL;\r
+ DependenciesSize = 0;\r
+ ImageBuffer = NULL;\r
+ ImageBufferSize = 0;\r
+\r
+ if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
\r
+ //\r
+ // Retrieve the private context structure\r
+ //\r
+ Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+\r
+ //\r
+ // Make sure the descriptor has already been loaded or refreshed\r
+ //\r
+ PopulateDescriptor (Private);\r
\r
- SetLastAttemptVersionInVariable (IncommingFwVersion); //set to 0 to clear any previous results.\r
+ //\r
+ // Set to 0 to clear any previous results.\r
+ //\r
+ SetLastAttemptVersionInVariable (Private, IncomingFwVersion);\r
\r
//\r
// if we have locked the device, then skip the set operation.\r
// it should be blocked by hardware too but we can catch here even faster\r
//\r
- if (mFmpDeviceLocked) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Device is already locked. Can't update.\n"));\r
+ if (Private->FmpDeviceLocked) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Device is already locked. Can't update.\n", mImageIdName));\r
Status = EFI_UNSUPPORTED;\r
goto cleanup;\r
}\r
\r
+ //\r
+ // Set check status to satisfied before CheckTheImage()\r
+ //\r
+ mDependenciesCheckStatus = DEPENDENCIES_SATISFIED;\r
+\r
//\r
// Call check image to verify the image\r
//\r
Status = CheckTheImage (This, ImageIndex, Image, ImageSize, &Updateable);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Check The Image failed with %r.\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName, Status));\r
if (Status == EFI_SECURITY_VIOLATION) {\r
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;\r
}\r
//\r
FmpHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize );\r
if (FmpHeader == NULL) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetFmpHeader failed.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));\r
Status = EFI_ABORTED;\r
goto cleanup;\r
}\r
- Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncommingFwVersion);\r
+ Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Check if there is dependency expression\r
+ //\r
+ IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP*) FmpHeader, FmpPayloadSize, &DependenciesSize);\r
+ if (IsDepexValid && (DependenciesSize < FmpPayloadSize)) {\r
+ //\r
+ // Fmp payload is after dependency expression\r
+ //\r
+ Dependencies = (EFI_FIRMWARE_IMAGE_DEP*) FmpHeader;\r
+ FmpHeader = (UINT8 *) FmpHeader + DependenciesSize;\r
+ FmpPayloadSize = FmpPayloadSize - DependenciesSize;\r
+ Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);\r
+ }\r
+ }\r
if (!EFI_ERROR (Status)) {\r
//\r
// Set to actual value\r
//\r
- SetLastAttemptVersionInVariable (IncommingFwVersion);\r
+ SetLastAttemptVersionInVariable (Private, IncomingFwVersion);\r
}\r
\r
\r
if (Updateable != IMAGE_UPDATABLE_VALID) {\r
DEBUG (\r
(DEBUG_ERROR,\r
- "FmpDxed: SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",\r
- Updateable)\r
+ "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",\r
+ mImageIdName, Updateable)\r
);\r
+ if (mDependenciesCheckStatus == DEPENDENCIES_UNSATISFIED) {\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;\r
+ } else if (mDependenciesCheckStatus == DEPENDENCIES_INVALID) {\r
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;\r
+ }\r
Status = EFI_ABORTED;\r
goto cleanup;\r
}\r
\r
if (Progress == NULL) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Invalid progress callback\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName));\r
Status = EFI_INVALID_PARAMETER;\r
goto cleanup;\r
}\r
\r
mProgressFunc = Progress;\r
- mProgressSupported = TRUE;\r
\r
//\r
// Checking the image is at least 1%\r
//\r
Status = Progress (1);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Progress Callback failed with Status %r.\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Progress Callback failed with Status %r.\n", mImageIdName, Status));\r
}\r
\r
//\r
//\r
Status = CheckSystemPower (&BooleanValue);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemPower - API call failed %r.\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName, Status));\r
goto cleanup;\r
}\r
if (!BooleanValue) {\r
Status = EFI_ABORTED;\r
DEBUG (\r
(DEBUG_ERROR,\r
- "FmpDxe: SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n")\r
+ "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n", mImageIdName)\r
);\r
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT;\r
goto cleanup;\r
//\r
Status = CheckSystemThermal (&BooleanValue);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemThermal - API call failed %r.\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName, Status));\r
goto cleanup;\r
}\r
if (!BooleanValue) {\r
Status = EFI_ABORTED;\r
DEBUG (\r
(DEBUG_ERROR,\r
- "FmpDxe: SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n")\r
+ "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n", mImageIdName)\r
);\r
goto cleanup;\r
}\r
//\r
Status = CheckSystemEnvironment (&BooleanValue);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName, Status));\r
goto cleanup;\r
}\r
if (!BooleanValue) {\r
Status = EFI_ABORTED;\r
DEBUG (\r
(DEBUG_ERROR,\r
- "FmpDxe: SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n")\r
+ "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n", mImageIdName)\r
);\r
goto cleanup;\r
}\r
// Save LastAttemptStatus as error so that if SetImage never returns the error\r
// state is recorded.\r
//\r
- SetLastAttemptStatusInVariable (LastAttemptStatus);\r
+ SetLastAttemptStatusInVariable (Private, LastAttemptStatus);\r
\r
//\r
// Strip off all the headers so the device can process its firmware\r
//\r
Status = GetFmpPayloadHeaderSize (FmpHeader, FmpPayloadSize, &FmpHeaderSize);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName, Status));\r
goto cleanup;\r
}\r
\r
- AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize );\r
+ AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);\r
if (AllHeaderSize == 0) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetAllHeaderSize failed.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName));\r
Status = EFI_ABORTED;\r
goto cleanup;\r
}\r
\r
+ //\r
+ // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY\r
+ //\r
+ if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {\r
+ //\r
+ // To support saving dependency, extend param "Image" of FmpDeviceSetImage() to\r
+ // contain the dependency inside. FmpDeviceSetImage() is responsible for saving\r
+ // the dependency which can be used for future dependency check.\r
+ //\r
+ ImageBufferSize = DependenciesSize + ImageSize - AllHeaderSize;\r
+ ImageBuffer = AllocatePool (ImageBufferSize);\r
+ if (ImageBuffer == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - AllocatePool failed.\n", mImageIdName));\r
+ Status = EFI_ABORTED;\r
+ goto cleanup;\r
+ }\r
+ CopyMem (ImageBuffer, Dependencies->Dependencies, DependenciesSize);\r
+ CopyMem (ImageBuffer + DependenciesSize, (UINT8 *)Image + AllHeaderSize, ImageBufferSize - DependenciesSize);\r
+ } else {\r
+ ImageBufferSize = ImageSize - AllHeaderSize;\r
+ ImageBuffer = AllocateCopyPool(ImageBufferSize, (UINT8 *)Image + AllHeaderSize);\r
+ if (ImageBuffer == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - AllocatePool failed.\n", mImageIdName));\r
+ Status = EFI_ABORTED;\r
+ goto cleanup;\r
+ }\r
+ }\r
+\r
//\r
// Indicate that control is handed off to FmpDeviceLib\r
//\r
//Copy the requested image to the firmware using the FmpDeviceLib\r
//\r
Status = FmpDeviceSetImage (\r
- (((UINT8 *)Image) + AllHeaderSize),\r
- ImageSize - AllHeaderSize,\r
+ ImageBuffer,\r
+ ImageBufferSize,\r
VendorCode,\r
FmpDxeProgress,\r
- IncommingFwVersion,\r
+ IncomingFwVersion,\r
AbortReason\r
);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", mImageIdName, Status));\r
goto cleanup;\r
}\r
\r
//\r
// Update the version stored in variable\r
//\r
- if (!mRuntimeVersionSupported) {\r
- UINT32 Version = DEFAULT_VERSION;\r
+ if (!Private->RuntimeVersionSupported) {\r
+ Version = DEFAULT_VERSION;\r
GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);\r
- SetVersionInVariable (Version);\r
+ SetVersionInVariable (Private, Version);\r
}\r
\r
//\r
// Update lowest supported variable\r
//\r
- {\r
- UINT32 Version = DEFAULT_LOWESTSUPPORTEDVERSION;\r
- GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &Version);\r
- SetLowestSupportedVersionInVariable (Version);\r
- }\r
+ LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
+ GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);\r
+ SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion);\r
\r
LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
\r
- //\r
- // Set flag so the descriptor is repopulated\r
- // This is only applied to devices that do not require reset\r
- //\r
- GetAttributesStatus = FmpDeviceGetAttributes (&AttributesSupported, &AttributesSetting);\r
- if (!EFI_ERROR (GetAttributesStatus)) {\r
- if (((AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED) == 0) ||\r
- ((AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED) == 0)) {\r
- mDescriptorPopulated = FALSE;\r
- }\r
+cleanup:\r
+ if (ImageBuffer != NULL) {\r
+ FreePool (ImageBuffer);\r
}\r
\r
-cleanup:\r
mProgressFunc = NULL;\r
- mProgressSupported = FALSE;\r
- SetLastAttemptStatusInVariable (LastAttemptStatus);\r
+ SetLastAttemptStatusInVariable (Private, LastAttemptStatus);\r
\r
if (Progress != NULL) {\r
//\r
Progress (100);\r
}\r
\r
+ //\r
+ // Need repopulate after SetImage is called to\r
+ // update LastAttemptVersion and LastAttemptStatus.\r
+ //\r
+ Private->DescriptorPopulated = FALSE;\r
+\r
return Status;\r
}\r
\r
IN VOID *Context\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
\r
- if (!mFmpDeviceLocked) {\r
- if (IsLockFmpDeviceAtLockEventGuidRequired ()) {\r
- //\r
- // Lock all UEFI Variables used by this module.\r
- //\r
- Status = LockAllFmpVariables ();\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variables. Status = %r.\n"));\r
- } else {\r
- DEBUG ((DEBUG_INFO, "FmpDxe: All variables locked\n"));\r
- }\r
+ Private = (FIRMWARE_MANAGEMENT_PRIVATE_DATA *)Context;\r
\r
- //\r
- // Lock the firmware device\r
- //\r
- Status = FmpDeviceLock();\r
- if (EFI_ERROR (Status)) {\r
- if (Status != EFI_UNSUPPORTED) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status));\r
- } else {\r
- DEBUG ((DEBUG_WARN, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status));\r
- }\r
+ if (!Private->FmpDeviceLocked) {\r
+ //\r
+ // Lock the firmware device\r
+ //\r
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+ Status = FmpDeviceLock();\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status != EFI_UNSUPPORTED) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));\r
+ } else {\r
+ DEBUG ((DEBUG_WARN, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));\r
}\r
- mFmpDeviceLocked = TRUE;\r
- } else {\r
- DEBUG ((DEBUG_VERBOSE, "FmpDxe: Not calling FmpDeviceLock() because mfg mode\n"));\r
}\r
+ Private->FmpDeviceLocked = TRUE;\r
}\r
}\r
\r
IN EFI_HANDLE Handle\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
- EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *FmpProgress;\r
-\r
- Status = EFI_SUCCESS;\r
- Fmp = NULL;\r
- FmpProgress = NULL;\r
+ EFI_STATUS Status;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
\r
//\r
// Only allow a single FMP Protocol instance to be installed\r
//\r
- if (mFmpInstalled) {\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ (VOID **)&Fmp,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
return EFI_ALREADY_STARTED;\r
}\r
\r
//\r
// Allocate FMP Protocol instance\r
//\r
- Fmp = AllocateZeroPool (sizeof (EFI_FIRMWARE_MANAGEMENT_PROTOCOL));\r
- if (Fmp == NULL) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for FMP Protocol instance.\n"));\r
+ Private = AllocateCopyPool (\r
+ sizeof (mFirmwareManagementPrivateDataTemplate),\r
+ &mFirmwareManagementPrivateDataTemplate\r
+ );\r
+ if (Private == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to allocate memory for private structure.\n", mImageIdName));\r
Status = EFI_OUT_OF_RESOURCES;\r
goto cleanup;\r
}\r
\r
//\r
- // Allocate FMP Progress Protocol instance\r
+ // Initialize private context data structure\r
//\r
- FmpProgress = AllocateZeroPool (sizeof (EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL));\r
- if (FmpProgress == NULL) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for FMP Progress Protocol instance.\n"));\r
- Status = EFI_OUT_OF_RESOURCES;\r
- FreePool (Fmp);\r
+ Private->Handle = Handle;\r
+ Private->FmpDeviceContext = NULL;\r
+ Status = FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ Private->FmpDeviceContext = NULL;\r
+ } else if (EFI_ERROR (Status)) {\r
goto cleanup;\r
}\r
\r
//\r
- // Set up FMP Protocol function pointers\r
+ // Make sure the descriptor has already been loaded or refreshed\r
//\r
- Fmp->GetImageInfo = GetTheImageInfo;\r
- Fmp->GetImage = GetTheImage;\r
- Fmp->SetImage = SetTheImage;\r
- Fmp->CheckImage = CheckTheImage;\r
- Fmp->GetPackageInfo = GetPackageInfo;\r
- Fmp->SetPackageInfo = SetPackageInfo;\r
+ PopulateDescriptor (Private);\r
\r
- //\r
- // Fill in FMP Progress Protocol fields for Version 1\r
- //\r
- FmpProgress->Version = 1;\r
- FmpProgress->ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);\r
- FmpProgress->WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);\r
+ if (IsLockFmpDeviceAtLockEventGuidRequired ()) {\r
+ //\r
+ // Register all UEFI Variables used by this module to be locked.\r
+ //\r
+ Status = LockAllFmpVariables (Private);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register variables to lock. Status = %r.\n", mImageIdName, Status));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): All variables registered to lock\n", mImageIdName));\r
+ }\r
+\r
+ //\r
+ // Create and register notify function to lock the FMP device.\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ FmpDxeLockEventNotify,\r
+ Private,\r
+ mLockGuid,\r
+ &Private->FmpDeviceLockEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register notification. Status = %r\n", mImageIdName, Status));\r
+ }\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): Not registering notification to call FmpDeviceLock() because mfg mode\n", mImageIdName));\r
+ }\r
\r
//\r
// Install FMP Protocol and FMP Progress Protocol\r
//\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Handle,\r
- &gEfiFirmwareManagementProtocolGuid,\r
- Fmp,\r
- &gEdkiiFirmwareManagementProgressProtocolGuid,\r
- FmpProgress,\r
+ &Private->Handle,\r
+ &gEfiFirmwareManagementProtocolGuid, &Private->Fmp,\r
+ &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress,\r
NULL\r
);\r
-\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: FMP Protocol install error. Status = %r.\n", Status));\r
- FreePool (Fmp);\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol install error. Status = %r.\n", mImageIdName, Status));\r
goto cleanup;\r
}\r
\r
- DEBUG ((DEBUG_INFO, "FmpDxe: FMP Protocol Installed!\n"));\r
- mFmpInstalled = TRUE;\r
-\r
cleanup:\r
\r
+ if (EFI_ERROR (Status)) {\r
+ if (Private != NULL) {\r
+ if (Private->FmpDeviceLockEvent != NULL) {\r
+ gBS->CloseEvent (Private->FmpDeviceLockEvent);\r
+ }\r
+ if (Private->Descriptor.VersionName != NULL) {\r
+ FreePool (Private->Descriptor.VersionName);\r
+ }\r
+ if (Private->FmpDeviceContext != NULL) {\r
+ FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
+ }\r
+ if (Private->VersionVariableName != NULL) {\r
+ FreePool (Private->VersionVariableName);\r
+ }\r
+ if (Private->LsvVariableName != NULL) {\r
+ FreePool (Private->LsvVariableName);\r
+ }\r
+ if (Private->LastAttemptStatusVariableName != NULL) {\r
+ FreePool (Private->LastAttemptStatusVariableName);\r
+ }\r
+ if (Private->LastAttemptVersionVariableName != NULL) {\r
+ FreePool (Private->LastAttemptVersionVariableName);\r
+ }\r
+ if (Private->FmpStateVariableName != NULL) {\r
+ FreePool (Private->FmpStateVariableName);\r
+ }\r
+ FreePool (Private);\r
+ }\r
+ }\r
+\r
return Status;\r
}\r
\r
+/**\r
+ Function to uninstall FMP instance.\r
+\r
+ @param[in] Handle The device handle to install a FMP instance on.\r
+\r
+ @retval EFI_SUCCESS FMP Installed\r
+ @retval EFI_INVALID_PARAMETER Handle was invalid\r
+ @retval other Error installing FMP\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UninstallFmpInstance (\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ (VOID **)&Fmp,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol open error. Status = %r.\n", mImageIdName, Status));\r
+ return Status;\r
+ }\r
+\r
+ Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (Fmp);\r
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+\r
+ if (Private->FmpDeviceLockEvent != NULL) {\r
+ gBS->CloseEvent (Private->FmpDeviceLockEvent);\r
+ }\r
+\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ Private->Handle,\r
+ &gEfiFirmwareManagementProtocolGuid, &Private->Fmp,\r
+ &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol uninstall error. Status = %r.\n", mImageIdName, Status));\r
+ return Status;\r
+ }\r
+\r
+ if (Private->Descriptor.VersionName != NULL) {\r
+ FreePool (Private->Descriptor.VersionName);\r
+ }\r
+ if (Private->FmpDeviceContext != NULL) {\r
+ FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
+ }\r
+ if (Private->VersionVariableName != NULL) {\r
+ FreePool (Private->VersionVariableName);\r
+ }\r
+ if (Private->LsvVariableName != NULL) {\r
+ FreePool (Private->LsvVariableName);\r
+ }\r
+ if (Private->LastAttemptStatusVariableName != NULL) {\r
+ FreePool (Private->LastAttemptStatusVariableName);\r
+ }\r
+ if (Private->LastAttemptVersionVariableName != NULL) {\r
+ FreePool (Private->LastAttemptVersionVariableName);\r
+ }\r
+ if (Private->FmpStateVariableName != NULL) {\r
+ FreePool (Private->FmpStateVariableName);\r
+ }\r
+ FreePool (Private);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Unloads the application and its installed protocol.\r
+\r
+ @param ImageHandle Handle that identifies the image to be unloaded.\r
+ @param SystemTable The system table.\r
+\r
+ @retval EFI_SUCCESS The image has been unloaded.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FmpDxeLibDestructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ if (mFmpSingleInstance) {\r
+ return UninstallFmpInstance (ImageHandle);\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Main entry for this driver/library.\r
\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_GUID *LockGuid;\r
\r
//\r
// Verify that a new FILE_GUID value has been provided in the <Defines>\r
//\r
// PcdFmpDeviceImageIdName must be set to a non-empty Unicode string\r
//\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib PcdFmpDeviceImageIdName is an empty string.\n"));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe: PcdFmpDeviceImageIdName is an empty string.\n"));\r
ASSERT (FALSE);\r
+ return EFI_UNSUPPORTED;\r
}\r
\r
//\r
//\r
DetectTestKey ();\r
\r
+ //\r
+ // Fill in FMP Progress Protocol fields for Version 1\r
+ //\r
+ mFmpProgress.Version = 1;\r
+ mFmpProgress.ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);\r
+ mFmpProgress.WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);\r
+\r
+ // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.\r
+ // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then\r
+ // gEfiEndOfDxeEventGroupGuid is used.\r
+ //\r
+ mLockGuid = &gEfiEndOfDxeEventGroupGuid;\r
+ if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {\r
+ mLockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);\r
+ }\r
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): Lock GUID: %g\n", mImageIdName, mLockGuid));\r
+\r
//\r
// Register with library the install function so if the library uses\r
// UEFI driver model/driver binding protocol it can install FMP on its device handle\r
//\r
Status = RegisterFmpInstaller (InstallFmpInstance);\r
if (Status == EFI_UNSUPPORTED) {\r
- DEBUG ((DEBUG_INFO, "FmpDxe: FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n"));\r
- Status = InstallFmpInstance (ImageHandle);\r
+ mFmpSingleInstance = TRUE;\r
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n", mImageIdName));\r
+ Status = RegisterFmpUninstaller (UninstallFmpInstance);\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ Status = InstallFmpInstance (ImageHandle);\r
+ } else {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
} else if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib registration returned %r. No FMP installed.\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib registration returned %r. No FMP installed.\n", mImageIdName, Status));\r
} else {\r
DEBUG ((\r
DEBUG_INFO,\r
- "FmpDxe: FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n"\r
+ "FmpDxe(%s): FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n",\r
+ mImageIdName\r
));\r
+ Status = RegisterFmpUninstaller (UninstallFmpInstance);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));\r
+ }\r
}\r
\r
- //\r
- // Register notify function to lock the FMP device.\r
- // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.\r
- // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then\r
- // gEfiEndOfDxeEventGroupGuid is used.\r
- //\r
- LockGuid = &gEfiEndOfDxeEventGroupGuid;\r
- if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {\r
- LockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);\r
- }\r
- DEBUG ((DEBUG_INFO, "FmpDxe: Lock GUID: %g\n", LockGuid));\r
-\r
- Status = gBS->CreateEventEx (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_CALLBACK,\r
- FmpDxeLockEventNotify,\r
- NULL,\r
- LockGuid,\r
- &mFmpDeviceLockEvent\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to register for ready to boot. Status = %r\n", Status));\r
- }\r
- ASSERT_EFI_ERROR (Status);\r
-\r
return Status;\r
}\r