|
5 | 5 | * Copyright (c) 2016-2019 JUUL Labs |
6 | 6 | * Copyright (c) 2019-2023 Arm Limited |
7 | 7 | * Copyright (c) 2024-2025 Nordic Semiconductor ASA |
| 8 | + * Portions Copyright (c) 2025 Analog Devices Inc. |
8 | 9 | * |
9 | 10 | * Original license: |
10 | 11 | * |
@@ -2990,6 +2991,130 @@ boot_update_hw_rollback_protection(struct boot_loader_state *state) |
2990 | 2991 | #endif |
2991 | 2992 | } |
2992 | 2993 |
|
| 2994 | + |
| 2995 | +#if (BOOT_IMAGE_NUMBER == 1) && defined(MCUBOOT_RAM_LOAD) |
| 2996 | + |
| 2997 | +static int |
| 2998 | +read_image_info(uint32_t addr, struct image_header *hdr, |
| 2999 | + uint32_t *total_size, uint32_t *footer_size) |
| 3000 | +{ |
| 3001 | + struct image_tlv_info info; |
| 3002 | + uint32_t off; |
| 3003 | + uint32_t protect_tlv_size; |
| 3004 | + |
| 3005 | + memcpy(hdr, (unsigned char *)addr, sizeof(struct image_header)); |
| 3006 | + if (hdr->ih_magic != IMAGE_MAGIC) { |
| 3007 | + BOOT_LOG_INF("IMAGE_MAGIC not correct."); |
| 3008 | + return BOOT_EBADIMAGE; |
| 3009 | + } |
| 3010 | + |
| 3011 | + off = BOOT_TLV_OFF(hdr); |
| 3012 | + |
| 3013 | + memcpy(&info, (unsigned char *)(addr + off), sizeof(info)); |
| 3014 | + |
| 3015 | + protect_tlv_size = hdr->ih_protect_tlv_size; |
| 3016 | + if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { |
| 3017 | + if (protect_tlv_size != info.it_tlv_tot) { |
| 3018 | + return BOOT_EBADIMAGE; |
| 3019 | + } |
| 3020 | + |
| 3021 | + memcpy(&info, (unsigned char *)(addr + off + info.it_tlv_tot), sizeof(info)); |
| 3022 | + } else if (protect_tlv_size != 0) { |
| 3023 | + return BOOT_EBADIMAGE; |
| 3024 | + } |
| 3025 | + |
| 3026 | + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { |
| 3027 | + return BOOT_EBADIMAGE; |
| 3028 | + } |
| 3029 | + |
| 3030 | + *footer_size = protect_tlv_size + info.it_tlv_tot; |
| 3031 | + *total_size = off + *footer_size; |
| 3032 | + |
| 3033 | + return 0; |
| 3034 | +} |
| 3035 | + |
| 3036 | +/** |
| 3037 | + * Check the main image and find sub images, then copy them to the target addr. |
| 3038 | + * Set boot image address with the first image that found in the list. |
| 3039 | + * |
| 3040 | + * ------------------------- |
| 3041 | + * | Header | |
| 3042 | + * ------------------------- |
| 3043 | + * | SubImage (optional) | |
| 3044 | + * | (Header+Data+Footer) | |
| 3045 | + * ------------------------- |
| 3046 | + * | SubImage (optional) | |
| 3047 | + * | (Header+Data+Footer) | |
| 3048 | + * ------------------------- |
| 3049 | + * | ..... | |
| 3050 | + * ------------------------- |
| 3051 | + * | Footer | |
| 3052 | + * ------------------------- |
| 3053 | + * |
| 3054 | + * @param addr Image start address |
| 3055 | + * @param rsp On success, indicates how booting should occur. |
| 3056 | + * |
| 3057 | + * @return 0 on success; nonzero on failure. |
| 3058 | + */ |
| 3059 | +static int |
| 3060 | +process_sub_images(uint32_t addr, struct boot_rsp *rsp) |
| 3061 | +{ |
| 3062 | + int rc = 0; |
| 3063 | + bool first_subimage = true; |
| 3064 | + uint32_t main_image_size; |
| 3065 | + struct image_header hdr; |
| 3066 | + uint32_t img_total_size; |
| 3067 | + uint32_t img_footer_size; |
| 3068 | + |
| 3069 | + /* read main image info */ |
| 3070 | + rc = read_image_info(addr, &hdr, &img_total_size, &img_footer_size); |
| 3071 | + if (rc != 0) { |
| 3072 | + /* No valid image header, main image format not correct. */ |
| 3073 | + return rc; |
| 3074 | + } |
| 3075 | + |
| 3076 | + /* Set main image size */ |
| 3077 | + main_image_size = img_total_size; |
| 3078 | + /* Decrease image header size and footer size */ |
| 3079 | + main_image_size -= (hdr.ih_hdr_size + img_footer_size); |
| 3080 | + |
| 3081 | + /* Pass image header */ |
| 3082 | + addr += hdr.ih_hdr_size; |
| 3083 | + |
| 3084 | + while (main_image_size) { |
| 3085 | + /* read sub image info */ |
| 3086 | + rc = read_image_info(addr, &hdr, &img_total_size, &img_footer_size); |
| 3087 | + if (rc != 0) { |
| 3088 | + /* No valid sub-image header, so it migth be single image return 0 */ |
| 3089 | + rc = 0; |
| 3090 | + break; |
| 3091 | + } |
| 3092 | + |
| 3093 | + /* copy image to target addr */ |
| 3094 | + if (hdr.ih_flags & IMAGE_F_RAM_LOAD) { |
| 3095 | + /* |
| 3096 | + * For heterogenous system that have multi core on same IC. |
| 3097 | + * Assuming main core that execute MCUBoot able to access other cores ITCM/DTCM |
| 3098 | + */ |
| 3099 | + memcpy((unsigned char *)(hdr.ih_load_addr), (unsigned char *)addr, img_total_size); |
| 3100 | + BOOT_LOG_INF("Copying image from 0x%x to 0x%x is succeeded.", addr, hdr.ih_load_addr); |
| 3101 | + } |
| 3102 | + |
| 3103 | + /* Execute first sub image */ |
| 3104 | + if ((first_subimage) && !(hdr.ih_flags & IMAGE_F_NON_BOOTABLE)) { |
| 3105 | + first_subimage = false; |
| 3106 | + rsp->br_hdr = (struct image_header *)hdr.ih_load_addr; |
| 3107 | + } |
| 3108 | + |
| 3109 | + /* go next image */ |
| 3110 | + main_image_size -= img_total_size; |
| 3111 | + addr += img_total_size; |
| 3112 | + } |
| 3113 | + |
| 3114 | + return rc; |
| 3115 | +} |
| 3116 | +#endif // #if (BOOT_IMAGE_NUMBER == 1) && defined(MCUBOOT_RAM_LOAD) |
| 3117 | + |
2993 | 3118 | fih_ret |
2994 | 3119 | context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) |
2995 | 3120 | { |
@@ -3055,6 +3180,10 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) |
3055 | 3180 |
|
3056 | 3181 | fill_rsp(state, rsp); |
3057 | 3182 |
|
| 3183 | +#if (BOOT_IMAGE_NUMBER == 1) && defined(MCUBOOT_RAM_LOAD) |
| 3184 | + (void) process_sub_images(rsp->br_hdr->ih_load_addr, rsp); |
| 3185 | +#endif |
| 3186 | + |
3058 | 3187 | close: |
3059 | 3188 | boot_close_all_flash_areas(state); |
3060 | 3189 |
|
|
0 commit comments