?? ian_xmodem.c
字號:
return(CMD_FAILURE);
}
memcpy((char *)(xif.dataddr), TFS_BASE(tfp), tfp->filsize);
#endif
}
r = Xdown(&xif, XMODEM);
if (size) {
/* override size by user specified value */
xif.size = size;
}
printf("\n");
if ( r < 0 ) {
printf("%s\n", xerr_msg(r));
return(CMD_FAILURE);
}
if ( ! xif.verify ) {
#if INCLUDE_TFS
if (xif.size > 0 && fname && fname[0]) {
/* save file to TFS */
r = tfsadd(fname, info, flags,
(uchar *)xif.dataddr, xif.size);
if (r != TFS_OKAY) {
printf("%s: %s: %s\n",
xerr_msg(XERR_TFS),
fname, (char *)tfsctrl(TFS_ERRMSG,r,0));
return(CMD_FAILURE);
}
}
#endif
}
printf("Rcvd 1 file.\n");
if ( xif.verify ) {
printf(" %s: %ld bytes, %d blocks, %d errors, "
"first err @ 0x%08lx\n",
fname[0] ? fname : "<noname>",
xif.size,
xif.pktcnt,
xif.errcnt, xif.firsterrat);
} else {
printf(" %s: %ld bytes, %d blocks, @ 0x%08lx\n",
fname[0] ? fname : "<no-name>",
xif.size,
xif.pktcnt,
xif.dataddr);
}
}
#if INCLUDE_FLASH
/* whether it is an X or a Y modem download, if newboot
is set, the (last) downloaded file will be written
to the boot-sector */
if (xif.size > 0 && newboot) {
extern int FlashProtectWindow;
char *bb;
ulong bootbase;
bb = getenv("BOOTROMBASE");
if (bb)
bootbase = strtoul(bb,0,0);
else
bootbase = BOOTROM_BASE;
FlashProtectWindow = 1;
printf("Reprogramming boot @ 0x%lx from 0x%lx, %ld bytes.\n",
bootbase, xif.dataddr, xif.size);
if (askuser("OK?")) {
if (flashewrite(&FlashBank[0], (char *)bootbase,
(char *)xif.dataddr, xif.size) == -1) {
/* flashewrite should never return */
printf("failed\n");
return(CMD_FAILURE);
}
}
}
#endif
} else {
/* Neither Upload nor Download */
return(CMD_PARAM_ERROR);
}
return(CMD_SUCCESS);
}
/***************************************************************************/
static char*
xerr_msg (int code)
{
return (code >= 0) ? xerr_msgs[0] : xerr_msgs[-code];
}
/***************************************************************************/
static void
doCAN (void)
{
waitclear();
/* send eight CANs */
rputchar(CAN); rputchar(CAN);
rputchar(CAN); rputchar(CAN);
rputchar(CAN); rputchar(CAN);
rputchar(CAN); rputchar(CAN);
/* send eight backspaces */
rputchar(BS); rputchar(BS);
rputchar(BS); rputchar(BS);
rputchar(BS); rputchar(BS);
rputchar(BS); rputchar(BS);
waitclear();
}
/***************************************************************************
* DOWNLOAD STUFF
**************************************************************************/
/* getPacket():
* Used by Xdown to retrieve packets.
*/
static int
getPacket(uchar *pkt, int len, int usecrc)
{
int i;
uchar seq[2];
/* s: Get and check the frame sequence number */
if ( waitbytes(seq, 2, CHAR_TMO) < 0 ) {
Mtrace("T<seq>");
return -1;
}
if ( seq[0] != (uchar)(~seq[1]) ) {
Mtrace("~<%02x != %02x>", seq[0], seq[1]);
return -1;
}
Mtrace("s");
/* d: Get the frame's data */
if ( waitbytes(pkt, len, CHAR_TMO) < 0 ) {
Mtrace("T<data>");
return -1;
}
Mtrace("d");
/* d: Get the frame's CRC or checksum */
if ( usecrc ) {
int c;
ushort crc, xcrc;
c = waitchar(CHAR_TMO);
if ( c < 0 ) {
Mtrace("T<crc>");
return -1;
}
crc = (ushort)c << 8;
c = (uchar)waitchar(CHAR_TMO);
if ( c < 0 ) {
Mtrace("T<crc>");
return -1;
}
crc |= (ushort)c;
xcrc = xcrc16((uchar *)pkt,(ulong)(len));
if (crc != xcrc) {
Mtrace("C<%04x != %04x>", crc, xcrc);
return -1;
}
} else {
uchar csum;
int xcsum;
xcsum = waitchar(CHAR_TMO);
if ( xcsum < 0 ) {
Mtrace("T<xcsum>");
return -1;
}
csum = 0;
for(i=0; i < len; i++)
csum += *pkt++;
if (csum != xcsum) {
Mtrace("c<%02x != %02x>",csum,xcsum);
return -1;
}
}
Mtrace("c");
return seq[0];
}
/***************************************************************************/
/*
* waitPacket
*
* Receive a X or Y modem packet. Step the reception state-machine.
*
* Acknowledge the previous frame (or 'kick' the transmiter with a 'C'
* or NAK if this is the first frame), and receive the next-one. Also
* handle frame retransmitions.
*
* Arguments:
* - pb - packet (frame) buffer. Write the packet-data here.
* - *len - packet's size in bytes will be written here
* - sno - packet sequence number to wait for.
* - usercrc - if non-zero, user 16-bit CRC instread of 8-bit checksum.
*
* Returns:
* 0 - if packet was received successfully
* 1 - if an EOT was received instead of a packet
* Something negative on fatal error:
* XERR_SYNC : Synchronization lost
* XERR_CAN : Operation canceled
* XERR_UCAN : Operation canceled by user
*/
static int
waitPacket (uchar *pb, int *len, ulong lsno, int usecrc)
{
char nak;
int done, rval;
int c, r, sno, psize;
if ( usecrc ) {
nak = 'C';
} else {
nak = NAK;
}
if ( (lsno == 0 || lsno == 1) ) {
/* if it is the first frame of a X or Y modem session,
'kick' the transmiter by sending a NAK or a 'C' */
rputchar(nak);
} else {
/* if it is not the first frame of an X or Y modem session,
acknowledge the previous frame */
rputchar(ACK);
}
sno = lsno % 0x100;
/* loop exitst with:
done = 1: packet received succesfully
done = 2: EOT received and acknowledged
done < 0: Fatal error. 'done' holds error code. */
do {
done = 0;
c = waitchar(FRAME_TMO);
switch ( c ) {
case STX:
case SOH:
/* ok, its a block */
Mtrace("P[");
*len = psize = (c == STX) ? 1024 : 128;
r = getPacket(pb, psize, usecrc);
Mtrace("]");
if (r < 0) {
/* block reception not ok. request retransmission */
waitclear();
rputchar(nak);
break;
}
if ( r != sno ) {
/* block sequence number is not quite right,
but it might still do */
if ( (lsno == 0) || ( sno - r != 1 && r - sno != 0xff ) ) {
/* shit! desperately out of sync.
CAN the whole thing */
Mtrace("S<%02x != %02x>", r, sno);
doCAN();
done = XERR_SYNC;
} else {
/* no worries, it's just a retransmission */
Mtrace("S");
rputchar(ACK);
if (lsno == 1) {
Mtrace("0");
rputchar(nak);
}
}
} else {
/* seq. number just fine */
Mtrace("s");
if ( lsno == 0 ) {
Mtrace("0");
rputchar(ACK);
}
done = 1;
}
break;
case CAN:
Mtrace("C");
/* wait for a second CAN */
c = (char)waitchar(CHAR_TMO);
if (c != CAN) {
Mtrace("<%02x>", c);
waitclear();
rputchar(nak);
} else {
Mtrace("C");
done = XERR_CAN;
}
break;
case ESC:
/* User-invoked abort */
Mtrace("X");
/* wait for a second ESC */
c = (char)waitchar(CHAR_TMO);
if (c != ESC) {
waitclear();
rputchar(nak);
done = 0;
} else {
done = XERR_UCAN;
}
break;
case EOT:
Mtrace("E");
/* first make sure that this is really an EOT,
and not a corrupted start-frame; use the fact that
self-respecting EOTs always come alone, not followed
by other characters. */
c = waitchar(CHAR_TMO);
if ( c >= 0 ) {
/* probably not an EOT, request retransmission */
Mtrace("<%02x>", c);
waitclear();
rputchar(nak);
break;
}
/* ok it is probably a true EOT, send an ACK */
rputchar(ACK);
Mtrace("a", c);
if (lsno != 0) {
done = 2;
}
break;
default:
/* request retransmission */
Mtrace("?<%02x>",(uchar)c);
waitclear();
rputchar(nak);
break;
}
} while (!done);
if (done == 1) {
rval = 0;
} else if (done == 2) {
rval = 1;
} else {
rval = done;
}
return rval;
}
/***************************************************************************/
/* Xdown():
*
* Download, or verify a file using the XMODEM protocol
*
* Arguments:
* - xip - structure containing transfer info:
* usecrc IN - use 16bit-CRC instead of 8bit-checksum.
* verify IN - operate in verification mode.
* dataddr: IN - downloaded file will be stored starting from here.
* in verification mode, downloaded file will be
* compared with data starting from here.
* size: OUT - size of received file in bytes.
* pktcnt: OUT - number of frames transfered.
* errcnt: OUT - number of errors, if mode is verification.
* firsterrat: OUT - address of first error, if mode is verification.
* - proto - protocol type (y-modem or x-modem); Used to make very small
* adjustment to the operation of the function.
*
* Returns:
* On success: something non-negative.
* On error: something negative.
* XERR_GEN : General error
* XERR_TOUT : Timeout
* XERR_SYNC : Lost synchronization
* XERR_CAN : Operation canceled
* XERR_UCAN : Operation canceled by user
*/
static int
Xdown(struct xinfo *xip, int proto)
{
int i, r;
ulong sno;
int psize;
char *tmppkt, *dataddr;
Mtrace("--XD--");
dataddr = (char *)(xip->dataddr);
if ( xip->verify ) {
tmppkt = pktbuff;
} else {
tmppkt = (char *)(xip->dataddr);
}
sno = 1;
xip->pktcnt = 0;
xip->errcnt = 0;
xip->firsterrat = 0;
xip->size = 0;
do {
r = waitPacket(tmppkt, &psize, sno, xip->usecrc);
if ( r == 0 ) {
sno++;
xip->pktcnt++;
xip->size += psize;
if ( xip->verify ) {
for (i = 0; i < psize; i++, dataddr++) {
if (tmppkt[i] != *dataddr) {
if (xip->errcnt++ == 0)
xip->firsterrat = (ulong)dataddr;
}
}
} else {
tmppkt += psize;
}
}
} while ( ! r );
if ( r == 1 && proto == XMODEM ) {
/* send a couple more ACKs to make sure that at least
one reaches its destination */
rputchar(ACK); rputchar(ACK); rputchar(ACK);
rputchar(ACK); rputchar(ACK); rputchar(ACK);
/* send backspaces in-case ACKs have reached the user's
terminal */
rputchar(BS); rputchar(BS); rputchar(BS);
rputchar(BS); rputchar(BS); rputchar(BS);
}
if (proto == XMODEM) {
/* trash any final garbage send by the transmiter */
waitclear();
}
return r;
}
/***************************************************************************/
/* Ydown():
*
* Download (uMon <-- Host) a file using the YMODEM protocol
*
* Arguments:
* - yip - structure containing transfer info:
* usecrc IN - use 16bit CRC instead of 8bit checksum.
* onek x
* verify IN - verify the downloaded file against stored data.
* baseaddr: IN - download the first file here.
* flags IN - TFS flags to use when writing to TFS.
* info IN - TFS info to use when writing to TFS.
* filecnt OUT - Number of files successfully downloaded.
* fname[i] OUT - Name of the i'th file downloaded.
* size[i]: OUT - size of the i'th file downloaded in bytes.
* pktcnt[i]: OUT - nr of frames transfered when downloading i'th file.
* errcnt[i]: OUT - number of errors detected when verifying i'th file.
* firsterrat[i]: OUT - address of the first error of the i'th file.
*
* Returns:
* On success: something non-negative.
* On error: something negative.
* XERR_GEN : General error
* XERR_TOUT : Timeout
* XERR_NOFILE : File not found (verification mode)
* XERR_TFS : TFS error
* XERR_SYNC : Synchronization error
* XERR_CAN : Operation canceled
* XERR_UCAN : Operation canceled by user
*/
static int
Ydown(struct yinfo *yip)
{
TFILE *tfp;
int rval, r, psize;
char *tmppkt;
ulong dataddr;
char *fname, *basename, *s1, *fsize;
rval = 0;
yip->filecnt = 0;
tmppkt = pktbuff;
dataddr = yip->baseaddr;
do {
yip->dataddr[yip->filecnt] = dataddr;
yip->size[yip->filecnt] = 0;
yip->pktcnt[yip->filecnt] = 0;
yip->errcnt[yip->filecnt] = 0;
yip->firsterrat[yip->filecnt] = 0;
/*
* receive and parse the header-block
*/
r = waitPacket(tmppkt, &psize, 0, 1);
if ( r < 0 ) {
rval = r;
break;
}
/* first comes the file-name */
fname = (char *)(tmppkt);
/* buggy ymodems delimit fields with SP instead of NULL.
Cope. */
s1 = strchr(fname,' ');
if (s1) *s1 = '\0';
/* if file-name contains path, cut it off and just keep
the stem */
basename = strrchr(fname,'/');
if (! basename) basename = fname;
/* after the file-name comes the file-size */
fsize = basename + strlen(basename) + 1;
/* buggy ymodems delimit fields with SP instead of NULL.
cope. */
s1 = strchr(fsize,' ');
if (s1) *s1 = '\0';
/* copy info to xip fields */
yip->size[yip->filecnt] = atoi(fsize);
strcpy(yip->fname[yip->filecnt], basename);
Mtrace("<f=%s>",yip->fname[yip->filecnt]);
Mtrace("<z=%d>",yip->size[yip->filecnt]);
Mtrace("]");
if ( ! yip->fname[yip->filecnt][0] )
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -