blob: 3a2abc836734ca849888cb824bc1020fbdc959ff [file] [log] [blame]
Simon Glass3eb3cce2021-09-25 07:03:09 -06001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2021 Google LLC
4 */
5
6#define LOG_CATEGORY LOGC_BOOT
7
8#include <common.h>
9#include <abuf.h>
10#include <log.h>
11#include <malloc.h>
12#include <linux/zstd.h>
13
14int zstd_decompress(struct abuf *in, struct abuf *out)
15{
Brandon Maierdbe88da2023-01-12 10:27:45 -060016 zstd_dctx *ctx;
17 size_t wsize, len;
Simon Glass3eb3cce2021-09-25 07:03:09 -060018 void *workspace;
Simon Glass3eb3cce2021-09-25 07:03:09 -060019 int ret;
20
Brandon Maierdbe88da2023-01-12 10:27:45 -060021 wsize = zstd_dctx_workspace_bound();
Simon Glass3eb3cce2021-09-25 07:03:09 -060022 workspace = malloc(wsize);
23 if (!workspace) {
24 debug("%s: cannot allocate workspace of size %zu\n", __func__,
25 wsize);
26 return -ENOMEM;
27 }
28
Brandon Maierdbe88da2023-01-12 10:27:45 -060029 ctx = zstd_init_dctx(workspace, wsize);
30 if (!ctx) {
31 log_err("%s: zstd_init_dctx() failed\n", __func__);
Simon Glass3eb3cce2021-09-25 07:03:09 -060032 ret = -EPERM;
33 goto do_free;
34 }
35
Brandon Maierdbe88da2023-01-12 10:27:45 -060036 /*
37 * Find out how large the frame actually is, there may be junk at
38 * the end of the frame that zstd_decompress_dctx() can't handle.
39 */
40 len = zstd_find_frame_compressed_size(abuf_data(in), abuf_size(in));
41 if (zstd_is_error(len)) {
42 log_err("%s: failed to detect compressed size: %d\n", __func__,
43 zstd_get_error_code(len));
44 ret = -EINVAL;
45 goto do_free;
46 }
Simon Glass3eb3cce2021-09-25 07:03:09 -060047
Brandon Maierdbe88da2023-01-12 10:27:45 -060048 len = zstd_decompress_dctx(ctx, abuf_data(out), abuf_size(out),
49 abuf_data(in), len);
50 if (zstd_is_error(len)) {
51 log_err("%s: failed to decompress: %d\n", __func__,
52 zstd_get_error_code(len));
53 ret = -EINVAL;
54 goto do_free;
Simon Glass3eb3cce2021-09-25 07:03:09 -060055 }
56
Brandon Maierdbe88da2023-01-12 10:27:45 -060057 ret = len;
Simon Glass3eb3cce2021-09-25 07:03:09 -060058do_free:
59 free(workspace);
60 return ret;
61}