summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasily Gorbik <gor@linux.ibm.com>2018-05-15 07:28:53 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2018-10-09 05:21:14 -0400
commit49698745e53c417370ac5cfe8b849bb65d62f129 (patch)
treea8f3d4ed57debe3d68f222c94e422dd1e52cf630
parentb09decfd99f8258408decfaa07c5cce6c06fe2cf (diff)
s390: move ipl block and cmd line handling to early boot phase
To distinguish zfcpdump case and to be able to parse some of the kernel command line arguments early (e.g. mem=) ipl block retrieval and command line construction code is moved to the early boot phase. "memory_end" is set up correctly respecting "mem=" and hsa_size in case of the zfcpdump. arch/s390/boot/string.c is introduced to provide string handling and command line parsing functions to early boot phase code for the compressed kernel image case. Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/boot/Makefile3
-rw-r--r--arch/s390/boot/boot.h3
-rw-r--r--arch/s390/boot/cmdline.c2
-rw-r--r--arch/s390/boot/ctype.c2
-rw-r--r--arch/s390/boot/ipl_parm.c173
-rw-r--r--arch/s390/boot/ipl_vmparm.c2
-rw-r--r--arch/s390/boot/startup.c3
-rw-r--r--arch/s390/boot/string.c100
-rw-r--r--arch/s390/include/asm/boot_data.h11
-rw-r--r--arch/s390/include/asm/ipl.h4
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/early.c47
-rw-r--r--arch/s390/kernel/ipl.c117
-rw-r--r--arch/s390/kernel/ipl_vmparm.c36
-rw-r--r--arch/s390/kernel/setup.c26
15 files changed, 355 insertions, 176 deletions
diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile
index b6903c47e0ac..f58edd8b2e34 100644
--- a/arch/s390/boot/Makefile
+++ b/arch/s390/boot/Makefile
@@ -27,7 +27,8 @@ endif
27 27
28CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char 28CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char
29 29
30obj-y := head.o als.o startup.o mem_detect.o ebcdic.o sclp_early_core.o mem.o 30obj-y := head.o als.o startup.o mem_detect.o ipl_parm.o string.o ebcdic.o
31obj-y += sclp_early_core.o mem.o ipl_vmparm.o cmdline.o ctype.o
31targets := bzImage startup.a section_cmp.boot.data $(obj-y) 32targets := bzImage startup.a section_cmp.boot.data $(obj-y)
32subdir- := compressed 33subdir- := compressed
33 34
diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h
index 808154b99a5d..fc41e2277ea8 100644
--- a/arch/s390/boot/boot.h
+++ b/arch/s390/boot/boot.h
@@ -4,5 +4,8 @@
4 4
5void startup_kernel(void); 5void startup_kernel(void);
6void detect_memory(void); 6void detect_memory(void);
7void store_ipl_parmblock(void);
8void setup_boot_command_line(void);
9void setup_memory_end(void);
7 10
8#endif /* BOOT_BOOT_H */ 11#endif /* BOOT_BOOT_H */
diff --git a/arch/s390/boot/cmdline.c b/arch/s390/boot/cmdline.c
new file mode 100644
index 000000000000..73d826cdbdeb
--- /dev/null
+++ b/arch/s390/boot/cmdline.c
@@ -0,0 +1,2 @@
1// SPDX-License-Identifier: GPL-2.0
2#include "../../../lib/cmdline.c"
diff --git a/arch/s390/boot/ctype.c b/arch/s390/boot/ctype.c
new file mode 100644
index 000000000000..2495810b47e3
--- /dev/null
+++ b/arch/s390/boot/ctype.c
@@ -0,0 +1,2 @@
1// SPDX-License-Identifier: GPL-2.0
2#include "../../../lib/ctype.c"
diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c
new file mode 100644
index 000000000000..7f8e546400a1
--- /dev/null
+++ b/arch/s390/boot/ipl_parm.c
@@ -0,0 +1,173 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/init.h>
3#include <linux/ctype.h>
4#include <asm/ebcdic.h>
5#include <asm/sclp.h>
6#include <asm/sections.h>
7#include <asm/boot_data.h>
8#include "boot.h"
9
10char __bootdata(early_command_line)[COMMAND_LINE_SIZE];
11struct ipl_parameter_block __bootdata(early_ipl_block);
12int __bootdata(early_ipl_block_valid);
13
14unsigned long __bootdata(memory_end);
15int __bootdata(memory_end_set);
16
17static inline int __diag308(unsigned long subcode, void *addr)
18{
19 register unsigned long _addr asm("0") = (unsigned long)addr;
20 register unsigned long _rc asm("1") = 0;
21 unsigned long reg1, reg2;
22 psw_t old = S390_lowcore.program_new_psw;
23
24 asm volatile(
25 " epsw %0,%1\n"
26 " st %0,%[psw_pgm]\n"
27 " st %1,%[psw_pgm]+4\n"
28 " larl %0,1f\n"
29 " stg %0,%[psw_pgm]+8\n"
30 " diag %[addr],%[subcode],0x308\n"
31 "1: nopr %%r7\n"
32 : "=&d" (reg1), "=&a" (reg2),
33 [psw_pgm] "=Q" (S390_lowcore.program_new_psw),
34 [addr] "+d" (_addr), "+d" (_rc)
35 : [subcode] "d" (subcode)
36 : "cc", "memory");
37 S390_lowcore.program_new_psw = old;
38 return _rc;
39}
40
41void store_ipl_parmblock(void)
42{
43 int rc;
44
45 rc = __diag308(DIAG308_STORE, &early_ipl_block);
46 if (rc == DIAG308_RC_OK &&
47 early_ipl_block.hdr.version <= IPL_MAX_SUPPORTED_VERSION)
48 early_ipl_block_valid = 1;
49}
50
51static size_t scpdata_length(const char *buf, size_t count)
52{
53 while (count) {
54 if (buf[count - 1] != '\0' && buf[count - 1] != ' ')
55 break;
56 count--;
57 }
58 return count;
59}
60
61static size_t ipl_block_get_ascii_scpdata(char *dest, size_t size,
62 const struct ipl_parameter_block *ipb)
63{
64 size_t count;
65 size_t i;
66 int has_lowercase;
67
68 count = min(size - 1, scpdata_length(ipb->ipl_info.fcp.scp_data,
69 ipb->ipl_info.fcp.scp_data_len));
70 if (!count)
71 goto out;
72
73 has_lowercase = 0;
74 for (i = 0; i < count; i++) {
75 if (!isascii(ipb->ipl_info.fcp.scp_data[i])) {
76 count = 0;
77 goto out;
78 }
79 if (!has_lowercase && islower(ipb->ipl_info.fcp.scp_data[i]))
80 has_lowercase = 1;
81 }
82
83 if (has_lowercase)
84 memcpy(dest, ipb->ipl_info.fcp.scp_data, count);
85 else
86 for (i = 0; i < count; i++)
87 dest[i] = tolower(ipb->ipl_info.fcp.scp_data[i]);
88out:
89 dest[count] = '\0';
90 return count;
91}
92
93static void append_ipl_block_parm(void)
94{
95 char *parm, *delim;
96 size_t len, rc = 0;
97
98 len = strlen(early_command_line);
99
100 delim = early_command_line + len; /* '\0' character position */
101 parm = early_command_line + len + 1; /* append right after '\0' */
102
103 switch (early_ipl_block.hdr.pbt) {
104 case DIAG308_IPL_TYPE_CCW:
105 rc = ipl_block_get_ascii_vmparm(
106 parm, COMMAND_LINE_SIZE - len - 1, &early_ipl_block);
107 break;
108 case DIAG308_IPL_TYPE_FCP:
109 rc = ipl_block_get_ascii_scpdata(
110 parm, COMMAND_LINE_SIZE - len - 1, &early_ipl_block);
111 break;
112 }
113 if (rc) {
114 if (*parm == '=')
115 memmove(early_command_line, parm + 1, rc);
116 else
117 *delim = ' '; /* replace '\0' with space */
118 }
119}
120
121static inline int has_ebcdic_char(const char *str)
122{
123 int i;
124
125 for (i = 0; str[i]; i++)
126 if (str[i] & 0x80)
127 return 1;
128 return 0;
129}
130
131void setup_boot_command_line(void)
132{
133 COMMAND_LINE[ARCH_COMMAND_LINE_SIZE - 1] = 0;
134 /* convert arch command line to ascii if necessary */
135 if (has_ebcdic_char(COMMAND_LINE))
136 EBCASC(COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
137 /* copy arch command line */
138 strcpy(early_command_line, strim(COMMAND_LINE));
139
140 /* append IPL PARM data to the boot command line */
141 if (early_ipl_block_valid)
142 append_ipl_block_parm();
143}
144
145static char command_line_buf[COMMAND_LINE_SIZE] __section(.data);
146static void parse_mem_opt(void)
147{
148 char *args;
149 char *param, *val;
150
151 args = strcpy(command_line_buf, early_command_line);
152 while (*args) {
153 args = next_arg(args, &param, &val);
154
155 if (!strcmp(param, "mem")) {
156 memory_end = memparse(val, NULL);
157 memory_end_set = 1;
158 }
159 }
160}
161
162void setup_memory_end(void)
163{
164 parse_mem_opt();
165#ifdef CONFIG_CRASH_DUMP
166 if (!OLDMEM_BASE && early_ipl_block_valid &&
167 early_ipl_block.hdr.pbt == DIAG308_IPL_TYPE_FCP &&
168 early_ipl_block.ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP) {
169 if (!sclp_early_get_hsa_size(&memory_end) && memory_end)
170 memory_end_set = 1;
171 }
172#endif
173}
diff --git a/arch/s390/boot/ipl_vmparm.c b/arch/s390/boot/ipl_vmparm.c
new file mode 100644
index 000000000000..8dacd5fadfd7
--- /dev/null
+++ b/arch/s390/boot/ipl_vmparm.c
@@ -0,0 +1,2 @@
1// SPDX-License-Identifier: GPL-2.0
2#include "../kernel/ipl_vmparm.c"
diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
index b0e9f4619203..4d441317cdeb 100644
--- a/arch/s390/boot/startup.c
+++ b/arch/s390/boot/startup.c
@@ -51,6 +51,9 @@ void startup_kernel(void)
51 51
52 rescue_initrd(); 52 rescue_initrd();
53 sclp_early_read_info(); 53 sclp_early_read_info();
54 store_ipl_parmblock();
55 setup_boot_command_line();
56 setup_memory_end();
54 detect_memory(); 57 detect_memory();
55 if (!IS_ENABLED(CONFIG_KERNEL_UNCOMPRESSED)) { 58 if (!IS_ENABLED(CONFIG_KERNEL_UNCOMPRESSED)) {
56 img = decompress_kernel(); 59 img = decompress_kernel();
diff --git a/arch/s390/boot/string.c b/arch/s390/boot/string.c
new file mode 100644
index 000000000000..09ca9130e73a
--- /dev/null
+++ b/arch/s390/boot/string.c
@@ -0,0 +1,100 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/ctype.h>
3#include <linux/kernel.h>
4#include "../lib/string.c"
5
6int strncmp(const char *cs, const char *ct, size_t count)
7{
8 unsigned char c1, c2;
9
10 while (count) {
11 c1 = *cs++;
12 c2 = *ct++;
13 if (c1 != c2)
14 return c1 < c2 ? -1 : 1;
15 if (!c1)
16 break;
17 count--;
18 }
19 return 0;
20}
21
22char *skip_spaces(const char *str)
23{
24 while (isspace(*str))
25 ++str;
26 return (char *)str;
27}
28
29char *strim(char *s)
30{
31 size_t size;
32 char *end;
33
34 size = strlen(s);
35 if (!size)
36 return s;
37
38 end = s + size - 1;
39 while (end >= s && isspace(*end))
40 end--;
41 *(end + 1) = '\0';
42
43 return skip_spaces(s);
44}
45
46/* Works only for digits and letters, but small and fast */
47#define TOLOWER(x) ((x) | 0x20)
48
49static unsigned int simple_guess_base(const char *cp)
50{
51 if (cp[0] == '0') {
52 if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
53 return 16;
54 else
55 return 8;
56 } else {
57 return 10;
58 }
59}
60
61/**
62 * simple_strtoull - convert a string to an unsigned long long
63 * @cp: The start of the string
64 * @endp: A pointer to the end of the parsed string will be placed here
65 * @base: The number base to use
66 */
67
68unsigned long long simple_strtoull(const char *cp, char **endp,
69 unsigned int base)
70{
71 unsigned long long result = 0;
72
73 if (!base)
74 base = simple_guess_base(cp);
75
76 if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
77 cp += 2;
78
79 while (isxdigit(*cp)) {
80 unsigned int value;
81
82 value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
83 if (value >= base)
84 break;
85 result = result * base + value;
86 cp++;
87 }
88 if (endp)
89 *endp = (char *)cp;
90
91 return result;
92}
93
94long simple_strtol(const char *cp, char **endp, unsigned int base)
95{
96 if (*cp == '-')
97 return -simple_strtoull(cp + 1, endp, base);
98
99 return simple_strtoull(cp, endp, base);
100}
diff --git a/arch/s390/include/asm/boot_data.h b/arch/s390/include/asm/boot_data.h
new file mode 100644
index 000000000000..2d999ccb977a
--- /dev/null
+++ b/arch/s390/include/asm/boot_data.h
@@ -0,0 +1,11 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _ASM_S390_BOOT_DATA_H
3
4#include <asm/setup.h>
5#include <asm/ipl.h>
6
7extern char early_command_line[COMMAND_LINE_SIZE];
8extern struct ipl_parameter_block early_ipl_block;
9extern int early_ipl_block_valid;
10
11#endif /* _ASM_S390_BOOT_DATA_H */
diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h
index ae5135704616..a8389e2d2f03 100644
--- a/arch/s390/include/asm/ipl.h
+++ b/arch/s390/include/asm/ipl.h
@@ -89,8 +89,8 @@ void __init save_area_add_vxrs(struct save_area *, __vector128 *vxrs);
89 89
90extern void s390_reset_system(void); 90extern void s390_reset_system(void);
91extern void ipl_store_parameters(void); 91extern void ipl_store_parameters(void);
92extern size_t append_ipl_vmparm(char *, size_t); 92extern size_t ipl_block_get_ascii_vmparm(char *dest, size_t size,
93extern size_t append_ipl_scpdata(char *, size_t); 93 const struct ipl_parameter_block *ipb);
94 94
95enum ipl_type { 95enum ipl_type {
96 IPL_TYPE_UNKNOWN = 1, 96 IPL_TYPE_UNKNOWN = 1,
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index dbfd1730e631..7ad6fa60a1f2 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -47,7 +47,7 @@ obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o early_nobss.o
47obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o 47obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
48obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o 48obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o
49obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o alternative.o 49obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o alternative.o
50obj-y += nospec-branch.o 50obj-y += nospec-branch.o ipl_vmparm.o
51 51
52extra-y += head64.o vmlinux.lds 52extra-y += head64.o vmlinux.lds
53 53
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 5b28b434f8a1..af5c2b3f7065 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -29,10 +29,9 @@
29#include <asm/cpcmd.h> 29#include <asm/cpcmd.h>
30#include <asm/sclp.h> 30#include <asm/sclp.h>
31#include <asm/facility.h> 31#include <asm/facility.h>
32#include <asm/boot_data.h>
32#include "entry.h" 33#include "entry.h"
33 34
34static void __init setup_boot_command_line(void);
35
36/* 35/*
37 * Initialize storage key for kernel pages 36 * Initialize storage key for kernel pages
38 */ 37 */
@@ -284,51 +283,11 @@ static int __init cad_setup(char *str)
284} 283}
285early_param("cad", cad_setup); 284early_param("cad", cad_setup);
286 285
287/* Set up boot command line */ 286char __bootdata(early_command_line)[COMMAND_LINE_SIZE];
288static void __init append_to_cmdline(size_t (*ipl_data)(char *, size_t))
289{
290 char *parm, *delim;
291 size_t rc, len;
292
293 len = strlen(boot_command_line);
294
295 delim = boot_command_line + len; /* '\0' character position */
296 parm = boot_command_line + len + 1; /* append right after '\0' */
297
298 rc = ipl_data(parm, COMMAND_LINE_SIZE - len - 1);
299 if (rc) {
300 if (*parm == '=')
301 memmove(boot_command_line, parm + 1, rc);
302 else
303 *delim = ' '; /* replace '\0' with space */
304 }
305}
306
307static inline int has_ebcdic_char(const char *str)
308{
309 int i;
310
311 for (i = 0; str[i]; i++)
312 if (str[i] & 0x80)
313 return 1;
314 return 0;
315}
316
317static void __init setup_boot_command_line(void) 287static void __init setup_boot_command_line(void)
318{ 288{
319 COMMAND_LINE[ARCH_COMMAND_LINE_SIZE - 1] = 0;
320 /* convert arch command line to ascii if necessary */
321 if (has_ebcdic_char(COMMAND_LINE))
322 EBCASC(COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
323 /* copy arch command line */ 289 /* copy arch command line */
324 strlcpy(boot_command_line, strstrip(COMMAND_LINE), 290 strlcpy(boot_command_line, early_command_line, ARCH_COMMAND_LINE_SIZE);
325 ARCH_COMMAND_LINE_SIZE);
326
327 /* append IPL PARM data to the boot command line */
328 if (MACHINE_IS_VM)
329 append_to_cmdline(append_ipl_vmparm);
330
331 append_to_cmdline(append_ipl_scpdata);
332} 291}
333 292
334static void __init check_image_bootable(void) 293static void __init check_image_bootable(void)
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 4296d7e61fb6..f1d69f78bb1d 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -29,6 +29,8 @@
29#include <asm/checksum.h> 29#include <asm/checksum.h>
30#include <asm/debug.h> 30#include <asm/debug.h>
31#include <asm/os_info.h> 31#include <asm/os_info.h>
32#include <asm/sections.h>
33#include <asm/boot_data.h>
32#include "entry.h" 34#include "entry.h"
33 35
34#define IPL_PARM_BLOCK_VERSION 0 36#define IPL_PARM_BLOCK_VERSION 0
@@ -117,6 +119,9 @@ static char *dump_type_str(enum dump_type type)
117 } 119 }
118} 120}
119 121
122struct ipl_parameter_block __bootdata(early_ipl_block);
123int __bootdata(early_ipl_block_valid);
124
120static int ipl_block_valid; 125static int ipl_block_valid;
121static struct ipl_parameter_block ipl_block; 126static struct ipl_parameter_block ipl_block;
122 127
@@ -262,115 +267,16 @@ static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
262 267
263static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); 268static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
264 269
265/* VM IPL PARM routines */
266static size_t reipl_get_ascii_vmparm(char *dest, size_t size,
267 const struct ipl_parameter_block *ipb)
268{
269 int i;
270 size_t len;
271 char has_lowercase = 0;
272
273 len = 0;
274 if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
275 (ipb->ipl_info.ccw.vm_parm_len > 0)) {
276
277 len = min_t(size_t, size - 1, ipb->ipl_info.ccw.vm_parm_len);
278 memcpy(dest, ipb->ipl_info.ccw.vm_parm, len);
279 /* If at least one character is lowercase, we assume mixed
280 * case; otherwise we convert everything to lowercase.
281 */
282 for (i = 0; i < len; i++)
283 if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */
284 (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */
285 (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */
286 has_lowercase = 1;
287 break;
288 }
289 if (!has_lowercase)
290 EBC_TOLOWER(dest, len);
291 EBCASC(dest, len);
292 }
293 dest[len] = 0;
294
295 return len;
296}
297
298size_t append_ipl_vmparm(char *dest, size_t size)
299{
300 size_t rc;
301
302 rc = 0;
303 if (ipl_block_valid && ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW)
304 rc = reipl_get_ascii_vmparm(dest, size, &ipl_block);
305 else
306 dest[0] = 0;
307 return rc;
308}
309
310static ssize_t ipl_vm_parm_show(struct kobject *kobj, 270static ssize_t ipl_vm_parm_show(struct kobject *kobj,
311 struct kobj_attribute *attr, char *page) 271 struct kobj_attribute *attr, char *page)
312{ 272{
313 char parm[DIAG308_VMPARM_SIZE + 1] = {}; 273 char parm[DIAG308_VMPARM_SIZE + 1] = {};
314 274
315 append_ipl_vmparm(parm, sizeof(parm)); 275 if (ipl_block_valid && (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW))
276 ipl_block_get_ascii_vmparm(parm, sizeof(parm), &ipl_block);
316 return sprintf(page, "%s\n", parm); 277 return sprintf(page, "%s\n", parm);
317} 278}
318 279
319static size_t scpdata_length(const char* buf, size_t count)
320{
321 while (count) {
322 if (buf[count - 1] != '\0' && buf[count - 1] != ' ')
323 break;
324 count--;
325 }
326 return count;
327}
328
329static size_t reipl_append_ascii_scpdata(char *dest, size_t size,
330 const struct ipl_parameter_block *ipb)
331{
332 size_t count;
333 size_t i;
334 int has_lowercase;
335
336 count = min(size - 1, scpdata_length(ipb->ipl_info.fcp.scp_data,
337 ipb->ipl_info.fcp.scp_data_len));
338 if (!count)
339 goto out;
340
341 has_lowercase = 0;
342 for (i = 0; i < count; i++) {
343 if (!isascii(ipb->ipl_info.fcp.scp_data[i])) {
344 count = 0;
345 goto out;
346 }
347 if (!has_lowercase && islower(ipb->ipl_info.fcp.scp_data[i]))
348 has_lowercase = 1;
349 }
350
351 if (has_lowercase)
352 memcpy(dest, ipb->ipl_info.fcp.scp_data, count);
353 else
354 for (i = 0; i < count; i++)
355 dest[i] = tolower(ipb->ipl_info.fcp.scp_data[i]);
356out:
357 dest[count] = '\0';
358 return count;
359}
360
361size_t append_ipl_scpdata(char *dest, size_t len)
362{
363 size_t rc;
364
365 rc = 0;
366 if (ipl_block_valid && ipl_block.hdr.pbt == DIAG308_IPL_TYPE_FCP)
367 rc = reipl_append_ascii_scpdata(dest, len, &ipl_block);
368 else
369 dest[0] = 0;
370 return rc;
371}
372
373
374static struct kobj_attribute sys_ipl_vm_parm_attr = 280static struct kobj_attribute sys_ipl_vm_parm_attr =
375 __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL); 281 __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL);
376 282
@@ -564,7 +470,7 @@ static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb,
564{ 470{
565 char vmparm[DIAG308_VMPARM_SIZE + 1] = {}; 471 char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
566 472
567 reipl_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb); 473 ipl_block_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
568 return sprintf(page, "%s\n", vmparm); 474 return sprintf(page, "%s\n", vmparm);
569} 475}
570 476
@@ -1769,11 +1675,10 @@ void __init setup_ipl(void)
1769 1675
1770void __init ipl_store_parameters(void) 1676void __init ipl_store_parameters(void)
1771{ 1677{
1772 int rc; 1678 if (early_ipl_block_valid) {
1773 1679 memcpy(&ipl_block, &early_ipl_block, sizeof(ipl_block));
1774 rc = diag308(DIAG308_STORE, &ipl_block);
1775 if (rc == DIAG308_RC_OK && ipl_block.hdr.version <= IPL_MAX_SUPPORTED_VERSION)
1776 ipl_block_valid = 1; 1680 ipl_block_valid = 1;
1681 }
1777} 1682}
1778 1683
1779void s390_reset_system(void) 1684void s390_reset_system(void)
diff --git a/arch/s390/kernel/ipl_vmparm.c b/arch/s390/kernel/ipl_vmparm.c
new file mode 100644
index 000000000000..411838c0a0af
--- /dev/null
+++ b/arch/s390/kernel/ipl_vmparm.c
@@ -0,0 +1,36 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <asm/ebcdic.h>
3#include <asm/ipl.h>
4
5/* VM IPL PARM routines */
6size_t ipl_block_get_ascii_vmparm(char *dest, size_t size,
7 const struct ipl_parameter_block *ipb)
8{
9 int i;
10 size_t len;
11 char has_lowercase = 0;
12
13 len = 0;
14 if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
15 (ipb->ipl_info.ccw.vm_parm_len > 0)) {
16
17 len = min_t(size_t, size - 1, ipb->ipl_info.ccw.vm_parm_len);
18 memcpy(dest, ipb->ipl_info.ccw.vm_parm, len);
19 /* If at least one character is lowercase, we assume mixed
20 * case; otherwise we convert everything to lowercase.
21 */
22 for (i = 0; i < len; i++)
23 if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */
24 (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */
25 (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */
26 has_lowercase = 1;
27 break;
28 }
29 if (!has_lowercase)
30 EBC_TOLOWER(dest, len);
31 EBCASC(dest, len);
32 }
33 dest[len] = 0;
34
35 return len;
36}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 36fb37d7a36c..ae3810c04872 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -90,8 +90,8 @@ char elf_platform[ELF_PLATFORM_SIZE];
90 90
91unsigned long int_hwcap = 0; 91unsigned long int_hwcap = 0;
92 92
93int __initdata memory_end_set; 93int __bootdata(memory_end_set);
94unsigned long __initdata memory_end; 94unsigned long __bootdata(memory_end);
95unsigned long __bootdata(max_physmem_end); 95unsigned long __bootdata(max_physmem_end);
96struct mem_detect_info __bootdata(mem_detect); 96struct mem_detect_info __bootdata(mem_detect);
97 97
@@ -286,15 +286,6 @@ void machine_power_off(void)
286void (*pm_power_off)(void) = machine_power_off; 286void (*pm_power_off)(void) = machine_power_off;
287EXPORT_SYMBOL_GPL(pm_power_off); 287EXPORT_SYMBOL_GPL(pm_power_off);
288 288
289static int __init early_parse_mem(char *p)
290{
291 memory_end = memparse(p, &p);
292 memory_end &= PAGE_MASK;
293 memory_end_set = 1;
294 return 0;
295}
296early_param("mem", early_parse_mem);
297
298static int __init parse_vmalloc(char *arg) 289static int __init parse_vmalloc(char *arg)
299{ 290{
300 if (!arg) 291 if (!arg)
@@ -605,17 +596,8 @@ static struct notifier_block kdump_mem_nb = {
605 */ 596 */
606static void reserve_memory_end(void) 597static void reserve_memory_end(void)
607{ 598{
608#ifdef CONFIG_CRASH_DUMP 599 if (memory_end_set)
609 if (ipl_info.type == IPL_TYPE_FCP_DUMP && 600 memblock_reserve(memory_end, ULONG_MAX);
610 !OLDMEM_BASE && sclp.hsa_size) {
611 memory_end = sclp.hsa_size;
612 memory_end &= PAGE_MASK;
613 memory_end_set = 1;
614 }
615#endif
616 if (!memory_end_set)
617 return;
618 memblock_reserve(memory_end, ULONG_MAX);
619} 601}
620 602
621/* 603/*