]> git.baikalelectronics.ru Git - kernel.git/commitdiff
s390/ipl: provide uapi header for list directed IPL
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 20 Feb 2019 13:26:51 +0000 (14:26 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 26 Apr 2019 10:34:05 +0000 (12:34 +0200)
The IPL parameter block is used as an interface between Linux and
the machine to query and change the boot device and boot options.
To be able to create IPL parameter block in user space and pass it
as segment to kexec provide an uapi header with proper structure
definitions for the block.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/boot/ipl_parm.c
arch/s390/include/asm/ipl.h
arch/s390/include/uapi/asm/ipl.h [new file with mode: 0644]
arch/s390/kernel/ipl.c
arch/s390/kernel/ipl_vmparm.c

index 849cf786db91cd9057c2943fcf7804674a4ac47b..96777092fb14dd509276d8f2b291f45a3c0aee0a 100644 (file)
@@ -106,12 +106,12 @@ static void append_ipl_block_parm(void)
        delim = early_command_line + len;    /* '\0' character position */
        parm = early_command_line + len + 1; /* append right after '\0' */
 
-       switch (ipl_block.hdr.pbt) {
-       case DIAG308_IPL_TYPE_CCW:
+       switch (ipl_block.pb0_hdr.pbt) {
+       case IPL_PBT_CCW:
                rc = ipl_block_get_ascii_vmparm(
                        parm, COMMAND_LINE_SIZE - len - 1, &ipl_block);
                break;
-       case DIAG308_IPL_TYPE_FCP:
+       case IPL_PBT_FCP:
                rc = ipl_block_get_ascii_scpdata(
                        parm, COMMAND_LINE_SIZE - len - 1, &ipl_block);
                break;
@@ -238,8 +238,8 @@ void setup_memory_end(void)
 {
 #ifdef CONFIG_CRASH_DUMP
        if (!OLDMEM_BASE && ipl_block_valid &&
-           ipl_block.hdr.pbt == DIAG308_IPL_TYPE_FCP &&
-           ipl_block.fcp.opt == DIAG308_IPL_OPT_DUMP) {
+           ipl_block.pb0_hdr.pbt == IPL_PBT_FCP &&
+           ipl_block.fcp.opt == IPL_PB0_FCP_OPT_DUMP) {
                if (!sclp_early_get_hsa_size(&memory_end) && memory_end)
                        memory_end_set = 1;
        }
index 3530b613234f13e8e3a487eddb07ee92fcaffa3f..878f6fd5f2e74dc7c18b26fafbbee6b0b06fe017 100644 (file)
 #include <asm/types.h>
 #include <asm/cio.h>
 #include <asm/setup.h>
+#include <uapi/asm/ipl.h>
 
-#define NSS_NAME_SIZE  8
-
-#define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \
-                             sizeof(struct ipl_block_fcp))
-
-#define IPL_PARM_BLK0_FCP_LEN (sizeof(struct ipl_block_fcp) + 16)
+struct ipl_parameter_block {
+       struct ipl_pl_hdr hdr;
+       union {
+               struct ipl_pb_hdr pb0_hdr;
+               struct ipl_pb0_common common;
+               struct ipl_pb0_fcp fcp;
+               struct ipl_pb0_ccw ccw;
+               char raw[PAGE_SIZE - sizeof(struct ipl_pl_hdr)];
+       };
+} __packed __aligned(PAGE_SIZE);
 
-#define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \
-                             sizeof(struct ipl_block_ccw))
+#define NSS_NAME_SIZE 8
 
-#define IPL_PARM_BLK0_CCW_LEN (sizeof(struct ipl_block_ccw) + 16)
+#define IPL_BP_FCP_LEN (sizeof(struct ipl_pl_hdr) + \
+                             sizeof(struct ipl_pb0_fcp))
+#define IPL_BP0_FCP_LEN (sizeof(struct ipl_pb0_fcp))
+#define IPL_BP_CCW_LEN (sizeof(struct ipl_pl_hdr) + \
+                             sizeof(struct ipl_pb0_ccw))
+#define IPL_BP0_CCW_LEN (sizeof(struct ipl_pb0_ccw))
 
 #define IPL_MAX_SUPPORTED_VERSION (0)
 
