mirror of
https://github.com/ventoy/Ventoy.git
synced 2025-12-15 16:26:20 +00:00
initial commit
This commit is contained in:
207
GRUB2/grub-2.04/grub-core/ventoy/huffman.c
Normal file
207
GRUB2/grub-2.04/grub-core/ventoy/huffman.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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
|
||||
*
|
||||
* Huffman alphabets
|
||||
*
|
||||
*/
|
||||
|
||||
#include "wimboot.h"
|
||||
#include "huffman.h"
|
||||
|
||||
/**
|
||||
* Transcribe binary value (for debugging)
|
||||
*
|
||||
* @v value Value
|
||||
* @v bits Length of value (in bits)
|
||||
* @ret string Transcribed value
|
||||
*/
|
||||
const char * huffman_bin ( unsigned long value, unsigned int bits ) {
|
||||
static char buf[ ( 8 * sizeof ( value ) ) + 1 /* NUL */ ];
|
||||
char *out = buf;
|
||||
|
||||
/* Sanity check */
|
||||
assert ( bits < sizeof ( buf ) );
|
||||
|
||||
/* Transcribe value */
|
||||
while ( bits-- )
|
||||
*(out++) = ( ( value & ( 1 << bits ) ) ? '1' : '0' );
|
||||
*out = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump Huffman alphabet (for debugging)
|
||||
*
|
||||
* @v alphabet Huffman alphabet
|
||||
*/
|
||||
static void __attribute__ (( unused ))
|
||||
huffman_dump_alphabet ( struct huffman_alphabet *alphabet ) {
|
||||
struct huffman_symbols *sym;
|
||||
unsigned int bits;
|
||||
unsigned int huf;
|
||||
unsigned int i;
|
||||
|
||||
(void)huf;
|
||||
|
||||
/* Dump symbol table for each utilised length */
|
||||
for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) /
|
||||
sizeof ( alphabet->huf[0] ) ) ; bits++ ) {
|
||||
sym = &alphabet->huf[ bits - 1 ];
|
||||
if ( sym->freq == 0 )
|
||||
continue;
|
||||
huf = ( sym->start >> sym->shift );
|
||||
DBG ( "Huffman length %d start \"%s\" freq %d:", bits,
|
||||
huffman_bin ( huf, sym->bits ), sym->freq );
|
||||
for ( i = 0 ; i < sym->freq ; i++ ) {
|
||||
DBG ( " %03x", sym->raw[ huf + i ] );
|
||||
}
|
||||
DBG ( "\n" );
|
||||
}
|
||||
|
||||
/* Dump quick lookup table */
|
||||
DBG ( "Huffman quick lookup:" );
|
||||
for ( i = 0 ; i < ( sizeof ( alphabet->lookup ) /
|
||||
sizeof ( alphabet->lookup[0] ) ) ; i++ ) {
|
||||
DBG ( " %d", ( alphabet->lookup[i] + 1 ) );
|
||||
}
|
||||
DBG ( "\n" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct Huffman alphabet
|
||||
*
|
||||
* @v alphabet Huffman alphabet
|
||||
* @v lengths Symbol length table
|
||||
* @v count Number of symbols
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int huffman_alphabet ( struct huffman_alphabet *alphabet,
|
||||
uint8_t *lengths, unsigned int count ) {
|
||||
struct huffman_symbols *sym;
|
||||
unsigned int huf;
|
||||
unsigned int cum_freq;
|
||||
unsigned int bits;
|
||||
unsigned int raw;
|
||||
unsigned int adjustment;
|
||||
unsigned int prefix;
|
||||
int empty;
|
||||
int complete;
|
||||
|
||||
/* Clear symbol table */
|
||||
memset ( alphabet->huf, 0, sizeof ( alphabet->huf ) );
|
||||
|
||||
/* Count number of symbols with each Huffman-coded length */
|
||||
empty = 1;
|
||||
for ( raw = 0 ; raw < count ; raw++ ) {
|
||||
bits = lengths[raw];
|
||||
if ( bits ) {
|
||||
alphabet->huf[ bits - 1 ].freq++;
|
||||
empty = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* In the degenerate case of having no symbols (i.e. an unused
|
||||
* alphabet), generate a trivial alphabet with exactly two
|
||||
* single-bit codes. This allows callers to avoid having to
|
||||
* check for this special case.
|
||||
*/
|
||||
if ( empty )
|
||||
alphabet->huf[0].freq = 2;
|
||||
|
||||
/* Populate Huffman-coded symbol table */
|
||||
huf = 0;
|
||||
cum_freq = 0;
|
||||
for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) /
|
||||
sizeof ( alphabet->huf[0] ) ) ; bits++ ) {
|
||||
sym = &alphabet->huf[ bits - 1 ];
|
||||
sym->bits = bits;
|
||||
sym->shift = ( HUFFMAN_BITS - bits );
|
||||
sym->start = ( huf << sym->shift );
|
||||
sym->raw = &alphabet->raw[cum_freq];
|
||||
huf += sym->freq;
|
||||
if ( huf > ( 1U << bits ) ) {
|
||||
DBG ( "Huffman alphabet has too many symbols with "
|
||||
"lengths <=%d\n", bits );
|
||||
return -1;
|
||||
}
|
||||
huf <<= 1;
|
||||
cum_freq += sym->freq;
|
||||
}
|
||||
complete = ( huf == ( 1U << bits ) );
|
||||
|
||||
/* Populate raw symbol table */
|
||||
for ( raw = 0 ; raw < count ; raw++ ) {
|
||||
bits = lengths[raw];
|
||||
if ( bits ) {
|
||||
sym = &alphabet->huf[ bits - 1 ];
|
||||
*(sym->raw++) = raw;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust Huffman-coded symbol table raw pointers and populate
|
||||
* quick lookup table.
|
||||
*/
|
||||
for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) /
|
||||
sizeof ( alphabet->huf[0] ) ) ; bits++ ) {
|
||||
sym = &alphabet->huf[ bits - 1 ];
|
||||
|
||||
/* Adjust raw pointer */
|
||||
sym->raw -= sym->freq; /* Reset to first symbol */
|
||||
adjustment = ( sym->start >> sym->shift );
|
||||
sym->raw -= adjustment; /* Adjust for quick indexing */
|
||||
|
||||
/* Populate quick lookup table */
|
||||
for ( prefix = ( sym->start >> HUFFMAN_QL_SHIFT ) ;
|
||||
prefix < ( 1 << HUFFMAN_QL_BITS ) ; prefix++ ) {
|
||||
alphabet->lookup[prefix] = ( bits - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that there are no invalid codes */
|
||||
if ( ! complete ) {
|
||||
DBG ( "Huffman alphabet is incomplete\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Huffman symbol set
|
||||
*
|
||||
* @v alphabet Huffman alphabet
|
||||
* @v huf Raw input value (normalised to HUFFMAN_BITS bits)
|
||||
* @ret sym Huffman symbol set
|
||||
*/
|
||||
struct huffman_symbols * huffman_sym ( struct huffman_alphabet *alphabet,
|
||||
unsigned int huf ) {
|
||||
struct huffman_symbols *sym;
|
||||
unsigned int lookup_index;
|
||||
|
||||
/* Find symbol set for this length */
|
||||
lookup_index = ( huf >> HUFFMAN_QL_SHIFT );
|
||||
sym = &alphabet->huf[ alphabet->lookup[ lookup_index ] ];
|
||||
while ( huf < sym->start )
|
||||
sym--;
|
||||
return sym;
|
||||
}
|
||||
108
GRUB2/grub-2.04/grub-core/ventoy/huffman.h
Normal file
108
GRUB2/grub-2.04/grub-core/ventoy/huffman.h
Normal file
@@ -0,0 +1,108 @@
|
||||
#ifndef _HUFFMAN_H
|
||||
#define _HUFFMAN_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 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
|
||||
*
|
||||
* Huffman alphabets
|
||||
*
|
||||
*/
|
||||
|
||||
/** Maximum length of a Huffman symbol (in bits) */
|
||||
#define HUFFMAN_BITS 16
|
||||
|
||||
/** Raw huffman symbol */
|
||||
typedef uint16_t huffman_raw_symbol_t;
|
||||
|
||||
/** Quick lookup length for a Huffman symbol (in bits)
|
||||
*
|
||||
* This is a policy decision.
|
||||
*/
|
||||
#define HUFFMAN_QL_BITS 7
|
||||
|
||||
/** Quick lookup shift */
|
||||
#define HUFFMAN_QL_SHIFT ( HUFFMAN_BITS - HUFFMAN_QL_BITS )
|
||||
|
||||
/** A Huffman-coded set of symbols of a given length */
|
||||
struct huffman_symbols {
|
||||
/** Length of Huffman-coded symbols (in bits) */
|
||||
uint8_t bits;
|
||||
/** Shift to normalise symbols of this length to HUFFMAN_BITS bits */
|
||||
uint8_t shift;
|
||||
/** Number of Huffman-coded symbols having this length */
|
||||
uint16_t freq;
|
||||
/** First symbol of this length (normalised to HUFFMAN_BITS bits)
|
||||
*
|
||||
* Stored as a 32-bit value to allow the value
|
||||
* (1<<HUFFMAN_BITS ) to be used for empty sets of symbols
|
||||
* longer than the maximum utilised length.
|
||||
*/
|
||||
uint32_t start;
|
||||
/** Raw symbols having this length */
|
||||
huffman_raw_symbol_t *raw;
|
||||
};
|
||||
|
||||
/** A Huffman-coded alphabet */
|
||||
struct huffman_alphabet {
|
||||
/** Huffman-coded symbol set for each length */
|
||||
struct huffman_symbols huf[HUFFMAN_BITS];
|
||||
/** Quick lookup table */
|
||||
uint8_t lookup[ 1 << HUFFMAN_QL_BITS ];
|
||||
/** Raw symbols
|
||||
*
|
||||
* Ordered by Huffman-coded symbol length, then by symbol
|
||||
* value. This field has a variable length.
|
||||
*/
|
||||
huffman_raw_symbol_t raw[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get Huffman symbol length
|
||||
*
|
||||
* @v sym Huffman symbol set
|
||||
* @ret len Length (in bits)
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) unsigned int
|
||||
huffman_len ( struct huffman_symbols *sym ) {
|
||||
|
||||
return sym->bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Huffman symbol value
|
||||
*
|
||||
* @v sym Huffman symbol set
|
||||
* @v huf Raw input value (normalised to HUFFMAN_BITS bits)
|
||||
* @ret raw Raw symbol value
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) huffman_raw_symbol_t
|
||||
huffman_raw ( struct huffman_symbols *sym, unsigned int huf ) {
|
||||
|
||||
return sym->raw[ huf >> sym->shift ];
|
||||
}
|
||||
|
||||
extern int huffman_alphabet ( struct huffman_alphabet *alphabet,
|
||||
uint8_t *lengths, unsigned int count );
|
||||
extern struct huffman_symbols *
|
||||
huffman_sym ( struct huffman_alphabet *alphabet, unsigned int huf );
|
||||
|
||||
#endif /* _HUFFMAN_H */
|
||||
666
GRUB2/grub-2.04/grub-core/ventoy/lzx.c
Normal file
666
GRUB2/grub-2.04/grub-core/ventoy/lzx.c
Normal file
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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
|
||||
*
|
||||
* LZX decompression
|
||||
*
|
||||
* This algorithm is derived jointly from the document "[MS-PATCH]:
|
||||
* LZX DELTA Compression and Decompression", available from
|
||||
*
|
||||
* http://msdn.microsoft.com/en-us/library/cc483133.aspx
|
||||
*
|
||||
* and from the file lzx-decompress.c in the wimlib source code.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "wimboot.h"
|
||||
#include "huffman.h"
|
||||
#include "lzx.h"
|
||||
|
||||
/** Base positions, indexed by position slot */
|
||||
static unsigned int lzx_position_base[LZX_POSITION_SLOTS];
|
||||
|
||||
/**
|
||||
* Attempt to accumulate bits from LZX bitstream
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v bits Number of bits to accumulate
|
||||
* @v norm_value Accumulated value (normalised to 16 bits)
|
||||
*
|
||||
* Note that there may not be sufficient accumulated bits in the
|
||||
* bitstream; callers must check that sufficient bits are available
|
||||
* before using the value.
|
||||
*/
|
||||
static int lzx_accumulate ( struct lzx *lzx, unsigned int bits ) {
|
||||
const uint16_t *src16;
|
||||
|
||||
/* Accumulate more bits if required */
|
||||
if ( ( lzx->bits < bits ) &&
|
||||
( lzx->input.offset < lzx->input.len ) ) {
|
||||
src16 = (const uint16_t *)( ( char * ) lzx->input.data + lzx->input.offset );
|
||||
lzx->input.offset += sizeof ( *src16 );
|
||||
lzx->accumulator |= ( *src16 << ( 16 - lzx->bits ) );
|
||||
lzx->bits += 16;
|
||||
}
|
||||
|
||||
return ( lzx->accumulator >> 16 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume accumulated bits from LZX bitstream
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v bits Number of bits to consume
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_consume ( struct lzx *lzx, unsigned int bits ) {
|
||||
|
||||
/* Fail if insufficient bits are available */
|
||||
if ( lzx->bits < bits ) {
|
||||
DBG ( "LZX input overrun in %#zx/%#zx out %#zx)\n",
|
||||
lzx->input.offset, lzx->input.len, lzx->output.offset );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Consume bits */
|
||||
lzx->accumulator <<= bits;
|
||||
lzx->bits -= bits;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bits from LZX bitstream
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v bits Number of bits to fetch
|
||||
* @ret value Value, or negative error
|
||||
*/
|
||||
static int lzx_getbits ( struct lzx *lzx, unsigned int bits ) {
|
||||
int norm_value;
|
||||
int rc;
|
||||
|
||||
/* Accumulate more bits if required */
|
||||
norm_value = lzx_accumulate ( lzx, bits );
|
||||
|
||||
/* Consume bits */
|
||||
if ( ( rc = lzx_consume ( lzx, bits ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return ( norm_value >> ( 16 - bits ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Align LZX bitstream for byte access
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v bits Minimum number of padding bits
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_align ( struct lzx *lzx, unsigned int bits ) {
|
||||
int pad;
|
||||
|
||||
/* Get padding bits */
|
||||
pad = lzx_getbits ( lzx, bits );
|
||||
if ( pad < 0 )
|
||||
return pad;
|
||||
|
||||
/* Consume all accumulated bits */
|
||||
lzx_consume ( lzx, lzx->bits );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bytes from LZX bitstream
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v data Data buffer, or NULL
|
||||
* @v len Length of data buffer
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_getbytes ( struct lzx *lzx, void *data, size_t len ) {
|
||||
|
||||
/* Sanity check */
|
||||
if ( ( lzx->input.offset + len ) > lzx->input.len ) {
|
||||
DBG ( "LZX input overrun in %#zx/%#zx out %#zx)\n",
|
||||
lzx->input.offset, lzx->input.len, lzx->output.offset );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy data */
|
||||
if ( data )
|
||||
memcpy ( data, ( lzx->input.data + lzx->input.offset ), len );
|
||||
lzx->input.offset += len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode LZX Huffman-coded symbol
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v alphabet Huffman alphabet
|
||||
* @ret raw Raw symbol, or negative error
|
||||
*/
|
||||
static int lzx_decode ( struct lzx *lzx, struct huffman_alphabet *alphabet ) {
|
||||
struct huffman_symbols *sym;
|
||||
int huf;
|
||||
int rc;
|
||||
|
||||
/* Accumulate sufficient bits */
|
||||
huf = lzx_accumulate ( lzx, HUFFMAN_BITS );
|
||||
if ( huf < 0 )
|
||||
return huf;
|
||||
|
||||
/* Decode symbol */
|
||||
sym = huffman_sym ( alphabet, huf );
|
||||
|
||||
/* Consume bits */
|
||||
if ( ( rc = lzx_consume ( lzx, huffman_len ( sym ) ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return huffman_raw ( sym, huf );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Huffman alphabet from raw length table
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v count Number of symbols
|
||||
* @v bits Length of each length (in bits)
|
||||
* @v lengths Lengths table to fill in
|
||||
* @v alphabet Huffman alphabet to fill in
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_raw_alphabet ( struct lzx *lzx, unsigned int count,
|
||||
unsigned int bits, uint8_t *lengths,
|
||||
struct huffman_alphabet *alphabet ) {
|
||||
unsigned int i;
|
||||
int len;
|
||||
int rc;
|
||||
|
||||
/* Read lengths */
|
||||
for ( i = 0 ; i < count ; i++ ) {
|
||||
len = lzx_getbits ( lzx, bits );
|
||||
if ( len < 0 )
|
||||
return len;
|
||||
lengths[i] = len;
|
||||
}
|
||||
|
||||
/* Generate Huffman alphabet */
|
||||
if ( ( rc = huffman_alphabet ( alphabet, lengths, count ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate pretree
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v count Number of symbols
|
||||
* @v lengths Lengths table to fill in
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_pretree ( struct lzx *lzx, unsigned int count,
|
||||
uint8_t *lengths ) {
|
||||
unsigned int i;
|
||||
unsigned int length;
|
||||
int dup = 0;
|
||||
int code;
|
||||
int rc;
|
||||
|
||||
/* Generate pretree alphabet */
|
||||
if ( ( rc = lzx_raw_alphabet ( lzx, LZX_PRETREE_CODES,
|
||||
LZX_PRETREE_BITS, lzx->pretree_lengths,
|
||||
&lzx->pretree ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Read lengths */
|
||||
for ( i = 0 ; i < count ; i++ ) {
|
||||
|
||||
if ( dup ) {
|
||||
|
||||
/* Duplicate previous length */
|
||||
lengths[i] = lengths[ i - 1 ];
|
||||
dup--;
|
||||
|
||||
} else {
|
||||
|
||||
/* Get next code */
|
||||
code = lzx_decode ( lzx, &lzx->pretree );
|
||||
if ( code < 0 )
|
||||
return code;
|
||||
|
||||
/* Interpret code */
|
||||
if ( code <= 16 ) {
|
||||
length = ( ( lengths[i] - code + 17 ) % 17 );
|
||||
} else if ( code == 17 ) {
|
||||
length = 0;
|
||||
dup = lzx_getbits ( lzx, 4 );
|
||||
if ( dup < 0 )
|
||||
return dup;
|
||||
dup += 3;
|
||||
} else if ( code == 18 ) {
|
||||
length = 0;
|
||||
dup = lzx_getbits ( lzx, 5 );
|
||||
if ( dup < 0 )
|
||||
return dup;
|
||||
dup += 19;
|
||||
} else if ( code == 19 ) {
|
||||
length = 0;
|
||||
dup = lzx_getbits ( lzx, 1 );
|
||||
if ( dup < 0 )
|
||||
return dup;
|
||||
dup += 3;
|
||||
code = lzx_decode ( lzx, &lzx->pretree );
|
||||
if ( code < 0 )
|
||||
return code;
|
||||
length = ( ( lengths[i] - code + 17 ) % 17 );
|
||||
} else {
|
||||
DBG ( "Unrecognised pretree code %d\n", code );
|
||||
return -1;
|
||||
}
|
||||
lengths[i] = length;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
if ( dup ) {
|
||||
DBG ( "Pretree duplicate overrun\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate aligned offset Huffman alphabet
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_alignoffset_alphabet ( struct lzx *lzx ) {
|
||||
int rc;
|
||||
|
||||
/* Generate aligned offset alphabet */
|
||||
if ( ( rc = lzx_raw_alphabet ( lzx, LZX_ALIGNOFFSET_CODES,
|
||||
LZX_ALIGNOFFSET_BITS,
|
||||
lzx->alignoffset_lengths,
|
||||
&lzx->alignoffset ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate main Huffman alphabet
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_main_alphabet ( struct lzx *lzx ) {
|
||||
int rc;
|
||||
|
||||
/* Generate literal symbols pretree */
|
||||
if ( ( rc = lzx_pretree ( lzx, LZX_MAIN_LIT_CODES,
|
||||
lzx->main_lengths.literals ) ) != 0 ) {
|
||||
DBG ( "Could not construct main literal pretree\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Generate remaining symbols pretree */
|
||||
if ( ( rc = lzx_pretree ( lzx, ( LZX_MAIN_CODES - LZX_MAIN_LIT_CODES ),
|
||||
lzx->main_lengths.remainder ) ) != 0 ) {
|
||||
DBG ( "Could not construct main remainder pretree\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Generate Huffman alphabet */
|
||||
if ( ( rc = huffman_alphabet ( &lzx->main, lzx->main_lengths.literals,
|
||||
LZX_MAIN_CODES ) ) != 0 ) {
|
||||
DBG ( "Could not generate main alphabet\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate length Huffman alphabet
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_length_alphabet ( struct lzx *lzx ) {
|
||||
int rc;
|
||||
|
||||
/* Generate pretree */
|
||||
if ( ( rc = lzx_pretree ( lzx, LZX_LENGTH_CODES,
|
||||
lzx->length_lengths ) ) != 0 ) {
|
||||
DBG ( "Could not generate length pretree\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Generate Huffman alphabet */
|
||||
if ( ( rc = huffman_alphabet ( &lzx->length, lzx->length_lengths,
|
||||
LZX_LENGTH_CODES ) ) != 0 ) {
|
||||
DBG ( "Could not generate length alphabet\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process LZX block header
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_block_header ( struct lzx *lzx ) {
|
||||
size_t block_len;
|
||||
int block_type;
|
||||
int default_len;
|
||||
int len_high;
|
||||
int len_low;
|
||||
int rc;
|
||||
|
||||
/* Get block type */
|
||||
block_type = lzx_getbits ( lzx, LZX_BLOCK_TYPE_BITS );
|
||||
if ( block_type < 0 )
|
||||
return block_type;
|
||||
lzx->block_type = block_type;
|
||||
|
||||
/* Check block length */
|
||||
default_len = lzx_getbits ( lzx, 1 );
|
||||
if ( default_len < 0 )
|
||||
return default_len;
|
||||
if ( default_len ) {
|
||||
block_len = LZX_DEFAULT_BLOCK_LEN;
|
||||
} else {
|
||||
len_high = lzx_getbits ( lzx, 8 );
|
||||
if ( len_high < 0 )
|
||||
return len_high;
|
||||
len_low = lzx_getbits ( lzx, 8 );
|
||||
if ( len_low < 0 )
|
||||
return len_low;
|
||||
block_len = ( ( len_high << 8 ) | len_low );
|
||||
}
|
||||
lzx->output.threshold = ( lzx->output.offset + block_len );
|
||||
|
||||
/* Handle block type */
|
||||
switch ( block_type ) {
|
||||
case LZX_BLOCK_ALIGNOFFSET :
|
||||
/* Generated aligned offset alphabet */
|
||||
if ( ( rc = lzx_alignoffset_alphabet ( lzx ) ) != 0 )
|
||||
return rc;
|
||||
/* Fall through */
|
||||
case LZX_BLOCK_VERBATIM :
|
||||
/* Generate main alphabet */
|
||||
if ( ( rc = lzx_main_alphabet ( lzx ) ) != 0 )
|
||||
return rc;
|
||||
/* Generate lengths alphabet */
|
||||
if ( ( rc = lzx_length_alphabet ( lzx ) ) != 0 )
|
||||
return rc;
|
||||
break;
|
||||
case LZX_BLOCK_UNCOMPRESSED :
|
||||
/* Align input stream */
|
||||
if ( ( rc = lzx_align ( lzx, 1 ) ) != 0 )
|
||||
return rc;
|
||||
/* Read new repeated offsets */
|
||||
if ( ( rc = lzx_getbytes ( lzx, &lzx->repeated_offset,
|
||||
sizeof ( lzx->repeated_offset )))!=0)
|
||||
return rc;
|
||||
break;
|
||||
default:
|
||||
DBG ( "Unrecognised block type %d\n", block_type );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process uncompressed data
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_uncompressed ( struct lzx *lzx ) {
|
||||
void *data;
|
||||
size_t len;
|
||||
int rc;
|
||||
|
||||
/* Copy bytes */
|
||||
data = ( lzx->output.data ?
|
||||
( lzx->output.data + lzx->output.offset ) : NULL );
|
||||
len = ( lzx->output.threshold - lzx->output.offset );
|
||||
if ( ( rc = lzx_getbytes ( lzx, data, len ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Align input stream */
|
||||
if ( len % 2 )
|
||||
lzx->input.offset++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an LZX token
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* Variable names are chosen to match the LZX specification
|
||||
* pseudo-code.
|
||||
*/
|
||||
static int lzx_token ( struct lzx *lzx ) {
|
||||
unsigned int length_header;
|
||||
unsigned int position_slot;
|
||||
unsigned int offset_bits;
|
||||
unsigned int i;
|
||||
size_t match_offset;
|
||||
size_t match_length;
|
||||
int verbatim_bits;
|
||||
int aligned_bits;
|
||||
int maindata;
|
||||
int length;
|
||||
uint8_t *copy;
|
||||
|
||||
/* Get maindata symelse*/
|
||||
maindata = lzx_decode ( lzx, &lzx->main );
|
||||
if ( maindata < 0 )
|
||||
return maindata;
|
||||
|
||||
/* Check for literals */
|
||||
if ( maindata < LZX_MAIN_LIT_CODES ) {
|
||||
if ( lzx->output.data )
|
||||
lzx->output.data[lzx->output.offset] = maindata;
|
||||
lzx->output.offset++;
|
||||
return 0;
|
||||
}
|
||||
maindata -= LZX_MAIN_LIT_CODES;
|
||||
|
||||
/* Calculate the match length */
|
||||
length_header = ( maindata & 7 );
|
||||
if ( length_header == 7 ) {
|
||||
length = lzx_decode ( lzx, &lzx->length );
|
||||
if ( length < 0 )
|
||||
return length;
|
||||
} else {
|
||||
length = 0;
|
||||
}
|
||||
match_length = ( length_header + 2 + length );
|
||||
|
||||
/* Calculate the position slot */
|
||||
position_slot = ( maindata >> 3 );
|
||||
if ( position_slot < LZX_REPEATED_OFFSETS ) {
|
||||
|
||||
/* Repeated offset */
|
||||
match_offset = lzx->repeated_offset[position_slot];
|
||||
lzx->repeated_offset[position_slot] = lzx->repeated_offset[0];
|
||||
lzx->repeated_offset[0] = match_offset;
|
||||
|
||||
} else {
|
||||
|
||||
/* Non-repeated offset */
|
||||
offset_bits = lzx_footer_bits ( position_slot );
|
||||
if ( ( lzx->block_type == LZX_BLOCK_ALIGNOFFSET ) &&
|
||||
( offset_bits >= 3 ) ) {
|
||||
verbatim_bits = lzx_getbits ( lzx, ( offset_bits - 3 ));
|
||||
if ( verbatim_bits < 0 )
|
||||
return verbatim_bits;
|
||||
verbatim_bits <<= 3;
|
||||
aligned_bits = lzx_decode ( lzx, &lzx->alignoffset );
|
||||
if ( aligned_bits < 0 )
|
||||
return aligned_bits;
|
||||
} else {
|
||||
verbatim_bits = lzx_getbits ( lzx, offset_bits );
|
||||
if ( verbatim_bits < 0 )
|
||||
return verbatim_bits;
|
||||
aligned_bits = 0;
|
||||
}
|
||||
match_offset = ( lzx_position_base[position_slot] +
|
||||
verbatim_bits + aligned_bits - 2 );
|
||||
|
||||
/* Update repeated offset list */
|
||||
for ( i = ( LZX_REPEATED_OFFSETS - 1 ) ; i > 0 ; i-- )
|
||||
lzx->repeated_offset[i] = lzx->repeated_offset[ i - 1 ];
|
||||
lzx->repeated_offset[0] = match_offset;
|
||||
}
|
||||
|
||||
/* Copy data */
|
||||
if ( match_offset > lzx->output.offset ) {
|
||||
DBG ( "LZX match underrun out 0x%x offset 0x%x len 0x%x\n",
|
||||
lzx->output.offset, match_offset, match_length );
|
||||
return -1;
|
||||
}
|
||||
if ( lzx->output.data ) {
|
||||
copy = &lzx->output.data[lzx->output.offset];
|
||||
for ( i = 0 ; i < match_length ; i++ )
|
||||
copy[i] = copy[ i - match_offset ];
|
||||
}
|
||||
lzx->output.offset += match_length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate E8 jump addresses
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
*/
|
||||
static void lzx_translate_jumps ( struct lzx *lzx ) {
|
||||
size_t offset;
|
||||
int32_t *target;
|
||||
|
||||
/* Sanity check */
|
||||
if ( lzx->output.offset < 10 )
|
||||
return;
|
||||
|
||||
/* Scan for jump instructions */
|
||||
for ( offset = 0 ; offset < ( lzx->output.offset - 10 ) ; offset++ ) {
|
||||
|
||||
/* Check for jump instruction */
|
||||
if ( lzx->output.data[offset] != 0xe8 )
|
||||
continue;
|
||||
|
||||
/* Translate jump target */
|
||||
target = ( ( int32_t * ) &lzx->output.data[ offset + 1 ] );
|
||||
if ( *target >= 0 ) {
|
||||
if ( *target < LZX_WIM_MAGIC_FILESIZE )
|
||||
*target -= offset;
|
||||
} else {
|
||||
if ( *target >= -( ( int32_t ) offset ) )
|
||||
*target += LZX_WIM_MAGIC_FILESIZE;
|
||||
}
|
||||
offset += sizeof ( *target );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress LZX-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 lzx_decompress ( const void *data, size_t len, void *buf ) {
|
||||
struct lzx lzx;
|
||||
unsigned int i;
|
||||
int rc;
|
||||
|
||||
/* Sanity check */
|
||||
if ( len % 2 ) {
|
||||
DBG ( "LZX cannot handle odd-length input data\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialise global state, if required */
|
||||
if ( ! lzx_position_base[ LZX_POSITION_SLOTS - 1 ] ) {
|
||||
for ( i = 1 ; i < LZX_POSITION_SLOTS ; i++ ) {
|
||||
lzx_position_base[i] =
|
||||
( lzx_position_base[i-1] +
|
||||
( 1 << lzx_footer_bits ( i - 1 ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialise decompressor */
|
||||
memset ( &lzx, 0, sizeof ( lzx ) );
|
||||
lzx.input.data = data;
|
||||
lzx.input.len = len;
|
||||
lzx.output.data = buf;
|
||||
for ( i = 0 ; i < LZX_REPEATED_OFFSETS ; i++ )
|
||||
lzx.repeated_offset[i] = 1;
|
||||
|
||||
/* Process blocks */
|
||||
while ( lzx.input.offset < lzx.input.len ) {
|
||||
|
||||
/* Process block header */
|
||||
if ( ( rc = lzx_block_header ( &lzx ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Process block contents */
|
||||
if ( lzx.block_type == LZX_BLOCK_UNCOMPRESSED ) {
|
||||
|
||||
/* Copy uncompressed data */
|
||||
if ( ( rc = lzx_uncompressed ( &lzx ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
} else {
|
||||
|
||||
/* Process token stream */
|
||||
while ( lzx.output.offset < lzx.output.threshold ) {
|
||||
if ( ( rc = lzx_token ( &lzx ) ) != 0 )
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Postprocess to undo E8 jump compression */
|
||||
if ( lzx.output.data )
|
||||
lzx_translate_jumps ( &lzx );
|
||||
|
||||
return lzx.output.offset;
|
||||
}
|
||||
179
GRUB2/grub-2.04/grub-core/ventoy/lzx.h
Normal file
179
GRUB2/grub-2.04/grub-core/ventoy/lzx.h
Normal file
@@ -0,0 +1,179 @@
|
||||
#ifndef _LZX_H
|
||||
#define _LZX_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 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
|
||||
*
|
||||
* LZX decompression
|
||||
*
|
||||
*/
|
||||
|
||||
#include "huffman.h"
|
||||
|
||||
/** Number of aligned offset codes */
|
||||
#define LZX_ALIGNOFFSET_CODES 8
|
||||
|
||||
/** Aligned offset code length (in bits) */
|
||||
#define LZX_ALIGNOFFSET_BITS 3
|
||||
|
||||
/** Number of pretree codes */
|
||||
#define LZX_PRETREE_CODES 20
|
||||
|
||||
/** Pretree code length (in bits) */
|
||||
#define LZX_PRETREE_BITS 4
|
||||
|
||||
/** Number of literal main codes */
|
||||
#define LZX_MAIN_LIT_CODES 256
|
||||
|
||||
/** Number of position slots */
|
||||
#define LZX_POSITION_SLOTS 30
|
||||
|
||||
/** Number of main codes */
|
||||
#define LZX_MAIN_CODES ( LZX_MAIN_LIT_CODES + ( 8 * LZX_POSITION_SLOTS ) )
|
||||
|
||||
/** Number of length codes */
|
||||
#define LZX_LENGTH_CODES 249
|
||||
|
||||
/** Block type length (in bits) */
|
||||
#define LZX_BLOCK_TYPE_BITS 3
|
||||
|
||||
/** Default block length */
|
||||
#define LZX_DEFAULT_BLOCK_LEN 32768
|
||||
|
||||
/** Number of repeated offsets */
|
||||
#define LZX_REPEATED_OFFSETS 3
|
||||
|
||||
/** Don't ask */
|
||||
#define LZX_WIM_MAGIC_FILESIZE 12000000
|
||||
|
||||
/** Block types */
|
||||
enum lzx_block_type {
|
||||
/** Verbatim block */
|
||||
LZX_BLOCK_VERBATIM = 1,
|
||||
/** Aligned offset block */
|
||||
LZX_BLOCK_ALIGNOFFSET = 2,
|
||||
/** Uncompressed block */
|
||||
LZX_BLOCK_UNCOMPRESSED = 3,
|
||||
};
|
||||
|
||||
/** An LZX input stream */
|
||||
struct lzx_input_stream {
|
||||
/** Data */
|
||||
const uint8_t *data;
|
||||
/** Length */
|
||||
size_t len;
|
||||
/** Offset within stream */
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
/** An LZX output stream */
|
||||
struct lzx_output_stream {
|
||||
/** Data, or NULL */
|
||||
uint8_t *data;
|
||||
/** Offset within stream */
|
||||
size_t offset;
|
||||
/** End of current block within stream */
|
||||
size_t threshold;
|
||||
};
|
||||
|
||||
/** LZX decompressor */
|
||||
struct lzx {
|
||||
/** Input stream */
|
||||
struct lzx_input_stream input;
|
||||
/** Output stream */
|
||||
struct lzx_output_stream output;
|
||||
/** Accumulator */
|
||||
uint32_t accumulator;
|
||||
/** Number of bits in accumulator */
|
||||
unsigned int bits;
|
||||
/** Block type */
|
||||
enum lzx_block_type block_type;
|
||||
/** Repeated offsets */
|
||||
unsigned int repeated_offset[LZX_REPEATED_OFFSETS];
|
||||
|
||||
/** Aligned offset Huffman alphabet */
|
||||
struct huffman_alphabet alignoffset;
|
||||
/** Aligned offset raw symbols
|
||||
*
|
||||
* Must immediately follow the aligned offset Huffman
|
||||
* alphabet.
|
||||
*/
|
||||
huffman_raw_symbol_t alignoffset_raw[LZX_ALIGNOFFSET_CODES];
|
||||
/** Aligned offset code lengths */
|
||||
uint8_t alignoffset_lengths[LZX_ALIGNOFFSET_CODES];
|
||||
|
||||
/** Pretree Huffman alphabet */
|
||||
struct huffman_alphabet pretree;
|
||||
/** Pretree raw symbols
|
||||
*
|
||||
* Must immediately follow the pretree Huffman alphabet.
|
||||
*/
|
||||
huffman_raw_symbol_t pretree_raw[LZX_PRETREE_CODES];
|
||||
/** Preetree code lengths */
|
||||
uint8_t pretree_lengths[LZX_PRETREE_CODES];
|
||||
|
||||
/** Main Huffman alphabet */
|
||||
struct huffman_alphabet main;
|
||||
/** Main raw symbols
|
||||
*
|
||||
* Must immediately follow the main Huffman alphabet.
|
||||
*/
|
||||
huffman_raw_symbol_t main_raw[LZX_MAIN_CODES];
|
||||
/** Main code lengths */
|
||||
struct {
|
||||
/** Literals */
|
||||
uint8_t literals[LZX_MAIN_LIT_CODES];
|
||||
/** Remaining symbols */
|
||||
uint8_t remainder[ LZX_MAIN_CODES - LZX_MAIN_LIT_CODES ];
|
||||
} __attribute__ (( packed )) main_lengths;
|
||||
|
||||
/** Length Huffman alphabet */
|
||||
struct huffman_alphabet length;
|
||||
/** Length raw symbols
|
||||
*
|
||||
* Must immediately follow the length Huffman alphabet.
|
||||
*/
|
||||
huffman_raw_symbol_t length_raw[LZX_LENGTH_CODES];
|
||||
/** Length code lengths */
|
||||
uint8_t length_lengths[LZX_LENGTH_CODES];
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate number of footer bits for a given position slot
|
||||
*
|
||||
* @v position_slot Position slot
|
||||
* @ret footer_bits Number of footer bits
|
||||
*/
|
||||
static inline unsigned int lzx_footer_bits ( unsigned int position_slot ) {
|
||||
|
||||
if ( position_slot < 2 ) {
|
||||
return 0;
|
||||
} else if ( position_slot < 38 ) {
|
||||
return ( ( position_slot / 2 ) - 1 );
|
||||
} else {
|
||||
return 17;
|
||||
}
|
||||
}
|
||||
|
||||
extern ssize_t lzx_decompress ( const void *data, size_t len, void *buf );
|
||||
|
||||
#endif /* _LZX_H */
|
||||
1153
GRUB2/grub-2.04/grub-core/ventoy/ventoy.c
Normal file
1153
GRUB2/grub-2.04/grub-core/ventoy/ventoy.c
Normal file
File diff suppressed because it is too large
Load Diff
507
GRUB2/grub-2.04/grub-core/ventoy/ventoy_def.h
Normal file
507
GRUB2/grub-2.04/grub-core/ventoy/ventoy_def.h
Normal file
@@ -0,0 +1,507 @@
|
||||
/******************************************************************************
|
||||
* ventoy_def.h
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __VENTOY_DEF_H__
|
||||
#define __VENTOY_DEF_H__
|
||||
|
||||
#define JSON_SUCCESS 0
|
||||
#define JSON_FAILED 1
|
||||
#define JSON_NOT_FOUND 2
|
||||
|
||||
#define ulonglong unsigned long long
|
||||
|
||||
#define vtoy_to_upper(c) (((char)(c) >= 'a' && (char)(c) <= 'z') ? ((char)(c) - 'a' + 'A') : (char)(c))
|
||||
|
||||
#define VENTOY_CMD_RETURN(err) grub_errno = (err); return (err)
|
||||
#define VENTOY_FILE_TYPE (GRUB_FILE_TYPE_NO_DECOMPRESS | GRUB_FILE_TYPE_LINUX_INITRD)
|
||||
|
||||
#define ventoy_env_op1(op, a) grub_env_##op(a)
|
||||
#define ventoy_env_op2(op, a, b) grub_env_##op((a), (b))
|
||||
|
||||
#define ventoy_get_env(key) ventoy_env_op1(get, key)
|
||||
#define ventoy_set_env(key, val) ventoy_env_op2(set, key, val)
|
||||
|
||||
typedef struct ventoy_initrd_ctx
|
||||
{
|
||||
const char *path_prefix;
|
||||
const char *dir_prefix;
|
||||
}ventoy_initrd_ctx;
|
||||
|
||||
typedef struct cmd_para
|
||||
{
|
||||
const char *name;
|
||||
grub_extcmd_func_t func;
|
||||
grub_command_flags_t flags;
|
||||
const struct grub_arg_option *parser;
|
||||
|
||||
const char *summary;
|
||||
const char *description;
|
||||
|
||||
grub_extcmd_t cmd;
|
||||
}cmd_para;
|
||||
|
||||
#define ventoy_align(value, align) (((value) + ((align) - 1)) & (~((align) - 1)))
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct cpio_newc_header
|
||||
{
|
||||
char c_magic[6];
|
||||
char c_ino[8];
|
||||
char c_mode[8];
|
||||
char c_uid[8];
|
||||
char c_gid[8];
|
||||
char c_nlink[8];
|
||||
char c_mtime[8];
|
||||
char c_filesize[8];
|
||||
char c_devmajor[8];
|
||||
char c_devminor[8];
|
||||
char c_rdevmajor[8];
|
||||
char c_rdevminor[8];
|
||||
char c_namesize[8];
|
||||
char c_check[8];
|
||||
}cpio_newc_header;
|
||||
#pragma pack()
|
||||
|
||||
|
||||
#define cmd_raw_name ctxt->extcmd->cmd->name
|
||||
#define check_free(p, func) if (p) { func(p); p = NULL; }
|
||||
|
||||
typedef int (*grub_char_check_func)(int c);
|
||||
#define ventoy_is_decimal(str) ventoy_string_check(str, grub_isdigit)
|
||||
|
||||
|
||||
// El Torito Boot Record Volume Descriptor
|
||||
#pragma pack(1)
|
||||
typedef struct eltorito_descriptor
|
||||
{
|
||||
grub_uint8_t type;
|
||||
grub_uint8_t id[5];
|
||||
grub_uint8_t version;
|
||||
grub_uint8_t system_id[32];
|
||||
grub_uint8_t reserved[32];
|
||||
grub_uint32_t sector;
|
||||
}eltorito_descriptor;
|
||||
|
||||
typedef struct ventoy_iso9660_override
|
||||
{
|
||||
grub_uint32_t first_sector;
|
||||
grub_uint32_t first_sector_be;
|
||||
grub_uint32_t size;
|
||||
grub_uint32_t size_be;
|
||||
}ventoy_iso9660_override;
|
||||
|
||||
typedef struct ventoy_udf_override
|
||||
{
|
||||
grub_uint32_t length;
|
||||
grub_uint32_t position;
|
||||
}ventoy_udf_override;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
|
||||
typedef struct img_info
|
||||
{
|
||||
char path[512];
|
||||
char name[256];
|
||||
|
||||
struct img_info *next;
|
||||
struct img_info *prev;
|
||||
}img_info;
|
||||
|
||||
typedef struct img_iterator_node
|
||||
{
|
||||
struct img_iterator_node *next;
|
||||
img_info **tail;
|
||||
char dir[400];
|
||||
}img_iterator_node;
|
||||
|
||||
typedef struct initrd_info
|
||||
{
|
||||
char name[256];
|
||||
|
||||
grub_uint64_t offset;
|
||||
grub_uint64_t size;
|
||||
|
||||
grub_uint8_t iso_type; // 0: iso9660 1:udf
|
||||
grub_uint32_t udf_start_block;
|
||||
|
||||
grub_uint64_t override_offset;
|
||||
grub_uint32_t override_length;
|
||||
char override_data[32];
|
||||
|
||||
struct initrd_info *next;
|
||||
struct initrd_info *prev;
|
||||
}initrd_info;
|
||||
|
||||
extern initrd_info *g_initrd_img_list;
|
||||
extern initrd_info *g_initrd_img_tail;
|
||||
extern int g_initrd_img_count;
|
||||
extern int g_valid_initrd_count;
|
||||
|
||||
extern img_info *g_ventoy_img_list;
|
||||
extern int g_ventoy_img_count;
|
||||
|
||||
extern grub_uint8_t *g_ventoy_cpio_buf;
|
||||
extern grub_uint32_t g_ventoy_cpio_size;
|
||||
extern cpio_newc_header *g_ventoy_initrd_head;
|
||||
extern grub_uint8_t *g_ventoy_runtime_buf;
|
||||
|
||||
extern ventoy_guid g_ventoy_guid;
|
||||
|
||||
extern ventoy_img_chunk_list g_img_chunk_list;
|
||||
|
||||
extern int g_ventoy_debug;
|
||||
void ventoy_debug(const char *fmt, ...);
|
||||
#define debug(fmt, ...) if (g_ventoy_debug) ventoy_debug("[VTOY]: "fmt, __VA_ARGS__)
|
||||
|
||||
|
||||
|
||||
#define FLAG_HEADER_RESERVED 0x00000001
|
||||
#define FLAG_HEADER_COMPRESSION 0x00000002
|
||||
#define FLAG_HEADER_READONLY 0x00000004
|
||||
#define FLAG_HEADER_SPANNED 0x00000008
|
||||
#define FLAG_HEADER_RESOURCE_ONLY 0x00000010
|
||||
#define FLAG_HEADER_METADATA_ONLY 0x00000020
|
||||
#define FLAG_HEADER_WRITE_IN_PROGRESS 0x00000040
|
||||
#define FLAG_HEADER_RP_FIX 0x00000080 // reparse point fixup
|
||||
#define FLAG_HEADER_COMPRESS_RESERVED 0x00010000
|
||||
#define FLAG_HEADER_COMPRESS_XPRESS 0x00020000
|
||||
#define FLAG_HEADER_COMPRESS_LZX 0x00040000
|
||||
|
||||
#define RESHDR_FLAG_FREE 0x01
|
||||
#define RESHDR_FLAG_METADATA 0x02
|
||||
#define RESHDR_FLAG_COMPRESSED 0x04
|
||||
#define RESHDR_FLAG_SPANNED 0x08
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/* A WIM resource header */
|
||||
typedef struct wim_resource_header
|
||||
{
|
||||
grub_uint64_t size_in_wim:56; /* Compressed length */
|
||||
grub_uint64_t flags:8; /* flags */
|
||||
grub_uint64_t offset; /* Offset */
|
||||
grub_uint64_t raw_size; /* Uncompressed length */
|
||||
}wim_resource_header;
|
||||
|
||||
/* WIM resource header length mask */
|
||||
#define WIM_RESHDR_ZLEN_MASK 0x00ffffffffffffffULL
|
||||
|
||||
/* WIM resource header flags */
|
||||
typedef enum wim_resource_header_flags
|
||||
{
|
||||
WIM_RESHDR_METADATA = ( 0x02ULL << 56 ), /* Resource contains metadata */
|
||||
WIM_RESHDR_COMPRESSED = ( 0x04ULL << 56 ), /* Resource is compressed */
|
||||
WIM_RESHDR_PACKED_STREAMS = ( 0x10ULL << 56 ), /* Resource is compressed using packed streams */
|
||||
}wim_resource_header_flags;
|
||||
|
||||
#define WIM_HEAD_SIGNATURE "MSWIM\0\0"
|
||||
|
||||
/* WIM header */
|
||||
typedef struct wim_header
|
||||
{
|
||||
grub_uint8_t signature[8]; /* Signature */
|
||||
grub_uint32_t header_len; /* Header length */
|
||||
grub_uint32_t version; /* Verson */
|
||||
grub_uint32_t flags; /* Flags */
|
||||
grub_uint32_t chunk_len; /* Chunk length */
|
||||
grub_uint8_t guid[16]; /* GUID */
|
||||
grub_uint16_t part; /* Part number */
|
||||
grub_uint16_t parts; /* Total number of parts */
|
||||
grub_uint32_t images; /* number of images */
|
||||
wim_resource_header lookup; /* Lookup table */
|
||||
wim_resource_header xml; /* XML data */
|
||||
wim_resource_header metadata; /* Boot metadata */
|
||||
grub_uint32_t boot_index; /* Boot index */
|
||||
wim_resource_header integrity; /* Integrity table */
|
||||
grub_uint8_t reserved[60]; /* Reserved */
|
||||
} wim_header;
|
||||
|
||||
/* WIM header flags */
|
||||
typedef enum wim_header_flags
|
||||
{
|
||||
WIM_HDR_XPRESS = 0x00020000, /* WIM uses Xpress compresson */
|
||||
WIM_HDR_LZX = 0x00040000, /* WIM uses LZX compression */
|
||||
}wim_header_flags;
|
||||
|
||||
/* A WIM file hash */
|
||||
typedef struct wim_hash
|
||||
{
|
||||
/* SHA-1 hash */
|
||||
grub_uint8_t sha1[20];
|
||||
}wim_hash;
|
||||
|
||||
/* A WIM lookup table entry */
|
||||
typedef struct wim_lookup_entry
|
||||
{
|
||||
wim_resource_header resource; /* Resource header */
|
||||
grub_uint16_t part; /* Part number */
|
||||
grub_uint32_t refcnt; /* Reference count */
|
||||
wim_hash hash; /* Hash */
|
||||
}wim_lookup_entry;
|
||||
|
||||
/* WIM chunk length */
|
||||
#define WIM_CHUNK_LEN 32768
|
||||
|
||||
/* A WIM chunk buffer */
|
||||
typedef struct wim_chunk_buffer
|
||||
{
|
||||
grub_uint8_t data[WIM_CHUNK_LEN]; /*Data */
|
||||
}wim_chunk_buffer;
|
||||
|
||||
/* Security data */
|
||||
typedef struct wim_security_header
|
||||
{
|
||||
grub_uint32_t len; /* Length */
|
||||
grub_uint32_t count; /* Number of entries */
|
||||
}wim_security_header;
|
||||
|
||||
/* Directory entry */
|
||||
typedef struct wim_directory_entry
|
||||
{
|
||||
grub_uint64_t len; /* Length */
|
||||
grub_uint32_t attributes; /* Attributes */
|
||||
grub_uint32_t security; /* Security ID */
|
||||
grub_uint64_t subdir; /* Subdirectory offset */
|
||||
grub_uint8_t reserved1[16]; /* Reserved */
|
||||
grub_uint64_t created; /* Creation time */
|
||||
grub_uint64_t accessed; /* Last access time */
|
||||
grub_uint64_t written; /* Last written time */
|
||||
wim_hash hash; /* Hash */
|
||||
grub_uint8_t reserved2[12]; /* Reserved */
|
||||
grub_uint16_t streams; /* Streams */
|
||||
grub_uint16_t short_name_len; /* Short name length */
|
||||
grub_uint16_t name_len; /* Name length */
|
||||
}wim_directory_entry;
|
||||
|
||||
/** Normal file */
|
||||
#define WIM_ATTR_NORMAL 0x00000080UL
|
||||
|
||||
/** No security information exists for this file */
|
||||
#define WIM_NO_SECURITY 0xffffffffUL
|
||||
|
||||
#pragma pack()
|
||||
|
||||
|
||||
typedef struct wim_tail
|
||||
{
|
||||
grub_uint32_t wim_raw_size;
|
||||
grub_uint32_t wim_align_size;
|
||||
|
||||
grub_uint8_t iso_type;
|
||||
grub_uint64_t file_offset;
|
||||
grub_uint32_t udf_start_block;
|
||||
grub_uint64_t fe_entry_size_offset;
|
||||
grub_uint64_t override_offset;
|
||||
grub_uint32_t override_len;
|
||||
grub_uint8_t override_data[32];
|
||||
|
||||
wim_header wim_header;
|
||||
|
||||
wim_hash bin_hash;
|
||||
grub_uint32_t jump_exe_len;
|
||||
grub_uint8_t *jump_bin_data;
|
||||
grub_uint32_t bin_raw_len;
|
||||
grub_uint32_t bin_align_len;
|
||||
|
||||
grub_uint8_t *new_meta_data;
|
||||
grub_uint32_t new_meta_len;
|
||||
grub_uint32_t new_meta_align_len;
|
||||
|
||||
grub_uint8_t *new_lookup_data;
|
||||
grub_uint32_t new_lookup_len;
|
||||
grub_uint32_t new_lookup_align_len;
|
||||
}wim_tail;
|
||||
|
||||
|
||||
|
||||
typedef enum _JSON_TYPE
|
||||
{
|
||||
JSON_TYPE_NUMBER = 0,
|
||||
JSON_TYPE_STRING,
|
||||
JSON_TYPE_BOOL,
|
||||
JSON_TYPE_ARRAY,
|
||||
JSON_TYPE_OBJECT,
|
||||
JSON_TYPE_NULL,
|
||||
JSON_TYPE_BUTT
|
||||
}JSON_TYPE;
|
||||
|
||||
|
||||
typedef struct _VTOY_JSON
|
||||
{
|
||||
struct _VTOY_JSON *pstPrev;
|
||||
struct _VTOY_JSON *pstNext;
|
||||
struct _VTOY_JSON *pstChild;
|
||||
|
||||
JSON_TYPE enDataType;
|
||||
union
|
||||
{
|
||||
char *pcStrVal;
|
||||
int iNumVal;
|
||||
grub_uint64_t lValue;
|
||||
}unData;
|
||||
|
||||
char *pcName;
|
||||
}VTOY_JSON;
|
||||
|
||||
typedef struct _JSON_PARSE
|
||||
{
|
||||
char *pcKey;
|
||||
void *pDataBuf;
|
||||
grub_uint32_t uiBufSize;
|
||||
}JSON_PARSE;
|
||||
|
||||
#define JSON_NEW_ITEM(pstJson, ret) \
|
||||
{ \
|
||||
(pstJson) = (VTOY_JSON *)grub_zalloc(sizeof(VTOY_JSON)); \
|
||||
if (NULL == (pstJson)) \
|
||||
{ \
|
||||
json_debug("Failed to alloc memory for json.\n"); \
|
||||
return (ret); \
|
||||
} \
|
||||
}
|
||||
|
||||
typedef int (*ventoy_plugin_entry_pf)(VTOY_JSON *json, const char *isodisk);
|
||||
|
||||
typedef struct plugin_entry
|
||||
{
|
||||
const char *key;
|
||||
ventoy_plugin_entry_pf entryfunc;
|
||||
}plugin_entry;
|
||||
|
||||
|
||||
void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param);
|
||||
grub_err_t ventoy_cmd_isolinux_initrd_collect(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_grub_initrd_collect(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_specify_initrd_file(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_dump_initrd_list(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_clear_initrd_list(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_uint32_t ventoy_get_iso_boot_catlog(grub_file_t file);
|
||||
int ventoy_has_efi_eltorito(grub_file_t file, grub_uint32_t sector);
|
||||
grub_err_t ventoy_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
int ventoy_cpio_newc_fill_head(void *buf, int filesize, void *filedata, const char *name);
|
||||
grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...);
|
||||
int ventoy_is_file_exist(const char *fmt, ...);
|
||||
int ventoy_fill_data(grub_uint32_t buflen, char *buffer);
|
||||
grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wimdows_locate_wim(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
|
||||
VTOY_JSON *vtoy_json_find_item
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
JSON_TYPE enDataType,
|
||||
const char *szKey
|
||||
);
|
||||
int vtoy_json_parse_value
|
||||
(
|
||||
char *pcNewStart,
|
||||
char *pcRawStart,
|
||||
VTOY_JSON *pstJson,
|
||||
const char *pcData,
|
||||
const char **ppcEnd
|
||||
);
|
||||
VTOY_JSON * vtoy_json_create(void);
|
||||
int vtoy_json_parse(VTOY_JSON *pstJson, const char *szJsonData);
|
||||
|
||||
int vtoy_json_scan_parse
|
||||
(
|
||||
const VTOY_JSON *pstJson,
|
||||
grub_uint32_t uiParseNum,
|
||||
JSON_PARSE *pstJsonParse
|
||||
);
|
||||
|
||||
int vtoy_json_scan_array
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
VTOY_JSON **ppstArrayItem
|
||||
);
|
||||
|
||||
int vtoy_json_scan_array_ex
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
VTOY_JSON **ppstArrayItem
|
||||
);
|
||||
int vtoy_json_scan_object
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
VTOY_JSON **ppstObjectItem
|
||||
);
|
||||
int vtoy_json_get_int
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
int *piValue
|
||||
);
|
||||
int vtoy_json_get_uint
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
grub_uint32_t *puiValue
|
||||
);
|
||||
int vtoy_json_get_uint64
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
grub_uint64_t *pui64Value
|
||||
);
|
||||
int vtoy_json_get_bool
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
grub_uint8_t *pbValue
|
||||
);
|
||||
int vtoy_json_get_string
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
grub_uint32_t uiBufLen,
|
||||
char *pcBuf
|
||||
);
|
||||
const char * vtoy_json_get_string_ex(VTOY_JSON *pstJson, const char *szKey);
|
||||
int vtoy_json_destroy(VTOY_JSON *pstJson);
|
||||
|
||||
|
||||
grub_uint32_t CalculateCrc32
|
||||
(
|
||||
const void *Buffer,
|
||||
grub_uint32_t Length,
|
||||
grub_uint32_t InitValue
|
||||
);
|
||||
|
||||
static inline int ventoy_isspace (int c)
|
||||
{
|
||||
return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
|
||||
}
|
||||
|
||||
static inline int ventoy_is_word_end(int c)
|
||||
{
|
||||
return (c == 0 || c == ',' || ventoy_isspace(c));
|
||||
}
|
||||
|
||||
#endif /* __VENTOY_DEF_H__ */
|
||||
|
||||
736
GRUB2/grub-2.04/grub-core/ventoy/ventoy_json.c
Normal file
736
GRUB2/grub-2.04/grub-core/ventoy/ventoy_json.c
Normal file
@@ -0,0 +1,736 @@
|
||||
/******************************************************************************
|
||||
* ventoy_json.c
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/ventoy.h>
|
||||
#include "ventoy_def.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static void json_debug(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, fmt);
|
||||
grub_vprintf (fmt, args);
|
||||
va_end (args);
|
||||
|
||||
grub_printf("\n");
|
||||
}
|
||||
|
||||
static void vtoy_json_free(VTOY_JSON *pstJsonHead)
|
||||
{
|
||||
VTOY_JSON *pstNext = NULL;
|
||||
|
||||
while (NULL != pstJsonHead)
|
||||
{
|
||||
pstNext = pstJsonHead->pstNext;
|
||||
if ((pstJsonHead->enDataType < JSON_TYPE_BUTT) && (NULL != pstJsonHead->pstChild))
|
||||
{
|
||||
vtoy_json_free(pstJsonHead->pstChild);
|
||||
}
|
||||
|
||||
grub_free(pstJsonHead);
|
||||
pstJsonHead = pstNext;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static char *vtoy_json_skip(const char *pcData)
|
||||
{
|
||||
while ((NULL != pcData) && ('\0' != *pcData) && (*pcData <= 32))
|
||||
{
|
||||
pcData++;
|
||||
}
|
||||
|
||||
return (char *)pcData;
|
||||
}
|
||||
|
||||
VTOY_JSON *vtoy_json_find_item
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
JSON_TYPE enDataType,
|
||||
const char *szKey
|
||||
)
|
||||
{
|
||||
while (NULL != pstJson)
|
||||
{
|
||||
if ((enDataType == pstJson->enDataType) &&
|
||||
(0 == grub_strcmp(szKey, pstJson->pcName)))
|
||||
{
|
||||
return pstJson;
|
||||
}
|
||||
pstJson = pstJson->pstNext;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int vtoy_json_parse_number
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *pcData,
|
||||
const char **ppcEnd
|
||||
)
|
||||
{
|
||||
unsigned long Value;
|
||||
|
||||
Value = grub_strtoul(pcData, (char **)ppcEnd, 10);
|
||||
if (*ppcEnd == pcData)
|
||||
{
|
||||
json_debug("Failed to parse json number %s.", pcData);
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
pstJson->enDataType = JSON_TYPE_NUMBER;
|
||||
pstJson->unData.lValue = Value;
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
static int vtoy_json_parse_string
|
||||
(
|
||||
char *pcNewStart,
|
||||
char *pcRawStart,
|
||||
VTOY_JSON *pstJson,
|
||||
const char *pcData,
|
||||
const char **ppcEnd
|
||||
)
|
||||
{
|
||||
grub_uint32_t uiLen = 0;
|
||||
const char *pcPos = NULL;
|
||||
const char *pcTmp = pcData + 1;
|
||||
|
||||
*ppcEnd = pcData;
|
||||
|
||||
if ('\"' != *pcData)
|
||||
{
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
pcPos = grub_strchr(pcTmp, '\"');
|
||||
if ((NULL == pcPos) || (pcPos < pcTmp))
|
||||
{
|
||||
json_debug("Invalid string %s.", pcData);
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
*ppcEnd = pcPos + 1;
|
||||
uiLen = (grub_uint32_t)(unsigned long)(pcPos - pcTmp);
|
||||
|
||||
pstJson->enDataType = JSON_TYPE_STRING;
|
||||
pstJson->unData.pcStrVal = pcNewStart + (pcTmp - pcRawStart);
|
||||
pstJson->unData.pcStrVal[uiLen] = '\0';
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
static int vtoy_json_parse_array
|
||||
(
|
||||
char *pcNewStart,
|
||||
char *pcRawStart,
|
||||
VTOY_JSON *pstJson,
|
||||
const char *pcData,
|
||||
const char **ppcEnd
|
||||
)
|
||||
{
|
||||
int Ret = JSON_SUCCESS;
|
||||
VTOY_JSON *pstJsonChild = NULL;
|
||||
VTOY_JSON *pstJsonItem = NULL;
|
||||
const char *pcTmp = pcData + 1;
|
||||
|
||||
*ppcEnd = pcData;
|
||||
pstJson->enDataType = JSON_TYPE_ARRAY;
|
||||
|
||||
if ('[' != *pcData)
|
||||
{
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
pcTmp = vtoy_json_skip(pcTmp);
|
||||
|
||||
if (']' == *pcTmp)
|
||||
{
|
||||
*ppcEnd = pcTmp + 1;
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
JSON_NEW_ITEM(pstJson->pstChild, JSON_FAILED);
|
||||
|
||||
Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJson->pstChild, pcTmp, ppcEnd);
|
||||
if (JSON_SUCCESS != Ret)
|
||||
{
|
||||
json_debug("Failed to parse array child.");
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
pstJsonChild = pstJson->pstChild;
|
||||
pcTmp = vtoy_json_skip(*ppcEnd);
|
||||
while ((NULL != pcTmp) && (',' == *pcTmp))
|
||||
{
|
||||
JSON_NEW_ITEM(pstJsonItem, JSON_FAILED);
|
||||
pstJsonChild->pstNext = pstJsonItem;
|
||||
pstJsonItem->pstPrev = pstJsonChild;
|
||||
pstJsonChild = pstJsonItem;
|
||||
|
||||
Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
|
||||
if (JSON_SUCCESS != Ret)
|
||||
{
|
||||
json_debug("Failed to parse array child.");
|
||||
return JSON_FAILED;
|
||||
}
|
||||
pcTmp = vtoy_json_skip(*ppcEnd);
|
||||
}
|
||||
|
||||
if ((NULL != pcTmp) && (']' == *pcTmp))
|
||||
{
|
||||
*ppcEnd = pcTmp + 1;
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppcEnd = pcTmp;
|
||||
return JSON_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static int vtoy_json_parse_object
|
||||
(
|
||||
char *pcNewStart,
|
||||
char *pcRawStart,
|
||||
VTOY_JSON *pstJson,
|
||||
const char *pcData,
|
||||
const char **ppcEnd
|
||||
)
|
||||
{
|
||||
int Ret = JSON_SUCCESS;
|
||||
VTOY_JSON *pstJsonChild = NULL;
|
||||
VTOY_JSON *pstJsonItem = NULL;
|
||||
const char *pcTmp = pcData + 1;
|
||||
|
||||
*ppcEnd = pcData;
|
||||
pstJson->enDataType = JSON_TYPE_OBJECT;
|
||||
|
||||
if ('{' != *pcData)
|
||||
{
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
pcTmp = vtoy_json_skip(pcTmp);
|
||||
if ('}' == *pcTmp)
|
||||
{
|
||||
*ppcEnd = pcTmp + 1;
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
JSON_NEW_ITEM(pstJson->pstChild, JSON_FAILED);
|
||||
|
||||
Ret = vtoy_json_parse_string(pcNewStart, pcRawStart, pstJson->pstChild, pcTmp, ppcEnd);
|
||||
if (JSON_SUCCESS != Ret)
|
||||
{
|
||||
json_debug("Failed to parse array child.");
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
pstJsonChild = pstJson->pstChild;
|
||||
pstJsonChild->pcName = pstJsonChild->unData.pcStrVal;
|
||||
pstJsonChild->unData.pcStrVal = NULL;
|
||||
|
||||
pcTmp = vtoy_json_skip(*ppcEnd);
|
||||
if ((NULL == pcTmp) || (':' != *pcTmp))
|
||||
{
|
||||
*ppcEnd = pcTmp;
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
|
||||
if (JSON_SUCCESS != Ret)
|
||||
{
|
||||
json_debug("Failed to parse array child.");
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
pcTmp = vtoy_json_skip(*ppcEnd);
|
||||
while ((NULL != pcTmp) && (',' == *pcTmp))
|
||||
{
|
||||
JSON_NEW_ITEM(pstJsonItem, JSON_FAILED);
|
||||
pstJsonChild->pstNext = pstJsonItem;
|
||||
pstJsonItem->pstPrev = pstJsonChild;
|
||||
pstJsonChild = pstJsonItem;
|
||||
|
||||
Ret = vtoy_json_parse_string(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
|
||||
if (JSON_SUCCESS != Ret)
|
||||
{
|
||||
json_debug("Failed to parse array child.");
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
pcTmp = vtoy_json_skip(*ppcEnd);
|
||||
pstJsonChild->pcName = pstJsonChild->unData.pcStrVal;
|
||||
pstJsonChild->unData.pcStrVal = NULL;
|
||||
if ((NULL == pcTmp) || (':' != *pcTmp))
|
||||
{
|
||||
*ppcEnd = pcTmp;
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
|
||||
if (JSON_SUCCESS != Ret)
|
||||
{
|
||||
json_debug("Failed to parse array child.");
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
pcTmp = vtoy_json_skip(*ppcEnd);
|
||||
}
|
||||
|
||||
if ((NULL != pcTmp) && ('}' == *pcTmp))
|
||||
{
|
||||
*ppcEnd = pcTmp + 1;
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppcEnd = pcTmp;
|
||||
return JSON_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int vtoy_json_parse_value
|
||||
(
|
||||
char *pcNewStart,
|
||||
char *pcRawStart,
|
||||
VTOY_JSON *pstJson,
|
||||
const char *pcData,
|
||||
const char **ppcEnd
|
||||
)
|
||||
{
|
||||
pcData = vtoy_json_skip(pcData);
|
||||
|
||||
switch (*pcData)
|
||||
{
|
||||
case 'n':
|
||||
{
|
||||
if (0 == grub_strncmp(pcData, "null", 4))
|
||||
{
|
||||
pstJson->enDataType = JSON_TYPE_NULL;
|
||||
*ppcEnd = pcData + 4;
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'f':
|
||||
{
|
||||
if (0 == grub_strncmp(pcData, "false", 5))
|
||||
{
|
||||
pstJson->enDataType = JSON_TYPE_BOOL;
|
||||
pstJson->unData.lValue = 0;
|
||||
*ppcEnd = pcData + 5;
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 't':
|
||||
{
|
||||
if (0 == grub_strncmp(pcData, "true", 4))
|
||||
{
|
||||
pstJson->enDataType = JSON_TYPE_BOOL;
|
||||
pstJson->unData.lValue = 1;
|
||||
*ppcEnd = pcData + 4;
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '\"':
|
||||
{
|
||||
return vtoy_json_parse_string(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd);
|
||||
}
|
||||
case '[':
|
||||
{
|
||||
return vtoy_json_parse_array(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd);
|
||||
}
|
||||
case '{':
|
||||
{
|
||||
return vtoy_json_parse_object(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd);
|
||||
}
|
||||
case '-':
|
||||
{
|
||||
return vtoy_json_parse_number(pstJson, pcData, ppcEnd);
|
||||
}
|
||||
default :
|
||||
{
|
||||
if (*pcData >= '0' && *pcData <= '9')
|
||||
{
|
||||
return vtoy_json_parse_number(pstJson, pcData, ppcEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ppcEnd = pcData;
|
||||
json_debug("Invalid json data %u.", (grub_uint8_t)(*pcData));
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
VTOY_JSON * vtoy_json_create(void)
|
||||
{
|
||||
VTOY_JSON *pstJson = NULL;
|
||||
|
||||
pstJson = (VTOY_JSON *)grub_zalloc(sizeof(VTOY_JSON));
|
||||
if (NULL == pstJson)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pstJson;
|
||||
}
|
||||
|
||||
int vtoy_json_parse(VTOY_JSON *pstJson, const char *szJsonData)
|
||||
{
|
||||
grub_uint32_t uiMemSize = 0;
|
||||
int Ret = JSON_SUCCESS;
|
||||
char *pcNewBuf = NULL;
|
||||
const char *pcEnd = NULL;
|
||||
|
||||
uiMemSize = grub_strlen(szJsonData) + 1;
|
||||
pcNewBuf = (char *)grub_malloc(uiMemSize);
|
||||
if (NULL == pcNewBuf)
|
||||
{
|
||||
json_debug("Failed to alloc new buf.");
|
||||
return JSON_FAILED;
|
||||
}
|
||||
grub_memcpy(pcNewBuf, szJsonData, uiMemSize);
|
||||
pcNewBuf[uiMemSize - 1] = 0;
|
||||
|
||||
Ret = vtoy_json_parse_value(pcNewBuf, (char *)szJsonData, pstJson, szJsonData, &pcEnd);
|
||||
if (JSON_SUCCESS != Ret)
|
||||
{
|
||||
json_debug("Failed to parse json data %s start=%p, end=%p:%s.",
|
||||
szJsonData, szJsonData, pcEnd, pcEnd);
|
||||
return JSON_FAILED;
|
||||
}
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
int vtoy_json_scan_parse
|
||||
(
|
||||
const VTOY_JSON *pstJson,
|
||||
grub_uint32_t uiParseNum,
|
||||
JSON_PARSE *pstJsonParse
|
||||
)
|
||||
{
|
||||
grub_uint32_t i = 0;
|
||||
const VTOY_JSON *pstJsonCur = NULL;
|
||||
JSON_PARSE *pstCurParse = NULL;
|
||||
|
||||
for (pstJsonCur = pstJson; NULL != pstJsonCur; pstJsonCur = pstJsonCur->pstNext)
|
||||
{
|
||||
if ((JSON_TYPE_OBJECT == pstJsonCur->enDataType) ||
|
||||
(JSON_TYPE_ARRAY == pstJsonCur->enDataType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0, pstCurParse = NULL; i < uiParseNum; i++)
|
||||
{
|
||||
if (0 == grub_strcmp(pstJsonParse[i].pcKey, pstJsonCur->pcName))
|
||||
{
|
||||
pstCurParse = pstJsonParse + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == pstCurParse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (pstJsonCur->enDataType)
|
||||
{
|
||||
case JSON_TYPE_NUMBER:
|
||||
{
|
||||
if (sizeof(grub_uint32_t) == pstCurParse->uiBufSize)
|
||||
{
|
||||
*(grub_uint32_t *)(pstCurParse->pDataBuf) = (grub_uint32_t)pstJsonCur->unData.lValue;
|
||||
}
|
||||
else if (sizeof(grub_uint16_t) == pstCurParse->uiBufSize)
|
||||
{
|
||||
*(grub_uint16_t *)(pstCurParse->pDataBuf) = (grub_uint16_t)pstJsonCur->unData.lValue;
|
||||
}
|
||||
else if (sizeof(grub_uint8_t) == pstCurParse->uiBufSize)
|
||||
{
|
||||
*(grub_uint8_t *)(pstCurParse->pDataBuf) = (grub_uint8_t)pstJsonCur->unData.lValue;
|
||||
}
|
||||
else if ((pstCurParse->uiBufSize > sizeof(grub_uint64_t)))
|
||||
{
|
||||
grub_snprintf((char *)pstCurParse->pDataBuf, pstCurParse->uiBufSize, "%llu",
|
||||
(unsigned long long)(pstJsonCur->unData.lValue));
|
||||
}
|
||||
else
|
||||
{
|
||||
json_debug("Invalid number data buf size %u.", pstCurParse->uiBufSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSON_TYPE_STRING:
|
||||
{
|
||||
grub_strncpy((char *)pstCurParse->pDataBuf, pstJsonCur->unData.pcStrVal, pstCurParse->uiBufSize);
|
||||
break;
|
||||
}
|
||||
case JSON_TYPE_BOOL:
|
||||
{
|
||||
*(grub_uint8_t *)(pstCurParse->pDataBuf) = (pstJsonCur->unData.lValue) > 0 ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
default :
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
int vtoy_json_scan_array
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
VTOY_JSON **ppstArrayItem
|
||||
)
|
||||
{
|
||||
VTOY_JSON *pstJsonItem = NULL;
|
||||
|
||||
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_ARRAY, szKey);
|
||||
if (NULL == pstJsonItem)
|
||||
{
|
||||
json_debug("Key %s is not found in json data.", szKey);
|
||||
return JSON_NOT_FOUND;
|
||||
}
|
||||
|
||||
*ppstArrayItem = pstJsonItem;
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
int vtoy_json_scan_array_ex
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
VTOY_JSON **ppstArrayItem
|
||||
)
|
||||
{
|
||||
VTOY_JSON *pstJsonItem = NULL;
|
||||
|
||||
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_ARRAY, szKey);
|
||||
if (NULL == pstJsonItem)
|
||||
{
|
||||
json_debug("Key %s is not found in json data.", szKey);
|
||||
return JSON_NOT_FOUND;
|
||||
}
|
||||
|
||||
*ppstArrayItem = pstJsonItem->pstChild;
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
int vtoy_json_scan_object
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
VTOY_JSON **ppstObjectItem
|
||||
)
|
||||
{
|
||||
VTOY_JSON *pstJsonItem = NULL;
|
||||
|
||||
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_OBJECT, szKey);
|
||||
if (NULL == pstJsonItem)
|
||||
{
|
||||
json_debug("Key %s is not found in json data.", szKey);
|
||||
return JSON_NOT_FOUND;
|
||||
}
|
||||
|
||||
*ppstObjectItem = pstJsonItem;
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
int vtoy_json_get_int
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
int *piValue
|
||||
)
|
||||
{
|
||||
VTOY_JSON *pstJsonItem = NULL;
|
||||
|
||||
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
|
||||
if (NULL == pstJsonItem)
|
||||
{
|
||||
json_debug("Key %s is not found in json data.", szKey);
|
||||
return JSON_NOT_FOUND;
|
||||
}
|
||||
|
||||
*piValue = (int)pstJsonItem->unData.lValue;
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
int vtoy_json_get_uint
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
grub_uint32_t *puiValue
|
||||
)
|
||||
{
|
||||
VTOY_JSON *pstJsonItem = NULL;
|
||||
|
||||
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
|
||||
if (NULL == pstJsonItem)
|
||||
{
|
||||
json_debug("Key %s is not found in json data.", szKey);
|
||||
return JSON_NOT_FOUND;
|
||||
}
|
||||
|
||||
*puiValue = (grub_uint32_t)pstJsonItem->unData.lValue;
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
int vtoy_json_get_uint64
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
grub_uint64_t *pui64Value
|
||||
)
|
||||
{
|
||||
VTOY_JSON *pstJsonItem = NULL;
|
||||
|
||||
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
|
||||
if (NULL == pstJsonItem)
|
||||
{
|
||||
json_debug("Key %s is not found in json data.", szKey);
|
||||
return JSON_NOT_FOUND;
|
||||
}
|
||||
|
||||
*pui64Value = (grub_uint64_t)pstJsonItem->unData.lValue;
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
int vtoy_json_get_bool
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
grub_uint8_t *pbValue
|
||||
)
|
||||
{
|
||||
VTOY_JSON *pstJsonItem = NULL;
|
||||
|
||||
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_BOOL, szKey);
|
||||
if (NULL == pstJsonItem)
|
||||
{
|
||||
json_debug("Key %s is not found in json data.", szKey);
|
||||
return JSON_NOT_FOUND;
|
||||
}
|
||||
|
||||
*pbValue = pstJsonItem->unData.lValue > 0 ? 1 : 0;
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
int vtoy_json_get_string
|
||||
(
|
||||
VTOY_JSON *pstJson,
|
||||
const char *szKey,
|
||||
grub_uint32_t uiBufLen,
|
||||
char *pcBuf
|
||||
)
|
||||
{
|
||||
VTOY_JSON *pstJsonItem = NULL;
|
||||
|
||||
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_STRING, szKey);
|
||||
if (NULL == pstJsonItem)
|
||||
{
|
||||
json_debug("Key %s is not found in json data.", szKey);
|
||||
return JSON_NOT_FOUND;
|
||||
}
|
||||
|
||||
grub_strncpy(pcBuf, pstJsonItem->unData.pcStrVal, uiBufLen);
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
const char * vtoy_json_get_string_ex(VTOY_JSON *pstJson, const char *szKey)
|
||||
{
|
||||
VTOY_JSON *pstJsonItem = NULL;
|
||||
|
||||
if ((NULL == pstJson) || (NULL == szKey))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_STRING, szKey);
|
||||
if (NULL == pstJsonItem)
|
||||
{
|
||||
json_debug("Key %s is not found in json data.", szKey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pstJsonItem->unData.pcStrVal;
|
||||
}
|
||||
|
||||
int vtoy_json_destroy(VTOY_JSON *pstJson)
|
||||
{
|
||||
if (NULL == pstJson)
|
||||
{
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
if (NULL != pstJson->pstChild)
|
||||
{
|
||||
vtoy_json_free(pstJson->pstChild);
|
||||
}
|
||||
|
||||
if (NULL != pstJson->pstNext)
|
||||
{
|
||||
vtoy_json_free(pstJson->pstNext);
|
||||
}
|
||||
|
||||
grub_free(pstJson);
|
||||
|
||||
return JSON_SUCCESS;
|
||||
}
|
||||
|
||||
1050
GRUB2/grub-2.04/grub-core/ventoy/ventoy_linux.c
Normal file
1050
GRUB2/grub-2.04/grub-core/ventoy/ventoy_linux.c
Normal file
File diff suppressed because it is too large
Load Diff
151
GRUB2/grub-2.04/grub-core/ventoy/ventoy_plugin.c
Normal file
151
GRUB2/grub-2.04/grub-core/ventoy/ventoy_plugin.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/******************************************************************************
|
||||
* ventoy_plugin.c
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/ventoy.h>
|
||||
#include "ventoy_def.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
|
||||
{
|
||||
const char *value;
|
||||
char filepath[256];
|
||||
|
||||
value = vtoy_json_get_string_ex(json->pstChild, "file");
|
||||
if (value)
|
||||
{
|
||||
grub_snprintf(filepath, sizeof(filepath), "%s/ventoy/%s", isodisk, value);
|
||||
if (ventoy_is_file_exist(filepath) == 0)
|
||||
{
|
||||
debug("Theme file %s does not exist\n", filepath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("vtoy_theme %s\n", filepath);
|
||||
grub_env_set("vtoy_theme", filepath);
|
||||
}
|
||||
|
||||
value = vtoy_json_get_string_ex(json->pstChild, "gfxmode");
|
||||
if (value)
|
||||
{
|
||||
debug("vtoy_gfxmode %s\n", value);
|
||||
grub_env_set("vtoy_gfxmode", value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static plugin_entry g_plugin_entries[] =
|
||||
{
|
||||
{ "theme", ventoy_plugin_theme_entry },
|
||||
};
|
||||
|
||||
static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
|
||||
{
|
||||
int i;
|
||||
VTOY_JSON *cur = json;
|
||||
|
||||
while (cur)
|
||||
{
|
||||
for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
|
||||
{
|
||||
if (grub_strcmp(g_plugin_entries[i].key, cur->pcName) == 0)
|
||||
{
|
||||
debug("Plugin entry for %s\n", g_plugin_entries[i].key);
|
||||
g_plugin_entries[i].entryfunc(cur, isodisk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cur = cur->pstNext;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int ret = 0;
|
||||
char *buf = NULL;
|
||||
grub_file_t file;
|
||||
VTOY_JSON *json = NULL;
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s/ventoy/ventoy.json", args[0]);
|
||||
if (!file)
|
||||
{
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
debug("json configuration file size %d\n", (int)file->size);
|
||||
|
||||
buf = grub_malloc(file->size + 1);
|
||||
if (!buf)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
buf[file->size] = 0;
|
||||
grub_file_read(file, buf, file->size);
|
||||
grub_file_close(file);
|
||||
|
||||
json = vtoy_json_create();
|
||||
if (!json)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ret = vtoy_json_parse(json, buf);
|
||||
if (ret)
|
||||
{
|
||||
debug("Failed to parse json string %d\n", ret);
|
||||
grub_free(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ventoy_parse_plugin_config(json->pstChild, args[0]);
|
||||
|
||||
vtoy_json_destroy(json);
|
||||
|
||||
grub_free(buf);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
931
GRUB2/grub-2.04/grub-core/ventoy/ventoy_windows.c
Normal file
931
GRUB2/grub-2.04/grub-core/ventoy/ventoy_windows.c
Normal file
@@ -0,0 +1,931 @@
|
||||
/******************************************************************************
|
||||
* ventoy_windows.c
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/ventoy.h>
|
||||
#include "ventoy_def.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
wim_hash g_old_hash;
|
||||
wim_tail g_wim_data;
|
||||
|
||||
static wim_lookup_entry *g_replace_look = NULL;
|
||||
|
||||
grub_ssize_t lzx_decompress ( const void *data, grub_size_t len, void *buf );
|
||||
|
||||
static int wim_name_cmp(const char *search, grub_uint16_t *name, grub_uint16_t namelen)
|
||||
{
|
||||
char c1 = vtoy_to_upper(*search);
|
||||
char c2 = vtoy_to_upper(*name);
|
||||
|
||||
while (namelen > 0 && (c1 == c2))
|
||||
{
|
||||
search++;
|
||||
name++;
|
||||
namelen--;
|
||||
|
||||
c1 = vtoy_to_upper(*search);
|
||||
c2 = vtoy_to_upper(*name);
|
||||
}
|
||||
|
||||
if (namelen == 0 && *search == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ventoy_is_pe64(grub_uint8_t *buffer)
|
||||
{
|
||||
grub_uint32_t pe_off;
|
||||
|
||||
if (buffer[0] != 'M' || buffer[1] != 'Z')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pe_off = *(grub_uint32_t *)(buffer + 60);
|
||||
|
||||
if (buffer[pe_off] != 'P' || buffer[pe_off + 1] != 'E')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*(grub_uint16_t *)(buffer + pe_off + 24) == 0x020b)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
check_free(g_wim_data.jump_bin_data, grub_free);
|
||||
check_free(g_wim_data.new_meta_data, grub_free);
|
||||
check_free(g_wim_data.new_lookup_data, grub_free);
|
||||
|
||||
grub_memset(&g_wim_data, 0, sizeof(g_wim_data));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_load_jump_exe(const char *path, grub_uint8_t **data, grub_uint32_t *size, wim_hash *hash)
|
||||
{
|
||||
grub_uint32_t i;
|
||||
grub_uint32_t align;
|
||||
grub_file_t file;
|
||||
|
||||
debug("windows load jump %s\n", path);
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", path);
|
||||
if (!file)
|
||||
{
|
||||
debug("Can't open file %s\n", path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
align = ventoy_align((int)file->size, 2048);
|
||||
|
||||
debug("file %s size:%d align:%u\n", path, (int)file->size, align);
|
||||
|
||||
*size = (grub_uint32_t)file->size;
|
||||
*data = (grub_uint8_t *)grub_malloc(align);
|
||||
if ((*data) == NULL)
|
||||
{
|
||||
debug("Failed to alloc memory size %u\n", align);
|
||||
goto end;
|
||||
}
|
||||
|
||||
grub_file_read(file, (*data), file->size);
|
||||
|
||||
if (hash)
|
||||
{
|
||||
grub_crypto_hash(GRUB_MD_SHA1, hash->sha1, (*data), file->size);
|
||||
|
||||
if (g_ventoy_debug)
|
||||
{
|
||||
debug("%s", "jump bin 64 hash: ");
|
||||
for (i = 0; i < sizeof(hash->sha1); i++)
|
||||
{
|
||||
ventoy_debug("%02x ", hash->sha1[i]);
|
||||
}
|
||||
ventoy_debug("\n");
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
grub_file_close(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_get_override_info(grub_file_t file)
|
||||
{
|
||||
grub_uint32_t start_block;
|
||||
grub_uint64_t file_offset;
|
||||
grub_uint64_t override_offset;
|
||||
grub_uint32_t override_len;
|
||||
grub_uint64_t fe_entry_size_offset;
|
||||
|
||||
if (grub_strcmp(file->fs->name, "iso9660") == 0)
|
||||
{
|
||||
g_wim_data.iso_type = 0;
|
||||
override_len = sizeof(ventoy_iso9660_override);
|
||||
override_offset = grub_iso9660_get_last_file_dirent_pos(file) + 2;
|
||||
|
||||
grub_file_read(file, &start_block, 1); // just read for hook trigger
|
||||
file_offset = grub_iso9660_get_last_read_pos(file);
|
||||
|
||||
debug("iso9660 wim size:%llu override_offset:%llu file_offset:%llu\n",
|
||||
(ulonglong)file->size, (ulonglong)override_offset, (ulonglong)file_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_wim_data.iso_type = 1;
|
||||
override_len = sizeof(ventoy_udf_override);
|
||||
override_offset = grub_udf_get_last_file_attr_offset(file, &start_block, &fe_entry_size_offset);
|
||||
|
||||
file_offset = grub_udf_get_file_offset(file);
|
||||
|
||||
debug("UDF wim size:%llu override_offset:%llu file_offset:%llu start_block=%u\n",
|
||||
(ulonglong)file->size, (ulonglong)override_offset, (ulonglong)file_offset, start_block);
|
||||
}
|
||||
|
||||
g_wim_data.file_offset = file_offset;
|
||||
g_wim_data.udf_start_block = start_block;
|
||||
g_wim_data.fe_entry_size_offset = fe_entry_size_offset;
|
||||
g_wim_data.override_offset = override_offset;
|
||||
g_wim_data.override_len = override_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_read_resource(grub_file_t fp, wim_resource_header *head, void **buffer)
|
||||
{
|
||||
int decompress_len = 0;
|
||||
int total_decompress = 0;
|
||||
grub_uint32_t i = 0;
|
||||
grub_uint32_t chunk_num = 0;
|
||||
grub_uint32_t chunk_size = 0;
|
||||
grub_uint32_t last_chunk_size = 0;
|
||||
grub_uint32_t last_decompress_size = 0;
|
||||
grub_uint32_t cur_offset = 0;
|
||||
grub_uint8_t *cur_dst = NULL;
|
||||
grub_uint8_t *buffer_compress = NULL;
|
||||
grub_uint8_t *buffer_decompress = NULL;
|
||||
grub_uint32_t *chunk_offset = NULL;
|
||||
|
||||
buffer_decompress = (grub_uint8_t *)grub_malloc(head->raw_size + head->size_in_wim);
|
||||
if (NULL == buffer_decompress)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_file_seek(fp, head->offset);
|
||||
|
||||
if (head->size_in_wim == head->raw_size)
|
||||
{
|
||||
grub_file_read(fp, buffer_decompress, head->size_in_wim);
|
||||
*buffer = buffer_decompress;
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer_compress = buffer_decompress + head->raw_size;
|
||||
grub_file_read(fp, buffer_compress, head->size_in_wim);
|
||||
|
||||
chunk_num = (head->raw_size + WIM_CHUNK_LEN - 1) / WIM_CHUNK_LEN;
|
||||
cur_offset = (chunk_num - 1) * 4;
|
||||
chunk_offset = (grub_uint32_t *)buffer_compress;
|
||||
|
||||
cur_dst = buffer_decompress;
|
||||
|
||||
for (i = 0; i < chunk_num - 1; i++)
|
||||
{
|
||||
chunk_size = (i == 0) ? chunk_offset[i] : chunk_offset[i] - chunk_offset[i - 1];
|
||||
|
||||
if (WIM_CHUNK_LEN == chunk_size)
|
||||
{
|
||||
grub_memcpy(cur_dst, buffer_compress + cur_offset, chunk_size);
|
||||
decompress_len = (int)chunk_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
decompress_len = (int)lzx_decompress(buffer_compress + cur_offset, chunk_size, cur_dst);
|
||||
}
|
||||
|
||||
//debug("chunk_size:%u decompresslen:%d\n", chunk_size, decompress_len);
|
||||
|
||||
total_decompress += decompress_len;
|
||||
cur_dst += decompress_len;
|
||||
cur_offset += chunk_size;
|
||||
}
|
||||
|
||||
/* last chunk */
|
||||
last_chunk_size = (grub_uint32_t)(head->size_in_wim - cur_offset);
|
||||
last_decompress_size = head->raw_size - total_decompress;
|
||||
|
||||
if (last_chunk_size < WIM_CHUNK_LEN && last_chunk_size == last_decompress_size)
|
||||
{
|
||||
debug("Last chunk %u uncompressed\n", last_chunk_size);
|
||||
grub_memcpy(cur_dst, buffer_compress + cur_offset, last_chunk_size);
|
||||
decompress_len = (int)last_chunk_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
decompress_len = (int)lzx_decompress(buffer_compress + cur_offset, head->size_in_wim - cur_offset, cur_dst);
|
||||
}
|
||||
|
||||
cur_dst += decompress_len;
|
||||
total_decompress += decompress_len;
|
||||
|
||||
if (cur_dst != buffer_decompress + head->raw_size)
|
||||
{
|
||||
debug("head->size_in_wim:%llu head->raw_size:%llu cur_dst:%p buffer_decompress:%p total_decompress:%d\n",
|
||||
(ulonglong)head->size_in_wim, (ulonglong)head->raw_size, cur_dst, buffer_decompress, total_decompress);
|
||||
grub_free(buffer_decompress);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*buffer = buffer_decompress;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static wim_directory_entry * search_wim_dirent(wim_directory_entry *dir, const char *search_name)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (dir->len && dir->name_len)
|
||||
{
|
||||
if (wim_name_cmp(search_name, (grub_uint16_t *)(dir + 1), dir->name_len / 2) == 0)
|
||||
{
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
dir = (wim_directory_entry *)((grub_uint8_t *)dir + dir->len);
|
||||
} while(dir->len);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static wim_directory_entry * search_full_wim_dirent
|
||||
(
|
||||
void *meta_data,
|
||||
wim_directory_entry *dir,
|
||||
const char **path
|
||||
)
|
||||
{
|
||||
wim_directory_entry *subdir = NULL;
|
||||
wim_directory_entry *search = dir;
|
||||
|
||||
while (*path)
|
||||
{
|
||||
subdir = (wim_directory_entry *)((char *)meta_data + search->subdir);
|
||||
search = search_wim_dirent(subdir, *path);
|
||||
if (!search)
|
||||
{
|
||||
debug("%s search failed\n", *path);
|
||||
}
|
||||
|
||||
path++;
|
||||
}
|
||||
return search;
|
||||
}
|
||||
|
||||
static wim_directory_entry * search_replace_wim_dirent(void *meta_data, wim_directory_entry *dir)
|
||||
{
|
||||
wim_directory_entry *wim_dirent = NULL;
|
||||
const char *winpeshl_path[] = { "Windows", "System32", "winpeshl.exe", NULL };
|
||||
const char *pecmd_path[] = { "Windows", "System32", "PECMD.exe", NULL };
|
||||
|
||||
wim_dirent = search_full_wim_dirent(meta_data, dir, winpeshl_path);
|
||||
if (wim_dirent)
|
||||
{
|
||||
return wim_dirent;
|
||||
}
|
||||
|
||||
wim_dirent = search_full_wim_dirent(meta_data, dir, pecmd_path);
|
||||
if (wim_dirent)
|
||||
{
|
||||
return wim_dirent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static wim_lookup_entry * ventoy_find_look_entry(wim_header *header, wim_lookup_entry *lookup, wim_hash *hash)
|
||||
{
|
||||
grub_uint32_t i = 0;
|
||||
|
||||
for (i = 0; i < (grub_uint32_t)header->lookup.raw_size / sizeof(wim_lookup_entry); i++)
|
||||
{
|
||||
if (grub_memcmp(&lookup[i].hash, hash, sizeof(wim_hash)) == 0)
|
||||
{
|
||||
return lookup + i;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static wim_lookup_entry * ventoy_find_meta_entry(wim_header *header, wim_lookup_entry *lookup)
|
||||
{
|
||||
grub_uint32_t i = 0;
|
||||
grub_uint32_t index = 0;;
|
||||
|
||||
if ((header == NULL) || (lookup == NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < (grub_uint32_t)header->lookup.raw_size / sizeof(wim_lookup_entry); i++)
|
||||
{
|
||||
if (lookup[i].resource.flags & RESHDR_FLAG_METADATA)
|
||||
{
|
||||
index++;
|
||||
if (index == header->boot_index)
|
||||
{
|
||||
return lookup + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ventoy_update_all_hash(void *meta_data, wim_directory_entry *dir)
|
||||
{
|
||||
if ((meta_data == NULL) || (dir == NULL))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dir->len == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (dir->subdir == 0 && grub_memcmp(dir->hash.sha1, g_old_hash.sha1, sizeof(wim_hash)) == 0)
|
||||
{
|
||||
debug("find target file, name_len:%u upadte hash\n", dir->name_len);
|
||||
grub_memcpy(dir->hash.sha1, &(g_wim_data.bin_hash), sizeof(wim_hash));
|
||||
}
|
||||
|
||||
if (dir->subdir)
|
||||
{
|
||||
ventoy_update_all_hash(meta_data, (wim_directory_entry *)((char *)meta_data + dir->subdir));
|
||||
}
|
||||
|
||||
dir = (wim_directory_entry *)((char *)dir + dir->len);
|
||||
} while (dir->len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_cat_exe_file_data(grub_uint32_t exe_len, grub_uint8_t *exe_data)
|
||||
{
|
||||
int pe64 = 0;
|
||||
char file[256];
|
||||
grub_uint32_t jump_len = 0;
|
||||
grub_uint32_t jump_align = 0;
|
||||
grub_uint8_t *jump_data = NULL;
|
||||
|
||||
pe64 = ventoy_is_pe64(exe_data);
|
||||
|
||||
grub_snprintf(file, sizeof(file), "%s/vtoyjump%d.exe", grub_env_get("vtoy_path"), pe64 ? 64 : 32);
|
||||
ventoy_load_jump_exe(file, &jump_data, &jump_len, NULL);
|
||||
jump_align = ventoy_align(jump_len, 16);
|
||||
|
||||
g_wim_data.jump_exe_len = jump_len;
|
||||
g_wim_data.bin_raw_len = jump_align + sizeof(ventoy_os_param) + exe_len;
|
||||
g_wim_data.bin_align_len = ventoy_align(g_wim_data.bin_raw_len, 2048);
|
||||
|
||||
g_wim_data.jump_bin_data = grub_malloc(g_wim_data.bin_align_len);
|
||||
if (g_wim_data.jump_bin_data)
|
||||
{
|
||||
grub_memcpy(g_wim_data.jump_bin_data, jump_data, jump_len);
|
||||
grub_memcpy(g_wim_data.jump_bin_data + jump_align + sizeof(ventoy_os_param), exe_data, exe_len);
|
||||
}
|
||||
|
||||
debug("jump_exe_len:%u bin_raw_len:%u bin_align_len:%u\n",
|
||||
g_wim_data.jump_exe_len, g_wim_data.bin_raw_len, g_wim_data.bin_align_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_update_before_chain(ventoy_os_param *param)
|
||||
{
|
||||
grub_uint32_t jump_align = 0;
|
||||
wim_lookup_entry *meta_look = NULL;
|
||||
wim_security_header *security = NULL;
|
||||
wim_directory_entry *rootdir = NULL;
|
||||
wim_header *head = &(g_wim_data.wim_header);
|
||||
wim_lookup_entry *lookup = (wim_lookup_entry *)g_wim_data.new_lookup_data;
|
||||
|
||||
jump_align = ventoy_align(g_wim_data.jump_exe_len, 16);
|
||||
if (g_wim_data.jump_bin_data)
|
||||
{
|
||||
grub_memcpy(g_wim_data.jump_bin_data + jump_align, param, sizeof(ventoy_os_param));
|
||||
}
|
||||
|
||||
grub_crypto_hash(GRUB_MD_SHA1, g_wim_data.bin_hash.sha1, g_wim_data.jump_bin_data, g_wim_data.bin_raw_len);
|
||||
|
||||
security = (wim_security_header *)g_wim_data.new_meta_data;
|
||||
rootdir = (wim_directory_entry *)(g_wim_data.new_meta_data + ((security->len + 7) & 0xFFFFFFF8U));
|
||||
|
||||
/* update all winpeshl.exe dirent entry's hash */
|
||||
ventoy_update_all_hash(g_wim_data.new_meta_data, rootdir);
|
||||
|
||||
/* update winpeshl.exe lookup entry data (hash/offset/length) */
|
||||
if (g_replace_look)
|
||||
{
|
||||
debug("update replace lookup entry_id:%ld\n", ((long)g_replace_look - (long)lookup) / sizeof(wim_lookup_entry));
|
||||
g_replace_look->resource.raw_size = g_wim_data.bin_raw_len;
|
||||
g_replace_look->resource.size_in_wim = g_wim_data.bin_raw_len;
|
||||
g_replace_look->resource.flags = 0;
|
||||
g_replace_look->resource.offset = g_wim_data.wim_align_size;
|
||||
|
||||
grub_memcpy(g_replace_look->hash.sha1, g_wim_data.bin_hash.sha1, sizeof(wim_hash));
|
||||
}
|
||||
|
||||
/* update metadata's hash */
|
||||
meta_look = ventoy_find_meta_entry(head, lookup);
|
||||
if (meta_look)
|
||||
{
|
||||
debug("find meta lookup entry_id:%ld\n", ((long)meta_look - (long)lookup) / sizeof(wim_lookup_entry));
|
||||
grub_memcpy(&meta_look->resource, &head->metadata, sizeof(wim_resource_header));
|
||||
grub_crypto_hash(GRUB_MD_SHA1, meta_look->hash.sha1, g_wim_data.new_meta_data, g_wim_data.new_meta_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_wimdows_locate_wim(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int rc;
|
||||
grub_file_t file;
|
||||
grub_uint32_t exe_len;
|
||||
grub_uint8_t *exe_data = NULL;
|
||||
grub_uint8_t *decompress_data = NULL;
|
||||
wim_lookup_entry *lookup = NULL;
|
||||
wim_security_header *security = NULL;
|
||||
wim_directory_entry *rootdir = NULL;
|
||||
wim_directory_entry *search = NULL;
|
||||
wim_header *head = &(g_wim_data.wim_header);
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
debug("windows locate wim start %s\n", args[0]);
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
|
||||
if (!file)
|
||||
{
|
||||
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
|
||||
}
|
||||
|
||||
ventoy_get_override_info(file);
|
||||
|
||||
grub_file_seek(file, 0);
|
||||
grub_file_read(file, head, sizeof(wim_header));
|
||||
|
||||
if (grub_memcmp(head->signature, WIM_HEAD_SIGNATURE, sizeof(head->signature)))
|
||||
{
|
||||
debug("Not a valid wim file %s\n", (char *)head->signature);
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (head->flags & FLAG_HEADER_COMPRESS_XPRESS)
|
||||
{
|
||||
debug("Xpress compress is not supported 0x%x\n", head->flags);
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = ventoy_read_resource(file, &head->metadata, (void **)&decompress_data);
|
||||
if (rc)
|
||||
{
|
||||
grub_printf("failed to read meta data %d\n", rc);
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
security = (wim_security_header *)decompress_data;
|
||||
rootdir = (wim_directory_entry *)(decompress_data + ((security->len + 7) & 0xFFFFFFF8U));
|
||||
|
||||
/* search winpeshl.exe dirent entry */
|
||||
search = search_replace_wim_dirent(decompress_data, rootdir);
|
||||
if (!search)
|
||||
{
|
||||
debug("Failed to find replace file %p\n", search);
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug("find replace file at %p\n", search);
|
||||
|
||||
grub_memcpy(&g_old_hash, search->hash.sha1, sizeof(wim_hash));
|
||||
|
||||
debug("read lookup offset:%llu size:%llu\n", (ulonglong)head->lookup.offset, (ulonglong)head->lookup.raw_size);
|
||||
lookup = grub_malloc(head->lookup.raw_size);
|
||||
grub_file_seek(file, head->lookup.offset);
|
||||
grub_file_read(file, lookup, head->lookup.raw_size);
|
||||
|
||||
/* find and extact winpeshl.exe */
|
||||
g_replace_look = ventoy_find_look_entry(head, lookup, &g_old_hash);
|
||||
if (g_replace_look)
|
||||
{
|
||||
exe_len = (grub_uint32_t)g_replace_look->resource.raw_size;
|
||||
debug("find replace lookup entry_id:%ld raw_size:%u\n",
|
||||
((long)g_replace_look - (long)lookup) / sizeof(wim_lookup_entry), exe_len);
|
||||
|
||||
if (0 == ventoy_read_resource(file, &(g_replace_look->resource), (void **)&(exe_data)))
|
||||
{
|
||||
ventoy_cat_exe_file_data(exe_len, exe_data);
|
||||
grub_free(exe_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("failed to read replace file meta data %u\n", exe_len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("failed to find lookup entry for replace file 0x%02x 0x%02x\n", g_old_hash.sha1[0], g_old_hash.sha1[1]);
|
||||
}
|
||||
|
||||
g_wim_data.wim_raw_size = (grub_uint32_t)file->size;
|
||||
g_wim_data.wim_align_size = ventoy_align(g_wim_data.wim_raw_size, 2048);
|
||||
|
||||
check_free(g_wim_data.new_meta_data, grub_free);
|
||||
g_wim_data.new_meta_data = decompress_data;
|
||||
g_wim_data.new_meta_len = head->metadata.raw_size;
|
||||
g_wim_data.new_meta_align_len = ventoy_align(g_wim_data.new_meta_len, 2048);
|
||||
|
||||
check_free(g_wim_data.new_lookup_data, grub_free);
|
||||
g_wim_data.new_lookup_data = (grub_uint8_t *)lookup;
|
||||
g_wim_data.new_lookup_len = (grub_uint32_t)head->lookup.raw_size;
|
||||
g_wim_data.new_lookup_align_len = ventoy_align(g_wim_data.new_lookup_len, 2048);
|
||||
|
||||
head->metadata.flags = RESHDR_FLAG_METADATA;
|
||||
head->metadata.offset = g_wim_data.wim_align_size + g_wim_data.bin_align_len;
|
||||
head->metadata.size_in_wim = g_wim_data.new_meta_len;
|
||||
head->metadata.raw_size = g_wim_data.new_meta_len;
|
||||
|
||||
head->lookup.flags = 0;
|
||||
head->lookup.offset = head->metadata.offset + g_wim_data.new_meta_align_len;
|
||||
head->lookup.size_in_wim = g_wim_data.new_lookup_len;
|
||||
head->lookup.raw_size = g_wim_data.new_lookup_len;
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
debug("%s", "windows locate wim finish\n");
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
static grub_uint32_t ventoy_get_override_chunk_num(void)
|
||||
{
|
||||
/* 1: block count in Partition Descriptor */
|
||||
/* 2: file_size in file_entry or extend_file_entry */
|
||||
/* 3: data_size and position in extend data short ad */
|
||||
/* 4: new wim file header */
|
||||
return 4;
|
||||
}
|
||||
|
||||
static void ventoy_windows_fill_override_data( grub_uint64_t isosize, void *override)
|
||||
{
|
||||
grub_uint32_t data32;
|
||||
grub_uint64_t data64;
|
||||
grub_uint64_t sector;
|
||||
grub_uint32_t new_wim_size;
|
||||
ventoy_override_chunk *cur;
|
||||
|
||||
sector = (isosize + 2047) / 2048;
|
||||
|
||||
cur = (ventoy_override_chunk *)override;
|
||||
|
||||
new_wim_size = g_wim_data.wim_align_size + g_wim_data.bin_align_len +
|
||||
g_wim_data.new_meta_align_len + g_wim_data.new_lookup_align_len;
|
||||
|
||||
if (g_wim_data.iso_type == 0)
|
||||
{
|
||||
ventoy_iso9660_override *dirent = (ventoy_iso9660_override *)g_wim_data.override_data;
|
||||
|
||||
dirent->first_sector = (grub_uint32_t)sector;
|
||||
dirent->size = new_wim_size;
|
||||
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
|
||||
dirent->size_be = grub_swap_bytes32(dirent->size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ventoy_udf_override *udf = (ventoy_udf_override *)g_wim_data.override_data;
|
||||
udf->length = new_wim_size;
|
||||
udf->position = (grub_uint32_t)sector - g_wim_data.udf_start_block;
|
||||
}
|
||||
|
||||
//override 1: sector number in pd data
|
||||
cur->img_offset = grub_udf_get_last_pd_size_offset();
|
||||
cur->override_size = 4;
|
||||
data32 = sector - g_wim_data.udf_start_block + (new_wim_size / 2048);
|
||||
grub_memcpy(cur->override_data, &(data32), 4);
|
||||
|
||||
//override 2: filesize in file_entry
|
||||
cur++;
|
||||
cur->img_offset = g_wim_data.fe_entry_size_offset;
|
||||
cur->override_size = 8;
|
||||
data64 = new_wim_size;
|
||||
grub_memcpy(cur->override_data, &(data64), 8);
|
||||
|
||||
/* override 3: position and length in extend data */
|
||||
cur++;
|
||||
cur->img_offset = g_wim_data.override_offset;
|
||||
cur->override_size = g_wim_data.override_len;
|
||||
grub_memcpy(cur->override_data, g_wim_data.override_data, cur->override_size);
|
||||
|
||||
/* override 4: new wim file header */
|
||||
cur++;
|
||||
cur->img_offset = g_wim_data.file_offset;
|
||||
cur->override_size = sizeof(wim_header);
|
||||
grub_memcpy(cur->override_data, &(g_wim_data.wim_header), cur->override_size);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ventoy_windows_fill_virt_data( grub_uint64_t isosize, ventoy_chain_head *chain)
|
||||
{
|
||||
grub_uint64_t sector;
|
||||
grub_uint32_t offset;
|
||||
grub_uint32_t wim_secs;
|
||||
grub_uint32_t mem_secs;
|
||||
char *override = NULL;
|
||||
ventoy_virt_chunk *cur = NULL;
|
||||
|
||||
sector = (isosize + 2047) / 2048;
|
||||
offset = sizeof(ventoy_virt_chunk);
|
||||
|
||||
wim_secs = g_wim_data.wim_align_size / 2048;
|
||||
mem_secs = (g_wim_data.bin_align_len + g_wim_data.new_meta_align_len + g_wim_data.new_lookup_align_len) / 2048;
|
||||
|
||||
override = (char *)chain + chain->virt_chunk_offset;
|
||||
cur = (ventoy_virt_chunk *)override;
|
||||
|
||||
cur->remap_sector_start = sector;
|
||||
cur->remap_sector_end = cur->remap_sector_start + wim_secs;
|
||||
cur->org_sector_start = (grub_uint32_t)(g_wim_data.file_offset / 2048);
|
||||
|
||||
cur->mem_sector_start = cur->remap_sector_end;
|
||||
cur->mem_sector_end = cur->mem_sector_start + mem_secs;
|
||||
cur->mem_sector_offset = offset;
|
||||
|
||||
grub_memcpy(override + offset, g_wim_data.jump_bin_data, g_wim_data.bin_raw_len);
|
||||
offset += g_wim_data.bin_align_len;
|
||||
|
||||
grub_memcpy(override + offset, g_wim_data.new_meta_data, g_wim_data.new_meta_len);
|
||||
offset += g_wim_data.new_meta_align_len;
|
||||
|
||||
grub_memcpy(override + offset, g_wim_data.new_lookup_data, g_wim_data.new_lookup_len);
|
||||
offset += g_wim_data.new_lookup_align_len;
|
||||
|
||||
chain->virt_img_size_in_bytes += g_wim_data.wim_align_size +
|
||||
g_wim_data.bin_align_len +
|
||||
g_wim_data.new_meta_align_len +
|
||||
g_wim_data.new_lookup_align_len;
|
||||
return;
|
||||
}
|
||||
|
||||
static int ventoy_windows_drive_map(ventoy_chain_head *chain)
|
||||
{
|
||||
grub_disk_t disk;
|
||||
|
||||
debug("drive map begin <%p> ...\n", chain);
|
||||
|
||||
if (chain->disk_drive == 0x80)
|
||||
{
|
||||
disk = grub_disk_open("hd1");
|
||||
if (disk)
|
||||
{
|
||||
grub_disk_close(disk);
|
||||
debug("drive map needed %p\n", disk);
|
||||
chain->drive_map = 0x81;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("failed to open disk %s\n", "hd1");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("no need to map 0x%x\n", chain->disk_drive);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int unknown_image = 0;
|
||||
int ventoy_compatible = 0;
|
||||
grub_uint32_t size = 0;
|
||||
grub_uint64_t isosize = 0;
|
||||
grub_uint32_t boot_catlog = 0;
|
||||
grub_uint32_t img_chunk_size = 0;
|
||||
grub_uint32_t override_size = 0;
|
||||
grub_uint32_t virt_chunk_size = 0;
|
||||
grub_file_t file;
|
||||
grub_disk_t disk;
|
||||
const char *pLastChain = NULL;
|
||||
const char *compatible;
|
||||
ventoy_chain_head *chain;
|
||||
char envbuf[64];
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
debug("chain data begin <%s> ...\n", args[0]);
|
||||
|
||||
compatible = grub_env_get("ventoy_compatible");
|
||||
if (compatible && compatible[0] == 'Y')
|
||||
{
|
||||
ventoy_compatible = 1;
|
||||
}
|
||||
|
||||
if (NULL == g_img_chunk_list.chunk)
|
||||
{
|
||||
grub_printf("ventoy not ready\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 == ventoy_compatible && g_wim_data.new_meta_data == NULL)
|
||||
{
|
||||
unknown_image = 1;
|
||||
debug("Warning: %s was not recognized by Ventoy\n", args[0]);
|
||||
}
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
|
||||
if (!file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
isosize = file->size;
|
||||
|
||||
boot_catlog = ventoy_get_iso_boot_catlog(file);
|
||||
if (boot_catlog)
|
||||
{
|
||||
if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file, boot_catlog)))
|
||||
{
|
||||
grub_env_set("LoadIsoEfiDriver", "on");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ventoy_is_efi_os())
|
||||
{
|
||||
grub_env_set("LoadIsoEfiDriver", "on");
|
||||
}
|
||||
else
|
||||
{
|
||||
return grub_error(GRUB_ERR_BAD_ARGUMENT, "File %s is not bootable", args[0]);
|
||||
}
|
||||
}
|
||||
|
||||
img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
|
||||
|
||||
if (ventoy_compatible || unknown_image)
|
||||
{
|
||||
size = sizeof(ventoy_chain_head) + img_chunk_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
override_size = ventoy_get_override_chunk_num() * sizeof(ventoy_override_chunk);
|
||||
virt_chunk_size = sizeof(ventoy_virt_chunk) + g_wim_data.bin_align_len +
|
||||
g_wim_data.new_meta_align_len + g_wim_data.new_lookup_align_len;;
|
||||
size = sizeof(ventoy_chain_head) + img_chunk_size + override_size + virt_chunk_size;
|
||||
}
|
||||
|
||||
pLastChain = grub_env_get("vtoy_chain_mem_addr");
|
||||
if (pLastChain)
|
||||
{
|
||||
chain = (ventoy_chain_head *)grub_strtoul(pLastChain, NULL, 16);
|
||||
if (chain)
|
||||
{
|
||||
debug("free last chain memory %p\n", chain);
|
||||
grub_free(chain);
|
||||
}
|
||||
}
|
||||
|
||||
chain = grub_malloc(size);
|
||||
if (!chain)
|
||||
{
|
||||
grub_printf("Failed to alloc chain memory size %u\n", size);
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (unsigned long)chain);
|
||||
grub_env_set("vtoy_chain_mem_addr", envbuf);
|
||||
grub_snprintf(envbuf, sizeof(envbuf), "%u", size);
|
||||
grub_env_set("vtoy_chain_mem_size", envbuf);
|
||||
|
||||
grub_memset(chain, 0, sizeof(ventoy_chain_head));
|
||||
|
||||
/* part 1: os parameter */
|
||||
ventoy_fill_os_param(file, &(chain->os_param));
|
||||
|
||||
if (g_wim_data.jump_bin_data && g_wim_data.new_meta_data)
|
||||
{
|
||||
ventoy_update_before_chain(&(chain->os_param));
|
||||
}
|
||||
|
||||
/* part 2: chain head */
|
||||
disk = file->device->disk;
|
||||
chain->disk_drive = disk->id;
|
||||
chain->disk_sector_size = (1 << disk->log_sector_size);
|
||||
chain->real_img_size_in_bytes = file->size;
|
||||
chain->virt_img_size_in_bytes = (file->size + 2047) / 2048 * 2048;
|
||||
chain->boot_catalog = boot_catlog;
|
||||
|
||||
if (!ventoy_is_efi_os())
|
||||
{
|
||||
grub_file_seek(file, boot_catlog * 2048);
|
||||
grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector));
|
||||
}
|
||||
|
||||
/* part 3: image chunk */
|
||||
chain->img_chunk_offset = sizeof(ventoy_chain_head);
|
||||
chain->img_chunk_num = g_img_chunk_list.cur_chunk;
|
||||
grub_memcpy((char *)chain + chain->img_chunk_offset, g_img_chunk_list.chunk, img_chunk_size);
|
||||
|
||||
if (ventoy_compatible || unknown_image)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (g_wim_data.new_meta_data == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* part 4: override chunk */
|
||||
chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size;
|
||||
chain->override_chunk_num = ventoy_get_override_chunk_num();
|
||||
ventoy_windows_fill_override_data(isosize, (char *)chain + chain->override_chunk_offset);
|
||||
|
||||
/* part 5: virt chunk */
|
||||
chain->virt_chunk_offset = chain->override_chunk_offset + override_size;
|
||||
chain->virt_chunk_num = 1;
|
||||
ventoy_windows_fill_virt_data(isosize, chain);
|
||||
|
||||
if (ventoy_is_efi_os() == 0)
|
||||
{
|
||||
ventoy_windows_drive_map(chain);
|
||||
}
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
|
||||
65
GRUB2/grub-2.04/grub-core/ventoy/wimboot.h
Normal file
65
GRUB2/grub-2.04/grub-core/ventoy/wimboot.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/******************************************************************************
|
||||
* wimboot.h
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef __WIMBOOT_H__
|
||||
#define __WIMBOOT_H__
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/ventoy.h>
|
||||
#include "ventoy_def.h"
|
||||
|
||||
|
||||
#define size_t grub_size_t
|
||||
#define ssize_t grub_ssize_t
|
||||
#define memset grub_memset
|
||||
#define memcpy grub_memcpy
|
||||
|
||||
#define uint8_t grub_uint8_t
|
||||
#define uint16_t grub_uint16_t
|
||||
#define uint32_t grub_uint32_t
|
||||
#define uint64_t grub_uint64_t
|
||||
#define int32_t grub_int32_t
|
||||
|
||||
|
||||
|
||||
#define assert(exp)
|
||||
|
||||
//#define DBG grub_printf
|
||||
#define DBG(fmt, ...)
|
||||
|
||||
const char * huffman_bin ( unsigned long value, unsigned int bits );
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user