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

📄 mkfwimage.c

📁 Linux Home Server 是专门为家庭和SOHO/SMB 设计的高性价比的ISCSI 存储服务器, 具有如下的特色: 强大的iscsi 存储服务器软件; 混合iscsi 和NAS 服务;
💻 C
字号:
/* * Copyright (C) 2007 Ubiquiti Networks, Inc. * Copyright (C) 2008 Lukas Kuna <ValXdater@seznam.cz> * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <zlib.h>#include <sys/mman.h>#include <netinet/in.h>#include <stdio.h>#include <stdlib.h>#include <limits.h>#include "fw.h"typedef struct part_data {	char 	partition_name[64];	int  	partition_index;	u_int32_t	partition_baseaddr;	u_int32_t	partition_startaddr;	u_int32_t	partition_memaddr;	u_int32_t	partition_entryaddr;	u_int32_t  partition_length;	char	filename[PATH_MAX];	struct stat stats;} part_data_t;#define MAX_SECTIONS	8#define DEFAULT_OUTPUT_FILE 	"firmware-image.bin"#define DEFAULT_VERSION		"UNKNOWN"#define OPTIONS "hv:o:r:k:s:"#define FIRMWARE_MAX_LENGTH	(0x390000)#define partition_startaddr	(0xBFC30000)static int debug = 0;typedef struct image_info {	char version[256];	char outputfile[PATH_MAX];	u_int32_t	part_count;	part_data_t parts[MAX_SECTIONS];} image_info_t;static void write_header(void* mem, const char* version){	header_t* header = mem;	memset(header, 0, sizeof(header_t));	memcpy(header->magic, MAGIC_HEADER, MAGIC_LENGTH);	strncpy(header->version, version, sizeof(header->version));	header->crc = htonl(crc32(0L, (unsigned char *)header,				sizeof(header_t) - 2 * sizeof(u_int32_t)));	header->pad = 0L;}static void write_signature(void* mem, u_int32_t sig_offset){	/* write signature */	signature_t* sign = (signature_t*)(mem + sig_offset);	memset(sign, 0, sizeof(signature_t));	memcpy(sign->magic, MAGIC_END, MAGIC_LENGTH);	sign->crc = htonl(crc32(0L,(unsigned char *)mem, sig_offset));	sign->pad = 0L;}static int write_part(void* mem, part_data_t* d){	char* addr;	int fd;	part_t* p = mem;	part_crc_t* crc = mem + sizeof(part_t) + d->stats.st_size;	fd = open(d->filename, O_RDONLY);	if (fd < 0)	{		ERROR("Failed opening file '%s'\n", d->filename);		return -1;	}	if ((addr=(char*)mmap(0, d->stats.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED)	{		ERROR("Failed mmaping memory for file '%s'\n", d->filename);		close(fd);		return -2;	}	memcpy(mem + sizeof(part_t), addr, d->stats.st_size);	munmap(addr, d->stats.st_size);	memset(p->name, 0, sizeof(p->name));	strncpy(p->magic, MAGIC_PART, MAGIC_LENGTH);	strncpy(p->name, d->partition_name, sizeof(p->name));	p->index = htonl(d->partition_index);	p->data_size = htonl(d->stats.st_size);	p->part_size = htonl(d->partition_length);	p->baseaddr = htonl(d->partition_baseaddr);	p->memaddr = htonl(d->partition_memaddr);	p->entryaddr = htonl(d->partition_entryaddr);	crc->crc = htonl(crc32(0L, mem, d->stats.st_size + sizeof(part_t)));	crc->pad = 0L;	return 0;}static void usage(const char* progname){	INFO("Version %s\n"             "Usage: %s [options]\n"	     "\t-v <version string>\t - firmware version information, default: %s\n"	     "\t-o <output file>\t - firmware output file, default: %s\n"	     "\t-k <kernel file>\t\t - kernel file\n"	     "\t-r <rootfs file>\t\t - rootfs file\n"	     "\t-h\t\t\t - this help\n", VERSION,	     progname, DEFAULT_VERSION, DEFAULT_OUTPUT_FILE);}static void print_image_info(const image_info_t* im){	int i = 0;	INFO("Firmware version: '%s'\n"	     "Output file: '%s'\n"	     "Part count: %u\n",	     im->version, im->outputfile,	     im->part_count);	for (i = 0; i < im->part_count; ++i)	{		const part_data_t* d = &im->parts[i];		INFO(" %10s: %8ld bytes (free: %8ld)\n",		     d->partition_name,		     d->stats.st_size,		     d->partition_length - d->stats.st_size);	}}static u_int32_t filelength(const char* file){	FILE *p;	int ret = -1;	if ( (p = fopen(file, "rb") ) == NULL) return (-1);	fseek(p, 0, SEEK_END);	ret = ftell(p);	fclose (p);	return (ret);}static int create_image_layout(const char* kernelfile, const char* rootfsfile, image_info_t* im){	part_data_t* kernel = &im->parts[0];	part_data_t* rootfs = &im->parts[1];	strcpy(kernel->partition_name, "kernel");	kernel->partition_index = 1;	kernel->partition_baseaddr = partition_startaddr;	if ( (kernel->partition_length = filelength(kernelfile)) < 0) return (-1);	kernel->partition_memaddr = 0x80041000;	kernel->partition_entryaddr = 0x80041000;	strncpy(kernel->filename, kernelfile, sizeof(kernel->filename));	if (filelength(rootfsfile) + kernel->partition_length > FIRMWARE_MAX_LENGTH)		return (-2);	strcpy(rootfs->partition_name, "rootfs");	rootfs->partition_index = 2;	rootfs->partition_baseaddr = partition_startaddr + kernel->partition_length;	rootfs->partition_length = FIRMWARE_MAX_LENGTH - kernel->partition_length;	rootfs->partition_memaddr = 0x00000000;	rootfs->partition_entryaddr = 0x00000000;	strncpy(rootfs->filename, rootfsfile, sizeof(rootfs->filename));	im->part_count = 2;	return 0;}/** * Checks the availability and validity of all image components. * Fills in stats member of the part_data structure. */static int validate_image_layout(image_info_t* im){	int i;	if (im->part_count == 0 || im->part_count > MAX_SECTIONS)	{		ERROR("Invalid part count '%d'\n", im->part_count);		return -1;	}	for (i = 0; i < im->part_count; ++i)	{		part_data_t* d = &im->parts[i];		int len = strlen(d->partition_name);		if (len == 0 || len > 16)		{			ERROR("Invalid partition name '%s' of the part %d\n",					d->partition_name, i);			return -1;		}		if (stat(d->filename, &d->stats) < 0)		{			ERROR("Couldn't stat file '%s' from part '%s'\n",				       	d->filename, d->partition_name);			return -2;		}		if (d->stats.st_size == 0)		{			ERROR("File '%s' from part '%s' is empty!\n",				       	d->filename, d->partition_name);			return -3;		}		if (d->stats.st_size > d->partition_length) {			ERROR("File '%s' too big (%d) - max size: 0x%08X (exceeds %lu bytes)\n",				       	d->filename, i, d->partition_length,					d->stats.st_size - d->partition_length);			return -4;		}	}	return 0;}static int build_image(image_info_t* im){	char* mem;	char* ptr;	u_int32_t mem_size;	FILE* f;	int i;	// build in-memory buffer	mem_size = sizeof(header_t) + sizeof(signature_t);	for (i = 0; i < im->part_count; ++i)	{		part_data_t* d = &im->parts[i];		mem_size += sizeof(part_t) + d->stats.st_size + sizeof(part_crc_t);	}	mem = (char*)calloc(mem_size, 1);	if (mem == NULL)	{		ERROR("Cannot allocate memory chunk of size '%u'\n", mem_size);		return -1;	}	// write header	write_header(mem, im->version);	ptr = mem + sizeof(header_t);	// write all parts	for (i = 0; i < im->part_count; ++i)	{		part_data_t* d = &im->parts[i];		int rc;		if ((rc = write_part(ptr, d)) != 0)		{			ERROR("ERROR: failed writing part %u '%s'\n", i, d->partition_name);		}		ptr += sizeof(part_t) + d->stats.st_size + sizeof(part_crc_t);	}	// write signature	write_signature(mem, mem_size - sizeof(signature_t));	// write in-memory buffer into file	if ((f = fopen(im->outputfile, "w")) == NULL)	{		ERROR("Can not create output file: '%s'\n", im->outputfile);		return -10;	}	if (fwrite(mem, mem_size, 1, f) != 1)	{		ERROR("Could not write %d bytes into file: '%s'\n",				mem_size, im->outputfile);		return -11;	}	free(mem);	fclose(f);	return 0;}int main(int argc, char* argv[]){	char kernelfile[PATH_MAX];	char rootfsfile[PATH_MAX];	int o, rc;	image_info_t im;	memset(&im, 0, sizeof(im));	memset(kernelfile, 0, sizeof(kernelfile));	memset(rootfsfile, 0, sizeof(rootfsfile));	strcpy(im.outputfile, DEFAULT_OUTPUT_FILE);	strcpy(im.version, DEFAULT_VERSION);	while ((o = getopt(argc, argv, OPTIONS)) != -1)	{		switch (o) {		case 'v':			if (optarg)				strncpy(im.version, optarg, sizeof(im.version));			break;		case 'o':			if (optarg)				strncpy(im.outputfile, optarg, sizeof(im.outputfile));			break;		case 'h':			usage(argv[0]);			return -1;		case 'k':			if (optarg)				strncpy(kernelfile, optarg, sizeof(kernelfile));			break;		case 'r':			if (optarg)				strncpy(rootfsfile, optarg, sizeof(rootfsfile));			break;		case 's':			if (optarg)				#undef partition_startaddr				#define partition_startaddr	(optarg)			break;		}	}	if (strlen(kernelfile) == 0)	{		ERROR("Kernel file is not specified, cannot continue\n");		usage(argv[0]);		return -2;	}	if (strlen(rootfsfile) == 0)	{		ERROR("Root FS file is not specified, cannot continue\n");		usage(argv[0]);		return -2;	}	if ((rc = create_image_layout(kernelfile, rootfsfile, &im)) != 0)	{		ERROR("Failed creating firmware layout description - error code: %d\n", rc);		return -3;	}	if ((rc = validate_image_layout(&im)) != 0)	{		ERROR("Failed validating firmware layout - error code: %d\n", rc);		return -4;	}	print_image_info(&im);	if ((rc = build_image(&im)) != 0)	{		ERROR("Failed building image file '%s' - error code: %d\n", im.outputfile, rc);		return -5;	}	return 0;}

⌨️ 快捷键说明

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