summaryrefslogtreecommitdiff
path: root/lib/zstd/zstd.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/zstd/zstd.c')
-rw-r--r--lib/zstd/zstd.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/lib/zstd/zstd.c b/lib/zstd/zstd.c
new file mode 100644
index 00000000000..14bde369068
--- /dev/null
+++ b/lib/zstd/zstd.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ */
+
+#define LOG_CATEGORY LOGC_BOOT
+
+#include <abuf.h>
+#include <log.h>
+#include <malloc.h>
+#include <linux/errno.h>
+#include <linux/zstd.h>
+
+int zstd_decompress(struct abuf *in, struct abuf *out)
+{
+ zstd_dctx *ctx;
+ size_t wsize, len;
+ void *workspace;
+ int ret;
+
+ wsize = zstd_dctx_workspace_bound();
+ workspace = malloc(wsize);
+ if (!workspace) {
+ debug("%s: cannot allocate workspace of size %zu\n", __func__,
+ wsize);
+ return -ENOMEM;
+ }
+
+ ctx = zstd_init_dctx(workspace, wsize);
+ if (!ctx) {
+ log_err("%s: zstd_init_dctx() failed\n", __func__);
+ ret = -EPERM;
+ goto do_free;
+ }
+
+ /*
+ * Find out how large the frame actually is, there may be junk at
+ * the end of the frame that zstd_decompress_dctx() can't handle.
+ */
+ len = zstd_find_frame_compressed_size(abuf_data(in), abuf_size(in));
+ if (zstd_is_error(len)) {
+ log_err("%s: failed to detect compressed size: %d\n", __func__,
+ zstd_get_error_code(len));
+ ret = -EINVAL;
+ goto do_free;
+ }
+
+ len = zstd_decompress_dctx(ctx, abuf_data(out), abuf_size(out),
+ abuf_data(in), len);
+ if (zstd_is_error(len)) {
+ log_err("%s: failed to decompress: %d\n", __func__,
+ zstd_get_error_code(len));
+ ret = -EINVAL;
+ goto do_free;
+ }
+
+ ret = len;
+do_free:
+ free(workspace);
+ return ret;
+}