blob: 872c80d6a7145e888b996e8d39bacce9fa474a29 [file] [log] [blame]
David Brown5153bd62017-01-06 11:16:53 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#include <zephyr.h>
David Brown5153bd62017-01-06 11:16:53 -070021#include <flash.h>
22
Ricardo Salveti3a2c1242017-01-19 10:22:35 -020023#include MCUBOOT_TARGET_CONFIG
24
David Brown5153bd62017-01-06 11:16:53 -070025#include <flash_map/flash_map.h>
26#include <hal/hal_flash.h>
27#include <sysflash/sysflash.h>
28
Marti Bolivar4a97b4c2017-01-31 18:20:02 -050029#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
30#include "bootutil/bootutil_log.h"
Ricardo Salveti7cf3d9e2017-01-18 16:38:22 -020031
David Brown5153bd62017-01-06 11:16:53 -070032extern struct device *boot_flash_device;
33
34/*
35 * The flash area describes essentially the partition table of the
36 * flash. In this case, it starts with FLASH_AREA_IMAGE_0.
37 */
38static const struct flash_area part_map[] = {
39 {
40 .fa_id = FLASH_AREA_IMAGE_0,
Ricardo Salveti3a2c1242017-01-19 10:22:35 -020041 .fa_off = FLASH_AREA_IMAGE_0_OFFSET,
42 .fa_size = FLASH_AREA_IMAGE_0_SIZE,
David Brown5153bd62017-01-06 11:16:53 -070043 },
44 {
45 .fa_id = FLASH_AREA_IMAGE_1,
Ricardo Salveti3a2c1242017-01-19 10:22:35 -020046 .fa_off = FLASH_AREA_IMAGE_1_OFFSET,
47 .fa_size = FLASH_AREA_IMAGE_1_SIZE,
David Brown5153bd62017-01-06 11:16:53 -070048 },
49 {
50 .fa_id = FLASH_AREA_IMAGE_SCRATCH,
Ricardo Salveti3a2c1242017-01-19 10:22:35 -020051 .fa_off = FLASH_AREA_IMAGE_SCRATCH_OFFSET,
52 .fa_size = FLASH_AREA_IMAGE_SCRATCH_SIZE,
David Brown5153bd62017-01-06 11:16:53 -070053 },
54};
55
56/*
David Brown5153bd62017-01-06 11:16:53 -070057 * `open` a flash area. The `area` in this case is not the individual
58 * sectors, but describes the particular flash area in question.
59 */
60int flash_area_open(uint8_t id, const struct flash_area **area)
61{
62 int i;
Ricardo Salveti7cf3d9e2017-01-18 16:38:22 -020063
Marti Bolivar4a97b4c2017-01-31 18:20:02 -050064 BOOT_LOG_DBG("%s: area %d", __func__, id);
David Brown5153bd62017-01-06 11:16:53 -070065
66 for (i = 0; i < ARRAY_SIZE(part_map); i++) {
67 if (id == part_map[i].fa_id)
68 break;
69 }
70 if (i == ARRAY_SIZE(part_map))
71 return -1;
72
73 *area = &part_map[i];
74 return 0;
75}
76
77/*
78 * Nothing to do on close.
79 */
80void flash_area_close(const struct flash_area *area)
81{
82}
83
84int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
85 uint32_t len)
86{
Marti Bolivar4a97b4c2017-01-31 18:20:02 -050087 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
88 area->fa_id, off, len);
David Brown5153bd62017-01-06 11:16:53 -070089 return flash_read(boot_flash_device, area->fa_off + off, dst, len);
90}
91
92int flash_area_write(const struct flash_area *area, uint32_t off, const void *src,
93 uint32_t len)
94{
Michael Scotte12746c2017-01-31 16:07:08 -080095 int rc = 0;
96
Marti Bolivar4a97b4c2017-01-31 18:20:02 -050097 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
98 area->fa_id, off, len);
Michael Scotte12746c2017-01-31 16:07:08 -080099 flash_write_protection_set(boot_flash_device, false);
100 rc = flash_write(boot_flash_device, area->fa_off + off, src, len);
101 flash_write_protection_set(boot_flash_device, true);
102 return rc;
David Brown5153bd62017-01-06 11:16:53 -0700103}
104
105int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
106{
Marti Bolivar53cfdb92017-02-10 15:05:22 -0500107 int rc;
108
Marti Bolivar4a97b4c2017-01-31 18:20:02 -0500109 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
Marti Bolivar53cfdb92017-02-10 15:05:22 -0500110 area->fa_id, off, len);
111 flash_write_protection_set(boot_flash_device, false);
112 rc = flash_erase(boot_flash_device, area->fa_off + off, len);
113 flash_write_protection_set(boot_flash_device, true);
114 return rc;
David Brown5153bd62017-01-06 11:16:53 -0700115}
116
117uint8_t flash_area_align(const struct flash_area *area)
118{
119 return hal_flash_align(area->fa_id);
120}
121
122/*
123 * This depends on the mappings defined in sysflash.h, and assumes
124 * that slot 0, slot 1, and the scratch area area contiguous.
125 */
126int flash_area_id_from_image_slot(int slot)
127{
128 return slot + FLASH_AREA_IMAGE_0;
129}
130
131/*
132 * Lookup the sector map for a given flash area. This should fill in
133 * `ret` with all of the sectors in the area. `*cnt` will be set to
134 * the storage at `ret` and should be set to the final number of
135 * sectors in this area.
136 */
137int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret)
138{
139 uint32_t off;
Michael Scottde6ee592017-01-31 16:11:57 -0800140 uint32_t len;
141 uint32_t max_cnt = *cnt;
David Brown5153bd62017-01-06 11:16:53 -0700142
Marti Bolivar4a97b4c2017-01-31 18:20:02 -0500143 BOOT_LOG_DBG("%s: lookup area %d", __func__, idx);
David Brown5153bd62017-01-06 11:16:53 -0700144 /*
145 * This simple layout has uniform slots, so just fill in the
146 * right one.
147 */
148 if (idx < FLASH_AREA_IMAGE_0 || idx > FLASH_AREA_IMAGE_SCRATCH)
149 return -1;
150
151 if (*cnt < 1)
152 return -1;
153
Michael Scottde6ee592017-01-31 16:11:57 -0800154 switch (idx) {
155 case FLASH_AREA_IMAGE_0:
156 off = FLASH_AREA_IMAGE_0_OFFSET;
157 len = FLASH_AREA_IMAGE_0_SIZE;
158 break;
159 case FLASH_AREA_IMAGE_1:
160 off = FLASH_AREA_IMAGE_1_OFFSET;
161 len = FLASH_AREA_IMAGE_1_SIZE;
162 break;
163 case FLASH_AREA_IMAGE_SCRATCH:
164 off = FLASH_AREA_IMAGE_SCRATCH_OFFSET;
165 len = FLASH_AREA_IMAGE_SCRATCH_SIZE;
166 break;
167 default:
168 SYS_LOG_ERR("%s: unknown flash area %d", __func__, idx);
169 return -1;
170 }
David Brown5153bd62017-01-06 11:16:53 -0700171
Michael Scottde6ee592017-01-31 16:11:57 -0800172 *cnt = 0;
173 while (len > 0 && *cnt < max_cnt) {
174 ret[*cnt].fa_id = idx;
175 ret[*cnt].fa_device_id = 0;
176 ret[*cnt].pad16 = 0;
177 ret[*cnt].fa_off = off + (FLASH_AREA_IMAGE_SCRATCH_SIZE * (*cnt));
178 ret[*cnt].fa_size = FLASH_AREA_IMAGE_SCRATCH_SIZE;
179 *cnt = *cnt + 1;
180 len -= FLASH_AREA_IMAGE_SCRATCH_SIZE;
181 }
David Brown5153bd62017-01-06 11:16:53 -0700182
183 return 0;
184}