blob: bf9cd19cfa34265f889c091de074cd17a7ea6926 [file] [log] [blame]
Simon Glass94d0a2e2021-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{
16 ZSTD_DStream *dstream;
17 ZSTD_inBuffer in_buf;
18 ZSTD_outBuffer out_buf;
19 void *workspace;
20 size_t wsize;
21 int ret;
22
23 wsize = ZSTD_DStreamWorkspaceBound(abuf_size(in));
24 workspace = malloc(wsize);
25 if (!workspace) {
26 debug("%s: cannot allocate workspace of size %zu\n", __func__,
27 wsize);
28 return -ENOMEM;
29 }
30
31 dstream = ZSTD_initDStream(abuf_size(in), workspace, wsize);
32 if (!dstream) {
33 log_err("%s: ZSTD_initDStream failed\n", __func__);
34 ret = -EPERM;
35 goto do_free;
36 }
37
38 in_buf.src = abuf_data(in);
39 in_buf.pos = 0;
40 in_buf.size = abuf_size(in);
41
42 out_buf.dst = abuf_data(out);
43 out_buf.pos = 0;
44 out_buf.size = abuf_size(out);
45
46 while (1) {
47 size_t res;
48
49 res = ZSTD_decompressStream(dstream, &out_buf, &in_buf);
50 if (ZSTD_isError(res)) {
51 ret = ZSTD_getErrorCode(res);
52 log_err("ZSTD_decompressStream error %d\n", ret);
53 goto do_free;
54 }
55
56 if (in_buf.pos >= abuf_size(in) || !res)
57 break;
58 }
59
60 ret = out_buf.pos;
61do_free:
62 free(workspace);
63 return ret;
64}