diff options
| -rw-r--r-- | lib/lwip/lwip/src/apps/tftp/tftp.c | 51 | ||||
| -rw-r--r-- | lib/lwip/lwip/src/include/lwip/apps/tftp_client.h | 1 | ||||
| -rw-r--r-- | net/lwip/tftp.c | 35 |
3 files changed, 74 insertions, 13 deletions
diff --git a/lib/lwip/lwip/src/apps/tftp/tftp.c b/lib/lwip/lwip/src/apps/tftp/tftp.c index 25da952e925..e73bea20e63 100644 --- a/lib/lwip/lwip/src/apps/tftp/tftp.c +++ b/lib/lwip/lwip/src/apps/tftp/tftp.c @@ -98,6 +98,7 @@ struct tftp_state { int last_pkt; u16_t blknum; u16_t blksize; + u32_t tsize; u8_t retries; u8_t mode_write; u8_t tftp_mode; @@ -167,6 +168,7 @@ send_request(const ip_addr_t *addr, u16_t port, u16_t opcode, const char* fname, { size_t fname_length = strlen(fname)+1; size_t mode_length = strlen(mode)+1; + size_t tsize_length = strlen("tsize")+3; /* "tsize\0\0\0" */ size_t blksize_length = 0; int blksize = tftp_state.blksize; struct pbuf* p; @@ -182,7 +184,7 @@ send_request(const ip_addr_t *addr, u16_t port, u16_t opcode, const char* fname, } } - p = init_packet(opcode, 0, fname_length + mode_length + blksize_length - 2); + p = init_packet(opcode, 0, fname_length + mode_length + blksize_length + tsize_length - 2); if (p == NULL) { return ERR_MEM; } @@ -190,8 +192,9 @@ send_request(const ip_addr_t *addr, u16_t port, u16_t opcode, const char* fname, payload = (char*) p->payload; MEMCPY(payload+2, fname, fname_length); MEMCPY(payload+2+fname_length, mode, mode_length); + sprintf(payload+2+fname_length+mode_length, "tsize%c%u%c", 0, 0, 0); if (tftp_state.blksize) - sprintf(payload+2+fname_length+mode_length, "blksize%c%d", 0, tftp_state.blksize); + sprintf(payload+2+fname_length+mode_length+tsize_length, "blksize%c%d", 0, tftp_state.blksize); tftp_state.wait_oack = true; ret = udp_sendto(tftp_state.upcb, p, addr, port); @@ -450,14 +453,24 @@ tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr } blknum = lwip_ntohs(sbuf[1]); - if (tftp_state.blksize && tftp_state.wait_oack) { + if (tftp_state.wait_oack) { /* - * Data received while we are expecting an OACK for our blksize option. + * Data received while we are expecting an OACK for our tsize option. * This means the server doesn't support it, let's switch back to the * default block size. */ - tftp_state.blksize = 0; - tftp_state.wait_oack = false; + tftp_state.tsize = 0; + tftp_state.wait_oack = false; + + if (tftp_state.blksize) { + /* + * Data received while we are expecting an OACK for our blksize option. + * This means the server doesn't support it, let's switch back to the + * default block size. + */ + tftp_state.blksize = 0; + tftp_state.wait_oack = false; + } } if (blknum == tftp_state.blknum) { pbuf_remove_header(p, TFTP_HEADER_LENGTH); @@ -527,21 +540,31 @@ tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr } break; case PP_HTONS(TFTP_OACK): { - const char *optval = find_option(p, "blksize"); + const char *blksizeoptval = find_option(p, "blksize"); + const char *tsizeoptval = find_option(p, "tsize"); u16_t srv_blksize = 0; + u32_t srv_tsize = 0; tftp_state.wait_oack = false; - if (optval) { + if (blksizeoptval) { if (!tftp_state.blksize) { /* We did not request this option */ send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "blksize unexpected"); } - srv_blksize = atoi(optval); + srv_blksize = atoi(blksizeoptval); if (srv_blksize <= 0 || srv_blksize > tftp_state.blksize) { send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Invalid blksize"); } LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: accepting blksize=%d\n", srv_blksize)); tftp_state.blksize = srv_blksize; } + if (tsizeoptval) { + srv_tsize = atoi(tsizeoptval); + if (srv_tsize <= 0) { + srv_tsize = 0; /* tsize is optional */ + } + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: accepting tsize=%d\n", srv_tsize)); + tftp_state.tsize = srv_tsize; + } send_ack(addr, port, 0); break; } @@ -656,6 +679,16 @@ tftp_init_client(const struct tftp_context *ctx) } /** @ingroup tftp + * Get the transfer size used by the TFTP client. The server may + * report zero in case this is unsupported. + */ +u32_t +tftp_client_get_tsize(void) +{ + return tftp_state.tsize; +} + +/** @ingroup tftp * Set the block size to be used by the TFTP client. The server may choose to * accept a lower value. * @param blksize Block size in bytes diff --git a/lib/lwip/lwip/src/include/lwip/apps/tftp_client.h b/lib/lwip/lwip/src/include/lwip/apps/tftp_client.h index e1e21d06b67..78de50f4924 100644 --- a/lib/lwip/lwip/src/include/lwip/apps/tftp_client.h +++ b/lib/lwip/lwip/src/include/lwip/apps/tftp_client.h @@ -45,6 +45,7 @@ enum tftp_transfer_mode { err_t tftp_init_client(const struct tftp_context* ctx); void tftp_client_set_blksize(u16_t blksize); +u32_t tftp_client_get_tsize(void); err_t tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode); err_t tftp_put(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode); diff --git a/net/lwip/tftp.c b/net/lwip/tftp.c index 86516e66273..5c3becc68c6 100644 --- a/net/lwip/tftp.c +++ b/net/lwip/tftp.c @@ -31,6 +31,7 @@ struct tftp_ctx { ulong daddr; ulong size; ulong block_count; + ulong hash_count; ulong start_time; enum done_state done; }; @@ -49,6 +50,8 @@ struct tftp_ctx { static int store_block(struct tftp_ctx *ctx, void *src, u16_t len) { ulong store_addr = ctx->daddr; + ulong tftp_tsize; + ulong pos; void *ptr; if (CONFIG_IS_ENABLED(LMB)) { @@ -67,10 +70,21 @@ static int store_block(struct tftp_ctx *ctx, void *src, u16_t len) ctx->daddr += len; ctx->size += len; ctx->block_count++; - if (ctx->block_count % 10 == 0) { - putc('#'); - if (ctx->block_count % (65 * 10) == 0) - puts("\n\t "); + + tftp_tsize = tftp_client_get_tsize(); + if (tftp_tsize) { + pos = clamp(ctx->size, 0UL, tftp_tsize); + + while (ctx->hash_count < pos * 50 / tftp_tsize) { + putc('#'); + ctx->hash_count++; + } + } else { + if (ctx->block_count % 10 == 0) { + putc('#'); + if (ctx->block_count % (65 * 10) == 0) + puts("\n\t "); + } } return 0; @@ -84,6 +98,7 @@ static void *tftp_open(const char *fname, const char *mode, u8_t is_write) static void tftp_close(void *handle) { struct tftp_ctx *ctx = handle; + ulong tftp_tsize; ulong elapsed; if (ctx->done == FAILURE || ctx->done == ABORTED) { @@ -92,6 +107,17 @@ static void tftp_close(void *handle) } ctx->done = SUCCESS; + tftp_tsize = tftp_client_get_tsize(); + if (tftp_tsize) { + /* Print hash marks for the last packet received */ + while (ctx->hash_count < 49) { + putc('#'); + ctx->hash_count++; + } + puts(" "); + print_size(tftp_tsize, ""); + } + elapsed = get_timer(ctx->start_time); if (elapsed > 0) { puts("\n\t "); /* Line up with "Loading: " */ @@ -176,6 +202,7 @@ static int tftp_loop(struct udevice *udev, ulong addr, char *fname, ctx.done = NOT_DONE; ctx.size = 0; ctx.block_count = 0; + ctx.hash_count = 0; ctx.daddr = addr; printf("Using %s device\n", udev->name); |
