/* * check if FS crashed during compaction and if yes, complete the compaction operation */ static FS_STATUS CompleteCompaction(uint8_t firstLogIndex,bool secondLogExists,uint8_t secondLogIndex,bool corruptedEUExists,uint8_t corruptedEUIndex) { LogEntry firstEntry,secondEntry; if (READ_LOG_ENTRY(firstLogIndex,firstEntry) != OPERATION_SUCCESS) { return FAILURE_ACCESSING_FLASH; } if (secondLogExists) { if (READ_LOG_ENTRY(secondLogIndex,secondEntry) != OPERATION_SUCCESS) { return FAILURE_ACCESSING_FLASH; } //if both entries are uninitilize, no log exist in contradicaion to the fact that //if two logs exist we are in the middle of Block compaction and one LogEntry must exists if (firstEntry.data == FLASH_UNINIT_4_BYTES && secondEntry.data == FLASH_UNINIT_4_BYTES) { return FAILURE; } //if the first entry is not uninitilize and the second is, this means that firstLogIndex is the real log //and we are trying to erase secondLogIndex if (firstEntry.data != FLASH_UNINIT_4_BYTES) { gLogIndex = firstLogIndex; firstEntry.bits.euIndex = secondLogIndex; firstEntry.bits.valid = 0; } //vice versa else { gLogIndex = secondLogIndex; secondEntry.bits.euIndex = firstLogIndex; secondEntry.bits.valid = 1; } //firstEntry will hold the valid data firstEntry.data &= secondEntry.data; } //no valid entry - FS didn't crash during block compaction, do nothing if (firstEntry.data == FLASH_UNINIT_4_BYTES) { return FS_SUCCESS; } //in case of invalid LogEntry CorrectLogEntry(&firstEntry); //verify that if coruppted EraseUnit exist, this is indeed the EraseUnit we tried to erase if (corruptedEUExists && firstEntry.bits.euIndex != corruptedEUIndex) { return FAILURE; } return CompactBlock(firstEntry.bits.euIndex,firstEntry); }
BOOL HAL_CONFIG_BLOCK::UpdateBlockWithName( const char* Name, void* Data, size_t Length, BOOL isChipRO ) { #if defined(HAL_REDUCESIZE) return FALSE; #else if(Name == NULL) return FALSE; BOOL fRet = FALSE; BYTE* pXipConfigBuf = NULL; const HAL_CONFIG_BLOCK *pLastConfig = NULL; HAL_CONFIG_BLOCK_STORAGE_DATA blData; if(!GetConfigSectorAddress(blData)) return FALSE; if(g_ConfigurationSector.ConfigurationLength == 0xFFFFFFFF) { return FALSE; } const ConfigurationSector* pStaticCfg = NULL; const HAL_CONFIG_BLOCK *pConfig = NULL; GLOBAL_LOCK(irq); if(blData.isXIP) { pConfig = (const HAL_CONFIG_BLOCK*)(blData.ConfigAddress+ g_ConfigurationSector.ConfigurationLength); pStaticCfg = &g_ConfigurationSector; } else { pXipConfigBuf = (BYTE*)private_malloc(blData.BlockLength); if(pXipConfigBuf != NULL) { blData.Device->Read( blData.ConfigAddress, blData.BlockLength, pXipConfigBuf ); pConfig = (const HAL_CONFIG_BLOCK*)&pXipConfigBuf[g_ConfigurationSector.ConfigurationLength]; pStaticCfg = (const ConfigurationSector*)pXipConfigBuf; } else { return FALSE; } } if(pConfig != NULL) { pConfig = pConfig->Find(Name, FALSE, TRUE); pLastConfig = pConfig->Find("", FALSE, TRUE); } if(pConfig != NULL) { const void* physAddr; const void* physEnd; // try compacting the config block if the first attempt to update fails for(int i=0; i<2; i++) { // if we could not get the last config then we must be full if(pLastConfig != NULL) { if(blData.isXIP) { physAddr = (const void*)pConfig; physEnd = (const void*)pLastConfig; } else { physAddr = (const void*)(blData.ConfigAddress + ((size_t)pConfig - (size_t)pXipConfigBuf)); physEnd = (const void*)(blData.ConfigAddress + ((size_t)pLastConfig - (size_t)pXipConfigBuf)); private_free(pXipConfigBuf); pXipConfigBuf = NULL; } if(Data != NULL) { HAL_CONFIG_BLOCK header; header.Prepare( Name, Data, Length ); fRet = UpdateBlock( blData, physAddr, (const HAL_CONFIG_BLOCK*)&header, Data, Length, physEnd, isChipRO ); } else if(physAddr != physEnd) { fRet = UpdateBlock( blData, physAddr, NULL, NULL, 0, physEnd, isChipRO ); } else { fRet = TRUE; } if(fRet) break; } CompactBlock( blData, pStaticCfg, pLastConfig ); if(!blData.isXIP && pXipConfigBuf != NULL) { blData.Device->Read( blData.ConfigAddress, blData.BlockLength, pXipConfigBuf ); pConfig = (const HAL_CONFIG_BLOCK*)&pXipConfigBuf[g_ConfigurationSector.ConfigurationLength]; } else { pConfig = (const HAL_CONFIG_BLOCK*)(blData.ConfigAddress + g_ConfigurationSector.ConfigurationLength); } pConfig = pConfig->Find(Name, FALSE, TRUE); pLastConfig = pConfig->Find("", FALSE, TRUE); } } if(pXipConfigBuf != NULL) { private_free(pXipConfigBuf); } return fRet; #endif }
FS_STATUS fs_write(const char* filename, unsigned length, const char* data) { LogEntry entry; FS_STATUS status = MAXIMUM_FLASH_SIZE_EXCEEDED; uint8_t euIndex,oldLogIndex; if (filename == NULL || data == NULL) { return COMMAND_PARAMETERS_ERROR; } if (length > MAX_FILE_SIZE) { return MAXIMUM_FILE_SIZE_EXCEEDED; } if (gFilesCount > MAX_FILES_CAPACITY) { return MAXIMUM_FILES_CAPACITY_EXCEEDED; } if (!gFsIsReady) { return FS_NOT_READY; } if (tx_mutex_get(&gFsGlobalLock,TX_NO_WAIT) != TX_SUCCESS) { return FS_IS_BUSY; } do { //try to find free space if (findFreeEraseUnit(length,&euIndex)) { status = eraseFileFromFS(filename); if (status != FS_SUCCESS && status != FILE_NOT_FOUND) { status = FAILURE_ACCESSING_FLASH; break; } status = writeFile(filename,length,data,euIndex); } //try to find EraseUnit that after compaction will have enough space else if (findEraseUnitToCompact(&euIndex,length+sizeof(SectorDescriptor))) { entry.data = FLASH_UNINIT_4_BYTES; oldLogIndex = gLogIndex; if (CompactBlock(euIndex,entry) == FS_SUCCESS) { //erase previouse file with same name if such exist status = eraseFileFromFS(filename); if (status != FS_SUCCESS && status != FILE_NOT_FOUND) { status = FAILURE_ACCESSING_FLASH; break; } //write the actual file status = writeFile(filename,length,data,oldLogIndex); } } }while(false); tx_mutex_put(&gFsGlobalLock); return status; }