Description: lsreipl: No information about booted NSS is printed
Symptom:     When an NSS is booted, lsreipl does not print anything and
             returns with exit code 0.
Problem:     A check for NSS ipl type is missing.
Solution:    Add missing check and print NSS name in case an NSS has been
             IPLed. Besides of that fix this patch also contains two more
             bug fixes:
             * Add missing NULL string termination when reading sysfs attributes
             * Fix possible SIGSEGV for "chreipl node /dev/dasdxy"
Problem-ID:  58480
---
 ipl_tools/ccw.c     |   42 ++++++++++++++++----------------------
 ipl_tools/chreipl.h |    9 +++++---
 ipl_tools/fcp.c     |   13 ++++++-----
 ipl_tools/ipl.c     |   57 +++++++++++++++++++++++++++++++---------------------
 ipl_tools/main.c    |   25 +++++++++++++++++-----
 ipl_tools/system.c  |    3 +-
 6 files changed, 87 insertions(+), 62 deletions(-)

Index: s390-tools-sles11/ipl_tools/fcp.c
===================================================================
--- s390-tools-sles11.orig/ipl_tools/fcp.c
+++ s390-tools-sles11/ipl_tools/fcp.c
@@ -33,12 +33,11 @@
 
 /*
  * return the current reipl type from /sys/firmware/reipl/reipl_type
- * 0 = fcp, 1 = ccw, -1, error
+ * 0 = fcp, 1 = ccw, 2 = nss, -1 = unknown
  */
-int get_reipl_type(void)
+int get_reipl_type(char *reipltype)
 {
 	FILE *filp;
-	char reipltype[4];
 	char path[4096];
 	int rc;
 
@@ -49,7 +48,7 @@ int get_reipl_type(void)
 			fprintf(stderr,	"%s: Can not open /sys/firmware/"
 				"reipl/reipl_type: ", name);
 			fprintf(stderr, "%s\n", strerror(errno));
-			return -1;
+			exit(1);
 		}
 		rc = fscanf(filp, "%s", reipltype);
 		fclose(filp);
@@ -57,17 +56,19 @@ int get_reipl_type(void)
 			fprintf(stderr, "%s: Failed to read "
 				"/sys/firmware/reipl/reipl_type:", name);
 			fprintf(stderr, "%s\n", strerror(errno));
-			return -1;
+			exit(1);
 		}
 		if (strncmp(reipltype, "fcp", strlen("fcp")) == 0)
 			return T_FCP;
 		else if (strncmp(reipltype, "ccw", strlen("ccw")) == 0)
 			return T_CCW;
-		/* TODO: add NSS support */
+		else if (strncmp(reipltype, "nss", strlen("nss")) == 0)
+			return T_NSS;
 	} else {
 		fprintf(stderr, "%s: Can not open /sys/firmware/reipl/"
 			"reipl_type:", name);
 		fprintf(stderr, " %s\n", strerror(errno));
+		exit(1);
 	}
 	return -1;
 }
Index: s390-tools-sles11/ipl_tools/ipl.c
===================================================================
--- s390-tools-sles11.orig/ipl_tools/ipl.c
+++ s390-tools-sles11/ipl_tools/ipl.c
@@ -33,12 +33,11 @@
 
 /*
  * return the ipl type based on /sys/firmware/ipl/ipl_type
- * returns 0 in case of fcp and 1 in case of ccw, -1 otherwise
+ * returns 0 in case of fcp and 1 in case of ccw, 2 for nss and -1 otherwise
  */
-int get_ipl_type()
+int get_ipl_type(char *reipltype)
 {
 	FILE *filp;
-	char reipltype[4];
 	char path[4096];
 	int rc;
 
@@ -49,7 +48,7 @@ int get_ipl_type()
 			fprintf(stderr,	"%s: Can not open /sys/firmware/ipl/"
 				"ipl_type: ", name);
 			fprintf(stderr, "%s\n", strerror(errno));
-			return -1;
+			exit(1);
 		}
 		rc = fscanf(filp, "%s", reipltype);
 		fclose(filp);
@@ -57,12 +56,14 @@ int get_ipl_type()
 			fprintf(stderr, "%s: Failed to read "
 				"/sys/firmware/ipl/ipl_type: ", name);
 			fprintf(stderr, "%s\n", strerror(errno));
-			return -1;
+			exit(1);
 		}
 		if (strncmp(reipltype, "fcp", strlen("fcp")) == 0)
 			return T_FCP;
 		else if (strncmp(reipltype, "ccw", strlen("ccw")) == 0)
 			return T_CCW;
