diff options
Diffstat (limited to 'src/crypto/deflate.c')
| -rw-r--r-- | src/crypto/deflate.c | 123 |
1 files changed, 58 insertions, 65 deletions
diff --git a/src/crypto/deflate.c b/src/crypto/deflate.c index 7ad39ec1b..1d54749e0 100644 --- a/src/crypto/deflate.c +++ b/src/crypto/deflate.c @@ -22,13 +22,13 @@ */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); +FILE_SECBOOT ( PERMITTED ); #include <string.h> #include <strings.h> #include <errno.h> #include <assert.h> #include <ctype.h> -#include <ipxe/uaccess.h> #include <ipxe/deflate.h> /** @file @@ -300,24 +300,21 @@ static int deflate_alphabet ( struct deflate *deflate, * Attempt to accumulate bits from input stream * * @v deflate Decompressor - * @v in Compressed input data * @v target Number of bits to accumulate * @ret excess Number of excess bits accumulated (may be negative) */ static int deflate_accumulate ( struct deflate *deflate, - struct deflate_chunk *in, unsigned int target ) { uint8_t byte; while ( deflate->bits < target ) { /* Check for end of input */ - if ( in->offset >= in->len ) + if ( deflate->in == deflate->end ) break; /* Acquire byte from input */ - copy_from_user ( &byte, in->data, in->offset++, - sizeof ( byte ) ); + byte = *(deflate->in++); deflate->accumulator = ( deflate->accumulator | ( byte << deflate->bits ) ); deflate->rotalumucca = ( deflate->rotalumucca | @@ -359,12 +356,10 @@ static int deflate_consume ( struct deflate *deflate, unsigned int count ) { * Attempt to extract a fixed number of bits from input stream * * @v deflate Decompressor - * @v in Compressed input data * @v target Number of bits to extract * @ret data Extracted bits (or negative if not yet accumulated) */ -static int deflate_extract ( struct deflate *deflate, struct deflate_chunk *in, - unsigned int target ) { +static int deflate_extract ( struct deflate *deflate, unsigned int target ) { int excess; int data; @@ -373,7 +368,7 @@ static int deflate_extract ( struct deflate *deflate, struct deflate_chunk *in, return 0; /* Attempt to accumulate bits */ - excess = deflate_accumulate ( deflate, in, target ); + excess = deflate_accumulate ( deflate, target ); if ( excess < 0 ) return excess; @@ -389,12 +384,10 @@ static int deflate_extract ( struct deflate *deflate, struct deflate_chunk *in, * Attempt to decode a Huffman-coded symbol from input stream * * @v deflate Decompressor - * @v in Compressed input data * @v alphabet Huffman alphabet * @ret code Raw code (or negative if not yet accumulated) */ static int deflate_decode ( struct deflate *deflate, - struct deflate_chunk *in, struct deflate_alphabet *alphabet ) { struct deflate_huf_symbols *huf_sym; uint16_t huf; @@ -407,7 +400,7 @@ static int deflate_decode ( struct deflate *deflate, * even if the stream still contains some complete * Huffman-coded symbols. */ - deflate_accumulate ( deflate, in, DEFLATE_HUFFMAN_BITS ); + deflate_accumulate ( deflate, DEFLATE_HUFFMAN_BITS ); /* Normalise the bit-reversed accumulated value to 16 bits */ huf = ( deflate->rotalumucca >> 16 ); @@ -449,24 +442,22 @@ static void deflate_discard_to_byte ( struct deflate *deflate ) { * Copy data to output buffer (if available) * * @v out Output data buffer - * @v start Source data - * @v offset Starting offset within source data + * @v in Input data * @v len Length to copy */ -static void deflate_copy ( struct deflate_chunk *out, - userptr_t start, size_t offset, size_t len ) { - size_t out_offset = out->offset; +static void deflate_copy ( struct deflate_chunk *out, const void *in, + size_t len ) { + const uint8_t *in_byte = in; + uint8_t *out_byte = ( out->data + out->offset ); size_t copy_len; /* Copy data one byte at a time, to allow for overlap */ - if ( out_offset < out->len ) { - copy_len = ( out->len - out_offset ); + if ( out->offset < out->len ) { + copy_len = ( out->len - out->offset ); if ( copy_len > len ) copy_len = len; - while ( copy_len-- ) { - memcpy_user ( out->data, out_offset++, - start, offset++, 1 ); - } + while ( copy_len-- ) + *(out_byte++) = *(in_byte++); } out->offset += len; } @@ -475,7 +466,8 @@ static void deflate_copy ( struct deflate_chunk *out, * Inflate compressed data * * @v deflate Decompressor - * @v in Compressed input data + * @v data Compressed input data + * @v len Length of compressed input data * @v out Output data buffer * @ret rc Return status code * @@ -489,10 +481,13 @@ static void deflate_copy ( struct deflate_chunk *out, * caller can use this to find the length of the decompressed data * before allocating the output data buffer. */ -int deflate_inflate ( struct deflate *deflate, - struct deflate_chunk *in, +int deflate_inflate ( struct deflate *deflate, const void *data, size_t len, struct deflate_chunk *out ) { + /* Store input data pointers */ + deflate->in = data; + deflate->end = ( data + len ); + /* This could be implemented more neatly if gcc offered a * means for enforcing tail recursion. */ @@ -509,7 +504,7 @@ int deflate_inflate ( struct deflate *deflate, int cm; /* Extract header */ - header = deflate_extract ( deflate, in, ZLIB_HEADER_BITS ); + header = deflate_extract ( deflate, ZLIB_HEADER_BITS ); if ( header < 0 ) { deflate->resume = &&zlib_header; return 0; @@ -538,7 +533,7 @@ int deflate_inflate ( struct deflate *deflate, int btype; /* Extract block header */ - header = deflate_extract ( deflate, in, DEFLATE_HEADER_BITS ); + header = deflate_extract ( deflate, DEFLATE_HEADER_BITS ); if ( header < 0 ) { deflate->resume = &&block_header; return 0; @@ -571,17 +566,17 @@ int deflate_inflate ( struct deflate *deflate, } literal_len: { - int len; + int llen; /* Extract LEN field */ - len = deflate_extract ( deflate, in, DEFLATE_LITERAL_LEN_BITS ); - if ( len < 0 ) { + llen = deflate_extract ( deflate, DEFLATE_LITERAL_LEN_BITS ); + if ( llen < 0 ) { deflate->resume = &&literal_len; return 0; } /* Record length of literal data */ - deflate->remaining = len; + deflate->remaining = llen; DBGC2 ( deflate, "DEFLATE %p literal block length %#04zx\n", deflate, deflate->remaining ); } @@ -590,7 +585,7 @@ int deflate_inflate ( struct deflate *deflate, int nlen; /* Extract NLEN field */ - nlen = deflate_extract ( deflate, in, DEFLATE_LITERAL_LEN_BITS); + nlen = deflate_extract ( deflate, DEFLATE_LITERAL_LEN_BITS ); if ( nlen < 0 ) { deflate->resume = &&literal_nlen; return 0; @@ -608,20 +603,20 @@ int deflate_inflate ( struct deflate *deflate, literal_data: { size_t in_remaining; - size_t len; + size_t dlen; /* Calculate available amount of literal data */ - in_remaining = ( in->len - in->offset ); - len = deflate->remaining; - if ( len > in_remaining ) - len = in_remaining; + in_remaining = ( deflate->end - deflate->in ); + dlen = deflate->remaining; + if ( dlen > in_remaining ) + dlen = in_remaining; /* Copy data to output buffer */ - deflate_copy ( out, in->data, in->offset, len ); + deflate_copy ( out, deflate->in, dlen ); /* Consume data from input buffer */ - in->offset += len; - deflate->remaining -= len; + deflate->in += dlen; + deflate->remaining -= dlen; /* Finish processing if we are blocked */ if ( deflate->remaining ) { @@ -657,7 +652,7 @@ int deflate_inflate ( struct deflate *deflate, unsigned int hclen; /* Extract block header */ - header = deflate_extract ( deflate, in, DEFLATE_DYNAMIC_BITS ); + header = deflate_extract ( deflate, DEFLATE_DYNAMIC_BITS ); if ( header < 0 ) { deflate->resume = &&dynamic_header; return 0; @@ -684,7 +679,7 @@ int deflate_inflate ( struct deflate *deflate, } dynamic_codelen: { - int len; + int clen; unsigned int index; int rc; @@ -692,18 +687,18 @@ int deflate_inflate ( struct deflate *deflate, while ( deflate->length_index < deflate->length_target ) { /* Extract code length length */ - len = deflate_extract ( deflate, in, - DEFLATE_CODELEN_BITS ); - if ( len < 0 ) { + clen = deflate_extract ( deflate, + DEFLATE_CODELEN_BITS ); + if ( clen < 0 ) { deflate->resume = &&dynamic_codelen; return 0; } /* Store code length */ index = deflate_codelen_map[deflate->length_index++]; - deflate_set_length ( deflate, index, len ); + deflate_set_length ( deflate, index, clen ); DBGCP ( deflate, "DEFLATE %p codelen for %d is %d\n", - deflate, index, len ); + deflate, index, clen ); } /* Generate code length alphabet */ @@ -722,25 +717,25 @@ int deflate_inflate ( struct deflate *deflate, } dynamic_litlen_distance: { - int len; + int clen; int index; /* Decode literal/length/distance code length */ - len = deflate_decode ( deflate, in, &deflate->distance_codelen); - if ( len < 0 ) { + clen = deflate_decode ( deflate, &deflate->distance_codelen ); + if ( clen < 0 ) { deflate->resume = &&dynamic_litlen_distance; return 0; } /* Prepare for extra bits */ - if ( len < 16 ) { - deflate->length = len; + if ( clen < 16 ) { + deflate->length = clen; deflate->extra_bits = 0; deflate->dup_len = 1; } else { static const uint8_t dup_len[3] = { 3, 3, 11 }; static const uint8_t extra_bits[3] = { 2, 3, 7 }; - index = ( len - 16 ); + index = ( clen - 16 ); deflate->dup_len = dup_len[index]; deflate->extra_bits = extra_bits[index]; if ( index ) @@ -753,7 +748,7 @@ int deflate_inflate ( struct deflate *deflate, unsigned int dup_len; /* Extract extra bits */ - extra = deflate_extract ( deflate, in, deflate->extra_bits ); + extra = deflate_extract ( deflate, deflate->extra_bits ); if ( extra < 0 ) { deflate->resume = &&dynamic_litlen_distance_extra; return 0; @@ -830,7 +825,7 @@ int deflate_inflate ( struct deflate *deflate, while ( 1 ) { /* Decode Huffman code */ - code = deflate_decode ( deflate, in, &deflate->litlen ); + code = deflate_decode ( deflate, &deflate->litlen ); if ( code < 0 ) { deflate->resume = &&lzhuf_litlen; return 0; @@ -844,8 +839,7 @@ int deflate_inflate ( struct deflate *deflate, DBGCP ( deflate, "DEFLATE %p literal %#02x " "('%c')\n", deflate, byte, ( isprint ( byte ) ? byte : '.' ) ); - deflate_copy ( out, virt_to_user ( &byte ), 0, - sizeof ( byte ) ); + deflate_copy ( out, &byte, sizeof ( byte ) ); } else if ( code == DEFLATE_LITLEN_END ) { @@ -876,7 +870,7 @@ int deflate_inflate ( struct deflate *deflate, int extra; /* Extract extra bits */ - extra = deflate_extract ( deflate, in, deflate->extra_bits ); + extra = deflate_extract ( deflate, deflate->extra_bits ); if ( extra < 0 ) { deflate->resume = &&lzhuf_litlen_extra; return 0; @@ -892,8 +886,7 @@ int deflate_inflate ( struct deflate *deflate, unsigned int bits; /* Decode Huffman code */ - code = deflate_decode ( deflate, in, - &deflate->distance_codelen ); + code = deflate_decode ( deflate, &deflate->distance_codelen ); if ( code < 0 ) { deflate->resume = &&lzhuf_distance; return 0; @@ -914,7 +907,7 @@ int deflate_inflate ( struct deflate *deflate, size_t dup_distance; /* Extract extra bits */ - extra = deflate_extract ( deflate, in, deflate->extra_bits ); + extra = deflate_extract ( deflate, deflate->extra_bits ); if ( extra < 0 ) { deflate->resume = &&lzhuf_distance_extra; return 0; @@ -934,7 +927,7 @@ int deflate_inflate ( struct deflate *deflate, } /* Copy data, allowing for overlap */ - deflate_copy ( out, out->data, ( out->offset - dup_distance ), + deflate_copy ( out, ( out->data + out->offset - dup_distance ), dup_len ); /* Process next literal/length symbol */ @@ -972,7 +965,7 @@ int deflate_inflate ( struct deflate *deflate, * cases involved in calling deflate_extract() to * obtain a full 32 bits. */ - excess = deflate_accumulate ( deflate, in, ZLIB_ADLER32_BITS ); + excess = deflate_accumulate ( deflate, ZLIB_ADLER32_BITS ); if ( excess < 0 ) { deflate->resume = &&zlib_adler32; return 0; |
