uboot/fs/squashfs/sqfs_decompressor.c
<<
>>
Prefs
   1// 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>
  12
  13#if IS_ENABLED(CONFIG_LZO)
  14#include <linux/lzo.h>
  15#endif
  16
  17#if IS_ENABLED(CONFIG_ZLIB)
  18#include <u-boot/zlib.h>
  19#endif
  20
  21#if IS_ENABLED(CONFIG_ZSTD)
  22#include <linux/zstd.h>
  23#endif
  24
  25#include "sqfs_decompressor.h"
  26#include "sqfs_utils.h"
  27
  28int sqfs_decompressor_init(struct squashfs_ctxt *ctxt)
  29{
  30        u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression);
  31
  32        switch (comp_type) {
  33#if IS_ENABLED(CONFIG_LZO)
  34        case SQFS_COMP_LZO:
  35                break;
  36#endif
  37#if IS_ENABLED(CONFIG_ZLIB)
  38        case SQFS_COMP_ZLIB:
  39                break;
  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;
  47#endif
  48        default:
  49                printf("Error: unknown compression type.\n");
  50                return -EINVAL;
  51        }
  52
  53        return 0;
  54}
  55
  56void sqfs_decompressor_cleanup(struct squashfs_ctxt *ctxt)
  57{
  58        u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression);
  59
  60        switch (comp_type) {
  61#if IS_ENABLED(CONFIG_LZO)
  62        case SQFS_COMP_LZO:
  63                break;
  64#endif
  65#if IS_ENABLED(CONFIG_ZLIB)
  66        case SQFS_COMP_ZLIB:
  67                break;
  68#endif
  69#if IS_ENABLED(CONFIG_ZSTD)
  70        case SQFS_COMP_ZSTD:
  71                free(ctxt->zstd_workspace);
  72                break;
  73#endif
  74        }
  75}
  76
  77#if IS_ENABLED(CONFIG_ZLIB)
  78static 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
  94#if IS_ENABLED(CONFIG_ZSTD)
  95static 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
 110int sqfs_decompress(struct squashfs_ctxt *ctxt, void *dest,
 111                    unsigned long *dest_len, void *source, u32 src_len)
 112{
 113        u16 comp_type = get_unaligned_le16(&ctxt->sblk->compression);
 114        int ret = 0;
 115
 116        switch (comp_type) {
 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
 129#if IS_ENABLED(CONFIG_ZLIB)
 130        case SQFS_COMP_ZLIB:
 131                ret = uncompress(dest, dest_len, source, src_len);
 132                if (ret) {
 133                        zlib_decompression_status(ret);
 134                        return -EINVAL;
 135                }
 136
 137                break;
 138#endif
 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
 149        default:
 150                printf("Error: unknown compression type.\n");
 151                return -EINVAL;
 152        }
 153
 154        return ret;
 155}
 156