fwtool: add support for extracting the truncated data part to stdout

This allows extracing the firmware + metadata from a signed firmware without
altering the original image file

Signed-off-by: Felix Fietkau <nbd@nbd.name>
openwrt-19.07
Felix Fietkau 2019-02-12 16:24:14 +01:00
parent d5681e45f0
commit 8f4e31ea6e
1 changed files with 23 additions and 2 deletions

View File

@ -43,6 +43,7 @@ struct data_buf {
static FILE *signature_file, *metadata_file, *firmware_file; static FILE *signature_file, *metadata_file, *firmware_file;
static int file_mode = MODE_DEFAULT; static int file_mode = MODE_DEFAULT;
static bool truncate_file; static bool truncate_file;
static bool write_truncated;
static bool quiet = false; static bool quiet = false;
static uint32_t crc_table[256]; static uint32_t crc_table[256];
@ -64,6 +65,7 @@ usage(const char *progname)
" -s <file>: Extract signature file from firmware image\n" " -s <file>: Extract signature file from firmware image\n"
" -i <file>: Extract metadata file from firmware image\n" " -i <file>: Extract metadata file from firmware image\n"
" -t: Remove extracted chunks from firmare image (using -s, -i)\n" " -t: Remove extracted chunks from firmare image (using -s, -i)\n"
" -T: Output firmware image without extracted chunks to stdout (using -s, -i)\n"
" -q: Quiet (suppress error messages)\n" " -q: Quiet (suppress error messages)\n"
"\n", progname); "\n", progname);
return 1; return 1;
@ -280,8 +282,10 @@ extract_data(const char *name)
struct fwimage_trailer tr; struct fwimage_trailer tr;
struct data_buf dbuf = {}; struct data_buf dbuf = {};
uint32_t crc32 = ~0; uint32_t crc32 = ~0;
int data_len = 0;
int ret = 1; int ret = 1;
void *buf; void *buf;
bool metadata_keep = false;
firmware_file = open_file(name, false); firmware_file = open_file(name, false);
if (!firmware_file) { if (!firmware_file) {
@ -301,6 +305,9 @@ extract_data(const char *name)
do { do {
char *tmp = dbuf.cur; char *tmp = dbuf.cur;
if (write_truncated && dbuf.prev)
fwrite(dbuf.prev, 1, BUFLEN, stdout);
dbuf.cur = dbuf.prev; dbuf.cur = dbuf.prev;
dbuf.prev = tmp; dbuf.prev = tmp;
@ -317,7 +324,6 @@ extract_data(const char *name)
} while (dbuf.cur_len == BUFLEN); } while (dbuf.cur_len == BUFLEN);
while (1) { while (1) {
int data_len;
if (extract_tail(&dbuf, &tr, sizeof(tr))) if (extract_tail(&dbuf, &tr, sizeof(tr)))
break; break;
@ -349,6 +355,7 @@ extract_data(const char *name)
} else if (tr.type == FWIMAGE_INFO) { } else if (tr.type == FWIMAGE_INFO) {
if (!metadata_file) { if (!metadata_file) {
dbuf.file_len += data_len + sizeof(tr); dbuf.file_len += data_len + sizeof(tr);
metadata_keep = true;
break; break;
} }
@ -368,6 +375,17 @@ extract_data(const char *name)
if (!ret && truncate_file) if (!ret && truncate_file)
ftruncate(fileno(firmware_file), dbuf.file_len); ftruncate(fileno(firmware_file), dbuf.file_len);
if (write_truncated) {
if (dbuf.prev)
fwrite(dbuf.prev, 1, BUFLEN, stdout);
if (dbuf.cur)
fwrite(dbuf.cur, 1, dbuf.cur_len, stdout);
if (metadata_keep) {
fwrite(buf, data_len, 1, stdout);
fwrite(&tr, sizeof(tr), 1, stdout);
}
}
out: out:
free(buf); free(buf);
free(dbuf.cur); free(dbuf.cur);
@ -392,7 +410,7 @@ int main(int argc, char **argv)
crc32_filltable(crc_table); crc32_filltable(crc_table);
while ((ch = getopt(argc, argv, "i:I:qs:S:t")) != -1) { while ((ch = getopt(argc, argv, "i:I:qs:S:tT")) != -1) {
ret = 0; ret = 0;
switch(ch) { switch(ch) {
case 'S': case 'S':
@ -410,6 +428,9 @@ int main(int argc, char **argv)
case 't': case 't':
truncate_file = true; truncate_file = true;
break; break;
case 'T':
write_truncated = true;
break;
case 'q': case 'q':
quiet = true; quiet = true;
break; break;