blob: be90a8e1dd83a352eb59440deee94bee85097fc5 [file] [log] [blame]
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +02001/*
2 * Copyright (c) 2018 Nordic Semiconductor ASA
3 * Copyright (c) 2015 Runtime Inc
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
Gerard Marull-Paretas34dd9e72022-05-09 12:13:12 +02008#include <zephyr/kernel.h>
Gerard Marull-Paretas3cd2cec2022-05-09 12:10:05 +02009#include <zephyr/devicetree.h>
10#include <zephyr/drivers/flash.h>
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +020011
12#include "target.h"
13
14#include <flash_map_backend/flash_map_backend.h>
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +020015#include <sysflash/sysflash.h>
16
17#include "bootutil/bootutil_log.h"
18
Carlos Falgueras GarcĂ­aa4b4b0f2021-06-22 10:00:22 +020019BOOT_LOG_MODULE_DECLARE(mcuboot);
Emanuele Di Santo9f1933d2018-11-20 10:59:59 +010020
Gerard Marull-Paretasaa041a22022-03-25 12:22:29 +010021#if (!defined(CONFIG_XTENSA) && DT_HAS_CHOSEN(zephyr_flash_controller))
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +020022#define FLASH_DEVICE_ID SOC_FLASH_0_ID
Rajavardhan Gundi73bb71b2019-01-28 15:07:04 +053023#define FLASH_DEVICE_BASE CONFIG_FLASH_BASE_ADDRESS
Kumar Gala8eadf8c2022-07-27 09:15:46 -050024#define FLASH_DEVICE_NODE DT_CHOSEN(zephyr_flash_controller)
Marek Matej67693442023-01-23 17:54:36 +010025
Georgij Cernysiov4030aac2022-09-08 18:11:51 +020026#elif (defined(CONFIG_XTENSA) && DT_NODE_EXISTS(DT_INST(0, jedec_spi_nor)))
Rajavardhan Gundi40c28e32018-12-09 13:32:01 +053027#define FLASH_DEVICE_ID SPI_FLASH_0_ID
Rajavardhan Gundi73bb71b2019-01-28 15:07:04 +053028#define FLASH_DEVICE_BASE 0
Kumar Gala8eadf8c2022-07-27 09:15:46 -050029#define FLASH_DEVICE_NODE DT_INST(0, jedec_spi_nor)
Marek Matej67693442023-01-23 17:54:36 +010030
31#elif defined(CONFIG_SOC_FAMILY_ESP32)
32
33#define FLASH_DEVICE_ID SPI_FLASH_0_ID
34#define FLASH_DEVICE_BASE 0
35#define FLASH_DEVICE_NODE DT_CHOSEN(zephyr_flash_controller)
36
Rajavardhan Gundi40c28e32018-12-09 13:32:01 +053037#else
38#error "FLASH_DEVICE_ID could not be determined"
39#endif
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +020040
Kumar Gala8eadf8c2022-07-27 09:15:46 -050041static const struct device *flash_dev = DEVICE_DT_GET(FLASH_DEVICE_NODE);
Emanuele Di Santo205c8c62018-07-20 11:42:31 +020042
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +020043int flash_device_base(uint8_t fd_id, uintptr_t *ret)
44{
45 if (fd_id != FLASH_DEVICE_ID) {
46 BOOT_LOG_ERR("invalid flash ID %d; expected %d",
47 fd_id, FLASH_DEVICE_ID);
48 return -EINVAL;
49 }
50 *ret = FLASH_DEVICE_BASE;
51 return 0;
52}
53
54/*
Andrzej Puzdrowski419a4752019-01-23 16:31:19 +010055 * This depends on the mappings defined in sysflash.h.
David Vincze2d736ad2019-02-18 11:50:22 +010056 * MCUBoot uses continuous numbering for the primary slot, the secondary slot,
57 * and the scratch while zephyr might number it differently.
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +020058 */
Fabio Utzigb0f04732019-07-31 09:49:19 -030059int flash_area_id_from_multi_image_slot(int image_index, int slot)
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +020060{
Fabio Utzigb0f04732019-07-31 09:49:19 -030061 switch (slot) {
62 case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index);
Andrzej Puzdrowskifdff3e12020-09-15 08:23:25 +020063#if !defined(CONFIG_SINGLE_APPLICATION_SLOT)
Fabio Utzigb0f04732019-07-31 09:49:19 -030064 case 1: return FLASH_AREA_IMAGE_SECONDARY(image_index);
Fabio Utzigc58842e2019-11-28 10:30:01 -030065#endif
Andrzej Puzdrowskic49d7c92021-05-13 12:52:34 +020066#if defined(CONFIG_BOOT_SWAP_USING_SCRATCH)
67 case 2: return FLASH_AREA_IMAGE_SCRATCH;
Dominik Ermel8101c0c2020-05-19 13:01:16 +000068#endif
Andrzej Puzdrowski419a4752019-01-23 16:31:19 +010069 }
70
71 return -EINVAL; /* flash_area_open will fail on that */
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +020072}
Emanuele Di Santo205c8c62018-07-20 11:42:31 +020073
Fabio Utzigb0f04732019-07-31 09:49:19 -030074int flash_area_id_from_image_slot(int slot)
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +010075{
Fabio Utzigb0f04732019-07-31 09:49:19 -030076 return flash_area_id_from_multi_image_slot(0, slot);
77}
78
79int flash_area_id_to_multi_image_slot(int image_index, int area_id)
80{
81 if (area_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +010082 return 0;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +010083 }
Andrzej Puzdrowskifdff3e12020-09-15 08:23:25 +020084#if !defined(CONFIG_SINGLE_APPLICATION_SLOT)
Fabio Utzigb0f04732019-07-31 09:49:19 -030085 if (area_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
David Vinczeb75c12a2019-03-22 14:58:33 +010086 return 1;
87 }
Dominik Ermel8101c0c2020-05-19 13:01:16 +000088#endif
David Vinczeb75c12a2019-03-22 14:58:33 +010089
90 BOOT_LOG_ERR("invalid flash area ID");
91 return -1;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +010092}
93
Dominik Ermel6c8932e2021-07-09 10:28:40 +000094#if defined(CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD)
95int flash_area_id_from_direct_image(int image_id)
96{
97 switch (image_id) {
98 case 0:
99 case 1:
Dominik Ermel2c539342022-08-24 14:37:11 +0000100 return FIXED_PARTITION_ID(slot0_partition);
101#if FIXED_PARTITION_EXISTS(slot1_partition)
Dominik Ermel6c8932e2021-07-09 10:28:40 +0000102 case 2:
Dominik Ermel2c539342022-08-24 14:37:11 +0000103 return FIXED_PARTITION_ID(slot1_partition);
Dominik Ermel6c8932e2021-07-09 10:28:40 +0000104#endif
Dominik Ermel2c539342022-08-24 14:37:11 +0000105#if FIXED_PARTITION_EXISTS(slot2_partition)
Dominik Ermel6c8932e2021-07-09 10:28:40 +0000106 case 3:
Dominik Ermel2c539342022-08-24 14:37:11 +0000107 return FIXED_PARTITION_ID(slot2_partition);
Dominik Ermel6c8932e2021-07-09 10:28:40 +0000108#endif
Dominik Ermel2c539342022-08-24 14:37:11 +0000109#if FIXED_PARTITION_EXISTS(slot3_partition)
Dominik Ermel6c8932e2021-07-09 10:28:40 +0000110 case 4:
Dominik Ermel2c539342022-08-24 14:37:11 +0000111 return FIXED_PARTITION_ID(slot3_partition);
Dominik Ermel6c8932e2021-07-09 10:28:40 +0000112#endif
113 }
114 return -EINVAL;
115}
116#endif
117
Emanuele Di Santo205c8c62018-07-20 11:42:31 +0200118int flash_area_sector_from_off(off_t off, struct flash_sector *sector)
119{
120 int rc;
121 struct flash_pages_info page;
122
123 rc = flash_get_page_info_by_offs(flash_dev, off, &page);
124 if (rc) {
125 return rc;
126 }
127
128 sector->fs_off = page.start_offset;
129 sector->fs_size = page.size;
130
131 return rc;
Fabio Utzig42ad4462018-08-14 08:55:23 -0300132}
133
Dominik Ermeldc1b9f02021-04-23 05:28:25 +0000134uint8_t flash_area_get_device_id(const struct flash_area *fa)
135{
136 (void)fa;
137 return FLASH_DEVICE_ID;
138}
139
Fabio Utzigcea90f92018-09-19 08:12:46 -0300140#define ERASED_VAL 0xff
Andrzej Puzdrowskic0dbdd42020-10-27 13:17:59 +0100141__weak uint8_t flash_area_erased_val(const struct flash_area *fap)
Fabio Utzig42ad4462018-08-14 08:55:23 -0300142{
143 (void)fap;
Fabio Utzigcea90f92018-09-19 08:12:46 -0300144 return ERASED_VAL;
145}
Dominik Ermel069aea42023-01-05 13:32:55 +0000146
147int flash_area_get_sector(const struct flash_area *fap, off_t off,
148 struct flash_sector *fsp)
149{
150 struct flash_pages_info fpi;
151 int rc;
152
153 if (off >= fap->fa_size) {
154 return -ERANGE;
155 }
156
157 rc = flash_get_page_info_by_offs(fap->fa_dev, fap->fa_off + off,
158 &fpi);
159
160 if (rc == 0) {
161 fsp->fs_off = fpi.start_offset - fap->fa_off;
162 fsp->fs_size = fpi.size;
163 }
164
165 return rc;
166}