2929#define EXPECTED_SIG_TLV IMAGE_TLV_ED25519
3030#endif
3131
32+ #define DECOMP_BUF_SIZE CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE
33+ #if defined(CONFIG_NRF_COMPRESS_ARM_THUMB )
34+ #define DECOMP_BUF_EXTRA_SIZE 2
35+ #else
36+ #define DECOMP_BUF_EXTRA_SIZE 0
37+ #endif
38+ #define DECOMP_BUF_ALLOC_SIZE (DECOMP_BUF_SIZE + DECOMP_BUF_EXTRA_SIZE)
39+
3240/* Number of times that consumed data by decompression system can be 0 in a row before aborting */
3341#define OFFSET_ZERO_CHECK_TIMES 3
3442
@@ -317,11 +325,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index
317325 BOOT_LOG_ERR ("Decompression error: %d" , rc );
318326 rc = BOOT_EBADSTATUS ;
319327 goto finish ;
320- } else if (current_size != offset_arm_thumb ) {
321- BOOT_LOG_ERR ("Decompression expected offset mismatch: %d vs %d" ,
322- current_size , offset_arm_thumb );
323- rc = BOOT_EBADSTATUS ;
324- goto finish ;
325328 }
326329
327330 bootutil_sha_update (& sha_ctx , output_arm_thumb , output_size_arm_thumb );
@@ -863,7 +866,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl
863866 struct nrf_compress_implementation * compression_lzma = NULL ;
864867 struct nrf_compress_implementation * compression_arm_thumb = NULL ;
865868 struct image_header * hdr ;
866- TARGET_STATIC uint8_t decomp_buf [CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE ] __attribute__((aligned (4 )));
869+ TARGET_STATIC uint8_t decomp_buf [DECOMP_BUF_ALLOC_SIZE ] __attribute__((aligned (4 )));
867870 TARGET_STATIC struct image_header modified_hdr ;
868871
869872 hdr = boot_img_hdr (state , BOOT_SECONDARY_SLOT );
@@ -950,6 +953,10 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl
950953 while (pos < hdr -> ih_img_size ) {
951954 uint32_t copy_size = hdr -> ih_img_size - pos ;
952955 uint32_t tmp_off = 0 ;
956+ #if defined(CONFIG_NRF_COMPRESS_ARM_THUMB )
957+ uint8_t excess_data_buffer [DECOMP_BUF_EXTRA_SIZE ];
958+ bool excess_data_buffer_full = false;
959+ #endif
953960
954961 if (copy_size > buf_size ) {
955962 copy_size = buf_size ;
@@ -985,8 +992,8 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl
985992 last_packet = true;
986993 }
987994
988- rc = compression_lzma -> decompress (NULL , & buf [tmp_off ], chunk_size , last_packet , & offset ,
989- & output , & output_size );
995+ rc = compression_lzma -> decompress (NULL , & buf [tmp_off ], chunk_size , last_packet ,
996+ & offset , & output , & output_size );
990997
991998 if (rc ) {
992999 BOOT_LOG_ERR ("Decompression error: %d" , rc );
@@ -996,42 +1003,55 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl
9961003
9971004 /* Copy data to secondary buffer for writing out */
9981005 while (output_size > 0 ) {
999- uint32_t data_size = (sizeof ( decomp_buf ) - decomp_buf_size );
1006+ uint32_t data_size = (DECOMP_BUF_SIZE - decomp_buf_size );
10001007
10011008 if (data_size > output_size ) {
10021009 data_size = output_size ;
10031010 }
10041011
1005- memcpy (& decomp_buf [decomp_buf_size ], & output [compression_buffer_pos ], data_size );
1012+ #if defined(CONFIG_NRF_COMPRESS_ARM_THUMB )
1013+ if (hdr -> ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT ) {
1014+ memcpy (& decomp_buf [decomp_buf_size + DECOMP_BUF_EXTRA_SIZE ],
1015+ & output [compression_buffer_pos ], data_size );
1016+ } else
1017+ #endif
1018+ {
1019+ memcpy (& decomp_buf [decomp_buf_size ], & output [compression_buffer_pos ],
1020+ data_size );
1021+ }
1022+
10061023 compression_buffer_pos += data_size ;
10071024
10081025 decomp_buf_size += data_size ;
10091026 output_size -= data_size ;
10101027
10111028 /* Write data out from secondary buffer when it is full */
1012- if (decomp_buf_size == sizeof (decomp_buf )) {
1029+ if (decomp_buf_size == DECOMP_BUF_SIZE ) {
1030+ #if defined(CONFIG_NRF_COMPRESS_ARM_THUMB )
10131031 if (hdr -> ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT ) {
1014- /* Run this through the ARM thumb filter */
1015- uint32_t offset_arm_thumb = 0 ;
1016- uint32_t output_size_arm_thumb = 0 ;
1032+ uint32_t filter_writeback_pos = 0 ;
10171033 uint32_t processed_size = 0 ;
1018- uint8_t * output_arm_thumb = NULL ;
10191034
1020- while (processed_size < sizeof (decomp_buf )) {
1021- uint32_t current_size = sizeof (decomp_buf );
1035+ /* Run this through the ARM thumb filter */
1036+ while (processed_size < DECOMP_BUF_SIZE ) {
1037+ uint32_t offset_arm_thumb = 0 ;
1038+ uint32_t output_size_arm_thumb = 0 ;
1039+ uint8_t * output_arm_thumb = NULL ;
1040+ uint32_t current_size = DECOMP_BUF_SIZE ;
10221041 bool arm_thumb_last_packet = false;
10231042
10241043 if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE ) {
10251044 current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE ;
10261045 }
10271046
1028- if (last_packet && (processed_size + current_size ) ==
1029- sizeof ( decomp_buf ) ) {
1047+ if (last_packet && (processed_size + current_size ) == DECOMP_BUF_SIZE
1048+ && output_size == 0 ) {
10301049 arm_thumb_last_packet = true;
10311050 }
10321051
10331052 rc = compression_arm_thumb -> decompress (NULL ,
1034- & decomp_buf [processed_size ],
1053+ & decomp_buf [processed_size +
1054+ DECOMP_BUF_EXTRA_SIZE ],
10351055 current_size ,
10361056 arm_thumb_last_packet ,
10371057 & offset_arm_thumb ,
@@ -1044,25 +1064,70 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl
10441064 goto finish ;
10451065 }
10461066
1047- memcpy (& decomp_buf [processed_size ], output_arm_thumb , current_size );
1067+ memcpy (& decomp_buf [filter_writeback_pos ], output_arm_thumb ,
1068+ output_size_arm_thumb );
1069+ filter_writeback_pos += output_size_arm_thumb ;
10481070 processed_size += current_size ;
10491071 }
1050- }
10511072
1052- rc = flash_area_write (fap_dst , (off_dst + hdr -> ih_hdr_size + write_pos ),
1053- decomp_buf , sizeof (decomp_buf ));
1073+ if (excess_data_buffer_full == true)
1074+ {
1075+ /* Restore extra data removed from previous iteration to the write
1076+ * buffer
1077+ */
1078+ memmove (& decomp_buf [DECOMP_BUF_EXTRA_SIZE ], decomp_buf ,
1079+ filter_writeback_pos );
1080+ memcpy (decomp_buf , excess_data_buffer , DECOMP_BUF_EXTRA_SIZE );
1081+ excess_data_buffer_full = false;
1082+ filter_writeback_pos += DECOMP_BUF_EXTRA_SIZE ;
1083+ }
10541084
1055- if (rc != 0 ) {
1056- BOOT_LOG_ERR (
1057- "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d" ,
1058- (off_dst + hdr -> ih_hdr_size + write_pos ), sizeof (decomp_buf ),
1059- fap_dst -> fa_id , rc );
1060- rc = BOOT_EFLASH ;
1061- goto finish ;
1062- }
1085+ if ((filter_writeback_pos % sizeof (uint32_t )) != 0 )
1086+ {
1087+ /* Since there are an extra 2 bytes here, remove them and stash for
1088+ * later usage to prevent flash write issues with non-word boundary
1089+ * writes
1090+ */
1091+ memcpy (excess_data_buffer , & decomp_buf [filter_writeback_pos -
1092+ DECOMP_BUF_EXTRA_SIZE ],
1093+ DECOMP_BUF_EXTRA_SIZE );
1094+ excess_data_buffer_full = true;
1095+ filter_writeback_pos -= DECOMP_BUF_EXTRA_SIZE ;
1096+ }
1097+
1098+ rc = flash_area_write (fap_dst , (off_dst + hdr -> ih_hdr_size + write_pos ),
1099+ decomp_buf , filter_writeback_pos );
1100+
1101+ if (rc != 0 ) {
1102+ BOOT_LOG_ERR (
1103+ "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d" ,
1104+ (off_dst + hdr -> ih_hdr_size + write_pos ), DECOMP_BUF_SIZE ,
1105+ fap_dst -> fa_id , rc );
1106+ rc = BOOT_EFLASH ;
1107+ goto finish ;
1108+ }
1109+
1110+ write_pos += filter_writeback_pos ;
1111+ decomp_buf_size = 0 ;
1112+ filter_writeback_pos = 0 ;
1113+ } else
1114+ #endif
1115+ {
1116+ rc = flash_area_write (fap_dst , (off_dst + hdr -> ih_hdr_size + write_pos ),
1117+ decomp_buf , DECOMP_BUF_SIZE );
1118+
1119+ if (rc != 0 ) {
1120+ BOOT_LOG_ERR (
1121+ "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d" ,
1122+ (off_dst + hdr -> ih_hdr_size + write_pos ), DECOMP_BUF_SIZE ,
1123+ fap_dst -> fa_id , rc );
1124+ rc = BOOT_EFLASH ;
1125+ goto finish ;
1126+ }
10631127
1064- write_pos += sizeof (decomp_buf );
1065- decomp_buf_size = 0 ;
1128+ write_pos += DECOMP_BUF_SIZE ;
1129+ decomp_buf_size = 0 ;
1130+ }
10661131 }
10671132 }
10681133
@@ -1072,6 +1137,27 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl
10721137 pos += copy_size ;
10731138 }
10741139
1140+ #if defined(CONFIG_NRF_COMPRESS_ARM_THUMB )
1141+ if (hdr -> ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT && decomp_buf_size > 0 ) {
1142+ /* Extra data that has not been written out that needs ARM thumb filter applied */
1143+ uint32_t offset_arm_thumb = 0 ;
1144+ uint32_t output_size_arm_thumb = 0 ;
1145+ uint8_t * output_arm_thumb = NULL ;
1146+
1147+ rc = compression_arm_thumb -> decompress (NULL , & decomp_buf [DECOMP_BUF_EXTRA_SIZE ],
1148+ decomp_buf_size , true, & offset_arm_thumb ,
1149+ & output_arm_thumb , & output_size_arm_thumb );
1150+
1151+ if (rc ) {
1152+ BOOT_LOG_ERR ("Decompression error: %d" , rc );
1153+ rc = BOOT_EBADSTATUS ;
1154+ goto finish ;
1155+ }
1156+
1157+ memcpy (decomp_buf , output_arm_thumb , output_size_arm_thumb );
1158+ }
1159+ #endif
1160+
10751161 /* Clean up decompression system */
10761162 (void )compression_lzma -> deinit (NULL );
10771163 (void )compression_arm_thumb -> deinit (NULL );
0 commit comments