Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. |
| 3 | * |
| 4 | * SPDX-License-Identifier: Apache-2.0 |
| 5 | */ |
| 6 | |
| 7 | #include <string.h> |
| 8 | #include <stdlib.h> |
| 9 | |
| 10 | #include "mcuboot_config/mcuboot_logging.h" |
| 11 | #include "flash_map_backend/flash_map_backend.h" |
| 12 | #include "sysflash/sysflash.h" |
| 13 | #include "bootutil/bootutil.h" |
| 14 | |
Shubham Kulkarni | cd86965 | 2021-07-20 11:44:08 +0530 | [diff] [blame] | 15 | #include "esp_err.h" |
| 16 | #include "bootloader_flash.h" |
| 17 | #include "bootloader_flash_priv.h" |
| 18 | |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 19 | #define ARRAY_SIZE(arr) sizeof(arr)/sizeof(arr[0]) |
| 20 | |
| 21 | #define BOOTLOADER_START_ADDRESS 0x1000 |
| 22 | #define BOOTLOADER_SIZE CONFIG_ESP_BOOTLOADER_SIZE |
| 23 | #define APPLICATION_PRIMARY_START_ADDRESS CONFIG_ESP_APPLICATION_PRIMARY_START_ADDRESS |
| 24 | #define APPLICATION_SECONDARY_START_ADDRESS CONFIG_ESP_APPLICATION_SECONDARY_START_ADDRESS |
| 25 | #define APPLICATION_SIZE CONFIG_ESP_APPLICATION_SIZE |
| 26 | #define SCRATCH_OFFSET CONFIG_ESP_SCRATCH_OFFSET |
| 27 | #define SCRATCH_SIZE CONFIG_ESP_SCRATCH_SIZE |
| 28 | |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 29 | extern int ets_printf(const char *fmt, ...); |
| 30 | |
| 31 | static const struct flash_area bootloader = { |
| 32 | .fa_id = FLASH_AREA_BOOTLOADER, |
| 33 | .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH, |
| 34 | .fa_off = BOOTLOADER_START_ADDRESS, |
| 35 | .fa_size = BOOTLOADER_SIZE, |
| 36 | }; |
| 37 | |
| 38 | static const struct flash_area primary_img0 = { |
| 39 | .fa_id = FLASH_AREA_IMAGE_PRIMARY(0), |
| 40 | .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH, |
| 41 | .fa_off = APPLICATION_PRIMARY_START_ADDRESS, |
| 42 | .fa_size = APPLICATION_SIZE, |
| 43 | }; |
| 44 | |
| 45 | static const struct flash_area secondary_img0 = { |
| 46 | .fa_id = FLASH_AREA_IMAGE_SECONDARY(0), |
| 47 | .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH, |
| 48 | .fa_off = APPLICATION_SECONDARY_START_ADDRESS, |
| 49 | .fa_size = APPLICATION_SIZE, |
| 50 | }; |
| 51 | |
| 52 | static const struct flash_area scratch_img0 = { |
| 53 | .fa_id = FLASH_AREA_IMAGE_SCRATCH, |
| 54 | .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH, |
| 55 | .fa_off = SCRATCH_OFFSET, |
| 56 | .fa_size = SCRATCH_SIZE, |
| 57 | }; |
| 58 | |
| 59 | static const struct flash_area *s_flash_areas[] = { |
| 60 | &bootloader, |
| 61 | &primary_img0, |
| 62 | &secondary_img0, |
| 63 | &scratch_img0, |
| 64 | }; |
| 65 | |
| 66 | static const struct flash_area *prv_lookup_flash_area(uint8_t id) { |
| 67 | for (size_t i = 0; i < ARRAY_SIZE(s_flash_areas); i++) { |
| 68 | const struct flash_area *area = s_flash_areas[i]; |
| 69 | if (id == area->fa_id) { |
| 70 | return area; |
| 71 | } |
| 72 | } |
| 73 | return NULL; |
| 74 | } |
| 75 | |
| 76 | int flash_area_open(uint8_t id, const struct flash_area **area_outp) |
| 77 | { |
| 78 | MCUBOOT_LOG_DBG("%s: ID=%d", __func__, (int)id); |
| 79 | const struct flash_area *area = prv_lookup_flash_area(id); |
| 80 | *area_outp = area; |
| 81 | return area != NULL ? 0 : -1; |
| 82 | } |
| 83 | |
| 84 | void flash_area_close(const struct flash_area *area) |
| 85 | { |
| 86 | |
| 87 | } |
| 88 | |
| 89 | int flash_area_read(const struct flash_area *fa, uint32_t off, void *dst, |
| 90 | uint32_t len) |
| 91 | { |
Shubham Kulkarni | cd86965 | 2021-07-20 11:44:08 +0530 | [diff] [blame] | 92 | uint32_t internal_data = 0, read_len = 0; |
| 93 | void *read_ptr; |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 94 | if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) { |
| 95 | return -1; |
| 96 | } |
| 97 | |
| 98 | const uint32_t end_offset = off + len; |
Shubham Kulkarni | cd86965 | 2021-07-20 11:44:08 +0530 | [diff] [blame] | 99 | |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 100 | if (end_offset > fa->fa_size) { |
| 101 | MCUBOOT_LOG_ERR("%s: Out of Bounds (0x%x vs 0x%x)", __func__, end_offset, fa->fa_size); |
| 102 | return -1; |
| 103 | } |
Shubham Kulkarni | cd86965 | 2021-07-20 11:44:08 +0530 | [diff] [blame] | 104 | read_len = (len < 4) ? sizeof(uint32_t) : len; |
| 105 | read_ptr = (len < 4) ? (void *)&internal_data : dst; |
| 106 | if (bootloader_flash_read(fa->fa_off + off, read_ptr, read_len, true) != ESP_OK) { |
| 107 | MCUBOOT_LOG_ERR("%s: Flash read failed", __func__); |
| 108 | return -1; |
| 109 | } |
| 110 | if (len < 4) { |
| 111 | memcpy(dst, read_ptr, len); |
| 112 | } |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 113 | return 0; |
| 114 | } |
| 115 | |
| 116 | int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src, |
| 117 | uint32_t len) |
| 118 | { |
Shubham Kulkarni | cd86965 | 2021-07-20 11:44:08 +0530 | [diff] [blame] | 119 | uint32_t write_len = len, write_data = 0; |
| 120 | void *write_ptr = (void *)src; |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 121 | if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) { |
| 122 | return -1; |
| 123 | } |
| 124 | |
| 125 | const uint32_t end_offset = off + len; |
Shubham Kulkarni | cd86965 | 2021-07-20 11:44:08 +0530 | [diff] [blame] | 126 | |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 127 | if (end_offset > fa->fa_size) { |
| 128 | MCUBOOT_LOG_ERR("%s: Out of Bounds (0x%x vs 0x%x)", __func__, end_offset, fa->fa_size); |
| 129 | return -1; |
| 130 | } |
| 131 | |
Shubham Kulkarni | cd86965 | 2021-07-20 11:44:08 +0530 | [diff] [blame] | 132 | const uint32_t start_addr = fa->fa_off + off; |
| 133 | MCUBOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len); |
| 134 | if (len < 4) { |
| 135 | flash_area_read(fa, start_addr, &write_data, sizeof(uint32_t)); |
| 136 | memcpy(&write_data, src, len); |
| 137 | write_ptr = (void *)&write_data; |
| 138 | write_len = sizeof(uint32_t); |
| 139 | } |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 140 | |
Shubham Kulkarni | cd86965 | 2021-07-20 11:44:08 +0530 | [diff] [blame] | 141 | if (bootloader_flash_write(start_addr, write_ptr, write_len, false) != ESP_OK) { |
| 142 | MCUBOOT_LOG_ERR("%s: Flash write failed", __func__); |
| 143 | return -1; |
| 144 | } |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 145 | #if VALIDATE_PROGRAM_OP |
| 146 | if (memcmp((void *)addr, src, len) != 0) { |
| 147 | MCUBOOT_LOG_ERR("%s: Program Failed", __func__); |
| 148 | assert(0); |
| 149 | } |
| 150 | #endif |
| 151 | |
| 152 | return 0; |
| 153 | } |
| 154 | |
| 155 | int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len) |
| 156 | { |
| 157 | if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) { |
| 158 | return -1; |
| 159 | } |
| 160 | |
| 161 | if ((len % FLASH_SECTOR_SIZE) != 0 || (off % FLASH_SECTOR_SIZE) != 0) { |
| 162 | MCUBOOT_LOG_ERR("%s: Not aligned on sector Offset: 0x%x Length: 0x%x", __func__, |
| 163 | (int)off, (int)len); |
| 164 | return -1; |
| 165 | } |
| 166 | |
| 167 | const uint32_t start_addr = fa->fa_off + off; |
| 168 | MCUBOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len); |
| 169 | |
Shubham Kulkarni | cd86965 | 2021-07-20 11:44:08 +0530 | [diff] [blame] | 170 | if (bootloader_flash_erase_range(start_addr, len) != ESP_OK) { |
| 171 | MCUBOOT_LOG_ERR("%s: Flash erase failed", __func__); |
| 172 | return -1; |
| 173 | } |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 174 | #if VALIDATE_PROGRAM_OP |
| 175 | for (size_t i = 0; i < len; i++) { |
| 176 | uint8_t *val = (void *)(start_addr + i); |
| 177 | if (*val != 0xff) { |
| 178 | MCUBOOT_LOG_ERR("%s: Erase at 0x%x Failed", __func__, (int)val); |
| 179 | assert(0); |
| 180 | } |
| 181 | } |
| 182 | #endif |
| 183 | |
| 184 | return 0; |
| 185 | } |
| 186 | |
| 187 | size_t flash_area_align(const struct flash_area *area) |
| 188 | { |
| 189 | return 4; |
| 190 | } |
| 191 | |
| 192 | uint8_t flash_area_erased_val(const struct flash_area *area) |
| 193 | { |
| 194 | return 0xff; |
| 195 | } |
| 196 | |
| 197 | int flash_area_get_sectors(int fa_id, uint32_t *count, |
| 198 | struct flash_sector *sectors) |
| 199 | { |
| 200 | const struct flash_area *fa = prv_lookup_flash_area(fa_id); |
| 201 | if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) { |
| 202 | return -1; |
| 203 | } |
| 204 | |
| 205 | const size_t sector_size = FLASH_SECTOR_SIZE; |
| 206 | uint32_t total_count = 0; |
| 207 | for (size_t off = 0; off < fa->fa_size; off += sector_size) { |
| 208 | // Note: Offset here is relative to flash area, not device |
| 209 | sectors[total_count].fs_off = off; |
| 210 | sectors[total_count].fs_size = sector_size; |
| 211 | total_count++; |
| 212 | } |
| 213 | |
| 214 | *count = total_count; |
| 215 | return 0; |
| 216 | } |
| 217 | |
| 218 | int flash_area_id_from_multi_image_slot(int image_index, int slot) |
| 219 | { |
| 220 | MCUBOOT_LOG_DBG("%s", __func__); |
| 221 | switch (slot) { |
| 222 | case 0: |
| 223 | return FLASH_AREA_IMAGE_PRIMARY(image_index); |
| 224 | case 1: |
| 225 | return FLASH_AREA_IMAGE_SECONDARY(image_index); |
| 226 | } |
| 227 | |
| 228 | MCUBOOT_LOG_ERR("Unexpected Request: image_index=%d, slot=%d", image_index, slot); |
| 229 | return -1; /* flash_area_open will fail on that */ |
| 230 | } |
| 231 | |
| 232 | int flash_area_id_from_image_slot(int slot) |
| 233 | { |
Almir Okato | d532029 | 2021-06-18 02:00:40 -0300 | [diff] [blame^] | 234 | return flash_area_id_from_multi_image_slot(0, slot); |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 235 | } |
| 236 | |
| 237 | int flash_area_to_sectors(int idx, int *cnt, struct flash_area *fa) |
| 238 | { |
Almir Okato | d532029 | 2021-06-18 02:00:40 -0300 | [diff] [blame^] | 239 | return -1; |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 240 | } |
| 241 | |
| 242 | void mcuboot_assert_handler(const char *file, int line, const char *func) |
| 243 | { |
| 244 | ets_printf("assertion failed: file \"%s\", line %d, func: %s\n", file, line, func); |
| 245 | abort(); |
| 246 | } |