-struct ipl_list_hdr {
-       u32 len;
-       u8  reserved1[3];
-       u8  version;
-       u32 blk0_len;
-       u8  pbt;
-       u8  flags;
-       u16 reserved2;
-       u8  loadparm[8];
-} __attribute__((packed));
-
-struct ipl_block_fcp {
-       u8  reserved1[305-1];
-       u8  opt;
-       u8  reserved2[3];
-       u16 reserved3;
-       u16 devno;
-       u8  reserved4[4];
-       u64 wwpn;
-       u64 lun;
-       u32 bootprog;
-       u8  reserved5[12];
-       u64 br_lba;
-       u32 scp_data_len;
-       u8  reserved6[260];
-       u8  scp_data[];
-} __attribute__((packed));
-
-#define DIAG308_VMPARM_SIZE    64
-#define DIAG308_SCPDATA_SIZE   (PAGE_SIZE - (sizeof(struct ipl_list_hdr) + \
-                                offsetof(struct ipl_block_fcp, scp_data)))
-
-struct ipl_block_ccw {
-       u8  reserved1[84];
-       u16 reserved2 : 13;
-       u8  ssid : 3;
-       u16 devno;
-       u8  vm_flags;
-       u8  reserved3[3];
-       u32 vm_parm_len;
-       u8  nss_name[8];
-       u8  vm_parm[DIAG308_VMPARM_SIZE];
-       u8  reserved4[8];
-} __attribute__((packed));
-
-struct ipl_parameter_block {
-       struct ipl_list_hdr hdr;
-       union {
-               struct ipl_block_fcp fcp;
-               struct ipl_block_ccw ccw;
-               char raw[PAGE_SIZE - sizeof(struct ipl_list_hdr)];
-       };
-} __packed __aligned(PAGE_SIZE);
+#define DIAG308_VMPARM_SIZE (64)
+#define DIAG308_SCPDATA_OFFSET offsetof(struct ipl_parameter_block, \
+                                       fcp.scp_data)
+#define DIAG308_SCPDATA_SIZE (PAGE_SIZE - DIAG308_SCPDATA_OFFSET)
 
 struct save_area;
 struct save_area * __init save_area_alloc(bool is_boot_cpu);
@@ -132,25 +92,6 @@ enum diag308_subcode  {
        DIAG308_STORE = 6,
 };
 
