188d52c6aSLei Wen /* 288d52c6aSLei Wen * (C) Copyright 2012 388d52c6aSLei Wen * Lei Wen <leiwen@marvell.com>, Marvell Inc. 488d52c6aSLei Wen * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 688d52c6aSLei Wen */ 788d52c6aSLei Wen 888d52c6aSLei Wen #include <common.h> 988d52c6aSLei Wen #include <watchdog.h> 1088d52c6aSLei Wen #include <command.h> 1188d52c6aSLei Wen #include <image.h> 1288d52c6aSLei Wen #include <malloc.h> 13*6e295186SSimon Glass #include <memalign.h> 1488d52c6aSLei Wen #include <u-boot/zlib.h> 1588d52c6aSLei Wen #include "zlib/zutil.h" 1688d52c6aSLei Wen 1788d52c6aSLei Wen #ifndef CONFIG_GZIP_COMPRESS_DEF_SZ 1888d52c6aSLei Wen #define CONFIG_GZIP_COMPRESS_DEF_SZ 0x200 1988d52c6aSLei Wen #endif 2088d52c6aSLei Wen #define ZALLOC_ALIGNMENT 16 2188d52c6aSLei Wen 2288d52c6aSLei Wen static void *zalloc(void *x, unsigned items, unsigned size) 2388d52c6aSLei Wen { 2488d52c6aSLei Wen void *p; 2588d52c6aSLei Wen 2688d52c6aSLei Wen size *= items; 2788d52c6aSLei Wen size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); 2888d52c6aSLei Wen 294519668bSMarcel Ziswiler p = malloc_cache_aligned(size); 3088d52c6aSLei Wen 3188d52c6aSLei Wen return (p); 3288d52c6aSLei Wen } 3388d52c6aSLei Wen 3488d52c6aSLei Wen static void zfree(void *x, void *addr, unsigned nb) 3588d52c6aSLei Wen { 3688d52c6aSLei Wen free (addr); 3788d52c6aSLei Wen } 3888d52c6aSLei Wen 3988d52c6aSLei Wen int gzip(void *dst, unsigned long *lenp, 4088d52c6aSLei Wen unsigned char *src, unsigned long srclen) 4188d52c6aSLei Wen { 4288d52c6aSLei Wen return zzip(dst, lenp, src, srclen, 1, NULL); 4388d52c6aSLei Wen } 4488d52c6aSLei Wen 4588d52c6aSLei Wen /* 4688d52c6aSLei Wen * Compress blocks with zlib 4788d52c6aSLei Wen */ 4888d52c6aSLei Wen int zzip(void *dst, unsigned long *lenp, unsigned char *src, 4988d52c6aSLei Wen unsigned long srclen, int stoponerr, 5088d52c6aSLei Wen int (*func)(unsigned long, unsigned long)) 5188d52c6aSLei Wen { 5288d52c6aSLei Wen z_stream s; 5388d52c6aSLei Wen int r, flush, orig, window; 5488d52c6aSLei Wen unsigned long comp_len, left_len; 5588d52c6aSLei Wen 5688d52c6aSLei Wen if (!srclen) 5788d52c6aSLei Wen return 0; 5888d52c6aSLei Wen 5988d52c6aSLei Wen #ifndef CONFIG_GZIP 6088d52c6aSLei Wen window = MAX_WBITS; 6188d52c6aSLei Wen #else 6288d52c6aSLei Wen window = 2 * MAX_WBITS; 6388d52c6aSLei Wen #endif 6488d52c6aSLei Wen orig = *lenp; 6588d52c6aSLei Wen s.zalloc = zalloc; 6688d52c6aSLei Wen s.zfree = zfree; 6788d52c6aSLei Wen s.opaque = Z_NULL; 6888d52c6aSLei Wen 6988d52c6aSLei Wen r = deflateInit2_(&s, Z_BEST_SPEED, Z_DEFLATED, window, 7088d52c6aSLei Wen DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, 7188d52c6aSLei Wen ZLIB_VERSION, sizeof(z_stream)); 7288d52c6aSLei Wen if (r != Z_OK) { 7388d52c6aSLei Wen printf ("Error: deflateInit2_() returned %d\n", r); 7488d52c6aSLei Wen return -1; 7588d52c6aSLei Wen } 7688d52c6aSLei Wen 7788d52c6aSLei Wen while (srclen > 0) { 7888d52c6aSLei Wen comp_len = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ) ? 7988d52c6aSLei Wen CONFIG_GZIP_COMPRESS_DEF_SZ : srclen; 8088d52c6aSLei Wen 8188d52c6aSLei Wen s.next_in = src; 8288d52c6aSLei Wen s.avail_in = comp_len; 8388d52c6aSLei Wen flush = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ)? 8488d52c6aSLei Wen Z_NO_FLUSH : Z_FINISH; 8588d52c6aSLei Wen 8688d52c6aSLei Wen do { 8788d52c6aSLei Wen left_len = (*lenp > CONFIG_GZIP_COMPRESS_DEF_SZ) ? 8888d52c6aSLei Wen CONFIG_GZIP_COMPRESS_DEF_SZ : *lenp; 8988d52c6aSLei Wen s.next_out = dst; 9088d52c6aSLei Wen s.avail_out = left_len; 9188d52c6aSLei Wen r = deflate(&s, flush); 9288d52c6aSLei Wen if (r == Z_STREAM_ERROR && stoponerr == 1) { 9388d52c6aSLei Wen printf("Error: deflate() returned %d\n", r); 9488d52c6aSLei Wen r = -1; 9588d52c6aSLei Wen goto bail; 9688d52c6aSLei Wen } 9788d52c6aSLei Wen if (!func) { 9888d52c6aSLei Wen dst += (left_len - s.avail_out); 9988d52c6aSLei Wen *lenp -= (left_len - s.avail_out); 10088d52c6aSLei Wen } else if (left_len - s.avail_out > 0) { 10188d52c6aSLei Wen r = func((unsigned long)dst, 10288d52c6aSLei Wen left_len - s.avail_out); 10388d52c6aSLei Wen if (r < 0) 10488d52c6aSLei Wen goto bail; 10588d52c6aSLei Wen } 10688d52c6aSLei Wen } while (s.avail_out == 0 && (*lenp > 0)); 10788d52c6aSLei Wen if (s.avail_in) { 10888d52c6aSLei Wen printf("Deflate failed to consume %u bytes", s.avail_in); 10988d52c6aSLei Wen r = -1; 11088d52c6aSLei Wen goto bail; 11188d52c6aSLei Wen } 11288d52c6aSLei Wen if (*lenp == 0) { 11388d52c6aSLei Wen printf("Deflate need more space to compress " 11488d52c6aSLei Wen "left %lu bytes\n", srclen); 11588d52c6aSLei Wen r = -1; 11688d52c6aSLei Wen goto bail; 11788d52c6aSLei Wen } 11888d52c6aSLei Wen srclen -= comp_len; 11988d52c6aSLei Wen src += comp_len; 12088d52c6aSLei Wen } 12188d52c6aSLei Wen 12288d52c6aSLei Wen r = 0; 12388d52c6aSLei Wen bail: 12488d52c6aSLei Wen deflateEnd(&s); 12588d52c6aSLei Wen *lenp = orig - *lenp; 12688d52c6aSLei Wen return r; 12788d52c6aSLei Wen } 128