From 3d66ed27cef459fad56abac0191c7529de6f8094 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 3 Jan 2023 17:18:11 -0600 Subject: [PATCH] oofatfs: enable use of random volume IDs This may help address #7409 if the underlying cause is the deterministic volume ID. However, not all boards have working urandom (samd21 at least does not) so a couple of fallbacks are attempted when it fails. I verified that on a pico_w, each `storage.erase_filesystem()` gives a distinct 32-bit volume ID (pico_w's urandom can never fail) --- lib/oofatfs/ff.c | 12 +++++++++--- lib/oofatfs/ff.h | 4 ++++ lib/oofatfs/ffconf.h | 6 +++++- py/circuitpy_mpconfig.h | 1 + supervisor/shared/fatfs.c | 18 +++++++++++++++++- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/lib/oofatfs/ff.c b/lib/oofatfs/ff.c index e6afd57800..9d3c67cf7d 100644 --- a/lib/oofatfs/ff.c +++ b/lib/oofatfs/ff.c @@ -257,6 +257,11 @@ #define GET_FATTIME() get_fattime() #endif +#if FF_FS_MAKE_VOLID == 1 +#define MAKE_VOLID(x) (make_volid()) +#else +#define MAKE_VOLID(x) (GET_FATTIME()) +#endif /* File lock controls */ #if FF_FS_LOCK != 0 @@ -5421,6 +5426,7 @@ FRESULT f_mkfs ( DWORD tbl[3]; #endif + DWORD volid = MAKE_VOLID(); /* Check mounted drive and clear work area */ fs->fs_type = 0; /* Clear mounted volume */ @@ -5622,7 +5628,7 @@ FRESULT f_mkfs ( st_dword(buf + BPB_DataOfsEx, b_data - b_vol); /* Data offset [sector] */ st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */ st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]); /* Root dir cluster # */ - st_dword(buf + BPB_VolIDEx, GET_FATTIME()); /* VSN */ + st_dword(buf + BPB_VolIDEx, volid); /* VSN */ st_word(buf + BPB_FSVerEx, 0x100); /* Filesystem version (1.00) */ for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */ for (buf[BPB_SecPerClusEx] = 0, i = au; i >>= 1; buf[BPB_SecPerClusEx]++) ; /* Log2 of cluster size [sector] */ @@ -5758,7 +5764,7 @@ FRESULT f_mkfs ( st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */ #if FF_MKFS_FAT32 if (fmt == FS_FAT32) { - st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */ + st_dword(buf + BS_VolID32, volid); /* VSN */ st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ @@ -5769,7 +5775,7 @@ FRESULT f_mkfs ( } else #endif { - st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */ + st_dword(buf + BS_VolID, volid); /* VSN */ st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ buf[BS_BootSig] = 0x29; /* Extended boot signature */ diff --git a/lib/oofatfs/ff.h b/lib/oofatfs/ff.h index a8aa00e9af..b133d770db 100644 --- a/lib/oofatfs/ff.h +++ b/lib/oofatfs/ff.h @@ -334,6 +334,10 @@ FRESULT f_setcp (WORD cp); /* Set curre DWORD get_fattime (void); #endif +#if FF_FS_MAKE_VOLID +DWORD make_volid (void); +#endif + /* LFN support functions */ #if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */ WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ diff --git a/lib/oofatfs/ffconf.h b/lib/oofatfs/ffconf.h index 248987dda3..52ff6d0a7a 100644 --- a/lib/oofatfs/ffconf.h +++ b/lib/oofatfs/ffconf.h @@ -373,6 +373,10 @@ / SemaphoreHandle_t and etc. A header file for O/S definitions needs to be / included somewhere in the scope of ff.h. */ - +#ifndef FF_FS_MAKE_VOLID +#define FF_FS_MAKE_VOLID (0) +#endif +/* The option FF_FS_MAKE_VOLID enables the use of a function to return a 32-bit volume identifier. +/ If it is disabled, a Volume ID based on the current time is used. */ /*--- End of configuration options ---*/ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index dc528d0787..8bfb69297a 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -594,6 +594,7 @@ void supervisor_run_background_tasks_if_tick(void); #define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (0) #endif +#define FF_FS_MAKE_VOLID (1) #define MICROPY_PY_OPTIMIZE_PROPERTY_FLASH_SIZE (CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE) diff --git a/supervisor/shared/fatfs.c b/supervisor/shared/fatfs.c index 76db02d6bf..f1452bf567 100644 --- a/supervisor/shared/fatfs.c +++ b/supervisor/shared/fatfs.c @@ -28,9 +28,11 @@ #include "py/runtime.h" #include "lib/oofatfs/ff.h" -#include "shared/timeutils/timeutils.h" +#include "shared-bindings/microcontroller/Processor.h" +#include "shared-bindings/os/__init__.h" #include "shared-bindings/rtc/RTC.h" #include "shared-bindings/time/__init__.h" +#include "shared/timeutils/timeutils.h" DWORD _time_override = 0; DWORD get_fattime(void) { @@ -50,3 +52,17 @@ DWORD get_fattime(void) { void override_fattime(DWORD time) { _time_override = time; } + +DWORD make_volid(void) { + DWORD result; + if (!common_hal_os_urandom((uint8_t *)&result, sizeof(result))) { + #if CIRCUITPY_MICROCONTROLLER && COMMON_HAL_MCU_PROCESSOR_UID_LENGTH >= 4 + uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH]; + common_hal_mcu_processor_get_uid(raw_id); + memcpy(&result, raw_id, sizeof(result)); + #else + result = (DWORD)common_hal_time_monotonic_ns(); + #endif + } + return result; +}