SPIFFS : FIXES FS corruption against high numbero f current losses, high number of files manipulation. FIXES LOG_BLOCK erasing handlers. FIXES Garbage Collector. Overall, SPIFFS should now be WAY MORE resilient to any form of misbehavior. In case of corrupted filesystem (should still be readable !), spamming 'mem spiffs check' from the client will ensure at least 2 new free 4k blocks each tile (if number of LOG_PAGE available is enough) and in the same pass will move/reorganize the LOG_PAGES of contextual blocks. Yiha

This commit is contained in:
cjbrigato 2019-08-13 15:58:08 +02:00 committed by Philippe Teuwen
parent 1da98c7aa6
commit 961f98c125
8 changed files with 100 additions and 69 deletions

View file

@ -8,27 +8,8 @@
//-----------------------------------------------------------------------------
// main code for HF Mifare aka ColinRun by Colin Brigato
//-----------------------------------------------------------------------------
#include "standalone.h" // standalone definitions
#include <stdbool.h> // for bool
#include <stdio.h>
#include <inttypes.h>
#include "hf_colin.h"
#include "appmain.h"
#include "fpgaloader.h"
#include "dbprint.h"
#include "ticks.h"
#include "commonutil.h"
#include "crc16.h"
#include "BigBuf.h"
#include "frozen.h"
#include "proxmark3_arm.h"
#include "mifaresim.h" // mifare1ksim
#include "mifareutil.h"
#include "iso14443a.h"
#include "util.h"
#include "vtsend.h"
#include "spiffs.h"
#include "string.h"
#define MF1KSZ 1024
#define MF1KSZSIZE 64
@ -720,8 +701,10 @@ readysim:
SpinOff(100);
LED_C_ON();
uint16_t flags;
switch (p_card.uidlen) {
DBGLEVEL = DBG_NONE;
//uint16_t flags=0;
/*switch (p_card.uidlen) {
case 10:
flags = FLAG_10B_UID_IN_DATA;
break;
@ -734,13 +717,23 @@ readysim:
default:
flags = FLAG_UID_IN_EMUL;
break;
}
}*/
// Use UID, SAK, ATQA from EMUL, if uid not defined
// if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
flags |= FLAG_UID_IN_EMUL;
//flags |= FLAG_UID_IN_EMUL;
//}
Mifare1ksim(flags | FLAG_MF_1K, 0, cjuid, 0, 0);
//flags |= FLAG_MF_1K;
//if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
// flags |= FLAG_UID_IN_EMUL;
//}
//flags = 0x10;
uint16_t flags = 0;
flags = 16;
DbprintfEx(FLAG_NEWLINE,"\n\n\n\n\n\n\n\nn\n\nn\n\n\nflags: %d (0x%02x)",flags,flags);
cjSetCursLeft();
SpinOff(1000);
Mifare1ksim(flags , 0, cjuid);
LED_C_OFF();
SpinOff(50);
vtsend_cursor_position_restore(NULL);

View file

@ -1518,6 +1518,10 @@ static void PacketReceived(PacketCommandNG *packet) {
test_spiffs();
break;
}
case CMD_SPIFFS_CHECK: {
rdv40_spiffs_check();
break;
}
case CMD_SPIFFS_MOUNT: {
rdv40_spiffs_lazy_mount();
break;
@ -1901,6 +1905,11 @@ void __attribute__((noreturn)) AppMain(void) {
#ifdef WITH_FLASH
// If flash is not present, BUSY_TIMEOUT kicks in, let's do it after USB
loadT55xxConfig();
//
// Enforce a spiffs check/garbage collection at boot so we are likely to never
// fall under the 2 contigous free blocks availables
rdv40_spiffs_check();
#endif
for (;;) {

View file

@ -22,9 +22,11 @@
// case, will ensure a flush by rollbacking to previous Unmounted state
#define RDV40_SPIFFS_CACHE_SZ ((LOG_PAGE_SIZE + 32) * 4)
#define SPIFFS_FD_SIZE (32)
#define RDV40_SPIFFS_MAX_FD (2)
#define RDV40_SPIFFS_MAX_FD (3)
#define RDV40_SPIFFS_FDBUF_SZ (SPIFFS_FD_SIZE * RDV40_SPIFFS_MAX_FD)
#define RDV40_LLERASE_BLOCKSIZE (64*1024)
#define RDV40_SPIFFS_LAZY_HEADER \
int changed = 0; \
if ((level == RDV40_SPIFFS_SAFETY_LAZY) || (level == RDV40_SPIFFS_SAFETY_SAFE)) { \
@ -43,12 +45,6 @@
RDV40_SPIFFS_SAFE_FOOTER
#include "spiffs.h"
#include "flashmem.h"
#include "dbprint.h"
#include "printf.h"
#include "common.h"
#include "string.h"
#include "BigBuf.h"
///// FLASH LEVEL R/W/E operations for feeding SPIFFS Driver/////////////////
static s32_t rdv40_spiffs_llread(u32_t addr, u32_t size, u8_t *dst) {
@ -70,28 +66,29 @@ static s32_t rdv40_spiffs_llwrite(u32_t addr, u32_t size, u8_t *src) {
static s32_t rdv40_spiffs_llerase(u32_t addr, u32_t size) {
uint8_t erased = 0;
if (!FlashInit()) {
return 130;
}
uint32_t bytes_erased = 0, bytes_remaining = size;
while (bytes_remaining > 0) {
addr += bytes_erased;
if (DBGLEVEL > 2) Dbprintf("LLERASEDBG : Orig addr : %d\n", addr);
uint8_t block, sector = 0;
block = addr / RDV40_LLERASE_BLOCKSIZE;
if (block){
addr = addr - (block*RDV40_LLERASE_BLOCKSIZE);
}
if (DBGLEVEL > 2) Dbprintf("LLERASEDBG : Result addr : %d\n", addr);
sector = addr / SPIFFS_CFG_LOG_BLOCK_SZ;
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
FlashSendByte(SECTORERASE);
Flash_TransferAdresse(addr);
FlashSendLastByte(0);
bytes_remaining -= 4096;
bytes_erased += 4096;
}
if (DBGLEVEL > 2) Dbprintf("LLERASEDBG : block : %d, sector : %d \n", block, sector);
erased = Flash_Erase4k(block, sector);
Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop();
return SPIFFS_OK;
return SPIFFS_OK == erased ;
}
////////////////////////////////////////////////////////////////////////////////
@ -162,6 +159,15 @@ int rdv40_spiffs_unmount() {
}
return ret;
}
int rdv40_spiffs_check() {
rdv40_spiffs_lazy_mount();
SPIFFS_check(&fs);
SPIFFS_gc_quick(&fs,0);
rdv40_spiffs_lazy_unmount();
rdv40_spiffs_lazy_mount();
return SPIFFS_gc(&fs,8192) == SPIFFS_OK;
}
////////////////////////////////////////////////////////////////////////////////
///// Base RDV40_SPIFFS_SAFETY_NORMAL operations////////////////////////////////
@ -533,21 +539,16 @@ void rdv40_spiffs_safe_print_fsinfo() {
rdv40_spiffs_fsinfo fsinfo;
rdv40_spiffs_getfsinfo(&fsinfo, RDV40_SPIFFS_SAFETY_SAFE);
DbpString(_BLUE_("Flash Memory FileSystem Info (SPIFFS)"));
// Dbprintf("-------------------------------------");
Dbprintf(" Logical Block Size........." _YELLOW_("%d")"bytes", fsinfo.blockSize);
Dbprintf(" Logical Page Size.........." _YELLOW_("%d")"bytes", fsinfo.pageSize);
Dbprintf("");
Dbprintf(" Max Open Files............." _YELLOW_("%d")"file descriptors", fsinfo.maxOpenFiles);
Dbprintf(" Max Path Length............" _YELLOW_("%d")"chars", fsinfo.maxPathLength);
// DbpString(_BLUE_("Details"));
DbpString("");
Dbprintf(" Filesystem\tSize\tUsed\tAvailable\tUse%\tMounted on");
Dbprintf(" spiffs \t%d B\t%d B\t%d B\t\t"_YELLOW_("%d%")"\t/"
, fsinfo.totalBytes
, fsinfo.usedBytes
, fsinfo.freeBytes
, fsinfo.usedPercent
);
Dbprintf("-------------------------------------");
Dbprintf("* Filesystem Logical Block Size.........%d bytes", fsinfo.blockSize);
Dbprintf("* Filesystem Logical Page Size..........%d bytes", fsinfo.pageSize);
Dbprintf("--");
Dbprintf("* Filesystem Max Open Files.............%d file descriptors", fsinfo.maxOpenFiles);
Dbprintf("* Filesystem Max Path Length............%d chars", fsinfo.maxPathLength);
Dbprintf("--");
Dbprintf("Filesystem\tSize\tUsed\tAvailable\tUse%\tMounted on");
Dbprintf("spiffs\t%dB\t%dB\t%dB\t\t%d%\t/", fsinfo.totalBytes, fsinfo.usedBytes, fsinfo.freeBytes,
fsinfo.usedPercent);
}
// this function is safe and WILL rollback since it is only a PRINTING function,

View file

@ -7,8 +7,9 @@
#ifndef SPIFFS_H_
#define SPIFFS_H_
#include "common.h"
#if defined(__cplusplus)
extern "C" {
#endif
#include "spiffs_config.h"
@ -32,7 +33,7 @@ typedef struct rdv40_spiffs_fsinfo {
int rdv40_spiffs_read_as_filetype(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level);
int rdv40_spiffs_check();
int rdv40_spiffs_lazy_unmount();
int rdv40_spiffs_lazy_mount();
int rdv40_spiffs_lazy_mount_rollback(int changed);
@ -853,5 +854,8 @@ u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages);
#if SPIFFS_CACHE
#endif
#if defined(__cplusplus)
}
#endif
#endif /* SPIFFS_H_ */

View file

@ -39,17 +39,17 @@ static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) {
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 &&
(cp->flags & SPIFFS_CACHE_FLAG_DIRTY)) {
u8_t *mem = spiffs_get_cache_page(fs, cache, ix);
SPIFFS_CACHE_DBG("CACHE_FREE: write cache page "_SPIPRIi" pix "_SPIPRIpg"\n", ix, cp->pix);
SPIFFS_CACHE_DBG("CACHE_FREE: write cache page "_SPIPRIi" pix "_SPIPRIpg"\n", ix, cp->ucache.spix.pix);
res = SPIFFS_HAL_WRITE(fs, SPIFFS_PAGE_TO_PADDR(fs, cp->ucache.spix.pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), mem);
}
#if SPIFFS_CACHE_WR
if (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) {
SPIFFS_CACHE_DBG("CACHE_FREE: free cache page "_SPIPRIi" objid "_SPIPRIid"\n", ix, cp->obj_id);
SPIFFS_CACHE_DBG("CACHE_FREE: free cache page "_SPIPRIi" objid "_SPIPRIid"\n", ix, cp->ucache.swrc.obj_id);
} else
#endif
{
SPIFFS_CACHE_DBG("CACHE_FREE: free cache page "_SPIPRIi" pix "_SPIPRIpg"\n", ix, cp->pix);
SPIFFS_CACHE_DBG("CACHE_FREE: free cache page "_SPIPRIi" pix "_SPIPRIpg"\n", ix, cp->ucache.spix.pix);
}
cache->cpage_use_map &= ~(1 << ix);
cp->flags = 0;
@ -156,7 +156,7 @@ s32_t spiffs_phys_rd(
if (cp) {
cp->flags = SPIFFS_CACHE_FLAG_WRTHRU;
cp->ucache.spix.pix = SPIFFS_PADDR_TO_PAGE(fs, addr);
SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page "_SPIPRIi" for pix "_SPIPRIpg "\n", cp->ix, cp->pix);
SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page "_SPIPRIi" for pix "_SPIPRIpg "\n", cp->ix, cp->ucache.spix.pix);
s32_t res2 = SPIFFS_HAL_READ(fs,
addr - SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr),

View file

@ -8,7 +8,22 @@
#ifndef SPIFFS_CONFIG_H_
#define SPIFFS_CONFIG_H_
#include "common.h"
// ----------- 8< ------------
// Following includes are for the linux test build of spiffs
// These may/should/must be removed/altered/replaced in your target
//#include <stdio.h>
//#include <stdlib.h>
//
#include "printf.h"
#include "string.h"
#include "flashmem.h"
void Dbprintf(const char *fmt, ...);
//#include <stddef.h>
//#include <unistd.h>
// ----------- >8 ------------
typedef int s32_t;
typedef uint32_t u32_t;
@ -26,7 +41,7 @@ typedef uint8_t u8_t;
#endif
// Set spiffs debug output call for garbage collecting.
#ifndef SPIFFS_GC_DBG
#define SPIFFS_GC_DBG(_f, ...)
#define SPIFFS_GC_DBG(_f, ...) //Dbprintf(_f, ## __VA_ARGS__)
#define SPIFFS_GC_DBGF(str) SPIFFS_GC_DBG(str,NULL)
#endif
// Set spiffs debug output call for caching.
@ -36,7 +51,7 @@ typedef uint8_t u8_t;
#endif
// Set spiffs debug output call for system consistency checks.
#ifndef SPIFFS_CHECK_DBG
#define SPIFFS_CHECK_DBG(_f, ...) //SPIFFS_CHECK_DBG(_f, ## __VA_ARGS__)
#define SPIFFS_CHECK_DBG(_f, ...) //Dbprintf(_f, ## __VA_ARGS__)
#define SPIFFS_CHECK_DBGF(str) SPIFFS_CHECK_DBG(str,NULL)
#endif
// Set spiffs debug output call for all api invocations.

View file

@ -39,6 +39,13 @@ static int CmdFlashMemSpiFFSTest(const char *Cmd) {
return PM3_SUCCESS;
}
static int CmdFlashMemSpiFFSCheck(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
clearCommandBuffer();
SendCommandNG(CMD_SPIFFS_CHECK, NULL, 0);
return PM3_SUCCESS;
}
static int CmdFlashMemSpiFFSTree(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
clearCommandBuffer();
@ -439,6 +446,7 @@ static command_t CommandTable[] = {
"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash,
"Copy a file to another (destructively) in SPIFFS FileSystem in FlashMEM (spiffs)"
},
{"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented Filesystem"},
{"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS FileSystem in FlashMEM (spiffs)"},
{"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print filesystem info and usage statistics (spiffs)"},
{"load", CmdFlashMemSpiFFSLoad, IfPm3Flash, "Upload file into SPIFFS Filesystem (spiffs)"},

View file

@ -299,6 +299,7 @@ typedef struct {
#define CMD_SPIFFS_PRINT_FSINFO 0x2133
#define CMD_SPIFFS_DOWNLOAD 0x2134
#define CMD_SPIFFS_DOWNLOADED 0x2135
#define CMD_SPIFFS_CHECK 0x3000
// more ?