File s390-tools-sles11sp2-zipl_parmfile_addr.patch of Package s390-tools

Description: zipl: Prevent unsupported parmfile address.
Symptom:     The system is not bootable after changing the parmfile address.
Problem:     Zipl allows the user to specify the address for the parmfile.
             But below 0x10000 there are several zipl internal
             addresses used e.g. 0x2000 as entry point for the
             internal loader. The usage of this addresses is not
             prevented.
Solution:    Block all addresses below 0x10000. Also remove default
             address for the parmfile and let the address be calculated
             automatically.
Problem-ID:  75229
---
 zipl/include/zipl.h |    6 ++----
 zipl/src/job.c      |   40 +++++++++++++++++++---------------------
 2 files changed, 21 insertions(+), 25 deletions(-)

--- a/zipl/include/zipl.h
+++ b/zipl/include/zipl.h
@@ -18,16 +18,14 @@
 #define ZIPL_MAGIC_SIZE			4
 #define DISK_LAYOUT_ID			0x00000001
 
-#define ZIPL_STAGE2_LOAD_ADDRESS	0x2000
+#define ZIPL_STAGE2_LOAD_ADDRESS        0x2000
 #define ZIPL_STAGE3_ENTRY_ADDRESS	0xa028LL
-#define DEFAULT_PARMFILE_ADDRESS	0x1000LL
-#define DEFAULT_STAGE3_ADDRESS		0xa000LL
 #define DEFAULT_IMAGE_ADDRESS		0x10000LL
+#define DEFAULT_STAGE3_ADDRESS          0xa000LL
 #define MINIMUM_ADDRESS 		0x10000LL
 #define ADDRESS_LIMIT 			0x80000000LL
 #define UNSPECIFIED_ADDRESS		-1ULL
 #define MAXIMUM_PARMLINE_SIZE 		0x380
-#define MAXIMUM_STAGE3_SIZE 		0x1000
 #define MAXIMUM_PHYSICAL_BLOCKSIZE 	0x1000
 
 #define PSW_ADDRESS_MASK		0x000000007fffffffLL
--- a/zipl/src/job.c
+++ b/zipl/src/job.c
@@ -24,7 +24,6 @@
 #include "misc.h"
 #include "scan.h"
 
-
 /* Command line options */
 static struct option options[] = {
 	{ "config",		required_argument,	NULL, 'c'},
@@ -494,14 +493,14 @@ sort_cl_array(struct component_loc* cl,
 
 static int
 get_ipl_components(struct job_ipl_data *ipl, struct component_loc **clp,
-		   int *nump, address_t *stage3_addrp)
+		   int *nump)
 {
 	struct component_loc *cl;
 	int num;
 	int rc;
 
-	/* Get memory for image, parmline, ramdisk, loader */
-	cl = misc_calloc(4, sizeof(struct component_loc));
+	/* Get memory for image, parmline, ramdisk */
+	cl = misc_calloc(3, sizeof(struct component_loc));
 	if (cl == NULL)
 		return -1;
 	/* Fill in component data */
@@ -524,10 +523,7 @@ get_ipl_components(struct job_ipl_data *
 		if (rc)
 			goto error;
 	}
-	rc = set_cl_element(&cl[num++], "internal loader", NULL, stage3_addrp,
-		MAXIMUM_STAGE3_SIZE, 0, MAXIMUM_PHYSICAL_BLOCKSIZE);
-	if (rc)
-		goto error;
+
 	*clp = cl;
 	*nump = num;
 	return 0;
@@ -539,15 +535,14 @@ error:
 
 static int
 get_dump_fs_components(struct job_dump_fs_data *dump_fs,
-		       struct component_loc **clp, int *nump,
-		       address_t *stage3_addrp)
+		       struct component_loc **clp, int *nump)
 {
 	struct component_loc *cl;
 	int num;
 	int rc;
 
 	/* Get memory for image, parmline, ramdisk, loader */
-	cl = misc_calloc(4, sizeof(struct component_loc));
+	cl = misc_calloc(3, sizeof(struct component_loc));
 	if (cl == NULL)
 		return -1;
 	/* Fill in component data */
@@ -569,10 +564,7 @@ get_dump_fs_components(struct job_dump_f
 		if (rc)
 			goto error;
 	}
-	rc = set_cl_element(&cl[num++], "internal loader", NULL, stage3_addrp,
-			    MAXIMUM_STAGE3_SIZE, 0, MAXIMUM_PHYSICAL_BLOCKSIZE);
-	if (rc)
-		goto error;
+
 	*clp = cl;
 	*nump = num;
 	return 0;
@@ -643,6 +635,14 @@ check_component_address_data(struct comp
 				     ADDRESS_LIMIT);
 			return -1;
 		}
+		if (*cl[i].addrp < MINIMUM_ADDRESS) {
+			if (name != NULL)
+				error_text("Section '%s'", name);
+			error_reason("Component '%s' falls below available "
+				     "address space (limit is 0x%08x)",
+				     cl[i].name, MINIMUM_ADDRESS);
+			return -1;
+		}
 	}
 	/* Check for overlap */
 	for (i = 0; i < num - 1; i++) {
@@ -717,10 +717,9 @@ finalize_ipl_address_data(struct job_ipl
 {
 	struct component_loc *cl;
 	int num;
-	address_t stage3_addr = DEFAULT_STAGE3_ADDRESS;
 	int rc;
 
-	rc = get_ipl_components(ipl, &cl, &num, &stage3_addr);
+	rc = get_ipl_components(ipl, &cl, &num);
 	if (rc)
 		return rc;
 	sort_cl_array(cl, num);
@@ -739,10 +738,9 @@ finalize_dump_fs_address_data(struct job
 {
 	struct component_loc *cl;
 	int num;
-	address_t stage3_addr = DEFAULT_STAGE3_ADDRESS;
 	int rc;
 
-	rc = get_dump_fs_components(dump_fs, &cl, &num, &stage3_addr);
+	rc = get_dump_fs_components(dump_fs, &cl, &num);
 	if (rc)
 		return rc;
 	sort_cl_array(cl, num);
@@ -904,7 +902,7 @@ check_job_dump_fs_data(struct job_dump_f
 		dump_fs->ramdisk_addr = UNSPECIFIED_ADDRESS;
 	}
 
-	dump_fs->parm_addr = DEFAULT_PARMFILE_ADDRESS;
+	dump_fs->parm_addr = UNSPECIFIED_ADDRESS;
 	return finalize_dump_fs_address_data(dump_fs, name);
 }
 
@@ -1195,7 +1193,7 @@ get_parmline(char* filename, char* line,
 	int to;
 	int got_lf;
 
-	addr = DEFAULT_PARMFILE_ADDRESS;
+	addr = UNSPECIFIED_ADDRESS;
 	if (filename != NULL) {
 		/* Need a filename copy to be able to change it */
 		filename = misc_strdup(filename);