/** 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; AuthenticatedImage = NULL; AuthenticatedImageSize = 0; 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; }
/** Authenticated system firmware FMP capsule image. Caution: This function may receive untrusted input. @param[in] Image The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION. @param[in] ImageSize The size of FMP capsule image in bytes. @param[in] ForceVersionMatch TRUE: The version of capsule must be as same as the version of current image. FALSE: The version of capsule must be as same as greater than the lowest supported version of current image. @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. @param[out] AuthenticatedImage The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION. @param[out] AuthenticatedImageSize The size of the authenticated capsule image in bytes. @retval TRUE Authentication passes and the authenticated image is extracted. @retval FALSE Authentication fails and the authenticated image is not extracted. **/ EFI_STATUS EFIAPI CapsuleAuthenticateSystemFirmware ( IN VOID *Image, IN UINTN ImageSize, IN BOOLEAN ForceVersionMatch, OUT UINT32 *LastAttemptVersion, OUT UINT32 *LastAttemptStatus, OUT VOID **AuthenticatedImage, OUT UINTN *AuthenticatedImageSize ) { BOOLEAN Result; EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageFmpInfo; UINTN ImageFmpInfoSize; EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageFmpInfo; UINTN CurrentImageFmpInfoSize; VOID *SystemFirmwareImage; UINTN SystemFirmwareImageSize; *LastAttemptVersion = 0; // // NOTE: This function need run in an isolated environment. // Do not touch FMP protocol and its private structure. // Result = ExtractAuthenticatedImage((VOID *)Image, ImageSize, LastAttemptStatus, AuthenticatedImage, AuthenticatedImageSize); if (!Result) { DEBUG((DEBUG_INFO, "ExtractAuthenticatedImage - fail\n")); return EFI_SECURITY_VIOLATION; } DEBUG((DEBUG_INFO, "AuthenticatedImage - 0x%x - 0x%x\n", *AuthenticatedImage, *AuthenticatedImageSize)); Result = ExtractSystemFirmwareImage(*AuthenticatedImage, *AuthenticatedImageSize, &SystemFirmwareImage, &SystemFirmwareImageSize); if (!Result) { *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; DEBUG((DEBUG_INFO, "ExtractSystemFirmwareImage - fail\n")); return EFI_SECURITY_VIOLATION; } DEBUG((DEBUG_INFO, "SystemFirmwareImage - 0x%x - 0x%x\n", SystemFirmwareImage, SystemFirmwareImageSize)); Result = ExtractSystemFirmwareImageFmpInfo(SystemFirmwareImage, SystemFirmwareImageSize, &ImageFmpInfo, &ImageFmpInfoSize); if (!Result) { *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; DEBUG((DEBUG_INFO, "ExtractSystemFirmwareImageFmpInfo - fail\n")); return EFI_SECURITY_VIOLATION; } *LastAttemptVersion = ImageFmpInfo->Version; DEBUG((DEBUG_INFO, "ImageFmpInfo - 0x%x - 0x%x\n", ImageFmpInfo, ImageFmpInfoSize)); DEBUG((DEBUG_INFO, "NewImage Version - 0x%x\n", ImageFmpInfo->Version)); DEBUG((DEBUG_INFO, "NewImage LowestSupportedImageVersion - 0x%x\n", ImageFmpInfo->LowestSupportedImageVersion)); CurrentImageFmpInfo = mImageFmpInfo; CurrentImageFmpInfoSize = mImageFmpInfoSize; DEBUG((DEBUG_INFO, "ImageFmpInfo - 0x%x - 0x%x\n", CurrentImageFmpInfo, CurrentImageFmpInfoSize)); DEBUG((DEBUG_INFO, "Current Version - 0x%x\n", CurrentImageFmpInfo->Version)); DEBUG((DEBUG_INFO, "Current LowestSupportedImageVersion - 0x%x\n", CurrentImageFmpInfo->LowestSupportedImageVersion)); if (ForceVersionMatch) { if (CurrentImageFmpInfo->Version != ImageFmpInfo->Version) { *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION; DEBUG((DEBUG_INFO, "ForceVersionMatch check - fail\n")); return EFI_SECURITY_VIOLATION; } } else { if (CurrentImageFmpInfo->Version < ImageFmpInfo->LowestSupportedImageVersion) { *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION; DEBUG((DEBUG_INFO, "LowestSupportedImageVersion check - fail\n")); return EFI_SECURITY_VIOLATION; } } *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; return EFI_SUCCESS; }