Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.
Upstream: https://github.com/ARMmbed/DAPLink
source/daplink/drag-n-drop/file_stream.c@0:01f31e923fe2, 2020-04-07 (annotated)
- Committer:
- Pawel Zarembski
- Date:
- Tue Apr 07 12:55:42 2020 +0200
- Revision:
- 0:01f31e923fe2
hani: DAPLink with reset workaround
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Pawel Zarembski |
0:01f31e923fe2 | 1 | /** |
Pawel Zarembski |
0:01f31e923fe2 | 2 | * @file file_stream.c |
Pawel Zarembski |
0:01f31e923fe2 | 3 | * @brief Implementation of file_stream.h |
Pawel Zarembski |
0:01f31e923fe2 | 4 | * |
Pawel Zarembski |
0:01f31e923fe2 | 5 | * DAPLink Interface Firmware |
Pawel Zarembski |
0:01f31e923fe2 | 6 | * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved |
Pawel Zarembski |
0:01f31e923fe2 | 7 | * SPDX-License-Identifier: Apache-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 8 | * |
Pawel Zarembski |
0:01f31e923fe2 | 9 | * Licensed under the Apache License, Version 2.0 (the "License"); you may |
Pawel Zarembski |
0:01f31e923fe2 | 10 | * not use this file except in compliance with the License. |
Pawel Zarembski |
0:01f31e923fe2 | 11 | * You may obtain a copy of the License at |
Pawel Zarembski |
0:01f31e923fe2 | 12 | * |
Pawel Zarembski |
0:01f31e923fe2 | 13 | * http://www.apache.org/licenses/LICENSE-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 14 | * |
Pawel Zarembski |
0:01f31e923fe2 | 15 | * Unless required by applicable law or agreed to in writing, software |
Pawel Zarembski |
0:01f31e923fe2 | 16 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
Pawel Zarembski |
0:01f31e923fe2 | 17 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
Pawel Zarembski |
0:01f31e923fe2 | 18 | * See the License for the specific language governing permissions and |
Pawel Zarembski |
0:01f31e923fe2 | 19 | * limitations under the License. |
Pawel Zarembski |
0:01f31e923fe2 | 20 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 21 | |
Pawel Zarembski |
0:01f31e923fe2 | 22 | #include <string.h> |
Pawel Zarembski |
0:01f31e923fe2 | 23 | |
Pawel Zarembski |
0:01f31e923fe2 | 24 | #include "file_stream.h" |
Pawel Zarembski |
0:01f31e923fe2 | 25 | #include "util.h" |
Pawel Zarembski |
0:01f31e923fe2 | 26 | #include "intelhex.h" |
Pawel Zarembski |
0:01f31e923fe2 | 27 | #include "flash_decoder.h" |
Pawel Zarembski |
0:01f31e923fe2 | 28 | #include "error.h" |
Pawel Zarembski |
0:01f31e923fe2 | 29 | #include "cmsis_os2.h" |
Pawel Zarembski |
0:01f31e923fe2 | 30 | #include "compiler.h" |
Pawel Zarembski |
0:01f31e923fe2 | 31 | #include "validation.h" |
Pawel Zarembski |
0:01f31e923fe2 | 32 | |
Pawel Zarembski |
0:01f31e923fe2 | 33 | typedef enum { |
Pawel Zarembski |
0:01f31e923fe2 | 34 | STREAM_STATE_CLOSED, |
Pawel Zarembski |
0:01f31e923fe2 | 35 | STREAM_STATE_OPEN, |
Pawel Zarembski |
0:01f31e923fe2 | 36 | STREAM_STATE_END, |
Pawel Zarembski |
0:01f31e923fe2 | 37 | STREAM_STATE_ERROR |
Pawel Zarembski |
0:01f31e923fe2 | 38 | } stream_state_t; |
Pawel Zarembski |
0:01f31e923fe2 | 39 | |
Pawel Zarembski |
0:01f31e923fe2 | 40 | typedef bool (*stream_detect_cb_t)(const uint8_t *data, uint32_t size); |
Pawel Zarembski |
0:01f31e923fe2 | 41 | typedef error_t (*stream_open_cb_t)(void *state); |
Pawel Zarembski |
0:01f31e923fe2 | 42 | typedef error_t (*stream_write_cb_t)(void *state, const uint8_t *data, uint32_t size); |
Pawel Zarembski |
0:01f31e923fe2 | 43 | typedef error_t (*stream_close_cb_t)(void *state); |
Pawel Zarembski |
0:01f31e923fe2 | 44 | |
Pawel Zarembski |
0:01f31e923fe2 | 45 | typedef struct { |
Pawel Zarembski |
0:01f31e923fe2 | 46 | stream_detect_cb_t detect; |
Pawel Zarembski |
0:01f31e923fe2 | 47 | stream_open_cb_t open; |
Pawel Zarembski |
0:01f31e923fe2 | 48 | stream_write_cb_t write; |
Pawel Zarembski |
0:01f31e923fe2 | 49 | stream_close_cb_t close; |
Pawel Zarembski |
0:01f31e923fe2 | 50 | } stream_t; |
Pawel Zarembski |
0:01f31e923fe2 | 51 | |
Pawel Zarembski |
0:01f31e923fe2 | 52 | typedef struct { |
Pawel Zarembski |
0:01f31e923fe2 | 53 | uint8_t vector_buf[FLASH_DECODER_MIN_SIZE]; |
Pawel Zarembski |
0:01f31e923fe2 | 54 | uint8_t buf_pos; |
Pawel Zarembski |
0:01f31e923fe2 | 55 | uint32_t flash_addr; |
Pawel Zarembski |
0:01f31e923fe2 | 56 | } bin_state_t; |
Pawel Zarembski |
0:01f31e923fe2 | 57 | |
Pawel Zarembski |
0:01f31e923fe2 | 58 | typedef struct { |
Pawel Zarembski |
0:01f31e923fe2 | 59 | bool parsing_complete; |
Pawel Zarembski |
0:01f31e923fe2 | 60 | uint8_t bin_buffer[256]; |
Pawel Zarembski |
0:01f31e923fe2 | 61 | } hex_state_t; |
Pawel Zarembski |
0:01f31e923fe2 | 62 | |
Pawel Zarembski |
0:01f31e923fe2 | 63 | typedef union { |
Pawel Zarembski |
0:01f31e923fe2 | 64 | bin_state_t bin; |
Pawel Zarembski |
0:01f31e923fe2 | 65 | hex_state_t hex; |
Pawel Zarembski |
0:01f31e923fe2 | 66 | } shared_state_t; |
Pawel Zarembski |
0:01f31e923fe2 | 67 | |
Pawel Zarembski |
0:01f31e923fe2 | 68 | static bool detect_bin(const uint8_t *data, uint32_t size); |
Pawel Zarembski |
0:01f31e923fe2 | 69 | static error_t open_bin(void *state); |
Pawel Zarembski |
0:01f31e923fe2 | 70 | static error_t write_bin(void *state, const uint8_t *data, uint32_t size); |
Pawel Zarembski |
0:01f31e923fe2 | 71 | static error_t close_bin(void *state); |
Pawel Zarembski |
0:01f31e923fe2 | 72 | |
Pawel Zarembski |
0:01f31e923fe2 | 73 | static bool detect_hex(const uint8_t *data, uint32_t size); |
Pawel Zarembski |
0:01f31e923fe2 | 74 | static error_t open_hex(void *state); |
Pawel Zarembski |
0:01f31e923fe2 | 75 | static error_t write_hex(void *state, const uint8_t *data, uint32_t size); |
Pawel Zarembski |
0:01f31e923fe2 | 76 | static error_t close_hex(void *state); |
Pawel Zarembski |
0:01f31e923fe2 | 77 | |
Pawel Zarembski |
0:01f31e923fe2 | 78 | stream_t stream[] = { |
Pawel Zarembski |
0:01f31e923fe2 | 79 | {detect_bin, open_bin, write_bin, close_bin}, // STREAM_TYPE_BIN |
Pawel Zarembski |
0:01f31e923fe2 | 80 | {detect_hex, open_hex, write_hex, close_hex}, // STREAM_TYPE_HEX |
Pawel Zarembski |
0:01f31e923fe2 | 81 | }; |
Pawel Zarembski |
0:01f31e923fe2 | 82 | COMPILER_ASSERT(ARRAY_SIZE(stream) == STREAM_TYPE_COUNT); |
Pawel Zarembski |
0:01f31e923fe2 | 83 | // STREAM_TYPE_NONE must not be included in count |
Pawel Zarembski |
0:01f31e923fe2 | 84 | COMPILER_ASSERT(STREAM_TYPE_NONE > STREAM_TYPE_COUNT); |
Pawel Zarembski |
0:01f31e923fe2 | 85 | |
Pawel Zarembski |
0:01f31e923fe2 | 86 | static shared_state_t shared_state; |
Pawel Zarembski |
0:01f31e923fe2 | 87 | static stream_state_t state = STREAM_STATE_CLOSED; |
Pawel Zarembski |
0:01f31e923fe2 | 88 | static stream_t *current_stream = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 89 | |
Pawel Zarembski |
0:01f31e923fe2 | 90 | // Thread variables (STUB these if RTX is not used) |
Pawel Zarembski |
0:01f31e923fe2 | 91 | static osThreadId_t stream_thread_tid = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 92 | static void stream_thread_set(void) |
Pawel Zarembski |
0:01f31e923fe2 | 93 | { |
Pawel Zarembski |
0:01f31e923fe2 | 94 | stream_thread_tid = osThreadGetId(); |
Pawel Zarembski |
0:01f31e923fe2 | 95 | } |
Pawel Zarembski |
0:01f31e923fe2 | 96 | static void stream_thread_assert(void) |
Pawel Zarembski |
0:01f31e923fe2 | 97 | { |
Pawel Zarembski |
0:01f31e923fe2 | 98 | util_assert(osThreadGetId() == stream_thread_tid); |
Pawel Zarembski |
0:01f31e923fe2 | 99 | } |
Pawel Zarembski |
0:01f31e923fe2 | 100 | |
Pawel Zarembski |
0:01f31e923fe2 | 101 | stream_type_t stream_start_identify(const uint8_t *data, uint32_t size) |
Pawel Zarembski |
0:01f31e923fe2 | 102 | { |
Pawel Zarembski |
0:01f31e923fe2 | 103 | stream_type_t i; |
Pawel Zarembski |
0:01f31e923fe2 | 104 | |
Pawel Zarembski |
0:01f31e923fe2 | 105 | for (i = STREAM_TYPE_START; i < STREAM_TYPE_COUNT; i++) { |
Pawel Zarembski |
0:01f31e923fe2 | 106 | if (stream[i].detect(data, size)) { |
Pawel Zarembski |
0:01f31e923fe2 | 107 | return i; |
Pawel Zarembski |
0:01f31e923fe2 | 108 | } |
Pawel Zarembski |
0:01f31e923fe2 | 109 | } |
Pawel Zarembski |
0:01f31e923fe2 | 110 | |
Pawel Zarembski |
0:01f31e923fe2 | 111 | return STREAM_TYPE_NONE; |
Pawel Zarembski |
0:01f31e923fe2 | 112 | } |
Pawel Zarembski |
0:01f31e923fe2 | 113 | |
Pawel Zarembski |
0:01f31e923fe2 | 114 | // Identify the file type from its extension |
Pawel Zarembski |
0:01f31e923fe2 | 115 | stream_type_t stream_type_from_name(const vfs_filename_t filename) |
Pawel Zarembski |
0:01f31e923fe2 | 116 | { |
Pawel Zarembski |
0:01f31e923fe2 | 117 | // 8.3 file names must be in upper case |
Pawel Zarembski |
0:01f31e923fe2 | 118 | if (0 == strncmp("BIN", &filename[8], 3)) { |
Pawel Zarembski |
0:01f31e923fe2 | 119 | return STREAM_TYPE_BIN; |
Pawel Zarembski |
0:01f31e923fe2 | 120 | } else if (0 == strncmp("HEX", &filename[8], 3)) { |
Pawel Zarembski |
0:01f31e923fe2 | 121 | return STREAM_TYPE_HEX; |
Pawel Zarembski |
0:01f31e923fe2 | 122 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 123 | return STREAM_TYPE_NONE; |
Pawel Zarembski |
0:01f31e923fe2 | 124 | } |
Pawel Zarembski |
0:01f31e923fe2 | 125 | } |
Pawel Zarembski |
0:01f31e923fe2 | 126 | |
Pawel Zarembski |
0:01f31e923fe2 | 127 | error_t stream_open(stream_type_t stream_type) |
Pawel Zarembski |
0:01f31e923fe2 | 128 | { |
Pawel Zarembski |
0:01f31e923fe2 | 129 | error_t status; |
Pawel Zarembski |
0:01f31e923fe2 | 130 | |
Pawel Zarembski |
0:01f31e923fe2 | 131 | // Stream must not be open already |
Pawel Zarembski |
0:01f31e923fe2 | 132 | if (state != STREAM_STATE_CLOSED) { |
Pawel Zarembski |
0:01f31e923fe2 | 133 | util_assert(0); |
Pawel Zarembski |
0:01f31e923fe2 | 134 | return ERROR_INTERNAL; |
Pawel Zarembski |
0:01f31e923fe2 | 135 | } |
Pawel Zarembski |
0:01f31e923fe2 | 136 | |
Pawel Zarembski |
0:01f31e923fe2 | 137 | // Stream must be of a supported type |
Pawel Zarembski |
0:01f31e923fe2 | 138 | if (stream_type >= STREAM_TYPE_COUNT) { |
Pawel Zarembski |
0:01f31e923fe2 | 139 | util_assert(0); |
Pawel Zarembski |
0:01f31e923fe2 | 140 | return ERROR_INTERNAL; |
Pawel Zarembski |
0:01f31e923fe2 | 141 | } |
Pawel Zarembski |
0:01f31e923fe2 | 142 | |
Pawel Zarembski |
0:01f31e923fe2 | 143 | stream_thread_set(); |
Pawel Zarembski |
0:01f31e923fe2 | 144 | // Initialize all variables |
Pawel Zarembski |
0:01f31e923fe2 | 145 | memset(&shared_state, 0, sizeof(shared_state)); |
Pawel Zarembski |
0:01f31e923fe2 | 146 | state = STREAM_STATE_OPEN; |
Pawel Zarembski |
0:01f31e923fe2 | 147 | current_stream = &stream[stream_type]; |
Pawel Zarembski |
0:01f31e923fe2 | 148 | // Initialize the specified stream |
Pawel Zarembski |
0:01f31e923fe2 | 149 | status = current_stream->open(&shared_state); |
Pawel Zarembski |
0:01f31e923fe2 | 150 | |
Pawel Zarembski |
0:01f31e923fe2 | 151 | if (ERROR_SUCCESS != status) { |
Pawel Zarembski |
0:01f31e923fe2 | 152 | state = STREAM_STATE_ERROR; |
Pawel Zarembski |
0:01f31e923fe2 | 153 | } |
Pawel Zarembski |
0:01f31e923fe2 | 154 | |
Pawel Zarembski |
0:01f31e923fe2 | 155 | return status; |
Pawel Zarembski |
0:01f31e923fe2 | 156 | } |
Pawel Zarembski |
0:01f31e923fe2 | 157 | |
Pawel Zarembski |
0:01f31e923fe2 | 158 | error_t stream_write(const uint8_t *data, uint32_t size) |
Pawel Zarembski |
0:01f31e923fe2 | 159 | { |
Pawel Zarembski |
0:01f31e923fe2 | 160 | error_t status; |
Pawel Zarembski |
0:01f31e923fe2 | 161 | |
Pawel Zarembski |
0:01f31e923fe2 | 162 | // Stream must be open already |
Pawel Zarembski |
0:01f31e923fe2 | 163 | if (state != STREAM_STATE_OPEN) { |
Pawel Zarembski |
0:01f31e923fe2 | 164 | util_assert(0); |
Pawel Zarembski |
0:01f31e923fe2 | 165 | return ERROR_INTERNAL; |
Pawel Zarembski |
0:01f31e923fe2 | 166 | } |
Pawel Zarembski |
0:01f31e923fe2 | 167 | |
Pawel Zarembski |
0:01f31e923fe2 | 168 | // Check thread after checking state since the stream thread is |
Pawel Zarembski |
0:01f31e923fe2 | 169 | // set only if stream_open has been called |
Pawel Zarembski |
0:01f31e923fe2 | 170 | stream_thread_assert(); |
Pawel Zarembski |
0:01f31e923fe2 | 171 | // Write to stream |
Pawel Zarembski |
0:01f31e923fe2 | 172 | status = current_stream->write(&shared_state, data, size); |
Pawel Zarembski |
0:01f31e923fe2 | 173 | |
Pawel Zarembski |
0:01f31e923fe2 | 174 | if (ERROR_SUCCESS_DONE == status) { |
Pawel Zarembski |
0:01f31e923fe2 | 175 | state = STREAM_STATE_END; |
Pawel Zarembski |
0:01f31e923fe2 | 176 | } else if ((ERROR_SUCCESS_DONE_OR_CONTINUE == status) || (ERROR_SUCCESS == status)) { |
Pawel Zarembski |
0:01f31e923fe2 | 177 | // Stream should remain in the open state |
Pawel Zarembski |
0:01f31e923fe2 | 178 | util_assert(STREAM_STATE_OPEN == state); |
Pawel Zarembski |
0:01f31e923fe2 | 179 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 180 | state = STREAM_STATE_ERROR; |
Pawel Zarembski |
0:01f31e923fe2 | 181 | } |
Pawel Zarembski |
0:01f31e923fe2 | 182 | |
Pawel Zarembski |
0:01f31e923fe2 | 183 | return status; |
Pawel Zarembski |
0:01f31e923fe2 | 184 | } |
Pawel Zarembski |
0:01f31e923fe2 | 185 | |
Pawel Zarembski |
0:01f31e923fe2 | 186 | error_t stream_close(void) |
Pawel Zarembski |
0:01f31e923fe2 | 187 | { |
Pawel Zarembski |
0:01f31e923fe2 | 188 | error_t status; |
Pawel Zarembski |
0:01f31e923fe2 | 189 | |
Pawel Zarembski |
0:01f31e923fe2 | 190 | // Stream must not be closed already |
Pawel Zarembski |
0:01f31e923fe2 | 191 | if (STREAM_STATE_CLOSED == state) { |
Pawel Zarembski |
0:01f31e923fe2 | 192 | util_assert(0); |
Pawel Zarembski |
0:01f31e923fe2 | 193 | return ERROR_INTERNAL; |
Pawel Zarembski |
0:01f31e923fe2 | 194 | } |
Pawel Zarembski |
0:01f31e923fe2 | 195 | |
Pawel Zarembski |
0:01f31e923fe2 | 196 | // Check thread after checking state since the stream thread is |
Pawel Zarembski |
0:01f31e923fe2 | 197 | // set only if stream_open has been called |
Pawel Zarembski |
0:01f31e923fe2 | 198 | stream_thread_assert(); |
Pawel Zarembski |
0:01f31e923fe2 | 199 | // Close stream |
Pawel Zarembski |
0:01f31e923fe2 | 200 | status = current_stream->close(&shared_state); |
Pawel Zarembski |
0:01f31e923fe2 | 201 | state = STREAM_STATE_CLOSED; |
Pawel Zarembski |
0:01f31e923fe2 | 202 | return status; |
Pawel Zarembski |
0:01f31e923fe2 | 203 | } |
Pawel Zarembski |
0:01f31e923fe2 | 204 | |
Pawel Zarembski |
0:01f31e923fe2 | 205 | /* Binary file processing */ |
Pawel Zarembski |
0:01f31e923fe2 | 206 | |
Pawel Zarembski |
0:01f31e923fe2 | 207 | static bool detect_bin(const uint8_t *data, uint32_t size) |
Pawel Zarembski |
0:01f31e923fe2 | 208 | { |
Pawel Zarembski |
0:01f31e923fe2 | 209 | return FLASH_DECODER_TYPE_UNKNOWN != flash_decoder_detect_type(data, size, 0, false); |
Pawel Zarembski |
0:01f31e923fe2 | 210 | } |
Pawel Zarembski |
0:01f31e923fe2 | 211 | |
Pawel Zarembski |
0:01f31e923fe2 | 212 | static error_t open_bin(void *state) |
Pawel Zarembski |
0:01f31e923fe2 | 213 | { |
Pawel Zarembski |
0:01f31e923fe2 | 214 | error_t status; |
Pawel Zarembski |
0:01f31e923fe2 | 215 | status = flash_decoder_open(); |
Pawel Zarembski |
0:01f31e923fe2 | 216 | return status; |
Pawel Zarembski |
0:01f31e923fe2 | 217 | } |
Pawel Zarembski |
0:01f31e923fe2 | 218 | |
Pawel Zarembski |
0:01f31e923fe2 | 219 | static error_t write_bin(void *state, const uint8_t *data, uint32_t size) |
Pawel Zarembski |
0:01f31e923fe2 | 220 | { |
Pawel Zarembski |
0:01f31e923fe2 | 221 | error_t status; |
Pawel Zarembski |
0:01f31e923fe2 | 222 | bin_state_t *bin_state = (bin_state_t *)state; |
Pawel Zarembski |
0:01f31e923fe2 | 223 | |
Pawel Zarembski |
0:01f31e923fe2 | 224 | if (bin_state->buf_pos < FLASH_DECODER_MIN_SIZE) { |
Pawel Zarembski |
0:01f31e923fe2 | 225 | flash_decoder_type_t flash_type; |
Pawel Zarembski |
0:01f31e923fe2 | 226 | uint32_t size_left; |
Pawel Zarembski |
0:01f31e923fe2 | 227 | uint32_t copy_size; |
Pawel Zarembski |
0:01f31e923fe2 | 228 | uint32_t start_addr; |
Pawel Zarembski |
0:01f31e923fe2 | 229 | const flash_intf_t *flash_intf; |
Pawel Zarembski |
0:01f31e923fe2 | 230 | // Buffer Data |
Pawel Zarembski |
0:01f31e923fe2 | 231 | size_left = FLASH_DECODER_MIN_SIZE - bin_state->buf_pos; |
Pawel Zarembski |
0:01f31e923fe2 | 232 | copy_size = MIN(size_left, size); |
Pawel Zarembski |
0:01f31e923fe2 | 233 | memcpy(bin_state->vector_buf + bin_state->buf_pos, data, copy_size); |
Pawel Zarembski |
0:01f31e923fe2 | 234 | bin_state->buf_pos += copy_size; |
Pawel Zarembski |
0:01f31e923fe2 | 235 | |
Pawel Zarembski |
0:01f31e923fe2 | 236 | if (bin_state->buf_pos < FLASH_DECODER_MIN_SIZE) { |
Pawel Zarembski |
0:01f31e923fe2 | 237 | // Not enough data to determine type |
Pawel Zarembski |
0:01f31e923fe2 | 238 | return ERROR_SUCCESS; |
Pawel Zarembski |
0:01f31e923fe2 | 239 | } |
Pawel Zarembski |
0:01f31e923fe2 | 240 | |
Pawel Zarembski |
0:01f31e923fe2 | 241 | data += copy_size; |
Pawel Zarembski |
0:01f31e923fe2 | 242 | size -= copy_size; |
Pawel Zarembski |
0:01f31e923fe2 | 243 | // Determine type |
Pawel Zarembski |
0:01f31e923fe2 | 244 | flash_type = flash_decoder_detect_type(bin_state->vector_buf, bin_state->buf_pos, 0, false); |
Pawel Zarembski |
0:01f31e923fe2 | 245 | |
Pawel Zarembski |
0:01f31e923fe2 | 246 | if (FLASH_DECODER_TYPE_UNKNOWN == flash_type) { |
Pawel Zarembski |
0:01f31e923fe2 | 247 | return ERROR_FD_UNSUPPORTED_UPDATE; |
Pawel Zarembski |
0:01f31e923fe2 | 248 | } |
Pawel Zarembski |
0:01f31e923fe2 | 249 | |
Pawel Zarembski |
0:01f31e923fe2 | 250 | // Determine flash addresss |
Pawel Zarembski |
0:01f31e923fe2 | 251 | status = flash_decoder_get_flash(flash_type, 0, false, &start_addr, &flash_intf); |
Pawel Zarembski |
0:01f31e923fe2 | 252 | |
Pawel Zarembski |
0:01f31e923fe2 | 253 | if (ERROR_SUCCESS != status) { |
Pawel Zarembski |
0:01f31e923fe2 | 254 | return status; |
Pawel Zarembski |
0:01f31e923fe2 | 255 | } |
Pawel Zarembski |
0:01f31e923fe2 | 256 | |
Pawel Zarembski |
0:01f31e923fe2 | 257 | bin_state->flash_addr = start_addr; |
Pawel Zarembski |
0:01f31e923fe2 | 258 | // Pass on data to the decoder |
Pawel Zarembski |
0:01f31e923fe2 | 259 | status = flash_decoder_write(bin_state->flash_addr, bin_state->vector_buf, bin_state->buf_pos); |
Pawel Zarembski |
0:01f31e923fe2 | 260 | |
Pawel Zarembski |
0:01f31e923fe2 | 261 | if (ERROR_SUCCESS != status) { |
Pawel Zarembski |
0:01f31e923fe2 | 262 | return status; |
Pawel Zarembski |
0:01f31e923fe2 | 263 | } |
Pawel Zarembski |
0:01f31e923fe2 | 264 | |
Pawel Zarembski |
0:01f31e923fe2 | 265 | bin_state->flash_addr += bin_state->buf_pos; |
Pawel Zarembski |
0:01f31e923fe2 | 266 | } |
Pawel Zarembski |
0:01f31e923fe2 | 267 | |
Pawel Zarembski |
0:01f31e923fe2 | 268 | // Write data |
Pawel Zarembski |
0:01f31e923fe2 | 269 | status = flash_decoder_write(bin_state->flash_addr, data, size); |
Pawel Zarembski |
0:01f31e923fe2 | 270 | |
Pawel Zarembski |
0:01f31e923fe2 | 271 | if (ERROR_SUCCESS != status) { |
Pawel Zarembski |
0:01f31e923fe2 | 272 | return status; |
Pawel Zarembski |
0:01f31e923fe2 | 273 | } |
Pawel Zarembski |
0:01f31e923fe2 | 274 | |
Pawel Zarembski |
0:01f31e923fe2 | 275 | bin_state->flash_addr += size; |
Pawel Zarembski |
0:01f31e923fe2 | 276 | // There is no way to determine the end of a binary |
Pawel Zarembski |
0:01f31e923fe2 | 277 | // file so any point could be the end |
Pawel Zarembski |
0:01f31e923fe2 | 278 | return ERROR_SUCCESS_DONE_OR_CONTINUE; |
Pawel Zarembski |
0:01f31e923fe2 | 279 | } |
Pawel Zarembski |
0:01f31e923fe2 | 280 | |
Pawel Zarembski |
0:01f31e923fe2 | 281 | static error_t close_bin(void *state) |
Pawel Zarembski |
0:01f31e923fe2 | 282 | { |
Pawel Zarembski |
0:01f31e923fe2 | 283 | error_t status; |
Pawel Zarembski |
0:01f31e923fe2 | 284 | status = flash_decoder_close(); |
Pawel Zarembski |
0:01f31e923fe2 | 285 | return status; |
Pawel Zarembski |
0:01f31e923fe2 | 286 | } |
Pawel Zarembski |
0:01f31e923fe2 | 287 | |
Pawel Zarembski |
0:01f31e923fe2 | 288 | /* Hex file processing */ |
Pawel Zarembski |
0:01f31e923fe2 | 289 | |
Pawel Zarembski |
0:01f31e923fe2 | 290 | static bool detect_hex(const uint8_t *data, uint32_t size) |
Pawel Zarembski |
0:01f31e923fe2 | 291 | { |
Pawel Zarembski |
0:01f31e923fe2 | 292 | return 1 == validate_hexfile(data); |
Pawel Zarembski |
0:01f31e923fe2 | 293 | } |
Pawel Zarembski |
0:01f31e923fe2 | 294 | |
Pawel Zarembski |
0:01f31e923fe2 | 295 | static error_t open_hex(void *state) |
Pawel Zarembski |
0:01f31e923fe2 | 296 | { |
Pawel Zarembski |
0:01f31e923fe2 | 297 | error_t status; |
Pawel Zarembski |
0:01f31e923fe2 | 298 | hex_state_t *hex_state = (hex_state_t *)state; |
Pawel Zarembski |
0:01f31e923fe2 | 299 | memset(hex_state, 0, sizeof(*hex_state)); |
Pawel Zarembski |
0:01f31e923fe2 | 300 | reset_hex_parser(); |
Pawel Zarembski |
0:01f31e923fe2 | 301 | hex_state->parsing_complete = false; |
Pawel Zarembski |
0:01f31e923fe2 | 302 | status = flash_decoder_open(); |
Pawel Zarembski |
0:01f31e923fe2 | 303 | return status; |
Pawel Zarembski |
0:01f31e923fe2 | 304 | } |
Pawel Zarembski |
0:01f31e923fe2 | 305 | |
Pawel Zarembski |
0:01f31e923fe2 | 306 | static error_t write_hex(void *state, const uint8_t *data, uint32_t size) |
Pawel Zarembski |
0:01f31e923fe2 | 307 | { |
Pawel Zarembski |
0:01f31e923fe2 | 308 | error_t status = ERROR_SUCCESS; |
Pawel Zarembski |
0:01f31e923fe2 | 309 | hex_state_t *hex_state = (hex_state_t *)state; |
Pawel Zarembski |
0:01f31e923fe2 | 310 | hexfile_parse_status_t parse_status = HEX_PARSE_UNINIT; |
Pawel Zarembski |
0:01f31e923fe2 | 311 | uint32_t bin_start_address = 0; // Decoded from the hex file, the binary buffer data starts at this address |
Pawel Zarembski |
0:01f31e923fe2 | 312 | uint32_t bin_buf_written = 0; // The amount of data in the binary buffer starting at address above |
Pawel Zarembski |
0:01f31e923fe2 | 313 | uint32_t block_amt_parsed = 0; // amount of data parsed in the block on the last call |
Pawel Zarembski |
0:01f31e923fe2 | 314 | |
Pawel Zarembski |
0:01f31e923fe2 | 315 | while (1) { |
Pawel Zarembski |
0:01f31e923fe2 | 316 | // try to decode a block of hex data into bin data |
Pawel Zarembski |
0:01f31e923fe2 | 317 | parse_status = parse_hex_blob(data, size, &block_amt_parsed, hex_state->bin_buffer, sizeof(hex_state->bin_buffer), &bin_start_address, &bin_buf_written); |
Pawel Zarembski |
0:01f31e923fe2 | 318 | |
Pawel Zarembski |
0:01f31e923fe2 | 319 | // the entire block of hex was decoded. This is a simple state |
Pawel Zarembski |
0:01f31e923fe2 | 320 | if (HEX_PARSE_OK == parse_status) { |
Pawel Zarembski |
0:01f31e923fe2 | 321 | if (bin_buf_written > 0) { |
Pawel Zarembski |
0:01f31e923fe2 | 322 | status = flash_decoder_write(bin_start_address, hex_state->bin_buffer, bin_buf_written); |
Pawel Zarembski |
0:01f31e923fe2 | 323 | } |
Pawel Zarembski |
0:01f31e923fe2 | 324 | |
Pawel Zarembski |
0:01f31e923fe2 | 325 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 326 | } else if (HEX_PARSE_UNALIGNED == parse_status) { |
Pawel Zarembski |
0:01f31e923fe2 | 327 | if (bin_buf_written > 0) { |
Pawel Zarembski |
0:01f31e923fe2 | 328 | status = flash_decoder_write(bin_start_address, hex_state->bin_buffer, bin_buf_written); |
Pawel Zarembski |
0:01f31e923fe2 | 329 | |
Pawel Zarembski |
0:01f31e923fe2 | 330 | if (ERROR_SUCCESS != status) { |
Pawel Zarembski |
0:01f31e923fe2 | 331 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 332 | } |
Pawel Zarembski |
0:01f31e923fe2 | 333 | } |
Pawel Zarembski |
0:01f31e923fe2 | 334 | |
Pawel Zarembski |
0:01f31e923fe2 | 335 | // incrememntal offset to finish the block |
Pawel Zarembski |
0:01f31e923fe2 | 336 | size -= block_amt_parsed; |
Pawel Zarembski |
0:01f31e923fe2 | 337 | data += block_amt_parsed; |
Pawel Zarembski |
0:01f31e923fe2 | 338 | } else if (HEX_PARSE_EOF == parse_status) { |
Pawel Zarembski |
0:01f31e923fe2 | 339 | if (bin_buf_written > 0) { |
Pawel Zarembski |
0:01f31e923fe2 | 340 | status = flash_decoder_write(bin_start_address, hex_state->bin_buffer, bin_buf_written); |
Pawel Zarembski |
0:01f31e923fe2 | 341 | } |
Pawel Zarembski |
0:01f31e923fe2 | 342 | |
Pawel Zarembski |
0:01f31e923fe2 | 343 | if (ERROR_SUCCESS == status) { |
Pawel Zarembski |
0:01f31e923fe2 | 344 | status = ERROR_SUCCESS_DONE; |
Pawel Zarembski |
0:01f31e923fe2 | 345 | } |
Pawel Zarembski |
0:01f31e923fe2 | 346 | |
Pawel Zarembski |
0:01f31e923fe2 | 347 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 348 | } else if (HEX_PARSE_CKSUM_FAIL == parse_status) { |
Pawel Zarembski |
0:01f31e923fe2 | 349 | status = ERROR_HEX_CKSUM; |
Pawel Zarembski |
0:01f31e923fe2 | 350 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 351 | } else if ((HEX_PARSE_UNINIT == parse_status) || (HEX_PARSE_FAILURE == parse_status)) { |
Pawel Zarembski |
0:01f31e923fe2 | 352 | util_assert(HEX_PARSE_UNINIT != parse_status); |
Pawel Zarembski |
0:01f31e923fe2 | 353 | status = ERROR_HEX_PARSER; |
Pawel Zarembski |
0:01f31e923fe2 | 354 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 355 | } |
Pawel Zarembski |
0:01f31e923fe2 | 356 | } |
Pawel Zarembski |
0:01f31e923fe2 | 357 | |
Pawel Zarembski |
0:01f31e923fe2 | 358 | return status; |
Pawel Zarembski |
0:01f31e923fe2 | 359 | } |
Pawel Zarembski |
0:01f31e923fe2 | 360 | |
Pawel Zarembski |
0:01f31e923fe2 | 361 | static error_t close_hex(void *state) |
Pawel Zarembski |
0:01f31e923fe2 | 362 | { |
Pawel Zarembski |
0:01f31e923fe2 | 363 | error_t status; |
Pawel Zarembski |
0:01f31e923fe2 | 364 | status = flash_decoder_close(); |
Pawel Zarembski |
0:01f31e923fe2 | 365 | return status; |
Pawel Zarembski |
0:01f31e923fe2 | 366 | } |