Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers flash_decoder.c Source File

flash_decoder.c

Go to the documentation of this file.
00001 /**
00002  * @file    flash_decoder.c
00003  * @brief   Implementation of flash_decoder.h
00004  *
00005  * DAPLink Interface Firmware
00006  * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
00007  * SPDX-License-Identifier: Apache-2.0
00008  *
00009  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  * not use this file except in compliance with the License.
00011  * You may obtain a copy of the License at
00012  *
00013  * http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing, software
00016  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  * See the License for the specific language governing permissions and
00019  * limitations under the License.
00020  */
00021 
00022 #include <string.h>
00023 
00024 #include "flash_decoder.h"
00025 #include "util.h"
00026 #include "daplink.h"
00027 #include "flash_manager.h"
00028 #include "target_config.h"  // for target_device
00029 #include "settings.h"       // for config_get_automation_allowed
00030 #include "validation.h"
00031 #include "target_board.h"
00032 
00033 // Set to 1 to enable debugging
00034 #define DEBUG_FLASH_DECODER     0
00035 
00036 #if DEBUG_FLASH_DECODER
00037 #include "daplink_debug.h"
00038 #define flash_decoder_printf    debug_msg
00039 #else
00040 #define flash_decoder_printf(...)
00041 #endif
00042 
00043 typedef enum {
00044     DECODER_STATE_CLOSED,
00045     DECODER_STATE_OPEN,
00046     DECODER_STATE_DONE,
00047     DECODER_STATE_ERROR
00048 } decoder_state_t;
00049 
00050 static uint8_t flash_buf[FLASH_DECODER_MIN_SIZE];
00051 static decoder_state_t state = DECODER_STATE_CLOSED;
00052 static flash_decoder_type_t flash_type;
00053 static uint32_t flash_buf_pos;
00054 static uint32_t initial_addr;
00055 static uint32_t current_addr;
00056 static bool flash_initialized;
00057 static bool initial_addr_set;
00058 static bool flash_type_target_bin;
00059 
00060 static bool flash_decoder_is_at_end(uint32_t addr, const uint8_t *data, uint32_t size);
00061 
00062 flash_decoder_type_t flash_decoder_detect_type(const uint8_t *data, uint32_t size, uint32_t addr, bool addr_valid)
00063 {
00064     daplink_info_t info;
00065     util_assert(size >= FLASH_DECODER_MIN_SIZE);
00066     // Check if this is a daplink image
00067     memcpy(&info, data + DAPLINK_INFO_OFFSET, sizeof(info));
00068     if(!addr_valid){ //reset until we know the binary type
00069         flash_type_target_bin = false;
00070     }
00071     if (DAPLINK_HIC_ID == info.hic_id) {
00072         if (DAPLINK_BUILD_KEY_IF == info.build_key) {
00073             // Interface update
00074             return FLASH_DECODER_TYPE_INTERFACE;
00075         } else if (DAPLINK_BUILD_KEY_BL == info.build_key) {
00076             // Bootloader update
00077             return FLASH_DECODER_TYPE_BOOTLOADER;
00078         } else {
00079             return FLASH_DECODER_TYPE_UNKNOWN;
00080         }
00081     }
00082 
00083     // Check if a valid vector table for the target can be found
00084     if (validate_bin_nvic(data)) {
00085         if(!addr_valid){ //binary is a bin type
00086             flash_type_target_bin = true;
00087         }
00088         return FLASH_DECODER_TYPE_TARGET;
00089     }
00090 
00091     // If an address is specified then the data can be decoded
00092     if (addr_valid) {
00093         // TODO - future improvement - make sure address is within target's flash
00094         return FLASH_DECODER_TYPE_TARGET;
00095     }
00096 
00097     return FLASH_DECODER_TYPE_UNKNOWN;
00098 }
00099 
00100 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)
00101 {
00102     error_t status = ERROR_SUCCESS;
00103     uint32_t flash_start_local;
00104     const flash_intf_t *flash_intf_local = 0;
00105 
00106     if ((0 == start_addr) || (0 == flash_intf)) {
00107         util_assert(0);
00108         return ERROR_INTERNAL;
00109     }
00110 
00111     *start_addr = 0;
00112     *flash_intf = 0;
00113     flash_start_local = 0;
00114     flash_intf_local = 0;
00115 
00116     if (daplink_is_bootloader()) {
00117         if (FLASH_DECODER_TYPE_INTERFACE == type) {
00118             if (addr_valid && (DAPLINK_ROM_IF_START != addr)) {
00119                 // Address is wrong so display error message
00120                 status = ERROR_FD_INTF_UPDT_ADDR_WRONG;
00121             } else {
00122                 // Setup for update
00123                 flash_start_local = DAPLINK_ROM_IF_START;
00124                 flash_intf_local = flash_intf_iap_protected;
00125             }
00126         } else if (FLASH_DECODER_TYPE_TARGET == type) {
00127             // "Target" update in this case would be a 3rd party interface application
00128             flash_start_local = DAPLINK_ROM_IF_START;
00129             flash_intf_local = flash_intf_iap_protected;
00130         } else {
00131             status = ERROR_FD_UNSUPPORTED_UPDATE;
00132         }
00133     } else if (daplink_is_interface()) {
00134         if (FLASH_DECODER_TYPE_BOOTLOADER == type) {
00135             if (addr_valid && (DAPLINK_ROM_BL_START != addr)) {
00136                 // Address is wrong so display error message
00137                 status = ERROR_FD_BL_UPDT_ADDR_WRONG;
00138             } else {
00139                 // Setup for update
00140                 flash_start_local = DAPLINK_ROM_BL_START;
00141                 flash_intf_local = flash_intf_iap_protected;
00142             }
00143         } else if (FLASH_DECODER_TYPE_TARGET == type) {
00144             if (g_board_info.target_cfg) {
00145                 region_info_t * region = g_board_info.target_cfg->flash_regions;
00146                 for (; region->start != 0 || region->end != 0; ++region) {
00147                     if (kRegionIsDefault  == region->flags) {
00148                         flash_start_local = region->start;
00149                         break;
00150                     }
00151                 }
00152                 flash_intf_local = flash_intf_target;
00153             } else {
00154                 status = ERROR_FD_UNSUPPORTED_UPDATE;
00155             }
00156         } else {
00157             status = ERROR_FD_UNSUPPORTED_UPDATE;
00158         }
00159     } else {
00160         status = ERROR_FD_UNSUPPORTED_UPDATE;
00161     }
00162 
00163     // Don't allow bootloader updates unless automation is allowed
00164     if (!config_get_automation_allowed() && (FLASH_DECODER_TYPE_BOOTLOADER == type)) {
00165         status = ERROR_FD_UNSUPPORTED_UPDATE;
00166     }
00167 
00168     if (ERROR_SUCCESS != status) {
00169         return status;
00170     }
00171 
00172     if (0 == flash_intf_local) {
00173         util_assert(0);
00174         return ERROR_INTERNAL;
00175     }
00176 
00177     *start_addr = flash_start_local;
00178     *flash_intf = flash_intf_local;
00179     return status;
00180 }
00181 
00182 error_t flash_decoder_open(void)
00183 {
00184     flash_decoder_printf("flash_decoder_open()\r\n");
00185 
00186     // Stream must not be open already
00187     if (state != DECODER_STATE_CLOSED) {
00188         util_assert(0);
00189         return ERROR_INTERNAL;
00190     }
00191 
00192     memset(flash_buf, 0xff, sizeof(flash_buf));
00193     state = DECODER_STATE_OPEN;
00194     flash_type = FLASH_DECODER_TYPE_UNKNOWN;
00195     flash_buf_pos = 0;
00196     initial_addr = 0;
00197     current_addr = 0;
00198     flash_initialized = false;
00199     initial_addr_set = false;
00200     return ERROR_SUCCESS;
00201 }
00202 
00203 error_t flash_decoder_write(uint32_t addr, const uint8_t *data, uint32_t size)
00204 {
00205     error_t status;
00206     flash_decoder_printf("flash_decoder_write(addr=0x%x, size=0x%x)\r\n", addr, size);
00207 
00208     if (DECODER_STATE_OPEN != state) {
00209         util_assert(0);
00210         return ERROR_INTERNAL;
00211     }
00212 
00213     // Set the initial address the first time through
00214     if (!initial_addr_set) {
00215         initial_addr = addr;
00216         current_addr = initial_addr;
00217         flash_decoder_printf("     initial_addr=0x%x\r\n", initial_addr);
00218         initial_addr_set = true;
00219     }
00220 
00221     if (!flash_initialized) {
00222         uint32_t copy_size;
00223         bool flash_type_known = false;
00224         bool sequential;
00225         // Check if the data is sequential
00226         sequential = addr == current_addr;
00227         current_addr += size;
00228 
00229         // Buffer data until the flash type is known
00230         if (sequential) {
00231             // Copy data into buffer
00232             copy_size = MIN(size, sizeof(flash_buf) - flash_buf_pos);
00233             memcpy(&flash_buf[flash_buf_pos], data, copy_size);
00234             flash_buf_pos += copy_size;
00235             flash_decoder_printf("    buffering %i bytes\r\n", copy_size);
00236             // Update vars so they no longer include the buffered data
00237             data += copy_size;
00238             size -= copy_size;
00239             addr += copy_size;
00240 
00241             // If enough data has been buffered then determine the type
00242             if (flash_buf_pos >= sizeof(flash_buf)) {
00243                 util_assert(sizeof(flash_buf) == flash_buf_pos);
00244                 // Determine flash type and get info for it
00245                 flash_type = flash_decoder_detect_type(flash_buf, flash_buf_pos, initial_addr, true);
00246                 flash_decoder_printf("    Buffering complete, setting flash_type=%i\r\n", flash_type);
00247                 flash_type_known = true;
00248             }
00249         } else {
00250             flash_type = FLASH_DECODER_TYPE_TARGET;
00251             flash_decoder_printf("    Non sequential addr, setting flash_type=%i\r\n", flash_type);
00252             flash_type_known = true;
00253         }
00254 
00255         // If flash type is known initialize the flash manager
00256         if (flash_type_known) {
00257             const flash_intf_t *flash_intf;
00258             uint32_t flash_start_addr;
00259             status = flash_decoder_get_flash(flash_type, initial_addr, true, &flash_start_addr, &flash_intf);
00260 
00261             if (ERROR_SUCCESS != status) {
00262                 state = DECODER_STATE_ERROR;
00263                 return status;
00264             }
00265 
00266             flash_decoder_printf("    flash_start_addr=0x%x\r\n", flash_start_addr);
00267             // Initialize flash manager
00268             util_assert(!flash_initialized);
00269             status = flash_manager_init(flash_intf);
00270             flash_decoder_printf("    flash_manager_init ret %i\r\n", status);
00271 
00272             if (ERROR_SUCCESS != status) {
00273                 state = DECODER_STATE_ERROR;
00274                 return status;
00275             }
00276 
00277             flash_initialized = true;
00278         }
00279 
00280         // If flash has been initalized then write out buffered data
00281         if (flash_initialized) {
00282             status = flash_manager_data(initial_addr, flash_buf, flash_buf_pos);
00283             flash_decoder_printf("    Flushing buffer initial_addr=0x%x, flash_buf_pos=%i, flash_manager_data ret=%i\r\n",
00284                                  initial_addr, flash_buf_pos, status);
00285 
00286             if (ERROR_SUCCESS != status) {
00287                 state = DECODER_STATE_ERROR;
00288                 return status;
00289             }
00290         }
00291     }
00292 
00293     // Write data as normal if flash has been initialized
00294     if (flash_initialized) {
00295         status = flash_manager_data(addr, data, size);
00296         flash_decoder_printf("    Writing data, addr=0x%x, size=0x%x, flash_manager_data ret %i\r\n",
00297                              addr, size, status);
00298 
00299         if (ERROR_SUCCESS != status) {
00300             state = DECODER_STATE_ERROR;
00301             return status;
00302         }
00303     }
00304 
00305     // Check if this is the end of data
00306     if (flash_decoder_is_at_end(addr, data, size)) {
00307         flash_decoder_printf("    End of transfer detected - addr 0x%08x, size 0x%08x\r\n",
00308                              addr, size);
00309         state = DECODER_STATE_DONE;
00310         return ERROR_SUCCESS_DONE;
00311     }
00312 
00313     return ERROR_SUCCESS;
00314 }
00315 
00316 error_t flash_decoder_close(void)
00317 {
00318     error_t status = ERROR_SUCCESS;
00319     decoder_state_t prev_state = state;
00320     flash_decoder_printf("flash_decoder_close()\r\n");
00321 
00322     if (DECODER_STATE_CLOSED == state) {
00323         util_assert(0);
00324         return ERROR_INTERNAL;
00325     }
00326 
00327     state = DECODER_STATE_CLOSED;
00328 
00329     if (flash_initialized) {
00330         status = flash_manager_uninit();
00331         flash_decoder_printf("    flash_manager_uninit ret %i\r\n", status);
00332     }
00333 
00334     if ((DECODER_STATE_DONE != prev_state) &&
00335             (flash_type != FLASH_DECODER_TYPE_TARGET) &&
00336             (status == ERROR_SUCCESS)) {
00337         status = ERROR_IAP_UPDT_INCOMPLETE;
00338     }
00339 
00340     return status;
00341 }
00342 
00343 static bool flash_decoder_is_at_end(uint32_t addr, const uint8_t *data, uint32_t size)
00344 {
00345     uint32_t end_addr=0;
00346 
00347     switch (flash_type) {
00348         case FLASH_DECODER_TYPE_BOOTLOADER:
00349             end_addr = DAPLINK_ROM_BL_START + DAPLINK_ROM_BL_SIZE;
00350             break;
00351 
00352         case FLASH_DECODER_TYPE_INTERFACE:
00353             end_addr = DAPLINK_ROM_IF_START + DAPLINK_ROM_IF_SIZE;
00354             break;
00355 
00356         case FLASH_DECODER_TYPE_TARGET:
00357             //only if we are sure it is a bin for the target; without check unordered hex files will cause to terminate flashing
00358             if (flash_type_target_bin && g_board_info.target_cfg) {
00359                 region_info_t * region = g_board_info.target_cfg->flash_regions;
00360                 for (; region->start != 0 || region->end != 0; ++region) {
00361                     if (addr >= region->start &&  addr<=region->end) {
00362                         end_addr = region->end;
00363                         break;
00364                     }
00365                 }
00366                 if(end_addr == 0){ //invalid end_addr
00367                     return false;
00368                 }
00369 
00370             }
00371             else {
00372                 return false;
00373             }
00374             break;
00375 
00376         default:
00377             return false;
00378     }
00379 
00380     if (addr + size >= end_addr) {
00381         return true;
00382     } else {
00383         return false;
00384     }
00385 }