mirror of https://github.com/hak5/openwrt.git
firmware-utils: mksercommfw: overhaul image creation
Move the zip compression into a build recipe. Pad the image using the existing build recipes as well to remove duplicate functionality Change the code to append header and footer in two steps. Allow to use a fixed filename as the netgear update image does. Use a fixed timestamp within the zip archive to make the images reproducible. Due to the changes we are now compatible to the gnu89 c standard used by default on the buildbots and we don't need to force a more recent standard anymore. Beside all changes, the footer still looks wrong in compare to the netgear update image. Signed-off-by: Mathias Kresin <dev@kresin.me>openwrt-19.07
parent
18c9faa032
commit
26a016731d
|
@ -168,6 +168,16 @@ define Build/gzip
|
||||||
@mv $@.new $@
|
@mv $@.new $@
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
define Build/zip
|
||||||
|
mkdir $@.tmp
|
||||||
|
mv $@ $@.tmp/$(1)
|
||||||
|
|
||||||
|
zip -j -X \
|
||||||
|
$(if $(SOURCE_DATE_EPOCH),--mtime="$(SOURCE_DATE_EPOCH)") \
|
||||||
|
$@ $@.tmp/$(if $(1),$(1),$@)
|
||||||
|
rm -rf $@.tmp
|
||||||
|
endef
|
||||||
|
|
||||||
define Build/jffs2
|
define Build/jffs2
|
||||||
rm -rf $(KDIR_TMP)/$(DEVICE_NAME)/jffs2 && \
|
rm -rf $(KDIR_TMP)/$(DEVICE_NAME)/jffs2 && \
|
||||||
mkdir -p $(KDIR_TMP)/$(DEVICE_NAME)/jffs2/$$(dirname $(1)) && \
|
mkdir -p $(KDIR_TMP)/$(DEVICE_NAME)/jffs2/$$(dirname $(1)) && \
|
||||||
|
|
|
@ -2,17 +2,22 @@
|
||||||
# MT76x8 Profiles
|
# MT76x8 Profiles
|
||||||
#
|
#
|
||||||
|
|
||||||
DEVICE_VARS += SERCOMM_KERNEL_OFFSET SERCOMM_HWID SERCOMM_HWVER SERCOMM_SWVER
|
DEVICE_VARS += SERCOMM_HWID SERCOMM_HWVER SERCOMM_SWVER
|
||||||
|
|
||||||
define Build/mksercommfw
|
define Build/sercom-seal
|
||||||
$(STAGING_DIR_HOST)/bin/mksercommfw \
|
$(STAGING_DIR_HOST)/bin/mksercommfw \
|
||||||
$@ \
|
-i $@ \
|
||||||
$(SERCOMM_KERNEL_OFFSET) \
|
-b $(SERCOMM_HWID) \
|
||||||
$(SERCOMM_HWID) \
|
-r $(SERCOMM_HWVER) \
|
||||||
$(SERCOMM_HWVER) \
|
-v $(SERCOMM_SWVER) \
|
||||||
$(SERCOMM_SWVER)
|
$(1)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
define Build/sercom-footer
|
||||||
|
$(call Build/sercom-seal,-f)
|
||||||
|
endef
|
||||||
|
|
||||||
|
|
||||||
define Device/tplink
|
define Device/tplink
|
||||||
TPLINK_FLASHLAYOUT :=
|
TPLINK_FLASHLAYOUT :=
|
||||||
TPLINK_HWID :=
|
TPLINK_HWID :=
|
||||||
|
@ -116,14 +121,14 @@ define Device/netgear_r6120
|
||||||
IMAGE_SIZE := $(ralink_default_fw_size_16M)
|
IMAGE_SIZE := $(ralink_default_fw_size_16M)
|
||||||
DEVICE_TITLE := Netgear AC1200 R6120
|
DEVICE_TITLE := Netgear AC1200 R6120
|
||||||
DEVICE_PACKAGES := kmod-mt76x2 kmod-usb2 kmod-usb-ohci
|
DEVICE_PACKAGES := kmod-mt76x2 kmod-usb2 kmod-usb-ohci
|
||||||
SERCOMM_KERNEL_OFFSET := 0x90000
|
|
||||||
SERCOMM_HWID := CGQ
|
SERCOMM_HWID := CGQ
|
||||||
SERCOMM_HWVER := A001
|
SERCOMM_HWVER := A001
|
||||||
SERCOMM_SWVER := 0x0040
|
SERCOMM_SWVER := 0x0040
|
||||||
IMAGES += factory.img
|
IMAGES += factory.img
|
||||||
IMAGE/default := append-kernel | pad-to $$$$(BLOCKSIZE)| append-rootfs | pad-rootfs
|
IMAGE/default := append-kernel | pad-to $$$$(BLOCKSIZE)| append-rootfs | pad-rootfs
|
||||||
IMAGE/sysupgrade.bin := $$(IMAGE/default) | append-metadata | check-size $$$$(IMAGE_SIZE)
|
IMAGE/sysupgrade.bin := $$(IMAGE/default) | append-metadata | check-size $$$$(IMAGE_SIZE)
|
||||||
IMAGE/factory.img := $$(IMAGE/default) | mksercommfw
|
IMAGE/factory.img := pad-extra 576k | $$(IMAGE/default) | \
|
||||||
|
sercom-footer | pad-to 128 | zip R6120.bin | sercom-seal
|
||||||
endef
|
endef
|
||||||
TARGET_DEVICES += netgear_r6120
|
TARGET_DEVICES += netgear_r6120
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ define Host/Compile
|
||||||
$(call cc,mkdhpimg buffalo-lib, -Wall)
|
$(call cc,mkdhpimg buffalo-lib, -Wall)
|
||||||
$(call cc,mkdlinkfw mkdlinkfw-lib, -lz -Wall --std=c99)
|
$(call cc,mkdlinkfw mkdlinkfw-lib, -lz -Wall --std=c99)
|
||||||
$(call cc,dns313-header, -Wall)
|
$(call cc,dns313-header, -Wall)
|
||||||
$(call cc,mksercommfw, -Wall --std=gnu99)
|
$(call cc,mksercommfw, -Wall)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Host/Install
|
define Host/Install
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <byteswap.h>
|
#include <byteswap.h>
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
#if !defined(__BYTE_ORDER)
|
#if !defined(__BYTE_ORDER)
|
||||||
#error "Unknown byte order"
|
#error "Unknown byte order"
|
||||||
|
@ -12,14 +13,8 @@
|
||||||
|
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
#define cpu_to_be32(x) (x)
|
#define cpu_to_be32(x) (x)
|
||||||
#define be32_to_cpu(x) (x)
|
|
||||||
#define cpu_to_be16(x) (x)
|
|
||||||
#define be16_to_cpu(x) (x)
|
|
||||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
#define cpu_to_be32(x) bswap_32(x)
|
#define cpu_to_be32(x) bswap_32(x)
|
||||||
#define be32_to_cpu(x) bswap_32(x)
|
|
||||||
#define cpu_to_be16(x) bswap_16(x)
|
|
||||||
#define be16_to_cpu(x) bswap_16(x)
|
|
||||||
#else
|
#else
|
||||||
#error "Unsupported endianness"
|
#error "Unsupported endianness"
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,9 +28,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ERR(...) {printf(__VA_ARGS__); }
|
#define ERR(...) {printf(__VA_ARGS__); }
|
||||||
#define ALIGN(a,b) ((a) + ((b) - ((a) % (b))))
|
|
||||||
#define ROOTFS_ALIGN 128
|
|
||||||
#define HEADER_SIZE 71
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fw Header Layout for Netgear / Sercomm devices (bytes)
|
* Fw Header Layout for Netgear / Sercomm devices (bytes)
|
||||||
|
@ -51,14 +43,12 @@
|
||||||
* magic : 63-69 ASCII
|
* magic : 63-69 ASCII
|
||||||
* ChkSum : 511 Inverse value of the full image checksum while this location is 0x00
|
* ChkSum : 511 Inverse value of the full image checksum while this location is 0x00
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const char* magic = "sErCoMm"; /* 7 */
|
static const char* magic = "sErCoMm"; /* 7 */
|
||||||
|
|
||||||
/* 7-11: version control/download control ? */
|
|
||||||
static const unsigned char version[4] = { 0x00, 0x01, 0x00, 0x00 };
|
static const unsigned char version[4] = { 0x00, 0x01, 0x00, 0x00 };
|
||||||
|
static const int header_sz = 512;
|
||||||
|
static const int footer_sz = 71;
|
||||||
|
|
||||||
|
static int is_header = 1;
|
||||||
/* 512 onwards -> ZIP containing rootfs with the same Header */
|
|
||||||
|
|
||||||
struct file_info {
|
struct file_info {
|
||||||
char* file_name; /* name of the file */
|
char* file_name; /* name of the file */
|
||||||
|
@ -68,23 +58,32 @@ struct file_info {
|
||||||
|
|
||||||
static u_int8_t getCheckSum(char* data, int len) {
|
static u_int8_t getCheckSum(char* data, int len) {
|
||||||
u_int8_t new = 0;
|
u_int8_t new = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
ERR("Invalid pointer provided!\n");
|
ERR("Invalid pointer provided!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
new += data[i];
|
new += data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bufferFile(struct file_info* finfo) {
|
/*
|
||||||
int fs = 0;
|
* read file into buffer
|
||||||
|
* add space for header/footer
|
||||||
|
*/
|
||||||
|
static int copyToOutputBuf(struct file_info* finfo) {
|
||||||
FILE* fp = NULL;
|
FILE* fp = NULL;
|
||||||
|
|
||||||
|
int file_sz = 0;
|
||||||
|
int extra_sz;
|
||||||
|
int hdr_pos;
|
||||||
|
int img_pos;
|
||||||
|
|
||||||
if (!finfo || !finfo->file_name) {
|
if (!finfo || !finfo->file_name) {
|
||||||
ERR("Invalid pointer provided!\n");
|
ERR("Invalid pointer provided!\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -100,25 +99,39 @@ static int bufferFile(struct file_info* finfo) {
|
||||||
/* Get filesize */
|
/* Get filesize */
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
fseek(fp, 0L, SEEK_END);
|
fseek(fp, 0L, SEEK_END);
|
||||||
fs = ftell(fp);
|
file_sz = ftell(fp);
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
|
|
||||||
if (fs < 0) {
|
if (file_sz < 1) {
|
||||||
ERR("Error getting filesize: %s\n", finfo->file_name);
|
ERR("Error getting filesize: %s\n", finfo->file_name);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG("Filesize: %i\n", fs);
|
if (is_header) {
|
||||||
finfo->file_size = fs;
|
extra_sz = header_sz;
|
||||||
|
hdr_pos = 0;
|
||||||
|
img_pos = header_sz;
|
||||||
|
} else {
|
||||||
|
extra_sz = footer_sz;
|
||||||
|
hdr_pos = file_sz;
|
||||||
|
img_pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(finfo->file_data = malloc(fs))) {
|
DBG("Filesize: %i\n", file_sz);
|
||||||
|
finfo->file_size = file_sz + extra_sz;
|
||||||
|
|
||||||
|
if (!(finfo->file_data = malloc(finfo->file_size))) {
|
||||||
ERR("Out of memory!\n");
|
ERR("Out of memory!\n");
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fread(finfo->file_data, 1, fs, fp) != fs) {
|
/* init header/footer bytes */
|
||||||
|
memset(finfo->file_data + hdr_pos, 0, extra_sz);
|
||||||
|
|
||||||
|
/* read file and take care of leading header if exists */
|
||||||
|
if (fread(finfo->file_data + img_pos, 1, file_sz, fp) != file_sz) {
|
||||||
ERR("Error reading file %s\n", finfo->file_name);
|
ERR("Error reading file %s\n", finfo->file_name);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -127,7 +140,7 @@ static int bufferFile(struct file_info* finfo) {
|
||||||
DBG("File: read successful\n");
|
DBG("File: read successful\n");
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
return 0;
|
return hdr_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int writeFile(struct file_info* finfo) {
|
static int writeFile(struct file_info* finfo) {
|
||||||
|
@ -157,266 +170,92 @@ static int writeFile(struct file_info* finfo) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fi_clean(struct file_info* finfo) {
|
|
||||||
if (!finfo)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (finfo->file_name) {
|
|
||||||
finfo->file_name = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (finfo->file_data) {
|
|
||||||
free(finfo->file_data);
|
|
||||||
finfo->file_data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
finfo->file_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usage(char* argv[]) {
|
static void usage(char* argv[]) {
|
||||||
printf("Usage: %s <sysupgradefile> <kernel_offset> <HWID> <HWVER> <SWID>\n"
|
printf("Usage: %s [OPTIONS...]\n"
|
||||||
"All are positional arguments ... \n"
|
"\n"
|
||||||
" sysupgradefile: File with the kernel uimage at 0\n"
|
"Options:\n"
|
||||||
" kernel_offset: Offset where the kernel is located (decimal, hex or octal notation)\n"
|
" -f add sercom footer (if absent, header)\n"
|
||||||
" HWID: Hardware ID, ASCII\n"
|
" -b <hwid> use hardware id specified with <hwid> (ASCII)\n"
|
||||||
" HWVER: Hardware Version, ASCII\n"
|
" -r <hwrev> use hardware revision specified with <hwrev> (ASCII)\n"
|
||||||
" SWID: Software Version (decimal, hex or octal notation)\n"
|
" -v <version> set image version to <version> (decimal, hex or octal notation)\n"
|
||||||
" \n"
|
" -i <file> input file\n"
|
||||||
, argv[0]);
|
, argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
int ret = 1;
|
|
||||||
int rootfsname_sz;
|
|
||||||
int zipfsname_sz;
|
|
||||||
int zipcmd_sz;
|
|
||||||
u_int32_t kernel_offset = 0x90000; /* offset for the kernel inside the rootfs, default val */
|
|
||||||
u_int32_t swVer = 0;
|
|
||||||
struct file_info sysupgrade = { 0 };
|
|
||||||
struct file_info header = { 0 };
|
|
||||||
struct file_info rootfs = { 0 };
|
|
||||||
struct file_info zippedfs = { 0 };
|
|
||||||
struct file_info image = { 0 };
|
struct file_info image = { 0 };
|
||||||
|
|
||||||
char* hwID = NULL;
|
char* hwID = NULL;
|
||||||
char* hwVer = NULL;
|
char* hwVer = NULL;
|
||||||
char* rootfsname = NULL;
|
u_int32_t swVer = 0;
|
||||||
char* zipfsname = NULL;
|
|
||||||
char* zipcmd = NULL;
|
|
||||||
u_int8_t chkSum;
|
u_int8_t chkSum;
|
||||||
|
int hdr_offset;
|
||||||
|
|
||||||
if (argc == 2) {
|
while ( 1 ) {
|
||||||
struct file_info myfile = { argv[1], 0, 0 };
|
int c;
|
||||||
|
|
||||||
if (bufferFile(&myfile))
|
c = getopt(argc, argv, "b:i:r:v:f");
|
||||||
return 1;
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
chkSum = getCheckSum(myfile.file_data, myfile.file_size);
|
switch (c) {
|
||||||
printf("Checksum for File: 0x%hhX\n", chkSum);
|
case 'b':
|
||||||
|
hwID = optarg;
|
||||||
return 0;
|
break;
|
||||||
|
case 'f':
|
||||||
|
is_header = 0;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
image.file_name = optarg;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
hwVer = optarg;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
swVer = (u_int32_t) strtol(optarg, NULL, 0);
|
||||||
|
swVer = cpu_to_be32(swVer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc != 6) {
|
if (!hwID || !hwVer || !image.file_name) {
|
||||||
usage(argv);
|
usage(argv);
|
||||||
return 1;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Building fw image for sercomm devices ..\n");
|
/*
|
||||||
|
* copy input to buffer, add extra space for header/footer and return
|
||||||
|
* header position
|
||||||
|
*/
|
||||||
|
hdr_offset = copyToOutputBuf(&image);
|
||||||
|
if (hdr_offset < 0)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
/* process args */
|
DBG("Filling header: %s %s %2X %s\n", hwID, hwVer, swVer, magic);
|
||||||
hwID = argv[3];
|
|
||||||
hwVer = argv[4];
|
|
||||||
|
|
||||||
sysupgrade.file_name = argv[1];
|
strncpy(image.file_data + hdr_offset + 0, magic, 7);
|
||||||
image.file_name = argv[1];
|
memcpy(image.file_data + hdr_offset + 7, version, sizeof(version));
|
||||||
kernel_offset = (u_int32_t) strtol(argv[2], NULL, 0);
|
strncpy(image.file_data + hdr_offset + 11, hwID, 34);
|
||||||
swVer = (u_int32_t) strtol(argv[5], NULL, 0);
|
strncpy(image.file_data + hdr_offset + 45, hwVer, 10);
|
||||||
swVer = cpu_to_be32(swVer);
|
memcpy(image.file_data + hdr_offset + 55, &swVer, sizeof(swVer));
|
||||||
|
strncpy(image.file_data + hdr_offset + 63, magic, 7);
|
||||||
|
|
||||||
/* Check if files actually exist */
|
/* calculate checksum and invert checksum */
|
||||||
if (access(sysupgrade.file_name, (F_OK | R_OK))) {
|
if (is_header) {
|
||||||
/* Error */
|
chkSum = getCheckSum(image.file_data, image.file_size);
|
||||||
ERR("File not found: %s\n", sysupgrade.file_name);
|
chkSum = (chkSum ^ 0xFF) + 1;
|
||||||
goto cleanup;
|
DBG("Checksum for Image: %hhX\n", chkSum);
|
||||||
|
|
||||||
|
/* write checksum to header */
|
||||||
|
image.file_data[511] = (char) chkSum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate amount of required memory (incl. 0-term) */
|
/* overwrite input file */
|
||||||
rootfsname_sz = strlen(sysupgrade.file_name) + 7 + 1;
|
if (writeFile(&image))
|
||||||
zipfsname_sz = strlen(sysupgrade.file_name) + 7 + 4 + 1;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
/* Allocate required memory */
|
return EXIT_SUCCESS;
|
||||||
if (!(rootfsname = (char*) malloc(rootfsname_sz)) || !(zipfsname =
|
|
||||||
(char*) malloc(zipfsname_sz))) {
|
|
||||||
/* Error */
|
|
||||||
ERR("Out of memory!\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create filenames */
|
|
||||||
if (snprintf(rootfsname, rootfsname_sz, "%s.rootfs", sysupgrade.file_name)
|
|
||||||
>= rootfsname_sz
|
|
||||||
|| snprintf(zipfsname, zipfsname_sz, "%s.rootfs.zip",
|
|
||||||
sysupgrade.file_name) >= zipfsname_sz) {
|
|
||||||
/* Error */
|
|
||||||
ERR("Buffer too small!\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Buffer all files */
|
|
||||||
if (bufferFile(&sysupgrade)) {
|
|
||||||
/* Error */
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG("Building header: %s %s %2X %s\n", hwID, hwVer, swVer, magic);
|
|
||||||
|
|
||||||
/* Construct the firmware header/magic */
|
|
||||||
header.file_name = NULL;
|
|
||||||
header.file_size = HEADER_SIZE;
|
|
||||||
|
|
||||||
if (!(header.file_data = (char*) calloc(1, HEADER_SIZE))) {
|
|
||||||
/* Error */
|
|
||||||
ERR("Out of memory!\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(header.file_data + 0, magic, 7);
|
|
||||||
memcpy(header.file_data + 7, version, sizeof(version));
|
|
||||||
strncpy(header.file_data + 11, hwID, 34);
|
|
||||||
strncpy(header.file_data + 45, hwVer, 10);
|
|
||||||
memcpy(header.file_data + 55, &swVer, sizeof(swVer));
|
|
||||||
strncpy(header.file_data + 63, magic, 7);
|
|
||||||
|
|
||||||
DBG("Creating rootfs ..\n");
|
|
||||||
|
|
||||||
/* Construct a rootfs */
|
|
||||||
rootfs.file_name = rootfsname;
|
|
||||||
rootfs.file_size = ALIGN(
|
|
||||||
sysupgrade.file_size + kernel_offset + header.file_size,
|
|
||||||
ROOTFS_ALIGN);
|
|
||||||
|
|
||||||
if (!(rootfs.file_data = calloc(1, rootfs.file_size))) {
|
|
||||||
/* Error */
|
|
||||||
ERR("Out of memory!\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy Owrt image to kernel location */
|
|
||||||
memcpy(rootfs.file_data + kernel_offset, sysupgrade.file_data,
|
|
||||||
sysupgrade.file_size);
|
|
||||||
|
|
||||||
/* Append header after the owrt image. The updater searches for it */
|
|
||||||
memcpy(rootfs.file_data + kernel_offset + sysupgrade.file_size,
|
|
||||||
header.file_data, header.file_size);
|
|
||||||
|
|
||||||
/* Write to file */
|
|
||||||
if (writeFile(&rootfs)) {
|
|
||||||
/* Error */
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Construct a zip */
|
|
||||||
DBG("Preparing to zip ..\n");
|
|
||||||
|
|
||||||
/* now that we got the rootfs, repeat the whole thing again(sorta):
|
|
||||||
* 1. zip the rootfs */
|
|
||||||
zipcmd_sz = 3 + 1 + strlen(zipfsname) + 1 + strlen(rootfs.file_name) + 1;
|
|
||||||
|
|
||||||
if (!(zipcmd = malloc(zipcmd_sz))) {
|
|
||||||
/* Error */
|
|
||||||
ERR("Out of memory!\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snprintf(zipcmd, zipcmd_sz, "%s %s %s", "zip", zipfsname,
|
|
||||||
rootfs.file_name) >= zipcmd_sz) {
|
|
||||||
/* Error */
|
|
||||||
ERR("Buffer too small!\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (system(zipcmd)) {
|
|
||||||
/* Error */
|
|
||||||
ERR("Error creating a zip file!\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* and load zipped fs */
|
|
||||||
zippedfs.file_name = zipfsname;
|
|
||||||
|
|
||||||
if (bufferFile(&zippedfs)) {
|
|
||||||
/* Error */
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG("Creating Image.\n");
|
|
||||||
|
|
||||||
/* 2. create new file 512 + rootfs size */
|
|
||||||
image.file_size = zippedfs.file_size + 512;
|
|
||||||
if (!(image.file_data = malloc(zippedfs.file_size + 512))) {
|
|
||||||
/* Error */
|
|
||||||
ERR("Out of memory!\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 3. add header to file */
|
|
||||||
memcpy(image.file_data, header.file_data, header.file_size);
|
|
||||||
|
|
||||||
/* 4. clear remaining space */
|
|
||||||
if (header.file_size < 512)
|
|
||||||
memset(image.file_data + header.file_size, 0, 512 - header.file_size);
|
|
||||||
|
|
||||||
/* 5. copy zipfile at loc 512 */
|
|
||||||
memcpy(image.file_data + 512, zippedfs.file_data, zippedfs.file_size);
|
|
||||||
|
|
||||||
/* 6. do a checksum run, and compute checksum */
|
|
||||||
chkSum = getCheckSum(image.file_data, image.file_size);
|
|
||||||
|
|
||||||
DBG("Checksum for Image: %hhX\n", chkSum);
|
|
||||||
|
|
||||||
/* 7. write the checksum inverted into byte 511 to bring it to 0 on verification */
|
|
||||||
chkSum = (chkSum ^ 0xFF) + 1;
|
|
||||||
image.file_data[511] = (char) chkSum;
|
|
||||||
|
|
||||||
chkSum = getCheckSum(image.file_data, image.file_size);
|
|
||||||
DBG("Checksum for after fix: %hhX\n", chkSum);
|
|
||||||
|
|
||||||
if (chkSum != 0) {
|
|
||||||
ERR("Invalid checksum!\n")
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 8. pray that the updater will accept the file */
|
|
||||||
if (writeFile(&image)) {
|
|
||||||
/* Error */
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* All seems OK */
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
|
|
||||||
if (rootfs.file_name && !access(rootfs.file_name, F_OK | W_OK))
|
|
||||||
remove(rootfs.file_name);
|
|
||||||
|
|
||||||
if (zippedfs.file_name && !access(zippedfs.file_name, F_OK | W_OK))
|
|
||||||
remove(zippedfs.file_name);
|
|
||||||
|
|
||||||
fi_clean(&sysupgrade);
|
|
||||||
fi_clean(&header);
|
|
||||||
fi_clean(&rootfs);
|
|
||||||
fi_clean(&zippedfs);
|
|
||||||
fi_clean(&image);
|
|
||||||
|
|
||||||
if (rootfsname)
|
|
||||||
free(rootfsname);
|
|
||||||
|
|
||||||
if (zipfsname)
|
|
||||||
free(zipfsname);
|
|
||||||
|
|
||||||
if (zipcmd)
|
|
||||||
free(zipcmd);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue