summaryrefslogtreecommitdiffstats
path: root/utils/nwztools/upgtools/upgtool.c
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2020-07-21 15:15:10 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2020-10-11 13:08:03 +0200
commit1b5e82440549ab161e26863baa1bb06cc9f2aa64 (patch)
treebcc40634dcd7720de1a950174a9c1d2b2a291ce7 /utils/nwztools/upgtools/upgtool.c
parent1f338f70789fdb7d6bbd954cc1444f59a156e83c (diff)
downloadrockbox-1b5e824405.tar.gz
rockbox-1b5e824405.zip
nwztool/upgtool: add support for compression
To decompress some output file(s), simply pass -z <idx> where idx is the index of the file to decompress, starting from 0. For example upgtool -e NW_WM_FW.UPG -o tmp/ -m nw-wm1a -z 6 -z 7 to decompress files 6 and 7. To compress file, use the same options: upgtool -c NW_WM_FW.UPG -m nw-wm1a -z 2 script.sh md5sum.txt system.img Change-Id: I1ef0b3e02c98e58154f1a959fb1ad70ad2ce6500
Diffstat (limited to 'utils/nwztools/upgtools/upgtool.c')
-rw-r--r--utils/nwztools/upgtools/upgtool.c107
1 files changed, 96 insertions, 11 deletions
diff --git a/utils/nwztools/upgtools/upgtool.c b/utils/nwztools/upgtools/upgtool.c
index 81cb4aa939..8a9194ebe4 100644
--- a/utils/nwztools/upgtools/upgtool.c
+++ b/utils/nwztools/upgtools/upgtool.c
@@ -29,6 +29,7 @@
#include <ctype.h>
#include "misc.h"
#include <sys/stat.h>
+#include <zlib.h>
#include "keysig_search.h"
#include "upg.h"
@@ -46,17 +47,11 @@ static char *g_kas = NULL;
static char *g_key = NULL;
static char *g_sig = NULL;
static int g_nr_threads = 1;
+#define MAX_NR_FILES 32
+bool g_compress[MAX_NR_FILES] = {false};
enum keysig_search_method_t g_keysig_search = KEYSIG_SEARCH_NONE;
-#define let_the_force_flow(x) do { if(!g_force) return x; } while(0)
-#define continue_the_force(x) if(x) let_the_force_flow(x)
-
-#define check_field(v_exp, v_have, str_ok, str_bad) \
- if((v_exp) != (v_have)) \
- { cprintf(RED, str_bad); let_the_force_flow(__LINE__); } \
- else { cprintf(RED, str_ok); }
-
#define cprintf(col, ...) do {color(col); printf(__VA_ARGS__); }while(0)
#define cprintf_field(str1, ...) do{ cprintf(GREEN, str1); cprintf(YELLOW, __VA_ARGS__); }while(0)
@@ -176,7 +171,51 @@ static int do_upg(void *buf, long size)
continue;
}
free(str);
- fwrite(file->files[i].data, 1, file->files[i].size, f);
+ if(g_compress[i])
+ {
+ void *buf = file->files[i].data;
+ int size = file->files[i].size;
+ int pos = 0;
+ /* the fwpup tool seems to assume that every block decompresses to less than 4096 bytes,
+ * so I guess the encoder splits the input in chunks */
+ int max_chunk_size = 4096;
+ void *chunk = malloc(max_chunk_size);
+ if(g_debug)
+ cprintf(GREY, "decompressing file %d with chunk size %d...\n", i, max_chunk_size);
+ while(pos + 4 <= size)
+ {
+ int compressed_chunk_size = *(uint32_t *)(buf + pos);
+ if(g_debug)
+ cprintf(GREY, "%d ", compressed_chunk_size);
+ if(compressed_chunk_size < 0)
+ {
+ cprintf(RED, "invalid block size when decompressing, something is wrong\n");
+ break;
+ }
+ if(compressed_chunk_size == 0)
+ break;
+ uLongf chunk_size = max_chunk_size;
+ int zres = uncompress(chunk, &chunk_size, buf + pos + 4, compressed_chunk_size);
+ if(zres == Z_BUF_ERROR)
+ cprintf(RED, "the encoder produced a block greater than %d, I can't handle that\n", max_chunk_size);
+ if(zres == Z_DATA_ERROR)
+ cprintf(RED, "the compressed data seems corrupted\n");
+ if(zres != Z_OK)
+ {
+ cprintf(RED, "the compressed suffered an error %d\n", zres);
+ break;
+ }
+ pos += 4 + compressed_chunk_size;
+ fwrite(chunk, 1, chunk_size, f);
+ }
+ free(chunk);
+ if(g_debug)
+ cprintf(GREY, "done.");
+ }
+ else
+ {
+ fwrite(file->files[i].data, 1, file->files[i].size, f);
+ }
fclose(f);
}
upg_free(file);
@@ -277,7 +316,40 @@ static int create_upg(int argc, char **argv)
return 1;
}
fclose(f);
- upg_append(upg, buf, size);
+ if(g_compress[i])
+ {
+ int out_buf_max_sz = size; /* we expect that the output will not take more space */
+ void *out_buf = malloc(out_buf_max_sz);
+ int out_buf_pos = 0, in_buf_pos = 0;
+ int max_chunk_size = 4096; /* the OF encoder/decoder expect that */
+ while(in_buf_pos < size)
+ {
+ int chunk_size = MIN(size - in_buf_pos, max_chunk_size);
+ uLongf dest_len = out_buf_max_sz - out_buf_pos - 4; /* we reserve 4 for the size */
+ int zres = compress(out_buf + out_buf_pos + 4, &dest_len, buf + in_buf_pos, chunk_size);
+ if(zres == Z_BUF_ERROR)
+ {
+ cprintf(RED, "the compresser produced a file greater than its input, I can't handle that\n");
+ return 1;
+ }
+ else if(zres != Z_OK)
+ {
+ cprintf(RED, "the compresser suffered an error %d\n", zres);
+ return 1;
+ }
+ /* write output size in the output buffer */
+ *(uint32_t *)(out_buf + out_buf_pos) = dest_len;
+ out_buf_pos += 4 + dest_len;
+ in_buf_pos += chunk_size;
+ }
+ /* add an extra zero-length chunk */
+ *(uint32_t *)(out_buf + out_buf_pos) = 0;
+ out_buf_pos += 4;
+ upg_append(upg, out_buf, out_buf_pos);
+ free(buf);
+ }
+ else
+ upg_append(upg, buf, size);
}
size_t size = 0;
@@ -325,6 +397,7 @@ static void usage(void)
printf(" -s/--sig <sig>\tForce sig\n");
printf(" -e/--extract\t\tExtract a UPG archive\n");
printf(" -c/--create\t\tCreate a UPG archive\n");
+ printf(" -z/--compress <idx>\t\t(De)compress file <idx> (starts at 0)\n");
printf("keysig search method:\n");
for(int i = KEYSIG_SEARCH_FIRST; i < KEYSIG_SEARCH_LAST; i++)
printf(" %-10s\t%s\n", keysig_search_desc[i].name, keysig_search_desc[i].comment);
@@ -355,10 +428,11 @@ int main(int argc, char **argv)
{"extract", no_argument, 0, 'e'},
{"create", no_argument, 0 ,'c'},
{"threads", required_argument, 0, 't'},
+ {"compress", required_argument, 0, 'z'},
{0, 0, 0, 0}
};
- int c = getopt_long(argc, argv, "?dnfo:m:l:a:k:s:ect:", long_options, NULL);
+ int c = getopt_long(argc, argv, "?dnfo:m:l:a:k:s:ect:z:", long_options, NULL);
if(c == -1)
break;
switch(c)
@@ -418,6 +492,17 @@ int main(int argc, char **argv)
return 1;
}
break;
+ case 'z':
+ {
+ int idx = strtol(optarg, NULL, 0);
+ if(idx < 0 || idx >= MAX_NR_FILES)
+ {
+ cprintf(GREY, "Invalid file index\n");
+ return 1;
+ }
+ g_compress[idx] = true;
+ break;
+ }
default:
abort();
}