]> glassweightruler.freedombox.rocks Git - Ventoy.git/commitdiff
add XPRESS support (#317)
authorA1ive <10670106+a1ive@users.noreply.github.com>
Fri, 17 Jul 2020 14:29:24 +0000 (22:29 +0800)
committerGitHub <noreply@github.com>
Fri, 17 Jul 2020 14:29:24 +0000 (22:29 +0800)
GRUB2/MOD_SRC/grub-2.04/grub-core/Makefile.core.def
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/xpress.c [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/xpress.h [new file with mode: 0644]

index d0455f9fb46cd5542b63480434d31d2a1d158f30..c8867f37d4ee71da72c15ce6bfd0cca7b2dfdaa5 100644 (file)
@@ -1582,6 +1582,7 @@ module = {
   common = ventoy/ventoy_plugin.c;
   common = ventoy/ventoy_json.c;
   common = ventoy/lzx.c;
+  common = ventoy/xpress.c;
   common = ventoy/huffman.c;
 };
 
index d756afcb5e88822cfa3367a733e8b8f4fb89926d..01ae478ca74e68e021ae29b1283112b89fd331e2 100644 (file)
@@ -51,6 +51,7 @@ static grub_uint32_t g_suppress_wincd_override_data = 0;
 grub_uint8_t g_temp_buf[512];
 
 grub_ssize_t lzx_decompress ( const void *data, grub_size_t len, void *buf );
+grub_ssize_t xca_decompress ( const void *data, grub_size_t len, void *buf );
 
 static wim_patch *ventoy_find_wim_patch(const char *path)
 {
@@ -478,6 +479,8 @@ static int ventoy_read_resource(grub_file_t fp, wim_resource_header *head, void
         else
         {
             decompress_len = (int)lzx_decompress(buffer_compress + cur_offset, chunk_size, cur_dst);
+            if (decompress < 0)
+                decompress_len = (int)xca_decompress(buffer_compress + cur_offset, chunk_size, cur_dst);
         }
 
         //debug("chunk_size:%u decompresslen:%d\n", chunk_size, decompress_len);
@@ -499,7 +502,9 @@ static int ventoy_read_resource(grub_file_t fp, wim_resource_header *head, void
     }
     else
     {
-        decompress_len = (int)lzx_decompress(buffer_compress + cur_offset, head->size_in_wim - cur_offset, cur_dst);            
+        decompress_len = (int)lzx_decompress(buffer_compress + cur_offset, head->size_in_wim - cur_offset, cur_dst);
+        if (decompress < 0)
+            decompress_len = (int)xca_decompress(buffer_compress + cur_offset, head->size_in_wim - cur_offset, cur_dst);
     }
     
     cur_dst += decompress_len;
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/xpress.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/xpress.c
new file mode 100644 (file)
index 0000000..bfb3125
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * 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
+ *
+ * Xpress Compression Algorithm (MS-XCA) decompression
+ *
+ */
+
+#include "wimboot.h"
+#include "huffman.h"
+#include "xpress.h"
+
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+/**
+ * Decompress XCA-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 xca_decompress ( const void *data, size_t len, void *buf ) {
+       const void *src = data;
+       const void *end = ( uint8_t * ) src + len;
+       uint8_t *out = buf;
+       size_t out_len = 0;
+       size_t out_len_threshold = 0;
+       const struct xca_huf_len *lengths;
+       struct xca xca;
+       uint32_t accum = 0;
+       int extra_bits = 0;
+       unsigned int huf;
+       struct huffman_symbols *sym;
+       unsigned int raw;
+       unsigned int match_len;
+       unsigned int match_offset_bits;
+       unsigned int match_offset;
+       const uint8_t *copy;
+       int rc;
+
+       /* Process data stream */
+       while ( src < end ) {
+
+               /* (Re)initialise decompressor if applicable */
+               if ( out_len >= out_len_threshold ) {
+
+                       /* Construct symbol lengths */
+                       lengths = src;
+                       src = ( uint8_t * ) src + sizeof ( *lengths );
+                       if ( src > end ) {
+                               DBG ( "XCA too short to hold Huffman lengths table.\n");
+                               return -1;
+                       }
+                       for ( raw = 0 ; raw < XCA_CODES ; raw++ )
+                               xca.lengths[raw] = xca_huf_len ( lengths, raw );
+
+                       /* Construct Huffman alphabet */
+                       if ( ( rc = huffman_alphabet ( &xca.alphabet,
+                                                      xca.lengths,
+                                                      XCA_CODES ) ) != 0 )
+                               return rc;
+
+                       /* Initialise state */
+                       accum = XCA_GET16 ( src );
+                       accum <<= 16;
+                       accum |= XCA_GET16 ( src );
+                       extra_bits = 16;
+
+                       /* Determine next threshold */
+                       out_len_threshold = ( out_len + XCA_BLOCK_SIZE );
+               }
+
+               /* Determine symbol */
+               huf = ( accum >> ( 32 - HUFFMAN_BITS ) );
+               sym = huffman_sym ( &xca.alphabet, huf );
+               raw = huffman_raw ( sym, huf );
+               accum <<= huffman_len ( sym );
+               extra_bits -= huffman_len ( sym );
+               if ( extra_bits < 0 ) {
+                       accum |= ( XCA_GET16 ( src ) << ( -extra_bits ) );
+                       extra_bits += 16;
+               }
+
+               /* Process symbol */
+               if ( raw < XCA_END_MARKER ) {
+
+                       /* Literal symbol - add to output stream */
+                       if ( buf )
+                               *(out++) = raw;
+                       out_len++;
+
+               } else if ( ( raw == XCA_END_MARKER ) &&
+                           ( (uint8_t *) src >= ( ( uint8_t * ) end - 1 ) ) ) {
+
+                       /* End marker symbol */
+                       return out_len;
+
+               } else {
+
+                       /* LZ77 match symbol */
+                       raw -= XCA_END_MARKER;
+                       match_offset_bits = ( raw >> 4 );
+                       match_len = ( raw & 0x0f );
+                       if ( match_len == 0x0f ) {
+                               match_len = XCA_GET8 ( src );
+                               if ( match_len == 0xff ) {
+                                       match_len = XCA_GET16 ( src );
+                               } else {
+                                       match_len += 0x0f;
+                               }
+                       }
+                       match_len += 3;
+                       if ( match_offset_bits ) {
+                               match_offset =
+                                       ( ( accum >> ( 32 - match_offset_bits ))
+                                         + ( 1 << match_offset_bits ) );
+                       } else {
+                               match_offset = 1;
+                       }
+                       accum <<= match_offset_bits;
+                       extra_bits -= match_offset_bits;
+                       if ( extra_bits < 0 ) {
+                               accum |= ( XCA_GET16 ( src ) << (-extra_bits) );
+                               extra_bits += 16;
+                       }
+
+                       /* Copy data */
+                       out_len += match_len;
+                       if ( buf ) {
+                               copy = ( out - match_offset );
+                               while ( match_len-- )
+                                       *(out++) = *(copy++);
+                       }
+               }
+       }
+
+       return out_len;
+}
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/xpress.h b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/xpress.h
new file mode 100644 (file)
index 0000000..6a430f7
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef _XCA_H
+#define _XCA_H
+
+/*
+ * 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
+ *
+ * Xpress Compression Algorithm (MS-XCA) decompression
+ *
+ */
+
+#include "huffman.h"
+
+/** Number of XCA codes */
+#define XCA_CODES 512
+
+/** XCA decompressor */
+struct xca {
+       /** Huffman alphabet */
+       struct huffman_alphabet alphabet;
+       /** Raw symbols
+        *
+        * Must immediately follow the Huffman alphabet.
+        */
+       huffman_raw_symbol_t raw[XCA_CODES];
+       /** Code lengths */
+       uint8_t lengths[XCA_CODES];
+};
+
+/** XCA symbol Huffman lengths table */
+struct xca_huf_len {
+       /** Lengths of each symbol */
+       uint8_t nibbles[ XCA_CODES / 2 ];
+} __attribute__ (( packed ));
+
+/**
+ * Extract Huffman-coded length of a raw symbol
+ *
+ * @v lengths          Huffman lengths table
+ * @v symbol           Raw symbol
+ * @ret len            Huffman-coded length
+ */
+static inline unsigned int xca_huf_len ( const struct xca_huf_len *lengths,
+                                        unsigned int symbol ) {
+       return ( ( ( lengths->nibbles[ symbol / 2 ] ) >>
+                  ( 4 * ( symbol % 2 ) ) ) & 0x0f );
+}
+
+/** Get word from source data stream */
+#define XCA_GET16( src ) ( {                   \
+       const uint16_t *src16 = src;            \
+       src = ( uint8_t * ) src + sizeof ( *src16 );            \
+       *src16; } )
+
+/** Get byte from source data stream */
+#define XCA_GET8( src ) ( {                    \
+       const uint8_t *src8 = src;              \
+       src = ( uint8_t * ) src + sizeof ( *src8 );             \
+       *src8; } )
+
+/** XCA source data stream end marker */
+#define XCA_END_MARKER 256
+
+/** XCA block size */
+#define XCA_BLOCK_SIZE ( 64 * 1024 )
+
+extern ssize_t xca_decompress ( const void *data, size_t len, void *buf );
+
+#endif /* _XCA_H */