📄 xmodem.c
字号:
#include <stdio.h>#include <setup.h>#include <time.h>#include <command.h>#include <string.h>#include "types.h"#define SOH 0x01#define STX 0x02#define EOT 0x04#define ACK 0x06#define NAK 0x15#define CAN 0x18#define BS 0x08#define report(fmt, args...) printf(fmt, ##args)#define assert(fmt, args...) //printf(fmt, ##args)#define failed(fmt, args...) //printf(fmt, ##args)static int xmodem_recv(void *addr, uint size);static void *recv_block(void *buff, int size);static bool ignore_data(int size);static uint16 xmodem_crc(void *addr, int len);extern int uart_getb(void);extern int uart_putb(int ch);static inline int xmodem_getb(int timeout){ int ch; clock_t end; end = clock() + CLOCKS_PER_SEC * timeout; while (clock() < end){ ch = uart_getb(); if (ch >= 0) return ch; } return -1;}static inline int xmodem_putb(int ch){ return uart_putb(ch);}static void xmodem_usage(void){ usage_format("xmodem {loader/kernel/ramdisk/root}", "receive file with xmodem"); usage_format("xmodem address", "receive file with xmodem"); return;}static bool do_xmodem(int argc, char **argv){ int received; ulong maxsize=0, tmp; void *addr; struct map *mp; if (argc != 2) goto invalid; mp = find_map(argv[1]); if (mp){ addr = (void *)mp->dramb; maxsize = mp->maxs; } else if (strtoul(argv[1], &tmp, 16)){ addr = (void *)tmp; maxsize = -1; } else goto invalid; received = xmodem_recv(addr, maxsize); report("\r \r"); report("\r \r"); if (!received) report(" xmodem : failed. not received.\n"); else if (received > maxsize) report(" xmodem : failed. file size is too big.\n"); else if (received) report(" xmodem : %d (0x%08X) bytes received.\n", received, received); if (mp) mp->drams = received; if (!received || received > maxsize) return false; return true;invalid : xmodem_usage(); return false;}struct command_t cmd_xmodem = { .name = "xmodem", .run = do_xmodem, .usage = xmodem_usage};static int xmodem_recv(void *addr, uint maxsize){ int ch; int received; int retry; uchar buff[1024], *dest=addr, *s; int blksize=0; int blknum1, blknum2, lastblk;// uint8 blknum1, blknum2, lastblk; uint16 crc1, crc2, crcu, crcl; received = 0; lastblk = 0; retry = 20; while (retry > 0){ if (!received) xmodem_putb('C'); ch = xmodem_getb(1); if (ch < 0){ retry--; continue; } retry = 1; if (ch == SOH){ blksize = 128; } else if (ch == STX){ blksize = 1024; } else if (ch == EOT){ xmodem_putb(ACK); break; } else return 0; blknum1 = xmodem_getb(1); if (blknum1 < 0) break; blknum2 = xmodem_getb(1); if (blknum2 < 0) break; if (blknum1 != (uint8)~blknum2) goto cancel; if (blknum1 == (uint8)lastblk){ ignore_data(blksize + 2); xmodem_putb(ACK); continue; } if (blknum1 != (uint8)(lastblk + 1)) goto cancel; lastblk++; recv_block(buff, blksize); if (maxsize - blksize < 0) goto cancel; memcpy(dest, buff, blksize); dest += blksize; maxsize -= blksize; received += blksize; crc1 = xmodem_crc(buff, blksize); crcu = xmodem_getb(1); crcl = xmodem_getb(1); crc2 = (crcu << 8) | crcl; ch = (crc1 == crc2) ? ACK : NAK; xmodem_putb(ch); } s = (uchar *)addr + received - 1; /* remove pad (0x1A) */ while (*s == 0x1A) s--; return s - (uchar *)addr + 1;cancel : xmodem_putb(CAN); while (xmodem_getb(1) >= 0); return 0;}static bool ignore_data(int size){ int ch; while (size--){ ch = xmodem_getb(1); if (ch < 0) return false; } return true;}static void *recv_block(void *buff, int size){ int ch; uchar *s = buff; while (size-- > 0){ ch = xmodem_getb(1); if (ch < 0) return 0; *s++ = ch; } return buff;}static uint16 xmodem_crc(void *addr, int len){ int i; uint16 crc; uchar *s = addr; crc = 0; while (len-- > 0){ crc = crc ^ ((int)*s++ << 8); for (i=0; i < 8; i++) crc = (crc & 0x8000) ? crc << 1 ^ 0x1021 : crc << 1; } return crc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -