Path: blob/master/arch/s390/boot/compressed/misc.c
15125 views
/*1* Definitions and wrapper functions for kernel decompressor2*3* Copyright IBM Corp. 20104*5* Author(s): Martin Schwidefsky <[email protected]>6*/78#include <asm/uaccess.h>9#include <asm/page.h>10#include <asm/ipl.h>11#include "sizes.h"1213/*14* gzip declarations15*/16#define STATIC static1718#undef memset19#undef memcpy20#undef memmove21#define memmove memmove22#define memzero(s, n) memset((s), 0, (n))2324/* Symbols defined by linker scripts */25extern char input_data[];26extern int input_len;27extern char _text, _end;28extern char _bss, _ebss;2930static void error(char *m);3132static unsigned long free_mem_ptr;33static unsigned long free_mem_end_ptr;3435#ifdef CONFIG_HAVE_KERNEL_BZIP236#define HEAP_SIZE 0x40000037#else38#define HEAP_SIZE 0x1000039#endif4041#ifdef CONFIG_KERNEL_GZIP42#include "../../../../lib/decompress_inflate.c"43#endif4445#ifdef CONFIG_KERNEL_BZIP246#include "../../../../lib/decompress_bunzip2.c"47#endif4849#ifdef CONFIG_KERNEL_LZMA50#include "../../../../lib/decompress_unlzma.c"51#endif5253#ifdef CONFIG_KERNEL_LZO54#include "../../../../lib/decompress_unlzo.c"55#endif5657#ifdef CONFIG_KERNEL_XZ58#include "../../../../lib/decompress_unxz.c"59#endif6061extern _sclp_print_early(const char *);6263int puts(const char *s)64{65_sclp_print_early(s);66return 0;67}6869void *memset(void *s, int c, size_t n)70{71char *xs;7273if (c == 0)74return __builtin_memset(s, 0, n);7576xs = (char *) s;77if (n > 0)78do {79*xs++ = c;80} while (--n > 0);81return s;82}8384void *memcpy(void *__dest, __const void *__src, size_t __n)85{86return __builtin_memcpy(__dest, __src, __n);87}8889void *memmove(void *__dest, __const void *__src, size_t __n)90{91char *d;92const char *s;9394if (__dest <= __src)95return __builtin_memcpy(__dest, __src, __n);96d = __dest + __n;97s = __src + __n;98while (__n--)99*--d = *--s;100return __dest;101}102103static void error(char *x)104{105unsigned long long psw = 0x000a0000deadbeefULL;106107puts("\n\n");108puts(x);109puts("\n\n -- System halted");110111asm volatile("lpsw %0" : : "Q" (psw));112}113114/*115* Safe guard the ipl parameter block against a memory area that will be116* overwritten. The validity check for the ipl parameter block is complex117* (see cio_get_iplinfo and ipl_save_parameters) but if the pointer to118* the ipl parameter block intersects with the passed memory area we can119* safely assume that we can read from that memory. In that case just copy120* the memory to IPL_PARMBLOCK_ORIGIN even if there is no ipl parameter121* block.122*/123static void check_ipl_parmblock(void *start, unsigned long size)124{125void *src, *dst;126127src = (void *)(unsigned long) S390_lowcore.ipl_parmblock_ptr;128if (src + PAGE_SIZE <= start || src >= start + size)129return;130dst = (void *) IPL_PARMBLOCK_ORIGIN;131memmove(dst, src, PAGE_SIZE);132S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN;133}134135unsigned long decompress_kernel(void)136{137unsigned long output_addr;138unsigned char *output;139140output_addr = ((unsigned long) &_end + HEAP_SIZE + 4095UL) & -4096UL;141check_ipl_parmblock((void *) 0, output_addr + SZ__bss_start);142memset(&_bss, 0, &_ebss - &_bss);143free_mem_ptr = (unsigned long)&_end;144free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;145output = (unsigned char *) output_addr;146147#ifdef CONFIG_BLK_DEV_INITRD148/*149* Move the initrd right behind the end of the decompressed150* kernel image.151*/152if (INITRD_START && INITRD_SIZE &&153INITRD_START < (unsigned long) output + SZ__bss_start) {154check_ipl_parmblock(output + SZ__bss_start,155INITRD_START + INITRD_SIZE);156memmove(output + SZ__bss_start,157(void *) INITRD_START, INITRD_SIZE);158INITRD_START = (unsigned long) output + SZ__bss_start;159}160#endif161162puts("Uncompressing Linux... ");163decompress(input_data, input_len, NULL, NULL, output, NULL, error);164puts("Ok, booting the kernel.\n");165return (unsigned long) output;166}167168169170