|
| 1 | +/******************************************************************************* |
| 2 | +* Copyright 2011-2012, Cypress Semiconductor Corporation. All rights reserved. |
| 3 | +* You may use this file only in accordance with the license, terms, conditions, |
| 4 | +* disclaimers, and limitations in the end user license agreement accompanying |
| 5 | +* the software package with which this file was provided. |
| 6 | +********************************************************************************/ |
| 7 | + |
| 8 | +#include "cybtldr_command.h" |
| 9 | +#include "cybtldr_api.h" |
| 10 | + |
| 11 | +/* The highest number of memory arrays for any device. This includes flash and EEPROM arrays */ |
| 12 | +#define MAX_DEV_ARRAYS 0x80 |
| 13 | +/* The default value if a flash array has not yet received data */ |
| 14 | +#define NO_FLASH_ARRAY_DATA 0 |
| 15 | +/* The maximum number of flash arrays */ |
| 16 | +#define MAX_FLASH_ARRAYS 0x40 |
| 17 | +/* The minimum array id for EEPROM arrays. */ |
| 18 | +#define MIN_EEPROM_ARRAY 0x40 |
| 19 | + |
| 20 | +unsigned long g_validRows[MAX_FLASH_ARRAYS]; |
| 21 | +static CyBtldr_CommunicationsData* g_comm; |
| 22 | + |
| 23 | +int CyBtldr_TransferData(unsigned char* inBuf, int inSize, unsigned char* outBuf, int outSize) |
| 24 | +{ |
| 25 | + int err = g_comm->WriteData(inBuf, inSize); |
| 26 | + |
| 27 | + if (CYRET_SUCCESS == err) |
| 28 | + err = g_comm->ReadData(outBuf, outSize); |
| 29 | + |
| 30 | + if (CYRET_SUCCESS != err) |
| 31 | + err |= CYRET_ERR_COMM_MASK; |
| 32 | + |
| 33 | + return err; |
| 34 | +} |
| 35 | + |
| 36 | +int CyBtldr_ValidateRow(unsigned char arrayId, unsigned short rowNum) |
| 37 | +{ |
| 38 | + unsigned long inSize; |
| 39 | + unsigned long outSize; |
| 40 | + unsigned short minRow = 0; |
| 41 | + unsigned short maxRow = 0; |
| 42 | + unsigned char inBuf[MAX_COMMAND_SIZE]; |
| 43 | + unsigned char outBuf[MAX_COMMAND_SIZE]; |
| 44 | + unsigned char status = CYRET_SUCCESS; |
| 45 | + int err = CYRET_SUCCESS; |
| 46 | + |
| 47 | + if (arrayId < MAX_FLASH_ARRAYS) |
| 48 | + { |
| 49 | + if (NO_FLASH_ARRAY_DATA == g_validRows[arrayId]) |
| 50 | + { |
| 51 | + err = CyBtldr_CreateGetFlashSizeCmd(arrayId, inBuf, &inSize, &outSize); |
| 52 | + if (CYRET_SUCCESS == err) |
| 53 | + err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize); |
| 54 | + if (CYRET_SUCCESS == err) |
| 55 | + err = CyBtldr_ParseGetFlashSizeCmdResult(outBuf, outSize, &minRow, &maxRow, &status); |
| 56 | + if (CYRET_SUCCESS != status) |
| 57 | + err = status | CYRET_ERR_BTLDR_MASK; |
| 58 | + |
| 59 | + if (CYRET_SUCCESS == err) |
| 60 | + { |
| 61 | + if (CYRET_SUCCESS == status) |
| 62 | + g_validRows[arrayId] = (minRow << 16) + maxRow; |
| 63 | + else |
| 64 | + err = status | CYRET_ERR_BTLDR_MASK; |
| 65 | + } |
| 66 | + } |
| 67 | + if (CYRET_SUCCESS == err) |
| 68 | + { |
| 69 | + minRow = (unsigned short)(g_validRows[arrayId] >> 16); |
| 70 | + maxRow = (unsigned short)g_validRows[arrayId]; |
| 71 | + if (rowNum < minRow || rowNum > maxRow) |
| 72 | + err = CYRET_ERR_ROW; |
| 73 | + } |
| 74 | + } |
| 75 | + else |
| 76 | + err = CYRET_ERR_ARRAY; |
| 77 | + |
| 78 | + return err; |
| 79 | +} |
| 80 | + |
| 81 | + |
| 82 | +int CyBtldr_StartBootloadOperation(CyBtldr_CommunicationsData* comm, unsigned long expSiId, |
| 83 | + unsigned char expSiRev, unsigned long* blVer, const unsigned char* securityKeyBuf) |
| 84 | +{ |
| 85 | + const unsigned long SUPPORTED_BOOTLOADER = 0x010000; |
| 86 | + const unsigned long BOOTLOADER_VERSION_MASK = 0xFF0000; |
| 87 | + unsigned long i; |
| 88 | + unsigned long inSize = 0; |
| 89 | + unsigned long outSize = 0; |
| 90 | + unsigned long siliconId = 0; |
| 91 | + unsigned char inBuf[MAX_COMMAND_SIZE]; |
| 92 | + unsigned char outBuf[MAX_COMMAND_SIZE]; |
| 93 | + unsigned char siliconRev = 0; |
| 94 | + unsigned char status = CYRET_SUCCESS; |
| 95 | + int err; |
| 96 | + |
| 97 | + g_comm = comm; |
| 98 | + for (i = 0; i < MAX_FLASH_ARRAYS; i++) |
| 99 | + g_validRows[i] = NO_FLASH_ARRAY_DATA; |
| 100 | + |
| 101 | + err = g_comm->OpenConnection(); |
| 102 | + if (CYRET_SUCCESS != err) |
| 103 | + err |= CYRET_ERR_COMM_MASK; |
| 104 | + |
| 105 | + if (CYRET_SUCCESS == err) |
| 106 | + err = CyBtldr_CreateEnterBootLoaderCmd(inBuf, &inSize, &outSize, securityKeyBuf); |
| 107 | + if (CYRET_SUCCESS == err) |
| 108 | + err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize); |
| 109 | + if (CYRET_SUCCESS == err) |
| 110 | + err = CyBtldr_ParseEnterBootLoaderCmdResult(outBuf, outSize, &siliconId, &siliconRev, blVer, &status); |
| 111 | + else if (CyBtldr_TryParseParketStatus(outBuf, outSize, &status) == CYRET_SUCCESS) |
| 112 | + err = status | CYRET_ERR_BTLDR_MASK; //if the response we get back is a valid packet overide the err with the response's status |
| 113 | + |
| 114 | + if (CYRET_SUCCESS == err) |
| 115 | + { |
| 116 | + if (CYRET_SUCCESS != status) |
| 117 | + err = status | CYRET_ERR_BTLDR_MASK; |
| 118 | + if (expSiId != siliconId || expSiRev != siliconRev) |
| 119 | + err = CYRET_ERR_DEVICE; |
| 120 | + else if ((*blVer & BOOTLOADER_VERSION_MASK) != SUPPORTED_BOOTLOADER) |
| 121 | + err = CYRET_ERR_VERSION; |
| 122 | + } |
| 123 | + |
| 124 | + return err; |
| 125 | +} |
| 126 | + |
| 127 | +int CyBtldr_GetApplicationStatus(unsigned char appID, unsigned char* isValid, unsigned char* isActive) |
| 128 | +{ |
| 129 | + unsigned long inSize = 0; |
| 130 | + unsigned long outSize = 0; |
| 131 | + unsigned char inBuf[MAX_COMMAND_SIZE]; |
| 132 | + unsigned char outBuf[MAX_COMMAND_SIZE]; |
| 133 | + unsigned char status = CYRET_SUCCESS; |
| 134 | + int err; |
| 135 | + |
| 136 | + err = CyBtldr_CreateGetAppStatusCmd(appID, inBuf, &inSize, &outSize); |
| 137 | + if (CYRET_SUCCESS == err) |
| 138 | + err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize); |
| 139 | + if (CYRET_SUCCESS == err) |
| 140 | + err = CyBtldr_ParseGetAppStatusCmdResult(outBuf, outSize, isValid, isActive, &status); |
| 141 | + |
| 142 | + if (CYRET_SUCCESS == err) |
| 143 | + { |
| 144 | + if (CYRET_SUCCESS != status) |
| 145 | + err = status | CYRET_ERR_BTLDR_MASK; |
| 146 | + } |
| 147 | + |
| 148 | + return err; |
| 149 | +} |
| 150 | + |
| 151 | +int CyBtldr_SetApplicationStatus(unsigned char appID) |
| 152 | +{ |
| 153 | + unsigned long inSize = 0; |
| 154 | + unsigned long outSize = 0; |
| 155 | + unsigned char inBuf[MAX_COMMAND_SIZE]; |
| 156 | + unsigned char outBuf[MAX_COMMAND_SIZE]; |
| 157 | + unsigned char status = CYRET_SUCCESS; |
| 158 | + int err; |
| 159 | + |
| 160 | + err = CyBtldr_CreateSetActiveAppCmd(appID, inBuf, &inSize, &outSize); |
| 161 | + if (CYRET_SUCCESS == err) |
| 162 | + err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize); |
| 163 | + if (CYRET_SUCCESS == err) |
| 164 | + err = CyBtldr_ParseSetActiveAppCmdResult(outBuf, outSize, &status); |
| 165 | + |
| 166 | + if (CYRET_SUCCESS == err) |
| 167 | + { |
| 168 | + if (CYRET_SUCCESS != status) |
| 169 | + err = status | CYRET_ERR_BTLDR_MASK; |
| 170 | + } |
| 171 | + |
| 172 | + return err; |
| 173 | +} |
| 174 | + |
| 175 | +int CyBtldr_EndBootloadOperation(void) |
| 176 | +{ |
| 177 | + unsigned long inSize; |
| 178 | + unsigned long outSize; |
| 179 | + unsigned char inBuf[MAX_COMMAND_SIZE]; |
| 180 | + |
| 181 | + int err = CyBtldr_CreateExitBootLoaderCmd(inBuf, &inSize, &outSize); |
| 182 | + if (CYRET_SUCCESS == err) |
| 183 | + { |
| 184 | + err = g_comm->WriteData(inBuf, inSize); |
| 185 | + |
| 186 | + if (CYRET_SUCCESS == err) |
| 187 | + err = g_comm->CloseConnection(); |
| 188 | + |
| 189 | + if (CYRET_SUCCESS != err) |
| 190 | + err |= CYRET_ERR_COMM_MASK; |
| 191 | + } |
| 192 | + g_comm = NULL; |
| 193 | + |
| 194 | + return err; |
| 195 | +} |
| 196 | + |
| 197 | +int CyBtldr_ProgramRow(unsigned char arrayID, unsigned short rowNum, unsigned char* buf, unsigned short size) |
| 198 | +{ |
| 199 | + const int TRANSFER_HEADER_SIZE = 11; |
| 200 | + |
| 201 | + unsigned char inBuf[MAX_COMMAND_SIZE]; |
| 202 | + unsigned char outBuf[MAX_COMMAND_SIZE]; |
| 203 | + unsigned long inSize; |
| 204 | + unsigned long outSize; |
| 205 | + unsigned long offset = 0; |
| 206 | + unsigned short subBufSize; |
| 207 | + unsigned char status = CYRET_SUCCESS; |
| 208 | + int err = CYRET_SUCCESS; |
| 209 | + |
| 210 | + if (arrayID < MAX_FLASH_ARRAYS) |
| 211 | + err = CyBtldr_ValidateRow(arrayID, rowNum); |
| 212 | + |
| 213 | + //Break row into pieces to ensure we don't send too much for the transfer protocol |
| 214 | + while ((CYRET_SUCCESS == err) && ((size - offset + TRANSFER_HEADER_SIZE) > g_comm->MaxTransferSize)) |
| 215 | + { |
| 216 | + subBufSize = (unsigned short)(g_comm->MaxTransferSize - TRANSFER_HEADER_SIZE); |
| 217 | + |
| 218 | + err = CyBtldr_CreateSendDataCmd(&buf[offset], subBufSize, inBuf, &inSize, &outSize); |
| 219 | + if (CYRET_SUCCESS == err) |
| 220 | + err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize); |
| 221 | + if (CYRET_SUCCESS == err) |
| 222 | + err = CyBtldr_ParseSendDataCmdResult(outBuf, outSize, &status); |
| 223 | + if (CYRET_SUCCESS != status) |
| 224 | + err = status | CYRET_ERR_BTLDR_MASK; |
| 225 | + |
| 226 | + offset += subBufSize; |
| 227 | + } |
| 228 | + |
| 229 | + if (CYRET_SUCCESS == err) |
| 230 | + { |
| 231 | + subBufSize = (unsigned short)(size - offset); |
| 232 | + |
| 233 | + err = CyBtldr_CreateProgramRowCmd(arrayID, rowNum, &buf[offset], subBufSize, inBuf, &inSize, &outSize); |
| 234 | + if (CYRET_SUCCESS == err) |
| 235 | + err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize); |
| 236 | + if (CYRET_SUCCESS == err) |
| 237 | + err = CyBtldr_ParseProgramRowCmdResult(outBuf, outSize, &status); |
| 238 | + if (CYRET_SUCCESS != status) |
| 239 | + err = status | CYRET_ERR_BTLDR_MASK; |
| 240 | + } |
| 241 | + |
| 242 | + return err; |
| 243 | +} |
| 244 | + |
| 245 | +int CyBtldr_EraseRow(unsigned char arrayID, unsigned short rowNum) |
| 246 | +{ |
| 247 | + unsigned char inBuf[MAX_COMMAND_SIZE]; |
| 248 | + unsigned char outBuf[MAX_COMMAND_SIZE]; |
| 249 | + unsigned long inSize = 0; |
| 250 | + unsigned long outSize = 0; |
| 251 | + unsigned char status = CYRET_SUCCESS; |
| 252 | + int err = CYRET_SUCCESS; |
| 253 | + |
| 254 | + if (arrayID < MAX_FLASH_ARRAYS) |
| 255 | + err = CyBtldr_ValidateRow(arrayID, rowNum); |
| 256 | + if (CYRET_SUCCESS == err) |
| 257 | + err = CyBtldr_CreateEraseRowCmd(arrayID, rowNum, inBuf, &inSize, &outSize); |
| 258 | + if (CYRET_SUCCESS == err) |
| 259 | + err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize); |
| 260 | + if (CYRET_SUCCESS == err) |
| 261 | + err = CyBtldr_ParseEraseRowCmdResult(outBuf, outSize, &status); |
| 262 | + if (CYRET_SUCCESS != status) |
| 263 | + err = status | CYRET_ERR_BTLDR_MASK; |
| 264 | + |
| 265 | + return err; |
| 266 | +} |
| 267 | + |
| 268 | +int CyBtldr_VerifyRow(unsigned char arrayID, unsigned short rowNum, unsigned char checksum) |
| 269 | +{ |
| 270 | + unsigned char inBuf[MAX_COMMAND_SIZE]; |
| 271 | + unsigned char outBuf[MAX_COMMAND_SIZE]; |
| 272 | + unsigned long inSize = 0; |
| 273 | + unsigned long outSize = 0; |
| 274 | + unsigned char rowChecksum = 0; |
| 275 | + unsigned char status = CYRET_SUCCESS; |
| 276 | + int err = CYRET_SUCCESS; |
| 277 | + |
| 278 | + if (arrayID < MAX_FLASH_ARRAYS) |
| 279 | + err = CyBtldr_ValidateRow(arrayID, rowNum); |
| 280 | + if (CYRET_SUCCESS == err) |
| 281 | + err = CyBtldr_CreateVerifyRowCmd(arrayID, rowNum, inBuf, &inSize, &outSize); |
| 282 | + if (CYRET_SUCCESS == err) |
| 283 | + err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize); |
| 284 | + if (CYRET_SUCCESS == err) |
| 285 | + err = CyBtldr_ParseVerifyRowCmdResult(outBuf, outSize, &rowChecksum, &status); |
| 286 | + if (CYRET_SUCCESS != status) |
| 287 | + err = status | CYRET_ERR_BTLDR_MASK; |
| 288 | + if ((CYRET_SUCCESS == err) && (rowChecksum != checksum)) |
| 289 | + err = CYRET_ERR_CHECKSUM; |
| 290 | + |
| 291 | + return err; |
| 292 | +} |
| 293 | + |
| 294 | +int CyBtldr_VerifyApplication() |
| 295 | +{ |
| 296 | + unsigned char inBuf[MAX_COMMAND_SIZE]; |
| 297 | + unsigned char outBuf[MAX_COMMAND_SIZE]; |
| 298 | + unsigned long inSize = 0; |
| 299 | + unsigned long outSize = 0; |
| 300 | + unsigned char checksumValid = 0; |
| 301 | + unsigned char status = CYRET_SUCCESS; |
| 302 | + |
| 303 | + int err = CyBtldr_CreateVerifyChecksumCmd(inBuf, &inSize, &outSize); |
| 304 | + if (CYRET_SUCCESS == err) |
| 305 | + err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize); |
| 306 | + if (CYRET_SUCCESS == err) |
| 307 | + err = CyBtldr_ParseVerifyChecksumCmdResult(outBuf, outSize, &checksumValid, &status); |
| 308 | + if (CYRET_SUCCESS != status) |
| 309 | + err = status | CYRET_ERR_BTLDR_MASK; |
| 310 | + if ((CYRET_SUCCESS == err) && (!checksumValid)) |
| 311 | + err = CYRET_ERR_CHECKSUM; |
| 312 | + |
| 313 | + return err; |
| 314 | +} |
0 commit comments