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>
This commit is contained in:
parent
3eb90bad65
commit
20dde48bca
@ -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…
Reference in New Issue
Block a user