--- 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; }