1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/string.h> 3 #include <asm/setup.h> 4 #include <asm/sclp.h> 5 #include "compressed/decompressor.h" 6 #include "boot.h" 7 8 extern char __boot_data_start[], __boot_data_end[]; 9 10 void error(char *x) 11 { 12 sclp_early_printk("\n\n"); 13 sclp_early_printk(x); 14 sclp_early_printk("\n\n -- System halted"); 15 16 disabled_wait(0xdeadbeef); 17 } 18 19 #ifdef CONFIG_KERNEL_UNCOMPRESSED 20 unsigned long mem_safe_offset(void) 21 { 22 return vmlinux.default_lma + vmlinux.image_size + vmlinux.bss_size; 23 } 24 #endif 25 26 static void rescue_initrd(void) 27 { 28 unsigned long min_initrd_addr; 29 30 if (!IS_ENABLED(CONFIG_BLK_DEV_INITRD)) 31 return; 32 if (!INITRD_START || !INITRD_SIZE) 33 return; 34 min_initrd_addr = mem_safe_offset(); 35 if (min_initrd_addr <= INITRD_START) 36 return; 37 memmove((void *)min_initrd_addr, (void *)INITRD_START, INITRD_SIZE); 38 INITRD_START = min_initrd_addr; 39 } 40 41 static void copy_bootdata(void) 42 { 43 if (__boot_data_end - __boot_data_start != vmlinux.bootdata_size) 44 error(".boot.data section size mismatch"); 45 memcpy((void *)vmlinux.bootdata_off, __boot_data_start, vmlinux.bootdata_size); 46 } 47 48 void startup_kernel(void) 49 { 50 void *img; 51 52 rescue_initrd(); 53 sclp_early_read_info(); 54 store_ipl_parmblock(); 55 setup_boot_command_line(); 56 setup_memory_end(); 57 detect_memory(); 58 if (!IS_ENABLED(CONFIG_KERNEL_UNCOMPRESSED)) { 59 img = decompress_kernel(); 60 memmove((void *)vmlinux.default_lma, img, vmlinux.image_size); 61 } 62 copy_bootdata(); 63 vmlinux.entry(); 64 } 65