Skip to content

Commit e2cbc2d

Browse files
committed
Fix filesystem writability from USB
1 parent d585b1d commit e2cbc2d

File tree

7 files changed

+36
-18
lines changed

7 files changed

+36
-18
lines changed

extmod/vfs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
#define MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED (0x0020)
5353
// Bit set when something has claimed the right to mutate the blockdev.
5454
#define MP_BLOCKDEV_FLAG_LOCKED (0x0040)
55+
// Ignore write protections. Used to override other flags temporarily.
56+
#define MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION (0x0080)
5557

5658
// constants for block protocol ioctl
5759
#define MP_BLOCKDEV_IOCTL_INIT (1)

extmod/vfs_fat.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -427,13 +427,10 @@ static MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_statvfs_obj, fat_vfs_statvfs);
427427
static mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) {
428428
fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in);
429429

430-
// Read-only device indicated by writeblocks[0] == MP_OBJ_NULL.
431-
// User can specify read-only device by:
432-
// 1. readonly=True keyword argument
433-
// 2. nonexistent writeblocks method (then writeblocks[0] == MP_OBJ_NULL already)
434-
if (mp_obj_is_true(readonly)) {
435-
self->blockdev.writeblocks[0] = MP_OBJ_NULL;
436-
}
430+
// CIRCUITPY-CHANGE: Use MP_BLOCKDEV_FLAG_USB_WRITABLE instead of writeblocks[0] =/!= MP_OBJ_NULL
431+
// to specify read-write.
432+
// If readonly to Python, it's writable by USB and vice versa.
433+
filesystem_set_writable_by_usb(self, mp_obj_is_true(readonly));
437434

438435
// check if we need to make the filesystem
439436
FRESULT res = (self->blockdev.flags & MP_BLOCKDEV_FLAG_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK;

extmod/vfs_fat_diskio.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
#include "lib/oofatfs/diskio.h"
4444
#include "extmod/vfs_fat.h"
4545

46+
// CIRCUITPY-CHANGE
47+
#include "supervisor/filesystem.h"
48+
4649
typedef void *bdev_t;
4750
static fs_user_mount_t *disk_get_device(void *bdev) {
4851
return (fs_user_mount_t *)bdev;
@@ -153,7 +156,8 @@ DRESULT disk_ioctl(
153156
if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
154157
// error initialising
155158
stat = STA_NOINIT;
156-
} else if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) {
159+
// CIRCUITPY-CHANGE: writability from Python check
160+
} else if (!filesystem_is_writable_by_python(vfs)) {
157161
stat = STA_PROTECT;
158162
} else {
159163
stat = 0;

main.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,14 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
863863
boot_output = &boot_text;
864864
#endif
865865

866+
// Get the base filesystem.
867+
fs_user_mount_t *vfs = filesystem_circuitpy();
868+
FATFS *fs = &vfs->fatfs;
869+
870+
// Allow boot.py access to CIRCUITPY, and allow writes to boot_out.txt.
871+
// We can't use the regular flags for this, because they might get modified inside boot.py.
872+
filesystem_set_ignore_write_protection(vfs, true);
873+
866874
// Write version info
867875
mp_printf(&mp_plat_print, "%s\nBoard ID:%s\n", MICROPY_FULL_VERSION_INFO, CIRCUITPY_BOARD_ID);
868876
#if CIRCUITPY_MICROCONTROLLER && COMMON_HAL_MCU_PROCESSOR_UID_LENGTH > 0
@@ -881,10 +889,6 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
881889

882890

883891
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
884-
// Get the base filesystem.
885-
fs_user_mount_t *vfs = filesystem_circuitpy();
886-
FATFS *fs = &vfs->fatfs;
887-
888892
boot_output = NULL;
889893
#if CIRCUITPY_STATUS_BAR
890894
supervisor_status_bar_resume();
@@ -906,16 +910,16 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
906910
// in case power is momentary or will fail shortly due to, say a low, battery.
907911
mp_hal_delay_ms(1000);
908912

909-
// USB isn't up, so we can write the file.
910-
// operating at the oofatfs (f_open) layer means the usb concurrent write permission
911-
// is not even checked!
912913
f_open(fs, &boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS);
913914
UINT chars_written;
914915
f_write(&boot_output_file, boot_text.buf, boot_text.len, &chars_written);
915916
f_close(&boot_output_file);
916917
filesystem_flush();
917918
}
918919
#endif
920+
921+
// Back to regular filesystem protections.
922+
filesystem_set_ignore_write_protection(vfs, false);
919923
}
920924

921925
cleanup_after_vm(_exec_result.exception);

supervisor/filesystem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ void filesystem_set_internal_writable_by_usb(bool usb_writable);
2121
void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection);
2222
void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable);
2323
void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concurrent_write_protection);
24+
void filesystem_set_ignore_write_protection(fs_user_mount_t *vfs, bool ignore_write_protection);
2425

2526
// Whether user code can modify the filesystem. It doesn't depend on the state
2627
// of USB. Don't use this for a workflow. In workflows, grab the shared file

supervisor/shared/filesystem.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,14 @@ void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable) {
248248

249249
bool filesystem_is_writable_by_python(fs_user_mount_t *vfs) {
250250
return ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0) ||
251-
((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) == 0);
251+
((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) == 0) ||
252+
((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION) != 0);
252253
}
253254

254255
bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs) {
255256
return ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0) ||
256-
((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) != 0);
257+
((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) != 0) ||
258+
((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION) != 0);
257259
}
258260

259261
void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection) {
@@ -268,6 +270,14 @@ void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concu
268270
}
269271
}
270272

273+
void filesystem_set_ignore_write_protection(fs_user_mount_t *vfs, bool ignore_write_protection) {
274+
if (ignore_write_protection) {
275+
vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION;
276+
} else {
277+
vfs->blockdev.flags &= ~MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION;
278+
}
279+
}
280+
271281
bool filesystem_present(void) {
272282
return _circuitpy_vfs.len > 0;
273283
}

supervisor/shared/usb/usb_msc_flash.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ bool tud_msc_is_writable_cb(uint8_t lun) {
249249
if (vfs == NULL) {
250250
return false;
251251
}
252-
if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL || !filesystem_is_writable_by_usb(vfs)) {
252+
if (!filesystem_is_writable_by_usb(vfs)) {
253253
return false;
254254
}
255255
// Lock the blockdev once we say we're writable.

0 commit comments

Comments
 (0)