From faa33d89a272a77e647d540e7b85dfcf8a9b75ee Mon Sep 17 00:00:00 2001 From: John Reiser Date: Mon, 30 Apr 2007 13:48:50 -0700 Subject: [PATCH] Documentation: UPX_F_VMLINUX_PPC32 changes to arch/powerpc/boot/main.c --- src/p_vmlinx.cpp | 103 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/src/p_vmlinx.cpp b/src/p_vmlinx.cpp index e0718761..308335eb 100644 --- a/src/p_vmlinx.cpp +++ b/src/p_vmlinx.cpp @@ -331,6 +331,109 @@ void PackVmlinuxBase::pack(OutputFile *fo) hdr_info.b_cto8 = ft.cto; fo->write(&hdr_info, sizeof(hdr_info)); fo_off += sizeof(hdr_info); ppc32_extra += sizeof(hdr_info); + +#if 0 /*{ Documentation: changes to arch/powerpc/boot/main.c */ +struct b_info { + unsigned sz_unc; + unsigned sz_cpr; + unsigned char b_method; + unsigned char b_ftid; + unsigned char b_cto8; + unsigned char b_unused; +}; +typedef int (*upx_f_unc)( /* uncompress */ + unsigned char const *src, unsigned src_len, + unsigned char *dst, unsigned *dst_len, + int method +); +typedef int (*upx_f_unf)( /* unfilter */ + unsigned char *buf, + unsigned len, + unsigned cto8, + unsigned ftid +); + +unsigned char const *upx_expand( // return updated src [aligned, too] + unsigned char const *src, + unsigned char *dst, + unsigned *const dst_len, + upx_f_unc const f_unc +) +{ + if (0==*dst_len) { + *dst_len = ((struct b_info const *)src)->sz_unc; + } + upx_f_unf const f_unf = (upx_f_unf)(sizeof(int) + (char *)f_unc); + unsigned total_len = 0; + unsigned need = *dst_len; + while (0 < need) { + struct b_info const *const b_hdr = (struct b_info const *)src; + src = (unsigned char const *)(1+ b_hdr); + unsigned blk_len = b_hdr->sz_unc; + int const rv = (*f_unc)(src, b_hdr->sz_cpr, dst, &blk_len, b_hdr->b_method); + if (0!=rv) { + printf("decompress error %d\n\r", rv); + exit(); + } + if (b_hdr->b_ftid) { + (*f_unf)(dst, b_hdr->sz_unc, b_hdr->b_cto8, b_hdr->b_ftid); + } + src += b_hdr->sz_cpr; + src += (3& -(int)src); // 4-byte align + dst += b_hdr->sz_unc; + total_len += b_hdr->sz_unc; + need -= b_hdr->sz_unc; + } + *dst_len = total_len; + return src; +} + +void prep_kernel(unsigned long a1, unsigned long a2) +{ + upx_f_unc f_unc = (upx_f_unc)0; + + vmlinuz.addr = (unsigned long)_vmlinux_start; + vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); + + if (0x55505821 == *(unsigned *)vmlinuz.addr) { + /* was compressed by upx */ + /* Uncompress elfheader */ + unsigned const *const fwa = (unsigned *)vmlinuz.addr; + f_unc = (upx_f_unc)((char *)&fwa[2] + fwa[1]); + unsigned dst_len = 0; + unsigned char const *src = (unsigned char const *)&fwa[2]; + src = upx_expand(src, (unsigned char *)elfheader, &dst_len, f_unc); + unsigned const src_len = src - (unsigned char const *)&fwa[0]; + vmlinuz.addr += src_len; + vmlinuz.size -= src_len; + } else { + memcpy(elfheader, (const void *)vmlinuz.addr, + sizeof(elfheader)); + } +===== + /* Eventually gunzip the kernel */ + if (f_unc) { + /* was compressed by upx */ + printf("upx_expand (0x%lx <- 0x%lx:0x%0lx)...", + vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); + unsigned dst_len = vmlinux.size - elfoffset; + upx_expand((unsigned char const *)vmlinuz.addr, + (unsigned char *)vmlinux.addr, &dst_len, f_unc); + printf("done 0x%lx bytes\n\r", len); + } else { + memmove((void *)vmlinux.addr,(void *)vmlinuz.addr, + vmlinuz.size); + /* Skip over the ELF header */ +#ifdef DEBUG + printf("... skipping 0x%lx bytes of ELF header\n\r", + elfoffset); +#endif + vmlinux.addr += elfoffset; + } +===== +} +#endif /*}*/ + } else { compressWithFilters(&ft, 512, &cconf, getStrategy(ft));