0001
0002
0003
0004
0005
0006
0007
0008 #include "elf.h"
0009 #include "page.h"
0010 #include "string.h"
0011 #include "stdio.h"
0012 #include "ops.h"
0013 #include "reg.h"
0014 #include "types.h"
0015
0016
0017
0018
0019
0020
0021
0022 #define STATIC static
0023 #define INIT
0024
0025
0026
0027
0028
0029
0030
0031 #ifdef CONFIG_KERNEL_GZIP
0032 # include "decompress_inflate.c"
0033 #endif
0034
0035 #ifdef CONFIG_KERNEL_XZ
0036 # include "xz_config.h"
0037 # include "../../../lib/decompress_unxz.c"
0038 #endif
0039
0040
0041 static unsigned long decompressed_bytes;
0042 static unsigned long limit;
0043 static unsigned long skip;
0044 static char *output_buffer;
0045
0046
0047
0048
0049
0050 static long flush(void *v, unsigned long buffer_size)
0051 {
0052 unsigned long end = decompressed_bytes + buffer_size;
0053 unsigned long size = buffer_size;
0054 unsigned long offset = 0;
0055 char *in = v;
0056 char *out;
0057
0058
0059
0060
0061
0062 if (decompressed_bytes >= limit)
0063 return -1;
0064
0065
0066 if (end <= skip) {
0067 decompressed_bytes += buffer_size;
0068 return buffer_size;
0069 }
0070
0071
0072 if (decompressed_bytes < skip && end > skip) {
0073 offset = skip - decompressed_bytes;
0074
0075 in += offset;
0076 size -= offset;
0077 decompressed_bytes += offset;
0078 }
0079
0080 out = &output_buffer[decompressed_bytes - skip];
0081 size = min(decompressed_bytes + size, limit) - decompressed_bytes;
0082
0083 memcpy(out, in, size);
0084 decompressed_bytes += size;
0085
0086 return buffer_size;
0087 }
0088
0089 static void print_err(char *s)
0090 {
0091
0092 if (decompressed_bytes >= limit)
0093 return;
0094
0095 printf("Decompression error: '%s'\n\r", s);
0096 }
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116 long partial_decompress(void *inbuf, unsigned long input_size,
0117 void *outbuf, unsigned long output_size, unsigned long _skip)
0118 {
0119 int ret;
0120
0121
0122
0123
0124
0125 output_size += _skip;
0126
0127 decompressed_bytes = 0;
0128 output_buffer = outbuf;
0129 limit = output_size;
0130 skip = _skip;
0131
0132 ret = __decompress(inbuf, input_size, NULL, flush, outbuf,
0133 output_size, NULL, print_err);
0134
0135
0136
0137
0138
0139 if (decompressed_bytes < limit)
0140 return ret;
0141
0142 return decompressed_bytes - skip;
0143 }