diff --git a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/ParseConfigProfile.c b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/ParseConfigProfile.c new file mode 100644 index 0000000000..dcad76287c --- /dev/null +++ b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/ParseConfigProfile.c @@ -0,0 +1,213 @@ +/** @file + Parse the INI configuration file and pass the information to the update driver + so that the driver can perform update accordingly. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "SystemFirmwareDxe.h" +#include +#include + +#define MAX_LINE_LENGTH 512 + +/** + Parse Config data file to get the updated data array. + + @param[in] DataBuffer Config raw file buffer. + @param[in] BufferSize Size of raw buffer. + @param[in, out] ConfigHeader Pointer to the config header. + @param[in, out] UpdateArray Pointer to the config of update data. + + @retval EFI_NOT_FOUND No config data is found. + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS Parse the config file successfully. + +**/ +EFI_STATUS +ParseUpdateDataFile ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize, + IN OUT CONFIG_HEADER *ConfigHeader, + IN OUT UPDATE_CONFIG_DATA **UpdateArray + ) +{ + EFI_STATUS Status; + CHAR8 *SectionName; + CHAR8 Entry[MAX_LINE_LENGTH]; + UINTN Num; + UINT64 Num64; + UINTN Index; + EFI_GUID FileGuid; + VOID *Context; + + // + // First process the data buffer and get all sections and entries + // + Context = OpenIniFile(DataBuffer, BufferSize); + if (Context == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Now get NumOfUpdate + // + Status = GetDecimalUintnFromDataFile( + Context, + "Head", + "NumOfUpdate", + &Num + ); + if (EFI_ERROR(Status) || (Num == 0)) { + DEBUG((DEBUG_ERROR, "NumOfUpdate not found\n")); + CloseIniFile(Context); + return EFI_NOT_FOUND; + } + + ConfigHeader->NumOfUpdates = Num; + *UpdateArray = AllocateZeroPool ((sizeof (UPDATE_CONFIG_DATA) * Num)); + if (*UpdateArray == NULL) { + CloseIniFile(Context); + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0 ; Index < ConfigHeader->NumOfUpdates ; Index++) { + // + // Get the section name of each update + // + AsciiStrCpyS (Entry, MAX_LINE_LENGTH, "Update"); + AsciiValueToString(Entry + AsciiStrLen(Entry), 0, Index, 0); + Status = GetStringFromDataFile( + Context, + "Head", + Entry, + &SectionName + ); + if (EFI_ERROR(Status) || (SectionName == NULL)) { + DEBUG((DEBUG_ERROR, "[%d] %a not found\n", Index, Entry)); + CloseIniFile(Context); + return EFI_NOT_FOUND; + } + + // + // The section name of this update has been found. + // Now looks for all the config data of this update + // + (*UpdateArray)[Index].Index = Index; + + // + // FirmwareType + // + Status = GetDecimalUintnFromDataFile( + Context, + SectionName, + "FirmwareType", + &Num + ); + if (EFI_ERROR(Status)) { + CloseIniFile(Context); + DEBUG((DEBUG_ERROR, "[%d] FirmwareType not found\n", Index)); + return EFI_NOT_FOUND; + } + (*UpdateArray)[Index].FirmwareType = (PLATFORM_FIRMWARE_TYPE) Num; + + // + // AddressType + // + Status = GetDecimalUintnFromDataFile( + Context, + SectionName, + "AddressType", + &Num + ); + if (EFI_ERROR(Status)) { + CloseIniFile(Context); + DEBUG((DEBUG_ERROR, "[%d] AddressType not found\n", Index)); + return EFI_NOT_FOUND; + } + (*UpdateArray)[Index].AddressType = (FLASH_ADDRESS_TYPE) Num; + + // + // BaseAddress + // + Status = GetHexUint64FromDataFile( + Context, + SectionName, + "BaseAddress", + &Num64 + ); + if (EFI_ERROR(Status)) { + CloseIniFile(Context); + DEBUG((DEBUG_ERROR, "[%d] BaseAddress not found\n", Index)); + return EFI_NOT_FOUND; + } + (*UpdateArray)[Index].BaseAddress = (EFI_PHYSICAL_ADDRESS) Num64; + + // + // FileBuid + // + Status = GetGuidFromDataFile( + Context, + SectionName, + "FileGuid", + &FileGuid + ); + if (EFI_ERROR(Status)) { + CloseIniFile(Context); + DEBUG((DEBUG_ERROR, "[%d] FileGuid not found\n", Index)); + return EFI_NOT_FOUND; + } + + CopyGuid(&((*UpdateArray)[Index].FileGuid), &FileGuid); + + // + // Length + // + Status = GetHexUintnFromDataFile( + Context, + SectionName, + "Length", + &Num + ); + if (EFI_ERROR(Status)) { + CloseIniFile(Context); + DEBUG((DEBUG_ERROR, "[%d] Length not found\n", Index)); + return EFI_NOT_FOUND; + } + (*UpdateArray)[Index].Length = (UINTN) Num; + + // + // ImageOffset + // + Status = GetHexUintnFromDataFile( + Context, + SectionName, + "ImageOffset", + &Num + ); + if (EFI_ERROR(Status)) { + CloseIniFile(Context); + DEBUG((DEBUG_ERROR, "[%d] ImageOffset not found\n", Index)); + return EFI_NOT_FOUND; + } + (*UpdateArray)[Index].ImageOffset = (UINTN) Num; + } + + // + // Now all configuration data got. Free those temporary buffers + // + CloseIniFile(Context); + + return EFI_SUCCESS; +} + diff --git a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c new file mode 100644 index 0000000000..642a99d526 --- /dev/null +++ b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c @@ -0,0 +1,385 @@ +/** @file + Produce FMP instance for system firmware. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "SystemFirmwareDxe.h" + +EFI_GUID gSystemFmpLastAttemptVariableGuid = SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_GUID; +EFI_GUID gSystemFmpProtocolGuid = SYSTEM_FMP_PROTOCOL_GUID; + +EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol = { + FmpGetImageInfo, + FmpGetImage, + FmpSetImage, + FmpCheckImage, + FmpGetPackageInfo, + FmpSetPackageInfo +}; + +/** + Returns information about the current firmware image(s) of the device. + + 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, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer. + On input, this is the size of the buffer allocated by the caller. + On output, it is the size of the buffer returned by the firmware + if the buffer was large enough, or the size of the buffer needed + to contain the image(s) information if the buffer was too small. + @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s) + information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs. + @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number + associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] DescriptorCount A pointer to the location in which firmware returns the number of + descriptors or firmware images within this device. + @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes, + of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] PackageVersion A version number that represents all the firmware images in the device. + The format is vendor specific and new version must have a greater value + than the old version. If PackageVersion is not supported, the value is + 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison + is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates + that package version update is in progress. + @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the + package version name. The buffer is allocated by this function with + AllocatePool(), and it is the caller's responsibility to free it with a call + to FreePool(). + + @retval EFI_SUCCESS The device was successfully updated with the new image. + @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size + needed to hold the image(s) information is returned in ImageInfoSize. + @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL. + @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image. + +**/ +EFI_STATUS +EFIAPI +FmpGetImageInfo ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN OUT UINTN *ImageInfoSize, + IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo, + OUT UINT32 *DescriptorVersion, + OUT UINT8 *DescriptorCount, + OUT UINTN *DescriptorSize, + OUT UINT32 *PackageVersion, + OUT CHAR16 **PackageVersionName + ) +{ + SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate; + EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor; + + SystemFmpPrivate = SYSTEM_FMP_PRIVATE_DATA_FROM_FMP(This); + + if(ImageInfoSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (*ImageInfoSize < sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * SystemFmpPrivate->DescriptorCount) { + *ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * SystemFmpPrivate->DescriptorCount; + return EFI_BUFFER_TOO_SMALL; + } + + if (ImageInfo == NULL || + DescriptorVersion == NULL || + DescriptorCount == NULL || + DescriptorSize == NULL || + PackageVersion == NULL || + PackageVersionName == NULL) { + return EFI_INVALID_PARAMETER; + } + + *ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * SystemFmpPrivate->DescriptorCount; + *DescriptorSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR); + *DescriptorCount = SystemFmpPrivate->DescriptorCount; + *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; + + // + // supports 1 ImageInfo descriptor + // + ImageDescriptor = SystemFmpPrivate->ImageDescriptor; + ImageInfo->ImageIndex = ImageDescriptor->ImageIndex; + CopyGuid (&ImageInfo->ImageTypeId, &ImageDescriptor->ImageTypeId); + ImageInfo->ImageId = ImageDescriptor->ImageId; + if (ImageDescriptor->ImageIdNameStringOffset != 0) { + ImageInfo->ImageIdName = (CHAR16 *)((UINTN)ImageDescriptor + ImageDescriptor->ImageIdNameStringOffset); + } else { + ImageInfo->ImageIdName = NULL; + } + ImageInfo->Version = ImageDescriptor->Version; + if (ImageDescriptor->VersionNameStringOffset != 0) { + ImageInfo->VersionName = (CHAR16 *)((UINTN)ImageDescriptor + ImageDescriptor->VersionNameStringOffset); + } else { + ImageInfo->VersionName = NULL; + } + ImageInfo->Size = (UINTN)ImageDescriptor->Size; + ImageInfo->AttributesSupported = ImageDescriptor->AttributesSupported; + ImageInfo->AttributesSetting = ImageDescriptor->AttributesSetting; + ImageInfo->Compatibilities = ImageDescriptor->Compatibilities; + ImageInfo->LowestSupportedImageVersion = ImageDescriptor->LowestSupportedImageVersion; + ImageInfo->LastAttemptVersion = SystemFmpPrivate->LastAttempt.LastAttemptVersion; + ImageInfo->LastAttemptStatus = SystemFmpPrivate->LastAttempt.LastAttemptStatus; + ImageInfo->HardwareInstance = ImageDescriptor->HardwareInstance; + + // + // package version + // + *PackageVersion = ImageDescriptor->PackageVersion; + if (ImageDescriptor->PackageVersionNameStringOffset != 0) { + *PackageVersionName = (VOID *)((UINTN)ImageDescriptor + ImageDescriptor->PackageVersionNameStringOffset); + *PackageVersionName = AllocateCopyPool(StrSize(*PackageVersionName), *PackageVersionName); + } else { + *PackageVersionName = NULL; + } + + return EFI_SUCCESS; +} + +/** + Retrieves a copy of the current firmware image of the device. + + 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. + The number is between 1 and DescriptorCount. + @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. + @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the + image. The current buffer size needed to hold the image is returned + in ImageSize. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_NOT_FOUND The current image is not copied to the buffer. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpGetImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN OUT VOID *Image, + IN OUT UINTN *ImageSize + ) +{ + SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate; + + if (Image == NULL || ImageSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + SystemFmpPrivate = SYSTEM_FMP_PRIVATE_DATA_FROM_FMP(This); + + if (ImageIndex == 0 || ImageIndex > SystemFmpPrivate->DescriptorCount || ImageSize == NULL || Image == NULL) { + return EFI_INVALID_PARAMETER; + } + + return EFI_UNSUPPORTED; +} + +/** + Checks if the firmware image is valid for the device. + + This function allows firmware update application to validate the firmware image without + invoking the SetImage() first. + + @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[in] Image Points to the new image. + @param[in] ImageSize Size of the new image in bytes. + @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides, + if available, additional information if the image is invalid. + + @retval EFI_SUCCESS The image was successfully checked. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpCheckImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN CONST VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *ImageUpdatable + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Returns information about the firmware package. + + This function returns package information. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance. + @param[out] PackageVersion A version number that represents all the firmware images in the device. + The format is vendor specific and new version must have a greater value + than the old version. If PackageVersion is not supported, the value is + 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version + comparison is to be performed using PackageVersionName. A value of + 0xFFFFFFFD indicates that package version update is in progress. + @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing + the package version name. The buffer is allocated by this function with + AllocatePool(), and it is the caller's responsibility to free it with a + call to FreePool(). + @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of + package version name. A value of 0 indicates the device does not support + update of package version name. Length is the number of Unicode characters, + including the terminating null character. + @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute + Definitions' for possible returned values of this parameter. A value of 1 + indicates the attribute is supported and the current setting value is + indicated in AttributesSetting. A value of 0 indicates the attribute is not + supported and the current setting value in AttributesSetting is meaningless. + @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned + values of this parameter + + @retval EFI_SUCCESS The package information was successfully returned. + @retval EFI_UNSUPPORTED The operation is not supported. + +**/ +EFI_STATUS +EFIAPI +FmpGetPackageInfo ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + OUT UINT32 *PackageVersion, + OUT CHAR16 **PackageVersionName, + OUT UINT32 *PackageVersionNameMaxLen, + OUT UINT64 *AttributesSupported, + OUT UINT64 *AttributesSetting + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Updates information about the firmware package. + + This function updates package information. + This function returns EFI_UNSUPPORTED if the package information is not updatable. + VendorCode enables vendor to implement vendor-specific package information update policy. + Null if the caller did not specify this policy or use the default policy. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance. + @param[in] Image Points to the authentication image. + Null if authentication is not required. + @param[in] ImageSize Size of the authentication image in bytes. + 0 if authentication is not required. + @param[in] VendorCode This enables vendor to implement vendor-specific firmware + image update policy. + Null indicates the caller did not specify this policy or use + the default policy. + @param[in] PackageVersion The new package version. + @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing + the package version name. + The string length is equal to or less than the value returned in + PackageVersionNameMaxLen. + + @retval EFI_SUCCESS The device was successfully updated with the new package + information. + @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value + returned in PackageVersionNameMaxLen. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpSetPackageInfo ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode, + IN UINT32 PackageVersion, + IN CONST CHAR16 *PackageVersionName + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Initialize SystemFmpDriver private data structure. + + @param[in] SystemFmpPrivate private data structure to be initialized. + + @return EFI_SUCCESS private data is initialized. +**/ +EFI_STATUS +InitializePrivateData ( + IN SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate + ) +{ + EFI_STATUS VarStatus; + UINTN VarSize; + + SystemFmpPrivate->Signature = SYSTEM_FMP_PRIVATE_DATA_SIGNATURE; + SystemFmpPrivate->Handle = NULL; + SystemFmpPrivate->DescriptorCount = 1; + CopyMem(&SystemFmpPrivate->Fmp, &mFirmwareManagementProtocol, sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL)); + + SystemFmpPrivate->ImageDescriptor = PcdGetPtr(PcdEdkiiSystemFirmwareImageDescriptor); + + SystemFmpPrivate->LastAttempt.LastAttemptVersion = 0x0; + SystemFmpPrivate->LastAttempt.LastAttemptStatus = 0x0; + VarSize = sizeof(SystemFmpPrivate->LastAttempt); + VarStatus = gRT->GetVariable( + SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME, + &gSystemFmpLastAttemptVariableGuid, + NULL, + &VarSize, + &SystemFmpPrivate->LastAttempt + ); + DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus)); + DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->LastAttempt.LastAttemptStatus)); + + return EFI_SUCCESS; +} + +/** + Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo. + + @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR + + @retval TRUE It is a system FMP. + @retval FALSE It is a device FMP. +**/ +BOOLEAN +IsSystemFmp ( + IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo + ) +{ + GUID *Guid; + UINTN Count; + UINTN Index; + + Guid = PcdGetPtr(PcdSystemFmpCapsuleImageTypeIdGuid); + Count = PcdGetSize(PcdSystemFmpCapsuleImageTypeIdGuid) / sizeof(GUID); + + for (Index = 0; Index < Count; Index++, Guid++) { + if (CompareGuid(&FmpImageInfo->ImageTypeId, Guid)) { + return TRUE; + } + } + + return FALSE; +} diff --git a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareDxe.h b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareDxe.h new file mode 100644 index 0000000000..dd3a68abfe --- /dev/null +++ b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareDxe.h @@ -0,0 +1,408 @@ +/** @file + System Firmware update header file. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SYSTEM_FIRMWARE_UPDATE_H_ +#define _SYSTEM_FIRMWARE_UPDATE_H_ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + UINT32 LastAttemptVersion; + UINT32 LastAttemptStatus; +} SYSTEM_FMP_LAST_ATTEMPT_VARIABLE; + +#define SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME L"SystemLastAttempVar" + +#define SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_GUID {0x2f564d6f, 0xcc2c, 0x4838, { 0xb9, 0xa8, 0xbe, 0x59, 0x48, 0xb0, 0x3d, 0x59 }} + +#define SYSTEM_FMP_PRIVATE_DATA_SIGNATURE SIGNATURE_32('S', 'Y', 'S', 'F') + +#define SYSTEM_FMP_PROTOCOL_GUID {0x6d16624a, 0x26a6, 0x4cb4, { 0x84, 0xfa, 0x6, 0x78, 0x5a, 0x7e, 0x82, 0x6a }} + +// +// SYSTEM FMP private data structure. +// + +struct _SYSTEM_FMP_PRIVATE_DATA { + UINT32 Signature; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL Fmp; + EFI_HANDLE Handle; + UINT8 DescriptorCount; + EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor; + SYSTEM_FMP_LAST_ATTEMPT_VARIABLE LastAttempt; +}; + +typedef struct _SYSTEM_FMP_PRIVATE_DATA SYSTEM_FMP_PRIVATE_DATA; + +/** + Returns a pointer to the SYSTEM_FMP_PRIVATE_DATA structure from the input a as Fmp. + + If the signatures matches, then a pointer to the data structure that contains + a specified field of that data structure is returned. + + @param a Pointer to the field specified by ServiceBinding within + a data structure of type SYSTEM_FMP_PRIVATE_DATA. + +**/ +#define SYSTEM_FMP_PRIVATE_DATA_FROM_FMP(a) \ + CR ( \ + (a), \ + SYSTEM_FMP_PRIVATE_DATA, \ + Fmp, \ + SYSTEM_FMP_PRIVATE_DATA_SIGNATURE \ + ) + + +// +// Update data +// + +typedef struct { + UINTN NumOfUpdates; +} CONFIG_HEADER; + +typedef struct { + UINTN Index; + PLATFORM_FIRMWARE_TYPE FirmwareType; + FLASH_ADDRESS_TYPE AddressType; + EFI_GUID FileGuid; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINTN Length; + UINTN ImageOffset; +} UPDATE_CONFIG_DATA; + +// +// System Firmware Update SMM Communication +// + +#define SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_FUNCTION_SET_IMAGE 1 + +typedef struct { + UINTN Function; + EFI_STATUS ReturnStatus; +//UINT8 Data[]; +} SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_HEAD; + +#define ABORT_REASON_MAX_SIZE 0x40 // UnicodeStringSize including final L'\0' + +#define CAPSULE_IMAGE_ADDITIONAL_MAX_SIZE (0x20020 + 0xA0000) // Addtional size for Capsule Header, FV block alignment + DispatchImage. + +typedef struct { + UINT8 ImageIndex; + UINTN ImageSize; + UINTN AbortReasonSize; + UINT32 LastAttemptVersion; + UINT32 LastAttemptStatus; +//UINT8 Data[AbortReasonMaxSize + ImageSize]; +} SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_SET_IMAGE; + + +/** + Returns information about the current firmware image(s) of the device. + + 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, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer. + On input, this is the size of the buffer allocated by the caller. + On output, it is the size of the buffer returned by the firmware + if the buffer was large enough, or the size of the buffer needed + to contain the image(s) information if the buffer was too small. + @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s) + information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs. + @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number + associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] DescriptorCount A pointer to the location in which firmware returns the number of + descriptors or firmware images within this device. + @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes, + of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] PackageVersion A version number that represents all the firmware images in the device. + The format is vendor specific and new version must have a greater value + than the old version. If PackageVersion is not supported, the value is + 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison + is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates + that package version update is in progress. + @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the + package version name. The buffer is allocated by this function with + AllocatePool(), and it is the caller's responsibility to free it with a call + to FreePool(). + + @retval EFI_SUCCESS The device was successfully updated with the new image. + @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size + needed to hold the image(s) information is returned in ImageInfoSize. + @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL. + @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image. + +**/ +EFI_STATUS +EFIAPI +FmpGetImageInfo ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN OUT UINTN *ImageInfoSize, + IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo, + OUT UINT32 *DescriptorVersion, + OUT UINT8 *DescriptorCount, + OUT UINTN *DescriptorSize, + OUT UINT32 *PackageVersion, + OUT CHAR16 **PackageVersionName + ); + +/** + Retrieves a copy of the current firmware image of the device. + + 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. + The number is between 1 and DescriptorCount. + @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. + @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the + image. The current buffer size needed to hold the image is returned + in ImageSize. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_NOT_FOUND The current image is not copied to the buffer. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpGetImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN OUT VOID *Image, + IN OUT UINTN *ImageSize + ); + +/** + Updates the firmware image of the device. + + This function updates the hardware with the new firmware image. + This function returns EFI_UNSUPPORTED if the firmware image is not updatable. + If the firmware image is updatable, the function should perform the following minimal validations + before proceeding to do the firmware image update. + - Validate the image authentication if image has attribute + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns + EFI_SECURITY_VIOLATION if the validation fails. + - Validate the image is a supported image for this device. The function returns EFI_ABORTED if + the image is unsupported. The function can optionally provide more detailed information on + why the image is not a supported image. + - Validate the data from VendorCode if not null. Image validation must be performed before + VendorCode data validation. VendorCode data is ignored or considered invalid if image + validation failed. The function returns EFI_ABORTED if the data is invalid. + + VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if + the caller did not specify the policy or use the default policy. As an example, vendor can implement + a policy to allow an option to force a firmware image update when the abort reason is due to the new + firmware image version is older than the current firmware image version or bad image checksum. + Sensitive operations such as those wiping the entire firmware image and render the device to be + non-functional should be encoded in the image itself rather than passed with the VendorCode. + AbortReason enables vendor to have the option to provide a more detailed description of the abort + reason to the caller. + + @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[in] Image Points to the new image. + @param[in] ImageSize Size of the new image in bytes. + @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy. + Null indicates the caller did not specify the policy or use the default policy. + @param[in] Progress A function used by the driver to report the progress of the firmware update. + @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more + details for the aborted operation. The buffer is allocated by this function + with AllocatePool(), and it is the caller's responsibility to free it with a + call to FreePool(). + + @retval EFI_SUCCESS The device was successfully updated with the new image. + @retval EFI_ABORTED The operation is aborted. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpSetImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, + OUT CHAR16 **AbortReason + ); + +/** + Checks if the firmware image is valid for the device. + + This function allows firmware update application to validate the firmware image without + invoking the SetImage() first. + + @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[in] Image Points to the new image. + @param[in] ImageSize Size of the new image in bytes. + @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides, + if available, additional information if the image is invalid. + + @retval EFI_SUCCESS The image was successfully checked. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpCheckImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN CONST VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *ImageUpdatable + ); + +/** + Returns information about the firmware package. + + This function returns package information. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance. + @param[out] PackageVersion A version number that represents all the firmware images in the device. + The format is vendor specific and new version must have a greater value + than the old version. If PackageVersion is not supported, the value is + 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version + comparison is to be performed using PackageVersionName. A value of + 0xFFFFFFFD indicates that package version update is in progress. + @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing + the package version name. The buffer is allocated by this function with + AllocatePool(), and it is the caller's responsibility to free it with a + call to FreePool(). + @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of + package version name. A value of 0 indicates the device does not support + update of package version name. Length is the number of Unicode characters, + including the terminating null character. + @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute + Definitions' for possible returned values of this parameter. A value of 1 + indicates the attribute is supported and the current setting value is + indicated in AttributesSetting. A value of 0 indicates the attribute is not + supported and the current setting value in AttributesSetting is meaningless. + @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned + values of this parameter + + @retval EFI_SUCCESS The package information was successfully returned. + @retval EFI_UNSUPPORTED The operation is not supported. + +**/ +EFI_STATUS +EFIAPI +FmpGetPackageInfo ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + OUT UINT32 *PackageVersion, + OUT CHAR16 **PackageVersionName, + OUT UINT32 *PackageVersionNameMaxLen, + OUT UINT64 *AttributesSupported, + OUT UINT64 *AttributesSetting + ); + +/** + Updates information about the firmware package. + + This function updates package information. + This function returns EFI_UNSUPPORTED if the package information is not updatable. + VendorCode enables vendor to implement vendor-specific package information update policy. + Null if the caller did not specify this policy or use the default policy. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance. + @param[in] Image Points to the authentication image. + Null if authentication is not required. + @param[in] ImageSize Size of the authentication image in bytes. + 0 if authentication is not required. + @param[in] VendorCode This enables vendor to implement vendor-specific firmware + image update policy. + Null indicates the caller did not specify this policy or use + the default policy. + @param[in] PackageVersion The new package version. + @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing + the package version name. + The string length is equal to or less than the value returned in + PackageVersionNameMaxLen. + + @retval EFI_SUCCESS The device was successfully updated with the new package + information. + @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value + returned in PackageVersionNameMaxLen. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpSetPackageInfo ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode, + IN UINT32 PackageVersion, + IN CONST CHAR16 *PackageVersionName + ); + +/** + Initialize SystemFmpDriver private data structure. + + @param[in] SystemFmpPrivate private data structure to be initialized. + + @return EFI_SUCCESS private data is initialized. +**/ +EFI_STATUS +InitializePrivateData ( + IN SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate + ); + +extern EFI_GUID gSystemFmpLastAttemptVariableGuid; +extern EFI_GUID mCurrentImageTypeId; +extern EFI_GUID gSystemFmpProtocolGuid; + +#endif + diff --git a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxe.c b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxe.c new file mode 100644 index 0000000000..9d5832fed2 --- /dev/null +++ b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxe.c @@ -0,0 +1,262 @@ +/** @file + SetImage instance to report system firmware and act as agent to system update. + + Caution: This module requires additional review when modified. + This module will have external input - capsule image. + This external input must be validated carefully to avoid security issue like + buffer overflow, integer overflow. + + FmpSetImage() will receive untrusted input and do basic validation. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "SystemFirmwareDxe.h" + +// +// SystemFmp driver private data +// +SYSTEM_FMP_PRIVATE_DATA *mSystemFmpPrivate = NULL; + +/** + Dispatch system FMP images. + + Caution: This function may receive untrusted input. + + @param[in] Image The EDKII system FMP capsule image. + @param[in] ImageSize The size of the EDKII system FMP capsule image in bytes. + @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + + @retval EFI_SUCESS Process Capsule Image successfully. + @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware. + @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted. + @retval EFI_OUT_OF_RESOURCES Not enough memory. +**/ +EFI_STATUS +DispatchSystemFmpImages ( + IN VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *LastAttemptVersion, + OUT UINT32 *LastAttemptStatus + ) +{ + EFI_STATUS Status; + VOID *AuthenticatedImage; + UINTN AuthenticatedImageSize; + VOID *DispatchFvImage; + UINTN DispatchFvImageSize; + EFI_HANDLE FvProtocolHandle; + EFI_FIRMWARE_VOLUME_HEADER *FvImage; + BOOLEAN Result; + + DEBUG((DEBUG_INFO, "DispatchSystemFmpImages\n")); + + // + // Verify + // + Status = CapsuleAuthenticateSystemFirmware(Image, ImageSize, FALSE, LastAttemptVersion, LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticateImage - %r\n", Status)); + return Status; + } + + // + // Get FV + // + Result = ExtractDriverFvImage(AuthenticatedImage, AuthenticatedImageSize, &DispatchFvImage, &DispatchFvImageSize); + if (Result) { + DEBUG((DEBUG_INFO, "ExtractDriverFvImage\n")); + // + // Dispatch + // + if (((EFI_FIRMWARE_VOLUME_HEADER *)DispatchFvImage)->FvLength == DispatchFvImageSize) { + FvImage = AllocatePages(EFI_SIZE_TO_PAGES(DispatchFvImageSize)); + if (FvImage != NULL) { + CopyMem(FvImage, DispatchFvImage, DispatchFvImageSize); + Status = gDS->ProcessFirmwareVolume( + (VOID *)FvImage, + (UINTN)FvImage->FvLength, + &FvProtocolHandle + ); + DEBUG((DEBUG_INFO, "ProcessFirmwareVolume - %r\n", Status)); + if (!EFI_ERROR(Status)) { + gDS->Dispatch(); + DEBUG((DEBUG_INFO, "Dispatch Done\n")); + } + } + } + } + + return EFI_SUCCESS; +} + +/** + Updates the firmware image of the device. + + This function updates the hardware with the new firmware image. + This function returns EFI_UNSUPPORTED if the firmware image is not updatable. + If the firmware image is updatable, the function should perform the following minimal validations + before proceeding to do the firmware image update. + - Validate the image authentication if image has attribute + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns + EFI_SECURITY_VIOLATION if the validation fails. + - Validate the image is a supported image for this device. The function returns EFI_ABORTED if + the image is unsupported. The function can optionally provide more detailed information on + why the image is not a supported image. + - Validate the data from VendorCode if not null. Image validation must be performed before + VendorCode data validation. VendorCode data is ignored or considered invalid if image + validation failed. The function returns EFI_ABORTED if the data is invalid. + + VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if + the caller did not specify the policy or use the default policy. As an example, vendor can implement + a policy to allow an option to force a firmware image update when the abort reason is due to the new + firmware image version is older than the current firmware image version or bad image checksum. + Sensitive operations such as those wiping the entire firmware image and render the device to be + non-functional should be encoded in the image itself rather than passed with the VendorCode. + AbortReason enables vendor to have the option to provide a more detailed description of the abort + reason to the caller. + + @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[in] Image Points to the new image. + @param[in] ImageSize Size of the new image in bytes. + @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy. + Null indicates the caller did not specify the policy or use the default policy. + @param[in] Progress A function used by the driver to report the progress of the firmware update. + @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more + details for the aborted operation. The buffer is allocated by this function + with AllocatePool(), and it is the caller's responsibility to free it with a + call to FreePool(). + + @retval EFI_SUCCESS The device was successfully updated with the new image. + @retval EFI_ABORTED The operation is aborted. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpSetImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, + OUT CHAR16 **AbortReason + ) +{ + SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *SystemFmp; + EFI_STATUS Status; + EFI_STATUS VarStatus; + + if (Image == NULL || ImageSize == 0 || AbortReason == NULL) { + return EFI_INVALID_PARAMETER; + } + + SystemFmpPrivate = SYSTEM_FMP_PRIVATE_DATA_FROM_FMP(This); + *AbortReason = NULL; + + if (ImageIndex == 0 || ImageIndex > SystemFmpPrivate->DescriptorCount) { + return EFI_INVALID_PARAMETER; + } + + // + // Process FV + // + Status = DispatchSystemFmpImages((VOID *)Image, ImageSize, &SystemFmpPrivate->LastAttempt.LastAttemptVersion, &SystemFmpPrivate->LastAttempt.LastAttemptStatus); + DEBUG((DEBUG_INFO, "(Agent)SetImage - LastAttemp Version - 0x%x, State - 0x%x\n", SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->LastAttempt.LastAttemptStatus)); + if (EFI_ERROR(Status)) { + VarStatus = gRT->SetVariable( + SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME, + &gSystemFmpLastAttemptVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(SystemFmpPrivate->LastAttempt), + &SystemFmpPrivate->LastAttempt + ); + DEBUG((DEBUG_INFO, "(Agent)SetLastAttemp - %r\n", VarStatus)); + return Status; + } + + // + // Pass Thru + // + Status = gBS->LocateProtocol(&gSystemFmpProtocolGuid, NULL, (VOID **)&SystemFmp); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_INFO, "(Agent)SetImage - SystemFmpProtocol - %r\n", Status)); + SystemFmpPrivate->LastAttempt.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; + VarStatus = gRT->SetVariable( + SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME, + &gSystemFmpLastAttemptVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(SystemFmpPrivate->LastAttempt), + &SystemFmpPrivate->LastAttempt + ); + DEBUG((DEBUG_INFO, "(Agent)SetLastAttemp - %r\n", VarStatus)); + return Status; + } + + return SystemFmp->SetImage(SystemFmp, ImageIndex, Image, ImageSize, VendorCode, Progress, AbortReason); +} + +/** + System FMP module entrypoint + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @return EFI_SUCCESS System FMP module is initialized. +**/ +EFI_STATUS +EFIAPI +SystemFirmwareReportMainDxe ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Initialize SystemFmpPrivateData + // + mSystemFmpPrivate = AllocateZeroPool (sizeof(SYSTEM_FMP_PRIVATE_DATA)); + if (mSystemFmpPrivate == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = InitializePrivateData(mSystemFmpPrivate); + if (EFI_ERROR(Status)) { + FreePool(mSystemFmpPrivate); + mSystemFmpPrivate = NULL; + return Status; + } + + // + // Install FMP protocol. + // + Status = gBS->InstallProtocolInterface ( + &mSystemFmpPrivate->Handle, + &gEfiFirmwareManagementProtocolGuid, + EFI_NATIVE_INTERFACE, + &mSystemFmpPrivate->Fmp + ); + if (EFI_ERROR (Status)) { + FreePool(mSystemFmpPrivate); + mSystemFmpPrivate = NULL; + return Status; + } + + return Status; +} diff --git a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxe.inf b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxe.inf new file mode 100644 index 0000000000..89a86ff941 --- /dev/null +++ b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxe.inf @@ -0,0 +1,69 @@ +## @file +# SystemFirmware FMP report driver. +# +# Produce FMP instance to report system firmware EFI_FIRMWARE_IMAGE_DESCRIPTOR. +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SystemFirmwareReportDxe + MODULE_UNI_FILE = SystemFirmwareReportDxe.uni + FILE_GUID = BC1A046C-7DBD-41F2-94E5-D7595554CAF4 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = SystemFirmwareReportMainDxe + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = X64 +# + +[Sources] + SystemFirmwareCommonDxe.c + SystemFirmwareReportDxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SignedCapsulePkg/SignedCapsulePkg.dec + +[LibraryClasses] + BaseLib + UefiLib + BaseMemoryLib + DebugLib + PcdLib + MemoryAllocationLib + UefiBootServicesTableLib + HobLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + DxeServicesLib + DxeServicesTableLib + PrintLib + EdkiiSystemCapsuleLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGuid ## CONSUMES + gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor ## CONSUMES + +[Protocols] + gEfiFirmwareManagementProtocolGuid ## PRODUCES + +[Depex] + gEfiVariableArchProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + SystemFirmwareReportDxeExtra.uni + diff --git a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxe.uni b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxe.uni new file mode 100644 index 0000000000..34edebac0e --- /dev/null +++ b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxe.uni @@ -0,0 +1,21 @@ +// /** @file +// SystemFirmware FMP report driver. +// +// Produce FMP instance to report system firmware EFI_FIRMWARE_IMAGE_DESCRIPTOR. +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "SystemFirmware FMP report driver." + +#string STR_MODULE_DESCRIPTION #language en-US "Produce FMP instance to report system firmware EFI_FIRMWARE_IMAGE_DESCRIPTOR." diff --git a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxeExtra.uni b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxeExtra.uni new file mode 100644 index 0000000000..212134dd98 --- /dev/null +++ b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxeExtra.uni @@ -0,0 +1,20 @@ +// /** @file +// SystemFirmwareReportDxe Localized Strings and Content +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"SystemFirmwareReport DXE Driver" + + diff --git a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c new file mode 100644 index 0000000000..ae783ffe4d --- /dev/null +++ b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c @@ -0,0 +1,526 @@ +/** @file + SetImage instance to update system firmware. + + Caution: This module requires additional review when modified. + This module will have external input - capsule image. + This external input must be validated carefully to avoid security issue like + buffer overflow, integer overflow. + + FmpSetImage() will receive untrusted input and do basic validation. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "SystemFirmwareDxe.h" + +// +// SystemFmp driver private data +// +SYSTEM_FMP_PRIVATE_DATA *mSystemFmpPrivate = NULL; + +EFI_GUID mCurrentImageTypeId; + +BOOLEAN mNvRamUpdated = FALSE; + +/** + Parse Config data file to get the updated data array. + + @param[in] DataBuffer Config raw file buffer. + @param[in] BufferSize Size of raw buffer. + @param[in, out] ConfigHeader Pointer to the config header. + @param[in, out] UpdateArray Pointer to the config of update data. + + @retval EFI_NOT_FOUND No config data is found. + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS Parse the config file successfully. + +**/ +EFI_STATUS +ParseUpdateDataFile ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize, + IN OUT CONFIG_HEADER *ConfigHeader, + IN OUT UPDATE_CONFIG_DATA **UpdateArray + ); + +/** + Update System Firmware image component. + + @param[in] SystemFirmwareImage Points to the System Firmware image. + @param[in] SystemFirmwareImageSize The length of the System Firmware image in bytes. + @param[in] ConfigData Points to the component configuration structure. + @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + + @retval EFI_SUCCESS The System Firmware image is updated. + @retval EFI_WRITE_PROTECTED The flash device is read only. +**/ +EFI_STATUS +PerformUpdate ( + IN VOID *SystemFirmwareImage, + IN UINTN SystemFirmwareImageSize, + IN UPDATE_CONFIG_DATA *ConfigData, + OUT UINT32 *LastAttemptVersion, + OUT UINT32 *LastAttemptStatus + ) +{ + EFI_STATUS Status; + + DEBUG((DEBUG_INFO, "PlatformUpdate:")); + DEBUG((DEBUG_INFO, " BaseAddress - 0x%lx,", ConfigData->BaseAddress)); + DEBUG((DEBUG_INFO, " ImageOffset - 0x%x,", ConfigData->ImageOffset)); + DEBUG((DEBUG_INFO, " Legnth - 0x%x\n", ConfigData->Length)); + Status = PerformFlashWrite ( + ConfigData->FirmwareType, + ConfigData->BaseAddress, + ConfigData->AddressType, + (VOID *)((UINTN)SystemFirmwareImage + (UINTN)ConfigData->ImageOffset), + ConfigData->Length + ); + if (!EFI_ERROR(Status)) { + *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; + if (ConfigData->FirmwareType == PlatformFirmwareTypeNvRam) { + mNvRamUpdated = TRUE; + } + } else { + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + } + return Status; +} + +/** + Update System Firmware image. + + @param[in] SystemFirmwareImage Points to the System Firmware image. + @param[in] SystemFirmwareImageSize The length of the System Firmware image in bytes. + @param[in] ConfigImage Points to the config file image. + @param[in] ConfigImageSize The length of the config file image in bytes. + @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + + @retval EFI_SUCCESS The System Firmware image is updated. + @retval EFI_WRITE_PROTECTED The flash device is read only. +**/ +EFI_STATUS +UpdateImage ( + IN VOID *SystemFirmwareImage, + IN UINTN SystemFirmwareImageSize, + IN VOID *ConfigImage, + IN UINTN ConfigImageSize, + OUT UINT32 *LastAttemptVersion, + OUT UINT32 *LastAttemptStatus + ) +{ + EFI_STATUS Status; + UPDATE_CONFIG_DATA *ConfigData; + UPDATE_CONFIG_DATA *UpdateConfigData; + CONFIG_HEADER ConfigHeader; + UINTN Index; + + if (ConfigImage == NULL) { + DEBUG((DEBUG_INFO, "PlatformUpdate (NoConfig):")); + DEBUG((DEBUG_INFO, " BaseAddress - 0x%x,", 0)); + DEBUG((DEBUG_INFO, " Length - 0x%x\n", SystemFirmwareImageSize)); + // ASSUME the whole System Firmware include NVRAM region. + Status = PerformFlashWrite ( + PlatformFirmwareTypeNvRam, + 0, + FlashAddressTypeRelativeAddress, + SystemFirmwareImage, + SystemFirmwareImageSize + ); + if (!EFI_ERROR(Status)) { + *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; + mNvRamUpdated = TRUE; + } else { + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + } + return Status; + } + + DEBUG((DEBUG_INFO, "PlatformUpdate (With Config):\n")); + ConfigData = NULL; + ZeroMem (&ConfigHeader, sizeof(ConfigHeader)); + Status = ParseUpdateDataFile ( + ConfigImage, + ConfigImageSize, + &ConfigHeader, + &ConfigData + ); + DEBUG((DEBUG_INFO, "ParseUpdateDataFile - %r\n", Status)); + if (EFI_ERROR(Status)) { + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + return EFI_INVALID_PARAMETER; + } + DEBUG((DEBUG_INFO, "ConfigHeader.NumOfUpdates - 0x%x\n", ConfigHeader.NumOfUpdates)); + DEBUG((DEBUG_INFO, "PcdEdkiiSystemFirmwareFileGuid - %g\n", PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid))); + + Index = 0; + UpdateConfigData = ConfigData; + while (Index < ConfigHeader.NumOfUpdates) { + if (CompareGuid(&UpdateConfigData->FileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid))) { + DEBUG((DEBUG_INFO, "FileGuid - %g (processing)\n", &UpdateConfigData->FileGuid)); + Status = PerformUpdate ( + SystemFirmwareImage, + SystemFirmwareImageSize, + UpdateConfigData, + LastAttemptVersion, + LastAttemptStatus + ); + // + // Shall updates be serialized so that if an update is not successfully completed, + // the remaining updates won't be performed. + // + if (EFI_ERROR (Status)) { + break; + } + } else { + DEBUG((DEBUG_INFO, "FileGuid - %g (ignored)\n", &UpdateConfigData->FileGuid)); + } + + Index++; + UpdateConfigData++; + } + + return Status; +} + +/** + Authenticate and update System Firmware image. + + Caution: This function may receive untrusted input. + + @param[in] Image The EDKII system FMP capsule image. + @param[in] ImageSize The size of the EDKII system FMP capsule image in bytes. + @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + + @retval EFI_SUCCESS EDKII system FMP capsule passes authentication and the System Firmware image is updated. + @retval EFI_SECURITY_VIOLATION EDKII system FMP capsule fails authentication and the System Firmware image is not updated. + @retval EFI_WRITE_PROTECTED The flash device is read only. +**/ +EFI_STATUS +SystemFirmwareAuthenticatedUpdate ( + IN VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *LastAttemptVersion, + OUT UINT32 *LastAttemptStatus + ) +{ + EFI_STATUS Status; + VOID *SystemFirmwareImage; + UINTN SystemFirmwareImageSize; + VOID *ConfigImage; + UINTN ConfigImageSize; + VOID *AuthenticatedImage; + UINTN AuthenticatedImageSize; + + DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate...\n")); + + Status = CapsuleAuthenticateSystemFirmware(Image, ImageSize, FALSE, LastAttemptVersion, LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticateImage - %r\n", Status)); + return Status; + } + + DEBUG((DEBUG_INFO, "ExtractSystemFirmwareImage ...\n")); + ExtractSystemFirmwareImage(AuthenticatedImage, AuthenticatedImageSize, &SystemFirmwareImage, &SystemFirmwareImageSize); + DEBUG((DEBUG_INFO, "ExtractConfigImage ...\n")); + ExtractConfigImage(AuthenticatedImage, AuthenticatedImageSize, &ConfigImage, &ConfigImageSize); + + DEBUG((DEBUG_INFO, "UpdateImage ...\n")); + Status = UpdateImage(SystemFirmwareImage, SystemFirmwareImageSize, ConfigImage, ConfigImageSize, LastAttemptVersion, LastAttemptStatus); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_INFO, "UpdateImage - %r\n", Status)); + return Status; + } + + DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate Done\n")); + + return EFI_SUCCESS; +} + +/** + + This code finds variable in storage blocks (Volatile or Non-Volatile). + + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[out] Attributes Attribute value of the variable found. + @param[in, out] DataSize Size of Data found. If size is less than the + data, this value contains the required size. + @param[out] Data Data pointer. + + @return EFI_INVALID_PARAMETER Invalid parameter. + @return EFI_SUCCESS Find the specified variable. + @return EFI_NOT_FOUND Not found. + @return EFI_BUFFER_TO_SMALL DataSize is too small for the result. + +**/ +EFI_STATUS +EFIAPI +GetVariableHook ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +{ + DEBUG((DEBUG_INFO, "GetVariableHook - %S, %g\n", VariableName, VendorGuid)); + return EFI_NOT_AVAILABLE_YET; +} + +/** + + This code Finds the Next available variable. + + @param[in, out] VariableNameSize Size of the variable name. + @param[in, out] VariableName Pointer to variable name. + @param[in, out] VendorGuid Variable Vendor Guid. + + @return EFI_INVALID_PARAMETER Invalid parameter. + @return EFI_SUCCESS Find the specified variable. + @return EFI_NOT_FOUND Not found. + @return EFI_BUFFER_TO_SMALL DataSize is too small for the result. + +**/ +EFI_STATUS +EFIAPI +GetNextVariableNameHook ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ) +{ + DEBUG((DEBUG_INFO, "GetNextVariableNameHook - %S, %g\n", VariableName, VendorGuid)); + return EFI_NOT_AVAILABLE_YET; +} + +/** + + This code sets variable in storage blocks (Volatile or Non-Volatile). + + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[in] Attributes Attribute value of the variable found + @param[in] DataSize Size of Data found. If size is less than the + data, this value contains the required size. + @param[in] Data Data pointer. + + @return EFI_INVALID_PARAMETER Invalid parameter. + @return EFI_SUCCESS Set successfully. + @return EFI_OUT_OF_RESOURCES Resource not enough to set variable. + @return EFI_NOT_FOUND Not found. + @return EFI_WRITE_PROTECTED Variable is read-only. + +**/ +EFI_STATUS +EFIAPI +SetVariableHook ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +{ + DEBUG((DEBUG_INFO, "SetVariableHook - %S, %g, 0x%x (0x%x)\n", VariableName, VendorGuid, Attributes, DataSize)); + return EFI_NOT_AVAILABLE_YET; +} + +/** + + This code returns information about the EFI variables. + + @param[in] Attributes Attributes bitmask to specify the type of variables + on which to return information. + @param[out] MaximumVariableStorageSize Pointer to the maximum size of the storage space available + for the EFI variables associated with the attributes specified. + @param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available + for EFI variables associated with the attributes specified. + @param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables + associated with the attributes specified. + + @return EFI_SUCCESS Query successfully. + +**/ +EFI_STATUS +EFIAPI +QueryVariableInfoHook ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ) +{ + DEBUG((DEBUG_INFO, "QueryVariableInfoHook - 0x%x\n", Attributes)); + return EFI_NOT_AVAILABLE_YET; +} + +/** + Updates the firmware image of the device. + + This function updates the hardware with the new firmware image. + This function returns EFI_UNSUPPORTED if the firmware image is not updatable. + If the firmware image is updatable, the function should perform the following minimal validations + before proceeding to do the firmware image update. + - Validate the image authentication if image has attribute + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns + EFI_SECURITY_VIOLATION if the validation fails. + - Validate the image is a supported image for this device. The function returns EFI_ABORTED if + the image is unsupported. The function can optionally provide more detailed information on + why the image is not a supported image. + - Validate the data from VendorCode if not null. Image validation must be performed before + VendorCode data validation. VendorCode data is ignored or considered invalid if image + validation failed. The function returns EFI_ABORTED if the data is invalid. + + VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if + the caller did not specify the policy or use the default policy. As an example, vendor can implement + a policy to allow an option to force a firmware image update when the abort reason is due to the new + firmware image version is older than the current firmware image version or bad image checksum. + Sensitive operations such as those wiping the entire firmware image and render the device to be + non-functional should be encoded in the image itself rather than passed with the VendorCode. + AbortReason enables vendor to have the option to provide a more detailed description of the abort + reason to the caller. + + @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[in] Image Points to the new image. + @param[in] ImageSize Size of the new image in bytes. + @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy. + Null indicates the caller did not specify the policy or use the default policy. + @param[in] Progress A function used by the driver to report the progress of the firmware update. + @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more + details for the aborted operation. The buffer is allocated by this function + with AllocatePool(), and it is the caller's responsibility to free it with a + call to FreePool(). + + @retval EFI_SUCCESS The device was successfully updated with the new image. + @retval EFI_ABORTED The operation is aborted. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpSetImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, + OUT CHAR16 **AbortReason + ) +{ + EFI_STATUS Status; + EFI_STATUS VarStatus; + SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate; + + if (Image == NULL || ImageSize == 0 || AbortReason == NULL) { + return EFI_INVALID_PARAMETER; + } + + SystemFmpPrivate = SYSTEM_FMP_PRIVATE_DATA_FROM_FMP(This); + *AbortReason = NULL; + + if (ImageIndex == 0 || ImageIndex > SystemFmpPrivate->DescriptorCount) { + return EFI_INVALID_PARAMETER; + } + + Status = SystemFirmwareAuthenticatedUpdate((VOID *)Image, ImageSize, &SystemFmpPrivate->LastAttempt.LastAttemptVersion, &SystemFmpPrivate->LastAttempt.LastAttemptStatus); + DEBUG((DEBUG_INFO, "SetImage - LastAttemp Version - 0x%x, State - 0x%x\n", SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->LastAttempt.LastAttemptStatus)); + + // + // If NVRAM is updated, we should no longer touch variable services, because + // the current variable driver may not manage the new NVRAM region. + // + if (mNvRamUpdated) { + DEBUG ((DEBUG_INFO, "NvRamUpdated, Update Variable Serivces\n")); + gRT->GetVariable = GetVariableHook; + gRT->GetNextVariableName = GetNextVariableNameHook; + gRT->SetVariable = SetVariableHook; + gRT->QueryVariableInfo = QueryVariableInfoHook; + + gRT->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ( + (UINT8 *) &gRT->Hdr, + gRT->Hdr.HeaderSize, + &gRT->Hdr.CRC32 + ); + } + + VarStatus = gRT->SetVariable( + SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME, + &gSystemFmpLastAttemptVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(SystemFmpPrivate->LastAttempt), + &SystemFmpPrivate->LastAttempt + ); + DEBUG((DEBUG_INFO, "SetLastAttemp - %r\n", VarStatus)); + + return Status; +} + +/** + System FMP module entrypoint + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @return EFI_SUCCESS System FMP module is initialized. +**/ +EFI_STATUS +EFIAPI +SystemFirmwareUpdateMainDxe ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Initialize SystemFmpPrivateData + // + mSystemFmpPrivate = AllocateZeroPool (sizeof(SYSTEM_FMP_PRIVATE_DATA)); + if (mSystemFmpPrivate == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = InitializePrivateData(mSystemFmpPrivate); + if (EFI_ERROR(Status)) { + FreePool(mSystemFmpPrivate); + mSystemFmpPrivate = NULL; + return Status; + } + + // + // Install FMP protocol. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mSystemFmpPrivate->Handle, + &gEfiFirmwareManagementProtocolGuid, + &mSystemFmpPrivate->Fmp, + &gSystemFmpProtocolGuid, + &mSystemFmpPrivate->Fmp, + NULL + ); + if (EFI_ERROR (Status)) { + FreePool(mSystemFmpPrivate); + mSystemFmpPrivate = NULL; + return Status; + } + + return Status; +} diff --git a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf new file mode 100644 index 0000000000..7a6ca54bb3 --- /dev/null +++ b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf @@ -0,0 +1,72 @@ +## @file +# SystemFirmware FMP update driver. +# +# Produce FMP instance to update system firmware. +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SystemFirmwareUpdateDxe + MODULE_UNI_FILE = SystemFirmwareUpdateDxe.uni + FILE_GUID = 0A2FBD15-1C25-407E-8915-60C5652BC2AA + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = SystemFirmwareUpdateMainDxe + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = X64 +# + +[Sources] + SystemFirmwareCommonDxe.c + SystemFirmwareUpdateDxe.c + ParseConfigProfile.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SignedCapsulePkg/SignedCapsulePkg.dec + +[LibraryClasses] + BaseLib + UefiLib + BaseMemoryLib + DebugLib + PcdLib + MemoryAllocationLib + UefiBootServicesTableLib + HobLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + DxeServicesLib + EdkiiSystemCapsuleLib + PlatformFlashAccessLib + IniParsingLib + PrintLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGuid ## CONSUMES + gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareFileGuid ## CONSUMES + gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor ## CONSUMES + +[Protocols] + gEfiFirmwareManagementProtocolGuid ## PRODUCES + +[Depex] + gEfiVariableArchProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + SystemFirmwareUpdateDxeExtra.uni + diff --git a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni new file mode 100644 index 0000000000..40eb154628 --- /dev/null +++ b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni @@ -0,0 +1,21 @@ +// /** @file +// SystemFirmware FMP update driver. +// +// Produce FMP instance to update system firmware. +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "SystemFirmware FMP update driver." + +#string STR_MODULE_DESCRIPTION #language en-US "Produce FMP instance to update system firmware." diff --git a/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni new file mode 100644 index 0000000000..6588abce2b --- /dev/null +++ b/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni @@ -0,0 +1,20 @@ +// /** @file +// SystemFirmwareUpdateDxe Localized Strings and Content +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"SystemFirmwareUpdate DXE Driver" + +