1/* 2 * Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer 3 * 4 * This file is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of 7 * the License, or (at your option) any later version. 8 * 9 * Originally this code was part of ucl the data compression library 10 * for upx the ``Ultimate Packer of eXecutables''. 11 * 12 * - Converted to gas assembly, and refitted to work with etherboot. 13 * Eric Biederman 20 Aug 2002 14 * 15 * - Structure modified to be a subroutine call rather than an 16 * executable prefix. 17 * Michael Brown 30 Mar 2004 18 * 19 * - Modified to be compilable as either 16-bit or 32-bit code. 20 * Michael Brown 9 Mar 2005 21 */ 22 23FILE_LICENCE ( GPL2_OR_LATER ) 24 25/**************************************************************************** 26 * This file provides the decompress() and decompress16() functions 27 * which can be called in order to decompress an image compressed with 28 * the nrv2b utility in src/util. 29 * 30 * These functions are designed to be called by the prefix. They are 31 * position-independent code. 32 * 33 * The same basic assembly code is used to compile both 34 * decompress() and decompress16(). 35 **************************************************************************** 36 */ 37 38 .text 39 .arch i386 40 .section ".prefix.lib", "ax", @progbits 41 42#ifdef CODE16 43/**************************************************************************** 44 * decompress16 (real-mode near call, position independent) 45 * 46 * Decompress data in 16-bit mode 47 * 48 * Parameters (passed via registers): 49 * %ds:%esi - Start of compressed input data 50 * %es:%edi - Start of output buffer 51 * Returns: 52 * %ds:%esi - End of compressed input data 53 * %es:%edi - End of decompressed output data 54 * All other registers are preserved 55 * 56 * NOTE: It would be possible to build a smaller version of the 57 * decompression code for -DKEEP_IT_REAL by using 58 * #define REG(x) x 59 * to use 16-bit registers where possible. This would impose limits 60 * that the compressed data size must be in the range [1,65533-%si] 61 * and the uncompressed data size must be in the range [1,65536-%di] 62 * (where %si and %di are the input values for those registers). Note 63 * particularly that the lower limit is 1, not 0, and that the upper 64 * limit on the input (compressed) data really is 65533, since the 65 * algorithm may read up to three bytes beyond the end of the input 66 * data, since it reads dwords. 67 **************************************************************************** 68 */ 69 70#define REG(x) e ## x 71#define ADDR32 addr32 72 73 .code16 74 .globl decompress16 75decompress16: 76 77#else /* CODE16 */ 78 79/**************************************************************************** 80 * decompress (32-bit protected-mode near call, position independent) 81 * 82 * Parameters (passed via registers): 83 * %ds:%esi - Start of compressed input data 84 * %es:%edi - Start of output buffer 85 * Returns: 86 * %ds:%esi - End of compressed input data 87 * %es:%edi - End of decompressed output data 88 * All other registers are preserved 89 **************************************************************************** 90 */ 91 92#define REG(x) e ## x 93#define ADDR32 94 95 .code32 96 .globl decompress 97decompress: 98 99#endif /* CODE16 */ 100 101#define xAX REG(ax) 102#define xCX REG(cx) 103#define xBP REG(bp) 104#define xSI REG(si) 105#define xDI REG(di) 106 107 /* Save registers */ 108 push %xAX 109 pushl %ebx 110 push %xCX 111 push %xBP 112 /* Do the decompression */ 113 cld 114 xor %xBP, %xBP 115 dec %xBP /* last_m_off = -1 */ 116 jmp dcl1_n2b 117 118decompr_literals_n2b: 119 ADDR32 movsb 120decompr_loop_n2b: 121 addl %ebx, %ebx 122 jnz dcl2_n2b 123dcl1_n2b: 124 call getbit32 125dcl2_n2b: 126 jc decompr_literals_n2b 127 xor %xAX, %xAX 128 inc %xAX /* m_off = 1 */ 129loop1_n2b: 130 call getbit1 131 adc %xAX, %xAX /* m_off = m_off*2 + getbit() */ 132 call getbit1 133 jnc loop1_n2b /* while(!getbit()) */ 134 sub $3, %xAX 135 jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */ 136 shl $8, %xAX 137 ADDR32 movb (%xSI), %al /* m_off = (m_off - 3)*256 + src[ilen++] */ 138 inc %xSI 139 xor $-1, %xAX 140 jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */ 141 mov %xAX, %xBP /* last_m_off = m_off ?*/ 142decompr_ebpeax_n2b: 143 xor %xCX, %xCX 144 call getbit1 145 adc %xCX, %xCX /* m_len = getbit() */ 146 call getbit1 147 adc %xCX, %xCX /* m_len = m_len*2 + getbit()) */ 148 jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */ 149 inc %xCX /* m_len++ */ 150loop2_n2b: 151 call getbit1 152 adc %xCX, %xCX /* m_len = m_len*2 + getbit() */ 153 call getbit1 154 jnc loop2_n2b /* while(!getbit()) */ 155 inc %xCX 156 inc %xCX /* m_len += 2 */ 157decompr_got_mlen_n2b: 158 cmp $-0xd00, %xBP 159 adc $1, %xCX /* m_len = m_len + 1 + (last_m_off > 0xd00) */ 160 push %xSI 161 ADDR32 lea (%xBP,%xDI), %xSI /* m_pos = dst + olen + -m_off */ 162 rep 163 es ADDR32 movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */ 164 pop %xSI 165 jmp decompr_loop_n2b 166 167 168getbit1: 169 addl %ebx, %ebx 170 jnz 1f 171getbit32: 172 ADDR32 movl (%xSI), %ebx 173 sub $-4, %xSI /* sets carry flag */ 174 adcl %ebx, %ebx 1751: 176 ret 177 178decompr_end_n2b: 179 /* Restore registers and return */ 180 pop %xBP 181 pop %xCX 182 popl %ebx 183 pop %xAX 184 ret 185