0.8.1 x86_64 UEFI menu cannot select items #2

Open
opened 2026-10-02 09:16:11 -04:00 by mmBesar · 1 comment

Environment

  • OpenPXE v0.8.1

  • x86_64 UEFI

  • OpenPXE running in Docker

  • PXE clients tested:

    • QEMU/KVM VM
    • Physical x86_64 laptop
  • Both clients show the same behavior

  • OpenPXE serves snponly.efi

Problem

The OpenPXE iPXE menu is displayed normally and keyboard navigation works:

  • Up / Down
  • Home / End
  • Page Up / Page Down

However, the highlighted item cannot be selected.

  • Enter does not activate the highlighted item.
  • The main menu's x shortcut (item --key x exit) also does not activate Exit.
  • Instead, pressing Enter or x moves the selection back to the default Queued Deployment item.

The same behavior occurs on both the VM and physical laptop.

Reproduction

The generated main menu contains:

menu OpenPXE - network boot menu
item local            Boot from Local HDD
item linux            Linux Installers  >
item tools            Tools  >
item queue            Queued Deployment  (join queue)
item --key x exit    Exit iPXE

choose --default queue --timeout 600000 target || goto menu

The menu renders correctly, but choose never appears to commit the selected item.

Important test

I can interrupt the boot with Ctrl-B and reach:

iPXE>

From there:

chain http://10.10.10.10:8069/boot/_linux_menu.ipxe

successfully opens the Linux installer menu.

I can then directly chain:

chain http://10.10.10.10:8069/boot/debian-13-7-0-amd64-netinst-sanboot.ipxe

and Debian 13 successfully boots into the installer.

This confirms that PXE, TFTP, HTTP scripting, OpenPXE ISO handling, and the generated boot scripts are working.

The problem appears to be specifically with interactive menu selection/input.

Request

Could you check the x86_64 UEFI snponly.efi / bundled iPXE input configuration and menu-selection behavior in v0.8.1?

I can test a patched snponly.efi or development build if useful.

## Environment * OpenPXE **v0.8.1** * x86_64 UEFI * OpenPXE running in Docker * PXE clients tested: * QEMU/KVM VM * Physical x86_64 laptop * Both clients show the same behavior * OpenPXE serves `snponly.efi` ## Problem The OpenPXE iPXE menu is displayed normally and keyboard navigation works: * Up / Down * Home / End * Page Up / Page Down However, **the highlighted item cannot be selected**. * Enter does not activate the highlighted item. * The main menu's `x` shortcut (`item --key x exit`) also does not activate Exit. * Instead, pressing Enter or `x` moves the selection back to the default **Queued Deployment** item. The same behavior occurs on both the VM and physical laptop. ## Reproduction The generated main menu contains: ```ipxe menu OpenPXE - network boot menu item local Boot from Local HDD item linux Linux Installers > item tools Tools > item queue Queued Deployment (join queue) item --key x exit Exit iPXE choose --default queue --timeout 600000 target || goto menu ``` The menu renders correctly, but `choose` never appears to commit the selected item. ## Important test I can interrupt the boot with `Ctrl-B` and reach: ```text iPXE> ``` From there: ```text chain http://10.10.10.10:8069/boot/_linux_menu.ipxe ``` successfully opens the Linux installer menu. I can then directly chain: ```text chain http://10.10.10.10:8069/boot/debian-13-7-0-amd64-netinst-sanboot.ipxe ``` and **Debian 13 successfully boots into the installer**. This confirms that PXE, TFTP, HTTP scripting, OpenPXE ISO handling, and the generated boot scripts are working. The problem appears to be specifically with **interactive menu selection/input**. ## Request Could you check the x86_64 UEFI `snponly.efi` / bundled iPXE input configuration and menu-selection behavior in v0.8.1? I can test a patched `snponly.efi` or development build if useful.
Owner

Thanks for the detailed report — and especially for the Ctrl-B tests. Hand-chaining debian-13-7-0-amd64-netinst-sanboot.ipxe booting fine localised this to the menu scripts rather than the network, HTTP/TFTP or the .efi binaries.

Root cause was in the scripts OpenPXE generates, not in iPXE selection or your firmware. The dispatch lines looked like this:

iseq ${target} local   && chain .../boot/_local.ipxe        || goto menu
iseq ${target} linux   && chain .../boot/_linux_menu.ipxe   || goto menu
...
iseq ${target} exit    && exit                              || goto menu

