Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.
Upstream: https://github.com/ARMmbed/DAPLink
source/daplink/drag-n-drop/vfs_user.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 vfs_user.c |
Pawel Zarembski |
0:01f31e923fe2 | 3 | * @brief Implementation of vfs_user.h |
Pawel Zarembski |
0:01f31e923fe2 | 4 | * |
Pawel Zarembski |
0:01f31e923fe2 | 5 | * DAPLink Interface Firmware |
Pawel Zarembski |
0:01f31e923fe2 | 6 | * Copyright (c) 2009-2020, ARM Limited, All Rights Reserved |
Pawel Zarembski |
0:01f31e923fe2 | 7 | * Copyright 2019, Cypress Semiconductor Corporation |
Pawel Zarembski |
0:01f31e923fe2 | 8 | * or a subsidiary of Cypress Semiconductor Corporation. |
Pawel Zarembski |
0:01f31e923fe2 | 9 | * SPDX-License-Identifier: Apache-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 10 | * |
Pawel Zarembski |
0:01f31e923fe2 | 11 | * Licensed under the Apache License, Version 2.0 (the "License"); you may |
Pawel Zarembski |
0:01f31e923fe2 | 12 | * not use this file except in compliance with the License. |
Pawel Zarembski |
0:01f31e923fe2 | 13 | * You may obtain a copy of the License at |
Pawel Zarembski |
0:01f31e923fe2 | 14 | * |
Pawel Zarembski |
0:01f31e923fe2 | 15 | * http://www.apache.org/licenses/LICENSE-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 16 | * |
Pawel Zarembski |
0:01f31e923fe2 | 17 | * Unless required by applicable law or agreed to in writing, software |
Pawel Zarembski |
0:01f31e923fe2 | 18 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
Pawel Zarembski |
0:01f31e923fe2 | 19 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
Pawel Zarembski |
0:01f31e923fe2 | 20 | * See the License for the specific language governing permissions and |
Pawel Zarembski |
0:01f31e923fe2 | 21 | * limitations under the License. |
Pawel Zarembski |
0:01f31e923fe2 | 22 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 23 | |
Pawel Zarembski |
0:01f31e923fe2 | 24 | #include <stdbool.h> |
Pawel Zarembski |
0:01f31e923fe2 | 25 | #include <ctype.h> |
Pawel Zarembski |
0:01f31e923fe2 | 26 | #include <string.h> |
Pawel Zarembski |
0:01f31e923fe2 | 27 | |
Pawel Zarembski |
0:01f31e923fe2 | 28 | #include "vfs_user.h" |
Pawel Zarembski |
0:01f31e923fe2 | 29 | #include "vfs_manager.h" |
Pawel Zarembski |
0:01f31e923fe2 | 30 | #include "error.h" |
Pawel Zarembski |
0:01f31e923fe2 | 31 | #include "util.h" |
Pawel Zarembski |
0:01f31e923fe2 | 32 | #include "settings.h" |
Pawel Zarembski |
0:01f31e923fe2 | 33 | #include "daplink.h" |
Pawel Zarembski |
0:01f31e923fe2 | 34 | #include "version_git.h" |
Pawel Zarembski |
0:01f31e923fe2 | 35 | #include "info.h" |
Pawel Zarembski |
0:01f31e923fe2 | 36 | #include "gpio.h" // for gpio_get_sw_reset |
Pawel Zarembski |
0:01f31e923fe2 | 37 | #include "flash_intf.h" // for flash_intf_target |
Pawel Zarembski |
0:01f31e923fe2 | 38 | #include "cortex_m.h" |
Pawel Zarembski |
0:01f31e923fe2 | 39 | #include "target_board.h" |
Pawel Zarembski |
0:01f31e923fe2 | 40 | #include "flash_manager.h" |
Pawel Zarembski |
0:01f31e923fe2 | 41 | |
Pawel Zarembski |
0:01f31e923fe2 | 42 | //! @brief Size in bytes of the virtual disk. |
Pawel Zarembski |
0:01f31e923fe2 | 43 | //! |
Pawel Zarembski |
0:01f31e923fe2 | 44 | //! Must be bigger than 4x the flash size of the biggest supported |
Pawel Zarembski |
0:01f31e923fe2 | 45 | //! device. This is to accomodate for hex file programming. |
Pawel Zarembski |
0:01f31e923fe2 | 46 | #define VFS_DISK_SIZE (MB(64)) |
Pawel Zarembski |
0:01f31e923fe2 | 47 | |
Pawel Zarembski |
0:01f31e923fe2 | 48 | //! @brief Constants for magic action or config files. |
Pawel Zarembski |
0:01f31e923fe2 | 49 | //! |
Pawel Zarembski |
0:01f31e923fe2 | 50 | //! The "magic files" are files with a special name that if created on the USB MSC volume, will |
Pawel Zarembski |
0:01f31e923fe2 | 51 | //! cause an event. There are two classes of magic files: action files and config files. The former |
Pawel Zarembski |
0:01f31e923fe2 | 52 | //! causes a given action to take place, while the latter changes a persistent configuration setting |
Pawel Zarembski |
0:01f31e923fe2 | 53 | //! to a predetermined value. |
Pawel Zarembski |
0:01f31e923fe2 | 54 | //! |
Pawel Zarembski |
0:01f31e923fe2 | 55 | //! See #s_magic_file_info for the mapping of filenames to these enums. |
Pawel Zarembski |
0:01f31e923fe2 | 56 | typedef enum _magic_file { |
Pawel Zarembski |
0:01f31e923fe2 | 57 | kDAPLinkModeActionFile, //!< Switch between interface and bootloader. |
Pawel Zarembski |
0:01f31e923fe2 | 58 | kTestAssertActionFile, //!< Force an assertion for testing. |
Pawel Zarembski |
0:01f31e923fe2 | 59 | kRefreshActionFile, //!< Force a remount. |
Pawel Zarembski |
0:01f31e923fe2 | 60 | kEraseActionFile, //!< Erase the target flash. |
Pawel Zarembski |
0:01f31e923fe2 | 61 | kAutoResetConfigFile, //!< Enable reset after flash. |
Pawel Zarembski |
0:01f31e923fe2 | 62 | kHardResetConfigFile, //!< Disable reset after flash. |
Pawel Zarembski |
0:01f31e923fe2 | 63 | kAutomationOnConfigFile, //!< Enable automation. |
Pawel Zarembski |
0:01f31e923fe2 | 64 | kAutomationOffConfigFile, //!< Disable automation. |
Pawel Zarembski |
0:01f31e923fe2 | 65 | kOverflowOnConfigFile, //!< Enable UART overflow reporting. |
Pawel Zarembski |
0:01f31e923fe2 | 66 | kOverflowOffConfigFile, //!< Disable UART overflow reporting. |
Pawel Zarembski |
0:01f31e923fe2 | 67 | kMSDOnConfigFile, //!< Enable USB MSC. Uh.... |
Pawel Zarembski |
0:01f31e923fe2 | 68 | kMSDOffConfigFile, //!< Disable USB MSC. |
Pawel Zarembski |
0:01f31e923fe2 | 69 | kPageEraseActionFile, //!< Enable page programming and sector erase for drag and drop. |
Pawel Zarembski |
0:01f31e923fe2 | 70 | kChipEraseActionFile, //!< Enable page programming and chip erase for drag and drop. |
Pawel Zarembski |
0:01f31e923fe2 | 71 | } magic_file_t; |
Pawel Zarembski |
0:01f31e923fe2 | 72 | |
Pawel Zarembski |
0:01f31e923fe2 | 73 | //! @brief Mapping from filename string to magic file enum. |
Pawel Zarembski |
0:01f31e923fe2 | 74 | typedef struct _magic_file_info { |
Pawel Zarembski |
0:01f31e923fe2 | 75 | const char *name; //!< Name of the magic file, must be in 8.3 format. |
Pawel Zarembski |
0:01f31e923fe2 | 76 | magic_file_t which; //!< Enum for the file. |
Pawel Zarembski |
0:01f31e923fe2 | 77 | } magic_file_info_t; |
Pawel Zarembski |
0:01f31e923fe2 | 78 | |
Pawel Zarembski |
0:01f31e923fe2 | 79 | static const char mbed_redirect_file[] = |
Pawel Zarembski |
0:01f31e923fe2 | 80 | "<!doctype html>\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 81 | "<!-- mbed Platform Website and Authentication Shortcut -->\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 82 | "<html>\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 83 | "<head>\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 84 | "<meta charset=\"utf-8\">\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 85 | "<title>mbed Website Shortcut</title>\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 86 | "</head>\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 87 | "<body>\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 88 | "<script>\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 89 | "window.location.replace(\"@R\");\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 90 | "</script>\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 91 | "</body>\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 92 | "</html>\r\n"; |
Pawel Zarembski |
0:01f31e923fe2 | 93 | |
Pawel Zarembski |
0:01f31e923fe2 | 94 | static const char error_prefix[] = "error: "; |
Pawel Zarembski |
0:01f31e923fe2 | 95 | static const char error_type_prefix[] = "type: "; |
Pawel Zarembski |
0:01f31e923fe2 | 96 | |
Pawel Zarembski |
0:01f31e923fe2 | 97 | static const vfs_filename_t assert_file = "ASSERT TXT"; |
Pawel Zarembski |
0:01f31e923fe2 | 98 | |
Pawel Zarembski |
0:01f31e923fe2 | 99 | //! @brief Table of magic files and their names. |
Pawel Zarembski |
0:01f31e923fe2 | 100 | static const magic_file_info_t s_magic_file_info[] = { |
Pawel Zarembski |
0:01f31e923fe2 | 101 | { daplink_mode_file_name, kDAPLinkModeActionFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 102 | { "ASSERT ACT", kTestAssertActionFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 103 | { "REFRESH ACT", kRefreshActionFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 104 | { "ERASE ACT", kEraseActionFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 105 | { "AUTO_RSTCFG", kAutoResetConfigFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 106 | { "HARD_RSTCFG", kHardResetConfigFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 107 | { "AUTO_ON CFG", kAutomationOnConfigFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 108 | { "AUTO_OFFCFG", kAutomationOffConfigFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 109 | { "OVFL_ON CFG", kOverflowOnConfigFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 110 | { "OVFL_OFFCFG", kOverflowOffConfigFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 111 | { "MSD_ON CFG", kMSDOnConfigFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 112 | { "MSD_OFF CFG", kMSDOffConfigFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 113 | { "PAGE_ON ACT", kPageEraseActionFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 114 | { "PAGE_OFFACT", kChipEraseActionFile }, |
Pawel Zarembski |
0:01f31e923fe2 | 115 | }; |
Pawel Zarembski |
0:01f31e923fe2 | 116 | |
Pawel Zarembski |
0:01f31e923fe2 | 117 | static uint8_t file_buffer[VFS_SECTOR_SIZE]; |
Pawel Zarembski |
0:01f31e923fe2 | 118 | static char assert_buf[64 + 1]; |
Pawel Zarembski |
0:01f31e923fe2 | 119 | static uint16_t assert_line; |
Pawel Zarembski |
0:01f31e923fe2 | 120 | static assert_source_t assert_source; |
Pawel Zarembski |
0:01f31e923fe2 | 121 | static uint32_t remount_count; |
Pawel Zarembski |
0:01f31e923fe2 | 122 | |
Pawel Zarembski |
0:01f31e923fe2 | 123 | static uint32_t get_file_size(vfs_read_cb_t read_func); |
Pawel Zarembski |
0:01f31e923fe2 | 124 | |
Pawel Zarembski |
0:01f31e923fe2 | 125 | static uint32_t read_file_mbed_htm(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors); |
Pawel Zarembski |
0:01f31e923fe2 | 126 | static uint32_t read_file_details_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors); |
Pawel Zarembski |
0:01f31e923fe2 | 127 | static uint32_t read_file_fail_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors); |
Pawel Zarembski |
0:01f31e923fe2 | 128 | static uint32_t read_file_assert_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors); |
Pawel Zarembski |
0:01f31e923fe2 | 129 | static uint32_t read_file_need_bl_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors); |
Pawel Zarembski |
0:01f31e923fe2 | 130 | |
Pawel Zarembski |
0:01f31e923fe2 | 131 | static uint32_t update_html_file(uint8_t *data, uint32_t datasize); |
Pawel Zarembski |
0:01f31e923fe2 | 132 | static uint32_t update_details_txt_file(uint8_t *data, uint32_t datasize); |
Pawel Zarembski |
0:01f31e923fe2 | 133 | static void erase_target(void); |
Pawel Zarembski |
0:01f31e923fe2 | 134 | |
Pawel Zarembski |
0:01f31e923fe2 | 135 | static uint32_t expand_info(uint8_t *buf, uint32_t bufsize); |
Pawel Zarembski |
0:01f31e923fe2 | 136 | |
Pawel Zarembski |
0:01f31e923fe2 | 137 | void vfs_user_build_filesystem() |
Pawel Zarembski |
0:01f31e923fe2 | 138 | { |
Pawel Zarembski |
0:01f31e923fe2 | 139 | uint32_t file_size; |
Pawel Zarembski |
0:01f31e923fe2 | 140 | vfs_file_t file_handle; |
Pawel Zarembski |
0:01f31e923fe2 | 141 | // Setup the filesystem based on target parameters |
Pawel Zarembski |
0:01f31e923fe2 | 142 | vfs_init(get_daplink_drive_name(), VFS_DISK_SIZE); |
Pawel Zarembski |
0:01f31e923fe2 | 143 | // MBED.HTM |
Pawel Zarembski |
0:01f31e923fe2 | 144 | file_size = get_file_size(read_file_mbed_htm); |
Pawel Zarembski |
0:01f31e923fe2 | 145 | vfs_create_file(get_daplink_url_name(), read_file_mbed_htm, 0, file_size); |
Pawel Zarembski |
0:01f31e923fe2 | 146 | // DETAILS.TXT |
Pawel Zarembski |
0:01f31e923fe2 | 147 | file_size = get_file_size(read_file_details_txt); |
Pawel Zarembski |
0:01f31e923fe2 | 148 | vfs_create_file("DETAILS TXT", read_file_details_txt, 0, file_size); |
Pawel Zarembski |
0:01f31e923fe2 | 149 | |
Pawel Zarembski |
0:01f31e923fe2 | 150 | // FAIL.TXT |
Pawel Zarembski |
0:01f31e923fe2 | 151 | if (vfs_mngr_get_transfer_status() != ERROR_SUCCESS) { |
Pawel Zarembski |
0:01f31e923fe2 | 152 | file_size = get_file_size(read_file_fail_txt); |
Pawel Zarembski |
0:01f31e923fe2 | 153 | vfs_create_file("FAIL TXT", read_file_fail_txt, 0, file_size); |
Pawel Zarembski |
0:01f31e923fe2 | 154 | } |
Pawel Zarembski |
0:01f31e923fe2 | 155 | |
Pawel Zarembski |
0:01f31e923fe2 | 156 | // ASSERT.TXT |
Pawel Zarembski |
0:01f31e923fe2 | 157 | if (config_ram_get_assert(assert_buf, sizeof(assert_buf), &assert_line, &assert_source)) { |
Pawel Zarembski |
0:01f31e923fe2 | 158 | file_size = get_file_size(read_file_assert_txt); |
Pawel Zarembski |
0:01f31e923fe2 | 159 | file_handle = vfs_create_file(assert_file, read_file_assert_txt, 0, file_size); |
Pawel Zarembski |
0:01f31e923fe2 | 160 | vfs_file_set_attr(file_handle, (vfs_file_attr_bit_t)0); // Remove read only attribute |
Pawel Zarembski |
0:01f31e923fe2 | 161 | } |
Pawel Zarembski |
0:01f31e923fe2 | 162 | |
Pawel Zarembski |
0:01f31e923fe2 | 163 | // NEED_BL.TXT |
Pawel Zarembski |
0:01f31e923fe2 | 164 | volatile uint32_t bl_start = DAPLINK_ROM_BL_START; // Silence warnings about null pointer |
Pawel Zarembski |
0:01f31e923fe2 | 165 | volatile uint32_t if_start = DAPLINK_ROM_IF_START; // Silence warnings about null pointer |
Pawel Zarembski |
0:01f31e923fe2 | 166 | |
Pawel Zarembski |
0:01f31e923fe2 | 167 | if (daplink_is_interface() && |
Pawel Zarembski |
0:01f31e923fe2 | 168 | (DAPLINK_ROM_BL_SIZE > 0) && |
Pawel Zarembski |
0:01f31e923fe2 | 169 | (0 == memcmp((void *)bl_start, (void *)if_start, DAPLINK_MIN_WRITE_SIZE))) { |
Pawel Zarembski |
0:01f31e923fe2 | 170 | // If the bootloader contains a copy of the interfaces vector table |
Pawel Zarembski |
0:01f31e923fe2 | 171 | // then an error occurred when updating so warn that the bootloader is |
Pawel Zarembski |
0:01f31e923fe2 | 172 | // missing. |
Pawel Zarembski |
0:01f31e923fe2 | 173 | file_size = get_file_size(read_file_need_bl_txt); |
Pawel Zarembski |
0:01f31e923fe2 | 174 | vfs_create_file("NEED_BL TXT", read_file_need_bl_txt, 0, file_size); |
Pawel Zarembski |
0:01f31e923fe2 | 175 | } |
Pawel Zarembski |
0:01f31e923fe2 | 176 | } |
Pawel Zarembski |
0:01f31e923fe2 | 177 | |
Pawel Zarembski |
0:01f31e923fe2 | 178 | // Default file change hook. |
Pawel Zarembski |
0:01f31e923fe2 | 179 | __WEAK bool vfs_user_file_change_handler_hook(const vfs_filename_t filename, vfs_file_change_t change, |
Pawel Zarembski |
0:01f31e923fe2 | 180 | vfs_file_t file, vfs_file_t new_file_data) |
Pawel Zarembski |
0:01f31e923fe2 | 181 | { |
Pawel Zarembski |
0:01f31e923fe2 | 182 | return false; |
Pawel Zarembski |
0:01f31e923fe2 | 183 | } |
Pawel Zarembski |
0:01f31e923fe2 | 184 | |
Pawel Zarembski |
0:01f31e923fe2 | 185 | // Default magic file hook. |
Pawel Zarembski |
0:01f31e923fe2 | 186 | __WEAK bool vfs_user_magic_file_hook(const vfs_filename_t filename, bool *do_remount) |
Pawel Zarembski |
0:01f31e923fe2 | 187 | { |
Pawel Zarembski |
0:01f31e923fe2 | 188 | return false; |
Pawel Zarembski |
0:01f31e923fe2 | 189 | } |
Pawel Zarembski |
0:01f31e923fe2 | 190 | |
Pawel Zarembski |
0:01f31e923fe2 | 191 | // Callback to handle changes to the root directory. Should be used with vfs_set_file_change_callback |
Pawel Zarembski |
0:01f31e923fe2 | 192 | 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) |
Pawel Zarembski |
0:01f31e923fe2 | 193 | { |
Pawel Zarembski |
0:01f31e923fe2 | 194 | // Call file changed hook. If it returns true, then it handled the request and we have nothing |
Pawel Zarembski |
0:01f31e923fe2 | 195 | // more to do. |
Pawel Zarembski |
0:01f31e923fe2 | 196 | if (vfs_user_file_change_handler_hook(filename, change, file, new_file_data)) { |
Pawel Zarembski |
0:01f31e923fe2 | 197 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 198 | } |
Pawel Zarembski |
0:01f31e923fe2 | 199 | |
Pawel Zarembski |
0:01f31e923fe2 | 200 | // Allow settings to be changed if automation mode is |
Pawel Zarembski |
0:01f31e923fe2 | 201 | // enabled or if the user is holding the reset button |
Pawel Zarembski |
0:01f31e923fe2 | 202 | bool btn_pressed = gpio_get_reset_btn(); |
Pawel Zarembski |
0:01f31e923fe2 | 203 | |
Pawel Zarembski |
0:01f31e923fe2 | 204 | if (!btn_pressed && !config_get_automation_allowed()) { |
Pawel Zarembski |
0:01f31e923fe2 | 205 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 206 | } |
Pawel Zarembski |
0:01f31e923fe2 | 207 | |
Pawel Zarembski |
0:01f31e923fe2 | 208 | if (VFS_FILE_CHANGED == change) { |
Pawel Zarembski |
0:01f31e923fe2 | 209 | // Unused |
Pawel Zarembski |
0:01f31e923fe2 | 210 | } |
Pawel Zarembski |
0:01f31e923fe2 | 211 | |
Pawel Zarembski |
0:01f31e923fe2 | 212 | else if (VFS_FILE_CREATED == change) { |
Pawel Zarembski |
0:01f31e923fe2 | 213 | bool do_remount = true; // Almost all magic files cause a remount. |
Pawel Zarembski |
0:01f31e923fe2 | 214 | int32_t which_magic_file = -1; |
Pawel Zarembski |
0:01f31e923fe2 | 215 | |
Pawel Zarembski |
0:01f31e923fe2 | 216 | // Let the hook examine the filename. If it returned false then look for the standard |
Pawel Zarembski |
0:01f31e923fe2 | 217 | // magic files. |
Pawel Zarembski |
0:01f31e923fe2 | 218 | if (!vfs_user_magic_file_hook(filename, &do_remount)) { |
Pawel Zarembski |
0:01f31e923fe2 | 219 | // Compare the new file's name to our table of magic filenames. |
Pawel Zarembski |
0:01f31e923fe2 | 220 | for (int32_t i = 0; i < ARRAY_SIZE(s_magic_file_info); ++i) { |
Pawel Zarembski |
0:01f31e923fe2 | 221 | if (!memcmp(filename, s_magic_file_info[i].name, sizeof(vfs_filename_t))) { |
Pawel Zarembski |
0:01f31e923fe2 | 222 | which_magic_file = i; |
Pawel Zarembski |
0:01f31e923fe2 | 223 | } |
Pawel Zarembski |
0:01f31e923fe2 | 224 | } |
Pawel Zarembski |
0:01f31e923fe2 | 225 | |
Pawel Zarembski |
0:01f31e923fe2 | 226 | // Check if we matched a magic filename and handle it. |
Pawel Zarembski |
0:01f31e923fe2 | 227 | if (which_magic_file != -1) { |
Pawel Zarembski |
0:01f31e923fe2 | 228 | switch (which_magic_file) { |
Pawel Zarembski |
0:01f31e923fe2 | 229 | case kDAPLinkModeActionFile: |
Pawel Zarembski |
0:01f31e923fe2 | 230 | if (daplink_is_interface()) { |
Pawel Zarembski |
0:01f31e923fe2 | 231 | config_ram_set_hold_in_bl(true); |
Pawel Zarembski |
0:01f31e923fe2 | 232 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 233 | // Do nothing - bootloader will go to interface by default |
Pawel Zarembski |
0:01f31e923fe2 | 234 | } |
Pawel Zarembski |
0:01f31e923fe2 | 235 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 236 | case kTestAssertActionFile: |
Pawel Zarembski |
0:01f31e923fe2 | 237 | // Test asserts |
Pawel Zarembski |
0:01f31e923fe2 | 238 | util_assert(0); |
Pawel Zarembski |
0:01f31e923fe2 | 239 | do_remount = false; |
Pawel Zarembski |
0:01f31e923fe2 | 240 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 241 | case kRefreshActionFile: |
Pawel Zarembski |
0:01f31e923fe2 | 242 | // Remount to update the drive |
Pawel Zarembski |
0:01f31e923fe2 | 243 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 244 | case kEraseActionFile: |
Pawel Zarembski |
0:01f31e923fe2 | 245 | erase_target(); |
Pawel Zarembski |
0:01f31e923fe2 | 246 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 247 | case kAutoResetConfigFile: |
Pawel Zarembski |
0:01f31e923fe2 | 248 | config_set_auto_rst(true); |
Pawel Zarembski |
0:01f31e923fe2 | 249 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 250 | case kHardResetConfigFile: |
Pawel Zarembski |
0:01f31e923fe2 | 251 | config_set_auto_rst(false); |
Pawel Zarembski |
0:01f31e923fe2 | 252 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 253 | case kAutomationOnConfigFile: |
Pawel Zarembski |
0:01f31e923fe2 | 254 | config_set_automation_allowed(true); |
Pawel Zarembski |
0:01f31e923fe2 | 255 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 256 | case kAutomationOffConfigFile: |
Pawel Zarembski |
0:01f31e923fe2 | 257 | config_set_automation_allowed(false); |
Pawel Zarembski |
0:01f31e923fe2 | 258 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 259 | case kOverflowOnConfigFile: |
Pawel Zarembski |
0:01f31e923fe2 | 260 | config_set_overflow_detect(true); |
Pawel Zarembski |
0:01f31e923fe2 | 261 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 262 | case kOverflowOffConfigFile: |
Pawel Zarembski |
0:01f31e923fe2 | 263 | config_set_overflow_detect(false); |
Pawel Zarembski |
0:01f31e923fe2 | 264 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 265 | case kMSDOnConfigFile: |
Pawel Zarembski |
0:01f31e923fe2 | 266 | config_ram_set_disable_msd(false); |
Pawel Zarembski |
0:01f31e923fe2 | 267 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 268 | case kMSDOffConfigFile: |
Pawel Zarembski |
0:01f31e923fe2 | 269 | config_ram_set_disable_msd(true); |
Pawel Zarembski |
0:01f31e923fe2 | 270 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 271 | case kPageEraseActionFile: |
Pawel Zarembski |
0:01f31e923fe2 | 272 | config_ram_set_page_erase(true); |
Pawel Zarembski |
0:01f31e923fe2 | 273 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 274 | case kChipEraseActionFile: |
Pawel Zarembski |
0:01f31e923fe2 | 275 | config_ram_set_page_erase(false); |
Pawel Zarembski |
0:01f31e923fe2 | 276 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 277 | default: |
Pawel Zarembski |
0:01f31e923fe2 | 278 | util_assert(false); |
Pawel Zarembski |
0:01f31e923fe2 | 279 | } |
Pawel Zarembski |
0:01f31e923fe2 | 280 | } |
Pawel Zarembski |
0:01f31e923fe2 | 281 | else { |
Pawel Zarembski |
0:01f31e923fe2 | 282 | do_remount = false; |
Pawel Zarembski |
0:01f31e923fe2 | 283 | } |
Pawel Zarembski |
0:01f31e923fe2 | 284 | } |
Pawel Zarembski |
0:01f31e923fe2 | 285 | |
Pawel Zarembski |
0:01f31e923fe2 | 286 | // Remount if requested. |
Pawel Zarembski |
0:01f31e923fe2 | 287 | if (do_remount) { |
Pawel Zarembski |
0:01f31e923fe2 | 288 | vfs_mngr_fs_remount(); |
Pawel Zarembski |
0:01f31e923fe2 | 289 | } |
Pawel Zarembski |
0:01f31e923fe2 | 290 | } |
Pawel Zarembski |
0:01f31e923fe2 | 291 | |
Pawel Zarembski |
0:01f31e923fe2 | 292 | else if (VFS_FILE_DELETED == change) { |
Pawel Zarembski |
0:01f31e923fe2 | 293 | if (!memcmp(filename, assert_file, sizeof(vfs_filename_t))) { |
Pawel Zarembski |
0:01f31e923fe2 | 294 | // Clear assert and remount to update the drive |
Pawel Zarembski |
0:01f31e923fe2 | 295 | util_assert_clear(); |
Pawel Zarembski |
0:01f31e923fe2 | 296 | vfs_mngr_fs_remount(); |
Pawel Zarembski |
0:01f31e923fe2 | 297 | } |
Pawel Zarembski |
0:01f31e923fe2 | 298 | } |
Pawel Zarembski |
0:01f31e923fe2 | 299 | } |
Pawel Zarembski |
0:01f31e923fe2 | 300 | |
Pawel Zarembski |
0:01f31e923fe2 | 301 | void vfs_user_disconnecting() |
Pawel Zarembski |
0:01f31e923fe2 | 302 | { |
Pawel Zarembski |
0:01f31e923fe2 | 303 | // Reset if programming was successful //TODO - move to flash layer |
Pawel Zarembski |
0:01f31e923fe2 | 304 | if (daplink_is_bootloader() && (ERROR_SUCCESS == vfs_mngr_get_transfer_status())) { |
Pawel Zarembski |
0:01f31e923fe2 | 305 | SystemReset(); |
Pawel Zarembski |
0:01f31e923fe2 | 306 | } |
Pawel Zarembski |
0:01f31e923fe2 | 307 | |
Pawel Zarembski |
0:01f31e923fe2 | 308 | // If hold in bootloader has been set then reset after usb is disconnected |
Pawel Zarembski |
0:01f31e923fe2 | 309 | if (daplink_is_interface() && (config_ram_get_hold_in_bl() || config_ram_get_disable_msd()==1)) { |
Pawel Zarembski |
0:01f31e923fe2 | 310 | SystemReset(); |
Pawel Zarembski |
0:01f31e923fe2 | 311 | } |
Pawel Zarembski |
0:01f31e923fe2 | 312 | |
Pawel Zarembski |
0:01f31e923fe2 | 313 | remount_count++; |
Pawel Zarembski |
0:01f31e923fe2 | 314 | } |
Pawel Zarembski |
0:01f31e923fe2 | 315 | |
Pawel Zarembski |
0:01f31e923fe2 | 316 | // Get the filesize from a filesize callback. |
Pawel Zarembski |
0:01f31e923fe2 | 317 | // The file data must be null terminated for this to work correctly. |
Pawel Zarembski |
0:01f31e923fe2 | 318 | static uint32_t get_file_size(vfs_read_cb_t read_func) |
Pawel Zarembski |
0:01f31e923fe2 | 319 | { |
Pawel Zarembski |
0:01f31e923fe2 | 320 | // Determine size of the file by faking a read |
Pawel Zarembski |
0:01f31e923fe2 | 321 | return read_func(0, file_buffer, 1); |
Pawel Zarembski |
0:01f31e923fe2 | 322 | } |
Pawel Zarembski |
0:01f31e923fe2 | 323 | |
Pawel Zarembski |
0:01f31e923fe2 | 324 | // File callback to be used with vfs_add_file to return file contents |
Pawel Zarembski |
0:01f31e923fe2 | 325 | static uint32_t read_file_mbed_htm(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors) |
Pawel Zarembski |
0:01f31e923fe2 | 326 | { |
Pawel Zarembski |
0:01f31e923fe2 | 327 | if (sector_offset != 0) { |
Pawel Zarembski |
0:01f31e923fe2 | 328 | return 0; |
Pawel Zarembski |
0:01f31e923fe2 | 329 | } |
Pawel Zarembski |
0:01f31e923fe2 | 330 | |
Pawel Zarembski |
0:01f31e923fe2 | 331 | return update_html_file(data, VFS_SECTOR_SIZE); |
Pawel Zarembski |
0:01f31e923fe2 | 332 | } |
Pawel Zarembski |
0:01f31e923fe2 | 333 | |
Pawel Zarembski |
0:01f31e923fe2 | 334 | // File callback to be used with vfs_add_file to return file contents |
Pawel Zarembski |
0:01f31e923fe2 | 335 | static uint32_t read_file_details_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors) |
Pawel Zarembski |
0:01f31e923fe2 | 336 | { |
Pawel Zarembski |
0:01f31e923fe2 | 337 | |
Pawel Zarembski |
0:01f31e923fe2 | 338 | if (sector_offset != 0) { |
Pawel Zarembski |
0:01f31e923fe2 | 339 | return 0; |
Pawel Zarembski |
0:01f31e923fe2 | 340 | } |
Pawel Zarembski |
0:01f31e923fe2 | 341 | |
Pawel Zarembski |
0:01f31e923fe2 | 342 | return update_details_txt_file(data, VFS_SECTOR_SIZE); |
Pawel Zarembski |
0:01f31e923fe2 | 343 | } |
Pawel Zarembski |
0:01f31e923fe2 | 344 | |
Pawel Zarembski |
0:01f31e923fe2 | 345 | // Text representation of each error type, starting from the rightmost bit |
Pawel Zarembski |
0:01f31e923fe2 | 346 | static const char* const error_type_names[] = { |
Pawel Zarembski |
0:01f31e923fe2 | 347 | "internal", |
Pawel Zarembski |
0:01f31e923fe2 | 348 | "transient", |
Pawel Zarembski |
0:01f31e923fe2 | 349 | "user", |
Pawel Zarembski |
0:01f31e923fe2 | 350 | "target", |
Pawel Zarembski |
0:01f31e923fe2 | 351 | "interface" |
Pawel Zarembski |
0:01f31e923fe2 | 352 | }; |
Pawel Zarembski |
0:01f31e923fe2 | 353 | |
Pawel Zarembski |
0:01f31e923fe2 | 354 | COMPILER_ASSERT(1 << ARRAY_SIZE(error_type_names) == ERROR_TYPE_MASK + 1); |
Pawel Zarembski |
0:01f31e923fe2 | 355 | |
Pawel Zarembski |
0:01f31e923fe2 | 356 | // File callback to be used with vfs_add_file to return file contents |
Pawel Zarembski |
0:01f31e923fe2 | 357 | static uint32_t read_file_fail_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors) |
Pawel Zarembski |
0:01f31e923fe2 | 358 | { |
Pawel Zarembski |
0:01f31e923fe2 | 359 | uint32_t size = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 360 | char *buf = (char *)data; |
Pawel Zarembski |
0:01f31e923fe2 | 361 | error_t status = vfs_mngr_get_transfer_status(); |
Pawel Zarembski |
0:01f31e923fe2 | 362 | const char *contents = error_get_string(status); |
Pawel Zarembski |
0:01f31e923fe2 | 363 | error_type_t type = error_get_type(status); |
Pawel Zarembski |
0:01f31e923fe2 | 364 | |
Pawel Zarembski |
0:01f31e923fe2 | 365 | if (sector_offset != 0) { |
Pawel Zarembski |
0:01f31e923fe2 | 366 | return 0; |
Pawel Zarembski |
0:01f31e923fe2 | 367 | } |
Pawel Zarembski |
0:01f31e923fe2 | 368 | |
Pawel Zarembski |
0:01f31e923fe2 | 369 | size += util_write_string(buf + size, error_prefix); |
Pawel Zarembski |
0:01f31e923fe2 | 370 | size += util_write_string(buf + size, contents); |
Pawel Zarembski |
0:01f31e923fe2 | 371 | size += util_write_string(buf + size, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 372 | size += util_write_string(buf + size, error_type_prefix); |
Pawel Zarembski |
0:01f31e923fe2 | 373 | |
Pawel Zarembski |
0:01f31e923fe2 | 374 | // Write each applicable error type, separated by commas |
Pawel Zarembski |
0:01f31e923fe2 | 375 | int index = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 376 | bool first = true; |
Pawel Zarembski |
0:01f31e923fe2 | 377 | while (type && index < ARRAY_SIZE(error_type_names)) { |
Pawel Zarembski |
0:01f31e923fe2 | 378 | if (!first) { |
Pawel Zarembski |
0:01f31e923fe2 | 379 | size += util_write_string(buf + size, ", "); |
Pawel Zarembski |
0:01f31e923fe2 | 380 | } |
Pawel Zarembski |
0:01f31e923fe2 | 381 | if (type & 1) { |
Pawel Zarembski |
0:01f31e923fe2 | 382 | size += util_write_string(buf + size, error_type_names[index]); |
Pawel Zarembski |
0:01f31e923fe2 | 383 | first = false; |
Pawel Zarembski |
0:01f31e923fe2 | 384 | } |
Pawel Zarembski |
0:01f31e923fe2 | 385 | index++; |
Pawel Zarembski |
0:01f31e923fe2 | 386 | type >>= 1; |
Pawel Zarembski |
0:01f31e923fe2 | 387 | } |
Pawel Zarembski |
0:01f31e923fe2 | 388 | |
Pawel Zarembski |
0:01f31e923fe2 | 389 | size += util_write_string(buf + size, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 390 | return size; |
Pawel Zarembski |
0:01f31e923fe2 | 391 | } |
Pawel Zarembski |
0:01f31e923fe2 | 392 | |
Pawel Zarembski |
0:01f31e923fe2 | 393 | // File callback to be used with vfs_add_file to return file contents |
Pawel Zarembski |
0:01f31e923fe2 | 394 | static uint32_t read_file_assert_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors) |
Pawel Zarembski |
0:01f31e923fe2 | 395 | { |
Pawel Zarembski |
0:01f31e923fe2 | 396 | uint32_t pos; |
Pawel Zarembski |
0:01f31e923fe2 | 397 | const char *source_str; |
Pawel Zarembski |
0:01f31e923fe2 | 398 | char *buf = (char *)data; |
Pawel Zarembski |
0:01f31e923fe2 | 399 | uint32_t * hexdumps = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 400 | uint8_t valid_hexdumps = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 401 | uint8_t index = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 402 | |
Pawel Zarembski |
0:01f31e923fe2 | 403 | if (sector_offset != 0) { |
Pawel Zarembski |
0:01f31e923fe2 | 404 | return 0; |
Pawel Zarembski |
0:01f31e923fe2 | 405 | } |
Pawel Zarembski |
0:01f31e923fe2 | 406 | |
Pawel Zarembski |
0:01f31e923fe2 | 407 | pos = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 408 | |
Pawel Zarembski |
0:01f31e923fe2 | 409 | if (ASSERT_SOURCE_BL == assert_source) { |
Pawel Zarembski |
0:01f31e923fe2 | 410 | source_str = "Bootloader"; |
Pawel Zarembski |
0:01f31e923fe2 | 411 | } else if (ASSERT_SOURCE_APP == assert_source) { |
Pawel Zarembski |
0:01f31e923fe2 | 412 | source_str = "Application"; |
Pawel Zarembski |
0:01f31e923fe2 | 413 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 414 | source_str = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 415 | } |
Pawel Zarembski |
0:01f31e923fe2 | 416 | |
Pawel Zarembski |
0:01f31e923fe2 | 417 | pos += util_write_string(buf + pos, "Assert\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 418 | pos += util_write_string(buf + pos, "File: "); |
Pawel Zarembski |
0:01f31e923fe2 | 419 | pos += util_write_string(buf + pos, assert_buf); |
Pawel Zarembski |
0:01f31e923fe2 | 420 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 421 | pos += util_write_string(buf + pos, "Line: "); |
Pawel Zarembski |
0:01f31e923fe2 | 422 | pos += util_write_uint32(buf + pos, assert_line); |
Pawel Zarembski |
0:01f31e923fe2 | 423 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 424 | |
Pawel Zarembski |
0:01f31e923fe2 | 425 | if (source_str != 0) { |
Pawel Zarembski |
0:01f31e923fe2 | 426 | pos += util_write_string(buf + pos, "Source: "); |
Pawel Zarembski |
0:01f31e923fe2 | 427 | pos += util_write_string(buf + pos, source_str); |
Pawel Zarembski |
0:01f31e923fe2 | 428 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 429 | } |
Pawel Zarembski |
0:01f31e923fe2 | 430 | |
Pawel Zarembski |
0:01f31e923fe2 | 431 | valid_hexdumps = config_ram_get_hexdumps(&hexdumps); |
Pawel Zarembski |
0:01f31e923fe2 | 432 | if ((valid_hexdumps > 0) && (hexdumps != 0)) { |
Pawel Zarembski |
0:01f31e923fe2 | 433 | //print hexdumps |
Pawel Zarembski |
0:01f31e923fe2 | 434 | pos += util_write_string(buf + pos, "Hexdumps\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 435 | while ((index < valid_hexdumps) && ((pos + 10) < VFS_SECTOR_SIZE)) { //hexdumps + newline is always 10 characters |
Pawel Zarembski |
0:01f31e923fe2 | 436 | pos += util_write_hex32(buf + pos, hexdumps[index++]); |
Pawel Zarembski |
0:01f31e923fe2 | 437 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 438 | } |
Pawel Zarembski |
0:01f31e923fe2 | 439 | } |
Pawel Zarembski |
0:01f31e923fe2 | 440 | |
Pawel Zarembski |
0:01f31e923fe2 | 441 | return pos; |
Pawel Zarembski |
0:01f31e923fe2 | 442 | } |
Pawel Zarembski |
0:01f31e923fe2 | 443 | |
Pawel Zarembski |
0:01f31e923fe2 | 444 | // File callback to be used with vfs_add_file to return file contents |
Pawel Zarembski |
0:01f31e923fe2 | 445 | static uint32_t read_file_need_bl_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors) |
Pawel Zarembski |
0:01f31e923fe2 | 446 | { |
Pawel Zarembski |
0:01f31e923fe2 | 447 | const char *contents = "A bootloader update was started but unable to complete.\r\n" |
Pawel Zarembski |
0:01f31e923fe2 | 448 | "Reload the bootloader to fix this error message.\r\n"; |
Pawel Zarembski |
0:01f31e923fe2 | 449 | uint32_t size = strlen(contents); |
Pawel Zarembski |
0:01f31e923fe2 | 450 | |
Pawel Zarembski |
0:01f31e923fe2 | 451 | if (sector_offset != 0) { |
Pawel Zarembski |
0:01f31e923fe2 | 452 | return 0; |
Pawel Zarembski |
0:01f31e923fe2 | 453 | } |
Pawel Zarembski |
0:01f31e923fe2 | 454 | |
Pawel Zarembski |
0:01f31e923fe2 | 455 | memcpy(data, contents, size); |
Pawel Zarembski |
0:01f31e923fe2 | 456 | return size; |
Pawel Zarembski |
0:01f31e923fe2 | 457 | } |
Pawel Zarembski |
0:01f31e923fe2 | 458 | |
Pawel Zarembski |
0:01f31e923fe2 | 459 | |
Pawel Zarembski |
0:01f31e923fe2 | 460 | static uint32_t update_html_file(uint8_t *data, uint32_t datasize) |
Pawel Zarembski |
0:01f31e923fe2 | 461 | { |
Pawel Zarembski |
0:01f31e923fe2 | 462 | char *buf = (char *)data; |
Pawel Zarembski |
0:01f31e923fe2 | 463 | //Needed by expand_info strlen |
Pawel Zarembski |
0:01f31e923fe2 | 464 | memset(buf, 0, datasize); |
Pawel Zarembski |
0:01f31e923fe2 | 465 | memcpy(buf, mbed_redirect_file, strlen(mbed_redirect_file)); |
Pawel Zarembski |
0:01f31e923fe2 | 466 | //expand |
Pawel Zarembski |
0:01f31e923fe2 | 467 | return expand_info(data, datasize); |
Pawel Zarembski |
0:01f31e923fe2 | 468 | } |
Pawel Zarembski |
0:01f31e923fe2 | 469 | |
Pawel Zarembski |
0:01f31e923fe2 | 470 | static uint32_t update_details_txt_file(uint8_t *data, uint32_t datasize) |
Pawel Zarembski |
0:01f31e923fe2 | 471 | { |
Pawel Zarembski |
0:01f31e923fe2 | 472 | uint32_t pos=0; |
Pawel Zarembski |
0:01f31e923fe2 | 473 | const char *mode_str; |
Pawel Zarembski |
0:01f31e923fe2 | 474 | |
Pawel Zarembski |
0:01f31e923fe2 | 475 | char *buf = (char *)data; |
Pawel Zarembski |
0:01f31e923fe2 | 476 | |
Pawel Zarembski |
0:01f31e923fe2 | 477 | //Needed by expand_info strlen |
Pawel Zarembski |
0:01f31e923fe2 | 478 | memset(buf, 0, datasize); |
Pawel Zarembski |
0:01f31e923fe2 | 479 | |
Pawel Zarembski |
0:01f31e923fe2 | 480 | pos += util_write_string(buf + pos, "# DAPLink Firmware - see https://mbed.com/daplink\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 481 | // Unique ID |
Pawel Zarembski |
0:01f31e923fe2 | 482 | pos += util_write_string(buf + pos, "Unique ID: @U\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 483 | // HIC ID |
Pawel Zarembski |
0:01f31e923fe2 | 484 | pos += util_write_string(buf + pos, "HIC ID: @D\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 485 | // Settings |
Pawel Zarembski |
0:01f31e923fe2 | 486 | pos += util_write_string(buf + pos, "Auto Reset: "); |
Pawel Zarembski |
0:01f31e923fe2 | 487 | pos += util_write_string(buf + pos, config_get_auto_rst() ? "1" : "0"); |
Pawel Zarembski |
0:01f31e923fe2 | 488 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 489 | pos += util_write_string(buf + pos, "Automation allowed: "); |
Pawel Zarembski |
0:01f31e923fe2 | 490 | pos += util_write_string(buf + pos, config_get_automation_allowed() ? "1" : "0"); |
Pawel Zarembski |
0:01f31e923fe2 | 491 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 492 | pos += util_write_string(buf + pos, "Overflow detection: "); |
Pawel Zarembski |
0:01f31e923fe2 | 493 | pos += util_write_string(buf + pos, config_get_overflow_detect() ? "1" : "0"); |
Pawel Zarembski |
0:01f31e923fe2 | 494 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 495 | pos += util_write_string(buf + pos, "Page erasing: "); |
Pawel Zarembski |
0:01f31e923fe2 | 496 | pos += util_write_string(buf + pos, config_ram_get_page_erase() ? "1" : "0"); |
Pawel Zarembski |
0:01f31e923fe2 | 497 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 498 | // Current mode |
Pawel Zarembski |
0:01f31e923fe2 | 499 | mode_str = daplink_is_bootloader() ? "Bootloader" : "Interface"; |
Pawel Zarembski |
0:01f31e923fe2 | 500 | pos += util_write_string(buf + pos, "Daplink Mode: "); |
Pawel Zarembski |
0:01f31e923fe2 | 501 | pos += util_write_string(buf + pos, mode_str); |
Pawel Zarembski |
0:01f31e923fe2 | 502 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 503 | // Current build's version |
Pawel Zarembski |
0:01f31e923fe2 | 504 | pos += util_write_string(buf + pos, mode_str); |
Pawel Zarembski |
0:01f31e923fe2 | 505 | pos += util_write_string(buf + pos, " Version: @V\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 506 | |
Pawel Zarembski |
0:01f31e923fe2 | 507 | // Other builds version (bl or if) |
Pawel Zarembski |
0:01f31e923fe2 | 508 | if (!daplink_is_bootloader() && info_get_bootloader_present()) { |
Pawel Zarembski |
0:01f31e923fe2 | 509 | pos += util_write_string(buf + pos, "Bootloader Version: "); |
Pawel Zarembski |
0:01f31e923fe2 | 510 | pos += util_write_uint32_zp(buf + pos, info_get_bootloader_version(), 4); |
Pawel Zarembski |
0:01f31e923fe2 | 511 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 512 | } |
Pawel Zarembski |
0:01f31e923fe2 | 513 | |
Pawel Zarembski |
0:01f31e923fe2 | 514 | if (!daplink_is_interface() && info_get_interface_present()) { |
Pawel Zarembski |
0:01f31e923fe2 | 515 | pos += util_write_string(buf + pos, "Interface Version: "); |
Pawel Zarembski |
0:01f31e923fe2 | 516 | pos += util_write_uint32_zp(buf + pos, info_get_interface_version(), 4); |
Pawel Zarembski |
0:01f31e923fe2 | 517 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 518 | } |
Pawel Zarembski |
0:01f31e923fe2 | 519 | |
Pawel Zarembski |
0:01f31e923fe2 | 520 | // GIT sha |
Pawel Zarembski |
0:01f31e923fe2 | 521 | pos += util_write_string(buf + pos, "Git SHA: "); |
Pawel Zarembski |
0:01f31e923fe2 | 522 | pos += util_write_string(buf + pos, GIT_COMMIT_SHA); |
Pawel Zarembski |
0:01f31e923fe2 | 523 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 524 | // Local modifications when making the build |
Pawel Zarembski |
0:01f31e923fe2 | 525 | pos += util_write_string(buf + pos, "Local Mods: "); |
Pawel Zarembski |
0:01f31e923fe2 | 526 | pos += util_write_uint32(buf + pos, GIT_LOCAL_MODS); |
Pawel Zarembski |
0:01f31e923fe2 | 527 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 528 | // Supported USB endpoints |
Pawel Zarembski |
0:01f31e923fe2 | 529 | pos += util_write_string(buf + pos, "USB Interfaces: "); |
Pawel Zarembski |
0:01f31e923fe2 | 530 | #ifdef MSC_ENDPOINT |
Pawel Zarembski |
0:01f31e923fe2 | 531 | pos += util_write_string(buf + pos, "MSD"); |
Pawel Zarembski |
0:01f31e923fe2 | 532 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 533 | #ifdef CDC_ENDPOINT |
Pawel Zarembski |
0:01f31e923fe2 | 534 | pos += util_write_string(buf + pos, ", CDC"); |
Pawel Zarembski |
0:01f31e923fe2 | 535 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 536 | #ifdef HID_ENDPOINT |
Pawel Zarembski |
0:01f31e923fe2 | 537 | pos += util_write_string(buf + pos, ", HID"); |
Pawel Zarembski |
0:01f31e923fe2 | 538 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 539 | #if (WEBUSB_INTERFACE) |
Pawel Zarembski |
0:01f31e923fe2 | 540 | pos += util_write_string(buf + pos, ", WebUSB"); |
Pawel Zarembski |
0:01f31e923fe2 | 541 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 542 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 543 | |
Pawel Zarembski |
0:01f31e923fe2 | 544 | // CRC of the bootloader (if there is one) |
Pawel Zarembski |
0:01f31e923fe2 | 545 | if (info_get_bootloader_present()) { |
Pawel Zarembski |
0:01f31e923fe2 | 546 | pos += util_write_string(buf + pos, "Bootloader CRC: 0x"); |
Pawel Zarembski |
0:01f31e923fe2 | 547 | pos += util_write_hex32(buf + pos, info_get_crc_bootloader()); |
Pawel Zarembski |
0:01f31e923fe2 | 548 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 549 | } |
Pawel Zarembski |
0:01f31e923fe2 | 550 | |
Pawel Zarembski |
0:01f31e923fe2 | 551 | // CRC of the interface |
Pawel Zarembski |
0:01f31e923fe2 | 552 | pos += util_write_string(buf + pos, "Interface CRC: 0x"); |
Pawel Zarembski |
0:01f31e923fe2 | 553 | pos += util_write_hex32(buf + pos, info_get_crc_interface()); |
Pawel Zarembski |
0:01f31e923fe2 | 554 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 555 | |
Pawel Zarembski |
0:01f31e923fe2 | 556 | // Number of remounts that have occurred |
Pawel Zarembski |
0:01f31e923fe2 | 557 | pos += util_write_string(buf + pos, "Remount count: "); |
Pawel Zarembski |
0:01f31e923fe2 | 558 | pos += util_write_uint32(buf + pos, remount_count); |
Pawel Zarembski |
0:01f31e923fe2 | 559 | pos += util_write_string(buf + pos, "\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 560 | |
Pawel Zarembski |
0:01f31e923fe2 | 561 | //Target URL |
Pawel Zarembski |
0:01f31e923fe2 | 562 | pos += util_write_string(buf + pos, "URL: @R\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 563 | |
Pawel Zarembski |
0:01f31e923fe2 | 564 | return expand_info(data, datasize); |
Pawel Zarembski |
0:01f31e923fe2 | 565 | } |
Pawel Zarembski |
0:01f31e923fe2 | 566 | |
Pawel Zarembski |
0:01f31e923fe2 | 567 | // Fill buf with the contents of the mbed redirect file by |
Pawel Zarembski |
0:01f31e923fe2 | 568 | // expanding the special characters in mbed_redirect_file. |
Pawel Zarembski |
0:01f31e923fe2 | 569 | static uint32_t expand_info(uint8_t *buf, uint32_t bufsize) |
Pawel Zarembski |
0:01f31e923fe2 | 570 | { |
Pawel Zarembski |
0:01f31e923fe2 | 571 | uint8_t *orig_buf = buf; |
Pawel Zarembski |
0:01f31e923fe2 | 572 | uint8_t *insert_string; |
Pawel Zarembski |
0:01f31e923fe2 | 573 | |
Pawel Zarembski |
0:01f31e923fe2 | 574 | do { |
Pawel Zarembski |
0:01f31e923fe2 | 575 | // Look for key or the end of the string |
Pawel Zarembski |
0:01f31e923fe2 | 576 | while ((*buf != '@') && (*buf != 0)) { |
Pawel Zarembski |
0:01f31e923fe2 | 577 | buf++; |
Pawel Zarembski |
0:01f31e923fe2 | 578 | } |
Pawel Zarembski |
0:01f31e923fe2 | 579 | |
Pawel Zarembski |
0:01f31e923fe2 | 580 | // If key was found then replace it |
Pawel Zarembski |
0:01f31e923fe2 | 581 | if ('@' == *buf) { |
Pawel Zarembski |
0:01f31e923fe2 | 582 | switch (*(buf + 1)) { |
Pawel Zarembski |
0:01f31e923fe2 | 583 | case 'm': |
Pawel Zarembski |
0:01f31e923fe2 | 584 | case 'M': // MAC address |
Pawel Zarembski |
0:01f31e923fe2 | 585 | insert_string = (uint8_t *)info_get_mac(); |
Pawel Zarembski |
0:01f31e923fe2 | 586 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 587 | |
Pawel Zarembski |
0:01f31e923fe2 | 588 | case 'u': |
Pawel Zarembski |
0:01f31e923fe2 | 589 | case 'U': // UUID |
Pawel Zarembski |
0:01f31e923fe2 | 590 | insert_string = (uint8_t *)info_get_unique_id(); |
Pawel Zarembski |
0:01f31e923fe2 | 591 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 592 | |
Pawel Zarembski |
0:01f31e923fe2 | 593 | case 'b': |
Pawel Zarembski |
0:01f31e923fe2 | 594 | case 'B': // Board ID |
Pawel Zarembski |
0:01f31e923fe2 | 595 | insert_string = (uint8_t *)info_get_board_id(); |
Pawel Zarembski |
0:01f31e923fe2 | 596 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 597 | |
Pawel Zarembski |
0:01f31e923fe2 | 598 | case 'h': |
Pawel Zarembski |
0:01f31e923fe2 | 599 | case 'H': // Host ID |
Pawel Zarembski |
0:01f31e923fe2 | 600 | insert_string = (uint8_t *)info_get_host_id(); |
Pawel Zarembski |
0:01f31e923fe2 | 601 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 602 | |
Pawel Zarembski |
0:01f31e923fe2 | 603 | case 't': |
Pawel Zarembski |
0:01f31e923fe2 | 604 | case 'T': // Target ID |
Pawel Zarembski |
0:01f31e923fe2 | 605 | insert_string = (uint8_t *)info_get_target_id(); |
Pawel Zarembski |
0:01f31e923fe2 | 606 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 607 | |
Pawel Zarembski |
0:01f31e923fe2 | 608 | case 'd': |
Pawel Zarembski |
0:01f31e923fe2 | 609 | case 'D': // HIC |
Pawel Zarembski |
0:01f31e923fe2 | 610 | insert_string = (uint8_t *)info_get_hic_id(); |
Pawel Zarembski |
0:01f31e923fe2 | 611 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 612 | |
Pawel Zarembski |
0:01f31e923fe2 | 613 | case 'v': |
Pawel Zarembski |
0:01f31e923fe2 | 614 | case 'V': // Firmware version |
Pawel Zarembski |
0:01f31e923fe2 | 615 | insert_string = (uint8_t *)info_get_version(); |
Pawel Zarembski |
0:01f31e923fe2 | 616 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 617 | |
Pawel Zarembski |
0:01f31e923fe2 | 618 | case 'r': |
Pawel Zarembski |
0:01f31e923fe2 | 619 | case 'R': // URL replacement |
Pawel Zarembski |
0:01f31e923fe2 | 620 | insert_string = (uint8_t *)get_daplink_target_url(); |
Pawel Zarembski |
0:01f31e923fe2 | 621 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 622 | |
Pawel Zarembski |
0:01f31e923fe2 | 623 | default: |
Pawel Zarembski |
0:01f31e923fe2 | 624 | insert_string = (uint8_t *)"ERROR"; |
Pawel Zarembski |
0:01f31e923fe2 | 625 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 626 | } |
Pawel Zarembski |
0:01f31e923fe2 | 627 | |
Pawel Zarembski |
0:01f31e923fe2 | 628 | // Remove strip_count characters from the start of buf and then insert |
Pawel Zarembski |
0:01f31e923fe2 | 629 | // insert_string at the new start of buf. |
Pawel Zarembski |
0:01f31e923fe2 | 630 | uint32_t buf_len = strlen((const char *)buf); |
Pawel Zarembski |
0:01f31e923fe2 | 631 | uint32_t str_len = strlen((const char *)insert_string); |
Pawel Zarembski |
0:01f31e923fe2 | 632 | //buffer overflow check on insert |
Pawel Zarembski |
0:01f31e923fe2 | 633 | if( (buf + str_len + buf_len - 2) < (orig_buf+bufsize)){ |
Pawel Zarembski |
0:01f31e923fe2 | 634 | // push out string |
Pawel Zarembski |
0:01f31e923fe2 | 635 | memmove(buf + str_len, buf + 2, buf_len - 2); |
Pawel Zarembski |
0:01f31e923fe2 | 636 | // insert |
Pawel Zarembski |
0:01f31e923fe2 | 637 | memcpy(buf, insert_string, str_len); |
Pawel Zarembski |
0:01f31e923fe2 | 638 | }else{ |
Pawel Zarembski |
0:01f31e923fe2 | 639 | //stop the string expansion and leave as it is |
Pawel Zarembski |
0:01f31e923fe2 | 640 | buf += buf_len; |
Pawel Zarembski |
0:01f31e923fe2 | 641 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 642 | } |
Pawel Zarembski |
0:01f31e923fe2 | 643 | |
Pawel Zarembski |
0:01f31e923fe2 | 644 | } |
Pawel Zarembski |
0:01f31e923fe2 | 645 | } while (*buf != '\0'); |
Pawel Zarembski |
0:01f31e923fe2 | 646 | |
Pawel Zarembski |
0:01f31e923fe2 | 647 | return (buf - orig_buf); |
Pawel Zarembski |
0:01f31e923fe2 | 648 | } |
Pawel Zarembski |
0:01f31e923fe2 | 649 | |
Pawel Zarembski |
0:01f31e923fe2 | 650 | // Initialize flash algo, erase flash, uninit algo |
Pawel Zarembski |
0:01f31e923fe2 | 651 | static void erase_target(void) |
Pawel Zarembski |
0:01f31e923fe2 | 652 | { |
Pawel Zarembski |
0:01f31e923fe2 | 653 | flash_intf_target->init(); |
Pawel Zarembski |
0:01f31e923fe2 | 654 | flash_intf_target->erase_chip(); |
Pawel Zarembski |
0:01f31e923fe2 | 655 | flash_intf_target->uninit(); |
Pawel Zarembski |
0:01f31e923fe2 | 656 | } |