diff options
| author | Roman Yeryomin <roman@advem.lv> | 2012-09-13 00:13:39 +0300 | 
|---|---|---|
| committer | Roman Yeryomin <roman@advem.lv> | 2013-05-26 00:44:02 +0300 | 
| commit | a112ec0dd1e87df948c6a3ab4b0442641a5392dd (patch) | |
| tree | 4aa9f8d0efa4dfa97ce44287b7c25dd94f837337 /tools | |
| parent | c7f3f603795f07fcb7c6c4f6bfa9c74280726bac (diff) | |
Add bixutil to firmware-utils
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/firmware-utils/Makefile | 1 | ||||
| -rw-r--r-- | tools/firmware-utils/src/bixutil.c | 188 | 
2 files changed, 189 insertions, 0 deletions
diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile index 3fdf2d006..c7d0c0a0e 100644 --- a/tools/firmware-utils/Makefile +++ b/tools/firmware-utils/Makefile @@ -62,6 +62,7 @@ define Host/Compile  	$(call cc, mkcameofw, -Wall)  	$(call cc,seama md5)  	$(call cc,fix-u-media-header cyg_crc32,-Wall) +	$(call cc,bixutil)  endef  define Host/Install diff --git a/tools/firmware-utils/src/bixutil.c b/tools/firmware-utils/src/bixutil.c new file mode 100644 index 000000000..6e7dcd479 --- /dev/null +++ b/tools/firmware-utils/src/bixutil.c @@ -0,0 +1,188 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <time.h> +#include <fcntl.h> +#include <errno.h> + +#define RTL_PRODUCT_MAGIC1    0x59a0e842 +#define SQUASH_MAGIC          0x73717368 +#define RTL_IMAGE_VERSION     1 +#define RTL_IMAGE_TYPE_RDIR   0xb162 +#define RTL_IMAGE_TYPE_BOOT   0xea43 +#define RTL_IMAGE_TYPE_RUN    0x8dc9 +#define RTL_IMAGE_TYPE_KFS    0xd92f +#define RTL_IMAGE_TYPE_CCFG   0x2a05 +#define RTL_IMAGE_TYPE_DCFG   0x6ce8 +#define RTL_IMAGE_TYPE_LOG    0xc371 + +#define ENDIAN_SWITCH32(x) (((x) >> 24) |				\ +			    (((x) >> 8) & 0xFF00) |			\ +			    (((x) << 8) & 0xFF0000) |			\ +			    (((x) << 24) &0xFF000000)) +#define ENDIAN_SWITCH16(x) ((((x) >> 8) & 0xFF) |	\ +			    (((x) << 8) & 0xFF00)) + + +struct image_header { +	u_int32_t magic1; +	u_int16_t type; +	u_int8_t  ver; +	u_int8_t  align1; +	u_int16_t year; +	u_int8_t  mon; +	u_int8_t  day; +	u_int8_t  hour; +	u_int8_t  min; +	u_int8_t  sec; +	u_int8_t  align2; +	u_int32_t len; +	u_int16_t align3; +	u_int8_t  icsum; +	u_int8_t  hcsum; +}; + +void print_header(struct image_header *h) +{ +	printf("Magic1: 0x%08x\n", ENDIAN_SWITCH32(h->magic1)); +	printf("Type: 0x%04x\n", ENDIAN_SWITCH16(h->type)); +	printf("Version: %d\n", h->ver); +	printf("Built: %04d-%02d-%02d %02d:%02d:%02d\n", +	       ENDIAN_SWITCH16(h->year), h->mon, h->day, h->hour, +	       h->min, h->sec);  +	printf("Length: %ld\n", ENDIAN_SWITCH32(h->len)); +	printf("Checksums: 0x%02x (header), 0x%02x (image)\n", +	       h->hcsum, h->icsum); +} + +void *do_mmap(char *filename, int size, int readonly) +{ +	int fd; +	int openflags = O_RDWR | O_CREAT | O_TRUNC; +	int protflags = PROT_READ | PROT_WRITE; +	void *ptr; +	struct stat st; + +	if (readonly) { +		openflags = O_RDONLY; +		protflags = PROT_READ; +	} + +	if (!size) { +		if (!readonly)  +			goto failed; +		if (stat(filename, &st) != 0) { +			perror("stat failed"); +			goto failed; +		} +		size = st.st_size; +	} + +	if (!size)  +		goto failed; + +	if ((fd = open(filename, openflags, 0644)) == -1) { +		perror("open failed"); +		goto failed; +	} + +	if (!readonly)  +		ftruncate(fd, size); + +	ptr = mmap(0, size, protflags, MAP_SHARED, fd, 0); +	if (ptr == MAP_FAILED) { +		perror("mmap failed"); +		goto mmap_failed; +	} + +	return ptr; + +mmap_failed: +	close(fd); +failed: +	return NULL; +} + +int write_image(char *kernel, char *outfile) +{ +	unsigned char type; +	unsigned long ksize, padded; +	unsigned long i; +	unsigned char ch, *src, *dst; +	struct stat st; +	struct image_header *h; +	time_t tt; +	struct tm *ut; + +	tt = time(NULL); +	ut = localtime(&tt); + +	if (stat(kernel, &st) != 0) +		error(-1, "stat %s failed", kernel); +	ksize = st.st_size; + +	padded = sizeof(struct image_header) +  +		ksize + ksize % 4;  /* fs starts 32-bit aligned (?check) */ + +	h = (struct image_header *)do_mmap(outfile, padded, 0); +	if (!h)  +		return -1; + +	memset(h, 0, sizeof(struct image_header)); + +	dst = (unsigned char *)((unsigned)h + sizeof(struct image_header)); +	src = (unsigned char *)do_mmap(kernel, ksize, 1); +	if (!src) +		return -1; + +	for (i = 0; i < ksize; i++) { +		dst[i] = src[i]; +		h->icsum ^= src[i]; +	} + +	for (i = 0; i < ksize % 4; i++) +		dst[ksize + i] = 0; + +	munmap(src, ksize); + +	h->magic1 = ENDIAN_SWITCH32(RTL_PRODUCT_MAGIC1); +	h->type = ENDIAN_SWITCH16(RTL_IMAGE_TYPE_RUN); +	h->ver = RTL_IMAGE_VERSION; +	h->year = ENDIAN_SWITCH16(ut->tm_year + 1900); +	h->mon = ut->tm_mon + 1; +	h->day = ut->tm_mday; +	h->hour = ut->tm_hour; +	h->min = ut->tm_min; +	h->sec = ut->tm_sec; +	h->len = ENDIAN_SWITCH32(padded - sizeof(struct image_header)); + +	for (i = 0; i < (sizeof(struct image_header) - 1); i++) +		h->hcsum ^= ((unsigned char *)&h)[i]; +	munmap(h, padded); +	return 0; +} + +void usage(void)  +{ +	exit(1); +} + +int main(int argc, char *argv[])  +{ +	if (argc < 3) usage(); + +	printf("%d\n", sizeof(struct image_header)); +	if (!strncmp(argv[1], "info", 4)) { +		print_header((struct image_header *)do_mmap(argv[2], +							    0, 1)); +	} else if (!strncmp(argv[1], "pack", 4)) { +		write_image(argv[2], argv[3]); +	} else { +		usage(); +	} + +	return 0; +}  | 
