On Tue Mar 24 03:57:51 PDT 2020, Thomas Petazzoni wrote: > Building syslinux against gnu-efi 3.0.10 currently fails with: > > syslinux/efi/main.c:33:8: error: unknown type name ?jmp_buf? >??? 33 | static jmp_buf load_error_buf; >?????? |??????? ^~~~~~~ > syslinux/efi/main.c: In function ?local_boot?: > syslinux/efi/main.c:189:5: warning: implicit declaration of function ?longjmp? [-Wimplicit-function-declaration] >?? 189 |???? longjmp(&load_error_buf, 1); >?????? |???? ^~~~~~~ > syslinux/efi/main.c: In function ?build_gdt?: > syslinux/efi/main.c:907:75: warning: taking address of packed member of ?struct dt_desc? may result in an unaligned pointer value [-Waddress-of-packed-member] >?? 907 |? status = emalloc(gdt.limit, __SIZEOF_POINTER__ , (EFI_PHYSICAL_ADDRESS *)&gdt.base); > | ^~~~~~~~~ > syslinux/efi/main.c: In function ?efi_main?: > syslinux/efi/main.c:1390:7: warning: implicit declaration of function ?setjmp? [-Wimplicit-function-declaration] >? 1390 |? if (!setjmp(&load_error_buf)) >?????? |?????? ^~~~~~ > make[3]: *** [syslinux/mk/efi.mk:63: main.o] Error 1 > > This is due to gnu-efi commit 486ba3c3bdd147b7d98159b9e650be60bce0f027 > ("Do not include efisetjmp.h on efi.h"), in which they state: > >???? Do not include efisetjmp.h on efi.h > >???? People than really want to use efisetjmp implementation can include >???? the header on their own. > >???? Signed-off-by: leo <leo.sartre at geebol.fr> > > So we act as specified, and include <efisetjmp.h> from efi/main.c. > > Signed-off-by: Thomas Petazzoni <thomas.petazzoni at bootlin.com> > --- >? efi/main.c | 1 + >? 1 file changed, 1 insertion(+) > > diff --git a/efi/main.c b/efi/main.c > index 6a748412..e924cfb1 100644 > --- a/efi/main.c > +++ b/efi/main.c > @@ -12,6 +12,7 @@ >? #include <sys/ansi.h> > >? #include "efi.h" > +#include <efisetjmp.h> >? #include "fio.h" >? #include "version.h" >? #include "efi_pxe.h" > -- > 2.25.1 Hi Thomas, I'm not sure if this is the right approach, since syslinux also contains its own implementation, and the object file efi64/com32/lib/x86_64/setjmp.o on the linker command line is before the -lefi command line option, which means that the internal implementation is included in the resulting binary. Another thing I've noticed is that there are ampersands in the invocations of setjmp() and longjmp() in the efi/main.c file, but in no other file in the syslinux source tree, this was actually caught by a GCC-14 compiler error as it detected it as an incompatible pointer type for the params: efi/main.c: In function ?local_boot?: efi/main.c:188:13: error: passing argument 1 of ?longjmp? from incompatible pointer type [-Wincompatible-pointer-types] ? 188 |???? longjmp(&load_error_buf, 1); ????? |???????????? ^~~~~~~~~~~~~~~ ????? |???????????? | ????? |???????????? struct __jmp_buf (*)[1] In file included from efi/main.c:9: com32/include/setjmp.h:21:29: note: expected ?struct __jmp_buf *? but argument is of type ?struct __jmp_buf (*)[1]? ?? 21 | __extern __noreturn longjmp(jmp_buf, int); efi/main.c: In function ?efi_main?: efi/main.c:1398:21: error: passing argument 1 of ?setjmp? from incompatible pointer type [-Wincompatible-pointer-types] ?1398 |???????? if (!setjmp(&load_error_buf)) ????? |???????????????????? ^~~~~~~~~~~~~~~ ????? |???????????????????? | ????? |???????????????????? struct __jmp_buf (*)[1] com32/include/setjmp.h:20:21: note: expected ?struct __jmp_buf *? but argument is of type ?struct __jmp_buf (*)[1]? ?? 20 | __extern int setjmp(jmp_buf); ????? |???????????????????? ^~~~~~~ Therefore, I recommend a patch like this, which uses the syslinux version of the functions and fixes up their arguments: --- a/efi/main.c +++ b/efi/main.c @@ -6,6 +6,7 @@ ?#include <core.h> ?#include <fs.h> ?#include <com32.h> +#include <setjmp.h> ?#include <syslinux/memscan.h> ?#include <syslinux/firmware.h> ?#include <syslinux/linux.h> @@ -184,7 +185,7 @@ ????? * Inform the firmware that we failed to execute correctly, which ????? * will trigger the next entry in the EFI Boot Manager list. ????? */ -??? longjmp(&load_error_buf, 1); +??? longjmp(load_error_buf, 1); ?} ?void bios_timer_cleanup(void) @@ -1382,7 +1383,7 @@ ??????????????? status = uefi_call_wrapper(in->ReadKeyStroke, 2, in, &key); ??????? } while (status == EFI_SUCCESS); -?????? if (!setjmp(&load_error_buf)) +?????? if (!setjmp(load_error_buf)) ??????????????? load_env32(NULL); ??????? /* load_env32() failed.. cancel timer and bailout */ I was able to test to make sure it works with a configuration file like this: PROMPT? 1 TIMEOUT 50 DEFAULT debian LABEL debian ???? LINUX /vmlinuz ???? INITRD /initrd.gz LABEL localboot ???? LINUX .localboot The localboot option was able to successfully use the longjmp() function to get back to efi_main() and terminate the EFI application, getting me back to the EFI shell under QEMU, and getting my laptop to switch to the next boot option (grub) when I tried it on real hardware. Best Regards, Marek