rusefi/firmware/hw_layer/mmc_card_util.cpp

165 lines
4.5 KiB
C++

#include "pch.h"
#if EFI_PROD_CODE && EFI_FILE_LOGGING
#include "ff.h"
#include "mmc_card_util.h"
#include "backup_ram.h"
#include "mmc_card.h"
#define LOG_INDEX_FILENAME "index.txt"
#define HARD_FAULT_PREFIX "hard_"
// 10 because we want at least 4 character name (is that about TS protocol which we do not use any more?)
#define MIN_FILE_INDEX 10
int logFileIndex = MIN_FILE_INDEX;
static FIL FDLogFile NO_CACHE;
void incLogFileName() {
memset(&FDLogFile, 0, sizeof(FIL)); // clear the memory
FRESULT ret = f_open(&FDLogFile, LOG_INDEX_FILENAME, FA_READ); // This file has the index for next log file name
char data[_MAX_FILLER];
memset(data, 0, sizeof(data));
if (ret == FR_OK) {
UINT readed = 0;
// leave one byte for terminating 0
ret = f_read(&FDLogFile, (void*)data, sizeof(data) - 1, &readed);
if (ret != FR_OK) {
printError("log index file read", ret);
logFileIndex = MIN_FILE_INDEX;
} else {
efiPrintf("Got content [%s] size %d", data, readed);
logFileIndex = maxI(MIN_FILE_INDEX, atoi(data));
if (absI(logFileIndex) == ATOI_ERROR_CODE) {
logFileIndex = MIN_FILE_INDEX;
} else {
logFileIndex++; // next file would use next file name
}
}
f_close(&FDLogFile);
} else if (ret == FR_NO_FILE) {
// no index file - this is not an error, just an empty SD
logFileIndex = MIN_FILE_INDEX;
} else {
printError("log index file open", ret);
efiPrintf("%s: not found or error: %d", LOG_INDEX_FILENAME, ret);
logFileIndex = MIN_FILE_INDEX;
}
// truncate or create new
ret = f_open(&FDLogFile, LOG_INDEX_FILENAME, FA_CREATE_ALWAYS | FA_WRITE);
if (ret == FR_OK) {
UINT writen = 0;
size_t len = itoa10(data, logFileIndex) - data;
ret = f_write(&FDLogFile, (void*)data, len, &writen);
if ((ret != FR_OK) || (len != writen)) {
printError("log index write", ret);
}
f_close(&FDLogFile);
} else {
printError("log index file write", ret);
}
efiPrintf("New log file index %d", logFileIndex);
}
bool needsToWriteReportFile() {
#if EFI_BACKUP_SRAM
extern ErrorCookie errorCookieOnStart;
return errorCookieOnStart == ErrorCookie::HardFault;
#else
return false;
#endif // EFI_BACKUP_SRAM
}
PUBLIC_API_WEAK void onBoardWriteErrorFile(FIL *file) {
UNUSED(file);
}
#if EFI_BACKUP_SRAM
// todo: unit test? or better file stdlib method to do same?
static int mystrncasecmp(const char *s1, const char *s2, size_t n) {
if (n != 0) {
const char *us1 = (const char *)s1;
const char *us2 = (const char *)s2;
do {
if (mytolower(*us1) != mytolower(*us2))
return (mytolower(*us1) - mytolower(*us2));
if (*us1++ == '\0')
break;
us2++;
} while (--n != 0);
}
return (0);
}
static bool findFile(const char *path, const char *prefix) {
if (!isSdCardAlive()) {
efiPrintf("Error: No File system is mounted");
return false;
}
DIR dir;
FRESULT res = f_opendir(&dir, path);
if (res != FR_OK) {
efiPrintf("Error opening directory %s", path);
return false;
}
// todo: do we need paranoia loop limit?
while (true) {
FILINFO fno;
res = f_readdir(&dir, &fno);
if (res != FR_OK || fno.fname[0] == 0) {
// done!
break;
}
if (fno.fname[0] == '.') {
continue;
}
if ((fno.fattrib & AM_DIR) || mystrncasecmp(prefix, fno.fname, strlen(prefix) - 1)) {
// skipping folders and files with wrong names
continue;
}
efiPrintf("file found %lu:%s", (uint32_t)fno.fsize, fno.fname);
return true;
// efiPrintf("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %-12s", (fno.fattrib & AM_DIR) ? 'D' : '-',
// (fno.fattrib & AM_RDO) ? 'R' : '-', (fno.fattrib & AM_HID) ? 'H' : '-',
// (fno.fattrib & AM_SYS) ? 'S' : '-', (fno.fattrib & AM_ARC) ? 'A' : '-', (fno.fdate >> 9) + 1980,
// (fno.fdate >> 5) & 15, fno.fdate & 31, (fno.ftime >> 11), (fno.ftime >> 5) & 63, fno.fsize,
// fno.fname);
}
return false;
}
#endif // EFI_BACKUP_SRAM
void writeErrorReportFile() {
#if EFI_BACKUP_SRAM
extern ErrorCookie errorCookieOnStart;
static char fileName[_MAX_FILLER + 20];
auto sramState = getBackupSram();
if (errorCookieOnStart == ErrorCookie::HardFault) {
memset(&FDLogFile, 0, sizeof(FIL)); // clear the memory
sprintf(fileName, "%s%d.txt", HARD_FAULT_PREFIX, logFileIndex);
FRESULT ret = f_open(&FDLogFile, fileName, FA_CREATE_ALWAYS | FA_WRITE);
if (ret == FR_OK) {
onBoardWriteErrorFile(&FDLogFile);
f_printf(&FDLogFile, "type=%d\n", sramState->Err.FaultType);
// todo: figure out what else would be useful
f_close(&FDLogFile);
}
}
findFile(".", HARD_FAULT_PREFIX);
#endif // EFI_BACKUP_SRAM
}
#endif // EFI_PROD_CODE && EFI_FILE_LOGGING