1/* 2; arm-linux.kernel.vmlinux.S -- loader & decompressor for the vmlinux/arm format 3; 4; This file is part of the UPX executable compressor. 5; 6; Copyright (C) 1996-2020 Markus Franz Xaver Johannes Oberhumer 7; Copyright (C) 1996-2020 Laszlo Molnar 8; Copyright (C) 2004-2020 John Reiser 9; All Rights Reserved. 10; 11; UPX and the UCL library are free software; you can redistribute them 12; and/or modify them under the terms of the GNU General Public License as 13; published by the Free Software Foundation; either version 2 of 14; the License, or (at your option) any later version. 15; 16; This program is distributed in the hope that it will be useful, 17; but WITHOUT ANY WARRANTY; without even the implied warranty of 18; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19; GNU General Public License for more details. 20; 21; You should have received a copy of the GNU General Public License 22; along with this program; see the file COPYING. 23; If not, write to the Free Software Foundation, Inc., 24; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 25; 26; Markus F.X.J. Oberhumer Laszlo Molnar 27; <markus@oberhumer.com> <ezerotven+github@gmail.com> 28; 29; John Reiser 30; <jreiser@users.sourceforge.net> 31*/ 32 33#include "arch/arm/v5a/macros.S" 34 35 36/* 37; ============= 38; ============= ENTRY POINT 39; ============= 40 41 How to debug: run under qemu (http://fabrice.bellard.free.fr/qemu/) 42 after un-commenting the bkpt opcode below. That opcode forces qemu 43 to stop in gdb. You'll have to "set $pc+=4" by hand. 44*/ 45section LINUX000 46 // bkpt // qemu DEBUG only // 'bkpt' == 0xe1200070 47/* Calling sequence of equivalent code in arch/arm/boot/compressed/misc.c: 48decompress_kernel: # (char *out, char *tmp, char *tmp_end, int arch_id) 49 lr= &indata; ip= retaddr # from arm-linux.kernel.vmlinux-head.S 50*/ 51 str ip,[r2,#-4]! // push retaddr on new stack 52 stmdb r2!,{r0,r3,sp} // &outdata, arch_id, sp_in 53 sub r2,r2,#4 // space for outsize 54 loadcon8 3,METHOD // mov r3,#METHOD 55 stmdb r2!,{r3,lr} // METHOD, &indata 56 mov sp, r2 // method,&indata,space,&outdata,arch_id,sp_in,retaddr 57 58 ldr r3,2f // outsize 59 str r3,[sp,#2*4] // outsize 60 add r3, sp,#2*4 // &outsize 61 mov r2,r0 // &outdata 62 ldr r1,1f // insize 63 mov r0,lr // &indata 64 bl decompressor // (&indata, insize, &outdata, &outsize, method) 65 b 3f 661: 67 .long COMPRESSED_LENGTH 682: 69 .long UNCOMPRESSED_LENGTH 703: 71spin: 72 cmp r0,#0 // check for success 73 bne spin 74 75section LINUX010 76 ldr r0,[sp,#3*4] // &outdata 77 ldr r1,[sp,#2*4] // outsize 78 loadcon8 2,filter_cto // mov r2,#filter_cto 79 loadcon8 3,filter_id // mov r3,#filter_id 80 bl unfilter // unfilter(&outdata, outsize, cto, fid) 81 82section LINUX020 83 ldmia sp,{r0,r1,r2,r3,ip,sp,lr} // method, &indata, outsize, &outdata, arch_id, sp_in, retaddr 84// See arch/arm/boot/compressed/misc.c/flush_window(): out = &output_data[output_ptr]; 85 mov r0,r2 // rv= outsize 86 mov pc,lr // return 87 88// ============= 89// ============= UNFILTER 90// ============= 91section ctok32.00 92//f_unfilter: @ (char *ptr, uint len, uint cto, uint fid) 93 ptr .req r0 94 len .req r1 95 cto .req r2 @ unused 96 fid .req r3 97 98 t1 .req r2 99 t2 .req r3 100unfilter: 101 and fid,fid,#0xff 102section ctok32.50 103 cmp fid,#0x50 @ last use of fid 104section ctok32.51 105 cmp fid,#0x51 @ last use of fid 106 107section ctok32.10 108 movne pc,lr @ no-op if not filter 0x50 109 110 movs len,len,lsr #2 @ word count 111 cmpne ptr,#0 112 moveq pc,lr @ no-op if either len or ptr is 0 113 114top_unf: 115 sub len,len,#1 116 ldr t1,[ptr,len,lsl #2] 117 and t2,t1,#0x0f<<24 118 cmp t2, #0x0b<<24; bne tst_unf @ not 'bl' subroutine call 119 and t2,t1,#0xff<<24 @ all the non-displacement bits 120 sub t1,t1,len @ convert to word-relative displacement 121 bic t1,t1,#0xff<<24 @ restrict to displacement field 122 orr t1,t1,t2 @ re-combine 123 str t1,[ptr,len,lsl #2] 124tst_unf: 125 cmp len,#0 126 bne top_unf 127 mov pc,lr 128 129 .unreq ptr 130 .unreq len 131 .unreq cto 132 .unreq fid 133 134section LINUX030 135decompressor: 136/* 137 r0= inptr 138 r1= insize 139 r2= outptr 140 r3= &outsize 141 sp/ method 142*/ 143 144// ============= 145// ============= DECOMPRESSION 146// ============= 147 148section NRV2B 149#include "arch/arm/v5a/nrv2b_d8.S" 150 151section NRV2D 152#include "arch/arm/v5a/nrv2d_d8.S" 153 154section NRV2E 155#include "arch/arm/v5a/nrv2e_d8.S" 156 157#include "arch/arm/v5a/lzma_d.S" 158 159#include "include/header.S" 160 161/* vim:set ts=8 sw=8 et: */ 162