From 11f2ccb9570569a57ac0ef0148efcd9b35d7a6b6 Mon Sep 17 00:00:00 2001 From: Aswin Karuvally Date: Sun, 1 Feb 2026 18:39:38 +0530 Subject: [PATCH] hsci: Automatically set appropriate MTU for HSCI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At present, the hsci tool creates HiperSockets Converged Interface (HSCI) with MTU of 1500 bytes regardless of the values of MTU for the external and HiperSockets interface from which it is formed. This can degrade performance or worse, affect network connectivity through the converged interface. Update the tool to automatically set MTU of HSCI as the lower of the MTU values of external and HiperSockets interface. Reviewed-by: Alexandra Winter Signed-off-by: Aswin Karuvally Signed-off-by: Jan Höppner --- hsci/hsci | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hsci/hsci b/hsci/hsci index 5540e82fc..8f884c9ac 100755 --- a/hsci/hsci +++ b/hsci/hsci @@ -365,6 +365,13 @@ function add_hsci { fi fi + #### Set MTU for the veth pair + ndev_mtu="$(cat /sys/class/net/${ndev}/mtu)" + hsdev_mtu="$(cat /sys/class/net/${hsdev}/mtu)" + hsci_mtu=$(( ndev_mtu < hsdev_mtu ? ndev_mtu : hsdev_mtu )) + ip link set dev $hscibp mtu $hsci_mtu + ip link set dev $hsci mtu $hsci_mtu + #### Set veth pair to UP ip link set dev $hscibp up >/dev/null 2>&1 if [ $? -ne 0 ]; then From 376ddfbd22f3ca6bed4fb80f2a5eb1ee9c89e3d9 Mon Sep 17 00:00:00 2001 From: Mete Durlu Date: Tue, 17 Feb 2026 09:02:34 +0100 Subject: [PATCH] hyptop/opts: Replace sort_field option with sort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hyptop's "--sort_field" command line option has always been documented as "--sort", while the code _only_ explicitly has "--sort_field". Specifying the shorter "--sort" happened to work due to an unnoticed getopt() behavior. From getopt(3) man page: """ Long option names may be abbreviated if the abbreviation is unique or is an exact match for some defined option. """ With the addition of "--sort-field" as another unique identifier via commit c5695e43c4cd ("hyptop/opts: Replace long option formats for consistency") "--sort" is no longer unique. getopt() won't be able to use that as an abbreviation, since there is ambiguity between "--sort_field" and new "--sort-field" as they are defined as separate options. Replace "--sort-field" and "--sort_field" with plain "--sort" to adhere to the documented hyptop command line argument specification and resolve the broken behavior. Fixes: c5695e43c4cd ("hyptop/opts: Replace long option formats for consistency") Reported-by: Gorkem Kilinc Reviewed-by: Jan Höppner Signed-off-by: Mete Durlu Signed-off-by: Jan Höppner --- hyptop/opts.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/hyptop/opts.c b/hyptop/opts.c index ca1820691..a88296839 100644 --- a/hyptop/opts.c +++ b/hyptop/opts.c @@ -58,9 +58,8 @@ static char HELP_TEXT[] = * Options with underscore to keep compatibility */ #define OPT_BATCH_MODE 257 /* --batch_mode */ -#define OPT_SORT_FIELD 258 /* --sort | --sort_field */ -#define OPT_CPU_TYPES 259 /* --cpu_types */ -#define OPT_SMT_FACTOR 260 /* --smt_factor */ +#define OPT_CPU_TYPES 258 /* --cpu_types */ +#define OPT_SMT_FACTOR 259 /* --smt_factor */ /* * Initialize default settings @@ -224,7 +223,7 @@ static void l_fields_set(char *str) } /* - * Set the "--sort_field" option + * Set the "--sort" option */ static void l_sort_field_set(char *str) { @@ -371,8 +370,7 @@ void opts_parse(int argc, char *argv[]) { "sys", required_argument, NULL, 's'}, { "iterations", required_argument, NULL, 'n'}, { "fields", required_argument, NULL, 'f'}, - { "sort-field", required_argument, NULL, 'S'}, - { "sort_field", required_argument, NULL, OPT_SORT_FIELD}, + { "sort", required_argument, NULL, 'S'}, { "cpu-types", required_argument, NULL, 't'}, { "cpu_types", required_argument, NULL, OPT_CPU_TYPES}, { "format", required_argument, NULL, OPT_FORMAT }, @@ -420,7 +418,6 @@ void opts_parse(int argc, char *argv[]) case 'f': l_fields_set(optarg); break; - case OPT_SORT_FIELD: case 'S': l_sort_field_set(optarg); break; From 7c75df9e9634548a2513aa1e6dc7f6c100a4f37a Mon Sep 17 00:00:00 2001 From: Mete Durlu Date: Tue, 17 Feb 2026 09:54:08 +0100 Subject: [PATCH] hyptop/opts: Fix long command line option abbreviations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hyptop should be able to accept abbreviations of the long command line options as getopt() is able to match them. Ex; $ hyptop --batch-mode $ hyptop --batch $ hyptop --bat From getopt(3) man page: """ Long option names may be abbreviated if the abbreviation is unique or is an exact match for some defined option. """ After the introduction of commit c5695e43c4cd ("hyptop/opts: Replace long option formats for consistency") long command line options for hyptop received additional definitions to support dash separated option formats. Unfortunately these definitions were defined as new and unique options and caused an ambiguity for getopt() when abbreviations matched both definitions. Ex; $ hyptop --batch hyptop: option '--batch' is ambiguous; possibilities: '--batch-mode' '--batch_mode' Map both long option formats to the same short option to fix the issue and restore the functionality. Fixes: c5695e43c4cd ("hyptop/opts: Replace long option formats for consistency") Reported-by: Gorkem Kilinc Reviewed-by: Jan Höppner Signed-off-by: Mete Durlu Signed-off-by: Jan Höppner --- hyptop/opts.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/hyptop/opts.c b/hyptop/opts.c index a8829683..1a98cd99 100644 --- a/hyptop/opts.c +++ b/hyptop/opts.c @@ -54,13 +54,6 @@ static char HELP_TEXT[] = #define OPT_FORMAT 256 /* --format */ #define OPT_FORMAT_ALL 261 /* --all*/ -/* - * Options with underscore to keep compatibility - */ -#define OPT_BATCH_MODE 257 /* --batch_mode */ -#define OPT_CPU_TYPES 258 /* --cpu_types */ -#define OPT_SMT_FACTOR 259 /* --smt_factor */ - /* * Initialize default settings */ @@ -361,18 +354,18 @@ void opts_parse(int argc, char *argv[]) { "version", no_argument, NULL, 'v'}, { "help", no_argument, NULL, 'h'}, { "batch-mode", no_argument, NULL, 'b'}, - { "batch_mode", no_argument, NULL, OPT_BATCH_MODE}, + { "batch_mode", no_argument, NULL, 'b'}, { "all", no_argument, NULL, OPT_FORMAT_ALL }, { "delay", required_argument, NULL, 'd'}, { "smt-factor", required_argument, NULL, 'm'}, - { "smt_factor", required_argument, NULL, OPT_SMT_FACTOR}, + { "smt_factor", required_argument, NULL, 'm'}, { "window", required_argument, NULL, 'w'}, { "sys", required_argument, NULL, 's'}, { "iterations", required_argument, NULL, 'n'}, { "fields", required_argument, NULL, 'f'}, { "sort", required_argument, NULL, 'S'}, { "cpu-types", required_argument, NULL, 't'}, - { "cpu_types", required_argument, NULL, OPT_CPU_TYPES}, + { "cpu_types", required_argument, NULL, 't'}, { "format", required_argument, NULL, OPT_FORMAT }, { NULL, 0, NULL, 0 } }; @@ -391,14 +384,12 @@ void opts_parse(int argc, char *argv[]) case 'h': l_usage(); hyptop_exit(0); - case OPT_BATCH_MODE: case 'b': l_batch_mode_set(); break; case 'd': l_delay_set(optarg); break; - case OPT_SMT_FACTOR: case 'm': l_factor_set(optarg); break; @@ -411,7 +402,6 @@ void opts_parse(int argc, char *argv[]) case 'n': l_iterations_set(optarg); break; - case OPT_CPU_TYPES: case 't': l_cpu_types_set(optarg); break; From 50f909db8f53011b00c5819e593504264d23bb82 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Thu, 12 Mar 2026 18:36:00 +0100 Subject: [PATCH] zipl/boot: Fix stage3 secure boot trailer placement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The stage3 linker script places .sb.trailer so that it must end at COMMAND_LINE_EXTRA. The current script derives the start address from SIZEOF(.sb.trailer) before the section is emitted: . = COMMAND_LINE_EXTRA - SIZEOF(.sb.trailer); With binutils older than 2.39 before commit 648f6099d4dc ("-z relro relaxation and ld script SIZEOF") this can result in .sb.trailer being placed at COMMAND_LINE_EXTRA instead, moving the trailer into the following area and breaking the expected layout. The trailer has a fixed size, so use an explicit constant for the placement calculation and keep the ASSERT to verify the final section size. This makes the placement deterministic again. Fixes: a1126352ecfa ("zipl/boot: Improve linker scripts") Reviewed-by: Marc Hartmayer Signed-off-by: Vasily Gorbik Signed-off-by: Jan Höppner --- zipl/boot/stage3.lds.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zipl/boot/stage3.lds.S b/zipl/boot/stage3.lds.S index 35ed32d29..cbfaaf0fc 100644 --- a/zipl/boot/stage3.lds.S +++ b/zipl/boot/stage3.lds.S @@ -48,15 +48,16 @@ SECTIONS .rodata : {*(.rodata .rodata.*) } .data : { *(.data .data.*) } +#define SB_TRAILER_SIZE 32 /* Trailer needed for Secure Boot */ - . = COMMAND_LINE_EXTRA - SIZEOF(.sb.trailer); + . = COMMAND_LINE_EXTRA - SB_TRAILER_SIZE; .sb.trailer : { QUAD(0x0000c00000000000) QUAD(STAGE3_ENTRY + PSW_LOAD) QUAD(STAGE3_ENTRY) QUAD(0x000000207a49504c) } - ASSERT(SIZEOF(.sb.trailer) == 32, "Invalid .sb.trailer size") + ASSERT(SIZEOF(.sb.trailer) == SB_TRAILER_SIZE, "Invalid .sb.trailer size") . = COMMAND_LINE_EXTRA; .cmdline_extra : { From fcfee1aa84d3d3afef6a30b3657b2a2ea99edfce Mon Sep 17 00:00:00 2001 From: Eduard Shishkin Date: Mon, 16 Mar 2026 17:31:33 +0100 Subject: [PATCH] zipl/src: Fix a bug in building replicated program tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When installing IPL on mirrored targets, zipl builds multiple program tables (one such table per each mirror). If the option "--add-files" was specified, then zipl uses the in-bootmap files, that was written at the prevoius iteration (for the mirror ID #0) to build program tables for mirrors with ID #1 (and larger). The in-bootmap files already don't contain trailers. Despite this, the building process cuts off the tail of trailer size, which results in corrupted boot data. This bug may result in crashing the kernel when booting from mirrors with ID #1 (and larger) and manifests only if the boot components are signed and the option "--add-files" is specified for the installation session. Don't count the trailer, when building program tables using in-bootmap files written at the previous iteration. Fixes: 431e4542ca9c ("zipl/src: Reuse data of file components in bootmap") Signed-off-by: Eduard Shishkin Reviewed-by: Jan Höppner Signed-off-by: Jan Höppner --- zipl/src/bootmap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zipl/src/bootmap.c b/zipl/src/bootmap.c index 7d75b608..14a30c34 100644 --- a/zipl/src/bootmap.c +++ b/zipl/src/bootmap.c @@ -441,12 +441,14 @@ static int add_component_file(struct install_set *bis, const char *filename, if (add_files && comp_reg->offset > 0) { /* - * The file has been already written to the bootmap. + * The file has been already written to the bootmap, + * and that in-bootmap file doesn't contain a trailer. * Use the respective region in the bootmap file to * add the component */ filename = bis->filename; add_files = 0; + trailer = 0; } else { comp_reg = NULL; } From 984e008127985172bdfe90262d5dc705cc5149a1 Mon Sep 17 00:00:00 2001 From: Eduard Shishkin Date: Mon, 23 Mar 2026 16:31:50 +0100 Subject: [PATCH] zipl/src: Indicate in a verbose output if a component is signed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regardless of secure boot support, indicate in the verbose zipl(8) output if a component is signed. Signed-off-by: Eduard Shishkin Reviewed-by: Jan Höppner Signed-off-by: Jan Höppner --- zipl/src/bootmap.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/zipl/src/bootmap.c b/zipl/src/bootmap.c index 14a30c34..6a72d28c 100644 --- a/zipl/src/bootmap.c +++ b/zipl/src/bootmap.c @@ -704,9 +704,6 @@ static int add_ipl_program(struct install_set *bis, bool add_envblk, /* initiate values for ramdisk */ stats.st_size = 0; if (ipl->common.ramdisk != NULL) { - /* Add ramdisk */ - if (verbose && bis->mirrors[mirror_id].print_details) - printf(" initial ramdisk...: %s\n", ipl->common.ramdisk); /* Get ramdisk file size */ if (stat(ipl->common.ramdisk, &stats)) { error_reason(strerror(errno)); @@ -834,10 +831,10 @@ static int add_ipl_program(struct install_set *bis, bool add_envblk, offset += sizeof(struct component_entry); /* Add kernel image */ - if (verbose && bis->mirrors[mirror_id].print_details) - printf(" kernel image......: %s\n", ipl->common.image); - signature_size = extract_signature(ipl->common.image, &signature, &sig_head); + if (verbose && bis->mirrors[mirror_id].print_details) + printf(" kernel image......: %s%s\n", + ipl->common.image, signature_size ? " (signed)" : ""); if (signature_size && (is_secure == SECURE_BOOT_ENABLED || (is_secure == SECURE_BOOT_AUTO && secure_boot_supported))) { @@ -906,6 +903,10 @@ static int add_ipl_program(struct install_set *bis, bool add_envblk, if (ipl->common.ramdisk != NULL) { signature_size = extract_signature(ipl->common.ramdisk, &signature, &sig_head); + if (verbose && bis->mirrors[mirror_id].print_details) + printf(" initial ramdisk...: %s%s\n", + ipl->common.ramdisk, + signature_size ? " (signed)" : ""); if (signature_size && (is_secure == SECURE_BOOT_ENABLED || (is_secure == SECURE_BOOT_AUTO && From 9882aabe4434594cd055b95ad8427338207a8763 Mon Sep 17 00:00:00 2001 From: Eduard Shishkin Date: Mon, 8 Jun 2026 17:12:05 +0200 Subject: [PATCH] zipl/src: Update format of zipl helpers output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the format of zipl helpers output to support hybrid mirrors (i.e. composed of disks of different types and geometry). The new format imposes an additional requirement that any key-value pair "targetbase=X:Y" titles a new section with a set of target parmeters for the base disk identified by that pair. Without this change, zipl reports "Inconsistent script output". To reproduce the problem, build a mixed mirrored setup with first SCSI disk and second DASD disk, and prepare it for IPL. Fixes: 731f00202c53 ("zipl/src: Enable heterogeneous mirrors support") Reviewed-by: Stefan Haberland Signed-off-by: Eduard Shishkin Signed-off-by: Jan Höppner --- zipl/include/job.h | 2 +- zipl/src/disk.c | 81 ++++++++++++++++++---------------------------- 2 files changed, 32 insertions(+), 51 deletions(-) diff --git a/zipl/include/job.h b/zipl/include/job.h index 0acea592..3e93a323 100644 --- a/zipl/include/job.h +++ b/zipl/include/job.h @@ -167,7 +167,7 @@ struct job_data { static inline struct target *target_at(struct job_target_data *data, int index) { - return index >= MAX_TARGETS ? NULL : &data->targets[index]; + return index < 0 || index >= MAX_TARGETS ? NULL : &data->targets[index]; } static inline char *get_targetbase(struct job_target_data *data, int index) diff --git a/zipl/src/disk.c b/zipl/src/disk.c index 86ec6bc7..673224fb 100644 --- a/zipl/src/disk.c +++ b/zipl/src/disk.c @@ -176,6 +176,15 @@ static int determine_virtblk_type(struct device_info *dev_info, return rc; } +#define GET_TARGET_OR_GOTO_ERR() \ + do { \ + if (target_id < 0) \ + goto err_inc; \ + t = target_at(td, target_id); \ + if (!t) \ + goto err_exc; \ + } while (0) + /** * Process a script output represented by FH and consisting * of pairs 'key=value' (each such pair is on a separate line). @@ -189,57 +198,46 @@ static int determine_virtblk_type(struct device_info *dev_info, */ static int set_target_parameters(FILE *fh, struct job_target_data *td) { - int idx[LAST_TARGET_PARAM] = {0}; + int target_id = -1; struct target *t; char buffer[80]; char value[40]; - char *error; int i; /* reset array of target parameters */ memset(td->targets, 0, sizeof(td->targets)); - /** - * Process a stream of 'key=value' pairs and distribute - * them into groups. - * The i-th occurrence of some "key" in the stream means - * that the respective pair belongs to the group #i + /* + * Process a stream of key-value pairs and complete the array of + * target parameters. + * Each key-value pair "targetbase=foo" title a group of parameters + * for a new target. */ - error = "Exceeded the maximum number of base disks"; while (fgets(buffer, 80, fh)) { if (sscanf(buffer, "targetbase=%s", value) == 1) { - t = target_at(td, idx[TARGET_BASE]++); - if (!t) - goto error; + target_id++; /* new title */ + GET_TARGET_OR_GOTO_ERR(); t->targetbase = misc_strdup(value); goto found; } if (sscanf(buffer, "targettype=%s", value) == 1) { - t = target_at(td, idx[TARGET_TYPE]++); - if (!t) - goto error; + GET_TARGET_OR_GOTO_ERR(); type_from_target(value, &t->targettype); goto found; } if (sscanf(buffer, "targetgeometry=%s", value) == 1) { - t = target_at(td, idx[TARGET_GEOMETRY]++); - if (!t) - goto error; + GET_TARGET_OR_GOTO_ERR(); t->targetcylinders = atoi(strtok(value, ",")); t->targetheads = atoi(strtok(NULL, ",")); t->targetsectors = atoi(strtok(NULL, ",")); goto found; } if (sscanf(buffer, "targetblocksize=%s", value) == 1) { - t = target_at(td, idx[TARGET_BLOCKSIZE]++); - if (!t) - goto error; + GET_TARGET_OR_GOTO_ERR(); t->targetblocksize = atoi(value); goto found; } if (sscanf(buffer, "targetoffset=%s", value) == 1) { - t = target_at(td, idx[TARGET_OFFSET]++); - if (!t) - goto error; + GET_TARGET_OR_GOTO_ERR(); t->targetoffset = atol(value); goto found; } @@ -247,43 +245,26 @@ static int set_target_parameters(FILE *fh, struct job_target_data *td) found: t->check_params++; } + td->nr_targets = target_id + 1; /* Check for consistency */ - error = "Inconsistent script output"; - /* - * First, calculate total number of groups - */ - td->nr_targets = 0; - for (i = 0; i < MAX_TARGETS; i++) { - t = target_at(td, i); - if (t->check_params == 0) - break; - td->nr_targets++; - } if (!td->nr_targets) - /* No keywords found in the stream */ - goto error; - /* - * Each group has to include targetbase, targettype, - * targetblocksize and targetoffset. - */ - if (td->nr_targets != idx[TARGET_BASE] || - td->nr_targets != idx[TARGET_TYPE] || - td->nr_targets != idx[TARGET_BLOCKSIZE] || - td->nr_targets != idx[TARGET_OFFSET]) - goto error; + /* Missed a title pair "targetbase=foo" in the stream */ + goto err_inc; /* - * In addition, any group of "ECKD" type has to include - * targetgeometry + * Any group of "ECKD" type has to include targetgeometry */ for (i = 0; i < td->nr_targets; i++) { t = target_at(td, i); assert(t->check_params >= 4); if (disk_type_is_eckd(t->targettype) && t->check_params != 5) - goto error; + goto err_inc; } return 0; -error: - error_reason("%s", error); +err_inc: + error_reason("%s", "Inconsistent script output"); + return -1; +err_exc: + error_reason("%s", "Exceeded the maximum number of base disks"); return -1; } From f2902a1990783159a8358ead99b4dd19009183a1 Mon Sep 17 00:00:00 2001 From: Eduard Shishkin Date: Wed, 10 Jun 2026 18:05:55 +0200 Subject: [PATCH] zipl/src: Fix alignment of componets location in bootmap file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calculate the alignment value as maximum of physical block sizes of disks participating in the mirrored setup. Earlier the alignment was calculated as a physical block size of the first disk of a mirrored setup. Without this change, the assertion in disk_get_blocklist_from_file() 'assert(reg->offset % info->phy_block_size == 0)' is triggered in case when blocksize of base disk #J > blocksize of base disk #I && (J>I). To reproduce the problem, build a mixed mirrored setup with first SCSI disk, second DASD disk and prepare it for IPL. Fixes: 731f00202c53 ("zipl/src: Enable heterogeneous mirrors support") Reviewed-by: Stefan Haberland Signed-off-by: Eduard Shishkin Signed-off-by: Jan Höppner --- zipl/include/disk.h | 9 ++++---- zipl/include/install.h | 4 ++-- zipl/src/bootmap.c | 21 ++++++++++------- zipl/src/disk.c | 27 +++++++++++++++++----- zipl/src/install.c | 52 +++++++++++++++++++++++------------------- 5 files changed, 69 insertions(+), 44 deletions(-) diff --git a/zipl/include/disk.h b/zipl/include/disk.h index cce69f73a..ff64fda75 100644 --- a/zipl/include/disk.h +++ b/zipl/include/disk.h @@ -93,6 +93,7 @@ struct device_info { * as retrieved from "/proc/devices", or evaluated */ int fs_block_size; + int align; /* alignment of component location in bootmap */ struct disk_info base[MAX_TARGETS]; /* array of physical disks for * bootstrap blocks recording */ @@ -133,13 +134,13 @@ int disk_write_block_aligned(struct misc_fd *mfd, const void *data, blocknum_t disk_write_block_buffer(struct misc_fd *fd, int fd_is_basedisk, const void* buffer, size_t bytecount, disk_blockptr_t** blocklist, - int fs_block_size, struct disk_info *info); + int fs_block_size, int align, + struct disk_info *info); blocknum_t disk_write_block_buffer_align(struct misc_fd *mfd, int fd_is_basedisk, const void *buffer, size_t bytecount, disk_blockptr_t **blocklist, - int fs_block_size, - struct disk_info *info, int align, - off_t *offset); + int fs_block_size, int align, + struct disk_info *info, off_t *offset); void disk_print_devt(dev_t d); void disk_print_devname(dev_t d); void prepare_footnote_ptr(int source, char *ptr); diff --git a/zipl/include/install.h b/zipl/include/install.h index 71dc33d97..cc1f39b7f 100644 --- a/zipl/include/install.h +++ b/zipl/include/install.h @@ -160,13 +160,13 @@ int install_mvdump(char* const device[], struct job_target_data* target, int install_fba_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, blocknum_t *stage1b_count, disk_blockptr_t *stage2_list, - blocknum_t stage2_count, int fs_block_size, + blocknum_t stage2_count, int fs_block_size, int align, struct disk_info *info); int install_eckd_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, blocknum_t *stage1b_count, disk_blockptr_t *stage2_list, blocknum_t stage2_count, int fs_block_size, - struct disk_info *info); + int align, struct disk_info *info); int rewind_tape(int fd); #endif /* INSTALL_H */ diff --git a/zipl/src/bootmap.c b/zipl/src/bootmap.c index 6a72d28cb..9b5d2a12f 100644 --- a/zipl/src/bootmap.c +++ b/zipl/src/bootmap.c @@ -383,8 +383,8 @@ static int add_component_file_range(struct install_set *bis, 0 /* not a base disk */, buffer, size, list, bis->info->fs_block_size, + bis->info->align, info, - info->phy_block_size, /* * save component offset */ @@ -478,7 +478,7 @@ static int add_component_buffer_base(struct install_set *bis, void *buffer, align = fs_block_aligned_by_id(comp_id) ? bis->info->fs_block_size : - info->phy_block_size; + bis->info->align; if (bis->skip_prepare_device && bis->mirrors[mirror_id].skip_prepare_blocklist) @@ -486,8 +486,8 @@ static int add_component_buffer_base(struct install_set *bis, void *buffer, goto write_segment_table; /* Write buffer */ *count = disk_write_block_buffer_align(&bis->mfd, 0, buffer, size, list, - bis->info->fs_block_size, - info, align, &offset); + bis->info->fs_block_size, align, + info, &offset); if (*count == 0) { error_text("Could not write to bootmap file"); return -1; @@ -1265,7 +1265,7 @@ write_empty_block(struct misc_fd *mfd, disk_blockptr_t *block, static int install_stages_dasd_fba(struct misc_fd *mfd, char *filename, struct job_data *job, - int fs_block_size, + int fs_block_size, int align, struct disk_info *info, disk_blockptr_t **stage1b_list, blocknum_t *stage1b_count, @@ -1289,6 +1289,7 @@ static int install_stages_dasd_fba(struct misc_fd *mfd, char *filename, stage2_size, &stage2_list, fs_block_size, + align, info); free(stage2_data); if (stage2_count == 0) { @@ -1297,7 +1298,7 @@ static int install_stages_dasd_fba(struct misc_fd *mfd, char *filename, } if (install_fba_stage1b(mfd, stage1b_list, stage1b_count, stage2_list, stage2_count, - fs_block_size, info)) + fs_block_size, align, info)) return -1; free(stage2_list); break; @@ -1317,7 +1318,7 @@ static int install_stages_dasd_fba(struct misc_fd *mfd, char *filename, static int install_stages_eckd_dasd(struct misc_fd *mfd, char *filename, struct job_data *job, - int fs_block_size, + int fs_block_size, int align, struct disk_info *info, disk_blockptr_t *program_table, disk_blockptr_t **stage1b_list, @@ -1341,6 +1342,7 @@ static int install_stages_eckd_dasd(struct misc_fd *mfd, char *filename, stage2b_size, &stage2b_list, fs_block_size, + align, info); free(stage2b_data); if (stage2b_count == 0) { @@ -1349,7 +1351,7 @@ static int install_stages_eckd_dasd(struct misc_fd *mfd, char *filename, } if (install_eckd_stage1b(mfd, stage1b_list, stage1b_count, stage2b_list, stage2b_count, - fs_block_size, info)) + fs_block_size, align, info)) return -1; free(stage2b_list); break; @@ -1367,6 +1369,7 @@ static int install_stages_eckd_dasd(struct misc_fd *mfd, char *filename, stage2b_size, stage1b_list, fs_block_size, + align, info); free(stage2b_data); if (stage2b_count == 0) { @@ -1395,6 +1398,7 @@ static int bootmap_install_stages(struct job_data *job, struct install_set *bis, case disk_type_fba: rc = install_stages_dasd_fba(&bis->mfd, bis->filename, job, bis->info->fs_block_size, + bis->info->align, info, &pt->stage1b_list, &pt->stage1b_count, @@ -1404,6 +1408,7 @@ static int bootmap_install_stages(struct job_data *job, struct install_set *bis, case disk_type_eckd_cdl: rc = install_stages_eckd_dasd(&bis->mfd, bis->filename, job, bis->info->fs_block_size, + bis->info->align, info, &pt->table, &pt->stage1b_list, diff --git a/zipl/src/disk.c b/zipl/src/disk.c index 673224fb9..b2f2561da 100644 --- a/zipl/src/disk.c +++ b/zipl/src/disk.c @@ -575,7 +575,21 @@ static int disk_set_info_complete(struct job_target_data *td, return 0; } -static int device_set_info_complete(struct device_info *dev_info) +static void device_get_alignment(struct device_info *dev_info, + struct job_target_data *td) +{ + struct disk_info *base; + int i; + + for (i = 0; i < td->nr_targets; i++) { + base = &dev_info->base[i]; + if (dev_info->align < base->phy_block_size) + dev_info->align = base->phy_block_size; + } +} + +static int device_set_info_complete(struct device_info *dev_info, + struct job_target_data *td) { struct util_proc_part_entry part_entry; @@ -588,6 +602,7 @@ static int device_set_info_complete(struct device_info *dev_info) } /* Initialize file system block size with invalid value */ dev_info->fs_block_size = -1; + device_get_alignment(dev_info, td); return 0; } @@ -689,7 +704,7 @@ int device_get_info(const char *device, struct job_target_data *td, if (disk_set_info_complete(td, &data->base[i], &stats, fd)) goto error; } - if (device_set_info_complete(data)) + if (device_set_info_complete(data, td)) goto error; free(script_file); close(fd); @@ -1017,7 +1032,7 @@ blocknum_t disk_write_block_buffer_align(struct misc_fd *mfd, int fd_is_basedisk, const void *buffer, size_t bytecount, disk_blockptr_t **blocklist, int fs_block_size, - struct disk_info *info, int align, off_t *offset) + int align, struct disk_info *info, off_t *offset) { blocknum_t count; blocknum_t i; @@ -1058,12 +1073,12 @@ blocknum_t disk_write_block_buffer(struct misc_fd *mfd, int fd_is_basedisk, const void *buffer, size_t bytecount, disk_blockptr_t **blocklist, int fs_block_size, - struct disk_info *info) + int align, struct disk_info *info) { return disk_write_block_buffer_align(mfd, fd_is_basedisk, buffer, bytecount, blocklist, - fs_block_size, info, - info->phy_block_size, NULL); + fs_block_size, align, info, + NULL); } /* Print device node. */ diff --git a/zipl/src/install.c b/zipl/src/install.c index 176a00437..1baf153fa 100644 --- a/zipl/src/install.c +++ b/zipl/src/install.c @@ -172,7 +172,7 @@ install_fba_ccw(int fd, disk_blockptr_t *program_table, int install_eckd_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, blocknum_t *stage1b_count, disk_blockptr_t *stage2_list, - blocknum_t stage2_count, int fs_block_size, + blocknum_t stage2_count, int fs_block_size, int align, struct disk_info *info) { struct boot_eckd_stage1b *stage1b; @@ -189,7 +189,7 @@ install_eckd_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, goto out_free_stage1b; *stage1b_count = disk_write_block_buffer(mfd, 1, stage1b, stage1b_size, stage1b_list, fs_block_size, - info); + align, info); if (*stage1b_count == 0) goto out_free_stage1b; rc = 0; @@ -855,7 +855,7 @@ static void eckd_dump_store_param(struct eckd_dump_param *param, static int install_svdump_eckd_ldl(struct misc_fd *mfd, int fs_block_size, - struct disk_info *info, + int align, struct disk_info *info, const struct stage2dump_parm_tail *stage2dump_parms) { disk_blockptr_t *stage2_list, *stage1b_list; @@ -879,13 +879,13 @@ install_svdump_eckd_ldl(struct misc_fd *mfd, int fs_block_size, if (misc_seek(mfd->fd, info->geo.start * info->phy_block_size)) goto out_free_stage2; stage2_count = disk_write_block_buffer(mfd, 1, stage2, stage2_size, - &stage2_list, - fs_block_size, info); + &stage2_list, fs_block_size, + align, info); if (stage2_count == 0) goto out_free_stage2_list; if (install_eckd_stage1b(mfd, &stage1b_list, &stage1b_count, stage2_list, stage2_count, fs_block_size, - info)) + align, info)) goto out_free_stage2_list; /* Install stage 0 - afterwards we are at stage 1 position*/ boot_init_eckd_ldl_stage0(&stage0); @@ -913,8 +913,8 @@ install_svdump_eckd_ldl(struct misc_fd *mfd, int fs_block_size, } static int install_dump_eckd_cdl(struct misc_fd *mfd, int fs_block_size, - struct disk_info *info, void *stage2, - size_t stage2_size, int mvdump, + int align, struct disk_info *info, + void *stage2, size_t stage2_size, int mvdump, int force) { blocknum_t count, stage2_count, stage1b_count; @@ -939,13 +939,13 @@ static int install_dump_eckd_cdl(struct misc_fd *mfd, int fs_block_size, goto out; stage2_count = disk_write_block_buffer(mfd, 1, stage2, stage2_size, &stage2_list, fs_block_size, - info); + align, info); if (stage2_count == 0) goto out; /* Install stage 1b behind stage 2*/ if (install_eckd_stage1b(mfd, &stage1b_list, &stage1b_count, stage2_list, stage2_count, fs_block_size, - info)) + align, info)) goto out_free_stage2_list; /* Install stage 0 */ boot_init_eckd_cdl_stage0(&stage0_cdl); @@ -973,7 +973,7 @@ static int install_dump_eckd_cdl(struct misc_fd *mfd, int fs_block_size, static int install_svdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size, - struct disk_info *info, + int align, struct disk_info *info, const struct stage2dump_parm_tail *stage2dump_parms) { size_t stage2_size; @@ -982,7 +982,7 @@ install_svdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size, if (boot_get_eckd_dump_stage2(&stage2, &stage2_size, stage2dump_parms)) return -1; - rc = install_dump_eckd_cdl(mfd, fs_block_size, + rc = install_dump_eckd_cdl(mfd, fs_block_size, align, info, stage2, stage2_size, 0, 0); free(stage2); return rc; @@ -990,7 +990,7 @@ install_svdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size, static int install_mvdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size, - struct disk_info *info, + int align, struct disk_info *info, const struct stage2dump_parm_tail *stage2dump_parms, const struct mvdump_parm_table *mv_parm_table) { @@ -1002,7 +1002,7 @@ install_mvdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size, if (boot_get_eckd_mvdump_stage2(&stage2, &stage2_size, stage2dump_parms, mv_parm_table)) return -1; - rc = install_dump_eckd_cdl(mfd, fs_block_size, info, stage2, + rc = install_dump_eckd_cdl(mfd, fs_block_size, align, info, stage2, stage2_size, 1, stage2dump_parms->mvdump_force); free(stage2); @@ -1012,7 +1012,7 @@ install_mvdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size, int install_fba_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, blocknum_t *stage1b_count, disk_blockptr_t *stage2_list, - blocknum_t stage2_count, int fs_block_size, + blocknum_t stage2_count, int fs_block_size, int align, struct disk_info *info) { struct boot_fba_stage1b *stage1b; @@ -1029,7 +1029,7 @@ install_fba_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, goto out_free_stage1b; *stage1b_count = disk_write_block_buffer(mfd, 1, stage1b, stage1b_size, stage1b_list, fs_block_size, - info); + align, info); if (*stage1b_count == 0) goto out_free_stage1b; rc = 0; @@ -1041,7 +1041,7 @@ install_fba_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, static int install_svdump_fba(struct misc_fd *mfd, int fs_block_size, - struct disk_info *info, + int align, struct disk_info *info, const struct stage2dump_parm_tail *stage2dump_parms) { blocknum_t stage1b_count, stage2_count, blk; @@ -1067,7 +1067,7 @@ install_svdump_fba(struct misc_fd *mfd, int fs_block_size, goto out_free_stage2; stage2_count = disk_write_block_buffer(mfd, 1, stage2, stage2_size, &stage2_list, fs_block_size, - info); + align, info); if (stage2_count == 0) goto out_free_stage2; /* Install stage 1b in front of stage 2 */ @@ -1075,7 +1075,8 @@ install_svdump_fba(struct misc_fd *mfd, int fs_block_size, if (misc_seek(mfd->fd, blk * info->phy_block_size)) goto out_free_stage2_list; if (install_fba_stage1b(mfd, &stage1b_list, &stage1b_count, - stage2_list, stage2_count, fs_block_size, info)) + stage2_list, stage2_count, fs_block_size, + align, info)) goto out_free_stage2_list; /* Install stage 0/1 fill in dump partition parameter */ if (boot_init_fba_stage0(&stage0, stage1b_list, stage1b_count)) @@ -1219,14 +1220,17 @@ install_dump(const char *device, struct job_target_data *target, uint64_t mem, if (info->type == disk_type_eckd_ldl) rc = install_svdump_eckd_ldl(&mfd, dev_info->fs_block_size, - info, &stage2dump_parms); + dev_info->align, info, + &stage2dump_parms); else if (info->type == disk_type_eckd_cdl) rc = install_svdump_eckd_cdl(&mfd, dev_info->fs_block_size, - info, &stage2dump_parms); + dev_info->align, info, + &stage2dump_parms); else rc = install_svdump_fba(&mfd, dev_info->fs_block_size, - info, &stage2dump_parms); + dev_info->align, info, + &stage2dump_parms); break; case disk_type_scsi: error_reason("%s: Unsupported disk type '%s' (try --dumptofs)", @@ -1382,8 +1386,8 @@ install_mvdump(char* const device[], struct job_target_data* target, int count, printf("Installing dump record on target partition " "'%s'\n", device[i]); rc = install_mvdump_eckd_cdl(&mfd, dev_info[i]->fs_block_size, - info[i], &stage2dump_parms, - &mvdump_parms); + dev_info[i]->align, info[i], + &stage2dump_parms, &mvdump_parms); misc_free_temp_dev(tempdev); if (fsync(mfd.fd)) From 4f622325efa2e433254ea01d3eabf472dcc6f757 Mon Sep 17 00:00:00 2001 From: Eduard Shishkin Date: Thu, 11 Jun 2026 12:21:09 +0200 Subject: [PATCH] zipl/src: Fix add_component_file_range() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix add_component_file_range() to process components of all types (not only of COMPONENT_TYPE_LOAD), similar to how it is going in add_component_buffer(). Earlier components of COMPONENT_TYPE_SIGNATURE were processed only by add_component_buffer(). Starting from 60bc1e3, signatures for mirrors (i.e. base disks of #1 and larger ID) are processed also by the function add_component_file_range(), which works incorrectly for such type of components. Fixes: 60bc1e38d058 ("zipl/src: Reuse data of buffer components in bootmap") Reviewed-by: Stefan Haberland Signed-off-by: Eduard Shishkin Signed-off-by: Jan Höppner --- zipl/src/bootmap.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/zipl/src/bootmap.c b/zipl/src/bootmap.c index 9b5d2a12..0d6df2d2 100644 --- a/zipl/src/bootmap.c +++ b/zipl/src/bootmap.c @@ -413,8 +413,13 @@ static int add_component_file_range(struct install_set *bis, *count -= DIV_ROUND_UP(trailer, info->phy_block_size); } /* Fill in component location */ - location->addr = load_address; - location->size = *count * info->phy_block_size; + if (component_type_by_id(comp_id) == COMPONENT_TYPE_LOAD) { + location->addr = load_address; + location->size = *count * info->phy_block_size; + } else { + location->addr = 0; + location->size = 0; + } /* Try to compact list */ *count = disk_compact_blocklist(*list, *count, info); write_segment_table: From ee8897f9db5b93bc16799d0b534cc13c36719785 Mon Sep 17 00:00:00 2001 From: Eduard Shishkin Date: Thu, 11 Jun 2026 15:43:20 +0200 Subject: [PATCH] zipl/src: Add ->set_location() private method of program component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add/use ->set_location() private method of struct component_footer instead of checking component types every time when operating with program components. Reviewed-by: Stefan Haberland Signed-off-by: Eduard Shishkin Signed-off-by: Jan Höppner --- zipl/include/install.h | 9 +++++++ zipl/src/bootmap.c | 21 +++++----------- zipl/src/zipl.c | 54 ++++++++++++++++++++++++++++++++---------- 3 files changed, 57 insertions(+), 27 deletions(-) diff --git a/zipl/include/install.h b/zipl/include/install.h index cc1f39b7..874068ef 100644 --- a/zipl/include/install.h +++ b/zipl/include/install.h @@ -58,6 +58,9 @@ struct component_footer { * in the bootmap file. Otherwise, to * phy_block_size boundary. */ + void (*set_location)(struct component_loc *location, + address_t load_address, blocknum_t count, + int block_size); }; struct program_component { @@ -109,6 +112,12 @@ static inline enum scsi_layout get_scsi_layout(unsigned char *bootblock) return scsi_layout_unknown; } +static inline struct component_footer * +component_footer_by_id(enum program_component_id id) +{ + return &component_footers[id]; +} + static inline component_type component_type_by_id(enum program_component_id id) { return component_footers[id].type; diff --git a/zipl/src/bootmap.c b/zipl/src/bootmap.c index 0d6df2d2..78ff73aa 100644 --- a/zipl/src/bootmap.c +++ b/zipl/src/bootmap.c @@ -353,6 +353,7 @@ static int add_component_file_range(struct install_set *bis, { struct program_component *pc = get_component(bis, mirror_id, comp_id, menu_idx); + struct component_footer *cf = component_footer_by_id(comp_id); struct disk_info *info = &bis->info->base[mirror_id]; struct component_loc *location = &pc->loc; disk_blockptr_t **list = &pc->list; @@ -413,13 +414,7 @@ static int add_component_file_range(struct install_set *bis, *count -= DIV_ROUND_UP(trailer, info->phy_block_size); } /* Fill in component location */ - if (component_type_by_id(comp_id) == COMPONENT_TYPE_LOAD) { - location->addr = load_address; - location->size = *count * info->phy_block_size; - } else { - location->addr = 0; - location->size = 0; - } + cf->set_location(location, load_address, *count, info->phy_block_size); /* Try to compact list */ *count = disk_compact_blocklist(*list, *count, info); write_segment_table: @@ -472,6 +467,7 @@ static int add_component_buffer_base(struct install_set *bis, void *buffer, comp_id, menu_idx); struct file_range *comp_reg = get_component_range(bis, comp_id, menu_idx); + struct component_footer *cf = component_footer_by_id(comp_id); struct disk_info *info = &bis->info->base[mirror_id]; struct component_loc *location = &pc->loc; disk_blockptr_t **list = &pc->list; @@ -506,14 +502,9 @@ static int add_component_buffer_base(struct install_set *bis, void *buffer, comp_reg->offset = offset; comp_reg->len = size; } - if (component_type_by_id(comp_id) == COMPONENT_TYPE_LOAD) { - /* Fill in component location */ - location->addr = data.load_address; - location->size = *count * info->phy_block_size; - } else { - location->addr = 0; - location->size = 0; - } + /* Fill in component location */ + cf->set_location(location, data.load_address, *count, + info->phy_block_size); /* Try to compact list */ *count = disk_compact_blocklist(*list, *count, info); write_segment_table: diff --git a/zipl/src/zipl.c b/zipl/src/zipl.c index 21f6eb0a..faf5b118 100644 --- a/zipl/src/zipl.c +++ b/zipl/src/zipl.c @@ -257,57 +257,87 @@ main(int argc, char* argv[]) return abs(rc); } +static void set_location_common(struct component_loc *location, + address_t load_address, + blocknum_t count, + int block_size) +{ + location->addr = load_address; + location->size = count * block_size; +} + +static void set_location_noop(struct component_loc *location, + __attribute__((unused)) address_t load_address, + __attribute__((unused)) blocknum_t count, + __attribute__((unused)) int block_size) +{ + location->addr = 0; + location->size = 0; +} + /** * Program Component Footers */ struct component_footer component_footers[NR_PROGRAM_COMPONENTS] = { [COMPONENT_ID_HEAP_AREA] = { .type = COMPONENT_TYPE_LOAD, - .desc = "heap area" + .desc = "heap area", + .set_location = set_location_common }, [COMPONENT_ID_STACK_AREA] = { .type = COMPONENT_TYPE_LOAD, - .desc = "stack area" + .desc = "stack area", + .set_location = set_location_common }, [COMPONENT_ID_LOADER_SIGNATURE] = { .type = COMPONENT_TYPE_SIGNATURE, - .desc = "loader signature" + .desc = "loader signature", + .set_location = set_location_noop }, [COMPONENT_ID_LOADER] = { .type = COMPONENT_TYPE_LOAD, - .desc = "internal loader" + .desc = "internal loader", + .set_location = set_location_common }, [COMPONENT_ID_PARAMETERS] = { .type = COMPONENT_TYPE_LOAD, - .desc = "parameters" + .desc = "parameters", + .set_location = set_location_common }, [COMPONENT_ID_IMAGE_SIGNATURE] = { .type = COMPONENT_TYPE_SIGNATURE, - .desc = "image signature" + .desc = "image signature", + .set_location = set_location_noop, }, [COMPONENT_ID_KERNEL_IMAGE] = { .type = COMPONENT_TYPE_LOAD, - .desc = "kernel image" + .desc = "kernel image", + .set_location = set_location_common }, [COMPONENT_ID_PARMLINE] = { .type = COMPONENT_TYPE_LOAD, - .desc = "parmline" + .desc = "parmline", + .set_location = set_location_common }, [COMPONENT_ID_RAMDISK_SIGNATURE] = { .type = COMPONENT_TYPE_SIGNATURE, - .desc = "ramdisk signature" + .desc = "ramdisk signature", + .set_location = set_location_noop }, [COMPONENT_ID_RAMDISK] = { .type = COMPONENT_TYPE_LOAD, - .desc = "initial ramdisk" + .desc = "initial ramdisk", + .set_location = set_location_common }, [COMPONENT_ID_ENVBLK] = { .type = COMPONENT_TYPE_LOAD, .desc = "environment blk", - .fs_block_aligned = 1 + .fs_block_aligned = 1, + .set_location = set_location_common }, [COMPONENT_ID_SEGMENT_FILE] = { .type = COMPONENT_TYPE_EXECUTE, - .desc = "segment file" + .desc = "segment file", + .set_location = set_location_noop } };