diff --git a/core/attestation/pcr.c b/core/attestation/pcr.c index 543f4ad..a5f6dcf 100644 --- a/core/attestation/pcr.c +++ b/core/attestation/pcr.c @@ -593,7 +593,7 @@ static int pcr_get_measurement_data_internal (struct pcr_bank *pcr, uint8_t meas break; case PCR_DATA_TYPE_FLASH: { - struct flash *flash_device = measured_data->data.flash.flash; + const struct flash *flash_device = measured_data->data.flash.flash; size_t read_addr = measured_data->data.flash.addr + offset; if (offset > (measured_data->data.flash.length - 1)) { diff --git a/core/attestation/pcr_data.h b/core/attestation/pcr_data.h index d7c77a0..46d662b 100644 --- a/core/attestation/pcr_data.h +++ b/core/attestation/pcr_data.h @@ -55,7 +55,7 @@ struct pcr_measured_data { } memory; /**< Container for measured data stored in memory */ struct { - struct flash *flash; /**< Flash device containing the measured data */ + const struct flash *flash; /**< Flash device containing the measured data */ uint32_t addr; /**< Address in flash */ size_t length; /**< Measured data length */ } flash; /**< Container for measured data stored in flash */ diff --git a/core/common/image_header.c b/core/common/image_header.c index ca9a9c0..6e6d260 100644 --- a/core/common/image_header.c +++ b/core/common/image_header.c @@ -17,7 +17,7 @@ * * @return 0 if the header information was successfully loaded from flash or an error code. */ -int image_header_init (struct image_header *header, struct flash *flash, uint32_t addr, +int image_header_init (struct image_header *header, const struct flash *flash, uint32_t addr, uint32_t magic_num, size_t max_len) { int status; @@ -52,7 +52,7 @@ int image_header_init (struct image_header *header, struct flash *flash, uint32_ * Release the recovery image header data. * * @param header The header instance to release. - */ + */ void image_header_release (struct image_header *header) { if (header) { @@ -68,9 +68,9 @@ void image_header_release (struct image_header *header) * @param flash The flash that contains the image header. * @param addr The base address of the header. * - * @return 0 if header data was successfully loaded from flash or an error code. + * @return 0 if header data was successfully loaded from flash or an error code. */ -int image_header_load_data (struct image_header *header, struct flash *flash, uint32_t addr) +int image_header_load_data (struct image_header *header, const struct flash *flash, uint32_t addr) { size_t length; int status; @@ -102,7 +102,7 @@ int image_header_load_data (struct image_header *header, struct flash *flash, ui * * @return The total number of bytes in the header. */ -int image_header_get_length (struct image_header *header) +int image_header_get_length (const struct image_header *header) { if (header) { return header->info.length; diff --git a/core/common/image_header.h b/core/common/image_header.h index 5733c3c..44b7cf3 100644 --- a/core/common/image_header.h +++ b/core/common/image_header.h @@ -29,12 +29,13 @@ struct image_header { }; -int image_header_init (struct image_header *header, struct flash *flash, uint32_t addr, +int image_header_init (struct image_header *header, const struct flash *flash, uint32_t addr, uint32_t magic_num, size_t max_len); void image_header_release (struct image_header *header); -int image_header_load_data (struct image_header *header, struct flash *flash, uint32_t addr); -int image_header_get_length (struct image_header *header); +int image_header_load_data (struct image_header *header, const struct flash *flash, uint32_t addr); + +int image_header_get_length (const struct image_header *header); #define IMAGE_HEADER_ERROR(code) ROT_ERROR (ROT_MODULE_IMAGE_HEADER, code) diff --git a/core/firmware/app_context.h b/core/firmware/app_context.h index 3ee6dc5..001b94a 100644 --- a/core/firmware/app_context.h +++ b/core/firmware/app_context.h @@ -19,7 +19,7 @@ struct app_context { * * @return 0 if the application context has been saved or an error code. */ - int (*save) (struct app_context *context); + int (*save) (const struct app_context *context); }; diff --git a/core/firmware/app_image.c b/core/firmware/app_image.c index d702a28..02725c0 100644 --- a/core/firmware/app_image.c +++ b/core/firmware/app_image.c @@ -22,9 +22,9 @@ * * @return 0 if the application image is valid or an error code. */ -int app_image_verification (struct flash *flash, uint32_t start_addr, struct hash_engine *hash, - struct rsa_engine *rsa, const struct rsa_public_key *pub_key, uint8_t *hash_out, - size_t hash_length) +int app_image_verification (const struct flash *flash, uint32_t start_addr, + struct hash_engine *hash, struct rsa_engine *rsa, const struct rsa_public_key *pub_key, + uint8_t *hash_out, size_t hash_length) { return app_image_verification_with_header (flash, start_addr, 0, hash, rsa, pub_key, hash_out, hash_length); @@ -45,7 +45,7 @@ int app_image_verification (struct flash *flash, uint32_t start_addr, struct has * * @return 0 if the application image and the additional header are valid or an error code. */ -int app_image_verification_with_header (struct flash *flash, uint32_t start_addr, +int app_image_verification_with_header (const struct flash *flash, uint32_t start_addr, size_t header_length, struct hash_engine *hash, struct rsa_engine *rsa, const struct rsa_public_key *pub_key, uint8_t *hash_out, size_t hash_legnth) { @@ -88,8 +88,8 @@ int app_image_verification_with_header (struct flash *flash, uint32_t start_addr * * @return 0 if the entire application image was successfully loaded into memory or an error code. */ -int app_image_load (struct flash *flash, uint32_t start_addr, uint8_t *load_addr, size_t max_length, - size_t *load_length) +int app_image_load (const struct flash *flash, uint32_t start_addr, uint8_t *load_addr, + size_t max_length, size_t *load_length) { uint32_t length; int status; @@ -136,7 +136,7 @@ int app_image_load (struct flash *flash, uint32_t start_addr, uint8_t *load_addr * * @return 0 if the application image was loaded to memory and verified as good or an error code. */ -int app_image_load_and_verify (struct flash *flash, uint32_t start_addr, uint8_t *load_addr, +int app_image_load_and_verify (const struct flash *flash, uint32_t start_addr, uint8_t *load_addr, size_t max_length, struct hash_engine *hash, struct rsa_engine *rsa, const struct rsa_public_key *pub_key, uint8_t *hash_out, size_t hash_length, size_t *load_length) @@ -165,7 +165,7 @@ int app_image_load_and_verify (struct flash *flash, uint32_t start_addr, uint8_t * * @return 0 if the application image was loaded to memory and verified as good or an error code. */ -int app_image_load_and_verify_with_header (struct flash *flash, uint32_t start_addr, +int app_image_load_and_verify_with_header (const struct flash *flash, uint32_t start_addr, size_t header_length, uint8_t *load_addr, size_t max_length, struct hash_engine *hash, struct rsa_engine *rsa, const struct rsa_public_key *pub_key, uint8_t *hash_out, size_t hash_length, size_t *load_length) @@ -265,7 +265,7 @@ hash_fail: * * @return 0 if the image signature was successfully retrieved or an error code. */ -int app_image_get_signature (struct flash *flash, uint32_t start_addr, uint8_t *sig_out, +int app_image_get_signature (const struct flash *flash, uint32_t start_addr, uint8_t *sig_out, size_t sig_length) { uint32_t length; @@ -299,7 +299,7 @@ int app_image_get_signature (struct flash *flash, uint32_t start_addr, uint8_t * * * @return 0 if the image hash was successfully calculated or an error code. */ -int app_image_get_hash (struct flash *flash, uint32_t start_addr, struct hash_engine *hash, +int app_image_get_hash (const struct flash *flash, uint32_t start_addr, struct hash_engine *hash, uint8_t *hash_out, size_t hash_length) { return app_image_get_hash_with_header (flash, start_addr, 0, hash, hash_out, hash_length); @@ -319,8 +319,8 @@ int app_image_get_hash (struct flash *flash, uint32_t start_addr, struct hash_en * * @return 0 if the image hash was successfully calculated or an error code. */ -int app_image_get_hash_with_header (struct flash *flash, uint32_t start_addr, size_t header_length, - struct hash_engine *hash, uint8_t *hash_out, size_t hash_length) +int app_image_get_hash_with_header (const struct flash *flash, uint32_t start_addr, + size_t header_length, struct hash_engine *hash, uint8_t *hash_out, size_t hash_length) { uint32_t length; int status; @@ -351,7 +351,7 @@ int app_image_get_hash_with_header (struct flash *flash, uint32_t start_addr, si * * @return 0 if the data address was successfully retrieved or an error code. */ -int app_image_get_data_addr (struct flash *flash, uint32_t start_addr, uint32_t *data_addr) +int app_image_get_data_addr (const struct flash *flash, uint32_t start_addr, uint32_t *data_addr) { if ((flash == NULL) || (data_addr == NULL)) { return APP_IMAGE_INVALID_ARGUMENT; @@ -372,7 +372,7 @@ int app_image_get_data_addr (struct flash *flash, uint32_t start_addr, uint32_t * * @return 0 if the image length was successfully retrieved or an error code. */ -int app_image_get_length (struct flash *flash, uint32_t start_addr, uint32_t *img_length) +int app_image_get_length (const struct flash *flash, uint32_t start_addr, uint32_t *img_length) { if ((flash == NULL) || (img_length == NULL)) { return APP_IMAGE_INVALID_ARGUMENT; @@ -392,7 +392,7 @@ int app_image_get_length (struct flash *flash, uint32_t start_addr, uint32_t *im * * @return 0 if the image ending was successfully retrieved or an error code. */ -int app_image_get_image_end (struct flash *flash, uint32_t start_addr, uint32_t *end_addr) +int app_image_get_image_end (const struct flash *flash, uint32_t start_addr, uint32_t *end_addr) { uint32_t length; int status; diff --git a/core/firmware/app_image.h b/core/firmware/app_image.h index 1cb74ab..8f7ac78 100644 --- a/core/firmware/app_image.h +++ b/core/firmware/app_image.h @@ -21,34 +21,34 @@ #define APP_IMAGE_SIG_LENGTH 256 -int app_image_verification (struct flash *flash, uint32_t start_addr, struct hash_engine *hash, - struct rsa_engine *rsa, const struct rsa_public_key *pub_key, uint8_t *hash_out, - size_t hash_length); -int app_image_verification_with_header (struct flash *flash, uint32_t start_addr, +int app_image_verification (const struct flash *flash, uint32_t start_addr, + struct hash_engine *hash, struct rsa_engine *rsa, const struct rsa_public_key *pub_key, + uint8_t *hash_out, size_t hash_length); +int app_image_verification_with_header (const struct flash *flash, uint32_t start_addr, size_t header_length, struct hash_engine *hash, struct rsa_engine *rsa, const struct rsa_public_key *pub_key, uint8_t *hash_out, size_t hash_length); -int app_image_load (struct flash *flash, uint32_t start_addr, uint8_t *load_addr, size_t max_length, - size_t *load_length); -int app_image_load_and_verify (struct flash *flash, uint32_t start_addr, uint8_t *load_addr, +int app_image_load (const struct flash *flash, uint32_t start_addr, uint8_t *load_addr, + size_t max_length, size_t *load_length); +int app_image_load_and_verify (const struct flash *flash, uint32_t start_addr, uint8_t *load_addr, size_t max_length, struct hash_engine *hash, struct rsa_engine *rsa, const struct rsa_public_key *pub_key, uint8_t *hash_out, size_t hash_length, size_t *load_length); -int app_image_load_and_verify_with_header (struct flash *flash, uint32_t start_addr, +int app_image_load_and_verify_with_header (const struct flash *flash, uint32_t start_addr, size_t header_length, uint8_t *load_addr, size_t max_length, struct hash_engine *hash, struct rsa_engine *rsa, const struct rsa_public_key *pub_key, uint8_t *hash_out, size_t hash_length, size_t *load_length); -int app_image_get_signature (struct flash *flash, uint32_t start_addr, uint8_t *sig_out, +int app_image_get_signature (const struct flash *flash, uint32_t start_addr, uint8_t *sig_out, size_t sig_length); -int app_image_get_hash (struct flash *flash, uint32_t start_addr, struct hash_engine *hash, +int app_image_get_hash (const struct flash *flash, uint32_t start_addr, struct hash_engine *hash, uint8_t *hash_out, size_t hash_length); -int app_image_get_hash_with_header (struct flash *flash, uint32_t start_addr, size_t header_length, - struct hash_engine *hash, uint8_t *hash_out, size_t hash_length); +int app_image_get_hash_with_header (const struct flash *flash, uint32_t start_addr, + size_t header_length, struct hash_engine *hash, uint8_t *hash_out, size_t hash_length); -int app_image_get_data_addr (struct flash *flash, uint32_t start_addr, uint32_t *data_addr); -int app_image_get_length (struct flash *flash, uint32_t start_addr, uint32_t *img_length); -int app_image_get_image_end (struct flash *flash, uint32_t start_addr, uint32_t *end_addr); +int app_image_get_data_addr (const struct flash *flash, uint32_t start_addr, uint32_t *data_addr); +int app_image_get_length (const struct flash *flash, uint32_t start_addr, uint32_t *img_length); +int app_image_get_image_end (const struct flash *flash, uint32_t start_addr, uint32_t *end_addr); #define APP_IMAGE_ERROR(code) ROT_ERROR (ROT_MODULE_APP_IMAGE, code) diff --git a/core/firmware/firmware_component.c b/core/firmware/firmware_component.c index dc0a16d..64de340 100644 --- a/core/firmware/firmware_component.c +++ b/core/firmware/firmware_component.c @@ -50,7 +50,7 @@ union firmware_component_header_format { * * @return 0 if the component was successfully initialize or an error code. */ -int firmware_component_init (struct firmware_component *image, struct flash *flash, +int firmware_component_init (struct firmware_component *image, const struct flash *flash, uint32_t start_addr, uint32_t marker) { int status; @@ -103,8 +103,8 @@ int firmware_component_init (struct firmware_component *image, struct flash *fla * * @return 0 if the component was successfully initialized or an error code. */ -int firmware_component_init_with_header (struct firmware_component *image, struct flash *flash, - uint32_t start_addr, uint32_t marker, size_t header_length) +int firmware_component_init_with_header (struct firmware_component *image, + const struct flash *flash, uint32_t start_addr, uint32_t marker, size_t header_length) { int status; @@ -138,7 +138,7 @@ void firmware_component_release (struct firmware_component *image) * * @return The size of the component image. */ -static size_t firmware_component_get_image_length (struct firmware_component *image) +static size_t firmware_component_get_image_length (const struct firmware_component *image) { return image->header.info.length + FW_COMPONENT_HDR (image, 0).length + image->offset; } @@ -152,7 +152,7 @@ static size_t firmware_component_get_image_length (struct firmware_component *im * * @return 0 if the signature was read or an error code. */ -static int firmware_component_read_signature_data (struct firmware_component *image, +static int firmware_component_read_signature_data (const struct firmware_component *image, uint8_t **signature, size_t *sig_length) { int status; @@ -187,8 +187,9 @@ static int firmware_component_read_signature_data (struct firmware_component *im * * @return 0 if the component image is valid or an error code. */ -int firmware_component_verification (struct firmware_component *image, struct hash_engine *hash, - struct signature_verification *verification, uint8_t *hash_out, size_t hash_length) +int firmware_component_verification (const struct firmware_component *image, + struct hash_engine *hash, struct signature_verification *verification, uint8_t *hash_out, + size_t hash_length) { uint8_t *signature; size_t sig_length; @@ -228,7 +229,7 @@ int firmware_component_verification (struct firmware_component *image, struct ha * * @return 0 if the component was loaded into memory or an error code. */ -int firmware_component_load (struct firmware_component *image, uint8_t *load_addr, +int firmware_component_load (const struct firmware_component *image, uint8_t *load_addr, size_t max_length, size_t *load_length) { int status; @@ -270,7 +271,7 @@ int firmware_component_load (struct firmware_component *image, uint8_t *load_add * * @return 0 if the component was loaded to memory and verified as good or an error code. */ -int firmware_component_load_and_verify (struct firmware_component *image, uint8_t *load_addr, +int firmware_component_load_and_verify (const struct firmware_component *image, uint8_t *load_addr, size_t max_length, struct hash_engine *hash, struct signature_verification *verification, uint8_t *hash_out, size_t hash_length, size_t *load_length) { @@ -383,8 +384,9 @@ hash_fail: * * @return 0 if the component data is contained on the destination flash or an error code. */ -static int firmware_component_copy_to_flash (struct firmware_component *image, struct flash *flash, - uint32_t dest_addr, size_t max_length, size_t *copy_length, bool force_copy) +static int firmware_component_copy_to_flash (const struct firmware_component *image, + const struct flash *flash, uint32_t dest_addr, size_t max_length, size_t *copy_length, + bool force_copy) { int status; @@ -444,10 +446,11 @@ exit: * * @return 0 if the component was successfully copied to flash or an error code. */ -int firmware_component_copy (struct firmware_component *image, struct flash *flash, +int firmware_component_copy (const struct firmware_component *image, const struct flash *flash, uint32_t dest_addr, size_t max_length, size_t *copy_length) { - return firmware_component_copy_to_flash (image, flash, dest_addr, max_length, copy_length, true); + return firmware_component_copy_to_flash (image, flash, dest_addr, max_length, copy_length, + true); } /** @@ -465,10 +468,11 @@ int firmware_component_copy (struct firmware_component *image, struct flash *fla * * @return 0 if the component data is contained on the destination flash or an error code. */ -int firmware_component_compare_and_copy (struct firmware_component *image, struct flash *flash, - uint32_t dest_addr, size_t max_length, size_t *copy_length) +int firmware_component_compare_and_copy (const struct firmware_component *image, + const struct flash *flash, uint32_t dest_addr, size_t max_length, size_t *copy_length) { - return firmware_component_copy_to_flash (image, flash, dest_addr, max_length, copy_length, false); + return firmware_component_copy_to_flash (image, flash, dest_addr, max_length, copy_length, + false); } /** @@ -478,7 +482,7 @@ int firmware_component_compare_and_copy (struct firmware_component *image, struc * * @return The length of the image signature. */ -size_t firmware_component_get_signature_length (struct firmware_component *image) +size_t firmware_component_get_signature_length (const struct firmware_component *image) { if (image) { return FW_COMPONENT_HDR (image, 0).sig_length; @@ -498,7 +502,7 @@ size_t firmware_component_get_signature_length (struct firmware_component *image * @return The length of the signature in the buffer or an error code. Use ROT_IS_ERROR to check * the return for an error. */ -int firmware_component_get_signature (struct firmware_component *image, uint8_t *sig_out, +int firmware_component_get_signature (const struct firmware_component *image, uint8_t *sig_out, size_t sig_length) { size_t length; @@ -534,7 +538,7 @@ int firmware_component_get_signature (struct firmware_component *image, uint8_t * * @return 0 if the hash was calculated successfully or an error code. */ -int firmware_component_get_hash (struct firmware_component *image, struct hash_engine *hash, +int firmware_component_get_hash (const struct firmware_component *image, struct hash_engine *hash, uint8_t *hash_out, size_t hash_length) { size_t length; @@ -560,7 +564,7 @@ int firmware_component_get_hash (struct firmware_component *image, struct hash_e * * @return The flash address for the start of firmware data. */ -uint32_t firmware_component_get_data_addr (struct firmware_component *image) +uint32_t firmware_component_get_data_addr (const struct firmware_component *image) { if (image) { return image->start_addr + image->offset + image->header.info.length; @@ -578,7 +582,7 @@ uint32_t firmware_component_get_data_addr (struct firmware_component *image) * * @return The size of the component image. */ -size_t firmware_component_get_length (struct firmware_component *image) +size_t firmware_component_get_length (const struct firmware_component *image) { if (image) { return FW_COMPONENT_HDR (image, 0).length; @@ -597,7 +601,7 @@ size_t firmware_component_get_length (struct firmware_component *image) * * @return The address at the end of the image. */ -uint32_t firmware_component_get_image_end (struct firmware_component *image) +uint32_t firmware_component_get_image_end (const struct firmware_component *image) { if (image) { return image->start_addr + firmware_component_get_image_length (image) + diff --git a/core/firmware/firmware_component.h b/core/firmware/firmware_component.h index 16c5eb4..0f65805 100644 --- a/core/firmware/firmware_component.h +++ b/core/firmware/firmware_component.h @@ -17,42 +17,43 @@ * Handler for a single application component within a firmware image. */ struct firmware_component { - struct flash *flash; /**< Flash device containing the component. */ + const struct flash *flash; /**< Flash device containing the component. */ uint32_t start_addr; /**< Base address on flash of the component. */ size_t offset; /**< Offset to the start of the component image. */ struct image_header header; /**< Header for the component. */ }; -int firmware_component_init (struct firmware_component *image, struct flash *flash, +int firmware_component_init (struct firmware_component *image, const struct flash *flash, uint32_t start_addr, uint32_t marker); -int firmware_component_init_with_header (struct firmware_component *image, struct flash *flash, - uint32_t start_addr, uint32_t marker, size_t header_length); +int firmware_component_init_with_header (struct firmware_component *image, + const struct flash *flash, uint32_t start_addr, uint32_t marker, size_t header_length); void firmware_component_release (struct firmware_component *image); -int firmware_component_verification (struct firmware_component *image, struct hash_engine *hash, - struct signature_verification *verification, uint8_t *hash_out, size_t hash_length); +int firmware_component_verification (const struct firmware_component *image, + struct hash_engine *hash, struct signature_verification *verification, uint8_t *hash_out, + size_t hash_length); -int firmware_component_load (struct firmware_component *image, uint8_t *load_addr, +int firmware_component_load (const struct firmware_component *image, uint8_t *load_addr, size_t max_length, size_t *load_length); -int firmware_component_load_and_verify (struct firmware_component *image, uint8_t *load_addr, +int firmware_component_load_and_verify (const struct firmware_component *image, uint8_t *load_addr, size_t max_length, struct hash_engine *hash, struct signature_verification *verification, uint8_t *hash_out, size_t hash_length, size_t *load_length); -int firmware_component_copy (struct firmware_component *image, struct flash *flash, - uint32_t dest_addr, size_t max_length, size_t *copy_length); -int firmware_component_compare_and_copy (struct firmware_component *image, struct flash *flash, +int firmware_component_copy (const struct firmware_component *image, const struct flash *flash, uint32_t dest_addr, size_t max_length, size_t *copy_length); +int firmware_component_compare_and_copy (const struct firmware_component *image, + const struct flash *flash, uint32_t dest_addr, size_t max_length, size_t *copy_length); -size_t firmware_component_get_signature_length (struct firmware_component *image); -int firmware_component_get_signature (struct firmware_component *image, uint8_t *sig_out, +size_t firmware_component_get_signature_length (const struct firmware_component *image); +int firmware_component_get_signature (const struct firmware_component *image, uint8_t *sig_out, size_t sig_length); -int firmware_component_get_hash (struct firmware_component *image, struct hash_engine *hash, +int firmware_component_get_hash (const struct firmware_component *image, struct hash_engine *hash, uint8_t *hash_out, size_t hash_length); -uint32_t firmware_component_get_data_addr (struct firmware_component *image); -size_t firmware_component_get_length (struct firmware_component *image); -uint32_t firmware_component_get_image_end (struct firmware_component *image); +uint32_t firmware_component_get_data_addr (const struct firmware_component *image); +size_t firmware_component_get_length (const struct firmware_component *image); +uint32_t firmware_component_get_image_end (const struct firmware_component *image); #define FIRMWARE_COMPONENT_ERROR(code) ROT_ERROR (ROT_MODULE_FIRMWARE_COMPONENT, code) diff --git a/core/firmware/firmware_header.c b/core/firmware/firmware_header.c index 9db19f1..dd2881d 100644 --- a/core/firmware/firmware_header.c +++ b/core/firmware/firmware_header.c @@ -51,7 +51,7 @@ union firmware_header_format { * * @return 0 if the header was successfully loaded from flash or an error code. */ -int firmware_header_init (struct firmware_header *header, struct flash *flash, uint32_t addr) +int firmware_header_init (struct firmware_header *header, const struct flash *flash, uint32_t addr) { size_t length; int status; @@ -118,7 +118,7 @@ void firmware_header_release (struct firmware_header *header) * * @return 0 if the revision was available in the header or an error code. */ -int firmware_header_get_recovery_revision (struct firmware_header *header, int *revision) +int firmware_header_get_recovery_revision (const struct firmware_header *header, int *revision) { if ((header == NULL) || (revision == NULL)) { return FIRMWARE_HEADER_INVALID_ARGUMENT; @@ -137,7 +137,7 @@ int firmware_header_get_recovery_revision (struct firmware_header *header, int * * * @return The number of extra images or an error code. */ -int firmware_header_get_extra_images (struct firmware_header *header) +int firmware_header_get_extra_images (const struct firmware_header *header) { if (header == NULL) { return FIRMWARE_HEADER_INVALID_ARGUMENT; @@ -158,7 +158,8 @@ int firmware_header_get_extra_images (struct firmware_header *header) * * @return 0 if the revision was available in the header or an error code. */ -int firmware_header_get_earliest_allowed_revision (struct firmware_header *header, int *revision) +int firmware_header_get_earliest_allowed_revision (const struct firmware_header *header, + int *revision) { if ((header == NULL) || (revision == NULL)) { return FIRMWARE_HEADER_INVALID_ARGUMENT; @@ -187,7 +188,7 @@ int firmware_header_get_earliest_allowed_revision (struct firmware_header *heade * * @return 0 if the signature information was available in the header or an error code. */ -int firmware_header_get_signature_info (struct firmware_header *header, size_t *signed_length, +int firmware_header_get_signature_info (const struct firmware_header *header, size_t *signed_length, size_t *sig_length) { if ((header == NULL) || (signed_length == NULL) || (sig_length == NULL)) { diff --git a/core/firmware/firmware_header.h b/core/firmware/firmware_header.h index 831894d..0fe9b6f 100644 --- a/core/firmware/firmware_header.h +++ b/core/firmware/firmware_header.h @@ -22,13 +22,14 @@ struct firmware_header { }; -int firmware_header_init (struct firmware_header *header, struct flash *flash, uint32_t addr); +int firmware_header_init (struct firmware_header *header, const struct flash *flash, uint32_t addr); void firmware_header_release (struct firmware_header *header); -int firmware_header_get_recovery_revision (struct firmware_header *header, int *revision); -int firmware_header_get_extra_images (struct firmware_header *header); -int firmware_header_get_earliest_allowed_revision (struct firmware_header *header, int *revision); -int firmware_header_get_signature_info (struct firmware_header *header, size_t *signed_length, +int firmware_header_get_recovery_revision (const struct firmware_header *header, int *revision); +int firmware_header_get_extra_images (const struct firmware_header *header); +int firmware_header_get_earliest_allowed_revision (const struct firmware_header *header, + int *revision); +int firmware_header_get_signature_info (const struct firmware_header *header, size_t *signed_length, size_t *sig_length); diff --git a/core/firmware/firmware_image.h b/core/firmware/firmware_image.h index 5b8f634..61eded0 100644 --- a/core/firmware/firmware_image.h +++ b/core/firmware/firmware_image.h @@ -29,7 +29,7 @@ struct firmware_image { * * @return 0 if the image reference was updated successfully or an error code. */ - int (*load) (struct firmware_image *fw, struct flash *flash, uint32_t base_addr); + int (*load) (const struct firmware_image *fw, const struct flash *flash, uint32_t base_addr); /** * Verify the complete firmware image. All components in the image will be fully validated. @@ -46,7 +46,7 @@ struct firmware_image { * incorrect signature, FIRMWARE_IMAGE_BAD_SIGNATURE will be returned, regardless of the * underlying signature verification algorithm. */ - int (*verify) (struct firmware_image *fw, struct hash_engine *hash); + int (*verify) (const struct firmware_image *fw, struct hash_engine *hash); /** * Get the total size of the firmware image. @@ -56,7 +56,7 @@ struct firmware_image { * @return The size of the firmware image or an error code. Use ROT_IS_ERROR to check the * return value. */ - int (*get_image_size) (struct firmware_image *fw); + int (*get_image_size) (const struct firmware_image *fw); /** * Get the key manifest for the current firmware image. @@ -67,7 +67,7 @@ struct firmware_image { * manifest is managed by the firmware image instance and is only guaranteed to be valid until * the next call to firmware_image.load. */ - struct key_manifest* (*get_key_manifest) (struct firmware_image *fw); + const struct key_manifest* (*get_key_manifest) (const struct firmware_image *fw); /** * Get the main image header for the current firmware image. @@ -78,7 +78,7 @@ struct firmware_image { * is managed by the firmware image instance and is only guaranteed to be valid until the next * call to firmware_image.load. */ - struct firmware_header* (*get_firmware_header) (struct firmware_image *fw); + const struct firmware_header* (*get_firmware_header) (const struct firmware_image *fw); }; diff --git a/core/firmware/firmware_update.c b/core/firmware/firmware_update.c index 4e8b7bf..c643b7c 100644 --- a/core/firmware/firmware_update.c +++ b/core/firmware/firmware_update.c @@ -14,6 +14,7 @@ * Initialize the platform firmware updater. * * @param updater The updater to initialize. + * @param state Variable context for the updater. This must be uninitialized. * @param flash The device and address mapping for firmware images. * @param context The application context API. * @param fw The platform handler for firmware images. @@ -22,45 +23,102 @@ * * @return 0 if the updater was successfully initialized or an error code. */ -int firmware_update_init (struct firmware_update *updater, const struct firmware_flash_map *flash, - struct app_context *context, struct firmware_image *fw, struct hash_engine *hash, - int allowed_revision) +int firmware_update_init (struct firmware_update *updater, struct firmware_update_state *state, + const struct firmware_flash_map *flash, const struct app_context *context, + const struct firmware_image *fw, struct hash_engine *hash, int allowed_revision) { - int status; - - if ((updater == NULL) || (flash == NULL) || (context == NULL) || (fw == NULL) || - (hash == NULL)) { + if (updater == NULL) { return FIRMWARE_UPDATE_INVALID_ARGUMENT; } - if ((flash->active_flash == NULL) || (flash->staging_flash == NULL)) { - return FIRMWARE_UPDATE_INVALID_FLASH_MAP; - } - - if ((flash->backup_flash == NULL) && (flash->recovery_flash == NULL)) { - return FIRMWARE_UPDATE_INVALID_FLASH_MAP; - } - memset (updater, 0, sizeof (struct firmware_update)); - status = flash_updater_init (&updater->update_mgr, flash->staging_flash, flash->staging_addr, - flash->staging_size); - if (status != 0) { - return status; - } - - status = observable_init (&updater->observable); - if (status != 0) { - flash_updater_release (&updater->update_mgr); - return status; - } - + updater->state = state; updater->flash = flash; updater->fw = fw; updater->context = context; updater->hash = hash; - updater->recovery_rev = -1; - updater->min_rev = allowed_revision; + + return firmware_update_init_state (updater, allowed_revision); +} + +/** + * Initialize the platform firmware updater. + * + * Firmware images processed by the updater are not required to contain a firmware header. If the + * firmware header is present, it will be processed. If the firmware header is not present, the + * update will proceed without it and any workflows that require information from the header will + * be skipped. + * + * @param updater The updater to initialize. + * @param state Variable context for the updater. This must be uninitialized. + * @param flash The device and address mapping for firmware images. + * @param context The application context API. + * @param fw The platform handler for firmware images. + * @param hash The hash engine to use during updates. + * @param allowed_revision The lowest image ID that will be allowed for firmware updates. + * + * @return 0 if the updater was successfully initialized or an error code. + */ +int firmware_update_init_no_firmware_header (struct firmware_update *updater, + struct firmware_update_state *state, const struct firmware_flash_map *flash, + const struct app_context *context, const struct firmware_image *fw, struct hash_engine *hash, + int allowed_revision) +{ + int status; + + status = firmware_update_init (updater, state, flash, context, fw, hash, allowed_revision); + if (status == 0) { + updater->no_fw_header = true; + } + + return status; +} + +/** + * Initialize only the variable state for a firmware update handler. The rest of the firmware + * update instance is assumed to have already been initialized. + * + * This would generally be used with a statically initialized instance. + * + * @param updater The updater instance that contains the state to initialize. + * @param allowed_revision The lowest image ID that will be allowed for firmware updates. + * + * @return 0 if the state was successfully initialized or an error code. + */ +int firmware_update_init_state (const struct firmware_update *updater, int allowed_revision) +{ + int status; + + if ((updater == NULL) || (updater->state == NULL) || (updater->flash == NULL) || + (updater->context == NULL) || (updater->fw == NULL) || (updater->hash == NULL)) { + return FIRMWARE_UPDATE_INVALID_ARGUMENT; + } + + if ((updater->flash->active_flash == NULL) || (updater->flash->staging_flash == NULL)) { + return FIRMWARE_UPDATE_INVALID_FLASH_MAP; + } + + if ((updater->flash->backup_flash == NULL) && (updater->flash->recovery_flash == NULL)) { + return FIRMWARE_UPDATE_INVALID_FLASH_MAP; + } + + memset (updater->state, 0, sizeof (struct firmware_update_state)); + + status = flash_updater_init (&updater->state->update_mgr, updater->flash->staging_flash, + updater->flash->staging_addr, updater->flash->staging_size); + if (status != 0) { + return status; + } + + status = observable_init (&updater->state->observable); + if (status != 0) { + flash_updater_release (&updater->state->update_mgr); + return status; + } + + updater->state->recovery_rev = -1; + updater->state->min_rev = allowed_revision; return 0; } @@ -70,11 +128,11 @@ int firmware_update_init (struct firmware_update *updater, const struct firmware * * @param updater The updater to release. */ -void firmware_update_release (struct firmware_update *updater) +void firmware_update_release (const struct firmware_update *updater) { if (updater) { - observable_release (&updater->observable); - flash_updater_release (&updater->update_mgr); + observable_release (&updater->state->observable); + flash_updater_release (&updater->state->update_mgr); } } @@ -86,31 +144,11 @@ void firmware_update_release (struct firmware_update *updater) * @param updater The firmware updater to configure. * @param offset The offset to apply to images. */ -void firmware_update_set_image_offset (struct firmware_update *updater, int offset) +void firmware_update_set_image_offset (const struct firmware_update *updater, int offset) { if (updater != NULL) { - updater->img_offset = offset; - flash_updater_apply_update_offset (&updater->update_mgr, offset); - } -} - -/** - * Indicate to the updater if the firmware image is required to contain a firmware header or not. - * When a firmware header is required, images that fail to provide one will result in failure to - * apply that image. - * - * It is expected that this would be configured during initialization based on the firmware image - * expectations for a particular system. - * - * By default, the updater requires a firmware header on the image. - * - * @param updater The firmware updater to configure. - * @param has_fw_header Flag indicating if a firmware header is required for the update to succeed. - */ -void firmware_update_require_firmware_header (struct firmware_update *updater, bool has_fw_header) -{ - if (updater != NULL) { - updater->no_fw_header = !has_fw_header; + updater->state->img_offset = offset; + flash_updater_apply_update_offset (&updater->state->update_mgr, offset); } } @@ -124,10 +162,10 @@ void firmware_update_require_firmware_header (struct firmware_update *updater, b * @param updater The firmware updater to configure. * @param img_good Flag indicating if the current recovery image is good. */ -void firmware_update_set_recovery_good (struct firmware_update *updater, bool img_good) +void firmware_update_set_recovery_good (const struct firmware_update *updater, bool img_good) { if (updater != NULL) { - updater->recovery_bad = !img_good; + updater->state->recovery_bad = !img_good; } } @@ -138,10 +176,10 @@ void firmware_update_set_recovery_good (struct firmware_update *updater, bool im * @param updater The firmware updater to configure. * @param revision The revision ID of the recovery image. */ -void firmware_update_set_recovery_revision (struct firmware_update *updater, int revision) +void firmware_update_set_recovery_revision (const struct firmware_update *updater, int revision) { if (updater != NULL) { - updater->recovery_rev = revision; + updater->state->recovery_rev = revision; } } @@ -155,7 +193,7 @@ void firmware_update_set_recovery_revision (struct firmware_update *updater, int * * @param updater The updater to configure. */ -void firmware_update_validate_recovery_image (struct firmware_update *updater) +void firmware_update_validate_recovery_image (const struct firmware_update *updater) { int status; @@ -165,7 +203,7 @@ void firmware_update_validate_recovery_image (struct firmware_update *updater) if (updater->flash->recovery_flash) { status = updater->fw->load (updater->fw, updater->flash->recovery_flash, - updater->flash->recovery_addr + updater->img_offset); + updater->flash->recovery_addr + updater->state->img_offset); if (status == 0) { status = updater->fw->verify (updater->fw, updater->hash); @@ -176,11 +214,12 @@ void firmware_update_validate_recovery_image (struct firmware_update *updater) } if (status == 0) { - struct firmware_header *header; + const struct firmware_header *header; header = updater->fw->get_firmware_header (updater->fw); if (header != NULL) { - status = firmware_header_get_recovery_revision (header, &updater->recovery_rev); + status = firmware_header_get_recovery_revision (header, + &updater->state->recovery_rev); } else if (!updater->no_fw_header) { status = FIRMWARE_UPDATE_NO_FIRMWARE_HEADER; @@ -188,11 +227,11 @@ void firmware_update_validate_recovery_image (struct firmware_update *updater) } } - updater->recovery_bad = (status != 0); + updater->state->recovery_bad = (status != 0); debug_log_create_entry ( - (updater->recovery_bad) ? DEBUG_LOG_SEVERITY_WARNING : DEBUG_LOG_SEVERITY_INFO, - DEBUG_LOG_COMPONENT_CERBERUS_FW, FIRMWARE_LOGGING_RECOVERY_IMAGE, updater->recovery_bad, - status); + (updater->state->recovery_bad) ? DEBUG_LOG_SEVERITY_WARNING : DEBUG_LOG_SEVERITY_INFO, + DEBUG_LOG_COMPONENT_CERBERUS_FW, FIRMWARE_LOGGING_RECOVERY_IMAGE, + updater->state->recovery_bad, status); } } @@ -209,8 +248,9 @@ void firmware_update_validate_recovery_image (struct firmware_update *updater) * * @return 0 if the new image was copied successfully to the active region or an error code. */ -static int firmware_update_program_bootable (struct firmware_update *updater, struct flash *dest, - uint32_t dest_addr, struct flash *src, uint32_t src_addr, size_t length, uint32_t page) +static int firmware_update_program_bootable (const struct firmware_update *updater, + const struct flash *dest, uint32_t dest_addr, const struct flash *src, uint32_t src_addr, + size_t length, uint32_t page) { int status; @@ -237,8 +277,8 @@ static int firmware_update_program_bootable (struct firmware_update *updater, st * * @return 0 if the image was successfully finalized or an error code. */ -static int firmware_update_finalize_image (struct firmware_update *updater, struct flash *flash, - uint32_t address) +static int firmware_update_finalize_image (const struct firmware_update *updater, + const struct flash *flash, uint32_t address) { if (updater->internal.finalize_image) { return updater->internal.finalize_image (updater, flash, address); @@ -258,14 +298,14 @@ static int firmware_update_finalize_image (struct firmware_update *updater, stru * * @return 0 if image was successfully restored or an error code. */ -static int firmware_update_restore_image (struct firmware_update *updater, struct flash *dest, - uint32_t dest_addr, struct flash *src, uint32_t src_addr) +static int firmware_update_restore_image (const struct firmware_update *updater, + const struct flash *dest, uint32_t dest_addr, const struct flash *src, uint32_t src_addr) { int img_len; uint32_t page; int status; - status = updater->fw->load (updater->fw, src, src_addr + updater->img_offset); + status = updater->fw->load (updater->fw, src, src_addr + updater->state->img_offset); if (status != 0) { return status; } @@ -285,13 +325,14 @@ static int firmware_update_restore_image (struct firmware_update *updater, struc return status; } - status = flash_erase_region_and_verify (dest, dest_addr, img_len + updater->img_offset); + status = flash_erase_region_and_verify (dest, dest_addr, img_len + updater->state->img_offset); if (status != 0) { return status; } - status = firmware_update_program_bootable (updater, dest, dest_addr + updater->img_offset, src, - src_addr + updater->img_offset, img_len, page); + status = firmware_update_program_bootable (updater, dest, + dest_addr + updater->state->img_offset, src, src_addr + updater->state->img_offset, img_len, + page); if (status != 0) { return status; } @@ -308,17 +349,17 @@ static int firmware_update_restore_image (struct firmware_update *updater, struc * @return 0 if the recovery image was restored successfully or an error code. If the recovery * image is already good, FIRMWARE_UPDATE_RESTORE_NOT_NEEDED will be returned. */ -int firmware_update_restore_recovery_image (struct firmware_update *updater) +int firmware_update_restore_recovery_image (const struct firmware_update *updater) { int status = FIRMWARE_UPDATE_NO_RECOVERY_IMAGE; - struct firmware_header *header = NULL; + const struct firmware_header *header = NULL; if (updater == NULL) { return FIRMWARE_UPDATE_INVALID_ARGUMENT; } if (updater->flash->recovery_flash) { - if (updater->recovery_bad) { + if (updater->state->recovery_bad) { debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CERBERUS_FW, FIRMWARE_LOGGING_RECOVERY_RESTORE_START, 0, 0); @@ -326,14 +367,14 @@ int firmware_update_restore_recovery_image (struct firmware_update *updater) updater->flash->recovery_addr, updater->flash->active_flash, updater->flash->active_addr); if (status == 0) { - updater->recovery_bad = false; + updater->state->recovery_bad = false; header = updater->fw->get_firmware_header (updater->fw); if (header == NULL) { firmware_update_set_recovery_revision (updater, -1); } else { - firmware_header_get_recovery_revision (header, &updater->recovery_rev); + firmware_header_get_recovery_revision (header, &updater->state->recovery_rev); } } } @@ -353,7 +394,7 @@ int firmware_update_restore_recovery_image (struct firmware_update *updater) * * @return 0 if the active image was restored successfully or an error code. */ -int firmware_update_restore_active_image (struct firmware_update *updater) +int firmware_update_restore_active_image (const struct firmware_update *updater) { int status = FIRMWARE_UPDATE_NO_RECOVERY_IMAGE; @@ -377,13 +418,13 @@ int firmware_update_restore_active_image (struct firmware_update *updater) * * @return 1 if the recovery image is good, 0 if the recovery image is bad, or an error code. */ -int firmware_update_is_recovery_good (struct firmware_update *updater) +int firmware_update_is_recovery_good (const struct firmware_update *updater) { if (updater == NULL) { return FIRMWARE_UPDATE_INVALID_ARGUMENT; } - return updater->recovery_bad ? 0 : 1; + return updater->state->recovery_bad ? 0 : 1; } /** @@ -394,14 +435,14 @@ int firmware_update_is_recovery_good (struct firmware_update *updater) * * @return 0 if the observer was successfully added or an error code. */ -int firmware_update_add_observer (struct firmware_update *updater, +int firmware_update_add_observer (const struct firmware_update *updater, struct firmware_update_observer *observer) { if (updater == NULL) { return FIRMWARE_UPDATE_INVALID_ARGUMENT; } - return observable_add_observer (&updater->observable, observer); + return observable_add_observer (&updater->state->observable, observer); } /** @@ -412,14 +453,14 @@ int firmware_update_add_observer (struct firmware_update *updater, * * @return 0 if the observer was successfully removed or an error code. */ -int firmware_update_remove_observer (struct firmware_update *updater, +int firmware_update_remove_observer (const struct firmware_update *updater, struct firmware_update_observer *observer) { if (updater == NULL) { return FIRMWARE_UPDATE_INVALID_ARGUMENT; } - return observable_remove_observer (&updater->observable, observer); + return observable_remove_observer (&updater->state->observable, observer); } /** @@ -428,7 +469,7 @@ int firmware_update_remove_observer (struct firmware_update *updater, * @param callback The notification callback to trigger. * @param status The status to notify. */ -static void firmware_update_status_change (struct firmware_update_notification *callback, +static void firmware_update_status_change (const struct firmware_update_notification *callback, enum firmware_update_status status) { if ((callback != NULL) && (callback->status_change != NULL)) { @@ -459,9 +500,9 @@ static void firmware_update_status_change (struct firmware_update_notification * * * @return 0 if the new firmware image was successfully written or an error code. */ -static int firmware_update_write_image (struct firmware_update *updater, - struct firmware_update_notification *callback, struct flash *dest, uint32_t dest_addr, - struct flash *backup, uint32_t backup_addr, size_t update_len, +static int firmware_update_write_image (const struct firmware_update *updater, + const struct firmware_update_notification *callback, const struct flash *dest, + uint32_t dest_addr, const struct flash *backup, uint32_t backup_addr, size_t update_len, enum firmware_update_status backup_start, enum firmware_update_status backup_fail, enum firmware_update_status update_start, enum firmware_update_status update_fail, bool *img_good) @@ -474,7 +515,7 @@ static int firmware_update_write_image (struct firmware_update *updater, if (backup) { /* Backup the current image. */ firmware_update_status_change (callback, backup_start); - status = updater->fw->load (updater->fw, dest, dest_addr + updater->img_offset); + status = updater->fw->load (updater->fw, dest, dest_addr + updater->state->img_offset); if (status != 0) { firmware_update_status_change (callback, backup_fail); return status; @@ -486,8 +527,8 @@ static int firmware_update_write_image (struct firmware_update *updater, return backup_len; } - status = flash_copy_ext_and_verify (backup, backup_addr + updater->img_offset, dest, - dest_addr + updater->img_offset, backup_len); + status = flash_copy_ext_and_verify (backup, backup_addr + updater->state->img_offset, dest, + dest_addr + updater->state->img_offset, backup_len); if (status != 0) { firmware_update_status_change (callback, backup_fail); return status; @@ -504,15 +545,16 @@ static int firmware_update_write_image (struct firmware_update *updater, } *img_good = false; - status = flash_erase_region_and_verify (dest, dest_addr, update_len + updater->img_offset); + status = flash_erase_region_and_verify (dest, dest_addr, + update_len + updater->state->img_offset); if (status != 0) { firmware_update_status_change (callback, update_fail); return status; } - status = firmware_update_program_bootable (updater, dest, dest_addr + updater->img_offset, - updater->flash->staging_flash, updater->flash->staging_addr + updater->img_offset, - update_len, page); + status = firmware_update_program_bootable (updater, dest, + dest_addr + updater->state->img_offset, updater->flash->staging_flash, + updater->flash->staging_addr + updater->state->img_offset, update_len, page); if (status == 0) { status = firmware_update_finalize_image (updater, dest, dest_addr); } @@ -521,10 +563,10 @@ static int firmware_update_write_image (struct firmware_update *updater, if (backup) { /* Try to restore the image that was backed up. */ if (flash_erase_region_and_verify (dest, dest_addr, - backup_len + updater->img_offset) == 0) { + backup_len + updater->state->img_offset) == 0) { if (firmware_update_program_bootable (updater, dest, - dest_addr + updater->img_offset, backup, backup_addr + updater->img_offset, - backup_len, page) == 0) { + dest_addr + updater->state->img_offset, backup, + backup_addr + updater->state->img_offset, backup_len, page) == 0) { if (firmware_update_finalize_image (updater, dest, dest_addr) == 0) { *img_good = true; } @@ -546,7 +588,7 @@ static int firmware_update_write_image (struct firmware_update *updater, * - Save the application state that should be restored after the update. * - Copy the image in staging flash to active flash. * - Copy the image in staging flash to recovery flash, if the recovery manifest has been - * revoked. + * revoked or the recovery revision has changed. * - Update manifest revocation information in the device. * * @param updater The updater that should run. @@ -556,12 +598,12 @@ static int firmware_update_write_image (struct firmware_update *updater, * * @return 0 if the update completed successfully or an error code. */ -int firmware_update_run_update (struct firmware_update *updater, - struct firmware_update_notification *callback) +int firmware_update_run_update (const struct firmware_update *updater, + const struct firmware_update_notification *callback) { int new_len; - struct key_manifest *manifest; - struct firmware_header *header = NULL; + const struct key_manifest *manifest; + const struct firmware_header *header = NULL; bool recovery_updated = false; bool img_good; int manifest_revoked; @@ -577,13 +619,13 @@ int firmware_update_run_update (struct firmware_update *updater, /* Verify image in staging flash. */ firmware_update_status_change (callback, UPDATE_STATUS_VERIFYING_IMAGE); - if (flash_updater_get_remaining_bytes (&updater->update_mgr) > 0) { + if (flash_updater_get_remaining_bytes (&updater->state->update_mgr) > 0) { firmware_update_status_change (callback, UPDATE_STATUS_INCOMPLETE_IMAGE); return FIRMWARE_UPDATE_INCOMPLETE_IMAGE; } status = updater->fw->load (updater->fw, updater->flash->staging_flash, - updater->flash->staging_addr + updater->img_offset); + updater->flash->staging_addr + updater->state->img_offset); if (status != 0) { firmware_update_status_change (callback, UPDATE_STATUS_VERIFY_FAILURE); return status; @@ -609,7 +651,7 @@ int firmware_update_run_update (struct firmware_update *updater, return status; } - if (new_revision < updater->min_rev) { + if (new_revision < updater->state->min_rev) { firmware_update_status_change (callback, UPDATE_STATUS_INVALID_IMAGE); return FIRMWARE_UPDATE_REJECTED_ROLLBACK; } @@ -622,7 +664,7 @@ int firmware_update_run_update (struct firmware_update *updater, /* There is no FW header on the image, so just apply the updater's recovery revision to the * new image. Without a FW header, the recovery image will only get updated during * manifest revocation flows. */ - new_revision = updater->recovery_rev; + new_revision = updater->state->recovery_rev; } new_len = updater->fw->get_image_size (updater->fw); @@ -633,7 +675,7 @@ int firmware_update_run_update (struct firmware_update *updater, /* Notify the system of an update and see if it should be allowed. */ allow_update = 0; - observable_notify_observers_with_ptr (&updater->observable, + observable_notify_observers_with_ptr (&updater->state->observable, offsetof (struct firmware_update_observer, on_update_start), &allow_update); if (allow_update != 0) { firmware_update_status_change (callback, UPDATE_STATUS_SYSTEM_PREREQ_FAIL); @@ -649,7 +691,7 @@ int firmware_update_run_update (struct firmware_update *updater, } /* Don't allow the active image to be erased until we have a good recovery image. */ - if (updater->flash->recovery_flash && updater->recovery_bad) { + if (updater->flash->recovery_flash && updater->state->recovery_bad) { debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CERBERUS_FW, FIRMWARE_LOGGING_RECOVERY_UPDATE, 0, 0); debug_log_flush (); @@ -662,7 +704,7 @@ int firmware_update_run_update (struct firmware_update *updater, return status; } - updater->recovery_bad = !img_good; + updater->state->recovery_bad = !img_good; recovery_updated = true; } @@ -678,7 +720,7 @@ int firmware_update_run_update (struct firmware_update *updater, /* Check for manifest revocation. */ firmware_update_status_change (callback, UPDATE_STATUS_CHECK_REVOCATION); status = updater->fw->load (updater->fw, updater->flash->active_flash, - updater->flash->active_addr + updater->img_offset); + updater->flash->active_addr + updater->state->img_offset); if (status != 0) { firmware_update_status_change (callback, UPDATE_STATUS_REVOKE_CHK_FAIL); return status; @@ -698,9 +740,9 @@ int firmware_update_run_update (struct firmware_update *updater, /* Check if recovery update is necessary. */ firmware_update_status_change (callback, UPDATE_STATUS_CHECK_RECOVERY); - if (manifest_revoked || (updater->recovery_rev != new_revision)) { + if (manifest_revoked || (updater->state->recovery_rev != new_revision)) { if (updater->flash->recovery_flash && !recovery_updated) { - struct flash *backup; + const struct flash *backup; uint32_t backup_addr; if (updater->flash->rec_backup_flash) { @@ -722,13 +764,13 @@ int firmware_update_run_update (struct firmware_update *updater, UPDATE_STATUS_BACKUP_RECOVERY, UPDATE_STATUS_BACKUP_REC_FAIL, UPDATE_STATUS_UPDATE_RECOVERY, UPDATE_STATUS_UPDATE_REC_FAIL, &img_good); - updater->recovery_bad = !img_good; + updater->state->recovery_bad = !img_good; if (status != 0) { return status; } } - updater->recovery_rev = new_revision; + updater->state->recovery_rev = new_revision; if (manifest_revoked) { /* Revoke the old manifest. */ @@ -756,8 +798,8 @@ int firmware_update_run_update (struct firmware_update *updater, * * @return Preparation status, 0 if success or an error code. */ -int firmware_update_prepare_staging (struct firmware_update *updater, - struct firmware_update_notification *callback, size_t size) +int firmware_update_prepare_staging (const struct firmware_update *updater, + const struct firmware_update_notification *callback, size_t size) { int status; @@ -768,7 +810,7 @@ int firmware_update_prepare_staging (struct firmware_update *updater, firmware_update_status_change (callback, UPDATE_STATUS_STAGING_PREP); - status = flash_updater_prepare_for_update (&updater->update_mgr, size); + status = flash_updater_prepare_for_update (&updater->state->update_mgr, size); if (status != 0) { firmware_update_status_change (callback, UPDATE_STATUS_STAGING_PREP_FAIL); } @@ -788,8 +830,8 @@ int firmware_update_prepare_staging (struct firmware_update *updater, * * @return Programming status, 0 if success or an error code. */ -int firmware_update_write_to_staging (struct firmware_update *updater, - struct firmware_update_notification *callback, uint8_t *buf, size_t buf_len) +int firmware_update_write_to_staging (const struct firmware_update *updater, + const struct firmware_update_notification *callback, uint8_t *buf, size_t buf_len) { int status; @@ -800,7 +842,7 @@ int firmware_update_write_to_staging (struct firmware_update *updater, firmware_update_status_change (callback, UPDATE_STATUS_STAGING_WRITE); - status = flash_updater_write_update_data (&updater->update_mgr, buf, buf_len); + status = flash_updater_write_update_data (&updater->state->update_mgr, buf, buf_len); if (status != 0) { firmware_update_status_change (callback, UPDATE_STATUS_STAGING_WRITE_FAIL); } @@ -816,7 +858,7 @@ int firmware_update_write_to_staging (struct firmware_update *updater, * @return The number of bytes remaining in the current update. This can be negative if more bytes * have been received than expected. */ -int firmware_update_get_update_remaining (struct firmware_update *updater) +int firmware_update_get_update_remaining (const struct firmware_update *updater) { - return flash_updater_get_remaining_bytes (&updater->update_mgr); + return flash_updater_get_remaining_bytes (&updater->state->update_mgr); } diff --git a/core/firmware/firmware_update.h b/core/firmware/firmware_update.h index ab25138..2b5f6bd 100644 --- a/core/firmware/firmware_update.h +++ b/core/firmware/firmware_update.h @@ -21,21 +21,21 @@ * The flash addresses and devices to use for different firmware regions. */ struct firmware_flash_map { - struct flash *active_flash; /**< The flash device that contains the active region. */ - uint32_t active_addr; /**< The base address for the active flash region. */ - size_t active_size; /**< The size of the active flash region. */ - struct flash *backup_flash; /**< The flash device that contains the backup region. */ - uint32_t backup_addr; /**< The base address for the backup flash region. */ - size_t backup_size; /**< The size of the backup flash region. */ - struct flash *staging_flash; /**< The flash device that contains the staging region. */ - uint32_t staging_addr; /**< The base address for the staging flash region. */ - size_t staging_size; /**< The size of the staging flash region. */ - struct flash *recovery_flash; /**< The flash device that contains the recovery region. */ - uint32_t recovery_addr; /**< The base address for the recovery flash region. */ - size_t recovery_size; /**< The size of the recovery flash region. */ - struct flash *rec_backup_flash; /**< The flash device for the recovery backup region. */ - uint32_t rec_backup_addr; /**< The base address for the recovery backup region. */ - size_t rec_backup_size; /**< The size of the recovery backup flash region. */ + const struct flash *active_flash; /**< The flash device that contains the active region. */ + uint32_t active_addr; /**< The base address for the active flash region. */ + size_t active_size; /**< The size of the active flash region. */ + const struct flash *backup_flash; /**< The flash device that contains the backup region. */ + uint32_t backup_addr; /**< The base address for the backup flash region. */ + size_t backup_size; /**< The size of the backup flash region. */ + const struct flash *staging_flash; /**< The flash device that contains the staging region. */ + uint32_t staging_addr; /**< The base address for the staging flash region. */ + size_t staging_size; /**< The size of the staging flash region. */ + const struct flash *recovery_flash; /**< The flash device that contains the recovery region. */ + uint32_t recovery_addr; /**< The base address for the recovery flash region. */ + size_t recovery_size; /**< The size of the recovery flash region. */ + const struct flash *rec_backup_flash; /**< The flash device for the recovery backup region. */ + uint32_t rec_backup_addr; /**< The base address for the recovery backup region. */ + size_t rec_backup_size; /**< The size of the recovery backup flash region. */ }; /** @@ -95,7 +95,8 @@ struct firmware_update_hooks { * * @return 0 if the image was successfully finalized or an error code. */ - int (*finalize_image) (struct firmware_update *updater, struct flash *flash, uint32_t address); + int (*finalize_image) (const struct firmware_update *updater, const struct flash *flash, + uint32_t address); /** * Run additional verification on a boot image stored on flash. This will be called after @@ -110,26 +111,33 @@ struct firmware_update_hooks { * @return 0 if the image is valid or an error code. If the boot image is not valid, * FIRMWARE_UPDATE_INVALID_BOOT_IMAGE will be returned. */ - int (*verify_boot_image) (struct firmware_update *updater, struct flash *flash, + int (*verify_boot_image) (const struct firmware_update *updater, const struct flash *flash, uint32_t address); }; +/** + * Variable context for a firmware update handler. + */ +struct firmware_update_state { + struct flash_updater update_mgr; /**< Update manager for writing data to flash. */ + struct observable observable; /**< Observer manager for the updater. */ + bool recovery_bad; /**< Indication if the recovery image on flash is bad. */ + int recovery_rev; /**< Revision ID of the current recovery image. */ + int min_rev; /**< Minimum revision ID allowed for update. */ + int img_offset; /**< Offset to apply to FW image regions. */ +}; + /** * The meta-data and other dependencies necessary to run firmware update operations. */ struct firmware_update { struct firmware_update_hooks internal; /**< Internal interface to customize the update process. */ + struct firmware_update_state *state; /**< Variable context for the update context. */ const struct firmware_flash_map *flash; /**< The flash address mapping to use for the update. */ - struct firmware_image *fw; /**< The platform driver for handling firmware images. */ - struct hash_engine *hash; /**< The hash engine to use during update .*/ - struct app_context *context; /**< The platform application context API. */ - struct flash_updater update_mgr; /**< Update manager for writing data to flash. */ + const struct firmware_image *fw; /**< The platform driver for handling firmware images. */ + struct hash_engine *hash; /**< The hash engine to use during update. */ + const struct app_context *context; /**< The platform application context API. */ bool no_fw_header; /**< Indication that a firmware header is not required. */ - bool recovery_bad; /**< Indication if the recovery image on flash is bad. */ - int recovery_rev; /**< Revision ID of the current recovery image. */ - int min_rev; /**< Minimum revision ID allowed for update. */ - int img_offset; /**< Offset to apply to FW image regions. */ - struct observable observable; /**< Observer manager for the updater. */ }; /** @@ -142,39 +150,43 @@ struct firmware_update_notification { * @param context The context of the notification handler. * @param status The new status of the active firmware update. */ - void (*status_change) (struct firmware_update_notification *context, + void (*status_change) (const struct firmware_update_notification *context, enum firmware_update_status status); }; -int firmware_update_init (struct firmware_update *updater, const struct firmware_flash_map *flash, - struct app_context *context, struct firmware_image *fw, struct hash_engine *hash, +int firmware_update_init (struct firmware_update *updater, struct firmware_update_state *state, + const struct firmware_flash_map *flash, const struct app_context *context, + const struct firmware_image *fw, struct hash_engine *hash, int allowed_revision); +int firmware_update_init_no_firmware_header (struct firmware_update *updater, + struct firmware_update_state *state, const struct firmware_flash_map *flash, + const struct app_context *context, const struct firmware_image *fw, struct hash_engine *hash, int allowed_revision); -void firmware_update_release (struct firmware_update *updater); +int firmware_update_init_state (const struct firmware_update *updater, int allowed_revision); +void firmware_update_release (const struct firmware_update *updater); -void firmware_update_set_image_offset (struct firmware_update *updater, int offset); -void firmware_update_require_firmware_header (struct firmware_update *updater, bool has_fw_header); +void firmware_update_set_image_offset (const struct firmware_update *updater, int offset); -void firmware_update_set_recovery_revision (struct firmware_update *updater, int revision); -void firmware_update_set_recovery_good (struct firmware_update *updater, bool img_good); -void firmware_update_validate_recovery_image (struct firmware_update *updater); -int firmware_update_is_recovery_good (struct firmware_update *updater); +void firmware_update_set_recovery_revision (const struct firmware_update *updater, int revision); +void firmware_update_set_recovery_good (const struct firmware_update *updater, bool img_good); +void firmware_update_validate_recovery_image (const struct firmware_update *updater); +int firmware_update_is_recovery_good (const struct firmware_update *updater); -int firmware_update_restore_recovery_image (struct firmware_update *updater); -int firmware_update_restore_active_image (struct firmware_update *updater); +int firmware_update_restore_recovery_image (const struct firmware_update *updater); +int firmware_update_restore_active_image (const struct firmware_update *updater); -int firmware_update_add_observer (struct firmware_update *updater, +int firmware_update_add_observer (const struct firmware_update *updater, struct firmware_update_observer *observer); -int firmware_update_remove_observer (struct firmware_update *updater, +int firmware_update_remove_observer (const struct firmware_update *updater, struct firmware_update_observer *observer); -int firmware_update_run_update (struct firmware_update *updater, - struct firmware_update_notification *callback); -int firmware_update_prepare_staging (struct firmware_update *updater, - struct firmware_update_notification *callback, size_t size); -int firmware_update_write_to_staging (struct firmware_update *updater, - struct firmware_update_notification *callback, uint8_t *buf, size_t buf_len); -int firmware_update_get_update_remaining (struct firmware_update *updater); +int firmware_update_run_update (const struct firmware_update *updater, + const struct firmware_update_notification *callback); +int firmware_update_prepare_staging (const struct firmware_update *updater, + const struct firmware_update_notification *callback, size_t size); +int firmware_update_write_to_staging (const struct firmware_update *updater, + const struct firmware_update_notification *callback, uint8_t *buf, size_t buf_len); +int firmware_update_get_update_remaining (const struct firmware_update *updater); #define FIRMWARE_UPDATE_ERROR(code) ROT_ERROR (ROT_MODULE_FIRMWARE_UPDATE, code) diff --git a/core/firmware/firmware_update_static.h b/core/firmware/firmware_update_static.h new file mode 100644 index 0000000..9900932 --- /dev/null +++ b/core/firmware/firmware_update_static.h @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef FIRMWARE_UPDATE_STATIC_H_ +#define FIRMWARE_UPDATE_STATIC_H_ + +#include "firmware/firmware_update.h" + + +/** + * Constant initializer for the internal update customization hooks. + */ +#define FIRMWARE_UPDATE_INTERNAL_API_INIT { \ + .finalize_image = NULL, \ + .verify_boot_image = NULL \ + } + + +/** + * Initialize a static instance of a firmware update handler. This does not initialize the updater + * state. This can be a constant instance. + * + * There is no validation done on the arguments. + * + * @param state_ptr Variable context for the updater. + * @param flash_ptr The device and address mapping for firmware images. + * @param context_ptr The application context API. + * @param fw_ptr The platform handler for firmware images. + * @param hash_ptr The hash engine to use during updates. + */ +#define firmware_update_static_init(state_ptr, flash_ptr, context_ptr, fw_ptr, hash_ptr) { \ + .internal = FIRMWARE_UPDATE_INTERNAL_API_INIT, \ + .state = state_ptr, \ + .flash = flash_ptr, \ + .fw = fw_ptr, \ + .hash = hash_ptr, \ + .context = context_ptr, \ + .no_fw_header = false \ + } + +/** + * Initialize a static instance of a firmware update handler. This does not initialize the updater + * state. This can be a constant instance. + * + * Firmware images processed by the updater are not required to contain a firmware header. If the + * firmware header is present, it will be processed. If the firmware header is not present, the + * update will proceed without it and any workflows that required information from the header will + * be skipped. + * + * There is no validation done on the arguments. + * + * @param state_ptr Variable context for the updater. + * @param flash_ptr The device and address mapping for firmware images. + * @param context_ptr The application context API. + * @param fw_ptr The platform handler for firmware images. + * @param hash_ptr The hash engine to use during updates. + */ +#define firmware_update_static_init_no_firmware_header(state_ptr, flash_ptr, context_ptr, fw_ptr, \ + hash_ptr) { \ + .internal = FIRMWARE_UPDATE_INTERNAL_API_INIT, \ + .state = state_ptr, \ + .flash = flash_ptr, \ + .fw = fw_ptr, \ + .hash = hash_ptr, \ + .context = context_ptr, \ + .no_fw_header = true \ + } + + +#endif /* FIRMWARE_UPDATE_STATIC_H_ */ diff --git a/core/flash/flash_updater.c b/core/flash/flash_updater.c index ef8b85e..3ce75ec 100644 --- a/core/flash/flash_updater.c +++ b/core/flash/flash_updater.c @@ -19,7 +19,7 @@ * * @return 0 if the update manager was initialized successfully or an error code. */ -static int flash_updater_init_common (struct flash_updater *updater, struct flash *flash, +static int flash_updater_init_common (struct flash_updater *updater, const struct flash *flash, uint32_t base_addr, size_t max_size, int (*erase) (const struct flash*, uint32_t, size_t)) { if ((updater == NULL) || (flash == NULL)) { @@ -48,8 +48,8 @@ static int flash_updater_init_common (struct flash_updater *updater, struct flas * * @return 0 if the update manager was initialized successfully or an error code. */ -int flash_updater_init (struct flash_updater *updater, struct flash *flash, uint32_t base_addr, - size_t max_size) +int flash_updater_init (struct flash_updater *updater, const struct flash *flash, + uint32_t base_addr, size_t max_size) { return flash_updater_init_common (updater, flash, base_addr, max_size, flash_erase_region_and_verify); @@ -67,7 +67,7 @@ int flash_updater_init (struct flash_updater *updater, struct flash *flash, uint * * @return 0 if the update manager was initialized successfully or an error code. */ -int flash_updater_init_sector (struct flash_updater *updater, struct flash *flash, +int flash_updater_init_sector (struct flash_updater *updater, const struct flash *flash, uint32_t base_addr, size_t max_size) { return flash_updater_init_common (updater, flash, base_addr, max_size, diff --git a/core/flash/flash_updater.h b/core/flash/flash_updater.h index f1f4d94..0f5c164 100644 --- a/core/flash/flash_updater.h +++ b/core/flash/flash_updater.h @@ -15,7 +15,7 @@ * to sequential locations in flash. */ struct flash_updater { - struct flash *flash; /**< The flash to manage for updates. */ + const struct flash *flash; /**< The flash to manage for updates. */ uint32_t base_addr; /**< The start of the update region. */ size_t max_size; /**< The maximum size of an update. */ int update_size; /**< Expected size of the current update. */ @@ -24,9 +24,9 @@ struct flash_updater { }; -int flash_updater_init (struct flash_updater *updater, struct flash *flash, uint32_t base_addr, - size_t max_size); -int flash_updater_init_sector (struct flash_updater *updater, struct flash *flash, +int flash_updater_init (struct flash_updater *updater, const struct flash *flash, + uint32_t base_addr, size_t max_size); +int flash_updater_init_sector (struct flash_updater *updater, const struct flash *flash, uint32_t base_addr, size_t max_size); void flash_updater_release (struct flash_updater *updater); diff --git a/core/testing/firmware/firmware_update_test.c b/core/testing/firmware/firmware_update_test.c index 8f876ef..fe94357 100644 --- a/core/testing/firmware/firmware_update_test.c +++ b/core/testing/firmware/firmware_update_test.c @@ -7,6 +7,7 @@ #include "testing.h" #include "firmware/firmware_logging.h" #include "firmware/firmware_update.h" +#include "firmware/firmware_update_static.h" #include "flash/flash_common.h" #include "testing/mock/flash/flash_mock.h" #include "testing/mock/firmware/firmware_image_mock.h" @@ -40,6 +41,7 @@ struct firmware_update_testing { struct firmware_flash_map map; /**< Map of firmware images on updater.flash. */ struct firmware_update_notification_mock handler; /**< Mock for update notifications. */ struct firmware_update_observer_mock observer; /**< Mock for an update observer. */ + struct firmware_update_state state; /**< Context for the test updater. */ struct firmware_update test; /**< Firmware updater for testing. */ struct firmware_update_mock test_mock; /**< Mock updater for testing. */ bool is_mock; /**< Flag indicating which updater was initialized. */ @@ -174,11 +176,58 @@ static void firmware_update_testing_init_updater (CuTest *test, updater->is_mock = false; - status = firmware_update_init (&updater->test, &updater->map, &updater->app.base, - &updater->fw.base, &updater->hash.base, allowed); + status = firmware_update_init (&updater->test, &updater->state, &updater->map, + &updater->app.base, &updater->fw.base, &updater->hash.base, allowed); CuAssertIntEquals (test, 0, status); - firmware_update_set_recovery_revision (&updater->test, recovery); + if (recovery >= 0) { + firmware_update_set_recovery_revision (&updater->test, recovery); + } +} + +/** + * Initialize the test updater instance that doesn't require a firmware header on the image. + * + * @param test The testing framework. + * @param updater The testing components to initialize. + * @param allowed The allowed firmware ID for the updater. + * @param recovery The recovery firmware ID. + */ +static void firmware_update_testing_init_updater_no_firmware_header (CuTest *test, + struct firmware_update_testing *updater, int allowed, int recovery) +{ + int status; + + updater->is_mock = false; + + status = firmware_update_init_no_firmware_header (&updater->test, &updater->state, + &updater->map, &updater->app.base, &updater->fw.base, &updater->hash.base, allowed); + CuAssertIntEquals (test, 0, status); + + if (recovery >= 0) { + firmware_update_set_recovery_revision (&updater->test, recovery); + } +} + +/** + * Initialize the test updater state. + * + * @param test The testing framework. + * @param updater The test updater to initialize. + * @param allowed The allowed firmware ID for the updater. + * @param recovery The recovery firmware ID. + */ +static void firmware_update_testing_init_updater_state (CuTest *test, + struct firmware_update *updater, int allowed, int recovery) +{ + int status; + + status = firmware_update_init_state (updater, allowed); + CuAssertIntEquals (test, 0, status); + + if (recovery >= 0) { + firmware_update_set_recovery_revision (updater, recovery); + } } /** @@ -196,11 +245,13 @@ static void firmware_update_testing_init_updater_mock (CuTest *test, updater->is_mock = true; - status = firmware_update_mock_init (&updater->test_mock, &updater->map, &updater->app.base, - &updater->fw.base, &updater->hash.base, allowed); + status = firmware_update_mock_init (&updater->test_mock, &updater->state, &updater->map, + &updater->app.base, &updater->fw.base, &updater->hash.base, allowed); CuAssertIntEquals (test, 0, status); - firmware_update_set_recovery_revision (&updater->test_mock.base, recovery); + if (recovery >= 0) { + firmware_update_set_recovery_revision (&updater->test_mock.base, recovery); + } } /** @@ -219,6 +270,41 @@ static void firmware_update_testing_init (CuTest *test, struct firmware_update_t firmware_update_testing_init_updater (test, updater, allowed, recovery); } +/** + * Initialize a firmware updater for testing that doesn't require a firmware header on the image. + * + * @param test The testing framework. + * @param updater The testing components to initialize. + * @param allowed The allowed firmware ID for the updater. + * @param recovery The recovery firmware ID. + * @param header The header firmware ID. + */ +static void firmware_update_testing_init_no_firmware_header (CuTest *test, + struct firmware_update_testing *updater, int allowed, int recovery, int header) +{ + firmware_update_testing_init_dependencies (test, updater, header); + firmware_update_testing_init_updater_no_firmware_header (test, updater, allowed, recovery); +} + +/** + * Initialize a static firmware updater for testing. + * + * @param test The testing framework. + * @param updater The testing components to initialize. + * @param updater_static The static updater to initialize. + * @param allowed The allowed firmware ID for the updater. + * @param recovery The recovery firmware ID. + * @param header The header firmware ID. + */ +static void firmware_update_testing_init_static (CuTest *test, + struct firmware_update_testing *updater, struct firmware_update *updater_static, int allowed, + int recovery, int header) +{ + firmware_update_testing_init_dependencies (test, updater, header); + firmware_update_testing_init_updater_state (test, updater_static, allowed, recovery); + updater->is_mock = false; +} + /** * Initialize a mock firmware updater for testing. * @@ -323,10 +409,13 @@ static void firmware_update_test_init (CuTest *test) firmware_update_testing_init_dependencies (test, &updater, 0); updater.is_mock = false; - status = firmware_update_init (&updater.test, &updater.map, &updater.app.base, &updater.fw.base, - &updater.hash.base, 0); + status = firmware_update_init (&updater.test, &updater.state, &updater.map, &updater.app.base, + &updater.fw.base, &updater.hash.base, 0); CuAssertIntEquals (test, 0, status); + CuAssertPtrEquals (test, NULL, updater.test.internal.finalize_image); + CuAssertPtrEquals (test, NULL, updater.test.internal.verify_boot_image); + firmware_update_testing_validate_and_release (test, &updater); } @@ -339,24 +428,28 @@ static void firmware_update_test_init_null (CuTest *test) firmware_update_testing_init_dependencies (test, &updater, 0); - status = firmware_update_init (NULL, &updater.map, &updater.app.base, &updater.fw.base, - &updater.hash.base, 0); + status = firmware_update_init (NULL, &updater.state, &updater.map, &updater.app.base, + &updater.fw.base, &updater.hash.base, 0); CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); - status = firmware_update_init (&updater.test, NULL, &updater.app.base, &updater.fw.base, - &updater.hash.base, 0); + status = firmware_update_init (&updater.test, NULL, &updater.map, &updater.app.base, + &updater.fw.base, &updater.hash.base, 0); CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); - status = firmware_update_init (&updater.test, &updater.map, NULL, &updater.fw.base, - &updater.hash.base, 0); + status = firmware_update_init (&updater.test, &updater.state, NULL, &updater.app.base, + &updater.fw.base, &updater.hash.base, 0); CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); - status = firmware_update_init (&updater.test, &updater.map, &updater.app.base, NULL, - &updater.hash.base, 0); + status = firmware_update_init (&updater.test, &updater.state, &updater.map, NULL, + &updater.fw.base, &updater.hash.base, 0); CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); - status = firmware_update_init (&updater.test, &updater.map, &updater.app.base, &updater.fw.base, - NULL, 0); + status = firmware_update_init (&updater.test, &updater.state, &updater.map, &updater.app.base, + NULL, &updater.hash.base, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + status = firmware_update_init (&updater.test, &updater.state, &updater.map, &updater.app.base, + &updater.fw.base, NULL, 0); CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); firmware_update_testing_release_dependencies (test, &updater); @@ -374,8 +467,8 @@ static void firmware_update_test_init_no_recovery (CuTest *test) updater.map.rec_backup_flash = NULL; updater.is_mock = false; - status = firmware_update_init (&updater.test, &updater.map, &updater.app.base, &updater.fw.base, - &updater.hash.base, 0); + status = firmware_update_init (&updater.test, &updater.state, &updater.map, &updater.app.base, + &updater.fw.base, &updater.hash.base, 0); CuAssertIntEquals (test, 0, status); firmware_update_testing_validate_and_release (test, &updater); @@ -392,8 +485,8 @@ static void firmware_update_test_init_no_recovery_backup (CuTest *test) updater.map.rec_backup_flash = NULL; updater.is_mock = false; - status = firmware_update_init (&updater.test, &updater.map, &updater.app.base, &updater.fw.base, - &updater.hash.base, 0); + status = firmware_update_init (&updater.test, &updater.state, &updater.map, &updater.app.base, + &updater.fw.base, &updater.hash.base, 0); CuAssertIntEquals (test, 0, status); firmware_update_testing_validate_and_release (test, &updater); @@ -410,8 +503,8 @@ static void firmware_update_test_init_no_backup (CuTest *test) updater.map.backup_flash = NULL; updater.is_mock = false; - status = firmware_update_init (&updater.test, &updater.map, &updater.app.base, &updater.fw.base, - &updater.hash.base, 0); + status = firmware_update_init (&updater.test, &updater.state, &updater.map, &updater.app.base, + &updater.fw.base, &updater.hash.base, 0); CuAssertIntEquals (test, 0, status); firmware_update_testing_validate_and_release (test, &updater); @@ -429,8 +522,8 @@ static void firmware_update_test_init_no_recovery_no_backup (CuTest *test) updater.map.recovery_flash = NULL; updater.map.rec_backup_flash = NULL; - status = firmware_update_init (&updater.test, &updater.map, &updater.app.base, &updater.fw.base, - &updater.hash.base, 0); + status = firmware_update_init (&updater.test, &updater.state, &updater.map, &updater.app.base, + &updater.fw.base, &updater.hash.base, 0); CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_FLASH_MAP, status); firmware_update_testing_release_dependencies (test, &updater); @@ -446,14 +539,501 @@ static void firmware_update_test_init_no_active_or_staging (CuTest *test) firmware_update_testing_init_dependencies (test, &updater, 0); updater.map.active_flash = NULL; - status = firmware_update_init (&updater.test, &updater.map, &updater.app.base, &updater.fw.base, - &updater.hash.base, 0); + status = firmware_update_init (&updater.test, &updater.state, &updater.map, &updater.app.base, + &updater.fw.base, &updater.hash.base, 0); CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_FLASH_MAP, status); updater.map.active_flash = &updater.flash.base; updater.map.staging_flash = NULL; - status = firmware_update_init (&updater.test, &updater.map, &updater.app.base, &updater.fw.base, - &updater.hash.base, 0); + status = firmware_update_init (&updater.test, &updater.state, &updater.map, &updater.app.base, + &updater.fw.base, &updater.hash.base, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_FLASH_MAP, status); + + firmware_update_testing_release_dependencies (test, &updater); +} + +static void firmware_update_test_static_init (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + CuAssertPtrEquals (test, NULL, test_static.internal.finalize_image); + CuAssertPtrEquals (test, NULL, test_static.internal.verify_boot_image); + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.is_mock = false; + + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_static_init_null (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + + status = firmware_update_init_state (NULL, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + test_static.state = NULL; + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + test_static.state = &updater.state; + test_static.flash = NULL; + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + test_static.flash = &updater.map; + test_static.context = NULL; + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + test_static.context = &updater.app.base; + test_static.fw = NULL; + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + test_static.fw = &updater.fw.base; + test_static.hash = NULL; + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + firmware_update_testing_release_dependencies (test, &updater); +} + +static void firmware_update_test_static_init_no_recovery (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.recovery_flash = NULL; + updater.map.rec_backup_flash = NULL; + updater.is_mock = false; + + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_static_init_no_recovery_backup (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.rec_backup_flash = NULL; + updater.is_mock = false; + + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_static_init_no_backup (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.backup_flash = NULL; + updater.is_mock = false; + + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_static_init_no_recovery_no_backup (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.backup_flash = NULL; + updater.map.recovery_flash = NULL; + updater.map.rec_backup_flash = NULL; + + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_FLASH_MAP, status); + + firmware_update_testing_release_dependencies (test, &updater); +} + +static void firmware_update_test_static_init_no_active_or_staging (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.active_flash = NULL; + + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_FLASH_MAP, status); + + updater.map.active_flash = &updater.flash.base; + updater.map.staging_flash = NULL; + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_FLASH_MAP, status); + + firmware_update_testing_release_dependencies (test, &updater); +} + +static void firmware_update_test_init_no_firmware_header (CuTest *test) +{ + struct firmware_update_testing updater; + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.is_mock = false; + + status = firmware_update_init_no_firmware_header (&updater.test, &updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base, 0); + CuAssertIntEquals (test, 0, status); + + CuAssertPtrEquals (test, NULL, updater.test.internal.finalize_image); + CuAssertPtrEquals (test, NULL, updater.test.internal.verify_boot_image); + + firmware_update_testing_validate_and_release (test, &updater); +} + +static void firmware_update_test_init_no_firmware_header_null (CuTest *test) +{ + struct firmware_update_testing updater; + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + + status = firmware_update_init_no_firmware_header (NULL, &updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + status = firmware_update_init_no_firmware_header (&updater.test, NULL, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + status = firmware_update_init_no_firmware_header (&updater.test, &updater.state, NULL, + &updater.app.base, &updater.fw.base, &updater.hash.base, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + status = firmware_update_init_no_firmware_header (&updater.test, &updater.state, &updater.map, + NULL, &updater.fw.base, &updater.hash.base, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + status = firmware_update_init_no_firmware_header (&updater.test, &updater.state, &updater.map, + &updater.app.base, NULL, &updater.hash.base, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + status = firmware_update_init_no_firmware_header (&updater.test, &updater.state, &updater.map, + &updater.app.base, &updater.fw.base, NULL, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + firmware_update_testing_release_dependencies (test, &updater); +} + +static void firmware_update_test_init_no_firmware_header_no_recovery (CuTest *test) +{ + struct firmware_update_testing updater; + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.recovery_flash = NULL; + updater.map.rec_backup_flash = NULL; + updater.is_mock = false; + + status = firmware_update_init_no_firmware_header (&updater.test, &updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base, 0); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_validate_and_release (test, &updater); +} + +static void firmware_update_test_init_no_firmware_header_no_recovery_backup (CuTest *test) +{ + struct firmware_update_testing updater; + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.rec_backup_flash = NULL; + updater.is_mock = false; + + status = firmware_update_init_no_firmware_header (&updater.test, &updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base, 0); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_validate_and_release (test, &updater); +} + +static void firmware_update_test_init_no_firmware_header_no_backup (CuTest *test) +{ + struct firmware_update_testing updater; + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.backup_flash = NULL; + updater.is_mock = false; + + status = firmware_update_init_no_firmware_header (&updater.test, &updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base, 0); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_validate_and_release (test, &updater); +} + +static void firmware_update_test_init_no_firmware_header_no_recovery_no_backup (CuTest *test) +{ + struct firmware_update_testing updater; + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.backup_flash = NULL; + updater.map.recovery_flash = NULL; + updater.map.rec_backup_flash = NULL; + + status = firmware_update_init_no_firmware_header (&updater.test, &updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_FLASH_MAP, status); + + firmware_update_testing_release_dependencies (test, &updater); +} + +static void firmware_update_test_init_no_firmware_header_no_active_or_staging (CuTest *test) +{ + struct firmware_update_testing updater; + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.active_flash = NULL; + + status = firmware_update_init_no_firmware_header (&updater.test, &updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_FLASH_MAP, status); + + updater.map.active_flash = &updater.flash.base; + updater.map.staging_flash = NULL; + status = firmware_update_init_no_firmware_header (&updater.test, &updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_FLASH_MAP, status); + + firmware_update_testing_release_dependencies (test, &updater); +} + +static void firmware_update_test_static_init_no_firmware_header (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + CuAssertPtrEquals (test, NULL, test_static.internal.finalize_image); + CuAssertPtrEquals (test, NULL, test_static.internal.verify_boot_image); + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.is_mock = false; + + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_static_init_no_firmware_header_null (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + + status = firmware_update_init_state (NULL, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + test_static.state = NULL; + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + test_static.state = &updater.state; + test_static.flash = NULL; + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + test_static.flash = &updater.map; + test_static.context = NULL; + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + test_static.context = &updater.app.base; + test_static.fw = NULL; + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + test_static.fw = &updater.fw.base; + test_static.hash = NULL; + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_ARGUMENT, status); + + firmware_update_testing_release_dependencies (test, &updater); +} + +static void firmware_update_test_static_init_no_firmware_header_no_recovery (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.recovery_flash = NULL; + updater.map.rec_backup_flash = NULL; + updater.is_mock = false; + + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_static_init_no_firmware_header_no_recovery_backup (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.rec_backup_flash = NULL; + updater.is_mock = false; + + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_static_init_no_firmware_header_no_backup (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.backup_flash = NULL; + updater.is_mock = false; + + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_static_init_no_firmware_header_no_recovery_no_backup (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.backup_flash = NULL; + updater.map.recovery_flash = NULL; + updater.map.rec_backup_flash = NULL; + + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_FLASH_MAP, status); + + firmware_update_testing_release_dependencies (test, &updater); +} + +static void firmware_update_test_static_init_no_firmware_header_no_active_or_staging (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_dependencies (test, &updater, 0); + updater.map.active_flash = NULL; + + status = firmware_update_init_state (&test_static, 0); + CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_FLASH_MAP, status); + + updater.map.active_flash = &updater.flash.base; + updater.map.staging_flash = NULL; + status = firmware_update_init_state (&test_static, 0); CuAssertIntEquals (test, FIRMWARE_UPDATE_INVALID_FLASH_MAP, status); firmware_update_testing_release_dependencies (test, &updater); @@ -487,13 +1067,6 @@ static void firmware_update_test_set_image_offset_null (CuTest *test) firmware_update_set_image_offset (NULL, 0x100); } -static void firmware_update_test_require_firmware_header_null (CuTest *test) -{ - TEST_START; - - firmware_update_require_firmware_header (NULL, false); -} - static void firmware_update_test_add_observer_null (CuTest *test) { struct firmware_update_testing updater; @@ -1253,8 +1826,7 @@ static void firmware_update_test_run_update_no_firmware_header_not_required (CuT TEST_START; - firmware_update_testing_init (test, &updater, 0, 0, 0); - firmware_update_require_firmware_header (&updater.test, false); + firmware_update_testing_init_no_firmware_header (test, &updater, 0, 0, 0); status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); @@ -1316,8 +1888,7 @@ static void firmware_update_test_run_update_with_firmware_header_not_required (C TEST_START; - firmware_update_testing_init (test, &updater, 0, 0, 0); - firmware_update_require_firmware_header (&updater.test, false); + firmware_update_testing_init_no_firmware_header (test, &updater, 0, 0, 0); status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); @@ -1370,6 +1941,275 @@ static void firmware_update_test_run_update_with_firmware_header_not_required (C firmware_update_testing_validate_and_release (test, &updater); } +static void firmware_update_test_run_update_static_init (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_run_update_static_init_with_observer (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + int zero = 0; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + + status = firmware_update_add_observer (&test_static, &updater.observer.base); + CuAssertIntEquals (test, 0, status); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.observer.mock, updater.observer.base.on_update_start, + &updater.observer, 0, MOCK_ARG_PTR_CONTAINS (&zero, sizeof (zero))); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_run_update_static_init_no_firmware_header_not_required ( + CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) NULL); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_run_update_static_init_with_firmware_header_not_required ( + CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + static void firmware_update_test_run_update_null (CuTest *test) { struct firmware_update_testing updater; @@ -1587,8 +2427,7 @@ static void firmware_update_test_run_update_verify_rollback_disallowed_firmware_ TEST_START; - firmware_update_testing_init (test, &updater, 1, 1, 0); - firmware_update_require_firmware_header (&updater.test, false); + firmware_update_testing_init_no_firmware_header (test, &updater, 1, 1, 0); status = firmware_update_add_observer (&updater.test, &updater.observer.base); CuAssertIntEquals (test, 0, status); @@ -1613,6 +2452,77 @@ static void firmware_update_test_run_update_verify_rollback_disallowed_firmware_ firmware_update_testing_validate_and_release (test, &updater); } +static void firmware_update_test_run_update_static_init_verify_rollback_disallowed (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 1, 1, 0); + + status = firmware_update_add_observer (&test_static, &updater.observer.base); + CuAssertIntEquals (test, 0, status); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_INVALID_IMAGE)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, FIRMWARE_UPDATE_REJECTED_ROLLBACK, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_run_update_static_init_verify_rollback_disallowed_firmware_header_not_required ( + CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 1, 1, 0); + + status = firmware_update_add_observer (&test_static, &updater.observer.base); + CuAssertIntEquals (test, 0, status); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_INVALID_IMAGE)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, FIRMWARE_UPDATE_REJECTED_ROLLBACK, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + static void firmware_update_test_run_update_verify_null_firmware_header (CuTest *test) { struct firmware_update_testing updater; @@ -5425,6 +6335,7 @@ static void firmware_update_test_run_update_different_flash_devices (CuTest *tes struct flash_mock flash4; struct flash_mock flash5; struct firmware_flash_map map; + struct firmware_update_state state; struct firmware_update updater; struct firmware_update_notification_mock handler; int status; @@ -5478,7 +6389,7 @@ static void firmware_update_test_run_update_different_flash_devices (CuTest *tes map.recovery_flash = &flash4.base; map.rec_backup_flash = &flash5.base; - status = firmware_update_init (&updater, &map, &app.base, &fw.base, &hash.base, 0); + status = firmware_update_init (&updater, &state, &map, &app.base, &fw.base, &hash.base, 0); CuAssertIntEquals (test, 0, status); firmware_update_testing_init_firmware_header (test, &header, &flash1, 0); @@ -5590,6 +6501,7 @@ static void firmware_update_test_run_update_different_flash_devices_finalize_ima struct flash_mock flash4; struct flash_mock flash5; struct firmware_flash_map map; + struct firmware_update_state state; struct firmware_update_mock updater; struct firmware_update_notification_mock handler; int status; @@ -5643,7 +6555,7 @@ static void firmware_update_test_run_update_different_flash_devices_finalize_ima map.recovery_flash = &flash4.base; map.rec_backup_flash = &flash5.base; - status = firmware_update_mock_init (&updater, &map, &app.base, &fw.base, &hash.base, 0); + status = firmware_update_mock_init (&updater, &state, &map, &app.base, &fw.base, &hash.base, 0); CuAssertIntEquals (test, 0, status); firmware_update_testing_init_firmware_header (test, &header, &flash1, 0); @@ -9622,6 +10534,98 @@ static void firmware_update_test_run_update_new_recovery_revision_lower (CuTest firmware_update_testing_validate_and_release (test, &updater); } +static void firmware_update_test_run_update_recovery_revision_not_set (CuTest *test) +{ + struct firmware_update_testing updater; + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + uint8_t recovery_data[] = {0x21, 0x22, 0x23}; + struct debug_log_entry_info entry = { + .format = DEBUG_LOG_ENTRY_FORMAT, + .severity = DEBUG_LOG_SEVERITY_INFO, + .component = DEBUG_LOG_COMPONENT_CERBERUS_FW, + .msg_index = FIRMWARE_LOGGING_RECOVERY_UPDATE, + .arg1 = 0, + .arg2 = 0 + }; + + TEST_START; + + firmware_update_testing_init (test, &updater, 0, -1, 0); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + status |= mock_expect (&updater.log.mock, updater.log.base.create_entry, &updater.log, 0, + MOCK_ARG_PTR_CONTAINS_TMP ((uint8_t*) &entry, LOG_ENTRY_SIZE_TIME_FIELD_NOT_INCLUDED), + MOCK_ARG (sizeof (entry))); + status |= mock_expect (&updater.log.mock, updater.log.base.flush, &updater.log, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_RECOVERY)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (recovery_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x50000, 0x40000, + recovery_data, sizeof (recovery_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATE_RECOVERY)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x40000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x40000, 0x30000, + staging_data, sizeof (staging_data)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&updater.test, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_validate_and_release (test, &updater); +} + static void firmware_update_test_run_update_same_revision_after_recovery_update (CuTest *test) { struct firmware_update_testing updater; @@ -10135,8 +11139,7 @@ static void firmware_update_test_run_update_new_recovery_firmware_header_not_req TEST_START; - firmware_update_testing_init (test, &updater, 0, 0, 1); - firmware_update_require_firmware_header (&updater.test, false); + firmware_update_testing_init_no_firmware_header (test, &updater, 0, 0, 1); status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); @@ -10210,6 +11213,481 @@ static void firmware_update_test_run_update_new_recovery_firmware_header_not_req firmware_update_testing_validate_and_release (test, &updater); } +static void firmware_update_test_run_update_recovery_revision_not_set_firmware_header_not_required ( + CuTest *test) +{ + struct firmware_update_testing updater; + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + uint8_t recovery_data[] = {0x21, 0x22, 0x23}; + struct debug_log_entry_info entry = { + .format = DEBUG_LOG_ENTRY_FORMAT, + .severity = DEBUG_LOG_SEVERITY_INFO, + .component = DEBUG_LOG_COMPONENT_CERBERUS_FW, + .msg_index = FIRMWARE_LOGGING_RECOVERY_UPDATE, + .arg1 = 0, + .arg2 = 0 + }; + + TEST_START; + + firmware_update_testing_init_no_firmware_header (test, &updater, 0, -1, 0); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + status |= mock_expect (&updater.log.mock, updater.log.base.create_entry, &updater.log, 0, + MOCK_ARG_PTR_CONTAINS_TMP ((uint8_t*) &entry, LOG_ENTRY_SIZE_TIME_FIELD_NOT_INCLUDED), + MOCK_ARG (sizeof (entry))); + status |= mock_expect (&updater.log.mock, updater.log.base.flush, &updater.log, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_RECOVERY)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (recovery_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x50000, 0x40000, + recovery_data, sizeof (recovery_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATE_RECOVERY)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x40000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x40000, 0x30000, + staging_data, sizeof (staging_data)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&updater.test, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_validate_and_release (test, &updater); +} + +static void firmware_update_test_run_update_static_init_new_recovery_revision (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + uint8_t recovery_data[] = {0x21, 0x22, 0x23}; + struct debug_log_entry_info entry = { + .format = DEBUG_LOG_ENTRY_FORMAT, + .severity = DEBUG_LOG_SEVERITY_INFO, + .component = DEBUG_LOG_COMPONENT_CERBERUS_FW, + .msg_index = FIRMWARE_LOGGING_RECOVERY_UPDATE, + .arg1 = 0, + .arg2 = 0 + }; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 1); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + status |= mock_expect (&updater.log.mock, updater.log.base.create_entry, &updater.log, 0, + MOCK_ARG_PTR_CONTAINS_TMP ((uint8_t*) &entry, LOG_ENTRY_SIZE_TIME_FIELD_NOT_INCLUDED), + MOCK_ARG (sizeof (entry))); + status |= mock_expect (&updater.log.mock, updater.log.base.flush, &updater.log, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_RECOVERY)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (recovery_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x50000, 0x40000, + recovery_data, sizeof (recovery_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATE_RECOVERY)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x40000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x40000, 0x30000, + staging_data, sizeof (staging_data)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_run_update_static_init_recovery_revision_not_set (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + uint8_t recovery_data[] = {0x21, 0x22, 0x23}; + struct debug_log_entry_info entry = { + .format = DEBUG_LOG_ENTRY_FORMAT, + .severity = DEBUG_LOG_SEVERITY_INFO, + .component = DEBUG_LOG_COMPONENT_CERBERUS_FW, + .msg_index = FIRMWARE_LOGGING_RECOVERY_UPDATE, + .arg1 = 0, + .arg2 = 0 + }; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, -1, 0); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + status |= mock_expect (&updater.log.mock, updater.log.base.create_entry, &updater.log, 0, + MOCK_ARG_PTR_CONTAINS_TMP ((uint8_t*) &entry, LOG_ENTRY_SIZE_TIME_FIELD_NOT_INCLUDED), + MOCK_ARG (sizeof (entry))); + status |= mock_expect (&updater.log.mock, updater.log.base.flush, &updater.log, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_RECOVERY)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (recovery_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x50000, 0x40000, + recovery_data, sizeof (recovery_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATE_RECOVERY)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x40000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x40000, 0x30000, + staging_data, sizeof (staging_data)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_run_update_static_init_new_recovery_firmware_header_not_required ( + CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + uint8_t recovery_data[] = {0x21, 0x22, 0x23}; + struct debug_log_entry_info entry = { + .format = DEBUG_LOG_ENTRY_FORMAT, + .severity = DEBUG_LOG_SEVERITY_INFO, + .component = DEBUG_LOG_COMPONENT_CERBERUS_FW, + .msg_index = FIRMWARE_LOGGING_RECOVERY_UPDATE, + .arg1 = 0, + .arg2 = 0 + }; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 1); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + status |= mock_expect (&updater.log.mock, updater.log.base.create_entry, &updater.log, 0, + MOCK_ARG_PTR_CONTAINS_TMP ((uint8_t*) &entry, LOG_ENTRY_SIZE_TIME_FIELD_NOT_INCLUDED), + MOCK_ARG (sizeof (entry))); + status |= mock_expect (&updater.log.mock, updater.log.base.flush, &updater.log, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_RECOVERY)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (recovery_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x50000, 0x40000, + recovery_data, sizeof (recovery_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATE_RECOVERY)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x40000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x40000, 0x30000, + staging_data, sizeof (staging_data)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_run_update_static_init_recovery_revision_not_set_firmware_header_not_required ( + CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + uint8_t recovery_data[] = {0x21, 0x22, 0x23}; + struct debug_log_entry_info entry = { + .format = DEBUG_LOG_ENTRY_FORMAT, + .severity = DEBUG_LOG_SEVERITY_INFO, + .component = DEBUG_LOG_COMPONENT_CERBERUS_FW, + .msg_index = FIRMWARE_LOGGING_RECOVERY_UPDATE, + .arg1 = 0, + .arg2 = 0 + }; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, -1, 0); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + status |= mock_expect (&updater.log.mock, updater.log.base.create_entry, &updater.log, 0, + MOCK_ARG_PTR_CONTAINS_TMP ((uint8_t*) &entry, LOG_ENTRY_SIZE_TIME_FIELD_NOT_INCLUDED), + MOCK_ARG (sizeof (entry))); + status |= mock_expect (&updater.log.mock, updater.log.base.flush, &updater.log, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_RECOVERY)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (recovery_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x50000, 0x40000, + recovery_data, sizeof (recovery_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATE_RECOVERY)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x40000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x40000, 0x30000, + staging_data, sizeof (staging_data)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + static void firmware_update_test_prepare_staging (CuTest *test) { struct firmware_update_testing updater; @@ -10256,6 +11734,31 @@ static void firmware_update_test_prepare_staging_image_offset (CuTest *test) firmware_update_testing_validate_and_release (test, &updater); } +static void firmware_update_test_prepare_staging_static_init (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_STAGING_PREP)); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x30000, 5); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_prepare_staging (&test_static, &updater.handler.base, 5); + CuAssertIntEquals (test, 0, status); + CuAssertIntEquals (test, 5, firmware_update_get_update_remaining (&test_static)); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + static void firmware_update_test_prepare_staging_null_updater (CuTest *test) { struct firmware_update_testing updater; @@ -10465,6 +11968,37 @@ static void firmware_update_test_write_to_staging_image_offset (CuTest *test) firmware_update_testing_validate_and_release (test, &updater); } +static void firmware_update_test_write_to_staging_static_init (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_STAGING_WRITE)); + status |= mock_expect (&updater.flash.mock, updater.flash.base.write, &updater.flash, + sizeof (staging_data), MOCK_ARG (0x30000), + MOCK_ARG_PTR_CONTAINS (staging_data, sizeof (staging_data)), + MOCK_ARG (sizeof (staging_data))); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_write_to_staging (&test_static, &updater.handler.base, staging_data, + sizeof (staging_data)); + CuAssertIntEquals (test, 0, status); + CuAssertIntEquals (test, (int) -sizeof (staging_data), + firmware_update_get_update_remaining (&test_static)); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + static void firmware_update_test_write_to_staging_null_updater (CuTest *test) { struct firmware_update_testing updater; @@ -11147,186 +12681,6 @@ static void firmware_update_test_validate_recovery_image_set_recovery_revision ( firmware_header_release (&header2); } -static void firmware_update_test_validate_recovery_image_no_firmware_header_not_required ( - CuTest *test) -{ - struct firmware_update_testing updater; - int status; - uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; - uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; - struct debug_log_entry_info entry = { - .format = DEBUG_LOG_ENTRY_FORMAT, - .severity = DEBUG_LOG_SEVERITY_INFO, - .component = DEBUG_LOG_COMPONENT_CERBERUS_FW, - .msg_index = FIRMWARE_LOGGING_RECOVERY_IMAGE, - .arg1 = 0, - .arg2 = 0 - }; - - TEST_START; - - firmware_update_testing_init (test, &updater, 0, 0, 0); - firmware_update_require_firmware_header (&updater.test, false); - - firmware_update_set_recovery_good (&updater.test, false); - - status = mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, - MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, - MOCK_ARG (&updater.hash)); - - status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, - (intptr_t) NULL); - - status |= mock_expect (&updater.log.mock, updater.log.base.create_entry, &updater.log, 0, - MOCK_ARG_PTR_CONTAINS_TMP ((uint8_t*) &entry, LOG_ENTRY_SIZE_TIME_FIELD_NOT_INCLUDED), - MOCK_ARG (sizeof (entry))); - - CuAssertIntEquals (test, 0, status); - - firmware_update_validate_recovery_image (&updater.test); - CuAssertIntEquals (test, 1, firmware_update_is_recovery_good (&updater.test)); - - firmware_update_testing_validate (test, &updater); - debug_log = NULL; - - /* The recovery image validated as good, so the update should proceed normally. */ - - status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, - &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, - MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, - MOCK_ARG (&updater.hash)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, - (intptr_t) NULL); - status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, - sizeof (staging_data)); - - status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, - &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); - status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); - - status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, - &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, - MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, - sizeof (active_data)); - status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, - active_data, sizeof (active_data)); - - status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, - &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); - status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); - status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); - status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, - staging_data, sizeof (staging_data)); - - status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, - &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, - MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, - (intptr_t) &updater.manifest); - status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, - &updater.manifest, 0); - - status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, - &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); - - CuAssertIntEquals (test, 0, status); - - status = firmware_update_run_update (&updater.test, &updater.handler.base); - CuAssertIntEquals (test, 0, status); - - firmware_update_testing_validate_and_release (test, &updater); -} - -static void firmware_update_test_validate_recovery_image_with_firmware_header_not_required ( - CuTest *test) -{ - struct firmware_update_testing updater; - int status; - uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; - uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; - - TEST_START; - - firmware_update_testing_init (test, &updater, 0, 0, 0); - firmware_update_require_firmware_header (&updater.test, false); - debug_log = NULL; - - firmware_update_set_recovery_good (&updater.test, false); - - status = mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, - MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, - MOCK_ARG (&updater.hash)); - - status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, - (intptr_t) &updater.header); - - CuAssertIntEquals (test, 0, status); - - firmware_update_validate_recovery_image (&updater.test); - CuAssertIntEquals (test, 1, firmware_update_is_recovery_good (&updater.test)); - - firmware_update_testing_validate (test, &updater); - - /* The recovery image validated as good, so the update should proceed normally. */ - - status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, - &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, - MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, - MOCK_ARG (&updater.hash)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, - (intptr_t) &updater.header); - status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, - sizeof (staging_data)); - - status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, - &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); - status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); - - status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, - &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, - MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, - sizeof (active_data)); - status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, - active_data, sizeof (active_data)); - - status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, - &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); - status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); - status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); - status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, - staging_data, sizeof (staging_data)); - - status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, - &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, - MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); - status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, - (intptr_t) &updater.manifest); - status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, - &updater.manifest, 0); - - status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, - &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); - - CuAssertIntEquals (test, 0, status); - - status = firmware_update_run_update (&updater.test, &updater.handler.base); - CuAssertIntEquals (test, 0, status); - - firmware_update_testing_validate_and_release (test, &updater); -} - static void firmware_update_test_validate_recovery_image_bad (CuTest *test) { struct firmware_update_testing updater; @@ -11629,7 +12983,466 @@ static void firmware_update_test_validate_recovery_image_load_verify_bad_format firmware_update_testing_validate_and_release (test, &updater); } -static void firmware_update_test_validate_recovery_image_offset_null (CuTest *test) +static void firmware_update_test_validate_recovery_image_no_firmware_header_not_required ( + CuTest *test) +{ + struct firmware_update_testing updater; + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + struct debug_log_entry_info entry = { + .format = DEBUG_LOG_ENTRY_FORMAT, + .severity = DEBUG_LOG_SEVERITY_INFO, + .component = DEBUG_LOG_COMPONENT_CERBERUS_FW, + .msg_index = FIRMWARE_LOGGING_RECOVERY_IMAGE, + .arg1 = 0, + .arg2 = 0 + }; + + TEST_START; + + firmware_update_testing_init_no_firmware_header (test, &updater, 0, 0, 0); + + firmware_update_set_recovery_good (&updater.test, false); + + status = mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) NULL); + + status |= mock_expect (&updater.log.mock, updater.log.base.create_entry, &updater.log, 0, + MOCK_ARG_PTR_CONTAINS_TMP ((uint8_t*) &entry, LOG_ENTRY_SIZE_TIME_FIELD_NOT_INCLUDED), + MOCK_ARG (sizeof (entry))); + + CuAssertIntEquals (test, 0, status); + + firmware_update_validate_recovery_image (&updater.test); + CuAssertIntEquals (test, 1, firmware_update_is_recovery_good (&updater.test)); + + firmware_update_testing_validate (test, &updater); + debug_log = NULL; + + /* The recovery image validated as good, so the update should proceed normally. */ + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) NULL); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&updater.test, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_validate_and_release (test, &updater); +} + +static void firmware_update_test_validate_recovery_image_with_firmware_header_not_required ( + CuTest *test) +{ + struct firmware_update_testing updater; + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + + TEST_START; + + firmware_update_testing_init_no_firmware_header (test, &updater, 0, 0, 0); + debug_log = NULL; + + firmware_update_set_recovery_good (&updater.test, false); + + status = mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + + CuAssertIntEquals (test, 0, status); + + firmware_update_validate_recovery_image (&updater.test); + CuAssertIntEquals (test, 1, firmware_update_is_recovery_good (&updater.test)); + + firmware_update_testing_validate (test, &updater); + + /* The recovery image validated as good, so the update should proceed normally. */ + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&updater.test, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_validate_and_release (test, &updater); +} + +static void firmware_update_test_validate_recovery_image_static_init (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + struct debug_log_entry_info entry = { + .format = DEBUG_LOG_ENTRY_FORMAT, + .severity = DEBUG_LOG_SEVERITY_INFO, + .component = DEBUG_LOG_COMPONENT_CERBERUS_FW, + .msg_index = FIRMWARE_LOGGING_RECOVERY_IMAGE, + .arg1 = 0, + .arg2 = 0 + }; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + + firmware_update_set_recovery_good (&test_static, false); + + status = mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + + status |= mock_expect (&updater.log.mock, updater.log.base.create_entry, &updater.log, 0, + MOCK_ARG_PTR_CONTAINS_TMP ((uint8_t*) &entry, LOG_ENTRY_SIZE_TIME_FIELD_NOT_INCLUDED), + MOCK_ARG (sizeof (entry))); + + CuAssertIntEquals (test, 0, status); + + firmware_update_validate_recovery_image (&test_static); + CuAssertIntEquals (test, 1, firmware_update_is_recovery_good (&test_static)); + + firmware_update_testing_validate (test, &updater); + debug_log = NULL; + + /* The recovery image validated as good, so the update should proceed normally. */ + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_validate_recovery_image_static_init_no_firmware_header_not_required ( + CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + struct debug_log_entry_info entry = { + .format = DEBUG_LOG_ENTRY_FORMAT, + .severity = DEBUG_LOG_SEVERITY_INFO, + .component = DEBUG_LOG_COMPONENT_CERBERUS_FW, + .msg_index = FIRMWARE_LOGGING_RECOVERY_IMAGE, + .arg1 = 0, + .arg2 = 0 + }; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + + firmware_update_set_recovery_good (&test_static, false); + + status = mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) NULL); + + status |= mock_expect (&updater.log.mock, updater.log.base.create_entry, &updater.log, 0, + MOCK_ARG_PTR_CONTAINS_TMP ((uint8_t*) &entry, LOG_ENTRY_SIZE_TIME_FIELD_NOT_INCLUDED), + MOCK_ARG (sizeof (entry))); + + CuAssertIntEquals (test, 0, status); + + firmware_update_validate_recovery_image (&test_static); + CuAssertIntEquals (test, 1, firmware_update_is_recovery_good (&test_static)); + + firmware_update_testing_validate (test, &updater); + debug_log = NULL; + + /* The recovery image validated as good, so the update should proceed normally. */ + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) NULL); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_validate_recovery_image_static_init_with_firmware_header_not_required ( + CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + debug_log = NULL; + + firmware_update_set_recovery_good (&test_static, false); + + status = mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + + CuAssertIntEquals (test, 0, status); + + firmware_update_validate_recovery_image (&test_static); + CuAssertIntEquals (test, 1, firmware_update_is_recovery_good (&test_static)); + + firmware_update_testing_validate (test, &updater); + + /* The recovery image validated as good, so the update should proceed normally. */ + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_validate_recovery_image_null (CuTest *test) { TEST_START; @@ -12701,8 +14514,7 @@ static void firmware_update_test_restore_recovery_image_followed_by_update_no_fi TEST_START; - firmware_update_testing_init (test, &updater, 0, 0, 0); - firmware_update_require_firmware_header (&updater.test, false); + firmware_update_testing_init_no_firmware_header (test, &updater, 0, 0, 0); debug_log = NULL; firmware_update_set_recovery_good (&updater.test, false); @@ -12791,8 +14603,7 @@ static void firmware_update_test_restore_recovery_image_followed_by_update_with_ TEST_START; - firmware_update_testing_init (test, &updater, 0, 0, 0); - firmware_update_require_firmware_header (&updater.test, false); + firmware_update_testing_init_no_firmware_header (test, &updater, 0, 0, 0); debug_log = NULL; firmware_update_set_recovery_good (&updater.test, false); @@ -12871,6 +14682,239 @@ static void firmware_update_test_restore_recovery_image_followed_by_update_with_ firmware_update_testing_validate_and_release (test, &updater); } +static void firmware_update_test_restore_recovery_image_static_init (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + struct debug_log_entry_info entry = { + .format = DEBUG_LOG_ENTRY_FORMAT, + .severity = DEBUG_LOG_SEVERITY_INFO, + .component = DEBUG_LOG_COMPONENT_CERBERUS_FW, + .msg_index = FIRMWARE_LOGGING_RECOVERY_RESTORE_START, + .arg1 = 0, + .arg2 = 0 + }; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + + firmware_update_set_recovery_good (&test_static, false); + + status = mock_expect (&updater.log.mock, updater.log.base.create_entry, &updater.log, 0, + MOCK_ARG_PTR_CONTAINS_TMP ((uint8_t*) &entry, LOG_ENTRY_SIZE_TIME_FIELD_NOT_INCLUDED), + MOCK_ARG (sizeof (entry))); + + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x40000, sizeof (active_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x40000, 0x10000, + active_data, sizeof (active_data)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_restore_recovery_image (&test_static); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_restore_recovery_image_static_init_followed_by_update_no_firmware_header_not_required ( + CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + debug_log = NULL; + + firmware_update_set_recovery_good (&test_static, false); + + status = mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) NULL); + + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x40000, sizeof (active_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x40000, 0x10000, + active_data, sizeof (active_data)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_restore_recovery_image (&test_static); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_validate (test, &updater); + + /* The recovery image will not be updated since it was previously restored to a good state. */ + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) NULL); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + +static void firmware_update_test_restore_recovery_image_static_init_followed_by_update_with_firmware_header_not_required ( + CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init_no_firmware_header ( + &updater.state, &updater.map, &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t staging_data[] = {0x11, 0x12, 0x13, 0x14, 0x15}; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + debug_log = NULL; + + firmware_update_set_recovery_good (&test_static, false); + + status = mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x40000, sizeof (active_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x40000, 0x10000, + active_data, sizeof (active_data)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_restore_recovery_image (&test_static); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_validate (test, &updater); + + /* The recovery image will not be updated since it was previously restored to a good state. */ + + status = mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_VERIFYING_IMAGE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x30000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_firmware_header, &updater.fw, + (intptr_t) &updater.header); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_SAVING_STATE)); + status |= mock_expect (&updater.app.mock, updater.app.base.save, &updater.app, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_BACKUP_ACTIVE)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + status |= flash_mock_expect_erase_copy_verify (&updater.flash, &updater.flash, 0x20000, 0x10000, + active_data, sizeof (active_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_UPDATING_IMAGE)); + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (staging_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x30000, + staging_data, sizeof (staging_data)); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_REVOCATION)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x10000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_key_manifest, &updater.fw, + (intptr_t) &updater.manifest); + status |= mock_expect (&updater.manifest.mock, updater.manifest.base.revokes_old_manifest, + &updater.manifest, 0); + + status |= mock_expect (&updater.handler.mock, updater.handler.base.status_change, + &updater.handler, 0, MOCK_ARG (UPDATE_STATUS_CHECK_RECOVERY)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_run_update (&test_static, &updater.handler.base); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies(test, &updater); + firmware_update_release (&test_static); +} + static void firmware_update_test_restore_recovery_image_null (CuTest *test) { int status; @@ -13395,6 +15439,39 @@ static void firmware_update_test_restore_active_image_finalize_image_with_offset firmware_update_testing_validate_and_release (test, &updater); } +static void firmware_update_test_restore_active_image_static_init (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + int status; + uint8_t active_data[] = {0x01, 0x02, 0x03, 0x04}; + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + + status = mock_expect (&updater.fw.mock, updater.fw.base.load, &updater.fw, 0, + MOCK_ARG (&updater.flash), MOCK_ARG (0x40000)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.verify, &updater.fw, 0, + MOCK_ARG (&updater.hash)); + status |= mock_expect (&updater.fw.mock, updater.fw.base.get_image_size, &updater.fw, + sizeof (active_data)); + + status |= firmware_update_testing_flash_page_size (&updater.flash, FLASH_PAGE_SIZE); + status |= flash_mock_expect_erase_flash_verify (&updater.flash, 0x10000, sizeof (active_data)); + status |= flash_mock_expect_copy_flash_verify (&updater.flash, &updater.flash, 0x10000, 0x40000, + active_data, sizeof (active_data)); + + CuAssertIntEquals (test, 0, status); + + status = firmware_update_restore_active_image (&test_static); + CuAssertIntEquals (test, 0, status); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + static void firmware_update_test_restore_active_image_null (CuTest *test) { int status; @@ -13618,6 +15695,26 @@ static void firmware_update_test_is_recovery_good (CuTest *test) firmware_update_testing_validate_and_release (test, &updater); } +static void firmware_update_test_is_recovery_good_static_init (CuTest *test) +{ + struct firmware_update_testing updater; + struct firmware_update test_static = firmware_update_static_init (&updater.state, &updater.map, + &updater.app.base, &updater.fw.base, &updater.hash.base); + + TEST_START; + + firmware_update_testing_init_static (test, &updater, &test_static, 0, 0, 0); + + firmware_update_set_recovery_good (&test_static, false); + CuAssertIntEquals (test, 0, firmware_update_is_recovery_good (&test_static)); + + firmware_update_set_recovery_good (&test_static, true); + CuAssertIntEquals (test, 1, firmware_update_is_recovery_good (&test_static)); + + firmware_update_testing_release_dependencies (test, &updater); + firmware_update_release (&test_static); +} + static void firmware_update_test_is_recovery_good_null (CuTest *test) { TEST_START; @@ -13636,11 +15733,31 @@ TEST (firmware_update_test_init_no_recovery_backup); TEST (firmware_update_test_init_no_backup); TEST (firmware_update_test_init_no_recovery_no_backup); TEST (firmware_update_test_init_no_active_or_staging); +TEST (firmware_update_test_static_init); +TEST (firmware_update_test_static_init_null); +TEST (firmware_update_test_static_init_no_recovery); +TEST (firmware_update_test_static_init_no_recovery_backup); +TEST (firmware_update_test_static_init_no_backup); +TEST (firmware_update_test_static_init_no_recovery_no_backup); +TEST (firmware_update_test_static_init_no_active_or_staging); +TEST (firmware_update_test_init_no_firmware_header); +TEST (firmware_update_test_init_no_firmware_header_null); +TEST (firmware_update_test_init_no_firmware_header_no_recovery); +TEST (firmware_update_test_init_no_firmware_header_no_recovery_backup); +TEST (firmware_update_test_init_no_firmware_header_no_backup); +TEST (firmware_update_test_init_no_firmware_header_no_recovery_no_backup); +TEST (firmware_update_test_init_no_firmware_header_no_active_or_staging); +TEST (firmware_update_test_static_init_no_firmware_header); +TEST (firmware_update_test_static_init_no_firmware_header_null); +TEST (firmware_update_test_static_init_no_firmware_header_no_recovery); +TEST (firmware_update_test_static_init_no_firmware_header_no_recovery_backup); +TEST (firmware_update_test_static_init_no_firmware_header_no_backup); +TEST (firmware_update_test_static_init_no_firmware_header_no_recovery_no_backup); +TEST (firmware_update_test_static_init_no_firmware_header_no_active_or_staging); TEST (firmware_update_test_release_null); TEST (firmware_update_test_set_recovery_good_null); TEST (firmware_update_test_set_recovery_revision_null); TEST (firmware_update_test_set_image_offset_null); -TEST (firmware_update_test_require_firmware_header_null); TEST (firmware_update_test_add_observer_null); TEST (firmware_update_test_remove_observer_null); TEST (firmware_update_test_run_update); @@ -13656,6 +15773,10 @@ TEST (firmware_update_test_run_update_observer_removed); TEST (firmware_update_test_run_update_extra_data_received); TEST (firmware_update_test_run_update_no_firmware_header_not_required); TEST (firmware_update_test_run_update_with_firmware_header_not_required); +TEST (firmware_update_test_run_update_static_init); +TEST (firmware_update_test_run_update_static_init_with_observer); +TEST (firmware_update_test_run_update_static_init_no_firmware_header_not_required); +TEST (firmware_update_test_run_update_static_init_with_firmware_header_not_required); TEST (firmware_update_test_run_update_null); TEST (firmware_update_test_run_update_verify_incomplete_image); TEST (firmware_update_test_run_update_verify_fail_load); @@ -13664,6 +15785,8 @@ TEST (firmware_update_test_run_update_verify_manifest_revoked); TEST (firmware_update_test_run_update_verify_error); TEST (firmware_update_test_run_update_verify_rollback_disallowed); TEST (firmware_update_test_run_update_verify_rollback_disallowed_firmware_header_not_required); +TEST (firmware_update_test_run_update_static_init_verify_rollback_disallowed); +TEST (firmware_update_test_run_update_static_init_verify_rollback_disallowed_firmware_header_not_required); TEST (firmware_update_test_run_update_verify_null_firmware_header); TEST (firmware_update_test_run_update_verify_img_size_error); TEST (firmware_update_test_run_update_blocked_by_observer); @@ -13755,13 +15878,20 @@ TEST (firmware_update_test_run_update_after_recovery_bad_update_fail); TEST (firmware_update_test_run_update_after_recovery_bad_finalize_fail); TEST (firmware_update_test_run_update_new_recovery_revision_higher); TEST (firmware_update_test_run_update_new_recovery_revision_lower); +TEST (firmware_update_test_run_update_recovery_revision_not_set); TEST (firmware_update_test_run_update_same_revision_after_recovery_update); TEST (firmware_update_test_run_update_same_revision_after_manifest_revocation); TEST (firmware_update_test_run_update_recovery_bad_different_revision); TEST (firmware_update_test_run_update_same_revision_after_recovery_bad); TEST (firmware_update_test_run_update_new_recovery_firmware_header_not_required); +TEST (firmware_update_test_run_update_recovery_revision_not_set_firmware_header_not_required); +TEST (firmware_update_test_run_update_static_init_new_recovery_revision); +TEST (firmware_update_test_run_update_static_init_recovery_revision_not_set); +TEST (firmware_update_test_run_update_static_init_new_recovery_firmware_header_not_required); +TEST (firmware_update_test_run_update_static_init_recovery_revision_not_set_firmware_header_not_required); TEST (firmware_update_test_prepare_staging); TEST (firmware_update_test_prepare_staging_image_offset); +TEST (firmware_update_test_prepare_staging_static_init); TEST (firmware_update_test_prepare_staging_null_updater); TEST (firmware_update_test_prepare_staging_null_callback); TEST (firmware_update_test_prepare_staging_image_too_large); @@ -13770,6 +15900,7 @@ TEST (firmware_update_test_prepare_staging_erase_error); TEST (firmware_update_test_write_to_staging); TEST (firmware_update_test_write_to_staging_multiple_calls); TEST (firmware_update_test_write_to_staging_image_offset); +TEST (firmware_update_test_write_to_staging_static_init); TEST (firmware_update_test_write_to_staging_null_updater); TEST (firmware_update_test_write_to_staging_null_callback); TEST (firmware_update_test_write_to_staging_write_fail); @@ -13784,12 +15915,15 @@ TEST (firmware_update_test_validate_recovery_image_extra_verify); TEST (firmware_update_test_validate_recovery_image_extra_verify_offset); TEST (firmware_update_test_validate_recovery_image_no_recovery); TEST (firmware_update_test_validate_recovery_image_set_recovery_revision); -TEST (firmware_update_test_validate_recovery_image_no_firmware_header_not_required); -TEST (firmware_update_test_validate_recovery_image_with_firmware_header_not_required); TEST (firmware_update_test_validate_recovery_image_bad); TEST (firmware_update_test_validate_recovery_image_bad_extra_verify); TEST (firmware_update_test_validate_recovery_image_load_verify_bad_format); -TEST (firmware_update_test_validate_recovery_image_offset_null); +TEST (firmware_update_test_validate_recovery_image_no_firmware_header_not_required); +TEST (firmware_update_test_validate_recovery_image_with_firmware_header_not_required); +TEST (firmware_update_test_validate_recovery_image_static_init); +TEST (firmware_update_test_validate_recovery_image_static_init_no_firmware_header_not_required); +TEST (firmware_update_test_validate_recovery_image_static_init_with_firmware_header_not_required); +TEST (firmware_update_test_validate_recovery_image_null); TEST (firmware_update_test_validate_recovery_image_load_failure); TEST (firmware_update_test_validate_recovery_image_verify_failure); TEST (firmware_update_test_validate_recovery_image_extra_verify_failure); @@ -13808,6 +15942,9 @@ TEST (firmware_update_test_restore_recovery_image_followed_by_update_different_r TEST (firmware_update_test_restore_recovery_image_followed_by_update_null_header); TEST (firmware_update_test_restore_recovery_image_followed_by_update_no_firmware_header_not_required); TEST (firmware_update_test_restore_recovery_image_followed_by_update_with_firmware_header_not_required); +TEST (firmware_update_test_restore_recovery_image_static_init); +TEST (firmware_update_test_restore_recovery_image_static_init_followed_by_update_no_firmware_header_not_required); +TEST (firmware_update_test_restore_recovery_image_static_init_followed_by_update_with_firmware_header_not_required); TEST (firmware_update_test_restore_recovery_image_null); TEST (firmware_update_test_restore_recovery_image_fail_load); TEST (firmware_update_test_restore_recovery_image_invalid_image); @@ -13823,6 +15960,7 @@ TEST (firmware_update_test_restore_active_image_no_recovery); TEST (firmware_update_test_restore_active_image_with_offset); TEST (firmware_update_test_restore_active_image_finalize_image); TEST (firmware_update_test_restore_active_image_finalize_image_with_offset); +TEST (firmware_update_test_restore_active_image_static_init); TEST (firmware_update_test_restore_active_image_null); TEST (firmware_update_test_restore_active_image_fail_load); TEST (firmware_update_test_restore_active_image_invalid_image); @@ -13832,6 +15970,7 @@ TEST (firmware_update_test_restore_active_image_erase_failure); TEST (firmware_update_test_restore_active_image_write_active_error); TEST (firmware_update_test_restore_active_image_finalize_image_error); TEST (firmware_update_test_is_recovery_good); +TEST (firmware_update_test_is_recovery_good_static_init); TEST (firmware_update_test_is_recovery_good_null); TEST_SUITE_END; diff --git a/core/testing/mock/firmware/app_context_mock.c b/core/testing/mock/firmware/app_context_mock.c index a4a4814..75c4602 100644 --- a/core/testing/mock/firmware/app_context_mock.c +++ b/core/testing/mock/firmware/app_context_mock.c @@ -7,7 +7,7 @@ #include "app_context_mock.h" -static int app_context_mock_save (struct app_context *context) +static int app_context_mock_save (const struct app_context *context) { struct app_context_mock *mock = (struct app_context_mock*) context; diff --git a/core/testing/mock/firmware/firmware_image_mock.c b/core/testing/mock/firmware/firmware_image_mock.c index faa2227..75d7b4a 100644 --- a/core/testing/mock/firmware/firmware_image_mock.c +++ b/core/testing/mock/firmware/firmware_image_mock.c @@ -7,7 +7,7 @@ #include "firmware_image_mock.h" -static int firmware_image_mock_load (struct firmware_image *fw, struct flash *flash, +static int firmware_image_mock_load (const struct firmware_image *fw, const struct flash *flash, uint32_t base_addr) { struct firmware_image_mock *mock = (struct firmware_image_mock*) fw; @@ -20,7 +20,7 @@ static int firmware_image_mock_load (struct firmware_image *fw, struct flash *fl MOCK_ARG_CALL (base_addr)); } -static int firmware_image_mock_verify (struct firmware_image *fw, struct hash_engine *hash) +static int firmware_image_mock_verify (const struct firmware_image *fw, struct hash_engine *hash) { struct firmware_image_mock *mock = (struct firmware_image_mock*) fw; @@ -31,7 +31,7 @@ static int firmware_image_mock_verify (struct firmware_image *fw, struct hash_en MOCK_RETURN (&mock->mock, firmware_image_mock_verify, fw, MOCK_ARG_CALL (hash)); } -static int firmware_image_mock_get_image_size (struct firmware_image *fw) +static int firmware_image_mock_get_image_size (const struct firmware_image *fw) { struct firmware_image_mock *mock = (struct firmware_image_mock*) fw; @@ -42,7 +42,8 @@ static int firmware_image_mock_get_image_size (struct firmware_image *fw) MOCK_RETURN_NO_ARGS (&mock->mock, firmware_image_mock_get_image_size, fw); } -static struct key_manifest* firmware_image_mock_get_key_manifest (struct firmware_image *fw) +static const struct key_manifest* firmware_image_mock_get_key_manifest ( + const struct firmware_image *fw) { struct firmware_image_mock *mock = (struct firmware_image_mock*) fw; @@ -54,7 +55,8 @@ static struct key_manifest* firmware_image_mock_get_key_manifest (struct firmwar firmware_image_mock_get_key_manifest, fw); } -static struct firmware_header* firmware_image_mock_get_firmware_header (struct firmware_image *fw) +static const struct firmware_header* firmware_image_mock_get_firmware_header ( + const struct firmware_image *fw) { struct firmware_image_mock *mock = (struct firmware_image_mock*) fw; diff --git a/core/testing/mock/firmware/firmware_update_mock.c b/core/testing/mock/firmware/firmware_update_mock.c index 94ac31e..15efea6 100644 --- a/core/testing/mock/firmware/firmware_update_mock.c +++ b/core/testing/mock/firmware/firmware_update_mock.c @@ -7,8 +7,8 @@ #include "firmware_update_mock.h" -int firmware_update_mock_finalize_image (struct firmware_update *updater, struct flash *flash, - uint32_t address) +int firmware_update_mock_finalize_image (const struct firmware_update *updater, + const struct flash *flash, uint32_t address) { struct firmware_update_mock *mock = (struct firmware_update_mock*) updater; @@ -20,8 +20,8 @@ int firmware_update_mock_finalize_image (struct firmware_update *updater, struct MOCK_ARG_CALL (address)); } -int firmware_update_mock_verify_boot_image (struct firmware_update *updater, struct flash *flash, - uint32_t address) +int firmware_update_mock_verify_boot_image (const struct firmware_update *updater, + const struct flash *flash, uint32_t address) { struct firmware_update_mock *mock = (struct firmware_update_mock*) updater; @@ -94,8 +94,9 @@ static const char* firmware_update_mock_arg_name_map (void *func, int arg) * @return 0 if the mock was initialized successfully or an error code. */ int firmware_update_mock_init (struct firmware_update_mock *mock, - const struct firmware_flash_map *flash, struct app_context *context, struct firmware_image *fw, - struct hash_engine *hash, int allowed_revision) + struct firmware_update_state *state, const struct firmware_flash_map *flash, + struct app_context *context, struct firmware_image *fw, struct hash_engine *hash, + int allowed_revision) { int status; @@ -105,7 +106,7 @@ int firmware_update_mock_init (struct firmware_update_mock *mock, memset (mock, 0, sizeof (struct firmware_update_mock)); - status = firmware_update_init (&mock->base, flash, context, fw, hash, allowed_revision); + status = firmware_update_init (&mock->base, state, flash, context, fw, hash, allowed_revision); if (status != 0) { return status; } diff --git a/core/testing/mock/firmware/firmware_update_mock.h b/core/testing/mock/firmware/firmware_update_mock.h index f965e73..84b7ace 100644 --- a/core/testing/mock/firmware/firmware_update_mock.h +++ b/core/testing/mock/firmware/firmware_update_mock.h @@ -18,18 +18,19 @@ struct firmware_update_mock { int firmware_update_mock_init (struct firmware_update_mock *mock, - const struct firmware_flash_map *flash, struct app_context *context, struct firmware_image *fw, - struct hash_engine *hash, int allowed_revision); + struct firmware_update_state *state, const struct firmware_flash_map *flash, + struct app_context *context, struct firmware_image *fw, struct hash_engine *hash, + int allowed_revision); void firmware_update_mock_release (struct firmware_update_mock *mock); int firmware_update_mock_validate_and_release (struct firmware_update_mock *mock); -int firmware_update_mock_finalize_image (struct firmware_update *updater, struct flash *flash, - uint32_t address); +int firmware_update_mock_finalize_image (const struct firmware_update *updater, + const struct flash *flash, uint32_t address); void firmware_update_mock_enable_finalize_image (struct firmware_update_mock *mock); -int firmware_update_mock_verify_boot_image (struct firmware_update *updater, struct flash *flash, - uint32_t address); +int firmware_update_mock_verify_boot_image (const struct firmware_update *updater, + const struct flash *flash, uint32_t address); void firmware_update_mock_enable_verify_boot_image (struct firmware_update_mock *mock); diff --git a/core/testing/mock/firmware/firmware_update_notification_mock.c b/core/testing/mock/firmware/firmware_update_notification_mock.c index 513adf9..bd08985 100644 --- a/core/testing/mock/firmware/firmware_update_notification_mock.c +++ b/core/testing/mock/firmware/firmware_update_notification_mock.c @@ -8,7 +8,7 @@ static void firmware_update_notification_mock_state_change ( - struct firmware_update_notification *context, enum firmware_update_status state) + const struct firmware_update_notification *context, enum firmware_update_status state) { struct firmware_update_notification_mock *mock = (struct firmware_update_notification_mock*) context; diff --git a/projects/freertos/fw_update_task.c b/projects/freertos/fw_update_task.c index 7e9e742..be94154 100644 --- a/projects/freertos/fw_update_task.c +++ b/projects/freertos/fw_update_task.c @@ -251,10 +251,10 @@ static int fw_update_task_write_staging (struct firmware_update_control *update, return status; } -static void fw_update_task_status_change (struct firmware_update_notification *context, +static void fw_update_task_status_change (const struct firmware_update_notification *context, enum firmware_update_status status) { - struct fw_update_task_notify *notify = (struct fw_update_task_notify*) context; + const struct fw_update_task_notify *notify = (const struct fw_update_task_notify*) context; if (notify != NULL) { xSemaphoreTake (notify->task->lock, portMAX_DELAY); @@ -272,7 +272,7 @@ static void fw_update_task_status_change (struct firmware_update_notification *c * * @return 0 if the task was successfully initialized or an error code. */ -int fw_update_task_init (struct fw_update_task *task, struct firmware_update *updater, +int fw_update_task_init (struct fw_update_task *task, const struct firmware_update *updater, struct system *system) { if ((task == NULL) || (updater == NULL) || (system == NULL)) { diff --git a/projects/freertos/fw_update_task.h b/projects/freertos/fw_update_task.h index 7309464..48881ea 100644 --- a/projects/freertos/fw_update_task.h +++ b/projects/freertos/fw_update_task.h @@ -32,7 +32,7 @@ struct fw_update_task_notify { struct fw_update_task { struct firmware_update_control base; /**< The base control instance. */ struct fw_update_task_notify notify; /**< The update notification interface. */ - struct firmware_update *updater; /**< The firmware updater. */ + const struct firmware_update *updater; /**< The firmware updater. */ struct system *system; /**< The system manager. */ int update_status; /**< The last firmware update status. */ uint8_t running; /**< Flag indicating if an update is running. */ @@ -44,7 +44,7 @@ struct fw_update_task { }; -int fw_update_task_init (struct fw_update_task *task, struct firmware_update *updater, +int fw_update_task_init (struct fw_update_task *task, const struct firmware_update *updater, struct system *system); int fw_update_task_start (struct fw_update_task *task, uint16_t stack_words, bool running_recovery);