diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/kernel/early.c | 80 | ||||
-rw-r--r-- | arch/s390/kernel/ipl.c | 444 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 17 |
3 files changed, 458 insertions, 83 deletions
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index b2226e41f067..e22473993dc9 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/pfn.h> | 15 | #include <linux/pfn.h> |
16 | #include <linux/uaccess.h> | 16 | #include <linux/uaccess.h> |
17 | #include <asm/ebcdic.h> | ||
17 | #include <asm/ipl.h> | 18 | #include <asm/ipl.h> |
18 | #include <asm/lowcore.h> | 19 | #include <asm/lowcore.h> |
19 | #include <asm/processor.h> | 20 | #include <asm/processor.h> |
@@ -26,12 +27,40 @@ | |||
26 | /* | 27 | /* |
27 | * Create a Kernel NSS if the SAVESYS= parameter is defined | 28 | * Create a Kernel NSS if the SAVESYS= parameter is defined |
28 | */ | 29 | */ |
29 | #define DEFSYS_CMD_SIZE 96 | 30 | #define DEFSYS_CMD_SIZE 128 |
30 | #define SAVESYS_CMD_SIZE 32 | 31 | #define SAVESYS_CMD_SIZE 32 |
31 | 32 | ||
32 | char kernel_nss_name[NSS_NAME_SIZE + 1]; | 33 | char kernel_nss_name[NSS_NAME_SIZE + 1]; |
33 | 34 | ||
35 | static void __init setup_boot_command_line(void); | ||
36 | |||
37 | |||
34 | #ifdef CONFIG_SHARED_KERNEL | 38 | #ifdef CONFIG_SHARED_KERNEL |
39 | int __init savesys_ipl_nss(char *cmd, const int cmdlen); | ||
40 | |||
41 | asm( | ||
42 | " .section .init.text,\"ax\",@progbits\n" | ||
43 | " .align 4\n" | ||
44 | " .type savesys_ipl_nss, @function\n" | ||
45 | "savesys_ipl_nss:\n" | ||
46 | #ifdef CONFIG_64BIT | ||
47 | " stmg 6,15,48(15)\n" | ||
48 | " lgr 14,3\n" | ||
49 | " sam31\n" | ||
50 | " diag 2,14,0x8\n" | ||
51 | " sam64\n" | ||
52 | " lgr 2,14\n" | ||
53 | " lmg 6,15,48(15)\n" | ||
54 | #else | ||
55 | " stm 6,15,24(15)\n" | ||
56 | " lr 14,3\n" | ||
57 | " diag 2,14,0x8\n" | ||
58 | " lr 2,14\n" | ||
59 | " lm 6,15,24(15)\n" | ||
60 | #endif | ||
61 | " br 14\n" | ||
62 | " .size savesys_ipl_nss, .-savesys_ipl_nss\n"); | ||
63 | |||
35 | static noinline __init void create_kernel_nss(void) | 64 | static noinline __init void create_kernel_nss(void) |
36 | { | 65 | { |
37 | unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size; | 66 | unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size; |
@@ -39,6 +68,7 @@ static noinline __init void create_kernel_nss(void) | |||
39 | unsigned int sinitrd_pfn, einitrd_pfn; | 68 | unsigned int sinitrd_pfn, einitrd_pfn; |
40 | #endif | 69 | #endif |
41 | int response; | 70 | int response; |
71 | size_t len; | ||
42 | char *savesys_ptr; | 72 | char *savesys_ptr; |
43 | char upper_command_line[COMMAND_LINE_SIZE]; | 73 | char upper_command_line[COMMAND_LINE_SIZE]; |
44 | char defsys_cmd[DEFSYS_CMD_SIZE]; | 74 | char defsys_cmd[DEFSYS_CMD_SIZE]; |
@@ -49,8 +79,8 @@ static noinline __init void create_kernel_nss(void) | |||
49 | return; | 79 | return; |
50 | 80 | ||
51 | /* Convert COMMAND_LINE to upper case */ | 81 | /* Convert COMMAND_LINE to upper case */ |
52 | for (i = 0; i < strlen(COMMAND_LINE); i++) | 82 | for (i = 0; i < strlen(boot_command_line); i++) |
53 | upper_command_line[i] = toupper(COMMAND_LINE[i]); | 83 | upper_command_line[i] = toupper(boot_command_line[i]); |
54 | 84 | ||
55 | savesys_ptr = strstr(upper_command_line, "SAVESYS="); | 85 | savesys_ptr = strstr(upper_command_line, "SAVESYS="); |
56 | 86 | ||
@@ -83,7 +113,8 @@ static noinline __init void create_kernel_nss(void) | |||
83 | } | 113 | } |
84 | #endif | 114 | #endif |
85 | 115 | ||
86 | sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size); | 116 | sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK PARMREGS=0-13", |
117 | defsys_cmd, min_size); | ||
87 | sprintf(savesys_cmd, "SAVESYS %s \n IPL %s", | 118 | sprintf(savesys_cmd, "SAVESYS %s \n IPL %s", |
88 | kernel_nss_name, kernel_nss_name); | 119 | kernel_nss_name, kernel_nss_name); |
89 | 120 | ||
@@ -94,13 +125,24 @@ static noinline __init void create_kernel_nss(void) | |||
94 | return; | 125 | return; |
95 | } | 126 | } |
96 | 127 | ||
97 | __cpcmd(savesys_cmd, NULL, 0, &response); | 128 | len = strlen(savesys_cmd); |
129 | ASCEBC(savesys_cmd, len); | ||
130 | response = savesys_ipl_nss(savesys_cmd, len); | ||
98 | 131 | ||
99 | if (response != strlen(savesys_cmd)) { | 132 | /* On success: response is equal to the command size, |
133 | * max SAVESYS_CMD_SIZE | ||
134 | * On error: response contains the numeric portion of cp error message. | ||
135 | * for SAVESYS it will be >= 263 | ||
136 | */ | ||
137 | if (response > SAVESYS_CMD_SIZE) { | ||
100 | kernel_nss_name[0] = '\0'; | 138 | kernel_nss_name[0] = '\0'; |
101 | return; | 139 | return; |
102 | } | 140 | } |
103 | 141 | ||
142 | /* re-setup boot command line with new ipl vm parms */ | ||
143 | ipl_update_parameters(); | ||
144 | setup_boot_command_line(); | ||
145 | |||
104 | ipl_flags = IPL_NSS_VALID; | 146 | ipl_flags = IPL_NSS_VALID; |
105 | } | 147 | } |
106 | 148 | ||
@@ -397,6 +439,26 @@ static __init void rescue_initrd(void) | |||
397 | #endif | 439 | #endif |
398 | } | 440 | } |
399 | 441 | ||
442 | /* Set up boot command line */ | ||
443 | static void __init setup_boot_command_line(void) | ||
444 | { | ||
445 | char *parm = NULL; | ||
446 | |||
447 | /* copy arch command line */ | ||
448 | strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE); | ||
449 | boot_command_line[ARCH_COMMAND_LINE_SIZE - 1] = 0; | ||
450 | |||
451 | /* append IPL PARM data to the boot command line */ | ||
452 | if (MACHINE_IS_VM) { | ||
453 | parm = boot_command_line + strlen(boot_command_line); | ||
454 | *parm++ = ' '; | ||
455 | get_ipl_vmparm(parm); | ||
456 | if (parm[0] == '=') | ||
457 | memmove(boot_command_line, parm + 1, strlen(parm)); | ||
458 | } | ||
459 | } | ||
460 | |||
461 | |||
400 | /* | 462 | /* |
401 | * Save ipl parameters, clear bss memory, initialize storage keys | 463 | * Save ipl parameters, clear bss memory, initialize storage keys |
402 | * and create a kernel NSS at startup if the SAVESYS= parm is defined | 464 | * and create a kernel NSS at startup if the SAVESYS= parm is defined |
@@ -411,10 +473,12 @@ void __init startup_init(void) | |||
411 | init_kernel_storage_key(); | 473 | init_kernel_storage_key(); |
412 | lockdep_init(); | 474 | lockdep_init(); |
413 | lockdep_off(); | 475 | lockdep_off(); |
414 | detect_machine_type(); | ||
415 | create_kernel_nss(); | ||
416 | sort_main_extable(); | 476 | sort_main_extable(); |
417 | setup_lowcore_early(); | 477 | setup_lowcore_early(); |
478 | detect_machine_type(); | ||
479 | ipl_update_parameters(); | ||
480 | setup_boot_command_line(); | ||
481 | create_kernel_nss(); | ||
418 | detect_mvpg(); | 482 | detect_mvpg(); |
419 | detect_ieee(); | 483 | detect_ieee(); |
420 | detect_csp(); | 484 | detect_csp(); |
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 532542447d66..9f6dfd306abb 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/ebcdic.h> | 22 | #include <asm/ebcdic.h> |
23 | #include <asm/reset.h> | 23 | #include <asm/reset.h> |
24 | #include <asm/sclp.h> | 24 | #include <asm/sclp.h> |
25 | #include <asm/setup.h> | ||
25 | 26 | ||
26 | #define IPL_PARM_BLOCK_VERSION 0 | 27 | #define IPL_PARM_BLOCK_VERSION 0 |
27 | 28 | ||
@@ -121,6 +122,7 @@ enum ipl_method { | |||
121 | REIPL_METHOD_FCP_RO_VM, | 122 | REIPL_METHOD_FCP_RO_VM, |
122 | REIPL_METHOD_FCP_DUMP, | 123 | REIPL_METHOD_FCP_DUMP, |
123 | REIPL_METHOD_NSS, | 124 | REIPL_METHOD_NSS, |
125 | REIPL_METHOD_NSS_DIAG, | ||
124 | REIPL_METHOD_DEFAULT, | 126 | REIPL_METHOD_DEFAULT, |
125 | }; | 127 | }; |
126 | 128 | ||
@@ -134,14 +136,15 @@ enum dump_method { | |||
134 | 136 | ||
135 | static int diag308_set_works = 0; | 137 | static int diag308_set_works = 0; |
136 | 138 | ||
139 | static struct ipl_parameter_block ipl_block; | ||
140 | |||
137 | static int reipl_capabilities = IPL_TYPE_UNKNOWN; | 141 | static int reipl_capabilities = IPL_TYPE_UNKNOWN; |
138 | 142 | ||
139 | static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN; | 143 | static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN; |
140 | static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT; | 144 | static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT; |
141 | static struct ipl_parameter_block *reipl_block_fcp; | 145 | static struct ipl_parameter_block *reipl_block_fcp; |
142 | static struct ipl_parameter_block *reipl_block_ccw; | 146 | static struct ipl_parameter_block *reipl_block_ccw; |
143 | 147 | static struct ipl_parameter_block *reipl_block_nss; | |
144 | static char reipl_nss_name[NSS_NAME_SIZE + 1]; | ||
145 | 148 | ||
146 | static int dump_capabilities = DUMP_TYPE_NONE; | 149 | static int dump_capabilities = DUMP_TYPE_NONE; |
147 | static enum dump_type dump_type = DUMP_TYPE_NONE; | 150 | static enum dump_type dump_type = DUMP_TYPE_NONE; |
@@ -263,6 +266,56 @@ static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr, | |||
263 | 266 | ||
264 | static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); | 267 | static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); |
265 | 268 | ||
269 | /* VM IPL PARM routines */ | ||
270 | static void reipl_get_ascii_vmparm(char *dest, | ||
271 | const struct ipl_parameter_block *ipb) | ||
272 | { | ||
273 | int i; | ||
274 | int len = 0; | ||
275 | char has_lowercase = 0; | ||
276 | |||
277 | if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) && | ||
278 | (ipb->ipl_info.ccw.vm_parm_len > 0)) { | ||
279 | |||
280 | len = ipb->ipl_info.ccw.vm_parm_len; | ||
281 | memcpy(dest, ipb->ipl_info.ccw.vm_parm, len); | ||
282 | /* If at least one character is lowercase, we assume mixed | ||
283 | * case; otherwise we convert everything to lowercase. | ||
284 | */ | ||
285 | for (i = 0; i < len; i++) | ||
286 | if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */ | ||
287 | (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */ | ||
288 | (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */ | ||
289 | has_lowercase = 1; | ||
290 | break; | ||
291 | } | ||
292 | if (!has_lowercase) | ||
293 | EBC_TOLOWER(dest, len); | ||
294 | EBCASC(dest, len); | ||
295 | } | ||
296 | dest[len] = 0; | ||
297 | } | ||
298 | |||
299 | void get_ipl_vmparm(char *dest) | ||
300 | { | ||
301 | if (diag308_set_works && (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW)) | ||
302 | reipl_get_ascii_vmparm(dest, &ipl_block); | ||
303 | else | ||
304 | dest[0] = 0; | ||
305 | } | ||
306 | |||
307 | static ssize_t ipl_vm_parm_show(struct kobject *kobj, | ||
308 | struct kobj_attribute *attr, char *page) | ||
309 | { | ||
310 | char parm[DIAG308_VMPARM_SIZE + 1] = {}; | ||
311 | |||
312 | get_ipl_vmparm(parm); | ||
313 | return sprintf(page, "%s\n", parm); | ||
314 | } | ||
315 | |||
316 | static struct kobj_attribute sys_ipl_vm_parm_attr = | ||
317 | __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL); | ||
318 | |||
266 | static ssize_t sys_ipl_device_show(struct kobject *kobj, | 319 | static ssize_t sys_ipl_device_show(struct kobject *kobj, |
267 | struct kobj_attribute *attr, char *page) | 320 | struct kobj_attribute *attr, char *page) |
268 | { | 321 | { |
@@ -370,15 +423,27 @@ static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj, | |||
370 | static struct kobj_attribute sys_ipl_ccw_loadparm_attr = | 423 | static struct kobj_attribute sys_ipl_ccw_loadparm_attr = |
371 | __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL); | 424 | __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL); |
372 | 425 | ||
373 | static struct attribute *ipl_ccw_attrs[] = { | 426 | static struct attribute *ipl_ccw_attrs_vm[] = { |
427 | &sys_ipl_type_attr.attr, | ||
428 | &sys_ipl_device_attr.attr, | ||
429 | &sys_ipl_ccw_loadparm_attr.attr, | ||
430 | &sys_ipl_vm_parm_attr.attr, | ||
431 | NULL, | ||
432 | }; | ||
433 | |||
434 | static struct attribute *ipl_ccw_attrs_lpar[] = { | ||
374 | &sys_ipl_type_attr.attr, | 435 | &sys_ipl_type_attr.attr, |
375 | &sys_ipl_device_attr.attr, | 436 | &sys_ipl_device_attr.attr, |
376 | &sys_ipl_ccw_loadparm_attr.attr, | 437 | &sys_ipl_ccw_loadparm_attr.attr, |
377 | NULL, | 438 | NULL, |
378 | }; | 439 | }; |
379 | 440 | ||
380 | static struct attribute_group ipl_ccw_attr_group = { | 441 | static struct attribute_group ipl_ccw_attr_group_vm = { |
381 | .attrs = ipl_ccw_attrs, | 442 | .attrs = ipl_ccw_attrs_vm, |
443 | }; | ||
444 | |||
445 | static struct attribute_group ipl_ccw_attr_group_lpar = { | ||
446 | .attrs = ipl_ccw_attrs_lpar | ||
382 | }; | 447 | }; |
383 | 448 | ||
384 | /* NSS ipl device attributes */ | 449 | /* NSS ipl device attributes */ |
@@ -388,6 +453,8 @@ DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name); | |||
388 | static struct attribute *ipl_nss_attrs[] = { | 453 | static struct attribute *ipl_nss_attrs[] = { |
389 | &sys_ipl_type_attr.attr, | 454 | &sys_ipl_type_attr.attr, |
390 | &sys_ipl_nss_name_attr.attr, | 455 | &sys_ipl_nss_name_attr.attr, |
456 | &sys_ipl_ccw_loadparm_attr.attr, | ||
457 | &sys_ipl_vm_parm_attr.attr, | ||
391 | NULL, | 458 | NULL, |
392 | }; | 459 | }; |
393 | 460 | ||
@@ -450,7 +517,12 @@ static int __init ipl_init(void) | |||
450 | } | 517 | } |
451 | switch (ipl_info.type) { | 518 | switch (ipl_info.type) { |
452 | case IPL_TYPE_CCW: | 519 | case IPL_TYPE_CCW: |
453 | rc = sysfs_create_group(&ipl_kset->kobj, &ipl_ccw_attr_group); | 520 | if (MACHINE_IS_VM) |
521 | rc = sysfs_create_group(&ipl_kset->kobj, | ||
522 | &ipl_ccw_attr_group_vm); | ||
523 | else | ||
524 | rc = sysfs_create_group(&ipl_kset->kobj, | ||
525 | &ipl_ccw_attr_group_lpar); | ||
454 | break; | 526 | break; |
455 | case IPL_TYPE_FCP: | 527 | case IPL_TYPE_FCP: |
456 | case IPL_TYPE_FCP_DUMP: | 528 | case IPL_TYPE_FCP_DUMP: |
@@ -481,6 +553,83 @@ static struct shutdown_action __refdata ipl_action = { | |||
481 | * reipl shutdown action: Reboot Linux on shutdown. | 553 | * reipl shutdown action: Reboot Linux on shutdown. |
482 | */ | 554 | */ |
483 | 555 | ||
556 | /* VM IPL PARM attributes */ | ||
557 | static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb, | ||
558 | char *page) | ||
559 | { | ||
560 | char vmparm[DIAG308_VMPARM_SIZE + 1] = {}; | ||
561 | |||
562 | reipl_get_ascii_vmparm(vmparm, ipb); | ||
563 | return sprintf(page, "%s\n", vmparm); | ||
564 | } | ||
565 | |||
566 | static ssize_t reipl_generic_vmparm_store(struct ipl_parameter_block *ipb, | ||
567 | size_t vmparm_max, | ||
568 | const char *buf, size_t len) | ||
569 | { | ||
570 | int i, ip_len; | ||
571 | |||
572 | /* ignore trailing newline */ | ||
573 | ip_len = len; | ||
574 | if ((len > 0) && (buf[len - 1] == '\n')) | ||
575 | ip_len--; | ||
576 | |||
577 | if (ip_len > vmparm_max) | ||
578 | return -EINVAL; | ||
579 | |||
580 | /* parm is used to store kernel options, check for common chars */ | ||
581 | for (i = 0; i < ip_len; i++) | ||
582 | if (!(isalnum(buf[i]) || isascii(buf[i]) || isprint(buf[i]))) | ||
583 | return -EINVAL; | ||
584 | |||
585 | memset(ipb->ipl_info.ccw.vm_parm, 0, DIAG308_VMPARM_SIZE); | ||
586 | ipb->ipl_info.ccw.vm_parm_len = ip_len; | ||
587 | if (ip_len > 0) { | ||
588 | ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID; | ||
589 | memcpy(ipb->ipl_info.ccw.vm_parm, buf, ip_len); | ||
590 | ASCEBC(ipb->ipl_info.ccw.vm_parm, ip_len); | ||
591 | } else { | ||
592 | ipb->ipl_info.ccw.vm_flags &= ~DIAG308_VM_FLAGS_VP_VALID; | ||
593 | } | ||
594 | |||
595 | return len; | ||
596 | } | ||
597 | |||
598 | /* NSS wrapper */ | ||
599 | static ssize_t reipl_nss_vmparm_show(struct kobject *kobj, | ||
600 | struct kobj_attribute *attr, char *page) | ||
601 | { | ||
602 | return reipl_generic_vmparm_show(reipl_block_nss, page); | ||
603 | } | ||
604 | |||
605 | static ssize_t reipl_nss_vmparm_store(struct kobject *kobj, | ||
606 | struct kobj_attribute *attr, | ||
607 | const char *buf, size_t len) | ||
608 | { | ||
609 | return reipl_generic_vmparm_store(reipl_block_nss, 56, buf, len); | ||
610 | } | ||
611 | |||
612 | /* CCW wrapper */ | ||
613 | static ssize_t reipl_ccw_vmparm_show(struct kobject *kobj, | ||
614 | struct kobj_attribute *attr, char *page) | ||
615 | { | ||
616 | return reipl_generic_vmparm_show(reipl_block_ccw, page); | ||
617 | } | ||
618 | |||
619 | static ssize_t reipl_ccw_vmparm_store(struct kobject *kobj, | ||
620 | struct kobj_attribute *attr, | ||
621 | const char *buf, size_t len) | ||
622 | { | ||
623 | return reipl_generic_vmparm_store(reipl_block_ccw, 64, buf, len); | ||
624 | } | ||
625 | |||
626 | static struct kobj_attribute sys_reipl_nss_vmparm_attr = | ||
627 | __ATTR(parm, S_IRUGO | S_IWUSR, reipl_nss_vmparm_show, | ||
628 | reipl_nss_vmparm_store); | ||
629 | static struct kobj_attribute sys_reipl_ccw_vmparm_attr = | ||
630 | __ATTR(parm, S_IRUGO | S_IWUSR, reipl_ccw_vmparm_show, | ||
631 | reipl_ccw_vmparm_store); | ||
632 | |||
484 | /* FCP reipl device attributes */ | 633 | /* FCP reipl device attributes */ |
485 | 634 | ||
486 | DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n", | 635 | DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n", |
@@ -513,27 +662,26 @@ static struct attribute_group reipl_fcp_attr_group = { | |||
513 | DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n", | 662 | DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n", |
514 | reipl_block_ccw->ipl_info.ccw.devno); | 663 | reipl_block_ccw->ipl_info.ccw.devno); |
515 | 664 | ||
516 | static void reipl_get_ascii_loadparm(char *loadparm) | 665 | static void reipl_get_ascii_loadparm(char *loadparm, |
666 | struct ipl_parameter_block *ibp) | ||
517 | { | 667 | { |
518 | memcpy(loadparm, &reipl_block_ccw->ipl_info.ccw.load_param, | 668 | memcpy(loadparm, ibp->ipl_info.ccw.load_parm, LOADPARM_LEN); |
519 | LOADPARM_LEN); | ||
520 | EBCASC(loadparm, LOADPARM_LEN); | 669 | EBCASC(loadparm, LOADPARM_LEN); |
521 | loadparm[LOADPARM_LEN] = 0; | 670 | loadparm[LOADPARM_LEN] = 0; |
522 | strstrip(loadparm); | 671 | strstrip(loadparm); |
523 | } | 672 | } |
524 | 673 | ||
525 | static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj, | 674 | static ssize_t reipl_generic_loadparm_show(struct ipl_parameter_block *ipb, |
526 | struct kobj_attribute *attr, char *page) | 675 | char *page) |
527 | { | 676 | { |
528 | char buf[LOADPARM_LEN + 1]; | 677 | char buf[LOADPARM_LEN + 1]; |
529 | 678 | ||
530 | reipl_get_ascii_loadparm(buf); | 679 | reipl_get_ascii_loadparm(buf, ipb); |
531 | return sprintf(page, "%s\n", buf); | 680 | return sprintf(page, "%s\n", buf); |
532 | } | 681 | } |
533 | 682 | ||
534 | static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj, | 683 | static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb, |
535 | struct kobj_attribute *attr, | 684 | const char *buf, size_t len) |
536 | const char *buf, size_t len) | ||
537 | { | 685 | { |
538 | int i, lp_len; | 686 | int i, lp_len; |
539 | 687 | ||
@@ -552,35 +700,128 @@ static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj, | |||
552 | return -EINVAL; | 700 | return -EINVAL; |
553 | } | 701 | } |
554 | /* initialize loadparm with blanks */ | 702 | /* initialize loadparm with blanks */ |
555 | memset(&reipl_block_ccw->ipl_info.ccw.load_param, ' ', LOADPARM_LEN); | 703 | memset(ipb->ipl_info.ccw.load_parm, ' ', LOADPARM_LEN); |
556 | /* copy and convert to ebcdic */ | 704 | /* copy and convert to ebcdic */ |
557 | memcpy(&reipl_block_ccw->ipl_info.ccw.load_param, buf, lp_len); | 705 | memcpy(ipb->ipl_info.ccw.load_parm, buf, lp_len); |
558 | ASCEBC(reipl_block_ccw->ipl_info.ccw.load_param, LOADPARM_LEN); | 706 | ASCEBC(ipb->ipl_info.ccw.load_parm, LOADPARM_LEN); |
559 | return len; | 707 | return len; |
560 | } | 708 | } |
561 | 709 | ||
710 | /* NSS wrapper */ | ||
711 | static ssize_t reipl_nss_loadparm_show(struct kobject *kobj, | ||
712 | struct kobj_attribute *attr, char *page) | ||
713 | { | ||
714 | return reipl_generic_loadparm_show(reipl_block_nss, page); | ||
715 | } | ||
716 | |||
717 | static ssize_t reipl_nss_loadparm_store(struct kobject *kobj, | ||
718 | struct kobj_attribute *attr, | ||
719 | const char *buf, size_t len) | ||
720 | { | ||
721 | return reipl_generic_loadparm_store(reipl_block_nss, buf, len); | ||
722 | } | ||
723 | |||
724 | /* CCW wrapper */ | ||
725 | static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj, | ||
726 | struct kobj_attribute *attr, char *page) | ||
727 | { | ||
728 | return reipl_generic_loadparm_show(reipl_block_ccw, page); | ||
729 | } | ||
730 | |||
731 | static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj, | ||
732 | struct kobj_attribute *attr, | ||
733 | const char *buf, size_t len) | ||
734 | { | ||
735 | return reipl_generic_loadparm_store(reipl_block_ccw, buf, len); | ||
736 | } | ||
737 | |||
562 | static struct kobj_attribute sys_reipl_ccw_loadparm_attr = | 738 | static struct kobj_attribute sys_reipl_ccw_loadparm_attr = |
563 | __ATTR(loadparm, 0644, reipl_ccw_loadparm_show, | 739 | __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_ccw_loadparm_show, |
564 | reipl_ccw_loadparm_store); | 740 | reipl_ccw_loadparm_store); |
741 | |||
742 | static struct attribute *reipl_ccw_attrs_vm[] = { | ||
743 | &sys_reipl_ccw_device_attr.attr, | ||
744 | &sys_reipl_ccw_loadparm_attr.attr, | ||
745 | &sys_reipl_ccw_vmparm_attr.attr, | ||
746 | NULL, | ||
747 | }; | ||
565 | 748 | ||
566 | static struct attribute *reipl_ccw_attrs[] = { | 749 | static struct attribute *reipl_ccw_attrs_lpar[] = { |
567 | &sys_reipl_ccw_device_attr.attr, | 750 | &sys_reipl_ccw_device_attr.attr, |
568 | &sys_reipl_ccw_loadparm_attr.attr, | 751 | &sys_reipl_ccw_loadparm_attr.attr, |
569 | NULL, | 752 | NULL, |
570 | }; | 753 | }; |
571 | 754 | ||
572 | static struct attribute_group reipl_ccw_attr_group = { | 755 | static struct attribute_group reipl_ccw_attr_group_vm = { |
573 | .name = IPL_CCW_STR, | 756 | .name = IPL_CCW_STR, |
574 | .attrs = reipl_ccw_attrs, | 757 | .attrs = reipl_ccw_attrs_vm, |
758 | }; | ||
759 | |||
760 | static struct attribute_group reipl_ccw_attr_group_lpar = { | ||
761 | .name = IPL_CCW_STR, | ||
762 | .attrs = reipl_ccw_attrs_lpar, | ||
575 | }; | 763 | }; |
576 | 764 | ||
577 | 765 | ||
578 | /* NSS reipl device attributes */ | 766 | /* NSS reipl device attributes */ |
767 | static void reipl_get_ascii_nss_name(char *dst, | ||
768 | struct ipl_parameter_block *ipb) | ||
769 | { | ||
770 | memcpy(dst, ipb->ipl_info.ccw.nss_name, NSS_NAME_SIZE); | ||
771 | EBCASC(dst, NSS_NAME_SIZE); | ||
772 | dst[NSS_NAME_SIZE] = 0; | ||
773 | } | ||
774 | |||
775 | static ssize_t reipl_nss_name_show(struct kobject *kobj, | ||
776 | struct kobj_attribute *attr, char *page) | ||
777 | { | ||
778 | char nss_name[NSS_NAME_SIZE + 1] = {}; | ||
779 | |||
780 | reipl_get_ascii_nss_name(nss_name, reipl_block_nss); | ||
781 | return sprintf(page, "%s\n", nss_name); | ||
782 | } | ||
783 | |||
784 | static ssize_t reipl_nss_name_store(struct kobject *kobj, | ||
785 | struct kobj_attribute *attr, | ||
786 | const char *buf, size_t len) | ||
787 | { | ||
788 | int nss_len; | ||
789 | |||
790 | /* ignore trailing newline */ | ||
791 | nss_len = len; | ||
792 | if ((len > 0) && (buf[len - 1] == '\n')) | ||
793 | nss_len--; | ||
579 | 794 | ||
580 | DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name); | 795 | if (nss_len > NSS_NAME_SIZE) |
796 | return -EINVAL; | ||
797 | |||
798 | memset(reipl_block_nss->ipl_info.ccw.nss_name, 0x40, NSS_NAME_SIZE); | ||
799 | if (nss_len > 0) { | ||
800 | reipl_block_nss->ipl_info.ccw.vm_flags |= | ||
801 | DIAG308_VM_FLAGS_NSS_VALID; | ||
802 | memcpy(reipl_block_nss->ipl_info.ccw.nss_name, buf, nss_len); | ||
803 | ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, nss_len); | ||
804 | EBC_TOUPPER(reipl_block_nss->ipl_info.ccw.nss_name, nss_len); | ||
805 | } else { | ||
806 | reipl_block_nss->ipl_info.ccw.vm_flags &= | ||
807 | ~DIAG308_VM_FLAGS_NSS_VALID; | ||
808 | } | ||
809 | |||
810 | return len; | ||
811 | } | ||
812 | |||
813 | static struct kobj_attribute sys_reipl_nss_name_attr = | ||
814 | __ATTR(name, S_IRUGO | S_IWUSR, reipl_nss_name_show, | ||
815 | reipl_nss_name_store); | ||
816 | |||
817 | static struct kobj_attribute sys_reipl_nss_loadparm_attr = | ||
818 | __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nss_loadparm_show, | ||
819 | reipl_nss_loadparm_store); | ||
581 | 820 | ||
582 | static struct attribute *reipl_nss_attrs[] = { | 821 | static struct attribute *reipl_nss_attrs[] = { |
583 | &sys_reipl_nss_name_attr.attr, | 822 | &sys_reipl_nss_name_attr.attr, |
823 | &sys_reipl_nss_loadparm_attr.attr, | ||
824 | &sys_reipl_nss_vmparm_attr.attr, | ||
584 | NULL, | 825 | NULL, |
585 | }; | 826 | }; |
586 | 827 | ||
@@ -617,7 +858,10 @@ static int reipl_set_type(enum ipl_type type) | |||
617 | reipl_method = REIPL_METHOD_FCP_DUMP; | 858 | reipl_method = REIPL_METHOD_FCP_DUMP; |
618 | break; | 859 | break; |
619 | case IPL_TYPE_NSS: | 860 | case IPL_TYPE_NSS: |
620 | reipl_method = REIPL_METHOD_NSS; | 861 | if (diag308_set_works) |
862 | reipl_method = REIPL_METHOD_NSS_DIAG; | ||
863 | else | ||
864 | reipl_method = REIPL_METHOD_NSS; | ||
621 | break; | 865 | break; |
622 | case IPL_TYPE_UNKNOWN: | 866 | case IPL_TYPE_UNKNOWN: |
623 | reipl_method = REIPL_METHOD_DEFAULT; | 867 | reipl_method = REIPL_METHOD_DEFAULT; |
@@ -655,11 +899,38 @@ static struct kobj_attribute reipl_type_attr = | |||
655 | 899 | ||
656 | static struct kset *reipl_kset; | 900 | static struct kset *reipl_kset; |
657 | 901 | ||
902 | static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb, | ||
903 | const enum ipl_method m) | ||
904 | { | ||
905 | char loadparm[LOADPARM_LEN + 1] = {}; | ||
906 | char vmparm[DIAG308_VMPARM_SIZE + 1] = {}; | ||
907 | char nss_name[NSS_NAME_SIZE + 1] = {}; | ||
908 | size_t pos = 0; | ||
909 | |||
910 | reipl_get_ascii_loadparm(loadparm, ipb); | ||
911 | reipl_get_ascii_nss_name(nss_name, ipb); | ||
912 | reipl_get_ascii_vmparm(vmparm, ipb); | ||
913 | |||
914 | switch (m) { | ||
915 | case REIPL_METHOD_CCW_VM: | ||
916 | pos = sprintf(dst, "IPL %X CLEAR", ipb->ipl_info.ccw.devno); | ||
917 | break; | ||
918 | case REIPL_METHOD_NSS: | ||
919 | pos = sprintf(dst, "IPL %s", nss_name); | ||
920 | break; | ||
921 | default: | ||
922 | break; | ||
923 | } | ||
924 | if (strlen(loadparm) > 0) | ||
925 | pos += sprintf(dst + pos, " LOADPARM '%s'", loadparm); | ||
926 | if (strlen(vmparm) > 0) | ||
927 | sprintf(dst + pos, " PARM %s", vmparm); | ||
928 | } | ||
929 | |||
658 | static void reipl_run(struct shutdown_trigger *trigger) | 930 | static void reipl_run(struct shutdown_trigger *trigger) |
659 | { | 931 | { |
660 | struct ccw_dev_id devid; | 932 | struct ccw_dev_id devid; |
661 | static char buf[100]; | 933 | static char buf[128]; |
662 | char loadparm[LOADPARM_LEN + 1]; | ||
663 | 934 | ||
664 | switch (reipl_method) { | 935 | switch (reipl_method) { |
665 | case REIPL_METHOD_CCW_CIO: | 936 | case REIPL_METHOD_CCW_CIO: |
@@ -668,13 +939,7 @@ static void reipl_run(struct shutdown_trigger *trigger) | |||
668 | reipl_ccw_dev(&devid); | 939 | reipl_ccw_dev(&devid); |
669 | break; | 940 | break; |
670 | case REIPL_METHOD_CCW_VM: | 941 | case REIPL_METHOD_CCW_VM: |
671 | reipl_get_ascii_loadparm(loadparm); | 942 | get_ipl_string(buf, reipl_block_ccw, REIPL_METHOD_CCW_VM); |
672 | if (strlen(loadparm) == 0) | ||
673 | sprintf(buf, "IPL %X CLEAR", | ||
674 | reipl_block_ccw->ipl_info.ccw.devno); | ||
675 | else | ||
676 | sprintf(buf, "IPL %X CLEAR LOADPARM '%s'", | ||
677 | reipl_block_ccw->ipl_info.ccw.devno, loadparm); | ||
678 | __cpcmd(buf, NULL, 0, NULL); | 943 | __cpcmd(buf, NULL, 0, NULL); |
679 | break; | 944 | break; |
680 | case REIPL_METHOD_CCW_DIAG: | 945 | case REIPL_METHOD_CCW_DIAG: |
@@ -691,8 +956,12 @@ static void reipl_run(struct shutdown_trigger *trigger) | |||
691 | case REIPL_METHOD_FCP_RO_VM: | 956 | case REIPL_METHOD_FCP_RO_VM: |
692 | __cpcmd("IPL", NULL, 0, NULL); | 957 | __cpcmd("IPL", NULL, 0, NULL); |
693 | break; | 958 | break; |
959 | case REIPL_METHOD_NSS_DIAG: | ||
960 | diag308(DIAG308_SET, reipl_block_nss); | ||
961 | diag308(DIAG308_IPL, NULL); | ||
962 | break; | ||
694 | case REIPL_METHOD_NSS: | 963 | case REIPL_METHOD_NSS: |
695 | sprintf(buf, "IPL %s", reipl_nss_name); | 964 | get_ipl_string(buf, reipl_block_nss, REIPL_METHOD_NSS); |
696 | __cpcmd(buf, NULL, 0, NULL); | 965 | __cpcmd(buf, NULL, 0, NULL); |
697 | break; | 966 | break; |
698 | case REIPL_METHOD_DEFAULT: | 967 | case REIPL_METHOD_DEFAULT: |
@@ -707,16 +976,36 @@ static void reipl_run(struct shutdown_trigger *trigger) | |||
707 | disabled_wait((unsigned long) __builtin_return_address(0)); | 976 | disabled_wait((unsigned long) __builtin_return_address(0)); |
708 | } | 977 | } |
709 | 978 | ||
710 | static void __init reipl_probe(void) | 979 | static void reipl_block_ccw_init(struct ipl_parameter_block *ipb) |
711 | { | 980 | { |
712 | void *buffer; | 981 | ipb->hdr.len = IPL_PARM_BLK_CCW_LEN; |
982 | ipb->hdr.version = IPL_PARM_BLOCK_VERSION; | ||
983 | ipb->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; | ||
984 | ipb->hdr.pbt = DIAG308_IPL_TYPE_CCW; | ||
985 | } | ||
713 | 986 | ||
714 | buffer = (void *) get_zeroed_page(GFP_KERNEL); | 987 | static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb) |
715 | if (!buffer) | 988 | { |
716 | return; | 989 | /* LOADPARM */ |
717 | if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK) | 990 | /* check if read scp info worked and set loadparm */ |
718 | diag308_set_works = 1; | 991 | if (sclp_ipl_info.is_valid) |
719 | free_page((unsigned long)buffer); | 992 | memcpy(ipb->ipl_info.ccw.load_parm, |
993 | &sclp_ipl_info.loadparm, LOADPARM_LEN); | ||
994 | else | ||
995 | /* read scp info failed: set empty loadparm (EBCDIC blanks) */ | ||
996 | memset(ipb->ipl_info.ccw.load_parm, 0x40, LOADPARM_LEN); | ||
997 | ipb->hdr.flags = DIAG308_FLAGS_LP_VALID; | ||
998 | |||
999 | /* VM PARM */ | ||
1000 | if (MACHINE_IS_VM && diag308_set_works && | ||
1001 | (ipl_block.ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID)) { | ||
1002 | |||
1003 | ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID; | ||
1004 | ipb->ipl_info.ccw.vm_parm_len = | ||
1005 | ipl_block.ipl_info.ccw.vm_parm_len; | ||
1006 | memcpy(ipb->ipl_info.ccw.vm_parm, | ||
1007 | ipl_block.ipl_info.ccw.vm_parm, DIAG308_VMPARM_SIZE); | ||
1008 | } | ||
720 | } | 1009 | } |
721 | 1010 | ||
722 | static int __init reipl_nss_init(void) | 1011 | static int __init reipl_nss_init(void) |
@@ -725,10 +1014,31 @@ static int __init reipl_nss_init(void) | |||
725 | 1014 | ||
726 | if (!MACHINE_IS_VM) | 1015 | if (!MACHINE_IS_VM) |
727 | return 0; | 1016 | return 0; |
1017 | |||
1018 | reipl_block_nss = (void *) get_zeroed_page(GFP_KERNEL); | ||
1019 | if (!reipl_block_nss) | ||
1020 | return -ENOMEM; | ||
1021 | |||
1022 | if (!diag308_set_works) | ||
1023 | sys_reipl_nss_vmparm_attr.attr.mode = S_IRUGO; | ||
1024 | |||
728 | rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group); | 1025 | rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group); |
729 | if (rc) | 1026 | if (rc) |
730 | return rc; | 1027 | return rc; |
731 | strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1); | 1028 | |
1029 | reipl_block_ccw_init(reipl_block_nss); | ||
1030 | if (ipl_info.type == IPL_TYPE_NSS) { | ||
1031 | memset(reipl_block_nss->ipl_info.ccw.nss_name, | ||
1032 | ' ', NSS_NAME_SIZE); | ||
1033 | memcpy(reipl_block_nss->ipl_info.ccw.nss_name, | ||
1034 | kernel_nss_name, strlen(kernel_nss_name)); | ||
1035 | ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, NSS_NAME_SIZE); | ||
1036 | reipl_block_nss->ipl_info.ccw.vm_flags |= | ||
1037 | DIAG308_VM_FLAGS_NSS_VALID; | ||
1038 | |||
1039 | reipl_block_ccw_fill_parms(reipl_block_nss); | ||
1040 | } | ||
1041 | |||
732 | reipl_capabilities |= IPL_TYPE_NSS; | 1042 | reipl_capabilities |= IPL_TYPE_NSS; |
733 | return 0; | 1043 | return 0; |
734 | } | 1044 | } |
@@ -740,28 +1050,27 @@ static int __init reipl_ccw_init(void) | |||
740 | reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL); | 1050 | reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL); |
741 | if (!reipl_block_ccw) | 1051 | if (!reipl_block_ccw) |
742 | return -ENOMEM; | 1052 | return -ENOMEM; |
743 | rc = sysfs_create_group(&reipl_kset->kobj, &reipl_ccw_attr_group); | 1053 | |
744 | if (rc) { | 1054 | if (MACHINE_IS_VM) { |
745 | free_page((unsigned long)reipl_block_ccw); | 1055 | if (!diag308_set_works) |
746 | return rc; | 1056 | sys_reipl_ccw_vmparm_attr.attr.mode = S_IRUGO; |
1057 | rc = sysfs_create_group(&reipl_kset->kobj, | ||
1058 | &reipl_ccw_attr_group_vm); | ||
1059 | } else { | ||
1060 | if(!diag308_set_works) | ||
1061 | sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO; | ||
1062 | rc = sysfs_create_group(&reipl_kset->kobj, | ||
1063 | &reipl_ccw_attr_group_lpar); | ||
747 | } | 1064 | } |
748 | reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN; | 1065 | if (rc) |
749 | reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION; | 1066 | return rc; |
750 | reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; | 1067 | |
751 | reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; | 1068 | reipl_block_ccw_init(reipl_block_ccw); |
752 | reipl_block_ccw->hdr.flags = DIAG308_FLAGS_LP_VALID; | 1069 | if (ipl_info.type == IPL_TYPE_CCW) { |
753 | /* check if read scp info worked and set loadparm */ | ||
754 | if (sclp_ipl_info.is_valid) | ||
755 | memcpy(reipl_block_ccw->ipl_info.ccw.load_param, | ||
756 | &sclp_ipl_info.loadparm, LOADPARM_LEN); | ||
757 | else | ||
758 | /* read scp info failed: set empty loadparm (EBCDIC blanks) */ | ||
759 | memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40, | ||
760 | LOADPARM_LEN); | ||
761 | if (!MACHINE_IS_VM && !diag308_set_works) | ||
762 | sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO; | ||
763 | if (ipl_info.type == IPL_TYPE_CCW) | ||
764 | reipl_block_ccw->ipl_info.ccw.devno = ipl_devno; | 1070 | reipl_block_ccw->ipl_info.ccw.devno = ipl_devno; |
1071 | reipl_block_ccw_fill_parms(reipl_block_ccw); | ||
1072 | } | ||
1073 | |||
765 | reipl_capabilities |= IPL_TYPE_CCW; | 1074 | reipl_capabilities |= IPL_TYPE_CCW; |
766 | return 0; | 1075 | return 0; |
767 | } | 1076 | } |
@@ -1298,7 +1607,6 @@ static void __init shutdown_actions_init(void) | |||
1298 | 1607 | ||
1299 | static int __init s390_ipl_init(void) | 1608 | static int __init s390_ipl_init(void) |
1300 | { | 1609 | { |
1301 | reipl_probe(); | ||
1302 | sclp_get_ipl_info(&sclp_ipl_info); | 1610 | sclp_get_ipl_info(&sclp_ipl_info); |
1303 | shutdown_actions_init(); | 1611 | shutdown_actions_init(); |
1304 | shutdown_triggers_init(); | 1612 | shutdown_triggers_init(); |
@@ -1405,6 +1713,12 @@ void __init setup_ipl(void) | |||
1405 | atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); | 1713 | atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); |
1406 | } | 1714 | } |
1407 | 1715 | ||
1716 | void __init ipl_update_parameters(void) | ||
1717 | { | ||
1718 | if (diag308(DIAG308_STORE, &ipl_block) == DIAG308_RC_OK) | ||
1719 | diag308_set_works = 1; | ||
1720 | } | ||
1721 | |||
1408 | void __init ipl_save_parameters(void) | 1722 | void __init ipl_save_parameters(void) |
1409 | { | 1723 | { |
1410 | struct cio_iplinfo iplinfo; | 1724 | struct cio_iplinfo iplinfo; |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index b91caadf974d..e3b4cdbae34e 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -221,18 +221,17 @@ static void __init conmode_default(void) | |||
221 | #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) | 221 | #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) |
222 | static void __init setup_zfcpdump(unsigned int console_devno) | 222 | static void __init setup_zfcpdump(unsigned int console_devno) |
223 | { | 223 | { |
224 | static char str[64]; | 224 | static char str[41]; |
225 | 225 | ||
226 | if (ipl_info.type != IPL_TYPE_FCP_DUMP) | 226 | if (ipl_info.type != IPL_TYPE_FCP_DUMP) |
227 | return; | 227 | return; |
228 | if (console_devno != -1) | 228 | if (console_devno != -1) |
229 | sprintf(str, "cio_ignore=all,!0.0.%04x,!0.0.%04x", | 229 | sprintf(str, " cio_ignore=all,!0.0.%04x,!0.0.%04x", |
230 | ipl_info.data.fcp.dev_id.devno, console_devno); | 230 | ipl_info.data.fcp.dev_id.devno, console_devno); |
231 | else | 231 | else |
232 | sprintf(str, "cio_ignore=all,!0.0.%04x", | 232 | sprintf(str, " cio_ignore=all,!0.0.%04x", |
233 | ipl_info.data.fcp.dev_id.devno); | 233 | ipl_info.data.fcp.dev_id.devno); |
234 | strcat(COMMAND_LINE, " "); | 234 | strcat(boot_command_line, str); |
235 | strcat(COMMAND_LINE, str); | ||
236 | console_loglevel = 2; | 235 | console_loglevel = 2; |
237 | } | 236 | } |
238 | #else | 237 | #else |
@@ -778,11 +777,9 @@ setup_arch(char **cmdline_p) | |||
778 | printk("We are running native (64 bit mode)\n"); | 777 | printk("We are running native (64 bit mode)\n"); |
779 | #endif /* CONFIG_64BIT */ | 778 | #endif /* CONFIG_64BIT */ |
780 | 779 | ||
781 | /* Save unparsed command line copy for /proc/cmdline */ | 780 | /* Have one command line that is parsed and saved in /proc/cmdline */ |
782 | strlcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); | 781 | /* boot_command_line has been already set up in early.c */ |
783 | 782 | *cmdline_p = boot_command_line; | |
784 | *cmdline_p = COMMAND_LINE; | ||
785 | *(*cmdline_p + COMMAND_LINE_SIZE - 1) = '\0'; | ||
786 | 783 | ||
787 | ROOT_DEV = Root_RAM0; | 784 | ROOT_DEV = Root_RAM0; |
788 | 785 | ||