[PATCH v16 21/33] pc-bios/s390-ccw: Rework zipl_load_segment function
Change zipl_load_segment() to accept explicit blockno and address
parameters instead of ComponentEntry pointer and return segment length.
Modify this function to allow the caller to specify a memory address
where segment data should be loaded into.
seg_len variable is necessary to store the calculated segment length and
is used during signature verification. Return the length on success, or
a negative return code on failure.
Remove static qualifier and add function declaration to bootmap.h to
make it accessible to other modules.
Signed-off-by: Zhuoying Cai
Reviewed-by: Thomas Huth
Reviewed-by: Collin Walling
Reviewed-by: Jared Rossi
---
pc-bios/s390-ccw/bootmap.c | 14 ++
pc-bios/s390-ccw/bootmap.h | 13 +
2 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index 03841672be..d0ac97795d 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -613,19 +613,15 @@ static int ipl_eckd(void)
* IPL a SCSI disk
*/
-static int zipl_load_segment(ComponentEntry *entry)
+int zipl_load_segment(block_number_t blockno, uint64_t address)
{
const int max_entries = (MAX_SECTOR_SIZE / sizeof(ScsiBlockPtr));
ScsiBlockPtr *bprs = (void *)sec;
const int bprs_size = sizeof(sec);
-block_number_t blockno;
-uint64_t address;
int i;
char err_msg[] = "zIPL failed to read BPRS at 0x";
char *blk_no = &err_msg[30]; /* where to print blockno in (those ZZs) */
-
-blockno = entry->data.blockno;
-address = entry->compdat.load_addr;
+int seg_len = 0;
debug_print_int("loading segment at block", blockno);
debug_print_int("addr", address);
@@ -668,10 +664,12 @@ static int zipl_load_segment(ComponentEntry *entry)
puts("zIPL load segment failed");
return -EIO;
}
+
+seg_len += bprs->size * (bprs[i].blockct + 1);
}
} while (blockno);
-return 0;
+return seg_len;
}
static int zipl_run_normal(ComponentEntry **entry_ptr, const uint8_t *tmp_sec)
@@ -687,7 +685,7 @@ static int zipl_run_normal(ComponentEntry **entry_ptr,
const uint8_t *tmp_sec)
continue;
}
-if (zipl_load_segment(entry)) {
+if (zipl_load_segment(entry->data.blockno, entry->compdat.load_addr) <
0) {
return -1;
}
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
index 95943441d3..40580600b5 100644
--- a/pc-bios/s390-ccw/bootmap.h
+++ b/pc-bios/s390-ccw/bootmap.h
@@ -113,6 +113,19 @@ typedef struct ScsiMbr {
ScsiBlockPtr pt; /* block pointer to program table */
} __attribute__ ((packed)) ScsiMbr;
+/**
+ * zipl_load_segment
+ * @blockno: block number of the first BPRS describing the segment.
+ * @address: guest physical address at which to load the segment.
+ *
+ * Walks the BPRS chain starting at @blockno, loading each data block
+ * into guest memory at @address.
+ *
+ * Returns: length of the segment on success,
+ * negative value on error.
+ */
+int zipl_load_segment(block_number_t blockno, uint64_t address);
+
#define ZIPL_MAGIC "zIPL"
#define ZIPL_MAGIC_EBCDIC "\xa9\xc9\xd7\xd3"
#define IPL1_MAGIC "\xc9\xd7\xd3\xf1" /* == "IPL1" in EBCDIC */
--
2.54.0
[PATCH v16 21/33] pc-bios/s390-ccw: Rework zipl_load_segment function
Change zipl_load_segment() to accept explicit blockno and address
parameters instead of ComponentEntry pointer and return segment length.
Modify this function to allow the caller to specify a memory address
where segment data should be loaded into.
seg_len variable is necessary to store the calculated segment length and
is used during signature verification. Return the length on success, or
a negative return code on failure.
Remove static qualifier and add function declaration to bootmap.h to
make it accessible to other modules.
Signed-off-by: Zhuoying Cai
Reviewed-by: Thomas Huth
Reviewed-by: Collin Walling
Reviewed-by: Jared Rossi
---
pc-bios/s390-ccw/bootmap.c | 14 ++
pc-bios/s390-ccw/bootmap.h | 13 +
2 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index 03841672be..d0ac97795d 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -613,19 +613,15 @@ static int ipl_eckd(void)
* IPL a SCSI disk
*/
-static int zipl_load_segment(ComponentEntry *entry)
+int zipl_load_segment(block_number_t blockno, uint64_t address)
{
const int max_entries = (MAX_SECTOR_SIZE / sizeof(ScsiBlockPtr));
ScsiBlockPtr *bprs = (void *)sec;
const int bprs_size = sizeof(sec);
-block_number_t blockno;
-uint64_t address;
int i;
char err_msg[] = "zIPL failed to read BPRS at 0x";
char *blk_no = &err_msg[30]; /* where to print blockno in (those ZZs) */
-
-blockno = entry->data.blockno;
-address = entry->compdat.load_addr;
+int seg_len = 0;
debug_print_int("loading segment at block", blockno);
debug_print_int("addr", address);
@@ -668,10 +664,12 @@ static int zipl_load_segment(ComponentEntry *entry)
puts("zIPL load segment failed");
return -EIO;
}
+
+seg_len += bprs->size * (bprs[i].blockct + 1);
}
} while (blockno);
-return 0;
+return seg_len;
}
static int zipl_run_normal(ComponentEntry **entry_ptr, const uint8_t *tmp_sec)
@@ -687,7 +685,7 @@ static int zipl_run_normal(ComponentEntry **entry_ptr,
const uint8_t *tmp_sec)
continue;
}
-if (zipl_load_segment(entry)) {
+if (zipl_load_segment(entry->data.blockno, entry->compdat.load_addr) <
0) {
return -1;
}
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
index 95943441d3..40580600b5 100644
--- a/pc-bios/s390-ccw/bootmap.h
+++ b/pc-bios/s390-ccw/bootmap.h
@@ -113,6 +113,19 @@ typedef struct ScsiMbr {
ScsiBlockPtr pt; /* block pointer to program table */
} __attribute__ ((packed)) ScsiMbr;
+/**
+ * zipl_load_segment
+ * @blockno: block number of the first BPRS describing the segment.
+ * @address: guest physical address at which to load the segment.
+ *
+ * Walks the BPRS chain starting at @blockno, loading each data block
+ * into guest memory at @address.
+ *
+ * Returns: length of the segment on success,
+ * negative value on error.
+ */
+int zipl_load_segment(block_number_t blockno, uint64_t address);
+
#define ZIPL_MAGIC "zIPL"
#define ZIPL_MAGIC_EBCDIC "\xa9\xc9\xd7\xd3"
#define IPL1_MAGIC "\xc9\xd7\xd3\xf1" /* == "IPL1" in EBCDIC */
--
2.54.0
