|
|
1.1 root 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:
23: FILE_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
75: decompress16:
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
97: decompress:
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:
118: decompr_literals_n2b:
119: ADDR32 movsb
120: decompr_loop_n2b:
121: addl %ebx, %ebx
122: jnz dcl2_n2b
123: dcl1_n2b:
124: call getbit32
125: dcl2_n2b:
126: jc decompr_literals_n2b
127: xor %xAX, %xAX
128: inc %xAX /* m_off = 1 */
129: loop1_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 ?*/
142: decompr_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++ */
150: loop2_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 */
157: decompr_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:
168: getbit1:
169: addl %ebx, %ebx
170: jnz 1f
171: getbit32:
172: ADDR32 movl (%xSI), %ebx
173: sub $-4, %xSI /* sets carry flag */
174: adcl %ebx, %ebx
175: 1:
176: ret
177:
178: decompr_end_n2b:
179: /* Restore registers and return */
180: pop %xBP
181: pop %xCX
182: popl %ebx
183: pop %xAX
184: ret
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.