tftp.c
来自「ADS下的bios工程」· C语言 代码 · 共 192 行
C
192 行
#include <bios/netdev.h>#include <bios/boot.h>#include <bios/string.h>#include <bios/time.h>#include <bios/stdio.h>#include <bios/config.h> #undef DEBUG_S3C4_TFTP#ifdef DEBUG_S3C4_TFTP #define DEBUG_TFTP(fmt, args...) printf("%s-%s()[%d]: " fmt, __FILE__, __FUNCTION__, __LINE__, args)#else #define DEBUG_TFTP(fmt, args...)#endif/* extern functions */extern int udp_send(struct netdev *nd, struct sin *from, struct sin *to, struct buflist *data);extern int udp_recv(struct netdev *nd, struct sin *from, struct sin *to,void *buffer, int size);extern u32 bios_recv_bytes;/* global variables */static struct sin tftp_me, tftp_serv;/* function proto types */int do_tftp(struct netdev *dev);static int tftp_send_rrq(struct netdev *dev){ static struct tftp_rrq rrq; static struct buflist bl; tftp_me.sin_addr = dev->ip_addr; tftp_me.sin_port = htons(0x8000); tftp_serv.sin_addr = dev->serv_ip_addr; tftp_serv.sin_port = htons(0x45); memzero(&rrq, sizeof(rrq)); rrq.cmd = htons(TFTP_RRQ); sprintf(rrq.filename, "%s%c%s", dev->boot_file, 0, "octet"); bl.data = &rrq; bl.size = 102; bl.next = NULL; return udp_send(dev, &tftp_me, &tftp_serv, &bl);}static int tftp_send_ack(struct netdev *dev, int *block){ static struct tftp_ack ack; static struct buflist bl; ack.cmd = htons(TFTP_ACK); ack.block = htons(*block); bl.data = &ack; bl.size = 102; bl.next = NULL; return udp_send(dev, &tftp_me, &tftp_serv, &bl);}static int tftp_recv_data(struct netdev *dev, int *block, void *buffer){ static struct tftp_data data; static int recvd_block; /* 2001-2-24 */ int bytes; if (*block == 1) tftp_serv.sin_port = 0; DEBUG_TFTP("\n%s", "->"); bytes = udp_recv(dev, &tftp_serv, &tftp_me, &data, sizeof(data)); DEBUG_TFTP("BYTES(%d)\n", bytes); if (!bytes) return 0; if (data.cmd != htons(TFTP_DATA)) { printf("TFTP_ERROR: %x\n",data.cmd); if(data.cmd == htons(TFTP_ERROR)) { printf("TFTP_ERROR: %x\n",data.cmd); } return 0; } recvd_block = htons(data.block); if (recvd_block <= *block) { DEBUG_TFTP("RECV BLOCK(%d)<=BLOCK(%d)\n", recvd_block, *block); *block = recvd_block; /* 2001-2-24 */ tftp_send_ack(dev, &recvd_block); /* 2001-2-24 */ } if (recvd_block != *block) /* Need Check 2001-2-24 */ return 0; DEBUG_TFTP("TFTP PKT RECV OK(BLOCK = %d)\n", recvd_block); memcpy(buffer, data.data, bytes - 4); return bytes - 4;}#define TWIDDLE_IDX(x) (((x) >> 16) & 3)#define TWIDDLE_UPDATE(x) (((x) & 0xffff) == 0)int do_tftp(struct netdev *dev){ static const char twiddle[] = { '|', '/', '-', '\\' }; static unsigned char *data; static int block; int targ, error, bytes; int timeout; int retries; int total_bytes; block = 1; bytes = 0; timeout = CONF_TIMEOUT_MAJOR_BASE; retries = CONF_RETRIES; total_bytes = 0; data = (unsigned char *)load_addr; printf("\nTFTP Boot image(%s) loading at 0x%x...",dev->boot_file, (int)load_addr); do { if (block == 1) { error = tftp_send_rrq(dev); if(error) printf("tftp_send_rrq_error\n"); } else { error = tftp_send_ack(dev, &block); if(error) printf("tftp_send_ack_error\n"); } if (error) break; targ = centisecs + timeout; while (centisecs < targ) { bytes = tftp_recv_data(dev, &block, data + total_bytes); DEBUG_TFTP("RECVD BYTES(%d),BLOCK = %d\n", bytes, block); //printf("7"); if (bytes) { retries = CONF_RETRIES; timeout = CONF_TIMEOUT_MINOR_BASE; targ = centisecs + timeout; if (TWIDDLE_UPDATE(total_bytes)) printf("%c\010", twiddle[TWIDDLE_IDX(total_bytes)]); total_bytes += bytes; if (bytes == 512) block ++; else break; } } if (timeout == CONF_TIMEOUT_MINOR_BASE) timeout = CONF_TIMEOUT_MAJOR_BASE; if (bytes) break; if (!--retries) { printf("\010 timed out "); error = 1; break; } timeout = timeout * CONF_TIMEOUT_MULT; if (timeout > CONF_TIMEOUT_MAX) timeout = CONF_TIMEOUT_MAX; } while (1); if (error) { printf("\010 Error\n"); return 1; } printf("\010 %d Bytes \n", total_bytes); bios_recv_bytes = total_bytes; return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?