boop/Asixtool/bootcom.c
2017-07-01 22:09:52 +02:00

389 lines
7.1 KiB
C

/*
bootcom.c - com routines for the asix on.chip bootloader
Copyright (C) 2007 Ch. Klippel <ck@mamalala.net>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "bootcom.h"
#include "stdio.h"
#include "asix_serial.h"
#include "infohelper.h"
#include "fcntl.h"
#include "unistd.h"
#define MAXSECT 11
extern char verbosity;
char buf[5];
char fbuf[0x080000];
int do_erase;
unsigned int sectors[MAXSECT+1] = {
0x00000,
0x04000,
0x06000,
0x08000,
0x10000,
0x20000,
0x30000,
0x40000,
0x50000,
0x60000,
0x70000,
0x80000
};
int findSect(unsigned long adr)
{
int secnum = 0;
while((sectors[secnum] < adr) && (secnum < MAXSECT))
{
secnum++;
}
if(sectors[secnum] > adr)
return secnum-1;
else
return secnum;
}
void dumpBuf()
{
printf("%02X %02X %02X %02X %02X\n",(unsigned char)buf[0],(unsigned char)buf[1],(unsigned char)buf[2],(unsigned char)buf[3],(unsigned char)buf[4]);
}
void sendCMD(unsigned char a, unsigned char b, unsigned char c, unsigned char d, unsigned char e)
{
buf[0] = a;
buf[1] = b;
buf[2] = c;
buf[3] = d;
buf[4] = e;
sendBuf(5, buf);
}
int setAccessTime(unsigned char val)
{
sendCMD(0x81, 0x00, 0x00, 0x00, val);
getBuf(1, buf);
if(buf[0] == val)
return 1;
return 0;
}
int setIntervallTime(unsigned char val)
{
sendCMD(0x82, 0x00, 0x00, 0x00, val);
getBuf(1, buf);
if(buf[0] == val)
return 1;
return 0;
}
int readFlash(char *name, unsigned int start, unsigned int len)
{
FILE *outfile;
unsigned int ret, count, cdone;
unsigned char rollover = 0;
outfile = fopen(name,"w");
sendCMD(0x00, 0x00, 0x00, 0x00, 0x00);
ret = getBuf(5, buf);
cdone = 0;
count = start+len;
printInfoH(1, "bytes to read: ",len);
for(;start<count;start++)
{
sendCMD(0x00, start & 0xFF, (start & 0xFF00) >> 8, (start & 0xFF0000) >> 16, 0x00);
ret = getBuf(1, buf);
if(ret == 1)
{
fprintf(outfile, "%c",(unsigned char)buf[0]);
fflush(outfile);
}
else
{
printf("FAIL: %02i - %06X - %02X\n",ret, start, (unsigned char) buf[0]);
fprintf(outfile, "%c",(unsigned char)buf[0]);
fflush(outfile);
}
cdone++;
if(rollover == 0)
printProgress(0, "reading", cdone, len);
rollover++;
rollover &= 0x3F;
}
printProgress(0, "reading", cdone, len);
fclose(outfile);
return 1;
}
void resetFlash(unsigned int start)
{
sendCMD(0x80, 0x33, 0x03, (start & 0xFF0000) >> 16, 0xF0);
getBuf(1, buf);
}
void closeWrite(unsigned int start)
{
sendCMD(0x80, 0x33, 0x03, (start & 0xFF0000) >> 16, 0x90);
getBuf(1, buf);
resetFlash(start);
}
int eraseFlash(unsigned int adr)
{
unsigned char base = (adr & 0xFF0000) >> 16;
printInfoH(1, "erasing flash at ", adr & 0x00FF0000);
sendCMD(0x80, 0x55, 0x05, base, 0xAA);
if(!getBuf(1, buf))
{
goto bailOut;
}
sendCMD(0x80, 0xAA, 0x02, base, 0x55);
if(!getBuf(1, buf))
{
goto bailOut;
}
sendCMD(0x80, 0x55, 0x05, base, 0x80);
if(!getBuf(1, buf))
{
goto bailOut;
}
sendCMD(0x80, 0x55, 0x05, base, 0xAA);
if(!getBuf(1, buf))
{
goto bailOut;
}
sendCMD(0x80, 0xAA, 0x02, base, 0x55);
if(!getBuf(1, buf))
{
goto bailOut;
}
sendCMD(0x80, 0x55, 0x05, base, 0x10);
if(!getBuf(1, buf))
{
goto bailOut;
}
waitErase:
sendCMD(0x00, 0x00, 0x00, base, 0x00);
if(!getBuf(1, buf))
{
goto bailOut1;
}
if(buf[0] == 0x0A || buf[0] == 0x4E)
goto waitErase;
if((unsigned char)buf[0] != 0xFF)
goto bailOut2;
printInfoS(1, "successfully erased flash", 0);
resetFlash(adr);
return 1;
bailOut:
return printError("cant issue chip erase sequence, aborting!");
bailOut1:
return printError("no response during chip erase active, aborting");
bailOut2:
return printError("cant erase chip, aborting");
}
int eraseSector(unsigned int adr)
{
unsigned char baseH = (adr & 0xFF0000) >> 16;
unsigned char baseM = (adr & 0xFF00) >> 8;
unsigned char baseL = adr & 0xFF;
printInfoH(1, "erasing sector at ", adr);
sendCMD(0x80, 0x55, 0x05, 0x00, 0xAA);
if(!getBuf(1, buf))
{
goto bailOut;
}
sendCMD(0x80, 0xAA, 0x02, 0x00, 0x55);
if(!getBuf(1, buf))
{
goto bailOut;
}
sendCMD(0x80, 0x55, 0x05, 0x00, 0x80);
if(!getBuf(1, buf))
{
goto bailOut;
}
sendCMD(0x80, 0x55, 0x05, 0x00, 0xAA);
if(!getBuf(1, buf))
{
goto bailOut;
}
sendCMD(0x80, 0xAA, 0x02, 0x00, 0x55);
if(!getBuf(1, buf))
{
goto bailOut;
}
sendCMD(0x80, baseL, baseM, baseH, 0x30);
if(!getBuf(1, buf))
{
goto bailOut;
}
waitErase:
sendCMD(0x00, baseL, baseM, baseH, 0x00);
if(!getBuf(1, buf))
{
goto bailOut1;
}
if(buf[0] == 0x0A || buf[0] == 0x4E)
goto waitErase;
if((unsigned char)buf[0] != 0xFF)
goto bailOut2;
printInfoS(1, "successfully erased sector",0);
resetFlash(adr);
return 1;
bailOut:
return printError("cant issue sector erase sequence");
bailOut1:
return printError("no response during secttor erase active");
bailOut2:
return printError("cant erase sector");
}
unsigned int writeFlash(char *name, unsigned int start, unsigned int len)
{
int infile, flen;
unsigned int ret, count, cdone;
unsigned char rollover = 0;
sendCMD(0x00, 0x00, 0x00, 0x00, 0x00);
ret = getBuf(1, buf);
infile = open(name,O_RDONLY);
flen = read(infile, fbuf, 0x80000);
if(flen < len)
{
printInfoH(1, "adjusting number of bytes to ",flen);
len = flen;
}
cdone = 0;
count = start+len;
if(do_erase)
{
unsigned char startsec, endsec;
startsec = findSect(start);
endsec = findSect(start+len-1);
nextsect:
if(!eraseSector(sectors[startsec]))
{
return(printError("error at auto-erase"));
}
if(startsec != endsec)
{
startsec++;
goto nextsect;
}
}
printInfoH(1, "bytes to write: ",len);
retry:
sendCMD(0x80, 0x55, 0x05, (start & 0xFF0000) >> 16, 0xAA);
ret = getBuf(1, buf);
sendCMD(0x80, 0xAA, 0x02, (start & 0xFF0000) >> 16, 0x55);
ret = getBuf(1, buf);
sendCMD(0x80, 0x55, 0x05, (start & 0xFF0000) >> 16, 0x20);
ret = getBuf(1, buf);
for(;start<count;start++)
{
sendCMD(0x80, 0x33, 0x03, (start & 0xFF0000) >> 16, 0xA0);
ret = getBuf(1, buf);
sendCMD(0xC0, start & 0xFF, (start & 0xFF00) >> 8, (start & 0xFF0000) >> 16, (unsigned char) fbuf[cdone]);
ret = getBuf(2, buf);
if(ret == 1)
{
sleep(1);
closeWrite(start);
printf("\nretrying\n");
goto retry;
}
if((ret != 2))
{
closeWrite(start);
return printError("error during write: short response");
}
if((unsigned char)fbuf[cdone] != (unsigned char)buf[1])
{
closeWrite(start);
return printError("error during write: data mismatch");
}
cdone++;
if(rollover == 0)
printProgress(0, "writing", cdone, len);
rollover++;
rollover &= 0x3F;
}
printProgress(0, "writing", cdone, len);
closeWrite(start);
close(infile);
return len;
}