openwrt/target/linux/brcm47xx/patches-2.6.23/500-lzma_initramfs.patch

118 lines
3.2 KiB
Diff
Raw Normal View History

--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -287,7 +287,7 @@
if [ "${is_cpio_compressed}" = "compressed" ]; then
cat ${cpio_tfile} > ${output_file}
else
- cat ${cpio_tfile} | gzip -f -9 - > ${output_file}
+ lzma e -lc1 -lp2 -pb2 ${cpio_tfile} ${output_file}
fi
[ -z ${cpio_file} ] && rm ${cpio_tfile}
fi
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -441,6 +441,69 @@
outcnt = 0;
}
+#include <linux/LzmaDecode.h>
+static int __init lzma_unzip(void)
+{
+ unsigned int i; /* temp value */
+ unsigned int lc; /* literal context bits */
+ unsigned int lp; /* literal pos state bits */
+ unsigned int pb; /* pos state bits */
+ unsigned int osize; /* uncompressed size */
+ unsigned char *workspace;
+ unsigned char* outputbuffer;
+ unsigned int outsizeProcessed = 0;
+ int workspace_size;
+ int res;
+
+ // lzma args
+ i = get_byte();
+ lc = i % 9, i = i / 9;
+ lp = i % 5, pb = i / 5;
+
+ // skip dictionary size
+ for (i = 0; i < 4; i++)
+ get_byte();
+
+ /* read the lower half of uncompressed size in the header */
+ osize = ((unsigned int)get_byte()) +
+ ((unsigned int)get_byte() << 8) +
+ ((unsigned int)get_byte() << 16) +
+ ((unsigned int)get_byte() << 24);
+
+ /* skip rest of the header (upper half of uncompressed size) */
+ for (i = 0; i < 4; i++)
+ get_byte();
+
+ workspace_size = ((LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp))) * sizeof(CProb)) + 100;
+ printk( KERN_NOTICE "initramfs: LZMA lc=%d,lp=%d,pb=%d,origSize=%d\n",
+ lc,lp,pb,osize);
+ outputbuffer = kmalloc(osize, GFP_KERNEL);
+ if (outputbuffer == 0) {
+ printk(KERN_ERR "initramfs: Couldn't allocate lzma output buffer\n");
+ return -1;
+ }
+
+ workspace = kmalloc(workspace_size, GFP_KERNEL);
+ if (workspace == NULL) {
+ printk(KERN_ERR "initramfs: Couldn't allocate lzma workspace\n");
+ return -1;
+ }
+
+ res = LzmaDecode(workspace, workspace_size, lc, lp, pb, inbuf + inptr, insize - inptr, outputbuffer, osize, &outsizeProcessed);
+ if( res != 0 ) {
+ panic( KERN_ERR "initramfs: Lzma decode failure\n");
+ return -1;
+ }
+
+ flush_buffer(outputbuffer, outsizeProcessed);
+ inptr = insize;
+
+ kfree(outputbuffer);
+ kfree(workspace);
+ state = Reset;
+ return 0;
+}
+
static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
{
int written;
@@ -475,12 +538,28 @@
inptr = 0;
outcnt = 0; /* bytes in output buffer */
bytes_out = 0;
- crc = (ulg)0xffffffffL; /* shift register contents */
- makecrc();
- gunzip();
- if (state != Reset)
+ if( inbuf[0] == 037 && ((inbuf[1] == 0213) || (inbuf[1] == 0236)))
+ {
+ printk( KERN_NOTICE "detected gzip initramfs\n");
+ crc = (ulg)0xffffffffL; /* shift register contents */
+ makecrc();
+ gunzip();
+ if (state != Reset)
error("junk in gzipped archive");
- this_header = saved_offset + inptr;
+ }
+ else if(!memcmp(inbuf+1, "\x00\x00\x80\x00", 4)) /* FIXME: hardcoded dictionary size */
+ {
+ printk( KERN_NOTICE "detected lzma initramfs\n");
+ lzma_unzip();
+ }
+ else
+ {
+ // skip forward ?
+ crc = (ulg)0xffffffffL; /* shift register contents */
+ makecrc();
+ gunzip();
+ }
+ this_header = saved_offset + inptr;
buf += inptr;
len -= inptr;
}