3
3
* @brief Implementation of vfs_user.h
4
4
*
5
5
* DAPLink Interface Firmware
6
- * Copyright (c) 2009-2019 , ARM Limited, All Rights Reserved
6
+ * Copyright (c) 2009-2020 , ARM Limited, All Rights Reserved
7
7
* SPDX-License-Identifier: Apache-2.0
8
8
*
9
9
* Licensed under the Apache License, Version 2.0 (the "License"); you may
23
23
#include "ctype.h"
24
24
#include "string.h"
25
25
26
+ #include "vfs_user.h"
26
27
#include "vfs_manager.h"
27
28
#include "macro.h"
28
29
#include "error.h"
40
41
// device. This is to accomodate for hex file programming.
41
42
static const uint32_t disc_size = MB (64 );
42
43
44
+ //! @brief Constants for magic action or config files.
45
+ //!
46
+ //! The "magic files" are files with a special name that if created on the USB MSC volume, will
47
+ //! cause an event. There are two classes of magic files: action files and config files. The former
48
+ //! causes a given action to take place, while the latter changes a persistent configuration setting
49
+ //! to a predetermined value.
50
+ //!
51
+ //! See #s_magic_file_info for the mapping of filenames to these enums.
52
+ typedef enum _magic_file {
53
+ kDAPLinkModeActionFile , //!< Switch between interface and bootloader.
54
+ kTestAssertActionFile , //!< Force an assertion for testing.
55
+ kRefreshActionFile , //!< Force a remount.
56
+ kEraseActionFile , //!< Erase the target flash.
57
+ kAutoResetConfigFile , //!< Enable reset after flash.
58
+ kHardResetConfigFile , //!< Disable reset after flash.
59
+ kAutomationOnConfigFile , //!< Enable automation.
60
+ kAutomationOffConfigFile , //!< Disable automation.
61
+ kOverflowOnConfigFile , //!< Enable UART overflow reporting.
62
+ kOverflowOffConfigFile , //!< Disable UART overflow reporting.
63
+ kMSDOnConfigFile , //!< Enable USB MSC. Uh....
64
+ kMSDOffConfigFile , //!< Disable USB MSC.
65
+ } magic_file_t ;
66
+
67
+ //! @brief Mapping from filename string to magic file enum.
68
+ typedef struct _magic_file_info {
69
+ const char * name ; //!< Name of the magic file, must be in 8.3 format.
70
+ magic_file_t which ; //!< Enum for the file.
71
+ } magic_file_info_t ;
72
+
43
73
static const char mbed_redirect_file [] =
44
74
"<!doctype html>\r\n"
45
75
"<!-- mbed Platform Website and Authentication Shortcut -->\r\n"
@@ -60,6 +90,22 @@ static const char error_type_prefix[] = "type: ";
60
90
61
91
static const vfs_filename_t assert_file = "ASSERT TXT" ;
62
92
93
+ //! @brief Table of magic files and their names.
94
+ static const magic_file_info_t s_magic_file_info [] = {
95
+ { daplink_mode_file_name , kDAPLinkModeActionFile },
96
+ { "ASSERT ACT" , kTestAssertActionFile },
97
+ { "REFRESH ACT" , kRefreshActionFile },
98
+ { "ERASE ACT" , kEraseActionFile },
99
+ { "AUTO_RSTCFG" , kAutoResetConfigFile },
100
+ { "HARD_RSTCFG" , kHardResetConfigFile },
101
+ { "AUTO_ON CFG" , kAutomationOnConfigFile },
102
+ { "AUTO_OFFCFG" , kAutomationOffConfigFile },
103
+ { "OVFL_ON CFG" , kOverflowOnConfigFile },
104
+ { "OVFL_OFFCFG" , kOverflowOffConfigFile },
105
+ { "MSD_ON CFG" , kMSDOnConfigFile },
106
+ { "MSD_OFF CFG" , kMSDOffConfigFile },
107
+ };
108
+
63
109
static uint8_t file_buffer [VFS_SECTOR_SIZE ];
64
110
static char assert_buf [64 + 1 ];
65
111
static uint16_t assert_line ;
@@ -123,9 +169,28 @@ void vfs_user_build_filesystem()
123
169
}
124
170
}
125
171
172
+ // Default file change hook.
173
+ __WEAK bool vfs_user_file_change_handler_hook (const vfs_filename_t filename , vfs_file_change_t change ,
174
+ vfs_file_t file , vfs_file_t new_file_data )
175
+ {
176
+ return false;
177
+ }
178
+
179
+ // Default magic file hook.
180
+ __WEAK bool vfs_user_magic_file_hook (const vfs_filename_t filename , bool * do_remount )
181
+ {
182
+ return false;
183
+ }
184
+
126
185
// Callback to handle changes to the root directory. Should be used with vfs_set_file_change_callback
127
186
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 )
128
187
{
188
+ // Call file changed hook. If it returns true, then it handled the request and we have nothing
189
+ // more to do.
190
+ if (vfs_user_file_change_handler_hook (filename , change , file , new_file_data )) {
191
+ return ;
192
+ }
193
+
129
194
// Allow settings to be changed if automation mode is
130
195
// enabled or if the user is holding the reset button
131
196
bool btn_pressed = gpio_get_reset_btn ();
@@ -138,52 +203,81 @@ void vfs_user_file_change_handler(const vfs_filename_t filename, vfs_file_change
138
203
// Unused
139
204
}
140
205
141
- if (VFS_FILE_CREATED == change ) {
142
- if (!memcmp (filename , daplink_mode_file_name , sizeof (vfs_filename_t ))) {
143
- if (daplink_is_interface ()) {
144
- config_ram_set_hold_in_bl (true);
145
- } else {
146
- // Do nothing - bootloader will go to interface by default
206
+ else if (VFS_FILE_CREATED == change ) {
207
+ bool do_remount = true; // Almost all magic files cause a remount.
208
+ int32_t which_magic_file = -1 ;
209
+
210
+ // Let the hook examine the filename. If it returned false then look for the standard
211
+ // magic files.
212
+ if (!vfs_user_magic_file_hook (filename , & do_remount )) {
213
+ // Compare the new file's name to our table of magic filenames.
214
+ for (int32_t i = 0 ; i < ARRAY_SIZE (s_magic_file_info ); ++ i ) {
215
+ if (!memcmp (filename , s_magic_file_info [i ].name , sizeof (vfs_filename_t ))) {
216
+ which_magic_file = i ;
217
+ }
147
218
}
148
219
149
- vfs_mngr_fs_remount ();
150
- } else if (!memcmp (filename , "AUTO_RSTCFG" , sizeof (vfs_filename_t ))) {
151
- config_set_auto_rst (true);
152
- vfs_mngr_fs_remount ();
153
- } else if (!memcmp (filename , "HARD_RSTCFG" , sizeof (vfs_filename_t ))) {
154
- config_set_auto_rst (false);
155
- vfs_mngr_fs_remount ();
156
- } else if (!memcmp (filename , "ASSERT ACT" , sizeof (vfs_filename_t ))) {
157
- // Test asserts
158
- util_assert (0 );
159
- } else if (!memcmp (filename , "REFRESH ACT" , sizeof (vfs_filename_t ))) {
160
- // Remount to update the drive
161
- vfs_mngr_fs_remount ();
162
- } else if (!memcmp (filename , "AUTO_ON CFG" , sizeof (vfs_filename_t ))) {
163
- config_set_automation_allowed (true);
164
- vfs_mngr_fs_remount ();
165
- } else if (!memcmp (filename , "AUTO_OFFCFG" , sizeof (vfs_filename_t ))) {
166
- config_set_automation_allowed (false);
167
- vfs_mngr_fs_remount ();
168
- } else if (!memcmp (filename , "ERASE ACT" , sizeof (vfs_filename_t ))) {
169
- erase_target ();
170
- vfs_mngr_fs_remount ();
171
- } else if (!memcmp (filename , "OVFL_ON CFG" , sizeof (vfs_filename_t ))) {
172
- config_set_overflow_detect (true);
173
- vfs_mngr_fs_remount ();
174
- } else if (!memcmp (filename , "OVFL_OFFCFG" , sizeof (vfs_filename_t ))) {
175
- config_set_overflow_detect (false);
176
- vfs_mngr_fs_remount ();
177
- } else if (!memcmp (filename , "MSD_ON ACT" , sizeof (vfs_filename_t ))) {
178
- config_ram_set_disable_msd (false);
179
- vfs_mngr_fs_remount ();
180
- } else if (!memcmp (filename , "MSD_OFF ACT" , sizeof (vfs_filename_t ))) {
181
- config_ram_set_disable_msd (true);
220
+ // Check if we matched a magic filename and handle it.
221
+ if (which_magic_file != -1 ) {
222
+ switch (which_magic_file ) {
223
+ case kDAPLinkModeActionFile :
224
+ if (daplink_is_interface ()) {
225
+ config_ram_set_hold_in_bl (true);
226
+ } else {
227
+ // Do nothing - bootloader will go to interface by default
228
+ }
229
+ break ;
230
+ case kTestAssertActionFile :
231
+ // Test asserts
232
+ util_assert (0 );
233
+ do_remount = false;
234
+ break ;
235
+ case kRefreshActionFile :
236
+ // Remount to update the drive
237
+ break ;
238
+ case kEraseActionFile :
239
+ erase_target ();
240
+ break ;
241
+ case kAutoResetConfigFile :
242
+ config_set_auto_rst (true);
243
+ break ;
244
+ case kHardResetConfigFile :
245
+ config_set_auto_rst (false);
246
+ break ;
247
+ case kAutomationOnConfigFile :
248
+ config_set_automation_allowed (true);
249
+ break ;
250
+ case kAutomationOffConfigFile :
251
+ config_set_automation_allowed (false);
252
+ break ;
253
+ case kOverflowOnConfigFile :
254
+ config_set_overflow_detect (true);
255
+ break ;
256
+ case kOverflowOffConfigFile :
257
+ config_set_overflow_detect (false);
258
+ break ;
259
+ case kMSDOnConfigFile :
260
+ config_ram_set_disable_msd (false);
261
+ break ;
262
+ case kMSDOffConfigFile :
263
+ config_ram_set_disable_msd (true);
264
+ break ;
265
+ default :
266
+ util_assert (false);
267
+ }
268
+ }
269
+ else {
270
+ do_remount = false;
271
+ }
272
+ }
273
+
274
+ // Remount if requested.
275
+ if (do_remount ) {
182
276
vfs_mngr_fs_remount ();
183
277
}
184
278
}
185
279
186
- if (VFS_FILE_DELETED == change ) {
280
+ else if (VFS_FILE_DELETED == change ) {
187
281
if (!memcmp (filename , assert_file , sizeof (vfs_filename_t ))) {
188
282
// Clear assert and remount to update the drive
189
283
util_assert_clear ();
0 commit comments