[syslinux] fixing debian's hd-media image

Ady Ady ady-sf at hotmail.com
Thu Dec 6 09:26:14 PST 2018


> On Wed, Dec 5, 2018 at 2:21 PM Ady Ady via Syslinux <syslinux at zytor.com> wrote:
> >
> > After some discussion/debugging behind the scenes, we are back on
> > track, with updated Debian packages.
> >
> >
> > 0_ Starting from an _original_ (so-called "hd-media") boot.img mounted
> > in "target" (or "$target", or some similar notation), and the version
> > of Syslinux-related packages in the OS should be
> > "6.04~git20171011.af7e95c3+dfsg1-6" or newer. At the moment I'm writing
> > this, the packages are in Debian "Unstable" (repo).
> >
> > Although not all the packages are essential for this procedure, the
> > Syslinux-related packages I'm referring to are, at least:
> >
> > _ extlinux
> > _ isolinux
> > _ pxelinux
> > _ syslinux
> > _ syslinux-common
> > _ syslinux-efi
> > _ syslinux-utils
> >
> > Note: For each and every step in the following procedure, it is assumed
> > that any (prior) process has finished (successfully) and that relevant
> > files have been saved and closed before continuing to the next step.
> >
> > 1_ Create 'target/boot/syslinux/syslinux.cfg'
> >
> >
> > 2_ Content of 'target/boot/syslinux/syslinux.cfg' (please note that the
> > PATH directive here is followed by a space character, a dot and a slash
> > character; in theory the slash is optional and I choose to use it for
> > directories; the space and the dot are absolutely essential in our
> > setup):
> >
> > # D-I config version 2.0
> > # search path for the c32 support libraries (libcom32, libutil etc.)
> > PATH ./
> > DEFAULT debian
> > PROMPT 0
> > LABEL debian
> > CONFIG ../../debian.cfg ../../
> >
> >
> > 3_ Rename 'target/syslinux.cfg' to 'target/debian.cfg'
> >
> >
> > 4_ Edit content of 'target/debian.cfg' to (only) be:
> >
> > include menu.cfg
> > default vesamenu.c32
> > prompt 0
> > timeout 0
> >
> >
> > 5_ Edit content of 'target/exithelp.cfg' to (only) be:
> >
> > label menu
> >         kernel vesamenu.c32
> >         config debian.cfg
> >
> >
> > 6_ (Possibly you need some special/root rights/permissions for this
> > step) Delete 'target/ldlinux.*' and 'target/*.c32'.
> >
> >
> > 7_ From the 'bios' subdirectory for Syslinux files in your OS
> > (package), copy:
> >  _ vesamenu.c32
> >  _ libcom32.c32
> >  _ libutil.c32
> >
> > to 'target/boot/syslinux/*.c32'.
> >
> >
> > 8_ Install SYSLINUX to the adequate directory (shown below). Since the
> > "device" (boot.img) is currently mounted, I'm using here the 'extlinux'
> > command. Please adapt the command to the pertinent paths / notation /
> > script(s):
> >
> >  extlinux --install $target/boot/syslinux/
> >
> > or
> >
> >  extlinux --install target/boot/syslinux/
> >
> > or similar, depending on the adequate notation (for your script).
> >
> > Alternatively, the installation of SYSLINUX can instead be performed
> > later on, once/when the device is unmounted, by using one of the
> > alternative official installers for SYSLINUX. This alternative is
> > currently _not_ described in this procedure.
> >
> > Note1: "$target" (or "target") is just one way for me to post the
> > command here. Your real path / script / notation might be slightly
> > different (yet, all variants shall include the subdirectory
> > "boot/syslinux"). Please adapt it accordingly.
> >
> > Note2: the last slash character in the above command might cause an
> > error (which might also be "silent") in some (OS') environments whereas
> > it might be a requirement in others; YMMV - reports are appreciated.
> >
> > For more details about several alternative official installers for
> > Syslinux, see:
> >
> >  www.syslinux.org/wiki/index.php/Install
> >
> >
> > 9_ Create 'target/EFI/BOOT/SYSLINUX/EFI64/'.
> >
> > Optionally, create the directory 'target/EFI/BOOT/SYSLINUX/EFI32/' too.
> >
> >
> > 10_ From the 'efi64' subdirectory for Syslinux files in your OS, copy
> > 'syslinux.efi' to 'target/EFI/BOOT/BOOTX64.EFI'.
> >
> > Optionally, from the 'efi32' subdirectory for Syslinux files in your
> > OS, copy 'syslinux.efi' to 'target/EFI/BOOT/BOOTIA32.EFI'.
> >
> >
> > 11_ From the 'efi64' subdirectory for Syslinux files in your OS, copy
> > 'ldlinux.e64' to 'target/EFI/BOOT/LDLINUX.E64'.
> >
> > Optionally, from the 'efi32' subdirectory for Syslinux files, copy
> > 'ldlinux.e32' to 'target/EFI/BOOT/LDLINUX.E32'.
> >
> >
> > 12_ From the 'efi64' subdirectory for Syslinux files, copy:
> >  _ vesamenu.c32
> >  _ libcom32.c32
> >  _ libutil.c32
> >
> > to 'target/EFI/BOOT/SYSLINUX/EFI64/*.c32'.
> >
> > Optionally, from the 'efi32' subdirectory for Syslinux files, copy:
> >  _ vesamenu.c32
> >  _ libcom32.c32
> >  _ libutil.c32
> >
> > to 'target/EFI/BOOT/SYSLINUX/EFI32/*.c32'.
> >
> >
> > 13_ Create 'target/EFI/BOOT/SYSLX64.CFG'.
> >
> > Optionally, create 'target/EFI/BOOT/SYSLIA32.CFG'.
> >
> >
> > 14_ Content of 'target/EFI/BOOT/SYSLX64.CFG':
> >
> > # D-I config version 2.0
> > # search path for the c32 support libraries (libcom32, libutil etc.)
> > PATH SYSLINUX/EFI64/
> > DEFAULT debian
> > PROMPT 0
> > LABEL debian
> > CONFIG ../../debian.cfg ../../
> >
> >
> > Optionally, the content of 'target/EFI/BOOT/SYSLIA32.CFG':
> >
> > # D-I config version 2.0
> > # search path for the c32 support libraries (libcom32, libutil etc.)
> > PATH SYSLINUX/EFI32/
> > DEFAULT debian
> > PROMPT 0
> > LABEL debian
> > CONFIG ../../debian.cfg ../../
> >
> >
> > 15_ Unmount the 'target', test and report back! :).
> >
> > Hopefully I have no typos in the above steps. Let's also hope that the
> > description was clear enough to follow, and that the results are as
> > expected.
> >
> > Please note that there are potential improvements to the above setup
> > and that not every single aspect of the resulting boot.img has been
> > tested.
> >
> 
> legacy still works as before. (at least help and booting linux do, I
> didn't test every option)
> 
> uefi falis with:
> Failed to load COM32 file vesamenu.c32
> 
> this change fixes it:
> > $target/EFI/BOOT/SYSLX64.CFG <<EOF
> -PATH SYSLINUX/EFI64/
> +PATH EFI/BOOT/SYSLINUX/EFI64/
> 
> Lack of leading / tells me CWD is / not /EFI/BOOT
> 
> good news: linux boots.
> 
> bad news: selecting the Help option locks it up - menu is still there
> and keys don't move highlight or anything.  cpu
> 
> here is the relevant bits of
> https://salsa.debian.org/debconf-video-team/ansible/blob/61b833ad1a010c4f046ea9d1d8c81679e97671e9/usbinst/uefi/build_uefi.sh
> 
> + cp /usr/lib/SYSLINUX.EFI/efi64/syslinux.efi target/EFI/BOOT/BOOTX64.EFI
> + cp /usr/lib/syslinux/modules/efi64/ldlinux.e64 target/EFI/BOOT/LDLINUX.E64
> + cp \
> /usr/lib/syslinux/modules/efi64/vesamenu.c32 \
> /usr/lib/syslinux/modules/efi64/libcom32.c32 \
> /usr/lib/syslinux/modules/efi64/libutil.c32 \
> target/EFI/BOOT/SYSLINUX/EFI64
> 
> target
> ├── adtxt.cfg
> ├── boot
> │   └── syslinux
> │       ├── ldlinux.c32
> │       ├── ldlinux.sys
> │       ├── libcom32.c32
> │       ├── libutil.c32
> │       ├── syslinux.cfg
> │       └── vesamenu.c32
> ├── debian.cfg
> ├── disk.lbl
> ├── EFI
> │   └── BOOT
> │       ├── BOOTX64.EFI
> │       ├── LDLINUX.E64
> │       ├── SYSLINUX
> │       │   └── EFI64
> │       │       ├── libcom32.c32
> │       │       ├── libutil.c32
> │       │       └── vesamenu.c32
> │       └── SYSLX64.CFG
> ├── exithelp.cfg
> ├── f10.txt
> ├── f1.txt
> ├── f2.txt
> ├── f3.txt
> ├── f4.txt
> ├── f5.txt
> ├── f6.txt
> ├── f7.txt
> ├── f8.txt
> ├── f9.txt
> ├── initrd.gz
> ├── linux
> ├── menu.cfg
> ├── prompt.cfg
> ├── rqtxt.cfg
> ├── splash.png
> ├── stdmenu.cfg
> └── txt.cfg
> 
> + cat target/boot/syslinux/syslinux.cfg
> # D-I config version 2.0
> # search path for the c32 support libraries (libcom32, libutil etc.)
> PATH ./
> DEFAULT debian
> PROMPT 0
> LABEL debian
> CONFIG ../../debian.cfg ../../
> 
> + cat target/debian.cfg
> include menu.cfg
> default vesamenu.c32
> prompt 0
> timeout 0
> 
> + cat target/exithelp.cfg
> label menu
>     kernel vesamenu.c32
>     config debian.cfg
> 
> + cat target/EFI/BOOT/SYSLX64.CFG
> # D-I config version 2.0
> # search path for the c32 support libraries (libcom32, libutil etc.)
> PATH EFI/BOOT/SYSLINUX/EFI64/
> DEFAULT debian
> PROMPT 0
> LABEL debian
> CONFIG ../../debian.cfg ../../
> 
> + qemu-system-x86_64 -m 512 -bios OVMF.fd -drive file=boot.img,format=raw
 
 
tl;dr: the PATH directive is a buggy, almost-useless crap. The problem 
is a known bug in the crappy PATH directive.

Before I explain what's the problem, I'll repeat what I wrote in a 
prior email, which should put the explanation in context.

BEWARE:
 We are about to use the PATH directive. This PATH directive has 
several issues, inconveniences, shortcomings, and bugs. Hence, the next 
test _might_ "fail" to show the boot menu.

The initial WD when booting in UEFI mode is '/EFI/BOOT/'. At this point 
(when SYSLX64.CFG has been parsed), we have not needed any c32 module 
yet, and the PATH directive points to "(CWD/)SYSLINUX/EFI64/".

Then we use the CONFIG directive in order to do 2 things: change the WD 
to be "/" and then parse "debian.cfg". The reason to change the WD is 
because we want to use the already-existent "*.cfg" files, "as-is". If 
we were to leave the WD as it was (i.e. '/EFI/BOOT/'), then we would 
need to create (and maintain) multiple sets of cfg files, in which the 
only difference would be the path for each command. This is the reason 
for not using the INCLUDE directive instead of CONFIG.

While the new CWD is "/", the PATH directive is still translated to 
"(CWD/)SYSLINUX/EFI64/", which now means "/SYSLINUX/EFI64/", which of 
course doesn't exist. Since it doesn't exist, vesamenu.c32 cannot be 
found.

Note that the error message you got was "Failed to load COM32 file 
vesamenu.c32". Besides the fact that the error doesn't explicitly say 
"... because we couldn't find the file", the error message is not 
pointing to the required c32 library modules (as you got in prior 
tests), and rightly so. The problem is not that syslinux.efi cannot 
find the library modules, but rather that vesamenu.c32 cannot be found.

When you modified the PATH directive to be "EFI/BOOT/SYSLINUX/EFI64/", 
the initial cfg file loaded (i.e. SYSLX64.CFG) doesn't fail because we 
don't call for any c32 module at all, so "nobody cares" that the 
resulting path, "EFI/BOOT/EFI/BOOT/SYSLINUX/EFI64/" (this was the 
resulting path indeed, not a typo) doesn't exist.

With the modified PATH directive, when the CONFIG directive changes the 
WD and "debian.cfg" is parsed, the resulting alternative "PATH" for c32 
modules ends up being "(CWD/)EFI/BOOT/SYSLINUX/EFI64/", which indeed 
exists and the c32 modules can be found in it. This explains why your 
edition "works".

But that edition is only a workaround for the specific setup. Any 
modification in the cfg structure, or any potential change in any path 
(as Debian derivatives and others might be interested in doing, for 
several reasons) would potentially "break" the workaround and users / 
distros would again end up with the same error message as you did.

So, the solution "could potentially" be to use an absolute path for the 
PATH directive. For example, in SYSLX64.CFG, the line "could 
potentially" be (please keep reading before actually performing any 
change):

