From 0dac47cb6204dd08a92ef6b311b6107414c17c9a Mon Sep 17 00:00:00 2001 From: Mikhail Zaslonko Date: Thu, 2 Mar 2023 11:50:08 +0100 Subject: [PATCH] zipl/boot: Introduce write_addr_range() helper function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move code from write_dump_segment() to write_addr_range() function to use it later for writing compressed dump segments as well. Verify that passed address range is a multiple of dasd block size. Signed-off-by: Mikhail Zaslonko Reviewed-by: Alexander Egorenkov Signed-off-by: Jan Höppner --- zipl/boot/eckd2dump.c | 43 ++++++++++++++++++++++++++++++------------- zipl/boot/eckd2dump.h | 1 + 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/zipl/boot/eckd2dump.c b/zipl/boot/eckd2dump.c index c02b2e71..037ace16 100644 --- a/zipl/boot/eckd2dump.c +++ b/zipl/boot/eckd2dump.c @@ -447,25 +447,23 @@ void readblock(unsigned long blk, unsigned long addr, unsigned long blk_count) } /* - * Write dump segment with the header to DASD and return the next free - * block number + * Write len/device.blk_size blocks of data at start address starting from + * given block and return the next free block number. The len value must be + * a multiple of a block size (4096 bytes). */ -unsigned long write_dump_segment(unsigned long blk, - struct df_s390_dump_segm_hdr *segm) +unsigned long write_addr_range(unsigned long blk, unsigned long start, unsigned long len) { unsigned long addr, start_blk, blk_count, zero_page; - /* Write the dump segment header itself (1 page) */ - zero_page = get_zeroed_page(); - writeblock(blk, (unsigned long)segm, m2b(PAGE_SIZE), zero_page); - free_page(zero_page); - blk += m2b(PAGE_SIZE); - /* Write the dump segment */ - addr = segm->start; + /* Verify the range is a multiple of a block size */ + if (len % device.blk_size) + panic(EINTERNAL, "Invalid address range: [%016x, %016x]", + start, start + len); + addr = start; start_blk = blk; - while (addr < segm->start + segm->len) { + while (addr < start + len) { /* Remaining blocks to write */ - blk_count = m2b(segm->len) - (blk - start_blk); + blk_count = m2b(len) - (blk - start_blk); blk_count = MIN(blk_count, eckd_blk_max); zero_page = get_zeroed_page(); writeblock(blk, addr, blk_count, zero_page); @@ -477,6 +475,25 @@ unsigned long write_dump_segment(unsigned long blk, return blk; } +/* + * Write dump segment with the header to DASD and return the next free + * block number + */ +unsigned long write_dump_segment(unsigned long blk, + struct df_s390_dump_segm_hdr *segm) +{ + unsigned long zero_page; + + /* Write the dump segment header itself (1 page) */ + zero_page = get_zeroed_page(); + writeblock(blk, (unsigned long)segm, + m2b(sizeof(struct df_s390_dump_segm_hdr)), zero_page); + free_page(zero_page); + blk += m2b(PAGE_SIZE); + /* Write the dump segment */ + return write_addr_range(blk, segm->start, segm->len); +} + /* * Init ECKD common */ diff --git a/zipl/boot/eckd2dump.h b/zipl/boot/eckd2dump.h index f7dc5701..702e1f95 100644 --- a/zipl/boot/eckd2dump.h +++ b/zipl/boot/eckd2dump.h @@ -51,5 +51,6 @@ void writeblock(unsigned long blk, unsigned long addr, unsigned long blk_count, void readblock(unsigned long blk, unsigned long addr, unsigned long blk_count); unsigned long write_dump_segment(unsigned long blk, struct df_s390_dump_segm_hdr *segm); +unsigned long write_addr_range(unsigned long blk, unsigned long addr, unsigned long len); #endif /* ECKD2DUMP_H */