1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2021 Google LLC 4 */ 5 6#define LOG_CATEGORY LOGC_BOOT 7 8#include <abuf.h> 9#include <log.h> 10#include <malloc.h> 11#include <linux/errno.h> 12#include <linux/zstd.h> 13 14int zstd_decompress(struct abuf *in, struct abuf *out) 15{ 16 zstd_dctx *ctx; 17 size_t wsize, len; 18 void *workspace; 19 int ret; 20 21 wsize = zstd_dctx_workspace_bound(); 22 workspace = malloc(wsize); 23 if (!workspace) { 24 debug("%s: cannot allocate workspace of size %zu\n", __func__, 25 wsize); 26 return -ENOMEM; 27 } 28 29 ctx = zstd_init_dctx(workspace, wsize); 30 if (!ctx) { 31 log_err("%s: zstd_init_dctx() failed\n", __func__); 32 ret = -EPERM; 33 goto do_free; 34 } 35 36 /* 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 } 47 48 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; 55 } 56 57 ret = len; 58do_free: 59 free(workspace); 60 return ret; 61} 62