528 lines
8.6 KiB
C
528 lines
8.6 KiB
C
#include "infohelper.h"
|
|
#include "lpctool_serial.h"
|
|
#include "toolcom.h"
|
|
#include "toolcmd.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <termios.h>
|
|
|
|
const unsigned long secinfo[20] =
|
|
{ 0x00000,
|
|
0x04000,
|
|
0x06000,
|
|
0x08000,
|
|
0x10000,
|
|
0x20000,
|
|
0x30000,
|
|
0x40000,
|
|
0x50000,
|
|
0x60000,
|
|
0x70000,
|
|
0x80000,
|
|
0x90000,
|
|
0xA0000,
|
|
0xB0000,
|
|
0xC0000,
|
|
0xD0000,
|
|
0xE0000,
|
|
0xF0000,
|
|
0x100000 };
|
|
|
|
|
|
struct t_chunk *chunklist = NULL;
|
|
|
|
union {
|
|
unsigned char cbuf[MAXBUF];
|
|
unsigned short sbuf[MAXBUF/2];
|
|
unsigned long lbuf[MAXBUF/4];
|
|
} buffs;
|
|
|
|
int makeList(unsigned long *buf, unsigned long len)
|
|
{
|
|
unsigned long mlen;
|
|
t_chunk *mlist;
|
|
int cnt;
|
|
unsigned long gap, pos;
|
|
if(chunklist)
|
|
freeList();
|
|
|
|
mlen = len>>2;
|
|
gap = 0;
|
|
pos = 0;
|
|
cnt = 1;
|
|
|
|
if(mlen)
|
|
{
|
|
printInfoS(2,"creating list of chunks",0);
|
|
|
|
chunklist = malloc(sizeof(t_chunk));
|
|
|
|
mlist = chunklist;
|
|
|
|
if(mlist)
|
|
{
|
|
mlist->start = 0x80000000;
|
|
mlist->len = 0;
|
|
mlist->prev = NULL;
|
|
mlist->next = NULL;
|
|
}
|
|
|
|
while(mlen)
|
|
{
|
|
gap = 0;
|
|
if(buf[pos] != 0xFFFFFFFF)
|
|
{
|
|
mlist->len += 4;
|
|
mlen --;
|
|
pos ++;
|
|
}
|
|
else while(buf[pos] == 0xFFFFFFFF)
|
|
{
|
|
gap += 4;
|
|
pos ++;
|
|
mlen --;
|
|
}
|
|
if(gap)
|
|
{
|
|
if(gap >= MIN_GAP)
|
|
{
|
|
mlist->next = malloc(sizeof(t_chunk));
|
|
if(mlist->next)
|
|
{
|
|
cnt++;
|
|
mlist->next->start = chunklist->start + (pos*4);
|
|
mlist->next->prev = mlist;
|
|
mlist->next->next = NULL;
|
|
mlist->next->len = 0;
|
|
mlist = mlist->next;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
mlist->len += gap;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
printInfoH(2, "chunk entries created:",cnt);
|
|
return(cnt);
|
|
}
|
|
|
|
void freeList(void)
|
|
{
|
|
t_chunk *mlist;
|
|
int cnt;
|
|
|
|
if(chunklist)
|
|
{
|
|
mlist = chunklist;
|
|
cnt = 0;
|
|
|
|
while(mlist->next != NULL)
|
|
{
|
|
mlist = mlist->next;
|
|
cnt++;
|
|
free(mlist->prev);
|
|
}
|
|
cnt++;
|
|
free(mlist);
|
|
}
|
|
}
|
|
|
|
|
|
int getRESULT(unsigned char acktype)
|
|
{
|
|
char buf[4];
|
|
unsigned char q;
|
|
|
|
switch(acktype)
|
|
{
|
|
case ACK:
|
|
q = getBuf(4, buf);
|
|
if(strncmp(buf, ACKTOKEN, 4))
|
|
{
|
|
return printError("wrong response, expected ACK!");
|
|
}
|
|
return 1;
|
|
break;
|
|
|
|
case HELO:
|
|
q = getBuf(4, buf);
|
|
if(strncmp(buf, HELOTOKEN, 4))
|
|
{
|
|
return printError("wrong response, expected HELO");
|
|
}
|
|
return 1;
|
|
break;
|
|
case BACK:
|
|
q = getBuf(1, buf);
|
|
if(strncmp(buf, BACKTOKEN, 1))
|
|
{
|
|
return printError("wrong response, expected !");
|
|
}
|
|
return 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
int openRamTool()
|
|
{
|
|
char buf[1];
|
|
unsigned char q;
|
|
|
|
buf[0] = HELO_CMD;
|
|
|
|
sendBuf(1, buf);
|
|
|
|
reconfSerial(TOOLBAUD, 0, 50);
|
|
q = getRESULT(HELO);
|
|
reconfSerial(TOOLBAUD, 0, 5);
|
|
|
|
return q;
|
|
}
|
|
|
|
int setToolAdr(unsigned long adr)
|
|
{
|
|
char buf[5];
|
|
|
|
buf[0] = SETADR_CMD;
|
|
buf[1] =(adr & 0xFF000000) >> 24;
|
|
buf[2] =(adr & 0x00FF0000) >> 16;
|
|
buf[3] =(adr & 0x0000FF00) >> 8;
|
|
buf[4] = adr & 0x000000FF;
|
|
|
|
sendBuf(5, buf);
|
|
|
|
return getRESULT(ACK);
|
|
}
|
|
|
|
int eraseFlash(void)
|
|
{
|
|
char buf[1];
|
|
|
|
printInfoS(0,"erasing flash", 0);
|
|
|
|
buf[0] = FULLERASE_CMD;
|
|
|
|
sendBuf(1, buf);
|
|
|
|
return getRESULT(ACK);
|
|
}
|
|
|
|
int eraseFlashSector(void)
|
|
{
|
|
char buf[1];
|
|
|
|
buf[0] = SECTERASE_CMD;
|
|
|
|
sendBuf(1, buf);
|
|
|
|
return getRESULT(ACK);
|
|
}
|
|
|
|
int enableBulk(unsigned char b)
|
|
{
|
|
char buf[1];
|
|
|
|
if(b)
|
|
{
|
|
buf[0] = BULKENABLE_CMD;
|
|
}
|
|
else
|
|
{
|
|
buf[0] = BULKDISABLE_CMD;
|
|
}
|
|
|
|
sendBuf(1, buf);
|
|
|
|
return getRESULT(ACK);
|
|
}
|
|
|
|
int setNumBytes(unsigned long numBytes)
|
|
{
|
|
char buf[5];
|
|
|
|
buf[0] = SETNUMBYTES_CMD;
|
|
buf[1] =(numBytes & 0xFF000000) >> 24;
|
|
buf[2] =(numBytes & 0x00FF0000) >> 16;
|
|
buf[3] =(numBytes & 0x0000FF00) >> 8;
|
|
buf[4] = numBytes & 0x000000FF;
|
|
|
|
sendBuf(5, buf);
|
|
|
|
return getRESULT(ACK);
|
|
}
|
|
|
|
int writeFlash(void)
|
|
{
|
|
char buf[2];
|
|
|
|
buf[0] = WRITE_CMD;
|
|
buf[1] = WRITEGO_CMD;
|
|
|
|
sendBuf(2, buf);
|
|
|
|
return getRESULT(ACK);
|
|
}
|
|
|
|
int uploadBuf(unsigned char nwords, unsigned char* buf)
|
|
{
|
|
unsigned short cnt,cnt2, cnt3;
|
|
unsigned long checksum;
|
|
char tbuf[6];
|
|
checksum = 0;
|
|
tbuf[0] = FILLBUF_CMD;
|
|
tbuf[1] = nwords;
|
|
|
|
if(!sendBuf(2,tbuf))
|
|
return 0;
|
|
|
|
cnt = nwords << 2;
|
|
cnt2 = 0;
|
|
|
|
#define XFERSIZE 16
|
|
|
|
while(cnt >= XFERSIZE)
|
|
{
|
|
|
|
cnt3=XFERSIZE;
|
|
while(cnt3--)
|
|
checksum += buf[cnt2++];
|
|
|
|
if(!sendBuf(XFERSIZE, (char*)buf+cnt2-XFERSIZE))
|
|
return 0;
|
|
|
|
if(!getRESULT(BACK))
|
|
return 0;
|
|
|
|
cnt -= XFERSIZE;
|
|
}
|
|
|
|
if(cnt)
|
|
{
|
|
cnt3 = cnt;
|
|
while(cnt--)
|
|
checksum += buf[cnt2++];
|
|
|
|
if(!sendBuf(cnt3, (char*)buf+cnt2-cnt3))
|
|
return 0;
|
|
|
|
if(!getRESULT(BACK))
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
tbuf[0] = (checksum >> 24) & 0xFF;
|
|
tbuf[1] = (checksum >> 16) & 0xFF;
|
|
tbuf[2] = (checksum >> 8) & 0xFF;
|
|
tbuf[3] = checksum & 0xFF;
|
|
if(!sendBuf(4, tbuf))
|
|
return 0;
|
|
|
|
return getRESULT(ACK);
|
|
}
|
|
|
|
int uploadChunks(int fd, unsigned long loc, unsigned int erase)
|
|
{
|
|
unsigned long fsize, cnt, total, csize;
|
|
unsigned char buf[MAXBUF];
|
|
unsigned int numChunks;
|
|
t_chunk *curr_chunk;
|
|
|
|
if(!setToolAdr(loc))
|
|
{
|
|
freeList();
|
|
return printError("failed to set address");
|
|
}
|
|
|
|
if(erase & 0x40)
|
|
{
|
|
printInfoS(2,"erasing flash sector", 0);
|
|
if(!eraseFlashSector())
|
|
return printError("failed to erase start sector");
|
|
printInfoS(2,"flash sector erased", 0);
|
|
}
|
|
else if((erase & 0x20) || (erase & 0x10))
|
|
{
|
|
printInfoS(2,"erasing whole flash", 0);
|
|
reconfSerial(TOOLBAUD, 0, 200);
|
|
|
|
if(!eraseFlash())
|
|
return printError("failed to erase whole flash");
|
|
reconfSerial(TOOLBAUD, 0, 5);
|
|
|
|
printInfoS(2,"whole flash erased", 0);
|
|
}
|
|
|
|
printInfoS(2,"enabling bulk write",0);
|
|
if(!enableBulk(1))
|
|
return printError("bulk write enable failed");
|
|
|
|
fsize = read(fd, buf, MAXBUF);
|
|
total = fsize;
|
|
cnt = 0;
|
|
|
|
printInfoH(2,"setting total number of bytes to", fsize);
|
|
if(!setNumBytes(fsize))
|
|
return printError("cannot set total number of bytes");
|
|
|
|
printInfoS(0,"starting flash upload (chunk mode)", 0);
|
|
|
|
numChunks = makeList((unsigned long*)buf, fsize);
|
|
curr_chunk = chunklist;
|
|
|
|
printProgress(0,"Flash",cnt,total);
|
|
|
|
while(numChunks--)
|
|
{
|
|
if(!setToolAdr(curr_chunk->start))
|
|
{
|
|
freeList();
|
|
return printError("failed to set address");
|
|
}
|
|
|
|
csize = curr_chunk->len;
|
|
cnt = curr_chunk->start & 0x00FFFFFF;
|
|
|
|
while(csize >= 512)
|
|
{
|
|
if(!uploadBuf(128, buf+cnt))
|
|
{
|
|
freeList();
|
|
return printError("buffer upload failed");;
|
|
}
|
|
else
|
|
{
|
|
if(!writeFlash())
|
|
{
|
|
freeList();
|
|
return printError("flash write failed");;
|
|
}
|
|
}
|
|
csize -= 512;
|
|
cnt += 512;
|
|
printProgress(0,"Flash",cnt,total);
|
|
}
|
|
if(csize)
|
|
{
|
|
if(!uploadBuf(csize>>2, buf+cnt))
|
|
{
|
|
freeList();
|
|
return printError("buffer upload failed");;
|
|
}
|
|
else
|
|
{
|
|
if(!writeFlash())
|
|
{
|
|
freeList();
|
|
return printError("flash write failed");;
|
|
}
|
|
}
|
|
csize = 0;
|
|
printProgress(0,"Flash",cnt,total);
|
|
}
|
|
|
|
curr_chunk = curr_chunk->next;
|
|
}
|
|
|
|
printProgress(0,"Flash",total,total);
|
|
|
|
freeList();
|
|
|
|
if(!enableBulk(0))
|
|
return printError("bulk write disable failed");;
|
|
|
|
printInfoH(0,"flash upload (chunk mode) complete, total bytes:", total);
|
|
return 1;
|
|
}
|
|
|
|
int uploadFlash(int fd, unsigned long loc, unsigned int erase)
|
|
{
|
|
unsigned long fsize, cnt, total;
|
|
unsigned char buf[MAXBUF];
|
|
|
|
printInfoH(2,"setting address to", loc);
|
|
if(!setToolAdr(loc))
|
|
return printError("failed to set address");
|
|
|
|
if(erase & 0x40)
|
|
{
|
|
printInfoS(2,"erasing flash sector", 0);
|
|
if(!eraseFlashSector())
|
|
return printError("failed to erase start sector");
|
|
printInfoS(2,"flash sector erased", 0);
|
|
}
|
|
else if((erase & 0x20) || (erase & 0x10))
|
|
{
|
|
printInfoS(2,"erasing whole flash", 0);
|
|
reconfSerial(TOOLBAUD, 0, 200);
|
|
|
|
if(!eraseFlash())
|
|
return printError("failed to erase whole flash");
|
|
reconfSerial(TOOLBAUD, 0, 5);
|
|
|
|
printInfoS(2,"whole flash erased", 0);
|
|
}
|
|
|
|
printInfoS(2,"enabling bulk write",0);
|
|
if(!enableBulk(1))
|
|
return printError("bulk write enable failed");
|
|
|
|
fsize = read(fd, buf, MAXBUF);
|
|
|
|
printInfoH(2,"setting total number of bytes to", fsize);
|
|
if(!setNumBytes(fsize))
|
|
return printError("cannot set total number of bytes");
|
|
|
|
cnt = 0;
|
|
total = fsize;
|
|
|
|
printInfoS(0,"starting flash upload", 0);
|
|
printProgress(0,"Flash",cnt,total);
|
|
|
|
while(fsize >= 512)
|
|
{
|
|
if(!uploadBuf(128, buf+cnt))
|
|
{
|
|
return printError("buffer upload failed");;
|
|
}
|
|
else
|
|
{
|
|
if(!writeFlash())
|
|
return printError("flash write failed");;
|
|
}
|
|
fsize -= 512;
|
|
cnt += 512;
|
|
printProgress(0,"Flash",cnt,total);
|
|
}
|
|
if(fsize)
|
|
{
|
|
if(!uploadBuf(fsize>>2, buf+cnt))
|
|
{
|
|
return printError("buffer upload failed");;
|
|
}
|
|
else
|
|
{
|
|
if(!writeFlash())
|
|
return printError("flash write failed");;
|
|
}
|
|
fsize = 0;
|
|
printProgress(0,"Flash",total,total);
|
|
}
|
|
|
|
if(!enableBulk(0))
|
|
return printError("bulk write disable failed");;
|
|
|
|
printInfoH(0,"flash upload complete, total bytes:", total);
|
|
return 1;
|
|
}
|
|
|
|
|