1724dc336SVasily Gorbik // SPDX-License-Identifier: GPL-2.0 2724dc336SVasily Gorbik #include <linux/kernel.h> 3724dc336SVasily Gorbik #include <linux/string.h> 4*9a78c70aSVasily Gorbik #include <linux/ctype.h> 5724dc336SVasily Gorbik #include <asm/lowcore.h> 63ca8b855SVasily Gorbik #include <asm/setup.h> 7724dc336SVasily Gorbik #include <asm/sclp.h> 8*9a78c70aSVasily Gorbik #include <stdarg.h> 9724dc336SVasily Gorbik #include "boot.h" 10724dc336SVasily Gorbik 11724dc336SVasily Gorbik const char hex_asc[] = "0123456789abcdef"; 12724dc336SVasily Gorbik 13*9a78c70aSVasily Gorbik static char *as_hex(char *dst, unsigned long val, int pad) 14724dc336SVasily Gorbik { 15*9a78c70aSVasily Gorbik char *p, *end = p = dst + max(pad, (int)__fls(val | 1) / 4 + 1); 16*9a78c70aSVasily Gorbik 17*9a78c70aSVasily Gorbik for (*p-- = 0; p >= dst; val >>= 4) 18*9a78c70aSVasily Gorbik *p-- = hex_asc[val & 0x0f]; 19*9a78c70aSVasily Gorbik return end; 20724dc336SVasily Gorbik } 21724dc336SVasily Gorbik 22*9a78c70aSVasily Gorbik void decompressor_printk(const char *fmt, ...) 23724dc336SVasily Gorbik { 24*9a78c70aSVasily Gorbik char buf[1024] = { 0 }; 25*9a78c70aSVasily Gorbik char *end = buf + sizeof(buf) - 1; /* make sure buf is 0 terminated */ 26*9a78c70aSVasily Gorbik unsigned long pad; 27*9a78c70aSVasily Gorbik char *p = buf; 28*9a78c70aSVasily Gorbik va_list args; 29*9a78c70aSVasily Gorbik 30*9a78c70aSVasily Gorbik va_start(args, fmt); 31*9a78c70aSVasily Gorbik for (; p < end && *fmt; fmt++) { 32*9a78c70aSVasily Gorbik if (*fmt != '%') { 33*9a78c70aSVasily Gorbik *p++ = *fmt; 34*9a78c70aSVasily Gorbik continue; 35*9a78c70aSVasily Gorbik } 36*9a78c70aSVasily Gorbik pad = isdigit(*++fmt) ? simple_strtol(fmt, (char **)&fmt, 10) : 0; 37*9a78c70aSVasily Gorbik switch (*fmt) { 38*9a78c70aSVasily Gorbik case 's': 39*9a78c70aSVasily Gorbik p = buf + strlcat(buf, va_arg(args, char *), sizeof(buf)); 40*9a78c70aSVasily Gorbik break; 41*9a78c70aSVasily Gorbik case 'l': 42*9a78c70aSVasily Gorbik if (*++fmt != 'x' || end - p <= max(sizeof(long) * 2, pad)) 43*9a78c70aSVasily Gorbik goto out; 44*9a78c70aSVasily Gorbik p = as_hex(p, va_arg(args, unsigned long), pad); 45*9a78c70aSVasily Gorbik break; 46*9a78c70aSVasily Gorbik case 'x': 47*9a78c70aSVasily Gorbik if (end - p <= max(sizeof(int) * 2, pad)) 48*9a78c70aSVasily Gorbik goto out; 49*9a78c70aSVasily Gorbik p = as_hex(p, va_arg(args, unsigned int), pad); 50*9a78c70aSVasily Gorbik break; 51*9a78c70aSVasily Gorbik default: 52*9a78c70aSVasily Gorbik goto out; 53*9a78c70aSVasily Gorbik } 54*9a78c70aSVasily Gorbik } 55*9a78c70aSVasily Gorbik out: 56*9a78c70aSVasily Gorbik va_end(args); 57*9a78c70aSVasily Gorbik sclp_early_printk(buf); 58724dc336SVasily Gorbik } 59724dc336SVasily Gorbik 60724dc336SVasily Gorbik void print_pgm_check_info(void) 61724dc336SVasily Gorbik { 62*9a78c70aSVasily Gorbik unsigned long *gpregs = (unsigned long *)S390_lowcore.gpregs_save_area; 63724dc336SVasily Gorbik struct psw_bits *psw = &psw_bits(S390_lowcore.psw_save_area); 64724dc336SVasily Gorbik 65*9a78c70aSVasily Gorbik decompressor_printk("Linux version %s\n", kernel_version); 66*9a78c70aSVasily Gorbik decompressor_printk("Kernel fault: interruption code %04x ilc:%x\n", 67*9a78c70aSVasily Gorbik S390_lowcore.pgm_code, S390_lowcore.pgm_ilc >> 1); 68*9a78c70aSVasily Gorbik if (kaslr_enabled) 69*9a78c70aSVasily Gorbik decompressor_printk("Kernel random base: %lx\n", __kaslr_offset); 70*9a78c70aSVasily Gorbik decompressor_printk("PSW : %016lx %016lx\n", 71*9a78c70aSVasily Gorbik S390_lowcore.psw_save_area.mask, 72*9a78c70aSVasily Gorbik S390_lowcore.psw_save_area.addr); 73*9a78c70aSVasily Gorbik decompressor_printk( 74*9a78c70aSVasily Gorbik " R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x P:%x AS:%x CC:%x PM:%x RI:%x EA:%x\n", 75*9a78c70aSVasily Gorbik psw->per, psw->dat, psw->io, psw->ext, psw->key, psw->mcheck, 76*9a78c70aSVasily Gorbik psw->wait, psw->pstate, psw->as, psw->cc, psw->pm, psw->ri, 77*9a78c70aSVasily Gorbik psw->eaba); 78*9a78c70aSVasily Gorbik decompressor_printk("GPRS: %016lx %016lx %016lx %016lx\n", 79*9a78c70aSVasily Gorbik gpregs[0], gpregs[1], gpregs[2], gpregs[3]); 80*9a78c70aSVasily Gorbik decompressor_printk(" %016lx %016lx %016lx %016lx\n", 81*9a78c70aSVasily Gorbik gpregs[4], gpregs[5], gpregs[6], gpregs[7]); 82*9a78c70aSVasily Gorbik decompressor_printk(" %016lx %016lx %016lx %016lx\n", 83*9a78c70aSVasily Gorbik gpregs[8], gpregs[9], gpregs[10], gpregs[11]); 84*9a78c70aSVasily Gorbik decompressor_printk(" %016lx %016lx %016lx %016lx\n", 85*9a78c70aSVasily Gorbik gpregs[12], gpregs[13], gpregs[14], gpregs[15]); 86724dc336SVasily Gorbik } 87