@@ -81,6 +81,10 @@ config HAVE_ZLIB
bool
option env="HAVE_ZLIB"
+config HAVE_XZ
+ bool
+ option env="HAVE_XZ"
+
config HAVE_ZSTD
bool
option env="HAVE_ZSTD"
@@ -529,6 +533,10 @@ config GUNZIP
depends on HAVE_ZLIB
default y
+config XZ
+ bool "XZ compression support"
+ depends on HAVE_XZ
+
config ZSTD
bool "Zstd compression support"
depends on HAVE_ZSTD
@@ -62,6 +62,10 @@ ifeq ($(HAVE_ZLIB),)
export HAVE_ZLIB = y
endif
+ifeq ($(HAVE_XZ),)
+export HAVE_XZ = y
+endif
+
ifeq ($(HAVE_ZSTD),)
export HAVE_ZSTD = y
endif
@@ -177,6 +177,10 @@ ifeq ($(CONFIG_GUNZIP),y)
LDLIBS += z
endif
+ifeq ($(CONFIG_XZ),y)
+LDLIBS += lzma
+endif
+
ifeq ($(CONFIG_ZSTD),y)
LDLIBS += zstd
endif
@@ -16,6 +16,9 @@
#ifdef CONFIG_GUNZIP
#include <zlib.h>
#endif
+#ifdef CONFIG_XZ
+#include <lzma.h>
+#endif
#ifdef CONFIG_ZSTD
#include <zstd.h>
#endif
@@ -332,7 +335,7 @@ static int decrypt_step(void *state, void *buffer, size_t size)
return 0;
}
-#if defined(CONFIG_GUNZIP) || defined(CONFIG_ZSTD)
+#if defined(CONFIG_GUNZIP) || defined(CONFIG_ZSTD) || defined(CONFIG_XZ)
typedef int (*DecompressStep)(void *state, void *buffer, size_t size);
struct DecompressState {
@@ -391,6 +394,53 @@ static int gunzip_step(void *state, void *buffer, size_t size)
#endif
+#ifdef CONFIG_XZ
+struct XzState {
+ lzma_stream strm;
+ bool initialized;
+};
+static int xz_step(void* state, void* buffer, size_t size)
+{
+ struct DecompressState *ds = (struct DecompressState *)state;
+ struct XzState *s = (struct XzState *)ds->impl_state;
+ lzma_ret ret;
+ int outlen = 0;
+ lzma_action action = LZMA_RUN;
+
+ s->strm.next_out = buffer;
+ s->strm.avail_out = size;
+
+ while (outlen == 0) {
+ if (s->strm.avail_in == 0) {
+ ret = ds->upstream_step(ds->upstream_state, ds->input, sizeof ds->input);
+ if (ret < 0) {
+ return ret;
+ } else if (ret == 0) {
+ ds->eof = true;
+ }
+ s->strm.avail_in = ret;
+ s->strm.next_in = ds->input;
+ }
+ if (ds->eof) {
+ action = LZMA_FINISH;
+ }
+
+ ret = lzma_code(&s->strm, action);
+ outlen = size - s->strm.avail_out;
+ if (ret == LZMA_STREAM_END) {
+ ds->eof = true;
+ break;
+ }
+ if (ret != LZMA_OK && ret != LZMA_BUF_ERROR) {
+ ERROR("xz failed (returned %d)", ret);
+ return -1;
+ }
+ }
+ return outlen;
+}
+
+#endif
+
#ifdef CONFIG_ZSTD
struct ZstdState {
@@ -496,7 +546,7 @@ int copyfile(struct swupdate_copy *args)
.outlen = 0, .eof = false
};
-#if defined(CONFIG_GUNZIP) || defined(CONFIG_ZSTD)
+#if defined(CONFIG_GUNZIP) || defined(CONFIG_ZSTD) || defined(CONFIG_XZ)
struct DecompressState decompress_state = {
.upstream_step = NULL, .upstream_state = NULL,
.impl_state = NULL
@@ -513,6 +563,12 @@ int copyfile(struct swupdate_copy *args)
.initialized = false,
};
#endif
+#ifdef CONFIG_XZ
+ struct XzState xz_state = {
+ .strm = LZMA_STREAM_INIT,
+ .initialized = false,
+ };
+#endif
#ifdef CONFIG_ZSTD
struct ZstdState zstd_state = {
.dctx = NULL,
@@ -585,6 +641,19 @@ int copyfile(struct swupdate_copy *args)
decompress_state.impl_state = &gunzip_state;
} else
#endif
+#ifdef CONFIG_XZ
+ if (args->compressed == COMPRESSED_XZ) {
+ if (lzma_stream_decoder(&xz_state.strm, UINT32_MAX,
+ LZMA_CONCATENATED) != LZMA_OK) {
+ ERROR("(lzma_stream_decoder failed");
+ ret = -EFAULT;
+ goto copyfile_exit;
+ }
+ xz_state.initialized = true;
+ decompress_step = &xz_step;
+ decompress_state.impl_state = &xz_state;
+ } else
+#endif
#ifdef CONFIG_ZSTD
if (args->compressed == COMPRESSED_ZSTD) {
if ((zstd_state.dctx = ZSTD_createDStream()) == NULL) {
@@ -630,7 +699,7 @@ int copyfile(struct swupdate_copy *args)
state = &decrypt_state;
}
-#if defined(CONFIG_GUNZIP) || defined(CONFIG_ZSTD)
+#if defined(CONFIG_GUNZIP) || defined(CONFIG_ZSTD) || defined(CONFIG_XZ)
if (args->compressed) {
decompress_state.upstream_step = step;
decompress_state.upstream_state = state;
@@ -699,6 +768,11 @@ copyfile_exit:
inflateEnd(&gunzip_state.strm);
}
#endif
+#ifdef CONFIG_XZ
+ if (xz_state.initialized) {
+ lzma_end(&xz_state.strm);
+ }
+#endif
#ifdef CONFIG_ZSTD
if (zstd_state.dctx != NULL) {
ZSTD_freeDStream(zstd_state.dctx);
@@ -283,6 +283,8 @@ static void lua_string_to_img(struct img_type *img, const char *key,
if (!strcmp(key, "compressed")) {
if (!strcmp(value, "zlib")) {
img->compressed = COMPRESSED_ZLIB;
+ } else if (!strcmp(value, "xz")) {
+ img->compressed = COMPRESSED_XZ;
} else if (!strcmp(value, "zstd")) {
img->compressed = COMPRESSED_ZSTD;
} else {
@@ -530,6 +532,9 @@ static void update_table(lua_State* L, struct img_type *img)
case COMPRESSED_ZLIB:
LUA_PUSH_IMG_STRING_VALUE(img, "compressed", "zlib");
break;
+ case COMPRESSED_XZ:
+ LUA_PUSH_IMG_STRING_VALUE(img, "compressed", "xz");
+ break;
case COMPRESSED_ZSTD:
LUA_PUSH_IMG_STRING_VALUE(img, "compressed", "zstd");
break;
@@ -1415,8 +1415,8 @@ There are 4 main sections inside sw-description:
| | | files | compressed and must be decompressed |
| | | | before being installed. the value |
| | | | denotes the compression type. |
- | | | | currently supported values are "zlib" |
- | | | | and "zstd". |
+ | | | | currently supported values are "xz", |
+ | | | | "zlib" and "zstd". |
+-------------+----------+------------+---------------------------------------+
| compressed | bool (dep| images | Deprecated. Use the string form. true |
| | recated) | files | is equal to 'compressed = "zlib"'. |
@@ -57,7 +57,7 @@ General Overview
SWUpdate can recreate UBI volumes, resizing them and
copying the new software.
-- support for compressed images, using the zlib and zstd library.
+- support for compressed images, using the xz, zlib and zstd library.
tarball (tgz file) are supported.
- support for partitioned USB-pen or unpartitioned (mainly
@@ -61,6 +61,7 @@ enum compression_type {
COMPRESSED_FALSE,
COMPRESSED_TRUE,
COMPRESSED_ZLIB,
+ COMPRESSED_XZ,
COMPRESSED_ZSTD,
};
@@ -87,6 +87,8 @@ static void sw_append_stream(struct img_type *img, const char *key,
if (value != NULL) {
if (!strcmp(value, "zlib")) {
img->compressed = COMPRESSED_ZLIB;
+ } else if (!strcmp(value, "xz")) {
+ img->compressed = COMPRESSED_XZ;
} else if (!strcmp(value, "zstd")) {
img->compressed = COMPRESSED_ZSTD;
} else {
@@ -441,6 +441,8 @@ static int parse_common_attributes(parsertype p, void *elem, struct img_type *im
if ((compressed = get_field_string(p, elem, "compressed")) != NULL) {
if (!strcmp(compressed, "zlib")) {
image->compressed = COMPRESSED_ZLIB;
+ } else if (!strcmp(compressed, "xz")) {
+ image->compressed = COMPRESSED_XZ;
} else if (!strcmp(compressed, "zstd")) {
image->compressed = COMPRESSED_ZSTD;
} else {
XZ compresses better than GZIP Signed-off-by: Joakim Tjernlund <joakim.tjernlund@infinera.com> --- Kconfig | 8 ++++ Makefile.deps | 4 ++ Makefile.flags | 4 ++ core/cpio_utils.c | 80 +++++++++++++++++++++++++++++++++-- corelib/lua_interface.c | 5 +++ doc/source/sw-description.rst | 4 +- doc/source/swupdate.rst | 2 +- include/util.h | 1 + parser/parse_external.c | 2 + parser/parser.c | 2 + 10 files changed, 106 insertions(+), 6 deletions(-)