Flash encryption and FAT filesystem corruption
Posted: Fri Dec 02, 2022 12:07 am
Our team's project is using the FatFs file system demonstrated in the wear_levelling example project to embed three text files up to 4KB each. After enabling flash encryption on the FAT data partition, we have noticed that the second or third file will periodically become corrupted entirely for small strings, or corrupted in the second half of larger files. This occurs every time after the flash partition has been erased and reformatted, and is also occasionally seen after deleting and replacing files. The corrupted values appear to be consistent for a given file (i.e the string '"written using ESP-IDF v4.4.2-2-gc59a104546" will always become "�(p�`���b�,(�`q:�`�k" when corrupted).
This behavior was recreated on the wear_levelling example with a few modifications on an ESP32-PICO-MINI-02 devkit with flash encryption and secure boot v2 enabled. Further experimentation showed that the issue would disappear when the FAT partition size was at least 0x84000 bytes large when WL_SECTOR_SIZE was set to 4096 in the sdkconfig, or 0xB1000 bytes for a sector size of 512.
It is noted in the flash encryption documentation that the NVS storage library is not compatible with flash encryption, but we could not find direct references to the FatFs library. Is flash encryption compatible with the FAT filesystem? And if so, are there additional minimum partition size requirements beyond those described in the FatFs documentation to ensure proper operation?
Modified wear_levelling example code:
Monitor output of bug occuring:
This behavior was recreated on the wear_levelling example with a few modifications on an ESP32-PICO-MINI-02 devkit with flash encryption and secure boot v2 enabled. Further experimentation showed that the issue would disappear when the FAT partition size was at least 0x84000 bytes large when WL_SECTOR_SIZE was set to 4096 in the sdkconfig, or 0xB1000 bytes for a sector size of 512.
It is noted in the flash encryption documentation that the NVS storage library is not compatible with flash encryption, but we could not find direct references to the FatFs library. Is flash encryption compatible with the FAT filesystem? And if so, are there additional minimum partition size requirements beyond those described in the FatFs documentation to ensure proper operation?
Modified wear_levelling example code:
Code: Select all
void app_main(void)
{
ESP_LOGI(TAG, "Mounting FAT filesystem");
// To mount device we need name of device partition, define base_path
// and allow format partition in case if it is new one and was not formated before
const esp_vfs_fat_mount_config_t mount_config = {
.max_files = 4,
.format_if_mount_failed = true,
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE
};
esp_err_t err = esp_vfs_fat_spiflash_mount(base_path, "storage", &mount_config, &s_wl_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
return;
}
ESP_LOGI(TAG, "Opening file");
FILE *f = fopen("/spiflash/hello.txt", "wb");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
fprintf(f, "written using ESP-IDF %s\n", esp_get_idf_version());
fclose(f);
ESP_LOGI(TAG, "File written");
// Open file for reading
ESP_LOGI(TAG, "Reading file");
f = fopen("/spiflash/hello.txt", "rb");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}
char line[128];
fgets(line, sizeof(line), f);
fclose(f);
// strip newline
char *pos = strchr(line, '\n');
if (pos) {
*pos = '\0';
}
ESP_LOGI(TAG, "Read from file: '%s'", line);
//File 2
ESP_LOGI(TAG, "Opening file");
f = fopen("/spiflash/hello2.txt", "wb");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
fprintf(f, "written using ESP-IDF %s\n", esp_get_idf_version());
fclose(f);
ESP_LOGI(TAG, "File written");
// Open file for reading
ESP_LOGI(TAG, "Reading file");
f = fopen("/spiflash/hello2.txt", "rb");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}
fgets(line, sizeof(line), f);
fclose(f);
// strip newline
pos = strchr(line, '\n');
if (pos) {
*pos = '\0';
}
ESP_LOGI(TAG, "Read from file: '%s'", line);
//File 3
ESP_LOGI(TAG, "Opening file");
f = fopen("/spiflash/hello3.txt", "wb");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
fprintf(f, "written using ESP-IDF %s\n", esp_get_idf_version());
fclose(f);
ESP_LOGI(TAG, "File written");
// Open file for reading
ESP_LOGI(TAG, "Reading file");
f = fopen("/spiflash/hello3.txt", "rb");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}
fgets(line, sizeof(line), f);
fclose(f);
// strip newline
pos = strchr(line, '\n');
if (pos) {
*pos = '\0';
}
ESP_LOGI(TAG, "Read from file: '%s'", line);
// Unmount FATFS
ESP_LOGI(TAG, "Unmounting FAT filesystem");
ESP_ERROR_CHECK( esp_vfs_fat_spiflash_unmount(base_path, s_wl_handle));
ESP_LOGI(TAG, "Done");
}
Code: Select all
I (0) cpu_start: App cpu up.
I (179) cpu_start: Pro cpu start user code
I (179) cpu_start: cpu freq: 160000000
I (179) cpu_start: Application information:
I (184) cpu_start: Project name: wear_levelling_example
I (190) cpu_start: App version: 1
I (195) cpu_start: Compile time: Dec 1 2022 14:40:40
I (201) cpu_start: ELF file SHA256: bea26e30432862ed...
I (207) cpu_start: ESP-IDF: v4.4.2-2-gc59a104546
I (213) heap_init: Initializing. RAM available for dynamic allocation:
I (220) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (226) heap_init: At 3FFB2C58 len 0002D3A8 (180 KiB): DRAM
I (232) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (239) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (245) heap_init: At 4008B6D4 len 0001492C (82 KiB): IRAM
I (252) spi_flash: detected chip: generic
I (256) spi_flash: flash io: dio
W (260) flash_encrypt: Flash encryption mode is DEVELOPMENT (not secure)
I (269) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (278) example: Mounting FAT filesystem
W (288) vfs_fat_spiflash: f_mount failed (13)
I (298) vfs_fat_spiflash: Formatting FATFS partition, allocation unit size=512
I (1998) vfs_fat_spiflash: Mounting again
I (1998) example: Opening file
I (2798) example: File written
I (2798) example: Reading file
I (2808) example: Read from file: 'written using ESP-IDF v4.4.2-2-gc59a104546'
I (2808) example: Opening file
I (3628) example: File written
I (3638) example: Reading file
I (3638) example: Read from file: 'written using ESP-IDF v4.4.2-2-gc59a104546'
I (3648) example: Opening file
I (4478) example: File written
I (4488) example: Reading file
I (4498) example: Read from file: '�(p�`���b�,(�`q:�`�k'
I (4498) example: Unmounting FAT filesystem
I (4638) example: Done