diff --git a/include/dump/s390_dump.h b/include/dump/s390_dump.h index 6740c811..86959295 100644 --- a/include/dump/s390_dump.h +++ b/include/dump/s390_dump.h @@ -35,6 +35,15 @@ enum df_s390_arch { DF_S390_ARCH_64 = 2, }; +/* + * zipl parameters passed at tail of dump tools + */ +struct stage2dump_parm_tail { + char reserved[6]; + uint16_t mvdump_force; + uint64_t mem_upper_limit; +} __packed; + /* * s390 dump header format */ diff --git a/zipl/boot/stage2dump.h b/zipl/boot/stage2dump.h index b039d9c3..fb47d2e6 100644 --- a/zipl/boot/stage2dump.h +++ b/zipl/boot/stage2dump.h @@ -20,15 +20,6 @@ #define ROUND_UP(x, a) ROUND_DOWN((x) + (typeof(x))(a) - 1, a) #define IS_ALIGNED(x, a) ~((x) & ((typeof(x))(a) - 1)) -/* - * zipl parameters passed at tail of dump tools - */ -struct stage2dump_parm_tail { - char reserved[6]; - uint16_t mvdump_force; - uint64_t mem_upper_limit; -} __packed; - extern struct stage2dump_parm_tail __section(.stage2dump.tail) parm_tail; /* diff --git a/zipl/include/boot.h b/zipl/include/boot.h index 54755f52..100f4d31 100644 --- a/zipl/include/boot.h +++ b/zipl/include/boot.h @@ -16,6 +16,7 @@ #include "boot/boot_defs.h" #include "lib/zt_common.h" +#include "dump/s390_dump.h" #include "disk.h" #include "job.h" @@ -185,12 +186,16 @@ int boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr, address_t envblk_addr, size_t envblk_len); int boot_get_tape_ipl(void** data, size_t* size, address_t parm_addr, address_t initrd_addr, address_t image_addr); -int boot_get_tape_dump(void** data, size_t* size, uint64_t mem); -int boot_get_eckd_dump_stage2(void** data, size_t* size, uint64_t mem); +int boot_get_tape_dump(void **data, size_t *size, + const struct stage2dump_parm_tail *stage2dump_parms); +int boot_get_eckd_dump_stage2(void **data, size_t *size, + const struct stage2dump_parm_tail *stage2dump_parms); int boot_get_eckd_ld_ipl_br(void **br_ptr, size_t *size_ptr, disk_blockptr_t *table, struct disk_info *info); -int boot_get_eckd_mvdump_stage2(void** data, size_t* size, uint64_t mem, - uint8_t force, struct mvdump_parm_table); -int boot_get_fba_dump_stage2(void** data, size_t* size, uint64_t mem); +int boot_get_eckd_mvdump_stage2(void **data, size_t *size, + const struct stage2dump_parm_tail *stage2dump_parms, + const struct mvdump_parm_table *mv_parm_table); +int boot_get_fba_dump_stage2(void **data, size_t *size, + const struct stage2dump_parm_tail *stage2dump_parms); #endif /* BOOT_H */ diff --git a/zipl/src/boot.c b/zipl/src/boot.c index 3aebe168..bbe51eb6 100644 --- a/zipl/src/boot.c +++ b/zipl/src/boot.c @@ -19,6 +19,7 @@ #include "lib/util_libc.h" #include "boot/loaders_layout.h" +#include "stage2dump.h" #include "stage3.h" #include "boot.h" @@ -504,17 +505,19 @@ boot_get_eckd_stage2(void** data, size_t* size, struct job_data* job) int -boot_get_tape_dump(void** data, size_t* size, uint64_t mem) +boot_get_tape_dump(void **data, size_t *size, + const struct stage2dump_parm_tail *stage2dump_parms) { - void* buffer; + void *buffer; + size_t offset; buffer = misc_malloc(DATA_SIZE(tape2dump)); if (buffer == NULL) return -1; memcpy(buffer, DATA_ADDR(tape2dump), DATA_SIZE(tape2dump)); /* Write mem size to end of dump record */ - memcpy(VOID_ADD(buffer, DATA_SIZE(tape2dump) - sizeof(mem)), &mem, - sizeof(mem)); + offset = DATA_SIZE(tape2dump) - sizeof(struct stage2dump_parm_tail); + memcpy(VOID_ADD(buffer, offset), stage2dump_parms, sizeof(struct stage2dump_parm_tail)); *data = buffer; *size = DATA_SIZE(tape2dump); return 0; @@ -522,42 +525,47 @@ boot_get_tape_dump(void** data, size_t* size, uint64_t mem) int -boot_get_eckd_dump_stage2(void** data, size_t* size, uint64_t mem) +boot_get_eckd_dump_stage2(void **data, size_t *size, + const struct stage2dump_parm_tail *stage2dump_parms) { - void* buffer; + void *buffer; + size_t offset; buffer = misc_malloc(DATA_SIZE(eckd2dump_sv)); if (buffer == NULL) return -1; memcpy(buffer, DATA_ADDR(eckd2dump_sv), DATA_SIZE(eckd2dump_sv)); /* Write mem size to end of dump record */ - memcpy(VOID_ADD(buffer, DATA_SIZE(eckd2dump_sv) - sizeof(mem)), - &mem, sizeof(mem)); + offset = DATA_SIZE(eckd2dump_sv) - sizeof(struct stage2dump_parm_tail); + memcpy(VOID_ADD(buffer, offset), stage2dump_parms, + sizeof(struct stage2dump_parm_tail)); *data = buffer; *size = DATA_SIZE(eckd2dump_sv); return 0; } int -boot_get_eckd_mvdump_stage2(void** data, size_t* size, uint64_t mem, - uint8_t force, struct mvdump_parm_table parm) +boot_get_eckd_mvdump_stage2(void **data, size_t *size, + const struct stage2dump_parm_tail *stage2dump_parms, + const struct mvdump_parm_table *mv_parm_table) { - void* buffer; + void *buffer; + size_t offset; buffer = misc_malloc(DATA_SIZE(eckd2dump_mv)); if (buffer == NULL) return -1; memcpy(buffer, DATA_ADDR(eckd2dump_mv), DATA_SIZE(eckd2dump_mv)); - /* Write mem size and force indicator (as specified by zipl -M) - * to end of dump record, right before 512-byte parameter table */ - memcpy(VOID_ADD(buffer, DATA_SIZE(eckd2dump_mv) - sizeof(mem) - - sizeof(struct mvdump_parm_table)), &mem, sizeof(mem)); - memcpy(VOID_ADD(buffer, DATA_SIZE(eckd2dump_mv) - sizeof(mem) - - sizeof(force) - sizeof(struct mvdump_parm_table)), - &force, sizeof(force)); - memcpy(VOID_ADD(buffer, DATA_SIZE(eckd2dump_mv) - - sizeof(struct mvdump_parm_table)), &parm, + /* + * Write stage2 dump parameters to end of dump record, right before + * 512-byte parameter table + */ + offset = DATA_SIZE(eckd2dump_mv) - sizeof(struct mvdump_parm_table); + memcpy(VOID_ADD(buffer, offset), mv_parm_table, sizeof(struct mvdump_parm_table)); + offset = offset - sizeof(struct stage2dump_parm_tail); + memcpy(VOID_ADD(buffer, offset), stage2dump_parms, + sizeof(struct stage2dump_parm_tail)); *data = buffer; *size = DATA_SIZE(eckd2dump_mv); return 0; @@ -565,17 +573,20 @@ boot_get_eckd_mvdump_stage2(void** data, size_t* size, uint64_t mem, int -boot_get_fba_dump_stage2(void** data, size_t* size, uint64_t mem) +boot_get_fba_dump_stage2(void **data, size_t *size, + const struct stage2dump_parm_tail *stage2dump_parms) { - void* buffer; + void *buffer; + size_t offset; buffer = misc_malloc(DATA_SIZE(fba2dump)); if (buffer == NULL) return -1; memcpy(buffer, DATA_ADDR(fba2dump), DATA_SIZE(fba2dump)); /* Write mem size to end of dump record */ - memcpy(VOID_ADD(buffer, DATA_SIZE(fba2dump) - sizeof(mem)), - &mem, sizeof(mem)); + offset = DATA_SIZE(fba2dump) - sizeof(struct stage2dump_parm_tail); + memcpy(VOID_ADD(buffer, offset), stage2dump_parms, + sizeof(struct stage2dump_parm_tail)); *data = buffer; *size = DATA_SIZE(fba2dump); return 0; diff --git a/zipl/src/install.c b/zipl/src/install.c index 3e2545da..447cb739 100644 --- a/zipl/src/install.c +++ b/zipl/src/install.c @@ -791,7 +791,8 @@ static void eckd_dump_store_param(struct eckd_dump_param *param, param->bpt = info->geo.sectors; } -static int install_svdump_eckd_ldl(int fd, struct disk_info *info, uint64_t mem) +static int install_svdump_eckd_ldl(int fd, struct disk_info *info, + const struct stage2dump_parm_tail *stage2dump_parms) { disk_blockptr_t *stage2_list, *stage1b_list; blocknum_t stage2_count, stage1b_count; @@ -802,7 +803,7 @@ static int install_svdump_eckd_ldl(int fd, struct disk_info *info, uint64_t mem) void *stage2; int rc = -1; - if (boot_get_eckd_dump_stage2(&stage2, &stage2_size, mem)) + if (boot_get_eckd_dump_stage2(&stage2, &stage2_size, stage2dump_parms)) goto out; if (blk_cnt(stage2_size, info) > STAGE2_BLK_CNT_MAX) { error_reason("ECKD dump record is too large"); @@ -901,13 +902,14 @@ out: } static int -install_svdump_eckd_cdl(int fd, struct disk_info *info, uint64_t mem) +install_svdump_eckd_cdl(int fd, struct disk_info *info, + const struct stage2dump_parm_tail *stage2dump_parms) { size_t stage2_size; void *stage2; int rc; - if (boot_get_eckd_dump_stage2(&stage2, &stage2_size, mem)) + if (boot_get_eckd_dump_stage2(&stage2, &stage2_size, stage2dump_parms)) return -1; rc = install_dump_eckd_cdl(fd, info, stage2, stage2_size, 0, 0); free(stage2); @@ -915,18 +917,20 @@ install_svdump_eckd_cdl(int fd, struct disk_info *info, uint64_t mem) } static int -install_mvdump_eckd_cdl(int fd, struct disk_info *info, uint64_t mem, - uint8_t force, struct mvdump_parm_table parm) +install_mvdump_eckd_cdl(int fd, struct disk_info *info, + const struct stage2dump_parm_tail *stage2dump_parms, + const struct mvdump_parm_table *mv_parm_table) { size_t stage2_size; void *stage2; int rc; /* Write stage 2 + parameter block */ - if (boot_get_eckd_mvdump_stage2(&stage2, &stage2_size, mem, - force, parm)) + if (boot_get_eckd_mvdump_stage2(&stage2, &stage2_size, stage2dump_parms, + mv_parm_table)) return -1; - rc = install_dump_eckd_cdl(fd, info, stage2, stage2_size, 1, force); + rc = install_dump_eckd_cdl(fd, info, stage2, stage2_size, 1, + stage2dump_parms->mvdump_force); free(stage2); return rc; } @@ -960,7 +964,8 @@ out: } static int -install_svdump_fba(int fd, struct disk_info *info, uint64_t mem) +install_svdump_fba(int fd, struct disk_info *info, + const struct stage2dump_parm_tail *stage2dump_parms) { blocknum_t stage1b_count, stage2_count, blk; disk_blockptr_t *stage1b_list, *stage2_list; @@ -974,7 +979,7 @@ install_svdump_fba(int fd, struct disk_info *info, uint64_t mem) if (overwrite_partition_start(fd, info, 0)) goto out; /* Install stage 2 at end of partition */ - if (boot_get_fba_dump_stage2(&stage2, &stage2_size, mem)) + if (boot_get_fba_dump_stage2(&stage2, &stage2_size, stage2dump_parms)) goto out; if (blk_cnt(stage2_size, info) > STAGE2_BLK_CNT_MAX) { error_reason("FBA dump record is too large"); @@ -1017,13 +1022,13 @@ out: } static int -install_dump_tape(int fd, uint64_t mem) +install_dump_tape(int fd, const struct stage2dump_parm_tail *stage2dump_parms) { void* buffer; size_t size; int rc; - rc = boot_get_tape_dump(&buffer, &size, mem); + rc = boot_get_tape_dump(&buffer, &size, stage2dump_parms); if (rc) return rc; rc = DRY_RUN_FUNC(misc_write(fd, buffer, size)); @@ -1037,12 +1042,14 @@ install_dump_tape(int fd, uint64_t mem) int install_dump(const char* device, struct job_target_data* target, uint64_t mem) { + struct stage2dump_parm_tail stage2dump_parms = {0}; struct disk_info* info; char* tempdev; uint64_t part_size; int fd; int rc; + stage2dump_parms.mem_upper_limit = mem; fd = misc_open_exclusive(device); if (fd == -1) { error_text("Could not open dump device '%s'", device); @@ -1060,7 +1067,7 @@ install_dump(const char* device, struct job_target_data* target, uint64_t mem) } if (verbose) printf("Installing tape dump record\n"); - rc = install_dump_tape(fd, mem); + rc = install_dump_tape(fd, &stage2dump_parms); if (rc) { error_text("Could not install dump record on tape " "device '%s'", device); @@ -1128,11 +1135,11 @@ install_dump(const char* device, struct job_target_data* target, uint64_t mem) disk_get_type_name(info->type)); } if (info->type == disk_type_eckd_ldl) - rc = install_svdump_eckd_ldl(fd, info, mem); + rc = install_svdump_eckd_ldl(fd, info, &stage2dump_parms); else if (info->type == disk_type_eckd_cdl) - rc = install_svdump_eckd_cdl(fd, info, mem); + rc = install_svdump_eckd_cdl(fd, info, &stage2dump_parms); else - rc = install_svdump_fba(fd, info, mem); + rc = install_svdump_fba(fd, info, &stage2dump_parms); break; case disk_type_scsi: error_reason("%s: Unsupported disk type '%s' (try --dumptofs)", @@ -1160,16 +1167,19 @@ install_mvdump(char* const device[], struct job_target_data* target, int count, uint64_t mem, uint8_t force) { struct disk_info* info[MAX_DUMP_VOLUMES] = {0}; - struct mvdump_parm_table parm; + struct stage2dump_parm_tail stage2dump_parms = {0}; + struct mvdump_parm_table mvdump_parms; char* tempdev; uint64_t total_size = 0; int rc = 0, i, j, fd; struct timeval time; - memset(&parm, 0, sizeof(struct mvdump_parm_table)); + stage2dump_parms.mvdump_force = force; + stage2dump_parms.mem_upper_limit = mem; + memset(&mvdump_parms, 0, sizeof(struct mvdump_parm_table)); gettimeofday(&time, NULL); - parm.num_param = count; - parm.timestamp = (time.tv_sec << 20) + time.tv_usec; + mvdump_parms.num_param = count; + mvdump_parms.timestamp = (time.tv_sec << 20) + time.tv_usec; for (i = 0; i < count; i++) { int dummy, ssid; char busid[16]; @@ -1223,13 +1233,13 @@ install_mvdump(char* const device[], struct job_target_data* target, int count, rc = -1; goto out; } - parm.param[i].start_blk = info[i]->geo.start; - parm.param[i].end_blk = info[i]->geo.start + + mvdump_parms.param[i].start_blk = info[i]->geo.start; + mvdump_parms.param[i].end_blk = info[i]->geo.start + info[i]->phy_blocks - 1; - parm.param[i].bpt = info[i]->geo.sectors; - parm.param[i].num_heads = info[i]->geo.heads; - parm.param[i].blocksize = info[i]->phy_block_size >> 8; - parm.param[i].devno = info[i]->devno; + mvdump_parms.param[i].bpt = info[i]->geo.sectors; + mvdump_parms.param[i].num_heads = info[i]->geo.heads; + mvdump_parms.param[i].blocksize = info[i]->phy_block_size >> 8; + mvdump_parms.param[i].devno = info[i]->devno; if (util_sys_get_dev_addr(device[i], busid) != 0) { error_text("Could not find bus-ID for '%s'", device[i]); rc = -1; @@ -1240,7 +1250,7 @@ install_mvdump(char* const device[], struct job_target_data* target, int count, rc = -1; goto out; } - parm.ssid[i] = ssid; + mvdump_parms.ssid[i] = ssid; } if (verbose) { for (i = 0; i < count; i++) { @@ -1281,7 +1291,7 @@ install_mvdump(char* const device[], struct job_target_data* target, int count, if (verbose) printf("Installing dump record on target partition " "'%s'\n", device[i]); - rc = install_mvdump_eckd_cdl(fd, info[i], mem, force, parm); + rc = install_mvdump_eckd_cdl(fd, info[i], &stage2dump_parms, &mvdump_parms); misc_free_temp_dev(tempdev); if (fsync(fd))