2 * arch/s390/kernel/ipl.c
3 * ipl/reipl/dump support for Linux on s390.
5 * Copyright (C) IBM Corp. 2005,2006
6 * Author(s): Michael Holzheu <holzheu@de.ibm.com>
7 * Heiko Carstens <heiko.carstens@de.ibm.com>
8 * Volker Sameske <sameske@de.ibm.com>
11 #include <linux/types.h>
12 #include <linux/module.h>
13 #include <linux/device.h>
14 #include <linux/delay.h>
15 #include <linux/reboot.h>
16 #include <linux/ctype.h>
18 #include <asm/setup.h>
19 #include <asm/cpcmd.h>
21 #include <asm/ebcdic.h>
23 #define IPL_PARM_BLOCK_VERSION 0
24 #define LOADPARM_LEN 8
26 extern char s390_readinfo_sccb[];
27 #define SCCB_VALID (*((__u16*)&s390_readinfo_sccb[6]) == 0x0010)
28 #define SCCB_LOADPARM (&s390_readinfo_sccb[24])
29 #define SCCB_FLAG (s390_readinfo_sccb[91])
38 #define IPL_NONE_STR "none"
39 #define IPL_UNKNOWN_STR "unknown"
40 #define IPL_CCW_STR "ccw"
41 #define IPL_FCP_STR "fcp"
43 static char *ipl_type_str(enum ipl_type type)
52 case IPL_TYPE_UNKNOWN:
54 return IPL_UNKNOWN_STR;
63 IPL_METHOD_FCP_RO_DIAG,
64 IPL_METHOD_FCP_RW_DIAG,
68 enum shutdown_action {
74 #define SHUTDOWN_REIPL_STR "reipl"
75 #define SHUTDOWN_DUMP_STR "dump"
76 #define SHUTDOWN_STOP_STR "stop"
78 static char *shutdown_action_str(enum shutdown_action action)
82 return SHUTDOWN_REIPL_STR;
84 return SHUTDOWN_DUMP_STR;
86 return SHUTDOWN_STOP_STR;
92 enum diag308_subcode {
99 enum diag308_ipl_type {
100 DIAG308_IPL_TYPE_FCP = 0,
101 DIAG308_IPL_TYPE_CCW = 2,
105 DIAG308_IPL_OPT_IPL = 0x10,
106 DIAG308_IPL_OPT_DUMP = 0x20,
113 static int diag308_set_works = 0;
115 static int reipl_capabilities = IPL_TYPE_UNKNOWN;
116 static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
117 static enum ipl_method reipl_method = IPL_METHOD_NONE;
118 static struct ipl_parameter_block *reipl_block_fcp;
119 static struct ipl_parameter_block *reipl_block_ccw;
121 static int dump_capabilities = IPL_TYPE_NONE;
122 static enum ipl_type dump_type = IPL_TYPE_NONE;
123 static enum ipl_method dump_method = IPL_METHOD_NONE;
124 static struct ipl_parameter_block *dump_block_fcp;
125 static struct ipl_parameter_block *dump_block_ccw;
127 static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
129 static int diag308(unsigned long subcode, void *addr)
131 register unsigned long _addr asm("0") = (unsigned long) addr;
132 register unsigned long _rc asm("1") = 0;
135 " diag %0,%2,0x308\n"
138 : "+d" (_addr), "+d" (_rc)
139 : "d" (subcode) : "cc", "memory");
145 #define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \
146 static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \
149 return sprintf(page, _format, _value); \
151 static struct subsys_attribute sys_##_prefix##_##_name##_attr = \
152 __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL);
154 #define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \
155 static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \
158 return sprintf(page, _fmt_out, \
159 (unsigned long long) _value); \
161 static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
162 const char *buf, size_t len) \
164 unsigned long long value; \
165 if (sscanf(buf, _fmt_in, &value) != 1) \
170 static struct subsys_attribute sys_##_prefix##_##_name##_attr = \
171 __ATTR(_name,(S_IRUGO | S_IWUSR), \
172 sys_##_prefix##_##_name##_show, \
173 sys_##_prefix##_##_name##_store);
175 static void make_attrs_ro(struct attribute **attrs)
178 (*attrs)->mode = S_IRUGO;
187 static enum ipl_type ipl_get_type(void)
189 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
191 if (!(ipl_flags & IPL_DEVNO_VALID))
192 return IPL_TYPE_UNKNOWN;
193 if (!(ipl_flags & IPL_PARMBLOCK_VALID))
195 if (ipl->hdr.version > IPL_MAX_SUPPORTED_VERSION)
196 return IPL_TYPE_UNKNOWN;
197 if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP)
198 return IPL_TYPE_UNKNOWN;
202 static ssize_t ipl_type_show(struct subsystem *subsys, char *page)
204 return sprintf(page, "%s\n", ipl_type_str(ipl_get_type()));
207 static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
209 static ssize_t sys_ipl_device_show(struct subsystem *subsys, char *page)
211 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
213 switch (ipl_get_type()) {
215 return sprintf(page, "0.0.%04x\n", ipl_devno);
217 return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno);
223 static struct subsys_attribute sys_ipl_device_attr =
224 __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
226 static ssize_t ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off,
229 unsigned int size = IPL_PARMBLOCK_SIZE;
233 if (off + count > size)
235 memcpy(buf, (void *)IPL_PARMBLOCK_START + off, count);
239 static struct bin_attribute ipl_parameter_attr = {
241 .name = "binary_parameter",
243 .owner = THIS_MODULE,
246 .read = &ipl_parameter_read,
249 static ssize_t ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off,
252 unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
253 void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
257 if (off + count > size)
259 memcpy(buf, scp_data + off, count);
263 static struct bin_attribute ipl_scp_data_attr = {
267 .owner = THIS_MODULE,
270 .read = &ipl_scp_data_read,
273 /* FCP ipl device attributes */
275 DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n", (unsigned long long)
276 IPL_PARMBLOCK_START->ipl_info.fcp.wwpn);
277 DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n", (unsigned long long)
278 IPL_PARMBLOCK_START->ipl_info.fcp.lun);
279 DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long)
280 IPL_PARMBLOCK_START->ipl_info.fcp.bootprog);
281 DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
282 IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
284 static struct attribute *ipl_fcp_attrs[] = {
285 &sys_ipl_type_attr.attr,
286 &sys_ipl_device_attr.attr,
287 &sys_ipl_fcp_wwpn_attr.attr,
288 &sys_ipl_fcp_lun_attr.attr,
289 &sys_ipl_fcp_bootprog_attr.attr,
290 &sys_ipl_fcp_br_lba_attr.attr,
294 static struct attribute_group ipl_fcp_attr_group = {
295 .attrs = ipl_fcp_attrs,
298 /* CCW ipl device attributes */
300 static ssize_t ipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
302 char loadparm[LOADPARM_LEN + 1] = {};
305 return sprintf(page, "#unknown#\n");
306 memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN);
307 EBCASC(loadparm, LOADPARM_LEN);
309 return sprintf(page, "%s\n", loadparm);
312 static struct subsys_attribute sys_ipl_ccw_loadparm_attr =
313 __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
315 static struct attribute *ipl_ccw_attrs[] = {
316 &sys_ipl_type_attr.attr,
317 &sys_ipl_device_attr.attr,
318 &sys_ipl_ccw_loadparm_attr.attr,
322 static struct attribute_group ipl_ccw_attr_group = {
323 .attrs = ipl_ccw_attrs,
326 /* UNKNOWN ipl device attributes */
328 static struct attribute *ipl_unknown_attrs[] = {
329 &sys_ipl_type_attr.attr,
333 static struct attribute_group ipl_unknown_attr_group = {
334 .attrs = ipl_unknown_attrs,
337 static decl_subsys(ipl, NULL, NULL);
343 /* FCP reipl device attributes */
345 DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n",
346 reipl_block_fcp->ipl_info.fcp.wwpn);
347 DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%016llx\n",
348 reipl_block_fcp->ipl_info.fcp.lun);
349 DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
350 reipl_block_fcp->ipl_info.fcp.bootprog);
351 DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
352 reipl_block_fcp->ipl_info.fcp.br_lba);
353 DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
354 reipl_block_fcp->ipl_info.fcp.devno);
356 static struct attribute *reipl_fcp_attrs[] = {
357 &sys_reipl_fcp_device_attr.attr,
358 &sys_reipl_fcp_wwpn_attr.attr,
359 &sys_reipl_fcp_lun_attr.attr,
360 &sys_reipl_fcp_bootprog_attr.attr,
361 &sys_reipl_fcp_br_lba_attr.attr,
365 static struct attribute_group reipl_fcp_attr_group = {
367 .attrs = reipl_fcp_attrs,
370 /* CCW reipl device attributes */
372 DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
373 reipl_block_ccw->ipl_info.ccw.devno);
375 static void reipl_get_ascii_loadparm(char *loadparm)
377 memcpy(loadparm, &reipl_block_ccw->ipl_info.ccw.load_param,
379 EBCASC(loadparm, LOADPARM_LEN);
380 loadparm[LOADPARM_LEN] = 0;
384 static ssize_t reipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
386 char buf[LOADPARM_LEN + 1];
388 reipl_get_ascii_loadparm(buf);
389 return sprintf(page, "%s\n", buf);
392 static ssize_t reipl_ccw_loadparm_store(struct subsystem *subsys,
393 const char *buf, size_t len)
397 /* ignore trailing newline */
399 if ((len > 0) && (buf[len - 1] == '\n'))
401 /* loadparm can have max 8 characters and must not start with a blank */
402 if ((lp_len > LOADPARM_LEN) || ((lp_len > 0) && (buf[0] == ' ')))
404 /* loadparm can only contain "a-z,A-Z,0-9,SP,." */
405 for (i = 0; i < lp_len; i++) {
406 if (isalpha(buf[i]) || isdigit(buf[i]) || (buf[i] == ' ') ||
411 /* initialize loadparm with blanks */
412 memset(&reipl_block_ccw->ipl_info.ccw.load_param, ' ', LOADPARM_LEN);
413 /* copy and convert to ebcdic */
414 memcpy(&reipl_block_ccw->ipl_info.ccw.load_param, buf, lp_len);
415 ASCEBC(reipl_block_ccw->ipl_info.ccw.load_param, LOADPARM_LEN);
419 static struct subsys_attribute sys_reipl_ccw_loadparm_attr =
420 __ATTR(loadparm, 0644, reipl_ccw_loadparm_show,
421 reipl_ccw_loadparm_store);
423 static struct attribute *reipl_ccw_attrs[] = {
424 &sys_reipl_ccw_device_attr.attr,
425 &sys_reipl_ccw_loadparm_attr.attr,
429 static struct attribute_group reipl_ccw_attr_group = {
431 .attrs = reipl_ccw_attrs,
436 static int reipl_set_type(enum ipl_type type)
438 if (!(reipl_capabilities & type))
444 reipl_method = IPL_METHOD_CCW_VM;
446 reipl_method = IPL_METHOD_CCW_CIO;
449 if (diag308_set_works)
450 reipl_method = IPL_METHOD_FCP_RW_DIAG;
451 else if (MACHINE_IS_VM)
452 reipl_method = IPL_METHOD_FCP_RO_VM;
454 reipl_method = IPL_METHOD_FCP_RO_DIAG;
457 reipl_method = IPL_METHOD_NONE;
463 static ssize_t reipl_type_show(struct subsystem *subsys, char *page)
465 return sprintf(page, "%s\n", ipl_type_str(reipl_type));
468 static ssize_t reipl_type_store(struct subsystem *subsys, const char *buf,
473 if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
474 rc = reipl_set_type(IPL_TYPE_CCW);
475 else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
476 rc = reipl_set_type(IPL_TYPE_FCP);
477 return (rc != 0) ? rc : len;
480 static struct subsys_attribute reipl_type_attr =
481 __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
483 static decl_subsys(reipl, NULL, NULL);
489 /* FCP dump device attributes */
491 DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n",
492 dump_block_fcp->ipl_info.fcp.wwpn);
493 DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n",
494 dump_block_fcp->ipl_info.fcp.lun);
495 DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
496 dump_block_fcp->ipl_info.fcp.bootprog);
497 DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
498 dump_block_fcp->ipl_info.fcp.br_lba);
499 DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
500 dump_block_fcp->ipl_info.fcp.devno);
502 static struct attribute *dump_fcp_attrs[] = {
503 &sys_dump_fcp_device_attr.attr,
504 &sys_dump_fcp_wwpn_attr.attr,
505 &sys_dump_fcp_lun_attr.attr,
506 &sys_dump_fcp_bootprog_attr.attr,
507 &sys_dump_fcp_br_lba_attr.attr,
511 static struct attribute_group dump_fcp_attr_group = {
513 .attrs = dump_fcp_attrs,
516 /* CCW dump device attributes */
518 DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
519 dump_block_ccw->ipl_info.ccw.devno);
521 static struct attribute *dump_ccw_attrs[] = {
522 &sys_dump_ccw_device_attr.attr,
526 static struct attribute_group dump_ccw_attr_group = {
528 .attrs = dump_ccw_attrs,
533 static int dump_set_type(enum ipl_type type)
535 if (!(dump_capabilities & type))
540 dump_method = IPL_METHOD_CCW_VM;
542 dump_method = IPL_METHOD_CCW_CIO;
545 dump_method = IPL_METHOD_FCP_RW_DIAG;
548 dump_method = IPL_METHOD_NONE;
554 static ssize_t dump_type_show(struct subsystem *subsys, char *page)
556 return sprintf(page, "%s\n", ipl_type_str(dump_type));
559 static ssize_t dump_type_store(struct subsystem *subsys, const char *buf,
564 if (strncmp(buf, IPL_NONE_STR, strlen(IPL_NONE_STR)) == 0)
565 rc = dump_set_type(IPL_TYPE_NONE);
566 else if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
567 rc = dump_set_type(IPL_TYPE_CCW);
568 else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
569 rc = dump_set_type(IPL_TYPE_FCP);
570 return (rc != 0) ? rc : len;
573 static struct subsys_attribute dump_type_attr =
574 __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
576 static decl_subsys(dump, NULL, NULL);
579 static void dump_smp_stop_all(void)
583 for_each_online_cpu(cpu) {
584 if (cpu == smp_processor_id())
586 while (signal_processor(cpu, sigp_stop) == sigp_busy)
592 #define dump_smp_stop_all() do { } while (0)
596 * Shutdown actions section
599 static decl_subsys(shutdown_actions, NULL, NULL);
603 static ssize_t on_panic_show(struct subsystem *subsys, char *page)
605 return sprintf(page, "%s\n", shutdown_action_str(on_panic_action));
608 static ssize_t on_panic_store(struct subsystem *subsys, const char *buf,
611 if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0)
612 on_panic_action = SHUTDOWN_REIPL;
613 else if (strncmp(buf, SHUTDOWN_DUMP_STR,
614 strlen(SHUTDOWN_DUMP_STR)) == 0)
615 on_panic_action = SHUTDOWN_DUMP;
616 else if (strncmp(buf, SHUTDOWN_STOP_STR,
617 strlen(SHUTDOWN_STOP_STR)) == 0)
618 on_panic_action = SHUTDOWN_STOP;
625 static struct subsys_attribute on_panic_attr =
626 __ATTR(on_panic, 0644, on_panic_show, on_panic_store);
628 static void print_fcp_block(struct ipl_parameter_block *fcp_block)
630 printk(KERN_EMERG "wwpn: %016llx\n",
631 (unsigned long long)fcp_block->ipl_info.fcp.wwpn);
632 printk(KERN_EMERG "lun: %016llx\n",
633 (unsigned long long)fcp_block->ipl_info.fcp.lun);
634 printk(KERN_EMERG "bootprog: %lld\n",
635 (unsigned long long)fcp_block->ipl_info.fcp.bootprog);
636 printk(KERN_EMERG "br_lba: %lld\n",
637 (unsigned long long)fcp_block->ipl_info.fcp.br_lba);
638 printk(KERN_EMERG "device: %llx\n",
639 (unsigned long long)fcp_block->ipl_info.fcp.devno);
640 printk(KERN_EMERG "opt: %x\n", fcp_block->ipl_info.fcp.opt);
645 struct ccw_dev_id devid;
646 static char buf[100];
647 char loadparm[LOADPARM_LEN + 1];
649 switch (reipl_type) {
651 reipl_get_ascii_loadparm(loadparm);
652 printk(KERN_EMERG "reboot on ccw device: 0.0.%04x\n",
653 reipl_block_ccw->ipl_info.ccw.devno);
654 printk(KERN_EMERG "loadparm = '%s'\n", loadparm);
657 printk(KERN_EMERG "reboot on fcp device:\n");
658 print_fcp_block(reipl_block_fcp);
664 switch (reipl_method) {
665 case IPL_METHOD_CCW_CIO:
666 devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
667 if (ipl_get_type() == IPL_TYPE_CCW && devid.devno == ipl_devno)
668 diag308(DIAG308_IPL, NULL);
670 reipl_ccw_dev(&devid);
672 case IPL_METHOD_CCW_VM:
673 if (strlen(loadparm) == 0)
674 sprintf(buf, "IPL %X",
675 reipl_block_ccw->ipl_info.ccw.devno);
677 sprintf(buf, "IPL %X LOADPARM '%s'",
678 reipl_block_ccw->ipl_info.ccw.devno, loadparm);
679 cpcmd(buf, NULL, 0, NULL);
681 case IPL_METHOD_CCW_DIAG:
682 diag308(DIAG308_SET, reipl_block_ccw);
683 diag308(DIAG308_IPL, NULL);
685 case IPL_METHOD_FCP_RW_DIAG:
686 diag308(DIAG308_SET, reipl_block_fcp);
687 diag308(DIAG308_IPL, NULL);
689 case IPL_METHOD_FCP_RO_DIAG:
690 diag308(DIAG308_IPL, NULL);
692 case IPL_METHOD_FCP_RO_VM:
693 cpcmd("IPL", NULL, 0, NULL);
695 case IPL_METHOD_NONE:
698 cpcmd("IPL", NULL, 0, NULL);
699 diag308(DIAG308_IPL, NULL);
702 printk(KERN_EMERG "reboot failed!\n");
703 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
706 static void do_dump(void)
708 struct ccw_dev_id devid;
709 static char buf[100];
713 printk(KERN_EMERG "Automatic dump on ccw device: 0.0.%04x\n",
714 dump_block_ccw->ipl_info.ccw.devno);
717 printk(KERN_EMERG "Automatic dump on fcp device:\n");
718 print_fcp_block(dump_block_fcp);
724 switch (dump_method) {
725 case IPL_METHOD_CCW_CIO:
727 devid.devno = dump_block_ccw->ipl_info.ccw.devno;
729 reipl_ccw_dev(&devid);
731 case IPL_METHOD_CCW_VM:
733 sprintf(buf, "STORE STATUS");
734 cpcmd(buf, NULL, 0, NULL);
735 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
736 cpcmd(buf, NULL, 0, NULL);
738 case IPL_METHOD_CCW_DIAG:
739 diag308(DIAG308_SET, dump_block_ccw);
740 diag308(DIAG308_DUMP, NULL);
742 case IPL_METHOD_FCP_RW_DIAG:
743 diag308(DIAG308_SET, dump_block_fcp);
744 diag308(DIAG308_DUMP, NULL);
746 case IPL_METHOD_NONE:
750 printk(KERN_EMERG "Dump failed!\n");
755 static int __init ipl_register_fcp_files(void)
759 rc = sysfs_create_group(&ipl_subsys.kset.kobj,
760 &ipl_fcp_attr_group);
763 rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
764 &ipl_parameter_attr);
767 rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
772 sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr);
775 sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
780 static int __init ipl_init(void)
784 rc = firmware_register(&ipl_subsys);
787 switch (ipl_get_type()) {
789 rc = sysfs_create_group(&ipl_subsys.kset.kobj,
790 &ipl_ccw_attr_group);
793 rc = ipl_register_fcp_files();
796 rc = sysfs_create_group(&ipl_subsys.kset.kobj,
797 &ipl_unknown_attr_group);
801 firmware_unregister(&ipl_subsys);
805 static void __init reipl_probe(void)
809 buffer = (void *) get_zeroed_page(GFP_KERNEL);
812 if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK)
813 diag308_set_works = 1;
814 free_page((unsigned long)buffer);
817 static int __init reipl_ccw_init(void)
821 reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
822 if (!reipl_block_ccw)
824 rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_ccw_attr_group);
826 free_page((unsigned long)reipl_block_ccw);
829 reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
830 reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
831 reipl_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw);
832 reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
833 /* check if read scp info worked and set loadparm */
835 memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
836 SCCB_LOADPARM, LOADPARM_LEN);
838 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
839 memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
841 /* FIXME: check for diag308_set_works when enabling diag ccw reipl */
843 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
844 if (ipl_get_type() == IPL_TYPE_CCW)
845 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
846 reipl_capabilities |= IPL_TYPE_CCW;
850 static int __init reipl_fcp_init(void)
854 if ((!diag308_set_works) && (ipl_get_type() != IPL_TYPE_FCP))
856 if ((!diag308_set_works) && (ipl_get_type() == IPL_TYPE_FCP))
857 make_attrs_ro(reipl_fcp_attrs);
859 reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
860 if (!reipl_block_fcp)
862 rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_fcp_attr_group);
864 free_page((unsigned long)reipl_block_fcp);
867 if (ipl_get_type() == IPL_TYPE_FCP) {
868 memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
870 reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
871 reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
872 reipl_block_fcp->hdr.blk0_len =
873 sizeof(reipl_block_fcp->ipl_info.fcp);
874 reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
875 reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL;
877 reipl_capabilities |= IPL_TYPE_FCP;
881 static int __init reipl_init(void)
885 rc = firmware_register(&reipl_subsys);
888 rc = subsys_create_file(&reipl_subsys, &reipl_type_attr);
890 firmware_unregister(&reipl_subsys);
893 rc = reipl_ccw_init();
896 rc = reipl_fcp_init();
899 rc = reipl_set_type(ipl_get_type());
905 static int __init dump_ccw_init(void)
909 dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
912 rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_ccw_attr_group);
914 free_page((unsigned long)dump_block_ccw);
917 dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
918 dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
919 dump_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw);
920 dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
921 dump_capabilities |= IPL_TYPE_CCW;
925 static int __init dump_fcp_init(void)
929 if(!(SCCB_FLAG & 0x2) || !SCCB_VALID)
930 return 0; /* LDIPL DUMP is not installed */
931 if (!diag308_set_works)
933 dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
936 rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_fcp_attr_group);
938 free_page((unsigned long)dump_block_fcp);
941 dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
942 dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
943 dump_block_fcp->hdr.blk0_len = sizeof(dump_block_fcp->ipl_info.fcp);
944 dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
945 dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
946 dump_capabilities |= IPL_TYPE_FCP;
950 #define SHUTDOWN_ON_PANIC_PRIO 0
952 static int shutdown_on_panic_notify(struct notifier_block *self,
953 unsigned long event, void *data)
955 if (on_panic_action == SHUTDOWN_DUMP)
957 else if (on_panic_action == SHUTDOWN_REIPL)
962 static struct notifier_block shutdown_on_panic_nb = {
963 .notifier_call = shutdown_on_panic_notify,
964 .priority = SHUTDOWN_ON_PANIC_PRIO
967 static int __init dump_init(void)
971 rc = firmware_register(&dump_subsys);
974 rc = subsys_create_file(&dump_subsys, &dump_type_attr);
976 firmware_unregister(&dump_subsys);
979 rc = dump_ccw_init();
982 rc = dump_fcp_init();
985 dump_set_type(IPL_TYPE_NONE);
989 static int __init shutdown_actions_init(void)
993 rc = firmware_register(&shutdown_actions_subsys);
996 rc = subsys_create_file(&shutdown_actions_subsys, &on_panic_attr);
998 firmware_unregister(&shutdown_actions_subsys);
1001 atomic_notifier_chain_register(&panic_notifier_list,
1002 &shutdown_on_panic_nb);
1006 static int __init s390_ipl_init(void)
1020 rc = shutdown_actions_init();
1026 __initcall(s390_ipl_init);