mirror of https://github.com/ARMmbed/mbed-os.git
fatfs: Added erase disk to format
Right now, many users are trying out many different filesystems. Unfortunately, this can leave partially written filesystems on disk in various states. A very common pattern for using embedded filesystems is to attempt a mount, and on failure, format the storage with the filesystem. Unfortunately, this simply doesn't work if you try to change the filesystem being used on a piece of storage. Filesystems don't always use the same regions of storage, and can leave enough metadata lying around from old filesystems to trick a different mount into thinking a valid filesystem exists on disk. The filesystems we have were never designed to check for malicious modification and can't protect against arbitrary changes. That being said, it's caused enough problems for users, so as a workaround this patch adds a disk erase to the FAT filesystem format. The most common error happens when you use LittleFS, followed by FAT, followed again by LittleFS. No other combination of filesystem usage has shown a similar failure, but it is possible after extensive filesystem use, so it is still suggested to force a format of the storage when changing filesystems.pull/6866/head
parent
16ab71864e
commit
e77d57e0bc
|
@ -333,24 +333,83 @@ int FATFileSystem::unmount()
|
|||
int FATFileSystem::format(BlockDevice *bd, bd_size_t cluster_size)
|
||||
{
|
||||
FATFileSystem fs;
|
||||
int err = fs.mount(bd, false);
|
||||
fs.lock();
|
||||
|
||||
int err = bd->init();
|
||||
if (err) {
|
||||
fs.unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
// erase first handful of blocks
|
||||
bd_size_t header = 2*bd->get_erase_size();
|
||||
err = bd->erase(0, header);
|
||||
if (err) {
|
||||
bd->deinit();
|
||||
fs.unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
if (bd->get_erase_value() < 0) {
|
||||
// erase is unknown, need to write 1s
|
||||
bd_size_t program_size = bd->get_program_size();
|
||||
void *buf = malloc(program_size);
|
||||
if (!buf) {
|
||||
bd->deinit();
|
||||
fs.unlock();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(buf, 0xff, program_size);
|
||||
|
||||
for (bd_addr_t i = 0; i < header; i += program_size) {
|
||||
err = bd->program(buf, i, program_size);
|
||||
if (err) {
|
||||
free(buf);
|
||||
bd->deinit();
|
||||
fs.unlock();
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
// trim entire device to indicate it is unneeded
|
||||
err = bd->trim(0, bd->size());
|
||||
if (err) {
|
||||
bd->deinit();
|
||||
fs.unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bd->deinit();
|
||||
if (err) {
|
||||
fs.unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
err = fs.mount(bd, false);
|
||||
if (err) {
|
||||
fs.unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
// Logical drive number, Partitioning rule, Allocation unit size (bytes per cluster)
|
||||
fs.lock();
|
||||
FRESULT res = f_mkfs(fs._fsid, FM_ANY | FM_SFD, cluster_size, NULL, 0);
|
||||
fs.unlock();
|
||||
if (res != FR_OK) {
|
||||
fs.unmount();
|
||||
fs.unlock();
|
||||
return fat_error_remap(res);
|
||||
}
|
||||
|
||||
err = fs.unmount();
|
||||
if (err) {
|
||||
fs.unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
fs.unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue