add lzop decompression support

Add lzop decompression support to the existing lzo bitstream handling
(think gzip versus zlib), and support it for uImage decompression if
CONFIG_LZO is enabled.

Lzop doesn't compress as good as gzip (~10% worse), but decompression
is very fast (~0.7s faster here on a slow ppc). The lzop decompression
code is based on Albin Tonnerre's recent ARM Linux lzo support patch.

Cc: albin.tonnerre@free-electrons.com
Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
master
Peter Korsgaard 15 years ago committed by Wolfgang Denk
parent 3eb90bad65
commit 20dde48bca
  1. 22
      common/cmd_bootm.c
  2. 1
      common/image.c
  3. 1
      include/image.h
  4. 4
      include/linux/lzo.h
  5. 87
      lib_generic/lzo/lzo1x_decompress.c

@ -57,6 +57,10 @@
#include <lzma/LzmaTools.h>
#endif /* CONFIG_LZMA */
#ifdef CONFIG_LZO
#include <linux/lzo.h>
#endif /* CONFIG_LZO */
DECLARE_GLOBAL_DATA_PTR;
extern int gunzip (void *dst, int dstlen, unsigned char *src, unsigned long *lenp);
@ -405,6 +409,24 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)
*load_end = load + unc_len;
break;
#endif /* CONFIG_LZMA */
#ifdef CONFIG_LZO
case IH_COMP_LZO:
printf (" Uncompressing %s ... ", type_name);
int ret = lzop_decompress((const unsigned char *)image_start,
image_len, (unsigned char *)load,
&unc_len);
if (ret != LZO_E_OK) {
printf ("LZO: uncompress or overwrite error %d "
"- must RESET board to recover\n", ret);
if (boot_progress)
show_boot_progress (-6);
return BOOTM_ERR_RESET;
}
*load_end = load + unc_len;
break;
#endif /* CONFIG_LZO */
default:
printf ("Unimplemented compression type %d\n", comp);
return BOOTM_ERR_UNIMPLEMENTED;

@ -148,6 +148,7 @@ static table_entry_t uimage_comp[] = {
{ IH_COMP_BZIP2, "bzip2", "bzip2 compressed", },
{ IH_COMP_GZIP, "gzip", "gzip compressed", },
{ IH_COMP_LZMA, "lzma", "lzma compressed", },
{ IH_COMP_LZO, "lzo", "lzo compressed", },
{ -1, "", "", },
};

@ -164,6 +164,7 @@
#define IH_COMP_GZIP 1 /* gzip Compression Used */
#define IH_COMP_BZIP2 2 /* bzip2 Compression Used */
#define IH_COMP_LZMA 3 /* lzma Compression Used */
#define IH_COMP_LZO 4 /* lzo Compression Used */
#define IH_MAGIC 0x27051956 /* Image Magic Number */
#define IH_NMLEN 32 /* Image Name Length */

@ -27,6 +27,10 @@ int lzo1x_1_compress(const unsigned char *src, size_t src_len,
int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
unsigned char *dst, size_t *dst_len);
/* decompress lzop format */
int lzop_decompress(const unsigned char *src, size_t src_len,
unsigned char *dst, size_t *dst_len);
/*
* Return values (< 0 = Error)
*/

@ -24,6 +24,93 @@
#define COPY4(dst, src) \
put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
static const unsigned char lzop_magic[] = {
0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
};
#define HEADER_HAS_FILTER 0x00000800L
static inline const unsigned char *parse_header(const unsigned char *src)
{
u8 level = 0;
u16 version;
int i;
/* read magic: 9 first bytes */
for (i = 0; i < ARRAY_SIZE(lzop_magic); i++) {
if (*src++ != lzop_magic[i])
return NULL;
}
/* get version (2bytes), skip library version (2),
* 'need to be extracted' version (2) and
* method (1) */
version = get_unaligned_be16(src);
src += 7;
if (version >= 0x0940)
level = *src++;
if (get_unaligned_be32(src) & HEADER_HAS_FILTER)
src += 4; /* filter info */
/* skip flags, mode and mtime_low */
src += 12;
if (version >= 0x0940)
src += 4; /* skip mtime_high */
i = *src++;
/* don't care about the file name, and skip checksum */
src += i + 4;
return src;
}
int lzop_decompress(const unsigned char *src, size_t src_len,
unsigned char *dst, size_t *dst_len)
{
unsigned char *start = dst;
const unsigned char *send = src + src_len;
u32 slen, dlen;
size_t tmp;
int r;
src = parse_header(src);
if (!src)
return LZO_E_ERROR;
while (src < send) {
/* read uncompressed block size */
dlen = get_unaligned_be32(src);
src += 4;
/* exit if last block */
if (dlen == 0) {
*dst_len = dst - start;
return LZO_E_OK;
}
/* read compressed block size, and skip block checksum info */
slen = get_unaligned_be32(src);
src += 8;
if (slen <= 0 || slen > dlen)
return LZO_E_ERROR;
/* decompress */
tmp = dlen;
r = lzo1x_decompress_safe((u8 *) src, slen, dst, &tmp);
if (r != LZO_E_OK)
return r;
if (dlen != tmp)
return LZO_E_ERROR;
src += slen;
dst += dlen;
}
return LZO_E_INPUT_OVERRUN;
}
int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
unsigned char *out, size_t *out_len)
{

Loading…
Cancel
Save