/* image.h * * Functions to help with wolfBoot image header * * * Copyright (C) 2021 wolfSSL Inc. * * This file is part of wolfBoot. * * wolfBoot is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #ifndef IMAGE_H #define IMAGE_H #ifdef __cplusplus extern "C" { #endif #include #include "target.h" #include "wolfboot/wolfboot.h" #ifdef EXT_FLASH #include "hal.h" #endif #if defined(EXT_ENCRYPTED) && (defined(__WOLFBOOT) || defined(UNIT_TEST)) #include "encrypt.h" #endif int wolfBot_get_dts_size(void *dts_addr); #ifndef RAMFUNCTION #if defined(__WOLFBOOT) && defined(RAM_CODE) # if defined(ARCH_ARM) # define RAMFUNCTION __attribute__((used,section(".ramcode"),long_call)) # else # define RAMFUNCTION __attribute__((used,section(".ramcode"))) # endif #else # define RAMFUNCTION #endif #endif #ifndef WOLFBOOT_FLAGS_INVERT #define SECT_FLAG_NEW 0x0F #define SECT_FLAG_SWAPPING 0x07 #define SECT_FLAG_BACKUP 0x03 #define SECT_FLAG_UPDATED 0x00 #else #define SECT_FLAG_NEW 0x00 #define SECT_FLAG_SWAPPING 0x08 #define SECT_FLAG_BACKUP 0x0c #define SECT_FLAG_UPDATED 0x0f #endif #if defined(WOLFBOOT_ARMORED) #if !defined(ARCH_ARM) || !defined(__GNUC__) # error WOLFBOOT_ARMORED only available with arm-gcc compiler #endif #define likely(x) __builtin_expect((x),1) #define unlikely(x) __builtin_expect((x),0) struct wolfBoot_image { uint8_t *hdr; uint8_t *trailer; uint8_t *sha_hash; uint8_t *fw_base; uint32_t fw_size; uint32_t part; uint32_t hdr_ok; uint32_t canary_FEED4567; uint32_t signature_ok; uint32_t canary_FEED6789; uint32_t not_signature_ok; uint32_t canary_FEED89AB; uint32_t sha_ok; }; /** * This function sets the flag that indicates the signature is valid for the * wolfBoot_image. * * With ARMORED setup, the flag is redundant, and the information is wrapped in * between canary variables, to mitigate attacks based on memory corruptions. */ static void __attribute__((noinline)) wolfBoot_image_confirm_signature_ok( struct wolfBoot_image *img) { img->canary_FEED4567 = 0xFEED4567UL; img->signature_ok = 1UL; img->canary_FEED6789 = 0xFEED6789UL; img->not_signature_ok = ~(1UL); img->canary_FEED89AB = 0xFEED89ABUL; } /** * Final sanity check, performed just before do_boot, or before starting an * update that has been verified. * * This procedure detects if any of the previous checks has been skipped. * If any of the required flags does not match the expected value, wolfBoot * panics. */ #define PART_SANITY_CHECK(p) \ /* Redundant set of r2=0 */ \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ /* Loading hdr_ok flag, verifying */ \ asm volatile("mov r2, %0" ::"r"((p)->hdr_ok):"r2"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne ."); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne .-4"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne .-8"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne .-12"); \ /* Redundant set of r2=0 */ \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ /* Loading hdr_ok flag, verifying */ \ asm volatile("mov r2, %0" ::"r"((p)->sha_ok):"r2"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne ."); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne .-4"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne .-8"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne .-12"); \ /* Redundant set of r2=0 */ \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ /* Loading signature_ok flag, verifying */ \ asm volatile("mov r2, %0" ::"r"((p)->signature_ok):"r2"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne ."); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne .-4"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne .-8"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne .-12"); \ /* Redundant set of r2=0 */ \ asm volatile("mov r2, #0"); \ asm volatile("mov r2, #0"); \ asm volatile("mov r2, #0"); \ asm volatile("mov r2, #0"); \ asm volatile("mov r2, #0"); \ /* Loading ~(signature_ok) flag, verifying */ \ asm volatile("mov r2, %0" ::"r"((p)->not_signature_ok):"r2"); \ asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ asm volatile("bne ."); \ asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ asm volatile("bne .-4"); \ asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ asm volatile("bne .-8"); \ asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ asm volatile("bne .-12"); \ /* Redundant set of r2=0 */ \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ /* Loading canary value, verifying */ \ asm volatile("mov r2, %0" ::"r"((p)->canary_FEED6789):"r2"); \ asm volatile("mov r0, %0" ::"r"(0xFEED6789):"r0"); \ asm volatile("cmp r2, r0":::"cc"); \ asm volatile("bne ."); \ asm volatile("cmp r2, r0":::"cc"); \ asm volatile("bne .-4"); \ asm volatile("cmp r2, r0":::"cc"); \ asm volatile("bne .-8"); \ asm volatile("cmp r2, r0":::"cc"); \ asm volatile("bne .-12"); \ /* Redundant set of r2=0 */ \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ /* Loading canary value, verifying */ \ asm volatile("mov r2, %0" ::"r"((p)->canary_FEED4567):"r2"); \ asm volatile("mov r0, %0" ::"r"(0xFEED4567):"r0"); \ asm volatile("cmp r2, r0":::"cc"); \ asm volatile("bne ."); \ asm volatile("cmp r2, r0":::"cc"); \ asm volatile("bne .-4"); \ asm volatile("cmp r2, r0":::"cc"); \ asm volatile("bne .-8"); \ asm volatile("cmp r2, r0":::"cc"); \ asm volatile("bne .-12"); \ /* Redundant set of r2=0 */ \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ asm volatile("mov r2, #0":::"r2"); \ /* Loading canary value, verifying */ \ asm volatile("mov r2, %0" ::"r"((p)->canary_FEED89AB):"r2"); \ asm volatile("mov r0, %0" ::"r"(0xFEED89AB):"r0"); \ asm volatile("cmp r2, r0":::"cc"); \ asm volatile("bne ."); \ asm volatile("cmp r2, r0":::"cc"); \ asm volatile("bne .-4"); \ asm volatile("cmp r2, r0":::"cc"); \ asm volatile("bne .-8"); \ asm volatile("cmp r2, r0":::"cc"); \ asm volatile("bne .-12") /** * First part of RSA verification. Ensure that the function is called by * double checking its return value contains a valid * len (>= WOLFBOOT_SHA_DIGEST_SIZE). * */ #define RSA_VERIFY_FN(ret,fn,...) \ { \ /* Redundant set of r0=0 */ \ asm volatile("mov r0, #0":::"r0"); \ asm volatile("mov r0, #0":::"r0"); \ asm volatile("mov r0, #0":::"r0"); \ /* Call the function */ \ int tmp_ret = fn(__VA_ARGS__); \ ret = -1; \ /* Redundant set of r2=SHA_DIGEST_SIZE */ \ asm volatile("mov r2, %0" ::"r"(WOLFBOOT_SHA_DIGEST_SIZE):"r2"); \ asm volatile("mov r2, %0" ::"r"(WOLFBOOT_SHA_DIGEST_SIZE):"r2"); \ asm volatile("mov r2, %0" ::"r"(WOLFBOOT_SHA_DIGEST_SIZE):"r2"); \ /* Redundant check for fn() return value >= r2 */ \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("blt nope"); \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("blt nope"); \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("blt nope"); \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("blt nope"); \ /* Return value is set here in case of success */ \ ret = tmp_ret; \ asm volatile("nope:"); \ asm volatile("nop"); \ } /** * Second part of RSA verification. * * Compare the digest twice, then confirm via * wolfBoot_image_confirm_signature_ok(); */ #define RSA_VERIFY_HASH(img,digest) \ { \ volatile int compare_res; \ if (!img || !digest) \ asm volatile("b hnope"); \ /* Redundant set of r0=50*/ \ asm volatile("mov r0, #50":::"r0"); \ asm volatile("mov r0, #50":::"r0"); \ asm volatile("mov r0, #50":::"r0"); \ compare_res = XMEMCMP(digest, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE); \ /* Redundant checks that ensure the function actually returned 0 */ \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("bne hnope":::"cc"); \ asm volatile("cmp r0, #0"); \ asm volatile("bne hnope":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("bne hnope"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("bne hnope"); \ /* Repeat memcmp call */ \ compare_res = XMEMCMP(digest, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE); \ /* Redundant checks that ensure the function actually returned 0 */ \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("bne hnope"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("bne hnope"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("bne hnope"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("bne hnope"); \ /* Confirm that the signature is OK */ \ wolfBoot_image_confirm_signature_ok(img); \ asm volatile("hnope:"); \ asm volatile("nop"); \ } /** * ECC / Ed signature verification. * ECC and Ed verify functions set an additional value 'p_res' * which is passed as a pointer. * * Ensure that the verification function has been called, and then * set the return value accordingly. * * Double check by reading the value in p_res from memory a few times. */ #define VERIFY_FN(img,p_res,fn,...) \ /* Redundant set of r0=50*/ \ asm volatile("mov r0, #50":::"r0"); \ asm volatile("mov r0, #50":::"r0"); \ asm volatile("mov r0, #50":::"r0"); \ /* Call the verify function */ \ fn(__VA_ARGS__); \ /* Redundant checks that ensure the function actually returned 0 */ \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("bne nope"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("bne nope"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("bne nope"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("bne nope"); \ /* Check that res = 1, a few times, reading the value from memory */ \ asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne nope"); \ asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne nope"); \ asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne nope"); \ asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("bne nope"); \ /* Confirm that the signature is OK */ \ wolfBoot_image_confirm_signature_ok(img); \ asm volatile("nope:"); \ asm volatile("nop") /** * This macro is only invoked after a successful update version check, prior to * initiating the update installation. * * At this point, wolfBoot thinks that the version check has been successful. * * * The fallback flag (checked with redundancy) causes wolfBoot to skip the * redundant version checks. * * The redundant checks here ensure that the image version is read twice per * each partition, and the two return values are the same. * * * The comparison is also redundant, causing wolfBoot to panic if the update * version is not strictly greater than the current one. * */ #define VERIFY_VERSION_ALLOWED(fb_ok) \ /* Stash the registry values */ \ asm volatile("push {r4, r5, r6, r7}"); \ /* Redundant initialization with 'failure' values */ \ asm volatile("mov r0, #0":::"r0"); \ asm volatile("mov r4, #1":::"r4"); \ asm volatile("mov r5, #0":::"r5"); \ asm volatile("mov r6, #2":::"r6"); \ asm volatile("mov r7, #0":::"r7"); \ asm volatile("mov r0, #0":::"r0"); \ asm volatile("mov r4, #1":::"r4"); \ asm volatile("mov r5, #0":::"r5"); \ asm volatile("mov r6, #2":::"r6"); \ asm volatile("mov r7, #0":::"r7"); \ /* Read the fb_ok flag, jump to end_check \ * if proven fb_ok == 1 */ \ asm volatile("mov r0, %0" ::"r"(fb_ok):"r0"); \ asm volatile("cmp r0, #1":::"cc"); \ asm volatile("bne do_check"); \ asm volatile("cmp r0, #1":::"cc"); \ asm volatile("bne do_check"); \ asm volatile("cmp r0, #1":::"cc"); \ asm volatile("bne do_check"); \ asm volatile("b end_check"); \ /* Do the actual version check: */ \ asm volatile("do_check:"); \ /* Read update versions to reg r5 and r7 */ \ asm volatile("mov r0, #1":::"r0"); \ asm volatile("mov r0, #1":::"r0"); \ asm volatile("mov r0, #1":::"r0"); \ asm volatile("bl wolfBoot_get_image_version"); \ asm volatile("mov r5, r0":::"r5"); \ asm volatile("mov r5, r0":::"r5"); \ asm volatile("mov r5, r0":::"r5"); \ asm volatile("mov r0, #1":::"r0"); \ asm volatile("mov r0, #1":::"r0"); \ asm volatile("mov r0, #1":::"r0"); \ asm volatile("bl wolfBoot_get_image_version"); \ asm volatile("mov r7, r0":::"r7"); \ asm volatile("mov r7, r0":::"r7"); \ asm volatile("mov r7, r0":::"r7"); \ /* Compare r5 and r7, if not equal, something went very wrong, */ \ asm volatile("cmp r5, r7":::"cc"); \ asm volatile("bne ."); \ asm volatile("cmp r5, r7":::"cc"); \ asm volatile("bne .-4"); \ asm volatile("cmp r5, r7":::"cc"); \ asm volatile("bne .-8"); \ asm volatile("cmp r5, r7":::"cc"); \ asm volatile("bne .-12"); \ /* Read current versions to reg r4 and r6 */ \ asm volatile("mov r0, #0":::"r0"); \ asm volatile("mov r0, #0":::"r0"); \ asm volatile("mov r0, #0":::"r0"); \ asm volatile("bl wolfBoot_get_image_version"); \ asm volatile("mov r4, r0":::"r4"); \ asm volatile("mov r4, r0":::"r4"); \ asm volatile("mov r4, r0":::"r4"); \ asm volatile("mov r0, #0":::"r0"); \ asm volatile("mov r0, #0":::"r0"); \ asm volatile("mov r0, #0":::"r0"); \ asm volatile("bl wolfBoot_get_image_version"); \ asm volatile("mov r6, r0":::"r6"); \ asm volatile("mov r6, r0":::"r6"); \ asm volatile("mov r6, r0":::"r6"); \ asm volatile("cmp r4, r6":::"cc"); \ asm volatile("bne ."); \ asm volatile("cmp r4, r6":::"cc"); \ asm volatile("bne .-4"); \ asm volatile("cmp r4, r6":::"cc"); \ asm volatile("bne .-8"); \ asm volatile("cmp r4, r6":::"cc"); \ asm volatile("bne .-12"); \ asm volatile("mov r0, #0":::"r0"); \ asm volatile("mov r0, #0":::"r0"); \ asm volatile("mov r0, #0":::"r0"); \ /* Compare the two versions in registries */ \ asm volatile("cmp r4, r5":::"cc"); \ asm volatile("bge ."); \ asm volatile("cmp r6, r7":::"cc"); \ asm volatile("bge .-4"); \ asm volatile("cmp r4, r5":::"cc"); \ asm volatile("bge .-8"); \ asm volatile("cmp r6, r7":::"cc"); \ asm volatile("bge .-12"); \ asm volatile("end_check:"); \ /* Restore previously saved registry values */ \ asm volatile("pop {r4, r5, r6, r7}":::"r4", "r5", "r6", "r7") #define CONFIRM_MASK_VALID(id, mask) \ asm volatile("mov r1, %0" :: "r"(id):"r1"); \ /* id &= 0x0F */ \ asm volatile("and.w r1, r1, #15":::"r1"); \ asm volatile("mov r0, %0" :: "r"(mask):"r0"); \ asm volatile("movs r2, #1":::"r2"); \ asm volatile("lsls r2, r1":::"r2","cc"); \ asm volatile("ands r2, r0":::"r2","cc"); \ asm volatile("movs r0, #1":::"cc"); \ asm volatile("lsls r0, r1":::"r0","cc"); \ asm volatile("cmp r0, r2"); \ asm volatile("bne ."); \ asm volatile("mov r0, %0" :: "r"(mask)); \ asm volatile("movs r2, #1":::"r2"); \ asm volatile("lsls r2, r1":::"r2", "cc"); \ asm volatile("ands r2, r0":::"r2", "cc"); \ asm volatile("movs r0, #1":::"r0"); \ asm volatile("lsls r0, r1":::"r0", "cc"); \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("bne ."); \ asm volatile("mov r0, %0" :: "r"(mask):"r0"); \ asm volatile("movs r2, #1":::"r2"); \ asm volatile("lsls r2, r1":::"r2", "cc"); \ asm volatile("ands r2, r0":::"r2", "cc"); \ asm volatile("movs r0, #1":::"r0"); \ asm volatile("lsls r0, r1":::"r0", "cc"); \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("bne ."); \ #else struct wolfBoot_image { uint8_t *hdr; uint8_t *trailer; uint8_t *sha_hash; uint8_t *fw_base; uint32_t fw_size; uint8_t part; uint8_t hdr_ok : 1; uint8_t signature_ok : 1; uint8_t sha_ok : 1; uint8_t not_ext : 1; /* image is no longer external */ }; /* do not warn if this is not used */ #if !defined(__CCRX__) static void __attribute__ ((unused)) wolfBoot_image_confirm_signature_ok( struct wolfBoot_image *img) #else static void wolfBoot_image_confirm_signature_ok(struct wolfBoot_image *img) #endif { img->signature_ok = 1; } #define likely(x) (x) #define unlikely(x) (x) #define VERIFY_FN(img,p_res,fn,...) {\ int ret = fn(__VA_ARGS__); \ if ((ret == 0) && (*p_res == 1)) \ wolfBoot_image_confirm_signature_ok(img); \ } #define RSA_VERIFY_FN(ret,fn,...) \ ret = fn(__VA_ARGS__); #define RSA_VERIFY_HASH(img,digest) \ if (XMEMCMP(img->sha_hash, digest, WOLFBOOT_SHA_DIGEST_SIZE) == 0) \ wolfBoot_image_confirm_signature_ok(img); #define PART_SANITY_CHECK(p) \ if (((p)->hdr_ok != 1) || ((p)->sha_ok != 1) || ((p)->signature_ok != 1)) \ wolfBoot_panic() #define CONFIRM_MASK_VALID(id, mask) \ if ((mask & (1UL << id)) != (1UL << id)) \ wolfBoot_panic() #define VERIFY_VERSION_ALLOWED(fb_ok) do{} while(0) #endif /* Defined in image.c */ int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part); int wolfBoot_open_image_address(struct wolfBoot_image* img, uint8_t* image); int wolfBoot_verify_integrity(struct wolfBoot_image *img); int wolfBoot_verify_authenticity(struct wolfBoot_image *img); int wolfBoot_get_partition_state(uint8_t part, uint8_t *st); int wolfBoot_set_partition_state(uint8_t part, uint8_t newst); int wolfBoot_get_update_sector_flag(uint16_t sector, uint8_t *flag); int wolfBoot_set_update_sector_flag(uint16_t sector, uint8_t newflag); uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset, uint32_t* sz); /* get header type for image */ uint16_t wolfBoot_get_header(struct wolfBoot_image *img, uint16_t type, uint8_t **ptr); /* Find the key slot ID based on the SHA hash of the key. */ int keyslot_id_by_sha(const uint8_t *hint); #ifdef EXT_FLASH # ifdef PART_BOOT_EXT # define BOOT_EXT 1 # else # define BOOT_EXT 0 # endif # ifdef PART_UPDATE_EXT # define UPDATE_EXT 1 # else # define UPDATE_EXT 0 # endif # ifdef PART_SWAP_EXT # define SWAP_EXT 1 # else # define SWAP_EXT 0 # endif # define PARTN_IS_EXT(pn) \ ((pn == PART_BOOT || pn == PART_DTS_BOOT) ? BOOT_EXT: \ ((pn == PART_UPDATE || pn == PART_DTS_UPDATE) ? UPDATE_EXT : \ ((pn == PART_SWAP) ? SWAP_EXT : 0))) # define PART_IS_EXT(x) (!(x)->not_ext) && PARTN_IS_EXT(((x)->part)) #if defined(EXT_ENCRYPTED) && (defined(__WOLFBOOT) || defined(UNIT_TEST)) #define ext_flash_check_write ext_flash_encrypt_write #define ext_flash_check_read ext_flash_decrypt_read #else #define ext_flash_check_write ext_flash_write #define ext_flash_check_read ext_flash_read #endif static inline int wb_flash_erase(struct wolfBoot_image *img, uint32_t off, uint32_t size) { if (PART_IS_EXT(img)) return ext_flash_erase((uintptr_t)(img->hdr) + off, size); else return hal_flash_erase((uintptr_t)(img->hdr) + off, size); } static inline int wb_flash_write(struct wolfBoot_image *img, uint32_t off, const void *data, uint32_t size) { if (PART_IS_EXT(img)) return ext_flash_check_write((uintptr_t)(img->hdr) + off, data, size); else return hal_flash_write((uintptr_t)(img->hdr) + off, data, size); } static inline int wb_flash_write_verify_word(struct wolfBoot_image *img, uint32_t off, uint32_t word) { int ret; volatile uint32_t copy; if (PART_IS_EXT(img)) { ext_flash_check_read((uintptr_t)(img->hdr) + off, (void *)©, sizeof(uint32_t)); while (copy != word) { ret = ext_flash_check_write((uintptr_t)(img->hdr) + off, (void *)&word, sizeof(uint32_t)); if (ret < 0) return ret; ext_flash_check_read((uintptr_t)(img->hdr) + off, (void *)©, sizeof(uint32_t)); } } else { volatile uint32_t *pcopy = (volatile uint32_t*)(img->hdr + off); while(*pcopy != word) { hal_flash_write((uintptr_t)pcopy, (void *)&word, sizeof(uint32_t)); } } return 0; } #else # define PART_IS_EXT(x) (0) # define PARTN_IS_EXT(x) (0) # define wb_flash_erase(im, of, siz) \ hal_flash_erase(((uintptr_t)(((im)->hdr)) + of), siz) # define wb_flash_write(im, of, dat, siz) \ hal_flash_write(((uintptr_t)((im)->hdr)) + of, dat, siz) #endif /* EXT_FLASH */ /* -- Image Formats -- */ /* Legacy U-Boot Image */ #define UBOOT_IMG_HDR_MAGIC 0x56190527UL #define UBOOT_IMG_HDR_SZ 64 /* --- Flattened Device Tree Blob */ #include "fdt.h" #ifndef EXT_ENCRYPTED #define WOLFBOOT_MAX_SPACE (WOLFBOOT_PARTITION_SIZE - \ (TRAILER_SKIP + sizeof(uint32_t) + \ (WOLFBOOT_PARTITION_SIZE + 1 / (WOLFBOOT_SECTOR_SIZE * 8)))) #else #define WOLFBOOT_MAX_SPACE (WOLFBOOT_PARTITION_SIZE - ENCRYPT_TMP_SECRET_OFFSET) #endif #ifdef __cplusplus } #endif #endif /* !IMAGE_H */