diff options
Diffstat (limited to 'arch/s390/boot/compressed')
-rw-r--r-- | arch/s390/boot/compressed/.gitignore | 5 | ||||
-rw-r--r-- | arch/s390/boot/compressed/Makefile | 74 | ||||
-rw-r--r-- | arch/s390/boot/compressed/head.S | 52 | ||||
-rw-r--r-- | arch/s390/boot/compressed/misc.c | 116 | ||||
-rw-r--r-- | arch/s390/boot/compressed/vmlinux.lds.S | 65 | ||||
-rw-r--r-- | arch/s390/boot/compressed/vmlinux.scr.lds.S | 15 |
6 files changed, 327 insertions, 0 deletions
diff --git a/arch/s390/boot/compressed/.gitignore b/arch/s390/boot/compressed/.gitignore new file mode 100644 index 000000000..45aeb4f08 --- /dev/null +++ b/arch/s390/boot/compressed/.gitignore @@ -0,0 +1,5 @@ +sizes.h +vmlinux +vmlinux.lds +vmlinux.scr.lds +vmlinux.bin.full diff --git a/arch/s390/boot/compressed/Makefile b/arch/s390/boot/compressed/Makefile new file mode 100644 index 000000000..9b3d821e5 --- /dev/null +++ b/arch/s390/boot/compressed/Makefile @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# linux/arch/s390/boot/compressed/Makefile +# +# create a compressed vmlinux image from the original vmlinux +# + +KCOV_INSTRUMENT := n +GCOV_PROFILE := n +UBSAN_SANITIZE := n +KASAN_SANITIZE := n + +obj-y := $(if $(CONFIG_KERNEL_UNCOMPRESSED),,head.o misc.o) piggy.o +targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 +targets += vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.lz4 +targets += vmlinux.scr.lds $(obj-y) $(if $(CONFIG_KERNEL_UNCOMPRESSED),,sizes.h) + +KBUILD_AFLAGS := $(KBUILD_AFLAGS_DECOMPRESSOR) +KBUILD_CFLAGS := $(KBUILD_CFLAGS_DECOMPRESSOR) + +OBJECTS := $(addprefix $(obj)/,$(obj-y)) + +LDFLAGS_vmlinux := --oformat $(LD_BFD) -e startup -T +$(obj)/vmlinux: $(obj)/vmlinux.lds $(objtree)/arch/s390/boot/startup.a $(OBJECTS) FORCE + $(call if_changed,ld) + +# extract required uncompressed vmlinux symbols and adjust them to reflect offsets inside vmlinux.bin +sed-sizes := -e 's/^\([0-9a-fA-F]*\) . \(__bss_start\|_end\)$$/\#define SZ\2 (0x\1 - 0x100000)/p' + +quiet_cmd_sizes = GEN $@ + cmd_sizes = $(NM) $< | sed -n $(sed-sizes) > $@ + +$(obj)/sizes.h: vmlinux + $(call if_changed,sizes) + +AFLAGS_head.o += -I$(objtree)/$(obj) +$(obj)/head.o: $(obj)/sizes.h + +CFLAGS_misc.o += -I$(objtree)/$(obj) +$(obj)/misc.o: $(obj)/sizes.h + +OBJCOPYFLAGS_vmlinux.bin := -R .comment -S +$(obj)/vmlinux.bin: vmlinux + $(call if_changed,objcopy) + +vmlinux.bin.all-y := $(obj)/vmlinux.bin + +suffix-$(CONFIG_KERNEL_GZIP) := .gz +suffix-$(CONFIG_KERNEL_BZIP2) := .bz2 +suffix-$(CONFIG_KERNEL_LZ4) := .lz4 +suffix-$(CONFIG_KERNEL_LZMA) := .lzma +suffix-$(CONFIG_KERNEL_LZO) := .lzo +suffix-$(CONFIG_KERNEL_XZ) := .xz + +$(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) FORCE + $(call if_changed,gzip) +$(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) FORCE + $(call if_changed,bzip2) +$(obj)/vmlinux.bin.lz4: $(vmlinux.bin.all-y) FORCE + $(call if_changed,lz4) +$(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE + $(call if_changed,lzma) +$(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) FORCE + $(call if_changed,lzo) +$(obj)/vmlinux.bin.xz: $(vmlinux.bin.all-y) FORCE + $(call if_changed,xzkern) + +LDFLAGS_piggy.o := -r --format binary --oformat $(LD_BFD) -T +$(obj)/piggy.o: $(obj)/vmlinux.scr.lds $(obj)/vmlinux.bin$(suffix-y) + $(call if_changed,ld) + +chkbss := $(filter-out $(obj)/misc.o $(obj)/piggy.o,$(OBJECTS)) +chkbss-target := $(obj)/vmlinux.bin +include $(srctree)/arch/s390/scripts/Makefile.chkbss diff --git a/arch/s390/boot/compressed/head.S b/arch/s390/boot/compressed/head.S new file mode 100644 index 000000000..df8dbbc17 --- /dev/null +++ b/arch/s390/boot/compressed/head.S @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Startup glue code to uncompress the kernel + * + * Copyright IBM Corp. 2010 + * + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> + */ + +#include <linux/init.h> +#include <linux/linkage.h> +#include <asm/asm-offsets.h> +#include <asm/thread_info.h> +#include <asm/page.h> +#include "sizes.h" + +__HEAD +ENTRY(startup_decompressor) + basr %r13,0 # get base +.LPG1: + # setup stack + lg %r15,.Lstack-.LPG1(%r13) + aghi %r15,-160 + brasl %r14,decompress_kernel + # Set up registers for memory mover. We move the decompressed image to + # 0x100000, where startup_continue of the decompressed image is supposed + # to be. + lgr %r4,%r2 + lg %r2,.Loffset-.LPG1(%r13) + lg %r3,.Lmvsize-.LPG1(%r13) + lgr %r5,%r3 + # Move the memory mover someplace safe so it doesn't overwrite itself. + la %r1,0x200 + mvc 0(mover_end-mover,%r1),mover-.LPG1(%r13) + # When the memory mover is done we pass control to + # arch/s390/kernel/head64.S:startup_continue which lives at 0x100000 in + # the decompressed image. + lgr %r6,%r2 + br %r1 +mover: + mvcle %r2,%r4,0 + jo mover + br %r6 +mover_end: + + .align 8 +.Lstack: + .quad 0x8000 + (1<<(PAGE_SHIFT+THREAD_SIZE_ORDER)) +.Loffset: + .quad 0x100000 +.Lmvsize: + .quad SZ__bss_start diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c new file mode 100644 index 000000000..f66ad73c2 --- /dev/null +++ b/arch/s390/boot/compressed/misc.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Definitions and wrapper functions for kernel decompressor + * + * Copyright IBM Corp. 2010 + * + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> + */ + +#include <linux/uaccess.h> +#include <asm/page.h> +#include <asm/sclp.h> +#include <asm/ipl.h> +#include "sizes.h" + +/* + * gzip declarations + */ +#define STATIC static + +#undef memset +#undef memcpy +#undef memmove +#define memmove memmove +#define memzero(s, n) memset((s), 0, (n)) + +/* Symbols defined by linker scripts */ +extern char input_data[]; +extern int input_len; +extern char _end[]; +extern char _bss[], _ebss[]; + +static void error(char *m); + +static unsigned long free_mem_ptr; +static unsigned long free_mem_end_ptr; + +#ifdef CONFIG_HAVE_KERNEL_BZIP2 +#define HEAP_SIZE 0x400000 +#else +#define HEAP_SIZE 0x10000 +#endif + +#ifdef CONFIG_KERNEL_GZIP +#include "../../../../lib/decompress_inflate.c" +#endif + +#ifdef CONFIG_KERNEL_BZIP2 +#include "../../../../lib/decompress_bunzip2.c" +#endif + +#ifdef CONFIG_KERNEL_LZ4 +#include "../../../../lib/decompress_unlz4.c" +#endif + +#ifdef CONFIG_KERNEL_LZMA +#include "../../../../lib/decompress_unlzma.c" +#endif + +#ifdef CONFIG_KERNEL_LZO +#include "../../../../lib/decompress_unlzo.c" +#endif + +#ifdef CONFIG_KERNEL_XZ +#include "../../../../lib/decompress_unxz.c" +#endif + +static int puts(const char *s) +{ + sclp_early_printk(s); + return 0; +} + +static void error(char *x) +{ + unsigned long long psw = 0x000a0000deadbeefULL; + + puts("\n\n"); + puts(x); + puts("\n\n -- System halted"); + + asm volatile("lpsw %0" : : "Q" (psw)); +} + +unsigned long decompress_kernel(void) +{ + void *output, *kernel_end; + + output = (void *) ALIGN((unsigned long) _end + HEAP_SIZE, PAGE_SIZE); + kernel_end = output + SZ__bss_start; + +#ifdef CONFIG_BLK_DEV_INITRD + /* + * Move the initrd right behind the end of the decompressed + * kernel image. This also prevents initrd corruption caused by + * bss clearing since kernel_end will always be located behind the + * current bss section.. + */ + if (INITRD_START && INITRD_SIZE && kernel_end > (void *) INITRD_START) { + memmove(kernel_end, (void *) INITRD_START, INITRD_SIZE); + INITRD_START = (unsigned long) kernel_end; + } +#endif + + /* + * Clear bss section. free_mem_ptr and free_mem_end_ptr need to be + * initialized afterwards since they reside in bss. + */ + memset(_bss, 0, _ebss - _bss); + free_mem_ptr = (unsigned long) _end; + free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; + + __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error); + return (unsigned long) output; +} + diff --git a/arch/s390/boot/compressed/vmlinux.lds.S b/arch/s390/boot/compressed/vmlinux.lds.S new file mode 100644 index 000000000..b16ac8b3c --- /dev/null +++ b/arch/s390/boot/compressed/vmlinux.lds.S @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include <asm-generic/vmlinux.lds.h> + +OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") +OUTPUT_ARCH(s390:64-bit) + +ENTRY(startup) + +SECTIONS +{ + /* Be careful parts of head_64.S assume startup_32 is at + * address 0. + */ + . = 0; + .head.text : { + _head = . ; + HEAD_TEXT + _ehead = . ; + } + .text : { + _text = .; /* Text */ + *(.text) + *(.text.*) + _etext = . ; + } + .rodata : { + _rodata = . ; + *(.rodata) /* read-only data */ + *(EXCLUDE_FILE (*piggy.o) .rodata.compressed) + _erodata = . ; + } + .data : { + _data = . ; + *(.data) + *(.data.*) + _edata = . ; + } + startup_continue = 0x100000; +#ifdef CONFIG_KERNEL_UNCOMPRESSED + . = 0x100000; +#else + . = ALIGN(8); +#endif + .rodata.compressed : { + *(.rodata.compressed) + } + . = ALIGN(256); + .bss : { + _bss = . ; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(8); /* For convenience during zeroing */ + _ebss = .; + } + _end = .; + + /* Sections to be discarded */ + /DISCARD/ : { + *(.eh_frame) + *(__ex_table) + *(*__ksymtab*) + *(___kcrctab*) + } +} diff --git a/arch/s390/boot/compressed/vmlinux.scr.lds.S b/arch/s390/boot/compressed/vmlinux.scr.lds.S new file mode 100644 index 000000000..ff01d18c9 --- /dev/null +++ b/arch/s390/boot/compressed/vmlinux.scr.lds.S @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +SECTIONS +{ + .rodata.compressed : { +#ifndef CONFIG_KERNEL_UNCOMPRESSED + input_len = .; + LONG(input_data_end - input_data) input_data = .; +#endif + *(.data) +#ifndef CONFIG_KERNEL_UNCOMPRESSED + output_len = . - 4; + input_data_end = .; +#endif + } +} |