summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>2011-01-28 11:13:24 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2011-01-28 19:05:00 +0100
commita3463cc12877f6527624972c190a80ebb787a604 (patch)
tree3cbef39445fa1f457b607e86d21d25bd45d94e58
parent488fbba21f89e517089a99f5cea20aa3ad4bce62 (diff)
downloadbarebox-a3463cc12877f6527624972c190a80ebb787a604.tar.gz
barebox-a3463cc12877f6527624972c190a80ebb787a604.tar.xz
lib/decompress_unlzo: use fill and full to read and write data
this will all to simplify the sync with the kernel and later easly add the self decompression support to barebox as example with a lzo compression will reduce barebox from 180224 to 99863 bytes so 55.41% -rwxr-xr-x 1 root root 99863 Jan 28 02:17 build/versatilepb/barebox.bin.lzo we also reduce the binary size by 224 bytes Old version # ls -al build/versatilepb/barebox.bin -rwxr-xr-x 1 root root 180468 Jan 28 02:14 build/versatilepb/barebox.bin New version # ls -al build/versatilepb/barebox* -rwxr-xr-x 1 root root 180244 Jan 28 02:13 build/versatilepb/barebox.bin Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--lib/decompress_unlzo.c180
1 files changed, 92 insertions, 88 deletions
diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c
index 8f9cdcf27b..fc5c49f455 100644
--- a/lib/decompress_unlzo.c
+++ b/lib/decompress_unlzo.c
@@ -47,98 +47,73 @@ static const unsigned char lzop_magic[] = {
#define LZO_BLOCK_SIZE (256*1024l)
#define HEADER_HAS_FILTER 0x00000800L
-static inline int parse_header(int in_fd)
+static inline int parse_header(u8 *input, u8 *skip)
{
- u8 l;
+ int l;
+ u8 *parse = input;
+ u8 level = 0;
u16 version;
- int ret;
- unsigned char buf[256]; /* maximum filename length + 1 */
- /* read magic (9), library version (2), 'need to be extracted'
- * version (2) and method (1)
- */
- ret = read(in_fd, buf, 9);
- if (ret < 0)
- return ret;
-
- /* check magic */
+ /* read magic: 9 first bits */
for (l = 0; l < 9; l++) {
- if (buf[l] != lzop_magic[l])
- return -EINVAL;
+ if (*parse++ != lzop_magic[l])
+ return 0;
}
-
- ret = read(in_fd, buf, 4); /* version, lib_version */
- if (ret < 0)
- return ret;
- version = get_unaligned_be16(buf);
-
- if (version >= 0x0940) {
- ret = read(in_fd, buf, 2); /* version to extract */
- if (ret < 0)
- return ret;
- }
-
- ret = read(in_fd, buf, 1); /* method */
- if (ret < 0)
- return ret;
-
+ /* get version (2bytes), skip library version (2),
+ * 'need to be extracted' version (2) and
+ * method (1) */
+ version = get_unaligned_be16(parse);
+ parse += 7;
if (version >= 0x0940)
- read(in_fd, buf, 1); /* level */
-
- ret = read(in_fd, buf, 4); /* flags */
- if (ret < 0)
- return ret;
-
- if (get_unaligned_be32(buf) & HEADER_HAS_FILTER) {
- ret = read(in_fd, buf, 4); /* skip filter info */
- if (ret < 0)
- return ret;
- }
+ level = *parse++;
+ if (get_unaligned_be32(parse) & HEADER_HAS_FILTER)
+ parse += 8; /* flags + filter info */
+ else
+ parse += 4; /* flags */
/* skip mode and mtime_low */
- ret = read(in_fd, buf, 8);
- if (ret < 0)
- return ret;
-
- if (version >= 0x0940) {
- ret = read(in_fd, buf, 4); /* skip mtime_high */
- if (ret < 0)
- return ret;
- }
+ parse += 8;
+ if (version >= 0x0940)
+ parse += 4; /* skip mtime_high */
- ret = read(in_fd, &l, 1);
- if (ret < 0)
- return ret;
+ l = *parse++;
/* don't care about the file name, and skip checksum */
- ret = read(in_fd, buf, l + 4);
- if (ret < 0)
- return ret;
+ parse += l + 4;
- return 0;
+ *skip = parse - input;
+ return 1;
}
-int unlzo(int in_fd, int out_fd, int *dest_len)
+static int __unlzo(int *dest_len,
+ int (*fill) (void *, unsigned int),
+ int (*flush) (void *, unsigned int))
{
- u8 r = 0;
+ u8 skip = 0, r = 0;
u32 src_len, dst_len;
size_t tmp;
- u8 *in_buf, *out_buf;
+ u8 *in_buf, *in_buf_save, *out_buf, *out_buf_save;
int obytes_processed = 0;
- unsigned char buf[8];
- int ret;
-
- if (parse_header(in_fd))
- return -EINVAL;
+ int ret = -1;
out_buf = xmalloc(LZO_BLOCK_SIZE);
in_buf = xmalloc(lzo1x_worst_compress(LZO_BLOCK_SIZE));
+ in_buf_save = in_buf;
+ out_buf_save = out_buf;
+
+ ret = fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
+ if (ret < 0)
+ goto exit_free;
+
+ if (!parse_header(in_buf, &skip))
+ return -EINVAL;
+
+ in_buf += skip;
+
for (;;) {
/* read uncompressed block size */
- ret = read(in_fd, buf, 4);
- if (ret < 0)
- goto exit_free;
- dst_len = get_unaligned_be32(buf);
+ dst_len = get_unaligned_be32(in_buf);
+ in_buf += 4;
/* exit if last block */
if (dst_len == 0)
@@ -150,43 +125,53 @@ int unlzo(int in_fd, int out_fd, int *dest_len)
}
/* read compressed block size, and skip block checksum info */
- ret = read(in_fd, buf, 8);
- if (ret < 0)
- goto exit_free;
-
- src_len = get_unaligned_be32(buf);
+ src_len = get_unaligned_be32(in_buf);
+ in_buf += 8;
if (src_len <= 0 || src_len > dst_len) {
printf("file corrupted");
goto exit_free;
}
- ret = read(in_fd, in_buf, src_len);
- if (ret < 0)
- goto exit_free;
/* decompress */
tmp = dst_len;
- if (src_len < dst_len) {
- r = lzo1x_decompress_safe((u8 *) in_buf, src_len,
- out_buf, &tmp);
- if (r != LZO_E_OK || dst_len != tmp) {
+
+ /* When the input data is not compressed at all,
+ * lzo1x_decompress_safe will fail, so call memcpy()
+ * instead */
+ if (unlikely(dst_len == src_len)) {
+ if (src_len != dst_len) {
printf("Compressed data violation");
goto exit_free;
}
- ret = write(out_fd, out_buf, dst_len);
- if (ret < 0)
- goto exit_free;
+ out_buf = in_buf;
} else {
- if (src_len != dst_len) {
+ r = lzo1x_decompress_safe((u8 *) in_buf, src_len,
+ out_buf, &tmp);
+
+ if (r != LZO_E_OK || dst_len != tmp) {
printf("Compressed data violation");
goto exit_free;
}
- ret = write(out_fd, in_buf, dst_len);
- if (ret < 0)
- goto exit_free;
}
+ ret = flush(out_buf, dst_len);
+ if (ret < 0)
+ goto exit_free;
+
+ out_buf = in_buf + src_len;
+ in_buf = in_buf_save;
+ ret = fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
+ if (ret < 0)
+ goto exit_free;
+
+ if (ret == 0)
+ in_buf = out_buf;
+
+ out_buf = out_buf_save;
+
obytes_processed += dst_len;
+
}
exit_free:
@@ -197,3 +182,22 @@ exit_free:
return 0;
}
+static int in_fd;
+static int out_fd;
+
+static int unlzo_fill(void *buf, unsigned int len)
+{
+ return read(in_fd, buf, len);
+}
+
+static int unlzo_flush(void *buf, unsigned int len)
+{
+ return write(out_fd, buf, len);
+}
+
+int unlzo(int _in_fd, int _out_fd, int *dest_len)
+{
+ in_fd = _in_fd;
+ out_fd = _out_fd;
+ return __unlzo(dest_len, unlzo_fill, unlzo_flush);
+}