Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

Revision:
0:01f31e923fe2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/daplink/drag-n-drop/vfs_user.c	Tue Apr 07 12:55:42 2020 +0200
@@ -0,0 +1,656 @@
+/**
+ * @file    vfs_user.c
+ * @brief   Implementation of vfs_user.h
+ *
+ * DAPLink Interface Firmware
+ * Copyright (c) 2009-2020, ARM Limited, All Rights Reserved
+ * Copyright 2019, Cypress Semiconductor Corporation 
+ * or a subsidiary of Cypress Semiconductor Corporation.
+ * 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 <stdbool.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "vfs_user.h"
+#include "vfs_manager.h"
+#include "error.h"
+#include "util.h"
+#include "settings.h"
+#include "daplink.h"
+#include "version_git.h"
+#include "info.h"
+#include "gpio.h"           // for gpio_get_sw_reset
+#include "flash_intf.h"     // for flash_intf_target
+#include "cortex_m.h"
+#include "target_board.h"
+#include "flash_manager.h"
+
+//! @brief Size in bytes of the virtual disk.
+//!
+//! Must be bigger than 4x the flash size of the biggest supported
+//! device.  This is to accomodate for hex file programming.
+#define VFS_DISK_SIZE (MB(64))
+
+//! @brief Constants for magic action or config files.
+//!
+//! The "magic files" are files with a special name that if created on the USB MSC volume, will
+//! cause an event. There are two classes of magic files: action files and config files. The former
+//! causes a given action to take place, while the latter changes a persistent configuration setting
+//! to a predetermined value.
+//!
+//! See #s_magic_file_info for the mapping of filenames to these enums.
+typedef enum _magic_file {
+    kDAPLinkModeActionFile,     //!< Switch between interface and bootloader.
+    kTestAssertActionFile,      //!< Force an assertion for testing.
+    kRefreshActionFile,         //!< Force a remount.
+    kEraseActionFile,           //!< Erase the target flash.
+    kAutoResetConfigFile,       //!< Enable reset after flash.
+    kHardResetConfigFile,       //!< Disable reset after flash.
+    kAutomationOnConfigFile,    //!< Enable automation.
+    kAutomationOffConfigFile,   //!< Disable automation.
+    kOverflowOnConfigFile,      //!< Enable UART overflow reporting.
+    kOverflowOffConfigFile,     //!< Disable UART overflow reporting.
+    kMSDOnConfigFile,           //!< Enable USB MSC. Uh....
+    kMSDOffConfigFile,          //!< Disable USB MSC.
+    kPageEraseActionFile,       //!< Enable page programming and sector erase for drag and drop.
+    kChipEraseActionFile,       //!< Enable page programming and chip erase for drag and drop.
+} magic_file_t;
+
+//! @brief Mapping from filename string to magic file enum.
+typedef struct _magic_file_info {
+    const char *name;   //!< Name of the magic file, must be in 8.3 format.
+    magic_file_t which; //!< Enum for the file.
+} magic_file_info_t;
+
+static const char mbed_redirect_file[] =
+    "<!doctype html>\r\n"
+    "<!-- mbed Platform Website and Authentication Shortcut -->\r\n"
+    "<html>\r\n"
+    "<head>\r\n"
+    "<meta charset=\"utf-8\">\r\n"
+    "<title>mbed Website Shortcut</title>\r\n"
+    "</head>\r\n"
+    "<body>\r\n"
+    "<script>\r\n"
+    "window.location.replace(\"@R\");\r\n"
+    "</script>\r\n"
+    "</body>\r\n"
+    "</html>\r\n";
+
+static const char error_prefix[] = "error: ";
+static const char error_type_prefix[] = "type: ";
+
+static const vfs_filename_t assert_file = "ASSERT  TXT";
+
+//! @brief Table of magic files and their names.
+static const magic_file_info_t s_magic_file_info[] = {
+        { daplink_mode_file_name, kDAPLinkModeActionFile },
+        { "ASSERT  ACT", kTestAssertActionFile      },
+        { "REFRESH ACT", kRefreshActionFile         },
+        { "ERASE   ACT", kEraseActionFile           },
+        { "AUTO_RSTCFG", kAutoResetConfigFile       },
+        { "HARD_RSTCFG", kHardResetConfigFile       },
+        { "AUTO_ON CFG", kAutomationOnConfigFile    },
+        { "AUTO_OFFCFG", kAutomationOffConfigFile   },
+        { "OVFL_ON CFG", kOverflowOnConfigFile      },
+        { "OVFL_OFFCFG", kOverflowOffConfigFile     },
+        { "MSD_ON  CFG", kMSDOnConfigFile           },
+        { "MSD_OFF CFG", kMSDOffConfigFile          },
+        { "PAGE_ON ACT", kPageEraseActionFile       },
+        { "PAGE_OFFACT", kChipEraseActionFile       },
+    };
+
+static uint8_t file_buffer[VFS_SECTOR_SIZE];
+static char assert_buf[64 + 1];
+static uint16_t assert_line;
+static assert_source_t assert_source;
+static uint32_t remount_count;
+
+static uint32_t get_file_size(vfs_read_cb_t read_func);
+
+static uint32_t read_file_mbed_htm(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors);
+static uint32_t read_file_details_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors);
+static uint32_t read_file_fail_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors);
+static uint32_t read_file_assert_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors);
+static uint32_t read_file_need_bl_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors);
+
+static uint32_t update_html_file(uint8_t *data, uint32_t datasize);
+static uint32_t update_details_txt_file(uint8_t *data, uint32_t datasize);
+static void erase_target(void);
+
+static uint32_t expand_info(uint8_t *buf, uint32_t bufsize);
+
+void vfs_user_build_filesystem()
+{
+    uint32_t file_size;
+    vfs_file_t file_handle;
+    // Setup the filesystem based on target parameters
+    vfs_init(get_daplink_drive_name(), VFS_DISK_SIZE);
+    // MBED.HTM
+    file_size = get_file_size(read_file_mbed_htm);
+    vfs_create_file(get_daplink_url_name(), read_file_mbed_htm, 0, file_size);
+    // DETAILS.TXT
+    file_size = get_file_size(read_file_details_txt);
+    vfs_create_file("DETAILS TXT", read_file_details_txt, 0, file_size);
+
+    // FAIL.TXT
+    if (vfs_mngr_get_transfer_status() != ERROR_SUCCESS) {
+        file_size = get_file_size(read_file_fail_txt);
+        vfs_create_file("FAIL    TXT", read_file_fail_txt, 0, file_size);
+    }
+
+    // ASSERT.TXT
+    if (config_ram_get_assert(assert_buf, sizeof(assert_buf), &assert_line, &assert_source)) {
+        file_size = get_file_size(read_file_assert_txt);
+        file_handle = vfs_create_file(assert_file, read_file_assert_txt, 0, file_size);
+        vfs_file_set_attr(file_handle, (vfs_file_attr_bit_t)0); // Remove read only attribute
+    }
+
+    // NEED_BL.TXT
+    volatile uint32_t bl_start = DAPLINK_ROM_BL_START; // Silence warnings about null pointer
+    volatile uint32_t if_start = DAPLINK_ROM_IF_START; // Silence warnings about null pointer
+
+    if (daplink_is_interface() &&
+            (DAPLINK_ROM_BL_SIZE > 0) &&
+            (0 == memcmp((void *)bl_start, (void *)if_start, DAPLINK_MIN_WRITE_SIZE))) {
+        // If the bootloader contains a copy of the interfaces vector table
+        // then an error occurred when updating so warn that the bootloader is
+        // missing.
+        file_size = get_file_size(read_file_need_bl_txt);
+        vfs_create_file("NEED_BL TXT", read_file_need_bl_txt, 0, file_size);
+    }
+}
+
+// Default file change hook.
+__WEAK bool vfs_user_file_change_handler_hook(const vfs_filename_t filename, vfs_file_change_t change,
+        vfs_file_t file, vfs_file_t new_file_data)
+{
+    return false;
+}
+
+// Default magic file hook.
+__WEAK bool vfs_user_magic_file_hook(const vfs_filename_t filename, bool *do_remount)
+{
+    return false;
+}
+
+// Callback to handle changes to the root directory.  Should be used with vfs_set_file_change_callback
+void vfs_user_file_change_handler(const vfs_filename_t filename, vfs_file_change_t change, vfs_file_t file, vfs_file_t new_file_data)
+{
+    // Call file changed hook. If it returns true, then it handled the request and we have nothing
+    // more to do.
+    if (vfs_user_file_change_handler_hook(filename, change, file, new_file_data)) {
+        return;
+    }
+
+    // Allow settings to be changed if automation mode is
+    // enabled or if the user is holding the reset button
+    bool btn_pressed = gpio_get_reset_btn();
+
+    if (!btn_pressed && !config_get_automation_allowed()) {
+        return;
+    }
+
+    if (VFS_FILE_CHANGED == change) {
+        // Unused
+    }
+
+    else if (VFS_FILE_CREATED == change) {
+        bool do_remount = true; // Almost all magic files cause a remount.
+        int32_t which_magic_file = -1;
+
+        // Let the hook examine the filename. If it returned false then look for the standard
+        // magic files.
+        if (!vfs_user_magic_file_hook(filename, &do_remount)) {
+            // Compare the new file's name to our table of magic filenames.
+            for (int32_t i = 0; i < ARRAY_SIZE(s_magic_file_info); ++i) {
+                if (!memcmp(filename, s_magic_file_info[i].name, sizeof(vfs_filename_t))) {
+                    which_magic_file = i;
+                }
+            }
+
+            // Check if we matched a magic filename and handle it.
+            if (which_magic_file != -1) {
+                switch (which_magic_file) {
+                    case kDAPLinkModeActionFile:
+                        if (daplink_is_interface()) {
+                            config_ram_set_hold_in_bl(true);
+                        } else {
+                            // Do nothing - bootloader will go to interface by default
+                        }
+                        break;
+                    case kTestAssertActionFile:
+                        // Test asserts
+                        util_assert(0);
+                        do_remount = false;
+                        break;
+                    case kRefreshActionFile:
+                        // Remount to update the drive
+                        break;
+                    case kEraseActionFile:
+                        erase_target();
+                        break;
+                    case kAutoResetConfigFile:
+                        config_set_auto_rst(true);
+                        break;
+                    case kHardResetConfigFile:
+                        config_set_auto_rst(false);
+                        break;
+                    case kAutomationOnConfigFile:
+                        config_set_automation_allowed(true);
+                        break;
+                    case kAutomationOffConfigFile:
+                        config_set_automation_allowed(false);
+                        break;
+                    case kOverflowOnConfigFile:
+                        config_set_overflow_detect(true);
+                        break;
+                    case kOverflowOffConfigFile:
+                        config_set_overflow_detect(false);
+                        break;
+                    case kMSDOnConfigFile:
+                        config_ram_set_disable_msd(false);
+                        break;
+                    case kMSDOffConfigFile:
+                        config_ram_set_disable_msd(true);
+                        break;
+                    case kPageEraseActionFile:
+                        config_ram_set_page_erase(true);
+                        break;
+                    case kChipEraseActionFile:
+                        config_ram_set_page_erase(false);
+                        break;
+                    default:
+                        util_assert(false);
+                }
+            }
+            else {
+                do_remount = false;
+            }
+        }
+
+        // Remount if requested.
+        if (do_remount) {
+            vfs_mngr_fs_remount();
+        }
+    }
+
+    else if (VFS_FILE_DELETED == change) {
+        if (!memcmp(filename, assert_file, sizeof(vfs_filename_t))) {
+            // Clear assert and remount to update the drive
+            util_assert_clear();
+            vfs_mngr_fs_remount();
+        }
+    }
+}
+
+void vfs_user_disconnecting()
+{
+    // Reset if programming was successful  //TODO - move to flash layer
+    if (daplink_is_bootloader() && (ERROR_SUCCESS == vfs_mngr_get_transfer_status())) {
+        SystemReset();
+    }
+
+    // If hold in bootloader has been set then reset after usb is disconnected
+    if (daplink_is_interface() && (config_ram_get_hold_in_bl() || config_ram_get_disable_msd()==1)) {
+        SystemReset();
+    }
+
+    remount_count++;
+}
+
+// Get the filesize from a filesize callback.
+// The file data must be null terminated for this to work correctly.
+static uint32_t get_file_size(vfs_read_cb_t read_func)
+{
+    // Determine size of the file by faking a read
+    return read_func(0, file_buffer, 1);
+}
+
+// File callback to be used with vfs_add_file to return file contents
+static uint32_t read_file_mbed_htm(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors)
+{
+    if (sector_offset != 0) {
+        return 0;
+    }
+
+    return update_html_file(data, VFS_SECTOR_SIZE);
+}
+
+// File callback to be used with vfs_add_file to return file contents
+static uint32_t read_file_details_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors)
+{
+
+    if (sector_offset != 0) {
+        return 0;
+    }
+
+    return update_details_txt_file(data, VFS_SECTOR_SIZE);
+}
+
+// Text representation of each error type, starting from the rightmost bit
+static const char* const error_type_names[] = {
+    "internal",
+    "transient",
+    "user",
+    "target",
+    "interface"
+};
+
+COMPILER_ASSERT(1 << ARRAY_SIZE(error_type_names) == ERROR_TYPE_MASK + 1);
+
+// File callback to be used with vfs_add_file to return file contents
+static uint32_t read_file_fail_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors)
+{
+    uint32_t size = 0;
+    char *buf = (char *)data;
+    error_t status = vfs_mngr_get_transfer_status();
+    const char *contents = error_get_string(status);
+    error_type_t type = error_get_type(status);
+
+    if (sector_offset != 0) {
+        return 0;
+    }
+
+    size += util_write_string(buf + size, error_prefix);
+    size += util_write_string(buf + size, contents);
+    size += util_write_string(buf + size, "\r\n");
+    size += util_write_string(buf + size, error_type_prefix);
+
+    // Write each applicable error type, separated by commas
+    int index = 0;
+    bool first = true;
+    while (type && index < ARRAY_SIZE(error_type_names)) {
+        if (!first) {
+            size += util_write_string(buf + size, ", ");
+        }
+        if (type & 1) {
+            size += util_write_string(buf + size, error_type_names[index]);
+            first = false;
+        }
+        index++;
+        type >>= 1;
+    }
+
+    size += util_write_string(buf + size, "\r\n");
+    return size;
+}
+
+// File callback to be used with vfs_add_file to return file contents
+static uint32_t read_file_assert_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors)
+{
+    uint32_t pos;
+    const char *source_str;
+    char *buf = (char *)data;
+    uint32_t * hexdumps = 0;
+    uint8_t valid_hexdumps = 0;
+    uint8_t index = 0;
+
+    if (sector_offset != 0) {
+        return 0;
+    }
+
+    pos = 0;
+
+    if (ASSERT_SOURCE_BL == assert_source) {
+        source_str = "Bootloader";
+    } else if (ASSERT_SOURCE_APP == assert_source) {
+        source_str = "Application";
+    } else {
+        source_str = 0;
+    }
+
+    pos += util_write_string(buf + pos, "Assert\r\n");
+    pos += util_write_string(buf + pos, "File: ");
+    pos += util_write_string(buf + pos, assert_buf);
+    pos += util_write_string(buf + pos, "\r\n");
+    pos += util_write_string(buf + pos, "Line: ");
+    pos += util_write_uint32(buf + pos, assert_line);
+    pos += util_write_string(buf + pos, "\r\n");
+
+    if (source_str != 0) {
+        pos += util_write_string(buf + pos, "Source: ");
+        pos += util_write_string(buf + pos, source_str);
+        pos += util_write_string(buf + pos, "\r\n");
+    }
+
+    valid_hexdumps = config_ram_get_hexdumps(&hexdumps);
+    if ((valid_hexdumps > 0) && (hexdumps != 0)) {
+        //print hexdumps
+        pos += util_write_string(buf + pos, "Hexdumps\r\n");
+        while ((index < valid_hexdumps) && ((pos + 10) < VFS_SECTOR_SIZE)) { //hexdumps + newline is always 10 characters
+            pos += util_write_hex32(buf + pos, hexdumps[index++]);
+            pos += util_write_string(buf + pos, "\r\n");
+        }
+    }
+
+    return pos;
+}
+
+// File callback to be used with vfs_add_file to return file contents
+static uint32_t read_file_need_bl_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors)
+{
+    const char *contents = "A bootloader update was started but unable to complete.\r\n"
+                           "Reload the bootloader to fix this error message.\r\n";
+    uint32_t size = strlen(contents);
+
+    if (sector_offset != 0) {
+        return 0;
+    }
+
+    memcpy(data, contents, size);
+    return size;
+}
+
+
+static uint32_t update_html_file(uint8_t *data, uint32_t datasize)
+{
+    char *buf = (char *)data;
+    //Needed by expand_info strlen
+    memset(buf, 0, datasize);
+    memcpy(buf, mbed_redirect_file, strlen(mbed_redirect_file));
+    //expand
+    return expand_info(data, datasize);
+}
+
+static uint32_t update_details_txt_file(uint8_t *data, uint32_t datasize)
+{
+    uint32_t pos=0;
+    const char *mode_str;
+
+    char *buf = (char *)data;
+
+    //Needed by expand_info strlen
+    memset(buf, 0, datasize);
+
+    pos += util_write_string(buf + pos, "# DAPLink Firmware - see https://mbed.com/daplink\r\n");
+    // Unique ID
+    pos += util_write_string(buf + pos, "Unique ID: @U\r\n");
+    // HIC ID
+    pos += util_write_string(buf + pos, "HIC ID: @D\r\n");
+    // Settings
+    pos += util_write_string(buf + pos, "Auto Reset: ");
+    pos += util_write_string(buf + pos, config_get_auto_rst() ? "1" : "0");
+    pos += util_write_string(buf + pos, "\r\n");
+    pos += util_write_string(buf + pos, "Automation allowed: ");
+    pos += util_write_string(buf + pos, config_get_automation_allowed() ? "1" : "0");
+    pos += util_write_string(buf + pos, "\r\n");
+    pos += util_write_string(buf + pos, "Overflow detection: ");
+    pos += util_write_string(buf + pos, config_get_overflow_detect() ? "1" : "0");
+    pos += util_write_string(buf + pos, "\r\n");
+    pos += util_write_string(buf + pos, "Page erasing: ");
+    pos += util_write_string(buf + pos, config_ram_get_page_erase() ? "1" : "0");
+    pos += util_write_string(buf + pos, "\r\n");
+    // Current mode
+    mode_str = daplink_is_bootloader() ? "Bootloader" : "Interface";
+    pos += util_write_string(buf + pos, "Daplink Mode: ");
+    pos += util_write_string(buf + pos, mode_str);
+    pos += util_write_string(buf + pos, "\r\n");
+    // Current build's version
+    pos += util_write_string(buf + pos, mode_str);
+    pos += util_write_string(buf + pos, " Version: @V\r\n");
+
+    // Other builds version (bl or if)
+    if (!daplink_is_bootloader() && info_get_bootloader_present()) {
+        pos += util_write_string(buf + pos, "Bootloader Version: ");
+        pos += util_write_uint32_zp(buf + pos, info_get_bootloader_version(), 4);
+        pos += util_write_string(buf + pos, "\r\n");
+    }
+
+    if (!daplink_is_interface() && info_get_interface_present()) {
+        pos += util_write_string(buf + pos, "Interface Version: ");
+        pos += util_write_uint32_zp(buf + pos, info_get_interface_version(), 4);
+        pos += util_write_string(buf + pos, "\r\n");
+    }
+
+    // GIT sha
+    pos += util_write_string(buf + pos, "Git SHA: ");
+    pos += util_write_string(buf + pos, GIT_COMMIT_SHA);
+    pos += util_write_string(buf + pos, "\r\n");
+    // Local modifications when making the build
+    pos += util_write_string(buf + pos, "Local Mods: ");
+    pos += util_write_uint32(buf + pos, GIT_LOCAL_MODS);
+    pos += util_write_string(buf + pos, "\r\n");
+    // Supported USB endpoints
+    pos += util_write_string(buf + pos, "USB Interfaces: ");
+#ifdef MSC_ENDPOINT
+    pos += util_write_string(buf + pos, "MSD");
+#endif
+#ifdef CDC_ENDPOINT
+    pos += util_write_string(buf + pos, ", CDC");
+#endif
+#ifdef HID_ENDPOINT
+    pos += util_write_string(buf + pos, ", HID");
+#endif
+#if (WEBUSB_INTERFACE)
+    pos += util_write_string(buf + pos, ", WebUSB");
+#endif
+    pos += util_write_string(buf + pos, "\r\n");
+
+    // CRC of the bootloader (if there is one)
+    if (info_get_bootloader_present()) {
+        pos += util_write_string(buf + pos, "Bootloader CRC: 0x");
+        pos += util_write_hex32(buf + pos, info_get_crc_bootloader());
+        pos += util_write_string(buf + pos, "\r\n");
+    }
+
+    // CRC of the interface
+    pos += util_write_string(buf + pos, "Interface CRC: 0x");
+    pos += util_write_hex32(buf + pos, info_get_crc_interface());
+    pos += util_write_string(buf + pos, "\r\n");
+
+    // Number of remounts that have occurred
+    pos += util_write_string(buf + pos, "Remount count: ");
+    pos += util_write_uint32(buf + pos, remount_count);
+    pos += util_write_string(buf + pos, "\r\n");
+
+    //Target URL
+    pos += util_write_string(buf + pos, "URL: @R\r\n");
+
+    return expand_info(data, datasize);
+}
+
+// Fill buf with the contents of the mbed redirect file by
+// expanding the special characters in mbed_redirect_file.
+static uint32_t expand_info(uint8_t *buf, uint32_t bufsize)
+{
+    uint8_t *orig_buf = buf;
+    uint8_t *insert_string;
+
+    do {
+        // Look for key or the end of the string
+        while ((*buf != '@') && (*buf != 0)) {
+            buf++;
+        }
+
+        // If key was found then replace it
+        if ('@' == *buf) {
+            switch (*(buf + 1)) {
+                case 'm':
+                case 'M':   // MAC address
+                    insert_string = (uint8_t *)info_get_mac();
+                    break;
+
+                case 'u':
+                case 'U':   // UUID
+                    insert_string = (uint8_t *)info_get_unique_id();
+                    break;
+
+                case 'b':
+                case 'B':   // Board ID
+                    insert_string = (uint8_t *)info_get_board_id();
+                    break;
+
+                case 'h':
+                case 'H':   // Host ID
+                    insert_string = (uint8_t *)info_get_host_id();
+                    break;
+
+                case 't':
+                case 'T':   // Target ID
+                    insert_string = (uint8_t *)info_get_target_id();
+                    break;
+
+                case 'd':
+                case 'D':   // HIC
+                    insert_string = (uint8_t *)info_get_hic_id();
+                    break;
+
+                case 'v':
+                case 'V':   // Firmware version
+                    insert_string = (uint8_t *)info_get_version();
+                    break;
+
+                case 'r':
+                case 'R':   // URL replacement
+                    insert_string = (uint8_t *)get_daplink_target_url();
+                    break;
+
+                default:
+                    insert_string = (uint8_t *)"ERROR";
+                    break;
+            }
+
+            // Remove strip_count characters from the start of buf and then insert
+            // insert_string at the new start of buf.
+            uint32_t buf_len = strlen((const char *)buf);
+            uint32_t str_len = strlen((const char *)insert_string);
+            //buffer overflow check on insert
+            if( (buf + str_len + buf_len - 2) < (orig_buf+bufsize)){
+                // push out string
+                memmove(buf + str_len, buf + 2, buf_len - 2);
+                // insert
+                memcpy(buf, insert_string, str_len);
+            }else{
+                //stop the string expansion and leave as it is
+                buf += buf_len;
+                break;
+            }
+
+        }
+    } while (*buf != '\0');
+
+    return (buf - orig_buf);
+}
+
+// Initialize flash algo, erase flash, uninit algo
+static void erase_target(void)
+{
+    flash_intf_target->init();
+    flash_intf_target->erase_chip();
+    flash_intf_target->uninit();
+}