+		else if (strncmp(reipltype, "nss", strlen("nss")) == 0)
+			return T_NSS;
 	} else {
 		fprintf(stderr, "%s: Can not open /sys/firmware/ipl/"
 			"ipl_type:", name);
@@ -111,30 +112,38 @@ int get_ipl_loadparam(void)
 void print_ipl_settings(void)
 {
 	int rc, type;
-	char bootprog[1024], lba[1024];
+	char bootprog[1024], lba[1024], nss_name[NSS_NAME_LEN_MAX + 1];
+	char reipltype[IPL_TYPE_LEN_MAX + 1];
 
-	type = get_ipl_type();
-	/*
-	 * TODO: add nss support
-	 */
-	if (type == 1)
+	type = get_ipl_type(reipltype);
+	switch (type) {
+	case T_NSS:
+		printf("IPL type:      nss\n");
+		rc = strrd(nss_name, "/sys/firmware/ipl/name");
+		if (rc != 0)
+			exit(1);
+		printf("Name:          %s\n", nss_name);
+		break;
+	case T_CCW:
 		printf("IPL type:      ccw\n");
-	if (type == 0)
-		printf("IPL type:      fcp\n");
-	rc = strrd(devno, "/sys/firmware/ipl/device");
-	if (rc != 0)
-		exit(1) /* the error msg comes from get_ipl_device */;
-	if (strlen(devno) > 0)
-		printf("Device:        %s\n", devno);
-	if (type == 1) {
+		rc = strrd(devno, "/sys/firmware/ipl/device");
+		if (rc != 0)
+			exit(1);
+		if (strlen(devno) > 0)
+			printf("Device:        %s\n", devno);
 		rc = get_ipl_loadparam();
 		if (rc != -1)
 			printf("Loadparm:      %d\n", rc);
 		else
 			printf("Loadparm:      \n");
-	}
-	if (type == 0) {
-		/* these settings are only available for fcp */
+		break;
+	case T_FCP:
+		printf("IPL type:      fcp\n");
+		rc = strrd(devno, "/sys/firmware/ipl/device");
+		if (rc != 0)
+			exit(1);
+		if (strlen(devno) > 0)
+			printf("Device:        %s\n", devno);
 		rc = strrd(wwpn, "/sys/firmware/reipl/fcp/wwpn");
 		if (rc != -1 && strlen(wwpn) > 0)
 			printf("WWPN:          %s\n", wwpn);
@@ -147,6 +156,10 @@ void print_ipl_settings(void)
 		rc = strrd(lba, "/sys/firmware/ipl/br_lba");
 		if (rc != -1 &&  strlen(lba) > 0)
 			printf("br_lba:        %s\n", lba);
+		break;
+	default:
+		printf("IPL type:      %s (unknown)\n", reipltype);
+		break;
 	}
 	exit(0);
 }
Index: s390-tools-sles11/ipl_tools/main.c
===================================================================
--- s390-tools-sles11.orig/ipl_tools/main.c
+++ s390-tools-sles11/ipl_tools/main.c
@@ -57,13 +57,22 @@ int action;		/* either CCW, FCP or NODE 
 int lsreipl(int argc, char *argv[])
 {
 	int rc;
-	char bootprog[1024], lba[1024], val[9];
+	char bootprog[1024], lba[1024], val[9], reipltype[IPL_TYPE_LEN_MAX + 1];
+	char nss_name[NSS_NAME_LEN_MAX + 1];
 
 	/* parse the command line options in getop.c */
 	parse_lsreipl_options(argc, argv);
 
-	rc = get_reipl_type();
-	if (rc == 0) {
+	rc = get_reipl_type(reipltype);
+	switch (rc) {
+	case T_NSS:
+		printf("Re-IPL type:   nss\n");
+		rc = strrd(nss_name, "/sys/firmware/reipl/nss/name");
+		if (rc != 0)
+			exit(1);
+		printf("Name:          %s\n", nss_name);
+		break;
+	case T_FCP:
 		printf("Re-IPL type: fcp\n");
 		rc = strrd(wwpn, "/sys/firmware/reipl/fcp/wwpn");
 		if (rc != 0)
@@ -90,8 +99,8 @@ int lsreipl(int argc, char *argv[])
 			printf("bootprog:    %s\n", bootprog);
 		if (strlen(lba) > 0)
 			printf("br_lba:      %s\n", lba);
-	}
-	if (rc == 1) {
+		break;
+	case T_CCW:
 		printf("Re-IPL type:   ccw\n");
 		rc = strrd(devno, "/sys/firmware/reipl/ccw/device");
 		if (rc != 0)
@@ -106,6 +115,10 @@ int lsreipl(int argc, char *argv[])
 			printf("Loadparm:      %s\n", val);
 		else
 			printf("Loadparm:      \n");
+		break;
+	default:
+		printf("Re-IPL type: %s (unknown)\n", reipltype);
+		break;
 	}
 	return 0;
 }
@@ -134,7 +147,7 @@ int reipl(int argc, char *argv[])
 					"partition: %s\n", name, partition);
 				exit(1);
 			}
