Merge branch 'master' of git://git.denx.de/u-boot
[platform/kernel/u-boot.git] / lib / zstd / zstd.c
1 // 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
14 int 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;
61 do_free:
62         free(workspace);
63         return ret;
64 }