~ubuntu-branches/debian/sid/upx-ucl/sid

« back to all changes in this revision

Viewing changes to src/p_vmlinz.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Robert Luberda
  • Date: 2009-10-16 12:56:47 UTC
  • mfrom: (1.2.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20091016125647-vity1npel2qsmr9c
Tags: 3.04-1
* New upstream release:
  + FTBFS with gcc 4.4 fixed by upstream (closes: #548566).
* p_mach.cpp: Fix from upstream vcs: mach/fat needs seek() 
  after set_extent().

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
   This file is part of the UPX executable compressor.
4
4
 
5
 
   Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
6
 
   Copyright (C) 1996-2008 Laszlo Molnar
 
5
   Copyright (C) 1996-2009 Markus Franz Xaver Johannes Oberhumer
 
6
   Copyright (C) 1996-2009 Laszlo Molnar
7
7
   All Rights Reserved.
8
8
 
9
9
   UPX and the UCL library are free software; you can redistribute them
28
28
 
29
29
#include "conf.h"
30
30
 
 
31
#include "p_elf.h"
31
32
#include "file.h"
32
33
#include "filter.h"
33
34
#include "packer.h"
52
53
 
53
54
PackVmlinuzI386::PackVmlinuzI386(InputFile *f) :
54
55
    super(f), physical_start(0x100000), page_offset(0), config_physical_align(0)
 
56
    , filter_len(0)
55
57
{
56
58
    bele = &N_BELE_RTP::le_policy;
57
 
    COMPILE_TIME_ASSERT(sizeof(boot_sect_t) == 0x218);
 
59
    COMPILE_TIME_ASSERT(sizeof(boot_sect_t) == 0x250);
58
60
}
59
61
 
60
62
 
82
84
    return filters;
83
85
}
84
86
 
 
87
int PackVmlinuzI386::getStrategy(Filter &/*ft*/)
 
88
{
 
89
    // If user specified the filter, then use it (-2==filter_strategy).
 
90
    // Else try the first two filters, and pick the better (2==filter_strategy).
 
91
    return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));
 
92
}
 
93
 
85
94
 
