uboot/test/compression.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2013, The Chromium Authors
   4 */
   5
   6#include <common.h>
   7#include <abuf.h>
   8#include <bootm.h>
   9#include <command.h>
  10#include <gzip.h>
  11#include <image.h>
  12#include <log.h>
  13#include <malloc.h>
  14#include <mapmem.h>
  15#include <asm/io.h>
  16
  17#include <u-boot/lz4.h>
  18#include <u-boot/zlib.h>
  19#include <bzlib.h>
  20
  21#include <lzma/LzmaTypes.h>
  22#include <lzma/LzmaDec.h>
  23#include <lzma/LzmaTools.h>
  24
  25#include <linux/lzo.h>
  26#include <linux/zstd.h>
  27#include <test/compression.h>
  28#include <test/suites.h>
  29#include <test/ut.h>
  30
  31static const char plain[] =
  32        "I am a highly compressable bit of text.\n"
  33        "I am a highly compressable bit of text.\n"
  34        "I am a highly compressable bit of text.\n"
  35        "There are many like me, but this one is mine.\n"
  36        "If I were any shorter, there wouldn't be much sense in\n"
  37        "compressing me in the first place. At least with lzo, anyway,\n"
  38        "which appears to behave poorly in the face of short text\n"
  39        "messages.\n";
  40
  41/* bzip2 -c /tmp/plain.txt > /tmp/plain.bz2 */
  42static const char bzip2_compressed[] =
  43        "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\xe5\x63\xdd\x09\x00\x00"
  44        "\x28\x57\x80\x00\x10\x40\x85\x20\x20\x04\x00\x3f\xef\xdf\xf0\x30"
  45        "\x00\xd6\xd0\x34\x91\x89\xa6\xf5\x4d\x19\x1a\x19\x0d\x02\x34\xd4"
  46        "\xc9\x00\x34\x34\x00\x02\x48\x41\x35\x4f\xd4\xc6\x88\xd3\x50\x3d"
  47        "\x4f\x51\x82\x4f\x88\xc3\x0d\x05\x62\x4f\x91\xa3\x52\x1b\xd0\x52"
  48        "\x41\x4a\xa3\x98\xc2\x6b\xca\xa3\x82\xa5\xac\x8b\x15\x99\x68\xad"
  49        "\xdf\x29\xd6\xf1\xf7\x5a\x10\xcd\x8c\x26\x61\x94\x95\xfe\x9e\x16"
  50        "\x18\x28\x69\xd4\x23\x64\xcc\x2b\xe5\xe8\x5f\x00\xa4\x70\x26\x2c"
  51        "\xee\xbd\x59\x6d\x6a\xec\xfc\x31\xda\x59\x0a\x14\x2a\x60\x1c\xf0"
  52        "\x04\x86\x73\x9a\xc5\x5b\x87\x3f\x5b\x4c\x93\xe6\xb5\x35\x0d\xa6"
  53        "\xb1\x2e\x62\x7b\xab\x67\xe7\x99\x2a\x14\x5e\x9f\x64\xcb\x96\xf4"
  54        "\x0d\x65\xd4\x39\xe6\x8b\x7e\xea\x1c\x03\x69\x97\x83\x58\x91\x96"
  55        "\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef"
  56        "\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a"
  57        "\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48";
  58static const unsigned long bzip2_compressed_size = sizeof(bzip2_compressed) - 1;
  59
  60/* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
  61static const char lzma_compressed[] =
  62        "\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x88"
  63        "\x08\x26\xd8\x41\xff\x99\xc8\xcf\x66\x3d\x80\xac\xba\x17\xf1\xc8"
  64        "\xb9\xdf\x49\x37\xb1\x68\xa0\x2a\xdd\x63\xd1\xa7\xa3\x66\xf8\x15"
  65        "\xef\xa6\x67\x8a\x14\x18\x80\xcb\xc7\xb1\xcb\x84\x6a\xb2\x51\x16"
  66        "\xa1\x45\xa0\xd6\x3e\x55\x44\x8a\x5c\xa0\x7c\xe5\xa8\xbd\x04\x57"
  67        "\x8f\x24\xfd\xb9\x34\x50\x83\x2f\xf3\x46\x3e\xb9\xb0\x00\x1a\xf5"
  68        "\xd3\x86\x7e\x8f\x77\xd1\x5d\x0e\x7c\xe1\xac\xde\xf8\x65\x1f\x4d"
  69        "\xce\x7f\xa7\x3d\xaa\xcf\x26\xa7\x58\x69\x1e\x4c\xea\x68\x8a\xe5"
  70        "\x89\xd1\xdc\x4d\xc7\xe0\x07\x42\xbf\x0c\x9d\x06\xd7\x51\xa2\x0b"
  71        "\x7c\x83\x35\xe1\x85\xdf\xee\xfb\xa3\xee\x2f\x47\x5f\x8b\x70\x2b"
  72        "\xe1\x37\xf3\x16\xf6\x27\x54\x8a\x33\x72\x49\xea\x53\x7d\x60\x0b"
  73        "\x21\x90\x66\xe7\x9e\x56\x61\x5d\xd8\xdc\x59\xf0\xac\x2f\xd6\x49"
  74        "\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3"
  75        "\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff"
  76        "\xfd\xf5\x50\x8d\xca";
  77static const unsigned long lzma_compressed_size = sizeof(lzma_compressed) - 1;
  78
  79/* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
  80static const char lzo_compressed[] =
  81        "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a\x10\x30\x20\x60\x09\x40\x01"
  82        "\x05\x03\x00\x00\x09\x00\x00\x81\xb4\x52\x09\x54\xf1\x00\x00\x00"
  83        "\x00\x09\x70\x6c\x61\x69\x6e\x2e\x74\x78\x74\x65\xb1\x07\x9c\x00"
  84        "\x00\x01\x5e\x00\x00\x01\x0f\xc3\xc7\x7a\xe0\x00\x16\x49\x20\x61"
  85        "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
  86        "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
  87        "\x65\x78\x74\x2e\x0a\x20\x2f\x9c\x00\x00\x22\x54\x68\x65\x72\x65"
  88        "\x20\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d"
  89        "\x65\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20"
  90        "\x69\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x84"
  91        "\x06\x0a\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x90"
  92        "\x08\x00\x08\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d"
  93        "\x75\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xf8\x19\x02"
  94        "\x69\x6e\x67\x20\x6d\x64\x02\x64\x06\x00\x5a\x20\x66\x69\x72\x73"
  95        "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
  96        "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x20\x61\x6e\x79\x77"
  97        "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
  98        "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
  99        "\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f"
 100        "\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73"
 101        "\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00";
 102static const unsigned long lzo_compressed_size = sizeof(lzo_compressed) - 1;
 103
 104/* lz4 -z /tmp/plain.txt > /tmp/plain.lz4 */
 105static const char lz4_compressed[] =
 106        "\x04\x22\x4d\x18\x64\x70\xb9\x01\x01\x00\x00\xff\x19\x49\x20\x61"
 107        "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
 108        "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
 109        "\x65\x78\x74\x2e\x0a\x28\x00\x3d\xf1\x25\x54\x68\x65\x72\x65\x20"
 110        "\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d\x65"
 111        "\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20\x69"
 112        "\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x32\x00"
 113        "\xd1\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x45\x00"
 114        "\xf4\x0b\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d\x75"
 115        "\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xcf\x00\x50\x69"
 116        "\x6e\x67\x20\x6d\x12\x00\x00\x32\x00\xf0\x11\x20\x66\x69\x72\x73"
 117        "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
 118        "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x63\x00\xf5\x14\x77"
 119        "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
 120        "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
 121        "\x6c\x79\x4e\x00\x30\x61\x63\x65\x27\x01\x01\x95\x00\x01\x2d\x01"
 122        "\xb0\x0a\x6d\x65\x73\x73\x61\x67\x65\x73\x2e\x0a\x00\x00\x00\x00"
 123        "\x9d\x12\x8c\x9d";
 124static const unsigned long lz4_compressed_size = sizeof(lz4_compressed) - 1;
 125
 126/* zstd -19 -c /tmp/plain.txt > /tmp/plain.zst */
 127static const char zstd_compressed[] =
 128        "\x28\xb5\x2f\xfd\x64\x5e\x00\xbd\x05\x00\x02\x0e\x26\x1a\x70\x17"
 129        "\xb8\x0d\x0c\x53\x5c\x9d\x97\xee\xa0\x5d\x84\x89\x3f\x5c\x7a\x78"
 130        "\x00\x80\x80\x0f\xe8\xdf\xaf\x06\x66\xd0\x23\xa6\x7a\x64\x8e\xf4"
 131        "\x0d\x5b\x47\x65\x26\x7e\x81\xdd\x0b\xe7\x5a\x95\x3d\x49\xcc\x67"
 132        "\xe0\x2d\x46\x58\xb6\xac\x64\x16\xf2\xe0\xf8\x16\x17\xaf\xda\x8f"
 133        "\x37\xc0\xc3\x0d\x3b\x89\x57\x15\x1e\x46\x46\x12\x9a\x84\xbe\xa6"
 134        "\xab\xcf\x50\x90\x5f\x78\x01\xd2\xc0\x51\x72\x59\x0b\xea\xab\xf2"
 135        "\xd4\x2b\x2d\x26\x7c\x10\x66\x78\x42\x64\x45\x3f\xa5\x15\x6f\xbd"
 136        "\x4a\x61\xe1\xc8\x27\xc0\xe3\x95\x0c\xf9\xca\x7c\xf5\x13\x30\xc3"
 137        "\x1a\x7c\x7d\xa4\x17\x0b\xff\x14\xa6\x7a\x95\xa0\x34\xbc\xce\x21"
 138        "\x78\x36\x23\x33\x11\x09\x00\x60\x13\x00\x63\xa3\x8e\x28\x94\x55"
 139        "\x15\xb6\x26\x68\x05\x4f\x23\x12\xee\x53\x55\x2d\x44\x2f\x54\x95"
 140        "\x01\xe4\xf4\x6e\xfa";
 141static const unsigned long zstd_compressed_size = sizeof(zstd_compressed) - 1;
 142
 143
 144#define TEST_BUFFER_SIZE        512
 145
 146typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
 147                           void *, unsigned long, unsigned long *);
 148
 149static int compress_using_gzip(struct unit_test_state *uts,
 150                               void *in, unsigned long in_size,
 151                               void *out, unsigned long out_max,
 152                               unsigned long *out_size)
 153{
 154        int ret;
 155        unsigned long inout_size = out_max;
 156
 157        ret = gzip(out, &inout_size, in, in_size);
 158        if (out_size)
 159                *out_size = inout_size;
 160
 161        return ret;
 162}
 163
 164static int uncompress_using_gzip(struct unit_test_state *uts,
 165                                 void *in, unsigned long in_size,
 166                                 void *out, unsigned long out_max,
 167                                 unsigned long *out_size)
 168{
 169        int ret;
 170        unsigned long inout_size = in_size;
 171
 172        ret = gunzip(out, out_max, in, &inout_size);
 173        if (out_size)
 174                *out_size = inout_size;
 175
 176        return ret;
 177}
 178
 179static int compress_using_bzip2(struct unit_test_state *uts,
 180                                void *in, unsigned long in_size,
 181                                void *out, unsigned long out_max,
 182                                unsigned long *out_size)
 183{
 184        /* There is no bzip2 compression in u-boot, so fake it. */
 185        ut_asserteq(in_size, strlen(plain));
 186        ut_asserteq_mem(plain, in, in_size);
 187
 188        if (bzip2_compressed_size > out_max)
 189                return -1;
 190
 191        memcpy(out, bzip2_compressed, bzip2_compressed_size);
 192        if (out_size)
 193                *out_size = bzip2_compressed_size;
 194
 195        return 0;
 196}
 197
 198static int uncompress_using_bzip2(struct unit_test_state *uts,
 199                                  void *in, unsigned long in_size,
 200                                  void *out, unsigned long out_max,
 201                                  unsigned long *out_size)
 202{
 203        int ret;
 204        unsigned int inout_size = out_max;
 205
 206        ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
 207                        CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
 208        if (out_size)
 209                *out_size = inout_size;
 210
 211        return (ret != BZ_OK);
 212}
 213
 214static int compress_using_lzma(struct unit_test_state *uts,
 215                               void *in, unsigned long in_size,
 216                               void *out, unsigned long out_max,
 217                               unsigned long *out_size)
 218{
 219        /* There is no lzma compression in u-boot, so fake it. */
 220        ut_asserteq(in_size,  strlen(plain));
 221        ut_asserteq_mem(plain, in, in_size);
 222
 223        if (lzma_compressed_size > out_max)
 224                return -1;
 225
 226        memcpy(out, lzma_compressed, lzma_compressed_size);
 227        if (out_size)
 228                *out_size = lzma_compressed_size;
 229
 230        return 0;
 231}
 232
 233static int uncompress_using_lzma(struct unit_test_state *uts,
 234                                 void *in, unsigned long in_size,
 235                                 void *out, unsigned long out_max,
 236                                 unsigned long *out_size)
 237{
 238        int ret;
 239        SizeT inout_size = out_max;
 240
 241        ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
 242        if (out_size)
 243                *out_size = inout_size;
 244
 245        return (ret != SZ_OK);
 246}
 247
 248static int compress_using_lzo(struct unit_test_state *uts,
 249                              void *in, unsigned long in_size,
 250                              void *out, unsigned long out_max,
 251                              unsigned long *out_size)
 252{
 253        /* There is no lzo compression in u-boot, so fake it. */
 254        ut_asserteq(in_size,  strlen(plain));
 255        ut_asserteq_mem(plain, in, in_size);
 256
 257        if (lzo_compressed_size > out_max)
 258                return -1;
 259
 260        memcpy(out, lzo_compressed, lzo_compressed_size);
 261        if (out_size)
 262                *out_size = lzo_compressed_size;
 263
 264        return 0;
 265}
 266
 267static int uncompress_using_lzo(struct unit_test_state *uts,
 268                                void *in, unsigned long in_size,
 269                                void *out, unsigned long out_max,
 270                                unsigned long *out_size)
 271{
 272        int ret;
 273        size_t input_size = in_size;
 274        size_t output_size = out_max;
 275
 276        ret = lzop_decompress(in, input_size, out, &output_size);
 277        if (out_size)
 278                *out_size = output_size;
 279
 280        return (ret != LZO_E_OK);
 281}
 282
 283static int compress_using_lz4(struct unit_test_state *uts,
 284                              void *in, unsigned long in_size,
 285                              void *out, unsigned long out_max,
 286                              unsigned long *out_size)
 287{
 288        /* There is no lz4 compression in u-boot, so fake it. */
 289        ut_asserteq(in_size,  strlen(plain));
 290        ut_asserteq_mem(plain, in, in_size);
 291
 292        if (lz4_compressed_size > out_max)
 293                return -1;
 294
 295        memcpy(out, lz4_compressed, lz4_compressed_size);
 296        if (out_size)
 297                *out_size = lz4_compressed_size;
 298
 299        return 0;
 300}
 301
 302static int uncompress_using_lz4(struct unit_test_state *uts,
 303                                void *in, unsigned long in_size,
 304                                void *out, unsigned long out_max,
 305                                unsigned long *out_size)
 306{
 307        int ret;
 308        size_t input_size = in_size;
 309        size_t output_size = out_max;
 310
 311        ret = ulz4fn(in, input_size, out, &output_size);
 312        if (out_size)
 313                *out_size = output_size;
 314
 315        return (ret != 0);
 316}
 317
 318static int compress_using_zstd(struct unit_test_state *uts,
 319                               void *in, unsigned long in_size,
 320                               void *out, unsigned long out_max,
 321                               unsigned long *out_size)
 322{
 323        /* There is no zstd compression in u-boot, so fake it. */
 324        ut_asserteq(in_size, strlen(plain));
 325        ut_asserteq_mem(plain, in, in_size);
 326
 327        if (zstd_compressed_size > out_max)
 328                return -1;
 329
 330        memcpy(out, zstd_compressed, zstd_compressed_size);
 331        if (out_size)
 332                *out_size = zstd_compressed_size;
 333
 334        return 0;
 335}
 336
 337static int uncompress_using_zstd(struct unit_test_state *uts,
 338                                 void *in, unsigned long in_size,
 339                                 void *out, unsigned long out_max,
 340                                 unsigned long *out_size)
 341{
 342        struct abuf in_buf, out_buf;
 343        int ret;
 344
 345        abuf_init_set(&in_buf, in, in_size);
 346        abuf_init_set(&out_buf, out, out_max);
 347
 348        ret = zstd_decompress(&in_buf, &out_buf);
 349        if (ret >= 0) {
 350                *out_size = ret;
 351                ret = 0;
 352        }
 353
 354        return ret;
 355}
 356
 357#define errcheck(statement) if (!(statement)) { \
 358        fprintf(stderr, "\tFailed: %s\n", #statement); \
 359        ret = 1; \
 360        goto out; \
 361}
 362
 363struct buf_state {
 364        ulong orig_size;
 365        ulong compressed_size;
 366        ulong uncompressed_size;
 367        void *orig_buf;
 368        void *compressed_buf;
 369        void *uncompressed_buf;
 370        void *compare_buf;
 371};
 372
 373static int run_test_internal(struct unit_test_state *uts, char *name,
 374                             mutate_func compress, mutate_func uncompress,
 375                             struct buf_state *buf)
 376{
 377        int ret;
 378
 379        /* Compress works as expected. */
 380        printf("\torig_size:%lu\n", buf->orig_size);
 381        memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
 382        ut_assertok(compress(uts, buf->orig_buf, buf->orig_size,
 383                          buf->compressed_buf, buf->compressed_size,
 384                          &buf->compressed_size));
 385        printf("\tcompressed_size:%lu\n", buf->compressed_size);
 386        ut_assert(buf->compressed_size > 0);
 387        ut_assert(buf->compressed_size < buf->orig_size);
 388        ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1]
 389                        != 'A');
 390        ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A');
 391
 392        /* Uncompresses with space remaining. */
 393        ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
 394                            buf->uncompressed_buf, buf->uncompressed_size,
 395                            &buf->uncompressed_size));
 396        printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
 397        ut_asserteq(buf->uncompressed_size, buf->orig_size);
 398        ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
 399
 400        /* Uncompresses with exactly the right size output buffer. */
 401        memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
 402        ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
 403                            buf->uncompressed_buf, buf->orig_size,
 404                            &buf->uncompressed_size));
 405        ut_asserteq(buf->uncompressed_size, buf->orig_size);
 406        ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
 407        ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A');
 408
 409        /* Uncompresses with trailing garbage in input buffer. */
 410        memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
 411        ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4,
 412                            buf->uncompressed_buf, buf->uncompressed_size,
 413                            &buf->uncompressed_size));
 414        ut_asserteq(buf->uncompressed_size, buf->orig_size);
 415        ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
 416
 417        /* Make sure compression does not over-run. */
 418        memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
 419        ret = compress(uts, buf->orig_buf, buf->orig_size,
 420                       buf->compare_buf, buf->compressed_size - 1,
 421                       NULL);
 422        ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A');
 423        ut_assert(ret != 0);
 424        printf("\tcompress does not overrun\n");
 425
 426        /* Make sure decompression does not over-run. */
 427        memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
 428        ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
 429                         buf->compare_buf, buf->uncompressed_size - 1,
 430                         NULL);
 431        ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A');
 432        ut_assert(ret != 0);
 433        printf("\tuncompress does not overrun\n");
 434
 435        /* Got here, everything is fine. */
 436        return 0;
 437}
 438
 439static int run_test(struct unit_test_state *uts, char *name,
 440                    mutate_func compress, mutate_func uncompress)
 441{
 442        struct buf_state sbuf, *buf = &sbuf;
 443        int ret;
 444
 445        printf(" testing %s ...\n", name);
 446
 447        buf->orig_buf = (void *)plain;
 448        buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
 449        errcheck(buf->orig_size > 0);
 450
 451        buf->compressed_size = TEST_BUFFER_SIZE;
 452        buf->uncompressed_size = TEST_BUFFER_SIZE;
 453        buf->compressed_buf = malloc(buf->compressed_size);
 454        errcheck(buf->compressed_buf);
 455        buf->uncompressed_buf = malloc(buf->uncompressed_size);
 456        errcheck(buf->uncompressed_buf);
 457        buf->compare_buf = malloc(buf->uncompressed_size);
 458        errcheck(buf->compare_buf);
 459
 460        ret = run_test_internal(uts, name, compress, uncompress, buf);
 461out:
 462        printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
 463
 464        free(buf->compare_buf);
 465        free(buf->uncompressed_buf);
 466        free(buf->compressed_buf);
 467
 468        return ret;
 469}
 470
 471static int compression_test_gzip(struct unit_test_state *uts)
 472{
 473        return run_test(uts, "gzip", compress_using_gzip,
 474                        uncompress_using_gzip);
 475}
 476COMPRESSION_TEST(compression_test_gzip, 0);
 477
 478static int compression_test_bzip2(struct unit_test_state *uts)
 479{
 480        return run_test(uts, "bzip2", compress_using_bzip2,
 481                        uncompress_using_bzip2);
 482}
 483COMPRESSION_TEST(compression_test_bzip2, 0);
 484
 485static int compression_test_lzma(struct unit_test_state *uts)
 486{
 487        return run_test(uts, "lzma", compress_using_lzma,
 488                        uncompress_using_lzma);
 489}
 490COMPRESSION_TEST(compression_test_lzma, 0);
 491
 492static int compression_test_lzo(struct unit_test_state *uts)
 493{
 494        return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
 495}
 496COMPRESSION_TEST(compression_test_lzo, 0);
 497
 498static int compression_test_lz4(struct unit_test_state *uts)
 499{
 500        return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
 501}
 502COMPRESSION_TEST(compression_test_lz4, 0);
 503
 504static int compression_test_zstd(struct unit_test_state *uts)
 505{
 506        return run_test(uts, "zstd", compress_using_zstd,
 507                        uncompress_using_zstd);
 508}
 509COMPRESSION_TEST(compression_test_zstd, 0);
 510
 511static int compress_using_none(struct unit_test_state *uts,
 512                               void *in, unsigned long in_size,
 513                               void *out, unsigned long out_max,
 514                               unsigned long *out_size)
 515{
 516        /* Here we just copy */
 517        memcpy(out, in, in_size);
 518        *out_size = in_size;
 519
 520        return 0;
 521}
 522
 523/**
 524 * run_bootm_test() - Run tests on the bootm decompression function
 525 *
 526 * @comp_type:  Compression type to test
 527 * @compress:   Our function to compress data
 528 * Return: 0 if OK, non-zero on failure
 529 */
 530static int run_bootm_test(struct unit_test_state *uts, int comp_type,
 531                          mutate_func compress)
 532{
 533        ulong compress_size = 1024;
 534        void *compress_buff;
 535        int unc_len;
 536        int err = 0;
 537        const ulong image_start = 0;
 538        const ulong load_addr = 0x1000;
 539        ulong load_end;
 540
 541        printf("Testing: %s\n", genimg_get_comp_name(comp_type));
 542        compress_buff = map_sysmem(image_start, 0);
 543        unc_len = strlen(plain);
 544        compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
 545                 &compress_size);
 546        err = image_decomp(comp_type, load_addr, image_start,
 547                           IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
 548                           compress_buff, compress_size, unc_len,
 549                           &load_end);
 550        ut_assertok(err);
 551        err = image_decomp(comp_type, load_addr, image_start,
 552                           IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
 553                           compress_buff, compress_size, unc_len - 1,
 554                           &load_end);
 555        ut_assert(err);
 556
 557        /* We can't detect corruption when not decompressing */
 558        if (comp_type == IH_COMP_NONE)
 559                return 0;
 560        memset(compress_buff + compress_size / 2, '\x49',
 561               compress_size / 2);
 562        err = image_decomp(comp_type, load_addr, image_start,
 563                           IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
 564                           compress_buff, compress_size, 0x10000,
 565                           &load_end);
 566        ut_assert(err);
 567
 568        return 0;
 569}
 570
 571static int compression_test_bootm_gzip(struct unit_test_state *uts)
 572{
 573        return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
 574}
 575COMPRESSION_TEST(compression_test_bootm_gzip, 0);
 576
 577static int compression_test_bootm_bzip2(struct unit_test_state *uts)
 578{
 579        return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
 580}
 581COMPRESSION_TEST(compression_test_bootm_bzip2, 0);
 582
 583static int compression_test_bootm_lzma(struct unit_test_state *uts)
 584{
 585        return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
 586}
 587COMPRESSION_TEST(compression_test_bootm_lzma, 0);
 588
 589static int compression_test_bootm_lzo(struct unit_test_state *uts)
 590{
 591        return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
 592}
 593COMPRESSION_TEST(compression_test_bootm_lzo, 0);
 594
 595static int compression_test_bootm_lz4(struct unit_test_state *uts)
 596{
 597        return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
 598}
 599COMPRESSION_TEST(compression_test_bootm_lz4, 0);
 600
 601static int compression_test_bootm_zstd(struct unit_test_state *uts)
 602{
 603        return run_bootm_test(uts, IH_COMP_ZSTD, compress_using_zstd);
 604}
 605COMPRESSION_TEST(compression_test_bootm_zstd, 0);
 606
 607static int compression_test_bootm_none(struct unit_test_state *uts)
 608{
 609        return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
 610}
 611COMPRESSION_TEST(compression_test_bootm_none, 0);
 612
 613int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
 614                      char *const argv[])
 615{
 616        struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test);
 617        const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test);
 618
 619        return cmd_ut_category("compression", "compression_test_",
 620                               tests, n_ents, argc, argv);
 621}
 622