Skip to content

Commit d218069

Browse files
authored
Merge pull request #1584 from tannewt/disable_concurrent_write_protection
Add option to disable the concurrent write protection
2 parents 3e877e0 + ed1ace0 commit d218069

File tree

14 files changed

+75
-42
lines changed

14 files changed

+75
-42
lines changed

extmod/vfs_fat.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
#define FSUSER_NO_FILESYSTEM (0x0008) // the block device has no filesystem on it
3939
// Device is writable over USB and read-only to MicroPython.
4040
#define FSUSER_USB_WRITABLE (0x0010)
41+
// Bit set when the above flag is checked before opening a file for write.
42+
#define FSUSER_CONCURRENT_WRITE_PROTECTED (0x0020)
4143

4244
typedef struct _fs_user_mount_t {
4345
mp_obj_base_t base;

extmod/vfs_fat_file.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "py/mperrno.h"
3535
#include "lib/oofatfs/ff.h"
3636
#include "extmod/vfs_fat.h"
37+
#include "supervisor/filesystem.h"
3738

3839
// this table converts from FRESULT to POSIX errno
3940
const byte fresult_to_errno_table[20] = {
@@ -187,7 +188,7 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar
187188
}
188189
}
189190
assert(vfs != NULL);
190-
if ((vfs->flags & FSUSER_USB_WRITABLE) != 0 && (mode & FA_WRITE) != 0) {
191+
if ((mode & FA_WRITE) != 0 && !filesystem_is_writable_by_python(vfs)) {
191192
mp_raise_OSError(MP_EROFS);
192193
}
193194

main.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,12 +323,12 @@ void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
323323
mp_hal_delay_ms(1500);
324324

325325
// USB isn't up, so we can write the file.
326-
filesystem_writable_by_python(true);
326+
filesystem_set_internal_writable_by_usb(false);
327327
f_open(fs, boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS);
328328

329329
// Switch the filesystem back to non-writable by Python now instead of later,
330330
// since boot.py might change it back to writable.
331-
filesystem_writable_by_python(false);
331+
filesystem_set_internal_writable_by_usb(true);
332332

333333
// Write version info to boot_out.txt.
334334
mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO);
@@ -416,7 +416,8 @@ int __attribute__((used)) main(void) {
416416

417417
// By default our internal flash is readonly to local python code and
418418
// writable over USB. Set it here so that boot.py can change it.
419-
filesystem_writable_by_python(false);
419+
filesystem_set_internal_concurrent_write_protection(true);
420+
filesystem_set_internal_writable_by_usb(true);
420421

421422
run_boot_py(safe_mode);
422423

ports/unix/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ SRC_C = \
149149
alloc.c \
150150
coverage.c \
151151
fatfs_port.c \
152+
supervisor/stub/filesystem.c \
152153
supervisor/stub/serial.c \
153154
supervisor/stub/stack.c \
154155
supervisor/shared/translate.c \

shared-bindings/storage/__init__.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,12 @@
5454
//|
5555
//| This is the CircuitPython analog to the UNIX ``mount`` command.
5656
//|
57+
//| :param bool readonly: True when the filesystem should be readonly to CircuitPython.
58+
//|
5759
mp_obj_t storage_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
5860
enum { ARG_readonly };
5961
static const mp_arg_t allowed_args[] = {
60-
{ MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_false} },
62+
{ MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
6163
};
6264

6365
// parse args
@@ -77,7 +79,7 @@ mp_obj_t storage_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_arg
7779
mp_raise_ValueError(translate("filesystem must provide mount method"));
7880
}
7981

80-
common_hal_storage_mount(vfs_obj, mnt_str, mp_obj_is_true(args[ARG_readonly].u_obj));
82+
common_hal_storage_mount(vfs_obj, mnt_str, args[ARG_readonly].u_bool);
8183

8284
return mp_const_none;
8385
}
@@ -101,14 +103,21 @@ mp_obj_t storage_umount(mp_obj_t mnt_in) {
101103
}
102104
MP_DEFINE_CONST_FUN_OBJ_1(storage_umount_obj, storage_umount);
103105

