Skip to content

Commit

Permalink
firmware-utils: add JBOOT bootloader image support
Browse files Browse the repository at this point in the history
Tested on D-Link DWR-116.
Based on mktplinkfw.

Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>
  • Loading branch information
CHKDSK88 authored and mkresin committed Mar 18, 2018
1 parent d11aa1d commit 84c1b78
Show file tree
Hide file tree
Showing 4 changed files with 921 additions and 0 deletions.
1 change: 1 addition & 0 deletions tools/firmware-utils/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ define Host/Compile
$(call cc,mkbuffaloimg, -Wall)
$(call cc,zyimage, -Wall)
$(call cc,mkdhpimg buffalo-lib, -Wall)
$(call cc,mkdlinkfw mkdlinkfw-lib, -lz -Wall)
endef

define Host/Install
Expand Down
172 changes: 172 additions & 0 deletions tools/firmware-utils/src/mkdlinkfw-lib.c
Original file line number Diff line number Diff line change
@@ -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;
}
83 changes: 83 additions & 0 deletions tools/firmware-utils/src/mkdlinkfw-lib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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.
*/

#ifndef mkdlinkfw_lib_h
#define mkdlinkfw_lib_h

#define AUH_MAGIC "DLK"
#define AUH_SIZE 80
#define AUH_LVPS 0x01
#define AUH_HDR_ID 0x4842
#define AUH_HDR_VER 0x02
#define AUH_SEC_ID 0x04
#define AUH_INFO_TYPE 0x04

#define STAG_SIZE 16
#define STAG_ID 0x04
#define STAG_MAGIC 0x2B24
#define STAG_CMARK_FACTORY 0xFF

#define SCH2_SIZE 40
#define SCH2_MAGIC 0x2124
#define SCH2_VER 0x02

#define FLAT 0
#define JZ 1
#define GZIP 2
#define LZMA 3

#define RAM_ENTRY_ADDR 0x80000000
#define RAM_LOAD_ADDR 0x80000000
#define JBOOT_SIZE 0x10000

#define ALL_HEADERS_SIZE (AUH_SIZE + STAG_SIZE + SCH2_SIZE)
#define MAX_HEADER_COUNTER 10
#define TIMESTAMP_MAGIC 0x35016f00L

#define FACTORY 0
#define SYSUPGRADE 1

#define ALIGN(x, a) ({ typeof(a) __a = (a); (((x) + __a - 1) & ~(__a - 1)); })

#define ERR(fmt, ...) do { \
fflush(0); \
fprintf(stderr, "[%s] *** error: " fmt "\n", \
progname, ## __VA_ARGS__); \
} while (0)

#define ERRS(fmt, ...) do { \
int save = errno; \
fflush(0); \
fprintf(stderr, "[%s] *** error: " fmt ": %s\n", \
progname, ## __VA_ARGS__, strerror(save)); \
} while (0)

#define DBG(fmt, ...) do { \
fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__); \
} while (0)

struct file_info {
char *file_name; /* name of the file */
uint32_t file_size; /* length of the file */
};

uint32_t jboot_timestamp(void);
uint16_t jboot_checksum(uint16_t start_val, uint16_t *data, int size);
int get_file_stat(struct file_info *fdata);
int read_to_buf(const struct file_info *fdata, char *buf);
int pad_jffs2(char *buf, int currlen, int maxlen);
int write_fw(const char *ofname, const char *data, int len);

#endif /* mkdlinkfw_lib_h */
Loading

0 comments on commit 84c1b78

Please sign in to comment.