📄 tftpdl.c
字号:
#include <target/io.h>#include <target/herrno.h>#include <target/flash.h>#include "mmu.h"#include "memregions.h"#include "board.h"#include "tftpdl.h"#include <target/net/eth.h>#include <target/net/tftp.h>#include <target/net/eth_util.h>#include "eth_smsc911x.h"#define DOWNLOAD_FILE_BUFFER_ADDR (0x81000000)#define TFTP_RETRY (3)#if defined(DEBUG_TFTPDL)#define DEBUG_INFO(args...) hprintf(args)#else#define DEBUG_INFO(args...)#endif/**************************************************************************** * ****************************************************************************/static intprogram_file(dl_file_t *dl_file){ u32 dst, src; u32 programed = 0; int size; int block; int ret; int i; hprintf("programing: %s\n", dl_file->region); DEBUG_INFO(" flash_addr: %p\n", dl_file->flash_addr); DEBUG_INFO(" file_name: %s\n", dl_file->file); DEBUG_INFO(" file_size: %p\n", dl_file->file_size); DEBUG_INFO(" ram_addr: %p\n", dl_file->ram_addr); block = flash_addr_to_eraseblock(dl_file->flash_addr); if (dl_file->flash_addr != flash_get_eraseblock_addr(block)) return -1; dst = dl_file->flash_addr; src = dl_file->ram_addr; while (programed < dl_file->file_size) { hprintf("#"); size = flash_get_eraseblock_size(block); if (programed + size > dl_file->file_size) { int padding; u8 *buf; size = dl_file->file_size - programed; padding = ((size % 4) ? (4 - (size % 4)) : 0); buf = (u8 *)(dl_file->ram_addr + dl_file->file_size); for (i=0; i<padding; i++) *buf++ = 0xff; size += padding; } DEBUG_INFO("ERASE: %p\n", dst); DEBUG_INFO("PROGRAM: ram(%p) -- size(%p) -> flash(%p)\n", src, size, dst); ret = flash_erase(dst); if (ret != 0) { hprintf("\nerase error\n"); return ret; } ret = flash_program(src, dst, size); if (ret != 0) { hprintf("\nprogram error\n"); return ret; } programed += size; src += size; dst += size; block++; } hprintf("\n\n"); return 0;}/**************************************************************************** * ****************************************************************************/static intprogram_download_file(app_opt_info_t *info){ int i; int ret; for (i=0; i<MAX_REGION_NUM; i++) { if (info->dl_file[i].file) { ret = program_file(&info->dl_file[i]); if (ret < 0) return ret; } } hprintf("completed!!\n\n"); return 0;}/**************************************************************************** * ****************************************************************************/static intdownload_using_tftp(app_opt_info_t *info){ u32 ram_addr = DOWNLOAD_FILE_BUFFER_ADDR; int retry; int ret; int i; for (i=0; i<MAX_REGION_NUM; i++) { if (info->dl_file[i].file) { retry = TFTP_RETRY; while (retry-- > 0) { ret = tftp_get(info->server_ipaddr, info->dl_file[i].file, &info->dl_file[i].file_size, (void *)ram_addr, info->dl_file[i].flash_size); switch (ret) { case -1:/* Common Error */ if (retry > 0) { hprintf("retry: \n"); smsc911x_eth_init(info->client_ipaddr); continue; } return -H_EIO; case -2:/* TFTP Error */ return -H_EIO; default: break; } break; } if (info->dl_file[i].file_size > info->dl_file[i].flash_size) { hprintf("too large filesize\n"); return -H_EIO; } info->dl_file[i].ram_addr = ram_addr; ram_addr += info->dl_file[i].flash_size; } } return 0;}/**************************************************************************** * ****************************************************************************/static voidinitialize_region_info(app_opt_info_t *info){ int i; int index = 0; for (i=0; i<MAX_REGION_NUM; i++) { if (regions[i].type == MAP_TYPE_FLASH) { int name_len = safe_strlen(regions[i].name); int ptr = 0; info->dl_file[index].label[ptr++] = '-'; info->dl_file[index].label[ptr++] = '-'; safe_memcpy(&info->dl_file[index].label[ptr], regions[i].name, name_len); ptr += name_len; info->dl_file[index].label[ptr++] = '='; info->dl_file[index].label[ptr++] = 0; /*NULL*/ info->dl_file[index].region = regions[i].name; info->dl_file[index].flash_addr = regions[i].start; info->dl_file[index].flash_size = regions[i].size; index++; } }#if defined(DEBUG_TFTPDL) for (i=0; i<MAX_REGION_NUM; i++) if (info->dl_file[i].label[0]) { DEBUG_INFO("label: %s\n", info->dl_file[i].label); DEBUG_INCO(" start: %p\n", info->dl_file[i].flash_addr); DEBUG_INFO(" size: %p\n", info->dl_file[i].flash_size); }#endif}/**************************************************************************** * ****************************************************************************/static intcheck_region_label(app_opt_info_t *info, char *label){ int i; for (i=0; info->dl_file[i].label[0]; i++) if (safe_strncmp(label, info->dl_file[i].label, safe_strlen(info->dl_file[i].label)) == 0) return i; return -1;}/**************************************************************************** * ****************************************************************************/static int parse_ipaddr(const char *str, unsigned char *ipaddr){ unsigned int num; int i,j; int ptr; for (i=0, ptr=0; i<4; i++) { for (j=0, num=0; j<4; j++, ptr++) { if (str[ptr] == 0) { if (i < 3) return -1; break; } switch (str[ptr]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if(j > 2) return -1; num = (num * 10) + (str[ptr] - '0'); break; case '.': j = 4; break; default: return -1; } } if (num >= 255) return -1; ipaddr[i] = (unsigned char)num; } if (str[ptr] != 0) return -1; return 0;}/**************************************************************************** * ****************************************************************************/static int option_detect(int argc, char *argv[], app_opt_info_t *info){ int i; int ret; for (i=1; i<argc; i++) if (safe_strncmp("--help", argv[i], 7) == 0) return -1; if(argc < 3) return -1; ret = parse_ipaddr(argv[1], info->client_ipaddr); if(ret == -1){ hprintf("unknown ipaddr: %s\n", argv[1]); return -1; } ret = parse_ipaddr(argv[2], info->server_ipaddr); if(ret == -1){ hprintf("unknown ipaddr: %s\n", argv[2]); return -1; } initialize_region_info(info); for (i=3; i<argc; i++) { if (safe_strncmp(argv[i], "--fake", 7) == 0) { info->fake = 1; continue; } ret = check_region_label(info, argv[i]); if (ret == -1) hprintf("unknown option: %s\n", argv[i]); info->dl_file[ret].file = &argv[i][safe_strlen(info->dl_file[ret].label)]; } return 0;}/**************************************************************************** * ****************************************************************************/static voidtftpdl_usage(void){ hprintf("Usage: tftpdl [Client-IPaddr] [Server-IPaddr] [option]\n"); hprintf("\n"); hprintf(" to download from server using TFTP, " "and to program on flash-memory.\n"); hprintf("\n"); hprintf("option:\n"); hprintf(" --help : display this message\n"); hprintf(" --fake : only download from server\n"); hprintf(" --(region)=[file] : e.g. --kernel=linux.bin.gz\n"); hprintf("\n");}/**************************************************************************** * ****************************************************************************/static inttftpdl_cmdfunc(int argc, char *argv[]){ app_opt_info_t info; int ret; int i; led_on(); safe_memset(&info, 0, sizeof(app_opt_info_t)); ret = option_detect(argc, argv, &info); if (ret == -1) { tftpdl_usage(); return 0; } hprintf("\n"); hprintf("Client: "); print_ip(info.client_ipaddr); hprintf("Server: "); print_ip(info.server_ipaddr); if (info.fake) hprintf("Fake Mode: %s\n", "Enable"); for (i=0; i<MAX_REGION_NUM; i++) if (info.dl_file[i].file) hprintf("Region(%s): %s\n", info.dl_file[i].region, info.dl_file[i].file); hprintf("\n"); hprintf("initializing net-device..."); ret = smsc911x_eth_init(info.client_ipaddr); if (ret == -1){ hprintf("NG\n"); led_off(); return -H_EIO; } hprintf("OK\n"); boost_on(BOOST_ETH_MODE); ret = download_using_tftp(&info); if (ret) { boost_off(); return ret; } if (!info.fake) ret = program_download_file(&info); boost_off(); led_off(); return ret;}/**************************************************************************** * ****************************************************************************/const command_t tftpdl_command = { "tftpdl", "--help", "flash programer using tftp", &tftpdl_cmdfunc };COMMAND(tftpdl_command);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -