File s390-tools-sles15sp2-40-zipl-sclp-add-sclp_print_ascii.patch of Package s390-tools.18357

Subject: [PATCH] [FEAT VS1804] zipl/sclp: add `sclp_print_ascii`
From: Marc Hartmayer <mhartmay@linux.ibm.com>

Summary:     genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
             initrd, optionally a file with the kernel command line, and it
             generates a single, loadable image file. The image consists of a
             concatenation of a plain text boot loader, the encrypted
             components for kernel, initrd, and cmdline, and the
             integrity-protected PV header, containing metadata necessary for
             running the guest in PV mode. It's possible to use this image file
             as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: f99560f734e8101a0e8195d73e3350d9211335b8
Problem-ID:  VS1804

Upstream-Description:

             zipl/sclp: add `sclp_print_ascii`

             Add `sclp_print_ascii` function that can be used to print output on
             the SCLP ASCII console. This would increase the size of the
             loaders (e.g. eckd2.bin and fba2.bin) and therefore might break the
             compilation. In order to avoid that add a macro 'ENABLE_SCLP_ASCII'
             which must be defined by the users of the `sclp_print_ascii` function.

             Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
             Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
             Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
             Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>


Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
 zipl/boot/sclp.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 zipl/boot/sclp.h |   20 +++++++++++++++++++-
 2 files changed, 69 insertions(+), 1 deletion(-)

--- a/zipl/boot/sclp.c
+++ b/zipl/boot/sclp.c
@@ -13,6 +13,10 @@
 #include "error.h"
 #include "boot/s390.h"
 #include "sclp.h"
+#include "ebcdic.h"
+#ifdef ENABLE_SCLP_ASCII
+# include "ebcdic_conv.h"
+#endif /* ENABLE_SCLP_ASCII */
 
 /* Perform service call. Return 0 on success, non-zero otherwise. */
 static int sclp_service_call(unsigned int command, void *sccb)
@@ -133,6 +137,10 @@ int sclp_setup(int initialise)
 		sccb->receive_mask = SCLP_EVENT_MASK_DISABLE;
 		sccb->send_mask = SCLP_EVENT_MASK_DISABLE;
 		break;
+	case SCLP_LINE_ASCII_INIT:
+		sccb->receive_mask = SCLP_EVENT_MASK_DISABLE;
+		sccb->send_mask = SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_ASCII;
+		break;
 	case SCLP_HSA_INIT:
 		sccb->receive_mask = SCLP_EVENT_MASK_DISABLE;
 		sccb->send_mask = SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_SDIAS;
@@ -161,6 +169,48 @@ out_free_page:
 	return rc;
 }
 
+#ifdef ENABLE_SCLP_ASCII
+/* Content of @buffer must be EBCDIC encoded. The function used for
+ * the conversion `ebcdic_to_ascii` differentiates whether the code
+ * runs on z/VM or not and then selects the appropriate EBCDIC
+ * coding.
+ */
+int sclp_print_ascii(const char *buffer)
+{
+	struct write_sccb *sccb = NULL;
+	int rc, str_len = strlen(buffer);
+	unsigned long data_len = str_len + 1;
+
+	/* don't overflow the sccb buffer */
+	if (data_len > SCCB_MAX_DATA_LEN)
+		data_len = SCCB_MAX_DATA_LEN;
+
+	sccb = (void *)get_zeroed_page();
+	sccb->header.length = sizeof(struct write_sccb) - sizeof(struct mdb)
+		+ data_len;
+	sccb->header.function_code = SCLP_FC_NORMAL_WRITE;
+	sccb->msg_buf.header.length = sizeof(struct msg_buf) - sizeof(struct mdb)
+		+ data_len;
+	sccb->msg_buf.header.type = SCLP_EVENT_DATA_ASCII;
+	sccb->msg_buf.header.flags = 0;
+	ebcdic_to_ascii(sccb->msg_buf.data,
+			(const unsigned char *)buffer,
+			data_len - 1);
+	sccb->msg_buf.data[data_len - 1] = '\0';
+
+	/* SCLP command for write data */
+	rc = start_sclp(SCLP_CMD_WRITE_DATA, sccb);
+	if (rc || sccb->header.response_code != 0x20) {
+		rc = 1;
+		goto out_free_page;
+	}
+	rc = 0;
+out_free_page:
+	free_page((unsigned long) sccb);
+	return rc;
+}
+#endif /* ENABLE_SCLP_ASCII */
+
 int sclp_print(char *buffer)
 {
 	struct write_sccb *sccb;
--- a/zipl/boot/sclp.h
+++ b/zipl/boot/sclp.h
@@ -28,9 +28,16 @@
 #define SCLP_CMD_READ_INFO2     0x00020001
 #define SCLP_CMD_READ_DATA      0x00770005
 
+/* SCLP function codes */
+#define SCLP_FC_NORMAL_WRITE	0
+
+/* SCLP event data types */
+#define SCLP_EVENT_DATA_ASCII	0x1a
+
 /* SCLP event masks */
 #define SCLP_EVENT_MASK_DISABLE	0x00000000
 #define SCLP_EVENT_MASK_SDIAS	0x00000010
+#define SCLP_EVENT_MASK_ASCII	0x00000040
 #define SCLP_EVENT_MASK_MSG	0x40000000
 #define SCLP_EVENT_MASK_OPCMD	0x80000000
 
@@ -46,6 +53,11 @@
 #define SCLP_DISABLE            0x1
 #define SCLP_HSA_INIT           0x2
 #define SCLP_HSA_INIT_ASYNC     0x3
+#define SCLP_LINE_ASCII_INIT    0x4
+
+#define SCCB_SIZE		PAGE_SIZE
+#define SCCB_MAX_DATA_LEN	(SCCB_SIZE - sizeof(struct sccb_header) \
+				 - sizeof(struct evbuf_header))
 
 typedef uint32_t sccb_mask_t;
 
@@ -114,7 +126,10 @@ struct mdb {
 
 struct msg_buf {
 	struct evbuf_header header;
-	struct mdb mdb;
+	union {
+		struct mdb mdb;
+		uint8_t data[0];
+	};
 } __packed;
 
 struct write_sccb {
@@ -164,6 +179,9 @@ struct read_sccb {
 int start_sclp(unsigned int, void *);
 int sclp_setup(int);
 int sclp_print(char *);
+# ifdef ENABLE_SCLP_ASCII
+int sclp_print_ascii(const char *);
+# endif /* ENABLE_SCLP_ASCII */
 int sclp_param(char *);
 int sclp_read(unsigned long, void *, int *);
 int sclp_read_info(struct read_info_sccb *sccb);
openSUSE Build Service is sponsored by