Repository navigation
Expand file tree
/
Copy pathflash_decoder.c
More file actions
314 lines (258 loc) · 9.46 KB
/
Copy pathflash_decoder.c
File metadata and controls
314 lines (258 loc) · 9.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
/**
* @file flash_decoder.c
* @brief Implementation of flash_decoder.h
*
* DAPLink Interface Firmware
* Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include "flash_decoder.h"
#include "util.h"
//#include "daplink.h"
#include "flash_manager.h"
//#include "target_config.h" // for target_device
#include "settings.h" // for config_get_automation_allowed
//#include "validation.h"
//#include "target_board.h"
//#include "cmsis_compiler.h"
// Set to 1 to enable debugging
#define DEBUG_FLASH_DECODER 0
#if DEBUG_FLASH_DECODER
#include "daplink_debug.h"
#define flash_decoder_printf debug_msg
#else
#define flash_decoder_printf(...)
#endif
typedef enum {
DECODER_STATE_CLOSED,
DECODER_STATE_OPEN,
DECODER_STATE_DONE,
DECODER_STATE_ERROR
} decoder_state_t;
static uint8_t flash_buf[FLASH_DECODER_MIN_SIZE];
static decoder_state_t state = DECODER_STATE_CLOSED;
static flash_decoder_type_t flash_type;
static uint32_t flash_buf_pos;
static uint32_t initial_addr;
static uint32_t current_addr;
static bool flash_initialized;
static bool initial_addr_set;
static bool flash_type_target_bin;
static bool flash_decoder_is_at_end(uint32_t addr, const uint8_t *data, uint32_t size);
__WEAK uint8_t board_detect_incompatible_image(const uint8_t *data, uint32_t size)
{
return 0; // Return 0 if image is compatible
}
flash_decoder_type_t flash_decoder_detect_type(const uint8_t *data, uint32_t size, uint32_t addr, bool addr_valid)
{
util_assert(size >= FLASH_DECODER_MIN_SIZE);
if(!addr_valid){ //reset until we know the binary type
flash_type_target_bin = false;
}
// Check if a valid vector table for the target can be found
// If an address is specified then the data can be decoded
if (addr_valid) {
// TODO - future improvement - make sure address is within target's flash
return FLASH_DECODER_TYPE_TARGET;
}
return FLASH_DECODER_TYPE_UNKNOWN;
}
error_t flash_decoder_get_flash(flash_decoder_type_t type, uint32_t addr, bool addr_valid, uint32_t *start_addr, const flash_intf_t **flash_intf)
{
error_t status = ERROR_SUCCESS;
uint32_t flash_start_local;
const flash_intf_t *flash_intf_local = 0;
if ((0 == start_addr) || (0 == flash_intf)) {
util_assert(0);
return ERROR_INTERNAL;
}
*start_addr = 0;
*flash_intf = 0;
flash_start_local = 0;
flash_intf_local = 0;
// Don't allow bootloader updates unless automation is allowed
if (ERROR_SUCCESS != status) {
return status;
}
if (0 == flash_intf_local) {
util_assert(0);
return ERROR_INTERNAL;
}
*start_addr = flash_start_local;
*flash_intf = flash_intf_local;
return status;
}
error_t flash_decoder_validate_target_image(flash_decoder_type_t type, const uint8_t *data, uint32_t size)
{
error_t status = ERROR_SUCCESS;
return status;
}
error_t flash_decoder_open(void)
{
flash_decoder_printf("flash_decoder_open()\r\n");
// Stream must not be open already
if (state != DECODER_STATE_CLOSED) {
util_assert(0);
return ERROR_INTERNAL;
}
memset(flash_buf, 0xff, sizeof(flash_buf));
state = DECODER_STATE_OPEN;
flash_type = FLASH_DECODER_TYPE_UNKNOWN;
flash_buf_pos = 0;
initial_addr = 0;
current_addr = 0;
flash_initialized = false;
initial_addr_set = false;
return ERROR_SUCCESS;
}
error_t flash_decoder_write(uint32_t addr, const uint8_t *data, uint32_t size)
{
error_t status;
flash_decoder_printf("flash_decoder_write(addr=0x%x, size=0x%x)\r\n", addr, size);
if (DECODER_STATE_OPEN != state) {
util_assert(0);
return ERROR_INTERNAL;
}
// Set the initial address the first time through
if (!initial_addr_set) {
initial_addr = addr;
current_addr = initial_addr;
flash_decoder_printf(" initial_addr=0x%x\r\n", initial_addr);
initial_addr_set = true;
}
if (!flash_initialized) {
uint32_t copy_size;
bool flash_type_known = false;
bool sequential;
// Check if the data is sequential
sequential = addr == current_addr;
current_addr += size;
// Buffer data until the flash type is known
if (sequential) {
// Copy data into buffer
copy_size = MIN(size, sizeof(flash_buf) - flash_buf_pos);
memcpy(&flash_buf[flash_buf_pos], data, copy_size);
flash_buf_pos += copy_size;
flash_decoder_printf(" buffering %i bytes\r\n", copy_size);
// Update vars so they no longer include the buffered data
data += copy_size;
size -= copy_size;
addr += copy_size;
// If enough data has been buffered then determine the type
if (flash_buf_pos >= sizeof(flash_buf)) {
util_assert(sizeof(flash_buf) == flash_buf_pos);
// Determine flash type and get info for it
flash_type = flash_decoder_detect_type(flash_buf, flash_buf_pos, initial_addr, true);
flash_decoder_printf(" Buffering complete, setting flash_type=%i\r\n", flash_type);
flash_type_known = true;
}
} else {
flash_type = FLASH_DECODER_TYPE_TARGET;
flash_decoder_printf(" Non sequential addr, setting flash_type=%i\r\n", flash_type);
flash_type_known = true;
}
// If flash type is known initialize the flash manager
if (flash_type_known) {
const flash_intf_t *flash_intf;
uint32_t flash_start_addr;
status = flash_decoder_get_flash(flash_type, initial_addr, true, &flash_start_addr, &flash_intf);
if (ERROR_SUCCESS != status) {
state = DECODER_STATE_ERROR;
return status;
}
// Validate incompatible target image file
flash_decoder_printf(" flash_start_addr=0x%x\r\n", flash_start_addr);
// Initialize flash manager
util_assert(!flash_initialized);
status = flash_manager_init(flash_intf);
flash_decoder_printf(" flash_manager_init ret %i\r\n", status);
if (ERROR_SUCCESS != status) {
state = DECODER_STATE_ERROR;
return status;
}
flash_initialized = true;
}
// If flash has been initalized then write out buffered data
if (flash_initialized) {
status = flash_manager_data(initial_addr, flash_buf, flash_buf_pos);
flash_decoder_printf(" Flushing buffer initial_addr=0x%x, flash_buf_pos=%i, flash_manager_data ret=%i\r\n",
initial_addr, flash_buf_pos, status);
if (ERROR_SUCCESS != status) {
state = DECODER_STATE_ERROR;
return status;
}
}
}
// Write data as normal if flash has been initialized
if (flash_initialized) {
status = flash_manager_data(addr, data, size);
flash_decoder_printf(" Writing data, addr=0x%x, size=0x%x, flash_manager_data ret %i\r\n",
addr, size, status);
if (ERROR_SUCCESS != status) {
state = DECODER_STATE_ERROR;
return status;
}
}
// Check if this is the end of data
if (flash_decoder_is_at_end(addr, data, size)) {
flash_decoder_printf(" End of transfer detected - addr 0x%08x, size 0x%08x\r\n",
addr, size);
state = DECODER_STATE_DONE;
return ERROR_SUCCESS_DONE;
}
return ERROR_SUCCESS;
}
error_t flash_decoder_close(void)
{
error_t status = ERROR_SUCCESS;
decoder_state_t prev_state = state;
flash_decoder_printf("flash_decoder_close()\r\n");
if (DECODER_STATE_CLOSED == state) {
util_assert(0);
return ERROR_INTERNAL;
}
state = DECODER_STATE_CLOSED;
if (flash_initialized) {
status = flash_manager_uninit();
flash_decoder_printf(" flash_manager_uninit ret %i\r\n", status);
}
if ((DECODER_STATE_DONE != prev_state) &&
(flash_type != FLASH_DECODER_TYPE_TARGET) &&
(status == ERROR_SUCCESS)) {
status = ERROR_IAP_UPDT_INCOMPLETE;
}
return status;
}
static bool flash_decoder_is_at_end(uint32_t addr, const uint8_t *data, uint32_t size)
{
uint32_t end_addr=0;
switch (flash_type) {
case FLASH_DECODER_TYPE_BOOTLOADER:
break;
case FLASH_DECODER_TYPE_INTERFACE:
break;
case FLASH_DECODER_TYPE_TARGET:
//only if we are sure it is a bin for the target; without check unordered hex files will cause to terminate flashing
break;
default:
return false;
}
if (addr + size >= end_addr) {
return true;
} else {
return false;
}
}