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