firmware-utils: add JBOOT bootloader image support
Tested on D-Link DWR-116. Based on mktplinkfw. Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>
This commit is contained in:
committed by
Mathias Kresin
parent
d11aa1d4af
commit
84c1b786b9
172
tools/firmware-utils/src/mkdlinkfw-lib.c
Normal file
172
tools/firmware-utils/src/mkdlinkfw-lib.c
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* mkdlinkfw
|
||||
*
|
||||
* Copyright (C) 2018 Paweł Dembicki <paweldembicki@gmail.com>
|
||||
*
|
||||
* This tool is based on mktplinkfw.
|
||||
* Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
|
||||
* Copyright (C) 2008,2009 Wang Jian <lark@linux.net.cn>
|
||||
*
|
||||
* 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 <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 <stdbool.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <zlib.h> /*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;
|
||||
}
|
||||
Reference in New Issue
Block a user