Merge branch 'pm-tools'
[linux-2.6-block.git] / arch / s390 / kernel / ipl.c
CommitLineData
ff6b8ea6 1/*
ff6b8ea6
MH
2 * ipl/reipl/dump support for Linux on s390.
3 *
a53c8fab 4 * Copyright IBM Corp. 2005, 2012
ff6b8ea6
MH
5 * Author(s): Michael Holzheu <holzheu@de.ibm.com>
6 * Heiko Carstens <heiko.carstens@de.ibm.com>
7 * Volker Sameske <sameske@de.ibm.com>
8 */
9
10#include <linux/types.h>
11#include <linux/module.h>
12#include <linux/device.h>
13#include <linux/delay.h>
14#include <linux/reboot.h>
03a4d208 15#include <linux/ctype.h>
0788fea4 16#include <linux/fs.h>
5a0e3ad6 17#include <linux/gfp.h>
60a0c68d 18#include <linux/crash_dump.h>
3ab121ab 19#include <linux/debug_locks.h>
1ec2772e 20#include <asm/diag.h>
46b05d26 21#include <asm/ipl.h>
ff6b8ea6
MH
22#include <asm/smp.h>
23#include <asm/setup.h>
24#include <asm/cpcmd.h>
25#include <asm/cio.h>
03a4d208 26#include <asm/ebcdic.h>
15e9b586 27#include <asm/reset.h>
ab14de6c 28#include <asm/sclp.h>
159d1ff8 29#include <asm/checksum.h>
3ab121ab 30#include <asm/debug.h>
4857d4bb 31#include <asm/os_info.h>
638ad34a 32#include "entry.h"
ff6b8ea6
MH
33
34#define IPL_PARM_BLOCK_VERSION 0
03a4d208 35
411ed322
MH
36#define IPL_UNKNOWN_STR "unknown"
37#define IPL_CCW_STR "ccw"
38#define IPL_FCP_STR "fcp"
39#define IPL_FCP_DUMP_STR "fcp_dump"
40#define IPL_NSS_STR "nss"
615b04b3 41
99ca4e58
MH
42#define DUMP_CCW_STR "ccw"
43#define DUMP_FCP_STR "fcp"
44#define DUMP_NONE_STR "none"
45
46/*
47 * Four shutdown trigger types are supported:
48 * - panic
49 * - halt
50 * - power off
51 * - reipl
7dd6b334 52 * - restart
99ca4e58
MH
53 */
54#define ON_PANIC_STR "on_panic"
55#define ON_HALT_STR "on_halt"
56#define ON_POFF_STR "on_poff"
57#define ON_REIPL_STR "on_reboot"
7dd6b334 58#define ON_RESTART_STR "on_restart"
99ca4e58
MH
59
60struct shutdown_action;
61struct shutdown_trigger {
62 char *name;
63 struct shutdown_action *action;
64};
65
66/*
099b7651 67 * The following shutdown action types are supported:
99ca4e58
MH
68 */
69#define SHUTDOWN_ACTION_IPL_STR "ipl"
70#define SHUTDOWN_ACTION_REIPL_STR "reipl"
71#define SHUTDOWN_ACTION_DUMP_STR "dump"
72#define SHUTDOWN_ACTION_VMCMD_STR "vmcmd"
73#define SHUTDOWN_ACTION_STOP_STR "stop"
099b7651 74#define SHUTDOWN_ACTION_DUMP_REIPL_STR "dump_reipl"
99ca4e58
MH
75
76struct shutdown_action {
77 char *name;
78 void (*fn) (struct shutdown_trigger *trigger);
79 int (*init) (void);
81088819 80 int init_rc;
99ca4e58
MH
81};
82
ff6b8ea6
MH
83static char *ipl_type_str(enum ipl_type type)
84{
85 switch (type) {
ff6b8ea6
MH
86 case IPL_TYPE_CCW:
87 return IPL_CCW_STR;
88 case IPL_TYPE_FCP:
89 return IPL_FCP_STR;
411ed322
MH
90 case IPL_TYPE_FCP_DUMP:
91 return IPL_FCP_DUMP_STR;
fe355b7f
HY
92 case IPL_TYPE_NSS:
93 return IPL_NSS_STR;
ff6b8ea6
MH
94 case IPL_TYPE_UNKNOWN:
95 default:
96 return IPL_UNKNOWN_STR;
97 }
98}
99
411ed322
MH
100enum dump_type {
101 DUMP_TYPE_NONE = 1,
102 DUMP_TYPE_CCW = 2,
103 DUMP_TYPE_FCP = 4,
104};
105
411ed322
MH
106static char *dump_type_str(enum dump_type type)
107{
108 switch (type) {
109 case DUMP_TYPE_NONE:
110 return DUMP_NONE_STR;
111 case DUMP_TYPE_CCW:
112 return DUMP_CCW_STR;
113 case DUMP_TYPE_FCP:
114 return DUMP_FCP_STR;
115 default:
116 return NULL;
117 }
118}
119
120/*
121 * Must be in data section since the bss section
122 * is not cleared when these are accessed.
123 */
124static u16 ipl_devno __attribute__((__section__(".data"))) = 0;
125u32 ipl_flags __attribute__((__section__(".data"))) = 0;
126
ff6b8ea6 127enum ipl_method {
411ed322
MH
128 REIPL_METHOD_CCW_CIO,
129 REIPL_METHOD_CCW_DIAG,
130 REIPL_METHOD_CCW_VM,
131 REIPL_METHOD_FCP_RO_DIAG,
132 REIPL_METHOD_FCP_RW_DIAG,
133 REIPL_METHOD_FCP_RO_VM,
134 REIPL_METHOD_FCP_DUMP,
135 REIPL_METHOD_NSS,
a0443fbb 136 REIPL_METHOD_NSS_DIAG,
411ed322
MH
137 REIPL_METHOD_DEFAULT,
138};
139
140enum dump_method {
141 DUMP_METHOD_NONE,
142 DUMP_METHOD_CCW_CIO,
143 DUMP_METHOD_CCW_DIAG,
144 DUMP_METHOD_CCW_VM,
145 DUMP_METHOD_FCP_DIAG,
ff6b8ea6
MH
146};
147
ff6b8ea6
MH
148static int diag308_set_works = 0;
149
a0443fbb
HB
150static struct ipl_parameter_block ipl_block;
151
ff6b8ea6 152static int reipl_capabilities = IPL_TYPE_UNKNOWN;
fe355b7f 153
ff6b8ea6 154static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
411ed322 155static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
ff6b8ea6
MH
156static struct ipl_parameter_block *reipl_block_fcp;
157static struct ipl_parameter_block *reipl_block_ccw;
a0443fbb 158static struct ipl_parameter_block *reipl_block_nss;
099b7651 159static struct ipl_parameter_block *reipl_block_actual;
fe355b7f 160
411ed322
MH
161static int dump_capabilities = DUMP_TYPE_NONE;
162static enum dump_type dump_type = DUMP_TYPE_NONE;
163static enum dump_method dump_method = DUMP_METHOD_NONE;
ff6b8ea6
MH
164static struct ipl_parameter_block *dump_block_fcp;
165static struct ipl_parameter_block *dump_block_ccw;
166
05dd2530
HC
167static struct sclp_ipl_info sclp_ipl_info;
168
1ec2772e 169static inline int __diag308(unsigned long subcode, void *addr)
ff6b8ea6 170{
94c12cc7 171 register unsigned long _addr asm("0") = (unsigned long) addr;
ff6b8ea6
MH
172 register unsigned long _rc asm("1") = 0;
173
94c12cc7
MS
174 asm volatile(
175 " diag %0,%2,0x308\n"
176 "0:\n"
177 EX_TABLE(0b,0b)
ff6b8ea6 178 : "+d" (_addr), "+d" (_rc)
94c12cc7 179 : "d" (subcode) : "cc", "memory");
ff6b8ea6
MH
180 return _rc;
181}
1ec2772e
MS
182
183int diag308(unsigned long subcode, void *addr)
184{
185 diag_stat_inc(DIAG_STAT_X308);
186 return __diag308(subcode, addr);
187}
411ed322 188EXPORT_SYMBOL_GPL(diag308);
ff6b8ea6
MH
189
190/* SYSFS */
191
3be7ae63 192#define IPL_ATTR_SHOW_FN(_prefix, _name, _format, args...) \
9b949165
GKH
193static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
194 struct kobj_attribute *attr, \
ff6b8ea6
MH
195 char *page) \
196{ \
3be7ae63
SO
197 return snprintf(page, PAGE_SIZE, _format, ##args); \
198}
199
200#define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \
201IPL_ATTR_SHOW_FN(_prefix, _name, _format, _value) \
9b949165 202static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
3be7ae63 203 __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL)
ff6b8ea6
MH
204
205#define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \
3be7ae63 206IPL_ATTR_SHOW_FN(_prefix, _name, _fmt_out, (unsigned long long) _value) \
9b949165
GKH
207static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
208 struct kobj_attribute *attr, \
ff6b8ea6
MH
209 const char *buf, size_t len) \
210{ \
211 unsigned long long value; \
212 if (sscanf(buf, _fmt_in, &value) != 1) \
213 return -EINVAL; \
214 _value = value; \
215 return len; \
216} \
9b949165 217static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
ff6b8ea6
MH
218 __ATTR(_name,(S_IRUGO | S_IWUSR), \
219 sys_##_prefix##_##_name##_show, \
3be7ae63 220 sys_##_prefix##_##_name##_store)
ff6b8ea6 221
fe355b7f 222#define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
3be7ae63 223IPL_ATTR_SHOW_FN(_prefix, _name, _fmt_out, _value) \
9b949165
GKH
224static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
225 struct kobj_attribute *attr, \
fe355b7f
HY
226 const char *buf, size_t len) \
227{ \
99ca4e58 228 strncpy(_value, buf, sizeof(_value) - 1); \
1d802e24 229 strim(_value); \
fe355b7f
HY
230 return len; \
231} \
9b949165 232static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
fe355b7f
HY
233 __ATTR(_name,(S_IRUGO | S_IWUSR), \
234 sys_##_prefix##_##_name##_show, \
3be7ae63 235 sys_##_prefix##_##_name##_store)
fe355b7f 236
ff6b8ea6
MH
237static void make_attrs_ro(struct attribute **attrs)
238{
239 while (*attrs) {
240 (*attrs)->mode = S_IRUGO;
241 attrs++;
242 }
243}
244
245/*
246 * ipl section
247 */
248
411ed322 249static __init enum ipl_type get_ipl_type(void)
ff6b8ea6
MH
250{
251 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
252
fe355b7f
HY
253 if (ipl_flags & IPL_NSS_VALID)
254 return IPL_TYPE_NSS;
e87bfe51 255 if (!(ipl_flags & IPL_DEVNO_VALID))
ff6b8ea6 256 return IPL_TYPE_UNKNOWN;
e87bfe51 257 if (!(ipl_flags & IPL_PARMBLOCK_VALID))
ff6b8ea6
MH
258 return IPL_TYPE_CCW;
259 if (ipl->hdr.version > IPL_MAX_SUPPORTED_VERSION)
260 return IPL_TYPE_UNKNOWN;
261 if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP)
262 return IPL_TYPE_UNKNOWN;
411ed322
MH
263 if (ipl->ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP)
264 return IPL_TYPE_FCP_DUMP;
ff6b8ea6
MH
265 return IPL_TYPE_FCP;
266}
267
411ed322
MH
268struct ipl_info ipl_info;
269EXPORT_SYMBOL_GPL(ipl_info);
270
9b949165
GKH
271static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
272 char *page)
ff6b8ea6 273{
411ed322 274 return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
ff6b8ea6
MH
275}
276
9b949165 277static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
ff6b8ea6 278
a0443fbb 279/* VM IPL PARM routines */
c4736d96
MS
280static size_t reipl_get_ascii_vmparm(char *dest, size_t size,
281 const struct ipl_parameter_block *ipb)
a0443fbb
HB
282{
283 int i;
684d2fd4 284 size_t len;
a0443fbb
HB
285 char has_lowercase = 0;
286
684d2fd4 287 len = 0;
a0443fbb
HB
288 if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
289 (ipb->ipl_info.ccw.vm_parm_len > 0)) {
290
684d2fd4 291 len = min_t(size_t, size - 1, ipb->ipl_info.ccw.vm_parm_len);
a0443fbb
HB
292 memcpy(dest, ipb->ipl_info.ccw.vm_parm, len);
293 /* If at least one character is lowercase, we assume mixed
294 * case; otherwise we convert everything to lowercase.
295 */
296 for (i = 0; i < len; i++)
297 if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */
298 (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */
299 (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */
300 has_lowercase = 1;
301 break;
302 }
303 if (!has_lowercase)
304 EBC_TOLOWER(dest, len);
305 EBCASC(dest, len);
306 }
307 dest[len] = 0;
684d2fd4
HB
308
309 return len;
a0443fbb
HB
310}
311
684d2fd4 312size_t append_ipl_vmparm(char *dest, size_t size)
a0443fbb 313{
684d2fd4
HB
314 size_t rc;
315
316 rc = 0;
a0443fbb 317 if (diag308_set_works && (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW))
684d2fd4 318 rc = reipl_get_ascii_vmparm(dest, size, &ipl_block);
a0443fbb
HB
319 else
320 dest[0] = 0;
684d2fd4 321 return rc;
a0443fbb
HB
322}
323
324static ssize_t ipl_vm_parm_show(struct kobject *kobj,
325 struct kobj_attribute *attr, char *page)
326{
327 char parm[DIAG308_VMPARM_SIZE + 1] = {};
328
684d2fd4 329 append_ipl_vmparm(parm, sizeof(parm));
a0443fbb
HB
330 return sprintf(page, "%s\n", parm);
331}
332
684d2fd4
HB
333static size_t scpdata_length(const char* buf, size_t count)
334{
335 while (count) {
336 if (buf[count - 1] != '\0' && buf[count - 1] != ' ')
337 break;
338 count--;
339 }
340 return count;
341}
342
c4736d96
MS
343static size_t reipl_append_ascii_scpdata(char *dest, size_t size,
344 const struct ipl_parameter_block *ipb)
684d2fd4
HB
345{
346 size_t count;
347 size_t i;
18d00acf 348 int has_lowercase;
684d2fd4
HB
349
350 count = min(size - 1, scpdata_length(ipb->ipl_info.fcp.scp_data,
351 ipb->ipl_info.fcp.scp_data_len));
352 if (!count)
353 goto out;
354
18d00acf
HB
355 has_lowercase = 0;
356 for (i = 0; i < count; i++) {
684d2fd4
HB
357 if (!isascii(ipb->ipl_info.fcp.scp_data[i])) {
358 count = 0;
359 goto out;
360 }
18d00acf
HB
361 if (!has_lowercase && islower(ipb->ipl_info.fcp.scp_data[i]))
362 has_lowercase = 1;
363 }
684d2fd4 364
18d00acf
HB
365 if (has_lowercase)
366 memcpy(dest, ipb->ipl_info.fcp.scp_data, count);
367 else
368 for (i = 0; i < count; i++)
369 dest[i] = tolower(ipb->ipl_info.fcp.scp_data[i]);
684d2fd4
HB
370out:
371 dest[count] = '\0';
372 return count;
373}
374
375size_t append_ipl_scpdata(char *dest, size_t len)
376{
377 size_t rc;
378
379 rc = 0;
380 if (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_FCP)
381 rc = reipl_append_ascii_scpdata(dest, len, &ipl_block);
382 else
383 dest[0] = 0;
384 return rc;
385}
386
387
a0443fbb
HB
388static struct kobj_attribute sys_ipl_vm_parm_attr =
389 __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL);
390
9b949165
GKH
391static ssize_t sys_ipl_device_show(struct kobject *kobj,
392 struct kobj_attribute *attr, char *page)
ff6b8ea6
MH
393{
394 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
395
411ed322 396 switch (ipl_info.type) {
ff6b8ea6
MH
397 case IPL_TYPE_CCW:
398 return sprintf(page, "0.0.%04x\n", ipl_devno);
399 case IPL_TYPE_FCP:
411ed322 400 case IPL_TYPE_FCP_DUMP:
ff6b8ea6
MH
401 return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno);
402 default:
403 return 0;
404 }
405}
406
9b949165 407static struct kobj_attribute sys_ipl_device_attr =
ff6b8ea6
MH
408 __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
409
2c3c8bea
CW
410static ssize_t ipl_parameter_read(struct file *filp, struct kobject *kobj,
411 struct bin_attribute *attr, char *buf,
412 loff_t off, size_t count)
ff6b8ea6 413{
0788fea4
AM
414 return memory_read_from_buffer(buf, count, &off, IPL_PARMBLOCK_START,
415 IPL_PARMBLOCK_SIZE);
ff6b8ea6 416}
22d557ab
SO
417static struct bin_attribute ipl_parameter_attr =
418 __BIN_ATTR(binary_parameter, S_IRUGO, ipl_parameter_read, NULL,
419 PAGE_SIZE);
ff6b8ea6 420
2c3c8bea
CW
421static ssize_t ipl_scp_data_read(struct file *filp, struct kobject *kobj,
422 struct bin_attribute *attr, char *buf,
423 loff_t off, size_t count)
ff6b8ea6
MH
424{
425 unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
426 void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
427
0788fea4 428 return memory_read_from_buffer(buf, count, &off, scp_data, size);
ff6b8ea6 429}
22d557ab
SO
430static struct bin_attribute ipl_scp_data_attr =
431 __BIN_ATTR(scp_data, S_IRUGO, ipl_scp_data_read, NULL, PAGE_SIZE);
ff6b8ea6 432
22d557ab
SO
433static struct bin_attribute *ipl_fcp_bin_attrs[] = {
434 &ipl_parameter_attr,
435 &ipl_scp_data_attr,
436 NULL,
ff6b8ea6
MH
437};
438
439/* FCP ipl device attributes */
440
441DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n", (unsigned long long)
442 IPL_PARMBLOCK_START->ipl_info.fcp.wwpn);
443DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n", (unsigned long long)
444 IPL_PARMBLOCK_START->ipl_info.fcp.lun);
445DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long)
446 IPL_PARMBLOCK_START->ipl_info.fcp.bootprog);
447DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
448 IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
449
9b949165
GKH
450static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
451 struct kobj_attribute *attr, char *page)
03a4d208
MH
452{
453 char loadparm[LOADPARM_LEN + 1] = {};
454
05dd2530 455 if (!sclp_ipl_info.is_valid)
03a4d208 456 return sprintf(page, "#unknown#\n");
05dd2530 457 memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
03a4d208 458 EBCASC(loadparm, LOADPARM_LEN);
1d802e24 459 strim(loadparm);
03a4d208
MH
460 return sprintf(page, "%s\n", loadparm);
461}
462
9b949165 463static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
03a4d208
MH
464 __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
465
69928601
MH
466static struct attribute *ipl_fcp_attrs[] = {
467 &sys_ipl_type_attr.attr,
468 &sys_ipl_device_attr.attr,
469 &sys_ipl_fcp_wwpn_attr.attr,
470 &sys_ipl_fcp_lun_attr.attr,
471 &sys_ipl_fcp_bootprog_attr.attr,
472 &sys_ipl_fcp_br_lba_attr.attr,
473 &sys_ipl_ccw_loadparm_attr.attr,
474 NULL,
475};
476
477static struct attribute_group ipl_fcp_attr_group = {
478 .attrs = ipl_fcp_attrs,
22d557ab 479 .bin_attrs = ipl_fcp_bin_attrs,
69928601
MH
480};
481
482/* CCW ipl device attributes */
483
a0443fbb
HB
484static struct attribute *ipl_ccw_attrs_vm[] = {
485 &sys_ipl_type_attr.attr,
486 &sys_ipl_device_attr.attr,
487 &sys_ipl_ccw_loadparm_attr.attr,
488 &sys_ipl_vm_parm_attr.attr,
489 NULL,
490};
491
492static struct attribute *ipl_ccw_attrs_lpar[] = {
ff6b8ea6
MH
493 &sys_ipl_type_attr.attr,
494 &sys_ipl_device_attr.attr,
03a4d208 495 &sys_ipl_ccw_loadparm_attr.attr,
ff6b8ea6
MH
496 NULL,
497};
498
a0443fbb
HB
499static struct attribute_group ipl_ccw_attr_group_vm = {
500 .attrs = ipl_ccw_attrs_vm,
501};
502
503static struct attribute_group ipl_ccw_attr_group_lpar = {
504 .attrs = ipl_ccw_attrs_lpar
ff6b8ea6
MH
505};
506
fe355b7f
HY
507/* NSS ipl device attributes */
508
509DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name);
510
511static struct attribute *ipl_nss_attrs[] = {
512 &sys_ipl_type_attr.attr,
513 &sys_ipl_nss_name_attr.attr,
a0443fbb
HB
514 &sys_ipl_ccw_loadparm_attr.attr,
515 &sys_ipl_vm_parm_attr.attr,
fe355b7f
HY
516 NULL,
517};
518
519static struct attribute_group ipl_nss_attr_group = {
520 .attrs = ipl_nss_attrs,
521};
522
ff6b8ea6
MH
523/* UNKNOWN ipl device attributes */
524
525static struct attribute *ipl_unknown_attrs[] = {
526 &sys_ipl_type_attr.attr,
527 NULL,
528};
529
530static struct attribute_group ipl_unknown_attr_group = {
531 .attrs = ipl_unknown_attrs,
532};
533
d91885be 534static struct kset *ipl_kset;
ff6b8ea6 535
2c2df118 536static void __ipl_run(void *unused)
99ca4e58
MH
537{
538 diag308(DIAG308_IPL, NULL);
539 if (MACHINE_IS_VM)
540 __cpcmd("IPL", NULL, 0, NULL);
541 else if (ipl_info.type == IPL_TYPE_CCW)
542 reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
543}
544
2c2df118
HC
545static void ipl_run(struct shutdown_trigger *trigger)
546{
8b646bd7 547 smp_call_ipl_cpu(__ipl_run, NULL);
2c2df118
HC
548}
549
2bc89b5e 550static int __init ipl_init(void)
99ca4e58
MH
551{
552 int rc;
553
554 ipl_kset = kset_create_and_add("ipl", NULL, firmware_kobj);
555 if (!ipl_kset) {
556 rc = -ENOMEM;
557 goto out;
558 }
559 switch (ipl_info.type) {
560 case IPL_TYPE_CCW:
a0443fbb
HB
561 if (MACHINE_IS_VM)
562 rc = sysfs_create_group(&ipl_kset->kobj,
563 &ipl_ccw_attr_group_vm);
564 else
565 rc = sysfs_create_group(&ipl_kset->kobj,
566 &ipl_ccw_attr_group_lpar);
99ca4e58
MH
567 break;
568 case IPL_TYPE_FCP:
569 case IPL_TYPE_FCP_DUMP:
22d557ab 570 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
99ca4e58
MH
571 break;
572 case IPL_TYPE_NSS:
573 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_nss_attr_group);
574 break;
575 default:
576 rc = sysfs_create_group(&ipl_kset->kobj,
577 &ipl_unknown_attr_group);
578 break;
579 }
580out:
581 if (rc)
582 panic("ipl_init failed: rc = %i\n", rc);
583
584 return 0;
585}
586
2bc89b5e
HC
587static struct shutdown_action __refdata ipl_action = {
588 .name = SHUTDOWN_ACTION_IPL_STR,
589 .fn = ipl_run,
590 .init = ipl_init,
591};
99ca4e58 592
ff6b8ea6 593/*
99ca4e58 594 * reipl shutdown action: Reboot Linux on shutdown.
ff6b8ea6
MH
595 */
596
a0443fbb
HB
597/* VM IPL PARM attributes */
598static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb,
599 char *page)
600{
601 char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
602
684d2fd4 603 reipl_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
a0443fbb
HB
604 return sprintf(page, "%s\n", vmparm);
605}
606
607static ssize_t reipl_generic_vmparm_store(struct ipl_parameter_block *ipb,
608 size_t vmparm_max,
609 const char *buf, size_t len)
610{
611 int i, ip_len;
612
613 /* ignore trailing newline */
614 ip_len = len;
615 if ((len > 0) && (buf[len - 1] == '\n'))
616 ip_len--;
617
618 if (ip_len > vmparm_max)
619 return -EINVAL;
620
621 /* parm is used to store kernel options, check for common chars */
622 for (i = 0; i < ip_len; i++)
623 if (!(isalnum(buf[i]) || isascii(buf[i]) || isprint(buf[i])))
624 return -EINVAL;
625
626 memset(ipb->ipl_info.ccw.vm_parm, 0, DIAG308_VMPARM_SIZE);
627 ipb->ipl_info.ccw.vm_parm_len = ip_len;
628 if (ip_len > 0) {
629 ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
630 memcpy(ipb->ipl_info.ccw.vm_parm, buf, ip_len);
631 ASCEBC(ipb->ipl_info.ccw.vm_parm, ip_len);
632 } else {
633 ipb->ipl_info.ccw.vm_flags &= ~DIAG308_VM_FLAGS_VP_VALID;
634 }
635
636 return len;
637}
638
639/* NSS wrapper */
640static ssize_t reipl_nss_vmparm_show(struct kobject *kobj,
641 struct kobj_attribute *attr, char *page)
642{
643 return reipl_generic_vmparm_show(reipl_block_nss, page);
644}
645
646static ssize_t reipl_nss_vmparm_store(struct kobject *kobj,
647 struct kobj_attribute *attr,
648 const char *buf, size_t len)
649{
650 return reipl_generic_vmparm_store(reipl_block_nss, 56, buf, len);
651}
652
653/* CCW wrapper */
654static ssize_t reipl_ccw_vmparm_show(struct kobject *kobj,
655 struct kobj_attribute *attr, char *page)
656{
657 return reipl_generic_vmparm_show(reipl_block_ccw, page);
658}
659
660static ssize_t reipl_ccw_vmparm_store(struct kobject *kobj,
661 struct kobj_attribute *attr,
662 const char *buf, size_t len)
663{
664 return reipl_generic_vmparm_store(reipl_block_ccw, 64, buf, len);
665}
666
667static struct kobj_attribute sys_reipl_nss_vmparm_attr =
668 __ATTR(parm, S_IRUGO | S_IWUSR, reipl_nss_vmparm_show,
669 reipl_nss_vmparm_store);
670static struct kobj_attribute sys_reipl_ccw_vmparm_attr =
671 __ATTR(parm, S_IRUGO | S_IWUSR, reipl_ccw_vmparm_show,
672 reipl_ccw_vmparm_store);
673
ff6b8ea6
MH
674/* FCP reipl device attributes */
675
2c3c8bea 676static ssize_t reipl_fcp_scpdata_read(struct file *filp, struct kobject *kobj,
684d2fd4
HB
677 struct bin_attribute *attr,
678 char *buf, loff_t off, size_t count)
679{
680 size_t size = reipl_block_fcp->ipl_info.fcp.scp_data_len;
681 void *scp_data = reipl_block_fcp->ipl_info.fcp.scp_data;
682
683 return memory_read_from_buffer(buf, count, &off, scp_data, size);
684}
685
2c3c8bea 686static ssize_t reipl_fcp_scpdata_write(struct file *filp, struct kobject *kobj,
684d2fd4
HB
687 struct bin_attribute *attr,
688 char *buf, loff_t off, size_t count)
689{
690 size_t padding;
691 size_t scpdata_len;
692
693 if (off < 0)
694 return -EINVAL;
695
696 if (off >= DIAG308_SCPDATA_SIZE)
697 return -ENOSPC;
698
699 if (count > DIAG308_SCPDATA_SIZE - off)
700 count = DIAG308_SCPDATA_SIZE - off;
701
702 memcpy(reipl_block_fcp->ipl_info.fcp.scp_data, buf + off, count);
703 scpdata_len = off + count;
704
705 if (scpdata_len % 8) {
706 padding = 8 - (scpdata_len % 8);
707 memset(reipl_block_fcp->ipl_info.fcp.scp_data + scpdata_len,
708 0, padding);
709 scpdata_len += padding;
710 }
711
712 reipl_block_fcp->ipl_info.fcp.scp_data_len = scpdata_len;
713 reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN + scpdata_len;
714 reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN + scpdata_len;
715
716 return count;
717}
22d557ab
SO
718static struct bin_attribute sys_reipl_fcp_scp_data_attr =
719 __BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_fcp_scpdata_read,
720 reipl_fcp_scpdata_write, PAGE_SIZE);
684d2fd4 721
22d557ab
SO
722static struct bin_attribute *reipl_fcp_bin_attrs[] = {
723 &sys_reipl_fcp_scp_data_attr,
724 NULL,
684d2fd4
HB
725};
726
eda4ddf7 727DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%llx\n",
ff6b8ea6 728 reipl_block_fcp->ipl_info.fcp.wwpn);
eda4ddf7 729DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%llx\n",
ff6b8ea6
MH
730 reipl_block_fcp->ipl_info.fcp.lun);
731DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
732 reipl_block_fcp->ipl_info.fcp.bootprog);
733DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
734 reipl_block_fcp->ipl_info.fcp.br_lba);
735DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
736 reipl_block_fcp->ipl_info.fcp.devno);
737
a0443fbb
HB
738static void reipl_get_ascii_loadparm(char *loadparm,
739 struct ipl_parameter_block *ibp)
03a4d208 740{
69928601 741 memcpy(loadparm, ibp->hdr.loadparm, LOADPARM_LEN);
03a4d208
MH
742 EBCASC(loadparm, LOADPARM_LEN);
743 loadparm[LOADPARM_LEN] = 0;
1d802e24 744 strim(loadparm);
03a4d208
MH
745}
746
a0443fbb
HB
747static ssize_t reipl_generic_loadparm_show(struct ipl_parameter_block *ipb,
748 char *page)
03a4d208
MH
749{
750 char buf[LOADPARM_LEN + 1];
751
a0443fbb 752 reipl_get_ascii_loadparm(buf, ipb);
03a4d208
MH
753 return sprintf(page, "%s\n", buf);
754}
755
a0443fbb
HB
756static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
757 const char *buf, size_t len)
03a4d208
MH
758{
759 int i, lp_len;
760
761 /* ignore trailing newline */
762 lp_len = len;
763 if ((len > 0) && (buf[len - 1] == '\n'))
764 lp_len--;
765 /* loadparm can have max 8 characters and must not start with a blank */
766 if ((lp_len > LOADPARM_LEN) || ((lp_len > 0) && (buf[0] == ' ')))
767 return -EINVAL;
768 /* loadparm can only contain "a-z,A-Z,0-9,SP,." */
769 for (i = 0; i < lp_len; i++) {
770 if (isalpha(buf[i]) || isdigit(buf[i]) || (buf[i] == ' ') ||
771 (buf[i] == '.'))
772 continue;
773 return -EINVAL;
774 }
775 /* initialize loadparm with blanks */
69928601 776 memset(ipb->hdr.loadparm, ' ', LOADPARM_LEN);
03a4d208 777 /* copy and convert to ebcdic */
69928601
MH
778 memcpy(ipb->hdr.loadparm, buf, lp_len);
779 ASCEBC(ipb->hdr.loadparm, LOADPARM_LEN);
03a4d208
MH
780 return len;
781}
782
69928601
MH
783/* FCP wrapper */
784static ssize_t reipl_fcp_loadparm_show(struct kobject *kobj,
785 struct kobj_attribute *attr, char *page)
786{
787 return reipl_generic_loadparm_show(reipl_block_fcp, page);
788}
789
790static ssize_t reipl_fcp_loadparm_store(struct kobject *kobj,
791 struct kobj_attribute *attr,
792 const char *buf, size_t len)
793{
794 return reipl_generic_loadparm_store(reipl_block_fcp, buf, len);
795}
796
797static struct kobj_attribute sys_reipl_fcp_loadparm_attr =
798 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_fcp_loadparm_show,
799 reipl_fcp_loadparm_store);
800
801static struct attribute *reipl_fcp_attrs[] = {
802 &sys_reipl_fcp_device_attr.attr,
803 &sys_reipl_fcp_wwpn_attr.attr,
804 &sys_reipl_fcp_lun_attr.attr,
805 &sys_reipl_fcp_bootprog_attr.attr,
806 &sys_reipl_fcp_br_lba_attr.attr,
807 &sys_reipl_fcp_loadparm_attr.attr,
808 NULL,
809};
810
811static struct attribute_group reipl_fcp_attr_group = {
812 .attrs = reipl_fcp_attrs,
22d557ab 813 .bin_attrs = reipl_fcp_bin_attrs,
69928601
MH
814};
815
816/* CCW reipl device attributes */
817
818DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
819 reipl_block_ccw->ipl_info.ccw.devno);
820
a0443fbb
HB
821/* NSS wrapper */
822static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
823 struct kobj_attribute *attr, char *page)
824{
825 return reipl_generic_loadparm_show(reipl_block_nss, page);
826}
827
828static ssize_t reipl_nss_loadparm_store(struct kobject *kobj,
829 struct kobj_attribute *attr,
830 const char *buf, size_t len)
831{
832 return reipl_generic_loadparm_store(reipl_block_nss, buf, len);
833}
834
835/* CCW wrapper */
836static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj,
837 struct kobj_attribute *attr, char *page)
838{
839 return reipl_generic_loadparm_show(reipl_block_ccw, page);
840}
841
842static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
843 struct kobj_attribute *attr,
844 const char *buf, size_t len)
845{
846 return reipl_generic_loadparm_store(reipl_block_ccw, buf, len);
847}
848
9b949165 849static struct kobj_attribute sys_reipl_ccw_loadparm_attr =
a0443fbb
HB
850 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_ccw_loadparm_show,
851 reipl_ccw_loadparm_store);
852
853static struct attribute *reipl_ccw_attrs_vm[] = {
854 &sys_reipl_ccw_device_attr.attr,
855 &sys_reipl_ccw_loadparm_attr.attr,
856 &sys_reipl_ccw_vmparm_attr.attr,
857 NULL,
858};
03a4d208 859
a0443fbb 860static struct attribute *reipl_ccw_attrs_lpar[] = {
ff6b8ea6 861 &sys_reipl_ccw_device_attr.attr,
03a4d208 862 &sys_reipl_ccw_loadparm_attr.attr,
ff6b8ea6
MH
863 NULL,
864};
865
a0443fbb 866static struct attribute_group reipl_ccw_attr_group_vm = {
ff6b8ea6 867 .name = IPL_CCW_STR,
a0443fbb
HB
868 .attrs = reipl_ccw_attrs_vm,
869};
870
871static struct attribute_group reipl_ccw_attr_group_lpar = {
872 .name = IPL_CCW_STR,
873 .attrs = reipl_ccw_attrs_lpar,
ff6b8ea6
MH
874};
875
fe355b7f
HY
876
877/* NSS reipl device attributes */
a0443fbb
HB
878static void reipl_get_ascii_nss_name(char *dst,
879 struct ipl_parameter_block *ipb)
880{
881 memcpy(dst, ipb->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
882 EBCASC(dst, NSS_NAME_SIZE);
883 dst[NSS_NAME_SIZE] = 0;
884}
885
886static ssize_t reipl_nss_name_show(struct kobject *kobj,
887 struct kobj_attribute *attr, char *page)
888{
889 char nss_name[NSS_NAME_SIZE + 1] = {};
890
891 reipl_get_ascii_nss_name(nss_name, reipl_block_nss);
892 return sprintf(page, "%s\n", nss_name);
893}
894
895static ssize_t reipl_nss_name_store(struct kobject *kobj,
896 struct kobj_attribute *attr,
897 const char *buf, size_t len)
898{
899 int nss_len;
900
901 /* ignore trailing newline */
902 nss_len = len;
903 if ((len > 0) && (buf[len - 1] == '\n'))
904 nss_len--;
fe355b7f 905
a0443fbb
HB
906 if (nss_len > NSS_NAME_SIZE)
907 return -EINVAL;
908
909 memset(reipl_block_nss->ipl_info.ccw.nss_name, 0x40, NSS_NAME_SIZE);
910 if (nss_len > 0) {
911 reipl_block_nss->ipl_info.ccw.vm_flags |=
912 DIAG308_VM_FLAGS_NSS_VALID;
913 memcpy(reipl_block_nss->ipl_info.ccw.nss_name, buf, nss_len);
914 ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
915 EBC_TOUPPER(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
916 } else {
917 reipl_block_nss->ipl_info.ccw.vm_flags &=
918 ~DIAG308_VM_FLAGS_NSS_VALID;
919 }
920
921 return len;
922}
923
924static struct kobj_attribute sys_reipl_nss_name_attr =
925 __ATTR(name, S_IRUGO | S_IWUSR, reipl_nss_name_show,
926 reipl_nss_name_store);
927
928static struct kobj_attribute sys_reipl_nss_loadparm_attr =
929 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nss_loadparm_show,
930 reipl_nss_loadparm_store);
fe355b7f
HY
931
932static struct attribute *reipl_nss_attrs[] = {
933 &sys_reipl_nss_name_attr.attr,
a0443fbb
HB
934 &sys_reipl_nss_loadparm_attr.attr,
935 &sys_reipl_nss_vmparm_attr.attr,
fe355b7f
HY
936 NULL,
937};
938
939static struct attribute_group reipl_nss_attr_group = {
940 .name = IPL_NSS_STR,
941 .attrs = reipl_nss_attrs,
942};
943
4857d4bb
MH
944static void set_reipl_block_actual(struct ipl_parameter_block *reipl_block)
945{
946 reipl_block_actual = reipl_block;
947 os_info_entry_add(OS_INFO_REIPL_BLOCK, reipl_block_actual,
948 reipl_block->hdr.len);
949}
950
ff6b8ea6
MH
951/* reipl type */
952
953static int reipl_set_type(enum ipl_type type)
954{
955 if (!(reipl_capabilities & type))
956 return -EINVAL;
957
958 switch(type) {
959 case IPL_TYPE_CCW:
48657d22
MH
960 if (diag308_set_works)
961 reipl_method = REIPL_METHOD_CCW_DIAG;
962 else if (MACHINE_IS_VM)
411ed322 963 reipl_method = REIPL_METHOD_CCW_VM;
ff6b8ea6 964 else
411ed322 965 reipl_method = REIPL_METHOD_CCW_CIO;
4857d4bb 966 set_reipl_block_actual(reipl_block_ccw);
ff6b8ea6
MH
967 break;
968 case IPL_TYPE_FCP:
969 if (diag308_set_works)
411ed322 970 reipl_method = REIPL_METHOD_FCP_RW_DIAG;
ff6b8ea6 971 else if (MACHINE_IS_VM)
411ed322 972 reipl_method = REIPL_METHOD_FCP_RO_VM;
ff6b8ea6 973 else
411ed322 974 reipl_method = REIPL_METHOD_FCP_RO_DIAG;
4857d4bb 975 set_reipl_block_actual(reipl_block_fcp);
411ed322
MH
976 break;
977 case IPL_TYPE_FCP_DUMP:
978 reipl_method = REIPL_METHOD_FCP_DUMP;
ff6b8ea6 979 break;
fe355b7f 980 case IPL_TYPE_NSS:
a0443fbb
HB
981 if (diag308_set_works)
982 reipl_method = REIPL_METHOD_NSS_DIAG;
983 else
984 reipl_method = REIPL_METHOD_NSS;
4857d4bb 985 set_reipl_block_actual(reipl_block_nss);
411ed322
MH
986 break;
987 case IPL_TYPE_UNKNOWN:
988 reipl_method = REIPL_METHOD_DEFAULT;
fe355b7f 989 break;
ff6b8ea6 990 default:
411ed322 991 BUG();
ff6b8ea6
MH
992 }
993 reipl_type = type;
994 return 0;
995}
996
9b949165
GKH
997static ssize_t reipl_type_show(struct kobject *kobj,
998 struct kobj_attribute *attr, char *page)
ff6b8ea6
MH
999{
1000 return sprintf(page, "%s\n", ipl_type_str(reipl_type));
1001}
1002
9b949165
GKH
1003static ssize_t reipl_type_store(struct kobject *kobj,
1004 struct kobj_attribute *attr,
1005 const char *buf, size_t len)
ff6b8ea6
MH
1006{
1007 int rc = -EINVAL;
1008
1009 if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
1010 rc = reipl_set_type(IPL_TYPE_CCW);
1011 else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
1012 rc = reipl_set_type(IPL_TYPE_FCP);
fe355b7f
HY
1013 else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
1014 rc = reipl_set_type(IPL_TYPE_NSS);
ff6b8ea6
MH
1015 return (rc != 0) ? rc : len;
1016}
1017
9b949165 1018static struct kobj_attribute reipl_type_attr =
99ca4e58 1019 __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
ff6b8ea6 1020
d91885be 1021static struct kset *reipl_kset;
684d2fd4 1022static struct kset *reipl_fcp_kset;
ff6b8ea6 1023
a0443fbb
HB
1024static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb,
1025 const enum ipl_method m)
1026{
1027 char loadparm[LOADPARM_LEN + 1] = {};
1028 char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
1029 char nss_name[NSS_NAME_SIZE + 1] = {};
1030 size_t pos = 0;
1031
1032 reipl_get_ascii_loadparm(loadparm, ipb);
1033 reipl_get_ascii_nss_name(nss_name, ipb);
684d2fd4 1034 reipl_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
a0443fbb
HB
1035
1036 switch (m) {
1037 case REIPL_METHOD_CCW_VM:
1038 pos = sprintf(dst, "IPL %X CLEAR", ipb->ipl_info.ccw.devno);
1039 break;
1040 case REIPL_METHOD_NSS:
1041 pos = sprintf(dst, "IPL %s", nss_name);
1042 break;
1043 default:
1044 break;
1045 }
1046 if (strlen(loadparm) > 0)
1047 pos += sprintf(dst + pos, " LOADPARM '%s'", loadparm);
1048 if (strlen(vmparm) > 0)
1049 sprintf(dst + pos, " PARM %s", vmparm);
1050}
1051
2c2df118 1052static void __reipl_run(void *unused)
ff6b8ea6
MH
1053{
1054 struct ccw_dev_id devid;
a0443fbb 1055 static char buf[128];
ff6b8ea6 1056
ff6b8ea6 1057 switch (reipl_method) {
411ed322 1058 case REIPL_METHOD_CCW_CIO:
ff6b8ea6
MH
1059 devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
1060 devid.ssid = 0;
1061 reipl_ccw_dev(&devid);
1062 break;
411ed322 1063 case REIPL_METHOD_CCW_VM:
a0443fbb 1064 get_ipl_string(buf, reipl_block_ccw, REIPL_METHOD_CCW_VM);
740b5706 1065 __cpcmd(buf, NULL, 0, NULL);
ff6b8ea6 1066 break;
411ed322 1067 case REIPL_METHOD_CCW_DIAG:
ff6b8ea6
MH
1068 diag308(DIAG308_SET, reipl_block_ccw);
1069 diag308(DIAG308_IPL, NULL);
1070 break;
411ed322 1071 case REIPL_METHOD_FCP_RW_DIAG:
ff6b8ea6
MH
1072 diag308(DIAG308_SET, reipl_block_fcp);
1073 diag308(DIAG308_IPL, NULL);
1074 break;
411ed322 1075 case REIPL_METHOD_FCP_RO_DIAG:
ff6b8ea6
MH
1076 diag308(DIAG308_IPL, NULL);
1077 break;
411ed322 1078 case REIPL_METHOD_FCP_RO_VM:
740b5706 1079 __cpcmd("IPL", NULL, 0, NULL);
ff6b8ea6 1080 break;
a0443fbb
HB
1081 case REIPL_METHOD_NSS_DIAG:
1082 diag308(DIAG308_SET, reipl_block_nss);
1083 diag308(DIAG308_IPL, NULL);
1084 break;
411ed322 1085 case REIPL_METHOD_NSS:
a0443fbb 1086 get_ipl_string(buf, reipl_block_nss, REIPL_METHOD_NSS);
fe355b7f
HY
1087 __cpcmd(buf, NULL, 0, NULL);
1088 break;
411ed322 1089 case REIPL_METHOD_DEFAULT:
ff6b8ea6 1090 if (MACHINE_IS_VM)
740b5706 1091 __cpcmd("IPL", NULL, 0, NULL);
ff6b8ea6
MH
1092 diag308(DIAG308_IPL, NULL);
1093 break;
411ed322 1094 case REIPL_METHOD_FCP_DUMP:
411ed322 1095 break;
ff6b8ea6 1096 }
208e5591 1097 disabled_wait((unsigned long) __builtin_return_address(0));
ff6b8ea6
MH
1098}
1099
2c2df118
HC
1100static void reipl_run(struct shutdown_trigger *trigger)
1101{
8b646bd7 1102 smp_call_ipl_cpu(__reipl_run, NULL);
2c2df118
HC
1103}
1104
a0443fbb 1105static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
ff6b8ea6 1106{
a0443fbb
HB
1107 ipb->hdr.len = IPL_PARM_BLK_CCW_LEN;
1108 ipb->hdr.version = IPL_PARM_BLOCK_VERSION;
1109 ipb->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
1110 ipb->hdr.pbt = DIAG308_IPL_TYPE_CCW;
1111}
ff6b8ea6 1112
a0443fbb
HB
1113static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
1114{
1115 /* LOADPARM */
1116 /* check if read scp info worked and set loadparm */
1117 if (sclp_ipl_info.is_valid)
69928601 1118 memcpy(ipb->hdr.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
a0443fbb
HB
1119 else
1120 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
69928601 1121 memset(ipb->hdr.loadparm, 0x40, LOADPARM_LEN);
a0443fbb
HB
1122 ipb->hdr.flags = DIAG308_FLAGS_LP_VALID;
1123
1124 /* VM PARM */
1125 if (MACHINE_IS_VM && diag308_set_works &&
1126 (ipl_block.ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID)) {
1127
1128 ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
1129 ipb->ipl_info.ccw.vm_parm_len =
1130 ipl_block.ipl_info.ccw.vm_parm_len;
1131 memcpy(ipb->ipl_info.ccw.vm_parm,
1132 ipl_block.ipl_info.ccw.vm_parm, DIAG308_VMPARM_SIZE);
1133 }
ff6b8ea6
MH
1134}
1135
99ca4e58 1136static int __init reipl_nss_init(void)
ff6b8ea6
MH
1137{
1138 int rc;
1139
99ca4e58
MH
1140 if (!MACHINE_IS_VM)
1141 return 0;
a0443fbb
HB
1142
1143 reipl_block_nss = (void *) get_zeroed_page(GFP_KERNEL);
1144 if (!reipl_block_nss)
1145 return -ENOMEM;
1146
1147 if (!diag308_set_works)
1148 sys_reipl_nss_vmparm_attr.attr.mode = S_IRUGO;
1149
99ca4e58 1150 rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group);
fe355b7f
HY
1151 if (rc)
1152 return rc;
a0443fbb
HB
1153
1154 reipl_block_ccw_init(reipl_block_nss);
1155 if (ipl_info.type == IPL_TYPE_NSS) {
1156 memset(reipl_block_nss->ipl_info.ccw.nss_name,
1157 ' ', NSS_NAME_SIZE);
1158 memcpy(reipl_block_nss->ipl_info.ccw.nss_name,
1159 kernel_nss_name, strlen(kernel_nss_name));
1160 ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
1161 reipl_block_nss->ipl_info.ccw.vm_flags |=
1162 DIAG308_VM_FLAGS_NSS_VALID;
1163
1164 reipl_block_ccw_fill_parms(reipl_block_nss);
1165 }
1166
fe355b7f
HY
1167 reipl_capabilities |= IPL_TYPE_NSS;
1168 return 0;
1169}
1170
ff6b8ea6
MH
1171static int __init reipl_ccw_init(void)
1172{
1173 int rc;
1174
1175 reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
1176 if (!reipl_block_ccw)
1177 return -ENOMEM;
a0443fbb
HB
1178
1179 if (MACHINE_IS_VM) {
1180 if (!diag308_set_works)
1181 sys_reipl_ccw_vmparm_attr.attr.mode = S_IRUGO;
1182 rc = sysfs_create_group(&reipl_kset->kobj,
1183 &reipl_ccw_attr_group_vm);
1184 } else {
1185 if(!diag308_set_works)
1186 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
1187 rc = sysfs_create_group(&reipl_kset->kobj,
1188 &reipl_ccw_attr_group_lpar);
ff6b8ea6 1189 }
a0443fbb
HB
1190 if (rc)
1191 return rc;
1192
1193 reipl_block_ccw_init(reipl_block_ccw);
1194 if (ipl_info.type == IPL_TYPE_CCW) {
ff6b8ea6 1195 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
a0443fbb
HB
1196 reipl_block_ccw_fill_parms(reipl_block_ccw);
1197 }
1198
ff6b8ea6
MH
1199 reipl_capabilities |= IPL_TYPE_CCW;
1200 return 0;
1201}
1202
1203static int __init reipl_fcp_init(void)
1204{
1205 int rc;
1206
008d2d11 1207 if (!diag308_set_works) {
684d2fd4 1208 if (ipl_info.type == IPL_TYPE_FCP) {
008d2d11 1209 make_attrs_ro(reipl_fcp_attrs);
684d2fd4
HB
1210 sys_reipl_fcp_scp_data_attr.attr.mode = S_IRUGO;
1211 } else
008d2d11
MH
1212 return 0;
1213 }
ff6b8ea6
MH
1214
1215 reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
1216 if (!reipl_block_fcp)
1217 return -ENOMEM;
684d2fd4
HB
1218
1219 /* sysfs: create fcp kset for mixing attr group and bin attrs */
1220 reipl_fcp_kset = kset_create_and_add(IPL_FCP_STR, NULL,
1221 &reipl_kset->kobj);
798620fb 1222 if (!reipl_fcp_kset) {
684d2fd4
HB
1223 free_page((unsigned long) reipl_block_fcp);
1224 return -ENOMEM;
1225 }
1226
1227 rc = sysfs_create_group(&reipl_fcp_kset->kobj, &reipl_fcp_attr_group);
ff6b8ea6 1228 if (rc) {
684d2fd4
HB
1229 kset_unregister(reipl_fcp_kset);
1230 free_page((unsigned long) reipl_block_fcp);
ff6b8ea6
MH
1231 return rc;
1232 }
684d2fd4 1233
69928601 1234 if (ipl_info.type == IPL_TYPE_FCP) {
ff6b8ea6 1235 memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
69928601
MH
1236 /*
1237 * Fix loadparm: There are systems where the (SCSI) LOADPARM
1238 * is invalid in the SCSI IPL parameter block, so take it
1239 * always from sclp_ipl_info.
1240 */
1241 memcpy(reipl_block_fcp->hdr.loadparm, sclp_ipl_info.loadparm,
1242 LOADPARM_LEN);
1243 } else {
ff6b8ea6
MH
1244 reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
1245 reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
fbb04f38 1246 reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
ff6b8ea6
MH
1247 reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
1248 reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL;
1249 }
1250 reipl_capabilities |= IPL_TYPE_FCP;
1251 return 0;
1252}
1253
4857d4bb
MH
1254static int __init reipl_type_init(void)
1255{
1256 enum ipl_type reipl_type = ipl_info.type;
1257 struct ipl_parameter_block *reipl_block;
1258 unsigned long size;
1259
1260 reipl_block = os_info_old_entry(OS_INFO_REIPL_BLOCK, &size);
1261 if (!reipl_block)
1262 goto out;
1263 /*
1264 * If we have an OS info reipl block, this will be used
1265 */
1266 if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_FCP) {
1267 memcpy(reipl_block_fcp, reipl_block, size);
1268 reipl_type = IPL_TYPE_FCP;
1269 } else if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_CCW) {
1270 memcpy(reipl_block_ccw, reipl_block, size);
1271 reipl_type = IPL_TYPE_CCW;
1272 }
1273out:
1274 return reipl_set_type(reipl_type);
1275}
1276
2bc89b5e 1277static int __init reipl_init(void)
ff6b8ea6
MH
1278{
1279 int rc;
1280
f62ed9e3 1281 reipl_kset = kset_create_and_add("reipl", NULL, firmware_kobj);
d91885be
GKH
1282 if (!reipl_kset)
1283 return -ENOMEM;
1284 rc = sysfs_create_file(&reipl_kset->kobj, &reipl_type_attr.attr);
ff6b8ea6 1285 if (rc) {
d91885be 1286 kset_unregister(reipl_kset);
ff6b8ea6
MH
1287 return rc;
1288 }
1289 rc = reipl_ccw_init();
1290 if (rc)
1291 return rc;
1292 rc = reipl_fcp_init();
fe355b7f
HY
1293 if (rc)
1294 return rc;
1295 rc = reipl_nss_init();
ff6b8ea6
MH
1296 if (rc)
1297 return rc;
4857d4bb 1298 return reipl_type_init();
ff6b8ea6
MH
1299}
1300
2bc89b5e
HC
1301static struct shutdown_action __refdata reipl_action = {
1302 .name = SHUTDOWN_ACTION_REIPL_STR,
1303 .fn = reipl_run,
1304 .init = reipl_init,
1305};
99ca4e58
MH
1306
1307/*
1308 * dump shutdown action: Dump Linux on shutdown.
1309 */
1310
1311/* FCP dump device attributes */
1312
eda4ddf7 1313DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%llx\n",
99ca4e58 1314 dump_block_fcp->ipl_info.fcp.wwpn);
eda4ddf7 1315DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%llx\n",
99ca4e58
MH
1316 dump_block_fcp->ipl_info.fcp.lun);
1317DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
1318 dump_block_fcp->ipl_info.fcp.bootprog);
1319DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
1320 dump_block_fcp->ipl_info.fcp.br_lba);
1321DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
1322 dump_block_fcp->ipl_info.fcp.devno);
1323
1324static struct attribute *dump_fcp_attrs[] = {
1325 &sys_dump_fcp_device_attr.attr,
1326 &sys_dump_fcp_wwpn_attr.attr,
1327 &sys_dump_fcp_lun_attr.attr,
1328 &sys_dump_fcp_bootprog_attr.attr,
1329 &sys_dump_fcp_br_lba_attr.attr,
1330 NULL,
1331};
1332
1333static struct attribute_group dump_fcp_attr_group = {
1334 .name = IPL_FCP_STR,
1335 .attrs = dump_fcp_attrs,
1336};
1337
1338/* CCW dump device attributes */
1339
1340DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
1341 dump_block_ccw->ipl_info.ccw.devno);
1342
1343static struct attribute *dump_ccw_attrs[] = {
1344 &sys_dump_ccw_device_attr.attr,
1345 NULL,
1346};
1347
1348static struct attribute_group dump_ccw_attr_group = {
1349 .name = IPL_CCW_STR,
1350 .attrs = dump_ccw_attrs,
1351};
1352
1353/* dump type */
1354
1355static int dump_set_type(enum dump_type type)
1356{
1357 if (!(dump_capabilities & type))
1358 return -EINVAL;
1359 switch (type) {
1360 case DUMP_TYPE_CCW:
48657d22
MH
1361 if (diag308_set_works)
1362 dump_method = DUMP_METHOD_CCW_DIAG;
1363 else if (MACHINE_IS_VM)
99ca4e58
MH
1364 dump_method = DUMP_METHOD_CCW_VM;
1365 else
1366 dump_method = DUMP_METHOD_CCW_CIO;
1367 break;
1368 case DUMP_TYPE_FCP:
1369 dump_method = DUMP_METHOD_FCP_DIAG;
1370 break;
1371 default:
1372 dump_method = DUMP_METHOD_NONE;
1373 }
1374 dump_type = type;
1375 return 0;
1376}
1377
1378static ssize_t dump_type_show(struct kobject *kobj,
1379 struct kobj_attribute *attr, char *page)
1380{
1381 return sprintf(page, "%s\n", dump_type_str(dump_type));
1382}
1383
1384static ssize_t dump_type_store(struct kobject *kobj,
1385 struct kobj_attribute *attr,
1386 const char *buf, size_t len)
1387{
1388 int rc = -EINVAL;
1389
1390 if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
1391 rc = dump_set_type(DUMP_TYPE_NONE);
1392 else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
1393 rc = dump_set_type(DUMP_TYPE_CCW);
1394 else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
1395 rc = dump_set_type(DUMP_TYPE_FCP);
1396 return (rc != 0) ? rc : len;
1397}
1398
1399static struct kobj_attribute dump_type_attr =
1400 __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
1401
1402static struct kset *dump_kset;
1403
0894b3ae
MH
1404static void diag308_dump(void *dump_block)
1405{
1406 diag308(DIAG308_SET, dump_block);
1407 while (1) {
1408 if (diag308(DIAG308_DUMP, NULL) != 0x302)
1409 break;
1410 udelay_simple(USEC_PER_SEC);
1411 }
1412}
1413
2c2df118 1414static void __dump_run(void *unused)
99ca4e58
MH
1415{
1416 struct ccw_dev_id devid;
1417 static char buf[100];
1418
1419 switch (dump_method) {
1420 case DUMP_METHOD_CCW_CIO:
99ca4e58
MH
1421 devid.devno = dump_block_ccw->ipl_info.ccw.devno;
1422 devid.ssid = 0;
1423 reipl_ccw_dev(&devid);
1424 break;
1425 case DUMP_METHOD_CCW_VM:
99ca4e58
MH
1426 sprintf(buf, "STORE STATUS");
1427 __cpcmd(buf, NULL, 0, NULL);
1428 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
1429 __cpcmd(buf, NULL, 0, NULL);
1430 break;
1431 case DUMP_METHOD_CCW_DIAG:
0894b3ae 1432 diag308_dump(dump_block_ccw);
99ca4e58
MH
1433 break;
1434 case DUMP_METHOD_FCP_DIAG:
0894b3ae 1435 diag308_dump(dump_block_fcp);
99ca4e58 1436 break;
2c2df118
HC
1437 default:
1438 break;
99ca4e58 1439 }
2c2df118
HC
1440}
1441
1442static void dump_run(struct shutdown_trigger *trigger)
1443{
1444 if (dump_method == DUMP_METHOD_NONE)
1445 return;
1446 smp_send_stop();
8b646bd7 1447 smp_call_ipl_cpu(__dump_run, NULL);
99ca4e58
MH
1448}
1449
ff6b8ea6
MH
1450static int __init dump_ccw_init(void)
1451{
1452 int rc;
1453
1454 dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
1455 if (!dump_block_ccw)
1456 return -ENOMEM;
d91885be 1457 rc = sysfs_create_group(&dump_kset->kobj, &dump_ccw_attr_group);
ff6b8ea6
MH
1458 if (rc) {
1459 free_page((unsigned long)dump_block_ccw);
1460 return rc;
1461 }
1462 dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
1463 dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
fbb04f38 1464 dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
ff6b8ea6 1465 dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
411ed322 1466 dump_capabilities |= DUMP_TYPE_CCW;
ff6b8ea6
MH
1467 return 0;
1468}
1469
ff6b8ea6
MH
1470static int __init dump_fcp_init(void)
1471{
1472 int rc;
1473
05dd2530 1474 if (!sclp_ipl_info.has_dump)
ff6b8ea6
MH
1475 return 0; /* LDIPL DUMP is not installed */
1476 if (!diag308_set_works)
1477 return 0;
1478 dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
1479 if (!dump_block_fcp)
1480 return -ENOMEM;
d91885be 1481 rc = sysfs_create_group(&dump_kset->kobj, &dump_fcp_attr_group);
ff6b8ea6
MH
1482 if (rc) {
1483 free_page((unsigned long)dump_block_fcp);
1484 return rc;
1485 }
1486 dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
1487 dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
fbb04f38 1488 dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
ff6b8ea6
MH
1489 dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
1490 dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
411ed322 1491 dump_capabilities |= DUMP_TYPE_FCP;
ff6b8ea6
MH
1492 return 0;
1493}
1494
2bc89b5e 1495static int __init dump_init(void)
ff6b8ea6
MH
1496{
1497 int rc;
1498
f62ed9e3 1499 dump_kset = kset_create_and_add("dump", NULL, firmware_kobj);
d91885be
GKH
1500 if (!dump_kset)
1501 return -ENOMEM;
99ca4e58 1502 rc = sysfs_create_file(&dump_kset->kobj, &dump_type_attr.attr);
ff6b8ea6 1503 if (rc) {
d91885be 1504 kset_unregister(dump_kset);
ff6b8ea6
MH
1505 return rc;
1506 }
1507 rc = dump_ccw_init();
1508 if (rc)
1509 return rc;
1510 rc = dump_fcp_init();
1511 if (rc)
1512 return rc;
411ed322 1513 dump_set_type(DUMP_TYPE_NONE);
ff6b8ea6
MH
1514 return 0;
1515}
1516
2bc89b5e
HC
1517static struct shutdown_action __refdata dump_action = {
1518 .name = SHUTDOWN_ACTION_DUMP_STR,
1519 .fn = dump_run,
1520 .init = dump_init,
1521};
99ca4e58 1522
099b7651
FM
1523static void dump_reipl_run(struct shutdown_trigger *trigger)
1524{
a7df7a94 1525 unsigned long ipib = (unsigned long) reipl_block_actual;
fbe76568
HC
1526 unsigned int csum;
1527
1528 csum = csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0);
1529 mem_assign_absolute(S390_lowcore.ipib, ipib);
1530 mem_assign_absolute(S390_lowcore.ipib_checksum, csum);
099b7651
FM
1531 dump_run(trigger);
1532}
1533
1534static int __init dump_reipl_init(void)
1535{
1536 if (!diag308_set_works)
1537 return -EOPNOTSUPP;
1538 else
1539 return 0;
1540}
1541
1542static struct shutdown_action __refdata dump_reipl_action = {
1543 .name = SHUTDOWN_ACTION_DUMP_REIPL_STR,
1544 .fn = dump_reipl_run,
1545 .init = dump_reipl_init,
1546};
1547
99ca4e58
MH
1548/*
1549 * vmcmd shutdown action: Trigger vm command on shutdown.
1550 */
1551
1552static char vmcmd_on_reboot[128];
1553static char vmcmd_on_panic[128];
1554static char vmcmd_on_halt[128];
1555static char vmcmd_on_poff[128];
7dd6b334 1556static char vmcmd_on_restart[128];
99ca4e58
MH
1557
1558DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot);
1559DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic);
1560DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt);
1561DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff);
7dd6b334 1562DEFINE_IPL_ATTR_STR_RW(vmcmd, on_restart, "%s\n", "%s\n", vmcmd_on_restart);
99ca4e58
MH
1563
1564static struct attribute *vmcmd_attrs[] = {
1565 &sys_vmcmd_on_reboot_attr.attr,
1566 &sys_vmcmd_on_panic_attr.attr,
1567 &sys_vmcmd_on_halt_attr.attr,
1568 &sys_vmcmd_on_poff_attr.attr,
7dd6b334 1569 &sys_vmcmd_on_restart_attr.attr,
99ca4e58
MH
1570 NULL,
1571};
1572
1573static struct attribute_group vmcmd_attr_group = {
1574 .attrs = vmcmd_attrs,
1575};
1576
1577static struct kset *vmcmd_kset;
1578
1579static void vmcmd_run(struct shutdown_trigger *trigger)
ff6b8ea6 1580{
8143adaf 1581 char *cmd;
99ca4e58
MH
1582
1583 if (strcmp(trigger->name, ON_REIPL_STR) == 0)
1584 cmd = vmcmd_on_reboot;
1585 else if (strcmp(trigger->name, ON_PANIC_STR) == 0)
1586 cmd = vmcmd_on_panic;
1587 else if (strcmp(trigger->name, ON_HALT_STR) == 0)
1588 cmd = vmcmd_on_halt;
1589 else if (strcmp(trigger->name, ON_POFF_STR) == 0)
1590 cmd = vmcmd_on_poff;
7dd6b334
MH
1591 else if (strcmp(trigger->name, ON_RESTART_STR) == 0)
1592 cmd = vmcmd_on_restart;
99ca4e58
MH
1593 else
1594 return;
1595
1596 if (strlen(cmd) == 0)
1597 return;
8143adaf 1598 __cpcmd(cmd, NULL, 0, NULL);
99ca4e58
MH
1599}
1600
1601static int vmcmd_init(void)
1602{
1603 if (!MACHINE_IS_VM)
b8e660b8 1604 return -EOPNOTSUPP;
99ca4e58
MH
1605 vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj);
1606 if (!vmcmd_kset)
1607 return -ENOMEM;
1608 return sysfs_create_group(&vmcmd_kset->kobj, &vmcmd_attr_group);
1609}
1610
1611static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR,
1612 vmcmd_run, vmcmd_init};
1613
1614/*
1615 * stop shutdown action: Stop Linux on shutdown.
1616 */
1617
1618static void stop_run(struct shutdown_trigger *trigger)
1619{
e1202eda
MH
1620 if (strcmp(trigger->name, ON_PANIC_STR) == 0 ||
1621 strcmp(trigger->name, ON_RESTART_STR) == 0)
c6547497 1622 disabled_wait((unsigned long) __builtin_return_address(0));
8b646bd7 1623 smp_stop_cpu();
99ca4e58
MH
1624}
1625
1626static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
1627 stop_run, NULL};
1628
1629/* action list */
1630
1631static struct shutdown_action *shutdown_actions_list[] = {
099b7651
FM
1632 &ipl_action, &reipl_action, &dump_reipl_action, &dump_action,
1633 &vmcmd_action, &stop_action};
99ca4e58
MH
1634#define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *))
1635
1636/*
1637 * Trigger section
1638 */
1639
1640static struct kset *shutdown_actions_kset;
1641
1642static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
1643 size_t len)
1644{
1645 int i;
099b7651 1646
99ca4e58 1647 for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
099b7651 1648 if (sysfs_streq(buf, shutdown_actions_list[i]->name)) {
81088819
FM
1649 if (shutdown_actions_list[i]->init_rc) {
1650 return shutdown_actions_list[i]->init_rc;
1651 } else {
1652 trigger->action = shutdown_actions_list[i];
1653 return len;
1654 }
99ca4e58
MH
1655 }
1656 }
1657 return -EINVAL;
1658}
1659
1660/* on reipl */
1661
1662static struct shutdown_trigger on_reboot_trigger = {ON_REIPL_STR,
1663 &reipl_action};
1664
1665static ssize_t on_reboot_show(struct kobject *kobj,
1666 struct kobj_attribute *attr, char *page)
1667{
1668 return sprintf(page, "%s\n", on_reboot_trigger.action->name);
1669}
1670
1671static ssize_t on_reboot_store(struct kobject *kobj,
1672 struct kobj_attribute *attr,
1673 const char *buf, size_t len)
1674{
1675 return set_trigger(buf, &on_reboot_trigger, len);
1676}
0f024379 1677static struct kobj_attribute on_reboot_attr = __ATTR_RW(on_reboot);
99ca4e58
MH
1678
1679static void do_machine_restart(char *__unused)
1680{
1681 smp_send_stop();
1682 on_reboot_trigger.action->fn(&on_reboot_trigger);
1683 reipl_run(NULL);
1684}
1685void (*_machine_restart)(char *command) = do_machine_restart;
1686
1687/* on panic */
1688
1689static struct shutdown_trigger on_panic_trigger = {ON_PANIC_STR, &stop_action};
1690
1691static ssize_t on_panic_show(struct kobject *kobj,
1692 struct kobj_attribute *attr, char *page)
1693{
1694 return sprintf(page, "%s\n", on_panic_trigger.action->name);
1695}
1696
1697static ssize_t on_panic_store(struct kobject *kobj,
1698 struct kobj_attribute *attr,
1699 const char *buf, size_t len)
1700{
1701 return set_trigger(buf, &on_panic_trigger, len);
1702}
0f024379 1703static struct kobj_attribute on_panic_attr = __ATTR_RW(on_panic);
99ca4e58
MH
1704
1705static void do_panic(void)
1706{
3ab121ab 1707 lgr_info_log();
99ca4e58
MH
1708 on_panic_trigger.action->fn(&on_panic_trigger);
1709 stop_run(&on_panic_trigger);
1710}
1711
7dd6b334
MH
1712/* on restart */
1713
1714static struct shutdown_trigger on_restart_trigger = {ON_RESTART_STR,
e1202eda 1715 &stop_action};
7dd6b334
MH
1716
1717static ssize_t on_restart_show(struct kobject *kobj,
1718 struct kobj_attribute *attr, char *page)
1719{
1720 return sprintf(page, "%s\n", on_restart_trigger.action->name);
1721}
1722
1723static ssize_t on_restart_store(struct kobject *kobj,
1724 struct kobj_attribute *attr,
1725 const char *buf, size_t len)
1726{
1727 return set_trigger(buf, &on_restart_trigger, len);
1728}
0f024379 1729static struct kobj_attribute on_restart_attr = __ATTR_RW(on_restart);
7dd6b334 1730
8b646bd7 1731static void __do_restart(void *ignore)
7dd6b334 1732{
fa7c0043 1733 __arch_local_irq_stosm(0x04); /* enable DAT */
7dd6b334 1734 smp_send_stop();
60a0c68d
MH
1735#ifdef CONFIG_CRASH_DUMP
1736 crash_kexec(NULL);
1737#endif
7dd6b334
MH
1738 on_restart_trigger.action->fn(&on_restart_trigger);
1739 stop_run(&on_restart_trigger);
1740}
1741
8b646bd7
MS
1742void do_restart(void)
1743{
3ab121ab
MH
1744 tracing_off();
1745 debug_locks_off();
1746 lgr_info_log();
8b646bd7
MS
1747 smp_call_online_cpu(__do_restart, NULL);
1748}
1749
99ca4e58
MH
1750/* on halt */
1751
1752static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};
1753
1754static ssize_t on_halt_show(struct kobject *kobj,
1755 struct kobj_attribute *attr, char *page)
1756{
1757 return sprintf(page, "%s\n", on_halt_trigger.action->name);
1758}
1759
1760static ssize_t on_halt_store(struct kobject *kobj,
1761 struct kobj_attribute *attr,
1762 const char *buf, size_t len)
1763{
1764 return set_trigger(buf, &on_halt_trigger, len);
1765}
0f024379 1766static struct kobj_attribute on_halt_attr = __ATTR_RW(on_halt);
99ca4e58
MH
1767
1768static void do_machine_halt(void)
1769{
1770 smp_send_stop();
1771 on_halt_trigger.action->fn(&on_halt_trigger);
1772 stop_run(&on_halt_trigger);
1773}
1774void (*_machine_halt)(void) = do_machine_halt;
1775
1776/* on power off */
1777
1778static struct shutdown_trigger on_poff_trigger = {ON_POFF_STR, &stop_action};
1779
1780static ssize_t on_poff_show(struct kobject *kobj,
1781 struct kobj_attribute *attr, char *page)
1782{
1783 return sprintf(page, "%s\n", on_poff_trigger.action->name);
1784}
1785
1786static ssize_t on_poff_store(struct kobject *kobj,
1787 struct kobj_attribute *attr,
1788 const char *buf, size_t len)
1789{
1790 return set_trigger(buf, &on_poff_trigger, len);
1791}
0f024379 1792static struct kobj_attribute on_poff_attr = __ATTR_RW(on_poff);
99ca4e58
MH
1793
1794static void do_machine_power_off(void)
1795{
1796 smp_send_stop();
1797 on_poff_trigger.action->fn(&on_poff_trigger);
1798 stop_run(&on_poff_trigger);
1799}
1800void (*_machine_power_off)(void) = do_machine_power_off;
1801
0f024379
SO
1802static struct attribute *shutdown_action_attrs[] = {
1803 &on_restart_attr.attr,
1804 &on_reboot_attr.attr,
1805 &on_panic_attr.attr,
1806 &on_halt_attr.attr,
1807 &on_poff_attr.attr,
1808 NULL,
1809};
1810
1811static struct attribute_group shutdown_action_attr_group = {
1812 .attrs = shutdown_action_attrs,
1813};
1814
99ca4e58
MH
1815static void __init shutdown_triggers_init(void)
1816{
d91885be 1817 shutdown_actions_kset = kset_create_and_add("shutdown_actions", NULL,
f62ed9e3 1818 firmware_kobj);
d91885be 1819 if (!shutdown_actions_kset)
99ca4e58 1820 goto fail;
0f024379
SO
1821 if (sysfs_create_group(&shutdown_actions_kset->kobj,
1822 &shutdown_action_attr_group))
7dd6b334 1823 goto fail;
99ca4e58
MH
1824 return;
1825fail:
1826 panic("shutdown_triggers_init failed\n");
1827}
1828
1829static void __init shutdown_actions_init(void)
1830{
1831 int i;
1832
1833 for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
1834 if (!shutdown_actions_list[i]->init)
1835 continue;
81088819
FM
1836 shutdown_actions_list[i]->init_rc =
1837 shutdown_actions_list[i]->init();
ff6b8ea6 1838 }
ff6b8ea6
MH
1839}
1840
1841static int __init s390_ipl_init(void)
1842{
69928601
MH
1843 char str[8] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40};
1844
d09293ae 1845 sclp_get_ipl_info(&sclp_ipl_info);
69928601
MH
1846 /*
1847 * Fix loadparm: There are systems where the (SCSI) LOADPARM
1848 * returned by read SCP info is invalid (contains EBCDIC blanks)
1849 * when the system has been booted via diag308. In that case we use
1850 * the value from diag308, if available.
1851 *
1852 * There are also systems where diag308 store does not work in
1853 * case the system is booted from HMC. Fortunately in this case
1854 * READ SCP info provides the correct value.
1855 */
1856 if (memcmp(sclp_ipl_info.loadparm, str, sizeof(str)) == 0 &&
1857 diag308_set_works)
1858 memcpy(sclp_ipl_info.loadparm, ipl_block.hdr.loadparm,
1859 LOADPARM_LEN);
99ca4e58
MH
1860 shutdown_actions_init();
1861 shutdown_triggers_init();
ff6b8ea6
MH
1862 return 0;
1863}
1864
1865__initcall(s390_ipl_init);
15e9b586 1866
99ca4e58
MH
1867static void __init strncpy_skip_quote(char *dst, char *src, int n)
1868{
1869 int sx, dx;
1870
1871 dx = 0;
1872 for (sx = 0; src[sx] != 0; sx++) {
1873 if (src[sx] == '"')
1874 continue;
1875 dst[dx++] = src[sx];
1876 if (dx >= n)
1877 break;
1878 }
1879}
1880
1881static int __init vmcmd_on_reboot_setup(char *str)
1882{
1883 if (!MACHINE_IS_VM)
1884 return 1;
1885 strncpy_skip_quote(vmcmd_on_reboot, str, 127);
1886 vmcmd_on_reboot[127] = 0;
1887 on_reboot_trigger.action = &vmcmd_action;
1888 return 1;
1889}
1890__setup("vmreboot=", vmcmd_on_reboot_setup);
1891
1892static int __init vmcmd_on_panic_setup(char *str)
1893{
1894 if (!MACHINE_IS_VM)
1895 return 1;
1896 strncpy_skip_quote(vmcmd_on_panic, str, 127);
1897 vmcmd_on_panic[127] = 0;
1898 on_panic_trigger.action = &vmcmd_action;
1899 return 1;
1900}
1901__setup("vmpanic=", vmcmd_on_panic_setup);
1902
1903static int __init vmcmd_on_halt_setup(char *str)
1904{
1905 if (!MACHINE_IS_VM)
1906 return 1;
1907 strncpy_skip_quote(vmcmd_on_halt, str, 127);
1908 vmcmd_on_halt[127] = 0;
1909 on_halt_trigger.action = &vmcmd_action;
1910 return 1;
1911}
1912__setup("vmhalt=", vmcmd_on_halt_setup);
1913
1914static int __init vmcmd_on_poff_setup(char *str)
1915{
1916 if (!MACHINE_IS_VM)
1917 return 1;
1918 strncpy_skip_quote(vmcmd_on_poff, str, 127);
1919 vmcmd_on_poff[127] = 0;
1920 on_poff_trigger.action = &vmcmd_action;
1921 return 1;
1922}
1923__setup("vmpoff=", vmcmd_on_poff_setup);
1924
1925static int on_panic_notify(struct notifier_block *self,
1926 unsigned long event, void *data)
1927{
1928 do_panic();
1929 return NOTIFY_OK;
1930}
1931
1932static struct notifier_block on_panic_nb = {
1933 .notifier_call = on_panic_notify,
7e9b580e 1934 .priority = INT_MIN,
99ca4e58
MH
1935};
1936
1937void __init setup_ipl(void)
1938{
1939 ipl_info.type = get_ipl_type();
1940 switch (ipl_info.type) {
1941 case IPL_TYPE_CCW:
1942 ipl_info.data.ccw.dev_id.devno = ipl_devno;
1943 ipl_info.data.ccw.dev_id.ssid = 0;
1944 break;
1945 case IPL_TYPE_FCP:
1946 case IPL_TYPE_FCP_DUMP:
1947 ipl_info.data.fcp.dev_id.devno =
1948 IPL_PARMBLOCK_START->ipl_info.fcp.devno;
1949 ipl_info.data.fcp.dev_id.ssid = 0;
1950 ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn;
1951 ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun;
1952 break;
1953 case IPL_TYPE_NSS:
1954 strncpy(ipl_info.data.nss.name, kernel_nss_name,
1955 sizeof(ipl_info.data.nss.name));
1956 break;
1957 case IPL_TYPE_UNKNOWN:
99ca4e58
MH
1958 /* We have no info to copy */
1959 break;
1960 }
1961 atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
1962}
1963
a0443fbb
HB
1964void __init ipl_update_parameters(void)
1965{
3a95e8eb
MH
1966 int rc;
1967
1968 rc = diag308(DIAG308_STORE, &ipl_block);
1969 if ((rc == DIAG308_RC_OK) || (rc == DIAG308_RC_NOCONFIG))
a0443fbb
HB
1970 diag308_set_works = 1;
1971}
1972
6fc321fd
HC
1973void __init ipl_save_parameters(void)
1974{
1975 struct cio_iplinfo iplinfo;
6fc321fd
HC
1976 void *src, *dst;
1977
1978 if (cio_get_iplinfo(&iplinfo))
1979 return;
1980
1981 ipl_devno = iplinfo.devno;
1982 ipl_flags |= IPL_DEVNO_VALID;
1983 if (!iplinfo.is_qdio)
1984 return;
1985 ipl_flags |= IPL_PARMBLOCK_VALID;
cbb870c8 1986 src = (void *)(unsigned long)S390_lowcore.ipl_parmblock_ptr;
6fc321fd
HC
1987 dst = (void *)IPL_PARMBLOCK_ORIGIN;
1988 memmove(dst, src, PAGE_SIZE);
cbb870c8 1989 S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN;
6fc321fd
HC
1990}
1991
15e9b586
HC
1992static LIST_HEAD(rcall);
1993static DEFINE_MUTEX(rcall_mutex);
1994
1995void register_reset_call(struct reset_call *reset)
1996{
1997 mutex_lock(&rcall_mutex);
1998 list_add(&reset->list, &rcall);
1999 mutex_unlock(&rcall_mutex);
2000}
2001EXPORT_SYMBOL_GPL(register_reset_call);
2002
2003void unregister_reset_call(struct reset_call *reset)
2004{
2005 mutex_lock(&rcall_mutex);
2006 list_del(&reset->list);
2007 mutex_unlock(&rcall_mutex);
2008}
2009EXPORT_SYMBOL_GPL(unregister_reset_call);
2010
2011static void do_reset_calls(void)
2012{
2013 struct reset_call *reset;
2014
9dc7356e
MH
2015 if (diag308_set_works) {
2016 diag308_reset();
2017 return;
2018 }
15e9b586
HC
2019 list_for_each_entry(reset, &rcall, list)
2020 reset->fn();
2021}
2022
c5dd8586 2023u32 dump_prefix_page;
15e9b586 2024
10ad34bc
MS
2025void s390_reset_system(void (*fn_pre)(void),
2026 void (*fn_post)(void *), void *data)
15e9b586
HC
2027{
2028 struct _lowcore *lc;
2029
15e9b586 2030 lc = (struct _lowcore *)(unsigned long) store_prefix();
a45e1414
MH
2031
2032 /* Stack for interrupt/machine check handler */
15e9b586
HC
2033 lc->panic_stack = S390_lowcore.panic_stack;
2034
da1cf23e 2035 /* Save prefix page address for dump case */
c5dd8586 2036 dump_prefix_page = (u32)(unsigned long) lc;
da1cf23e 2037
15e9b586
HC
2038 /* Disable prefixing */
2039 set_prefix(0);
2040
2041 /* Disable lowcore protection */
2042 __ctl_clear_bit(0,28);
2043
2044 /* Set new machine check handler */
e258d719 2045 S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT;
15e9b586 2046 S390_lowcore.mcck_new_psw.addr =
ab14de6c 2047 PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
a45e1414
MH
2048
2049 /* Set new program check handler */
e258d719 2050 S390_lowcore.program_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT;
a45e1414 2051 S390_lowcore.program_new_psw.addr =
ab14de6c 2052 PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
a45e1414 2053
852ffd0f
MH
2054 /*
2055 * Clear subchannel ID and number to signal new kernel that no CCW or
2056 * SCSI IPL has been done (for kexec and kdump)
2057 */
2058 S390_lowcore.subchannel_id = 0;
2059 S390_lowcore.subchannel_nr = 0;
2060
60a0c68d
MH
2061 /* Store status at absolute zero */
2062 store_status();
2063
10ad34bc
MS
2064 /* Call function before reset */
2065 if (fn_pre)
2066 fn_pre();
15e9b586 2067 do_reset_calls();
10ad34bc
MS
2068 /* Call function after reset */
2069 if (fn_post)
2070 fn_post(data);
15e9b586 2071}