예제 #1
0
/*
 * 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
}
예제 #3
0
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;
}