// // Created by cfif on 07.10.22. // #include "InternalFlashPage.h" #include "StorageOnFlashFlagchip.h" #define LOGGER env->logger #define LOG_SIGN "Storage" static uint32_t xStorageOnFlashArtery_Crc(uint8_t *data, size_t len) { uint32_t crc = 0; uint8_t *end = data + len; while (data < end) { crc += *data; ++data; } return crc; } static uint32_t xStorageOnFlashArtery_CrcFlash(uint8_t *addressOnFlash, size_t len) { uint32_t crc = 0; size_t left = len; uint8_t *end = addressOnFlash + len; uint32_t word; while (addressOnFlash < end) { word = iInternalFlashPage_ReadWord((uint32_t) addressOnFlash); for (uint8_t sub_byte = 0; (sub_byte < 4) && (left); ++sub_byte) { crc += ((uint8_t *) &word)[sub_byte]; --left; } addressOnFlash += 4; } return crc; } static eStorageStatus xStorageOnFlashFlagchip_DumpOn( tStorageOnFlashFlagchip *env, uint32_t dataCrc, uint32_t pageAddress, void *data, size_t size ) { // if (!bInternalFlashPage_Clear(pageAddress)) { // return STORAGE_ERR_DEVICE; // } // // size_t dataSizeOnFlash = sInternalFlashPage_Write(pageAddress, 0x0, env->data, env->size); size_t dataSizeOnFlash = bInternalFlashPage_DumpFromRam(pageAddress, data, size); if (dataSizeOnFlash < size) { return STORAGE_ERR_DEVICE; } uint64_t dataCrc64 = dataCrc; if (sInternalFlashPage_Write(pageAddress, dataSizeOnFlash, (uint8_t *) &dataCrc64, 8) != 8) { return STORAGE_ERR_DEVICE; } uint32_t flashCalcCrc = xStorageOnFlashArtery_CrcFlash((uint8_t *) pageAddress, size ); uint32_t flashReedCrc = iInternalFlashPage_ReadWord(pageAddress + dataSizeOnFlash); if ((flashCalcCrc == flashReedCrc) && (flashCalcCrc == dataCrc)) { return STORAGE_OK; } else { return STORAGE_ERR_DATA; } } static uint8_t xStorageOnFlashFlagchip_Dump(tStorageOnFlashFlagchip *env, void *data, size_t size) { size = size - 8; uint32_t crc = xStorageOnFlashArtery_Crc(data, size); if (xStorageOnFlashFlagchip_DumpOn(env, crc, env->recoveryFlashPageAddress, data, size) != STORAGE_OK) { return STORAGE_ERR_DEVICE; } if (xStorageOnFlashFlagchip_DumpOn(env, crc, env->mainFlashPageAddress, data, size) != STORAGE_OK) { return STORAGE_ERR_DEVICE; } return STORAGE_OK; } eStorageStatus xStorageOnFlashFlagchip_Load(tStorageOnFlashFlagchip *env, void *data, size_t size) { size_t offset_crc = size - 8; uint32_t recoveryCrcCalc = xStorageOnFlashArtery_CrcFlash((uint8_t *) env->recoveryFlashPageAddress, offset_crc); uint32_t recoveryCrcReed = iInternalFlashPage_ReadWord(env->recoveryFlashPageAddress + offset_crc); LoggerFormatInfo(LOGGER, LOG_SIGN, "Crc recovery page (calc): 0x%08X", recoveryCrcCalc) LoggerFormatInfo(LOGGER, LOG_SIGN, "Crc recovery page (flash): 0x%08X", recoveryCrcReed) uint32_t mainCrcCalc = xStorageOnFlashArtery_CrcFlash((uint8_t *) env->mainFlashPageAddress, offset_crc); uint32_t mainCrcReed = iInternalFlashPage_ReadWord(env->mainFlashPageAddress + offset_crc); LoggerFormatInfo(LOGGER, LOG_SIGN, "Crc main page (calc): 0x%08X", mainCrcCalc) LoggerFormatInfo(LOGGER, LOG_SIGN, "Crc main page (flash): 0x%08X", mainCrcReed) bool recoveryCrcOk = (recoveryCrcCalc == recoveryCrcReed); bool mainCrcOk = (mainCrcReed == mainCrcCalc); if (recoveryCrcOk && mainCrcOk) { if (recoveryCrcReed == mainCrcReed) { sInternalFlashPage_Read(env->mainFlashPageAddress, 0x0, data, offset_crc); return STORAGE_OK; } else { LoggerInfoStatic(LOGGER, LOG_SIGN, "Data recovery main page (main page <- recovery) ") sInternalFlashPage_Read(env->recoveryFlashPageAddress, 0x0, data, offset_crc); return xStorageOnFlashFlagchip_DumpOn(env, recoveryCrcCalc, env->mainFlashPageAddress, data, offset_crc); } } else if (recoveryCrcOk || mainCrcOk) { if (recoveryCrcOk) { LoggerInfoStatic(LOGGER, LOG_SIGN, "Data recovery main page (main page <- recovery)") sInternalFlashPage_Read(env->recoveryFlashPageAddress, 0x0, data, offset_crc); return xStorageOnFlashFlagchip_DumpOn(env, recoveryCrcCalc, env->mainFlashPageAddress, data, offset_crc); } else { LoggerInfoStatic(LOGGER, LOG_SIGN, "Data recovery recovery page (main page -> recovery)") sInternalFlashPage_Read(env->mainFlashPageAddress, 0x0, data, offset_crc); return xStorageOnFlashFlagchip_DumpOn(env, mainCrcCalc, env->recoveryFlashPageAddress, data, offset_crc); } } else { return STORAGE_ERR_DATA; } } void vStorageOnFlashFlagchip_Init( tStorageOnFlashFlagchip *env, uint32_t mainPage, uint32_t recoveryPage ) { env->mainFlashPageAddress = mainPage; env->recoveryFlashPageAddress = recoveryPage; } tStorageInterface xStorageOnFlashFlagchip_GetInterface(tStorageOnFlashFlagchip *env) { return (tStorageInterface) { .env = env, .load = (StorageIOTransaction) xStorageOnFlashFlagchip_Load, .dump = (StorageIOTransaction) xStorageOnFlashFlagchip_Dump }; }