root/arch/s390/kernel/ipl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ipl_type_str
  2. dump_type_str
  3. __diag308
  4. diag308
  5. get_ipl_type
  6. ipl_type_show
  7. ipl_secure_show
  8. ipl_has_secure_show
  9. ipl_vm_parm_show
  10. sys_ipl_device_show
  11. ipl_parameter_read
  12. ipl_scp_data_read
  13. ipl_ccw_loadparm_show
  14. __ipl_run
  15. ipl_run
  16. ipl_init
  17. reipl_generic_vmparm_show
  18. reipl_generic_vmparm_store
  19. reipl_nss_vmparm_show
  20. reipl_nss_vmparm_store
  21. reipl_ccw_vmparm_show
  22. reipl_ccw_vmparm_store
  23. reipl_fcp_scpdata_read
  24. reipl_fcp_scpdata_write
  25. reipl_get_ascii_loadparm
  26. reipl_generic_loadparm_show
  27. reipl_generic_loadparm_store
  28. reipl_fcp_loadparm_show
  29. reipl_fcp_loadparm_store
  30. reipl_nss_loadparm_show
  31. reipl_nss_loadparm_store
  32. reipl_ccw_loadparm_show
  33. reipl_ccw_loadparm_store
  34. reipl_get_ascii_nss_name
  35. reipl_nss_name_show
  36. reipl_nss_name_store
  37. set_os_info_reipl_block
  38. reipl_set_type
  39. reipl_type_show
  40. reipl_type_store
  41. __reipl_run
  42. reipl_run
  43. reipl_block_ccw_init
  44. reipl_block_ccw_fill_parms
  45. reipl_nss_init
  46. reipl_ccw_init
  47. reipl_fcp_init
  48. reipl_type_init
  49. reipl_init
  50. dump_set_type
  51. dump_type_show
  52. dump_type_store
  53. diag308_dump
  54. __dump_run
  55. dump_run
  56. dump_ccw_init
  57. dump_fcp_init
  58. dump_init
  59. dump_reipl_run
  60. vmcmd_run
  61. vmcmd_init
  62. stop_run
  63. set_trigger
  64. on_reboot_show
  65. on_reboot_store
  66. do_machine_restart
  67. on_panic_show
  68. on_panic_store
  69. do_panic
  70. on_restart_show
  71. on_restart_store
  72. __do_restart
  73. do_restart
  74. on_halt_show
  75. on_halt_store
  76. do_machine_halt
  77. on_poff_show
  78. on_poff_store
  79. do_machine_power_off
  80. shutdown_triggers_init
  81. shutdown_actions_init
  82. s390_ipl_init
  83. strncpy_skip_quote
  84. vmcmd_on_reboot_setup
  85. vmcmd_on_panic_setup
  86. vmcmd_on_halt_setup
  87. vmcmd_on_poff_setup
  88. on_panic_notify
  89. setup_ipl
  90. s390_reset_system
  91. ipl_report_add_component
  92. ipl_report_add_certificate
  93. ipl_report_init
  94. ipl_report_finish
  95. ipl_report_free

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

/* [<][>][^][v][top][bottom][index][help] */