-			rc = get_ccw_devno(device, devno);
+			rc = get_ccw_devno(device);
 			if (rc != 0)  {
 				fprintf(stderr, "%s: Unable to lookup device"
 					" number for device %s\n", name,
Index: s390-tools-sles11/ipl_tools/chreipl.h
===================================================================
--- s390-tools-sles11.orig/ipl_tools/chreipl.h
+++ s390-tools-sles11/ipl_tools/chreipl.h
@@ -34,6 +34,9 @@ extern char saction[8];
 extern char name[256];
 extern int action;
 
+#define IPL_TYPE_LEN_MAX	100
+#define NSS_NAME_LEN_MAX	8
+
 #define ACT_CCW		1
 #define ACT_FCP		2
 #define ACT_NODE	3
@@ -63,10 +66,10 @@ int is_valid_case(char *c);
 int is_valid_action(char *action);
 void parse_shutdown_options(int argc, char **argv);
 void strlow(char *s);
-int get_ccw_devno(char *device, char *devno);
-int get_reipl_type(void);
+int get_ccw_devno(char *device);
+int get_reipl_type(char *reipltype);
 void parse_lsreipl_options(int argc, char **argv);
-int get_ipl_type();
+int get_ipl_type(char *reipltype);
 int get_ipl_loadparam(void);
 void print_ipl_settings(void);
 int get_sa(char *action, char *file);
Index: s390-tools-sles11/ipl_tools/system.c
===================================================================
--- s390-tools-sles11.orig/ipl_tools/system.c
+++ s390-tools-sles11/ipl_tools/system.c
@@ -174,7 +174,7 @@ int strrd(char *string, char *file)
 			fprintf(stderr, "%s\n", strerror(errno));
 			exit(1);
 		}
-		rc = fread(string, 4096, 1, filp);
+		rc = fread(string, 1, 4096, filp);
 		fclose(filp);
 		/*
 		 *  special handling is required for
@@ -193,6 +193,7 @@ int strrd(char *string, char *file)
 			fprintf(stderr, "%s\n", strerror(errno));
 			return -1;
 		} else {
+			string[rc] = 0;
 			if (string[strlen(string) - 1] == '\n')
 				string[strlen(string) - 1] = 0;
 			return 0;
Index: s390-tools-sles11/ipl_tools/ccw.c
===================================================================
--- s390-tools-sles11.orig/ipl_tools/ccw.c
+++ s390-tools-sles11/ipl_tools/ccw.c
@@ -52,22 +52,19 @@ int isccwdev(const char *devno)
 }
 
 
-int get_ccw_devno_old_sysfs(char *device, char *devno)
+int get_ccw_devno_old_sysfs(char *device)
 {
 	FILE *filp;
-	int len, errorpath, rc;
+	int errorpath;
 	char path1[4096];
 	char buf[4096];
-	char *match, *s1, *s2;
+	char *match = NULL, *s1, *s2;
 
 	errorpath = 1;
-	rc = 0;
 	sprintf(path1, "/sys/block/%s/uevent", device);
 	filp = fopen(path1, "r");
-	if (!filp) {
-		rc = -1;
-		return rc;
-	}
+	if (!filp)
+		return -1;
 	/*
 	 * the uevent file contains an entry like this:
 	 * PHYSDEVPATH=/devices/css0/0.0.206a/0.0.7e78
@@ -77,16 +74,16 @@ int get_ccw_devno_old_sysfs(char *device
 		if (match != NULL)
 			break;
 	}
+	fclose(filp);
+	if (!match)
+		return -1;
 	s1 =  strchr(buf, '/');
 	s2 =  strrchr(buf, '/');
-	len = s2-s1;
-	strncpy(devno, s2 + 1, sizeof(devno));
-	devno[len] = '\0';
-	fclose(filp);
+	strncpy(devno, s2 + 1, sizeof(devno) - 1);
 	return 0;
 }
 
-int get_ccw_devno_new_sysfs(char *device, char *devno)
+int get_ccw_devno_new_sysfs(char *device)
 {
 	int len, errorpath, rc;
 	char path2[4096];
@@ -119,8 +116,7 @@ int get_ccw_devno_new_sysfs(char *device
 			return rc;
 		}
 	}
-	strncpy(devno, s2 + 1, sizeof(devno));
-	devno[len] = '\0';
+	strncpy(devno, s2 + 1, sizeof(devno) - 1);
 	return 0;
 }
 
@@ -134,16 +130,14 @@ int get_ccw_devno_new_sysfs(char *device
  *
  * This does not work when booting from tape
  */
-int get_ccw_devno(char *device, char *devno)
+int get_ccw_devno(char *device)
 {
-    if (get_ccw_devno_old_sysfs(device, devno) != 0) {
-	if (get_ccw_devno_new_sysfs(device, devno) != 0) {
-		fprintf(stderr, "%s: Failed to lookup the device number\n",
-			name);
-		return -1;
-	}
-    }
-    return 0;
+	if (get_ccw_devno_old_sysfs(device) == 0)
+		return 0;
+	if (get_ccw_devno_new_sysfs(device) == 0)
+		return 0;
+	fprintf(stderr, "%s: Failed to lookup the device number\n", name);
+	return -1;
 }
 
 int get_ccw_dev(char *partition, char *device)
