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

📄 mkmylofw.c

📁 Linux Home Server 是专门为家庭和SOHO/SMB 设计的高性价比的ISCSI 存储服务器, 具有如下的特色: 强大的iscsi 存储服务器软件; 混合iscsi 和NAS 服务;
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) 2006-2008 Gabor Juhos <juhosg@openwrt.org> * *  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. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *  Boston, MA  02110-1301, USA. * */#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <string.h>#include <unistd.h>     /* for unlink() */#include <libgen.h>#include <getopt.h>     /* for getopt() */#include <stdarg.h>#include <errno.h>#include <sys/stat.h>#include <endian.h>     /* for __BYTE_ORDER */#if defined(__CYGWIN__)#  include <byteswap.h>#endif#if (__BYTE_ORDER == __LITTLE_ENDIAN)#  define HOST_TO_LE16(x)	(x)#  define HOST_TO_LE32(x)	(x)#else#  define HOST_TO_LE16(x)	bswap_16(x)#  define HOST_TO_LE32(x)	bswap_32(x)#endif#include "myloader.h"#define MAX_FW_BLOCKS  	32#define MAX_ARG_COUNT   32#define MAX_ARG_LEN     1024#define FILE_BUF_LEN    (16*1024)struct fw_block {	uint32_t	addr;	uint32_t	blocklen; /* length of the block */	uint32_t	flags;	char		*name;  /* name of the file */	uint32_t	size;  	/* length of the file */	uint32_t	crc;    /* crc value of the file */};#define BLOCK_FLAG_HAVEHDR    0x0001struct cpx_board {	char		*model; /* model number*/	char		*name;	/* model name*/	char		*desc;  /* description */	uint16_t        vid;    /* vendor id */	uint16_t        did;    /* device id */	uint16_t        svid;   /* sub vendor id */	uint16_t        sdid;   /* sub device id */	uint32_t        flash_size;     /* size of flash */	uint32_t	part_offset;	/* offset of the partition_table */	uint32_t	part_size;	/* size of the partition_table */};#define BOARD(_vid, _did, _svid, _sdid, _flash, _mod, _name, _desc, _po, _ps) {		\	.model = _mod, .name = _name, .desc = _desc,   			\	.vid = _vid, .did = _did, .svid = _svid, .sdid = _sdid,         \	.flash_size = (_flash << 20),					\	.part_offset = _po, .part_size = _ps }#define CPX_BOARD(_did, _flash, _mod, _name, _desc, _po, _ps) \	BOARD(VENID_COMPEX, _did, VENID_COMPEX, _did, _flash, _mod, _name, _desc, _po, _ps)#define CPX_BOARD_ADM(_did, _flash, _mod, _name, _desc) \	CPX_BOARD(_did, _flash, _mod, _name, _desc, 0x10000, 0x10000)#define CPX_BOARD_AR71XX(_did, _flash, _mod, _name, _desc) \	CPX_BOARD(_did, _flash, _mod, _name, _desc, 0x20000, 0x8000)#define ALIGN(x,y)	((x)+((y)-1)) & ~((y)-1)char	*progname;char	*ofname = NULL;uint32_t flash_size = 0;int	fw_num_partitions = 0;int	fw_num_blocks = 0;int	verblevel = 0;struct mylo_fw_header fw_header;struct mylo_partition fw_partitions[MYLO_MAX_PARTITIONS];struct fw_block fw_blocks[MAX_FW_BLOCKS];struct cpx_board *board;struct cpx_board boards[] = {	CPX_BOARD_ADM(DEVID_COMPEX_NP18A, 4,		"NP18A", "Compex NetPassage 18A",		"Dualband Wireless A+G Internet Gateway"),	CPX_BOARD_ADM(DEVID_COMPEX_NP26G8M, 2,		"NP26G8M", "Compex NetPassage 26G (8M)",		"Wireless-G Broadband Multimedia Gateway"),	CPX_BOARD_ADM(DEVID_COMPEX_NP26G16M, 4,		"NP26G16M", "Compex NetPassage 26G (16M)",		"Wireless-G Broadband Multimedia Gateway"),	CPX_BOARD_ADM(DEVID_COMPEX_NP27G, 4,		"NP27G", "Compex NetPassage 27G",		"Wireless-G 54Mbps eXtended Range Router"),	CPX_BOARD_ADM(DEVID_COMPEX_NP28G, 4,		"NP28G", "Compex NetPassage 28G",		"Wireless 108Mbps Super-G XR Multimedia Router with 4 USB Ports"),	CPX_BOARD_ADM(DEVID_COMPEX_NP28GHS, 4,		"NP28GHS", "Compex NetPassage 28G (HotSpot)",		"HotSpot Solution"),	CPX_BOARD_ADM(DEVID_COMPEX_WP18, 4,		"WP18", "Compex NetPassage WP18",		"Wireless-G 54Mbps A+G Dualband Access Point"),	CPX_BOARD_ADM(DEVID_COMPEX_WP54G, 4,		"WP54G", "Compex WP54G",		"Wireless-G 54Mbps XR Access Point"),	CPX_BOARD_ADM(DEVID_COMPEX_WP54Gv1C, 2,		"WP54Gv1C", "Compex WP54G rev.1C",		"Wireless-G 54Mbps XR Access Point"),	CPX_BOARD_ADM(DEVID_COMPEX_WP54AG, 4,		"WP54AG", "Compex WP54AG",		"Wireless-AG 54Mbps XR Access Point"),	CPX_BOARD_ADM(DEVID_COMPEX_WPP54G, 4,		"WPP54G", "Compex WPP54G",		"Outdoor Access Point"),	CPX_BOARD_ADM(DEVID_COMPEX_WPP54AG, 4,		"WPP54AG", "Compex WPP54AG",		"Outdoor Access Point"),	CPX_BOARD_AR71XX(DEVID_COMPEX_WP543, 2,		"WP543", "Compex WP543",		"BareBoard"),	{.model = NULL}};voiderrmsgv(int syserr, const char *fmt, va_list arg_ptr){	int save = errno;	fflush(0);	fprintf(stderr, "[%s] Error: ", progname);	vfprintf(stderr, fmt, arg_ptr);	if (syserr != 0) {		fprintf(stderr, ": %s", strerror(save));	}	fprintf(stderr, "\n");}voiderrmsg(int syserr, const char *fmt, ...){	va_list arg_ptr;	va_start(arg_ptr, fmt);	errmsgv(syserr, fmt, arg_ptr);	va_end(arg_ptr);}voiddbgmsg(int level, const char *fmt, ...){	va_list arg_ptr;	if (verblevel >= level) {		fflush(0);		va_start(arg_ptr, fmt);		vfprintf(stderr, fmt, arg_ptr);		fprintf(stderr, "\n");		va_end(arg_ptr);	}}voidusage(int status){	FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;	struct cpx_board *board;	fprintf(stream, "Usage: %s [OPTION...] <file>\n", progname);	fprintf(stream,"\n""  <file>          write output to the <file>\n""\n""Options:\n""  -B <board>      create firmware for the board specified with <board>.\n""                  This option set vendor id, device id, subvendor id,\n""                  subdevice id, and flash size options to the right value.\n""                  valid <board> values:\n");	for (board = boards; board->model != NULL; board++){		fprintf(stream,"                      %-12s: %s\n",		 board->model, board->name);	};	fprintf(stream,"  -i <vid>:<did>[:<svid>[:<sdid>]]\n""                  create firmware for board with vendor id <vid>, device\n""                  id <did>, subvendor id <svid> and subdevice id <sdid>.\n""  -r <rev>        set board revision to <rev>.\n""  -s <size>       set flash size to <size>\n""  -b <addr>:<len>[:[<flags>]:<file>]\n""                  define block at <addr> with length of <len>.\n""                  valid <flag> values:\n""                      h : add crc header before the file data.\n""  -p <addr>:<len>[:<flags>[:<param>[:<file>]]]\n""                  add partition at <addr>, with size of <len> to the\n""                  partition table, set partition flags to <flags> and\n""                  partition parameter to <param>. If the <file> is specified\n""                  content of the file is also added to the firmware image.\n""                  valid <flag> values:\n""                      a:  this is the active partition. The bootloader loads\n""                          the firmware from this partition.\n""                      h:  the partition data have a header.\n""                      l:  the partition data uses LZMA compression.\n""                      p:  the bootloader loads data from this partition to\n""                          the RAM before decompress it.\n""  -h              show this screen\n"	);	exit(status);}/* * Code to compute the CRC-32 table. Borrowed from * gzip-1.0.3/makecrc.c. */static uint32_t crc_32_tab[256];voidinit_crc_table(void){	/* Not copyrighted 1990 Mark Adler	*/	uint32_t c;      /* crc shift register */	uint32_t e;      /* polynomial exclusive-or pattern */	int i;           /* counter for all possible eight bit values */	int k;           /* byte being shifted into crc apparatus */	/* terms of polynomial defining this crc (except x^32): */	static const int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};	/* Make exclusive-or pattern from polynomial */	e = 0;	for (i = 0; i < sizeof(p)/sizeof(int); i++)		e |= 1L << (31 - p[i]);	crc_32_tab[0] = 0;	for (i = 1; i < 256; i++) {		c = 0;		for (k = i | 256; k != 1; k >>= 1) {			c = c & 1 ? (c >> 1) ^ e : c >> 1;			if (k & 1)				c ^= e;		}		crc_32_tab[i] = c;	}}voidupdate_crc(uint8_t *p, uint32_t len, uint32_t *crc){	uint32_t t;	t = *crc ^ 0xFFFFFFFFUL;	while (len--) {		t = crc_32_tab[(t ^ *p++) & 0xff] ^ (t >> 8);	}	*crc = t ^ 0xFFFFFFFFUL;}uint32_tget_crc(uint8_t *p, uint32_t len){	uint32_t crc;	crc = 0;	update_crc(p ,len , &crc);	return crc;}intstr2u32(char *arg, uint32_t *val){	char *err = NULL;	uint32_t t;	errno=0;	t = strtoul(arg, &err, 0);	if (errno || (err==arg) || ((err != NULL) && *err)) {		return -1;	}	*val = t;	return 0;}intstr2u16(char *arg, uint16_t *val){	char *err = NULL;	uint32_t t;	errno=0;	t = strtoul(arg, &err, 0);	if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x10000)) {		return -1;	}	*val = t & 0xFFFF;	return 0;}struct cpx_board *find_board(char *model){	struct cpx_board *board;	struct cpx_board *tmp;	board = NULL;	for (tmp = boards; tmp->model != NULL; tmp++){		if (strcasecmp(model, tmp->model) == 0) {			board = tmp;			break;		}	};	return board;}intget_file_crc(struct fw_block *ff){	FILE *f;	uint8_t buf[FILE_BUF_LEN];	uint32_t readlen = sizeof(buf);	int res = -1;	size_t len;	if ((ff->flags & BLOCK_FLAG_HAVEHDR) == 0) {		res = 0;		goto out;	}	errno = 0;	f = fopen(ff->name,"r");	if (errno) {		errmsg(1,"unable to open file %s", ff->name);		goto out;	}	ff->crc = 0;	len = ff->size;	while (len > 0) {		if (len < readlen)			readlen = len;		errno = 0;		fread(buf, readlen, 1, f);		if (errno) {			errmsg(1,"unable to read from file %s",	ff->name);			goto out_close;		}		update_crc(buf, readlen, &ff->crc);		len -= readlen;	}	res = 0;out_close:	fclose(f);out:	return res;}intprocess_files(void){	struct fw_block *b;	struct stat st;	int i;	for (i = 0; i < fw_num_blocks; i++) {		b = &fw_blocks[i];		if ((b->addr + b->blocklen) > flash_size) {			errmsg(0, "block at 0x%08X is too big", b->addr);			return -1;		}		if (b->name == NULL)			continue;		if (stat(b->name, &st) < 0) {			errmsg(0, "stat failed on %s",b->name);			return -1;		}		if (b->blocklen == 0) {			b->blocklen = flash_size - b->addr;		}		if (st.st_size > b->blocklen) {			errmsg(0,"file %s is too big",b->name);			return -1;		}		b->size = st.st_size;	}	return 0;}intprocess_partitions(void){	struct mylo_partition *part;	int i;	for (i = 0; i < fw_num_partitions; i++) {		part = &fw_partitions[i];		if (part->addr > flash_size) {			errmsg(0, "invalid partition at 0x%08X", part->addr);			return -1;		}		if ((part->addr + part->size) > flash_size) {			errmsg(0, "partition at 0x%08X is too big", part->addr);			return -1;		}	}	return 0;}/* * routines to write data to the output file */intwrite_out_data(FILE *outfile, uint8_t *data, size_t len, uint32_t *crc){	errno = 0;	fwrite(data, len, 1, outfile);	if (errno) {		errmsg(1,"unable to write output file");		return -1;	}	if (crc) {		update_crc(data, len, crc);	}	return 0;}intwrite_out_desc(FILE *outfile, struct mylo_fw_blockdesc *desc, uint32_t *crc){	return write_out_data(outfile, (uint8_t *)desc,		sizeof(*desc), crc);}intwrite_out_padding(FILE *outfile, size_t len, uint8_t padc, uint32_t *crc){	uint8_t buff[512];	size_t  buflen = sizeof(buff);	memset(buff, padc, buflen);	while (len > 0) {		if (len < buflen)			buflen = len;		if (write_out_data(outfile, buff, buflen, crc))			return -1;		len -= buflen;	}	return 0;}intwrite_out_file(FILE *outfile, struct fw_block *block, uint32_t *crc){	char buff[FILE_BUF_LEN];	size_t  buflen = sizeof(buff);	FILE *f;	size_t len;	errno = 0;	if (block->name == NULL) {		return 0;	}	if ((block->flags & BLOCK_FLAG_HAVEHDR) != 0) {		struct mylo_partition_header ph;		if (get_file_crc(block) != 0)		        return -1;		ph.crc = HOST_TO_LE32(block->crc);		ph.len = HOST_TO_LE32(block->size);		if (write_out_data(outfile, (uint8_t *)&ph, sizeof(ph), crc) != 0)			return -1;	}	f = fopen(block->name,"r");	if (errno) {		errmsg(1,"unable to open file: %s", block->name);		return -1;	}	len = block->size;	while (len > 0) {		if (len < buflen)			buflen = len;		/* read data from source file */		errno = 0;		fread(buff, buflen, 1, f);		if (errno != 0) {			errmsg(1,"unable to read from file: %s",block->name);			return -1;		}		if (write_out_data(outfile, buff, buflen, crc) != 0)			return -1;		len -= buflen;	}	fclose(f);	/* align next block on a 4 byte boundary */	len = ALIGN(len,4) - block->size;	if (write_out_padding(outfile, len, 0xFF, crc))		return -1;	dbgmsg(1,"file %s written out", block->name);	return 0;}intwrite_out_header(FILE *outfile, uint32_t *crc){	struct mylo_fw_header hdr;	memset(&hdr, 0, sizeof(hdr));	hdr.magic = HOST_TO_LE32(MYLO_MAGIC_FIRMWARE);	hdr.crc = HOST_TO_LE32(fw_header.crc);	hdr.vid = HOST_TO_LE16(fw_header.vid);	hdr.did = HOST_TO_LE16(fw_header.did);	hdr.svid = HOST_TO_LE16(fw_header.svid);	hdr.sdid = HOST_TO_LE16(fw_header.sdid);	hdr.rev = HOST_TO_LE32(fw_header.rev);	hdr.fwhi = HOST_TO_LE32(fw_header.fwhi);	hdr.fwlo = HOST_TO_LE32(fw_header.fwlo);	hdr.flags = HOST_TO_LE32(fw_header.flags);	if (fseek(outfile, 0, SEEK_SET) != 0) {		errmsg(1,"fseek failed on output file");		return -1;	}	return write_out_data(outfile, (uint8_t *)&hdr, sizeof(hdr), crc);}intwrite_out_partitions(FILE *outfile, uint32_t *crc){	struct mylo_partition_table p;	struct mylo_partition *p1, *p2;	int i;	if (fw_num_partitions == 0)		return 0;	memset(&p, 0, sizeof(p));	p.magic = HOST_TO_LE32(MYLO_MAGIC_PARTITIONS);	for (i = 0; i < fw_num_partitions; i++) {		p1 = &p.partitions[i];		p2 = &fw_partitions[i];		p1->flags = HOST_TO_LE16(p2->flags);		p1->type = HOST_TO_LE16(PARTITION_TYPE_USED);		p1->addr = HOST_TO_LE32(p2->addr);		p1->size = HOST_TO_LE32(p2->size);		p1->param = HOST_TO_LE32(p2->param);	}	return write_out_data(outfile, (uint8_t *)&p, sizeof(p), crc);}intwrite_out_blocks(FILE *outfile, uint32_t *crc)

⌨️ 快捷键说明

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