diff options
Diffstat (limited to 'arch/s390/kernel/ipl.c')
-rw-r--r-- | arch/s390/kernel/ipl.c | 128 |
1 files changed, 85 insertions, 43 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 22aac5885ba2..39badb9ca0b3 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -455,22 +455,6 @@ DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long) | |||
455 | DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long) | 455 | DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long) |
456 | IPL_PARMBLOCK_START->ipl_info.fcp.br_lba); | 456 | IPL_PARMBLOCK_START->ipl_info.fcp.br_lba); |
457 | 457 | ||
458 | static struct attribute *ipl_fcp_attrs[] = { | ||
459 | &sys_ipl_type_attr.attr, | ||
460 | &sys_ipl_device_attr.attr, | ||
461 | &sys_ipl_fcp_wwpn_attr.attr, | ||
462 | &sys_ipl_fcp_lun_attr.attr, | ||
463 | &sys_ipl_fcp_bootprog_attr.attr, | ||
464 | &sys_ipl_fcp_br_lba_attr.attr, | ||
465 | NULL, | ||
466 | }; | ||
467 | |||
468 | static struct attribute_group ipl_fcp_attr_group = { | ||
469 | .attrs = ipl_fcp_attrs, | ||
470 | }; | ||
471 | |||
472 | /* CCW ipl device attributes */ | ||
473 | |||
474 | static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj, | 458 | static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj, |
475 | struct kobj_attribute *attr, char *page) | 459 | struct kobj_attribute *attr, char *page) |
476 | { | 460 | { |
@@ -487,6 +471,23 @@ static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj, | |||
487 | static struct kobj_attribute sys_ipl_ccw_loadparm_attr = | 471 | static struct kobj_attribute sys_ipl_ccw_loadparm_attr = |
488 | __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL); | 472 | __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL); |
489 | 473 | ||
474 | static struct attribute *ipl_fcp_attrs[] = { | ||
475 | &sys_ipl_type_attr.attr, | ||
476 | &sys_ipl_device_attr.attr, | ||
477 | &sys_ipl_fcp_wwpn_attr.attr, | ||
478 | &sys_ipl_fcp_lun_attr.attr, | ||
479 | &sys_ipl_fcp_bootprog_attr.attr, | ||
480 | &sys_ipl_fcp_br_lba_attr.attr, | ||
481 | &sys_ipl_ccw_loadparm_attr.attr, | ||
482 | NULL, | ||
483 | }; | ||
484 | |||
485 | static struct attribute_group ipl_fcp_attr_group = { | ||
486 | .attrs = ipl_fcp_attrs, | ||
487 | }; | ||
488 | |||
489 | /* CCW ipl device attributes */ | ||
490 | |||
490 | static struct attribute *ipl_ccw_attrs_vm[] = { | 491 | static struct attribute *ipl_ccw_attrs_vm[] = { |
491 | &sys_ipl_type_attr.attr, | 492 | &sys_ipl_type_attr.attr, |
492 | &sys_ipl_device_attr.attr, | 493 | &sys_ipl_device_attr.attr, |
@@ -765,28 +766,10 @@ DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n", | |||
765 | DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n", | 766 | DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n", |
766 | reipl_block_fcp->ipl_info.fcp.devno); | 767 | reipl_block_fcp->ipl_info.fcp.devno); |
767 | 768 | ||
768 | static struct attribute *reipl_fcp_attrs[] = { | ||
769 | &sys_reipl_fcp_device_attr.attr, | ||
770 | &sys_reipl_fcp_wwpn_attr.attr, | ||
771 | &sys_reipl_fcp_lun_attr.attr, | ||
772 | &sys_reipl_fcp_bootprog_attr.attr, | ||
773 | &sys_reipl_fcp_br_lba_attr.attr, | ||
774 | NULL, | ||
775 | }; | ||
776 | |||
777 | static struct attribute_group reipl_fcp_attr_group = { | ||
778 | .attrs = reipl_fcp_attrs, | ||
779 | }; | ||
780 | |||
781 | /* CCW reipl device attributes */ | ||
782 | |||
783 | DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n", | ||
784 | reipl_block_ccw->ipl_info.ccw.devno); | ||
785 | |||
786 | static void reipl_get_ascii_loadparm(char *loadparm, | 769 | static void reipl_get_ascii_loadparm(char *loadparm, |
787 | struct ipl_parameter_block *ibp) | 770 | struct ipl_parameter_block *ibp) |
788 | { | 771 | { |
789 | memcpy(loadparm, ibp->ipl_info.ccw.load_parm, LOADPARM_LEN); | 772 | memcpy(loadparm, ibp->hdr.loadparm, LOADPARM_LEN); |
790 | EBCASC(loadparm, LOADPARM_LEN); | 773 | EBCASC(loadparm, LOADPARM_LEN); |
791 | loadparm[LOADPARM_LEN] = 0; | 774 | loadparm[LOADPARM_LEN] = 0; |
792 | strim(loadparm); | 775 | strim(loadparm); |
@@ -821,13 +804,50 @@ static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb, | |||
821 | return -EINVAL; | 804 | return -EINVAL; |
822 | } | 805 | } |
823 | /* initialize loadparm with blanks */ | 806 | /* initialize loadparm with blanks */ |
824 | memset(ipb->ipl_info.ccw.load_parm, ' ', LOADPARM_LEN); | 807 | memset(ipb->hdr.loadparm, ' ', LOADPARM_LEN); |
825 | /* copy and convert to ebcdic */ | 808 | /* copy and convert to ebcdic */ |
826 | memcpy(ipb->ipl_info.ccw.load_parm, buf, lp_len); | 809 | memcpy(ipb->hdr.loadparm, buf, lp_len); |
827 | ASCEBC(ipb->ipl_info.ccw.load_parm, LOADPARM_LEN); | 810 | ASCEBC(ipb->hdr.loadparm, LOADPARM_LEN); |
828 | return len; | 811 | return len; |
829 | } | 812 | } |
830 | 813 | ||
814 | /* FCP wrapper */ | ||
815 | static ssize_t reipl_fcp_loadparm_show(struct kobject *kobj, | ||
816 | struct kobj_attribute *attr, char *page) | ||
817 | { | ||
818 | return reipl_generic_loadparm_show(reipl_block_fcp, page); | ||
819 | } | ||
820 | |||
821 | static ssize_t reipl_fcp_loadparm_store(struct kobject *kobj, | ||
822 | struct kobj_attribute *attr, | ||
823 | const char *buf, size_t len) | ||
824 | { | ||
825 | return reipl_generic_loadparm_store(reipl_block_fcp, buf, len); | ||
826 | } | ||
827 | |||
828 | static struct kobj_attribute sys_reipl_fcp_loadparm_attr = | ||
829 | __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_fcp_loadparm_show, | ||
830 | reipl_fcp_loadparm_store); | ||
831 | |||
832 | static struct attribute *reipl_fcp_attrs[] = { | ||
833 | &sys_reipl_fcp_device_attr.attr, | ||
834 | &sys_reipl_fcp_wwpn_attr.attr, | ||
835 | &sys_reipl_fcp_lun_attr.attr, | ||
836 | &sys_reipl_fcp_bootprog_attr.attr, | ||
837 | &sys_reipl_fcp_br_lba_attr.attr, | ||
838 | &sys_reipl_fcp_loadparm_attr.attr, | ||
839 | NULL, | ||
840 | }; | ||
841 | |||
842 | static struct attribute_group reipl_fcp_attr_group = { | ||
843 | .attrs = reipl_fcp_attrs, | ||
844 | }; | ||
845 | |||
846 | /* CCW reipl device attributes */ | ||
847 | |||
848 | DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n", | ||
849 | reipl_block_ccw->ipl_info.ccw.devno); | ||
850 | |||
831 | /* NSS wrapper */ | 851 | /* NSS wrapper */ |
832 | static ssize_t reipl_nss_loadparm_show(struct kobject *kobj, | 852 | static ssize_t reipl_nss_loadparm_show(struct kobject *kobj, |
833 | struct kobj_attribute *attr, char *page) | 853 | struct kobj_attribute *attr, char *page) |
@@ -1125,11 +1145,10 @@ static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb) | |||
1125 | /* LOADPARM */ | 1145 | /* LOADPARM */ |
1126 | /* check if read scp info worked and set loadparm */ | 1146 | /* check if read scp info worked and set loadparm */ |
1127 | if (sclp_ipl_info.is_valid) | 1147 | if (sclp_ipl_info.is_valid) |
1128 | memcpy(ipb->ipl_info.ccw.load_parm, | 1148 | memcpy(ipb->hdr.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN); |
1129 | &sclp_ipl_info.loadparm, LOADPARM_LEN); | ||
1130 | else | 1149 | else |
1131 | /* read scp info failed: set empty loadparm (EBCDIC blanks) */ | 1150 | /* read scp info failed: set empty loadparm (EBCDIC blanks) */ |
1132 | memset(ipb->ipl_info.ccw.load_parm, 0x40, LOADPARM_LEN); | 1151 | memset(ipb->hdr.loadparm, 0x40, LOADPARM_LEN); |
1133 | ipb->hdr.flags = DIAG308_FLAGS_LP_VALID; | 1152 | ipb->hdr.flags = DIAG308_FLAGS_LP_VALID; |
1134 | 1153 | ||
1135 | /* VM PARM */ | 1154 | /* VM PARM */ |
@@ -1251,9 +1270,16 @@ static int __init reipl_fcp_init(void) | |||
1251 | return rc; | 1270 | return rc; |
1252 | } | 1271 | } |
1253 | 1272 | ||
1254 | if (ipl_info.type == IPL_TYPE_FCP) | 1273 | if (ipl_info.type == IPL_TYPE_FCP) { |
1255 | memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE); | 1274 | memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE); |
1256 | else { | 1275 | /* |
1276 | * Fix loadparm: There are systems where the (SCSI) LOADPARM | ||
1277 | * is invalid in the SCSI IPL parameter block, so take it | ||
1278 | * always from sclp_ipl_info. | ||
1279 | */ | ||
1280 | memcpy(reipl_block_fcp->hdr.loadparm, sclp_ipl_info.loadparm, | ||
1281 | LOADPARM_LEN); | ||
1282 | } else { | ||
1257 | reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN; | 1283 | reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN; |
1258 | reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION; | 1284 | reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION; |
1259 | reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN; | 1285 | reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN; |
@@ -1864,7 +1890,23 @@ static void __init shutdown_actions_init(void) | |||
1864 | 1890 | ||
1865 | static int __init s390_ipl_init(void) | 1891 | static int __init s390_ipl_init(void) |
1866 | { | 1892 | { |
1893 | char str[8] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; | ||
1894 | |||
1867 | sclp_get_ipl_info(&sclp_ipl_info); | 1895 | sclp_get_ipl_info(&sclp_ipl_info); |
1896 | /* | ||
1897 | * Fix loadparm: There are systems where the (SCSI) LOADPARM | ||
1898 | * returned by read SCP info is invalid (contains EBCDIC blanks) | ||
1899 | * when the system has been booted via diag308. In that case we use | ||
1900 | * the value from diag308, if available. | ||
1901 | * | ||
1902 | * There are also systems where diag308 store does not work in | ||
1903 | * case the system is booted from HMC. Fortunately in this case | ||
1904 | * READ SCP info provides the correct value. | ||
1905 | */ | ||
1906 | if (memcmp(sclp_ipl_info.loadparm, str, sizeof(str)) == 0 && | ||
1907 | diag308_set_works) | ||
1908 | memcpy(sclp_ipl_info.loadparm, ipl_block.hdr.loadparm, | ||
1909 | LOADPARM_LEN); | ||
1868 | shutdown_actions_init(); | 1910 | shutdown_actions_init(); |
1869 | shutdown_triggers_init(); | 1911 | shutdown_triggers_init(); |
1870 | return 0; | 1912 | return 0; |