mirror of
https://github.com/ventoy/Ventoy.git
synced 2026-06-29 22:48:13 +00:00
1. Optimization for WIMBOOT mode.
2. Add WIMBOOT for UEFI mode.
This commit is contained in:
181
wimboot/wimboot-2.7.3/src/lznt1.c
Normal file
181
wimboot/wimboot-2.7.3/src/lznt1.c
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* LZNT1 decompression
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "wimboot.h"
|
||||
#include "lznt1.h"
|
||||
|
||||
/**
|
||||
* Decompress LZNT1-compressed data block
|
||||
*
|
||||
* @v data Compressed data
|
||||
* @v limit Length of compressed data up to end of block
|
||||
* @v offset Starting offset within compressed data
|
||||
* @v block Decompression buffer for this block, or NULL
|
||||
* @ret out_len Length of decompressed block, or negative error
|
||||
*/
|
||||
static ssize_t lznt1_block ( const void *data, size_t limit, size_t offset,
|
||||
void *block ) {
|
||||
const uint16_t *tuple;
|
||||
const uint8_t *copy_src;
|
||||
uint8_t *copy_dest = block;
|
||||
size_t copy_len;
|
||||
size_t block_out_len = 0;
|
||||
unsigned int split = 12;
|
||||
unsigned int next_threshold = 16;
|
||||
unsigned int tag_bit = 0;
|
||||
unsigned int tag = 0;
|
||||
|
||||
while ( offset != limit ) {
|
||||
|
||||
/* Extract tag */
|
||||
if ( tag_bit == 0 ) {
|
||||
tag = *( ( uint8_t * ) ( data + offset ) );
|
||||
offset++;
|
||||
if ( offset == limit )
|
||||
break;
|
||||
}
|
||||
|
||||
/* Calculate copy source and length */
|
||||
if ( tag & 1 ) {
|
||||
|
||||
/* Compressed value */
|
||||
if ( offset + sizeof ( *tuple ) > limit ) {
|
||||
DBG ( "LZNT1 compressed value overrun at "
|
||||
"%#zx\n", offset );
|
||||
return -1;
|
||||
}
|
||||
tuple = ( data + offset );
|
||||
offset += sizeof ( *tuple );
|
||||
copy_len = LZNT1_VALUE_LEN ( *tuple, split );
|
||||
block_out_len += copy_len;
|
||||
if ( copy_dest ) {
|
||||
copy_src = ( copy_dest -
|
||||
LZNT1_VALUE_OFFSET ( *tuple,
|
||||
split ) );
|
||||
while ( copy_len-- )
|
||||
*(copy_dest++) = *(copy_src++);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Uncompressed value */
|
||||
copy_src = ( data + offset );
|
||||
if ( copy_dest )
|
||||
*(copy_dest++) = *copy_src;
|
||||
offset++;
|
||||
block_out_len++;
|
||||
}
|
||||
|
||||
/* Update split, if applicable */
|
||||
while ( block_out_len > next_threshold ) {
|
||||
split--;
|
||||
next_threshold <<= 1;
|
||||
}
|
||||
|
||||
/* Move to next value */
|
||||
tag >>= 1;
|
||||
tag_bit = ( ( tag_bit + 1 ) % 8 );
|
||||
}
|
||||
|
||||
return block_out_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress LZNT1-compressed data
|
||||
*
|
||||
* @v data Compressed data
|
||||
* @v len Length of compressed data
|
||||
* @v buf Decompression buffer, or NULL
|
||||
* @ret out_len Length of decompressed data, or negative error
|
||||
*/
|
||||
ssize_t lznt1_decompress ( const void *data, size_t len, void *buf ) {
|
||||
const uint16_t *header;
|
||||
const uint8_t *end;
|
||||
size_t offset = 0;
|
||||
ssize_t out_len = 0;
|
||||
size_t block_len;
|
||||
size_t limit;
|
||||
void *block;
|
||||
ssize_t block_out_len;
|
||||
|
||||
while ( offset != len ) {
|
||||
|
||||
/* Check for end marker */
|
||||
if ( ( offset + sizeof ( *end ) ) == len ) {
|
||||
end = ( data + offset );
|
||||
if ( *end == 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
/* Extract block header */
|
||||
if ( ( offset + sizeof ( *header ) ) > len ) {
|
||||
DBG ( "LZNT1 block header overrun at %#zx\n", offset );
|
||||
return -1;
|
||||
}
|
||||
header = ( data + offset );
|
||||
offset += sizeof ( *header );
|
||||
|
||||
/* Process block */
|
||||
block_len = LZNT1_BLOCK_LEN ( *header );
|
||||
if ( LZNT1_BLOCK_COMPRESSED ( *header ) ) {
|
||||
|
||||
/* Compressed block */
|
||||
DBG2 ( "LZNT1 compressed block %#zx+%#zx\n",
|
||||
offset, block_len );
|
||||
limit = ( offset + block_len );
|
||||
block = ( buf ? ( buf + out_len ) : NULL );
|
||||
block_out_len = lznt1_block ( data, limit, offset,
|
||||
block );
|
||||
if ( block_out_len < 0 )
|
||||
return block_out_len;
|
||||
offset += block_len;
|
||||
out_len += block_out_len;
|
||||
|
||||
} else {
|
||||
|
||||
/* Uncompressed block */
|
||||
if ( ( offset + block_len ) > len ) {
|
||||
DBG ( "LZNT1 uncompressed block overrun at "
|
||||
"%#zx+%#zx\n", offset, block_len );
|
||||
return -1;
|
||||
}
|
||||
DBG2 ( "LZNT1 uncompressed block %#zx+%#zx\n",
|
||||
offset, block_len );
|
||||
if ( buf ) {
|
||||
memcpy ( ( buf + out_len ), ( data + offset ),
|
||||
block_len );
|
||||
}
|
||||
offset += block_len;
|
||||
out_len += block_len;
|
||||
}
|
||||
}
|
||||
|
||||
return out_len;
|
||||
}
|
||||
Reference in New Issue
Block a user