Message ID | 20230323110906.23783-4-masahisa.kojima@linaro.org |
---|---|
State | New |
Headers | show |
Series | FMP versioning support | expand |
On Thu, 23 Mar 2023 at 13:09, Masahisa Kojima <masahisa.kojima@linaro.org> wrote: > > The FMP Payload Header which EDK II capsule generation scripts > insert contains lowest supported version. > This commit reads the lowest supported version stored in the > "FmpStateXXXX" EFI non-volatile variable, then check if the > firmware version of ongoing capsule is equal or greater than > the lowest supported version. > > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org> > --- > Changes in v4: > - use log_err() instead of printf() > > Changes in v2: > - add error message when the firmware version is lower than > lowest supported version > > lib/efi_loader/efi_firmware.c | 50 ++++++++++++++++++++++++++++++++++- > 1 file changed, 49 insertions(+), 1 deletion(-) > > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c > index 7536fcfa55..9c25b5bb38 100644 > --- a/lib/efi_loader/efi_firmware.c > +++ b/lib/efi_loader/efi_firmware.c > @@ -385,6 +385,39 @@ void efi_firmware_parse_payload_header(const void **p_image, > *p_image_size = image_size; > } > > +/** > + * efi_firmware_get_lowest_supported_version - get the lowest supported version > + * @image_index: image_index > + * > + * Get the lowest supported version from FmpStateXXXX variable. > + * > + * Return: lowest supported version, return 0 if reading FmpStateXXXX > + * variable failed > + */ > +static > +u32 efi_firmware_get_lowest_supported_version(u8 image_index) > +{ > + u16 varname[13]; /* u"FmpStateXXXX" */ > + efi_status_t ret; > + efi_uintn_t size; > + efi_guid_t *image_type_id; > + struct fmp_state var_state = { 0 }; > + > + image_type_id = efi_firmware_get_image_type_id(image_index); > + if (!image_type_id) > + return 0; > + > + efi_create_indexed_name(varname, sizeof(varname), "FmpState", > + image_index); > + size = sizeof(var_state); > + ret = efi_get_variable_int(varname, image_type_id, NULL, &size, > + &var_state, NULL); > + if (ret != EFI_SUCCESS) > + return 0; > + > + return var_state.lowest_supported_version; > +} > + > /** > * efi_firmware_verify_image - verify image > * @p_image: Pointer to new image > @@ -392,7 +425,8 @@ void efi_firmware_parse_payload_header(const void **p_image, > * @image_index Image index > * @state Pointer to fmp state > * > - * Verify the capsule file > + * Verify the capsule authentication and check if the fw_version > + * is equal or greater than the lowest supported version. > * > * Return: status code > */ > @@ -403,10 +437,24 @@ efi_status_t efi_firmware_verify_image(const void **p_image, > struct fmp_state *state) > { > efi_status_t ret; > + u32 lowest_supported_version; > > ret = efi_firmware_capsule_authenticate(p_image, p_image_size, state); > efi_firmware_parse_payload_header(p_image, p_image_size, state); > > + /* check lowest_supported_version if capsule authentication passes */ > + if (ret == EFI_SUCCESS) { > + lowest_supported_version = > + efi_firmware_get_lowest_supported_version(image_index); > + if (lowest_supported_version > state->fw_version) { > + log_err("Firmware version %u too low. Expecting >= %u. Aborting update\n", > + state->fw_version, lowest_supported_version); > + state->last_attempt_status = > + LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION; > + ret = EFI_INVALID_PARAMETER; > + } > + } > + > return ret; > } > > -- > 2.17.1 > Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index 7536fcfa55..9c25b5bb38 100644 --- a/lib/efi_loader/efi_firmware.c +++ b/lib/efi_loader/efi_firmware.c @@ -385,6 +385,39 @@ void efi_firmware_parse_payload_header(const void **p_image, *p_image_size = image_size; } +/** + * efi_firmware_get_lowest_supported_version - get the lowest supported version + * @image_index: image_index + * + * Get the lowest supported version from FmpStateXXXX variable. + * + * Return: lowest supported version, return 0 if reading FmpStateXXXX + * variable failed + */ +static +u32 efi_firmware_get_lowest_supported_version(u8 image_index) +{ + u16 varname[13]; /* u"FmpStateXXXX" */ + efi_status_t ret; + efi_uintn_t size; + efi_guid_t *image_type_id; + struct fmp_state var_state = { 0 }; + + image_type_id = efi_firmware_get_image_type_id(image_index); + if (!image_type_id) + return 0; + + efi_create_indexed_name(varname, sizeof(varname), "FmpState", + image_index); + size = sizeof(var_state); + ret = efi_get_variable_int(varname, image_type_id, NULL, &size, + &var_state, NULL); + if (ret != EFI_SUCCESS) + return 0; + + return var_state.lowest_supported_version; +} + /** * efi_firmware_verify_image - verify image * @p_image: Pointer to new image @@ -392,7 +425,8 @@ void efi_firmware_parse_payload_header(const void **p_image, * @image_index Image index * @state Pointer to fmp state * - * Verify the capsule file + * Verify the capsule authentication and check if the fw_version + * is equal or greater than the lowest supported version. * * Return: status code */ @@ -403,10 +437,24 @@ efi_status_t efi_firmware_verify_image(const void **p_image, struct fmp_state *state) { efi_status_t ret; + u32 lowest_supported_version; ret = efi_firmware_capsule_authenticate(p_image, p_image_size, state); efi_firmware_parse_payload_header(p_image, p_image_size, state); + /* check lowest_supported_version if capsule authentication passes */ + if (ret == EFI_SUCCESS) { + lowest_supported_version = + efi_firmware_get_lowest_supported_version(image_index); + if (lowest_supported_version > state->fw_version) { + log_err("Firmware version %u too low. Expecting >= %u. Aborting update\n", + state->fw_version, lowest_supported_version); + state->last_attempt_status = + LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION; + ret = EFI_INVALID_PARAMETER; + } + } + return ret; }
The FMP Payload Header which EDK II capsule generation scripts insert contains lowest supported version. This commit reads the lowest supported version stored in the "FmpStateXXXX" EFI non-volatile variable, then check if the firmware version of ongoing capsule is equal or greater than the lowest supported version. Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org> --- Changes in v4: - use log_err() instead of printf() Changes in v2: - add error message when the firmware version is lower than lowest supported version lib/efi_loader/efi_firmware.c | 50 ++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-)