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 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} 65