86
95
bool PackVmlinuzI386::canPack()
87
96
{
95
104
 
96
105
int PackVmlinuzI386::readFileHeader()
97
106
{
98
 
    boot_sect_t h;
99
 
 
100
107
    setup_size = 0;
101
108
 
102
109
    fi->readx(&h, sizeof(h));
160
167
    unsigned cpa_0 = 0;
161
168
    unsigned cpa_1 = 0;
162
169
    int j;
 
170
    if (0x205<=h.version) {
 
171
        cpa_0 = h.kernel_alignment;
 
172
        cpa_1 = 0u - cpa_0;
 
173
    } else
163
174
    for ((p = &obuf[setup_size]), (j= 0); j < 0x200; ++j, ++p) {
164
175
        if (0==memcmp("\x89\xeb\x81\xc3", p, 4)
165
176
        &&  0==memcmp("\x81\xe3",      8+ p, 2)) {
225
236
 
226
237
    checkAlreadyPacked(obuf + setup_size, UPX_MIN(file_size - setup_size, (off_t)1024));
227
238
 
228
 
    for (int gzoff = setup_size; gzoff < file_size; gzoff++)
 
239
    int gzoff = setup_size;
 
240
    if (0x208<=h.version) {
 
241
        gzoff += h.payload_offset;
 
242
    }
 
243
    for (; gzoff < file_size; gzoff++)
229
244
    {
230
245
        // find gzip header (2 bytes magic + 1 byte method "deflated")
231
246
        int off = find(obuf + gzoff, file_size - gzoff, "\x1F\x8B\x08", 3);
232
247
        if (off < 0)
233
248
            break;
234
249
        gzoff += off;
235
 
        const int gzlen = file_size - gzoff;
 
250
        const int gzlen = (h.version < 0x208) ? (file_size - gzoff) : h.payload_length;
236
251
        if (gzlen < 256)
237
252
            break;
238
253
        // check gzip flag byte
281
296
        if (klen <= gzlen)
282
297
            continue;
283
298
 
 
299
        if (0x208<=h.version && 0==memcmp("\177ELF", ibuf, 4)) {
 
300
            // Full ELF in theory; for now, try to handle as .bin at physical_start.
 
301
            // Check for PT_LOAD.p_paddr being ascending and adjacent.
 
302
            Elf_LE32_Ehdr const *const ehdr = (Elf_LE32_Ehdr const *)(void const *)ibuf;
 
303
            Elf_LE32_Phdr const *phdr = (Elf_LE32_Phdr const *)(ehdr->e_phoff + (char const *)ehdr);
 
304
            Elf_LE32_Shdr const *shdr = (Elf_LE32_Shdr const *)(ehdr->e_shoff + (char const *)ehdr);
 
305
            unsigned hi_paddr = 0, lo_paddr = 0;
 
306
            unsigned delta_off = 0;
 
307
            for (unsigned j=0; j < ehdr->e_phnum; ++j, ++phdr) {
 
308
                if (phdr->PT_LOAD==phdr->p_type) {
 
309
                    unsigned step = (hi_paddr + phdr->p_align - 1) & ~(phdr->p_align - 1);
 
310
                    if (0==hi_paddr) { // first PT_LOAD
 
311
                        if (physical_start!=phdr->p_paddr) {
 
312
                            return 0;
 
313
                        }
 
314
                        delta_off = phdr->p_paddr - phdr->p_offset;
 
315
                        lo_paddr = phdr->p_paddr;
 
316
                        hi_paddr = phdr->p_filesz + phdr->p_paddr;
 
317
                    }
 
318
                    else if (step==phdr->p_paddr
 
319
                        && delta_off==(phdr->p_paddr - phdr->p_offset)) {
 
320
                        hi_paddr = phdr->p_filesz + phdr->p_paddr;
 
321
                    }
 
322
                    else {
 
323
                        return 0;  // Not equivalent to a .bin.  Too complex for now.
 
324
                    }
 
325
                }
 
326
            }
 
327
            // FIXME: ascending order is only a convention; might need sorting.
 
328
            for (unsigned j=1; j < ehdr->e_shnum; ++j) {
 
329
                if (shdr->SHT_PROGBITS==shdr->sh_type) { // SHT_REL might be intermixed
 
330
                    if (shdr->SHF_EXECINSTR & shdr[j].sh_flags) {
 
331
                        filter_len += shdr[j].sh_size;  // FIXME: include sh_addralign
 
332
                    }
 
333
                    else {
 
334
                        break;
 
335
                    }
 
336
                }
 
337
            }
 
338
            memmove(ibuf, (lo_paddr - delta_off) + ibuf, hi_paddr - lo_paddr);  // FIXME: set_size
 
339
            // FIXME: .bss ?  Apparently handled by head.S
 
340
        }
 
341
 
284
342
        if (opt->force > 0)
285
343
            return klen;
286
344
 
402
460
    upx_compress_config_t cconf; cconf.reset();
403
461
    // limit stack size needed for runtime decompression
404
462
    cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
405
 
    compressWithFilters(&ft, 512, &cconf);
 
463
    compressWithFilters(&ft, 512, &cconf, getStrategy(ft));
406
464
 
407
465
    const unsigned lsize = getLoaderSize();
408
466
 
419
477
 
420
478
    boot_sect_t * const bs = (boot_sect_t *) ((unsigned char *) setup_buf);
421
479
    bs->sys_size = ALIGN_UP(lsize + ph.c_len, 16u) / 16;
 
480
    bs->payload_length = ph.c_len;
422
481
 
423
482
    fo->write(setup_buf, setup_buf.getSize());
424
483
    fo->write(loader, lsize);
448
507
    initLoader(stub_i386_linux_kernel_vmlinuz, sizeof(stub_i386_linux_kernel_vmlinuz));
449
508
    if (0!=page_offset) { // relocatable kernel
450
509
        assert(0==ft->id || 0x40==(0xf0 & ft->id));  // others assume fixed buffer address
451
 
        addLoader("LINUZ000,LINUZVGA,LINUZ101,LINUZ110",
 
510
        addLoader("LINUZ000,LINUZ001,LINUZVGA,LINUZ101,LINUZ110",
452
511
            ((0!=config_physical_align) ? "LINUZ120" : "LINUZ130"),
453
512
            "LINUZ140,LZCUTPOI,LINUZ141",
454
513
            (ft->id ? "LINUZ145" : ""),
456
515
            NULL);
457
516
    }
458
517
    else {
459
 
        addLoader("LINUZ000,LINUZVGA,LINUZ001",
 
518
        addLoader("LINUZ000,LINUZ001,LINUZVGA,LINUZ005",
460
519
              ph.first_offset_found == 1 ? "LINUZ010" : "",
461
520
              (0x40==(0xf0 & ft->id)) ? "LZCKLLT1" : (ft->id ? "LZCALLT1" : ""),
462
521
              "LBZIMAGE,IDENTSTR",
511
570
 
512
571
    // prepare filter
513
572
    Filter ft(ph.level);
514
 
    ft.buf_len = ph.u_len;
 
573
    ft.buf_len = (filter_len ? filter_len : (ph.u_len * 3)/5);
 
574
    // May 2008: 3/5 is heuristic to cover most .text but avoid non-instructions.
 
575
    // Otherwise "call trick" filter cannot find a free marker byte,
 
576
    // especially when it searches over tables of data.
515
577
    ft.addvalue = 0;  // The destination buffer might be relocated at runtime.
516
578
 
517
579
    upx_compress_config_t cconf; cconf.reset();
518
 
    // limit stack size needed for runtime decompression
519
 
    cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
520
 
 
521
 
    // FIXME: new stub allows most of low memory as stack for Bvmlinuz ?
522
 
    //cconf.conf_lzma.max_num_probs = (0x99000 - 0x10250)>>1; // ushort: 560560 stack
523
 
 
524
 
    compressWithFilters(&ft, 512, &cconf);
 
580
    // LINUZ001 allows most of low memory as stack for Bvmlinuz
 
581
    cconf.conf_lzma.max_num_probs = (0x90000 - 0x10000)>>1; // ushort: 512 KiB stack
 
582
 
 
583
    compressWithFilters(&ft, 512, &cconf, getStrategy(ft));
525
584
 
526
585
    // align everything to dword boundary - it is easier to handle
527
586
    unsigned c_len = ph.c_len;
652
711
}
653
712
 
654
713
 
 
714
PackVmlinuzARMEL::PackVmlinuzARMEL(InputFile *f) :
 
715
    super(f), setup_size(0), filter_len(0)
 
716
{
 
717
    bele = &N_BELE_RTP::le_policy;
 
718
}
 
719
 
 
720
const int *PackVmlinuzARMEL::getCompressionMethods(int method, int level) const
 
721
{
 
722
    return Packer::getDefaultCompressionMethods_8(method, level);
 
723
}
 
724
 
 
725
const int *PackVmlinuzARMEL::getFilters() const
 
726
{
 
727
    static const int f50[] = { 0x50, FT_END };
 
728
    return f50;
 
729
}
 
730
 
 
731
int PackVmlinuzARMEL::getStrategy(Filter &/*ft*/)
 
732
{
 
733
    // If user specified the filter, then use it (-2==filter_strategy).
 
734
    // Else try the first two filters, and pick the better (2==filter_strategy).
 
735
    return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));
 
736
}
 
737
 
 
738
bool PackVmlinuzARMEL::canPack()
 
739
{
 
740
    return readFileHeader() == getFormat();
 
741
}
 
742
 
 
743
int PackVmlinuzARMEL::readFileHeader()
 
744
{
 
745
    unsigned int hdr[8];
 
746
 
 
747
    fi->readx(hdr, sizeof(hdr));
 
748
    for (int j=0; j < 8; ++j) {
 
749
        if (0xe1a00000!=get_te32(&hdr[j])) {
 
750
            return 0;
 
751
        }
 
752
    }
 
753
    return UPX_F_VMLINUZ_ARMEL;
 
754
}
 
755
 
 
756
int PackVmlinuzARMEL::decompressKernel()
 
757
{
 
758
    // read whole kernel image
 
759
    obuf.alloc(file_size);
 
760
    fi->seek(0, SEEK_SET);
 
761
    fi->readx(obuf, file_size);
 
762
 
 
763
    //checkAlreadyPacked(obuf + setup_size, UPX_MIN(file_size - setup_size, (off_t)1024));
 
764
 
 
765
    // Find head.S:
 
766
    //      bl decompress_kernel  # 0xeb......
 
767
    //      b call_kernel         # 0xea......
 
768
    //LC0: .word LC0              # self!
 
769
    unsigned decompress_kernel = 0;
 
770
    unsigned caller1 = 0;
 
771
    unsigned caller2 = 0;
 
772
    unsigned got_start = 0;
 
773
    unsigned got_end = 0;
 
774
    for (unsigned j = 0; j < 0x400; j+=4) {
 
775
        unsigned w;
 
776
        if (j!=get_te32(j + obuf)) {
 
777
            continue;
 
778
        }
 
779
        if (0xea000000!=(0xff000000&    get_te32(j - 4 + obuf))
 
780
        ||  0xeb000000!=(0xff000000&(w= get_te32(j - 8 + obuf))) ) {
 
781
            continue;
 
782
        }
 
783
        caller1 = j - 8;
 
784
        decompress_kernel = ((0x00ffffff & w)<<2) + 8+ caller1;
 
785
        for (unsigned k = 12; k<=128; k+=4) {
 
786
            w = get_te32(j - k + obuf);
 
787
            if (0xeb000000==(0xff000000 & w)
 
788
            &&  decompress_kernel==(((0x00ffffff & w)<<2) + 8+ j - k) ) {
 
789
                caller2 = j - k;
 
790
                break;
 
791
            }
 
792
        }
 
793
        got_start = get_te32(5*4 + j + obuf);
 
794
        got_end   = get_te32(6*4 + j + obuf);
 
795
#if 0  /*{*/
 
796
        printf("decompress_kernel=0x%x  got_start=0x%x  got_end=0x%x\n",
 
797
            decompress_kernel, got_start, got_end);
 
798
#endif  /*}*/
 
799
        break;
 
800
    }
 
801
    if (0==decompress_kernel) {
 
802
        return 0;
 
803
    }
 
804
 
 
805
    // Find first subroutine that is called by decompress_kernel,
 
806
    // which we will consider to be the start of the gunzip module
 
807
    // and the end of the non-gunzip modules.
 
808
    for (unsigned j = decompress_kernel; j < (unsigned)file_size; j+=4) {
 
809
        unsigned w = get_te32(j + obuf);
 
810
        if (0xeb800000==(0xff800000 & w)) {
 
811
            setup_size = 8+ ((0xff000000 | w)<<2) + j;
 
812
            // Move the GlobalOffsetTable.
 
813
            for (unsigned k = got_start; k < got_end; k+=4) {
 
814
                w = get_te32(k + obuf);
 
815
                // FIXME: must relocate w
 
816
                set_te32(k - got_start + setup_size + obuf, w);
 
817
            }
 
818
            setup_size += got_end - got_start;
 
819
            set_te32(&obuf[caller1], 0xeb000000 |
 
820
                (0x00ffffff & ((setup_size - (8+ caller1))>>2)) );
 
821
            set_te32(&obuf[caller2], 0xeb000000 |
 
822
                (0x00ffffff & ((setup_size - (8+ caller2))>>2)) );
 
823
            break;
 
824
        }
 
825
    }
 
826
 
 
827
    for (int gzoff = 0; gzoff < 0x4000; gzoff+=4) {
 
828
        // find gzip header (2 bytes magic + 1 byte method "deflated")
 
829
        int off = find(obuf + gzoff, file_size - gzoff, "\x1F\x8B\x08", 3);
 
830
        if (off < 0 || 0!=(3u & off))
 
831
            break;  // not found, or not word-aligned
 
832
        gzoff += off;
 
833
        const int gzlen = file_size - gzoff;
 
834
        if (gzlen < 256)
 
835
            break;
 
836
        // check gzip flag byte
 
837
        unsigned char flags = obuf[gzoff + 3];
 
838
        if ((flags & 0xe0) != 0)        // reserved bits set
 
839
            continue;
 
840
        //printf("found gzip header at offset %d\n", gzoff);
 
841
 
 
842
        // try to decompress
 
843
        int klen;
 
844
        int fd;
 
845
        off_t fd_pos;
 
846
        for (;;)
 
847
        {
 
848
            klen = -1;
 
849
            fd = -1;
 
850
            fd_pos = -1;
 
851
            // open
 
852
            fi->seek(gzoff, SEEK_SET);
 
853
            fd = dup(fi->getFd());
 
854
            if (fd < 0)
 
855
                break;
 
856
            gzFile zf = gzdopen(fd, "rb");
 
857
            if (zf == NULL)
 
858
                break;
 
859
            // estimate gzip-decompressed kernel size & alloc buffer
 
860
            if (ibuf.getSize() == 0)
 
861
                ibuf.alloc(gzlen * 3);
 
862
            // decompress
 
863
            klen = gzread(zf, ibuf, ibuf.getSize());
 
864
            fd_pos = lseek(fd, 0, SEEK_CUR);
 
865
            gzclose(zf);
 
866
            fd = -1;
 
867
            if (klen != (int)ibuf.getSize())
 
868
                break;
 
869
            // realloc and try again
 
870
            unsigned const s = ibuf.getSize();
 
871
            ibuf.dealloc();
 
872
            ibuf.alloc(3 * s / 2);
 
873
        }
 
874
        if (fd >= 0)
 
875
            (void) close(fd);
 
876
        if (klen <= 0)
 
877
            continue;
 
878
 
 
879
        if (klen <= gzlen)
 
880
            continue;
 
881
 
 
882
        if (opt->force > 0)
 
883
            return klen;
 
884
 
 
885
        // some checks
 
886
        if (fd_pos != file_size) {
 
887
            //printf("fd_pos: %ld, file_size: %ld\n", (long)fd_pos, (long)file_size);
 
888
        }
 
889
 
 
890
    //head_ok:
 
891
 
 
892
        // FIXME: more checks for special magic bytes in ibuf ???
 
893
        // FIXME: more checks for kernel architecture ???
 
894
 
 
895
        return klen;
 
896
    }
 
897
 
 
898
    return 0;
 
899
}
 
900
 
 
901
void PackVmlinuzARMEL::readKernel()
 
902
{
 
903
    int klen = decompressKernel();
 
904
    if (klen <= 0)
 
905
        throwCantPack("kernel decompression failed");
 
906
    //OutputFile::dump("kernel.img", ibuf, klen);
 
907
 
 
908
    // copy the setup boot code
 
909
    setup_buf.alloc(setup_size);
 
910
    memcpy(setup_buf, obuf, setup_size);
 
911
    //OutputFile::dump("setup.img", setup_buf, setup_size);
 
912
 
 
913
    obuf.dealloc();
 
914
    obuf.allocForCompression(klen);
 
915
 
 
916
    ph.u_len = klen;
 
917
    ph.filter = 0;
 
918
}
 
919
 
 
920
Linker* PackVmlinuzARMEL::newLinker() const
 
921
{
 
922
    return new ElfLinkerArmLE;
 
923
}
 
924
 
 
925
static const
 
926
#include "stub/arm-linux.kernel.vmlinux.h"
 
927
static const
 
928
#include "stub/armel-linux.kernel.vmlinuz-head.h"
 
929
 
 
930
void PackVmlinuzARMEL::buildLoader(const Filter *ft)
 
931
{
 
932
    // prepare loader; same as vmlinux (with 'x')
 
933
    initLoader(stub_arm_linux_kernel_vmlinux, sizeof(stub_arm_linux_kernel_vmlinux));
 
934
    addLoader("LINUX000", NULL);
 
935
    if (ft->id) {
 
936
        assert(ft->calls > 0);
 
937
        addLoader("LINUX010", NULL);
 
938
    }
 
939
    addLoader("LINUX020", NULL);
 
940
    if (ft->id) {
 
941
        addFilter32(ft->id);
 
942
    }
 
943
    addLoader("LINUX030", NULL);
 
944
         if (ph.method == M_NRV2E_8) addLoader("NRV2E", NULL);
 
945
    else if (ph.method == M_NRV2B_8) addLoader("NRV2B", NULL);
 
946
    else if (ph.method == M_NRV2D_8) addLoader("NRV2D", NULL);
 
947
    else if (M_IS_LZMA(ph.method))   addLoader("LZMA_ELF00",
 
948
        (opt->small ? "LZMA_DEC10" : "LZMA_DEC20"), "LZMA_DEC30", NULL);
 
949
    else throwBadLoader();
 
950
    addLoader("IDENTSTR,UPX1HEAD", NULL);
 
951
 
 
952
    // To debug (2008-09-14):
 
953
    //   Build gdb-6.8-21.fc9.src.rpm; ./configure --target=arm-none-elf; make
 
954
    //     Contains the fix for http://bugzilla.redhat.com/show_bug.cgi?id=436037
 
955
    //   Install qemu-0.9.1-6.fc9.i386.rpm
 
956
    //   qemu-system-arm -s -S -kernel <file> -nographic
 
957
    //   (gdb) target remote localhost:1234
 
958
    //   A very small boot loader runs at pc=0x0; the kernel is at 0x10000 (64KiB).
 
959
}
 
960
 
 
961
void PackVmlinuzARMEL::defineDecompressorSymbols()
 
962
{
 
963
    super::defineDecompressorSymbols();
 
964
    linker->defineSymbol(  "COMPRESSED_LENGTH", ph.c_len);
 
965
    linker->defineSymbol("UNCOMPRESSED_LENGTH", ph.u_len);
 
966
    linker->defineSymbol("METHOD", ph.method);
 
967
}
 
968
 
 
969
unsigned PackVmlinuzARMEL::write_vmlinuz_head(OutputFile *const fo)
 
970
{ // First word from vmlinuz-head.S
 
971
    fo->write(&stub_armel_linux_kernel_vmlinuz_head[0], 4);
 
972
 
 
973
    // Second word
 
974
    LE32 tmp_u32;
 
975
    unsigned const t = (0xff000000 &
 
976
            get_te32(&stub_armel_linux_kernel_vmlinuz_head[4]))
 
977
        | (0x00ffffff & (0u - 1 + ((3+ ph.c_len)>>2)));
 
978
    tmp_u32 = t;
 
979
    fo->write((void const *)&tmp_u32, 4);
 
980
 
 
981
    return sizeof(stub_armel_linux_kernel_vmlinuz_head);
 
982
}
 
983
 
 
984
void PackVmlinuzARMEL::pack(OutputFile *fo)
 
985
{
 
986
    readKernel();
 
987
 
 
988
    // prepare filter
 
989
    Filter ft(ph.level);
 
990
    ft.buf_len = ph.u_len;
 
991
    ft.addvalue = 0;
 
992
 
 
993
    // compress
 
994
    upx_compress_config_t cconf; cconf.reset();
 
995
    // limit stack size needed for runtime decompression
 
996
    cconf.conf_lzma.max_num_probs = 1846 + (768 << 5); // ushort: 52,844 byte stack
 
997
    compressWithFilters(&ft, 512, &cconf, getStrategy(ft));
 
998
 
 
999
    const unsigned lsize = getLoaderSize();
 
1000
 
 
1001
    defineDecompressorSymbols();
 
1002
    defineFilterSymbols(&ft);
 
1003
    relocateLoader();
 
1004
 
 
1005
    MemBuffer loader(lsize);
 
1006
    memcpy(loader, getLoader(), lsize);
 
1007
    patchPackHeader(loader, lsize);
 
1008
 
 
1009
//    boot_sect_t * const bs = (boot_sect_t *) ((unsigned char *) setup_buf);
 
1010
//    bs->sys_size = ALIGN_UP(lsize + ph.c_len, 16u) / 16;
 
1011
//    bs->payload_length = ph.c_len;
 
1012
 
 
1013
    fo->write(setup_buf, setup_buf.getSize());
 
1014
    write_vmlinuz_head(fo);
 
1015
    fo->write(obuf, ph.c_len);
 
1016
    unsigned const zero = 0;
 
1017
    fo->write((void const *)&zero, 3u & (0u - ph.c_len));
 
1018
    fo->write(loader, lsize);
 
1019
#if 0
 
1020
    printf("%-13s: setup        : %8ld bytes\n", getName(), (long) setup_buf.getSize());
 
1021
    printf("%-13s: loader       : %8ld bytes\n", getName(), (long) lsize);
 
1022
    printf("%-13s: compressed   : %8ld bytes\n", getName(), (long) ph.c_len);
 
1023
#endif
 
1024
 
 
1025
    // verify
 
1026
    verifyOverlappingDecompression();
 
1027
 
 
1028
    // finally check the compression ratio
 
1029
    if (!checkFinalCompressionRatio(fo))
 
1030
        throwNotCompressible();
 
1031
}
 
1032
 
 
1033
int PackVmlinuzARMEL::canUnpack()
 
1034
{
 
1035
    if (readFileHeader() != getFormat())
 
1036
        return false;
 
1037
    fi->seek(setup_size, SEEK_SET);
 
1038
    return readPackHeader(1024) ? 1 : -1;
 
1039
}
 
1040
 
 
1041
void PackVmlinuzARMEL::unpack(OutputFile *fo)
 
1042
{
 
1043
    // no uncompression support for this format, so that
 
1044
    // it is possible to remove the original deflate code (>10 KiB)
 
1045
 
 
1046
    // FIXME: but we could write the uncompressed "vmlinux" image
 
1047
 
 
1048
    ibuf.alloc(ph.c_len);
 
1049
    obuf.allocForUncompression(ph.u_len);
 
1050
 
 
1051
    fi->seek(setup_size + ph.buf_offset + ph.getPackHeaderSize(), SEEK_SET);
 
1052
    fi->readx(ibuf, ph.c_len);
 
1053
 
 
1054
    // decompress
 
1055
    decompress(ibuf, obuf);
 
1056
 
 
1057
    // unfilter
 
1058
    Filter ft(ph.level);
 
1059
    ft.init(ph.filter, 0);
 
1060
    ft.cto = (unsigned char) ph.filter_cto;
 
1061
    ft.unfilter(obuf, ph.u_len);
 
1062
 
 
1063
    // write decompressed file
 
1064
    if (fo)
 
1065
    {
 
1066
        throwCantUnpack("build a new kernel instead :-)");
 
1067
        //fo->write(obuf, ph.u_len);
 
1068
    }
 
1069
}
 
1070
 
655
1071
/*
656
1072
vi:ts=4:et
657
1073
*/