104-
//| .. function:: remount(mount_path, readonly=False)
106+
//| .. function:: remount(mount_path, readonly=False, *, disable_concurrent_write_protection=False)
105107
//|
106108
//| Remounts the given path with new parameters.
107109
//|
110+
//| :param bool readonly: True when the filesystem should be readonly to CircuitPython.
111+
//| :param bool disable_concurrent_write_protection: When True, the check that makes sure the
112+
//| underlying filesystem data is written by one computer is disabled. Disabling the protection
113+
//| allows CircuitPython and a host to write to the same filesystem with the risk that the
114+
//| filesystem will be corrupted.
115+
//|
108116
mp_obj_t storage_remount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
109-
enum { ARG_readonly };
117+
enum { ARG_readonly, ARG_disable_concurrent_write_protection };
110118
static const mp_arg_t allowed_args[] = {
111-
{ MP_QSTR_readonly, MP_ARG_BOOL | MP_ARG_REQUIRED, {.u_bool = false} },
119+
{ MP_QSTR_readonly, MP_ARG_BOOL, {.u_bool = false} },
120+
{ MP_QSTR_disable_concurrent_write_protection, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
112121
};
113122

114123
// get the mount point
@@ -118,7 +127,7 @@ mp_obj_t storage_remount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
118127
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
119128
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
120129

121-
common_hal_storage_remount(mnt_str, args[ARG_readonly].u_bool);
130+
common_hal_storage_remount(mnt_str, args[ARG_readonly].u_bool, args[ARG_disable_concurrent_write_protection].u_bool);
122131

123132
return mp_const_none;
124133
}

shared-bindings/storage/__init__.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
void common_hal_storage_mount(mp_obj_t vfs_obj, const char* path, bool readonly);
3434
void common_hal_storage_umount_path(const char* path);
3535
void common_hal_storage_umount_object(mp_obj_t vfs_obj);
36-
void common_hal_storage_remount(const char* path, bool readonly);
36+
void common_hal_storage_remount(const char* path, bool readonly, bool disable_concurrent_write_protection);
3737
mp_obj_t common_hal_storage_getmount(const char* path);
3838
void common_hal_storage_erase_filesystem(void);
3939

shared-module/storage/__init__.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ mp_obj_t common_hal_storage_getmount(const char *mount_path) {
143143
return storage_object_from_path(mount_path);
144144
}
145145

146-
void common_hal_storage_remount(const char *mount_path, bool readonly) {
146+
void common_hal_storage_remount(const char *mount_path, bool readonly, bool disable_concurrent_write_protection) {
147147
if (strcmp(mount_path, "/") != 0) {
148148
mp_raise_OSError(MP_EINVAL);
149149
}
@@ -156,7 +156,8 @@ void common_hal_storage_remount(const char *mount_path, bool readonly) {
156156
}
157157
#endif
158158

159-
supervisor_flash_set_usb_writable(readonly);
159+
filesystem_set_internal_writable_by_usb(readonly);
160+
filesystem_set_internal_concurrent_write_protection(!disable_concurrent_write_protection);
160161
}
161162

162163
void common_hal_storage_erase_filesystem(void) {

supervisor/filesystem.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,16 @@
2929

3030
#include <stdbool.h>
3131

32+
#include "extmod/vfs_fat.h"
33+
3234
void filesystem_init(bool create_allowed, bool force_create);
3335
void filesystem_flush(void);
34-
void filesystem_writable_by_python(bool writable);
3536
bool filesystem_present(void);
37+
void filesystem_set_internal_writable_by_usb(bool usb_writable);
38+
void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection);
39+
void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable);
40+
void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concurrent_write_protection);
41+
bool filesystem_is_writable_by_python(fs_user_mount_t *vfs);
42+
bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs);
3643

3744
#endif // MICROPY_INCLUDED_SUPERVISOR_FILESYSTEM_H

supervisor/flash.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
#include "supervisor/internal_flash.h"
3838
#endif
3939

40-
void supervisor_flash_set_usb_writable(bool usb_writable);
4140
void supervisor_flash_init(void);
4241
uint32_t supervisor_flash_get_block_size(void);
4342
uint32_t supervisor_flash_get_block_count(void);

supervisor/shared/filesystem.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
#include "supervisor/filesystem.h"
28+
2729
#include "extmod/vfs_fat.h"
2830
#include "lib/oofatfs/ff.h"
2931
#include "lib/oofatfs/diskio.h"
@@ -92,16 +94,42 @@ void filesystem_flush(void) {
9294
supervisor_flash_flush();
9395
}
9496

