18f75582aSVasily Gorbik // SPDX-License-Identifier: GPL-2.0 28f75582aSVasily Gorbik #include <linux/string.h> 315426ca4SVasily Gorbik #include <asm/setup.h> 47516fc11SVasily Gorbik #include <asm/sclp.h> 55abb9351SVasily Gorbik #include <asm/uv.h> 68f75582aSVasily Gorbik #include "compressed/decompressor.h" 78f75582aSVasily Gorbik #include "boot.h" 88f75582aSVasily Gorbik 9d1b52a43SVasily Gorbik extern char __boot_data_start[], __boot_data_end[]; 10bf9921a9SGerald Schaefer extern char __boot_data_preserved_start[], __boot_data_preserved_end[]; 11d1b52a43SVasily Gorbik 127516fc11SVasily Gorbik void error(char *x) 137516fc11SVasily Gorbik { 147516fc11SVasily Gorbik sclp_early_printk("\n\n"); 157516fc11SVasily Gorbik sclp_early_printk(x); 167516fc11SVasily Gorbik sclp_early_printk("\n\n -- System halted"); 177516fc11SVasily Gorbik 187516fc11SVasily Gorbik disabled_wait(0xdeadbeef); 197516fc11SVasily Gorbik } 207516fc11SVasily Gorbik 2115426ca4SVasily Gorbik #ifdef CONFIG_KERNEL_UNCOMPRESSED 2215426ca4SVasily Gorbik unsigned long mem_safe_offset(void) 2315426ca4SVasily Gorbik { 2415426ca4SVasily Gorbik return vmlinux.default_lma + vmlinux.image_size + vmlinux.bss_size; 2515426ca4SVasily Gorbik } 2615426ca4SVasily Gorbik #endif 2715426ca4SVasily Gorbik 289641b8ccSMartin Schwidefsky static void rescue_initrd(unsigned long addr) 2915426ca4SVasily Gorbik { 3015426ca4SVasily Gorbik if (!IS_ENABLED(CONFIG_BLK_DEV_INITRD)) 3115426ca4SVasily Gorbik return; 3215426ca4SVasily Gorbik if (!INITRD_START || !INITRD_SIZE) 3315426ca4SVasily Gorbik return; 349641b8ccSMartin Schwidefsky if (addr <= INITRD_START) 3515426ca4SVasily Gorbik return; 369641b8ccSMartin Schwidefsky memmove((void *)addr, (void *)INITRD_START, INITRD_SIZE); 379641b8ccSMartin Schwidefsky INITRD_START = addr; 3815426ca4SVasily Gorbik } 3915426ca4SVasily Gorbik 40d1b52a43SVasily Gorbik static void copy_bootdata(void) 41d1b52a43SVasily Gorbik { 42d1b52a43SVasily Gorbik if (__boot_data_end - __boot_data_start != vmlinux.bootdata_size) 43d1b52a43SVasily Gorbik error(".boot.data section size mismatch"); 44d1b52a43SVasily Gorbik memcpy((void *)vmlinux.bootdata_off, __boot_data_start, vmlinux.bootdata_size); 45bf9921a9SGerald Schaefer if (__boot_data_preserved_end - __boot_data_preserved_start != vmlinux.bootdata_preserved_size) 46bf9921a9SGerald Schaefer error(".boot.preserved.data section size mismatch"); 47bf9921a9SGerald Schaefer memcpy((void *)vmlinux.bootdata_preserved_off, __boot_data_preserved_start, vmlinux.bootdata_preserved_size); 48d1b52a43SVasily Gorbik } 49d1b52a43SVasily Gorbik 508f75582aSVasily Gorbik void startup_kernel(void) 518f75582aSVasily Gorbik { 529641b8ccSMartin Schwidefsky unsigned long safe_addr; 53369f91c3SVasily Gorbik void *img; 548f75582aSVasily Gorbik 5549698745SVasily Gorbik store_ipl_parmblock(); 569641b8ccSMartin Schwidefsky safe_addr = mem_safe_offset(); 579641b8ccSMartin Schwidefsky safe_addr = read_ipl_report(safe_addr); 589641b8ccSMartin Schwidefsky uv_query_info(); 599641b8ccSMartin Schwidefsky rescue_initrd(safe_addr); 609641b8ccSMartin Schwidefsky sclp_early_read_info(); 6149698745SVasily Gorbik setup_boot_command_line(); 62b5e80459SVasily Gorbik parse_boot_command_line(); 6349698745SVasily Gorbik setup_memory_end(); 646966d604SVasily Gorbik detect_memory(); 658f75582aSVasily Gorbik if (!IS_ENABLED(CONFIG_KERNEL_UNCOMPRESSED)) { 66369f91c3SVasily Gorbik img = decompress_kernel(); 67369f91c3SVasily Gorbik memmove((void *)vmlinux.default_lma, img, vmlinux.image_size); 688f75582aSVasily Gorbik } 69d1b52a43SVasily Gorbik copy_bootdata(); 70369f91c3SVasily Gorbik vmlinux.entry(); 718f75582aSVasily Gorbik } 72