📄 ry.c
字号:
/* * Receive file with YMODEM file transfer protocol * * Note: This code uses 8 bit checksum which may not be compatible with * some programs claiming to support YMODEM transfers. * * 1999/11/24 Nicolas Pitre <nico@cam.org>: * Integrated into EBSA285's BIOS for ARM Linux. * */#include <bios/stdio.h>#include <bios/string.h>#include <bios/time.h>#include <bios/timer.h>#include <bios/boot.h>#include <bios/bootdev.h>#define SERBASE 0x42000160#define OK 0#define ERROR (-1)#define FALSE 0#define TRUE 1#define CAN ('X'&037)#define SOH 1#define STX 2#define EOT 4#define ACK 6#define NAK 025#define TIMEOUT (-2)#define RETRYMAX 15#define WCEOT (-10)static long Bytesleft;static int Blklen;static char secbuf[1024];static unsigned long *pout;static void tx( int c ){ while (*((volatile int *)(SERBASE + 0x18)) & (1<<5)); *((volatile int *)(SERBASE)) = c;}static int rx(int timeout){ int c; unsigned int expire = centisecs + timeout * 100; while( centisecs <= expire ){ if ( ! (*((volatile int *)(SERBASE + 0x18)) & (1<<4)) ) { c = *((volatile int *)(SERBASE)); return c & 0xff; } } return TIMEOUT;}static inline void putsec (char *p, int n){ n += 3; n >>= 2; while( n-- ) *pout++ = *((unsigned long *)p)++;}static int procheader (char *name){ register char *p; Bytesleft = 0x7fffffff; p = name + 1 + strnlen (name, 128); if (*p) Bytesleft = atol(p); return OK;}static int wcgetsec (char *rxbuf){ register int checksum, wcj, firstch; register char *p; int sectcurr, errors; for (errors = 0; errors < RETRYMAX; errors++) { if ((firstch = rx(5)) == STX) { Blklen = 1024; goto get2; } if (firstch == SOH) { Blklen = 128; get2: sectcurr = rx(2); checksum = 0; if ((sectcurr + (rx(2))) == 0377) { for (p = rxbuf, wcj = Blklen; --wcj >= 0;) { if ((firstch = rx(2)) < 0) goto bilge; checksum += (*p++ = firstch); } if ((firstch = rx(2)) < 0) goto bilge; if (((checksum - firstch) & 0377) == 0) return sectcurr; } } else if (firstch == EOT) return WCEOT; else if (firstch == CAN) return ERROR; bilge: while (rx(2) != TIMEOUT); tx(NAK); } return ERROR;}static int wcrxpn (char *rpn){ register int c; et_tu: tx(NAK); while ((c = wcgetsec (rpn)) != 0) { if (c == WCEOT) { tx(ACK); rx(2); goto et_tu; } return ERROR; } tx(ACK); return OK;}static int wcrx (){ register int sectnum, sectcurr, sendchar, cblklen; sectnum = 0; sendchar = NAK; for (;;) { tx(sendchar); sectcurr = wcgetsec (secbuf); if (sectcurr == ((sectnum + 1) & 0377)) { sectnum++; cblklen = Bytesleft > Blklen ? Blklen : Bytesleft; putsec (secbuf, cblklen); if ((Bytesleft -= cblklen) < 0) Bytesleft = 0; sendchar = ACK; } else if (sectcurr == (sectnum & 0377)) sendchar = ACK; else if (sectcurr == WCEOT) { tx(ACK); return OK; } else if (sectcurr == ERROR) return ERROR; else return ERROR; }}static int wcreceive (){ for (;;) { if (wcrxpn (secbuf) == ERROR) break; if (secbuf[0] == 0) return OK; if (procheader (secbuf) == ERROR || wcrx () == ERROR) break; } return ERROR;}static int serial_load( void ){ int res; printf( "\nNow send file with y-modem (^X to abort) ...\n" ); pout = (unsigned long *)load_addr; res = wcreceive(); wait_cs( 50 ); printf( "\nTransfer %s, press any key.\n", (res == OK) ? "complete" : "failed" ); getc(); return res;}static int serial_dummy( void ){ return 0;}struct bootdev boot_serial = { "serial", serial_dummy, serial_dummy, serial_load, serial_dummy};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -