Originally created by Tails on #5835 (Redmine)
Rationale and context
The NX bit helps enabling executable space protection. Most 64bits, and some 32bits, x86 CPUs support this.
On Linux, PAE must be enabled to get the NX bit enabled. We cannot blindly enable PAE, as it "causes pre-Pentium Pro (including Pentium MMX) and Celeron M and Pentium M processors without NX support to fail to boot" (Wikipedia.
So we cannot default to use PAE, and should at least provide the non-bigmem one as an alternative choice in the bootloader or wait for non-PAE systems to be rare enough so that we can stop supporting them.
As of 2.6.39, Debian –686 kernels have PAE enabled (reference: Ben’s blog, that’s why we now ship a –486 kernel.
If we don’t want to ship –486 until non-PAE systems die, and forget about NX bit until then, we have to ship both –686-pae and –486, and have the bootloader autodetect the most appropriate one depending on what the kernel supports.
feature/multikernel branch (merged into
- installs two kernels (
- patches the syslinux menu configuration to autoselect best kernel wrt. hardware support, and automatically jump to an arch-specific appropriate sub-menu
- tested on CPUs: 486, amd64, 686 without PAE
- successfully run the Tails USB Installer with a
- given up shipping an amd64 kernel, due to the VirtualBox bugs about guest additions vs. 32-bit userspace + 64-bit kernel :(
- memtest with 686-pae on 4GB RAM and more was tried: worse results than with sdmem (2.5GB of the known pattern found after "wiping" with memtest, vs. 1.5GB when using sdmem), so we’re back to sdmem (54c81c1 reverted)
done in Tails 0.14
module seems to
provide what we need, allowing to do different things for 64-bit
hardware, 32-bit hardware with PAE support and 32-bit hardware without
PAE, like this:
label boot_kernel com32 ifcpu64.c32 append boot_kernel_64 -- boot_kernel_32pae -- boot_kernel_32 label boot_kernel_32 kernel vmlinuz_32 append ... label boot_kernel_32pae kernel vmlinuz_32pae append ... label boot_kernel_64 kernel vmlinuz_64 append ...
Unfortunately, it does not select a default kernel, but boots it right
away. So instead of booting a Linux kernel, we can boot the
vesamenu.c32 module with a different configuration file for each
label select_menu com32 /syslinux/ifcpu64.c32 append menu_amd64 -- menu_686-pae -- menu_486 label menu_amd64 kernel /syslinux/vesamenu.c32 append live_amd64.cfg label menu_686-pae kernel /syslinux/vesamenu.c32 append live_686-pae.cfg label menu_486 kernel /syslinux/vesamenu.c32 append live_486.cfg default select_menu
The HDT (hardware detection tool) syslinux module (homepage, page on syslinux wiki has code that might help supporting this; it’s been shipped in mainline syslinux for a while. On the other hand does not offer any kind of feature that can be used to parameterized the boot menu.
default64 menu keyword
Debian multi-arch installer’s syslinux menu autodetects amd64-compatible
hardware and pre-selects the right default kernel. Seems like it uses
default64 menu keyword (see debian-installer Git repository).
Unfortunately, this solution is not suitable for us because it does not
allow to select a kernel depending on PAE support, and is not part of
Other COM32 modules shipped with syslinux might be better suited for our
specific needs. See especially
ifcpu.c32; according to its source
code, it can "run one command if system match some CPU features, another
if it doesn’t" and is supposed to be used e.g. like this:
label ifcpu com32 ifcpu.c32 append pae -- boot_entry_1 -- boot_entry_2 label boot_entry_1 kernel vmlinuz_entry1 append ... label boot_entry_2 kernel vmlinuz_entry2 append ...
… which would almost suit our needs but only allows two alternatives, while we need three.