⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tftpdl.c

📁 Hermit-at-1.1.3,一款bootloader
💻 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 + -