1 /* 2 * misc.c 3 * 4 * This is a collection of several routines from gzip-1.0.3 5 * adapted for Linux. 6 * 7 * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 8 * puts by Nick Holloway 1993, better puts by Martin Mares 1995 9 * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 10 */ 11 12 /* 13 * we have to be careful, because no indirections are allowed here, and 14 * paravirt_ops is a kind of one. As it will only run in baremetal anyway, 15 * we just keep it from happening 16 */ 17 #undef CONFIG_PARAVIRT 18 #ifdef CONFIG_X86_32 19 #define _ASM_X86_DESC_H 1 20 #endif 21 22 #ifdef CONFIG_X86_64 23 #define _LINUX_STRING_H_ 1 24 #define __LINUX_BITMAP_H 1 25 #endif 26 27 #include <linux/linkage.h> 28 #include <linux/screen_info.h> 29 #include <linux/elf.h> 30 #include <linux/io.h> 31 #include <asm/page.h> 32 #include <asm/boot.h> 33 #include <asm/bootparam.h> 34 35 /* WARNING!! 36 * This code is compiled with -fPIC and it is relocated dynamically 37 * at run time, but no relocation processing is performed. 38 * This means that it is not safe to place pointers in static structures. 39 */ 40 41 /* 42 * Getting to provable safe in place decompression is hard. 43 * Worst case behaviours need to be analyzed. 44 * Background information: 45 * 46 * The file layout is: 47 * magic[2] 48 * method[1] 49 * flags[1] 50 * timestamp[4] 51 * extraflags[1] 52 * os[1] 53 * compressed data blocks[N] 54 * crc[4] orig_len[4] 55 * 56 * resulting in 18 bytes of non compressed data overhead. 57 * 58 * Files divided into blocks 59 * 1 bit (last block flag) 60 * 2 bits (block type) 61 * 62 * 1 block occurs every 32K -1 bytes or when there 50% compression 63 * has been achieved. The smallest block type encoding is always used. 64 * 65 * stored: 66 * 32 bits length in bytes. 67 * 68 * fixed: 69 * magic fixed tree. 70 * symbols. 71 * 72 * dynamic: 73 * dynamic tree encoding. 74 * symbols. 75 * 76 * 77 * The buffer for decompression in place is the length of the 78 * uncompressed data, plus a small amount extra to keep the algorithm safe. 79 * The compressed data is placed at the end of the buffer. The output 80 * pointer is placed at the start of the buffer and the input pointer 81 * is placed where the compressed data starts. Problems will occur 82 * when the output pointer overruns the input pointer. 83 * 84 * The output pointer can only overrun the input pointer if the input 85 * pointer is moving faster than the output pointer. A condition only 86 * triggered by data whose compressed form is larger than the uncompressed 87 * form. 88 * 89 * The worst case at the block level is a growth of the compressed data 90 * of 5 bytes per 32767 bytes. 91 * 92 * The worst case internal to a compressed block is very hard to figure. 93 * The worst case can at least be boundined by having one bit that represents 94 * 32764 bytes and then all of the rest of the bytes representing the very 95 * very last byte. 96 * 97 * All of which is enough to compute an amount of extra data that is required 98 * to be safe. To avoid problems at the block level allocating 5 extra bytes 99 * per 32767 bytes of data is sufficient. To avoind problems internal to a 100 * block adding an extra 32767 bytes (the worst case uncompressed block size) 101 * is sufficient, to ensure that in the worst case the decompressed data for 102 * block will stop the byte before the compressed data for a block begins. 103 * To avoid problems with the compressed data's meta information an extra 18 104 * bytes are needed. Leading to the formula: 105 * 106 * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size. 107 * 108 * Adding 8 bytes per 32K is a bit excessive but much easier to calculate. 109 * Adding 32768 instead of 32767 just makes for round numbers. 110 * Adding the decompressor_size is necessary as it musht live after all 111 * of the data as well. Last I measured the decompressor is about 14K. 112 * 10K of actual data and 4K of bss. 113 * 114 */ 115 116 /* 117 * gzip declarations 118 */ 119 #define STATIC static 120 121 #undef memset 122 #undef memcpy 123 #define memzero(s, n) memset((s), 0, (n)) 124 125 126 static void error(char *m); 127 128 /* 129 * This is set up by the setup-routine at boot-time 130 */ 131 static struct boot_params *real_mode; /* Pointer to real-mode data */ 132 static int quiet; 133 134 static void *memset(void *s, int c, unsigned n); 135 void *memcpy(void *dest, const void *src, unsigned n); 136 137 static void __putstr(int, const char *); 138 #define putstr(__x) __putstr(0, __x) 139 140 #ifdef CONFIG_X86_64 141 #define memptr long 142 #else 143 #define memptr unsigned 144 #endif 145 146 static memptr free_mem_ptr; 147 static memptr free_mem_end_ptr; 148 149 static char *vidmem; 150 static int vidport; 151 static int lines, cols; 152 153 #ifdef CONFIG_KERNEL_GZIP 154 #include "../../../../lib/decompress_inflate.c" 155 #endif 156 157 #ifdef CONFIG_KERNEL_BZIP2 158 #include "../../../../lib/decompress_bunzip2.c" 159 #endif 160 161 #ifdef CONFIG_KERNEL_LZMA 162 #include "../../../../lib/decompress_unlzma.c" 163 #endif 164 165 static void scroll(void) 166 { 167 int i; 168 169 memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2); 170 for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2) 171 vidmem[i] = ' '; 172 } 173 174 static void __putstr(int error, const char *s) 175 { 176 int x, y, pos; 177 char c; 178 179 #ifndef CONFIG_X86_VERBOSE_BOOTUP 180 if (!error) 181 return; 182 #endif 183 184 #ifdef CONFIG_X86_32 185 if (real_mode->screen_info.orig_video_mode == 0 && 186 lines == 0 && cols == 0) 187 return; 188 #endif 189 190 x = real_mode->screen_info.orig_x; 191 y = real_mode->screen_info.orig_y; 192 193 while ((c = *s++) != '\0') { 194 if (c == '\n') { 195 x = 0; 196 if (++y >= lines) { 197 scroll(); 198 y--; 199 } 200 } else { 201 vidmem[(x + cols * y) * 2] = c; 202 if (++x >= cols) { 203 x = 0; 204 if (++y >= lines) { 205 scroll(); 206 y--; 207 } 208 } 209 } 210 } 211 212 real_mode->screen_info.orig_x = x; 213 real_mode->screen_info.orig_y = y; 214 215 pos = (x + cols * y) * 2; /* Update cursor position */ 216 outb(14, vidport); 217 outb(0xff & (pos >> 9), vidport+1); 218 outb(15, vidport); 219 outb(0xff & (pos >> 1), vidport+1); 220 } 221 222 static void *memset(void *s, int c, unsigned n) 223 { 224 int i; 225 char *ss = s; 226 227 for (i = 0; i < n; i++) 228 ss[i] = c; 229 return s; 230 } 231 232 void *memcpy(void *dest, const void *src, unsigned n) 233 { 234 int i; 235 const char *s = src; 236 char *d = dest; 237 238 for (i = 0; i < n; i++) 239 d[i] = s[i]; 240 return dest; 241 } 242 243 244 static void error(char *x) 245 { 246 __putstr(1, "\n\n"); 247 __putstr(1, x); 248 __putstr(1, "\n\n -- System halted"); 249 250 while (1) 251 asm("hlt"); 252 } 253 254 static void parse_elf(void *output) 255 { 256 #ifdef CONFIG_X86_64 257 Elf64_Ehdr ehdr; 258 Elf64_Phdr *phdrs, *phdr; 259 #else 260 Elf32_Ehdr ehdr; 261 Elf32_Phdr *phdrs, *phdr; 262 #endif 263 void *dest; 264 int i; 265 266 memcpy(&ehdr, output, sizeof(ehdr)); 267 if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || 268 ehdr.e_ident[EI_MAG1] != ELFMAG1 || 269 ehdr.e_ident[EI_MAG2] != ELFMAG2 || 270 ehdr.e_ident[EI_MAG3] != ELFMAG3) { 271 error("Kernel is not a valid ELF file"); 272 return; 273 } 274 275 if (!quiet) 276 putstr("Parsing ELF... "); 277 278 phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum); 279 if (!phdrs) 280 error("Failed to allocate space for phdrs"); 281 282 memcpy(phdrs, output + ehdr.e_phoff, sizeof(*phdrs) * ehdr.e_phnum); 283 284 for (i = 0; i < ehdr.e_phnum; i++) { 285 phdr = &phdrs[i]; 286 287 switch (phdr->p_type) { 288 case PT_LOAD: 289 #ifdef CONFIG_RELOCATABLE 290 dest = output; 291 dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR); 292 #else 293 dest = (void *)(phdr->p_paddr); 294 #endif 295 memcpy(dest, 296 output + phdr->p_offset, 297 phdr->p_filesz); 298 break; 299 default: /* Ignore other PT_* */ break; 300 } 301 } 302 } 303 304 asmlinkage void decompress_kernel(void *rmode, memptr heap, 305 unsigned char *input_data, 306 unsigned long input_len, 307 unsigned char *output) 308 { 309 real_mode = rmode; 310 311 if (real_mode->hdr.loadflags & QUIET_FLAG) 312 quiet = 1; 313 314 if (real_mode->screen_info.orig_video_mode == 7) { 315 vidmem = (char *) 0xb0000; 316 vidport = 0x3b4; 317 } else { 318 vidmem = (char *) 0xb8000; 319 vidport = 0x3d4; 320 } 321 322 lines = real_mode->screen_info.orig_video_lines; 323 cols = real_mode->screen_info.orig_video_cols; 324 325 free_mem_ptr = heap; /* Heap */ 326 free_mem_end_ptr = heap + BOOT_HEAP_SIZE; 327 328 if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1)) 329 error("Destination address inappropriately aligned"); 330 #ifdef CONFIG_X86_64 331 if (heap > 0x3fffffffffffUL) 332 error("Destination address too large"); 333 #else 334 if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff)) 335 error("Destination address too large"); 336 #endif 337 #ifndef CONFIG_RELOCATABLE 338 if ((unsigned long)output != LOAD_PHYSICAL_ADDR) 339 error("Wrong destination address"); 340 #endif 341 342 if (!quiet) 343 putstr("\nDecompressing Linux... "); 344 decompress(input_data, input_len, NULL, NULL, output, NULL, error); 345 parse_elf(output); 346 if (!quiet) 347 putstr("done.\nBooting the kernel.\n"); 348 return; 349 } 350