WIP FPC-III support
[linux/fpc-iii.git] / arch / powerpc / boot / decompress.c
blob6098b879ac97b60b576c015038b631b5ca1cf7ac
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Wrapper around the kernel's pre-boot decompression library.
5 * Copyright (C) IBM Corporation 2016.
6 */
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"
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.
22 #define STATIC static
23 #define INIT
26 * The build process will copy the required zlib source files and headers
27 * out of lib/ and "fix" the includes so they do not pull in other kernel
28 * headers.
31 #ifdef CONFIG_KERNEL_GZIP
32 # include "decompress_inflate.c"
33 #endif
35 #ifdef CONFIG_KERNEL_XZ
36 # include "xz_config.h"
37 # include "../../../lib/decompress_unxz.c"
38 #endif
40 /* globals for tracking the state of the decompression */
41 static unsigned long decompressed_bytes;
42 static unsigned long limit;
43 static unsigned long skip;
44 static char *output_buffer;
47 * flush() is called by __decompress() when the decompressor's scratch buffer is
48 * full.
50 static long flush(void *v, unsigned long buffer_size)
52 unsigned long end = decompressed_bytes + buffer_size;
53 unsigned long size = buffer_size;
54 unsigned long offset = 0;
55 char *in = v;
56 char *out;
59 * if we hit our decompression limit, we need to fake an error to abort
60 * the in-progress decompression.
62 if (decompressed_bytes >= limit)
63 return -1;
65 /* skip this entire block */
66 if (end <= skip) {
67 decompressed_bytes += buffer_size;
68 return buffer_size;
71 /* skip some data at the start, but keep the rest of the block */
72 if (decompressed_bytes < skip && end > skip) {
73 offset = skip - decompressed_bytes;
75 in += offset;
76 size -= offset;
77 decompressed_bytes += offset;
80 out = &output_buffer[decompressed_bytes - skip];
81 size = min(decompressed_bytes + size, limit) - decompressed_bytes;
83 memcpy(out, in, size);
84 decompressed_bytes += size;
86 return buffer_size;
89 static void print_err(char *s)
91 /* suppress the "error" when we terminate the decompressor */
92 if (decompressed_bytes >= limit)
93 return;
95 printf("Decompression error: '%s'\n\r", s);
98 /**
99 * partial_decompress - decompresses part or all of a compressed buffer
100 * @inbuf: input buffer
101 * @input_size: length of the input buffer
102 * @outbuf: input buffer
103 * @output_size: length of the input buffer
104 * @skip number of output bytes to ignore
106 * This function takes compressed data from inbuf, decompresses and write it to
107 * outbuf. Once output_size bytes are written to the output buffer, or the
108 * stream is exhausted the function will return the number of bytes that were
109 * decompressed. Otherwise it will return whatever error code the decompressor
110 * reported (NB: This is specific to each decompressor type).
112 * The skip functionality is mainly there so the program and discover
113 * the size of the compressed image so that it can ask firmware (if present)
114 * for an appropriately sized buffer.
116 long partial_decompress(void *inbuf, unsigned long input_size,
117 void *outbuf, unsigned long output_size, unsigned long _skip)
119 int ret;
122 * The skipped bytes needs to be included in the size of data we want
123 * to decompress.
125 output_size += _skip;
127 decompressed_bytes = 0;
128 output_buffer = outbuf;
129 limit = output_size;
130 skip = _skip;
132 ret = __decompress(inbuf, input_size, NULL, flush, outbuf,
133 output_size, NULL, print_err);
136 * If decompression was aborted due to an actual error rather than
137 * a fake error that we used to abort, then we should report it.
139 if (decompressed_bytes < limit)
140 return ret;
142 return decompressed_bytes - skip;