33 * @brief Implementation of vfs_user.h
44 *
55 * DAPLink Interface Firmware
6- * Copyright (c) 2009-2019 , ARM Limited, All Rights Reserved
6+ * Copyright (c) 2009-2020 , ARM Limited, All Rights Reserved
77 * SPDX-License-Identifier: Apache-2.0
88 *
99 * Licensed under the Apache License, Version 2.0 (the "License"); you may
2323#include "ctype.h"
2424#include "string.h"
2525
26+ #include "vfs_user.h"
2627#include "vfs_manager.h"
2728#include "macro.h"
2829#include "error.h"
4041// device. This is to accomodate for hex file programming.
4142static const uint32_t disc_size = MB (64 );
4243
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+
4373static const char mbed_redirect_file [] =
4474 "<!doctype html>\r\n"
4575 "<!-- mbed Platform Website and Authentication Shortcut -->\r\n"
@@ -60,6 +90,22 @@ static const char error_type_prefix[] = "type: ";
6090
6191static const vfs_filename_t assert_file = "ASSERT TXT" ;
6292
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+
63109static uint8_t file_buffer [VFS_SECTOR_SIZE ];
64110static char assert_buf [64 + 1 ];
65111static uint16_t assert_line ;
@@ -123,9 +169,28 @@ void vfs_user_build_filesystem()
123169 }
124170}
125171
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+
126185// Callback to handle changes to the root directory. Should be used with vfs_set_file_change_callback
127186void 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 )
128187{
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+
129194 // Allow settings to be changed if automation mode is
130195 // enabled or if the user is holding the reset button
131196 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
138203 // Unused
139204 }
140205
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+ }
147218 }
148219
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 ) {
182276 vfs_mngr_fs_remount ();
183277 }
184278 }
185279
186- if (VFS_FILE_DELETED == change ) {
280+ else if (VFS_FILE_DELETED == change ) {
187281 if (!memcmp (filename , assert_file , sizeof (vfs_filename_t ))) {
188282 // Clear assert and remount to update the drive
189283 util_assert_clear ();
0 commit comments