Skip to content

Commit

Permalink
[nrf noup] zephyr: Add support for ARM thumb filter
Browse files Browse the repository at this point in the history
Adds support for ARM thumb filter usage for compressed firmware
updates

Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
  • Loading branch information
nordicjm committed Sep 24, 2024
1 parent 92121b1 commit 945338a
Showing 1 changed file with 105 additions and 18 deletions.
123 changes: 105 additions & 18 deletions boot/zephyr/decompression.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index
uint32_t write_pos = 0;
uint32_t protected_tlv_size = 0;
uint32_t decompressed_image_size;
struct nrf_compress_implementation *compression = NULL;
struct nrf_compress_implementation *compression_lzma = NULL;
struct nrf_compress_implementation *compression_arm_thumb = NULL;
TARGET_STATIC struct image_header modified_hdr;
bootutil_sha_context sha_ctx;
uint8_t flash_erased_value;
Expand All @@ -126,18 +127,23 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index
goto finish_without_clean;
}

compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA);
compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA);
compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB);

if (compression == NULL || compression->init == NULL || compression->deinit == NULL ||
compression->decompress_bytes_needed == NULL || compression->decompress == NULL) {
if (compression_lzma == NULL || compression_lzma->init == NULL ||
compression_lzma->deinit == NULL || compression_lzma->decompress_bytes_needed == NULL ||
compression_lzma->decompress == NULL || compression_arm_thumb == NULL ||
compression_arm_thumb->init == NULL || compression_arm_thumb->deinit == NULL ||
compression_arm_thumb->decompress_bytes_needed == NULL ||
compression_arm_thumb->decompress == NULL) {
/* Compression library missing or missing required function pointer */
BOOT_LOG_ERR("Decompression library fatal error");
rc = BOOT_EBADSTATUS;

goto finish_without_clean;
}

rc = compression->init(NULL);
rc = compression_lzma->init(NULL);

if (rc) {
BOOT_LOG_ERR("Decompression library fatal error");
Expand Down Expand Up @@ -225,7 +231,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index
uint32_t chunk_size;
bool last_packet = false;

chunk_size = compression->decompress_bytes_needed(NULL);
chunk_size = compression_lzma->decompress_bytes_needed(NULL);

if (chunk_size > (copy_size - tmp_off)) {
chunk_size = (copy_size - tmp_off);
Expand All @@ -235,8 +241,8 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index
last_packet = true;
}

rc = compression->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, &offset,
&output, &output_size);
rc = compression_lzma->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet,
&offset, &output, &output_size);

if (rc) {
BOOT_LOG_ERR("Decompression error: %d", rc);
Expand Down Expand Up @@ -282,8 +288,41 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index
offset_zero_check = 0;
}

/* Copy data to secondary buffer for calculating hash */
if (output_size > 0) {
bootutil_sha_update(&sha_ctx, output, output_size);
if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) {
/* Run this through the ARM thumb filter */
uint32_t offset_arm_thumb = 0;
uint8_t *output_arm_thumb = NULL;
uint32_t output_size_arm_thumb = 0;

rc = compression_arm_thumb->decompress(NULL, output, output_size, last_packet,
&offset_arm_thumb, &output_arm_thumb,
&output_size_arm_thumb);

if (rc) {
BOOT_LOG_ERR("Decompression error: %d", rc);
rc = BOOT_EBADSTATUS;

goto finish;
} else if (offset != offset_arm_thumb) {
BOOT_LOG_ERR("Decompression expected offset mismatch: %d vs %d", offset,
offset_arm_thumb);
rc = BOOT_EBADSTATUS;

goto finish;
} else if (output_size != output_size_arm_thumb) {
BOOT_LOG_ERR("Decompression expected output_size mismatch: %d vs %d",
output_size, output_size_arm_thumb);
rc = BOOT_EBADSTATUS;

goto finish;
}

bootutil_sha_update(&sha_ctx, output_arm_thumb, output_size_arm_thumb);
} else {
bootutil_sha_update(&sha_ctx, output, output_size);
}
}

tmp_off += offset;
Expand All @@ -302,7 +341,8 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index

