s390/ipl: add eckd support
[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 6 * Author(s): Michael Holzheu <holzheu@de.ibm.com>
ff6b8ea6
MH
7 * Volker Sameske <sameske@de.ibm.com>
8 */
9
10#include <linux/types.h>
3994a52b
PG
11#include <linux/export.h>
12#include <linux/init.h>
ff6b8ea6
MH
13#include <linux/device.h>
14#include <linux/delay.h>
d9b25bdf 15#include <linux/kstrtox.h>
f39650de 16#include <linux/panic_notifier.h>
ff6b8ea6 17#include <linux/reboot.h>
03a4d208 18#include <linux/ctype.h>
0788fea4 19#include <linux/fs.h>
5a0e3ad6 20#include <linux/gfp.h>
60a0c68d 21#include <linux/crash_dump.h>
3ab121ab 22#include <linux/debug_locks.h>
d09a307f 23#include <asm/asm-extable.h>
1ec2772e 24#include <asm/diag.h>
46b05d26 25#include <asm/ipl.h>
ff6b8ea6
MH
26#include <asm/smp.h>
27#include <asm/setup.h>
28#include <asm/cpcmd.h>
03a4d208 29#include <asm/ebcdic.h>
ab14de6c 30#include <asm/sclp.h>
159d1ff8 31#include <asm/checksum.h>
3ab121ab 32#include <asm/debug.h>
4df29d2b 33#include <asm/abs_lowcore.h>
4857d4bb 34#include <asm/os_info.h>
49698745
VG
35#include <asm/sections.h>
36#include <asm/boot_data.h>
638ad34a 37#include "entry.h"
ff6b8ea6
MH
38
39#define IPL_PARM_BLOCK_VERSION 0
03a4d208 40
411ed322
MH
41#define IPL_UNKNOWN_STR "unknown"
42#define IPL_CCW_STR "ccw"
87fd22e0 43#define IPL_ECKD_STR "eckd"
411ed322
MH
44#define IPL_FCP_STR "fcp"
45#define IPL_FCP_DUMP_STR "fcp_dump"
3737e8ee 46#define IPL_NVME_STR "nvme"
d70e38cb 47#define IPL_NVME_DUMP_STR "nvme_dump"
411ed322 48#define IPL_NSS_STR "nss"
615b04b3 49
99ca4e58
MH
50#define DUMP_CCW_STR "ccw"
51#define DUMP_FCP_STR "fcp"
d70e38cb 52#define DUMP_NVME_STR "nvme"
99ca4e58
MH
53#define DUMP_NONE_STR "none"
54
55/*
56 * Four shutdown trigger types are supported:
57 * - panic
58 * - halt
59 * - power off
60 * - reipl
7dd6b334 61 * - restart
99ca4e58
MH
62 */
63#define ON_PANIC_STR "on_panic"
64#define ON_HALT_STR "on_halt"
65#define ON_POFF_STR "on_poff"
66#define ON_REIPL_STR "on_reboot"
7dd6b334 67#define ON_RESTART_STR "on_restart"
99ca4e58
MH
68
69struct shutdown_action;
70struct shutdown_trigger {
71 char *name;
72 struct shutdown_action *action;
73};
74
75/*
099b7651 76 * The following shutdown action types are supported:
99ca4e58
MH
77 */
78#define SHUTDOWN_ACTION_IPL_STR "ipl"
79#define SHUTDOWN_ACTION_REIPL_STR "reipl"
80#define SHUTDOWN_ACTION_DUMP_STR "dump"
81#define SHUTDOWN_ACTION_VMCMD_STR "vmcmd"
82#define SHUTDOWN_ACTION_STOP_STR "stop"
099b7651 83#define SHUTDOWN_ACTION_DUMP_REIPL_STR "dump_reipl"
99ca4e58
MH
84
85struct shutdown_action {
86 char *name;
87 void (*fn) (struct shutdown_trigger *trigger);
88 int (*init) (void);
81088819 89 int init_rc;
99ca4e58
MH
90};
91
ff6b8ea6
MH
92static char *ipl_type_str(enum ipl_type type)
93{
94 switch (type) {
ff6b8ea6
MH
95 case IPL_TYPE_CCW:
96 return IPL_CCW_STR;
87fd22e0
SS
97 case IPL_TYPE_ECKD:
98 return IPL_ECKD_STR;
ff6b8ea6
MH
99 case IPL_TYPE_FCP:
100 return IPL_FCP_STR;
411ed322
MH
101 case IPL_TYPE_FCP_DUMP:
102 return IPL_FCP_DUMP_STR;
fe355b7f
HY
103 case IPL_TYPE_NSS:
104 return IPL_NSS_STR;
3737e8ee
JH
105 case IPL_TYPE_NVME:
106 return IPL_NVME_STR;
d70e38cb
JH
107 case IPL_TYPE_NVME_DUMP:
108 return IPL_NVME_DUMP_STR;
ff6b8ea6
MH
109 case IPL_TYPE_UNKNOWN:
110 default:
111 return IPL_UNKNOWN_STR;
112 }
113}
114
411ed322
MH
115enum dump_type {
116 DUMP_TYPE_NONE = 1,
117 DUMP_TYPE_CCW = 2,
118 DUMP_TYPE_FCP = 4,
d70e38cb 119 DUMP_TYPE_NVME = 8,
411ed322
MH
120};
121
411ed322
MH
122static char *dump_type_str(enum dump_type type)
123{
124 switch (type) {
125 case DUMP_TYPE_NONE:
126 return DUMP_NONE_STR;
127 case DUMP_TYPE_CCW:
128 return DUMP_CCW_STR;
129 case DUMP_TYPE_FCP:
130 return DUMP_FCP_STR;
d70e38cb
JH
131 case DUMP_TYPE_NVME:
132 return DUMP_NVME_STR;
411ed322
MH
133 default:
134 return NULL;
135 }
136}
137
1e941d39
VG
138int __bootdata_preserved(ipl_block_valid);
139struct ipl_parameter_block __bootdata_preserved(ipl_block);
9641b8cc
MS
140int __bootdata_preserved(ipl_secure_flag);
141
142unsigned long __bootdata_preserved(ipl_cert_list_addr);
143unsigned long __bootdata_preserved(ipl_cert_list_size);
144
145unsigned long __bootdata(early_ipl_comp_list_addr);
146unsigned long __bootdata(early_ipl_comp_list_size);
a0443fbb 147
ff6b8ea6 148static int reipl_capabilities = IPL_TYPE_UNKNOWN;
fe355b7f 149
ff6b8ea6 150static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
ff6b8ea6 151static struct ipl_parameter_block *reipl_block_fcp;
23a457b8 152static struct ipl_parameter_block *reipl_block_nvme;
ff6b8ea6 153static struct ipl_parameter_block *reipl_block_ccw;
87fd22e0 154static struct ipl_parameter_block *reipl_block_eckd;
a0443fbb 155static struct ipl_parameter_block *reipl_block_nss;
099b7651 156static struct ipl_parameter_block *reipl_block_actual;
fe355b7f 157
411ed322
MH
158static int dump_capabilities = DUMP_TYPE_NONE;
159static enum dump_type dump_type = DUMP_TYPE_NONE;
ff6b8ea6 160static struct ipl_parameter_block *dump_block_fcp;
d70e38cb 161static struct ipl_parameter_block *dump_block_nvme;
ff6b8ea6
MH
162static struct ipl_parameter_block *dump_block_ccw;
163
05dd2530
HC
164static struct sclp_ipl_info sclp_ipl_info;
165
5627b922 166static bool reipl_nvme_clear;
1a2ae03b
GS
167static bool reipl_fcp_clear;
168static bool reipl_ccw_clear;
87fd22e0 169static bool reipl_eckd_clear;
1a2ae03b 170
1ec2772e 171static inline int __diag308(unsigned long subcode, void *addr)
ff6b8ea6 172{
5a4e0f58 173 union register_pair r1;
ff6b8ea6 174
5a4e0f58
HC
175 r1.even = (unsigned long) addr;
176 r1.odd = 0;
94c12cc7 177 asm volatile(
5a4e0f58 178 " diag %[r1],%[subcode],0x308\n"
6c22c986 179 "0: nopr %%r7\n"
94c12cc7 180 EX_TABLE(0b,0b)
5a4e0f58
HC
181 : [r1] "+&d" (r1.pair)
182 : [subcode] "d" (subcode)
183 : "cc", "memory");
184 return r1.odd;
ff6b8ea6 185}
1ec2772e
MS
186
187int diag308(unsigned long subcode, void *addr)
188{
189 diag_stat_inc(DIAG_STAT_X308);
190 return __diag308(subcode, addr);
191}
411ed322 192EXPORT_SYMBOL_GPL(diag308);
ff6b8ea6
MH
193
194/* SYSFS */
195
3be7ae63 196#define IPL_ATTR_SHOW_FN(_prefix, _name, _format, args...) \
9b949165
GKH
197static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
198 struct kobj_attribute *attr, \
ff6b8ea6
MH
199 char *page) \
200{ \
92fd3565 201 return scnprintf(page, PAGE_SIZE, _format, ##args); \
3be7ae63
SO
202}
203
18e22a17
SO
204#define IPL_ATTR_CCW_STORE_FN(_prefix, _name, _ipl_blk) \
205static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
206 struct kobj_attribute *attr, \
207 const char *buf, size_t len) \
208{ \
209 unsigned long long ssid, devno; \
210 \
211 if (sscanf(buf, "0.%llx.%llx\n", &ssid, &devno) != 2) \
212 return -EINVAL; \
213 \
214 if (ssid > __MAX_SSID || devno > __MAX_SUBCHANNEL) \
215 return -EINVAL; \
216 \
217 _ipl_blk.ssid = ssid; \
218 _ipl_blk.devno = devno; \
219 return len; \
220}
221
222#define DEFINE_IPL_CCW_ATTR_RW(_prefix, _name, _ipl_blk) \
223IPL_ATTR_SHOW_FN(_prefix, _name, "0.%x.%04x\n", \
224 _ipl_blk.ssid, _ipl_blk.devno); \
225IPL_ATTR_CCW_STORE_FN(_prefix, _name, _ipl_blk); \
226static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
227 __ATTR(_name, (S_IRUGO | S_IWUSR), \
228 sys_##_prefix##_##_name##_show, \
229 sys_##_prefix##_##_name##_store) \
230
3be7ae63
SO
231#define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \
232IPL_ATTR_SHOW_FN(_prefix, _name, _format, _value) \
9b949165 233static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
3be7ae63 234 __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL)
ff6b8ea6
MH
235
236#define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \
3be7ae63 237IPL_ATTR_SHOW_FN(_prefix, _name, _fmt_out, (unsigned long long) _value) \
9b949165
GKH
238static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
239 struct kobj_attribute *attr, \
ff6b8ea6
MH
240 const char *buf, size_t len) \
241{ \
242 unsigned long long value; \
243 if (sscanf(buf, _fmt_in, &value) != 1) \
244 return -EINVAL; \
245 _value = value; \
246 return len; \
247} \
9b949165 248static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
ff6b8ea6
MH
249 __ATTR(_name,(S_IRUGO | S_IWUSR), \
250 sys_##_prefix##_##_name##_show, \
3be7ae63 251 sys_##_prefix##_##_name##_store)
ff6b8ea6 252
fe355b7f 253#define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
3be7ae63 254IPL_ATTR_SHOW_FN(_prefix, _name, _fmt_out, _value) \
9b949165
GKH
255static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
256 struct kobj_attribute *attr, \
fe355b7f
HY
257 const char *buf, size_t len) \
258{ \
99ca4e58 259 strncpy(_value, buf, sizeof(_value) - 1); \
1d802e24 260 strim(_value); \
fe355b7f
HY
261 return len; \
262} \
9b949165 263static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
fe355b7f
HY
264 __ATTR(_name,(S_IRUGO | S_IWUSR), \
265 sys_##_prefix##_##_name##_show, \
3be7ae63 266 sys_##_prefix##_##_name##_store)
fe355b7f 267
ff6b8ea6
MH
268/*
269 * ipl section
270 */
271
411ed322 272static __init enum ipl_type get_ipl_type(void)
ff6b8ea6 273{
d08091ac 274 if (!ipl_block_valid)
ff6b8ea6 275 return IPL_TYPE_UNKNOWN;
d08091ac 276
5f1207fb
MS
277 switch (ipl_block.pb0_hdr.pbt) {
278 case IPL_PBT_CCW:
ff6b8ea6 279 return IPL_TYPE_CCW;
5f1207fb
MS
280 case IPL_PBT_FCP:
281 if (ipl_block.fcp.opt == IPL_PB0_FCP_OPT_DUMP)
d08091ac
VG
282 return IPL_TYPE_FCP_DUMP;
283 else
284 return IPL_TYPE_FCP;
3737e8ee 285 case IPL_PBT_NVME:
d70e38cb
JH
286 if (ipl_block.nvme.opt == IPL_PB0_NVME_OPT_DUMP)
287 return IPL_TYPE_NVME_DUMP;
288 else
289 return IPL_TYPE_NVME;
87fd22e0
SS
290 case IPL_PBT_ECKD:
291 return IPL_TYPE_ECKD;
d08091ac
VG
292 }
293 return IPL_TYPE_UNKNOWN;
ff6b8ea6
MH
294}
295
411ed322
MH
296struct ipl_info ipl_info;
297EXPORT_SYMBOL_GPL(ipl_info);
298
9b949165
GKH
299static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
300 char *page)
ff6b8ea6 301{
411ed322 302 return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
ff6b8ea6
MH
303}
304
9b949165 305static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
ff6b8ea6 306
9641b8cc
MS
307static ssize_t ipl_secure_show(struct kobject *kobj,
308 struct kobj_attribute *attr, char *page)
309{
310 return sprintf(page, "%i\n", !!ipl_secure_flag);
311}
312
313static struct kobj_attribute sys_ipl_secure_attr =
314 __ATTR(secure, 0444, ipl_secure_show, NULL);
315
c9896acc
PR
316static ssize_t ipl_has_secure_show(struct kobject *kobj,
317 struct kobj_attribute *attr, char *page)
318{
1b2be207 319 return sprintf(page, "%i\n", !!sclp.has_sipl);
c9896acc
PR
320}
321
322static struct kobj_attribute sys_ipl_has_secure_attr =
323 __ATTR(has_secure, 0444, ipl_has_secure_show, NULL);
324
a0443fbb
HB
325static ssize_t ipl_vm_parm_show(struct kobject *kobj,
326 struct kobj_attribute *attr, char *page)
327{
328 char parm[DIAG308_VMPARM_SIZE + 1] = {};
329
5f1207fb 330 if (ipl_block_valid && (ipl_block.pb0_hdr.pbt == IPL_PBT_CCW))
49698745 331 ipl_block_get_ascii_vmparm(parm, sizeof(parm), &ipl_block);
a0443fbb
HB
332 return sprintf(page, "%s\n", parm);
333}
334
335static struct kobj_attribute sys_ipl_vm_parm_attr =
336 __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL);
337
9b949165
GKH
338static ssize_t sys_ipl_device_show(struct kobject *kobj,
339 struct kobj_attribute *attr, char *page)
ff6b8ea6 340{
411ed322 341 switch (ipl_info.type) {
ff6b8ea6 342 case IPL_TYPE_CCW:
86c74d86
MS
343 return sprintf(page, "0.%x.%04x\n", ipl_block.ccw.ssid,
344 ipl_block.ccw.devno);
87fd22e0
SS
345 case IPL_TYPE_ECKD:
346 return sprintf(page, "0.%x.%04x\n", ipl_block.eckd.ssid,
347 ipl_block.eckd.devno);
ff6b8ea6 348 case IPL_TYPE_FCP:
411ed322 349 case IPL_TYPE_FCP_DUMP:
86c74d86 350 return sprintf(page, "0.0.%04x\n", ipl_block.fcp.devno);
3737e8ee 351 case IPL_TYPE_NVME:
d70e38cb 352 case IPL_TYPE_NVME_DUMP:
3737e8ee 353 return sprintf(page, "%08ux\n", ipl_block.nvme.fid);
ff6b8ea6
MH
354 default:
355 return 0;
356 }
357}
358
9b949165 359static struct kobj_attribute sys_ipl_device_attr =
ff6b8ea6
MH
360 __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
361
2c3c8bea
CW
362static ssize_t ipl_parameter_read(struct file *filp, struct kobject *kobj,
363 struct bin_attribute *attr, char *buf,
364 loff_t off, size_t count)
ff6b8ea6 365{
bdbfe185
VG
366 return memory_read_from_buffer(buf, count, &off, &ipl_block,
367 ipl_block.hdr.len);
ff6b8ea6 368}
22d557ab
SO
369static struct bin_attribute ipl_parameter_attr =
370 __BIN_ATTR(binary_parameter, S_IRUGO, ipl_parameter_read, NULL,
371 PAGE_SIZE);
ff6b8ea6 372
2c3c8bea
CW
373static ssize_t ipl_scp_data_read(struct file *filp, struct kobject *kobj,
374 struct bin_attribute *attr, char *buf,
375 loff_t off, size_t count)
ff6b8ea6 376{
86c74d86
MS
377 unsigned int size = ipl_block.fcp.scp_data_len;
378 void *scp_data = &ipl_block.fcp.scp_data;
ff6b8ea6 379
0788fea4 380 return memory_read_from_buffer(buf, count, &off, scp_data, size);
ff6b8ea6 381}
3737e8ee
JH
382
383static ssize_t ipl_nvme_scp_data_read(struct file *filp, struct kobject *kobj,
384 struct bin_attribute *attr, char *buf,
385 loff_t off, size_t count)
386{
387 unsigned int size = ipl_block.nvme.scp_data_len;
388 void *scp_data = &ipl_block.nvme.scp_data;
389
390 return memory_read_from_buffer(buf, count, &off, scp_data, size);
391}
392
87fd22e0
SS
393static ssize_t ipl_eckd_scp_data_read(struct file *filp, struct kobject *kobj,
394 struct bin_attribute *attr, char *buf,
395 loff_t off, size_t count)
396{
397 unsigned int size = ipl_block.eckd.scp_data_len;
398 void *scp_data = &ipl_block.eckd.scp_data;
399
400 return memory_read_from_buffer(buf, count, &off, scp_data, size);
401}
402
22d557ab
SO
403static struct bin_attribute ipl_scp_data_attr =
404 __BIN_ATTR(scp_data, S_IRUGO, ipl_scp_data_read, NULL, PAGE_SIZE);
ff6b8ea6 405
3737e8ee
JH
406static struct bin_attribute ipl_nvme_scp_data_attr =
407 __BIN_ATTR(scp_data, S_IRUGO, ipl_nvme_scp_data_read, NULL, PAGE_SIZE);
408
87fd22e0
SS
409static struct bin_attribute ipl_eckd_scp_data_attr =
410 __BIN_ATTR(scp_data, S_IRUGO, ipl_eckd_scp_data_read, NULL, PAGE_SIZE);
411
22d557ab
SO
412static struct bin_attribute *ipl_fcp_bin_attrs[] = {
413 &ipl_parameter_attr,
414 &ipl_scp_data_attr,
415 NULL,
ff6b8ea6
MH
416};
417
3737e8ee
JH
418static struct bin_attribute *ipl_nvme_bin_attrs[] = {
419 &ipl_parameter_attr,
420 &ipl_nvme_scp_data_attr,
421 NULL,
422};
423
87fd22e0
SS
424static struct bin_attribute *ipl_eckd_bin_attrs[] = {
425 &ipl_parameter_attr,
426 &ipl_eckd_scp_data_attr,
427 NULL,
428};
429
ff6b8ea6
MH
430/* FCP ipl device attributes */
431
bdbfe185 432DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n",
86c74d86 433 (unsigned long long)ipl_block.fcp.wwpn);
bdbfe185 434DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n",
86c74d86 435 (unsigned long long)ipl_block.fcp.lun);
bdbfe185 436DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n",
86c74d86 437 (unsigned long long)ipl_block.fcp.bootprog);
bdbfe185 438DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n",
86c74d86 439 (unsigned long long)ipl_block.fcp.br_lba);
ff6b8ea6 440
3737e8ee
JH
441/* NVMe ipl device attributes */
442DEFINE_IPL_ATTR_RO(ipl_nvme, fid, "0x%08llx\n",
443 (unsigned long long)ipl_block.nvme.fid);
444DEFINE_IPL_ATTR_RO(ipl_nvme, nsid, "0x%08llx\n",
445 (unsigned long long)ipl_block.nvme.nsid);
446DEFINE_IPL_ATTR_RO(ipl_nvme, bootprog, "%lld\n",
447 (unsigned long long)ipl_block.nvme.bootprog);
448DEFINE_IPL_ATTR_RO(ipl_nvme, br_lba, "%lld\n",
449 (unsigned long long)ipl_block.nvme.br_lba);
450
87fd22e0
SS
451/* ECKD ipl device attributes */
452DEFINE_IPL_ATTR_RO(ipl_eckd, bootprog, "%lld\n",
453 (unsigned long long)ipl_block.eckd.bootprog);
454
455#define IPL_ATTR_BR_CHR_SHOW_FN(_name, _ipb) \
456static ssize_t eckd_##_name##_br_chr_show(struct kobject *kobj, \
457 struct kobj_attribute *attr, \
458 char *buf) \
459{ \
460 struct ipl_pb0_eckd *ipb = &(_ipb); \
461 \
462 if (!ipb->br_chr.cyl && \
463 !ipb->br_chr.head && \
464 !ipb->br_chr.record) \
465 return sprintf(buf, "auto\n"); \
466 \
467 return sprintf(buf, "0x%x,0x%x,0x%x\n", \
468 ipb->br_chr.cyl, \
469 ipb->br_chr.head, \
470 ipb->br_chr.record); \
471}
472
473#define IPL_ATTR_BR_CHR_STORE_FN(_name, _ipb) \
474static ssize_t eckd_##_name##_br_chr_store(struct kobject *kobj, \
475 struct kobj_attribute *attr, \
476 const char *buf, size_t len) \
477{ \
478 struct ipl_pb0_eckd *ipb = &(_ipb); \
479 unsigned long args[3] = { 0 }; \
480 char *p, *p1, *tmp = NULL; \
481 int i, rc; \
482 \
483 if (!strncmp(buf, "auto", 4)) \
484 goto out; \
485 \
486 tmp = kstrdup(buf, GFP_KERNEL); \
487 p = tmp; \
488 for (i = 0; i < 3; i++) { \
489 p1 = strsep(&p, ", "); \
490 if (!p1) { \
491 rc = -EINVAL; \
492 goto err; \
493 } \
494 rc = kstrtoul(p1, 0, args + i); \
495 if (rc) \
496 goto err; \
497 } \
498 \
499 rc = -EINVAL; \
500 if (i != 3) \
501 goto err; \
502 \
503 if ((args[0] || args[1]) && !args[2]) \
504 goto err; \
505 \
506 if (args[0] > UINT_MAX || args[1] > 255 || args[2] > 255) \
507 goto err; \
508 \
509out: \
510 ipb->br_chr.cyl = args[0]; \
511 ipb->br_chr.head = args[1]; \
512 ipb->br_chr.record = args[2]; \
513 rc = len; \
514err: \
515 kfree(tmp); \
516 return rc; \
517}
518
519IPL_ATTR_BR_CHR_SHOW_FN(ipl, ipl_block.eckd);
520static struct kobj_attribute sys_ipl_eckd_br_chr_attr =
521 __ATTR(br_chr, (S_IRUGO | S_IWUSR),
522 eckd_ipl_br_chr_show,
523 NULL);
524
525IPL_ATTR_BR_CHR_SHOW_FN(reipl, reipl_block_eckd->eckd);
526IPL_ATTR_BR_CHR_STORE_FN(reipl, reipl_block_eckd->eckd);
527
528static struct kobj_attribute sys_reipl_eckd_br_chr_attr =
529 __ATTR(br_chr, (S_IRUGO | S_IWUSR),
530 eckd_reipl_br_chr_show,
531 eckd_reipl_br_chr_store);
532
9b949165
GKH
533static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
534 struct kobj_attribute *attr, char *page)
03a4d208
MH
535{
536 char loadparm[LOADPARM_LEN + 1] = {};
537
05dd2530 538 if (!sclp_ipl_info.is_valid)
03a4d208 539 return sprintf(page, "#unknown#\n");
05dd2530 540 memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
03a4d208 541 EBCASC(loadparm, LOADPARM_LEN);
1d802e24 542 strim(loadparm);
03a4d208
MH
543 return sprintf(page, "%s\n", loadparm);
544}
545
9b949165 546static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
03a4d208
MH
547 __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
548
69928601
MH
549static struct attribute *ipl_fcp_attrs[] = {
550 &sys_ipl_type_attr.attr,
551 &sys_ipl_device_attr.attr,
552 &sys_ipl_fcp_wwpn_attr.attr,
553 &sys_ipl_fcp_lun_attr.attr,
554 &sys_ipl_fcp_bootprog_attr.attr,
555 &sys_ipl_fcp_br_lba_attr.attr,
556 &sys_ipl_ccw_loadparm_attr.attr,
9641b8cc 557 &sys_ipl_secure_attr.attr,
c9896acc 558 &sys_ipl_has_secure_attr.attr,
69928601
MH
559 NULL,
560};
561
562static struct attribute_group ipl_fcp_attr_group = {
563 .attrs = ipl_fcp_attrs,
22d557ab 564 .bin_attrs = ipl_fcp_bin_attrs,
69928601
MH
565};
566
3737e8ee
JH
567static struct attribute *ipl_nvme_attrs[] = {
568 &sys_ipl_type_attr.attr,
569 &sys_ipl_nvme_fid_attr.attr,
570 &sys_ipl_nvme_nsid_attr.attr,
571 &sys_ipl_nvme_bootprog_attr.attr,
572 &sys_ipl_nvme_br_lba_attr.attr,
573 &sys_ipl_ccw_loadparm_attr.attr,
574 &sys_ipl_secure_attr.attr,
575 &sys_ipl_has_secure_attr.attr,
576 NULL,
577};
578
579static struct attribute_group ipl_nvme_attr_group = {
580 .attrs = ipl_nvme_attrs,
581 .bin_attrs = ipl_nvme_bin_attrs,
582};
583
87fd22e0
SS
584static struct attribute *ipl_eckd_attrs[] = {
585 &sys_ipl_type_attr.attr,
586 &sys_ipl_eckd_bootprog_attr.attr,
587 &sys_ipl_eckd_br_chr_attr.attr,
588 &sys_ipl_device_attr.attr,
589 &sys_ipl_secure_attr.attr,
590 &sys_ipl_has_secure_attr.attr,
591 NULL,
592};
593
594static struct attribute_group ipl_eckd_attr_group = {
595 .attrs = ipl_eckd_attrs,
596 .bin_attrs = ipl_eckd_bin_attrs,
597};
3737e8ee 598
69928601
MH
599/* CCW ipl device attributes */
600
a0443fbb
HB
601static struct attribute *ipl_ccw_attrs_vm[] = {
602 &sys_ipl_type_attr.attr,
603 &sys_ipl_device_attr.attr,
604 &sys_ipl_ccw_loadparm_attr.attr,
605 &sys_ipl_vm_parm_attr.attr,
9641b8cc 606 &sys_ipl_secure_attr.attr,
c9896acc 607 &sys_ipl_has_secure_attr.attr,
a0443fbb
HB
608 NULL,
609};
610
611static struct attribute *ipl_ccw_attrs_lpar[] = {
ff6b8ea6
MH
612 &sys_ipl_type_attr.attr,
613 &sys_ipl_device_attr.attr,
03a4d208 614 &sys_ipl_ccw_loadparm_attr.attr,
9641b8cc 615 &sys_ipl_secure_attr.attr,
c9896acc 616 &sys_ipl_has_secure_attr.attr,
ff6b8ea6
MH
617 NULL,
618};
619
a0443fbb
HB
620static struct attribute_group ipl_ccw_attr_group_vm = {
621 .attrs = ipl_ccw_attrs_vm,
622};
623
624static struct attribute_group ipl_ccw_attr_group_lpar = {
625 .attrs = ipl_ccw_attrs_lpar
ff6b8ea6
MH
626};
627
628/* UNKNOWN ipl device attributes */
629
630static struct attribute *ipl_unknown_attrs[] = {
631 &sys_ipl_type_attr.attr,
632 NULL,
633};
634
635static struct attribute_group ipl_unknown_attr_group = {
636 .attrs = ipl_unknown_attrs,
637};
638
d91885be 639static struct kset *ipl_kset;
ff6b8ea6 640
2c2df118 641static void __ipl_run(void *unused)
99ca4e58 642{
d768bd89 643 __bpon();
0599eead 644 diag308(DIAG308_LOAD_CLEAR, NULL);
99ca4e58
MH
645}
646
2c2df118
HC
647static void ipl_run(struct shutdown_trigger *trigger)
648{
8b646bd7 649 smp_call_ipl_cpu(__ipl_run, NULL);
2c2df118
HC
650}
651
2bc89b5e 652static int __init ipl_init(void)
99ca4e58
MH
653{
654 int rc;
655
656 ipl_kset = kset_create_and_add("ipl", NULL, firmware_kobj);
657 if (!ipl_kset) {
658 rc = -ENOMEM;
659 goto out;
660 }
661 switch (ipl_info.type) {
662 case IPL_TYPE_CCW:
a0443fbb
HB
663 if (MACHINE_IS_VM)
664 rc = sysfs_create_group(&ipl_kset->kobj,
665 &ipl_ccw_attr_group_vm);
666 else
667 rc = sysfs_create_group(&ipl_kset->kobj,
668 &ipl_ccw_attr_group_lpar);
99ca4e58 669 break;
87fd22e0
SS
670 case IPL_TYPE_ECKD:
671 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_eckd_attr_group);
672 break;
99ca4e58
MH
673 case IPL_TYPE_FCP:
674 case IPL_TYPE_FCP_DUMP:
22d557ab 675 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
99ca4e58 676 break;
3737e8ee 677 case IPL_TYPE_NVME:
d70e38cb 678 case IPL_TYPE_NVME_DUMP:
3737e8ee
JH
679 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_nvme_attr_group);
680 break;
99ca4e58
MH
681 default:
682 rc = sysfs_create_group(&ipl_kset->kobj,
683 &ipl_unknown_attr_group);
684 break;
685 }
686out:
687 if (rc)
688 panic("ipl_init failed: rc = %i\n", rc);
689
690 return 0;
691}
692
2bc89b5e
HC
693static struct shutdown_action __refdata ipl_action = {
694 .name = SHUTDOWN_ACTION_IPL_STR,
695 .fn = ipl_run,
696 .init = ipl_init,
697};
99ca4e58 698
ff6b8ea6 699/*
99ca4e58 700 * reipl shutdown action: Reboot Linux on shutdown.
ff6b8ea6
MH
701 */
702
a0443fbb
HB
703/* VM IPL PARM attributes */
704static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb,
705 char *page)
706{
707 char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
708
49698745 709 ipl_block_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
a0443fbb
HB
710 return sprintf(page, "%s\n", vmparm);
711}
712
713static ssize_t reipl_generic_vmparm_store(struct ipl_parameter_block *ipb,
714 size_t vmparm_max,
715 const char *buf, size_t len)
716{
717 int i, ip_len;
718
719 /* ignore trailing newline */
720 ip_len = len;
721 if ((len > 0) && (buf[len - 1] == '\n'))
722 ip_len--;
723
724 if (ip_len > vmparm_max)
725 return -EINVAL;
726
727 /* parm is used to store kernel options, check for common chars */
728 for (i = 0; i < ip_len; i++)
729 if (!(isalnum(buf[i]) || isascii(buf[i]) || isprint(buf[i])))
730 return -EINVAL;
731
86c74d86
MS
732 memset(ipb->ccw.vm_parm, 0, DIAG308_VMPARM_SIZE);
733 ipb->ccw.vm_parm_len = ip_len;
a0443fbb 734 if (ip_len > 0) {
5f1207fb 735 ipb->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_VP;
86c74d86
MS
736 memcpy(ipb->ccw.vm_parm, buf, ip_len);
737 ASCEBC(ipb->ccw.vm_parm, ip_len);
a0443fbb 738 } else {
5f1207fb 739 ipb->ccw.vm_flags &= ~IPL_PB0_CCW_VM_FLAG_VP;
a0443fbb
HB
740 }
741
742 return len;
743}
744
745/* NSS wrapper */
746static ssize_t reipl_nss_vmparm_show(struct kobject *kobj,
747 struct kobj_attribute *attr, char *page)
748{
749 return reipl_generic_vmparm_show(reipl_block_nss, page);
750}
751
752static ssize_t reipl_nss_vmparm_store(struct kobject *kobj,
753 struct kobj_attribute *attr,
754 const char *buf, size_t len)
755{
756 return reipl_generic_vmparm_store(reipl_block_nss, 56, buf, len);
757}
758
759/* CCW wrapper */
760static ssize_t reipl_ccw_vmparm_show(struct kobject *kobj,
761 struct kobj_attribute *attr, char *page)
762{
763 return reipl_generic_vmparm_show(reipl_block_ccw, page);
764}
765
766static ssize_t reipl_ccw_vmparm_store(struct kobject *kobj,
767 struct kobj_attribute *attr,
768 const char *buf, size_t len)
769{
770 return reipl_generic_vmparm_store(reipl_block_ccw, 64, buf, len);
771}
772
773static struct kobj_attribute sys_reipl_nss_vmparm_attr =
774 __ATTR(parm, S_IRUGO | S_IWUSR, reipl_nss_vmparm_show,
775 reipl_nss_vmparm_store);
776static struct kobj_attribute sys_reipl_ccw_vmparm_attr =
777 __ATTR(parm, S_IRUGO | S_IWUSR, reipl_ccw_vmparm_show,
778 reipl_ccw_vmparm_store);
779
ff6b8ea6
MH
780/* FCP reipl device attributes */
781
2c3c8bea 782static ssize_t reipl_fcp_scpdata_read(struct file *filp, struct kobject *kobj,
684d2fd4
HB
783 struct bin_attribute *attr,
784 char *buf, loff_t off, size_t count)
785{
86c74d86
MS
786 size_t size = reipl_block_fcp->fcp.scp_data_len;
787 void *scp_data = reipl_block_fcp->fcp.scp_data;
684d2fd4
HB
788
789 return memory_read_from_buffer(buf, count, &off, scp_data, size);
790}
791
2c3c8bea 792static ssize_t reipl_fcp_scpdata_write(struct file *filp, struct kobject *kobj,
684d2fd4
HB
793 struct bin_attribute *attr,
794 char *buf, loff_t off, size_t count)
795{
e0bedada 796 size_t scpdata_len = count;
684d2fd4 797 size_t padding;
684d2fd4 798
684d2fd4 799
e0bedada
SO
800 if (off)
801 return -EINVAL;
684d2fd4 802
86c74d86 803 memcpy(reipl_block_fcp->fcp.scp_data, buf, count);
684d2fd4
HB
804 if (scpdata_len % 8) {
805 padding = 8 - (scpdata_len % 8);
86c74d86 806 memset(reipl_block_fcp->fcp.scp_data + scpdata_len,
684d2fd4
HB
807 0, padding);
808 scpdata_len += padding;
809 }
810
5f1207fb
MS
811 reipl_block_fcp->hdr.len = IPL_BP_FCP_LEN + scpdata_len;
812 reipl_block_fcp->fcp.len = IPL_BP0_FCP_LEN + scpdata_len;
86c74d86 813 reipl_block_fcp->fcp.scp_data_len = scpdata_len;
684d2fd4
HB
814
815 return count;
816}
22d557ab
SO
817static struct bin_attribute sys_reipl_fcp_scp_data_attr =
818 __BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_fcp_scpdata_read,
e0bedada 819 reipl_fcp_scpdata_write, DIAG308_SCPDATA_SIZE);
684d2fd4 820
22d557ab
SO
821static struct bin_attribute *reipl_fcp_bin_attrs[] = {
822 &sys_reipl_fcp_scp_data_attr,
823 NULL,
684d2fd4
HB
824};
825
eda4ddf7 826DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%llx\n",
86c74d86 827 reipl_block_fcp->fcp.wwpn);
eda4ddf7 828DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%llx\n",
86c74d86 829 reipl_block_fcp->fcp.lun);
ff6b8ea6 830DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
86c74d86 831 reipl_block_fcp->fcp.bootprog);
ff6b8ea6 832DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
86c74d86 833 reipl_block_fcp->fcp.br_lba);
ff6b8ea6 834DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
86c74d86 835 reipl_block_fcp->fcp.devno);
ff6b8ea6 836
a0443fbb
HB
837static void reipl_get_ascii_loadparm(char *loadparm,
838 struct ipl_parameter_block *ibp)
03a4d208 839{
5f1207fb 840 memcpy(loadparm, ibp->common.loadparm, LOADPARM_LEN);
03a4d208
MH
841 EBCASC(loadparm, LOADPARM_LEN);
842 loadparm[LOADPARM_LEN] = 0;
1d802e24 843 strim(loadparm);
03a4d208
MH
844}
845
a0443fbb
HB
846static ssize_t reipl_generic_loadparm_show(struct ipl_parameter_block *ipb,
847 char *page)
03a4d208
MH
848{
849 char buf[LOADPARM_LEN + 1];
850
a0443fbb 851 reipl_get_ascii_loadparm(buf, ipb);
03a4d208
MH
852 return sprintf(page, "%s\n", buf);
853}
854
a0443fbb
HB
855static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
856 const char *buf, size_t len)
03a4d208
MH
857{
858 int i, lp_len;
859
860 /* ignore trailing newline */
861 lp_len = len;
862 if ((len > 0) && (buf[len - 1] == '\n'))
863 lp_len--;
864 /* loadparm can have max 8 characters and must not start with a blank */
865 if ((lp_len > LOADPARM_LEN) || ((lp_len > 0) && (buf[0] == ' ')))
866 return -EINVAL;
867 /* loadparm can only contain "a-z,A-Z,0-9,SP,." */
868 for (i = 0; i < lp_len; i++) {
869 if (isalpha(buf[i]) || isdigit(buf[i]) || (buf[i] == ' ') ||
870 (buf[i] == '.'))
871 continue;
872 return -EINVAL;
873 }
874 /* initialize loadparm with blanks */
5f1207fb 875 memset(ipb->common.loadparm, ' ', LOADPARM_LEN);
03a4d208 876 /* copy and convert to ebcdic */
5f1207fb
MS
877 memcpy(ipb->common.loadparm, buf, lp_len);
878 ASCEBC(ipb->common.loadparm, LOADPARM_LEN);
879 ipb->common.flags |= IPL_PB0_FLAG_LOADPARM;
03a4d208
MH
880 return len;
881}
882
69928601
MH
883/* FCP wrapper */
884static ssize_t reipl_fcp_loadparm_show(struct kobject *kobj,
885 struct kobj_attribute *attr, char *page)
886{
887 return reipl_generic_loadparm_show(reipl_block_fcp, page);
888}
889
890static ssize_t reipl_fcp_loadparm_store(struct kobject *kobj,
891 struct kobj_attribute *attr,
892 const char *buf, size_t len)
893{
894 return reipl_generic_loadparm_store(reipl_block_fcp, buf, len);
895}
896
897static struct kobj_attribute sys_reipl_fcp_loadparm_attr =
898 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_fcp_loadparm_show,
899 reipl_fcp_loadparm_store);
900
1a2ae03b
GS
901static ssize_t reipl_fcp_clear_show(struct kobject *kobj,
902 struct kobj_attribute *attr, char *page)
903{
904 return sprintf(page, "%u\n", reipl_fcp_clear);
905}
906
907static ssize_t reipl_fcp_clear_store(struct kobject *kobj,
908 struct kobj_attribute *attr,
909 const char *buf, size_t len)
910{
d9b25bdf 911 if (kstrtobool(buf, &reipl_fcp_clear) < 0)
1a2ae03b
GS
912 return -EINVAL;
913 return len;
914}
915
69928601
MH
916static struct attribute *reipl_fcp_attrs[] = {
917 &sys_reipl_fcp_device_attr.attr,
918 &sys_reipl_fcp_wwpn_attr.attr,
919 &sys_reipl_fcp_lun_attr.attr,
920 &sys_reipl_fcp_bootprog_attr.attr,
921 &sys_reipl_fcp_br_lba_attr.attr,
922 &sys_reipl_fcp_loadparm_attr.attr,
923 NULL,
924};
925
926static struct attribute_group reipl_fcp_attr_group = {
927 .attrs = reipl_fcp_attrs,
22d557ab 928 .bin_attrs = reipl_fcp_bin_attrs,
69928601
MH
929};
930
1a2ae03b
GS
931static struct kobj_attribute sys_reipl_fcp_clear_attr =
932 __ATTR(clear, 0644, reipl_fcp_clear_show, reipl_fcp_clear_store);
933
23a457b8
JH
934/* NVME reipl device attributes */
935
936static ssize_t reipl_nvme_scpdata_read(struct file *filp, struct kobject *kobj,
937 struct bin_attribute *attr,
938 char *buf, loff_t off, size_t count)
939{
940 size_t size = reipl_block_nvme->nvme.scp_data_len;
941 void *scp_data = reipl_block_nvme->nvme.scp_data;
942
943 return memory_read_from_buffer(buf, count, &off, scp_data, size);
944}
945
946static ssize_t reipl_nvme_scpdata_write(struct file *filp, struct kobject *kobj,
947 struct bin_attribute *attr,
948 char *buf, loff_t off, size_t count)
949{
950 size_t scpdata_len = count;
951 size_t padding;
952
953 if (off)
954 return -EINVAL;
955
956 memcpy(reipl_block_nvme->nvme.scp_data, buf, count);
957 if (scpdata_len % 8) {
958 padding = 8 - (scpdata_len % 8);
959 memset(reipl_block_nvme->nvme.scp_data + scpdata_len,
960 0, padding);
961 scpdata_len += padding;
962 }
963
964 reipl_block_nvme->hdr.len = IPL_BP_FCP_LEN + scpdata_len;
965 reipl_block_nvme->nvme.len = IPL_BP0_FCP_LEN + scpdata_len;
966 reipl_block_nvme->nvme.scp_data_len = scpdata_len;
967
968 return count;
969}
970
971static struct bin_attribute sys_reipl_nvme_scp_data_attr =
972 __BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_nvme_scpdata_read,
973 reipl_nvme_scpdata_write, DIAG308_SCPDATA_SIZE);
974
975static struct bin_attribute *reipl_nvme_bin_attrs[] = {
976 &sys_reipl_nvme_scp_data_attr,
977 NULL,
978};
979
980DEFINE_IPL_ATTR_RW(reipl_nvme, fid, "0x%08llx\n", "%llx\n",
981 reipl_block_nvme->nvme.fid);
982DEFINE_IPL_ATTR_RW(reipl_nvme, nsid, "0x%08llx\n", "%llx\n",
983 reipl_block_nvme->nvme.nsid);
984DEFINE_IPL_ATTR_RW(reipl_nvme, bootprog, "%lld\n", "%lld\n",
985 reipl_block_nvme->nvme.bootprog);
986DEFINE_IPL_ATTR_RW(reipl_nvme, br_lba, "%lld\n", "%lld\n",
987 reipl_block_nvme->nvme.br_lba);
988
989/* nvme wrapper */
990static ssize_t reipl_nvme_loadparm_show(struct kobject *kobj,
991 struct kobj_attribute *attr, char *page)
992{
993 return reipl_generic_loadparm_show(reipl_block_nvme, page);
994}
995
996static ssize_t reipl_nvme_loadparm_store(struct kobject *kobj,
997 struct kobj_attribute *attr,
998 const char *buf, size_t len)
999{
1000 return reipl_generic_loadparm_store(reipl_block_nvme, buf, len);
1001}
1002
1003static struct kobj_attribute sys_reipl_nvme_loadparm_attr =
1004 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nvme_loadparm_show,
1005 reipl_nvme_loadparm_store);
1006
1007static struct attribute *reipl_nvme_attrs[] = {
1008 &sys_reipl_nvme_fid_attr.attr,
1009 &sys_reipl_nvme_nsid_attr.attr,
1010 &sys_reipl_nvme_bootprog_attr.attr,
1011 &sys_reipl_nvme_br_lba_attr.attr,
1012 &sys_reipl_nvme_loadparm_attr.attr,
1013 NULL,
1014};
1015
1016static struct attribute_group reipl_nvme_attr_group = {
1017 .attrs = reipl_nvme_attrs,
1018 .bin_attrs = reipl_nvme_bin_attrs
1019};
1020
5627b922
GS
1021static ssize_t reipl_nvme_clear_show(struct kobject *kobj,
1022 struct kobj_attribute *attr, char *page)
1023{
1024 return sprintf(page, "%u\n", reipl_nvme_clear);
1025}
1026
1027static ssize_t reipl_nvme_clear_store(struct kobject *kobj,
1028 struct kobj_attribute *attr,
1029 const char *buf, size_t len)
1030{
d9b25bdf 1031 if (kstrtobool(buf, &reipl_nvme_clear) < 0)
5627b922
GS
1032 return -EINVAL;
1033 return len;
1034}
1035
1036static struct kobj_attribute sys_reipl_nvme_clear_attr =
1037 __ATTR(clear, 0644, reipl_nvme_clear_show, reipl_nvme_clear_store);
1038
69928601 1039/* CCW reipl device attributes */
86c74d86 1040DEFINE_IPL_CCW_ATTR_RW(reipl_ccw, device, reipl_block_ccw->ccw);
69928601 1041
a0443fbb
HB
1042/* NSS wrapper */
1043static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
1044 struct kobj_attribute *attr, char *page)
1045{
1046 return reipl_generic_loadparm_show(reipl_block_nss, page);
1047}
1048
1049static ssize_t reipl_nss_loadparm_store(struct kobject *kobj,
1050 struct kobj_attribute *attr,
1051 const char *buf, size_t len)
1052{
1053 return reipl_generic_loadparm_store(reipl_block_nss, buf, len);
1054}
1055
1056/* CCW wrapper */
1057static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj,
1058 struct kobj_attribute *attr, char *page)
1059{
1060 return reipl_generic_loadparm_show(reipl_block_ccw, page);
1061}
1062
1063static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
1064 struct kobj_attribute *attr,
1065 const char *buf, size_t len)
1066{
1067 return reipl_generic_loadparm_store(reipl_block_ccw, buf, len);
1068}
1069
9b949165 1070static struct kobj_attribute sys_reipl_ccw_loadparm_attr =
a0443fbb
HB
1071 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_ccw_loadparm_show,
1072 reipl_ccw_loadparm_store);
1073
1a2ae03b
GS
1074static ssize_t reipl_ccw_clear_show(struct kobject *kobj,
1075 struct kobj_attribute *attr, char *page)
1076{
1077 return sprintf(page, "%u\n", reipl_ccw_clear);
1078}
1079
1080static ssize_t reipl_ccw_clear_store(struct kobject *kobj,
1081 struct kobj_attribute *attr,
1082 const char *buf, size_t len)
1083{
d9b25bdf 1084 if (kstrtobool(buf, &reipl_ccw_clear) < 0)
1a2ae03b
GS
1085 return -EINVAL;
1086 return len;
1087}
1088
1089static struct kobj_attribute sys_reipl_ccw_clear_attr =
1090 __ATTR(clear, 0644, reipl_ccw_clear_show, reipl_ccw_clear_store);
1091
a0443fbb
HB
1092static struct attribute *reipl_ccw_attrs_vm[] = {
1093 &sys_reipl_ccw_device_attr.attr,
1094 &sys_reipl_ccw_loadparm_attr.attr,
1095 &sys_reipl_ccw_vmparm_attr.attr,
1a2ae03b 1096 &sys_reipl_ccw_clear_attr.attr,
a0443fbb
HB
1097 NULL,
1098};
03a4d208 1099
a0443fbb 1100static struct attribute *reipl_ccw_attrs_lpar[] = {
ff6b8ea6 1101 &sys_reipl_ccw_device_attr.attr,
03a4d208 1102 &sys_reipl_ccw_loadparm_attr.attr,
1a2ae03b 1103 &sys_reipl_ccw_clear_attr.attr,
ff6b8ea6
MH
1104 NULL,
1105};
1106
a0443fbb 1107static struct attribute_group reipl_ccw_attr_group_vm = {
ff6b8ea6 1108 .name = IPL_CCW_STR,
a0443fbb
HB
1109 .attrs = reipl_ccw_attrs_vm,
1110};
1111
1112static struct attribute_group reipl_ccw_attr_group_lpar = {
1113 .name = IPL_CCW_STR,
1114 .attrs = reipl_ccw_attrs_lpar,
ff6b8ea6
MH
1115};
1116
87fd22e0
SS
1117/* ECKD reipl device attributes */
1118
1119static ssize_t reipl_eckd_scpdata_read(struct file *filp, struct kobject *kobj,
1120 struct bin_attribute *attr,
1121 char *buf, loff_t off, size_t count)
1122{
1123 size_t size = reipl_block_eckd->eckd.scp_data_len;
1124 void *scp_data = reipl_block_eckd->eckd.scp_data;
1125
1126 return memory_read_from_buffer(buf, count, &off, scp_data, size);
1127}
1128
1129static ssize_t reipl_eckd_scpdata_write(struct file *filp, struct kobject *kobj,
1130 struct bin_attribute *attr,
1131 char *buf, loff_t off, size_t count)
1132{
1133 size_t scpdata_len = count;
1134 size_t padding;
1135
1136 if (off)
1137 return -EINVAL;
1138
1139 memcpy(reipl_block_eckd->eckd.scp_data, buf, count);
1140 if (scpdata_len % 8) {
1141 padding = 8 - (scpdata_len % 8);
1142 memset(reipl_block_eckd->eckd.scp_data + scpdata_len,
1143 0, padding);
1144 scpdata_len += padding;
1145 }
1146
1147 reipl_block_eckd->hdr.len = IPL_BP_ECKD_LEN + scpdata_len;
1148 reipl_block_eckd->eckd.len = IPL_BP0_ECKD_LEN + scpdata_len;
1149 reipl_block_eckd->eckd.scp_data_len = scpdata_len;
1150
1151 return count;
1152}
1153
1154static struct bin_attribute sys_reipl_eckd_scp_data_attr =
1155 __BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_eckd_scpdata_read,
1156 reipl_eckd_scpdata_write, DIAG308_SCPDATA_SIZE);
1157
1158static struct bin_attribute *reipl_eckd_bin_attrs[] = {
1159 &sys_reipl_eckd_scp_data_attr,
1160 NULL,
1161};
1162
1163DEFINE_IPL_CCW_ATTR_RW(reipl_eckd, device, reipl_block_eckd->eckd);
1164DEFINE_IPL_ATTR_RW(reipl_eckd, bootprog, "%lld\n", "%lld\n",
1165 reipl_block_eckd->eckd.bootprog);
1166
1167static struct attribute *reipl_eckd_attrs[] = {
1168 &sys_reipl_eckd_device_attr.attr,
1169 &sys_reipl_eckd_bootprog_attr.attr,
1170 &sys_reipl_eckd_br_chr_attr.attr,
1171 NULL,
1172};
1173
1174static struct attribute_group reipl_eckd_attr_group = {
1175 .attrs = reipl_eckd_attrs,
1176 .bin_attrs = reipl_eckd_bin_attrs
1177};
1178
1179static ssize_t reipl_eckd_clear_show(struct kobject *kobj,
1180 struct kobj_attribute *attr, char *page)
1181{
1182 return sprintf(page, "%u\n", reipl_eckd_clear);
1183}
1184
1185static ssize_t reipl_eckd_clear_store(struct kobject *kobj,
1186 struct kobj_attribute *attr,
1187 const char *buf, size_t len)
1188{
1189 if (strtobool(buf, &reipl_eckd_clear) < 0)
1190 return -EINVAL;
1191 return len;
1192}
1193
1194static struct kobj_attribute sys_reipl_eckd_clear_attr =
1195 __ATTR(clear, 0644, reipl_eckd_clear_show, reipl_eckd_clear_store);
fe355b7f
HY
1196
1197/* NSS reipl device attributes */
a0443fbb
HB
1198static void reipl_get_ascii_nss_name(char *dst,
1199 struct ipl_parameter_block *ipb)
1200{
86c74d86 1201 memcpy(dst, ipb->ccw.nss_name, NSS_NAME_SIZE);
a0443fbb
HB
1202 EBCASC(dst, NSS_NAME_SIZE);
1203 dst[NSS_NAME_SIZE] = 0;
1204}
1205
1206static ssize_t reipl_nss_name_show(struct kobject *kobj,
1207 struct kobj_attribute *attr, char *page)
1208{
1209 char nss_name[NSS_NAME_SIZE + 1] = {};
1210
1211 reipl_get_ascii_nss_name(nss_name, reipl_block_nss);
1212 return sprintf(page, "%s\n", nss_name);
1213}
1214
1215static ssize_t reipl_nss_name_store(struct kobject *kobj,
1216 struct kobj_attribute *attr,
1217 const char *buf, size_t len)
1218{
1219 int nss_len;
1220
1221 /* ignore trailing newline */
1222 nss_len = len;
1223 if ((len > 0) && (buf[len - 1] == '\n'))
1224 nss_len--;
fe355b7f 1225
a0443fbb
HB
1226 if (nss_len > NSS_NAME_SIZE)
1227 return -EINVAL;
1228
86c74d86 1229 memset(reipl_block_nss->ccw.nss_name, 0x40, NSS_NAME_SIZE);
a0443fbb 1230 if (nss_len > 0) {
5f1207fb 1231 reipl_block_nss->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_NSS;
86c74d86
MS
1232 memcpy(reipl_block_nss->ccw.nss_name, buf, nss_len);
1233 ASCEBC(reipl_block_nss->ccw.nss_name, nss_len);
1234 EBC_TOUPPER(reipl_block_nss->ccw.nss_name, nss_len);
a0443fbb 1235 } else {
5f1207fb 1236 reipl_block_nss->ccw.vm_flags &= ~IPL_PB0_CCW_VM_FLAG_NSS;
a0443fbb
HB
1237 }
1238
1239 return len;
1240}
1241
1242static struct kobj_attribute sys_reipl_nss_name_attr =
1243 __ATTR(name, S_IRUGO | S_IWUSR, reipl_nss_name_show,
1244 reipl_nss_name_store);
1245
1246static struct kobj_attribute sys_reipl_nss_loadparm_attr =
1247 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nss_loadparm_show,
1248 reipl_nss_loadparm_store);
fe355b7f
HY
1249
1250static struct attribute *reipl_nss_attrs[] = {
1251 &sys_reipl_nss_name_attr.attr,
a0443fbb
HB
1252 &sys_reipl_nss_loadparm_attr.attr,
1253 &sys_reipl_nss_vmparm_attr.attr,
fe355b7f
HY
1254 NULL,
1255};
1256
1257static struct attribute_group reipl_nss_attr_group = {
1258 .name = IPL_NSS_STR,
1259 .attrs = reipl_nss_attrs,
1260};
1261
3b967847 1262void set_os_info_reipl_block(void)
4857d4bb 1263{
4857d4bb 1264 os_info_entry_add(OS_INFO_REIPL_BLOCK, reipl_block_actual,
3b967847 1265 reipl_block_actual->hdr.len);
4857d4bb
MH
1266}
1267
ff6b8ea6
MH
1268/* reipl type */
1269
1270static int reipl_set_type(enum ipl_type type)
1271{
1272 if (!(reipl_capabilities & type))
1273 return -EINVAL;
1274
1275 switch(type) {
1276 case IPL_TYPE_CCW:
3b967847 1277 reipl_block_actual = reipl_block_ccw;
ff6b8ea6 1278 break;
87fd22e0
SS
1279 case IPL_TYPE_ECKD:
1280 reipl_block_actual = reipl_block_eckd;
1281 break;
ff6b8ea6 1282 case IPL_TYPE_FCP:
3b967847 1283 reipl_block_actual = reipl_block_fcp;
411ed322 1284 break;
23a457b8
JH
1285 case IPL_TYPE_NVME:
1286 reipl_block_actual = reipl_block_nvme;
1287 break;
fe355b7f 1288 case IPL_TYPE_NSS:
3b967847 1289 reipl_block_actual = reipl_block_nss;
411ed322 1290 break;
ff6b8ea6 1291 default:
96c0cdbc 1292 break;
ff6b8ea6
MH
1293 }
1294 reipl_type = type;
1295 return 0;
1296}
1297
9b949165
GKH
1298static ssize_t reipl_type_show(struct kobject *kobj,
1299 struct kobj_attribute *attr, char *page)
ff6b8ea6
MH
1300{
1301 return sprintf(page, "%s\n", ipl_type_str(reipl_type));
1302}
1303
9b949165
GKH
1304static ssize_t reipl_type_store(struct kobject *kobj,
1305 struct kobj_attribute *attr,
1306 const char *buf, size_t len)
ff6b8ea6
MH
1307{
1308 int rc = -EINVAL;
1309
1310 if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
1311 rc = reipl_set_type(IPL_TYPE_CCW);
87fd22e0
SS
1312 else if (strncmp(buf, IPL_ECKD_STR, strlen(IPL_ECKD_STR)) == 0)
1313 rc = reipl_set_type(IPL_TYPE_ECKD);
ff6b8ea6
MH
1314 else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
1315 rc = reipl_set_type(IPL_TYPE_FCP);
23a457b8
JH
1316 else if (strncmp(buf, IPL_NVME_STR, strlen(IPL_NVME_STR)) == 0)
1317 rc = reipl_set_type(IPL_TYPE_NVME);
fe355b7f
HY
1318 else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
1319 rc = reipl_set_type(IPL_TYPE_NSS);
ff6b8ea6
MH
1320 return (rc != 0) ? rc : len;
1321}
1322
9b949165 1323static struct kobj_attribute reipl_type_attr =
99ca4e58 1324 __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
ff6b8ea6 1325
d91885be 1326static struct kset *reipl_kset;
684d2fd4 1327static struct kset *reipl_fcp_kset;
23a457b8 1328static struct kset *reipl_nvme_kset;
87fd22e0 1329static struct kset *reipl_eckd_kset;
ff6b8ea6 1330
2c2df118 1331static void __reipl_run(void *unused)
ff6b8ea6 1332{
96c0cdbc
VG
1333 switch (reipl_type) {
1334 case IPL_TYPE_CCW:
ff6b8ea6 1335 diag308(DIAG308_SET, reipl_block_ccw);
1a2ae03b
GS
1336 if (reipl_ccw_clear)
1337 diag308(DIAG308_LOAD_CLEAR, NULL);
1338 else
1339 diag308(DIAG308_LOAD_NORMAL_DUMP, NULL);
ff6b8ea6 1340 break;
87fd22e0
SS
1341 case IPL_TYPE_ECKD:
1342 diag308(DIAG308_SET, reipl_block_eckd);
1343 if (reipl_eckd_clear)
1344 diag308(DIAG308_LOAD_CLEAR, NULL);
1345 else
1346 diag308(DIAG308_LOAD_NORMAL, NULL);
1347 break;
96c0cdbc 1348 case IPL_TYPE_FCP:
ff6b8ea6 1349 diag308(DIAG308_SET, reipl_block_fcp);
1a2ae03b
GS
1350 if (reipl_fcp_clear)
1351 diag308(DIAG308_LOAD_CLEAR, NULL);
1352 else
1353 diag308(DIAG308_LOAD_NORMAL, NULL);
ff6b8ea6 1354 break;
23a457b8
JH
1355 case IPL_TYPE_NVME:
1356 diag308(DIAG308_SET, reipl_block_nvme);
5627b922
GS
1357 if (reipl_nvme_clear)
1358 diag308(DIAG308_LOAD_CLEAR, NULL);
1359 else
1360 diag308(DIAG308_LOAD_NORMAL, NULL);
23a457b8 1361 break;
96c0cdbc 1362 case IPL_TYPE_NSS:
a0443fbb 1363 diag308(DIAG308_SET, reipl_block_nss);
0599eead 1364 diag308(DIAG308_LOAD_CLEAR, NULL);
a0443fbb 1365 break;
96c0cdbc 1366 case IPL_TYPE_UNKNOWN:
0599eead 1367 diag308(DIAG308_LOAD_CLEAR, NULL);
ff6b8ea6 1368 break;
96c0cdbc 1369 case IPL_TYPE_FCP_DUMP:
d70e38cb 1370 case IPL_TYPE_NVME_DUMP:
411ed322 1371 break;
ff6b8ea6 1372 }
98587c2d 1373 disabled_wait();
ff6b8ea6
MH
1374}
1375
2c2df118
HC
1376static void reipl_run(struct shutdown_trigger *trigger)
1377{
8b646bd7 1378 smp_call_ipl_cpu(__reipl_run, NULL);
2c2df118
HC
1379}
1380
a0443fbb 1381static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
ff6b8ea6 1382{
5f1207fb 1383 ipb->hdr.len = IPL_BP_CCW_LEN;
a0443fbb 1384 ipb->hdr.version = IPL_PARM_BLOCK_VERSION;
5f1207fb
MS
1385 ipb->pb0_hdr.len = IPL_BP0_CCW_LEN;
1386 ipb->pb0_hdr.pbt = IPL_PBT_CCW;
a0443fbb 1387}
ff6b8ea6 1388
a0443fbb
HB
1389static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
1390{
1391 /* LOADPARM */
1392 /* check if read scp info worked and set loadparm */
1393 if (sclp_ipl_info.is_valid)
5f1207fb 1394 memcpy(ipb->ccw.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
a0443fbb
HB
1395 else
1396 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
5f1207fb
MS
1397 memset(ipb->ccw.loadparm, 0x40, LOADPARM_LEN);
1398 ipb->ccw.flags = IPL_PB0_FLAG_LOADPARM;
a0443fbb
HB
1399
1400 /* VM PARM */
a0832b3a 1401 if (MACHINE_IS_VM && ipl_block_valid &&
5f1207fb 1402 (ipl_block.ccw.vm_flags & IPL_PB0_CCW_VM_FLAG_VP)) {
a0443fbb 1403
5f1207fb 1404 ipb->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_VP;
86c74d86
MS
1405 ipb->ccw.vm_parm_len = ipl_block.ccw.vm_parm_len;
1406 memcpy(ipb->ccw.vm_parm,
1407 ipl_block.ccw.vm_parm, DIAG308_VMPARM_SIZE);
a0443fbb 1408 }
ff6b8ea6
MH
1409}
1410
99ca4e58 1411static int __init reipl_nss_init(void)
ff6b8ea6
MH
1412{
1413 int rc;
1414
99ca4e58
MH
1415 if (!MACHINE_IS_VM)
1416 return 0;
a0443fbb
HB
1417
1418 reipl_block_nss = (void *) get_zeroed_page(GFP_KERNEL);
1419 if (!reipl_block_nss)
1420 return -ENOMEM;
1421
99ca4e58 1422 rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group);
fe355b7f
HY
1423 if (rc)
1424 return rc;
a0443fbb
HB
1425
1426 reipl_block_ccw_init(reipl_block_nss);
fe355b7f
HY
1427 reipl_capabilities |= IPL_TYPE_NSS;
1428 return 0;
1429}
1430
ff6b8ea6
MH
1431static int __init reipl_ccw_init(void)
1432{
1433 int rc;
1434
1435 reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
1436 if (!reipl_block_ccw)
1437 return -ENOMEM;
a0443fbb 1438
d485235b
VG
1439 rc = sysfs_create_group(&reipl_kset->kobj,
1440 MACHINE_IS_VM ? &reipl_ccw_attr_group_vm
1441 : &reipl_ccw_attr_group_lpar);
a0443fbb
HB
1442 if (rc)
1443 return rc;
1444
1445 reipl_block_ccw_init(reipl_block_ccw);
1446 if (ipl_info.type == IPL_TYPE_CCW) {
86c74d86
MS
1447 reipl_block_ccw->ccw.ssid = ipl_block.ccw.ssid;
1448 reipl_block_ccw->ccw.devno = ipl_block.ccw.devno;
a0443fbb
HB
1449 reipl_block_ccw_fill_parms(reipl_block_ccw);
1450 }
1451
ff6b8ea6
MH
1452 reipl_capabilities |= IPL_TYPE_CCW;
1453 return 0;
1454}
1455
1456static int __init reipl_fcp_init(void)
1457{
1458 int rc;
1459
ff6b8ea6
MH
1460 reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
1461 if (!reipl_block_fcp)
1462 return -ENOMEM;
684d2fd4
HB
1463
1464 /* sysfs: create fcp kset for mixing attr group and bin attrs */
1465 reipl_fcp_kset = kset_create_and_add(IPL_FCP_STR, NULL,
1466 &reipl_kset->kobj);
798620fb 1467 if (!reipl_fcp_kset) {
684d2fd4
HB
1468 free_page((unsigned long) reipl_block_fcp);
1469 return -ENOMEM;
1470 }
1471
1472 rc = sysfs_create_group(&reipl_fcp_kset->kobj, &reipl_fcp_attr_group);
1a2ae03b
GS
1473 if (rc)
1474 goto out1;
1475
1476 if (test_facility(141)) {
1477 rc = sysfs_create_file(&reipl_fcp_kset->kobj,
1478 &sys_reipl_fcp_clear_attr.attr);
1479 if (rc)
1480 goto out2;
5627b922 1481 } else {
1a2ae03b 1482 reipl_fcp_clear = true;
5627b922 1483 }
684d2fd4 1484
69928601 1485 if (ipl_info.type == IPL_TYPE_FCP) {
bdbfe185 1486 memcpy(reipl_block_fcp, &ipl_block, sizeof(ipl_block));
69928601
MH
1487 /*
1488 * Fix loadparm: There are systems where the (SCSI) LOADPARM
1489 * is invalid in the SCSI IPL parameter block, so take it
1490 * always from sclp_ipl_info.
1491 */
5f1207fb 1492 memcpy(reipl_block_fcp->fcp.loadparm, sclp_ipl_info.loadparm,
69928601
MH
1493 LOADPARM_LEN);
1494 } else {
5f1207fb 1495 reipl_block_fcp->hdr.len = IPL_BP_FCP_LEN;
ff6b8ea6 1496 reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
5f1207fb
MS
1497 reipl_block_fcp->fcp.len = IPL_BP0_FCP_LEN;
1498 reipl_block_fcp->fcp.pbt = IPL_PBT_FCP;
1499 reipl_block_fcp->fcp.opt = IPL_PB0_FCP_OPT_IPL;
ff6b8ea6
MH
1500 }
1501 reipl_capabilities |= IPL_TYPE_FCP;
1502 return 0;
1a2ae03b
GS
1503
1504out2:
1505 sysfs_remove_group(&reipl_fcp_kset->kobj, &reipl_fcp_attr_group);
1506out1:
1507 kset_unregister(reipl_fcp_kset);
1508 free_page((unsigned long) reipl_block_fcp);
1509 return rc;
ff6b8ea6
MH
1510}
1511
23a457b8
JH
1512static int __init reipl_nvme_init(void)
1513{
1514 int rc;
1515
1516 reipl_block_nvme = (void *) get_zeroed_page(GFP_KERNEL);
1517 if (!reipl_block_nvme)
1518 return -ENOMEM;
1519
1520 /* sysfs: create kset for mixing attr group and bin attrs */
1521 reipl_nvme_kset = kset_create_and_add(IPL_NVME_STR, NULL,
1522 &reipl_kset->kobj);
1523 if (!reipl_nvme_kset) {
1524 free_page((unsigned long) reipl_block_nvme);
1525 return -ENOMEM;
1526 }
1527
1528 rc = sysfs_create_group(&reipl_nvme_kset->kobj, &reipl_nvme_attr_group);
5627b922
GS
1529 if (rc)
1530 goto out1;
1531
1532 if (test_facility(141)) {
1533 rc = sysfs_create_file(&reipl_nvme_kset->kobj,
1534 &sys_reipl_nvme_clear_attr.attr);
1535 if (rc)
1536 goto out2;
1537 } else {
1538 reipl_nvme_clear = true;
23a457b8
JH
1539 }
1540
1541 if (ipl_info.type == IPL_TYPE_NVME) {
1542 memcpy(reipl_block_nvme, &ipl_block, sizeof(ipl_block));
1543 /*
1544 * Fix loadparm: There are systems where the (SCSI) LOADPARM
1545 * is invalid in the IPL parameter block, so take it
1546 * always from sclp_ipl_info.
1547 */
1548 memcpy(reipl_block_nvme->nvme.loadparm, sclp_ipl_info.loadparm,
1549 LOADPARM_LEN);
1550 } else {
1551 reipl_block_nvme->hdr.len = IPL_BP_NVME_LEN;
1552 reipl_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION;
1553 reipl_block_nvme->nvme.len = IPL_BP0_NVME_LEN;
1554 reipl_block_nvme->nvme.pbt = IPL_PBT_NVME;
1555 reipl_block_nvme->nvme.opt = IPL_PB0_NVME_OPT_IPL;
1556 }
1557 reipl_capabilities |= IPL_TYPE_NVME;
1558 return 0;
5627b922
GS
1559
1560out2:
1561 sysfs_remove_group(&reipl_nvme_kset->kobj, &reipl_nvme_attr_group);
1562out1:
1563 kset_unregister(reipl_nvme_kset);
1564 free_page((unsigned long) reipl_block_nvme);
1565 return rc;
23a457b8
JH
1566}
1567
87fd22e0
SS
1568static int __init reipl_eckd_init(void)
1569{
1570 int rc;
1571
1572 if (!sclp.has_sipl_eckd)
1573 return 0;
1574
1575 reipl_block_eckd = (void *)get_zeroed_page(GFP_KERNEL);
1576 if (!reipl_block_eckd)
1577 return -ENOMEM;
1578
1579 /* sysfs: create kset for mixing attr group and bin attrs */
1580 reipl_eckd_kset = kset_create_and_add(IPL_ECKD_STR, NULL,
1581 &reipl_kset->kobj);
1582 if (!reipl_eckd_kset) {
1583 free_page((unsigned long)reipl_block_eckd);
1584 return -ENOMEM;
1585 }
1586
1587 rc = sysfs_create_group(&reipl_eckd_kset->kobj, &reipl_eckd_attr_group);
1588 if (rc)
1589 goto out1;
1590
1591 if (test_facility(141)) {
1592 rc = sysfs_create_file(&reipl_eckd_kset->kobj,
1593 &sys_reipl_eckd_clear_attr.attr);
1594 if (rc)
1595 goto out2;
1596 } else {
1597 reipl_eckd_clear = true;
1598 }
1599
1600 if (ipl_info.type == IPL_TYPE_ECKD) {
1601 memcpy(reipl_block_eckd, &ipl_block, sizeof(ipl_block));
1602 } else {
1603 reipl_block_eckd->hdr.len = IPL_BP_ECKD_LEN;
1604 reipl_block_eckd->hdr.version = IPL_PARM_BLOCK_VERSION;
1605 reipl_block_eckd->eckd.len = IPL_BP0_ECKD_LEN;
1606 reipl_block_eckd->eckd.pbt = IPL_PBT_ECKD;
1607 reipl_block_eckd->eckd.opt = IPL_PB0_ECKD_OPT_IPL;
1608 }
1609 reipl_capabilities |= IPL_TYPE_ECKD;
1610 return 0;
1611
1612out2:
1613 sysfs_remove_group(&reipl_eckd_kset->kobj, &reipl_eckd_attr_group);
1614out1:
1615 kset_unregister(reipl_eckd_kset);
1616 free_page((unsigned long)reipl_block_eckd);
1617 return rc;
1618}
1619
4857d4bb
MH
1620static int __init reipl_type_init(void)
1621{
1622 enum ipl_type reipl_type = ipl_info.type;
1623 struct ipl_parameter_block *reipl_block;
1624 unsigned long size;
1625
1626 reipl_block = os_info_old_entry(OS_INFO_REIPL_BLOCK, &size);
1627 if (!reipl_block)
1628 goto out;
1629 /*
1630 * If we have an OS info reipl block, this will be used
1631 */
5f1207fb 1632 if (reipl_block->pb0_hdr.pbt == IPL_PBT_FCP) {
4857d4bb
MH
1633 memcpy(reipl_block_fcp, reipl_block, size);
1634 reipl_type = IPL_TYPE_FCP;
23a457b8
JH
1635 } else if (reipl_block->pb0_hdr.pbt == IPL_PBT_NVME) {
1636 memcpy(reipl_block_nvme, reipl_block, size);
1637 reipl_type = IPL_TYPE_NVME;
5f1207fb 1638 } else if (reipl_block->pb0_hdr.pbt == IPL_PBT_CCW) {
4857d4bb
MH
1639 memcpy(reipl_block_ccw, reipl_block, size);
1640 reipl_type = IPL_TYPE_CCW;
87fd22e0
SS
1641 } else if (reipl_block->pb0_hdr.pbt == IPL_PBT_ECKD) {
1642 memcpy(reipl_block_eckd, reipl_block, size);
1643 reipl_type = IPL_TYPE_ECKD;
4857d4bb
MH
1644 }
1645out:
1646 return reipl_set_type(reipl_type);
1647}
1648
2bc89b5e 1649static int __init reipl_init(void)
ff6b8ea6
MH
1650{
1651 int rc;
1652
f62ed9e3 1653 reipl_kset = kset_create_and_add("reipl", NULL, firmware_kobj);
d91885be
GKH
1654 if (!reipl_kset)
1655 return -ENOMEM;
1656 rc = sysfs_create_file(&reipl_kset->kobj, &reipl_type_attr.attr);
ff6b8ea6 1657 if (rc) {
d91885be 1658 kset_unregister(reipl_kset);
ff6b8ea6
MH
1659 return rc;
1660 }
1661 rc = reipl_ccw_init();
87fd22e0
SS
1662 if (rc)
1663 return rc;
1664 rc = reipl_eckd_init();
ff6b8ea6
MH
1665 if (rc)
1666 return rc;
1667 rc = reipl_fcp_init();
23a457b8
JH
1668 if (rc)
1669 return rc;
1670 rc = reipl_nvme_init();
fe355b7f
HY
1671 if (rc)
1672 return rc;
1673 rc = reipl_nss_init();
ff6b8ea6
MH
1674 if (rc)
1675 return rc;
4857d4bb 1676 return reipl_type_init();
ff6b8ea6
MH
1677}
1678
2bc89b5e
HC
1679static struct shutdown_action __refdata reipl_action = {
1680 .name = SHUTDOWN_ACTION_REIPL_STR,
1681 .fn = reipl_run,
1682 .init = reipl_init,
1683};
99ca4e58
MH
1684
1685/*
1686 * dump shutdown action: Dump Linux on shutdown.
1687 */
1688
1689/* FCP dump device attributes */
1690
eda4ddf7 1691DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%llx\n",
86c74d86 1692 dump_block_fcp->fcp.wwpn);
eda4ddf7 1693DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%llx\n",
86c74d86 1694 dump_block_fcp->fcp.lun);
99ca4e58 1695DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
86c74d86 1696 dump_block_fcp->fcp.bootprog);
99ca4e58 1697DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
86c74d86 1698 dump_block_fcp->fcp.br_lba);
99ca4e58 1699DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
86c74d86 1700 dump_block_fcp->fcp.devno);
99ca4e58
MH
1701
1702static struct attribute *dump_fcp_attrs[] = {
1703 &sys_dump_fcp_device_attr.attr,
1704 &sys_dump_fcp_wwpn_attr.attr,
1705 &sys_dump_fcp_lun_attr.attr,
1706 &sys_dump_fcp_bootprog_attr.attr,
1707 &sys_dump_fcp_br_lba_attr.attr,
1708 NULL,
1709};
1710
1711static struct attribute_group dump_fcp_attr_group = {
1712 .name = IPL_FCP_STR,
1713 .attrs = dump_fcp_attrs,
1714};
1715
d70e38cb
JH
1716/* NVME dump device attributes */
1717DEFINE_IPL_ATTR_RW(dump_nvme, fid, "0x%08llx\n", "%llx\n",
1718 dump_block_nvme->nvme.fid);
1719DEFINE_IPL_ATTR_RW(dump_nvme, nsid, "0x%08llx\n", "%llx\n",
1720 dump_block_nvme->nvme.nsid);
1721DEFINE_IPL_ATTR_RW(dump_nvme, bootprog, "%lld\n", "%llx\n",
1722 dump_block_nvme->nvme.bootprog);
1723DEFINE_IPL_ATTR_RW(dump_nvme, br_lba, "%lld\n", "%llx\n",
1724 dump_block_nvme->nvme.br_lba);
1725
1726static struct attribute *dump_nvme_attrs[] = {
1727 &sys_dump_nvme_fid_attr.attr,
1728 &sys_dump_nvme_nsid_attr.attr,
1729 &sys_dump_nvme_bootprog_attr.attr,
1730 &sys_dump_nvme_br_lba_attr.attr,
1731 NULL,
1732};
1733
1734static struct attribute_group dump_nvme_attr_group = {
1735 .name = IPL_NVME_STR,
1736 .attrs = dump_nvme_attrs,
1737};
1738
99ca4e58 1739/* CCW dump device attributes */
86c74d86 1740DEFINE_IPL_CCW_ATTR_RW(dump_ccw, device, dump_block_ccw->ccw);
99ca4e58
MH
1741
1742static struct attribute *dump_ccw_attrs[] = {
1743 &sys_dump_ccw_device_attr.attr,
1744 NULL,
1745};
1746
1747static struct attribute_group dump_ccw_attr_group = {
1748 .name = IPL_CCW_STR,
1749 .attrs = dump_ccw_attrs,
1750};
1751
1752/* dump type */
1753
1754static int dump_set_type(enum dump_type type)
1755{
1756 if (!(dump_capabilities & type))
1757 return -EINVAL;
99ca4e58
MH
1758 dump_type = type;
1759 return 0;
1760}
1761
1762static ssize_t dump_type_show(struct kobject *kobj,
1763 struct kobj_attribute *attr, char *page)
1764{
1765 return sprintf(page, "%s\n", dump_type_str(dump_type));
1766}
1767
1768static ssize_t dump_type_store(struct kobject *kobj,
1769 struct kobj_attribute *attr,
1770 const char *buf, size_t len)
1771{
1772 int rc = -EINVAL;
1773
1774 if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
1775 rc = dump_set_type(DUMP_TYPE_NONE);
1776 else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
1777 rc = dump_set_type(DUMP_TYPE_CCW);
1778 else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
1779 rc = dump_set_type(DUMP_TYPE_FCP);
d70e38cb
JH
1780 else if (strncmp(buf, DUMP_NVME_STR, strlen(DUMP_NVME_STR)) == 0)
1781 rc = dump_set_type(DUMP_TYPE_NVME);
99ca4e58
MH
1782 return (rc != 0) ? rc : len;
1783}
1784
1785static struct kobj_attribute dump_type_attr =
1786 __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
1787
1788static struct kset *dump_kset;
1789
0894b3ae
MH
1790static void diag308_dump(void *dump_block)
1791{
1792 diag308(DIAG308_SET, dump_block);
1793 while (1) {
0599eead 1794 if (diag308(DIAG308_LOAD_NORMAL_DUMP, NULL) != 0x302)
0894b3ae 1795 break;
e0d62dcb 1796 udelay(USEC_PER_SEC);
0894b3ae
MH
1797 }
1798}
1799
2c2df118 1800static void __dump_run(void *unused)
99ca4e58 1801{
96c0cdbc
VG
1802 switch (dump_type) {
1803 case DUMP_TYPE_CCW:
0894b3ae 1804 diag308_dump(dump_block_ccw);
99ca4e58 1805 break;
96c0cdbc 1806 case DUMP_TYPE_FCP:
0894b3ae 1807 diag308_dump(dump_block_fcp);
99ca4e58 1808 break;
d70e38cb
JH
1809 case DUMP_TYPE_NVME:
1810 diag308_dump(dump_block_nvme);
1811 break;
2c2df118
HC
1812 default:
1813 break;
99ca4e58 1814 }
2c2df118
HC
1815}
1816
1817static void dump_run(struct shutdown_trigger *trigger)
1818{
96c0cdbc 1819 if (dump_type == DUMP_TYPE_NONE)
2c2df118
HC
1820 return;
1821 smp_send_stop();
8b646bd7 1822 smp_call_ipl_cpu(__dump_run, NULL);
99ca4e58
MH
1823}
1824
ff6b8ea6
MH
1825static int __init dump_ccw_init(void)
1826{
1827 int rc;
1828
1829 dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
1830 if (!dump_block_ccw)
1831 return -ENOMEM;
d91885be 1832 rc = sysfs_create_group(&dump_kset->kobj, &dump_ccw_attr_group);
ff6b8ea6
MH
1833 if (rc) {
1834 free_page((unsigned long)dump_block_ccw);
1835 return rc;
1836 }
5f1207fb 1837 dump_block_ccw->hdr.len = IPL_BP_CCW_LEN;
ff6b8ea6 1838 dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
5f1207fb
MS
1839 dump_block_ccw->ccw.len = IPL_BP0_CCW_LEN;
1840 dump_block_ccw->ccw.pbt = IPL_PBT_CCW;
411ed322 1841 dump_capabilities |= DUMP_TYPE_CCW;
ff6b8ea6
MH
1842 return 0;
1843}
1844
ff6b8ea6
MH
1845static int __init dump_fcp_init(void)
1846{
1847 int rc;
1848
05dd2530 1849 if (!sclp_ipl_info.has_dump)
ff6b8ea6 1850 return 0; /* LDIPL DUMP is not installed */
ff6b8ea6
MH
1851 dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
1852 if (!dump_block_fcp)
1853 return -ENOMEM;
d91885be 1854 rc = sysfs_create_group(&dump_kset->kobj, &dump_fcp_attr_group);
ff6b8ea6
MH
1855 if (rc) {
1856 free_page((unsigned long)dump_block_fcp);
1857 return rc;
1858 }
5f1207fb 1859 dump_block_fcp->hdr.len = IPL_BP_FCP_LEN;
ff6b8ea6 1860 dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
5f1207fb
MS
1861 dump_block_fcp->fcp.len = IPL_BP0_FCP_LEN;
1862 dump_block_fcp->fcp.pbt = IPL_PBT_FCP;
1863 dump_block_fcp->fcp.opt = IPL_PB0_FCP_OPT_DUMP;
411ed322 1864 dump_capabilities |= DUMP_TYPE_FCP;
ff6b8ea6
MH
1865 return 0;
1866}
1867
d70e38cb
JH
1868static int __init dump_nvme_init(void)
1869{
1870 int rc;
1871
1872 if (!sclp_ipl_info.has_dump)
1873 return 0; /* LDIPL DUMP is not installed */
1874 dump_block_nvme = (void *) get_zeroed_page(GFP_KERNEL);
1875 if (!dump_block_nvme)
1876 return -ENOMEM;
1877 rc = sysfs_create_group(&dump_kset->kobj, &dump_nvme_attr_group);
1878 if (rc) {
1879 free_page((unsigned long)dump_block_nvme);
1880 return rc;
1881 }
1882 dump_block_nvme->hdr.len = IPL_BP_NVME_LEN;
1883 dump_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION;
1884 dump_block_nvme->fcp.len = IPL_BP0_NVME_LEN;
1885 dump_block_nvme->fcp.pbt = IPL_PBT_NVME;
1886 dump_block_nvme->fcp.opt = IPL_PB0_NVME_OPT_DUMP;
1887 dump_capabilities |= DUMP_TYPE_NVME;
1888 return 0;
1889}
1890
2bc89b5e 1891static int __init dump_init(void)
ff6b8ea6
MH
1892{
1893 int rc;
1894
f62ed9e3 1895 dump_kset = kset_create_and_add("dump", NULL, firmware_kobj);
d91885be
GKH
1896 if (!dump_kset)
1897 return -ENOMEM;
99ca4e58 1898 rc = sysfs_create_file(&dump_kset->kobj, &dump_type_attr.attr);
ff6b8ea6 1899 if (rc) {
d91885be 1900 kset_unregister(dump_kset);
ff6b8ea6
MH
1901 return rc;
1902 }
1903 rc = dump_ccw_init();
1904 if (rc)
1905 return rc;
1906 rc = dump_fcp_init();
d70e38cb
JH
1907 if (rc)
1908 return rc;
1909 rc = dump_nvme_init();
ff6b8ea6
MH
1910 if (rc)
1911 return rc;
411ed322 1912 dump_set_type(DUMP_TYPE_NONE);
ff6b8ea6
MH
1913 return 0;
1914}
1915
2bc89b5e
HC
1916static struct shutdown_action __refdata dump_action = {
1917 .name = SHUTDOWN_ACTION_DUMP_STR,
1918 .fn = dump_run,
1919 .init = dump_init,
1920};
99ca4e58 1921
099b7651
FM
1922static void dump_reipl_run(struct shutdown_trigger *trigger)
1923{
a7df7a94 1924 unsigned long ipib = (unsigned long) reipl_block_actual;
4df29d2b
AG
1925 struct lowcore *abs_lc;
1926 unsigned long flags;
fbe76568
HC
1927 unsigned int csum;
1928
90b3baa2
HC
1929 csum = (__force unsigned int)
1930 csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0);
4df29d2b
AG
1931 abs_lc = get_abs_lowcore(&flags);
1932 abs_lc->ipib = ipib;
1933 abs_lc->ipib_checksum = csum;
1934 put_abs_lowcore(abs_lc, flags);
099b7651
FM
1935 dump_run(trigger);
1936}
1937
099b7651
FM
1938static struct shutdown_action __refdata dump_reipl_action = {
1939 .name = SHUTDOWN_ACTION_DUMP_REIPL_STR,
1940 .fn = dump_reipl_run,
099b7651
FM
1941};
1942
99ca4e58
MH
1943/*
1944 * vmcmd shutdown action: Trigger vm command on shutdown.
1945 */
1946
1947static char vmcmd_on_reboot[128];
1948static char vmcmd_on_panic[128];
1949static char vmcmd_on_halt[128];
1950static char vmcmd_on_poff[128];
7dd6b334 1951static char vmcmd_on_restart[128];
99ca4e58
MH
1952
1953DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot);
1954DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic);
1955DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt);
1956DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff);
7dd6b334 1957DEFINE_IPL_ATTR_STR_RW(vmcmd, on_restart, "%s\n", "%s\n", vmcmd_on_restart);
99ca4e58
MH
1958
1959static struct attribute *vmcmd_attrs[] = {
1960 &sys_vmcmd_on_reboot_attr.attr,
1961 &sys_vmcmd_on_panic_attr.attr,
1962 &sys_vmcmd_on_halt_attr.attr,
1963 &sys_vmcmd_on_poff_attr.attr,
7dd6b334 1964 &sys_vmcmd_on_restart_attr.attr,
99ca4e58
MH
1965 NULL,
1966};
1967
1968static struct attribute_group vmcmd_attr_group = {
1969 .attrs = vmcmd_attrs,
1970};
1971
1972static struct kset *vmcmd_kset;
1973
1974static void vmcmd_run(struct shutdown_trigger *trigger)
ff6b8ea6 1975{
8143adaf 1976 char *cmd;
99ca4e58
MH
1977
1978 if (strcmp(trigger->name, ON_REIPL_STR) == 0)
1979 cmd = vmcmd_on_reboot;
1980 else if (strcmp(trigger->name, ON_PANIC_STR) == 0)
1981 cmd = vmcmd_on_panic;
1982 else if (strcmp(trigger->name, ON_HALT_STR) == 0)
1983 cmd = vmcmd_on_halt;
1984 else if (strcmp(trigger->name, ON_POFF_STR) == 0)
1985 cmd = vmcmd_on_poff;
7dd6b334
MH
1986 else if (strcmp(trigger->name, ON_RESTART_STR) == 0)
1987 cmd = vmcmd_on_restart;
99ca4e58
MH
1988 else
1989 return;
1990
1991 if (strlen(cmd) == 0)
1992 return;
8143adaf 1993 __cpcmd(cmd, NULL, 0, NULL);
99ca4e58
MH
1994}
1995
1996static int vmcmd_init(void)
1997{
1998 if (!MACHINE_IS_VM)
b8e660b8 1999 return -EOPNOTSUPP;
99ca4e58
MH
2000 vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj);
2001 if (!vmcmd_kset)
2002 return -ENOMEM;
2003 return sysfs_create_group(&vmcmd_kset->kobj, &vmcmd_attr_group);
2004}
2005
2006static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR,
2007 vmcmd_run, vmcmd_init};
2008
2009/*
2010 * stop shutdown action: Stop Linux on shutdown.
2011 */
2012
2013static void stop_run(struct shutdown_trigger *trigger)
2014{
e1202eda
MH
2015 if (strcmp(trigger->name, ON_PANIC_STR) == 0 ||
2016 strcmp(trigger->name, ON_RESTART_STR) == 0)
98587c2d 2017 disabled_wait();
8b646bd7 2018 smp_stop_cpu();
99ca4e58
MH
2019}
2020
2021static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
2022 stop_run, NULL};
2023
2024/* action list */
2025
2026static struct shutdown_action *shutdown_actions_list[] = {
099b7651
FM
2027 &ipl_action, &reipl_action, &dump_reipl_action, &dump_action,
2028 &vmcmd_action, &stop_action};
99ca4e58
MH
2029#define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *))
2030
2031/*
2032 * Trigger section
2033 */
2034
2035static struct kset *shutdown_actions_kset;
2036
2037static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
2038 size_t len)
2039{
2040 int i;
099b7651 2041
99ca4e58 2042 for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
099b7651 2043 if (sysfs_streq(buf, shutdown_actions_list[i]->name)) {
81088819
FM
2044 if (shutdown_actions_list[i]->init_rc) {
2045 return shutdown_actions_list[i]->init_rc;
2046 } else {
2047 trigger->action = shutdown_actions_list[i];
2048 return len;
2049 }
99ca4e58
MH
2050 }
2051 }
2052 return -EINVAL;
2053}
2054
2055/* on reipl */
2056
2057static struct shutdown_trigger on_reboot_trigger = {ON_REIPL_STR,
2058 &reipl_action};
2059
2060static ssize_t on_reboot_show(struct kobject *kobj,
2061 struct kobj_attribute *attr, char *page)
2062{
2063 return sprintf(page, "%s\n", on_reboot_trigger.action->name);
2064}
2065
2066static ssize_t on_reboot_store(struct kobject *kobj,
2067 struct kobj_attribute *attr,
2068 const char *buf, size_t len)
2069{
2070 return set_trigger(buf, &on_reboot_trigger, len);
2071}
0f024379 2072static struct kobj_attribute on_reboot_attr = __ATTR_RW(on_reboot);
99ca4e58
MH
2073
2074static void do_machine_restart(char *__unused)
2075{
2076 smp_send_stop();
2077 on_reboot_trigger.action->fn(&on_reboot_trigger);
2078 reipl_run(NULL);
2079}
2080void (*_machine_restart)(char *command) = do_machine_restart;
2081
2082/* on panic */
2083
2084static struct shutdown_trigger on_panic_trigger = {ON_PANIC_STR, &stop_action};
2085
2086static ssize_t on_panic_show(struct kobject *kobj,
2087 struct kobj_attribute *attr, char *page)
2088{
2089 return sprintf(page, "%s\n", on_panic_trigger.action->name);
2090}
2091
2092static ssize_t on_panic_store(struct kobject *kobj,
2093 struct kobj_attribute *attr,
2094 const char *buf, size_t len)
2095{
2096 return set_trigger(buf, &on_panic_trigger, len);
2097}
0f024379 2098static struct kobj_attribute on_panic_attr = __ATTR_RW(on_panic);
99ca4e58
MH
2099
2100static void do_panic(void)
2101{
3ab121ab 2102 lgr_info_log();
99ca4e58
MH
2103 on_panic_trigger.action->fn(&on_panic_trigger);
2104 stop_run(&on_panic_trigger);
2105}
2106
7dd6b334
MH
2107/* on restart */
2108
2109static struct shutdown_trigger on_restart_trigger = {ON_RESTART_STR,
e1202eda 2110 &stop_action};
7dd6b334
MH
2111
2112static ssize_t on_restart_show(struct kobject *kobj,
2113 struct kobj_attribute *attr, char *page)
2114{
2115 return sprintf(page, "%s\n", on_restart_trigger.action->name);
2116}
2117
2118static ssize_t on_restart_store(struct kobject *kobj,
2119 struct kobj_attribute *attr,
2120 const char *buf, size_t len)
2121{
2122 return set_trigger(buf, &on_restart_trigger, len);
2123}
0f024379 2124static struct kobj_attribute on_restart_attr = __ATTR_RW(on_restart);
7dd6b334 2125
8b646bd7 2126static void __do_restart(void *ignore)
7dd6b334
MH
2127{
2128 smp_send_stop();
60a0c68d
MH
2129#ifdef CONFIG_CRASH_DUMP
2130 crash_kexec(NULL);
2131#endif
7dd6b334
MH
2132 on_restart_trigger.action->fn(&on_restart_trigger);
2133 stop_run(&on_restart_trigger);
2134}
2135
b44913fc 2136void do_restart(void *arg)
8b646bd7 2137{
3ab121ab
MH
2138 tracing_off();
2139 debug_locks_off();
2140 lgr_info_log();
b44913fc 2141 smp_call_online_cpu(__do_restart, arg);
8b646bd7
MS
2142}
2143
99ca4e58
MH
2144/* on halt */
2145
2146static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};
2147
2148static ssize_t on_halt_show(struct kobject *kobj,
2149 struct kobj_attribute *attr, char *page)
2150{
2151 return sprintf(page, "%s\n", on_halt_trigger.action->name);
2152}
2153
2154static ssize_t on_halt_store(struct kobject *kobj,
2155 struct kobj_attribute *attr,
2156 const char *buf, size_t len)
2157{
2158 return set_trigger(buf, &on_halt_trigger, len);
2159}
0f024379 2160static struct kobj_attribute on_halt_attr = __ATTR_RW(on_halt);
99ca4e58
MH
2161
2162static void do_machine_halt(void)
2163{
2164 smp_send_stop();
2165 on_halt_trigger.action->fn(&on_halt_trigger);
2166 stop_run(&on_halt_trigger);
2167}
2168void (*_machine_halt)(void) = do_machine_halt;
2169
2170/* on power off */
2171
2172static struct shutdown_trigger on_poff_trigger = {ON_POFF_STR, &stop_action};
2173
2174static ssize_t on_poff_show(struct kobject *kobj,
2175 struct kobj_attribute *attr, char *page)
2176{
2177 return sprintf(page, "%s\n", on_poff_trigger.action->name);
2178}
2179
2180static ssize_t on_poff_store(struct kobject *kobj,
2181 struct kobj_attribute *attr,
2182 const char *buf, size_t len)
2183{
2184 return set_trigger(buf, &on_poff_trigger, len);
2185}
0f024379 2186static struct kobj_attribute on_poff_attr = __ATTR_RW(on_poff);
99ca4e58
MH
2187
2188static void do_machine_power_off(void)
2189{
2190 smp_send_stop();
2191 on_poff_trigger.action->fn(&on_poff_trigger);
2192 stop_run(&on_poff_trigger);
2193}
2194void (*_machine_power_off)(void) = do_machine_power_off;
2195
0f024379
SO
2196static struct attribute *shutdown_action_attrs[] = {
2197 &on_restart_attr.attr,
2198 &on_reboot_attr.attr,
2199 &on_panic_attr.attr,
2200 &on_halt_attr.attr,
2201 &on_poff_attr.attr,
2202 NULL,
2203};
2204
2205static struct attribute_group shutdown_action_attr_group = {
2206 .attrs = shutdown_action_attrs,
2207};
2208
99ca4e58
MH
2209static void __init shutdown_triggers_init(void)
2210{
d91885be 2211 shutdown_actions_kset = kset_create_and_add("shutdown_actions", NULL,
f62ed9e3 2212 firmware_kobj);
d91885be 2213 if (!shutdown_actions_kset)
99ca4e58 2214 goto fail;
0f024379
SO
2215 if (sysfs_create_group(&shutdown_actions_kset->kobj,
2216 &shutdown_action_attr_group))
7dd6b334 2217 goto fail;
99ca4e58
MH
2218 return;
2219fail:
2220 panic("shutdown_triggers_init failed\n");
2221}
2222
2223static void __init shutdown_actions_init(void)
2224{
2225 int i;
2226
2227 for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
2228 if (!shutdown_actions_list[i]->init)
2229 continue;
81088819
FM
2230 shutdown_actions_list[i]->init_rc =
2231 shutdown_actions_list[i]->init();
ff6b8ea6 2232 }
ff6b8ea6
MH
2233}
2234
2235static int __init s390_ipl_init(void)
2236{
69928601
MH
2237 char str[8] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40};
2238
d5ab7a34 2239 sclp_early_get_ipl_info(&sclp_ipl_info);
69928601
MH
2240 /*
2241 * Fix loadparm: There are systems where the (SCSI) LOADPARM
2242 * returned by read SCP info is invalid (contains EBCDIC blanks)
2243 * when the system has been booted via diag308. In that case we use
2244 * the value from diag308, if available.
2245 *
2246 * There are also systems where diag308 store does not work in
2247 * case the system is booted from HMC. Fortunately in this case
2248 * READ SCP info provides the correct value.
2249 */
a0832b3a 2250 if (memcmp(sclp_ipl_info.loadparm, str, sizeof(str)) == 0 && ipl_block_valid)
5f1207fb 2251 memcpy(sclp_ipl_info.loadparm, ipl_block.ccw.loadparm, LOADPARM_LEN);
99ca4e58
MH
2252 shutdown_actions_init();
2253 shutdown_triggers_init();
ff6b8ea6
MH
2254 return 0;
2255}
2256
2257__initcall(s390_ipl_init);
15e9b586 2258
99ca4e58
MH
2259static void __init strncpy_skip_quote(char *dst, char *src, int n)
2260{
2261 int sx, dx;
2262
2263 dx = 0;
2264 for (sx = 0; src[sx] != 0; sx++) {
2265 if (src[sx] == '"')
2266 continue;
2267 dst[dx++] = src[sx];
2268 if (dx >= n)
2269 break;
2270 }
2271}
2272
2273static int __init vmcmd_on_reboot_setup(char *str)
2274{
2275 if (!MACHINE_IS_VM)
2276 return 1;
2277 strncpy_skip_quote(vmcmd_on_reboot, str, 127);
2278 vmcmd_on_reboot[127] = 0;
2279 on_reboot_trigger.action = &vmcmd_action;
2280 return 1;
2281}
2282__setup("vmreboot=", vmcmd_on_reboot_setup);
2283
2284static int __init vmcmd_on_panic_setup(char *str)
2285{
2286 if (!MACHINE_IS_VM)
2287 return 1;
2288 strncpy_skip_quote(vmcmd_on_panic, str, 127);
2289 vmcmd_on_panic[127] = 0;
2290 on_panic_trigger.action = &vmcmd_action;
2291 return 1;
2292}
2293__setup("vmpanic=", vmcmd_on_panic_setup);
2294
2295static int __init vmcmd_on_halt_setup(char *str)
2296{
2297 if (!MACHINE_IS_VM)
2298 return 1;
2299 strncpy_skip_quote(vmcmd_on_halt, str, 127);
2300 vmcmd_on_halt[127] = 0;
2301 on_halt_trigger.action = &vmcmd_action;
2302 return 1;
2303}
2304__setup("vmhalt=", vmcmd_on_halt_setup);
2305
2306static int __init vmcmd_on_poff_setup(char *str)
2307{
2308 if (!MACHINE_IS_VM)
2309 return 1;
2310 strncpy_skip_quote(vmcmd_on_poff, str, 127);
2311 vmcmd_on_poff[127] = 0;
2312 on_poff_trigger.action = &vmcmd_action;
2313 return 1;
2314}
2315__setup("vmpoff=", vmcmd_on_poff_setup);
2316
2317static int on_panic_notify(struct notifier_block *self,
2318 unsigned long event, void *data)
2319{
2320 do_panic();
2321 return NOTIFY_OK;
2322}
2323
2324static struct notifier_block on_panic_nb = {
2325 .notifier_call = on_panic_notify,
7e9b580e 2326 .priority = INT_MIN,
99ca4e58
MH
2327};
2328
2329void __init setup_ipl(void)
2330{
bdbfe185
VG
2331 BUILD_BUG_ON(sizeof(struct ipl_parameter_block) != PAGE_SIZE);
2332
99ca4e58
MH
2333 ipl_info.type = get_ipl_type();
2334 switch (ipl_info.type) {
2335 case IPL_TYPE_CCW:
86c74d86
MS
2336 ipl_info.data.ccw.dev_id.ssid = ipl_block.ccw.ssid;
2337 ipl_info.data.ccw.dev_id.devno = ipl_block.ccw.devno;
99ca4e58 2338 break;
87fd22e0
SS
2339 case IPL_TYPE_ECKD:
2340 ipl_info.data.eckd.dev_id.ssid = ipl_block.eckd.ssid;
2341 ipl_info.data.eckd.dev_id.devno = ipl_block.eckd.devno;
2342 break;
99ca4e58
MH
2343 case IPL_TYPE_FCP:
2344 case IPL_TYPE_FCP_DUMP:
18e22a17 2345 ipl_info.data.fcp.dev_id.ssid = 0;
86c74d86
MS
2346 ipl_info.data.fcp.dev_id.devno = ipl_block.fcp.devno;
2347 ipl_info.data.fcp.wwpn = ipl_block.fcp.wwpn;
2348 ipl_info.data.fcp.lun = ipl_block.fcp.lun;
99ca4e58 2349 break;
3737e8ee 2350 case IPL_TYPE_NVME:
d70e38cb 2351 case IPL_TYPE_NVME_DUMP:
3737e8ee
JH
2352 ipl_info.data.nvme.fid = ipl_block.nvme.fid;
2353 ipl_info.data.nvme.nsid = ipl_block.nvme.nsid;
2354 break;
99ca4e58 2355 case IPL_TYPE_NSS:
99ca4e58 2356 case IPL_TYPE_UNKNOWN:
99ca4e58
MH
2357 /* We have no info to copy */
2358 break;
2359 }
2360 atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
2361}
2362
1a36a39e 2363void s390_reset_system(void)
15e9b586 2364{
15e9b586
HC
2365 /* Disable prefixing */
2366 set_prefix(0);
2367
2368 /* Disable lowcore protection */
d485235b 2369 __ctl_clear_bit(0, 28);
c78d0c74 2370 diag_amode31_ops.diag308_reset();
15e9b586 2371}
937347ac
MS
2372
2373#ifdef CONFIG_KEXEC_FILE
2374
2375int ipl_report_add_component(struct ipl_report *report, struct kexec_buf *kbuf,
2376 unsigned char flags, unsigned short cert)
2377{
2378 struct ipl_report_component *comp;
2379
2380 comp = vzalloc(sizeof(*comp));
2381 if (!comp)
2382 return -ENOMEM;
2383 list_add_tail(&comp->list, &report->components);
2384
2385 comp->entry.addr = kbuf->mem;
2386 comp->entry.len = kbuf->memsz;
2387 comp->entry.flags = flags;
2388 comp->entry.certificate_index = cert;
2389
2390 report->size += sizeof(comp->entry);
2391
2392 return 0;
2393}
2394
2395int ipl_report_add_certificate(struct ipl_report *report, void *key,
2396 unsigned long addr, unsigned long len)
2397{
2398 struct ipl_report_certificate *cert;
2399
2400 cert = vzalloc(sizeof(*cert));
2401 if (!cert)
2402 return -ENOMEM;
2403 list_add_tail(&cert->list, &report->certificates);
2404
2405 cert->entry.addr = addr;
2406 cert->entry.len = len;
2407 cert->key = key;
2408
2409 report->size += sizeof(cert->entry);
2410 report->size += cert->entry.len;
2411
2412 return 0;
2413}
2414
2415struct ipl_report *ipl_report_init(struct ipl_parameter_block *ipib)
2416{
2417 struct ipl_report *report;
2418
2419 report = vzalloc(sizeof(*report));
2420 if (!report)
2421 return ERR_PTR(-ENOMEM);
2422
2423 report->ipib = ipib;
2424 INIT_LIST_HEAD(&report->components);
2425 INIT_LIST_HEAD(&report->certificates);
2426
2427 report->size = ALIGN(ipib->hdr.len, 8);
2428 report->size += sizeof(struct ipl_rl_hdr);
2429 report->size += sizeof(struct ipl_rb_components);
2430 report->size += sizeof(struct ipl_rb_certificates);
2431
2432 return report;
2433}
2434
2435void *ipl_report_finish(struct ipl_report *report)
2436{
2437 struct ipl_report_certificate *cert;
2438 struct ipl_report_component *comp;
2439 struct ipl_rb_certificates *certs;
2440 struct ipl_parameter_block *ipib;
2441 struct ipl_rb_components *comps;
2442 struct ipl_rl_hdr *rl_hdr;
2443 void *buf, *ptr;
2444
2445 buf = vzalloc(report->size);
2446 if (!buf)
20c76e24 2447 goto out;
937347ac
MS
2448 ptr = buf;
2449
2450 memcpy(ptr, report->ipib, report->ipib->hdr.len);
2451 ipib = ptr;
2452 if (ipl_secure_flag)
2453 ipib->hdr.flags |= IPL_PL_FLAG_SIPL;
2454 ipib->hdr.flags |= IPL_PL_FLAG_IPLSR;
2455 ptr += report->ipib->hdr.len;
2456 ptr = PTR_ALIGN(ptr, 8);
2457
2458 rl_hdr = ptr;
2459 ptr += sizeof(*rl_hdr);
2460
2461 comps = ptr;
2462 comps->rbt = IPL_RBT_COMPONENTS;
2463 ptr += sizeof(*comps);
2464 list_for_each_entry(comp, &report->components, list) {
2465 memcpy(ptr, &comp->entry, sizeof(comp->entry));
2466 ptr += sizeof(comp->entry);
2467 }
2468 comps->len = ptr - (void *)comps;
2469
2470 certs = ptr;
2471 certs->rbt = IPL_RBT_CERTIFICATES;
2472 ptr += sizeof(*certs);
2473 list_for_each_entry(cert, &report->certificates, list) {
2474 memcpy(ptr, &cert->entry, sizeof(cert->entry));
2475 ptr += sizeof(cert->entry);
2476 }
2477 certs->len = ptr - (void *)certs;
2478 rl_hdr->len = ptr - (void *)rl_hdr;
2479
2480 list_for_each_entry(cert, &report->certificates, list) {
2481 memcpy(ptr, cert->key, cert->entry.len);
2482 ptr += cert->entry.len;
2483 }
2484
2485 BUG_ON(ptr > buf + report->size);
20c76e24 2486out:
937347ac
MS
2487 return buf;
2488}
2489
2490int ipl_report_free(struct ipl_report *report)
2491{
2492 struct ipl_report_component *comp, *ncomp;
2493 struct ipl_report_certificate *cert, *ncert;
2494
2495 list_for_each_entry_safe(comp, ncomp, &report->components, list)
2496 vfree(comp);
2497
2498 list_for_each_entry_safe(cert, ncert, &report->certificates, list)
2499 vfree(cert);
2500
2501 vfree(report);
2502
2503 return 0;
2504}
2505
2506#endif