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