/* * 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; }