Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions extmod/vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
#define MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED (0x0020)
// Bit set when something has claimed the right to mutate the blockdev.
#define MP_BLOCKDEV_FLAG_LOCKED (0x0040)
// Ignore write protections. Used to override other flags temporarily.
#define MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION (0x0080)

// constants for block protocol ioctl
#define MP_BLOCKDEV_IOCTL_INIT (1)
Expand Down
11 changes: 4 additions & 7 deletions extmod/vfs_fat.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,13 +427,10 @@ static MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_statvfs_obj, fat_vfs_statvfs);
static mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) {
fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in);

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

// check if we need to make the filesystem
FRESULT res = (self->blockdev.flags & MP_BLOCKDEV_FLAG_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK;
Expand Down
6 changes: 5 additions & 1 deletion extmod/vfs_fat_diskio.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
#include "lib/oofatfs/diskio.h"
#include "extmod/vfs_fat.h"

// CIRCUITPY-CHANGE
#include "supervisor/filesystem.h"

typedef void *bdev_t;
static fs_user_mount_t *disk_get_device(void *bdev) {
return (fs_user_mount_t *)bdev;
Expand Down Expand Up @@ -153,7 +156,8 @@ DRESULT disk_ioctl(
if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
// error initialising
stat = STA_NOINIT;
} else if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) {
// CIRCUITPY-CHANGE: writability from Python check
} else if (!filesystem_is_writable_by_python(vfs)) {
stat = STA_PROTECT;
} else {
stat = 0;
Expand Down
18 changes: 11 additions & 7 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,14 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
boot_output = &boot_text;
#endif

// Get the base filesystem.
fs_user_mount_t *vfs = filesystem_circuitpy();
FATFS *fs = &vfs->fatfs;

// Allow boot.py access to CIRCUITPY, and allow writes to boot_out.txt.
// We can't use the regular flags for this, because they might get modified inside boot.py.
filesystem_set_ignore_write_protection(vfs, true);

// Write version info
mp_printf(&mp_plat_print, "%s\nBoard ID:%s\n", MICROPY_FULL_VERSION_INFO, CIRCUITPY_BOARD_ID);
#if CIRCUITPY_MICROCONTROLLER && COMMON_HAL_MCU_PROCESSOR_UID_LENGTH > 0
Expand All @@ -881,10 +889,6 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {


#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
// Get the base filesystem.
fs_user_mount_t *vfs = filesystem_circuitpy();
FATFS *fs = &vfs->fatfs;

boot_output = NULL;
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_resume();
Expand All @@ -906,16 +910,16 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
// in case power is momentary or will fail shortly due to, say a low, battery.
mp_hal_delay_ms(1000);

// USB isn't up, so we can write the file.
// operating at the oofatfs (f_open) layer means the usb concurrent write permission
// is not even checked!
f_open(fs, &boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS);
UINT chars_written;
f_write(&boot_output_file, boot_text.buf, boot_text.len, &chars_written);
f_close(&boot_output_file);
filesystem_flush();
}
#endif

// Back to regular filesystem protections.
filesystem_set_ignore_write_protection(vfs, false);
}

cleanup_after_vm(_exec_result.exception);
Expand Down
1 change: 1 addition & 0 deletions supervisor/filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ void filesystem_set_internal_writable_by_usb(bool usb_writable);
void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection);
void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable);
void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concurrent_write_protection);
void filesystem_set_ignore_write_protection(fs_user_mount_t *vfs, bool ignore_write_protection);

// Whether user code can modify the filesystem. It doesn't depend on the state
// of USB. Don't use this for a workflow. In workflows, grab the shared file
Expand Down
14 changes: 12 additions & 2 deletions supervisor/shared/filesystem.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,14 @@ void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable) {

bool filesystem_is_writable_by_python(fs_user_mount_t *vfs) {
return ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0) ||
((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) == 0);
((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) == 0) ||
((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION) != 0);
}

bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs) {
return ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0) ||
((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) != 0);
((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) != 0) ||
((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION) != 0);
}

void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection) {
Expand All @@ -268,6 +270,14 @@ void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concu
}
}

void filesystem_set_ignore_write_protection(fs_user_mount_t *vfs, bool ignore_write_protection) {
if (ignore_write_protection) {
vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION;
} else {
vfs->blockdev.flags &= ~MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION;
}
}

bool filesystem_present(void) {
return _circuitpy_vfs.len > 0;
}
Expand Down
2 changes: 1 addition & 1 deletion supervisor/shared/usb/usb_msc_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ bool tud_msc_is_writable_cb(uint8_t lun) {
if (vfs == NULL) {
return false;
}
if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL || !filesystem_is_writable_by_usb(vfs)) {
if (!filesystem_is_writable_by_usb(vfs)) {
return false;
}
// Lock the blockdev once we say we're writable.
Expand Down