X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=FmpDevicePkg%2FFmpDxe%2FFmpDxe.c;h=3cda86f6c46cca73b49b9d4e4f605437f94749a3;hb=e0961677d1b226c11fc39de4df2c2ecd0e7b9adc;hp=3544afd3dee744131f2bd3f1b129ff36ba64b4b3;hpb=f1a921cab2b8d5ca587059795ff57d9fc92b8995;p=mirror_edk2.git diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.c b/FmpDevicePkg/FmpDxe/FmpDxe.c index 3544afd3de..3cda86f6c4 100644 --- a/FmpDevicePkg/FmpDxe/FmpDxe.c +++ b/FmpDevicePkg/FmpDxe/FmpDxe.c @@ -1,67 +1,18 @@ -/** @file +/** @file Produces a Firmware Management Protocol that supports updates to a firmware image stored in a firmware device with platform and firmware device specific information provided through PCDs and libraries. Copyright (c) 2016, Microsoft Corporation. All rights reserved.
- Copyright (c) 2018, Intel Corporation. All rights reserved.
- - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent **/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "FmpDxe.h" #include "VariableSupport.h" -#define VERSION_STRING_NOT_SUPPORTED L"VERSION STRING NOT SUPPORTED" -#define VERSION_STRING_NOT_AVAILABLE L"VERSION STRING NOT AVAILABLE" - -/** - Check to see if any of the keys in PcdFmpDevicePkcs7CertBufferXdr matches - the test key. PcdFmpDeviceTestKeySha256Digest contains the SHA256 hash of - the test key. For each key in PcdFmpDevicePkcs7CertBufferXdr, compute the - SHA256 hash and compare it to PcdFmpDeviceTestKeySha256Digest. If the - SHA256 hash matches or there is then error computing the SHA256 hash, then - set PcdTestKeyUsed to TRUE. Skip this check if PcdTestKeyUsed is already - TRUE or PcdFmpDeviceTestKeySha256Digest is not exactly SHA256_DIGEST_SIZE - bytes. -**/ -VOID -DetectTestKey ( - VOID - ); - /// /// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the /// FILE_GUID must always be overridden in the section to provide @@ -73,23 +24,79 @@ const EFI_GUID mDefaultModuleFileGuid = { 0x78ef0a56, 0x1cf0, 0x4535, { 0xb5, 0xda, 0xf6, 0xfd, 0x2f, 0x40, 0x5a, 0x11 } }; -EFI_FIRMWARE_IMAGE_DESCRIPTOR mDesc; -BOOLEAN mDescriptorPopulated = FALSE; -BOOLEAN mRuntimeVersionSupported = TRUE; -BOOLEAN mFmpInstalled = FALSE; +/// +/// TRUE if FmpDeviceLib manages a single firmware storage device. +/// +BOOLEAN mFmpSingleInstance = FALSE; /// -/// Function pointer to progress function +/// Firmware Management Protocol instance that is initialized in the entry +/// point from PCD settings. /// -EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS mProgressFunc = NULL; -BOOLEAN mProgressSupported = FALSE; +EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL mFmpProgress; + +// +// Template of the private context structure for the Firmware Management +// Protocol instance +// +const FIRMWARE_MANAGEMENT_PRIVATE_DATA mFirmwareManagementPrivateDataTemplate = { + FIRMWARE_MANAGEMENT_PRIVATE_DATA_SIGNATURE, // Signature + NULL, // Handle + { // Fmp + GetTheImageInfo, + GetTheImage, + SetTheImage, + CheckTheImage, + GetPackageInfo, + SetPackageInfo + }, + FALSE, // DescriptorPopulated + { // Desc + 1, // ImageIndex + // + // ImageTypeId + // + { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, + 1, // ImageId + NULL, // ImageIdName + 0, // Version + NULL, // VersionName + 0, // Size + 0, // AttributesSupported + 0, // AttributesSetting + 0, // Compatibilities + 0, // LowestSupportedImageVersion + 0, // LastAttemptVersion + 0, // LastAttemptStatus + 0 // HardwareInstance + }, + NULL, // ImageIdName + NULL, // VersionName + TRUE, // RuntimeVersionSupported + NULL, // FmpDeviceLockEvent + FALSE, // FmpDeviceLocked + NULL, // FmpDeviceContext + NULL, // VersionVariableName + NULL, // LsvVariableName + NULL, // LastAttemptStatusVariableName + NULL, // LastAttemptVersionVariableName + NULL // FmpStateVariableName +}; -CHAR16 *mImageIdName = NULL; -UINT64 mImageId = 0x1; -CHAR16 *mVersionName = NULL; +/// +/// GUID that is used to create event used to lock the firmware storage device. +/// +EFI_GUID *mLockGuid = NULL; -EFI_EVENT mFmpDeviceLockEvent; -BOOLEAN mFmpDeviceLocked = FALSE; +/// +/// Progress() function pointer passed into SetTheImage() +/// +EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS mProgressFunc = NULL; + +/// +/// Null-terminated Unicode string retrieved from PcdFmpDeviceImageIdName. +/// +CHAR16 *mImageIdName = NULL; /** Callback function to report the process of the firmware updating. @@ -121,10 +128,6 @@ FmpDxeProgress ( Status = EFI_UNSUPPORTED; - if (!mProgressSupported) { - return Status; - } - if (mProgressFunc == NULL) { return Status; } @@ -135,7 +138,6 @@ FmpDxeProgress ( Status = mProgressFunc (((Completion * 92) / 100) + 6); if (Status == EFI_UNSUPPORTED) { - mProgressSupported = FALSE; mProgressFunc = NULL; } @@ -147,7 +149,7 @@ FmpDxeProgress ( the GUID value from the FmpDeviceLib. If the FmpDeviceLib does not provide a GUID value, then gEfiCallerIdGuid is returned. - @return The ImageTypeId GUID + @retval The ImageTypeId GUID **/ EFI_GUID * @@ -162,12 +164,12 @@ GetImageTypeIdGuid ( Status = FmpDeviceGetImageTypeIdGuidPtr (&FmpDeviceLibGuid); if (EFI_ERROR (Status)) { if (Status != EFI_UNSUPPORTED) { - DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", Status)); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", mImageIdName, Status)); } return &gEfiCallerIdGuid; } if (FmpDeviceLibGuid == NULL) { - DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n", mImageIdName)); return &gEfiCallerIdGuid; } return FmpDeviceLibGuid; @@ -176,7 +178,7 @@ GetImageTypeIdGuid ( /** Returns a pointer to the Null-terminated Unicode ImageIdName string. - @return Null-terminated Unicode ImageIdName string. + @retval Null-terminated Unicode ImageIdName string. **/ CHAR16 * @@ -193,12 +195,15 @@ GetImageTypeNameString ( 2. Check if we have a variable for lowest supported version (this will be updated with each capsule applied) 3. Check Fixed at build PCD - Take the largest value + @param[in] Private Pointer to the private context structure for the + Firmware Management Protocol instance. + + @retval The largest value **/ UINT32 GetLowestSupportedVersion ( - VOID + FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private ) { EFI_STATUS Status; @@ -222,6 +227,7 @@ GetLowestSupportedVersion ( // // Check the FmpDeviceLib // + DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION; Status = FmpDeviceGetLowestSupportedVersion (&DeviceLibLowestSupportedVersion); if (EFI_ERROR (Status)) { DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION; @@ -234,7 +240,7 @@ GetLowestSupportedVersion ( // // Check the lowest supported version UEFI variable for this device // - VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable(); + VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable (Private); if (VariableLowestSupportedVersion > ReturnLsv) { ReturnLsv = VariableLowestSupportedVersion; } @@ -246,101 +252,123 @@ GetLowestSupportedVersion ( } /** - Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the module global - variable mDesc. + Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the private + context structure. + + @param[in] Private Pointer to the private context structure for the + Firmware Management Protocol instance. **/ VOID PopulateDescriptor ( - VOID + FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private ) { EFI_STATUS Status; - mDesc.ImageIndex = 1; - CopyGuid (&mDesc.ImageTypeId, GetImageTypeIdGuid()); - mDesc.ImageId = mImageId; - mDesc.ImageIdName = GetImageTypeNameString(); + if (Private->DescriptorPopulated) { + return; + } + + Private->Descriptor.ImageIndex = 1; + CopyGuid (&Private->Descriptor.ImageTypeId, GetImageTypeIdGuid()); + Private->Descriptor.ImageId = Private->Descriptor.ImageIndex; + Private->Descriptor.ImageIdName = GetImageTypeNameString(); + + // + // Get the hardware instance from FmpDeviceLib + // + Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance); + if (Status == EFI_UNSUPPORTED) { + Private->Descriptor.HardwareInstance = 0; + } + + // + // Generate UEFI Variable names used to store status information for this + // FMP instance. + // + GenerateFmpVariableNames (Private); // // Get the version. Some devices don't support getting the firmware version // at runtime. If FmpDeviceLib does not support returning a version, then // it is stored in a UEFI variable. // - Status = FmpDeviceGetVersion (&mDesc.Version); + Status = FmpDeviceGetVersion (&Private->Descriptor.Version); if (Status == EFI_UNSUPPORTED) { - mRuntimeVersionSupported = FALSE; - mDesc.Version = GetVersionFromVariable(); + Private->RuntimeVersionSupported = FALSE; + Private->Descriptor.Version = GetVersionFromVariable (Private); } else if (EFI_ERROR (Status)) { // // Unexpected error. Use default version. // - DEBUG ((DEBUG_ERROR, "FmpDxe: GetVersion() from FmpDeviceLib (%s) returned %r\n", GetImageTypeNameString(), Status)); - mDesc.Version = DEFAULT_VERSION; + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetVersion() from FmpDeviceLib (%s) returned %r\n", mImageIdName, GetImageTypeNameString(), Status)); + Private->Descriptor.Version = DEFAULT_VERSION; } // // Free the current version name. Shouldn't really happen but this populate // function could be called multiple times (to refresh). // - if (mVersionName != NULL) { - FreePool (mVersionName); - mVersionName = NULL; + if (Private->Descriptor.VersionName != NULL) { + FreePool (Private->Descriptor.VersionName); + Private->Descriptor.VersionName = NULL; } // // Attempt to get the version string from the FmpDeviceLib // - Status = FmpDeviceGetVersionString (&mVersionName); + Status = FmpDeviceGetVersionString (&Private->Descriptor.VersionName); if (Status == EFI_UNSUPPORTED) { - DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() unsupported in FmpDeviceLib.\n")); - mVersionName = AllocateCopyPool ( - sizeof (VERSION_STRING_NOT_SUPPORTED), - VERSION_STRING_NOT_SUPPORTED - ); + DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() unsupported in FmpDeviceLib.\n", mImageIdName)); + Private->Descriptor.VersionName = AllocateCopyPool ( + sizeof (VERSION_STRING_NOT_SUPPORTED), + VERSION_STRING_NOT_SUPPORTED + ); } else if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() not available in FmpDeviceLib.\n")); - mVersionName = AllocateCopyPool ( - sizeof (VERSION_STRING_NOT_AVAILABLE), - VERSION_STRING_NOT_AVAILABLE - ); + DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() not available in FmpDeviceLib.\n", mImageIdName)); + Private->Descriptor.VersionName = AllocateCopyPool ( + sizeof (VERSION_STRING_NOT_AVAILABLE), + VERSION_STRING_NOT_AVAILABLE + ); } - mDesc.VersionName = mVersionName; - - mDesc.LowestSupportedImageVersion = GetLowestSupportedVersion(); + Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion (Private); // // Get attributes from the FmpDeviceLib // - FmpDeviceGetAttributes (&mDesc.AttributesSupported, &mDesc.AttributesSetting); + FmpDeviceGetAttributes ( + &Private->Descriptor.AttributesSupported, + &Private->Descriptor.AttributesSetting + ); // // Force set the updatable bits in the attributes; // - mDesc.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; - mDesc.AttributesSetting |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; + Private->Descriptor.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; + Private->Descriptor.AttributesSetting |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; // // Force set the authentication bits in the attributes; // - mDesc.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED); - mDesc.AttributesSetting |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED); + Private->Descriptor.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED); + Private->Descriptor.AttributesSetting |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED); - mDesc.Compatibilities = 0; + Private->Descriptor.Compatibilities = 0; // // Get the size of the firmware image from the FmpDeviceLib // - Status = FmpDeviceGetSize (&mDesc.Size); + Status = FmpDeviceGetSize (&Private->Descriptor.Size); if (EFI_ERROR (Status)) { - mDesc.Size = 0; + Private->Descriptor.Size = 0; } - mDesc.LastAttemptVersion = GetLastAttemptVersionFromVariable (); - mDesc.LastAttemptStatus = GetLastAttemptStatusFromVariable (); + Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable (Private); + Private->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable (Private); - mDescriptorPopulated = TRUE; + Private->DescriptorPopulated = TRUE; } /** @@ -394,15 +422,22 @@ GetTheImageInfo ( OUT CHAR16 **PackageVersionName ) { - EFI_STATUS Status; + EFI_STATUS Status; + FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private; Status = EFI_SUCCESS; + // + // Retrieve the private context structure + // + Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This); + FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext); + // // Check for valid pointer // if (ImageInfoSize == NULL) { - DEBUG ((DEBUG_ERROR, "FmpDxe: GetImageInfo() - ImageInfoSize is NULL.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is NULL.\n", mImageIdName)); Status = EFI_INVALID_PARAMETER; goto cleanup; } @@ -413,7 +448,7 @@ GetTheImageInfo ( // if (*ImageInfoSize < (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR))) { *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR); - DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImageInfo() - ImageInfoSize is to small.\n")); + DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is to small.\n", mImageIdName)); Status = EFI_BUFFER_TOO_SMALL; goto cleanup; } @@ -423,7 +458,7 @@ GetTheImageInfo ( // if ( (ImageInfo == NULL) || (DescriptorVersion == NULL) || (DescriptorCount == NULL) || (DescriptorSize == NULL) || (PackageVersion == NULL)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: GetImageInfo() - Pointer Parameter is NULL.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - Pointer Parameter is NULL.\n", mImageIdName)); Status = EFI_INVALID_PARAMETER; goto cleanup; } @@ -433,15 +468,15 @@ GetTheImageInfo ( // *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR); - - if (!mDescriptorPopulated) { - PopulateDescriptor(); - } + // + // Make sure the descriptor has already been loaded or refreshed + // + PopulateDescriptor (Private); // // Copy the image descriptor // - CopyMem (ImageInfo, &mDesc, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR)); + CopyMem (ImageInfo, &Private->Descriptor, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR)); *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; *DescriptorCount = 1; @@ -466,11 +501,11 @@ cleanup: This function allows a copy of the current firmware image to be created and saved. The saved copy could later been used, for example, in firmware image recovery or rollback. - @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance. - @param[in] ImageIndex A unique number identifying the firmware image(s) within the device. + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance. + @param[in] ImageIndex A unique number identifying the firmware image(s) within the device. The number is between 1 and DescriptorCount. - @param[out] Image Points to the buffer where the current image is copied to. - @param[out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes. + @param[in, out] Image Points to the buffer where the current image is copied to. + @param[in, out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes. On return, points to the length of the image, in bytes. @retval EFI_SUCCESS The device was successfully updated with the new image. @@ -492,22 +527,29 @@ GetTheImage ( IN OUT UINTN *ImageSize ) { - EFI_STATUS Status; - UINTN Size; + EFI_STATUS Status; + FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private; + UINTN Size; Status = EFI_SUCCESS; + // + // Retrieve the private context structure + // + Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This); + FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext); + // // Check to make sure index is 1 (only 1 image for this device) // if (ImageIndex != 1) { - DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - Image Index Invalid.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Index Invalid.\n", mImageIdName)); Status = EFI_INVALID_PARAMETER; goto cleanup; } - if ((ImageSize == NULL)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - ImageSize Pointer Parameter is NULL.\n")); + if (ImageSize == NULL) { + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - ImageSize Pointer Parameter is NULL.\n", mImageIdName)); Status = EFI_INVALID_PARAMETER; goto cleanup; } @@ -521,13 +563,13 @@ GetTheImage ( } if (*ImageSize < Size) { *ImageSize = Size; - DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImage() - ImageSize is to small.\n")); + DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName)); Status = EFI_BUFFER_TOO_SMALL; goto cleanup; } if (Image == NULL) { - DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - Image Pointer Parameter is NULL.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Pointer Parameter is NULL.\n", mImageIdName)); Status = EFI_INVALID_PARAMETER; goto cleanup; } @@ -638,21 +680,22 @@ CheckTheImage ( IN UINT8 ImageIndex, IN CONST VOID *Image, IN UINTN ImageSize, - OUT UINT32 *ImageUpdateable + OUT UINT32 *ImageUpdatable ) { - EFI_STATUS Status; - UINTN RawSize; - VOID *FmpPayloadHeader; - UINTN FmpPayloadSize; - UINT32 Version; - UINT32 FmpHeaderSize; - UINTN AllHeaderSize; - UINT32 Index; - VOID *PublicKeyData; - UINTN PublicKeyDataLength; - UINT8 *PublicKeyDataXdr; - UINT8 *PublicKeyDataXdrEnd; + EFI_STATUS Status; + FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private; + UINTN RawSize; + VOID *FmpPayloadHeader; + UINTN FmpPayloadSize; + UINT32 Version; + UINT32 FmpHeaderSize; + UINTN AllHeaderSize; + UINT32 Index; + VOID *PublicKeyData; + UINTN PublicKeyDataLength; + UINT8 *PublicKeyDataXdr; + UINT8 *PublicKeyDataXdrEnd; Status = EFI_SUCCESS; RawSize = 0; @@ -663,14 +706,18 @@ CheckTheImage ( AllHeaderSize = 0; // - // make sure the descriptor has already been loaded + // Retrieve the private context structure // - if (!mDescriptorPopulated) { - PopulateDescriptor(); - } + Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This); + FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext); - if (ImageUpdateable == NULL) { - DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - ImageUpdateable Pointer Parameter is NULL.\n")); + // + // Make sure the descriptor has already been loaded or refreshed + // + PopulateDescriptor (Private); + + if (ImageUpdatable == NULL) { + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName)); Status = EFI_INVALID_PARAMETER; goto cleanup; } @@ -678,14 +725,14 @@ CheckTheImage ( // //Set to valid and then if any tests fail it will update this flag. // - *ImageUpdateable = IMAGE_UPDATABLE_VALID; + *ImageUpdatable = IMAGE_UPDATABLE_VALID; if (Image == NULL) { - DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - Image Pointer Parameter is NULL.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName)); // // not sure if this is needed // - *ImageUpdateable = IMAGE_UPDATABLE_INVALID; + *ImageUpdatable = IMAGE_UPDATABLE_INVALID; return EFI_INVALID_PARAMETER; } @@ -693,7 +740,7 @@ CheckTheImage ( PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr); if (PublicKeyDataXdr == NULL || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: Invalid certificate, skipping it.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName)); Status = EFI_ABORTED; } else { // @@ -703,7 +750,8 @@ CheckTheImage ( Index++; DEBUG ( (DEBUG_INFO, - "FmpDxe: Certificate #%d [%p..%p].\n", + "FmpDxe(%s): Certificate #%d [%p..%p].\n", + mImageIdName, Index, PublicKeyDataXdr, PublicKeyDataXdrEnd @@ -714,7 +762,7 @@ CheckTheImage ( // // Key data extends beyond end of PCD // - DEBUG ((DEBUG_ERROR, "FmpDxe: Certificate size extends beyond end of PCD, skipping it.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate size extends beyond end of PCD, skipping it.\n", mImageIdName)); Status = EFI_ABORTED; break; } @@ -730,7 +778,7 @@ CheckTheImage ( // // Key data extends beyond end of PCD // - DEBUG ((DEBUG_ERROR, "FmpDxe: Certificate extends beyond end of PCD, skipping it.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName)); Status = EFI_ABORTED; break; } @@ -750,7 +798,7 @@ CheckTheImage ( } if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - Authentication Failed %r.\n", Status)); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Authentication Failed %r.\n", mImageIdName, Status)); goto cleanup; } @@ -758,8 +806,8 @@ CheckTheImage ( // Check to make sure index is 1 // if (ImageIndex != 1) { - DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - Image Index Invalid.\n")); - *ImageUpdateable = IMAGE_UPDATABLE_INVALID_TYPE; + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName)); + *ImageUpdatable = IMAGE_UPDATABLE_INVALID_TYPE; Status = EFI_SUCCESS; goto cleanup; } @@ -770,14 +818,14 @@ CheckTheImage ( // FmpPayloadHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize ); if (FmpPayloadHeader == NULL) { - DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpHeader failed.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName)); Status = EFI_ABORTED; goto cleanup; } Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", Status)); - *ImageUpdateable = IMAGE_UPDATABLE_INVALID; + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status)); + *ImageUpdatable = IMAGE_UPDATABLE_INVALID; Status = EFI_SUCCESS; goto cleanup; } @@ -785,13 +833,13 @@ CheckTheImage ( // // Check the lowest supported version // - if (Version < mDesc.LowestSupportedImageVersion) { + if (Version < Private->Descriptor.LowestSupportedImageVersion) { DEBUG ( (DEBUG_ERROR, - "FmpDxe: CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n", - Version, mDesc.LowestSupportedImageVersion) + "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n", + mImageIdName, Version, Private->Descriptor.LowestSupportedImageVersion) ); - *ImageUpdateable = IMAGE_UPDATABLE_INVALID_OLD; + *ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD; Status = EFI_SUCCESS; goto cleanup; } @@ -802,7 +850,7 @@ CheckTheImage ( Status = GetFmpPayloadHeaderSize (FmpPayloadHeader, FmpPayloadSize, &FmpHeaderSize); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status)); - *ImageUpdateable = IMAGE_UPDATABLE_INVALID; + *ImageUpdatable = IMAGE_UPDATABLE_INVALID; Status = EFI_SUCCESS; goto cleanup; } @@ -813,7 +861,7 @@ CheckTheImage ( // AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize ); if (AllHeaderSize == 0) { - DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetAllHeaderSize failed.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName)); Status = EFI_ABORTED; goto cleanup; } @@ -822,9 +870,9 @@ CheckTheImage ( // // FmpDeviceLib CheckImage function to do any specific checks // - Status = FmpDeviceCheckImage ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdateable); + Status = FmpDeviceCheckImage ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdatable); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName, Status)); } cleanup: @@ -889,18 +937,18 @@ SetTheImage ( OUT CHAR16 **AbortReason ) { - EFI_STATUS Status; - UINT32 Updateable; - BOOLEAN BooleanValue; - UINT32 FmpHeaderSize; - VOID *FmpHeader; - UINTN FmpPayloadSize; - UINT32 AllHeaderSize; - UINT32 IncommingFwVersion; - UINT32 LastAttemptStatus; - EFI_STATUS GetAttributesStatus; - UINT64 AttributesSupported; - UINT64 AttributesSetting; + EFI_STATUS Status; + FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private; + UINT32 Updateable; + BOOLEAN BooleanValue; + UINT32 FmpHeaderSize; + VOID *FmpHeader; + UINTN FmpPayloadSize; + UINT32 AllHeaderSize; + UINT32 IncommingFwVersion; + UINT32 LastAttemptStatus; + UINT32 Version; + UINT32 LowestSupportedVersion; Status = EFI_SUCCESS; Updateable = 0; @@ -912,16 +960,29 @@ SetTheImage ( IncommingFwVersion = 0; LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + // + // Retrieve the private context structure + // + Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This); + FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext); + + // + // Make sure the descriptor has already been loaded or refreshed + // + PopulateDescriptor (Private); - SetLastAttemptVersionInVariable (IncommingFwVersion); //set to 0 to clear any previous results. + // + // Set to 0 to clear any previous results. + // + SetLastAttemptVersionInVariable (Private, IncommingFwVersion); // // if we have locked the device, then skip the set operation. // it should be blocked by hardware too but we can catch here even faster // - if (mFmpDeviceLocked) { - DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Device is already locked. Can't update.\n")); - Status = EFI_ACCESS_DENIED; + if (Private->FmpDeviceLocked) { + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Device is already locked. Can't update.\n", mImageIdName)); + Status = EFI_UNSUPPORTED; goto cleanup; } @@ -930,7 +991,7 @@ SetTheImage ( // Status = CheckTheImage (This, ImageIndex, Image, ImageSize, &Updateable); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Check The Image failed with %r.\n", Status)); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName, Status)); if (Status == EFI_SECURITY_VIOLATION) { LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR; } @@ -943,7 +1004,7 @@ SetTheImage ( // FmpHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize ); if (FmpHeader == NULL) { - DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetFmpHeader failed.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName)); Status = EFI_ABORTED; goto cleanup; } @@ -952,35 +1013,34 @@ SetTheImage ( // // Set to actual value // - SetLastAttemptVersionInVariable (IncommingFwVersion); + SetLastAttemptVersionInVariable (Private, IncommingFwVersion); } if (Updateable != IMAGE_UPDATABLE_VALID) { DEBUG ( (DEBUG_ERROR, - "FmpDxed: SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n", - Updateable) + "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n", + mImageIdName, Updateable) ); Status = EFI_ABORTED; goto cleanup; } if (Progress == NULL) { - DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Invalid progress callback\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName)); Status = EFI_INVALID_PARAMETER; goto cleanup; } mProgressFunc = Progress; - mProgressSupported = TRUE; // // Checking the image is at least 1% // Status = Progress (1); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Progress Callback failed with Status %r.\n", Status)); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Progress Callback failed with Status %r.\n", mImageIdName, Status)); } // @@ -988,14 +1048,14 @@ SetTheImage ( // Status = CheckSystemPower (&BooleanValue); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemPower - API call failed %r.\n", Status)); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName, Status)); goto cleanup; } if (!BooleanValue) { Status = EFI_ABORTED; DEBUG ( (DEBUG_ERROR, - "FmpDxe: SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n") + "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n", mImageIdName) ); LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT; goto cleanup; @@ -1008,14 +1068,14 @@ SetTheImage ( // Status = CheckSystemThermal (&BooleanValue); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemThermal - API call failed %r.\n", Status)); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName, Status)); goto cleanup; } if (!BooleanValue) { Status = EFI_ABORTED; DEBUG ( (DEBUG_ERROR, - "FmpDxe: SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n") + "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n", mImageIdName) ); goto cleanup; } @@ -1027,14 +1087,14 @@ SetTheImage ( // Status = CheckSystemEnvironment (&BooleanValue); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", Status)); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName, Status)); goto cleanup; } if (!BooleanValue) { Status = EFI_ABORTED; DEBUG ( (DEBUG_ERROR, - "FmpDxe: SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n") + "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n", mImageIdName) ); goto cleanup; } @@ -1045,20 +1105,20 @@ SetTheImage ( // Save LastAttemptStatus as error so that if SetImage never returns the error // state is recorded. // - SetLastAttemptStatusInVariable (LastAttemptStatus); + SetLastAttemptStatusInVariable (Private, LastAttemptStatus); // // Strip off all the headers so the device can process its firmware // Status = GetFmpPayloadHeaderSize (FmpHeader, FmpPayloadSize, &FmpHeaderSize); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status)); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName, Status)); goto cleanup; } AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize ); if (AllHeaderSize == 0) { - DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetAllHeaderSize failed.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName)); Status = EFI_ABORTED; goto cleanup; } @@ -1080,7 +1140,7 @@ SetTheImage ( AbortReason ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", Status)); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", mImageIdName, Status)); goto cleanup; } @@ -1094,39 +1154,24 @@ SetTheImage ( // // Update the version stored in variable // - if (!mRuntimeVersionSupported) { - UINT32 Version = DEFAULT_VERSION; + if (!Private->RuntimeVersionSupported) { + Version = DEFAULT_VERSION; GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version); - SetVersionInVariable (Version); + SetVersionInVariable (Private, Version); } // // Update lowest supported variable // - { - UINT32 Version = DEFAULT_LOWESTSUPPORTEDVERSION; - GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &Version); - SetLowestSupportedVersionInVariable (Version); - } + LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION; + GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion); + SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion); LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; - // - // Set flag so the descriptor is repopulated - // This is only applied to devices that do not require reset - // - GetAttributesStatus = FmpDeviceGetAttributes (&AttributesSupported, &AttributesSetting); - if (!EFI_ERROR (GetAttributesStatus)) { - if (((AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED) == 0) || - ((AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED) == 0)) { - mDescriptorPopulated = FALSE; - } - } - cleanup: mProgressFunc = NULL; - mProgressSupported = FALSE; - SetLastAttemptStatusInVariable (LastAttemptStatus); + SetLastAttemptStatusInVariable (Private, LastAttemptStatus); if (Progress != NULL) { // @@ -1135,6 +1180,12 @@ cleanup: Progress (100); } + // + // Need repopulate after SetImage is called to + // update LastAttemptVersion and LastAttemptStatus. + // + Private->DescriptorPopulated = FALSE; + return Status; } @@ -1244,35 +1295,25 @@ FmpDxeLockEventNotify ( IN VOID *Context ) { - EFI_STATUS Status; + EFI_STATUS Status; + FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private; - if (!mFmpDeviceLocked) { - if (IsLockFmpDeviceAtLockEventGuidRequired ()) { - // - // Lock all UEFI Variables used by this module. - // - Status = LockAllFmpVariables (); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variables. Status = %r.\n")); - } else { - DEBUG ((DEBUG_INFO, "FmpDxe: All variables locked\n")); - } + Private = (FIRMWARE_MANAGEMENT_PRIVATE_DATA *)Context; - // - // Lock the firmware device - // - Status = FmpDeviceLock(); - if (EFI_ERROR (Status)) { - if (Status != EFI_UNSUPPORTED) { - DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status)); - } else { - DEBUG ((DEBUG_WARN, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status)); - } + if (!Private->FmpDeviceLocked) { + // + // Lock the firmware device + // + FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext); + Status = FmpDeviceLock(); + if (EFI_ERROR (Status)) { + if (Status != EFI_UNSUPPORTED) { + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status)); + } else { + DEBUG ((DEBUG_WARN, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status)); } - mFmpDeviceLocked = TRUE; - } else { - DEBUG ((DEBUG_VERBOSE, "FmpDxe: Not calling FmpDeviceLock() because mfg mode\n")); } + Private->FmpDeviceLocked = TRUE; } } @@ -1292,85 +1333,233 @@ InstallFmpInstance ( IN EFI_HANDLE Handle ) { - EFI_STATUS Status; - EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; - EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *FmpProgress; - - Status = EFI_SUCCESS; - Fmp = NULL; - FmpProgress = NULL; + EFI_STATUS Status; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; + FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private; // // Only allow a single FMP Protocol instance to be installed // - if (mFmpInstalled) { + Status = gBS->OpenProtocol ( + Handle, + &gEfiFirmwareManagementProtocolGuid, + (VOID **)&Fmp, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { return EFI_ALREADY_STARTED; } // // Allocate FMP Protocol instance // - Fmp = AllocateZeroPool (sizeof (EFI_FIRMWARE_MANAGEMENT_PROTOCOL)); - if (Fmp == NULL) { - DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for FMP Protocol instance.\n")); + Private = AllocateCopyPool ( + sizeof (mFirmwareManagementPrivateDataTemplate), + &mFirmwareManagementPrivateDataTemplate + ); + if (Private == NULL) { + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to allocate memory for private structure.\n", mImageIdName)); Status = EFI_OUT_OF_RESOURCES; goto cleanup; } // - // Allocate FMP Progress Protocol instance + // Initialize private context data structure // - FmpProgress = AllocateZeroPool (sizeof (EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL)); - if (FmpProgress == NULL) { - DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for FMP Progress Protocol instance.\n")); - Status = EFI_OUT_OF_RESOURCES; - FreePool (Fmp); + Private->Handle = Handle; + Private->FmpDeviceContext = NULL; + Status = FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext); + if (Status == EFI_UNSUPPORTED) { + Private->FmpDeviceContext = NULL; + } else if (EFI_ERROR (Status)) { goto cleanup; } // - // Set up FMP Protocol function pointers + // Make sure the descriptor has already been loaded or refreshed // - Fmp->GetImageInfo = GetTheImageInfo; - Fmp->GetImage = GetTheImage; - Fmp->SetImage = SetTheImage; - Fmp->CheckImage = CheckTheImage; - Fmp->GetPackageInfo = GetPackageInfo; - Fmp->SetPackageInfo = SetPackageInfo; + PopulateDescriptor (Private); - // - // Fill in FMP Progress Protocol fields for Version 1 - // - FmpProgress->Version = 1; - FmpProgress->ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor); - FmpProgress->WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds); + if (IsLockFmpDeviceAtLockEventGuidRequired ()) { + // + // Register all UEFI Variables used by this module to be locked. + // + Status = LockAllFmpVariables (Private); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register variables to lock. Status = %r.\n", mImageIdName, Status)); + } else { + DEBUG ((DEBUG_INFO, "FmpDxe(%s): All variables registered to lock\n", mImageIdName)); + } + + // + // Create and register notify function to lock the FMP device. + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + FmpDxeLockEventNotify, + Private, + mLockGuid, + &Private->FmpDeviceLockEvent + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register notification. Status = %r\n", mImageIdName, Status)); + } + ASSERT_EFI_ERROR (Status); + } else { + DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): Not registering notification to call FmpDeviceLock() because mfg mode\n", mImageIdName)); + } // // Install FMP Protocol and FMP Progress Protocol // Status = gBS->InstallMultipleProtocolInterfaces ( - &Handle, - &gEfiFirmwareManagementProtocolGuid, - Fmp, - &gEdkiiFirmwareManagementProgressProtocolGuid, - FmpProgress, + &Private->Handle, + &gEfiFirmwareManagementProtocolGuid, &Private->Fmp, + &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress, NULL ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: FMP Protocol install error. Status = %r.\n", Status)); - FreePool (Fmp); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol install error. Status = %r.\n", mImageIdName, Status)); goto cleanup; } - DEBUG ((DEBUG_INFO, "FmpDxe: FMP Protocol Installed!\n")); - mFmpInstalled = TRUE; - cleanup: + if (EFI_ERROR (Status)) { + if (Private != NULL) { + if (Private->FmpDeviceLockEvent != NULL) { + gBS->CloseEvent (Private->FmpDeviceLockEvent); + } + if (Private->Descriptor.VersionName != NULL) { + FreePool (Private->Descriptor.VersionName); + } + if (Private->FmpDeviceContext != NULL) { + FmpDeviceSetContext (NULL, &Private->FmpDeviceContext); + } + if (Private->VersionVariableName != NULL) { + FreePool (Private->VersionVariableName); + } + if (Private->LsvVariableName != NULL) { + FreePool (Private->LsvVariableName); + } + if (Private->LastAttemptStatusVariableName != NULL) { + FreePool (Private->LastAttemptStatusVariableName); + } + if (Private->LastAttemptVersionVariableName != NULL) { + FreePool (Private->LastAttemptVersionVariableName); + } + if (Private->FmpStateVariableName != NULL) { + FreePool (Private->FmpStateVariableName); + } + FreePool (Private); + } + } + return Status; } +/** + Function to uninstall FMP instance. + + @param[in] Handle The device handle to install a FMP instance on. + + @retval EFI_SUCCESS FMP Installed + @retval EFI_INVALID_PARAMETER Handle was invalid + @retval other Error installing FMP + +**/ +EFI_STATUS +EFIAPI +UninstallFmpInstance ( + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; + FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiFirmwareManagementProtocolGuid, + (VOID **)&Fmp, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol open error. Status = %r.\n", mImageIdName, Status)); + return Status; + } + + Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (Fmp); + FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext); + + if (Private->FmpDeviceLockEvent != NULL) { + gBS->CloseEvent (Private->FmpDeviceLockEvent); + } + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Private->Handle, + &gEfiFirmwareManagementProtocolGuid, &Private->Fmp, + &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol uninstall error. Status = %r.\n", mImageIdName, Status)); + return Status; + } + + if (Private->Descriptor.VersionName != NULL) { + FreePool (Private->Descriptor.VersionName); + } + if (Private->FmpDeviceContext != NULL) { + FmpDeviceSetContext (NULL, &Private->FmpDeviceContext); + } + if (Private->VersionVariableName != NULL) { + FreePool (Private->VersionVariableName); + } + if (Private->LsvVariableName != NULL) { + FreePool (Private->LsvVariableName); + } + if (Private->LastAttemptStatusVariableName != NULL) { + FreePool (Private->LastAttemptStatusVariableName); + } + if (Private->LastAttemptVersionVariableName != NULL) { + FreePool (Private->LastAttemptVersionVariableName); + } + if (Private->FmpStateVariableName != NULL) { + FreePool (Private->FmpStateVariableName); + } + FreePool (Private); + + return EFI_SUCCESS; +} + +/** + Unloads the application and its installed protocol. + + @param ImageHandle Handle that identifies the image to be unloaded. + @param SystemTable The system table. + + @retval EFI_SUCCESS The image has been unloaded. + +**/ +EFI_STATUS +EFIAPI +FmpDxeLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (mFmpSingleInstance) { + return UninstallFmpInstance (ImageHandle); + } + return EFI_SUCCESS; +} + /** Main entry for this driver/library. @@ -1386,7 +1575,6 @@ FmpDxeEntryPoint ( ) { EFI_STATUS Status; - EFI_GUID *LockGuid; // // Verify that a new FILE_GUID value has been provided in the @@ -1407,8 +1595,9 @@ FmpDxeEntryPoint ( // // PcdFmpDeviceImageIdName must be set to a non-empty Unicode string // - DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib PcdFmpDeviceImageIdName is an empty string.\n")); + DEBUG ((DEBUG_ERROR, "FmpDxe: PcdFmpDeviceImageIdName is an empty string.\n")); ASSERT (FALSE); + return EFI_UNSUPPORTED; } // @@ -1416,6 +1605,23 @@ FmpDxeEntryPoint ( // DetectTestKey (); + // + // Fill in FMP Progress Protocol fields for Version 1 + // + mFmpProgress.Version = 1; + mFmpProgress.ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor); + mFmpProgress.WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds); + + // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid. + // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then + // gEfiEndOfDxeEventGroupGuid is used. + // + mLockGuid = &gEfiEndOfDxeEventGroupGuid; + if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) { + mLockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid); + } + DEBUG ((DEBUG_INFO, "FmpDxe(%s): Lock GUID: %g\n", mImageIdName, mLockGuid)); + // // Register with library the install function so if the library uses // UEFI driver model/driver binding protocol it can install FMP on its device handle @@ -1424,41 +1630,28 @@ FmpDxeEntryPoint ( // Status = RegisterFmpInstaller (InstallFmpInstance); if (Status == EFI_UNSUPPORTED) { - DEBUG ((DEBUG_INFO, "FmpDxe: FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n")); - Status = InstallFmpInstance (ImageHandle); + mFmpSingleInstance = TRUE; + DEBUG ((DEBUG_INFO, "FmpDxe(%s): FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n", mImageIdName)); + Status = RegisterFmpUninstaller (UninstallFmpInstance); + if (Status == EFI_UNSUPPORTED) { + Status = InstallFmpInstance (ImageHandle); + } else { + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName)); + Status = EFI_UNSUPPORTED; + } } else if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib registration returned %r. No FMP installed.\n", Status)); + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib registration returned %r. No FMP installed.\n", mImageIdName, Status)); } else { DEBUG (( DEBUG_INFO, - "FmpDxe: FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n" + "FmpDxe(%s): FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n", + mImageIdName )); + Status = RegisterFmpUninstaller (UninstallFmpInstance); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName)); + } } - // - // Register notify function to lock the FMP device. - // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid. - // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then - // gEfiEndOfDxeEventGroupGuid is used. - // - LockGuid = &gEfiEndOfDxeEventGroupGuid; - if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) { - LockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid); - } - DEBUG ((DEBUG_INFO, "FmpDxe: Lock GUID: %g\n", LockGuid)); - - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - FmpDxeLockEventNotify, - NULL, - LockGuid, - &mFmpDeviceLockEvent - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to register for ready to boot. Status = %r\n", Status)); - } - ASSERT_EFI_ERROR (Status); - return Status; }