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