95-
void filesystem_writable_by_python(bool writable) {
97+
void filesystem_set_internal_writable_by_usb(bool writable) {
9698
fs_user_mount_t *vfs = &_internal_vfs;
9799

98-
if (!writable) {
100+
filesystem_set_writable_by_usb(vfs, writable);
101+
}
102+
103+
void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable) {
104+
if (usb_writable) {
99105
vfs->flags |= FSUSER_USB_WRITABLE;
100106
} else {
101107
vfs->flags &= ~FSUSER_USB_WRITABLE;
102108
}
103109
}
104110

111+
bool filesystem_is_writable_by_python(fs_user_mount_t *vfs) {
112+
return (vfs->flags & FSUSER_CONCURRENT_WRITE_PROTECTED) == 0 ||
113+
(vfs->flags & FSUSER_USB_WRITABLE) == 0;
114+
}
115+
116+
bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs) {
117+
return (vfs->flags & FSUSER_CONCURRENT_WRITE_PROTECTED) == 0 ||
118+
(vfs->flags & FSUSER_USB_WRITABLE) != 0;
119+
}
120+
121+
void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection) {
122+
filesystem_set_concurrent_write_protection(&_internal_vfs, concurrent_write_protection);
123+
}
124+
125+
void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concurrent_write_protection) {
126+
if (concurrent_write_protection) {
127+
vfs->flags |= FSUSER_CONCURRENT_WRITE_PROTECTED;
128+
} else {
129+
vfs->flags &= ~FSUSER_CONCURRENT_WRITE_PROTECTED;
130+
}
131+
}
132+
105133
bool filesystem_present(void) {
106134
return true;
107135
}

supervisor/shared/flash.c

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,6 @@
3333

3434
#define PART1_START_BLOCK (0x1)
3535

36-
void supervisor_flash_set_usb_writable(bool usb_writable) {
37-
mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table);
38-
for (uint8_t i = 0; current_mount != NULL; i++) {
39-
if (i == VFS_INDEX) {
40-
break;
41-
}
42-
current_mount = current_mount->next;
43-
}
44-
if (current_mount == NULL) {
45-
return;
46-
}
47-
fs_user_mount_t *vfs = (fs_user_mount_t *) current_mount->obj;
48-
49-
if (usb_writable) {
50-
vfs->flags |= FSUSER_USB_WRITABLE;
51-
} else {
52-
vfs->flags &= ~FSUSER_USB_WRITABLE;
53-
}
54-
}
55-
5636
// there is a singleton Flash object
5737
const mp_obj_type_t supervisor_flash_type;
5838
STATIC const mp_obj_base_t supervisor_flash_obj = {&supervisor_flash_type};

supervisor/shared/usb/usb_msc_flash.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "lib/oofatfs/ff.h"
3535
#include "py/mpstate.h"
3636

37+
#include "supervisor/filesystem.h"
3738
#include "supervisor/shared/autoreload.h"
3839

3940
#define MSC_FLASH_BLOCK_SIZE 512
@@ -148,8 +149,7 @@ bool tud_msc_is_writable_cb(uint8_t lun) {
148149
if (vfs == NULL) {
149150
return false;
150151
}
151-
if (vfs->writeblocks[0] == MP_OBJ_NULL ||
152-
(vfs->flags & FSUSER_USB_WRITABLE) == 0) {
152+
if (vfs->writeblocks[0] == MP_OBJ_NULL || !filesystem_is_writable_by_usb(vfs)) {
153153
return false;
154154
}
155155
return true;

supervisor/stub/filesystem.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,17 @@
2626

2727
#include "supervisor/filesystem.h"
2828

29-
void filesystem_init(void) {
29+
void filesystem_init(bool create_allowed, bool force_create) {
30+
(void) create_allowed;
31+
(void) force_create;
3032
}
3133

3234
void filesystem_flush(void) {
3335
}
3436

35-
void filesystem_writable_by_python(bool writable) {
37+
bool filesystem_is_writable_by_python(fs_user_mount_t *vfs) {
38+
(void) vfs;
39+
return true;
3640
}
3741

3842
bool filesystem_present(void) {

0 commit comments

Comments
 (0)