On Wed, 2026-07-01 at 16:49 -0400, Zhuoying Cai wrote:
> Rework s390_ipl_map_iplb_chain to always allocate maximum memory for
> the IPLB chain, regardless of the number of boot devices. This space
> is also used to store certificates during secure boot, providing a
> safe location for certificates until the kernel reads them during boot.
>
> Rename next_iplb to ipl_data to better reflect its multiple purposes:
> storing both IPLB chains and certificate data.
>
> Signed-off-by: Zhuoying Cai <[email protected]>
> ---
> hw/s390x/ipl.c | 13 ++++++++++---
> include/hw/s390x/ipl/qipl.h | 2 +-
> pc-bios/s390-ccw/iplb.h | 4 ++--
> 3 files changed, 13 insertions(+), 6 deletions(-)
>
> diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
> index 9cb41511e8..7734b6edc7 100644
> --- a/hw/s390x/ipl.c
> +++ b/hw/s390x/ipl.c
> @@ -425,10 +425,9 @@ static S390PCIBusDevice *s390_get_pci_device(DeviceState
> *dev_st, int *devtype)
> return pbdev;
> }
>
> -static uint64_t s390_ipl_map_iplb_chain(IplParameterBlock *iplb_chain)
> +static uint64_t s390_ipl_map_iplb_chain(IplParameterBlock *iplb_chain,
> uint16_t count)
> {
> S390IPLState *ipl = get_ipl_device();
> - uint16_t count = be16_to_cpu(ipl->qipl.chain_len);
> uint64_t len = sizeof(IplParameterBlock) * count;
> uint64_t chain_addr = find_iplb_chain_addr(ipl->bios_start_addr, count);
>
> @@ -629,8 +628,16 @@ static bool s390_init_all_iplbs(S390IPLState *ipl)
> dev_st = get_boot_device(i);
> s390_build_iplb(dev_st, &iplb_chain[i - 1]);
> }
> + }
>
> - ipl->qipl.next_iplb =
> cpu_to_be64(s390_ipl_map_iplb_chain(iplb_chain));
> + /*
> + * Allocate maximum space for IPLB chain and/or certificate storage.
> + * Once a valid boot device is found, this space will be used to store
> + * certificates if secure boot is enabled.
> + */
> + if (iplb_num > 1 || s390_has_certificate()) {
> + ipl->qipl.ipl_data = cpu_to_be64(s390_ipl_map_iplb_chain(iplb_chain,
> +
> MAX_BOOT_DEVS - 1));
I think iplb_chain needs to be explicitly initialized to zero now that you're
allocating a larger
space. load_next_iplb() is still honoring the length of the count when walking
the IPLBs, but the
above does a memcpy of the whole array.
> }
>
> return iplb_num;
> diff --git a/include/hw/s390x/ipl/qipl.h b/include/hw/s390x/ipl/qipl.h
> index a2180719b1..2b29dfa8c5 100644
> --- a/include/hw/s390x/ipl/qipl.h
> +++ b/include/hw/s390x/ipl/qipl.h
> @@ -61,7 +61,7 @@ struct QemuIplParameters {
> uint32_t boot_menu_timeout;
> uint8_t reserved3[2];
> uint16_t chain_len;
> - uint64_t next_iplb;
> + uint64_t ipl_data;
> } QEMU_PACKED;
> typedef struct QemuIplParameters QemuIplParameters;
>
> diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h
> index c92a3d0f0c..c807e7f49b 100644
> --- a/pc-bios/s390-ccw/iplb.h
> +++ b/pc-bios/s390-ccw/iplb.h
> @@ -61,11 +61,11 @@ static inline bool load_next_iplb(void)
> }
>
> qipl.index++;
> - next_iplb = (IplParameterBlock *) qipl.next_iplb;
> + next_iplb = (IplParameterBlock *) qipl.ipl_data;
> memcpy(iplb, next_iplb, sizeof(IplParameterBlock));
>
> qipl.chain_len--;
> - qipl.next_iplb = qipl.next_iplb + sizeof(IplParameterBlock);
> + qipl.ipl_data = qipl.ipl_data + sizeof(IplParameterBlock);
>
> return true;
> }