Skip to content

Commit

Permalink
- Update XZ Embedded.
Browse files Browse the repository at this point in the history
  • Loading branch information
Extrems committed Jan 1, 2025
1 parent a080a2e commit 5ca7787
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 40 deletions.
22 changes: 9 additions & 13 deletions cube/packer/source/xz/xz.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
extern "C" {
#endif

/* In Linux, this is used to make extern functions static when needed. */
/* "#define XZ_EXTERN static" can be used to make extern functions static. */
#ifndef XZ_EXTERN
# define XZ_EXTERN extern
#endif
Expand Down Expand Up @@ -290,10 +290,6 @@ XZ_EXTERN void xz_dec_end(struct xz_dec *s);
* 3/0/2, the first byte is 0xA2. This way the first byte can never be 0x00.
* Just like with LZMA2, lc + lp <= 4 must be true. The LZMA end-of-stream
* marker must not be used. The unused values are reserved for future use.
*
* These functions aren't used or available in preboot code and thus aren't
* marked with XZ_EXTERN. This avoids warnings about static functions that
* are never defined.
*/

/*
Expand All @@ -318,8 +314,8 @@ struct xz_dec_microlzma;
* struct xz_dec_microlzma. If memory allocation fails or
* dict_size is invalid, NULL is returned.
*/
extern struct xz_dec_microlzma *xz_dec_microlzma_alloc(enum xz_mode mode,
uint32_t dict_size);
XZ_EXTERN struct xz_dec_microlzma *xz_dec_microlzma_alloc(enum xz_mode mode,
uint32_t dict_size);

/**
* xz_dec_microlzma_reset() - Reset the MicroLZMA decoder state
Expand All @@ -335,9 +331,9 @@ extern struct xz_dec_microlzma *xz_dec_microlzma_alloc(enum xz_mode mode,
* requiring stdbool.h. This should normally be set to true.
* When this is set to false, error detection is weaker.
*/
extern void xz_dec_microlzma_reset(struct xz_dec_microlzma *s,
uint32_t comp_size, uint32_t uncomp_size,
int uncomp_size_is_exact);
XZ_EXTERN void xz_dec_microlzma_reset(struct xz_dec_microlzma *s,
uint32_t comp_size, uint32_t uncomp_size,
int uncomp_size_is_exact);

/**
* xz_dec_microlzma_run() - Run the MicroLZMA decoder
Expand Down Expand Up @@ -375,15 +371,15 @@ extern void xz_dec_microlzma_reset(struct xz_dec_microlzma *s,
* may be changed normally like with XZ_PREALLOC. This way input data can be
* provided from non-contiguous memory.
*/
extern enum xz_ret xz_dec_microlzma_run(struct xz_dec_microlzma *s,
struct xz_buf *b);
XZ_EXTERN enum xz_ret xz_dec_microlzma_run(struct xz_dec_microlzma *s,
struct xz_buf *b);

/**
* xz_dec_microlzma_end() - Free the memory allocated for the decoder state
* @s: Decoder state allocated using xz_dec_microlzma_alloc().
* If s is NULL, this function does nothing.
*/
extern void xz_dec_microlzma_end(struct xz_dec_microlzma *s);
XZ_EXTERN void xz_dec_microlzma_end(struct xz_dec_microlzma *s);

/*
* Standalone build (userspace build or in-kernel build for boot time use)
Expand Down
26 changes: 15 additions & 11 deletions cube/packer/source/xz/xz_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@
/* Uncomment to enable CRC64 support. */
/* #define XZ_USE_CRC64 */

#define XZ_DEC_SINGLE
/* #define XZ_DEC_PREALLOC */
/* #define XZ_DEC_DYNALLOC */

/* Uncomment as needed to enable BCJ filter decoders. */
/* #define XZ_DEC_X86 */
/* #define XZ_DEC_ARM */
Expand All @@ -29,6 +25,10 @@
/* #define XZ_DEC_IA64 */
/* #define XZ_DEC_SPARC */

#define XZ_DEC_SINGLE
/* #define XZ_DEC_PREALLOC */
/* #define XZ_DEC_DYNALLOC */

/*
* Visual Studio 2013 update 2 supports only __inline, not inline.
* MSVC v19.0 / VS 2015 and newer support both.
Expand Down Expand Up @@ -58,9 +58,10 @@ void memzero(void *buf, size_t size);
#define min_t(type, x, y) min(x, y)

#ifndef fallthrough
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311
# define fallthrough [[fallthrough]]
# elif defined(__GNUC__) && __GNUC__ >= 7
# elif (defined(__GNUC__) && __GNUC__ >= 7) \
|| (defined(__clang_major__) && __clang_major__ >= 10)
# define fallthrough __attribute__((__fallthrough__))
# else
# define fallthrough do {} while (0)
Expand Down Expand Up @@ -100,7 +101,7 @@ static inline uint32_t get_unaligned_le32(const uint8_t *buf)
#ifndef get_unaligned_be32
static inline uint32_t get_unaligned_be32(const uint8_t *buf)
{
return (uint32_t)(buf[0] << 24)
return (uint32_t)((uint32_t)buf[0] << 24)
| ((uint32_t)buf[1] << 16)
| ((uint32_t)buf[2] << 8)
| (uint32_t)buf[3];
Expand Down Expand Up @@ -128,12 +129,15 @@ static inline void put_unaligned_be32(uint32_t val, uint8_t *buf)
#endif

/*
* Use get_unaligned_le32() also for aligned access for simplicity. On
* little endian systems, #define get_le32(ptr) (*(const uint32_t *)(ptr))
* could save a few bytes in code size.
* To keep things simpler, use the generic unaligned methods also for
* aligned access. The only place where performance could matter is
* SHA-256 but files using SHA-256 aren't common.
*/
#ifndef get_le32
# define get_le32(ptr) __builtin_bswap32(*(const uint32_t *)(ptr))
# define get_le32 get_unaligned_le32
#endif
#ifndef get_be32
# define get_be32 get_unaligned_be32
#endif

#endif
18 changes: 10 additions & 8 deletions cube/packer/source/xz/xz_dec_lzma2.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ struct lzma_dec {
uint16_t dist_slot[DIST_STATES][DIST_SLOTS];

/*
* Probility trees for additional bits for match distance
* Probability trees for additional bits for match distance
* when the distance is in the range [4, 127].
*/
uint16_t dist_special[FULL_DISTANCES - DIST_MODEL_END];
Expand Down Expand Up @@ -1211,8 +1211,8 @@ struct xz_dec_microlzma {
struct xz_dec_lzma2 s;
};

enum xz_ret xz_dec_microlzma_run(struct xz_dec_microlzma *s_ptr,
struct xz_buf *b)
XZ_EXTERN enum xz_ret xz_dec_microlzma_run(struct xz_dec_microlzma *s_ptr,
struct xz_buf *b)
{
struct xz_dec_lzma2 *s = &s_ptr->s;

Expand Down Expand Up @@ -1289,8 +1289,8 @@ enum xz_ret xz_dec_microlzma_run(struct xz_dec_microlzma *s_ptr,
}
}

struct xz_dec_microlzma *xz_dec_microlzma_alloc(enum xz_mode mode,
uint32_t dict_size)
XZ_EXTERN struct xz_dec_microlzma *xz_dec_microlzma_alloc(enum xz_mode mode,
uint32_t dict_size)
{
struct xz_dec_microlzma *s;

Expand Down Expand Up @@ -1318,8 +1318,10 @@ struct xz_dec_microlzma *xz_dec_microlzma_alloc(enum xz_mode mode,
return s;
}

void xz_dec_microlzma_reset(struct xz_dec_microlzma *s, uint32_t comp_size,
uint32_t uncomp_size, int uncomp_size_is_exact)
XZ_EXTERN void xz_dec_microlzma_reset(struct xz_dec_microlzma *s,
uint32_t comp_size,
uint32_t uncomp_size,
int uncomp_size_is_exact)
{
/*
* comp_size is validated in xz_dec_microlzma_run().
Expand All @@ -1333,7 +1335,7 @@ void xz_dec_microlzma_reset(struct xz_dec_microlzma *s, uint32_t comp_size,
s->s.temp.size = 0;
}

void xz_dec_microlzma_end(struct xz_dec_microlzma *s)
XZ_EXTERN void xz_dec_microlzma_end(struct xz_dec_microlzma *s)
{
if (DEC_IS_MULTI(s->s.dict.mode))
vfree(s->s.dict.buf);
Expand Down
58 changes: 51 additions & 7 deletions cube/packer/source/xz/xz_dec_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
# define IS_CRC64(check_type) false
#endif

#ifdef XZ_USE_SHA256
# define IS_SHA256(check_type) ((check_type) == XZ_CHECK_SHA256)
#else
# define IS_SHA256(check_type) false
#endif

/* Hash used to validate the Index field */
struct xz_dec_hash {
vli_type unpadded;
Expand Down Expand Up @@ -145,9 +151,23 @@ struct xz_dec {
struct xz_dec_bcj *bcj;
bool bcj_active;
#endif

#ifdef XZ_USE_SHA256
/*
* SHA-256 value in Block
*
* struct xz_sha256 is over a hundred bytes and it's only accessed
* from a few places. By putting the SHA-256 state near the end
* of struct xz_dec (somewhere after the "index" member) reduces
* code size at least on x86 and RISC-V. It's because the first bytes
* of the struct can be accessed with smaller instructions; the
* members that are accessed from many places should be at the top.
*/
struct xz_sha256 sha256;
#endif
};

#ifdef XZ_DEC_ANY_CHECK
#if defined(XZ_DEC_ANY_CHECK) || defined(XZ_USE_SHA256)
/* Sizes of the Check field with different Check IDs */
static const uint8_t check_sizes[16] = {
0,
Expand All @@ -161,9 +181,9 @@ static const uint8_t check_sizes[16] = {

/*
* Fill s->temp by copying data starting from b->in[b->in_pos]. Caller
* must have set s->temp.pos to indicate how much data we are supposed
* to copy into s->temp.buf. Return true once s->temp.pos has reached
* s->temp.size.
* must have set s->temp.pos and s->temp.size to indicate how much data
* we are supposed to copy into s->temp.buf. Return true once s->temp.pos
* has reached s->temp.size.
*/
static bool fill_temp(struct xz_dec *s, struct xz_buf *b)
{
Expand Down Expand Up @@ -260,6 +280,11 @@ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b)
s->crc = xz_crc64(b->out + s->out_start,
b->out_pos - s->out_start, s->crc);
#endif
#ifdef XZ_USE_SHA256
else if (s->check_type == XZ_CHECK_SHA256)
xz_sha256_update(b->out + s->out_start,
b->out_pos - s->out_start, &s->sha256);
#endif

if (ret == XZ_STREAM_END) {
if (s->block_header.compressed != VLI_UNKNOWN
Expand All @@ -275,7 +300,7 @@ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b)
s->block.hash.unpadded += s->block_header.size
+ s->block.compressed;

#ifdef XZ_DEC_ANY_CHECK
#if defined(XZ_DEC_ANY_CHECK) || defined(XZ_USE_SHA256)
s->block.hash.unpadded += check_sizes[s->check_type];
#else
if (s->check_type == XZ_CHECK_CRC32)
Expand Down Expand Up @@ -428,13 +453,14 @@ static enum xz_ret dec_stream_header(struct xz_dec *s)

s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1];

if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type)
&& !IS_SHA256(s->check_type)) {
#ifdef XZ_DEC_ANY_CHECK
if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type))
return XZ_UNSUPPORTED_CHECK;
#else
if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type))
return XZ_OPTIONS_ERROR;
#endif
}

return XZ_OK;
}
Expand Down Expand Up @@ -639,6 +665,11 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
if (ret != XZ_OK)
return ret;

