@samitouri / QOSamiQemu / commits / 3289d6db95

hw/s390x/ipl: Rework s390_ipl_map_iplb_chain for certificate storage

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 <zycai@linux.ibm.com> Reviewed-by: Eric Farman <farman@linux.ibm.com> Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com> Link: https://lore.kernel.org/qemu-devel/20260730214624.2328883-19-zycai@linux.ibm.com Signed-off-by: Eric Farman <farman@linux.ibm.com>

Zhuoying Cai committed Jul 30, 2026 at 17:46 UTC 3289d6db95edc408cfeaab33de4cc41a9d7423be
4 files changed +20 -9
hw/s390x/ipl.c
+14 -4
@@ -426,10 +426,9 @@ static S390PCIBusDevice *s390_get_pci_device(DeviceState *dev_st, int *devtype)
426 return pbdev;
427 }
428
429 -static uint64_t s390_ipl_map_iplb_chain(IplParameterBlock *iplb_chain)
429 +static uint64_t s390_ipl_map_iplb_chain(IplParameterBlock *iplb_chain, uint16_t count)
430 {
431 S390IPLState *ipl = get_ipl_device();
432 - uint16_t count = be16_to_cpu(ipl->qipl.chain_len);
432 uint64_t len = sizeof(IplParameterBlock) * count;
433 uint64_t chain_addr = find_iplb_chain_addr(ipl->bios_start_addr, count);
434
@@ -593,7 +592,7 @@ void s390_rebuild_iplb(uint16_t dev_index, IplParameterBlock *iplb)
592 static bool s390_init_all_iplbs(S390IPLState *ipl)
593 {
594 int iplb_num = 0;
596 - IplParameterBlock iplb_chain[7];
595 + IplParameterBlock iplb_chain[MAX_BOOT_DEVS - 1] = { 0 };
596 DeviceState *dev_st = get_boot_device(0);
597 Object *machine = qdev_get_machine();
598
@@ -639,13 +638,24 @@ static bool s390_init_all_iplbs(S390IPLState *ipl)
638 dev_st = get_boot_device(i);
639 s390_build_iplb(dev_st, &iplb_chain[i - 1]);
640 }
641 + }
642
643 - ipl->qipl.next_iplb = cpu_to_be64(s390_ipl_map_iplb_chain(iplb_chain));
643 + /*
644 + * Allocate maximum space for IPLB chain and/or certificate storage.
645 + * Once a valid boot device is found, this space will be used to store
646 + * certificates if secure boot is enabled.
647 + */
648 + if (iplb_num > 1 || s390_has_certificate()) {
649 + ipl->qipl.ipl_data = cpu_to_be64(s390_ipl_map_iplb_chain(iplb_chain,
650 + MAX_BOOT_DEVS - 1));
651 }
652
653 return iplb_num;
654 }
655
656 +QEMU_BUILD_BUG_MSG(sizeof(IplParameterBlock) * (MAX_BOOT_DEVS - 1) != CERT_BUF_SIZE,
657 + "certificate buffer size is wrong");
658 +
659 static void update_machine_ipl_properties(IplParameterBlock *iplb)
660 {
661 Object *machine = qdev_get_machine();
hw/s390x/ipl.h
-2
@@ -23,8 +23,6 @@
23 #include "qom/object.h"
24 #include "target/s390x/kvm/pv.h"
25
26 -#define MAX_BOOT_DEVS 8 /* Max number of devices that may have a bootindex */
27 -
26 void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp);
27 void s390_ipl_fmt_loadparm(uint8_t *loadparm, char *str, Error **errp);
28 void s390_rebuild_iplb(uint16_t index, IplParameterBlock *iplb);
include/hw/s390x/ipl/qipl.h
+4 -1
@@ -43,7 +43,10 @@ typedef enum S390IplType S390IplType;
43 #define S390_IPLB_MIN_QEMU_SCSI_LEN 200
44 #define S390_IPLB_MAX_LEN 4096
45
46 +#define MAX_BOOT_DEVS 8 /* Max number of devices that may have a bootindex */
47 +
48 #define MAX_CERTIFICATES 64
49 +#define CERT_BUF_SIZE ((MAX_BOOT_DEVS - 1) * 4096)
50 /* largest supported block size - same as VIRTIO_DASD_DEFAULT_BLOCK_SIZE */
51 #define VIRTIO_MAX_BLOCK_SIZE 4096
52 #define MAX_COMP_ENTRIES ((VIRTIO_MAX_BLOCK_SIZE - 32) / 32)
@@ -63,7 +66,7 @@ struct QemuIplParameters {
66 uint32_t boot_menu_timeout;
67 uint8_t reserved3[2];
68 uint16_t chain_len;
66 - uint64_t next_iplb;
69 + uint64_t ipl_data;
70 } QEMU_PACKED;
71 typedef struct QemuIplParameters QemuIplParameters;
72
pc-bios/s390-ccw/iplb.h
+2 -2
@@ -61,11 +61,11 @@ static inline bool load_next_iplb(void)
61 }
62
63 qipl.index++;
64 - next_iplb = (IplParameterBlock *) qipl.next_iplb;
64 + next_iplb = (IplParameterBlock *) qipl.ipl_data;
65 memcpy(iplb, next_iplb, sizeof(IplParameterBlock));
66
67 qipl.chain_len--;
68 - qipl.next_iplb = qipl.next_iplb + sizeof(IplParameterBlock);
68 + qipl.ipl_data = qipl.ipl_data + sizeof(IplParameterBlock);
69
70 return true;
71 }