ramips: fix netgear r6120 factory image generation
as indicated in commit c5bf408ed6
"(ramips: fix image generation for mt76x8")
more rework was needed to fix the other issues.
Building on another machine, but using the same arch, showed
the application failing again for different reasons.
Fix this by completely rewriting the application, fixing following found issues:
- buffer overflows, resulting in stack corruption
- flaws in memory requirement calculations (too small, too large)
- memory leaks
- missing bounds checking on string handling
- non-reproducable images, by using unitilized memory in checksum calculation
- missing error handling, resulting in succes on specific image errors
- endianness errors when building on BE machines
- various minor build warnings
- documentation did not match the code actions (header item locations)
- allowing input to be decimal, hex or octal now
Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
This commit is contained in:
parent
d157a76c67
commit
b4e17a7440
2 changed files with 334 additions and 186 deletions
|
@ -115,10 +115,10 @@ 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-usb2 kmod-usb-ohci
|
DEVICE_PACKAGES := kmod-usb2 kmod-usb-ohci
|
||||||
SERCOMM_KERNEL_OFFSET := 90000
|
SERCOMM_KERNEL_OFFSET := 0x90000
|
||||||
SERCOMM_HWID := CGQ
|
SERCOMM_HWID := CGQ
|
||||||
SERCOMM_HWVER := A001
|
SERCOMM_HWVER := A001
|
||||||
SERCOMM_SWVER := 0040
|
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)
|
||||||
|
|
|
@ -2,139 +2,198 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
/* #define DEBUG 1 */
|
/* #define DEBUG 1 */
|
||||||
|
|
||||||
/*
|
#ifdef DEBUG
|
||||||
* Fw Header Layout for Netgear / Sercomm devices
|
#define DBG(...) {printf(__VA_ARGS__); }
|
||||||
* */
|
#else
|
||||||
static const char *magic = "sErCoMm"; /* 7 */
|
#define DBG(...) {}
|
||||||
/* 7-11: version control/download control ? */
|
#endif
|
||||||
unsigned char version[4] = {0x00, 0x01, 0x00, 0x00};
|
|
||||||
char *hwID = ""; /* 11-43 , ASCII/HEX */
|
|
||||||
char *hwVer = ""; /* 44-57 , ASCII/HEX */
|
|
||||||
char *swVer = ""; /* 58-62 , ASCII/HEX */
|
|
||||||
/* magic again. */
|
|
||||||
|
|
||||||
|
#define ERR(...) {printf(__VA_ARGS__); }
|
||||||
|
#define ALIGN(a,b) ((a) + ((b) - ((a) % (b))))
|
||||||
|
#define ROOTFS_ALIGN 128
|
||||||
#define HEADER_SIZE 71
|
#define HEADER_SIZE 71
|
||||||
|
|
||||||
/* null bytes until 511 */
|
/*
|
||||||
u_int32_t checksum = 0xFF; /* checksum */
|
* Fw Header Layout for Netgear / Sercomm devices (bytes)
|
||||||
|
*
|
||||||
|
* Size : 512 bytes + zipped image size
|
||||||
|
*
|
||||||
|
* Locations:
|
||||||
|
* magic : 0-6 ASCII
|
||||||
|
* version: 7-11 fixed
|
||||||
|
* hwID : 11-44 ASCII
|
||||||
|
* hwVer : 45-54 ASCII
|
||||||
|
* swVer : 55-62 uint32_t in BE
|
||||||
|
* magic : 63-69 ASCII
|
||||||
|
* ChkSum : 511 Inverse value of the full image checksum while this location is 0x00
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const char* magic = "sErCoMm"; /* 7 */
|
||||||
|
|
||||||
|
/* 7-11: version control/download control ? */
|
||||||
|
static const unsigned char version[4] = { 0x00, 0x01, 0x00, 0x00 };
|
||||||
|
|
||||||
|
|
||||||
/* 512 onwards -> ZIP containing rootfs with the same Header */
|
/* 512 onwards -> ZIP containing rootfs with the same Header */
|
||||||
|
|
||||||
|
|
||||||
/* appended on rootfs for the Header. */
|
|
||||||
const int footer_size = 128;
|
|
||||||
|
|
||||||
struct file_info {
|
struct file_info {
|
||||||
char *file_name; /* name of the file */
|
char* file_name; /* name of the file */
|
||||||
char *file_data; /* data of the file in memory */
|
char* file_data; /* data of the file in memory */
|
||||||
u_int32_t file_size; /* length of the file */
|
u_int32_t file_size; /* length of the file */
|
||||||
};
|
};
|
||||||
|
|
||||||
u_int8_t getCheckSum(char *data, int len)
|
static u_int8_t getCheckSum(char* data, int len) {
|
||||||
{
|
u_int8_t new = 0;
|
||||||
|
|
||||||
int32_t previous = 0;
|
if (!data) {
|
||||||
u_int32_t new = 0;
|
ERR("Invalid pointer provided!\n");
|
||||||
|
|
||||||
for (u_int32_t i = 0; i < len; i++) {
|
|
||||||
new = (data[i] + previous) % 256;
|
|
||||||
previous = new | previous & -256;
|
|
||||||
}
|
|
||||||
return (u_int8_t) new;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *bufferFile(struct file_info *finfo, int dontload)
|
|
||||||
{
|
|
||||||
int fs = 0;
|
|
||||||
FILE *f = NULL;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("Opening file: %s\n", finfo->file_name);
|
|
||||||
#endif
|
|
||||||
f = fopen(finfo->file_name, "rb");
|
|
||||||
if (f == NULL) {
|
|
||||||
perror("Error");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fseek(f, 0L, SEEK_END);
|
|
||||||
fs = ftell(f);
|
|
||||||
rewind(f);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("Filesize: %i .\n", fs);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
finfo->file_size = fs;
|
|
||||||
|
|
||||||
if (dontload) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *data = malloc(fs);
|
for (int i = 0; i < len; i++) {
|
||||||
finfo->file_data = data;
|
new += data[i];
|
||||||
|
|
||||||
int read = fread(data, fs, 1, f);
|
|
||||||
|
|
||||||
if (read != 1) {
|
|
||||||
printf("Error reading file %s.", finfo->file_name);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
return new;
|
||||||
printf("File: read successfully %i bytes.\n", read*fs);
|
|
||||||
#endif
|
|
||||||
fclose(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *writeFile(struct file_info *finfo)
|
static int bufferFile(struct file_info* finfo) {
|
||||||
{
|
int fs = 0;
|
||||||
|
FILE* fp = NULL;
|
||||||
|
|
||||||
#ifdef DEBUG
|
if (!finfo || !finfo->file_name) {
|
||||||
printf("Writing file: %s.\n", finfo->file_name);
|
ERR("Invalid pointer provided!\n");
|
||||||
#endif
|
return -1;
|
||||||
|
|
||||||
FILE *fout = fopen(finfo->file_name, "w");
|
|
||||||
|
|
||||||
if (!fwrite(finfo->file_data, finfo->file_size, 1, fout)) {
|
|
||||||
printf("Wanted to write, but something went wrong.\n");
|
|
||||||
fclose(fout);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
fclose(fout);
|
|
||||||
|
DBG("Opening file: %s\n", finfo->file_name);
|
||||||
|
|
||||||
|
if (!(fp = fopen(finfo->file_name, "rb"))) {
|
||||||
|
ERR("Error opening file: %s\n", finfo->file_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get filesize */
|
||||||
|
rewind(fp);
|
||||||
|
fseek(fp, 0L, SEEK_END);
|
||||||
|
fs = ftell(fp);
|
||||||
|
rewind(fp);
|
||||||
|
|
||||||
|
if (fs < 0) {
|
||||||
|
ERR("Error getting filesize: %s\n", finfo->file_name);
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG("Filesize: %i\n", fs);
|
||||||
|
finfo->file_size = fs;
|
||||||
|
|
||||||
|
if (!(finfo->file_data = malloc(fs))) {
|
||||||
|
ERR("Out of memory!\n");
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread(finfo->file_data, 1, fs, fp) != fs) {
|
||||||
|
ERR("Error reading file %s\n", finfo->file_name);
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG("File: read successful\n");
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *rmFile(struct file_info *finfo)
|
static int writeFile(struct file_info* finfo) {
|
||||||
{
|
FILE* fp;
|
||||||
remove(finfo->file_name);
|
|
||||||
free(finfo->file_data);
|
if (!finfo || !finfo->file_name) {
|
||||||
|
ERR("Invalid pointer provided!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG("Opening file: %s\n", finfo->file_name);
|
||||||
|
|
||||||
|
if (!(fp = fopen(finfo->file_name, "w"))) {
|
||||||
|
ERR("Error opening file: %s\n", finfo->file_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG("Writing file: %s\n", finfo->file_name);
|
||||||
|
|
||||||
|
if (fwrite(finfo->file_data, 1, finfo->file_size, fp) != finfo->file_size) {
|
||||||
|
ERR("Wanted to write, but something went wrong!\n");
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
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;
|
finfo->file_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *usage(char *argv[])
|
static void usage(char* argv[]) {
|
||||||
{
|
printf("Usage: %s <sysupgradefile> <kernel_offset> <HWID> <HWVER> <SWID>\n"
|
||||||
printf("Usage: %s <sysupgradefile> <kernel_offset> <HWID> <HWVER> <SWID>\n"
|
"All are positional arguments ... \n"
|
||||||
"All are positional arguments ... \n"
|
" sysupgradefile: File with the kernel uimage at 0\n"
|
||||||
" sysupgradefile: File with the kernel uimage at 0\n"
|
" kernel_offset: Offset where the kernel is located (decimal, hex or octal notation)\n"
|
||||||
" kernel_offset: Offset in Hex where the kernel is located\n"
|
" HWID: Hardware ID, ASCII\n"
|
||||||
" HWID: Hardware ID, ASCII\n"
|
" HWVER: Hardware Version, ASCII\n"
|
||||||
" HWVER: Hardware Version, ASCII\n"
|
" SWID: Software Version (decimal, hex or octal notation)\n"
|
||||||
" SWID: Software Version, Hex\n"
|
" \n"
|
||||||
" \n"
|
, argv[0]);
|
||||||
" ", argv[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char* argv[]) {
|
||||||
{
|
int ret = 1;
|
||||||
printf("Building fw image for sercomm devices.\n");
|
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 };
|
||||||
|
char* hwID = NULL;
|
||||||
|
char* hwVer = NULL;
|
||||||
|
char* rootfsname = NULL;
|
||||||
|
char* zipfsname = NULL;
|
||||||
|
char* zipcmd = NULL;
|
||||||
|
u_int8_t chkSum;
|
||||||
|
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
struct file_info myfile = {argv[1], 0, 0};
|
struct file_info myfile = { argv[1], 0, 0 };
|
||||||
bufferFile(&myfile, 0);
|
|
||||||
char chksum = getCheckSum(myfile.file_data, myfile.file_size);
|
if (bufferFile(&myfile))
|
||||||
printf("Checksum for File: %X.\n", chksum);
|
return 1;
|
||||||
|
|
||||||
|
chkSum = getCheckSum(myfile.file_data, myfile.file_size);
|
||||||
|
printf("Checksum for File: 0x%hhX\n", chkSum);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,113 +202,202 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Args */
|
printf("Building fw image for sercomm devices ..\n");
|
||||||
|
|
||||||
struct file_info sysupgrade = {argv[1], 0, 0};
|
/* process args */
|
||||||
bufferFile(&sysupgrade, 0);
|
hwID = argv[3];
|
||||||
|
hwVer = argv[4];
|
||||||
|
|
||||||
int kernel_offset = 0x90000; /* offset for the kernel inside the rootfs, default val */
|
sysupgrade.file_name = argv[1];
|
||||||
sscanf(argv[2], "%X", &kernel_offset);
|
image.file_name = argv[1];
|
||||||
#ifdef DEBUG
|
kernel_offset = (u_int32_t) strtol(argv[2], NULL, 0);
|
||||||
printf("Kernel_offset: at %X/%i bytes.\n", kernel_offset, kernel_offset);
|
swVer = (u_int32_t) strtol(argv[5], NULL, 0);
|
||||||
#endif
|
swVer = __cpu_to_be32(swVer);
|
||||||
char *hwID = argv[3];
|
|
||||||
char *hwVer = argv[4];
|
|
||||||
u_int32_t swVer = 0;
|
|
||||||
sscanf(argv[5],"%4X",&swVer);
|
|
||||||
swVer = bswap_32(swVer);
|
|
||||||
|
|
||||||
char *rootfsname = malloc(2*strlen(sysupgrade.file_name) + 8);
|
/* Check if files actually exist */
|
||||||
sprintf(rootfsname, "%s.rootfs", sysupgrade.file_name);
|
if (access(sysupgrade.file_name, (F_OK | R_OK))) {
|
||||||
|
/* Error */
|
||||||
|
ERR("File not found: %s\n", sysupgrade.file_name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
char *zipfsname = malloc(2*strlen(rootfsname) + 5);
|
/* Calculate amount of required memory (incl. 0-term) */
|
||||||
sprintf(zipfsname, "%s.zip", rootfsname);
|
rootfsname_sz = strlen(sysupgrade.file_name) + 7 + 1;
|
||||||
/* / Args */
|
zipfsname_sz = strlen(sysupgrade.file_name) + 7 + 4 + 1;
|
||||||
|
|
||||||
|
/* Allocate required memory */
|
||||||
|
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);
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("Building header: %s %s %2X %s.\n", hwID , hwVer, swVer, magic);
|
|
||||||
#endif
|
|
||||||
/* Construct the firmware header/magic */
|
/* Construct the firmware header/magic */
|
||||||
struct file_info header = {0, 0, 0};
|
header.file_name = NULL;
|
||||||
header.file_size = HEADER_SIZE;
|
header.file_size = HEADER_SIZE;
|
||||||
header.file_data = malloc(HEADER_SIZE);
|
|
||||||
bzero(header.file_data, header.file_size);
|
|
||||||
|
|
||||||
char *tg = header.file_data;
|
if (!(header.file_data = (char*) calloc(1, HEADER_SIZE))) {
|
||||||
strcpy(tg, magic);
|
/* Error */
|
||||||
memcpy(tg+7, version, 4*sizeof(char));
|
ERR("Out of memory!\n");
|
||||||
strcpy(tg+11, hwID);
|
goto cleanup;
|
||||||
strcpy(tg+45, hwVer);
|
}
|
||||||
memcpy(tg+55, &swVer,sizeof(u_int32_t));
|
|
||||||
strcpy(tg+63, magic);
|
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");
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("Header done, now creating rootfs.");
|
|
||||||
#endif
|
|
||||||
/* Construct a rootfs */
|
/* Construct a rootfs */
|
||||||
struct file_info rootfs = {0, 0, 0};
|
|
||||||
rootfs.file_size = sysupgrade.file_size + kernel_offset + footer_size;
|
|
||||||
rootfs.file_data = malloc(rootfs.file_size);
|
|
||||||
bzero(rootfs.file_data, rootfs.file_size);
|
|
||||||
rootfs.file_name = rootfsname;
|
rootfs.file_name = rootfsname;
|
||||||
|
rootfs.file_size = ALIGN(
|
||||||
|
sysupgrade.file_size + kernel_offset + header.file_size,
|
||||||
|
ROOTFS_ALIGN);
|
||||||
|
|
||||||
/* copy Owrt image to Kernel location */
|
if (!(rootfs.file_data = calloc(1, rootfs.file_size))) {
|
||||||
memcpy(rootfs.file_data+kernel_offset, sysupgrade.file_data, sysupgrade.file_size);
|
/* Error */
|
||||||
|
ERR("Out of memory!\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* 22 added to get away from sysup image, no other reason.
|
/* copy Owrt image to kernel location */
|
||||||
* updater searches for magic anyway */
|
memcpy(rootfs.file_data + kernel_offset, sysupgrade.file_data,
|
||||||
tg = rootfs.file_data + kernel_offset + sysupgrade.file_size+22;
|
sysupgrade.file_size);
|
||||||
|
|
||||||
memcpy(tg, header.file_data, header.file_size);
|
/* Append header after the owrt image. The updater searches for it */
|
||||||
writeFile(&rootfs);
|
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");
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("Preparing to zip.\n");
|
|
||||||
#endif
|
|
||||||
/* now that we got the rootfs, repeat the whole thing again(sorta):
|
/* now that we got the rootfs, repeat the whole thing again(sorta):
|
||||||
* 1. zip the rootfs */
|
* 1. zip the rootfs */
|
||||||
char *zipper = malloc(5 + 2*strlen(rootfs.file_name) + 6);
|
zipcmd_sz = 3 + 1 + strlen(zipfsname) + 1 + strlen(rootfs.file_name) + 1;
|
||||||
sprintf(zipper, "%s %s %s", "zip ", zipfsname, rootfs.file_name);
|
|
||||||
int ret = system(zipper);
|
|
||||||
|
|
||||||
/* clear rootfs file */
|
if (!(zipcmd = malloc(zipcmd_sz))) {
|
||||||
rmFile(&rootfs);
|
/* 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 */
|
/* and load zipped fs */
|
||||||
struct file_info zippedfs = {zipfsname, 0, 0};
|
zippedfs.file_name = zipfsname;
|
||||||
bufferFile(&zippedfs, 0);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
if (bufferFile(&zippedfs)) {
|
||||||
printf("Creating Image.\n");
|
/* Error */
|
||||||
#endif
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* 2. create new file 512+rootfs size */
|
DBG("Creating Image.\n");
|
||||||
struct file_info image = {argv[1], 0, 0};
|
|
||||||
image.file_data = malloc(zippedfs.file_size + 512);
|
/* 2. create new file 512 + rootfs size */
|
||||||
image.file_size = zippedfs.file_size + 512;
|
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. copy zipfile at loc 512 */
|
/* 3. add header to file */
|
||||||
memcpy(image.file_data+512, zippedfs.file_data, zippedfs.file_size);
|
|
||||||
rmFile(&zippedfs);
|
|
||||||
|
|
||||||
/* 4. add header to file */
|
|
||||||
memcpy(image.file_data, header.file_data, header.file_size);
|
memcpy(image.file_data, header.file_data, header.file_size);
|
||||||
|
|
||||||
/* 5. do a checksum run, and compute checksum */
|
/* 4. clear remaining space */
|
||||||
char chksum = getCheckSum(image.file_data, image.file_size);
|
if (header.file_size < 512)
|
||||||
#ifdef DEBUG
|
memset(image.file_data + header.file_size, 0, 512 - header.file_size);
|
||||||
printf("Checksum for Image: %X.\n", chksum);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 6. write the checksum invert into byte 511 to bring it to 0 */
|
/* 5. copy zipfile at loc 512 */
|
||||||
chksum = (chksum ^ 0xFF) + 1;
|
memcpy(image.file_data + 512, zippedfs.file_data, zippedfs.file_size);
|
||||||
memcpy(image.file_data+511, &chksum, 1);
|
|
||||||
|
|
||||||
chksum = getCheckSum(image.file_data, image.file_size);
|
/* 6. do a checksum run, and compute checksum */
|
||||||
#ifdef DEBUG
|
chkSum = getCheckSum(image.file_data, image.file_size);
|
||||||
printf("Checksum for after fix: %X.\n", chksum);
|
|
||||||
#endif
|
DBG("Checksum for Image: %hhX\n", chkSum);
|
||||||
/* 7. pray that the updater will accept the file */
|
|
||||||
writeFile(&image);
|
/* 7. write the checksum inverted into byte 511 to bring it to 0 on verification */
|
||||||
return 0;
|
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 a new issue