uboot/test/compression.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2013, The Chromium Authors
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#define DEBUG
   8
   9#include <common.h>
  10#include <command.h>
  11#include <malloc.h>
  12
  13#include <u-boot/zlib.h>
  14#include <bzlib.h>
  15
  16#include <lzma/LzmaTypes.h>
  17#include <lzma/LzmaDec.h>
  18#include <lzma/LzmaTools.h>
  19
  20#include <linux/lzo.h>
  21
  22static const char plain[] =
  23        "I am a highly compressable bit of text.\n"
  24        "I am a highly compressable bit of text.\n"
  25        "I am a highly compressable bit of text.\n"
  26        "There are many like me, but this one is mine.\n"
  27        "If I were any shorter, there wouldn't be much sense in\n"
  28        "compressing me in the first place. At least with lzo, anyway,\n"
  29        "which appears to behave poorly in the face of short text\n"
  30        "messages.\n";
  31
  32/* bzip2 -c /tmp/plain.txt > /tmp/plain.bz2 */
  33static const char bzip2_compressed[] =
  34        "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\xe5\x63\xdd\x09\x00\x00"
  35        "\x28\x57\x80\x00\x10\x40\x85\x20\x20\x04\x00\x3f\xef\xdf\xf0\x30"
  36        "\x00\xd6\xd0\x34\x91\x89\xa6\xf5\x4d\x19\x1a\x19\x0d\x02\x34\xd4"
  37        "\xc9\x00\x34\x34\x00\x02\x48\x41\x35\x4f\xd4\xc6\x88\xd3\x50\x3d"
  38        "\x4f\x51\x82\x4f\x88\xc3\x0d\x05\x62\x4f\x91\xa3\x52\x1b\xd0\x52"
  39        "\x41\x4a\xa3\x98\xc2\x6b\xca\xa3\x82\xa5\xac\x8b\x15\x99\x68\xad"
  40        "\xdf\x29\xd6\xf1\xf7\x5a\x10\xcd\x8c\x26\x61\x94\x95\xfe\x9e\x16"
  41        "\x18\x28\x69\xd4\x23\x64\xcc\x2b\xe5\xe8\x5f\x00\xa4\x70\x26\x2c"
  42        "\xee\xbd\x59\x6d\x6a\xec\xfc\x31\xda\x59\x0a\x14\x2a\x60\x1c\xf0"
  43        "\x04\x86\x73\x9a\xc5\x5b\x87\x3f\x5b\x4c\x93\xe6\xb5\x35\x0d\xa6"
  44        "\xb1\x2e\x62\x7b\xab\x67\xe7\x99\x2a\x14\x5e\x9f\x64\xcb\x96\xf4"
  45        "\x0d\x65\xd4\x39\xe6\x8b\x7e\xea\x1c\x03\x69\x97\x83\x58\x91\x96"
  46        "\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef"
  47        "\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a"
  48        "\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48";
  49static const unsigned long bzip2_compressed_size = 240;
  50
  51/* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
  52static const char lzma_compressed[] =
  53        "\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x88"
  54        "\x08\x26\xd8\x41\xff\x99\xc8\xcf\x66\x3d\x80\xac\xba\x17\xf1\xc8"
  55        "\xb9\xdf\x49\x37\xb1\x68\xa0\x2a\xdd\x63\xd1\xa7\xa3\x66\xf8\x15"
  56        "\xef\xa6\x67\x8a\x14\x18\x80\xcb\xc7\xb1\xcb\x84\x6a\xb2\x51\x16"
  57        "\xa1\x45\xa0\xd6\x3e\x55\x44\x8a\x5c\xa0\x7c\xe5\xa8\xbd\x04\x57"
  58        "\x8f\x24\xfd\xb9\x34\x50\x83\x2f\xf3\x46\x3e\xb9\xb0\x00\x1a\xf5"
  59        "\xd3\x86\x7e\x8f\x77\xd1\x5d\x0e\x7c\xe1\xac\xde\xf8\x65\x1f\x4d"
  60        "\xce\x7f\xa7\x3d\xaa\xcf\x26\xa7\x58\x69\x1e\x4c\xea\x68\x8a\xe5"
  61        "\x89\xd1\xdc\x4d\xc7\xe0\x07\x42\xbf\x0c\x9d\x06\xd7\x51\xa2\x0b"
  62        "\x7c\x83\x35\xe1\x85\xdf\xee\xfb\xa3\xee\x2f\x47\x5f\x8b\x70\x2b"
  63        "\xe1\x37\xf3\x16\xf6\x27\x54\x8a\x33\x72\x49\xea\x53\x7d\x60\x0b"
  64        "\x21\x90\x66\xe7\x9e\x56\x61\x5d\xd8\xdc\x59\xf0\xac\x2f\xd6\x49"
  65        "\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3"
  66        "\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff"
  67        "\xfd\xf5\x50\x8d\xca";
  68static const unsigned long lzma_compressed_size = 229;
  69
  70/* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
  71static const char lzo_compressed[] =
  72        "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a\x10\x30\x20\x60\x09\x40\x01"
  73        "\x05\x03\x00\x00\x09\x00\x00\x81\xb4\x52\x09\x54\xf1\x00\x00\x00"
  74        "\x00\x09\x70\x6c\x61\x69\x6e\x2e\x74\x78\x74\x65\xb1\x07\x9c\x00"
  75        "\x00\x01\x5e\x00\x00\x01\x0f\xc3\xc7\x7a\xe0\x00\x16\x49\x20\x61"
  76        "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
  77        "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
  78        "\x65\x78\x74\x2e\x0a\x20\x2f\x9c\x00\x00\x22\x54\x68\x65\x72\x65"
  79        "\x20\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d"
  80        "\x65\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20"
  81        "\x69\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x84"
  82        "\x06\x0a\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x90"
  83        "\x08\x00\x08\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d"
  84        "\x75\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xf8\x19\x02"
  85        "\x69\x6e\x67\x20\x6d\x64\x02\x64\x06\x00\x5a\x20\x66\x69\x72\x73"
  86        "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
  87        "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x20\x61\x6e\x79\x77"
  88        "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
  89        "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
  90        "\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f"
  91        "\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73"
  92        "\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00";
  93static const unsigned long lzo_compressed_size = 334;
  94
  95
  96#define TEST_BUFFER_SIZE        512
  97
  98typedef int (*mutate_func)(void *, unsigned long, void *, unsigned long,
  99                           unsigned long *);
 100
 101static int compress_using_gzip(void *in, unsigned long in_size,
 102                               void *out, unsigned long out_max,
 103                               unsigned long *out_size)
 104{
 105        int ret;
 106        unsigned long inout_size = out_max;
 107
 108        ret = gzip(out, &inout_size, in, in_size);
 109        if (out_size)
 110                *out_size = inout_size;
 111
 112        return ret;
 113}
 114
 115static int uncompress_using_gzip(void *in, unsigned long in_size,
 116                                 void *out, unsigned long out_max,
 117                                 unsigned long *out_size)
 118{
 119        int ret;
 120        unsigned long inout_size = in_size;
 121
 122        ret = gunzip(out, out_max, in, &inout_size);
 123        if (out_size)
 124                *out_size = inout_size;
 125
 126        return ret;
 127}
 128
 129static int compress_using_bzip2(void *in, unsigned long in_size,
 130                                void *out, unsigned long out_max,
 131                                unsigned long *out_size)
 132{
 133        /* There is no bzip2 compression in u-boot, so fake it. */
 134        assert(in_size == strlen(plain));
 135        assert(memcmp(plain, in, in_size) == 0);
 136
 137        if (bzip2_compressed_size > out_max)
 138                return -1;
 139
 140        memcpy(out, bzip2_compressed, bzip2_compressed_size);
 141        if (out_size)
 142                *out_size = bzip2_compressed_size;
 143
 144        return 0;
 145}
 146
 147static int uncompress_using_bzip2(void *in, unsigned long in_size,
 148                                  void *out, unsigned long out_max,
 149                                  unsigned long *out_size)
 150{
 151        int ret;
 152        unsigned int inout_size = out_max;
 153
 154        ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
 155                        CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
 156        if (out_size)
 157                *out_size = inout_size;
 158
 159        return (ret != BZ_OK);
 160}
 161
 162static int compress_using_lzma(void *in, unsigned long in_size,
 163                               void *out, unsigned long out_max,
 164                               unsigned long *out_size)
 165{
 166        /* There is no lzma compression in u-boot, so fake it. */
 167        assert(in_size == strlen(plain));
 168        assert(memcmp(plain, in, in_size) == 0);
 169
 170        if (lzma_compressed_size > out_max)
 171                return -1;
 172
 173        memcpy(out, lzma_compressed, lzma_compressed_size);
 174        if (out_size)
 175                *out_size = lzma_compressed_size;
 176
 177        return 0;
 178}
 179
 180static int uncompress_using_lzma(void *in, unsigned long in_size,
 181                                 void *out, unsigned long out_max,
 182                                 unsigned long *out_size)
 183{
 184        int ret;
 185        SizeT inout_size = out_max;
 186
 187        ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
 188        if (out_size)
 189                *out_size = inout_size;
 190
 191        return (ret != SZ_OK);
 192}
 193
 194static int compress_using_lzo(void *in, unsigned long in_size,
 195                              void *out, unsigned long out_max,
 196                              unsigned long *out_size)
 197{
 198        /* There is no lzo compression in u-boot, so fake it. */
 199        assert(in_size == strlen(plain));
 200        assert(memcmp(plain, in, in_size) == 0);
 201
 202        if (lzo_compressed_size > out_max)
 203                return -1;
 204
 205        memcpy(out, lzo_compressed, lzo_compressed_size);
 206        if (out_size)
 207                *out_size = lzo_compressed_size;
 208
 209        return 0;
 210}
 211
 212static int uncompress_using_lzo(void *in, unsigned long in_size,
 213                                void *out, unsigned long out_max,
 214                                unsigned long *out_size)
 215{
 216        int ret;
 217        size_t input_size = in_size;
 218        size_t output_size = out_max;
 219
 220        ret = lzop_decompress(in, input_size, out, &output_size);
 221        if (out_size)
 222                *out_size = output_size;
 223
 224        return (ret != LZO_E_OK);
 225}
 226
 227#define errcheck(statement) if (!(statement)) { \
 228        fprintf(stderr, "\tFailed: %s\n", #statement); \
 229        ret = 1; \
 230        goto out; \
 231}
 232
 233static int run_test(char *name, mutate_func compress, mutate_func uncompress)
 234{
 235        ulong orig_size, compressed_size, uncompressed_size;
 236        void *orig_buf;
 237        void *compressed_buf = NULL;
 238        void *uncompressed_buf = NULL;
 239        void *compare_buf = NULL;
 240        int ret;
 241
 242        printf(" testing %s ...\n", name);
 243
 244        orig_buf = (void *)plain;
 245        orig_size = strlen(orig_buf); /* Trailing NULL not included. */
 246        errcheck(orig_size > 0);
 247
 248        compressed_size = uncompressed_size = TEST_BUFFER_SIZE;
 249        compressed_buf = malloc(compressed_size);
 250        errcheck(compressed_buf != NULL);
 251        uncompressed_buf = malloc(uncompressed_size);
 252        errcheck(uncompressed_buf != NULL);
 253        compare_buf = malloc(uncompressed_size);
 254        errcheck(compare_buf != NULL);
 255
 256        /* Compress works as expected. */
 257        printf("\torig_size:%lu\n", orig_size);
 258        memset(compressed_buf, 'A', TEST_BUFFER_SIZE);
 259        errcheck(compress(orig_buf, orig_size,
 260                        compressed_buf, compressed_size,
 261                        &compressed_size) == 0);
 262        printf("\tcompressed_size:%lu\n", compressed_size);
 263        errcheck(compressed_size > 0);
 264        errcheck(compressed_size < orig_size);
 265        errcheck(((char *)compressed_buf)[compressed_size-1] != 'A');
 266        errcheck(((char *)compressed_buf)[compressed_size] == 'A');
 267
 268        /* Uncompresses with space remaining. */
 269        errcheck(uncompress(compressed_buf, compressed_size,
 270                          uncompressed_buf, uncompressed_size,
 271                          &uncompressed_size) == 0);
 272        printf("\tuncompressed_size:%lu\n", uncompressed_size);
 273        errcheck(uncompressed_size == orig_size);
 274        errcheck(memcmp(orig_buf, uncompressed_buf, orig_size) == 0);
 275
 276        /* Uncompresses with exactly the right size output buffer. */
 277        memset(uncompressed_buf, 'A', TEST_BUFFER_SIZE);
 278        errcheck(uncompress(compressed_buf, compressed_size,
 279                          uncompressed_buf, orig_size,
 280                          &uncompressed_size) == 0);
 281        errcheck(uncompressed_size == orig_size);
 282        errcheck(memcmp(orig_buf, uncompressed_buf, orig_size) == 0);
 283        errcheck(((char *)uncompressed_buf)[orig_size] == 'A');
 284
 285        /* Make sure compression does not over-run. */
 286        memset(compare_buf, 'A', TEST_BUFFER_SIZE);
 287        ret = compress(orig_buf, orig_size,
 288                       compare_buf, compressed_size - 1,
 289                       NULL);
 290        errcheck(((char *)compare_buf)[compressed_size] == 'A');
 291        errcheck(ret != 0);
 292        printf("\tcompress does not overrun\n");
 293
 294        /* Make sure decompression does not over-run. */
 295        memset(compare_buf, 'A', TEST_BUFFER_SIZE);
 296        ret = uncompress(compressed_buf, compressed_size,
 297                         compare_buf, uncompressed_size - 1,
 298                         NULL);
 299        errcheck(((char *)compare_buf)[uncompressed_size - 1] == 'A');
 300        errcheck(ret != 0);
 301        printf("\tuncompress does not overrun\n");
 302
 303        /* Got here, everything is fine. */
 304        ret = 0;
 305
 306out:
 307        printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
 308
 309        free(compare_buf);
 310        free(uncompressed_buf);
 311        free(compressed_buf);
 312
 313        return ret;
 314}
 315
 316
 317static int do_test_compression(cmd_tbl_t *cmdtp, int flag, int argc,
 318                               char * const argv[])
 319{
 320        int err = 0;
 321
 322        err += run_test("gzip", compress_using_gzip, uncompress_using_gzip);
 323        err += run_test("bzip2", compress_using_bzip2, uncompress_using_bzip2);
 324        err += run_test("lzma", compress_using_lzma, uncompress_using_lzma);
 325        err += run_test("lzo", compress_using_lzo, uncompress_using_lzo);
 326
 327        printf("test_compression %s\n", err == 0 ? "ok" : "FAILED");
 328
 329        return err;
 330}
 331
 332U_BOOT_CMD(
 333        test_compression,       5,      1,      do_test_compression,
 334        "Basic test of compressors: gzip bzip2 lzma lzo", ""
 335);
 336