finish:
/* Clean up decompression system */
(void)compression->deinit(NULL);
(void)compression_lzma->deinit(NULL);
(void)compression_arm_thumb->deinit(NULL);

finish_without_clean:
bootutil_sha_drop(&sha_ctx);
Expand Down Expand Up @@ -813,7 +853,8 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl
uint32_t unprotected_tlv_size = 0;
uint32_t tlv_write_size = 0;
uint32_t decompressed_image_size;
struct nrf_compress_implementation *compression = NULL;
struct nrf_compress_implementation *compression_lzma = NULL;
struct nrf_compress_implementation *compression_arm_thumb = NULL;
struct image_header *hdr;
TARGET_STATIC uint8_t decomp_buf[CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE] __attribute__((aligned(4)));
TARGET_STATIC struct image_header modified_hdr;
Expand All @@ -835,18 +876,23 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl
goto finish;
}

compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA);
compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA);
compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB);

if (compression == NULL || compression->init == NULL || compression->deinit == NULL ||
compression->decompress_bytes_needed == NULL || compression->decompress == NULL) {
if (compression_lzma == NULL || compression_lzma->init == NULL ||
compression_lzma->deinit == NULL || compression_lzma->decompress_bytes_needed == NULL ||
compression_lzma->decompress == NULL || compression_arm_thumb == NULL ||
compression_arm_thumb->init == NULL || compression_arm_thumb->deinit == NULL ||
compression_arm_thumb->decompress_bytes_needed == NULL ||
compression_arm_thumb->decompress == NULL) {
/* Compression library missing or missing required function pointer */
BOOT_LOG_ERR("Decompression library fatal error");
rc = BOOT_EBADSTATUS;

goto finish;
}

rc = compression->init(NULL);
rc = compression_lzma->init(NULL);

if (rc) {
BOOT_LOG_ERR("Decompression library fatal error");
Expand Down Expand Up @@ -933,7 +979,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl
uint8_t *output = NULL;
bool last_packet = false;

chunk_size = compression->decompress_bytes_needed(NULL);
chunk_size = compression_lzma->decompress_bytes_needed(NULL);

if (chunk_size > (copy_size - tmp_off)) {
chunk_size = (copy_size - tmp_off);
Expand All @@ -943,7 +989,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl
last_packet = true;
}

rc = compression->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, &offset,
rc = compression_lzma->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, &offset,
&output, &output_size);

if (rc) {
Expand All @@ -969,6 +1015,46 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl

/* Write data out from secondary buffer when it is full */
if (decomp_buf_size == sizeof(decomp_buf)) {
if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) {
/* Run this through the ARM thumb filter */
uint32_t offset_arm_thumb = 0;
uint32_t output_size_arm_thumb = 0;
uint32_t processed_size = 0;
uint8_t *output_arm_thumb = NULL;

while (processed_size < sizeof(decomp_buf)) {
uint32_t current_size = sizeof(decomp_buf);
bool arm_thumb_last_packet = false;

if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) {
current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE;
}

if (last_packet && (processed_size + current_size) ==
sizeof(decomp_buf)) {
arm_thumb_last_packet = true;
}

rc = compression_arm_thumb->decompress(NULL,
&decomp_buf[processed_size],
current_size,
arm_thumb_last_packet,
&offset_arm_thumb,
&output_arm_thumb,
&output_size_arm_thumb);

if (rc) {
BOOT_LOG_ERR("Decompression error: %d", rc);
rc = BOOT_EBADSTATUS;

goto finish;
}

memcpy(&decomp_buf[processed_size], output_arm_thumb, current_size);
processed_size += current_size;
}
}

rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos),
decomp_buf, sizeof(decomp_buf));

Expand All @@ -994,7 +1080,8 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl
}

/* Clean up decompression system */
(void)compression->deinit(NULL);
(void)compression_lzma->deinit(NULL);
(void)compression_arm_thumb->deinit(NULL);

if (protected_tlv_size > 0) {
rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size +
Expand Down

0 comments on commit 945338a

Please sign in to comment.