-enum diag308_ipl_type {
-       DIAG308_IPL_TYPE_FCP    = 0,
-       DIAG308_IPL_TYPE_CCW    = 2,
-};
-
-enum diag308_opt {
-       DIAG308_IPL_OPT_IPL     = 0x10,
-       DIAG308_IPL_OPT_DUMP    = 0x20,
-};
-
-enum diag308_flags {
-       DIAG308_FLAGS_LP_VALID  = 0x80,
-};
-
-enum diag308_vm_flags {
-       DIAG308_VM_FLAGS_NSS_VALID      = 0x80,
-       DIAG308_VM_FLAGS_VP_VALID       = 0x40,
-};
-
 enum diag308_rc {
        DIAG308_RC_OK           = 0x0001,
        DIAG308_RC_NOCONFIG     = 0x0102,
diff --git a/arch/s390/include/uapi/asm/ipl.h b/arch/s390/include/uapi/asm/ipl.h
new file mode 100644 (file)
index 0000000..3b513b3
--- /dev/null
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_S390_UAPI_IPL_H
+#define _ASM_S390_UAPI_IPL_H
+
+#include <linux/types.h>
+
+/* IPL Parameter List header */
+struct ipl_pl_hdr {
+       __u32 len;
+       __u8  reserved1[3];
+       __u8  version;
+} __packed;
+
+/* IPL Parameter Block header */
+struct ipl_pb_hdr {
+       __u32 len;
+       __u8  pbt;
+} __packed;
+
+/* IPL Parameter Block types */
+enum ipl_pbt {
+       IPL_PBT_FCP = 0,
+       IPL_PBT_SCP_DATA = 1,
+       IPL_PBT_CCW = 2,
+};
+
+/* IPL Parameter Block 0 with common fields */
+struct ipl_pb0_common {
+       __u32 len;
+       __u8  pbt;
+       __u8  flags;
+       __u8  reserved1[2];
+       __u8  loadparm[8];
+       __u8  reserved2[84];
+} __packed;
+
+#define IPL_PB0_FLAG_LOADPARM  0x80
+
+/* IPL Parameter Block 0 for FCP */
+struct ipl_pb0_fcp {
+       __u32 len;
+       __u8  pbt;
+       __u8  reserved1[3];
+       __u8  loadparm[8];
+       __u8  reserved2[304];
+       __u8  opt;
+       __u8  reserved3[3];
+       __u8  cssid;
+       __u8  reserved4[1];
+       __u16 devno;
+       __u8  reserved5[4];
+       __u64 wwpn;
+       __u64 lun;
+       __u32 bootprog;
+       __u8  reserved6[12];
+       __u64 br_lba;
+       __u32 scp_data_len;
+       __u8  reserved7[260];
+       __u8  scp_data[];
+} __packed;
+
+#define IPL_PB0_FCP_OPT_IPL    0x10
+#define IPL_PB0_FCP_OPT_DUMP   0x20
+
+/* IPL Parameter Block 0 for CCW */
+struct ipl_pb0_ccw {
+       __u32 len;
+       __u8  pbt;
+       __u8  flags;
+       __u8  reserved1[2];
+       __u8  loadparm[8];
+       __u8  reserved2[84];
+       __u16 reserved3 : 13;
+       __u8  ssid : 3;
+       __u16 devno;
+       __u8  vm_flags;
+       __u8  reserved4[3];
+       __u32 vm_parm_len;
+       __u8  nss_name[8];
+       __u8  vm_parm[64];
+       __u8  reserved5[8];
+} __packed;
+
+#define IPL_PB0_CCW_VM_FLAG_NSS                0x80
+#define IPL_PB0_CCW_VM_FLAG_VP         0x40
+
+/* IPL Parameter Block 1 for additional SCP data */
+struct ipl_pb1_scp_data {
+       __u32 len;
+       __u8  pbt;
+       __u8  scp_data[];
+} __packed;
+
+#endif
index d452f403a4293af025e91236a1aae4729f96b596..f9718bc67cd4edc36df86bc4185e659cf6248170 100644 (file)
@@ -244,11 +244,11 @@ static __init enum ipl_type get_ipl_type(void)
        if (!ipl_block_valid)
                return IPL_TYPE_UNKNOWN;
 
-       switch (ipl_block.hdr.pbt) {
-       case DIAG308_IPL_TYPE_CCW:
+       switch (ipl_block.pb0_hdr.pbt) {
+       case IPL_PBT_CCW:
                return IPL_TYPE_CCW;
-       case DIAG308_IPL_TYPE_FCP:
-               if (ipl_block.fcp.opt == DIAG308_IPL_OPT_DUMP)
+       case IPL_PBT_FCP:
+               if (ipl_block.fcp.opt == IPL_PB0_FCP_OPT_DUMP)
                        return IPL_TYPE_FCP_DUMP;
                else
                        return IPL_TYPE_FCP;
@@ -272,7 +272,7 @@ static ssize_t ipl_vm_parm_show(struct kobject *kobj,
 {
        char parm[DIAG308_VMPARM_SIZE + 1] = {};
 
-       if (ipl_block_valid && (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW))
+       if (ipl_block_valid && (ipl_block.pb0_hdr.pbt == IPL_PBT_CCW))
                ipl_block_get_ascii_vmparm(parm, sizeof(parm), &ipl_block);
        return sprintf(page, "%s\n", parm);
 }
@@ -495,11 +495,11 @@ static ssize_t reipl_generic_vmparm_store(struct ipl_parameter_block *ipb,
        memset(ipb->ccw.vm_parm, 0, DIAG308_VMPARM_SIZE);
        ipb->ccw.vm_parm_len = ip_len;
        if (ip_len > 0) {
-               ipb->ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
+               ipb->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_VP;
                memcpy(ipb->ccw.vm_parm, buf, ip_len);
                ASCEBC(ipb->ccw.vm_parm, ip_len);
        } else {
-               ipb->ccw.vm_flags &= ~DIAG308_VM_FLAGS_VP_VALID;
+               ipb->ccw.vm_flags &= ~IPL_PB0_CCW_VM_FLAG_VP;
        }
 
        return len;
@@ -571,9 +571,9 @@ static ssize_t reipl_fcp_scpdata_write(struct file *filp, struct kobject *kobj,
                scpdata_len += padding;
        }
 
+       reipl_block_fcp->hdr.len = IPL_BP_FCP_LEN + scpdata_len;
+       reipl_block_fcp->fcp.len = IPL_BP0_FCP_LEN + scpdata_len;
        reipl_block_fcp->fcp.scp_data_len = scpdata_len;
-       reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN + scpdata_len;
-       reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN + scpdata_len;
 
        return count;
 }
@@ -600,7 +600,7 @@ DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
 static void reipl_get_ascii_loadparm(char *loadparm,
                                     struct ipl_parameter_block *ibp)
 {
-       memcpy(loadparm, ibp->hdr.loadparm, LOADPARM_LEN);
+       memcpy(loadparm, ibp->common.loadparm, LOADPARM_LEN);
        EBCASC(loadparm, LOADPARM_LEN);
        loadparm[LOADPARM_LEN] = 0;
        strim(loadparm);
@@ -635,11 +635,11 @@ static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
                return -EINVAL;
        }
        /* initialize loadparm with blanks */
-       memset(ipb->hdr.loadparm, ' ', LOADPARM_LEN);
+       memset(ipb->common.loadparm, ' ', LOADPARM_LEN);
        /* copy and convert to ebcdic */
-       memcpy(ipb->hdr.loadparm, buf, lp_len);
-       ASCEBC(ipb->hdr.loadparm, LOADPARM_LEN);
-       ipb->hdr.flags |= DIAG308_FLAGS_LP_VALID;
+       memcpy(ipb->common.loadparm, buf, lp_len);
+       ASCEBC(ipb->common.loadparm, LOADPARM_LEN);
+       ipb->common.flags |= IPL_PB0_FLAG_LOADPARM;
        return len;
 }
 
@@ -769,14 +769,12 @@ static ssize_t reipl_nss_name_store(struct kobject *kobj,
 
        memset(reipl_block_nss->ccw.nss_name, 0x40, NSS_NAME_SIZE);
        if (nss_len > 0) {
-               reipl_block_nss->ccw.vm_flags |=
-                       DIAG308_VM_FLAGS_NSS_VALID;
+               reipl_block_nss->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_NSS;
                memcpy(reipl_block_nss->ccw.nss_name, buf, nss_len);
                ASCEBC(reipl_block_nss->ccw.nss_name, nss_len);
                EBC_TOUPPER(reipl_block_nss->ccw.nss_name, nss_len);
        } else {
-               reipl_block_nss->ccw.vm_flags &=
-                       ~DIAG308_VM_FLAGS_NSS_VALID;
+               reipl_block_nss->ccw.vm_flags &= ~IPL_PB0_CCW_VM_FLAG_NSS;
        }
 
        return len;
@@ -896,10 +894,10 @@ static void reipl_run(struct shutdown_trigger *trigger)
 
 static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
 {
-       ipb->hdr.len = IPL_PARM_BLK_CCW_LEN;
+       ipb->hdr.len = IPL_BP_CCW_LEN;
        ipb->hdr.version = IPL_PARM_BLOCK_VERSION;
-       ipb->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
-       ipb->hdr.pbt = DIAG308_IPL_TYPE_CCW;
+       ipb->pb0_hdr.len = IPL_BP0_CCW_LEN;
+       ipb->pb0_hdr.pbt = IPL_PBT_CCW;
 }
 
 static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
@@ -907,17 +905,17 @@ static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
        /* LOADPARM */
        /* check if read scp info worked and set loadparm */
        if (sclp_ipl_info.is_valid)
-               memcpy(ipb->hdr.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
+               memcpy(ipb->ccw.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
        else
                /* read scp info failed: set empty loadparm (EBCDIC blanks) */
-               memset(ipb->hdr.loadparm, 0x40, LOADPARM_LEN);
-       ipb->hdr.flags = DIAG308_FLAGS_LP_VALID;
+               memset(ipb->ccw.loadparm, 0x40, LOADPARM_LEN);
+       ipb->ccw.flags = IPL_PB0_FLAG_LOADPARM;
 
        /* VM PARM */
        if (MACHINE_IS_VM && ipl_block_valid &&
-           (ipl_block.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID)) {
+           (ipl_block.ccw.vm_flags & IPL_PB0_CCW_VM_FLAG_VP)) {
 
-               ipb->ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
+               ipb->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_VP;
                ipb->ccw.vm_parm_len = ipl_block.ccw.vm_parm_len;
                memcpy(ipb->ccw.vm_parm,
                       ipl_block.ccw.vm_parm, DIAG308_VMPARM_SIZE);
@@ -999,14 +997,14 @@ static int __init reipl_fcp_init(void)
                 * is invalid in the SCSI IPL parameter block, so take it
                 * always from sclp_ipl_info.
                 */
-               memcpy(reipl_block_fcp->hdr.loadparm, sclp_ipl_info.loadparm,
+               memcpy(reipl_block_fcp->fcp.loadparm, sclp_ipl_info.loadparm,
                       LOADPARM_LEN);
        } else {
-               reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
+               reipl_block_fcp->hdr.len = IPL_BP_FCP_LEN;
                reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
-               reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
-               reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
-               reipl_block_fcp->fcp.opt = DIAG308_IPL_OPT_IPL;
+               reipl_block_fcp->fcp.len = IPL_BP0_FCP_LEN;
+               reipl_block_fcp->fcp.pbt = IPL_PBT_FCP;
+               reipl_block_fcp->fcp.opt = IPL_PB0_FCP_OPT_IPL;
        }
        reipl_capabilities |= IPL_TYPE_FCP;
        return 0;
@@ -1024,10 +1022,10 @@ static int __init reipl_type_init(void)
        /*
         * If we have an OS info reipl block, this will be used
         */
-       if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_FCP) {
+       if (reipl_block->pb0_hdr.pbt == IPL_PBT_FCP) {
                memcpy(reipl_block_fcp, reipl_block, size);
                reipl_type = IPL_TYPE_FCP;
-       } else if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_CCW) {
+       } else if (reipl_block->pb0_hdr.pbt == IPL_PBT_CCW) {
                memcpy(reipl_block_ccw, reipl_block, size);
                reipl_type = IPL_TYPE_CCW;
        }
@@ -1191,10 +1189,10 @@ static int __init dump_ccw_init(void)
                free_page((unsigned long)dump_block_ccw);
                return rc;
        }
-       dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
+       dump_block_ccw->hdr.len = IPL_BP_CCW_LEN;
        dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
-       dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
-       dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
+       dump_block_ccw->ccw.len = IPL_BP0_CCW_LEN;
+       dump_block_ccw->ccw.pbt = IPL_PBT_CCW;
        dump_capabilities |= DUMP_TYPE_CCW;
        return 0;
 }
@@ -1213,11 +1211,11 @@ static int __init dump_fcp_init(void)
                free_page((unsigned long)dump_block_fcp);
                return rc;
        }
-       dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
+       dump_block_fcp->hdr.len = IPL_BP_FCP_LEN;
        dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
-       dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
-       dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
-       dump_block_fcp->fcp.opt = DIAG308_IPL_OPT_DUMP;
+       dump_block_fcp->fcp.len = IPL_BP0_FCP_LEN;
+       dump_block_fcp->fcp.pbt = IPL_PBT_FCP;
+       dump_block_fcp->fcp.opt = IPL_PB0_FCP_OPT_DUMP;
        dump_capabilities |= DUMP_TYPE_FCP;
        return 0;
 }
@@ -1576,7 +1574,7 @@ static int __init s390_ipl_init(void)
         * READ SCP info provides the correct value.
         */
        if (memcmp(sclp_ipl_info.loadparm, str, sizeof(str)) == 0 && ipl_block_valid)
-               memcpy(sclp_ipl_info.loadparm, ipl_block.hdr.loadparm, LOADPARM_LEN);
+               memcpy(sclp_ipl_info.loadparm, ipl_block.ccw.loadparm, LOADPARM_LEN);
        shutdown_actions_init();
        shutdown_triggers_init();
        return 0;
index 41613c1617ffcf0b6d7cacdeaeba24b022450dcb..af43535a976df3647f487475415efbf1d6638c6d 100644 (file)
@@ -11,7 +11,7 @@ size_t ipl_block_get_ascii_vmparm(char *dest, size_t size,
        char has_lowercase = 0;
 
        len = 0;
-       if ((ipb->ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
+       if ((ipb->ccw.vm_flags & IPL_PB0_CCW_VM_FLAG_VP) &&
            (ipb->ccw.vm_parm_len > 0)) {
 
                len = min_t(size_t, size - 1, ipb->ccw.vm_parm_len);