blob: 9457ee5f0f9894ea135e4a56c6de78417765199e [file] [log] [blame]
Joao Marcos Costac5100612020-07-30 15:33:47 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2020 Bootlin
4 *
5 * Author: Joao Marcos Costa <joaomarcos.costa@bootlin.com>
6 */
7
8#include <errno.h>
9#include <stdint.h>
10#include <stdio.h>
11#include <stdlib.h>
Joao Marcos Costa3634b352020-07-30 15:33:50 +020012#if IS_ENABLED(CONFIG_ZLIB)
13#include <u-boot/zlib.h>
14#endif
Joao Marcos Costac5100612020-07-30 15:33:47 +020015
Joao Marcos Costa9c948f52020-08-18 17:17:23 +020016#if IS_ENABLED(CONFIG_ZSTD)
17#include <linux/zstd.h>
18#endif
19
Joao Marcos Costac5100612020-07-30 15:33:47 +020020#include "sqfs_decompressor.h"
Joao Marcos Costac5100612020-07-30 15:33:47 +020021#include "sqfs_utils.h"
22
Joao Marcos Costa10f7cf52020-08-18 17:17:21 +020023int sqfs_decompressor_init(struct squashfs_ctxt *ctxt)
24{
25 u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression);
26
27 switch (comp_type) {
28#if IS_ENABLED(CONFIG_ZLIB)
29 case SQFS_COMP_ZLIB:
30 break;
31#endif
Joao Marcos Costa9c948f52020-08-18 17:17:23 +020032#if IS_ENABLED(CONFIG_ZSTD)
33 case SQFS_COMP_ZSTD:
34 ctxt->zstd_workspace = malloc(ZSTD_DCtxWorkspaceBound());
35 if (!ctxt->zstd_workspace)
36 return -ENOMEM;
37 break;
38#endif
Joao Marcos Costa10f7cf52020-08-18 17:17:21 +020039 default:
40 printf("Error: unknown compression type.\n");
41 return -EINVAL;
42 }
43
44 return 0;
45}
46
47void sqfs_decompressor_cleanup(struct squashfs_ctxt *ctxt)
48{
49 u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression);
50
51 switch (comp_type) {
52#if IS_ENABLED(CONFIG_ZLIB)
53 case SQFS_COMP_ZLIB:
54 break;
55#endif
Joao Marcos Costa9c948f52020-08-18 17:17:23 +020056#if IS_ENABLED(CONFIG_ZSTD)
57 case SQFS_COMP_ZSTD:
58 free(ctxt->zstd_workspace);
59 break;
60#endif
Joao Marcos Costa10f7cf52020-08-18 17:17:21 +020061 }
62}
63
Joao Marcos Costa3634b352020-07-30 15:33:50 +020064#if IS_ENABLED(CONFIG_ZLIB)
65static void zlib_decompression_status(int ret)
66{
67 switch (ret) {
68 case Z_BUF_ERROR:
69 printf("Error: 'dest' buffer is not large enough.\n");
70 break;
71 case Z_DATA_ERROR:
72 printf("Error: corrupted compressed data.\n");
73 break;
74 case Z_MEM_ERROR:
75 printf("Error: insufficient memory.\n");
76 break;
77 }
78}
79#endif
80
Joao Marcos Costa9c948f52020-08-18 17:17:23 +020081#if IS_ENABLED(CONFIG_ZSTD)
82static int sqfs_zstd_decompress(struct squashfs_ctxt *ctxt, void *dest,
83 unsigned long dest_len, void *source, u32 src_len)
84{
85 ZSTD_DCtx *ctx;
86 size_t wsize;
87 int ret;
88
89 wsize = ZSTD_DCtxWorkspaceBound();
90 ctx = ZSTD_initDCtx(ctxt->zstd_workspace, wsize);
91 ret = ZSTD_decompressDCtx(ctx, dest, dest_len, source, src_len);
92
93 return ZSTD_isError(ret);
94}
95#endif /* CONFIG_ZSTD */
96
Joao Marcos Costacdc11442020-08-18 17:17:22 +020097int sqfs_decompress(struct squashfs_ctxt *ctxt, void *dest,
98 unsigned long *dest_len, void *source, u32 src_len)
Joao Marcos Costac5100612020-07-30 15:33:47 +020099{
Joao Marcos Costacdc11442020-08-18 17:17:22 +0200100 u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression);
Joao Marcos Costac5100612020-07-30 15:33:47 +0200101 int ret = 0;
102
103 switch (comp_type) {
Joao Marcos Costa3634b352020-07-30 15:33:50 +0200104#if IS_ENABLED(CONFIG_ZLIB)
105 case SQFS_COMP_ZLIB:
Joao Marcos Costa10f7cf52020-08-18 17:17:21 +0200106 ret = uncompress(dest, dest_len, source, src_len);
Joao Marcos Costa3634b352020-07-30 15:33:50 +0200107 if (ret) {
108 zlib_decompression_status(ret);
109 return -EINVAL;
110 }
111
112 break;
113#endif
Joao Marcos Costa9c948f52020-08-18 17:17:23 +0200114#if IS_ENABLED(CONFIG_ZSTD)
115 case SQFS_COMP_ZSTD:
116 ret = sqfs_zstd_decompress(ctxt, dest, *dest_len, source, src_len);
117 if (ret) {
118 printf("ZSTD Error code: %d\n", ZSTD_getErrorCode(ret));
119 return -EINVAL;
120 }
121
122 break;
123#endif
Joao Marcos Costac5100612020-07-30 15:33:47 +0200124 default:
125 printf("Error: unknown compression type.\n");
126 return -EINVAL;
127 }
128
129 return ret;
130}