/******************************************************************************* * Copyright 2011-2012, Cypress Semiconductor Corporation. All rights reserved. * You may use this file only in accordance with the license, terms, conditions, * disclaimers, and limitations in the end user license agreement accompanying * the software package with which this file was provided. ********************************************************************************/ #include #include "cybtldr_parse.h" #include "cybtldr_command.h" #include "cybtldr_api.h" #include "cybtldr_api2.h" unsigned char g_abort; int CyBtldr_RunAction(CyBtldr_Action action, const char* file, CyBtldr_CommunicationsData* comm, CyBtldr_ProgressUpdate* update) { const unsigned long BL_VER_SUPPORT_VERIFY = 0x010214; /* Support for full flash verify added in v2.20 of cy_boot */ const unsigned char INVALID_APP = 0xFF; unsigned long blVer = 0; unsigned long siliconId = 0; unsigned short rowNum = 0; unsigned short bufSize = 0; unsigned char siliconRev = 0; unsigned char chksumtype = SUM_CHECKSUM; unsigned char checksum = 0; unsigned char checksum2 = 0; unsigned char arrayId = 0; unsigned char appId; unsigned char isValid; unsigned char isActive; unsigned char buffer[MAX_BUFFER_SIZE]; char line[MAX_BUFFER_SIZE]; unsigned int lineLen; char * app; int err; g_abort = 0; err = CyBtldr_OpenDataFile(file); if (CYRET_SUCCESS == err) { err = CyBtldr_ReadLine(&lineLen, line); if (CYRET_SUCCESS == err) err = CyBtldr_ParseHeader(lineLen, line, &siliconId, &siliconRev, &chksumtype); if (CYRET_SUCCESS == err) { CyBtldr_SetCheckSumType(chksumtype); err = CyBtldr_StartBootloadOperation(comm, siliconId, siliconRev, &blVer); } app = strrchr(file, '_'); appId = (app != NULL && '.' == app[2]) ? (CyBtldr_FromHex(app[1]) - 1) : INVALID_APP; if (CYRET_SUCCESS == err && INVALID_APP != appId) { /* NB: This block of code will still run for single app if file */ /* name format follows same as multi app (e.g. myfile_1.cyacd) */ /* This will return error if bootloader is for single app */ err = CyBtldr_GetApplicationStatus(appId, &isValid, &isActive); /* Active app can be verified, but not programmed or erased */ if (CYRET_SUCCESS == err && VERIFY != action && isActive) { /* This is multi app */ err = CYRET_ERR_ACTIVE; } else if (CYBTLDR_STAT_ERR_CMD == (err ^ (int)CYRET_ERR_BTLDR_MASK)) { /* Single app - restore previous CYRET_SUCCESS */ err = CYRET_SUCCESS; } } if (CYRET_SUCCESS == err) { while (CYRET_SUCCESS == err) { if (g_abort) { err = CYRET_ABORT; break; } err = CyBtldr_ReadLine(&lineLen, line); if (CYRET_SUCCESS == err) err = CyBtldr_ParseRowData(lineLen, line, &arrayId, &rowNum, buffer, &bufSize, &checksum); if (CYRET_SUCCESS == err) { switch (action) { case ERASE: err = CyBtldr_EraseRow(arrayId, rowNum); break; case PROGRAM: err = CyBtldr_ProgramRow(arrayId, rowNum, buffer, bufSize); if (CYRET_SUCCESS != err) break; /* Continue on to verify the row that was programmed */ case VERIFY: checksum2 = (unsigned char)(checksum + arrayId + rowNum + (rowNum >> 8) + bufSize + (bufSize >> 8)); err = CyBtldr_VerifyRow(arrayId, rowNum, checksum2); break; } if (CYRET_SUCCESS == err && NULL != update) update(arrayId, rowNum); } else if (CYRET_ERR_EOF == err) { err = CYRET_SUCCESS; break; } } if (CYRET_SUCCESS == err) { /* Set the active application to what was just programmed */ if (PROGRAM == action && INVALID_APP != appId) { err = CyBtldr_GetApplicationStatus(appId, &isValid, &isActive); if (CYRET_SUCCESS == err) { /* If valid set the active application to what was just programmed */ /* This is multi app */ err = (0 == isValid) ? CyBtldr_SetApplicationStatus(appId) : CYRET_ERR_CHECKSUM; } else if (CYBTLDR_STAT_ERR_CMD == (err ^ (int)CYRET_ERR_BTLDR_MASK)) { /* Single app - restore previous CYRET_SUCCESS */ err = CYRET_SUCCESS; } } /* Verify that the entire application is valid */ else if ((PROGRAM == action || VERIFY == action) && (blVer >= BL_VER_SUPPORT_VERIFY)) err = CyBtldr_VerifyApplication(); } CyBtldr_EndBootloadOperation(); } else if (CYRET_ERR_COMM_MASK != (CYRET_ERR_COMM_MASK & err)) CyBtldr_EndBootloadOperation(); CyBtldr_CloseDataFile(); } return err; } int CyBtldr_Program(const char* file, CyBtldr_CommunicationsData* comm, CyBtldr_ProgressUpdate* update) { return CyBtldr_RunAction(PROGRAM, file, comm, update); } int CyBtldr_Erase(const char* file, CyBtldr_CommunicationsData* comm, CyBtldr_ProgressUpdate* update) { return CyBtldr_RunAction(ERASE, file, comm, update); } int CyBtldr_Verify(const char* file, CyBtldr_CommunicationsData* comm, CyBtldr_ProgressUpdate* update) { return CyBtldr_RunAction(VERIFY, file, comm, update); } int CyBtldr_Abort(void) { g_abort = 1; return CYRET_SUCCESS; }