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