From adb362fc5cc87374817b20ac891d3b71928451e1 Mon Sep 17 00:00:00 2001 From: Piclaw Date: Tue, 9 Jun 2026 09:36:07 -0700 Subject: [PATCH 1/2] tools/ci_fetch_deps: add lib/mbedtls/ to nordic submodule list nordic boards build with CIRCUITPY_HASHLIB_MBEDTLS_ONLY=1 which pulls sha1.c / sha256.c / sha512.c / platform_util.c from lib/mbedtls but ci_fetch_deps.py never fetched the submodule, breaking custom builds. Drive-by; not strictly part of the #10972 fix, but needed for the custom build-board workflow to produce a CLUE UF2 for verification. --- tools/ci_fetch_deps.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/ci_fetch_deps.py b/tools/ci_fetch_deps.py index 339eec287126d..05559ac2d126e 100644 --- a/tools/ci_fetch_deps.py +++ b/tools/ci_fetch_deps.py @@ -69,6 +69,7 @@ def _all_submodules(): "mimxrt10xx": ["extmod/ulab/", "lib/tinyusb/", "lib/tlsf", "data/nvm.toml/"], "nordic": [ "extmod/ulab/", + "lib/mbedtls/", "lib/mp3/", "lib/protomatter/", "lib/tinyusb/", From a8924a8ef103b6bdbb8bbf47ad928ca748fb1fde Mon Sep 17 00:00:00 2001 From: Piclaw Date: Tue, 9 Jun 2026 10:15:43 -0700 Subject: [PATCH 2/2] supervisor/filesystem: let alternative writers (BLE-FT, web workflow) bypass STA_PROTECT while they hold the lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since #10659, filesystem_is_writable_by_python() returns false on any USB-device-capable board after main.c boot (CONCURRENT_WRITE_PROTECTED and USB_WRITABLE are both set). vfs_fat_diskio.c:disk_ioctl(IOCTL_STATUS) calls this function and reports STA_PROTECT when it returns false, so f_open(FA_WRITE) returns FR_WRITE_PROTECTED. This affects every non-USB-MSC writer that calls f_open directly through FatFS: - BLE File Transfer (supervisor/shared/bluetooth/file_transfer.c): all WRITE/MOVE/MKDIR/DELETE commands fail with STATUS_ERROR_READONLY even when the board has no host on the bus. This is the original #10972 repro on CLUE running from battery. - Web workflow PUT/POST/MOVE/DELETE (supervisor/shared/web_workflow): same path, web-editor #460/#506 surfaces this as a read-only error. - storage.remount(readonly=False): can take the lock but then can't actually write while the lock is held. Each of these already calls filesystem_lock() to claim the blockdev LOCKED flag before writing. USB MSC does NOT go through filesystem_lock; it grabs LOCKED directly via blockdev_lock() inside tud_msc_is_writable_cb. So filesystem_lock() is exactly the right place to grant temporary write permission via IGNORE_WRITE_PROTECTION, mirroring the pattern main.c uses around boot.py. After this change: - filesystem_lock() is the single source of truth for 'I'm the local writer right now'. Holders can f_open(FA_WRITE) and operate normally. - USB MSC continues to be mutually excluded via LOCKED; it never sets IGNORE_WRITE_PROTECTION because it doesn't go through filesystem_lock. - _is_writable_by_python and _is_writable_by_usb are unchanged; the symmetric mutex from #10659 is preserved. - Python direct open(FA_WRITE) without a lock still requires storage.disable_usb_drive() or storage.remount(readonly=False) — same as current behavior. Fixes #10972 --- supervisor/shared/filesystem.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/supervisor/shared/filesystem.c b/supervisor/shared/filesystem.c index 55fef541a6792..1d2a6180a9458 100644 --- a/supervisor/shared/filesystem.c +++ b/supervisor/shared/filesystem.c @@ -327,12 +327,23 @@ bool filesystem_lock(fs_user_mount_t *fs_mount) { return false; } fs_mount->lock_count += 1; + // CIRCUITPY-CHANGE: while a non-USB-MSC writer (BLE file transfer, web + // workflow, storage.remount) holds the filesystem lock, allow the + // FatFS f_open(FA_WRITE) path to bypass STA_PROTECT. Without this, the + // disk_ioctl(IOCTL_STATUS) -> filesystem_is_writable_by_python() check + // added by #10659 always sets STA_PROTECT on USB-device-capable boards, + // so even after the lock is held, f_open returns FR_WRITE_PROTECTED. + // USB MSC takes the lock via blockdev_lock() directly, NOT via + // filesystem_lock(), so this flag is never set on its behalf. + fs_mount->blockdev.flags |= MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION; return true; } void filesystem_unlock(fs_user_mount_t *fs_mount) { fs_mount->lock_count -= 1; if (fs_mount->lock_count == 0) { + // CIRCUITPY-CHANGE: clear the bypass when releasing the lock. + fs_mount->blockdev.flags &= ~MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION; blockdev_unlock(fs_mount); } }