[U-Boot] [RFC PATCH] add ability to handle compressed images to imxtract

imxtract currently can not handle compressed images. This patch adds handling for bzip2 and zip compression. In both cases, a destination address has to be specified for extraction.
Signed-off-by: Wolfgang Wegner w.wegner@astro-kom.de --- common/cmd_ximg.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 77 insertions(+), 5 deletions(-)
diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c index 5593b2d..e6eb336 100644 --- a/common/cmd_ximg.c +++ b/common/cmd_ximg.c @@ -31,8 +31,20 @@ #include <common.h> #include <command.h> #include <image.h> +#include <watchdog.h> +#include <u-boot/zlib.h> +#if defined(CONFIG_BZIP2) +#include <bzlib.h> +#endif #include <asm/byteorder.h>
+/* there is no prototype in zlib.h */ +int gunzip (void *, int, unsigned char *, unsigned long *); + +#ifndef CFG_XIMG_LEN +#define CFG_XIMG_LEN 0x800000 /* use 8MByte as default max gunzip size */ +#endif + int do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { @@ -50,6 +62,8 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) const void *fit_data; size_t fit_len; #endif + uint unc_len = CFG_XIMG_LEN; + uint8_t comp;
verify = getenv_yesno ("verify");
@@ -92,8 +106,9 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; }
- if (image_get_comp (hdr) != IH_COMP_NONE) { - printf("Wrong Compression Type for %s command\n", + comp = image_get_comp (hdr); + if ((comp != IH_COMP_NONE) && (argc < 4)) { + printf("Must specify load address for %s command with compressed image\n", cmdtp->name); return 1; } @@ -138,8 +153,8 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; }
- if (fit_image_check_comp (fit_hdr, noffset, IH_COMP_NONE)) { - printf("Wrong Compression Type for %s command\n", + if ((fit_image_check_comp (fit_hdr, noffset, IH_COMP_NONE)) && (argc < 4)) { + printf("Must specify load address for %s command with compressed image\n", cmdtp->name); return 1; } @@ -158,6 +173,11 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; }
+ if (fit_image_get_comp (fit_hdr, noffset, &comp)) { + puts ("Could not find script subimage compression type\n"); + return 1; + } + data = (ulong)fit_data; len = (ulong)fit_len; break; @@ -168,7 +188,59 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) }
if (argc > 3) { - memcpy((char *) dest, (char *) data, len); + switch (comp) { + case IH_COMP_NONE: +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + { + size_t l = len; + void *to = (void *) dest; + void *from = (void *)data; + + printf (" Loading part %d ... ", part); + + while (l > 0) { + size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l; + WATCHDOG_RESET(); + memmove (to, from, tail); + to += tail; + from += tail; + l -= tail; + } + } +#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ + memmove ((char *) dest, (char *)data, len); +#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ + break; + case IH_COMP_GZIP: + printf (" Uncompressing part %d (len %d) ... ", part, len); + if (gunzip ((void *) dest, unc_len, + (uchar *) data, &len) != 0) { + puts ("GUNZIP ERROR - image not loaded\n"); + return 1; + } + break; +#if defined(CONFIG_BZIP2) + case IH_COMP_BZIP2: + printf (" Uncompressing part %d ... ", part); + /* + * If we've got less than 4 MB of malloc() space, + * use slower decompression algorithm which requires + * at most 2300 KB of memory. + */ + i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load), + &unc_len, (char *)data, len, + CFG_MALLOC_LEN < (4096 * 1024), 0); + if (i != BZ_OK) { + printf ("BUNZIP2 ERROR %d - image not loaded\n", i); + return 1; + } + break; +#endif /* CONFIG_BZIP2 */ + default: + printf ("Unimplemented compression type %d\n", comp); + return 1; + } + puts ("OK\n"); }
sprintf(pbuf, "%8lx", data);

Dear Wolfgang Wegner,
In message 1256916625-30792-1-git-send-email-w.wegner@astro-kom.de you wrote:
imxtract currently can not handle compressed images. This patch adds handling for bzip2 and zip compression. In both cases, a destination address has to be specified for extraction.
Signed-off-by: Wolfgang Wegner w.wegner@astro-kom.de
...
+/* there is no prototype in zlib.h */ +int gunzip (void *, int, unsigned char *, unsigned long *);
Then we should add it there, once.
+#ifndef CFG_XIMG_LEN +#define CFG_XIMG_LEN 0x800000 /* use 8MByte as default max gunzip size */ +#endif
CFG_ has been deprectaed a long, long time ago. Please use CONFIG_SYS_ instead.
printf("Wrong Compression Type for %s command\n",
comp = image_get_comp (hdr);
if ((comp != IH_COMP_NONE) && (argc < 4)) {
printf("Must specify load address for %s command with compressed image\n",
Line too long. (Check globally).
if (argc > 3) {
memcpy((char *) dest, (char *) data, len);
switch (comp) {
case IH_COMP_NONE:
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
{
size_t l = len;
void *to = (void *) dest;
void *from = (void *)data;
printf (" Loading part %d ... ", part);
while (l > 0) {
size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;
WATCHDOG_RESET();
memmove (to, from, tail);
to += tail;
from += tail;
l -= tail;
}
}
+#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
memmove ((char *) dest, (char *)data, len);
+#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
It seems wrong to me to have inconsistent behaviour (with printf() in the "if", without in the "else" branch).
case IH_COMP_GZIP:
printf (" Uncompressing part %d (len %d) ... ", part, len);
...
+#if defined(CONFIG_BZIP2)
case IH_COMP_BZIP2:
printf (" Uncompressing part %d ... ", part);
Inconsistent behaviour. Why do we print "len" for IH_COMP_GZIP, but not for IH_COMP_BZIP2 ?
Best regards,
Wolfgang Denk

Dear Wolfgang Denk,
On 2 Dec 2009 at 22:43, Wolfgang Denk wrote:
Dear Wolfgang Wegner,
In message 1256916625-30792-1-git-send-email-w.wegner@astro-kom.de you wrote:
imxtract currently can not handle compressed images. This patch adds handling for bzip2 and zip compression. In both cases, a destination address has to be specified for extraction.
Signed-off-by: Wolfgang Wegner w.wegner@astro-kom.de
...
+/* there is no prototype in zlib.h */ +int gunzip (void *, int, unsigned char *, unsigned long *);
Then we should add it there, once.
I have to admit I am not sure if there might be a reason why there is no prototype nor if it would belong in zlib.h at all (IIRC it was there ages ago, but then re-structured, so probably even my comment is out-dated).
The implementation is in lib_generic/gunzip.c, and it is used by 19 other files. I could add it to a header but have (at least) two problems with it: - I do not know which header would be appropriate (generate a new one like e.g. lib_generic/addr_map.c -> include/addr_map.h?) - I can not test all the boards currently using it, as they belong to completely different architectures
Any comments welcome if/how I should proceed here.
[...] Addressing the other issues in the meantime... ;-)
Best regards, Wolfgang

Dear Wolfgang,
In message 4B19116D.11160.B40573@w.wegner.astro-kom.de you wrote:
The implementation is in lib_generic/gunzip.c, and it is used by 19 other files. I could add it to a header but have (at least) two problems with it:
- I do not know which header would be appropriate (generate a new one like e.g. lib_generic/addr_map.c -> include/addr_map.h?)
If in doubt, add it to common.h; we already have a bunch of other prototypes there.
- I can not test all the boards currently using it, as they belong to completely different architectures
Test what you can, then post. Others will test the rest.
Best regards,
Wolfgang Denk

imxtract currently can not handle compressed images. This patch adds handling for bzip2 and zip compression. In both cases, a destination address has to be specified for extraction.
Signed-off-by: Wolfgang Wegner w.wegner@astro-kom.de --- This new version needs gunzip() prototype in common.h as supplied by previous patch.
common/cmd_ximg.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 85 insertions(+), 7 deletions(-)
diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c index 5593b2d..3e5fb44 100644 --- a/common/cmd_ximg.c +++ b/common/cmd_ximg.c @@ -31,8 +31,17 @@ #include <common.h> #include <command.h> #include <image.h> +#include <watchdog.h> +#if defined(CONFIG_BZIP2) +#include <bzlib.h> +#endif #include <asm/byteorder.h>
+#ifndef CONFIG_SYS_XIMG_LEN +/* use 8MByte as default max gunzip size */ +#define CONFIG_SYS_XIMG_LEN 0x800000 +#endif + int do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { @@ -50,6 +59,8 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) const void *fit_data; size_t fit_len; #endif + uint unc_len = CONFIG_SYS_XIMG_LEN; + uint8_t comp;
verify = getenv_yesno ("verify");
@@ -92,8 +103,10 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; }
- if (image_get_comp (hdr) != IH_COMP_NONE) { - printf("Wrong Compression Type for %s command\n", + comp = image_get_comp (hdr); + if ((comp != IH_COMP_NONE) && (argc < 4)) { + printf("Must specify load address for %s command " + "with compressed image\n", cmdtp->name); return 1; } @@ -138,9 +151,11 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; }
- if (fit_image_check_comp (fit_hdr, noffset, IH_COMP_NONE)) { - printf("Wrong Compression Type for %s command\n", - cmdtp->name); + if (fit_image_check_comp (fit_hdr, noffset, IH_COMP_NONE) + && (argc < 4)) { + printf("Must specify load address for %s command " + "with compressed image\n", + cmdtp->name); return 1; }
@@ -153,11 +168,18 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) }
/* get subimage data address and length */ - if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) { + if (fit_image_get_data (fit_hdr, noffset, + &fit_data, &fit_len)) { puts ("Could not find script subimage data\n"); return 1; }
+ if (fit_image_get_comp (fit_hdr, noffset, &comp)) { + puts ("Could not find script subimage " + "compression type\n"); + return 1; + } + data = (ulong)fit_data; len = (ulong)fit_len; break; @@ -168,7 +190,63 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) }
if (argc > 3) { - memcpy((char *) dest, (char *) data, len); + switch (comp) { + case IH_COMP_NONE: +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + { + size_t l = len; + size_t tail; + void *to = (void *) dest; + void *from = (void *)data; + + printf (" Loading part %d ... ", part); + + while (l > 0) { + tail = (l > CHUNKSZ) ? CHUNKSZ : l; + WATCHDOG_RESET(); + memmove (to, from, tail); + to += tail; + from += tail; + l -= tail; + } + } +#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ + printf (" Loading part %d ... ", part); + memmove ((char *) dest, (char *)data, len); +#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ + break; + case IH_COMP_GZIP: + printf (" Uncompressing part %d ... ", part); + if (gunzip ((void *) dest, unc_len, + (uchar *) data, &len) != 0) { + puts ("GUNZIP ERROR - image not loaded\n"); + return 1; + } + break; +#if defined(CONFIG_BZIP2) + case IH_COMP_BZIP2: + printf (" Uncompressing part %d ... ", part); + /* + * If we've got less than 4 MB of malloc() space, + * use slower decompression algorithm which requires + * at most 2300 KB of memory. + */ + i = BZ2_bzBuffToBuffDecompress + ((char*)ntohl(hdr->ih_load), + &unc_len, (char *)data, len, + CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); + if (i != BZ_OK) { + printf ("BUNZIP2 ERROR %d - " + "image not loaded\n", i); + return 1; + } + break; +#endif /* CONFIG_BZIP2 */ + default: + printf ("Unimplemented compression type %d\n", comp); + return 1; + } + puts ("OK\n"); }
sprintf(pbuf, "%8lx", data);

Dear Wolfgang Wegner,
In message 1260436281-31824-1-git-send-email-w.wegner@astro-kom.de you wrote:
imxtract currently can not handle compressed images. This patch adds handling for bzip2 and zip compression. In both cases, a destination address has to be specified for extraction.
Signed-off-by: Wolfgang Wegner w.wegner@astro-kom.de
This new version needs gunzip() prototype in common.h as supplied by previous patch.
common/cmd_ximg.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 85 insertions(+), 7 deletions(-)
Applied, thanks.
Best regards,
Wolfgang Denk
participants (3)
-
w.wegner@astro-kom.de
-
Wolfgang Denk
-
Wolfgang Wegner