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

📄 netflash.c

📁 通过网络刷新flash的工具源代码.linux下使用的
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************//* * netflash.c:  network FLASH loader. * * Copyright (C) 1999-2001,  Greg Ungerer (gerg@snapgear.com) * Copyright (C) 2000-2001,  Lineo (www.lineo.com) * Copyright (C) 2000-2002,  SnapGear (www.snapgear.com) * * Copied and hacked from rootloader.c which was: * * Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>, * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *//****************************************************************************/#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <string.h>#include <assert.h>#include <ctype.h>#include <getopt.h>#include <errno.h>#include <unistd.h>#include <dirent.h>#include <signal.h>#include <sys/types.h>#include <sys/sysmacros.h>#include <sys/syscall.h>#include <sys/stat.h>#include <sys/mount.h>#include <sys/termios.h>#include <sys/socket.h>#include <sys/wait.h>#include <netinet/in.h>#include <stdarg.h>#include <linux/autoconf.h>#include <linux/version.h>#include <config/autoconf.h>#include <linux/major.h>#ifdef CONFIG_USER_NETFLASH_CRYPTO#include <openssl/bio.h>#include "crypto.h"#endif#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULES)#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)#include <mtd/mtd-user.h>#define MTD_CHAR_MAJOR 90#define MTD_BLOCK_MAJOR 31#else #include <linux/mtd/mtd.h>#endif#else#include <linux/blkmem.h>#endif#ifdef CONFIG_LEDMAN#include <linux/ledman.h>#endif#ifdef CONFIG_USER_NETFLASH_DECOMPRESS#include <zlib.h>#endif#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULES)#include <linux/jffs2.h>#endif#if defined(CONFIG_NFTL_RW) && !defined(NFTL_MAJOR) #define NFTL_MAJOR 93#endif#ifdef CONFIG_IDE#include <linux/hdreg.h>#endif#include <asm/byteorder.h>#include "netflash.h"#include "exit_codes.h"#include "versioning.h"/****************************************************************************/#ifdef CONFIG_USER_NETFLASH_HMACMD5#include "hmacmd5.h"#define HMACMD5_OPTIONS "m:"#else#define HMACMD5_OPTIONS#endif#ifdef CONFIG_USER_NETFLASH_DECOMPRESS#define DECOMPRESS_OPTIONS "z"#else#define DECOMPRESS_OPTIONS#endif /*CONFIG_USER_NETFLASH_DECOMPRESS*/#ifdef CONFIG_USER_NETFLASH_SETSRC#define SETSRC_OPTIONS "I:"#else#define SETSRC_OPTIONS#endif#define CMD_LINE_OPTIONS "bc:Cd:fFhiHjkKlno:pr:sStuv?" DECOMPRESS_OPTIONS HMACMD5_OPTIONS SETSRC_OPTIONS#define PID_DIR "/var/run"#define DHCPCD_PID_FILE "dhcpcd-"#define CHECKSUM_LENGTH	4#ifdef CONFIG_USER_BUSYBOX_WATCHDOGD#define CONFIG_USER_NETFLASH_WATCHDOG 1#endif/****************************************************************************/char *version = "2.1.4";int exitstatus = 0;struct fileblock_t *fileblocks = NULL;int fileblocks_num = 0;unsigned long file_offset = 0;unsigned long file_length = 0;unsigned long image_length = 0;unsigned int calc_checksum = 0;#define	BLOCK_OVERHEAD	16#define	block_len	(_block_len - BLOCK_OVERHEAD)int _block_len = 8192;int dothrow = 0;		/* Check version info of image; no program */int dolock, dounlock;	/* do we lock/unlock segments as we go */int checkimage;			/* Compare with current flash contents; no program */#if CONFIG_USER_NETFLASH_WATCHDOGint watchdog = 1;		/* tickle watchdog while writing to flash */int watchdog_fd = -1;   /* ensure this is initalised to an invalid fd */#endifint preserveconfig;		/* Preserve special bits of flash such as config fs */int preserve = 0;		/* Preserve and portions of flash not written to */int offset = 0;			/* Offset to start writing at */int stop_early = 0;		/* stop at end of input data, do not write full dev. */int nostop_early = 0;	/* no stop at end of input data, do write full dev. */int dojffs2;			/* Write the jffs2 magic to unused segments */#ifdef CONFIG_USER_NETFLASH_DECOMPRESSint doinflate;			/* Decompress the image */#endifint docgi = 0;			/* Read options and data from stdin in mime multipart format */#if defined(CONFIG_USER_NETFLASH_WITH_CGI) && !defined(RECOVER_PROGRAM)char cgi_data[64];      /* CGI section name for the image part */char cgi_options[64];   /* CGI section name for the command line options part */extern size_t cgi_load(const char *data_name, const char *options_name, char options[64]);#endifextern int tftpverbose;extern int ftpverbose;FILE	*nfd;#ifdef CONFIG_USER_NETFLASH_DECOMPRESSz_stream z;struct fileblock_t *zfb;static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */#endifstruct stat stat_rdev;#ifdef CONFIG_USER_NETFLASH_SETSRCchar	*srcaddr = NULL;#endifstatic void (* program_segment)(int rd, char *sgdata,		int sgpos, int sglength, int sgsize);static void exit_failed(int rc);/****************************************************************************/#define notice(a...) fprintf(stdout, "netflash: " a); fprintf(stdout, "\n"); fflush(stdout);#if defined(CONFIG_USER_NETFLASH_WITH_CGI) && !defined(RECOVER_PROGRAM)#define error(a...) fprintf(stdout, "netflash: " a); fprintf(stdout, "\n"); fflush(stdout);#else#define error(a...) fprintf(stderr, "netflash: " a); fprintf(stderr, "\n"); fflush(stderr);#endif/****************************************************************************/void restartinit(void){#if !defined(CONFIG_USER_NETFLASH_WITH_CGI) || defined(RECOVER_PROGRAM)	error("restarting init process...");#endif	kill(1, SIGCONT);#ifdef CONFIG_USER_NETFLASH_WATCHDOG	close(watchdog_fd);	system("watchdog /dev/watchdog");#endif}#ifdef CONFIG_USER_NETFLASH_CRYPTO#define memcpy_withsum(d, s, l, sum)	memcpy(d, s, l)#elsestatic void memcpy_withsum(void *dst, void *src, int len, unsigned int *sum){	unsigned char *dp = (unsigned char *)dst;	unsigned char *sp = (unsigned char *)src;	while(len > 0){		*dp = *sp;		*sum += *dp++;		sp++;		len--;	}}#endif/* *	Note: This routine is more general than it currently needs to *	be since it handles out of order writes. */void add_data(unsigned long address, unsigned char * data, unsigned long len){	int l;	struct fileblock_t *fb;	struct fileblock_t *fbprev = NULL;	struct fileblock_t *fbnew;	static unsigned long total = 0;	static unsigned lastk = 0;	/*printf("add_data(%lx:%lx)\n", address, len);*/	/* The fileblocks list is ordered, so initialise this outside	 * the while loop to save some search time. */	fb=fileblocks;	do {		/* Search for any blocks that overlap with the range we are adding */		for (; fb!=NULL; fbprev=fb, fb=fb->next) {			if (address < fb->pos)				break;						if (address < (fb->pos + fb->maxlength)) {				l = fb->maxlength - (address - fb->pos);				if (l > len)					l = len;				memcpy_withsum(fb->data + (address - fb->pos),					data, l, &calc_checksum);				fb->length = l + (address - fb->pos);								address += l;				data += l;				len -= l;				total += l;				if (len == 0)					return;			}		}			if (!docgi) {			if (total / 1024 != lastk) {				lastk = total / 1024;				printf("\r%dK", lastk); fflush(stdout);			}		}#ifdef CONFIG_USER_NETFLASH_WATCHDOG		if (watchdog)			write(watchdog_fd, "\0", 1); #endif		/* At this point:		 * fb = block following the range we are adding,		 *      or NULL if at end		 * fbprev = block preceding the range, or NULL if at start		 */#ifdef CONFIG_USER_NETFLASH_VERSION#ifndef CONFIG_USER_NETFLASH_CRYPTO		if (dothrow && fileblocks_num > 2) {			/* Steal the first block from the list. */			fbnew = fileblocks;			fileblocks = fbnew->next;			if (fbprev == fbnew)				fbprev = NULL;			fbnew->pos = address;			if (fb && ((fb->pos - address) < fbnew->maxlength))				fbnew->maxlength = fb->pos - address;		} else {#endif#endif /*CONFIG_USER_NETFLASH_VERSION*/			fbnew = malloc(sizeof(*fbnew));			if (!fbnew) {				error("Insufficient memory for image!");				exit_failed(NO_MEMORY);			}						fbnew->pos = address;			for (;;) {				if (fb && ((fb->pos - address) < block_len))					fbnew->maxlength = fb->pos - address;				else					fbnew->maxlength = block_len;							fbnew->data = malloc(fbnew->maxlength);				if (fbnew->data)					break;				/* Halve the block size and try again, down to 1 page */				if (_block_len < 4096) {					error("Insufficient memory for image!");					exit_failed(NO_MEMORY);				}				_block_len /= 2;			}			fileblocks_num++;#ifdef CONFIG_USER_NETFLASH_VERSION#ifndef CONFIG_USER_NETFLASH_CRYPTO		}#endif#endif		l = fbnew->maxlength;		if (l > len)			l = len;		memcpy_withsum(fbnew->data, data, l, &calc_checksum);		fbnew->length = l;		address += l;		data += l;		len -= l;				fbnew->next = fb;		if (fbprev)			fbprev->next = fbnew;		else			fileblocks = fbnew;		/* Next search starts after the block we just added */		fbprev = fbnew;	} while (len > 0);}/* *	Remove bytes from the end of the data. This is used to remove *	checksum/versioning data before writing or decompressing. */void remove_data(int length){	struct fileblock_t *fb;	struct fileblock_t *fbnext;	if (fileblocks != NULL && file_length >= length) {		file_length -= length;		for (fb = fileblocks; fb != NULL; fb = fb->next) {			if ((fb->pos + fb->length) >= file_length)				break;		}		fb->length = file_length - fb->pos;				while (fb->next != NULL) {			fbnext = fb->next;			fb->next = fbnext->next;			free(fbnext->data);			free(fbnext);		}	}}/* *	Generate a checksum over the data. */void chksum(){	unsigned char *sp = 0, *ep;	unsigned int file_checksum;	int i;	struct fileblock_t *fb;	file_checksum = 0;	if (fileblocks != NULL && file_length >= CHECKSUM_LENGTH) {#ifdef CONFIG_USER_NETFLASH_CRYPTO		/* No on the fly check sum so we have to calculate it all here */		for (fb = fileblocks; fb != NULL; fb = fb->next)			for (i=0; i<fb->length; i++)				calc_checksum += fb->data[i];#endif		for (fb = fileblocks; fb != NULL; fb = fb->next) {			if ((fb->pos + fb->length) >= (file_length - CHECKSUM_LENGTH)) {				sp = fb->data + (file_length - CHECKSUM_LENGTH - fb->pos);				break;			}		}		if (!fb) {			error("could not find fileblock containing checksum");			exit_failed(IMAGE_SHORT);		}				ep = fb->data + fb->length;		for (i = 0; i < CHECKSUM_LENGTH; i++) {			if (sp >= ep) {				fb = fb->next;				sp = fb->data;				ep = sp + fb->length;			}			file_checksum = (file_checksum << 8) | *sp;			calc_checksum -= *sp;			sp++;		}		remove_data(CHECKSUM_LENGTH);		calc_checksum = (calc_checksum & 0xffff) + (calc_checksum >> 16);		calc_checksum = (calc_checksum & 0xffff) + (calc_checksum >> 16);		if (calc_checksum != file_checksum) {			error("bad image checksum=0x%04x, expected checksum=0x%04x",					calc_checksum, file_checksum);			exit_failed(BAD_CHECKSUM);		}	} else {		error("image is too short to contain a checksum");		exit_failed(IMAGE_SHORT);	}}#ifdef CONFIG_USER_NETFLASH_HMACMD5int check_hmac_md5(char *key){	HMACMD5_CTX ctx;	int length, total;	unsigned char hash[16];	int i;	struct fileblock_t *fb;	if (fileblocks != NULL && file_length >= 16) {		HMACMD5Init(&ctx, key, strlen(key));		total = 0;		length = 0;		for (fb = fileblocks; fb != NULL; fb = fb->next) {			if (fb->length > (file_length - total - 16))				length = file_length - total - 16;			else				length = fb->length;			HMACMD5Update(&ctx, fb->data, length);			total += length;			if (length != fb->length)				break;		}		HMACMD5Final(hash, &ctx);		for (i=0; i<16; i++, length++) {			if (length>=fb->length) {				length = 0;				fb = fb->next;			}			if (hash[i] != fb->data[length]) {				error("bad HMAC MD5 signature");				exit_failed(BAD_HMAC_SIG);			}		}		notice("HMAC MD5 signature okay");		remove_data(16);    }}#endif#ifdef CONFIG_USER_NETFLASH_CRYPTO/* Extract bytes from end of the data. * These bytes are removed from the data. */static inline void extract_data(int length, char buf[]) {	unsigned long i, tpos;	struct fileblock_t *fb;	unsigned long target_length;	if (fileblocks != NULL && file_length >= length) {		target_length = file_length - length;		for (fb = fileblocks; fb != NULL; fb = fb->next) {			if ((fb->pos + fb->length) >= target_length)				break;		}		tpos = target_length - fb->pos;		for (i=0; i<length;) {			if (tpos >= fb->length) {				fb = fb->next;				tpos = 0;			}			buf[i++] = fb->data[tpos++];		}		remove_data(length);	} else {		error("insufficent data at end of image need %d only have %d",				length, (int)file_length);		exit_failed(IMAGE_SHORT);	}}/* Grab a block at the specified position.  This could span fileblock boundaries etc so * we pull it out piecemeal.  This could be written significantly more efficiently * I expect. */static inline void get_block(struct fileblock_t *fb,		unsigned long posn, char buf[], int sz) {	int i = 0;	unsigned long offset = posn - fb->pos;	while (i<sz) {		while (offset >= fb->length)			offset = 0, fb = fb->next;		buf[i++] = fb->data[offset++];	}}/* Write a block of information back into the file at the specified * position.  Again this isn't written overly efficiently. */static inline struct fileblock_t *put_block(struct fileblock_t *fb,		unsigned long posn, const char buf[], int sz) {	int i = 0;	unsigned long offset = posn - fb->pos;	while (i<sz) {		while (offset >= fb->length)			offset = 0, fb = fb->next;		fb->data[offset++] = buf[i++];	}	return fb;}/* Check the crypto signature on the image... * This always includes a public key encrypted header and an MD5 * checksum.  It optionally includes AES encryption of the image. */void check_crypto_signature(void) {	struct fileblock_t *fb;  	RSA *pkey;	struct header hdr;	struct little_header lhdr;		/* Load public key */	{		BIO *in;		struct stat st;		if (stat(PUBLIC_KEY_FILE, &st) == -1 && errno == ENOENT) {			printf("WARNING: no public key file found, %s\n",				PUBLIC_KEY_FILE);			return;		}		in = BIO_new(BIO_s_file());		if (in == NULL) {			error("cannot allocate a bio structure");			exit_failed(BAD_DECRYPT);		}		if (BIO_read_filename(in, PUBLIC_KEY_FILE) <= 0) {			error("cannot open public key file");			exit_failed(BAD_PUB_KEY);		}		pkey = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL);		if (pkey == NULL) {			error("cannot read public key");			exit_failed(BAD_PUB_KEY);		}	}	/* Decode header information */	extract_data(sizeof(struct little_header), (char *)&lhdr);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -