From 84c1b786b9830c17034e5de915ce11965666febd Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Sat, 3 Feb 2018 12:59:50 +0100 Subject: firmware-utils: add JBOOT bootloader image support Tested on D-Link DWR-116. Based on mktplinkfw. Signed-off-by: Pawel Dembicki --- tools/firmware-utils/src/mkdlinkfw-lib.c | 172 +++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 tools/firmware-utils/src/mkdlinkfw-lib.c (limited to 'tools/firmware-utils/src/mkdlinkfw-lib.c') diff --git a/tools/firmware-utils/src/mkdlinkfw-lib.c b/tools/firmware-utils/src/mkdlinkfw-lib.c new file mode 100644 index 0000000000..fcab856231 --- /dev/null +++ b/tools/firmware-utils/src/mkdlinkfw-lib.c @@ -0,0 +1,172 @@ +/* + * mkdlinkfw + * + * Copyright (C) 2018 Paweł Dembicki + * + * This tool is based on mktplinkfw. + * Copyright (C) 2009 Gabor Juhos + * Copyright (C) 2008,2009 Wang Jian + * + * 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 +#include +#include +#include +#include /* for unlink() */ +#include +#include /* for getopt() */ +#include +#include +#include +#include +#include +#include +#include /*for crc32 */ + +#include "mkdlinkfw-lib.h" + +extern char *progname; + +static unsigned char jffs2_eof_mark[4] = { 0xde, 0xad, 0xc0, 0xde }; + +uint32_t jboot_timestamp(void) +{ + time_t rawtime; + time(&rawtime); + return (((uint32_t) rawtime) - TIMESTAMP_MAGIC) >> 2; +} + +uint16_t jboot_checksum(uint16_t start_val, uint16_t *data, int size) +{ + uint32_t counter = start_val; + uint16_t *ptr = data; + + while (size > 1) { + counter += *ptr; + ++ptr; + while (counter >> 16) + counter = (uint16_t) counter + (counter >> 16); + size -= 2; + } + if (size > 0) { + counter += *(uint8_t *) ptr; + counter -= 0xFF; + } + while (counter >> 16) + counter = (uint16_t) counter + (counter >> 16); + return counter; +} + +int get_file_stat(struct file_info *fdata) +{ + struct stat st; + int res; + + if (fdata->file_name == NULL) + return 0; + + res = stat(fdata->file_name, &st); + if (res) { + ERRS("stat failed on %s", fdata->file_name); + return res; + } + + fdata->file_size = st.st_size; + return 0; +} + +int read_to_buf(const struct file_info *fdata, char *buf) +{ + FILE *f; + int ret = EXIT_FAILURE; + + f = fopen(fdata->file_name, "r"); + if (f == NULL) { + ERRS("could not open \"%s\" for reading", fdata->file_name); + goto out; + } + + errno = 0; + fread(buf, fdata->file_size, 1, f); + if (errno != 0) { + ERRS("unable to read from file \"%s\"", fdata->file_name); + goto out_close; + } + + ret = EXIT_SUCCESS; + + out_close: + fclose(f); + out: + return ret; +} + +int pad_jffs2(char *buf, int currlen, int maxlen) +{ + int len; + uint32_t pad_mask; + + len = currlen; + pad_mask = (4 * 1024) | (64 * 1024); /* EOF at 4KB and at 64KB */ + while ((len < maxlen) && (pad_mask != 0)) { + uint32_t mask; + int i; + + for (i = 10; i < 32; i++) { + mask = 1 << i; + if (pad_mask & mask) + break; + } + + len = ALIGN(len, mask); + + for (i = 10; i < 32; i++) { + mask = 1 << i; + if ((len & (mask - 1)) == 0) + pad_mask &= ~mask; + } + + for (i = 0; i < sizeof(jffs2_eof_mark); i++) + buf[len + i] = jffs2_eof_mark[i]; + + len += sizeof(jffs2_eof_mark); + } + + return len; +} + +int write_fw(const char *ofname, const char *data, int len) +{ + FILE *f; + int ret = EXIT_FAILURE; + + f = fopen(ofname, "w"); + if (f == NULL) { + ERRS("could not open \"%s\" for writing", ofname); + goto out; + } + + errno = 0; + fwrite(data, len, 1, f); + if (errno) { + ERRS("unable to write output file"); + goto out_flush; + } + + DBG("firmware file \"%s\" completed", ofname); + + ret = EXIT_SUCCESS; + + out_flush: + fflush(f); + fclose(f); + if (ret != EXIT_SUCCESS) + unlink(ofname); + out: + return ret; +} -- cgit v1.2.3