]> git.zerfleddert.de Git - rsbs2/blame - src/rsb-lz.c
supermicro-kvm: handle redirects to https
[rsbs2] / src / rsb-lz.c
CommitLineData
90836933 1#include <stdio.h>
14ff7444 2#include <stdlib.h>
7215c018 3#include <stdint.h>
14ff7444
MG
4#include <strings.h>
5#include <string.h>
e433bc03 6#include <unistd.h>
14ff7444 7#include <errno.h>
af1fed3a 8#include "rsb-crc.h"
90836933 9#include "rsb-lz.h"
e8563c43 10#include "filesystem.h"
90836933 11
2363a0d6 12void err_exit(const char *fname)
14ff7444 13{
e4a6d4c3 14 fprintf(stderr,"%s: error extracting...\n", fname);
14ff7444
MG
15 exit(1);
16}
17
7e4dc833 18struct data_in_s {
7215c018
MG
19 uint8_t *start;
20 uint8_t *stop;
21 uint8_t bitpos;
22 uint8_t byte;
14ff7444
MG
23};
24
7e4dc833 25struct data_out_s {
7215c018
MG
26 uint8_t *pos;
27 uint8_t *end;
7e4dc833
MG
28};
29
7215c018 30uint8_t get_next_in_byte(struct data_in_s *data_in)
af1fed3a 31{
7215c018 32 uint8_t byte;
5e9ad31f 33
6b2c0993 34 if (data_in->stop < data_in->start)
2363a0d6 35 err_exit(__func__);
5e9ad31f 36
6b2c0993
MG
37 byte = *(data_in->start);
38 data_in->start++;
5e9ad31f 39
6b2c0993 40 return byte;
af1fed3a
MG
41}
42
7215c018 43uint8_t get_next_bit(struct data_in_s *data_in)
e4a6d4c3 44{
7215c018 45 uint8_t bitval;
e4a6d4c3 46
59a213c0
MG
47 if (data_in->bitpos == 0x80) {
48 data_in->byte = get_next_in_byte(data_in);
e4a6d4c3 49 }
6b2c0993 50
6d8c2f71 51 bitval = data_in->bitpos & data_in->byte;
6b2c0993 52
59a213c0
MG
53 data_in->bitpos >>= 1;
54 if (data_in->bitpos == 0) {
55 data_in->bitpos = 0x80;
90c723bb
MG
56 }
57
6d8c2f71 58 if (bitval == 0)
e4a6d4c3
MG
59 return 0;
60
61 return 1;
62}
63
7215c018 64uint32_t get_next_bits(struct data_in_s *data_in, uint32_t bits)
3772880c 65{
7215c018
MG
66 uint32_t bit;
67 uint32_t next_bits;
3772880c 68
6d8c2f71 69 bit = 1 << (bits - 1);
3772880c 70
6d8c2f71
MG
71 next_bits = 0;
72 while (bit != 0) {
73 if (data_in->bitpos == 0x80) {
74 data_in->byte = get_next_in_byte(data_in);
3772880c 75 }
3772880c 76
6d8c2f71
MG
77 if ((data_in->bitpos & data_in->byte) != 0)
78 next_bits = next_bits | bit;
79
80 bit = bit >> 1;
3772880c 81
6d8c2f71 82 data_in->bitpos >>= 1;
3772880c 83
6d8c2f71
MG
84 if(data_in->bitpos == 0) {
85 data_in->bitpos = 0x80;
3772880c 86 }
90c723bb 87 }
3772880c 88
6d8c2f71 89 return next_bits;
3772880c
MG
90}
91
7215c018 92void write_byte(uint8_t byte, struct data_out_s *data_out)
af1fed3a 93{
b0ddcea9 94 if (data_out->pos > data_out->end) {
2363a0d6 95 err_exit(__func__);
e4a6d4c3 96 }
9897bfc3 97
b0ddcea9
MG
98 *(data_out->pos) = byte;
99 data_out->pos++;
af1fed3a
MG
100}
101
56a9a862 102void lz_expand(struct data_in_s *data_in, struct data_out_s *data_out)
af1fed3a 103{
7215c018
MG
104 uint32_t pos;
105 uint32_t wordoffset;
106 uint32_t i;
107 uint8_t byte;
108 uint32_t wordlen;
109 uint8_t buf[1024];
af1fed3a 110
56a9a862 111 pos = 1;
af1fed3a 112
90c723bb
MG
113 while (1) {
114 while (1) {
1d359f15 115 /* Compressed/uncompressed? */
56a9a862 116 if (get_next_bit(data_in) == 0)
05c92ac4 117 break;
af1fed3a 118
1d359f15 119 /* Uncompressed byte */
56a9a862 120 byte = get_next_bits(data_in, 8);
af1fed3a 121
56a9a862 122 write_byte(byte, data_out);
1d359f15
MG
123
124 /* Save byte in buffer, to be reused later */
56a9a862
MG
125 buf[pos] = byte;
126 pos = (pos + 1) & 0x3ff;
90c723bb 127 }
af1fed3a 128
1d359f15
MG
129 /* offset for start of dictionary word */
130 wordoffset = get_next_bits(data_in, 0x0a);
131 if(wordoffset == 0)
05c92ac4 132 return;
af1fed3a 133
1d359f15
MG
134 /* length of dictionary word used */
135 wordlen = get_next_bits(data_in, 0x04) + 1;
136 for (i = 0; i <= wordlen ; i++) {
137 /* lookup dictionary byte */
138 byte = buf[(wordoffset + i) & 0x3ff];
56a9a862 139 write_byte(byte, data_out);
1d359f15 140 /* Save byte in buffer, to be reused later */
56a9a862
MG
141 buf[pos] = byte;
142 pos = (pos + 1) & 0x3ff;
90c723bb
MG
143 }
144 }
af1fed3a
MG
145}
146
7215c018
MG
147void set_next_bit(uint8_t *buf, uint32_t set, uint32_t *currbit) {
148 uint8_t *pos;
149 uint8_t bitpos;
b637ae70
MG
150
151 if (set) {
152 pos = buf + ((*currbit) / 8);
153 bitpos = 0x80 >> ((*currbit) % 8);
154 *pos |= bitpos;
155 }
156
157 *currbit = *currbit + 1;
158}
159
7215c018
MG
160void write_bits(uint8_t *buf, uint32_t data, uint32_t bits, uint32_t *currbit) {
161 int32_t i;
162 uint32_t bitpos;
b637ae70
MG
163
164 bitpos = 1 << (bits - 1);
165
166 for (i = 0; i < bits; i++) {
167 set_next_bit(buf, data & bitpos, currbit);
168 bitpos >>= 1;
169 }
170}
171
7215c018 172uint8_t *compress_lz(uint8_t *inbuf, int32_t inlen, int32_t *outlen)
b637ae70 173{
7215c018
MG
174 uint8_t *end = inbuf + inlen;
175 uint8_t *outbuf;
176 uint8_t window[1024];
177 int32_t pos = 0;
178 int32_t fill = 0;
179 uint32_t currbit = 0;
180 int32_t offset;
181 int32_t wordlen;
182 int32_t found;
183 int32_t i;
b637ae70
MG
184
185 if ((outbuf = malloc((inlen * 2) + 4)) == NULL) {
186 perror("malloc");
187 }
188
7215c018 189 *((uint32_t*)outbuf) = LZ_MAGIC;
b637ae70
MG
190 currbit = 8 * 8;
191
192 while(inbuf < end) {
193 found = 0;
194 for (wordlen = 17; wordlen > 1; wordlen--) {
195 for (offset = 1; offset < ((fill < 1023) ? fill : 1023); offset++) {
196 if ((fill < 1023) &&
197 (wordlen + offset > fill))
198 break;
199
200 for (i = 0; i < wordlen; i++) {
201 if (inbuf[i] != window[(offset + i) & 0x3ff]) {
202 break;
203 }
204 }
205 if (i == wordlen)
206 found = 1;
207 }
208 if (found)
209 break;
210 }
211
212 if (found) {
213 write_bits(outbuf, 0x00, 0x01, &currbit);
214 write_bits(outbuf, offset, 0x0a, &currbit);
215 write_bits(outbuf, wordlen - 1, 0x04, &currbit);
216 for (i = 0; i < wordlen; i++) {
217 window[pos] = *(inbuf + i);
218 pos = (pos + 1) & 0x3ff;
219 }
220 inbuf += wordlen;
221
222 if (fill < sizeof(window))
223 fill += wordlen;
224 } else {
225 write_bits(outbuf, 0x01, 0x01, &currbit);
226 write_bits(outbuf, *inbuf, 0x08, &currbit);
227 window[pos] = *inbuf;
228 pos = (pos + 1) & 0x3ff;
229 inbuf++;
230 if (fill < sizeof(window))
231 fill++;
232 }
233 }
234
235 write_bits(outbuf, 0x00, 0x01, &currbit);
236 write_bits(outbuf, 0x00, 0x0a, &currbit);
237
238 *outlen = (currbit / 8) + 1;
239
7215c018 240 *((uint32_t*)(outbuf + 4)) = *outlen;
b637ae70
MG
241
242 return outbuf;
243}
244
6b2c0993 245/* Checksum is only used for the compressed firmware in 'firmware' */
7215c018 246uint32_t crc_check(uint8_t *buf, uint32_t len, uint32_t magic)
af1fed3a 247{
7215c018
MG
248 uint32_t file_crc;
249 uint32_t my_len;
250 uint32_t crc;
251 uint32_t my_magic;
af1fed3a 252
7215c018
MG
253 my_len = *((uint32_t*)(buf + 0x20));
254 my_magic = *((uint32_t*)(buf + 0x24));
af1fed3a 255
a7420422
MG
256 if (my_magic != magic) {
257 printf("\nmagic: 0x%08x <-> 0x%08x\n", my_magic, magic);
af1fed3a 258 return 2;
a7420422 259 }
af1fed3a 260
a7420422 261 if (len < my_len)
af1fed3a
MG
262 return 3;
263
a7420422 264 crc = ~rsb_crc(~0x00, buf, len);
7215c018 265 file_crc = *((uint32_t*)(buf + len));
af1fed3a 266
a7420422
MG
267 if (file_crc != crc) {
268 printf("\nChecksums: 0x%08x <-> 0x%08x!\n", crc, file_crc);
269 return 4;
270 }
af1fed3a 271
a7420422 272 return 0;
af1fed3a
MG
273}
274
7215c018 275uint8_t *extract_lz_file(uint8_t *inbuf, uint32_t *outlen , uint8_t check_crc)
14ff7444 276{
7215c018 277 uint8_t *outbuf;
7e4dc833
MG
278 struct data_in_s data_in;
279 struct data_out_s data_out;
14ff7444 280
7215c018 281 if (*((uint32_t*)inbuf) != LZ_MAGIC)
2363a0d6 282 err_exit(__func__);
e4a6d4c3 283
7215c018 284 *outlen = *((uint32_t*)(inbuf + 4));
e726b380 285 printf(", length: %d", *outlen);
14ff7444 286
e726b380 287 if ((outbuf = malloc(*outlen)) == NULL) {
e433bc03
MG
288 perror("malloc");
289 exit(1);
290 }
e433bc03 291
e726b380 292 bzero(outbuf, *outlen);
2363a0d6
MG
293
294 data_in.start = inbuf + 8;
e726b380 295 data_in.stop = inbuf + *outlen;
59a213c0
MG
296 data_in.byte = 0x00;
297 data_in.bitpos = 0x80;
14ff7444 298
2363a0d6 299 data_out.pos = outbuf;
e726b380 300 data_out.end = outbuf + *outlen;
14ff7444 301
7e4dc833 302 lz_expand(&data_in, &data_out);
14ff7444 303
a7420422 304 if (check_crc) {
7215c018
MG
305 uint32_t crclen;
306 int32_t ret;
af1fed3a 307
7215c018 308 crclen = *((uint32_t*)(outbuf + 0x20));
a7420422
MG
309
310 if ((ret = crc_check(outbuf, crclen, 0x46335053)) != 0) {
311 printf("crc_check return: %d\n", ret);
312 err_exit(__func__);
313 }
e433bc03 314 }
e726b380
MG
315
316 return outbuf;
14ff7444 317}
Impressum, Datenschutz