root/arch/powerpc/boot/decompress.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. flush
  2. print_err
  3. partial_decompress

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Wrapper around the kernel's pre-boot decompression library.
   4  *
   5  * Copyright (C) IBM Corporation 2016.
   6  */
   7 
   8 #include "elf.h"
   9 #include "page.h"
  10 #include "string.h"
  11 #include "stdio.h"
  12 #include "ops.h"
  13 #include "reg.h"
  14 #include "types.h"
  15 
  16 /*
  17  * The decompressor_*.c files play #ifdef games so they can be used in both
  18  * pre-boot and regular kernel code. We need these definitions to make the
  19  * includes work.
  20  */
  21 
  22 #define STATIC static
  23 #define INIT
  24 #define __always_inline inline
  25 
  26 /*
  27  * The build process will copy the required zlib source files and headers
  28  * out of lib/ and "fix" the includes so they do not pull in other kernel
  29  * headers.
  30  */
  31 
  32 #ifdef CONFIG_KERNEL_GZIP
  33 #       include "decompress_inflate.c"
  34 #endif
  35 
  36 #ifdef CONFIG_KERNEL_XZ
  37 #       include "xz_config.h"
  38 #       include "../../../lib/decompress_unxz.c"
  39 #endif
  40 
  41 /* globals for tracking the state of the decompression */
  42 static unsigned long decompressed_bytes;
  43 static unsigned long limit;
  44 static unsigned long skip;
  45 static char *output_buffer;
  46 
  47 /*
  48  * flush() is called by __decompress() when the decompressor's scratch buffer is
  49  * full.
  50  */
  51 static long flush(void *v, unsigned long buffer_size)
  52 {
  53         unsigned long end = decompressed_bytes + buffer_size;
  54         unsigned long size = buffer_size;
  55         unsigned long offset = 0;
  56         char *in = v;
  57         char *out;
  58 
  59         /*
  60          * if we hit our decompression limit, we need to fake an error to abort
  61          * the in-progress decompression.
  62          */
  63         if (decompressed_bytes >= limit)
  64                 return -1;
  65 
  66         /* skip this entire block */
  67         if (end <= skip) {
  68                 decompressed_bytes += buffer_size;
  69                 return buffer_size;
  70         }
  71 
  72         /* skip some data at the start, but keep the rest of the block */
  73         if (decompressed_bytes < skip && end > skip) {
  74                 offset = skip - decompressed_bytes;
  75 
  76                 in += offset;
  77                 size -= offset;
  78                 decompressed_bytes += offset;
  79         }
  80 
  81         out = &output_buffer[decompressed_bytes - skip];
  82         size = min(decompressed_bytes + size, limit) - decompressed_bytes;
  83 
  84         memcpy(out, in, size);
  85         decompressed_bytes += size;
  86 
  87         return buffer_size;
  88 }
  89 
  90 static void print_err(char *s)
  91 {
  92         /* suppress the "error" when we terminate the decompressor */
  93         if (decompressed_bytes >= limit)
  94                 return;
  95 
  96         printf("Decompression error: '%s'\n\r", s);
  97 }
  98 
  99 /**
 100  * partial_decompress - decompresses part or all of a compressed buffer
 101  * @inbuf:       input buffer
 102  * @input_size:  length of the input buffer
 103  * @outbuf:      input buffer
 104  * @output_size: length of the input buffer
 105  * @skip         number of output bytes to ignore
 106  *
 107  * This function takes compressed data from inbuf, decompresses and write it to
 108  * outbuf. Once output_size bytes are written to the output buffer, or the
 109  * stream is exhausted the function will return the number of bytes that were
 110  * decompressed. Otherwise it will return whatever error code the decompressor
 111  * reported (NB: This is specific to each decompressor type).
 112  *
 113  * The skip functionality is mainly there so the program and discover
 114  * the size of the compressed image so that it can ask firmware (if present)
 115  * for an appropriately sized buffer.
 116  */
 117 long partial_decompress(void *inbuf, unsigned long input_size,
 118         void *outbuf, unsigned long output_size, unsigned long _skip)
 119 {
 120         int ret;
 121 
 122         /*
 123          * The skipped bytes needs to be included in the size of data we want
 124          * to decompress.
 125          */
 126         output_size += _skip;
 127 
 128         decompressed_bytes = 0;
 129         output_buffer = outbuf;
 130         limit = output_size;
 131         skip = _skip;
 132 
 133         ret = __decompress(inbuf, input_size, NULL, flush, outbuf,
 134                 output_size, NULL, print_err);
 135 
 136         /*
 137          * If decompression was aborted due to an actual error rather than
 138          * a fake error that we used to abort, then we should report it.
 139          */
 140         if (decompressed_bytes < limit)
 141                 return ret;
 142 
 143         return decompressed_bytes - skip;
 144 }

/* [<][>][^][v][top][bottom][index][help] */