]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - wimboot/wimboot-2.7.3/src/lznt1.c
2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program 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 the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
35 * Decompress LZNT1-compressed data block
37 * @v data Compressed data
38 * @v limit Length of compressed data up to end of block
39 * @v offset Starting offset within compressed data
40 * @v block Decompression buffer for this block, or NULL
41 * @ret out_len Length of decompressed block, or negative error
43 static ssize_t
lznt1_block ( const void *data
, size_t limit
, size_t offset
,
45 const uint16_t *tuple
;
46 const uint8_t *copy_src
;
47 uint8_t *copy_dest
= block
;
49 size_t block_out_len
= 0;
50 unsigned int split
= 12;
51 unsigned int next_threshold
= 16;
52 unsigned int tag_bit
= 0;
55 while ( offset
!= limit
) {
59 tag
= *( ( uint8_t * ) ( data
+ offset
) );
61 if ( offset
== limit
)
65 /* Calculate copy source and length */
68 /* Compressed value */
69 if ( offset
+ sizeof ( *tuple
) > limit
) {
70 DBG ( "LZNT1 compressed value overrun at "
74 tuple
= ( data
+ offset
);
75 offset
+= sizeof ( *tuple
);
76 copy_len
= LZNT1_VALUE_LEN ( *tuple
, split
);
77 block_out_len
+= copy_len
;
79 copy_src
= ( copy_dest
-
80 LZNT1_VALUE_OFFSET ( *tuple
,
83 *(copy_dest
++) = *(copy_src
++);
88 /* Uncompressed value */
89 copy_src
= ( data
+ offset
);
91 *(copy_dest
++) = *copy_src
;
96 /* Update split, if applicable */
97 while ( block_out_len
> next_threshold
) {
102 /* Move to next value */
104 tag_bit
= ( ( tag_bit
+ 1 ) % 8 );
107 return block_out_len
;
111 * Decompress LZNT1-compressed data
113 * @v data Compressed data
114 * @v len Length of compressed data
115 * @v buf Decompression buffer, or NULL
116 * @ret out_len Length of decompressed data, or negative error
118 ssize_t
lznt1_decompress ( const void *data
, size_t len
, void *buf
) {
119 const uint16_t *header
;
126 ssize_t block_out_len
;
128 while ( offset
!= len
) {
130 /* Check for end marker */
131 if ( ( offset
+ sizeof ( *end
) ) == len
) {
132 end
= ( data
+ offset
);
137 /* Extract block header */
138 if ( ( offset
+ sizeof ( *header
) ) > len
) {
139 DBG ( "LZNT1 block header overrun at %#zx\n", offset
);
142 header
= ( data
+ offset
);
143 offset
+= sizeof ( *header
);
146 block_len
= LZNT1_BLOCK_LEN ( *header
);
147 if ( LZNT1_BLOCK_COMPRESSED ( *header
) ) {
149 /* Compressed block */
150 DBG2 ( "LZNT1 compressed block %#zx+%#zx\n",
152 limit
= ( offset
+ block_len
);
153 block
= ( buf
? ( buf
+ out_len
) : NULL
);
154 block_out_len
= lznt1_block ( data
, limit
, offset
,
156 if ( block_out_len
< 0 )
157 return block_out_len
;
159 out_len
+= block_out_len
;
163 /* Uncompressed block */
164 if ( ( offset
+ block_len
) > len
) {
165 DBG ( "LZNT1 uncompressed block overrun at "
166 "%#zx+%#zx\n", offset
, block_len
);
169 DBG2 ( "LZNT1 uncompressed block %#zx+%#zx\n",
172 memcpy ( ( buf
+ out_len
), ( data
+ offset
),
176 out_len
+= block_len
;