]>
Commit | Line | Data |
---|---|---|
c5100613 JMC |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * Copyright (C) 2020 Bootlin | |
4 | * | |
5 | * Author: Joao Marcos Costa <[email protected]> | |
6 | */ | |
7 | ||
8 | #include <errno.h> | |
9 | #include <stdint.h> | |
10 | #include <stdio.h> | |
11 | #include <stdlib.h> | |
6dfed163 JMC |
12 | |
13 | #if IS_ENABLED(CONFIG_LZO) | |
14 | #include <linux/lzo.h> | |
15 | #endif | |
16 | ||
3634b350 JMC |
17 | #if IS_ENABLED(CONFIG_ZLIB) |
18 | #include <u-boot/zlib.h> | |
19 | #endif | |
c5100613 | 20 | |
9c948f53 JMC |
21 | #if IS_ENABLED(CONFIG_ZSTD) |
22 | #include <linux/zstd.h> | |
23 | #endif | |
24 | ||
c5100613 | 25 | #include "sqfs_decompressor.h" |
c5100613 JMC |
26 | #include "sqfs_utils.h" |
27 | ||
10f7cf5f JMC |
28 | int sqfs_decompressor_init(struct squashfs_ctxt *ctxt) |
29 | { | |
30 | u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression); | |
31 | ||
32 | switch (comp_type) { | |
6dfed163 JMC |
33 | #if IS_ENABLED(CONFIG_LZO) |
34 | case SQFS_COMP_LZO: | |
35 | break; | |
36 | #endif | |
10f7cf5f JMC |
37 | #if IS_ENABLED(CONFIG_ZLIB) |
38 | case SQFS_COMP_ZLIB: | |
39 | break; | |
9c948f53 JMC |
40 | #endif |
41 | #if IS_ENABLED(CONFIG_ZSTD) | |
42 | case SQFS_COMP_ZSTD: | |
43 | ctxt->zstd_workspace = malloc(ZSTD_DCtxWorkspaceBound()); | |
44 | if (!ctxt->zstd_workspace) | |
45 | return -ENOMEM; | |
46 | break; | |
10f7cf5f JMC |
47 | #endif |
48 | default: | |
49 | printf("Error: unknown compression type.\n"); | |
50 | return -EINVAL; | |
51 | } | |
52 | ||
53 | return 0; | |
54 | } | |
55 | ||
56 | void sqfs_decompressor_cleanup(struct squashfs_ctxt *ctxt) | |
57 | { | |
58 | u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression); | |
59 | ||
60 | switch (comp_type) { | |
6dfed163 JMC |
61 | #if IS_ENABLED(CONFIG_LZO) |
62 | case SQFS_COMP_LZO: | |
63 | break; | |
64 | #endif | |
10f7cf5f JMC |
65 | #if IS_ENABLED(CONFIG_ZLIB) |
66 | case SQFS_COMP_ZLIB: | |
67 | break; | |
9c948f53 JMC |
68 | #endif |
69 | #if IS_ENABLED(CONFIG_ZSTD) | |
70 | case SQFS_COMP_ZSTD: | |
71 | free(ctxt->zstd_workspace); | |
72 | break; | |
10f7cf5f JMC |
73 | #endif |
74 | } | |
75 | } | |
76 | ||
3634b350 JMC |
77 | #if IS_ENABLED(CONFIG_ZLIB) |
78 | static void zlib_decompression_status(int ret) | |
79 | { | |
80 | switch (ret) { | |
81 | case Z_BUF_ERROR: | |
82 | printf("Error: 'dest' buffer is not large enough.\n"); | |
83 | break; | |
84 | case Z_DATA_ERROR: | |
85 | printf("Error: corrupted compressed data.\n"); | |
86 | break; | |
87 | case Z_MEM_ERROR: | |
88 | printf("Error: insufficient memory.\n"); | |
89 | break; | |
90 | } | |
91 | } | |
92 | #endif | |
93 | ||
9c948f53 JMC |
94 | #if IS_ENABLED(CONFIG_ZSTD) |
95 | static int sqfs_zstd_decompress(struct squashfs_ctxt *ctxt, void *dest, | |
96 | unsigned long dest_len, void *source, u32 src_len) | |
97 | { | |
98 | ZSTD_DCtx *ctx; | |
99 | size_t wsize; | |
100 | int ret; | |
101 | ||
102 | wsize = ZSTD_DCtxWorkspaceBound(); | |
103 | ctx = ZSTD_initDCtx(ctxt->zstd_workspace, wsize); | |
104 | ret = ZSTD_decompressDCtx(ctx, dest, dest_len, source, src_len); | |
105 | ||
106 | return ZSTD_isError(ret); | |
107 | } | |
108 | #endif /* CONFIG_ZSTD */ | |
109 | ||
cdc11441 JMC |
110 | int sqfs_decompress(struct squashfs_ctxt *ctxt, void *dest, |
111 | unsigned long *dest_len, void *source, u32 src_len) | |
c5100613 | 112 | { |
cdc11441 | 113 | u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression); |
c5100613 JMC |
114 | int ret = 0; |
115 | ||
116 | switch (comp_type) { | |
6dfed163 JMC |
117 | #if IS_ENABLED(CONFIG_LZO) |
118 | case SQFS_COMP_LZO: { | |
119 | size_t lzo_dest_len = *dest_len; | |
120 | ret = lzo1x_decompress_safe(source, src_len, dest, &lzo_dest_len); | |
121 | if (ret) { | |
122 | printf("LZO decompression failed. Error code: %d\n", ret); | |
123 | return -EINVAL; | |
124 | } | |
125 | ||
126 | break; | |
127 | } | |
128 | #endif | |
3634b350 JMC |
129 | #if IS_ENABLED(CONFIG_ZLIB) |
130 | case SQFS_COMP_ZLIB: | |
10f7cf5f | 131 | ret = uncompress(dest, dest_len, source, src_len); |
3634b350 JMC |
132 | if (ret) { |
133 | zlib_decompression_status(ret); | |
134 | return -EINVAL; | |
135 | } | |
136 | ||
137 | break; | |
138 | #endif | |
9c948f53 JMC |
139 | #if IS_ENABLED(CONFIG_ZSTD) |
140 | case SQFS_COMP_ZSTD: | |
141 | ret = sqfs_zstd_decompress(ctxt, dest, *dest_len, source, src_len); | |
142 | if (ret) { | |
143 | printf("ZSTD Error code: %d\n", ZSTD_getErrorCode(ret)); | |
144 | return -EINVAL; | |
145 | } | |
146 | ||
147 | break; | |
148 | #endif | |
c5100613 JMC |
149 | default: |
150 | printf("Error: unknown compression type.\n"); | |
151 | return -EINVAL; | |
152 | } | |
153 | ||
154 | return ret; | |
155 | } |