iPXE evaluates &&/|| strictly left to right (POSIX-shell style, src/core/exec.c system()), so for A && B || C the C branch runs whenever A fails. With A = iseq ${target} <item>, that means every item except the first one skipped its own chain and ran goto menu immediately — redrawing the menu with --default queue highlighted, exactly what you saw. x failed the same way, which is why Exit behaved like Enter. Only local (the first line) was ever reachable.

Fixed on main (commit e80a66b, tagged v0.8.2 — the version bump is in Cargo.toml):

  • dispatch is now the canonical iPXE pattern — goto ${target} || goto menu followed by one :label block per item, so a non-matching item can't fall into a stray goto menu;
  • menu-to-menu transitions use chain --replace (the new menu replaces the old image), so x exits to the firmware from any submenu and Back/forward navigation doesn't pile up nested scripts;
  • boot entries recover to the menu themselves if a kernel/initrd fetch fails (needed once menus --replace);
  • plus a few nearby script bugs of the same class: the arch-label probe ended in || true (true isn't an iPXE command — non-x86_64/UEFI/arm64 pairs would abort before drawing the menu), Utilities→Back redrew Utilities instead of returning to Tools, prompt --timeout aborted NIC Info, and the empty-password check compared against a literal "" token (iPXE has no quoting).

There's a new menu_dispatch_tests suite that runs the generated scripts through a small interpreter mirroring iPXE's system()/process_script() semantics and asserts each item reaches its expected chain URL — the old lines fail it. cargo test --workspace is green.

No firmware rebuild needed — the snponly.efi/ipxe.efi assets are untouched; only the server-generated scripts changed. So a new 0.8.2 image (or a build from main) is enough on the server side.

If you can retest once you're on 0.8.2, that'd be great — particularly Enter on a Linux/Windows submenu item, x from the top menu, and b/Back from a submenu back to the main menu. If anything still misbehaves, the menu/entry script text you get from Ctrl-B chain would pinpoint it.

Thanks for the detailed report — and especially for the Ctrl-B tests. Hand-chaining `debian-13-7-0-amd64-netinst-sanboot.ipxe` booting fine localised this to the menu scripts rather than the network, HTTP/TFTP or the .efi binaries. **Root cause** was in the scripts OpenPXE generates, not in iPXE selection or your firmware. The dispatch lines looked like this: ``` iseq ${target} local && chain .../boot/_local.ipxe || goto menu iseq ${target} linux && chain .../boot/_linux_menu.ipxe || goto menu ... iseq ${target} exit && exit || goto menu ``` iPXE evaluates `&&`/`||` strictly left to right (POSIX-shell style, `src/core/exec.c` `system()`), so for `A && B || C` the `C` branch runs whenever `A` fails. With `A` = `iseq ${target} <item>`, that means every item except the first one skipped its own `chain` and ran `goto menu` immediately — redrawing the menu with `--default queue` highlighted, exactly what you saw. `x` failed the same way, which is why Exit behaved like Enter. Only `local` (the first line) was ever reachable. **Fixed on `main`** (commit `e80a66b`, tagged `v0.8.2` — the version bump is in `Cargo.toml`): - dispatch is now the canonical iPXE pattern — `goto ${target} || goto menu` followed by one `:label` block per item, so a non-matching item can't fall into a stray `goto menu`; - menu-to-menu transitions use `chain --replace` (the new menu replaces the old image), so `x` exits to the firmware from any submenu and Back/forward navigation doesn't pile up nested scripts; - boot entries recover to the menu themselves if a kernel/initrd fetch fails (needed once menus `--replace`); - plus a few nearby script bugs of the same class: the arch-label probe ended in `|| true` (`true` isn't an iPXE command — non-x86_64/UEFI/arm64 pairs would abort before drawing the menu), Utilities→Back redrew Utilities instead of returning to Tools, `prompt --timeout` aborted NIC Info, and the empty-password check compared against a literal `""` token (iPXE has no quoting). There's a new `menu_dispatch_tests` suite that runs the generated scripts through a small interpreter mirroring iPXE's `system()`/`process_script()` semantics and asserts each item reaches its expected chain URL — the old lines fail it. `cargo test --workspace` is green. No firmware rebuild needed — the `snponly.efi`/`ipxe.efi` assets are untouched; only the server-generated scripts changed. So a new `0.8.2` image (or a build from `main`) is enough on the server side. If you can retest once you're on 0.8.2, that'd be great — particularly Enter on a Linux/Windows submenu item, `x` from the top menu, and `b`/Back from a submenu back to the main menu. If anything still misbehaves, the menu/entry script text you get from Ctrl-B `chain` would pinpoint it.
Sign in to join this conversation.
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mward4/OpenPXE#2