@@ -119,38 +119,49 @@ boot_flag_decode(uint8_t flag)
119119 return BOOT_FLAG_SET ;
120120}
121121
122- uint32_t
123- boot_slots_trailer_sz (uint8_t min_write_sz )
122+ /**
123+ * Determines if a status source table is satisfied by the specified magic
124+ * code.
125+ *
126+ * @param tbl_val A magic field from a status source table.
127+ * @param val The magic value in a trailer, encoded as a
128+ * BOOT_MAGIC_[...].
129+ *
130+ * @return 1 if the two values are compatible;
131+ * 0 otherwise.
132+ */
133+ int
134+ boot_magic_compatible_check (uint8_t tbl_val , uint8_t val )
124135{
125- return /* state for all sectors */
126- BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz +
127- #ifdef MCUBOOT_ENC_IMAGES
128- /* encryption keys */
129- BOOT_ENC_KEY_SIZE * 2 +
130- #endif
131- /* copy_done + image_ok + swap_size */
132- BOOT_MAX_ALIGN * 3 +
133- BOOT_MAGIC_SZ ;
136+ switch (tbl_val ) {
137+ case BOOT_MAGIC_ANY :
138+ return 1 ;
139+
140+ case BOOT_MAGIC_NOTGOOD :
141+ return val != BOOT_MAGIC_GOOD ;
142+
143+ default :
144+ return tbl_val == val ;
145+ }
134146}
135147
136- static uint32_t
137- boot_scratch_trailer_sz (uint8_t min_write_sz )
148+ uint32_t
149+ boot_trailer_sz (uint8_t min_write_sz )
138150{
139- /* state for one sector */
140- return BOOT_STATUS_STATE_COUNT * min_write_sz +
151+ return /* state for all sectors */
152+ BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz +
141153#ifdef MCUBOOT_ENC_IMAGES
142154 /* encryption keys */
143155 BOOT_ENC_KEY_SIZE * 2 +
144156#endif
145- /* image_ok + swap_size */
146- BOOT_MAX_ALIGN * 2 +
157+ /* swap_type + copy_done + image_ok + swap_size */
158+ BOOT_MAX_ALIGN * 4 +
147159 BOOT_MAGIC_SZ ;
148160}
149161
150162static uint32_t
151163boot_magic_off (const struct flash_area * fap )
152164{
153- assert (offsetof(struct image_trailer , magic ) == 16 );
154165 return fap -> fa_size - BOOT_MAGIC_SZ ;
155166}
156167
@@ -176,55 +187,41 @@ boot_status_off(const struct flash_area *fap)
176187
177188 elem_sz = flash_area_align (fap );
178189
179- if (fap -> fa_id == FLASH_AREA_IMAGE_SCRATCH ) {
180- off_from_end = boot_scratch_trailer_sz (elem_sz );
181- } else {
182- off_from_end = boot_slots_trailer_sz (elem_sz );
183- }
190+ off_from_end = boot_trailer_sz (elem_sz );
184191
185192 assert (off_from_end <= fap -> fa_size );
186193 return fap -> fa_size - off_from_end ;
187194}
188195
196+ uint32_t
197+ boot_swap_type_off (const struct flash_area * fap )
198+ {
199+ return fap -> fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3 ;
200+ }
201+
189202static uint32_t
190203boot_copy_done_off (const struct flash_area * fap )
191204{
192- assert (fap -> fa_id != FLASH_AREA_IMAGE_SCRATCH );
193- assert (offsetof(struct image_trailer , copy_done ) == 0 );
194205 return fap -> fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2 ;
195206}
196207
197208static uint32_t
198209boot_image_ok_off (const struct flash_area * fap )
199210{
200- assert (offsetof(struct image_trailer , image_ok ) == 8 );
201211 return fap -> fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN ;
202212}
203213
204214static uint32_t
205215boot_swap_size_off (const struct flash_area * fap )
206216{
207- /*
208- * The "swap_size" field if located just before the trailer.
209- * The scratch slot doesn't store "copy_done"...
210- */
211- if (fap -> fa_id == FLASH_AREA_IMAGE_SCRATCH ) {
212- return fap -> fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2 ;
213- }
214-
215- return fap -> fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3 ;
217+ return fap -> fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 4 ;
216218}
217219
218220#ifdef MCUBOOT_ENC_IMAGES
219221static uint32_t
220222boot_enc_key_off (const struct flash_area * fap , uint8_t slot )
221223{
222- if (fap -> fa_id == FLASH_AREA_IMAGE_SCRATCH ) {
223- return fap -> fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2 -
224- ((slot + 1 ) * BOOT_ENC_KEY_SIZE );
225- }
226-
227- return fap -> fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3 -
224+ return fap -> fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 4 -
228225 ((slot + 1 ) * BOOT_ENC_KEY_SIZE );
229226}
230227#endif
@@ -248,18 +245,26 @@ boot_read_swap_state(const struct flash_area *fap,
248245 state -> magic = boot_magic_decode (magic );
249246 }
250247
251- if (fap -> fa_id != FLASH_AREA_IMAGE_SCRATCH ) {
252- off = boot_copy_done_off (fap );
253- rc = flash_area_read_is_empty (fap , off , & state -> copy_done ,
254- sizeof state -> copy_done );
255- if (rc < 0 ) {
256- return BOOT_EFLASH ;
257- }
258- if (rc == 1 ) {
259- state -> copy_done = BOOT_FLAG_UNSET ;
260- } else {
261- state -> copy_done = boot_flag_decode (state -> copy_done );
262- }
248+ off = boot_swap_type_off (fap );
249+ rc = flash_area_read_is_empty (fap , off , & state -> swap_type ,
250+ sizeof state -> swap_type );
251+ if (rc < 0 ) {
252+ return BOOT_EFLASH ;
253+ }
254+ if (rc == 1 || state -> swap_type > BOOT_SWAP_TYPE_REVERT ) {
255+ state -> swap_type = BOOT_SWAP_TYPE_NONE ;
256+ }
257+
258+ off = boot_copy_done_off (fap );
259+ rc = flash_area_read_is_empty (fap , off , & state -> copy_done ,
260+ sizeof state -> copy_done );
261+ if (rc < 0 ) {
262+ return BOOT_EFLASH ;
263+ }
264+ if (rc == 1 ) {
265+ state -> copy_done = BOOT_FLAG_UNSET ;
266+ } else {
267+ state -> copy_done = boot_flag_decode (state -> copy_done );
263268 }
264269
265270 off = boot_image_ok_off (fap );
@@ -428,6 +433,8 @@ boot_write_magic(const struct flash_area *fap)
428433
429434 off = boot_magic_off (fap );
430435
436+ BOOT_LOG_DBG ("writing magic; fa_id=%d off=0x%x (0x%x)" ,
437+ fap -> fa_id , off , fap -> fa_off + off );
431438 rc = flash_area_write (fap , off , boot_img_magic , BOOT_MAGIC_SZ );
432439 if (rc != 0 ) {
433440 return BOOT_EFLASH ;
@@ -437,30 +444,19 @@ boot_write_magic(const struct flash_area *fap)
437444}
438445
439446static int
440- boot_write_flag (int flag , const struct flash_area * fap )
447+ boot_write_trailer_byte (const struct flash_area * fap , uint32_t off ,
448+ uint8_t val )
441449{
442- uint32_t off ;
443- int rc ;
444450 uint8_t buf [BOOT_MAX_ALIGN ];
445451 uint8_t align ;
446452 uint8_t erased_val ;
447-
448- switch (flag ) {
449- case BOOT_FLAG_COPY_DONE :
450- off = boot_copy_done_off (fap );
451- break ;
452- case BOOT_FLAG_IMAGE_OK :
453- off = boot_image_ok_off (fap );
454- break ;
455- default :
456- return BOOT_EBADARGS ;
457- }
453+ int rc ;
458454
459455 align = flash_area_align (fap );
460456 assert (align <= BOOT_MAX_ALIGN );
461457 erased_val = flash_area_erased_val (fap );
462458 memset (buf , erased_val , BOOT_MAX_ALIGN );
463- buf [0 ] = BOOT_FLAG_SET ;
459+ buf [0 ] = val ;
464460
465461 rc = flash_area_write (fap , off , buf , align );
466462 if (rc != 0 ) {
@@ -473,13 +469,39 @@ boot_write_flag(int flag, const struct flash_area *fap)
473469int
474470boot_write_copy_done (const struct flash_area * fap )
475471{
476- return boot_write_flag (BOOT_FLAG_COPY_DONE , fap );
472+ uint32_t off ;
473+
474+ off = boot_copy_done_off (fap );
475+ BOOT_LOG_DBG ("writing copy_done; fa_id=%d off=0x%x (0x%x)" ,
476+ fap -> fa_id , off , fap -> fa_off + off );
477+ return boot_write_trailer_byte (fap , off , BOOT_FLAG_SET );
477478}
478479
479480int
480481boot_write_image_ok (const struct flash_area * fap )
481482{
482- return boot_write_flag (BOOT_FLAG_IMAGE_OK , fap );
483+ uint32_t off ;
484+
485+ off = boot_image_ok_off (fap );
486+ BOOT_LOG_DBG ("writing image_ok; fa_id=%d off=0x%x (0x%x)" ,
487+ fap -> fa_id , off , fap -> fa_off + off );
488+ return boot_write_trailer_byte (fap , off , BOOT_FLAG_SET );
489+ }
490+
491+ /**
492+ * Writes the specified value to the `swap-type` field of an image trailer.
493+ * This value is persisted so that the boot loader knows what swap operation to
494+ * resume in case of an unexpected reset.
495+ */
496+ int
497+ boot_write_swap_type (const struct flash_area * fap , uint8_t swap_type )
498+ {
499+ uint32_t off ;
500+
501+ off = boot_swap_type_off (fap );
502+ BOOT_LOG_DBG ("writing swap_type; fa_id=%d off=0x%x (0x%x), swap_type=0x%x" ,
503+ fap -> fa_id , off , fap -> fa_off + off , swap_type );
504+ return boot_write_trailer_byte (fap , off , swap_type );
483505}
484506
485507int
@@ -501,6 +523,9 @@ boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size)
501523 memset (buf , erased_val , BOOT_MAX_ALIGN );
502524 memcpy (buf , (uint8_t * )& swap_size , sizeof swap_size );
503525
526+ BOOT_LOG_DBG ("writing swap_size; fa_id=%d off=0x%x (0x%x)" ,
527+ fap -> fa_id , off , fap -> fa_off + off );
528+
504529 rc = flash_area_write (fap , off , buf , align );
505530 if (rc != 0 ) {
506531 return BOOT_EFLASH ;
@@ -549,10 +574,10 @@ boot_swap_type(void)
549574 for (i = 0 ; i < BOOT_SWAP_TABLES_COUNT ; i ++ ) {
550575 table = boot_swap_tables + i ;
551576
552- if ((table -> magic_primary_slot == BOOT_MAGIC_ANY ||
553- table -> magic_primary_slot == primary_slot .magic ) &&
554- (table -> magic_secondary_slot == BOOT_MAGIC_ANY ||
555- table -> magic_secondary_slot == secondary_slot .magic ) &&
577+ if (boot_magic_compatible_check (table -> magic_primary_slot ,
578+ primary_slot .magic ) &&
579+ boot_magic_compatible_check (table -> magic_secondary_slot ,
580+ secondary_slot .magic ) &&
556581 (table -> image_ok_primary_slot == BOOT_FLAG_ANY ||
557582 table -> image_ok_primary_slot == primary_slot .image_ok ) &&
558583 (table -> image_ok_secondary_slot == BOOT_FLAG_ANY ||
@@ -591,6 +616,7 @@ boot_set_pending(int permanent)
591616{
592617 const struct flash_area * fap ;
593618 struct boot_swap_state state_secondary_slot ;
619+ uint8_t swap_type ;
594620 int rc ;
595621
596622 rc = boot_read_swap_state_by_id (FLASH_AREA_IMAGE_SECONDARY ,
@@ -616,6 +642,15 @@ boot_set_pending(int permanent)
616642 rc = boot_write_image_ok (fap );
617643 }
618644
645+ if (rc == 0 ) {
646+ if (permanent ) {
647+ swap_type = BOOT_SWAP_TYPE_PERM ;
648+ } else {
649+ swap_type = BOOT_SWAP_TYPE_TEST ;
650+ }
651+ rc = boot_write_swap_type (fap , swap_type );
652+ }
653+
619654 flash_area_close (fap );
620655 return rc ;
621656
0 commit comments