Merge tag 'timers-urgent-2021-08-08' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / arch / powerpc / boot / decompress.c
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
25 /*
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.
29  */
30
31 #ifdef CONFIG_KERNEL_GZIP
32 #       include "decompress_inflate.c"
33 #endif
34
35 #ifdef CONFIG_KERNEL_XZ
36 #       include "xz_config.h"
37 #       include "../../../lib/decompress_unxz.c"
38 #endif
39
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;
45
46 /*
47  * flush() is called by __decompress() when the decompressor's scratch buffer is
48  * full.
49  */
50 static long flush(void *v, unsigned long buffer_size)
51 {
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;
57
58         /*
59          * if we hit our decompression limit, we need to fake an error to abort
60          * the in-progress decompression.
61          */
62         if (decompressed_bytes >= limit)
63                 return -1;
64
65         /* skip this entire block */
66         if (end <= skip) {
67                 decompressed_bytes += buffer_size;
68                 return buffer_size;
69         }
70
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;
74
75                 in += offset;
76                 size -= offset;
77                 decompressed_bytes += offset;
78         }
79
80         out = &output_buffer[decompressed_bytes - skip];
81         size = min(decompressed_bytes + size, limit) - decompressed_bytes;
82
83         memcpy(out, in, size);
84         decompressed_bytes += size;
85
86         return buffer_size;
87 }
88
89 static void print_err(char *s)
90 {
91         /* suppress the "error" when we terminate the decompressor */
92         if (decompressed_bytes >= limit)
93                 return;
94
95         printf("Decompression error: '%s'\n\r", s);
96 }
97
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:      output buffer
103  * @output_size: length of the output buffer
104  * @skip         number of output bytes to ignore
105  *
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).
111  *
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.
115  */
116 long partial_decompress(void *inbuf, unsigned long input_size,
117         void *outbuf, unsigned long output_size, unsigned long _skip)
118 {
119         int ret;
120
121         /*
122          * The skipped bytes needs to be included in the size of data we want
123          * to decompress.
124          */
125         output_size += _skip;
126
127         decompressed_bytes = 0;
128         output_buffer = outbuf;
129         limit = output_size;
130         skip = _skip;
131
132         ret = __decompress(inbuf, input_size, NULL, flush, outbuf,
133                 output_size, NULL, print_err);
134
135         /*
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.
138          */
139         if (decompressed_bytes < limit)
140                 return ret;
141
142         return decompressed_bytes - skip;
143 }