From 8f4e31ea6eeb3ff70aea8cda53d4ec66ac460ae0 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 12 Feb 2019 16:24:14 +0100 Subject: [PATCH] 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 --- package/system/fwtool/src/fwtool.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/package/system/fwtool/src/fwtool.c b/package/system/fwtool/src/fwtool.c index 505fafcf7a7..3adc1e02492 100644 --- a/package/system/fwtool/src/fwtool.c +++ b/package/system/fwtool/src/fwtool.c @@ -43,6 +43,7 @@ struct data_buf { static FILE *signature_file, *metadata_file, *firmware_file; static int file_mode = MODE_DEFAULT; static bool truncate_file; +static bool write_truncated; static bool quiet = false; static uint32_t crc_table[256]; @@ -64,6 +65,7 @@ usage(const char *progname) " -s : Extract signature file from firmware image\n" " -i : Extract metadata file from firmware image\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" "\n", progname); return 1; @@ -280,8 +282,10 @@ extract_data(const char *name) struct fwimage_trailer tr; struct data_buf dbuf = {}; uint32_t crc32 = ~0; + int data_len = 0; int ret = 1; void *buf; + bool metadata_keep = false; firmware_file = open_file(name, false); if (!firmware_file) { @@ -301,6 +305,9 @@ extract_data(const char *name) do { char *tmp = dbuf.cur; + if (write_truncated && dbuf.prev) + fwrite(dbuf.prev, 1, BUFLEN, stdout); + dbuf.cur = dbuf.prev; dbuf.prev = tmp; @@ -317,7 +324,6 @@ extract_data(const char *name) } while (dbuf.cur_len == BUFLEN); while (1) { - int data_len; if (extract_tail(&dbuf, &tr, sizeof(tr))) break; @@ -349,6 +355,7 @@ extract_data(const char *name) } else if (tr.type == FWIMAGE_INFO) { if (!metadata_file) { dbuf.file_len += data_len + sizeof(tr); + metadata_keep = true; break; } @@ -368,6 +375,17 @@ extract_data(const char *name) if (!ret && truncate_file) 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: free(buf); free(dbuf.cur); @@ -392,7 +410,7 @@ int main(int argc, char **argv) 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; switch(ch) { case 'S': @@ -410,6 +428,9 @@ int main(int argc, char **argv) case 't': truncate_file = true; break; + case 'T': + write_truncated = true; + break; case 'q': quiet = true; break;