PATH /EFI/BOOT/SYSLINUX/EFI64/


The desired situation should be that the PATH directive should be able 
to interpret at least two kinds of cases:

_ relative paths in the PATH directive, and then maintain them always 
as relative to whichever the WD is at each time; while,

_ absolute paths in the PATH directive, and then maintain them always 
as absolute (a "fix" location), independently of whichever the WD is at 
each time.

"What's the problem then?", you might ask. The problem is that the 
almost-useless, buggy, incomplete and over-complicated PATH directive 
doesn't really understand absolute paths! This is a known bug, with a 
bug report already opened in the Syslinux bug tracker (also almost 
useless).

Instead of the PATH directive, from the users' perspective there should 
had been something better. Something like:

# Directive indicating an alternative path for c32 modules, depending 
on the platform that has been booted:
CPATH <platform> <path>

where <path> could be either relative or absolute.

Example (in the _same_ cfg file we can have multiple lines, each for a 
different platform, as oppose to the buggy PATH directive which 
requires separated cfg files):

CPATH bios /boot/syslinux/
CPATH efix64 /EFI/BOOT/SYSLINUX/EFI64/
CPATH efiia32 /EFI/BOOT/SYSLINUX/EFI32/

where "bios", efix64" and "efiia32" are (valid, supported) "platforms".


But, since the above proposal has been ignored, and since the buggy 
PATH directive has not been improved so as to actually be useful, all 
we have are partial workarounds.

In the past, Phil Pokorny has sent a patch for the PATH directive 
(twice, in fact). The patch is related to another half-baked "feature" 
of the PATH directive, and it is not related to the bug we are talking 
about. Perhaps Phil might be able to help solve this other bug in the 
PATH directive (or, should I dare to say it, make a patch to implement 
the above "CPATH" proposal in Syslinux :D).


@Carl, with this very long explanation, please feel free to choose 
whichever workaround you think its appropriate in order to deal with 
this bug.

As per the other points (Debian's "boot help" in efi mode, etc.), would 
you please start a new email thread, focused only on one issue at a 
time? We don't need the whole complex setup of BIOS+UEFI (plus multiple 
cfg files plus the crap of the PATH directive) in order to troubleshoot 
the other issues that are relevant to UEFI only.

Regards,
Ady.



More information about the Syslinux mailing list