* [PATCH v2 0/5] pc-bios/s390-ccw: Add "loadparm" and menu for pxelinux.cfg network booting
@ 2025-07-09 8:34 Thomas Huth
2025-07-09 8:34 ` [PATCH v2 1/5] pc-bios/s390-ccw: Allow to select a different pxelinux.cfg entry via loadparm Thomas Huth
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Thomas Huth @ 2025-07-09 8:34 UTC (permalink / raw)
To: qemu-devel, Jared Rossi, Zhuoying Cai
Cc: qemu-s390x, Christian Borntraeger, Eric Farman, Halil Pasic,
Matthew Rosato
Since we're linking the network booting code into the main s390-ccw.img
firmware binary nowadays, we can support the "loadparm" parameter now
quite easily for pxelinux.cfg config files that contain multiple entries,
and also add support for a simple boot menu here.
v2:
- Abort the boot process if loadparm points to an invalid entry instead
of trying to continue with the default entry
Thomas Huth (5):
pc-bios/s390-ccw: Allow to select a different pxelinux.cfg entry via
loadparm
pc-bios/s390-ccw: Allow up to 31 entries for pxelinux.cfg
pc-bios/s390-ccw: Make get_boot_index() from menu.c global
pc-bios/s390-ccw: Add a boot menu for booting via pxelinux.cfg
tests/functional: Add a test for s390x pxelinux.cfg network booting
MAINTAINERS | 1 +
pc-bios/s390-ccw/s390-ccw.h | 1 +
pc-bios/s390-ccw/menu.c | 6 +-
pc-bios/s390-ccw/netmain.c | 66 ++++++++++---
tests/functional/meson.build | 1 +
tests/functional/test_s390x_pxelinux.py | 119 ++++++++++++++++++++++++
6 files changed, 178 insertions(+), 16 deletions(-)
create mode 100755 tests/functional/test_s390x_pxelinux.py
--
2.50.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 1/5] pc-bios/s390-ccw: Allow to select a different pxelinux.cfg entry via loadparm
2025-07-09 8:34 [PATCH v2 0/5] pc-bios/s390-ccw: Add "loadparm" and menu for pxelinux.cfg network booting Thomas Huth
@ 2025-07-09 8:34 ` Thomas Huth
2025-07-09 18:46 ` Jared Rossi
2025-07-09 8:34 ` [PATCH v2 2/5] pc-bios/s390-ccw: Allow up to 31 entries for pxelinux.cfg Thomas Huth
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Thomas Huth @ 2025-07-09 8:34 UTC (permalink / raw)
To: qemu-devel, Jared Rossi, Zhuoying Cai
Cc: qemu-s390x, Christian Borntraeger, Eric Farman, Halil Pasic,
Matthew Rosato
From: Thomas Huth <thuth@redhat.com>
Since we're linking the network booting code into the main firmware
binary nowadays, we can support the "loadparm" parameter now quite
easily for pxelinux.cfg config files that contain multiple entries.
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/netmain.c | 32 ++++++++++++++++++++++++--------
1 file changed, 24 insertions(+), 8 deletions(-)
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
index 719a547ada0..c0aafca22d2 100644
--- a/pc-bios/s390-ccw/netmain.c
+++ b/pc-bios/s390-ccw/netmain.c
@@ -332,6 +332,27 @@ static int load_kernel_with_initrd(filename_ip_t *fn_ip,
return rc;
}
+static int net_select_and_load_kernel(filename_ip_t *fn_ip,
+ int num_ent, int selected,
+ struct pl_cfg_entry *entries)
+{
+ unsigned int loadparm = get_loadparm_index();
+
+ if (num_ent <= 0) {
+ return -1;
+ }
+
+ IPL_assert(loadparm <= num_ent,
+ "loadparm is set to an entry that is not available in the "
+ "pxelinux.cfg file!");
+
+ if (loadparm > 0) {
+ selected = loadparm - 1;
+ }
+
+ return load_kernel_with_initrd(fn_ip, &entries[selected]);
+}
+
#define MAX_PXELINUX_ENTRIES 16
static int net_try_pxelinux_cfg(filename_ip_t *fn_ip)
@@ -343,11 +364,8 @@ static int net_try_pxelinux_cfg(filename_ip_t *fn_ip)
DEFAULT_TFTP_RETRIES,
cfgbuf, sizeof(cfgbuf),
entries, MAX_PXELINUX_ENTRIES, &def_ent);
- if (num_ent > 0) {
- return load_kernel_with_initrd(fn_ip, &entries[def_ent]);
- }
- return -1;
+ return net_select_and_load_kernel(fn_ip, num_ent, def_ent, entries);
}
/**
@@ -433,10 +451,8 @@ static int net_try_direct_tftp_load(filename_ip_t *fn_ip)
num_ent = pxelinux_parse_cfg(cfgbuf, sizeof(cfgbuf), entries,
MAX_PXELINUX_ENTRIES, &def_ent);
- if (num_ent <= 0) {
- return -1;
- }
- return load_kernel_with_initrd(fn_ip, &entries[def_ent]);
+ return net_select_and_load_kernel(fn_ip, num_ent, def_ent,
+ entries);
}
}
--
2.50.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 2/5] pc-bios/s390-ccw: Allow up to 31 entries for pxelinux.cfg
2025-07-09 8:34 [PATCH v2 0/5] pc-bios/s390-ccw: Add "loadparm" and menu for pxelinux.cfg network booting Thomas Huth
2025-07-09 8:34 ` [PATCH v2 1/5] pc-bios/s390-ccw: Allow to select a different pxelinux.cfg entry via loadparm Thomas Huth
@ 2025-07-09 8:34 ` Thomas Huth
2025-07-09 18:47 ` Jared Rossi
2025-07-09 8:34 ` [PATCH v2 3/5] pc-bios/s390-ccw: Make get_boot_index() from menu.c global Thomas Huth
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Thomas Huth @ 2025-07-09 8:34 UTC (permalink / raw)
To: qemu-devel, Jared Rossi, Zhuoying Cai
Cc: qemu-s390x, Christian Borntraeger, Eric Farman, Halil Pasic,
Matthew Rosato
From: Thomas Huth <thuth@redhat.com>
We're going to support a menu for the pxelinux.cfg code, and to be able
to reuse some functionality from menu.c, we should align the maximum
amount of possible entries with the MAX_BOOT_ENTRIES constant that is
used there. Thus replace MAX_PXELINUX_ENTRIES with MAX_BOOT_ENTRIES.
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/netmain.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
index c0aafca22d2..6f64323cd84 100644
--- a/pc-bios/s390-ccw/netmain.c
+++ b/pc-bios/s390-ccw/netmain.c
@@ -353,17 +353,15 @@ static int net_select_and_load_kernel(filename_ip_t *fn_ip,
return load_kernel_with_initrd(fn_ip, &entries[selected]);
}
-#define MAX_PXELINUX_ENTRIES 16
-
static int net_try_pxelinux_cfg(filename_ip_t *fn_ip)
{
- struct pl_cfg_entry entries[MAX_PXELINUX_ENTRIES];
+ struct pl_cfg_entry entries[MAX_BOOT_ENTRIES];
int num_ent, def_ent = 0;
num_ent = pxelinux_load_parse_cfg(fn_ip, mac, get_uuid(),
DEFAULT_TFTP_RETRIES,
cfgbuf, sizeof(cfgbuf),
- entries, MAX_PXELINUX_ENTRIES, &def_ent);
+ entries, MAX_BOOT_ENTRIES, &def_ent);
return net_select_and_load_kernel(fn_ip, num_ent, def_ent, entries);
}
@@ -446,11 +444,11 @@ static int net_try_direct_tftp_load(filename_ip_t *fn_ip)
* a magic comment string.
*/
if (!strncasecmp("# pxelinux", cfgbuf, 10)) {
- struct pl_cfg_entry entries[MAX_PXELINUX_ENTRIES];
+ struct pl_cfg_entry entries[MAX_BOOT_ENTRIES];
int num_ent, def_ent = 0;
num_ent = pxelinux_parse_cfg(cfgbuf, sizeof(cfgbuf), entries,
- MAX_PXELINUX_ENTRIES, &def_ent);
+ MAX_BOOT_ENTRIES, &def_ent);
return net_select_and_load_kernel(fn_ip, num_ent, def_ent,
entries);
}
--
2.50.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 3/5] pc-bios/s390-ccw: Make get_boot_index() from menu.c global
2025-07-09 8:34 [PATCH v2 0/5] pc-bios/s390-ccw: Add "loadparm" and menu for pxelinux.cfg network booting Thomas Huth
2025-07-09 8:34 ` [PATCH v2 1/5] pc-bios/s390-ccw: Allow to select a different pxelinux.cfg entry via loadparm Thomas Huth
2025-07-09 8:34 ` [PATCH v2 2/5] pc-bios/s390-ccw: Allow up to 31 entries for pxelinux.cfg Thomas Huth
@ 2025-07-09 8:34 ` Thomas Huth
2025-07-09 18:47 ` Jared Rossi
2025-07-09 8:34 ` [PATCH v2 4/5] pc-bios/s390-ccw: Add a boot menu for booting via pxelinux.cfg Thomas Huth
2025-07-09 8:34 ` [PATCH v2 5/5] tests/functional: Add a test for s390x pxelinux.cfg network booting Thomas Huth
4 siblings, 1 reply; 11+ messages in thread
From: Thomas Huth @ 2025-07-09 8:34 UTC (permalink / raw)
To: qemu-devel, Jared Rossi, Zhuoying Cai
Cc: qemu-s390x, Christian Borntraeger, Eric Farman, Halil Pasic,
Matthew Rosato
From: Thomas Huth <thuth@redhat.com>
We are going to reuse this function for selecting an entry from
the pxelinux.cfg menu, so rename this function with a "menu_"
prefix and make it available globally.
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/s390-ccw.h | 1 +
| 6 +++---
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 6cdce3e5e5b..b1dc35cdedf 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -87,6 +87,7 @@ int menu_get_zipl_boot_index(const char *menu_data);
bool menu_is_enabled_zipl(void);
int menu_get_enum_boot_index(bool *valid_entries);
bool menu_is_enabled_enum(void);
+int menu_get_boot_index(bool *valid_entries);
#define MAX_BOOT_ENTRIES 31
--git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
index 84062e94af4..eeaff78f870 100644
--- a/pc-bios/s390-ccw/menu.c
+++ b/pc-bios/s390-ccw/menu.c
@@ -159,7 +159,7 @@ static void boot_menu_prompt(bool retry)
}
}
-static int get_boot_index(bool *valid_entries)
+int menu_get_boot_index(bool *valid_entries)
{
int boot_index;
bool retry = false;
@@ -224,7 +224,7 @@ int menu_get_zipl_boot_index(const char *menu_data)
}
printf("\n");
- return get_boot_index(valid_entries);
+ return menu_get_boot_index(valid_entries);
}
int menu_get_enum_boot_index(bool *valid_entries)
@@ -247,7 +247,7 @@ int menu_get_enum_boot_index(bool *valid_entries)
}
printf("\n");
- return get_boot_index(valid_entries);
+ return menu_get_boot_index(valid_entries);
}
void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout)
--
2.50.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 4/5] pc-bios/s390-ccw: Add a boot menu for booting via pxelinux.cfg
2025-07-09 8:34 [PATCH v2 0/5] pc-bios/s390-ccw: Add "loadparm" and menu for pxelinux.cfg network booting Thomas Huth
` (2 preceding siblings ...)
2025-07-09 8:34 ` [PATCH v2 3/5] pc-bios/s390-ccw: Make get_boot_index() from menu.c global Thomas Huth
@ 2025-07-09 8:34 ` Thomas Huth
2025-07-09 18:48 ` Jared Rossi
2025-07-09 8:34 ` [PATCH v2 5/5] tests/functional: Add a test for s390x pxelinux.cfg network booting Thomas Huth
4 siblings, 1 reply; 11+ messages in thread
From: Thomas Huth @ 2025-07-09 8:34 UTC (permalink / raw)
To: qemu-devel, Jared Rossi, Zhuoying Cai
Cc: qemu-s390x, Christian Borntraeger, Eric Farman, Halil Pasic,
Matthew Rosato
From: Thomas Huth <thuth@redhat.com>
Show a simple boot menu for pxelinux.cfg, too, if the user requested it.
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/netmain.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
index 6f64323cd84..a9521dff416 100644
--- a/pc-bios/s390-ccw/netmain.c
+++ b/pc-bios/s390-ccw/netmain.c
@@ -332,6 +332,28 @@ static int load_kernel_with_initrd(filename_ip_t *fn_ip,
return rc;
}
+static int net_boot_menu(int num_ent, int def_ent,
+ struct pl_cfg_entry *entries)
+{
+ bool valid_entries[MAX_BOOT_ENTRIES] = { false };
+ int idx;
+
+ puts("\ns390-ccw pxelinux.cfg boot menu:\n");
+ printf(" [0] default (%d)\n", def_ent + 1);
+ valid_entries[0] = true;
+
+ for (idx = 1; idx <= num_ent; idx++) {
+ printf(" [%d] %s\n", idx, entries[idx - 1].label);
+ valid_entries[idx] = true;
+ }
+ putchar('\n');
+
+ idx = menu_get_boot_index(valid_entries);
+ putchar('\n');
+
+ return idx;
+}
+
static int net_select_and_load_kernel(filename_ip_t *fn_ip,
int num_ent, int selected,
struct pl_cfg_entry *entries)
@@ -342,6 +364,10 @@ static int net_select_and_load_kernel(filename_ip_t *fn_ip,
return -1;
}
+ if (menu_is_enabled_enum() && num_ent > 1) {
+ loadparm = net_boot_menu(num_ent, selected, entries);
+ }
+
IPL_assert(loadparm <= num_ent,
"loadparm is set to an entry that is not available in the "
"pxelinux.cfg file!");
--
2.50.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 5/5] tests/functional: Add a test for s390x pxelinux.cfg network booting
2025-07-09 8:34 [PATCH v2 0/5] pc-bios/s390-ccw: Add "loadparm" and menu for pxelinux.cfg network booting Thomas Huth
` (3 preceding siblings ...)
2025-07-09 8:34 ` [PATCH v2 4/5] pc-bios/s390-ccw: Add a boot menu for booting via pxelinux.cfg Thomas Huth
@ 2025-07-09 8:34 ` Thomas Huth
2025-07-09 18:48 ` Jared Rossi
4 siblings, 1 reply; 11+ messages in thread
From: Thomas Huth @ 2025-07-09 8:34 UTC (permalink / raw)
To: qemu-devel, Jared Rossi, Zhuoying Cai
Cc: qemu-s390x, Christian Borntraeger, Eric Farman, Halil Pasic,
Matthew Rosato
From: Thomas Huth <thuth@redhat.com>
Check the various ways of booting a kernel via pxelinux.cfg file,
e.g. by specifying the config file name via the MAC address or the
UUID of the guest. Also check whether we can successfully load an
alternate kernel via the "loadparm" parameter here and whether the
boot menu shows up with "-boot menu=on".
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
MAINTAINERS | 1 +
tests/functional/meson.build | 1 +
tests/functional/test_s390x_pxelinux.py | 119 ++++++++++++++++++++++++
3 files changed, 121 insertions(+)
create mode 100755 tests/functional/test_s390x_pxelinux.py
diff --git a/MAINTAINERS b/MAINTAINERS
index 1842c3dd83f..e88ed2c0a97 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1805,6 +1805,7 @@ F: hw/s390x/ipl.*
F: pc-bios/s390-ccw/
F: pc-bios/s390-ccw.img
F: docs/devel/s390-dasd-ipl.rst
+F: tests/functional/test_s390x_pxelinux.py
T: git https://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org
diff --git a/tests/functional/meson.build b/tests/functional/meson.build
index 050c9000b95..1ae5f02fb37 100644
--- a/tests/functional/meson.build
+++ b/tests/functional/meson.build
@@ -281,6 +281,7 @@ tests_rx_system_thorough = [
tests_s390x_system_thorough = [
's390x_ccw_virtio',
+ 's390x_pxelinux',
's390x_replay',
's390x_topology',
's390x_tuxrun',
diff --git a/tests/functional/test_s390x_pxelinux.py b/tests/functional/test_s390x_pxelinux.py
new file mode 100755
index 00000000000..4fc33b8c46d
--- /dev/null
+++ b/tests/functional/test_s390x_pxelinux.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Functional test that checks the pxelinux.cfg network booting of a s390x VM
+# (TFTP booting without config file is already tested by the pxe qtest, so
+# we don't repeat that here).
+
+import os
+import shutil
+
+from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern
+
+
+pxelinux_cfg_contents='''# pxelinux.cfg style config file
+default Debian
+label Nonexisting
+kernel kernel.notavailable
+initrd initrd.notavailable
+label Debian
+kernel kernel.debian
+initrd initrd.debian
+append testoption=teststring
+label Fedora
+kernel kernel.fedora
+'''
+
+class S390PxeLinux(QemuSystemTest):
+
+ ASSET_DEBIAN_KERNEL = Asset(
+ ('https://snapshot.debian.org/archive/debian/'
+ '20201126T092837Z/dists/buster/main/installer-s390x/'
+ '20190702+deb10u6/images/generic/kernel.debian'),
+ 'd411d17c39ae7ad38d27534376cbe88b68b403c325739364122c2e6f1537e818')
+
+ ASSET_DEBIAN_INITRD = Asset(
+ ('https://snapshot.debian.org/archive/debian/'
+ '20201126T092837Z/dists/buster/main/installer-s390x/'
+ '20190702+deb10u6/images/generic/initrd.debian'),
+ '836bbd0fe6a5ca81274c28c2b063ea315ce1868660866e9b60180c575fef9fd5')
+
+ ASSET_FEDORA_KERNEL = Asset(
+ ('https://archives.fedoraproject.org/pub/archive'
+ '/fedora-secondary/releases/31/Server/s390x/os'
+ '/images/kernel.img'),
+ '480859574f3f44caa6cd35c62d70e1ac0609134e22ce2a954bbed9b110c06e0b')
+
+ def pxelinux_launch(self, pl_name='default', extra_opts=None):
+ self.require_netdev('user')
+ self.set_machine('s390-ccw-virtio')
+
+ debian_kernel = self.ASSET_DEBIAN_KERNEL.fetch()
+ debian_initrd = self.ASSET_DEBIAN_INITRD.fetch()
+ fedora_kernel = self.ASSET_FEDORA_KERNEL.fetch()
+
+ # Prepare a folder for the TFTP "server":
+ tftpdir = self.scratch_file('tftp')
+ shutil.rmtree(tftpdir, ignore_errors=True) # Remove stale stuff
+ os.mkdir(tftpdir)
+ shutil.copy(debian_kernel, os.path.join(tftpdir, 'kernel.debian'))
+ shutil.copy(debian_initrd, os.path.join(tftpdir, 'initrd.debian'))
+ shutil.copy(fedora_kernel, os.path.join(tftpdir, 'kernel.fedora'))
+
+ pxelinuxdir = self.scratch_file('tftp', 'pxelinux.cfg')
+ os.mkdir(pxelinuxdir)
+
+ cfg_fname = self.scratch_file('tftp', 'pxelinux.cfg', pl_name)
+ with open(cfg_fname, 'w', encoding='utf-8') as f:
+ f.write(pxelinux_cfg_contents)
+
+ virtio_net_dev = 'virtio-net-ccw,netdev=n1,bootindex=1'
+ if extra_opts:
+ virtio_net_dev += ',' + extra_opts
+
+ self.vm.add_args('-m', '384',
+ '-netdev', f'user,id=n1,tftp={tftpdir}',
+ '-device', virtio_net_dev)
+ self.vm.set_console()
+ self.vm.launch()
+
+
+ def test_default(self):
+ self.pxelinux_launch()
+ # The kernel prints its arguments to the console, so we can use
+ # this to check whether the kernel parameters are correctly handled:
+ wait_for_console_pattern(self, 'testoption=teststring')
+ # Now also check that we've successfully loaded the initrd:
+ wait_for_console_pattern(self, 'Unpacking initramfs...')
+ wait_for_console_pattern(self, 'Run /init as init process')
+
+ def test_mac(self):
+ self.pxelinux_launch(pl_name='01-02-ca-fe-ba-be-42',
+ extra_opts='mac=02:ca:fe:ba:be:42,loadparm=3')
+ wait_for_console_pattern(self, 'Linux version 5.3.7-301.fc31.s390x')
+
+ def test_uuid(self):
+ # Also add a non-bootable disk to check the fallback to network boot:
+ self.vm.add_args('-blockdev', 'null-co,size=65536,node-name=d1',
+ '-device', 'virtio-blk,drive=d1,bootindex=0,loadparm=1',
+ '-uuid', '550e8400-e29b-11d4-a716-446655441234')
+ self.pxelinux_launch(pl_name='550e8400-e29b-11d4-a716-446655441234')
+ wait_for_console_pattern(self, 'Debian 4.19.146-1 (2020-09-17)')
+
+ def test_ip(self):
+ self.vm.add_args('-M', 'loadparm=3')
+ self.pxelinux_launch(pl_name='0A00020F')
+ wait_for_console_pattern(self, 'Linux version 5.3.7-301.fc31.s390x')
+
+ def test_menu(self):
+ self.vm.add_args('-boot', 'menu=on,splash-time=10')
+ self.pxelinux_launch(pl_name='0A00')
+ wait_for_console_pattern(self, '[1] Nonexisting')
+ wait_for_console_pattern(self, '[2] Debian')
+ wait_for_console_pattern(self, '[3] Fedora')
+ wait_for_console_pattern(self, 'Debian 4.19.146-1 (2020-09-17)')
+
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
--
2.50.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 1/5] pc-bios/s390-ccw: Allow to select a different pxelinux.cfg entry via loadparm
2025-07-09 8:34 ` [PATCH v2 1/5] pc-bios/s390-ccw: Allow to select a different pxelinux.cfg entry via loadparm Thomas Huth
@ 2025-07-09 18:46 ` Jared Rossi
0 siblings, 0 replies; 11+ messages in thread
From: Jared Rossi @ 2025-07-09 18:46 UTC (permalink / raw)
To: Thomas Huth, qemu-devel, Zhuoying Cai
Cc: qemu-s390x, Christian Borntraeger, Eric Farman, Halil Pasic,
Matthew Rosato
Reviewed-by: Jared Rossi <jrossi@linux.ibm.com>
On 7/9/25 4:34 AM, Thomas Huth wrote:
> From: Thomas Huth <thuth@redhat.com>
>
> Since we're linking the network booting code into the main firmware
> binary nowadays, we can support the "loadparm" parameter now quite
> easily for pxelinux.cfg config files that contain multiple entries.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
> pc-bios/s390-ccw/netmain.c | 32 ++++++++++++++++++++++++--------
> 1 file changed, 24 insertions(+), 8 deletions(-)
>
> diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
> index 719a547ada0..c0aafca22d2 100644
> --- a/pc-bios/s390-ccw/netmain.c
> +++ b/pc-bios/s390-ccw/netmain.c
> @@ -332,6 +332,27 @@ static int load_kernel_with_initrd(filename_ip_t *fn_ip,
> return rc;
> }
>
> +static int net_select_and_load_kernel(filename_ip_t *fn_ip,
> + int num_ent, int selected,
> + struct pl_cfg_entry *entries)
> +{
> + unsigned int loadparm = get_loadparm_index();
> +
> + if (num_ent <= 0) {
> + return -1;
> + }
> +
> + IPL_assert(loadparm <= num_ent,
> + "loadparm is set to an entry that is not available in the "
> + "pxelinux.cfg file!");
> +
> + if (loadparm > 0) {
> + selected = loadparm - 1;
> + }
> +
> + return load_kernel_with_initrd(fn_ip, &entries[selected]);
> +}
> +
> #define MAX_PXELINUX_ENTRIES 16
>
> static int net_try_pxelinux_cfg(filename_ip_t *fn_ip)
> @@ -343,11 +364,8 @@ static int net_try_pxelinux_cfg(filename_ip_t *fn_ip)
> DEFAULT_TFTP_RETRIES,
> cfgbuf, sizeof(cfgbuf),
> entries, MAX_PXELINUX_ENTRIES, &def_ent);
> - if (num_ent > 0) {
> - return load_kernel_with_initrd(fn_ip, &entries[def_ent]);
> - }
>
> - return -1;
> + return net_select_and_load_kernel(fn_ip, num_ent, def_ent, entries);
> }
>
> /**
> @@ -433,10 +451,8 @@ static int net_try_direct_tftp_load(filename_ip_t *fn_ip)
>
> num_ent = pxelinux_parse_cfg(cfgbuf, sizeof(cfgbuf), entries,
> MAX_PXELINUX_ENTRIES, &def_ent);
> - if (num_ent <= 0) {
> - return -1;
> - }
> - return load_kernel_with_initrd(fn_ip, &entries[def_ent]);
> + return net_select_and_load_kernel(fn_ip, num_ent, def_ent,
> + entries);
> }
> }
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 2/5] pc-bios/s390-ccw: Allow up to 31 entries for pxelinux.cfg
2025-07-09 8:34 ` [PATCH v2 2/5] pc-bios/s390-ccw: Allow up to 31 entries for pxelinux.cfg Thomas Huth
@ 2025-07-09 18:47 ` Jared Rossi
0 siblings, 0 replies; 11+ messages in thread
From: Jared Rossi @ 2025-07-09 18:47 UTC (permalink / raw)
To: Thomas Huth, qemu-devel, Zhuoying Cai
Cc: qemu-s390x, Christian Borntraeger, Eric Farman, Halil Pasic,
Matthew Rosato
Reviewed-by: Jared Rossi <jrossi@linux.ibm.com>
On 7/9/25 4:34 AM, Thomas Huth wrote:
> From: Thomas Huth <thuth@redhat.com>
>
> We're going to support a menu for the pxelinux.cfg code, and to be able
> to reuse some functionality from menu.c, we should align the maximum
> amount of possible entries with the MAX_BOOT_ENTRIES constant that is
> used there. Thus replace MAX_PXELINUX_ENTRIES with MAX_BOOT_ENTRIES.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
> pc-bios/s390-ccw/netmain.c | 10 ++++------
> 1 file changed, 4 insertions(+), 6 deletions(-)
>
> diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
> index c0aafca22d2..6f64323cd84 100644
> --- a/pc-bios/s390-ccw/netmain.c
> +++ b/pc-bios/s390-ccw/netmain.c
> @@ -353,17 +353,15 @@ static int net_select_and_load_kernel(filename_ip_t *fn_ip,
> return load_kernel_with_initrd(fn_ip, &entries[selected]);
> }
>
> -#define MAX_PXELINUX_ENTRIES 16
> -
> static int net_try_pxelinux_cfg(filename_ip_t *fn_ip)
> {
> - struct pl_cfg_entry entries[MAX_PXELINUX_ENTRIES];
> + struct pl_cfg_entry entries[MAX_BOOT_ENTRIES];
> int num_ent, def_ent = 0;
>
> num_ent = pxelinux_load_parse_cfg(fn_ip, mac, get_uuid(),
> DEFAULT_TFTP_RETRIES,
> cfgbuf, sizeof(cfgbuf),
> - entries, MAX_PXELINUX_ENTRIES, &def_ent);
> + entries, MAX_BOOT_ENTRIES, &def_ent);
>
> return net_select_and_load_kernel(fn_ip, num_ent, def_ent, entries);
> }
> @@ -446,11 +444,11 @@ static int net_try_direct_tftp_load(filename_ip_t *fn_ip)
> * a magic comment string.
> */
> if (!strncasecmp("# pxelinux", cfgbuf, 10)) {
> - struct pl_cfg_entry entries[MAX_PXELINUX_ENTRIES];
> + struct pl_cfg_entry entries[MAX_BOOT_ENTRIES];
> int num_ent, def_ent = 0;
>
> num_ent = pxelinux_parse_cfg(cfgbuf, sizeof(cfgbuf), entries,
> - MAX_PXELINUX_ENTRIES, &def_ent);
> + MAX_BOOT_ENTRIES, &def_ent);
> return net_select_and_load_kernel(fn_ip, num_ent, def_ent,
> entries);
> }
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 3/5] pc-bios/s390-ccw: Make get_boot_index() from menu.c global
2025-07-09 8:34 ` [PATCH v2 3/5] pc-bios/s390-ccw: Make get_boot_index() from menu.c global Thomas Huth
@ 2025-07-09 18:47 ` Jared Rossi
0 siblings, 0 replies; 11+ messages in thread
From: Jared Rossi @ 2025-07-09 18:47 UTC (permalink / raw)
To: Thomas Huth, qemu-devel, Zhuoying Cai
Cc: qemu-s390x, Christian Borntraeger, Eric Farman, Halil Pasic,
Matthew Rosato
Reviewed-by: Jared Rossi <jrossi@linux.ibm.com>
On 7/9/25 4:34 AM, Thomas Huth wrote:
> From: Thomas Huth <thuth@redhat.com>
>
> We are going to reuse this function for selecting an entry from
> the pxelinux.cfg menu, so rename this function with a "menu_"
> prefix and make it available globally.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
> pc-bios/s390-ccw/s390-ccw.h | 1 +
> pc-bios/s390-ccw/menu.c | 6 +++---
> 2 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
> index 6cdce3e5e5b..b1dc35cdedf 100644
> --- a/pc-bios/s390-ccw/s390-ccw.h
> +++ b/pc-bios/s390-ccw/s390-ccw.h
> @@ -87,6 +87,7 @@ int menu_get_zipl_boot_index(const char *menu_data);
> bool menu_is_enabled_zipl(void);
> int menu_get_enum_boot_index(bool *valid_entries);
> bool menu_is_enabled_enum(void);
> +int menu_get_boot_index(bool *valid_entries);
>
> #define MAX_BOOT_ENTRIES 31
>
> diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
> index 84062e94af4..eeaff78f870 100644
> --- a/pc-bios/s390-ccw/menu.c
> +++ b/pc-bios/s390-ccw/menu.c
> @@ -159,7 +159,7 @@ static void boot_menu_prompt(bool retry)
> }
> }
>
> -static int get_boot_index(bool *valid_entries)
> +int menu_get_boot_index(bool *valid_entries)
> {
> int boot_index;
> bool retry = false;
> @@ -224,7 +224,7 @@ int menu_get_zipl_boot_index(const char *menu_data)
> }
>
> printf("\n");
> - return get_boot_index(valid_entries);
> + return menu_get_boot_index(valid_entries);
> }
>
> int menu_get_enum_boot_index(bool *valid_entries)
> @@ -247,7 +247,7 @@ int menu_get_enum_boot_index(bool *valid_entries)
> }
>
> printf("\n");
> - return get_boot_index(valid_entries);
> + return menu_get_boot_index(valid_entries);
> }
>
> void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout)
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 4/5] pc-bios/s390-ccw: Add a boot menu for booting via pxelinux.cfg
2025-07-09 8:34 ` [PATCH v2 4/5] pc-bios/s390-ccw: Add a boot menu for booting via pxelinux.cfg Thomas Huth
@ 2025-07-09 18:48 ` Jared Rossi
0 siblings, 0 replies; 11+ messages in thread
From: Jared Rossi @ 2025-07-09 18:48 UTC (permalink / raw)
To: Thomas Huth, qemu-devel, Zhuoying Cai
Cc: qemu-s390x, Christian Borntraeger, Eric Farman, Halil Pasic,
Matthew Rosato
Reviewed-by: Jared Rossi <jrossi@linux.ibm.com>
On 7/9/25 4:34 AM, Thomas Huth wrote:
> From: Thomas Huth <thuth@redhat.com>
>
> Show a simple boot menu for pxelinux.cfg, too, if the user requested it.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
> pc-bios/s390-ccw/netmain.c | 26 ++++++++++++++++++++++++++
> 1 file changed, 26 insertions(+)
>
> diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
> index 6f64323cd84..a9521dff416 100644
> --- a/pc-bios/s390-ccw/netmain.c
> +++ b/pc-bios/s390-ccw/netmain.c
> @@ -332,6 +332,28 @@ static int load_kernel_with_initrd(filename_ip_t *fn_ip,
> return rc;
> }
>
> +static int net_boot_menu(int num_ent, int def_ent,
> + struct pl_cfg_entry *entries)
> +{
> + bool valid_entries[MAX_BOOT_ENTRIES] = { false };
> + int idx;
> +
> + puts("\ns390-ccw pxelinux.cfg boot menu:\n");
> + printf(" [0] default (%d)\n", def_ent + 1);
> + valid_entries[0] = true;
> +
> + for (idx = 1; idx <= num_ent; idx++) {
> + printf(" [%d] %s\n", idx, entries[idx - 1].label);
> + valid_entries[idx] = true;
> + }
> + putchar('\n');
> +
> + idx = menu_get_boot_index(valid_entries);
> + putchar('\n');
> +
> + return idx;
> +}
> +
> static int net_select_and_load_kernel(filename_ip_t *fn_ip,
> int num_ent, int selected,
> struct pl_cfg_entry *entries)
> @@ -342,6 +364,10 @@ static int net_select_and_load_kernel(filename_ip_t *fn_ip,
> return -1;
> }
>
> + if (menu_is_enabled_enum() && num_ent > 1) {
> + loadparm = net_boot_menu(num_ent, selected, entries);
> + }
> +
> IPL_assert(loadparm <= num_ent,
> "loadparm is set to an entry that is not available in the "
> "pxelinux.cfg file!");
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 5/5] tests/functional: Add a test for s390x pxelinux.cfg network booting
2025-07-09 8:34 ` [PATCH v2 5/5] tests/functional: Add a test for s390x pxelinux.cfg network booting Thomas Huth
@ 2025-07-09 18:48 ` Jared Rossi
0 siblings, 0 replies; 11+ messages in thread
From: Jared Rossi @ 2025-07-09 18:48 UTC (permalink / raw)
To: Thomas Huth, qemu-devel, Zhuoying Cai
Cc: qemu-s390x, Christian Borntraeger, Eric Farman, Halil Pasic,
Matthew Rosato
Reviewed-by: Jared Rossi <jrossi@linux.ibm.com>
On 7/9/25 4:34 AM, Thomas Huth wrote:
> From: Thomas Huth <thuth@redhat.com>
>
> Check the various ways of booting a kernel via pxelinux.cfg file,
> e.g. by specifying the config file name via the MAC address or the
> UUID of the guest. Also check whether we can successfully load an
> alternate kernel via the "loadparm" parameter here and whether the
> boot menu shows up with "-boot menu=on".
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
> MAINTAINERS | 1 +
> tests/functional/meson.build | 1 +
> tests/functional/test_s390x_pxelinux.py | 119 ++++++++++++++++++++++++
> 3 files changed, 121 insertions(+)
> create mode 100755 tests/functional/test_s390x_pxelinux.py
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1842c3dd83f..e88ed2c0a97 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1805,6 +1805,7 @@ F: hw/s390x/ipl.*
> F: pc-bios/s390-ccw/
> F: pc-bios/s390-ccw.img
> F: docs/devel/s390-dasd-ipl.rst
> +F: tests/functional/test_s390x_pxelinux.py
> T: git https://github.com/borntraeger/qemu.git s390-next
> L: qemu-s390x@nongnu.org
>
> diff --git a/tests/functional/meson.build b/tests/functional/meson.build
> index 050c9000b95..1ae5f02fb37 100644
> --- a/tests/functional/meson.build
> +++ b/tests/functional/meson.build
> @@ -281,6 +281,7 @@ tests_rx_system_thorough = [
>
> tests_s390x_system_thorough = [
> 's390x_ccw_virtio',
> + 's390x_pxelinux',
> 's390x_replay',
> 's390x_topology',
> 's390x_tuxrun',
> diff --git a/tests/functional/test_s390x_pxelinux.py b/tests/functional/test_s390x_pxelinux.py
> new file mode 100755
> index 00000000000..4fc33b8c46d
> --- /dev/null
> +++ b/tests/functional/test_s390x_pxelinux.py
> @@ -0,0 +1,119 @@
> +#!/usr/bin/env python3
> +#
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +#
> +# Functional test that checks the pxelinux.cfg network booting of a s390x VM
> +# (TFTP booting without config file is already tested by the pxe qtest, so
> +# we don't repeat that here).
> +
> +import os
> +import shutil
> +
> +from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern
> +
> +
> +pxelinux_cfg_contents='''# pxelinux.cfg style config file
> +default Debian
> +label Nonexisting
> +kernel kernel.notavailable
> +initrd initrd.notavailable
> +label Debian
> +kernel kernel.debian
> +initrd initrd.debian
> +append testoption=teststring
> +label Fedora
> +kernel kernel.fedora
> +'''
> +
> +class S390PxeLinux(QemuSystemTest):
> +
> + ASSET_DEBIAN_KERNEL = Asset(
> + ('https://snapshot.debian.org/archive/debian/'
> + '20201126T092837Z/dists/buster/main/installer-s390x/'
> + '20190702+deb10u6/images/generic/kernel.debian'),
> + 'd411d17c39ae7ad38d27534376cbe88b68b403c325739364122c2e6f1537e818')
> +
> + ASSET_DEBIAN_INITRD = Asset(
> + ('https://snapshot.debian.org/archive/debian/'
> + '20201126T092837Z/dists/buster/main/installer-s390x/'
> + '20190702+deb10u6/images/generic/initrd.debian'),
> + '836bbd0fe6a5ca81274c28c2b063ea315ce1868660866e9b60180c575fef9fd5')
> +
> + ASSET_FEDORA_KERNEL = Asset(
> + ('https://archives.fedoraproject.org/pub/archive'
> + '/fedora-secondary/releases/31/Server/s390x/os'
> + '/images/kernel.img'),
> + '480859574f3f44caa6cd35c62d70e1ac0609134e22ce2a954bbed9b110c06e0b')
> +
> + def pxelinux_launch(self, pl_name='default', extra_opts=None):
> + self.require_netdev('user')
> + self.set_machine('s390-ccw-virtio')
> +
> + debian_kernel = self.ASSET_DEBIAN_KERNEL.fetch()
> + debian_initrd = self.ASSET_DEBIAN_INITRD.fetch()
> + fedora_kernel = self.ASSET_FEDORA_KERNEL.fetch()
> +
> + # Prepare a folder for the TFTP "server":
> + tftpdir = self.scratch_file('tftp')
> + shutil.rmtree(tftpdir, ignore_errors=True) # Remove stale stuff
> + os.mkdir(tftpdir)
> + shutil.copy(debian_kernel, os.path.join(tftpdir, 'kernel.debian'))
> + shutil.copy(debian_initrd, os.path.join(tftpdir, 'initrd.debian'))
> + shutil.copy(fedora_kernel, os.path.join(tftpdir, 'kernel.fedora'))
> +
> + pxelinuxdir = self.scratch_file('tftp', 'pxelinux.cfg')
> + os.mkdir(pxelinuxdir)
> +
> + cfg_fname = self.scratch_file('tftp', 'pxelinux.cfg', pl_name)
> + with open(cfg_fname, 'w', encoding='utf-8') as f:
> + f.write(pxelinux_cfg_contents)
> +
> + virtio_net_dev = 'virtio-net-ccw,netdev=n1,bootindex=1'
> + if extra_opts:
> + virtio_net_dev += ',' + extra_opts
> +
> + self.vm.add_args('-m', '384',
> + '-netdev', f'user,id=n1,tftp={tftpdir}',
> + '-device', virtio_net_dev)
> + self.vm.set_console()
> + self.vm.launch()
> +
> +
> + def test_default(self):
> + self.pxelinux_launch()
> + # The kernel prints its arguments to the console, so we can use
> + # this to check whether the kernel parameters are correctly handled:
> + wait_for_console_pattern(self, 'testoption=teststring')
> + # Now also check that we've successfully loaded the initrd:
> + wait_for_console_pattern(self, 'Unpacking initramfs...')
> + wait_for_console_pattern(self, 'Run /init as init process')
> +
> + def test_mac(self):
> + self.pxelinux_launch(pl_name='01-02-ca-fe-ba-be-42',
> + extra_opts='mac=02:ca:fe:ba:be:42,loadparm=3')
> + wait_for_console_pattern(self, 'Linux version 5.3.7-301.fc31.s390x')
> +
> + def test_uuid(self):
> + # Also add a non-bootable disk to check the fallback to network boot:
> + self.vm.add_args('-blockdev', 'null-co,size=65536,node-name=d1',
> + '-device', 'virtio-blk,drive=d1,bootindex=0,loadparm=1',
> + '-uuid', '550e8400-e29b-11d4-a716-446655441234')
> + self.pxelinux_launch(pl_name='550e8400-e29b-11d4-a716-446655441234')
> + wait_for_console_pattern(self, 'Debian 4.19.146-1 (2020-09-17)')
> +
> + def test_ip(self):
> + self.vm.add_args('-M', 'loadparm=3')
> + self.pxelinux_launch(pl_name='0A00020F')
> + wait_for_console_pattern(self, 'Linux version 5.3.7-301.fc31.s390x')
> +
> + def test_menu(self):
> + self.vm.add_args('-boot', 'menu=on,splash-time=10')
> + self.pxelinux_launch(pl_name='0A00')
> + wait_for_console_pattern(self, '[1] Nonexisting')
> + wait_for_console_pattern(self, '[2] Debian')
> + wait_for_console_pattern(self, '[3] Fedora')
> + wait_for_console_pattern(self, 'Debian 4.19.146-1 (2020-09-17)')
> +
> +
> +if __name__ == '__main__':
> + QemuSystemTest.main()
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-07-09 18:51 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-09 8:34 [PATCH v2 0/5] pc-bios/s390-ccw: Add "loadparm" and menu for pxelinux.cfg network booting Thomas Huth
2025-07-09 8:34 ` [PATCH v2 1/5] pc-bios/s390-ccw: Allow to select a different pxelinux.cfg entry via loadparm Thomas Huth
2025-07-09 18:46 ` Jared Rossi
2025-07-09 8:34 ` [PATCH v2 2/5] pc-bios/s390-ccw: Allow up to 31 entries for pxelinux.cfg Thomas Huth
2025-07-09 18:47 ` Jared Rossi
2025-07-09 8:34 ` [PATCH v2 3/5] pc-bios/s390-ccw: Make get_boot_index() from menu.c global Thomas Huth
2025-07-09 18:47 ` Jared Rossi
2025-07-09 8:34 ` [PATCH v2 4/5] pc-bios/s390-ccw: Add a boot menu for booting via pxelinux.cfg Thomas Huth
2025-07-09 18:48 ` Jared Rossi
2025-07-09 8:34 ` [PATCH v2 5/5] tests/functional: Add a test for s390x pxelinux.cfg network booting Thomas Huth
2025-07-09 18:48 ` Jared Rossi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).