diff --git a/components/micropython/CMakeLists.txt b/components/micropython/CMakeLists.txt
index 6efb5c7b96269ad23d0ae19de0fe3b08724427ed..370031c54bb193dced9ba331fcc97fd4bea8ebe7 100644
--- a/components/micropython/CMakeLists.txt
+++ b/components/micropython/CMakeLists.txt
@@ -37,15 +37,6 @@ set(MICROPY_SOURCE_SHARED
     ${MICROPY_DIR}/shared/runtime/pyexec.c
 )
 
-set(MICROPY_SOURCE_LIB
-    ${MICROPY_DIR}/lib/littlefs/lfs1.c
-    ${MICROPY_DIR}/lib/littlefs/lfs1_util.c
-    ${MICROPY_DIR}/lib/littlefs/lfs2.c
-    ${MICROPY_DIR}/lib/littlefs/lfs2_util.c
-    ${MICROPY_DIR}/lib/oofatfs/ff.c
-    ${MICROPY_DIR}/lib/oofatfs/ffunicode.c
-)
-
 set(MICROPY_SOURCE_DRIVERS
     ${MICROPY_DIR}/drivers/bus/softspi.c
     ${MICROPY_DIR}/drivers/dht/dht.c
@@ -85,7 +76,6 @@ set(MICROPY_SOURCE_QSTR
     "${MICROPY_SOURCE_EXTMOD}"
     "${MICROPY_SOURCE_USERMOD}"
     "${MICROPY_SOURCE_SHARED}"
-    "${MICROPY_SOURCE_LIB}"
     "${MICROPY_SOURCE_PORT}"
 )
 
@@ -138,7 +128,6 @@ idf_component_register(
         ${MICROPY_SOURCE_EXTMOD}
         ${MICROPY_SOURCE_USERMOD}
         ${MICROPY_SOURCE_SHARED}
-        ${MICROPY_SOURCE_LIB}
         ${MICROPY_SOURCE_DRIVERS}
         ${MICROPY_SOURCE_PORT}
     INCLUDE_DIRS
@@ -182,4 +171,4 @@ target_compile_definitions(${COMPONENT_TARGET} PUBLIC
 
 include("${MICROPY_DIR}/py/mkrules.cmake")
 
-target_link_libraries(${COMPONENT_LIB} INTERFACE "-u flow3r_startup")
\ No newline at end of file
+target_link_libraries(${COMPONENT_LIB} INTERFACE "-u flow3r_startup")
diff --git a/components/st3m/CMakeLists.txt b/components/st3m/CMakeLists.txt
index 34f3009113cd9c477e244a9bc3944d1ccf4bdcd4..408dad9876f5b3e4247bca20ce0b1e42003f208d 100644
--- a/components/st3m/CMakeLists.txt
+++ b/components/st3m/CMakeLists.txt
@@ -18,6 +18,7 @@ idf_component_register(
         st3m_ringbuffer.c
         st3m_tar.c
         st3m_fs.c
+        st3m_fs_flash.c
     INCLUDE_DIRS
         .
     REQUIRES
diff --git a/components/st3m/st3m_fs.c b/components/st3m/st3m_fs.c
index f774128ab447719ff91e2f16c430a7dc2401eb15..2a705a6003f3deeb6937b240ead5eef5d72bc358 100644
--- a/components/st3m/st3m_fs.c
+++ b/components/st3m/st3m_fs.c
@@ -1,5 +1,6 @@
 #include "st3m_fs.h"
 
+#include "st3m_fs_flash.h"
 #include "st3m_mode.h"
 #include "st3m_sys_data.h"
 #include "st3m_tar.h"
@@ -37,9 +38,6 @@ static struct dirent _root_dirents[4] = {
     },
 };
 
-// Handle of the wear levelling library instance
-static wl_handle_t s_wl_handle = WL_INVALID_HANDLE;
-
 static int _root_vfs_close(int fd) { return 0; }
 
 static int _root_vfs_fcntl(int fd, int cmd, int arg) { return 0; }
@@ -117,23 +115,15 @@ static esp_vfs_t _root_vfs = {
 void st3m_fs_init(void) {
     esp_err_t err;
 
+    st3m_fs_flash_init();
+
     if ((err = esp_vfs_register("", &_root_vfs, NULL)) != ESP_OK) {
         ESP_LOGE(TAG, "Failed to mount root VFS: %s", esp_err_to_name(err));
         return;
     }
 
-    const esp_vfs_fat_mount_config_t mount_config = {
-        .max_files = 4,
-        .format_if_mount_failed = true,
-        .allocation_unit_size = CONFIG_WL_SECTOR_SIZE
-    };
-
-    err = esp_vfs_fat_spiflash_mount("/flash", "vfs", &mount_config,
-                                     &s_wl_handle);
-    if (err != ESP_OK) {
+    if ((err = st3m_fs_flash_mount()) != ESP_OK) {
         ESP_LOGE(TAG, "Failed to mount FAT FS: %s", esp_err_to_name(err));
         return;
     }
-
-    ESP_LOGI(TAG, "Mounted Flash VFS Partition at /flash");
-}
+}
\ No newline at end of file
diff --git a/components/st3m/st3m_fs_flash.c b/components/st3m/st3m_fs_flash.c
new file mode 100644
index 0000000000000000000000000000000000000000..a3a9f4f5fe8a46289a3feb807ca322e97634752a
--- /dev/null
+++ b/components/st3m/st3m_fs_flash.c
@@ -0,0 +1,259 @@
+#include "st3m_fs_flash.h"
+
+#include "esp_log.h"
+#include "esp_system.h"
+#include "esp_vfs.h"
+#include "esp_vfs_fat.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/semphr.h"
+
+#include "diskio.h"
+#include "diskio_impl.h"
+#include "diskio_wl.h"
+#include "vfs_fat_internal.h"
+
+static const char *TAG = "st3m-fs-flash";
+
+static SemaphoreHandle_t _mu = NULL;
+static st3m_fs_flash_status_t _status = st3m_fs_flash_status_unmounted;
+
+// Handle of the wear levelling library instance
+static wl_handle_t _wl_handle = WL_INVALID_HANDLE;
+
+void st3m_fs_flash_init(void) {
+    assert(_mu == NULL);
+    _mu = xSemaphoreCreateMutex();
+    assert(_mu != NULL);
+
+    const esp_partition_t *data_partition = esp_partition_find_first(
+        ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "vfs");
+    if (data_partition == NULL) {
+        ESP_LOGE(TAG, "Could not find data partition.");
+        return;
+    }
+    esp_err_t res = wl_mount(data_partition, &_wl_handle);
+    if (res != ESP_OK) {
+        ESP_LOGE(TAG, "Mounting wear leveling failed.");
+        return;
+    }
+}
+
+st3m_fs_flash_status_t st3m_fs_flash_get_status(void) {
+    xSemaphoreTake(_mu, portMAX_DELAY);
+    st3m_fs_flash_status_t st = _status;
+    xSemaphoreGive(_mu);
+    return st;
+}
+
+static esp_err_t _f_mount_rw(FATFS *fs, const char *drv,
+                             const esp_vfs_fat_mount_config_t *mount_config) {
+    FRESULT fresult = f_mount(fs, drv, 1);
+    if (fresult != FR_OK) {
+        ESP_LOGW(TAG, "f_mount failed (%d)", fresult);
+
+        bool need_mount_again =
+            (fresult == FR_NO_FILESYSTEM || fresult == FR_INT_ERR) &&
+            mount_config->format_if_mount_failed;
+        if (!need_mount_again) {
+            return ESP_FAIL;
+        }
+
+        const size_t workbuf_size = 4096;
+        void *workbuf = ff_memalloc(workbuf_size);
+        if (workbuf == NULL) {
+            return ESP_ERR_NO_MEM;
+        }
+
+        size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(
+            CONFIG_WL_SECTOR_SIZE, mount_config->allocation_unit_size);
+        ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d",
+                 alloc_unit_size);
+        const MKFS_PARM opt = { (BYTE)(FM_ANY | FM_SFD), 0, 0, 0,
+                                alloc_unit_size };
+        fresult = f_mkfs(drv, &opt, workbuf, workbuf_size);
+        free(workbuf);
+        workbuf = NULL;
+        if (fresult != FR_OK) {
+            ESP_LOGE(TAG, "f_mkfs failed: %d", fresult);
+            return ESP_FAIL;
+        }
+
+        ESP_LOGI(TAG, "Mounting again");
+        fresult = f_mount(fs, drv, 0);
+        if (fresult != FR_OK) {
+            ESP_LOGE(TAG, "f_mount failed after format: %d", fresult);
+            return ESP_FAIL;
+        }
+    }
+    return ESP_OK;
+}
+
+static esp_err_t _st3m_fs_flash_mount_unlocked(void) {
+    esp_err_t ret;
+
+    if (_status == st3m_fs_flash_status_mounted) {
+        return ESP_OK;
+    }
+
+    BYTE pdrv = 0xFF;
+    if ((ret = ff_diskio_get_drive(&pdrv)) != ESP_OK) {
+        ESP_LOGE(TAG, "Getting drive number failed: %s", esp_err_to_name(ret));
+        return ret;
+    }
+
+    char drv[3] = { (char)('0' + pdrv), ':', 0 };
+    if ((ret = ff_diskio_register_wl_partition(pdrv, _wl_handle)) != ESP_OK) {
+        ESP_LOGE(TAG, "Registering WL partition failed: %s",
+                 esp_err_to_name(ret));
+        return ret;
+    }
+
+    FATFS *fs;
+    esp_vfs_fat_mount_config_t mount_config = { .max_files = 16,
+                                                .format_if_mount_failed = true,
+                                                .allocation_unit_size =
+                                                    CONFIG_WL_SECTOR_SIZE };
+
+    ret = esp_vfs_fat_register("/flash", drv, mount_config.max_files, &fs);
+    if (ret == ESP_ERR_INVALID_STATE) {
+        // it's okay, already registered with VFS
+    } else if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Registering FAT/WL partition failed: %s",
+                 esp_err_to_name(ret));
+        return ret;
+    }
+
+    if ((ret = _f_mount_rw(fs, drv, &mount_config)) != ESP_OK) {
+        ESP_LOGE(TAG, "Registering FAT/WL partition failed: %s",
+                 esp_err_to_name(ret));
+        return ret;
+    }
+
+    ESP_LOGI(TAG, "Mounted Flash VFS Partition at /flash");
+    _status = st3m_fs_flash_status_mounted;
+    return ESP_OK;
+}
+
+esp_err_t st3m_fs_flash_mount(void) {
+    xSemaphoreTake(_mu, portMAX_DELAY);
+    esp_err_t ret = _st3m_fs_flash_mount_unlocked();
+    xSemaphoreGive(_mu);
+    return ret;
+}
+
+static esp_err_t _st3m_fs_flash_unmount_unlocked(void) {
+    if (_status == st3m_fs_flash_status_unmounted) {
+        return ESP_OK;
+    }
+
+    BYTE pdrv = ff_diskio_get_pdrv_wl(_wl_handle);
+    if (pdrv == 0xFF) {
+        ESP_LOGE(TAG, "Could not get drive number");
+        return ESP_FAIL;
+    }
+
+    esp_err_t ret;
+    char drv[3] = { (char)('0' + pdrv), ':', 0 };
+    f_mount(0, drv, 0);
+    ff_diskio_unregister(pdrv);
+    ff_diskio_clear_pdrv_wl(_wl_handle);
+    if ((ret = esp_vfs_fat_unregister_path("/flash")) != ESP_OK) {
+        ESP_LOGE(TAG, "Could not unmount: %s", esp_err_to_name(ret));
+        return ret;
+    }
+
+    _status = st3m_fs_flash_status_unmounted;
+    return ESP_OK;
+}
+
+esp_err_t st3m_fs_flash_unmount(void) {
+    xSemaphoreTake(_mu, portMAX_DELAY);
+    esp_err_t ret = _st3m_fs_flash_unmount_unlocked();
+    xSemaphoreGive(_mu);
+    return ret;
+}
+
+int32_t st3m_fs_flash_read(uint8_t lun, uint32_t lba, uint32_t offset,
+                           void *buffer, uint32_t bufsize) {
+    size_t src_addr = lba * wl_sector_size(_wl_handle) + offset;
+    esp_err_t ret = wl_read(_wl_handle, src_addr, buffer, bufsize);
+    if (ret == ESP_OK) {
+        return bufsize;
+    } else {
+        return 0;
+    }
+}
+
+int32_t st3m_fs_flash_write(uint8_t lun, uint32_t lba, uint32_t offset,
+                            const void *buffer, uint32_t bufsize) {
+    size_t sector_size = wl_sector_size(_wl_handle);
+
+    size_t start = lba * sector_size + offset;
+    size_t size = bufsize;
+
+    size_t start_align = (start % sector_size);
+    if (start_align != 0) {
+        start -= start_align;
+        size += start_align;
+    }
+
+    size_t size_align = (size % sector_size);
+    if (size_align != 0) {
+        size_align = sector_size - size_align;
+        size += size_align;
+    }
+
+    uint8_t *copy = malloc(size);
+    assert(copy != 0);
+
+    // Prefix, if any.
+    if (start_align != 0) {
+        esp_err_t ret = wl_read(_wl_handle, start, copy, sector_size);
+        if (ret != ESP_OK) {
+            free(copy);
+            return 0;
+        }
+    }
+    // Suffix, if any.
+    // TODO(q3k): skip if this is the same as the previous read.
+    if (size_align != 0) {
+        esp_err_t ret = wl_read(_wl_handle, start + size - sector_size,
+                                copy + size - sector_size, sector_size);
+        if (ret != ESP_OK) {
+            free(copy);
+            return 0;
+        }
+    }
+    // Main data.
+    memcpy(copy + start_align, buffer, bufsize);
+
+    // Erase and write.
+    wl_erase_range(_wl_handle, start, size);
+    esp_err_t ret = wl_write(_wl_handle, start, copy, size);
+    free(copy);
+    if (ret != ESP_OK) {
+        return 0;
+    }
+    return bufsize;
+}
+
+esp_err_t st3m_fs_flash_erase(void) {
+    xSemaphoreTake(_mu, portMAX_DELAY);
+    if (_status != st3m_fs_flash_status_unmounted) {
+        xSemaphoreGive(_mu);
+        ESP_LOGE(TAG, "Cannot erase flash while mounted");
+        return ESP_ERR_INVALID_STATE;
+    }
+    // Only erase first 32 sectors as that's enough to trigger FAT reformat on
+    // reboot.
+    esp_err_t ret =
+        wl_erase_range(_wl_handle, 0, wl_sector_size(_wl_handle) * 32);
+    xSemaphoreGive(_mu);
+    return ret;
+}
+
+size_t st3m_fs_flash_get_blocksize(void) { return wl_sector_size(_wl_handle); }
+size_t st3m_fs_flash_get_blockcount(void) {
+    return wl_size(_wl_handle) / wl_sector_size(_wl_handle);
+}
\ No newline at end of file
diff --git a/components/st3m/st3m_fs_flash.h b/components/st3m/st3m_fs_flash.h
new file mode 100644
index 0000000000000000000000000000000000000000..ce34afc9b0a4ccbe19a40bd03ccc7f3ba769e233
--- /dev/null
+++ b/components/st3m/st3m_fs_flash.h
@@ -0,0 +1,40 @@
+#pragma once
+
+// This subsystem manages the wear-leveled FAT32 partition on the built-in SPI
+// flash.
+
+#include "esp_err.h"
+
+typedef enum {
+    // Not mounted, can be accessed via _write, _read, _erase.
+    st3m_fs_flash_status_unmounted = 0,
+    // Mounted on /flash.
+    st3m_fs_flash_status_mounted = 1,
+    st3m_fs_flash_status_error = 2,
+} st3m_fs_flash_status_t;
+
+// Return the current state/status of the internal flash FAT32 partition.
+st3m_fs_flash_status_t st3m_fs_flash_get_status(void);
+// Mount the partition on /flash. No-op if already mounted.
+esp_err_t st3m_fs_flash_mount(void);
+// Unmount the partition. No-op if already unmounted.
+esp_err_t st3m_fs_flash_unmount(void);
+
+// Read function for st3m_usb_msc. Should only be called if the flash is
+// unmounted.
+int32_t st3m_fs_flash_read(uint8_t lun, uint32_t lba, uint32_t offset,
+                           void *buffer, uint32_t bufsize);
+// Write function for st3m_usb_msc. Should only be called if the flash is
+// unmounted.
+int32_t st3m_fs_flash_write(uint8_t lun, uint32_t lba, uint32_t offset,
+                            const void *buffer, uint32_t bufsize);
+// Erase the FAT32 partition. Next mount will format it. Should only be called
+// if the flash is ummounted.
+esp_err_t st3m_fs_flash_erase(void);
+// Return block size (top-level, ie. as exposed by the wear leveling layer).
+size_t st3m_fs_flash_get_blocksize(void);
+// Return block count (top-level, ie. as exposed by the wear leveling layer).
+size_t st3m_fs_flash_get_blockcount(void);
+
+// Private.
+void st3m_fs_flash_init(void);
\ No newline at end of file
diff --git a/recovery/main/rec_main.c b/recovery/main/rec_main.c
index d03e5d14673e309e933aa96bdf02aa42e3952009..5729a49f30b4a5c77f0699b5754779d874da1bfd 100644
--- a/recovery/main/rec_main.c
+++ b/recovery/main/rec_main.c
@@ -4,10 +4,13 @@
 #include "freertos/task.h"
 
 #include "flow3r_bsp.h"
+#include "st3m_fs.h"
+#include "st3m_fs_flash.h"
 #include "st3m_gfx.h"
 #include "st3m_io.h"
 #include "st3m_usb.h"
 
+#include "rec_fatal.h"
 #include "rec_gui.h"
 #include "rec_vfs.h"
 
@@ -37,7 +40,10 @@ static void _main_disk_mode(void) {
 
 static void _main_erase_fat32(void) {
     rec_erasing_draw();
-    rec_vfs_wl_erase();
+    esp_err_t ret = st3m_fs_flash_erase();
+    if (ret != ESP_OK) {
+        rec_fatal("Erase failed");
+    }
     _cur_menu = &_erasedone_menu;
     _cur_menu->selected = 0;
 }
@@ -99,8 +105,7 @@ void app_main(void) {
     flow3r_bsp_display_set_backlight(100);
     flow3r_bsp_i2c_init();
     st3m_io_init();
-
-    rec_vfs_wl_init();
+    st3m_fs_init();
 
     TickType_t last_wake;
     last_wake = xTaskGetTickCount();
diff --git a/recovery/main/rec_vfs.c b/recovery/main/rec_vfs.c
index 5264f07f85c0bffdfa1720d8a85d08784f16c2ef..37accfbdefc3c8a4318ca04af1e0ce41f1ff6287 100644
--- a/recovery/main/rec_vfs.c
+++ b/recovery/main/rec_vfs.c
@@ -2,111 +2,23 @@
 
 #include "rec_fatal.h"
 
+#include "st3m_fs_flash.h"
 #include "st3m_usb.h"
 
 #include <string.h>
 
-static wl_handle_t _wl_handle = WL_INVALID_HANDLE;
-
-static int32_t _flash_read(uint8_t lun, uint32_t lba, uint32_t offset,
-                           void *buffer, uint32_t bufsize) {
-    size_t src_addr = lba * wl_sector_size(_wl_handle) + offset;
-    esp_err_t ret = wl_read(_wl_handle, src_addr, buffer, bufsize);
-    if (ret == ESP_OK) {
-        return bufsize;
-    } else {
-        return 0;
-    }
-}
-
-static int32_t _flash_write(uint8_t lun, uint32_t lba, uint32_t offset,
-                            const void *buffer, uint32_t bufsize) {
-    size_t sector_size = wl_sector_size(_wl_handle);
-
-    size_t start = lba * sector_size + offset;
-    size_t size = bufsize;
-
-    size_t start_align = (start % sector_size);
-    if (start_align != 0) {
-        start -= start_align;
-        size += start_align;
-    }
-
-    size_t size_align = (size % sector_size);
-    if (size_align != 0) {
-        size_align = sector_size - size_align;
-        size += size_align;
-    }
-
-    uint8_t *copy = malloc(size);
-    assert(copy != 0);
-
-    // Prefix, if any.
-    if (start_align != 0) {
-        esp_err_t ret = wl_read(_wl_handle, start, copy, sector_size);
-        if (ret != ESP_OK) {
-            free(copy);
-            return 0;
-        }
-    }
-    // Suffix, if any.
-    // TODO(q3k): skip if this is the same as the previous read.
-    if (size_align != 0) {
-        esp_err_t ret = wl_read(_wl_handle, start + size - sector_size,
-                                copy + size - sector_size, sector_size);
-        if (ret != ESP_OK) {
-            free(copy);
-            return 0;
-        }
-    }
-    // Main data.
-    memcpy(copy + start_align, buffer, bufsize);
-
-    // Erase and write.
-    wl_erase_range(_wl_handle, start, size);
-    esp_err_t ret = wl_write(_wl_handle, start, copy, size);
-    if (ret != ESP_OK) {
-        free(copy);
-        return 0;
-    }
-
-    return bufsize;
-}
-
-void rec_vfs_wl_init(void) {
-    const esp_partition_t *data_partition = esp_partition_find_first(
-        ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "vfs");
-    if (data_partition == NULL) {
-        rec_fatal("no data partition");
-    }
-    esp_err_t res = wl_mount(data_partition, &_wl_handle);
-    if (res != ESP_OK) {
-        rec_fatal("wear leveling failed");
-    }
-}
-
 void rec_vfs_wl_msc_start(void) {
     st3m_usb_msc_conf_t msc = {
-        .block_size = wl_sector_size(_wl_handle),
-        .block_count = wl_size(_wl_handle) / wl_sector_size(_wl_handle),
+        .block_size = st3m_fs_flash_get_blocksize(),
+        .block_count = st3m_fs_flash_get_blockcount(),
         .product_id = { 'f', 'l', 'o', 'w', '3', 'r', 0, 0, 0, 0, 0, 0, 0, 0, 0,
                         0 },
-        .fn_read10 = _flash_read,
-        .fn_write10 = _flash_write,
+        .fn_read10 = st3m_fs_flash_read,
+        .fn_write10 = st3m_fs_flash_write,
     };
     st3m_usb_mode_t usb_mode = {
         .kind = st3m_usb_mode_kind_disk,
         .disk = &msc,
     };
     st3m_usb_mode_switch(&usb_mode);
-}
-
-void rec_vfs_wl_erase(void) {
-    // Only erase first 32 sectors as that's enough to trigger FAT reformat on
-    // reboot.
-    esp_err_t ret =
-        wl_erase_range(_wl_handle, 0, wl_sector_size(_wl_handle) * 32);
-    if (ret != ESP_OK) {
-        rec_fatal("erase failed");
-    }
 }
\ No newline at end of file