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