#include #include #include #include #include #include #include #include #include #include "bl_commands.h" #include "gfabootlmast.h" #include "dbghlp.h" //////////////////////////////////////////////////////////////////////////////////// #define _dword_offset(m) (offsetof(GFA_APP_IMG_HEADER, m) / sizeof(uint32_t) - 2) #ifdef _DEBUG #define _EXEC_CALLBACK(pfn, ...) if(pfn) (*pfn)(__FILE__, __LINE__, __VA_ARGS__) #else // _DEBUG #define _EXEC_CALLBACK(pfn, ...) if(pfn) (*pfn)(__VA_ARGS__) #endif // _DEBUG #define _BOOTLOADER_EXEC_WAIT_TIME 250 #define _GFA_MAX_DUMP_DWORDS 16 #define _MAX_SEND_DATA_BLOCK_SIZE 76 #define _DEF_SEND_DATA_BLOCK_SIZE 64 //////////////////////////////////////////////////////////////////////////////////// typedef struct _GFA_BLM { HGFAMINEMST hMst; PFN_BU_CMD_DOWNLOAD_STATUS pfnBuCmdDownloadStatus; PFN_BU_CMD_SEND_DATA_STATUS pfnBuCmdSendDataStatus; int nVerbosity; }GFA_BLM, *LPGFA_BLM; typedef const GFA_BLM *LPCGFA_BLM; //////////////////////////////////////////////////////////////////////////////////// #define GFA_APP_BOOTLOADER_START_ADDRESS ((uint32_t)0x00000000) #define GFA_APP_APPLICATION_START_ADDRESS ((uint32_t)0x00002000) #define GFA_APP_IMG_HEADER_PREFIX_0 ((uint32_t)0xFF01FF02) #define GFA_APP_IMG_HEADER_PREFIX_1 ((uint32_t)0xFF03FF04) //////////////////////////////////////////////////////////////////////////////////// typedef struct _GFA_APP_IMG_HEADER { const uint32_t nPrefix0; const uint32_t nPrefix1; const uint32_t nImgLength; const uint32_t nImgCRC32; const uint32_t nReserved[4]; union { struct { const char * const pszImgMaterialNum; const char * const pszImgNameBuild; }app; struct { const char szImgMaterialNum[GFA_APP_MAX_IMG_MATERIAL_NUM_LENGTH]; const char szImgNameBuild[GFA_APP_MAX_IMG_NAME_BUILD_LENGTH]; }bl; }; }GFA_APP_IMG_HEADER, *LPGFA_APP_IMG_HEADER; typedef const GFA_APP_IMG_HEADER *LPCGFA_APP_IMG_HEADER; //////////////////////////////////////////////////////////////////////////////////// HGFABLM GfaBlmOpen(LPCGFA_BLM_CFG_PARAMS pblmcfg) { if(pblmcfg) { HGFAMINEMST hMst = GfaMininetMasterOpen(&pblmcfg->mmcp); if(hMst) { LPGFA_BLM pBlm = malloc(sizeof(GFA_BLM)); memset(pBlm, 0, sizeof(GFA_BLM)); pBlm->hMst = hMst; pBlm->pfnBuCmdDownloadStatus = pblmcfg->pfnBuCmdDownloadStatus; pBlm->pfnBuCmdSendDataStatus = pblmcfg->pfnBuCmdSendDataStatus; return (HGFABLM)pBlm; } return NULL; } errno = EINVAL; return NULL; } //////////////////////////////////////////////////////////////////////////////////// void GfaBlmClose(HGFABLM hBlm) { if(hBlm) { LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; GfaMininetMasterClose(pBlm->hMst); free(pBlm); } } ///////////////////////////////////////////////////////////////////////////// int GfaBlmResetSlaveIndex(HGFABLM hBlm, uint8_t nNodeAddr) { if(hBlm) { LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; return GfaMininetMasterResetSlaveIndex(pBlm->hMst, nNodeAddr); } errno = EINVAL; return -1; } //////////////////////////////////////////////////////////////////////////////////// ssize_t GfaBlmBUCmdPollData(HGFABLM hBlm, uint8_t nNodeAddr, void *pData, size_t nCbData, uint32_t nTimeoutMS) { if(hBlm && pData && nCbData && !NODE_IS_MULTICAST(nNodeAddr)) { size_t s, nReceived = 0; struct timeval tvRX; ssize_t nLen, nRet = -1; uint8_t cmd[32]; uint8_t txb[32]; uint8_t rxb[512]; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; uint8_t *pszData = (uint8_t*)pData; tvRX.tv_sec = nTimeoutMS / 1000; tvRX.tv_usec = (nTimeoutMS % 1000) * 1000; GfaMininetMasterSaveTimeouts(pBlm->hMst); GfaMininetMasterSetTimeouts(pBlm->hMst, &tvRX, NULL); while(nReceived < nCbData) { s = GfaBlmBuildCmdDataPacket("BU", 0, NULL, 0, cmd, sizeof(cmd), true); nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, cmd, s, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) <= 0) { nRet = -1; break; } if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) > 0) { uint8_t nIndex; nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { if((nRet = GfaMininetMasterGetDataFromSlaveFrame(rxb, nLen, pszData, nCbData - nReceived)) > 0) { pszData += nRet; nReceived += nRet; } } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { if(nTimeoutMS > 0) { if(nTimeoutMS >= 100) { usleep(100000); nTimeoutMS -= 100; // TRACE("\nACK ...\n"); } else { usleep(nTimeoutMS * 1000); nTimeoutMS = 0; // TRACE("\nACK ...\n"); } } else { errno = ETIMEDOUT; nReceived = 0; break; } } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { errno = -(int)nIndex; nReceived = 0; break; } else { errno = EPROTO; nReceived = 0; break; } } else { nReceived = 0; break; } } GfaMininetMasterRestoreTimeouts(pBlm->hMst); return nReceived; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmBUCmdReset(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nTimeoutMS) { if(hBlm) { LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; uint8_t nIndex; size_t s; ssize_t nRet, nLen; uint8_t cmd = COMMAND_RESET; uint8_t cmddata[16]; char txb[32], rxb[256], ack[2]; if((nRet = GfaBlmBootloaderSetBaudrate(hBlm, nNodeAddr, 19200)) != 0) return -1; s = GfaBlmBuildCmdDataPacket("BU", 0, &cmd, 1, cmddata, sizeof(cmddata), true); nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, cmddata, s, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen) return nRet; if(NODE_IS_MULTICAST(nNodeAddr)) return 0; if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0) return nLen; nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex); if( (nRet == MINET_SLAVE_RESPONSE_SUCCESS) || (nRet == MINET_SLAVE_RESPONSE_ACK)) { if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { if((nRet = GfaMininetMasterGetDataFromSlaveFrame(rxb, nLen, ack, 2)) != 2) return -1; } else { if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, ack, 2, 200)) != 2) return -1; } if( (ack[0] == 0) && (ack[1] == COMMAND_ACK)) { do { if(nTimeoutMS > _BOOTLOADER_EXEC_WAIT_TIME) { usleep(_BOOTLOADER_EXEC_WAIT_TIME * 1000); nTimeoutMS -= _BOOTLOADER_EXEC_WAIT_TIME; } else { usleep(nTimeoutMS * 1000); nTimeoutMS = 0; } if((nRet = GfaMininetMasterResetSlaveIndex(pBlm->hMst, nNodeAddr)) == 0) break; GfaMininetMasterPurgeDeviceRXBuffer(pBlm->hMst); } while(nTimeoutMS > 0); return nRet; } } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { errno = -(int)nIndex; return -1; } return -1; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmBUCmdPing(HGFABLM hBlm, uint8_t nNodeAddr) { if(hBlm && !NODE_IS_MULTICAST(nNodeAddr)) { uint8_t nIndex; ssize_t nRet, nLen; uint8_t nCmd = COMMAND_PING; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; char txb[32], rxb[32], cmd[8], ack[2]; size_t s = GfaBlmBuildCmdDataPacket("BU", 0, &nCmd, 1, cmd, sizeof(cmd), true); nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, cmd, s, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) < nLen) return nRet; if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0) return nLen; nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex); if( (nRet == MINET_SLAVE_RESPONSE_SUCCESS) || (nRet == MINET_SLAVE_RESPONSE_ACK)) { if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { if((nRet = GfaMininetMasterGetDataFromSlaveFrame(rxb, nLen, ack, 2)) != 2) return -1; } else { if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, ack, 2, 200)) != 2) return -1; } if(ack[0] == 0) { return (ack[1] == COMMAND_ACK); } else { errno = EPROTO; return -1; } } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { errno = -(int)nIndex; return -1; } return -1; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmBUCmdGetStatus(HGFABLM hBlm, uint8_t nNodeAddr, uint8_t *pbStatus) { if(hBlm && pbStatus && !NODE_IS_MULTICAST(nNodeAddr)) { uint8_t nIndex; ssize_t nRet, nLen; uint8_t nCmd = COMMAND_GET_STATUS; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; char txb[32], rxb[32], cmd[8], ack[3], stat[3]; size_t s = GfaBlmBuildCmdDataPacket("BU", 0, &nCmd, 1, cmd, sizeof(cmd), true); nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, cmd, s, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) < nLen) return nRet; if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0) return nLen; nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex); if( (nRet == MINET_SLAVE_RESPONSE_SUCCESS) || (nRet == MINET_SLAVE_RESPONSE_ACK)) { if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { if((nRet = GfaMininetMasterGetDataFromSlaveFrame(rxb, nLen, ack, 2)) != 2) return -1; } else { if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, ack, 2, 200)) != 2) return -1; } if(ack[0] == 0) { if(ack[1] == COMMAND_ACK) { if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, stat, 3, 200)) != 3) return -1; if((stat[0] == 3) && (stat[1] == stat[2])) { if(pbStatus) *pbStatus = stat[2]; nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, "BU\xCC", 3, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen) return nRet; if((nRet = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0) return nRet; nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nRet, true, &nIndex); return 0; } else { errno = EPROTO; return -1; } } else { errno = EPROTO; return -1; } } else { errno = EPROTO; return -1; } } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { errno = -(int)nIndex; return -1; } return -1; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmBUCmdDownload(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nFlashStartAddr, uint32_t nCbData, uint32_t nTimeoutMS) { if(hBlm && nCbData && !NODE_IS_MULTICAST(nNodeAddr)) { size_t s; ssize_t nRet, nLen; uint8_t nIndex, nStatus; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; uint32_t nAddr = bswap_32(nFlashStartAddr), nCount = bswap_32(nCbData); uint8_t txb[32], rxb[32], cmd[16], data[9], ack[2]; data[0] = COMMAND_DOWNLOAD; struct timeval tv; memcpy(&data[1], &nAddr, sizeof(nAddr)); memcpy(&data[5], &nCount, sizeof(nCount)); tv.tv_sec = nTimeoutMS / 1000; tv.tv_usec = (nTimeoutMS % 1000) * 1000; s = GfaBlmBuildCmdDataPacket("BU", 0, data, sizeof(data), cmd, sizeof(cmd), true); nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, cmd, s, txb, sizeof(txb)); GfaMininetMasterSaveTimeouts(pBlm->hMst); GfaMininetMasterSetTimeouts(pBlm->hMst, &tv, NULL); _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 1, 0); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen) { _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno); GfaMininetMasterRestoreTimeouts(pBlm->hMst); return -1; } if((nRet = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0) { _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno); GfaMininetMasterRestoreTimeouts(pBlm->hMst); return -1; } _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 2, 0); GfaMininetMasterRestoreTimeouts(pBlm->hMst); nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nRet, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { if((nRet = GfaMininetMasterGetDataFromSlaveFrame(rxb, nLen, ack, 2)) != 2) { _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno); return -1; } if((ack[0] == 0) && (ack[1] == COMMAND_ACK)) { if((nRet = GfaBlmBUCmdGetStatus(hBlm, nNodeAddr, &nStatus))) { _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno); return -1; } if(nStatus == COMMAND_RET_SUCCESS) { _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 3, 0); return 0; } } errno = EPROTO; return -1; } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, ack, 2, nTimeoutMS)) != 2) { _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno); return -1; } if((ack[0] == 0) && (ack[1] == COMMAND_ACK)) { if((nRet = GfaBlmBUCmdGetStatus(hBlm, nNodeAddr, &nStatus))) { _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno); return -1; } if(nStatus == COMMAND_RET_SUCCESS) { _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 3, 0); return 0; } } errno = EPROTO; _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno); return -1; } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { errno = -(int)nIndex; _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno); return -1; } else { errno = EPROTO; _EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno); return -1; } } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmBUCmdSendDataBlock(HGFABLM hBlm, uint8_t nNodeAddr, const void *pDataBlock, size_t nCbDataBlock) { if(hBlm && pDataBlock && nCbDataBlock && (nCbDataBlock <= 250) && !NODE_IS_MULTICAST(nNodeAddr)) { ssize_t nRet; struct timeval tv; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; tv.tv_sec = 0; tv.tv_usec = 500000; GfaMininetMasterSaveTimeouts(pBlm->hMst); GfaMininetMasterSetTimeouts(pBlm->hMst, &tv, NULL); do { size_t s; ssize_t nLen; uint8_t nIndex, nStatus; uint8_t txb[512], rxb[32], cmd[256], data[256], ack[2]; data[0] = COMMAND_SEND_DATA; memcpy(&data[1], pDataBlock, nCbDataBlock); s = GfaBlmBuildCmdDataPacket("BU", 0, data, nCbDataBlock + 1, cmd, sizeof(cmd), true); nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, cmd, s, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen) { nRet = -1; break; } if((nRet = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0) { nRet = -1; break; } nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nRet, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { if((nRet = GfaMininetMasterGetDataFromSlaveFrame(rxb, nLen, ack, 2)) != 2) { nRet = -1; break; } if((ack[0] == 0) && (ack[1] == COMMAND_ACK)) { if((nRet = GfaBlmBUCmdGetStatus(hBlm, nNodeAddr, &nStatus))) { nRet = -1; break; } if(nStatus != COMMAND_RET_SUCCESS) { errno = -nStatus; nRet = -1; break; } nRet = 0; break; } errno = EPROTO; nRet = -1; break; } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, ack, 2, 5000)) != 2) { nRet = -1; break; } if((ack[0] == 0) && (ack[1] == COMMAND_ACK)) { if((nRet = GfaBlmBUCmdGetStatus(hBlm, nNodeAddr, &nStatus))) { nRet = -1; break; } if(nStatus != COMMAND_RET_SUCCESS) { errno = -nStatus; nRet = -1; break; } nRet = 0; break; } errno = EPROTO; nRet = -1; break; } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { errno = -(int)nIndex; nRet = -1; break; } } while(false); GfaMininetMasterRestoreTimeouts(pBlm->hMst); return nRet; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmBUCmdSendData(HGFABLM hBlm, uint8_t nNodeAddr, const void *pData, size_t nCbData, size_t nCbBlock) { if(hBlm && pData && nCbData && !NODE_IS_MULTICAST(nNodeAddr)) { int nRet; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; const uint8_t *pbData = (const uint8_t*)pData; uint32_t nSent = 0; if(!nCbBlock || nCbBlock < 4 || nCbBlock > _MAX_SEND_DATA_BLOCK_SIZE) nCbBlock = _DEF_SEND_DATA_BLOCK_SIZE; else nCbBlock &= ~0x03; _EXEC_CALLBACK(pBlm->pfnBuCmdSendDataStatus, nNodeAddr, nCbBlock, nSent, 1, 0); while(nCbData >= nCbBlock) { if((nRet = GfaBlmBUCmdSendDataBlock(hBlm, nNodeAddr, pbData, nCbBlock)) != 0) { _EXEC_CALLBACK(pBlm->pfnBuCmdSendDataStatus, nNodeAddr, nCbBlock, nSent, 0, errno); return -1; } nCbData -= nCbBlock; pbData += nCbBlock; nSent += nCbBlock; _EXEC_CALLBACK(pBlm->pfnBuCmdSendDataStatus, nNodeAddr, nCbBlock, nSent, 2, 0); } if(nCbData) { if((nRet = GfaBlmBUCmdSendDataBlock(hBlm, nNodeAddr, pbData, nCbData)) != 0) { _EXEC_CALLBACK(pBlm->pfnBuCmdSendDataStatus, nNodeAddr, nCbBlock, nSent, 0, errno); return -1; } nSent += nCbData; nCbData = 0; _EXEC_CALLBACK(pBlm->pfnBuCmdSendDataStatus, nNodeAddr, nCbBlock, nSent, 2, 0); } _EXEC_CALLBACK(pBlm->pfnBuCmdSendDataStatus, nNodeAddr, nCbBlock, nSent, 3, 0); return 0; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmBUCmdSendDataFile(HGFABLM hBlm, uint8_t nNodeAddr, const char *pszFilename, uint32_t nFlashStartAddr, size_t nCbBlock, uint32_t nTimeoutMS) { if(hBlm && pszFilename && !NODE_IS_MULTICAST(nNodeAddr)) { int nRet = -1; ssize_t nFileLen; FILE *pf = NULL; uint8_t *pBuf = NULL; do { if(!(pf = fopen(pszFilename, "rb"))) break; if(fseek(pf, 0, SEEK_END)) break; if((nFileLen = ftell(pf)) < 0) break; if(fseek(pf, 0, SEEK_SET)) break; if( (nFileLen > 0) && (pBuf = (uint8_t*)malloc(nFileLen)) && (fread(pBuf, 1, nFileLen, pf) == (size_t)nFileLen)) { if((nRet = GfaBlmBUCmdDownload(hBlm, nNodeAddr, nFlashStartAddr, nFileLen, nTimeoutMS)) == 0) nRet = GfaBlmBUCmdSendData(hBlm, nNodeAddr, pBuf, nFileLen, nCbBlock); } } while(false); if(pBuf) free(pBuf); if(pf) fclose(pf); return nRet; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// GFA_BLM_EXEC_CONTEXT GfaBlmGetExecutionContext(HGFABLM hBlm, uint8_t nNodeAddr) { if(hBlm && !NODE_IS_MULTICAST(nNodeAddr)) { uint8_t nIndex; ssize_t nRet, nLen; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; char txb[32], rxb[32]; nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, "BU", 2, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen) return GfaBlmCtx_Err; if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0) return GfaBlmCtx_Err; nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) return GfaBlmCtx_Err; else if(nRet == MINET_SLAVE_RESPONSE_ACK) return GfaBlmCtx_Boot; else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) return GfaBlmCtx_App; return GfaBlmCtx_Err; } errno = EINVAL; return GfaBlmCtx_Err; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmBootloaderExecute(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t *pnImgCRC32, uint32_t nTimeoutMS) { if(hBlm && !NODE_IS_MULTICAST(nNodeAddr)) { uint8_t nIndex; uint32_t nImgCRC32; ssize_t nRet, nLen; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; char txb[32], rxb[32]; nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, "BE", 2, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen) return -1; if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0) return nLen; nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { if((nRet = GfaMininetMasterGetDataFromSlaveFrame(rxb, nLen, &nImgCRC32, sizeof(nImgCRC32))) == 4) { if(pnImgCRC32) *pnImgCRC32 = bswap_32(nImgCRC32); do { if(nTimeoutMS > _BOOTLOADER_EXEC_WAIT_TIME) { usleep(_BOOTLOADER_EXEC_WAIT_TIME * 1000); nTimeoutMS -= _BOOTLOADER_EXEC_WAIT_TIME; } else { usleep(nTimeoutMS * 1000); nTimeoutMS = 0; } if((nRet = GfaMininetMasterResetSlaveIndex(pBlm->hMst, nNodeAddr)) == 0) break; GfaMininetMasterPurgeDeviceRXBuffer(pBlm->hMst); } while(nTimeoutMS > 0); return nRet; } } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { return 0; } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { errno = -(int)nIndex; return -1; } return -1; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmBootloaderSetBaudrate(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nBaudrate) { if(hBlm) { uint8_t nIndex; size_t s; ssize_t nRet, nLen; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; if(GfaMininetMasterIsValidBaudrate(pBlm->hMst, nBaudrate)) { char txb[32], rxb[32], cmd[8]; uint32_t nBr = bswap_32(nBaudrate); s = GfaBlmBuildCmdDataPacket("BB", 0, &nBr, sizeof(nBr), cmd, sizeof(cmd), false); nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, cmd, s, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen) return nRet; if(NODE_IS_MULTICAST(nNodeAddr)) return 0; if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0) return nLen; nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_ACK) { return GfaMininetMasterSetBaudrate(pBlm->hMst, nBaudrate); } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { errno = -(int)nIndex; return -1; } return -1; } } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmBootloaderDump(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nAddress, uint32_t nCntDwords, void *pBuffer, size_t nCbBuffer) { if(hBlm && pBuffer && nCntDwords && !NODE_IS_MULTICAST(nNodeAddr)) { size_t s; uint8_t nIndex; ssize_t nRet, nLen; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; uint32_t i, dmp[_GFA_MAX_DUMP_DWORDS]; char txb[32], rxb[128], cmd[10]; if(nCntDwords > _GFA_MAX_DUMP_DWORDS) nCntDwords = _GFA_MAX_DUMP_DWORDS; if((nCntDwords * sizeof(uint32_t)) > nCbBuffer) { errno = ENOMEM; return -1; } struct _MEM { uint32_t nAddr; uint32_t nCount; }mem = {bswap_32(nAddress), bswap_32(nCntDwords)}; s = GfaBlmBuildCmdDataPacket("BD", 0, &mem, sizeof(mem), cmd, sizeof(cmd), false); nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, cmd, s, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen) return nRet; if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0) return nLen; nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { if((nRet = GfaMininetMasterGetDataFromSlaveFrame(rxb, nLen, dmp, sizeof(uint32_t) * nCntDwords)) != (ssize_t)(sizeof(uint32_t) * nCntDwords)) return -1; for(i = 0; i < nCntDwords; ++i) { dmp[i] = bswap_32(dmp[i]); } memcpy(pBuffer, dmp, sizeof(uint32_t) * nCntDwords); return 0; } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, dmp, sizeof(uint32_t) * nCntDwords, 200)) != (ssize_t)(sizeof(uint32_t) * nCntDwords)) return -1; for(i = 0; i < nCntDwords; ++i) { dmp[i] = bswap_32(dmp[i]); } memcpy(pBuffer, dmp, sizeof(uint32_t) * nCntDwords); return 0; } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { errno = -(int)nIndex; return -1; } return -1; } errno = EINVAL; return -1; } int GfaBlmGetImgInfo(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nDumpAddr, bool bCtxIsApp, LPGFA_IMG_INFO pii) { if(hBlm && pii && !NODE_IS_MULTICAST(nNodeAddr)) { ssize_t nRet = 0; uint32_t i, j, nPfx0Addr = 0; int32_t nPfx0Index = -1, nPfx1Index = -1; uint32_t aDump[_GFA_MAX_DUMP_DWORDS]; GFA_APP_IMG_HEADER aih; memset(&aih, 0, sizeof(aih)); memset(pii, 0, sizeof(GFA_IMG_INFO)); for(i = 0; i < 257; i += _GFA_MAX_DUMP_DWORDS) { if((nRet = GfaBlmBootloaderDump(hBlm, nNodeAddr, nDumpAddr, _GFA_MAX_DUMP_DWORDS, aDump, sizeof(aDump))) == 0) { for(j = 0; j < _GFA_MAX_DUMP_DWORDS; ++j, nDumpAddr += sizeof(uint32_t)) { switch(aDump[j]) { case GFA_APP_IMG_HEADER_PREFIX_0: nPfx0Addr = nDumpAddr; nPfx0Index = i + j; continue; case GFA_APP_IMG_HEADER_PREFIX_1: nPfx1Index = i + j; break; default: break; } if((nPfx0Index >= 0) && (nPfx1Index == (nPfx0Index + 1))) { uint32_t nDmpStart = nPfx0Addr + 2 * sizeof(uint32_t), *pDwDst = ((uint32_t*)&aih) + 2; uint32_t nCntDwAvail = 15 - j; if(bCtxIsApp) { uint32_t nDwOffsImgMaterialNum = _dword_offset(app.pszImgMaterialNum); uint32_t nDwOffsImgNameBuild = _dword_offset(app.pszImgNameBuild); uint32_t nDwOffsImgCRC32 = _dword_offset(nImgCRC32); size_t nSizeDst = (nDwOffsImgNameBuild + 1) * sizeof(uint32_t); uint32_t nCntDwToDmp, nCntDwToCpy; if(nCntDwAvail > nDwOffsImgNameBuild) { // have nImgLength, nImgCRC32, pszImgMaterialNum, pszImgNameBuild // need nothing nCntDwToCpy = nDwOffsImgNameBuild + 1; nCntDwToDmp = 0; memcpy(pDwDst, &aDump[j + 1], nCntDwToCpy * sizeof(uint32_t)); } else if(nCntDwAvail == nDwOffsImgNameBuild) { // have nImgLength, nImgCRC32, pszImgMaterialNum // need pszImgNameBuild nCntDwToCpy = nDwOffsImgNameBuild; nCntDwToDmp = 1; nDmpStart += nCntDwToCpy * sizeof(uint32_t); memcpy(pDwDst, &aDump[j + 1], nCntDwToCpy * sizeof(uint32_t)); pDwDst += nCntDwToCpy; nSizeDst -= nCntDwToCpy * sizeof(uint32_t); } else if(nCntDwAvail > nDwOffsImgCRC32) { // have nImgLength, nImgCRC32 // need pszImgMaterialNum, pszImgNameBuild nCntDwToCpy = 2; nCntDwToDmp = 2; nDmpStart += nDwOffsImgMaterialNum * sizeof(uint32_t); memcpy(pDwDst, &aDump[j + 1], nCntDwToCpy * sizeof(uint32_t)); pDwDst += nDwOffsImgMaterialNum; nSizeDst -= nDwOffsImgMaterialNum * sizeof(uint32_t); } else if(nCntDwAvail == nDwOffsImgCRC32) { // have nImgLength // need nImgCRC32, pszImgMaterialNum, pszImgNameBuild nCntDwToCpy = nDwOffsImgCRC32; nCntDwToDmp = 7; // 1 + 4 + 2 nDmpStart += sizeof(uint32_t); memcpy(pDwDst, &aDump[j + 1], nCntDwToCpy * sizeof(uint32_t)); pDwDst += nCntDwToCpy; nSizeDst -= nCntDwToCpy * sizeof(uint32_t); } else { // have nothing // need nImgLength, nImgCRC32, pszImgMaterialNum, pszImgNameBuild nCntDwToCpy = 0; nCntDwToDmp = nDwOffsImgNameBuild + 1; // 2 + 4 + 2 } if(nCntDwToDmp) { if((nRet = GfaBlmBootloaderDump(hBlm, nNodeAddr, nDmpStart, nCntDwToDmp, pDwDst, nSizeDst)) != 0) return -1; } pii->nImgLength = aih.nImgLength; pii->nImgCRC32 = aih.nImgCRC32; if((nRet = GfaBlmBootloaderDump(hBlm, nNodeAddr, (uint32_t)aih.app.pszImgMaterialNum, GFA_APP_MAX_IMG_MATERIAL_NUM_LENGTH / sizeof(uint32_t), pii->szImgMaterialNum, GFA_APP_MAX_IMG_MATERIAL_NUM_LENGTH)) != 0) return -1; if((nRet = GfaBlmBootloaderDump(hBlm, nNodeAddr, (uint32_t)aih.app.pszImgNameBuild, GFA_APP_MAX_IMG_NAME_BUILD_LENGTH / sizeof(uint32_t), pii->szImgNameBuild, GFA_APP_MAX_IMG_NAME_BUILD_LENGTH)) != 0) return -1; pii->szImgMaterialNum[GFA_APP_MAX_IMG_MATERIAL_NUM_LENGTH - 1] = '\0'; pii->szImgNameBuild[GFA_APP_MAX_IMG_NAME_BUILD_LENGTH - 1] = '\0'; return 0; } else { uint32_t nDwOffsImgMaterialNum = _dword_offset(bl.szImgMaterialNum); uint32_t nDwOffsImgNameBuild = _dword_offset(bl.szImgNameBuild); uint32_t nDwOffsImgCRC32 = _dword_offset(nImgCRC32); size_t nSizeDst = nDwOffsImgNameBuild * sizeof(uint32_t) + GFA_APP_MAX_IMG_NAME_BUILD_LENGTH; uint32_t nCntDwToDmp, nCntDwToCpy; if(nCntDwAvail >= (nDwOffsImgNameBuild + GFA_APP_MAX_IMG_NAME_BUILD_LENGTH / sizeof(uint32_t))) { // have nImgLength, nImgCRC32, szImgMaterialNum, szImgNameBuild // need nothing nCntDwToCpy = nDwOffsImgNameBuild + GFA_APP_MAX_IMG_NAME_BUILD_LENGTH / sizeof(uint32_t); nCntDwToDmp = 0; memcpy(pDwDst, &aDump[j + 1], nCntDwToCpy * sizeof(uint32_t)); } else if(nCntDwAvail > nDwOffsImgMaterialNum) { // have nImgLength, nImgCRC32, szImgMaterialNum // need szImgNameBuild nCntDwToCpy = nCntDwAvail; nCntDwToDmp = nSizeDst / sizeof(uint32_t) - nCntDwToCpy; // (1...3) + 6 nDmpStart += nCntDwToCpy * sizeof(uint32_t); memcpy(pDwDst, &aDump[j + 1], nCntDwToCpy * sizeof(uint32_t)); pDwDst += nCntDwToCpy; nSizeDst -= nCntDwToCpy * sizeof(uint32_t); } else if(nCntDwAvail > nDwOffsImgCRC32) { // have nImgLength, nImgCRC32 // need szImgMaterialNum, szImgNameBuild nCntDwToCpy = 2; nCntDwToDmp = (GFA_APP_MAX_IMG_MATERIAL_NUM_LENGTH + GFA_APP_MAX_IMG_NAME_BUILD_LENGTH) / sizeof(uint32_t); // 4 + 6 nDmpStart += nDwOffsImgMaterialNum * sizeof(uint32_t); memcpy(pDwDst, &aDump[j + 1], nCntDwToCpy * sizeof(uint32_t)); pDwDst += nDwOffsImgMaterialNum; nSizeDst -= nDwOffsImgMaterialNum * sizeof(uint32_t); } else if(nCntDwAvail == nDwOffsImgCRC32) { // have nImgLength // need nImgCRC32, szImgMaterialNum, szImgNameBuild nCntDwToCpy = nDwOffsImgCRC32; nCntDwToDmp = nSizeDst / sizeof(uint32_t) - nCntDwToCpy; // 1 + 4 + 4 + 6 nDmpStart += sizeof(uint32_t); memcpy(pDwDst, &aDump[j + 1], nCntDwToCpy * sizeof(uint32_t)); pDwDst += nCntDwToCpy; nSizeDst -= nCntDwToCpy * sizeof(uint32_t); } else { // have nothing // need nImgLength, nImgCRC32, pszImgMaterialNum, pszImgNameBuild nCntDwToCpy = 0; nCntDwToDmp = nSizeDst / sizeof(uint32_t); // 2 + 4 + 4 + 6 } if(nCntDwToDmp) { if((nRet = GfaBlmBootloaderDump(hBlm, nNodeAddr, nDmpStart, nCntDwToDmp, pDwDst, nSizeDst)) != 0) return -1; } pii->nImgLength = aih.nImgLength; pii->nImgCRC32 = aih.nImgCRC32; memcpy(pii->szImgMaterialNum, aih.bl.szImgMaterialNum, GFA_APP_MAX_IMG_MATERIAL_NUM_LENGTH); memcpy(pii->szImgNameBuild, aih.bl.szImgNameBuild, GFA_APP_MAX_IMG_NAME_BUILD_LENGTH); pii->szImgMaterialNum[GFA_APP_MAX_IMG_MATERIAL_NUM_LENGTH - 1] = '\0'; pii->szImgNameBuild[GFA_APP_MAX_IMG_NAME_BUILD_LENGTH - 1] = '\0'; return 0; } } } } else { break; } } return -1; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmGetInfoBD(HGFABLM hBlm, uint8_t nNodeAddr, LPGFA_BL_APP_IMG_INFO paii) { if(hBlm && paii && !NODE_IS_MULTICAST(nNodeAddr)) { int nRet1, nRet2; if((nRet1 = GfaBlmGetImgInfo(hBlm, nNodeAddr, GFA_APP_BOOTLOADER_START_ADDRESS, false, &paii->bl)) < 0) { memset(&paii->bl, 0, sizeof(paii->bl)); paii->bl.nImgLength = paii->bl.nImgCRC32 = 0xFFFFFFFF; } if((nRet2 = GfaBlmGetImgInfo(hBlm, nNodeAddr, GFA_APP_APPLICATION_START_ADDRESS, true, &paii->app)) < 0) { memset(&paii->app, 0, sizeof(paii->app)); paii->app.nImgLength = paii->app.nImgCRC32 = 0xFFFFFFFF; } return nRet1 + nRet2; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmGetInfoBI(HGFABLM hBlm, uint8_t nNodeAddr, LPGFA_BL_APP_IMG_INFO paii) { if(hBlm && paii && !NODE_IS_MULTICAST(nNodeAddr)) { uint8_t nIndex; ssize_t nRet, nLen; char txb[32], rxb[256]; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, "BI", 2, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen) return nRet; if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0) return nLen; nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { if((nRet = GfaMininetMasterGetDataFromSlaveFrame(rxb, nLen, paii, sizeof(GFA_BL_APP_IMG_INFO))) == sizeof(GFA_BL_APP_IMG_INFO)) { paii->bl.nImgLength = bswap_32(paii->bl.nImgLength); paii->bl.nImgCRC32 = bswap_32(paii->bl.nImgCRC32); paii->app.nImgLength = bswap_32(paii->app.nImgLength); paii->app.nImgCRC32 = bswap_32(paii->app.nImgCRC32); return 0; } errno = EPROTO; return -1; } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { errno = EPROTO; return -1; } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { errno = -(int)nIndex; return -1; } return -1; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmReadMaterialAndSerialID(HGFABLM hBlm, uint8_t nNodeAddr, char *pszMaterial, size_t nCbMaterial, char *pszSerial, size_t nCbSerial) { if(hBlm && pszMaterial && (nCbMaterial >= 16) && pszSerial && (nCbSerial >= 16) && !NODE_IS_MULTICAST(nNodeAddr)) { uint8_t nIndex; ssize_t nRet, nLen; char txb[32], rxb[64], data[32]; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, "BR", 2, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen) return nRet; if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0) return nLen; nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { if((nRet = GfaMininetMasterGetDataFromSlaveFrame(rxb, nLen, data, sizeof(data))) != 32) return -1; memcpy(pszMaterial, data, 16); pszMaterial[15] = '\0'; memcpy(pszSerial, &data[16], 16); pszSerial[15] = '\0'; return 0; } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, data, sizeof(data), 200)) != (ssize_t)sizeof(data)) return -1; memcpy(pszMaterial, data, 16); pszMaterial[15] = '\0'; memcpy(pszSerial, &data[16], 16); pszSerial[15] = '\0'; return 0; } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { errno = -(int)nIndex; return -1; } return -1; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmWriteMaterialAndSerialID(HGFABLM hBlm, uint8_t nNodeAddr, const char *pszMaterial, const char *pszSerial) { if(hBlm && pszMaterial && pszSerial && !NODE_IS_MULTICAST(nNodeAddr)) { uint8_t nIndex; size_t s; ssize_t nRet, nLen; size_t nLenMaterial, nLenSerial; LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; struct _TS { char szMaterial[16]; char szSerial[16]; }ts; char txb[64], rxb[32], cmd[64]; nLenMaterial = strlen(pszMaterial); nLenSerial = strlen(pszSerial); if((nLenMaterial > 15) || (nLenSerial > 15)) return -1; memcpy(ts.szMaterial, pszMaterial, nLenMaterial); if(nLenMaterial < 15) memset(&ts.szMaterial[nLenMaterial], ' ', 15 - nLenMaterial); ts.szMaterial[15] = '\0'; memcpy(ts.szSerial, pszSerial, nLenSerial); if(nLenSerial < 15) memset(&ts.szSerial[nLenSerial], ' ', 15 - nLenSerial); ts.szSerial[15] = '\0'; s = GfaBlmBuildCmdDataPacket("BW", 0, &ts, sizeof(ts), cmd, sizeof(cmd), false); nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, cmd, s, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen) return nRet; if((nRet = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0) return nRet; nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nRet, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { return 0; } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { return 0; } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { errno = -(int)nIndex; return -1; } return -1; } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// HGFAMINEMST GfaBlmGetMininetMasterHandle(HGFABLM hBlm) { if(hBlm) { LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; return pBlm->hMst; } errno = EINVAL; return NULL; } ///////////////////////////////////////////////////////////////////////////// int GfaBlmSetVerbosity(HGFABLM hBlm, int nVerbosity) { if(hBlm) { LPGFA_BLM pBlm = (LPGFA_BLM)hBlm; if(nVerbosity < 0) nVerbosity = 0; else if(nVerbosity > 4) nVerbosity = 4; pBlm->nVerbosity = nVerbosity; return GfaMininetMasterSetVerbosity(pBlm->hMst, pBlm->nVerbosity); } errno = EINVAL; return -1; } ///////////////////////////////////////////////////////////////////////////// uint8_t GfaBlmDataCheckSum(const void *pData, size_t nCbData) { uint8_t chk = 0; const uint8_t *pbData = (const uint8_t*)pData; while(nCbData--) { chk += *pbData++; } return chk; } ///////////////////////////////////////////////////////////////////////////// size_t GfaBlmBuildCmdDataPacket(const char *pszCmd, uint8_t tiCmd, const void *pCmdData, size_t nCbCmdData, void *pPacket, size_t nCbPacket, bool bAddLenAndCheck) { size_t nLen = strlen(pszCmd); uint8_t *pbPacket = (uint8_t*)pPacket; tiCmd = tiCmd; // not yet used if(nCbPacket < (nLen + nCbCmdData + ((pCmdData && nCbCmdData && bAddLenAndCheck) ? 2 : 0))) return 0; memcpy(pbPacket, pszCmd, nLen); pbPacket += nLen; if(pCmdData && nCbCmdData) { if(bAddLenAndCheck) { *pbPacket++ = nCbCmdData + 2; *pbPacket++ = GfaBlmDataCheckSum(pCmdData, nCbCmdData); nLen += 2; } memcpy(pbPacket, pCmdData, nCbCmdData); nLen += nCbCmdData; } return nLen; } const char* GfaBlmStrError(int nErrorCode) { switch(nErrorCode) { case -COMMAND_RET_UNKNOWN_CMD: return "Unknown Bootloader command"; case -COMMAND_RET_INVALID_CMD: return "Invalid Bootloader command"; case -COMMAND_RET_INVALID_ADR: return "Invalid Flash address"; case -COMMAND_RET_FLASH_FAIL: return "Bootloader failed to erase flash"; case -COMMAND_RET_CRC_FAIL: return "Invalid Image CRC32"; default: return GfaMininetMasterStrError(nErrorCode); } }