#ifdef XZ_USE_SHA256
if (s->check_type == XZ_CHECK_SHA256)
xz_sha256_reset(&s->sha256);
#endif

s->sequence = SEQ_BLOCK_UNCOMPRESS;

fallthrough;
Expand Down Expand Up @@ -685,6 +716,19 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
if (ret != XZ_STREAM_END)
return ret;
}
#ifdef XZ_USE_SHA256
else if (s->check_type == XZ_CHECK_SHA256) {
s->temp.size = 32;
if (!fill_temp(s, b))
return XZ_OK;

if (!xz_sha256_validate(s->temp.buf,
&s->sha256))
return XZ_DATA_ERROR;

s->pos = 0;
}
#endif
#ifdef XZ_DEC_ANY_CHECK
else if (!check_skip(s, b)) {
return XZ_OK;
Expand Down
26 changes: 25 additions & 1 deletion cube/packer/source/xz/xz_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#ifdef __KERNEL__
# include <linux/xz.h>
# include <linux/kernel.h>
# include <asm/unaligned.h>
# include <linux/unaligned.h>
/* XZ_PREBOOT may be defined only via decompress_unxz.c. */
# ifndef XZ_PREBOOT
# include <linux/slab.h>
Expand Down Expand Up @@ -111,6 +111,30 @@
# endif
#endif

struct xz_sha256 {
/* Buffered input data */
uint8_t data[64];

/* Internal state and the final hash value */
uint32_t state[8];

/* Size of the input data */
uint64_t size;
};

/* Reset the SHA-256 state to prepare for a new calculation. */
XZ_EXTERN void xz_sha256_reset(struct xz_sha256 *s);

/* Update the SHA-256 state with new data. */
XZ_EXTERN void xz_sha256_update(const uint8_t *buf, size_t size,
struct xz_sha256 *s);

/*
* Finish the SHA-256 calculation. Compare the result with the first 32 bytes
* from buf. Return true if the values are equal and false if they aren't.
*/
XZ_EXTERN bool xz_sha256_validate(const uint8_t *buf, struct xz_sha256 *s);

/*
* Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used
* before calling xz_dec_lzma2_run().
Expand Down
Loading

0 comments on commit 5ca7787

Please sign in to comment.