diff --git a/rust/Makefile b/rust/Makefile index df91ec7d..4233f570 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -40,7 +40,12 @@ endif #OPENSSL TEST_TARGETS := $(addsuffix _build,$(CARGO_TEST_TARGETS)) endif #CARGO -BUILD_TARGETS += $(PV_BUILD_TARGETS) +pvimg-bootloaders: + $(MAKE) -C pvimg/boot/ +.PHONY: pvimg-bootloaders + +BUILD_TARGETS += $(PV_BUILD_TARGETS) pvimg-bootloaders +INSTALL_TARGETS += pvimg-bootloaders # build release targets by default ifeq ("${D}","0") @@ -78,6 +83,7 @@ all: $(BUILD_TARGETS) install: $(INSTALL_TARGETS) $(INSTALL) -d -m 755 $(DESTDIR)$(USRBINDIR) $(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 pvattest/tools/pvextract-hdr $(DESTDIR)$(USRBINDIR) + $(MAKE) -C pvimg/boot install print-rust-targets: echo $(BUILD_TARGETS) @@ -86,6 +92,7 @@ clean: ifneq (${HAVE_CARGO},0) $(CARGO_CLEAN) ${ALL_CARGOFLAGS} endif # CARGO + $(MAKE) -C pvimg/boot/ clean $(RM) -- .check-dep-pvtools .detect-openssl.dep.c .check-cargo rust-test: $(CARGO_TEST_TARGETS) diff --git a/rust/pvimg/boot/.gitignore b/rust/pvimg/boot/.gitignore new file mode 100644 index 00000000..837684ed --- /dev/null +++ b/rust/pvimg/boot/.gitignore @@ -0,0 +1,4 @@ +*.elf +*.lds +*.bin +*.d diff --git a/rust/pvimg/boot/Makefile b/rust/pvimg/boot/Makefile new file mode 100644 index 00000000..88b858fd --- /dev/null +++ b/rust/pvimg/boot/Makefile @@ -0,0 +1,111 @@ +# Common definitions +include ../../../common.mak + +FILES := stage3a.bin stage3b.bin stage3b_reloc.bin +DEBUG_FILES := $(addsuffix .debug,$(FILES)) + +ifeq ($(HOST_ARCH),s390x) +ZIPL_DIR := $(rootdir)/zipl +ZIPL_BOOT_DIR := $(ZIPL_DIR)/boot +PKGDATADIR := $(TOOLS_DATADIR)/pvimg + +INCLUDE_PATHS := $(ZIPL_BOOT_DIR) $(ZIPL_DIR)/include $(rootdir)/include +INCLUDE_PARMS := $(addprefix -I,$(INCLUDE_PATHS)) + +ALL_CFLAGS := $(NO_PIE_CFLAGS) -Os -g \ + $(INCLUDE_PARMS) \ + -DENABLE_SCLP_ASCII=1 \ + -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \ + -fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \ + -fno-delete-null-pointer-checks -fno-stack-protector \ + -fexec-charset=IBM1047 -m64 -mpacked-stack \ + -mstack-size=4096 -mstack-guard=128 -msoft-float \ + -Wall -Wformat-security -Wextra \ + -Wno-array-bounds + +ZIPL_SRCS_C := libc.c ebcdic.c ebcdic_conv.c sclp.c +ZIPL_SRCS_ASM := entry.S + +ZIPL_OBJS_C := $(ZIPL_SRCS_C:%.c=%.o) +ZIPL_OBJS_ASM := $(ZIPL_SRCS_ASM:%.S=%.o) +ZIPL_OBJS := $(ZIPL_OBJS_C) $(ZIPL_OBJS_ASM) + +# Prevent make from using some default rules... +%: %.S + +%.o: %.S Makefile + $(CC) $(ALL_CFLAGS) -c -o $@ $< + +%.o: %.c Makefile + $(CC) $(ALL_CFLAGS) -c -o $@ $< + + +# Dependencies for the .lds generation +sources_lds_S = $(wildcard *.lds.S) +dependencies_lds_S = $(sources_lds_S:%.lds.S=.%.lds.d) +# Include all ".lds.d" dependency files for all make targets except for "clean" +ifneq ($(MAKECMDGOALS),clean) +-include $(dependencies_lds_S) +endif + +%.lds: %.lds.S Makefile + $(CPP) -Wp,-MD,.$@.d,-MT,$@ $(INCLUDE_PARMS) -P -C -o $@ $< + +# Special rules for zipl object files +$(ZIPL_OBJS_C): %.o : $(ZIPL_BOOT_DIR)/%.c + $(CC) $(ALL_CFLAGS) -c -o $@ $< + +$(ZIPL_OBJS_ASM): %.o : $(ZIPL_BOOT_DIR)/%.S + $(CC) $(ALL_CFLAGS) -c -o $@ $< + +dependencies_zipl_c := $(ZIPL_SRCS_C:%.c=.%.o.d) + +$(dependencies_zipl_c): .%.o.d : $(ZIPL_BOOT_DIR)/%.c + $(CC_SILENT) -MM $(ALL_CPPFLAGS) $(ALL_CFLAGS) $< > $@ + +ifneq ($(MAKECMDGOALS),clean) +-include $(dependencies_zipl_c) +endif + +stage3b_reloc.o: stage3b.bin + +stage3a.elf: head.o stage3a_init.o $(ZIPL_OBJS) +stage3b.elf: head.o $(ZIPL_OBJS) + +.SECONDARY: $(FILES:.bin=.lds) +%.elf: %.lds %.o + $(LINK) $(NO_PIE_LDFLAGS) $(NO_WARN_RWX_SEGMENTS_LDFLAGS) -Wl,-T,$< -Wl,--build-id=none -m64 -static -nostdlib $(filter %.o, $^) -o $@ + @chmod a-x $@ + +%.bin.debug: %.elf + $(OBJCOPY) --only-keep-debug $< $@ + @chmod a-x $@ + +%.bin: %.elf + $(OBJCOPY) -O binary $< $@ + @chmod a-x $@ + +install: stage3a.bin stage3b_reloc.bin + $(INSTALL) -d -m 755 $(DESTDIR)$(PKGDATADIR) + $(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3a.bin $(DESTDIR)$(PKGDATADIR) + $(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3b_reloc.bin $(DESTDIR)$(PKGDATADIR) + +else +# Don't generate the dependency files (see `common.mak` for the +# `-include $(dependencies_c)` statement). +.PHONY: $(dependencies_c) + +$(FILES) $(DEBUG_FILES): + echo " SKIP $@ due to HOST_ARCH != s390x" + +install: + echo " SKIP Bootloader installation due to HOST_ARCH != s390x" +endif + +.DEFAULT_GOAL := all +all: $(FILES) $(DEBUG_FILES) + +clean: + rm -f -- *.o *.elf *.bin *.map .*.d *.lds *.debug + +.PHONY: all clean diff --git a/rust/pvimg/boot/common_memory_layout.h b/rust/pvimg/boot/common_memory_layout.h new file mode 100644 index 00000000..a7f4d07b --- /dev/null +++ b/rust/pvimg/boot/common_memory_layout.h @@ -0,0 +1,24 @@ +/* + * Common memory layout for stage3a and stage3b bootloader. + * + * Copyright IBM Corp. 2020 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef COMMON_MEMORY_LAYOUT_H +#define COMMON_MEMORY_LAYOUT_H + +#include "boot/loaders_layout.h" + +#define STACK_ADDRESS STAGE3_STACK_ADDRESS +#define STACK_SIZE STAGE3_STACK_SIZE + +#define HEAP_ADDRESS STAGE3_HEAP_ADDRESS +#define HEAP_SIZE STAGE3_HEAP_SIZE + +#ifndef __ASSEMBLER__ + +#endif /* __ASSEMBLER__ */ +#endif /* COMMON_MEMORY_LAYOUT_H */ diff --git a/rust/pvimg/boot/head.S b/rust/pvimg/boot/head.S new file mode 100644 index 00000000..2a459487 --- /dev/null +++ b/rust/pvimg/boot/head.S @@ -0,0 +1,36 @@ +/* + * Entry code for stage 3a and stage 3b boot loader + * + * Copyright IBM Corp. 2020 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + + +#include "common_memory_layout.h" + +#include "boot/s390.h" +#include "boot/sigp.h" + +.section .text.start +.globl _start +_start: + /* Might be called after a diag308 so better set + * architecture and addressing mode + */ + lhi %r1, 1 + sigp %r1, %r0, SIGP_SET_ARCHITECTURE + sam64 + + /* Initialize stack */ + basr %r13, 0 +.Lbase: llgf %r15, .Lstack - .Lbase(%r13) + brasl %r14, initialize +.Lstack: .long STACK_ADDRESS + STACK_SIZE - STACK_FRAME_OVERHEAD +.previous + +/* The code doesn't require an executable stack */ +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/rust/pvimg/boot/stage3a.c b/rust/pvimg/boot/stage3a.c new file mode 100644 index 00000000..6f25219f --- /dev/null +++ b/rust/pvimg/boot/stage3a.c @@ -0,0 +1,60 @@ +/* + * Main program for stage3a bootloader + * + * Copyright IBM Corp. 2020 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "libc.h" +#include "stage3a.h" + +#include "lib/zt_common.h" +#include "boot/error.h" +#include "boot/s390.h" +#include "boot/ipl.h" +#include "sclp.h" + +static volatile struct stage3a_args __section(".loader_parms") loader_parms; + +void __noreturn start(void) +{ + int rc; + volatile struct stage3a_args *args = &loader_parms; + /* calculate the IPIB memory address */ + struct ipl_parameter_block *ipib = (void *)((uint64_t)args + args->ipib_offs); + + /* Calculate the PV header memory address and set it and its + * size in the IPIB. This allows the PV header to be position + * independent. + */ + ipib->pv.pv_hdr_addr = (uint64_t)args + args->hdr_offs; + ipib->pv.pv_hdr_size = args->hdr_size; + + /* set up ASCII and line-mode */ + sclp_setup(SCLP_LINE_ASCII_INIT); + + /* test if Secure Execution Unpack facility is available */ + stfle(S390_lowcore.stfle_fac_list, ARRAY_SIZE(S390_lowcore.stfle_fac_list)); + rc = test_facility(UNPACK_FACILITY); + if (rc == 0) + panic(ENOPV, "Secure unpack facility is not available\n"); + + rc = diag308(DIAG308_SET_PV, ipib); + if (rc != DIAG308_RC_OK) + panic(EPV, "Protected boot setup has failed: 0x%x\n", rc); + + rc = diag308(DIAG308_UNPACK_PV, 0x0); + if (rc != DIAG308_RC_OK) { + sclp_setup(SCLP_LINE_ASCII_INIT); + panic(EPV, "Protected boot has failed: 0x%x\n", rc); + } + + while (1) + ; +} + +void panic_notify(unsigned long UNUSED(rc)) +{ +} diff --git a/rust/pvimg/boot/stage3a.h b/rust/pvimg/boot/stage3a.h new file mode 100644 index 00000000..538c876d --- /dev/null +++ b/rust/pvimg/boot/stage3a.h @@ -0,0 +1,33 @@ +/* + * Main program for stage3a bootloader. + * + * Copyright IBM Corp. 2020 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef STAGE3A_H +#define STAGE3A_H + +#include "lib/zt_common.h" +#include "boot/loaders_layout.h" + +#define STAGE3A_INIT_ENTRY IMAGE_ENTRY +#define STAGE3A_ENTRY (STAGE3A_INIT_ENTRY + _AC(0x1000, UL)) +#define STAGE3A_LOAD_ADDRESS IMAGE_LOAD_ADDRESS + +#ifndef __ASSEMBLER__ + +#include + +/* Must not have any padding */ +struct stage3a_args { + uint64_t hdr_offs; + uint64_t hdr_size; + uint64_t ipib_offs; +}; +STATIC_ASSERT(sizeof(struct stage3a_args) == 3 * 8) + +#endif /* __ASSEMBLER__ */ +#endif /* STAGE3A_H */ diff --git a/rust/pvimg/boot/stage3a.lds.S b/rust/pvimg/boot/stage3a.lds.S new file mode 100644 index 00000000..cc50948d --- /dev/null +++ b/rust/pvimg/boot/stage3a.lds.S @@ -0,0 +1,98 @@ +/* + * Memory layout for stage 3a + * ========================== + * + * General memory layout + * --------------------- + * + * 0x00000 - 0x01fff Lowcore + * 0x02000 - 0x05fff Memory allocation (heap) + * 0x0f000 - 0x0ffff Stack + * 0x10000 - 0x10012 Jump to the "actual" stage3a code + * 0x11000 - 0x12fff Stage3a code + arguments (offsets and lengths to the + * actual data: IPIB and UV header) + */ + +#include "stage3a.h" +#include "common_memory_layout.h" + +OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") +OUTPUT_ARCH(s390:64-bit) + +ENTRY(_init) + +SECTIONS +{ + . = HEAP_ADDRESS; + __heap_start = .; + .heap : { + . = . + HEAP_SIZE; + ASSERT(__heap_stop - __heap_start == HEAP_SIZE, + "Heap section doesn't conform to the described memory layout"); + } + __heap_stop = .; + + . = STACK_ADDRESS; + __stack_start = .; + .stack : { + . = . + STACK_SIZE; + ASSERT(__stack_end - __stack_start == STACK_SIZE, + "Stack section doesn't conform to the described memory layout"); + } + __stack_end = .; + + . = STAGE3A_INIT_ENTRY; + __text_init_start = .; + .text : { + *(.text.init) + __text_init_stop = ABSOLUTE(.); + /* Text size of text_init must be smaller than 'PARMAREA - IMAGE_ENTRY', + * otherwise the text data could be overwritten by the original zipl stage3 + * boot loader */ + ASSERT(__text_init_stop - __text_init_start < PARMAREA - IMAGE_ENTRY, + "Text size must be smaller than 'PARMAREA - IMAGE_ENTRY'"); + . = 0x1000; + ASSERT(ABSOLUTE(.) == STAGE3A_ENTRY, + "Text section doesn't conform to the described memory layout"); + *(.text.start) + *(.text .text.*) + } + + .ex_table ALIGN(16) : { + __ex_table_start = .; + *(.ex_table) + __ex_table_stop = .; + } + + .bss ALIGN(16) : { + __bss_start = .; + *(.bss) + __bss_stop = .; + } + + .rodata ALIGN(16) : { + *(.rodata) + *(.rodata*) + } + + .data ALIGN(16) : { + *(.data) + . = ALIGN(16); + /* The IPIB offset and the UV header offset and size will be + * saved in 'loader_parms' */ + __loader_parms_start = .; + KEEP(*(.loader_parms)); + __loader_parms_stop = .; + ASSERT(__loader_parms_stop - __loader_parms_start == 3 * 8, + "Data size must be equal to 'sizeof(struct stage3a_args)'"); + ASSERT(ABSOLUTE(.) < 0x13000, "Data section doesn't conform to the described memory layout"); + } + + /* Sections to be discarded */ + /DISCARD/ : { + *(.eh_frame) + *(.interp) + *(.note.GNU-stack) + *(.note.package) + } +} diff --git a/rust/pvimg/boot/stage3a_init.S b/rust/pvimg/boot/stage3a_init.S new file mode 100644 index 00000000..de5ebcf1 --- /dev/null +++ b/rust/pvimg/boot/stage3a_init.S @@ -0,0 +1,33 @@ +/* + * Entry code for stage 3a boot loader + * + * Copyright IBM Corp. 2020 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "stage3a.h" +#include "boot/sigp.h" + +.section .text.init +.globl _init +_init: + /* set architecture and switch to 64bit */ + lhi %r1, 1 + sigp %r1, %r0, SIGP_SET_ARCHITECTURE + sam64 + /* The original stage3 boot loader will try to store the + * kernel command line and the address and size of the + * ramdisk. Simply ignore this by starting at 0x11000. + */ + basr %r13, 0 +.Lbase: llgf %r1, .Lstage3a_entry - .Lbase(%r13) + br %r1 +.Lstage3a_entry: .long STAGE3A_ENTRY +.previous + +/* The code doesn't require an executable stack */ +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/rust/pvimg/boot/stage3b.c b/rust/pvimg/boot/stage3b.c new file mode 100644 index 00000000..611c88ff --- /dev/null +++ b/rust/pvimg/boot/stage3b.c @@ -0,0 +1,90 @@ +/* + * Main program for stage3b bootloader + * + * Copyright IBM Corp. 2020 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "libc.h" +#include "stage3b.h" + +#include "lib/zt_common.h" +#include "boot/psw.h" +#include "boot/error.h" +#include "boot/s390.h" +#include "boot/linux_layout.h" +#include "boot/loaders_layout.h" +#include "sclp.h" + +static volatile struct stage3b_args __section(".loader_parms") loader_parms; + +static inline void __noreturn load_psw(struct psw_t psw) +{ + asm volatile("lpswe %0" : : "Q"(psw) : "cc"); + + while (1) + ; +} + +static unsigned long get_kernel_cmdline_size(void) +{ + unsigned long size = *(volatile unsigned long *)MAX_COMMAND_LINE_SIZE; + + if (size != 0) + return size; + + return LEGACY_COMMAND_LINE_SIZE; +} + +void __noreturn start(void) +{ + volatile struct stage3b_args *args = &loader_parms; + volatile struct memblob *kernel = &args->kernel; + volatile struct memblob *cmdline = &args->cmdline; + volatile struct memblob *initrd = &args->initrd; + struct psw_t psw = args->psw; + + /* set up ASCII and line-mode */ + sclp_setup(SCLP_LINE_ASCII_INIT); + + if (kernel->size < IMAGE_LOAD_ADDRESS) + panic(EINTERNAL, "Invalid kernel\n"); + + /* move the kernel and cut the kernel header */ + memmove((void *)IMAGE_LOAD_ADDRESS, (void *)(kernel->src + IMAGE_LOAD_ADDRESS), + kernel->size - IMAGE_LOAD_ADDRESS); + + if (cmdline->size > get_kernel_cmdline_size()) + panic(EINTERNAL, "Command line is too large\n"); + + if (cmdline->size > 0) { + /* make sure the cmdline is a null-terminated string */ + if (((char *)cmdline->src)[cmdline->size - 1] != '\0') + panic(EINTERNAL, "Command line needs to be null-terminated\n"); + + /* move the kernel cmdline */ + memmove((void *)COMMAND_LINE, (void *)cmdline->src, cmdline->size); + } + /* the initrd does not need to be moved */ + + if (initrd->size > 0) { + /* copy initrd start address and size into new kernel space */ + *(unsigned long long *)INITRD_START = initrd->src; + *(unsigned long long *)INITRD_SIZE = initrd->size; + } + + /* disable ASCII and line-mode */ + sclp_setup(SCLP_DISABLE); + + /* use lpswe instead of diag308 as a I/O subsystem reset is not + * needed as this was already done by the diag308 subcode 10 call + * in stage3a + */ + load_psw(psw); +} + +void panic_notify(unsigned long UNUSED(rc)) +{ +} diff --git a/rust/pvimg/boot/stage3b.h b/rust/pvimg/boot/stage3b.h new file mode 100644 index 00000000..41bb19f3 --- /dev/null +++ b/rust/pvimg/boot/stage3b.h @@ -0,0 +1,41 @@ +/* + * Main program for stage3b bootloader + * + * Copyright IBM Corp. 2020 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef STAGE3B_H +#define STAGE3B_H + +#include "lib/zt_common.h" +#include "boot/loaders_layout.h" + +#define STAGE3B_ENTRY STAGE3_ENTRY +#define STAGE3B_LOAD_ADDRESS STAGE3B_ENTRY + +#ifndef __ASSEMBLER__ + +#include + +#include "boot/psw.h" + +/* Must not have any padding included */ +struct memblob { + uint64_t src; + uint64_t size; +}; +STATIC_ASSERT(sizeof(struct memblob) == 2 * 8) + +/* Must not have any padding included */ +struct stage3b_args { + struct memblob kernel; + struct memblob cmdline; + struct memblob initrd; + struct psw_t psw; +}; +STATIC_ASSERT(sizeof(struct stage3b_args) == 3 * sizeof(struct memblob) + 16) +#endif /* __ASSEMBLER__ */ +#endif /* STAGE3B_H */ diff --git a/rust/pvimg/boot/stage3b.lds.S b/rust/pvimg/boot/stage3b.lds.S new file mode 100644 index 00000000..e0eb10a3 --- /dev/null +++ b/rust/pvimg/boot/stage3b.lds.S @@ -0,0 +1,84 @@ +/* + * Memory layout for stage 3b + * ========================== + * + * General memory layout + * --------------------- + * + * 0x00000 - 0x01fff Lowcore + * 0x02000 - 0x05fff Memory allocation (heap) + * 0x0a000 - 0x0efff Stage3b code + * 0x0f000 - 0x0ffff Stack + */ + +#include "stage3b.h" +#include "common_memory_layout.h" + +OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") +OUTPUT_ARCH(s390:64-bit) + +ENTRY(_start) + +SECTIONS +{ + . = HEAP_ADDRESS; + __heap_start = .; + .heap : { + . = . + HEAP_SIZE; + ASSERT(__heap_stop - __heap_start == HEAP_SIZE, + "Heap section doesn't conform to the described memory layout"); + } + __heap_stop = .; + + . = STAGE3B_ENTRY; + .text : { + *(.text.start) + *(.text .text.*) + } + + .ex_table ALIGN(16) : { + __ex_table_start = .; + *(.ex_table) + __ex_table_stop = .; + } + + .bss ALIGN(16) : { + __bss_start = .; + *(.bss) + __bss_stop = .; + } + + .rodata ALIGN(16) : { + *(.rodata) + *(.rodata*) + } + + .data ALIGN(16) : { + *(.data) + . = ALIGN(16); + __loader_parms_start = .; + KEEP(*(.loader_parms)); + __loader_parms_end = .; + ASSERT(__loader_parms_end - __loader_parms_start == 3 * 16 + 16, + "Data size must be equal to 'sizeof(struct stage3b_args)'"); + } + + . = STACK_ADDRESS; + __stack_start = .; + .stack : { + . = . + STACK_SIZE; + ASSERT(__stack_end - __stack_start == STACK_SIZE, + "Stack section doesn't conform to the described memory layout"); + } + __stack_end = .; + + ASSERT(. <= IMAGE_ENTRY, "stage3b size must be smaller than 0x10000 bytes") + + /* Sections to be discarded */ + /DISCARD/ : { + *(.eh_frame) + *(.interp) + *(.note.GNU-stack) + *(.note.package) + } +} diff --git a/rust/pvimg/boot/stage3b_reloc.S b/rust/pvimg/boot/stage3b_reloc.S new file mode 100644 index 00000000..1fe5d943 --- /dev/null +++ b/rust/pvimg/boot/stage3b_reloc.S @@ -0,0 +1,60 @@ +/* + * Relocator code for stage 3b boot loader + * + * Copyright IBM Corp. 2020 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "stage3b.h" +#include "boot/sigp.h" + +.macro MEMCPY dst,src,len + lgr %r0, \dst + lgr %r1, \len + lgr %r2, \src + lgr %r3, \len + +20: mvcle %r0, %r2, 0 + jo 20b +.endm + +.org 0x0 +.section .text.start +.globl _start +_start: + /* Might be called after a diag308 so better set + * architecture and addressing mode + */ + lhi %r1, 1 + sigp %r1, %r0, SIGP_SET_ARCHITECTURE + sam64 + + /* Location of stage3b in memory */ + larl %r8, stage3b_start + + /* Destination for stage3b */ + basr %r13, 0 +.Lbase: llgf %r9, .Lstage3b_load_address - .Lbase(%r13) + + /* Size of stage3b */ + lghi %r11, stage3b_end - stage3b_start + + /* Copy the stage3b loader to address STAGE3B_LOAD_ADDRESS */ + MEMCPY %r9, %r8, %r11 + + /* Branch to STAGE3B_ENTRY */ + llgf %r9, .Lstage3b_entry - .Lbase(%r13) + br %r9 +.Lstage3b_load_address: .long STAGE3B_LOAD_ADDRESS +.Lstage3b_entry: .long STAGE3B_ENTRY +stage3b_start: + .incbin "stage3b.bin" +stage3b_end: +.previous + +/* The code doesn't require an executable stack */ +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/rust/pvimg/boot/stage3b_reloc.lds.S b/rust/pvimg/boot/stage3b_reloc.lds.S new file mode 100644 index 00000000..52b7471a --- /dev/null +++ b/rust/pvimg/boot/stage3b_reloc.lds.S @@ -0,0 +1,20 @@ +OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") +OUTPUT_ARCH(s390:64-bit) + +ENTRY(_start) + +SECTIONS +{ + .text : { + *(.text.start) + *(.text .text.*) + } + + /* Sections to be discarded */ + /DISCARD/ : { + *(.eh_frame) + *(.interp) + *(.note.GNU-stack) + *(.note.package) + } +}