ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
ota_esphome_inflate.c
Go to the documentation of this file.
1/*
2 * uzlib - tiny deflate/inflate library (deflate, gzip, zlib)
3 *
4 * Copyright (c) 2003 by Joergen Ibsen / Jibz
5 * All Rights Reserved
6 * http://www.ibsensoftware.com/
7 *
8 * Copyright (c) 2014-2018 by Paul Sokolovsky
9 *
10 * This software is provided 'as-is', without any express
11 * or implied warranty. In no event will the authors be
12 * held liable for any damages arising from the use of
13 * this software.
14 *
15 * Permission is granted to anyone to use this software
16 * for any purpose, including commercial applications,
17 * and to alter it and redistribute it freely, subject to
18 * the following restrictions:
19 *
20 * 1. The origin of this software must not be
21 * misrepresented; you must not claim that you
22 * wrote the original software. If you use this
23 * software in a product, an acknowledgment in
24 * the product documentation would be appreciated
25 * but is not required.
26 *
27 * 2. Altered source versions must be plainly marked
28 * as such, and must not be misrepresented as
29 * being the original software.
30 *
31 * 3. This notice may not be removed or altered from
32 * any source distribution.
33 */
34
35/*
36 * Altered for ESPHome: this is the raw deflate decoder from uzlib's
37 * tinflate.c (v2.9.5) with the gzip/zlib header parsers, checksums,
38 * runtime table builder and in-memory (non ring window) output path
39 * removed, and the public names prefixed with ota_inflate.
40 */
41
42#include "ota_esphome_inflate.h"
43
44#include <stddef.h>
45
46#define TINF_OK OTA_INFLATE_OK
47#define TINF_DONE OTA_INFLATE_DONE
48#define TINF_DATA_ERROR OTA_INFLATE_DATA_ERROR
49#define TINF_DICT_ERROR OTA_INFLATE_DICT_ERROR
50#define TINF_DATA struct OtaInflateState
51#define TINF_TREE struct OtaInflateTree
52#define TINF_ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*(arr)))
53
54/* every output byte also goes into the ring window */
55#define TINF_PUT(d, c) \
56 { \
57 *d->dest++ = c; \
58 d->dict_ring[d->dict_idx++] = c; \
59 if (d->dict_idx == d->dict_size) \
60 d->dict_idx = 0; \
61 }
62
63/* --------------------------------------------------- *
64 * -- constant tables (upstream builds them at runtime) -- *
65 * --------------------------------------------------- */
66
67static const unsigned char LENGTH_BITS[30] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,
68 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
69static const unsigned short LENGTH_BASE[30] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
70 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
71
72static const unsigned char DIST_BITS[30] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
73 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
74static const unsigned short DIST_BASE[30] = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25,
75 33, 49, 65, 97, 129, 193, 257, 385, 513, 769,
76 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};
77
78/* special ordering of code length codes */
79static const unsigned char CLCIDX[] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
80
81/* ----------------------- *
82 * -- utility functions -- *
83 * ----------------------- */
84
85/* given an array of code lengths, build a tree */
86static void tinf_build_tree(TINF_TREE *t, const unsigned char *lengths, unsigned int num) {
87 unsigned short offs[16];
88 unsigned int i, sum;
89
90 /* clear code length count table */
91 for (i = 0; i < 16; ++i)
92 t->table[i] = 0;
93
94 /* scan symbol lengths, and sum code length counts */
95 for (i = 0; i < num; ++i)
96 t->table[lengths[i]]++;
97
98 /* In the lengths array, 0 means unused code. So, t->table[0] now contains
99 number of unused codes. But table's purpose is to contain # of codes of
100 particular length, and there're 0 codes of length 0. */
101 t->table[0] = 0;
102
103 /* compute offset table for distribution sort */
104 for (sum = 0, i = 0; i < 16; ++i) {
105 offs[i] = sum;
106 sum += t->table[i];
107 }
108
109 /* create code->symbol translation table (symbols sorted by code) */
110 for (i = 0; i < num; ++i) {
111 if (lengths[i])
112 t->trans[offs[lengths[i]]++] = i;
113 }
114}
115
116/* ---------------------- *
117 * -- decode functions -- *
118 * ---------------------- */
119
120static unsigned char uzlib_get_byte(TINF_DATA *d) {
121 /* If end of source buffer is not reached, return next byte from source
122 buffer. */
123 if (d->source < d->source_limit) {
124 return *d->source++;
125 }
126
127 /* Otherwise if there's callback and we haven't seen EOF yet, try to
128 read next byte using it. (Note: the callback can also update ->source
129 and ->source_limit). */
130 if (!d->eof) {
131 int val = d->source_read_cb(d);
132 if (val >= 0) {
133 return (unsigned char) val;
134 }
135 }
136
137 /* Otherwise, we hit EOF (either from ->source_read_cb() or from exhaustion
138 of the buffer), and it will be "sticky", i.e. further calls to this
139 function will end up here too. */
140 d->eof = true;
141
142 return 0;
143}
144
145/* get one bit from source stream */
146static int tinf_getbit(TINF_DATA *d) {
147 unsigned int bit;
148
149 /* check if tag is empty */
150 if (!d->bitcount--) {
151 /* load next tag */
152 d->tag = uzlib_get_byte(d);
153 d->bitcount = 7;
154 }
155
156 /* shift bit out of tag */
157 bit = d->tag & 0x01;
158 d->tag >>= 1;
159
160 return bit;
161}
162
163/* read a num bit value from a stream and add base */
164static unsigned int tinf_read_bits(TINF_DATA *d, int num, int base) {
165 unsigned int val = 0;
166
167 /* read num bits */
168 if (num) {
169 unsigned int limit = 1 << (num);
170 unsigned int mask;
171
172 for (mask = 1; mask < limit; mask *= 2)
173 if (tinf_getbit(d))
174 val += mask;
175 }
176
177 return val + base;
178}
179
180/* given a data stream and a tree, decode a symbol */
181static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t) {
182 int sum = 0, cur = 0, len = 0;
183
184 /* get more bits while code value is above sum */
185 do {
186 cur = 2 * cur + tinf_getbit(d);
187
188 if (++len == TINF_ARRAY_SIZE(t->table)) {
189 return TINF_DATA_ERROR;
190 }
191
192 sum += t->table[len];
193 cur -= t->table[len];
194
195 } while (cur >= 0);
196
197 sum += cur;
198 if (sum < 0 || sum >= t->size) {
199 return TINF_DATA_ERROR;
200 }
201
202 return t->trans[sum];
203}
204
205/* given a data stream, decode dynamic trees from it */
206static int tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) {
207 /* code lengths for 288 literal/len symbols and 32 dist symbols */
208 unsigned char lengths[288 + 32];
209 unsigned int hlit, hdist, hclen, hlimit;
210 unsigned int i, num, length;
211
212 /* get 5 bits HLIT (257-286) */
213 hlit = tinf_read_bits(d, 5, 257);
214
215 /* get 5 bits HDIST (1-32) */
216 hdist = tinf_read_bits(d, 5, 1);
217
218 /* get 4 bits HCLEN (4-19) */
219 hclen = tinf_read_bits(d, 4, 4);
220
221 for (i = 0; i < 19; ++i)
222 lengths[i] = 0;
223
224 /* read code lengths for code length alphabet */
225 for (i = 0; i < hclen; ++i) {
226 /* get 3 bits code length (0-7) */
227 unsigned int clen = tinf_read_bits(d, 3, 0);
228
229 lengths[CLCIDX[i]] = clen;
230 }
231
232 /* build code length tree, temporarily use length tree */
233 tinf_build_tree(lt, lengths, 19);
234
235 /* decode code lengths for the dynamic trees */
236 hlimit = hlit + hdist;
237 for (num = 0; num < hlimit;) {
238 int sym = tinf_decode_symbol(d, lt);
239 unsigned char fill_value = 0;
240 int lbits, lbase = 3;
241
242 /* error decoding */
243 if (sym < 0)
244 return sym;
245
246 switch (sym) {
247 case 16:
248 /* copy previous code length 3-6 times (read 2 bits) */
249 if (num == 0)
250 return TINF_DATA_ERROR;
251 fill_value = lengths[num - 1];
252 lbits = 2;
253 break;
254 case 17:
255 /* repeat code length 0 for 3-10 times (read 3 bits) */
256 lbits = 3;
257 break;
258 case 18:
259 /* repeat code length 0 for 11-138 times (read 7 bits) */
260 lbits = 7;
261 lbase = 11;
262 break;
263 default:
264 /* values 0-15 represent the actual code lengths */
265 lengths[num++] = sym;
266 /* continue the for loop */
267 continue;
268 }
269
270 /* special code length 16-18 are handled here */
271 length = tinf_read_bits(d, lbits, lbase);
272 if (num + length > hlimit)
273 return TINF_DATA_ERROR;
274 for (; length; --length) {
275 lengths[num++] = fill_value;
276 }
277 }
278
279 /* Check that there's "end of block" symbol */
280 if (lengths[256] == 0) {
281 return TINF_DATA_ERROR;
282 }
283
284 /* build dynamic trees */
285 tinf_build_tree(lt, lengths, hlit);
286 tinf_build_tree(dt, lengths + hlit, hdist);
287
288 return TINF_OK;
289}
290
291/* build the fixed huffman trees (RFC 1951 3.2.6) through the generic tree
292 builder; altered from upstream, which unrolls them by hand */
293static void tinf_build_fixed_trees(TINF_TREE *lt, TINF_TREE *dt) {
294 unsigned char lengths[288];
295 unsigned int i;
296
297 for (i = 0; i < 144; ++i)
298 lengths[i] = 8;
299 for (; i < 256; ++i)
300 lengths[i] = 9;
301 for (; i < 280; ++i)
302 lengths[i] = 7;
303 for (; i < 288; ++i)
304 lengths[i] = 8;
305 tinf_build_tree(lt, lengths, 288);
306
307 for (i = 0; i < 32; ++i)
308 lengths[i] = 5;
309 tinf_build_tree(dt, lengths, 32);
310}
311
312/* ----------------------------- *
313 * -- block inflate functions -- *
314 * ----------------------------- */
315
316/* given a stream and two trees, inflate next chunk of output (a byte or more) */
317static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) {
318 if (d->curlen == 0) {
319 unsigned int offs;
320 int dist;
321 int sym = tinf_decode_symbol(d, lt);
322
323 if (d->eof) {
324 return TINF_DATA_ERROR;
325 }
326
327 if (sym < 0) {
328 return sym;
329 }
330
331 /* literal byte */
332 if (sym < 256) {
333 TINF_PUT(d, sym);
334 return TINF_OK;
335 }
336
337 /* end of block */
338 if (sym == 256) {
339 return TINF_DONE;
340 }
341
342 /* substring from sliding dictionary */
343 sym -= 257;
344 if (sym >= 29) {
345 return TINF_DATA_ERROR;
346 }
347
348 /* possibly get more bits from length code */
349 d->curlen = tinf_read_bits(d, LENGTH_BITS[sym], LENGTH_BASE[sym]);
350
351 dist = tinf_decode_symbol(d, dt);
352 if (dist < 0 || dist >= 30) {
353 return TINF_DATA_ERROR;
354 }
355
356 /* possibly get more bits from distance code */
357 offs = tinf_read_bits(d, DIST_BITS[dist], DIST_BASE[dist]);
358
359 /* calculate and validate actual LZ offset to use */
360 if (offs > d->dict_size) {
361 return TINF_DICT_ERROR;
362 }
363 /* Note: we don't try to catch offset which points to not yet filled
364 part of the dictionary here. Doing so would require keeping another
365 variable to track "filled in" size of the dictionary. Appearance of
366 such an offset cannot lead to accessing memory outside of the
367 dictionary buffer, and clients which don't want to leak unrelated
368 information, should explicitly initialize dictionary buffer passed
369 to uzlib. */
370
371 d->lz_off = d->dict_idx - offs;
372 if (d->lz_off < 0) {
373 d->lz_off += d->dict_size;
374 }
375 }
376
377 /* copy next byte from dict substring */
378 TINF_PUT(d, d->dict_ring[d->lz_off]);
379 if ((unsigned) ++d->lz_off == d->dict_size) {
380 d->lz_off = 0;
381 }
382 d->curlen--;
383 return TINF_OK;
384}
385
386/* inflate next byte from uncompressed block of data */
387static int tinf_inflate_uncompressed_block(TINF_DATA *d) {
388 if (d->curlen == 0) {
389 unsigned int length, invlength;
390
391 /* get length */
392 length = uzlib_get_byte(d);
393 length += 256 * uzlib_get_byte(d);
394 /* get one's complement of length */
395 invlength = uzlib_get_byte(d);
396 invlength += 256 * uzlib_get_byte(d);
397 /* check length */
398 if (length != (~invlength & 0x0000ffff))
399 return TINF_DATA_ERROR;
400
401 /* increment length to properly return TINF_DONE below, without
402 producing data at the same time */
403 d->curlen = length + 1;
404
405 /* make sure we start next block on a byte boundary */
406 d->bitcount = 0;
407 }
408
409 if (--d->curlen == 0) {
410 return TINF_DONE;
411 }
412
413 unsigned char c = uzlib_get_byte(d);
414 TINF_PUT(d, c);
415 return TINF_OK;
416}
417
418/* ---------------------- *
419 * -- public functions -- *
420 * ---------------------- */
421
422/* initialize decompression structure */
423void ota_inflate_init(TINF_DATA *d, unsigned char *dict, unsigned int dict_len) {
424 d->source = NULL;
425 d->source_limit = NULL;
426 d->tag = 0;
427 d->eof = 0;
428 d->bitcount = 0;
429 d->lz_off = 0;
430 d->bfinal = 0;
431 d->btype = -1;
432 d->dict_size = dict_len;
433 d->dict_ring = dict;
434 d->dict_idx = 0;
435 d->curlen = 0;
436 d->ltree.trans = d->ltrans;
437 d->ltree.size = TINF_ARRAY_SIZE(d->ltrans);
438 d->dtree.trans = d->dtrans;
439 d->dtree.size = TINF_ARRAY_SIZE(d->dtrans);
440}
441
442/* inflate next output bytes from compressed stream */
443int ota_inflate(TINF_DATA *d) {
444 do {
445 int res;
446
447 /* start a new block */
448 if (d->btype == -1) {
449 int old_btype;
450 next_blk:
451 old_btype = d->btype;
452 /* read final block flag */
453 d->bfinal = tinf_getbit(d);
454 /* read block type (2 bits) */
455 d->btype = tinf_read_bits(d, 2, 0);
456
457 if (d->btype == 1 && old_btype != 1) {
458 /* build fixed huffman trees */
459 tinf_build_fixed_trees(&d->ltree, &d->dtree);
460 } else if (d->btype == 2) {
461 /* decode trees from stream */
462 res = tinf_decode_trees(d, &d->ltree, &d->dtree);
463 if (res != TINF_OK) {
464 return res;
465 }
466 }
467 }
468
469 /* process current block */
470 switch (d->btype) {
471 case 0:
472 /* decompress uncompressed block */
473 res = tinf_inflate_uncompressed_block(d);
474 break;
475 case 1:
476 case 2:
477 /* decompress block with fixed/dynamic huffman trees */
478 /* trees were decoded previously, so it's the same routine for both */
479 res = tinf_inflate_block_data(d, &d->ltree, &d->dtree);
480 break;
481 default:
482 return TINF_DATA_ERROR;
483 }
484
485 if (res == TINF_DONE && !d->bfinal) {
486 /* the block has ended (without producing more data), but we
487 can't return without data, so start procesing next block */
488 goto next_blk;
489 }
490
491 if (res != TINF_OK) {
492 return res;
493 }
494
495 } while (d->dest < d->dest_limit);
496
497 return TINF_OK;
498}
mopeka_std_values val[3]
static float float float t
void ota_inflate_init(TINF_DATA *d, unsigned char *dict, unsigned int dict_len)
int ota_inflate(TINF_DATA *d)
uint32_t len
uint16_t length
Definition tt21100.cpp:0