浏览代码

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 <[email protected]>
Felix Fietkau 6 年之前
父节点
当前提交
8f4e31ea6e
共有 1 个文件被更改,包括 23 次插入2 次删除
  1. 23 2
      package/system/fwtool/src/fwtool.c

+ 23 - 2
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 <file>:		Extract signature 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:			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;