|
22 | 22 | #include "image.h" |
23 | 23 | #include "hal.h" |
24 | 24 | #include "spi_flash.h" |
| 25 | +#include "wolfboot/wolfboot.h" |
25 | 26 |
|
26 | | -extern void do_boot(const uint32_t *app_offset); |
| 27 | +#ifdef RAM_CODE |
| 28 | +extern unsigned int _start_text; |
| 29 | +static volatile const uint32_t wolfboot_version = WOLFBOOT_VERSION; |
| 30 | +extern void (** const IV_RAM)(void); |
| 31 | +#endif |
27 | 32 |
|
28 | 33 | #define FLASHBUFFER_SIZE 256 |
29 | 34 | static int wolfBoot_copy_sector(struct wolfBoot_image *src, struct wolfBoot_image *dst, uint32_t sector) |
@@ -87,10 +92,16 @@ static int wolfBoot_update(int fallback_allowed) |
87 | 92 | /* Check the first sector to detect interrupted update */ |
88 | 93 | if ((wolfBoot_get_sector_flag(PART_UPDATE, 0, &flag) < 0) || (flag == SECT_FLAG_NEW)) |
89 | 94 | { |
| 95 | + uint8_t *update_type; |
90 | 96 | /* In case this is a new update, do the required |
91 | 97 | * checks on the firmware update |
92 | 98 | * before starting the swap |
93 | 99 | */ |
| 100 | + |
| 101 | + if (wolfBoot_find_header(update.hdr + IMAGE_HEADER_OFFSET, HDR_IMG_TYPE, &update_type) == sizeof(uint16_t)) { |
| 102 | + if ((update_type[0] != HDR_IMG_TYPE_APP) || update_type[1] != (HDR_IMG_TYPE_AUTH >> 8)) |
| 103 | + return -1; |
| 104 | + } |
94 | 105 | if (!update.hdr_ok || (wolfBoot_verify_integrity(&update) < 0) |
95 | 106 | || (wolfBoot_verify_authenticity(&update) < 0)) { |
96 | 107 | return -1; |
@@ -153,11 +164,89 @@ static int wolfBoot_update(int fallback_allowed) |
153 | 164 | return 0; |
154 | 165 | } |
155 | 166 |
|
| 167 | + |
| 168 | +#ifdef RAM_CODE |
| 169 | + |
| 170 | +static void RAMFUNCTION wolfBoot_erase_bootloader(void) |
| 171 | +{ |
| 172 | + uint32_t *start = (uint32_t *)&_start_text; |
| 173 | + uint32_t len = WOLFBOOT_PARTITION_BOOT_ADDRESS - (uint32_t)start; |
| 174 | + hal_flash_erase((uint32_t)start, len); |
| 175 | + |
| 176 | +} |
| 177 | + |
| 178 | +static void RAMFUNCTION wolfBoot_self_update(struct wolfBoot_image *src) |
| 179 | +{ |
| 180 | + uint32_t pos = 0; |
| 181 | + uint32_t src_offset = IMAGE_HEADER_SIZE; |
| 182 | + |
| 183 | + hal_flash_unlock(); |
| 184 | + wolfBoot_erase_bootloader(); |
| 185 | +#ifdef EXT_FLASH |
| 186 | + while (pos < src->fw_size) { |
| 187 | + if (PART_IS_EXT(src)) { |
| 188 | + uint8_t buffer[FLASHBUFFER_SIZE]; |
| 189 | + if (src_offset + pos < (src->fw_size + IMAGE_HEADER_SIZE + FLASHBUFFER_SIZE)) { |
| 190 | + ext_flash_read((uint32_t)(src->hdr) + src_offset + pos, (void *)buffer, FLASHBUFFER_SIZE); |
| 191 | + hal_flash_write(pos + (uint32_t)&_start_text, buffer, FLASHBUFFER_SIZE); |
| 192 | + } |
| 193 | + pos += FLASHBUFFER_SIZE; |
| 194 | + } |
| 195 | + goto lock_and_reset; |
| 196 | + } |
| 197 | +#endif |
| 198 | + while (pos < src->fw_size) { |
| 199 | + if (src_offset + pos < (src->fw_size + IMAGE_HEADER_SIZE + FLASHBUFFER_SIZE)) { |
| 200 | + uint8_t *orig = (uint8_t*)(src->hdr + src_offset + pos); |
| 201 | + hal_flash_write(pos + (uint32_t)&_start_text, orig, FLASHBUFFER_SIZE); |
| 202 | + } |
| 203 | + pos += FLASHBUFFER_SIZE; |
| 204 | + } |
| 205 | + |
| 206 | +lock_and_reset: |
| 207 | + hal_flash_lock(); |
| 208 | + arch_reboot(); |
| 209 | +} |
| 210 | + |
| 211 | +static void wolfBoot_check_self_update(void) |
| 212 | +{ |
| 213 | + uint8_t st; |
| 214 | + struct wolfBoot_image update; |
| 215 | + uint8_t *update_type; |
| 216 | + uint32_t update_version; |
| 217 | + |
| 218 | + /* Check for self update in the UPDATE partition */ |
| 219 | + if ((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0) && (st == IMG_STATE_UPDATING) && |
| 220 | + (wolfBoot_open_image(&update, PART_UPDATE) == 0) && |
| 221 | + (wolfBoot_find_header(update.hdr + IMAGE_HEADER_OFFSET, HDR_IMG_TYPE, &update_type) == sizeof(uint16_t)) && |
| 222 | + update_type[0] == HDR_IMG_TYPE_WOLFBOOT && |
| 223 | + update_type[1] == (HDR_IMG_TYPE_AUTH >> 8)) { |
| 224 | + uint32_t update_version = wolfBoot_update_firmware_version(); |
| 225 | + if (update_version <= wolfboot_version) { |
| 226 | + hal_flash_unlock(); |
| 227 | + wolfBoot_erase_partition(PART_UPDATE); |
| 228 | + hal_flash_lock(); |
| 229 | + return; |
| 230 | + } |
| 231 | + if (wolfBoot_verify_integrity(&update) < 0) |
| 232 | + return; |
| 233 | + if (wolfBoot_verify_authenticity(&update) < 0) |
| 234 | + return; |
| 235 | + wolfBoot_self_update(&update); |
| 236 | + } |
| 237 | +} |
| 238 | +#endif /* RAM_CODE for self_update */ |
| 239 | + |
156 | 240 | static void wolfBoot_start(void) |
157 | 241 | { |
158 | 242 | uint8_t st; |
159 | 243 | struct wolfBoot_image boot, update; |
160 | | - /* First, check if the BOOT partition is still in TESTING, |
| 244 | + |
| 245 | +#ifdef RAM_CODE |
| 246 | + wolfBoot_check_self_update(); |
| 247 | +#endif |
| 248 | + |
| 249 | + /* Check if the BOOT partition is still in TESTING, |
161 | 250 | * to trigger fallback. |
162 | 251 | */ |
163 | 252 | if ((wolfBoot_get_partition_state(PART_BOOT, &st) == 0) && (st == IMG_STATE_TESTING)) { |
|
0 commit comments