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)
This commit is contained in:
Jeff Epler 2023-01-03 17:18:11 -06:00
parent dc363e5a87
commit 3d66ed27ce
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
5 changed files with 36 additions and 5 deletions

View File

@ -257,6 +257,11 @@
#define GET_FATTIME() get_fattime() #define GET_FATTIME() get_fattime()
#endif #endif
#if FF_FS_MAKE_VOLID == 1
#define MAKE_VOLID(x) (make_volid())
#else
#define MAKE_VOLID(x) (GET_FATTIME())
#endif
/* File lock controls */ /* File lock controls */
#if FF_FS_LOCK != 0 #if FF_FS_LOCK != 0
@ -5421,6 +5426,7 @@ FRESULT f_mkfs (
DWORD tbl[3]; DWORD tbl[3];
#endif #endif
DWORD volid = MAKE_VOLID();
/* Check mounted drive and clear work area */ /* Check mounted drive and clear work area */
fs->fs_type = 0; /* Clear mounted volume */ 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_DataOfsEx, b_data - b_vol); /* Data offset [sector] */
st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */ 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_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) */ 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_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] */ 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] */ st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */
#if FF_MKFS_FAT32 #if FF_MKFS_FAT32
if (fmt == FS_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_FATSz32, sz_fat); /* FAT size [sector] */
st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */
st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */
@ -5769,7 +5775,7 @@ FRESULT f_mkfs (
} else } else
#endif #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] */ st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */
buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig] = 0x29; /* Extended boot signature */ buf[BS_BootSig] = 0x29; /* Extended boot signature */

View File

@ -334,6 +334,10 @@ FRESULT f_setcp (WORD cp); /* Set curre
DWORD get_fattime (void); DWORD get_fattime (void);
#endif #endif
#if FF_FS_MAKE_VOLID
DWORD make_volid (void);
#endif
/* LFN support functions */ /* LFN support functions */
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */ #if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */

View File

@ -373,6 +373,10 @@
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be / SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */ / 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 ---*/ /*--- End of configuration options ---*/

View File

@ -594,6 +594,7 @@ void supervisor_run_background_tasks_if_tick(void);
#define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (0) #define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (0)
#endif #endif
#define FF_FS_MAKE_VOLID (1)
#define MICROPY_PY_OPTIMIZE_PROPERTY_FLASH_SIZE (CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE) #define MICROPY_PY_OPTIMIZE_PROPERTY_FLASH_SIZE (CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE)

View File

@ -28,9 +28,11 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "lib/oofatfs/ff.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/rtc/RTC.h"
#include "shared-bindings/time/__init__.h" #include "shared-bindings/time/__init__.h"
#include "shared/timeutils/timeutils.h"
DWORD _time_override = 0; DWORD _time_override = 0;
DWORD get_fattime(void) { DWORD get_fattime(void) {
@ -50,3 +52,17 @@ DWORD get_fattime(void) {
void override_fattime(DWORD time) { void override_fattime(DWORD time) {
_time_override = 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;
}