[syslinux:wip.makefixes] WIP: massive amounts of build fixes

syslinux-bot for H. Peter Anvin (Intel) hpa at zytor.com
Wed Feb 27 16:51:12 PST 2019


Commit-ID:  0fe62bb555ca64873e3d7fde45c7850dabaf0d59
Gitweb:     https://www.syslinux.org/commit/0fe62bb555ca64873e3d7fde45c7850dabaf0d59
Author:     H. Peter Anvin (Intel) <hpa at zytor.com>
AuthorDate: Wed, 27 Feb 2019 16:45:34 -0800
Committer:  H. Peter Anvin (Intel) <hpa at zytor.com>
CommitDate: Wed, 27 Feb 2019 16:45:34 -0800

WIP: massive amounts of build fixes

Revamp a bunch of the build system to guarantee that we don't have any
unresolved symbols anywhere.

Remove a bunch of unused legacy interfaces.

Set up the build system to minimize the sizes of the core and
ldlinux.c32. The size of ldlinux.c32 is now small enough that it
should probably be folded back into the core and/or libcom32, since
the main issue was the size limit for btrfs.

This does not yet work for EFI; but it builds BIOS cleanly.  Still
very much a work in progress.

Signed-off-by: H. Peter Anvin (Intel) <hpa at zytor.com>

---
 .gitignore                                         |   2 -
 Makefile                                           |  52 +-
 com32/Makefile                                     |  24 +-
 com32/cmenu/Makefile                               |  23 +-
 com32/gdbstub/Makefile                             |   4 +-
 com32/gfxboot/.gitignore                           |   1 -
 com32/gfxboot/Makefile                             |  56 --
 com32/gfxboot/gfxboot.c                            | 976 ---------------------
 com32/gfxboot/realmode_callback.asm                | 190 ----
 com32/gplinclude/zzjson/zzjson.h                   |   4 +
 com32/gpllib/Makefile                              |  13 +-
 com32/gpllib/zzjson/zzjson_create.c                |   2 +
 com32/gpllib/zzjson/zzjson_parse.c                 |  15 +-
 com32/gpllib/zzjson/zzjson_print.c                 |  11 +
 com32/include/com32.h                              |  34 +-
 com32/include/elfutils.h                           | 123 +++
 com32/include/klibc/compiler.h                     |  11 +-
 com32/include/klibc/endian.h                       |  32 +-
 com32/include/libansi.h                            |  14 +-
 com32/include/sys/elf32.h                          |  21 +-
 com32/include/sys/elf64.h                          |  21 +-
 com32/include/sys/elfcommon.h                      |   8 +
 com32/include/sys/module.h                         |  35 +-
 com32/include/sys/module32.h                       |  35 -
 com32/include/sys/module64.h                       |  35 -
 com32/include/syslinux/argv.h                      |   8 +
 com32/include/syslinux/pxe_api.h                   |  11 +-
 com32/lib/Makefile                                 | 186 +++-
 {core => com32/lib}/errno.c                        |   1 -
 com32/lib/getopt.c                                 |   2 -
 com32/lib/getopt_common.c                          |  11 +
 com32/lib/getopt_long.c                            |   2 -
 com32/lib/i386/libgcc/__muldi3.S                   |  59 --
 com32/lib/sys/argv.c                               |  39 +-
 com32/lib/sys/cfarcall.c                           |  10 -
 com32/lib/sys/entry.S                              | 118 ---
 com32/lib/sys/farcall.c                            |  32 -
 .../localboot.h => com32/lib/sys/file_dev.c        |  12 +-
 com32/lib/sys/fileclose.c                          |  46 -
 com32/lib/sys/{fileread.c => fileops.c}            |  21 +-
 com32/lib/sys/intcall.c                            |  10 -
 com32/lib/sys/libansi.c                            |  17 +-
 com32/lib/sys/module/common.c                      |   2 +-
 com32/lib/sys/module/elfutils.c                    |   6 +-
 com32/lib/sys/module/elfutils.h                    |  65 --
 com32/lib/sys/open.c                               |   9 -
 com32/lib/sys/openmem.c                            |   2 -
 com32/lib/syslinux/cleanup.c                       |   4 +-
 com32/lib/syslinux/idle.c                          |   8 +
 com32/lib/syslinux/load_linux.c                    |   6 +-
 com32/lib/syslinux/nopxe.c                         |  31 +
 com32/lib/syslinux/version.c                       |   3 +-
 com32/libupload/Makefile                           |   2 +-
 com32/libutil/Makefile                             |  13 +-
 com32/lua/src/Makefile                             |  14 +-
 com32/lua/src/syslinux.c                           |  15 +-
 com32/modules/Makefile                             |   8 +-
 com32/modules/zzjson.c                             |   2 +-
 com32/samples/Makefile                             |  10 +-
 com32/sysdump/memory.c                             |   5 +-
 core/Makefile                                      |  98 ++-
 core/bios/adv.inc                                  |   7 +-
 core/bios/banner.inc                               |  24 +
 core/bios/bcopyxx.inc                              |   4 +-
 core/bios/call16.c                                 |  17 +-
 core/bios/callback.inc                             |  62 +-
 core/bios/com32.inc                                |  43 +-
 core/bios/common.inc                               |   1 +
 core/bios/config.inc                               |   2 +-
 core/bios/diskboot.inc                             |  15 +-
 core/bios/diskfs.inc                               |  16 +-
 core/bios/diskstart.inc                            |  15 +-
 core/bios/export.asm                               |  20 +
 core/bios/isolinux.asm                             |  44 +-
 core/bios/layout.inc                               |  26 +-
 core/bios/localboot.c                              |   2 +-
 core/bios/localboot.inc                            |   2 +-
 core/bios/lwip/thread/sem_asm.S                    |   2 +
 core/bios/lwip/thread/thread_asm.S                 |   2 +
 core/bios/macros.inc                               |  44 +
 core/bios/pm.inc                                   |   6 +-
 core/bios/prefix.inc                               |   2 +-
 core/bios/pxeisr.inc                               |  14 +-
 core/bios/pxelinux.inc                             |  57 +-
 core/bios/stack.inc                                |   2 +-
 core/bios/syslinux.ld                              | 264 +++---
 core/bios/timer.inc                                |   9 +-
 core/codepage.S                                    |   1 +
 core/elflink/elfutils.h                            |  67 --
 core/elflink/load_env32.c                          |   4 +-
 core/export.pl                                     |  83 ++
 core/fs/fs.c                                       |   2 +-
 core/include/core.h                                |  32 +-
 core/mem/init.c                                    |  10 +-
 diag/geodsp/Makefile                               |   8 +-
 diag/geodsp/geodspms.asm                           |   2 +
 diag/mbr/Makefile                                  |   1 -
 doc/pxelinux.txt                                   |   1 -
 dos/Makefile                                       |   4 +-
 dos/ldlinux.S                                      |   2 +-
 dosutil/Makefile                                   |   6 +-
 efi/Makefile                                       |   2 +-
 efi/main.c                                         |   2 +-
 {com32/elflink/ldlinux => ldlinux}/Makefile        |  38 +-
 {com32/elflink/ldlinux => ldlinux}/adv.c           |   0
 {com32/elflink/ldlinux => ldlinux}/advwrite.c      |   0
 {com32/elflink/ldlinux => ldlinux}/chainboot.c     |   2 +-
 {com32/elflink/ldlinux => ldlinux}/cli.c           |   7 +-
 {com32/elflink/ldlinux => ldlinux}/colors.c        |   0
 {com32/elflink/ldlinux => ldlinux}/config.h        |   0
 {com32/elflink/ldlinux => ldlinux}/execute.c       |   0
 {com32/elflink/ldlinux => ldlinux}/get_key.c       |   0
 {com32/elflink/ldlinux => ldlinux}/getadv.c        |   0
 {com32/elflink/ldlinux => ldlinux}/kernel.c        |   0
 {com32/elflink/ldlinux => ldlinux}/loadhigh.c      |   0
 com32/elflink/ldlinux/ldlinux.c => ldlinux/main.c  |   0
 {com32/elflink/ldlinux => ldlinux}/msg.c           |   0
 {com32/elflink/ldlinux => ldlinux}/readconfig.c    |   6 +-
 {com32/elflink/ldlinux => ldlinux}/refstr.c        |   0
 {com32/elflink/ldlinux => ldlinux}/setadv.c        |   0
 libinstaller/Makefile                              |  14 +-
 man/syslinux2ansi.1                                |   8 +-
 mbr/Makefile                                       |   1 -
 memdisk/Makefile                                   |   8 +-
 mk/efi.mk                                          |   2 -
 mk/elf.mk                                          |  97 +-
 mk/embedded.mk                                     |   2 +-
 mk/lib.mk                                          | 252 ------
 mk/syslinux.mk                                     |  10 +-
 txt/Makefile                                       |   1 -
 txt/pxelinux.txt                                   |   5 +-
 version                                            |   2 +-
 132 files changed, 1272 insertions(+), 2742 deletions(-)

diff --git a/.gitignore b/.gitignore
index 35a3c187..f24035e2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,8 +46,6 @@
 /utils/isohybrid.pl
 /utils/memdiskfind
 /utils/mkdiskimage
-/version.h
-/version.mk
 *GPATH
 *GRTAGS
 *GTAGS
diff --git a/Makefile b/Makefile
index b472945b..003dbf4b 100644
--- a/Makefile
+++ b/Makefile
@@ -71,7 +71,6 @@ MAKEDIR = $(topdir)/mk
 export MAKEDIR topdir OBJDIR
 
 include $(MAKEDIR)/syslinux.mk
--include $(OBJDIR)/version.mk
 
 private-targets = prerel unprerel official release burn isolinux.iso \
 		  preupload upload test unittest regression spotless
@@ -139,17 +138,17 @@ include $(MAKEDIR)/syslinux.mk
 ifeq ($(FWCLASS),BIOS)
 MODULES = memdisk/memdisk \
 	com32/menu/*.c32 com32/modules/*.c32 com32/mboot/*.c32 \
-	com32/hdt/*.c32 com32/rosh/*.c32 com32/gfxboot/*.c32 \
+	com32/hdt/*.c32 com32/rosh/*.c32 \
 	com32/sysdump/*.c32 com32/lua/src/*.c32 com32/chain/*.c32 \
 	com32/lib/*.c32 com32/libutil/*.c32 com32/gpllib/*.c32 \
-	com32/elflink/ldlinux/*.c32 com32/cmenu/libmenu/*.c32
+	com32/cmenu/libmenu/*.c32 ldlinux/$(LDLINUX)
 else
 # FIXME: Prune other BIOS-centric modules
 MODULES = com32/menu/*.c32 com32/modules/*.c32 com32/mboot/*.c32 \
-	com32/hdt/*.c32 com32/rosh/*.c32 com32/gfxboot/*.c32 \
+	com32/hdt/*.c32 com32/rosh/*.c32 \
 	com32/sysdump/*.c32 com32/lua/src/*.c32 com32/chain/*.c32 \
 	com32/lib/*.c32 com32/libutil/*.c32 com32/gpllib/*.c32 \
-	com32/cmenu/libmenu/*.c32 com32/elflink/ldlinux/$(LDLINUX)
+	com32/cmenu/libmenu/*.c32 ldlinux/$(LDLINUX)
 endif
 
 export FIRMWARE FWCLASS ARCH BITS
@@ -157,10 +156,9 @@ export FIRMWARE FWCLASS ARCH BITS
 # List of module objects that should be installed for all derivatives
 INSTALLABLE_MODULES = $(MODULES)
 
-# syslinux.exe is BTARGET so as to not require everyone to have the
+# syslinux.exe is BOBJECT so as to not require everyone to have the
 # mingw suite installed
-BTARGET  = version.gen version.h $(OBJDIR)/version.mk
-BOBJECTS = $(BTARGET) \
+BOBJECTS = \
 	mbr/*.bin \
 	core/pxelinux.0 core/lpxelinux.0 \
 	core/isolinux.bin core/isolinux-debug.bin \
@@ -178,7 +176,7 @@ BOBJECTS = $(BTARGET) \
 
 ifeq ($(FWCLASS),EFI)
 
-BSUBDIRS = codepage com32 lzo core mbr sample efi txt
+BSUBDIRS = codepage lzo core ldlinux com32 mbr sample efi txt
 ISUBDIRS =
 
 INSTALLSUBDIRS = efi
@@ -187,12 +185,10 @@ NETINSTALLABLE = efi/syslinux.efi $(INSTALLABLE_MODULES)
 
 else
 
-BSUBDIRS = codepage com32 lzo core memdisk mbr sample \
+BSUBDIRS = codepage lzo core ldlinux com32 memdisk mbr sample \
 	   diag libinstaller dos win32 win64 dosutil txt
 
-ITARGET  =
-IOBJECTS = $(ITARGET) \
-	utils/gethostip utils/isohybrid utils/mkdiskimage \
+IOBJECTS = utils/gethostip utils/isohybrid utils/mkdiskimage \
 	mtools/syslinux linux/syslinux extlinux/extlinux
 ISUBDIRS = libinstaller mtools linux extlinux utils
 
@@ -278,11 +274,17 @@ efi64:
 else # FIRMWARE
 
 all: all-local subdirs
-
-all-local: $(BTARGET) $(ITARGET)
 	-ls -l $(BOBJECTS) $(IOBJECTS)
+
+all-local:
+
 subdirs: $(BSUBDIRS) $(ISUBDIRS)
 
+libcore:
+	@mkdir -p com32
+	$(MAKE) -C com32 PRECORE=1 SRC="$(SRC)/com32" OBJ="$(OBJ)/com32" \
+		-f $(SRC)/com32/Makefile $(MAKECMDGOALS)
+
 $(sort $(ISUBDIRS) $(BSUBDIRS)):
 	@mkdir -p $@
 	$(MAKE) -C $@ SRC="$(SRC)/$@" OBJ="$(OBJ)/$@" \
@@ -303,7 +305,8 @@ $(BINFILES):
 dos extlinux linux mtools win32 win64: libinstaller
 libinstaller: core
 utils: mbr
-core: com32
+core: versions libcore
+com32: core
 efi: core
 
 installer: installer-local
@@ -322,10 +325,14 @@ strip: strip-local
 
 strip-local:
 
-version.gen: $(topdir)/version $(topdir)/version.pl
+versions: version.gen version.h version.mk
+
+version.gen: version version.pl
 	$(PERL) $(topdir)/version.pl $< $@ '%define < @'
-version.h: $(topdir)/version $(topdir)/version.pl
+version.h: version version.pl
 	$(PERL) $(topdir)/version.pl $< $@ '#define < @'
+version.mk: version version.pl
+	$(PERL) $(topdir)/version.pl $< $@ '< := @'
 
 local-install: installer
 	mkdir -m 755 -p $(INSTALLROOT)$(BINDIR)
@@ -407,11 +414,6 @@ local-spotless:
 		-type f -print0 \
 	| xargs -0rt rm -f
 
-spotless: local-spotless
+spotless:
 	rm -rf $(all_firmware)
-
-#
-# Common rules that are needed by every invocation of make.
-#
-$(OBJDIR)/version.mk: $(topdir)/version $(topdir)/version.pl
-	$(PERL) $(topdir)/version.pl $< $@ '< := @'
+	$(MAKE) local-spotless
diff --git a/com32/Makefile b/com32/Makefile
index 1aed8c8c..c2650307 100644
--- a/com32/Makefile
+++ b/com32/Makefile
@@ -1,26 +1,32 @@
-SUBDIRS = tools lib libutil gpllib libupload elflink/ldlinux modules mboot \
+ifdef PRECORE
+SUBDIRS = tools lib
+else
+SUBDIRS = tools lib libutil gpllib libupload modules mboot \
 	  menu samples elflink rosh cmenu lua/src
 
 ifneq ($(FWCLASS),EFI)
 # These tools are no applicable to EFI, or need serious porting
-SUBDIRS += hdt gfxboot sysdump chain
+SUBDIRS += hdt sysdump chain
 endif
+endif
+
+all tidy dist clean spotless install: subdirs
 
 .PHONY: subdirs $(SUBDIRS)
 subdirs: $(SUBDIRS)
 $(SUBDIRS):
 	@mkdir -p $(OBJ)/$@
-	$(MAKE) -C $(OBJ)/$@ SRC="$(SRC)"/$@ OBJ="$(OBJ)"/$@/ \
-		-f $(SRC)/$@/Makefile $(MAKECMDGOALS)
+	$(MAKE) -C $(OBJ)/$@ SRC='$(SRC)/$@' OBJ='$(OBJ)/$@' \
+		-f '$(SRC)/$@/Makefile' $(MAKECMDGOALS)
 
-all tidy dist clean spotless install: subdirs
+# Parallel dependencies 
+lib: tools
 
-# Parallel dependencies
-elflink/ldlinux gpllib libupload libutil: lib
+gpllib libupload libutil: lib
 cmenu: lib libutil
 
-chain gfxboot mboot menu modules rosh: lib libutil gpllib
+chain mboot menu modules rosh: lib libutil gpllib
 hdt: lib libutil gpllib libupload cmenu
 lua/src: lib libutil gpllib cmenu
-samples: lib libutil gpllib elflink/ldlinux
+samples: lib libutil gpllib
 sysdump: lib libutil gpllib libupload
diff --git a/com32/cmenu/Makefile b/com32/cmenu/Makefile
index b81b68ed..4a8e8524 100644
--- a/com32/cmenu/Makefile
+++ b/com32/cmenu/Makefile
@@ -17,29 +17,23 @@
 
 NOGPL := 1
 
-LIBS  = libmenu/libmenu.c32 \
-        $(objdir)/com32/libutil/libutil.c32 \
-        $(objdir)/com32/lib/libcom32.c32
-
-C_LIBS	  = libmenu/libmenu.c32
-
-VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
 CFLAGS	  += -I$(SRC)/libmenu
 
-LIBMENU = libmenu/syslnx.o libmenu/com32io.o libmenu/tui.o \
-	libmenu/menu.o libmenu/passwords.o libmenu/des.o libmenu/help.o \
-	$(objdir)/com32/libutil/libutil.c32 $(objdir)/com32/lib/libcom32.c32
+LIBMENU = libmenu/libmenu.c32
+EXTRALIBS = $(LIBMENU)
+
+LIBMENU_OBJS = libmenu/syslnx.o libmenu/com32io.o libmenu/tui.o \
+	       libmenu/menu.o libmenu/passwords.o libmenu/des.o libmenu/help.o
 
 CMENUS = $(patsubst %.c,%.c32,$(sort $(wildcard $(SRC)/*.c)))
 IMENUS = $(patsubst %.menu,%.c32,$(sort $(wildcard $(SRC)/*.menu)))
 
-MENUS = $(LIBS) $(subst $(SRC)/,,$(CMENUS) $(IMENUS))
+MENUS = $(LIBMENU) $(subst $(SRC)/,,$(CMENUS) $(IMENUS))
 
 .SUFFIXES: .S .c .o .elf .c32 .menu
 
-.PRECIOUS: %.c
 %.c: %.menu adv_menu.tpl
 	$(PYTHON) $(SRC)/menugen.py --input=$< --output=$@ --template=$(SRC)/adv_menu.tpl
 
@@ -48,9 +42,8 @@ all:	makeoutputdirs menus
 makeoutputdirs:
 	@mkdir -p $(OBJ)/libmenu
 
-libmenu/libmenu.elf: $(LIBMENU)
-	$(LD) -shared $(LDFLAGS) -soname $(patsubst %.elf,%.c32,$(@F)) \
-		-o $@ $^
+libmenu/libmenu.elf: $(LIBMENU_OBJS) $(C_LIBS)
+	$(LD) $(LDFLAGS) $(SHARED) -o $@ $^
 
 tidy dist:
 	rm -f *.o *.lo *.lst *.elf */*.o */*.elf .*.d */.*.d
diff --git a/com32/gdbstub/Makefile b/com32/gdbstub/Makefile
index 10c9c546..1564471d 100644
--- a/com32/gdbstub/Makefile
+++ b/com32/gdbstub/Makefile
@@ -16,7 +16,7 @@
 
 topdir = ../..
 MAKEDIR = $(topdir)/mk
-include $(MAKEDIR)/lib.mk
+include $(MAKEDIR)/elf.mk
 
 CFLAGS += -fPIE
 
@@ -31,7 +31,7 @@ OBJS = main.o int.o serial.o gdbstub.o
 all: $(MODULES) $(TESTFILES)
 
 gdbstub.elf : $(OBJS)
-	$(LD) -shared $(LDFLAGS) -soname $(patsubst %.elf,%.c32,$(@F)) -o $@ $^
+	$(LD) $(LDFLAGS) $(SHARED) -o $@ $^
 
 tidy dist clean:
 	rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp
diff --git a/com32/gfxboot/.gitignore b/com32/gfxboot/.gitignore
deleted file mode 100644
index 1944fd61..00000000
--- a/com32/gfxboot/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.tmp
diff --git a/com32/gfxboot/Makefile b/com32/gfxboot/Makefile
deleted file mode 100644
index 824d7d0d..00000000
--- a/com32/gfxboot/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-## -----------------------------------------------------------------------
-##
-##   Copyright 2001-2009 H. Peter Anvin - All Rights Reserved
-##   Copyright 2009 Intel Corporation; author: H. Peter Anvin
-##
-##   This program is free software; you can redistribute it and/or modify
-##   it under the terms of the GNU General Public License as published by
-##   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-##   Boston MA 02111-1307, USA; either version 2 of the License, or
-##   (at your option) any later version; incorporated herein by reference.
-##
-## -----------------------------------------------------------------------
-
-VPATH = $(SRC)
-include $(MAKEDIR)/elf.mk
-
-MODULES	  = gfxboot.c32
-
-all: $(MODULES)
-
-OBJS = gfxboot.o realmode_callback.o
-
-gfxboot.elf : $(OBJS) $(LIBS) $(C_LIBS)
-	$(LD) $(LDFLAGS) -o $@ $^
-
-realmode_callback.o: realmode_callback.asm
-ifeq ($(ARCH),i386)
-	$(NASM) -f bin -O99 -o $*.tmp -l $*.lst $<
-	$(OBJCOPY) -B i386 -I binary -O elf32-i386 \
-	  --redefine-sym _binary_$*_tmp_start=$*_start \
-	  --redefine-sym _binary_$*_tmp_end=$*_end \
-	  --strip-symbol _binary_$*_tmp_size \
-	  $*.tmp $@
-endif
-ifeq ($(ARCH),x86_64)
-	$(NASM) -f bin -O99 -o $*.tmp -l $*.lst $<
-	$(OBJCOPY) -B i386:x86-64 -I binary -O elf64-x86-64 \
-	  --redefine-sym _binary_$*_tmp_start=$*_start \
-	  --redefine-sym _binary_$*_tmp_end=$*_end \
-	  --strip-symbol _binary_$*_tmp_size \
-	  $*.tmp $@
-endif
-
-tidy dist:
-	rm -f *.o *.lo *.a *.lst .*.d *.tmp
-
-clean: tidy
-	rm -f *.lnx
-
-spotless: clean
-	rm -f *.lss *.c32 *.com
-	rm -f *~ \#*
-
-install:
-
--include .*.d
diff --git a/com32/gfxboot/gfxboot.c b/com32/gfxboot/gfxboot.c
deleted file mode 100644
index f67132c1..00000000
--- a/com32/gfxboot/gfxboot.c
+++ /dev/null
@@ -1,976 +0,0 @@
-/*
- *
- * gfxboot.c
- *
- * A com32 module to load gfxboot graphics.
- *
- * Copyright (c) 2009 Steffen Winterfeldt.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation, Inc., 53 Temple Place Ste 330, Boston MA
- * 02111-1307, USA; either version 2 of the License, or (at your option) any
- * later version; incorporated herein by reference.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <minmax.h>
-#include <ctype.h>
-
-#include <syslinux/loadfile.h>
-#include <syslinux/config.h>
-#include <syslinux/linux.h>
-#include <syslinux/boot.h>
-#include <console.h>
-#include <com32.h>
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-#define MAX_CONFIG_LINE_LEN	2048
-#define MAX_CMDLINE_LEN		2048
-
-// buffer for realmode callback
-// must be at least block size; can in theory be larger than 4k, but there's
-// not enough space left
-#define REALMODE_BUF_SIZE	4096
-#define LOWMEM_BUF_SIZE		65536
-
-// gfxboot working memory in MB
-#define	GFX_MEMORY_SIZE		7
-
-// read chunk size for progress bar
-#define CHUNK_SIZE	(64 << 10)
-
-// callback function numbers
-#define GFX_CB_INIT		0
-#define GFX_CB_DONE		1
-#define GFX_CB_INPUT		2
-#define GFX_CB_MENU_INIT	3
-#define GFX_CB_INFOBOX_INIT	4
-#define GFX_CB_INFOBOX_DONE	5
-#define GFX_CB_PROGRESS_INIT	6
-#define GFX_CB_PROGRESS_DONE	7
-#define GFX_CB_PROGRESS_UPDATE	8
-#define GFX_CB_PROGRESS_LIMIT	9		// unused
-#define GFX_CB_PASSWORD_INIT	10
-#define GFX_CB_PASSWORD_DONE	11
-
-// real mode code chunk, will be placed into lowmem buffer
-extern const char realmode_callback_start[], realmode_callback_end[];
-
-// gets in the way
-#undef linux
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// gfxboot config data (64 bytes)
-typedef struct __attribute__ ((packed)) {
-  uint8_t bootloader;		//  0: boot loader type (0: lilo, 1: syslinux, 2: grub)
-  uint8_t sector_shift;		//  1: sector shift
-  uint8_t media_type;		//  2: media type (0: disk, 1: floppy, 2: cdrom)
-  uint8_t failsafe;		//  3: turn on failsafe mode (bitmask)
-				//    0: SHIFT pressed
-				//    1: skip gfxboot
-				//    2: skip monitor detection
-  uint8_t sysconfig_size;	//  4: size of sysconfig data
-  uint8_t boot_drive;		//  5: BIOS boot drive
-  uint16_t callback;		//  6: offset to callback handler
-  uint16_t bootloader_seg;	//  8: code/data segment used by bootloader; must follow gfx_callback
-  uint16_t serial_port;		// 10: syslinux initialized serial port from 'serial' option
-  uint32_t user_info_0;		// 12: data for info box
-  uint32_t user_info_1;		// 16: data for info box
-  uint32_t bios_mem_size;	// 20: BIOS memory size (in bytes)
-  uint16_t xmem_0;		// 24: extended mem area 0 (start:size in MB; 12:4 bits) - obsolete
-  uint16_t xmem_1;		// 26: extended mem area 1 - obsolete
-  uint16_t xmem_2;		// 28: extended mem area 2 - obsolete
-  uint16_t xmem_3;		// 30: extended mem area 3 - obsolete
-  uint32_t file;		// 32: start of gfx file
-  uint32_t archive_start;	// 36: start of cpio archive
-  uint32_t archive_end;		// 40: end of cpio archive
-  uint32_t mem0_start;		// 44: low free memory start
-  uint32_t mem0_end;		// 48: low free memory end
-  uint32_t xmem_start;		// 52: extended mem start
-  uint32_t xmem_end;		// 56: extended mem end
-  uint16_t features;		// 60: feature flags returned by GFX_CB_INIT
-  				//    0: GFX_CB_MENU_INIT accepts 32 bit addresses
-  				//    1: knows about xmem_start, xmem_end
-  uint16_t reserved_1;		// 62:
-  uint32_t gfxboot_cwd;		// 64: if set, points to current gfxboot working directory relative
-				//     to syslinux working directory
-} gfx_config_t;
-
-
-// gfxboot menu description (18 bytes)
-typedef struct __attribute__ ((packed)) {
-  uint16_t entries;
-  char *default_entry;
-  char *label_list;
-  uint16_t label_size;
-  char *arg_list;
-  uint16_t arg_size;
-} gfx_menu_t;
-
-
-// menu description
-typedef struct menu_s {
-  struct menu_s *next;
-  char *label;		// config entry name
-  char *menu_label;	// text to show in boot menu
-  char *kernel;		// name of program to load
-  char *alt_kernel;	// alternative name in case user has replaced it
-  char *linux;		// de facto an alias for 'kernel'
-  char *localboot;	// boot from local disk
-  char *initrd;		// initrd as separate line (instead of as part of 'append')
-  char *append;		// kernel args
-  char *ipappend;	// append special pxelinux args (see doc)
-} menu_t;
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-gfx_config_t gfx_config;
-gfx_menu_t gfx_menu;
-
-menu_t *menu;
-menu_t *menu_default;
-static menu_t *menu_ptr, **menu_next;
-
-struct {
-  uint32_t jmp_table[12];
-  uint16_t code_seg;
-  char fname_buf[64];
-} gfx;
-
-void *lowmem_buf;
-
-int timeout;
-
-char cmdline[MAX_CMDLINE_LEN];
-
-// progress bar is visible
-unsigned progress_active;
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void show_message(char *file);
-char *get_config_file_name(void);
-char *skip_nonspaces(char *s);
-void chop_line(char *s);
-int read_config_file(const char *filename);
-unsigned magic_ok(unsigned char *buf, unsigned *code_size);
-unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len, unsigned *code_size);
-int gfx_init(char *file);
-int gfx_menu_init(void);
-void gfx_done(void);
-int gfx_input(void);
-void gfx_infobox(int type, char *str1, char *str2);
-void gfx_progress_init(ssize_t kernel_size, char *label);
-void gfx_progress_update(ssize_t size);
-void gfx_progress_done(void);
-void *load_one(char *file, ssize_t *file_size);
-void boot(int index);
-void boot_entry(menu_t *menu_ptr, char *arg);
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-int main(int argc, char **argv)
-{
-  int menu_index;
-  const union syslinux_derivative_info *sdi;
-  char working_dir[256];
-
-  openconsole(&dev_stdcon_r, &dev_stdcon_w);
-
-  lowmem_buf = lmalloc(LOWMEM_BUF_SIZE);
-  if (!lowmem_buf) {
-    printf("Could not allocate memory.\n");
-    return 1;
-  }
-
-  sdi = syslinux_derivative_info();
-
-  gfx_config.sector_shift = sdi->disk.sector_shift;
-  gfx_config.boot_drive = sdi->disk.drive_number;
-
-  if(sdi->c.filesystem == SYSLINUX_FS_PXELINUX) {
-    gfx_config.sector_shift = 11;
-    gfx_config.boot_drive = 0;
-  }
-
-  gfx_config.media_type = gfx_config.boot_drive < 0x80 ? 1 : 0;
-
-  if(sdi->c.filesystem == SYSLINUX_FS_ISOLINUX) {
-    gfx_config.media_type = sdi->iso.cd_mode ? 0 : 2;
-  }
-
-  gfx_config.bootloader = 1;
-  gfx_config.sysconfig_size = sizeof gfx_config;
-  gfx_config.bootloader_seg = 0;	// apparently not needed
-
-  if(argc < 2) {
-    printf("Usage: gfxboot.c32 bootlogo_file [message_file]\n");
-    if(argc > 2) show_message(argv[2]);
-
-    return 0;
-  }
-
-  if(read_config_file("~")) {
-    printf("Error reading config file\n");
-    if(argc > 2) show_message(argv[2]);
-
-    return 0;
-  }
-
-  if(getcwd(working_dir, sizeof working_dir)) {
-    gfx_config.gfxboot_cwd = (uint32_t) working_dir;
-  }
-
-  if(gfx_init(argv[1])) {
-    printf("Error setting up gfxboot\n");
-    if(argc > 2) show_message(argv[2]);
-
-    return 0;
-  }
-
-  gfx_menu_init();
-
-  for(;;) {
-    menu_index = gfx_input();
-
-    // abort gfx, return to text mode prompt
-    if(menu_index == -1) {
-      gfx_done();
-      break;
-    }
-
-    // does not return if it succeeds
-    boot(menu_index);
-  }
-
-  if(argc > 2) show_message(argv[2]);
-
-  return 0;
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void show_message(char *file)
-{
-  int c;
-  FILE *f;
-
-  if(!(f = fopen(file, "r"))) return;
-
-  while((c = getc(f)) != EOF) {
-    if(c < ' ' && c != '\n' && c != '\t') continue;
-    printf("%c", c);
-  }
-
-  fclose(f);
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-char *skip_nonspaces(char *s)
-{
-  while(*s && *s != ' ' && *s != '\t') s++;
-
-  return s;
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void chop_line(char *s)
-{
-  int i = strlen(s);
-
-  if(!i) return;
-
-  while(--i >= 0) {
-    if(s[i] == ' ' || s[i] == '\t' || s[i] == '\n') {
-      s[i] = 0;
-    }
-    else {
-      break;
-    }
-  }
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// Read and parse syslinux config file.
-//
-// return:
-//   0: ok, 1: error
-//
-int read_config_file(const char *filename)
-{
-  FILE *f;
-  char *s, *t, buf[MAX_CONFIG_LINE_LEN];
-  unsigned u, top_level = 0, text = 0;
-
-  if(!strcmp(filename, "~")) {
-    top_level = 1;
-    filename = syslinux_config_file();
-    gfx_menu.entries = 0;
-    gfx_menu.label_size = 0;
-    gfx_menu.arg_size = 0;
-    menu_ptr = NULL;
-    menu_next = &menu;
-    menu_default = calloc(1, sizeof *menu_default);
-  }
-
-  if(!(f = fopen(filename, "r"))) return 1;
-
-  while((s = fgets(buf, sizeof buf, f))) {
-    chop_line(s);
-    s = skipspace(s);
-    if(!*s || *s == '#') continue;
-    t = skip_nonspaces(s);
-    if(*t) *t++ = 0;
-    t = skipspace(t);
-
-    if(!strcasecmp(s, "endtext")) {
-      text = 0;
-      continue;
-    }
-
-    if (text)
-      continue;
-
-    if(!strcasecmp(s, "timeout")) {
-      timeout = atoi(t);
-      continue;
-    }
-
-    if(!strcasecmp(s, "default")) {
-      menu_default->label = strdup(t);
-      u = strlen(t);
-      if(u > gfx_menu.label_size) gfx_menu.label_size = u;
-      continue;
-    }
-
-    if(!strcasecmp(s, "label")) {
-      menu_ptr = *menu_next = calloc(1, sizeof **menu_next);
-      menu_next = &menu_ptr->next;
-      gfx_menu.entries++;
-      menu_ptr->label = menu_ptr->menu_label = strdup(t);
-      u = strlen(t);
-      if(u > gfx_menu.label_size) gfx_menu.label_size = u;
-      continue;
-    }
-
-    if(!strcasecmp(s, "kernel") && menu_ptr) {
-      menu_ptr->kernel = strdup(t);
-      continue;
-    }
-
-    if(!strcasecmp(s, "linux") && menu_ptr) {
-      menu_ptr->linux = strdup(t);
-      continue;
-    }
-
-    if(!strcasecmp(s, "localboot") && menu_ptr) {
-      menu_ptr->localboot = strdup(t);
-      continue;
-    }
-
-    if(!strcasecmp(s, "initrd") && menu_ptr) {
-      menu_ptr->initrd = strdup(t);
-      continue;
-    }
-
-    if(!strcasecmp(s, "append")) {
-      (menu_ptr ?: menu_default)->append = strdup(t);
-      u = strlen(t);
-      if(u > gfx_menu.arg_size) gfx_menu.arg_size = u;
-      continue;
-    }
-
-    if(!strcasecmp(s, "ipappend") || !strcasecmp(s, "sysappend")) {
-      (menu_ptr ?: menu_default)->ipappend = strdup(t);
-      continue;
-    }
-
-    if(!strcasecmp(s, "text")) {
-      text = 1;
-      continue;
-    }
-
-    if(!strcasecmp(s, "menu") && menu_ptr) {
-      s = skipspace(t);
-      t = skip_nonspaces(s);
-      if(*t) *t++ = 0;
-      t = skipspace(t);
-
-      if(!strcasecmp(s, "label")) {
-        menu_ptr->menu_label = strdup(t);
-        u = strlen(t);
-        if(u > gfx_menu.label_size) gfx_menu.label_size = u;
-        continue;
-      }
-
-      if(!strcasecmp(s, "include")) {
-        goto do_include;
-      }
-    }
-
-    if (!strcasecmp(s, "include")) {
-do_include:
-      s = t;
-      t = skip_nonspaces(s);
-      if (*t) *t = 0;
-      read_config_file(s);
-    }
-  }
-
-  fclose(f);
-
-  if (!top_level)
-    return 0;
-
-  if (gfx_menu.entries == 0) {
-    printf("No LABEL keywords found.\n");
-    return 1;
-  }
-
-  // final '\0'
-  gfx_menu.label_size++;
-  gfx_menu.arg_size++;
-
-  // ensure we have a default entry
-  if(!menu_default->label) menu_default->label = menu->label;
-
-  if(menu_default->label) {
-    for(menu_ptr = menu; menu_ptr; menu_ptr = menu_ptr->next) {
-      if(!strcmp(menu_default->label, menu_ptr->label)) {
-        menu_default->menu_label = menu_ptr->menu_label;
-        break;
-      }
-    }
-  }
-
-  gfx_menu.default_entry = menu_default->menu_label;
-  gfx_menu.label_list = calloc(gfx_menu.entries, gfx_menu.label_size);
-  gfx_menu.arg_list = calloc(gfx_menu.entries, gfx_menu.arg_size);
-
-  for(u = 0, menu_ptr = menu; menu_ptr; menu_ptr = menu_ptr->next, u++) {
-    if(!menu_ptr->append) menu_ptr->append = menu_default->append;
-    if(!menu_ptr->ipappend) menu_ptr->ipappend = menu_default->ipappend;
-
-    if(menu_ptr->menu_label) strcpy(gfx_menu.label_list + u * gfx_menu.label_size, menu_ptr->menu_label);
-    if(menu_ptr->append) strcpy(gfx_menu.arg_list + u * gfx_menu.arg_size, menu_ptr->append);
-  }
-
-  return 0;
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// Check header and return code start offset.
-//
-unsigned magic_ok(unsigned char *buf, unsigned *code_size)
-{
-  if(
-    *(unsigned *) buf == 0x0b2d97f00 &&		// magic id
-    (buf[4] == 8)				// version 8
-  ) {
-    *code_size = *(unsigned *) (buf + 12);
-    return *(unsigned *) (buf + 8);
-  }
-
-  return 0;
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// Search (cpio archive) for gfx file.
-//
-unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len, unsigned *code_size)
-{
-  unsigned i, fname_len, code_start = 0;
-
-  *gfx_file_start = 0;
-  *code_size = 0;
-
-  if((code_start = magic_ok(buf, code_size))) return code_start;
-
-  for(i = 0; i < len;) {
-    if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) {
-      fname_len = *(unsigned short *) (buf + i + 20);
-      *file_len = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16);
-      i += 26 + fname_len;
-      i = ((i + 1) & ~1);
-      if((code_start = magic_ok(buf + i, code_size))) {
-        *gfx_file_start = i;
-        return code_start;
-      }
-      i += *file_len;
-      i = ((i + 1) & ~1);
-    }
-    else {
-      break;
-    }
-  }
-
-  return code_start;
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// Initialize gfxboot code.
-//
-// return:
-//   0: ok, 1: error
-//
-int gfx_init(char *file)
-{
-  size_t archive_size = 0;
-  void *archive;
-  unsigned code_start, code_size, file_start, file_len, u;
-  com32sys_t r;
-  void *lowmem = lowmem_buf;
-  unsigned lowmem_size = LOWMEM_BUF_SIZE;
-
-  memset(&r,0,sizeof(r));
-  progress_active = 0;
-
-  printf("Loading %s...\n", file);
-  if(loadfile(file, &archive, &archive_size)) return 1;
-
-  if(!archive_size) return 1;
-
-  // printf("%s: %d\n", file, archive_size);
-
-  gfx_config.archive_start = (uint32_t) archive;
-  gfx_config.archive_end = gfx_config.archive_start + archive_size;
-
-  // locate file inside cpio archive
-  if(!(code_start = find_file(archive, archive_size, &file_start, &file_len, &code_size))) {
-    printf("%s: invalid file format\n", file);
-    return 1;
-  }
-
-#if 0
-  printf(
-    "code_start = 0x%x, code_size = 0x%x\n"
-    "archive_start = 0x%x, archive size = 0x%x\n"
-    "file_start = 0x%x, file_len = 0x%x\n",
-    code_start, code_size,
-    gfx_config.archive_start, archive_size,
-    file_start, file_len
-  );
-#endif
-
-  gfx_config.file = gfx_config.archive_start + file_start;
-
-  u = realmode_callback_end - realmode_callback_start;
-  u = (u + REALMODE_BUF_SIZE + 0xf) & ~0xf;
-
-  if(u + code_size > lowmem_size) {
-    printf("lowmem buffer too small: size %u, needed %u\n", lowmem_size, u + code_size);
-    return 1;
-  }
-
-  memcpy(lowmem + REALMODE_BUF_SIZE, realmode_callback_start,
-	 realmode_callback_end - realmode_callback_start);
-
-  // fill in buffer size and location
-  *(uint16_t *) (lowmem + REALMODE_BUF_SIZE) = REALMODE_BUF_SIZE;
-  *(uint16_t *) (lowmem + REALMODE_BUF_SIZE + 2) = (uint32_t) lowmem >> 4;
-
-  gfx_config.bootloader_seg = ((uint32_t) lowmem + REALMODE_BUF_SIZE) >> 4;
-  gfx_config.callback = 4;	// start address
-
-  lowmem += u;
-  lowmem_size -= u;
-
-  memcpy(lowmem, archive + file_start + code_start, code_size);
-
-  gfx_config.mem0_start = (uint32_t) lowmem + code_size;
-  gfx_config.mem0_end = (uint32_t) lowmem + lowmem_size;
-  // align a bit
-  gfx_config.mem0_start = (gfx_config.mem0_start + 0xf) & ~0xf;
-
-  gfx_config.xmem_start = (uint32_t) malloc(GFX_MEMORY_SIZE << 20);
-  if(gfx_config.xmem_start) {
-    gfx_config.xmem_end = gfx_config.xmem_start + (GFX_MEMORY_SIZE << 20);
-  }
-
-  // fake; not used anyway
-  gfx_config.bios_mem_size = 256 << 20;
-
-  gfx.code_seg = (uint32_t) lowmem >> 4;
-
-  for(u = 0; u < sizeof gfx.jmp_table / sizeof *gfx.jmp_table; u++) {
-    gfx.jmp_table[u] = (gfx.code_seg << 16) + *(uint16_t *) (lowmem + 2 * u);
-  }
-
-#if 0
-  for(u = 0; u < sizeof gfx.jmp_table / sizeof *gfx.jmp_table; u++) {
-    printf("%d: 0x%08x\n", u, gfx.jmp_table[u]);
-  }
-#endif
-
-  // we are ready to start
-
-  r.esi.l = (uint32_t) &gfx_config;
-  __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INIT], &r, &r);
-
-  if((r.eflags.l & EFLAGS_CF)) {
-    printf("graphics initialization failed\n");
-
-    return 1;
-  }
-
-  if((gfx_config.features & 3) != 3) {
-    gfx_done();
-
-    printf("%s: boot graphics code too old, please use newer version\n", file);
-
-    return 1;
-  }
-
-
-  return 0;
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-int gfx_menu_init(void)
-{
-  com32sys_t r;
-
-  memset(&r,0,sizeof(r));
-  r.esi.l = (uint32_t) &gfx_menu;
-  __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_MENU_INIT], &r, &r);
-
-  return 0;
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void gfx_done(void)
-{
-  com32sys_t r;
-
-  memset(&r,0,sizeof(r));
-  gfx_progress_done();
-
-  __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_DONE], &r, &r);
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// Run gfxboot main loop.
-//
-// return:
-//   boot menu index (-1: go to text mode prompt)
-//
-int gfx_input(void)
-{
-  com32sys_t r;
-
-  memset(&r,0,sizeof(r));
-  r.edi.l = (uint32_t) cmdline;
-  r.ecx.l = sizeof cmdline;
-  r.eax.l = timeout * 182 / 100;
-  timeout = 0;		// use timeout only first time
-  __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INPUT], &r, &r);
-  if((r.eflags.l & EFLAGS_CF)) r.eax.l = 1;
-
-  if(r.eax.l == 1) return -1;
-
-  return r.ebx.l;
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void gfx_infobox(int type, char *str1, char *str2)
-{
-  com32sys_t r;
-
-  memset(&r,0,sizeof(r));
-  r.eax.l = type;
-  r.esi.l = (uint32_t) str1;
-  r.edi.l = (uint32_t) str2;
-  __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INFOBOX_INIT], &r, &r);
-  r.edi.l = r.eax.l = 0;
-  __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INPUT], &r, &r);
-  __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INFOBOX_DONE], &r, &r);
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void gfx_progress_init(ssize_t kernel_size, char *label)
-{
-  com32sys_t r;
-
-  memset(&r,0,sizeof(r));
-  if(!progress_active) {
-    r.eax.l = kernel_size >> gfx_config.sector_shift;		// in sectors
-    r.esi.l = (uint32_t) label;
-    __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_PROGRESS_INIT], &r, &r);
-  }
-
-  progress_active = 1;
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void gfx_progress_update(ssize_t advance)
-{
-  com32sys_t r;
-
-  memset(&r,0,sizeof(r));
-  if(progress_active) {
-    r.eax.l = advance >> gfx_config.sector_shift;		// in sectors
-    __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_PROGRESS_UPDATE], &r, &r);
-  }
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void gfx_progress_done(void)
-{
-  com32sys_t r;
-
-  memset(&r,0,sizeof(r));
-  if(progress_active) {
-    __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_PROGRESS_DONE], &r, &r);
-  }
-
-  progress_active = 0;
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// Read file and update progress bar.
-//
-void *load_one(char *file, ssize_t *file_size)
-{
-  int fd;
-  void *buf = NULL;
-  char *str;
-  struct stat sbuf;
-  ssize_t size = 0, cur, i;
-
-  *file_size = 0;
-
-  if((fd = open(file, O_RDONLY)) == -1) {
-    asprintf(&str, "%s: file not found", file);
-    gfx_infobox(0, str, NULL);
-    free(str);
-    return buf;
-  }
-
-  if(!fstat(fd, &sbuf) && S_ISREG(sbuf.st_mode)) size = sbuf.st_size;
-
-  i = 0;
-
-  if(size) {
-    buf = malloc(size);
-    for(i = 1, cur = 0 ; cur < size && i > 0; cur += i) {
-      i = read(fd, buf + cur, min(CHUNK_SIZE, size - cur));
-      if(i == -1) break;
-      gfx_progress_update(i);
-    }
-  }
-  else {
-    do {
-      buf = realloc(buf, size + CHUNK_SIZE);
-      i = read(fd, buf + size, CHUNK_SIZE);
-      if(i == -1) break;
-      size += i;
-      gfx_progress_update(i);
-    } while(i > 0);
-  }
-
-  close(fd);
-
-  if(i == -1) {
-    asprintf(&str, "%s: read error @ %d", file, size);
-    gfx_infobox(0, str, NULL);
-    free(str);
-    free(buf);
-    buf = NULL;
-    size = 0;
-  }
-
-  *file_size = size;
-
-  return buf;
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// Boot menu entry.
-//
-// cmdline can optionally start with label string.
-//
-void boot(int index)
-{
-  char *arg, *alt_kernel;
-  menu_t *menu_ptr;
-  int i, label_len;
-  unsigned ipapp;
-  const struct syslinux_ipappend_strings *ipappend;
-  char *gfxboot_cwd = (char *) gfx_config.gfxboot_cwd;
-
-  if(gfxboot_cwd) {
-    chdir(gfxboot_cwd);
-    gfx_config.gfxboot_cwd = 0;
-  }
-
-  for(menu_ptr = menu; menu_ptr; menu_ptr = menu_ptr->next, index--) {
-    if(!index) break;
-  }
-
-  // invalid index or menu entry
-  if(!menu_ptr || !menu_ptr->menu_label) return;
-
-  arg = skipspace(cmdline);
-  label_len = strlen(menu_ptr->menu_label);
-
-  // if it does not start with label string, assume first word is kernel name
-  if(strncmp(arg, menu_ptr->menu_label, label_len)) {
-    alt_kernel = arg;
-    arg = skip_nonspaces(arg);
-    if(*arg) *arg++ = 0;
-    if(*alt_kernel) menu_ptr->alt_kernel = alt_kernel;
-  }
-  else {
-    arg += label_len;
-  }
-
-  arg = skipspace(arg);
-
-  // handle IPAPPEND
-  if(menu_ptr->ipappend && (ipapp = atoi(menu_ptr->ipappend))) {
-    ipappend = syslinux_ipappend_strings();
-    for(i = 0; i < ipappend->count; i++) {
-      if((ipapp & (1 << i)) && ipappend->ptr[i]) {
-        sprintf(arg + strlen(arg), " %s", ipappend->ptr[i]);
-      }
-    }
-  }
-
-  boot_entry(menu_ptr, arg);
-
-  gfx_progress_done();
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// Load & run kernel.
-//
-// Returns only on error.
-//
-void boot_entry(menu_t *menu_ptr, char *arg)
-{
-  void *kernel, *initrd_buf;
-  ssize_t kernel_size = 0, initrd_size = 0;
-  struct initramfs *initrd = NULL;
-  char *file, *cmd_buf;
-  int fd;
-  struct stat sbuf;
-  char *s, *s0, *t, *initrd_arg;
-
-  if(!menu_ptr) return;
-
-  if(menu_ptr->localboot) {
-    gfx_done();
-    syslinux_local_boot(strtol(menu_ptr->localboot, NULL, 0));
-
-    return;
-  }
-
-  file = menu_ptr->alt_kernel;
-  if(!file) file = menu_ptr->kernel;
-  if(!file) file = menu_ptr->linux;
-  if(!file) {
-    gfx_done();
-    asprintf(&cmd_buf, "%s %s", menu_ptr->label, arg);
-    syslinux_run_command(cmd_buf);
-    return;
-  }
-
-  // first, load kernel
-
-  kernel_size = 0;
-
-  if((fd = open(file, O_RDONLY)) >= 0) {
-    if(!fstat(fd, &sbuf) && S_ISREG(sbuf.st_mode)) kernel_size = sbuf.st_size;
-    close(fd);
-  }
-
-  gfx_progress_init(kernel_size, file);
-
-  kernel = load_one(file, &kernel_size);
-
-  if(!kernel) {
-    return;
-  }
-
-  if(kernel_size < 1024 || *(uint32_t *) (kernel + 0x202) != 0x53726448) {
-    // not a linux kernel
-    gfx_done();
-    asprintf(&cmd_buf, "%s %s", menu_ptr->label, arg);
-    syslinux_run_command(cmd_buf);
-    return;
-  }
-
-  // printf("kernel = %p, size = %d\n", kernel, kernel_size);
-
-  // parse cmdline for "initrd" option
-
-  initrd_arg = menu_ptr->initrd;
-
-  s = s0 = strdup(arg);
-
-  while(*s && strncmp(s, "initrd=", sizeof "initrd=" - 1)) {
-    s = skipspace(skip_nonspaces(s));
-  }
-
-  if(*s) {
-    s += sizeof "initrd=" - 1;
-    *skip_nonspaces(s) = 0;
-    initrd_arg = s;
-  }
-  else if(initrd_arg) {
-    free(s0);
-    initrd_arg = s0 = strdup(initrd_arg);
-  }
-
-  if(initrd_arg) {
-    initrd = initramfs_init();
-
-    while((t = strsep(&initrd_arg, ","))) {
-      initrd_buf = load_one(t, &initrd_size);
-
-      if(!initrd_buf) {
-        printf("%s: read error\n", t);
-        free(s0);
-        return;
-      }
-
-      initramfs_add_data(initrd, initrd_buf, initrd_size, initrd_size, 4);
-
-      // printf("initrd = %p, size = %d\n", initrd_buf, initrd_size);
-    }
-  }
-
-  free(s0);
-
-  gfx_done();
-
-  syslinux_boot_linux(kernel, kernel_size, initrd, NULL, arg);
-}
-
-
diff --git a/com32/gfxboot/realmode_callback.asm b/com32/gfxboot/realmode_callback.asm
deleted file mode 100644
index 2ff30f26..00000000
--- a/com32/gfxboot/realmode_callback.asm
+++ /dev/null
@@ -1,190 +0,0 @@
-		bits 16
-
-		section .text
-
-		; must be filled in
-f_buf_size	dw 0
-f_buf_seg	dw 0
-
-
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-gfx_cb:
-		push cs
-		pop ds
-
-		cmp al,cb_len
-		jae gfx_cb_80
-
-		movzx bx,al
-		add bx,bx
-		call word [bx+cb_table]
-		jmp gfx_cb_90
-
-gfx_cb_80:
-		mov al,0ffh
-gfx_cb_90:
-		retf
-
-
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-; Return status info.
-;
-; return:
-;  edx		filename buffer (64 bytes)
-;
-cb_status:
-		mov edx,cs
-		shl edx,4
-		add edx,f_name
-		xor al,al
-		ret
-
-
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-; Open file.
-;
-; return:
-;    al		0: ok, 1: file not found
-;   ecx		file length (al = 0)
-;
-cb_fopen:
-		mov si,f_name
-		push ds
-		pop es
-		mov ax,6
-		int 22h
-		xchg edx,eax
-		mov al,1
-		jc cb_fopen_90
-		cmp cx,[f_buf_size]
-		ja cb_fopen_90
-		or cx,cx
-		jz cb_fopen_90
-		mov [f_block_size],cx
-		or edx,edx
-		jz cb_fopen_90
-		mov [f_handle],si
-		mov [f_size],edx
-		mov ecx,edx
-		mov ax,[f_buf_size]
-		cwd
-		div word [f_block_size]
-		mov [f_blocks],ax
-
-		xor al,al
-cb_fopen_90:
-		ret
-
-
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-; Read next chunk.
-;
-; return:
-;   edx		buffer address (linear)
-;   ecx		data length (< 64k)
-;
-cb_fread:
-		xor ecx,ecx
-		mov si,[f_handle]
-		or si,si
-		jz cb_fread_80
-		mov cx,[f_blocks]
-		mov es,[f_buf_seg]
-		xor bx,bx
-		mov ax,7
-		int 22h
-		mov [f_handle],si
-		mov al,1
-		jc cb_fread_90
-cb_fread_80:
-		xor al,al
-cb_fread_90:
-		movzx edx,word [f_buf_seg]
-		shl edx,4
-		ret
-
-
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-; Return current working directory.
-;
-; return:
-;  edx		filename
-;
-cb_getcwd:
-		mov ax,1fh
-		int 22h
-		mov edx,es
-		shl edx,4
-		movzx ebx,bx
-		add edx,ebx
-		xor al,al
-		ret
-
-
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-; Set current working directory.
-;
-cb_chdir:
-		mov bx,f_name
-		push ds
-		pop es
-		mov ax,25h
-		int 22h
-		xor al,al
-		ret
-
-
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-; read sector
-;
-;  edx		sector
-;
-; return:
-;  edx		buffer (linear address)
-;
-;  Note: does not return on error!
-;
-cb_readsector:
-		xor edi,edi
-		xor esi,esi
-		mov cx,1
-		mov es,[f_buf_seg]
-		xor bx,bx
-		mov ax,19h
-		int 22h
-		movzx edx,word [f_buf_seg]
-		shl edx,4
-		xor al,al
-		ret
-
-
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-; Re-read fs structures.
-;
-cb_mount:
-		mov ax,26h
-		int 22h
-		setc al
-		ret
-
-
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-;
-		align 2, db 0
-
-cb_table	dw cb_status
-		dw cb_fopen
-		dw cb_fread
-		dw cb_getcwd
-		dw cb_chdir
-		dw cb_readsector
-		dw cb_mount
-cb_len		equ ($-cb_table)/2
-
-f_handle	dw 0
-f_block_size	dw 0
-f_blocks	dw 0
-f_size		dd 0
-f_name		times 64 db 0
-f_name_len	equ $ - f_name
-
diff --git a/com32/gplinclude/zzjson/zzjson.h b/com32/gplinclude/zzjson/zzjson.h
index d4b32e12..a33c7930 100644
--- a/com32/gplinclude/zzjson/zzjson.h
+++ b/com32/gplinclude/zzjson/zzjson.h
@@ -6,6 +6,8 @@
 
 #include <stdlib.h>
 
+#define NOFLOAT 1		/* SYSLINUX */
+
 /* Version: */
 
 #define ZZJSON_VERSION_MAJOR    1
@@ -73,7 +75,9 @@ typedef struct ZZJSON {
         struct {
             union {
                 unsigned long long ival;
+#ifndef NOFLOAT
                 double             dval;
+#endif
             } val;
         } number;
     } value;
diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile
index 1fec9145..543ea7bf 100644
--- a/com32/gpllib/Makefile
+++ b/com32/gpllib/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Include configuration rules
-include $(MAKEDIR)/lib.mk
+include $(MAKEDIR)/elf.mk
 
 REQFLAGS += -I$(SRC)/../gplinclude -I$(SRC)/../gplinclude/zzjson
 
@@ -17,14 +17,17 @@ AUXDIR   = $(DATADIR)/syslinux
 INCDIR   = /usr/include
 COM32DIR = $(AUXDIR)/com32
 
+LIBS     = $(LIBCOM32) $(LIBLDLINUX) $(LIBCORE)
+
 all: makeoutputdirs libgpl.c32
 
+.PHONY: makeoutputdirs
 makeoutputdirs:
-	@mkdir -p $(foreach b, \
-		$(addprefix $(OBJ),$(sort $(dir $(LIBOBJS)))),$(b))
+	mkdir -p $(foreach b, \
+		$(addprefix $(OBJ)/,$(sort $(dir $(LIBOBJS)))),$(b))
 
-libgpl.elf : $(LIBOBJS)
-	$(LD) -shared $(LDFLAGS) -soname $(patsubst %.elf,%.c32,$(@F)) -o $@ $^
+libgpl.elf: $(LIBOBJS) $(LIBS)
+	$(LD) $(LDFLAGS) $(SHARED) -o $@ $(LIBOBJS) --no-whole-archive $(LIBS)
 
 tidy dist clean:
 	find . \( -name \*.o -o -name .\*.d -o -name \*.tmp \) -print0 | \
diff --git a/com32/gpllib/zzjson/zzjson_create.c b/com32/gpllib/zzjson/zzjson_create.c
index 7e6bd5bd..5dc1f87a 100644
--- a/com32/gpllib/zzjson/zzjson_create.c
+++ b/com32/gpllib/zzjson/zzjson_create.c
@@ -34,12 +34,14 @@ ZZJSON *zzjson_create_null(ZZJSON_CONFIG *config) {
     return zzjson_create_templ(config, ZZJSON_NULL);
 }
 
+#ifndef NOFLOAT
 ZZJSON *zzjson_create_number_d(ZZJSON_CONFIG *config, double d) {
     ZZJSON *zzjson = zzjson_create_templ(config, ZZJSON_NUMBER_DOUBLE);
     if (zzjson)
         zzjson->value.number.val.dval = d;
     return zzjson;
 }
+#endif
 
 ZZJSON *zzjson_create_number_i(ZZJSON_CONFIG *config, long long i) {
     ZZJSON *zzjson = zzjson_create_templ(config, ZZJSON_NUMBER_NEGINT);
diff --git a/com32/gpllib/zzjson/zzjson_parse.c b/com32/gpllib/zzjson/zzjson_parse.c
index ecb6f61e..e242e06d 100644
--- a/com32/gpllib/zzjson/zzjson_parse.c
+++ b/com32/gpllib/zzjson/zzjson_parse.c
@@ -9,6 +9,8 @@
 #include <math.h>
 #include <stdio.h>
 
+#define NOFLOAT 1		/* SYSLINUX */
+
 #define GETC()          config->getchar(config->ihandle)
 #define UNGETC(c)       config->ungetchar(c, config->ihandle)
 #define SKIPWS()        skipws(config)
@@ -141,8 +143,11 @@ static ZZJSON *parse_string2(ZZJSON_CONFIG *config) {
 static ZZJSON *parse_number(ZZJSON_CONFIG *config) {
     ZZJSON *zzjson;
     unsigned long long ival = 0, expo = 0;
+    int c, dbl = 0, sign = 1;
+#ifndef NOFLOAT
+    int signexpo = 1;
     double dval = 0.0, frac = 0.0, fracshft = 10.0;
-    int c, dbl = 0, sign = 1, signexpo = 1;
+#endif
 
     SKIPWS();
     c = GETC();
@@ -178,8 +183,10 @@ skip:
     }
 
     while (isdigit(c)) {
+#ifndef NOFLOAT
         frac += (double)(c - '0') / fracshft;
         fracshft *= 10.0;
+#endif
         c = GETC();
     }
 
@@ -192,7 +199,9 @@ skipfrac:
     if (c == '+')
         c = GETC();
     else if (c == '-') {
+#ifndef NOFLOAT
         signexpo = -1;
+#endif
         c = GETC();
     }
 
@@ -210,11 +219,13 @@ skipfrac:
 skipexpo:
     UNGETC(c);
 
+#ifndef NOFLOAT
     if (dbl) {
         dval = sign * (long long) ival;
         dval += sign * frac;
         dval *= pow(10.0, (double) signexpo * expo);
     }
+#endif
 
     zzjson = config->calloc(1, sizeof(ZZJSON));
     if (!zzjson) {
@@ -223,7 +234,9 @@ skipexpo:
     }
     if (dbl) {
         zzjson->type = ZZJSON_NUMBER_DOUBLE;
+#ifndef NOFLOAT
         zzjson->value.number.val.dval = dval;
+#endif
     } else {
         zzjson->type = sign < 0 ? ZZJSON_NUMBER_NEGINT : ZZJSON_NUMBER_POSINT;
         zzjson->value.number.val.ival = ival;
diff --git a/com32/gpllib/zzjson/zzjson_print.c b/com32/gpllib/zzjson/zzjson_print.c
index a59b3b09..9f809222 100644
--- a/com32/gpllib/zzjson/zzjson_print.c
+++ b/com32/gpllib/zzjson/zzjson_print.c
@@ -5,6 +5,13 @@
 
 #include "zzjson.h"
 
+#ifdef CONFIG_NO_ERROR_MESSAGES
+#define ERROR(x...)
+#else
+#define ERROR(x...)     config->error(config->ehandle, ##x)
+#endif
+#define MEMERROR()      ERROR("out of memory")
+
 #define PRINT(fmt...) if (config->print(config->ohandle, ##fmt) < 0) return -1;
 //#define PUTC(c)       if (config->putchar(c, config->ohandle) < 0) return -1;
 #define PUTC(c)       PRINT("%c",c)
@@ -83,7 +90,11 @@ static int zzjson_print2(ZZJSON_CONFIG *config, ZZJSON *zzjson,
         case ZZJSON_NUMBER_DOUBLE:
             PRINT(objval ? " " : "\n%*s", indent, "");
             if (zzjson->type == ZZJSON_NUMBER_DOUBLE) {
+#ifndef NOFLOAT
                 PRINT("%16.16e", zzjson->value.number.val.dval);
+#else
+		ERROR("floats not supported");
+#endif
             } else {
                 if (zzjson->type == ZZJSON_NUMBER_NEGINT) PUTC('-');
                 PRINT("%llu", zzjson->value.number.val.ival);
diff --git a/com32/include/com32.h b/com32/include/com32.h
index 1a843e0b..a46284bb 100644
--- a/com32/include/com32.h
+++ b/com32/include/com32.h
@@ -89,14 +89,6 @@ extern struct com32_sys_args {
     const struct com32_pmapi *cs_pm;
 } __com32;
 
-/*
- * System call wrapper functions
- */
-void __intcall(uint8_t __i, const com32sys_t * __sr, com32sys_t * __dr);
-void __farcall(uint16_t __cs, uint16_t __ip,
-	       const com32sys_t * __sr, com32sys_t * __dr);
-int __cfarcall(uint16_t __cs, uint16_t __ip,
-	       const void *__stack, uint32_t __stack_size);
 extern const com32sys_t __com32_zero_regs;
 
 /*
@@ -188,6 +180,32 @@ static inline far_ptr_t FAR_PTR(void *__ptr)
     return __fptr;
 }
 
+/*
+ * BIOS callback functions
+ */
+void __intcall(uint8_t __i, const com32sys_t *__sr, com32sys_t *__dr);
+void ___farcall(uint32_t __csip, const com32sys_t *__sr, com32sys_t *__dr);
+static inline void
+__farcall(uint16_t __cs, uint16_t __ip, const com32sys_t *__sr, com32sys_t *__dr)
+{
+    far_ptr_t __csip;
+
+    __csip.offs = __ip;
+    __csip.seg  = __cs;
+    ___farcall(__csip.ptr, __sr, __dr);
+}
+
+int32_t ___cfarcall(uint32_t __csip, const void *__stk, uint32_t __stksize);
+static inline int32_t
+__cfarcall(uint16_t __cs, uint16_t __ip, const void *__stk, uint32_t __stksize)
+{
+    far_ptr_t __csip;
+
+    __csip.offs = __ip;
+    __csip.seg  = __cs;
+    return ___cfarcall(__csip.ptr, __stk, __stksize);
+}
+
 extern const char *com32_cmdline(void);
 
 #endif /* _COM32_H */
diff --git a/com32/include/elfutils.h b/com32/include/elfutils.h
new file mode 100644
index 00000000..831cf4cd
--- /dev/null
+++ b/com32/include/elfutils.h
@@ -0,0 +1,123 @@
+/*
+ * <elfutils.h>
+ *
+ * Native ELF utilities
+ */
+
+#ifndef ELF_UTILS_H_
+#define ELF_UTILS_H_
+
+#include <elf.h>
+#include <stdlib.h>
+
+#ifndef ELF_MACHINE
+# ifdef __x86_64__
+#  define ELF_MACHINE EM_X86_64
+# elif defined(__i386__)
+#  define ELF_MACHINE EM_386
+# else
+#  error "Unknown ELF architecture"
+# endif
+#endif
+
+#ifndef ELF_CLASS
+# ifndef ELF_CLASS_SIZE
+#  define ELF_CLASS_SIZE __SIZE_WIDTH__
+# endif
+# if ELF_CLASS_SIZE == 32
+#  define ELF_CLASS ELFCLASS32
+# else
+#  define ELF_CLASS ELFCLASS64
+# endif
+#endif
+#undef ELF_CLASS_SIZE		/* Redefined below to match ELF_CLASS */
+
+#ifndef ELF_DATA
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#  define ELF_DATA ELFDATA2LSB
+# else
+#  define ELF_DATA ELFDATA2MSB
+# endif
+#endif
+
+#ifndef ELF_VERSION
+# define ELF_VERSION EV_CURRENT
+#endif
+
+#if ELF_CLASS == ELFCLASS32
+# define ELF_CLASS_SIZE		32
+typedef Elf32_Addr		Elf_Addr;
+typedef Elf32_Dyn		Elf_Dyn;
+typedef Elf32_Word		Elf_Word;
+typedef Elf32_Off		Elf_Off;
+typedef Elf32_Sym		Elf_Sym;
+typedef Elf32_Ehdr		Elf_Ehdr;
+typedef Elf32_Phdr		Elf_Phdr;
+typedef Elf32_Rel		Elf_Rel;
+typedef Elf32_Bword		Elf_Bword;
+# define ELF_R_SYM(x)		ELF32_R_SYM(x)
+# define ELF_R_TYPE(x)		ELF32_R_TYPE(x)
+#elif ELF_CLASS == ELFCLASS64
+# define ELF_CLASS_SIZE		64
+typedef Elf64_Addr		Elf_Addr;
+typedef Elf64_Dyn		Elf_Dyn;
+typedef Elf64_Word		Elf_Word;
+typedef Elf64_Off		Elf_Off;
+typedef Elf64_Sym		Elf_Sym;
+typedef Elf64_Ehdr		Elf_Ehdr;
+typedef Elf64_Phdr		Elf_Phdr;
+typedef Elf64_Rel		Elf_Rel;
+typedef Elf64_Bwword		Elf_Bword;
+# define ELF_R_SYM(x)		ELF64_R_SYM(x)
+# define ELF_R_TYPE(x)		ELF64_R_TYPE(x)
+#else
+# error "Invalid ELF_CLASS"
+#endif
+
+/**
+ * elf_get_header - Returns a pointer to the ELF header structure.
+ * @elf_image: pointer to the ELF file image in memory
+ */
+static inline Elf_Ehdr *elf_get_header(void *elf_image)
+{
+    return (Elf_Ehdr *) elf_image;
+}
+
+/**
+ * elf_get_pht - Returns a pointer to the first entry in the PHT.
+ * @elf_image: pointer to the ELF file image in memory
+ */
+static inline Elf_Phdr *elf_get_pht(void *elf_image)
+{
+    Elf_Ehdr *elf_hdr = elf_get_header(elf_image);
+
+    return (Elf_Phdr *) ((Elf_Off) elf_hdr + elf_hdr->e_phoff);
+}
+
+//
+/**
+ * elf_get_ph - Returns the element with the given index in the PTH
+ * @elf_image: pointer to the ELF file image in memory
+ * @index: the index of the PHT entry to look for
+ */
+static inline Elf_Phdr *elf_get_ph(void *elf_image, int index)
+{
+    Elf_Phdr *elf_pht = elf_get_pht(elf_image);
+    Elf_Ehdr *elf_hdr = elf_get_header(elf_image);
+
+    return (Elf_Phdr *) ((Elf_Off) elf_pht + index * elf_hdr->e_phentsize);
+}
+
+/**
+ * elf_hash - Returns the index in a SysV hash table for the symbol name.
+ * @name: the name of the symbol to look for
+ */
+extern unsigned long elf_hash(const unsigned char *name);
+
+/**
+ * elf_gnu_hash - Returns the index in a GNU hash table for the symbol name.
+ * @name: the name of the symbol to look for
+ */
+extern unsigned long elf_gnu_hash(const unsigned char *name);
+
+#endif /*ELF_UTILS_H_ */
diff --git a/com32/include/klibc/compiler.h b/com32/include/klibc/compiler.h
index e8548b59..008650b3 100644
--- a/com32/include/klibc/compiler.h
+++ b/com32/include/klibc/compiler.h
@@ -125,9 +125,6 @@
 /* Packed structures */
 #define __packed	__attribute__((packed))
 
-/* Weak symbols */
-#define __weak          __attribute__((weak))
-
 /* Alignment */
 #define __aligned(x)	__attribute__((aligned(x)))
 #define __alignas(x)	__attribute__((aligned(__alignof__(x))))
@@ -139,6 +136,14 @@
 /* Weak symbols */
 #define __weak			__attribute__((weak))
 
+/* Symbols exported from the current module */
+#ifdef NO_PLT
+#define __export		__attribute__((visibility("protected")))
+#else
 #define __export		__attribute__((visibility("default")))
+#endif
+
+/* Symbols *not* to export from the current module */
+#define __hidden		__attribute__((visibility("hidden")))
 
 #endif
diff --git a/com32/include/klibc/endian.h b/com32/include/klibc/endian.h
index 94664212..278e92de 100644
--- a/com32/include/klibc/endian.h
+++ b/com32/include/klibc/endian.h
@@ -7,32 +7,10 @@
 #ifndef _KLIBC_ENDIAN_H
 #define _KLIBC_ENDIAN_H
 
-#define __LITTLE_ENDIAN		/* we're on i386, littleendian */
-
-/* Linux' asm/byteorder.h defines either __LITTLE_ENDIAN or
-   __BIG_ENDIAN, but the glibc/BSD-ish macros expect both to be
-   defined with __BYTE_ORDER defining which is actually used... */
-
-#if defined(__LITTLE_ENDIAN)
-# undef  __LITTLE_ENDIAN
-# define __LITTLE_ENDIAN 1234
-# define __BIG_ENDIAN    4321
-# define __PDP_ENDIAN    3412
-# define __BYTE_ORDER    __LITTLE_ENDIAN
-#elif defined(__BIG_ENDIAN)
-# undef  __BIG_ENDIAN
-# define __LITTLE_ENDIAN 1234
-# define __BIG_ENDIAN    4321
-# define __PDP_ENDIAN    3412
-# define __BYTE_ORDER    __BIG_ENDIAN
-#elif defined(__PDP_ENDIAN)
-# undef  __PDP_ENDIAN
-# define __LITTLE_ENDIAN 1234
-# define __BIG_ENDIAN    4321
-# define __PDP_ENDIAN    3412
-# define __BYTE_ORDER    __PDP_ENDIAN
-#else
-# error "Unknown byte order!"
-#endif
+/* Graciously provided by gcc */
+#define __LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
+#define __BIG_ENDIAN    __ORDER_BIG_ENDIAN__
+#define __PDP_ENDIAN    __ORDER_PDP_ENDIAN__
+#define __BYTE_ORDER    __BYTE_ORDER__
 
 #endif /* _KLIBC_ENDIAN_H */
diff --git a/com32/include/libansi.h b/com32/include/libansi.h
index 030fd0df..13118c1d 100644
--- a/com32/include/libansi.h
+++ b/com32/include/libansi.h
@@ -52,8 +52,9 @@ void disable_utf8(void);
 void set_g1_special_char(void);
 void set_us_g0_charset(void);
 void clear_entire_screen(void);
-void clearwindow(const char top, const char left, const char bot,
-		 const char right, const char fillchar, const char fillattr);
+void clearwindow(int top, int left, int bot, int right,
+		 char fillchar, unsigned char fillattr);
+void gotoxy(int row, int col);
 
 static inline void beep(void)
 {
@@ -63,10 +64,10 @@ static inline void beep(void)
 void reset_colors(void);
 
 /* Print a string */
-void csprint(const char *, const char);
+void csprint(const char *, unsigned char);
 
 /* Print one character, one or more times */
-void cprint(const char, const char, unsigned int);
+void cprint(char, unsigned char, unsigned int);
 
 /* Print one character, once */
 static inline void putch(const char x, char attr)
@@ -98,9 +99,4 @@ static inline void scrollup_once(void)
 	printf(CSI "S");
 }
 
-static inline void gotoxy(const char row, const char col)
-{
-	printf(CSI "%d;%dH", row + 1, col + 1);
-}
-
 #endif
diff --git a/com32/include/sys/elf32.h b/com32/include/sys/elf32.h
index c98c274b..c8fa5a2a 100644
--- a/com32/include/sys/elf32.h
+++ b/com32/include/sys/elf32.h
@@ -8,16 +8,17 @@
 #include <sys/elfcommon.h>
 
 /* ELF standard typedefs (yet more proof that <stdint.h> was way overdue) */
-typedef uint16_t Elf32_Half;
-typedef int16_t Elf32_SHalf;
-typedef uint32_t Elf32_Word;
-typedef int32_t Elf32_Sword;
-typedef uint64_t Elf32_Xword;
-typedef int64_t Elf32_Sxword;
-
-typedef uint32_t Elf32_Off;
-typedef uint32_t Elf32_Addr;
-typedef uint16_t Elf32_Section;
+typedef Elf_Half   Elf32_Half;
+typedef Elf_SHalf  Elf32_SHalf;
+typedef Elf_Word   Elf32_Word;
+typedef Elf_Sword  Elf32_Sword;
+typedef Elf_Xword  Elf32_Xword;
+typedef Elf_Sxword Elf32_Sxword;
+
+typedef Elf_Word   Elf32_Off;
+typedef Elf_Word   Elf32_Addr;
+typedef Elf_Half   Elf32_Section;
+typedef Elf_Word   Elf32_Bword;
 
 /* Dynamic header */
 
diff --git a/com32/include/sys/elf64.h b/com32/include/sys/elf64.h
index a76fc989..71c71a32 100644
--- a/com32/include/sys/elf64.h
+++ b/com32/include/sys/elf64.h
@@ -8,16 +8,17 @@
 #include <sys/elfcommon.h>
 
 /* ELF standard typedefs (yet more proof that <stdint.h> was way overdue) */
-typedef uint16_t Elf64_Half;
-typedef int16_t Elf64_SHalf;
-typedef uint32_t Elf64_Word;
-typedef int32_t Elf64_Sword;
-typedef uint64_t Elf64_Xword;
-typedef int64_t Elf64_Sxword;
-
-typedef uint64_t Elf64_Off;
-typedef uint64_t Elf64_Addr;
-typedef uint16_t Elf64_Section;
+typedef Elf_Half   Elf64_Half;
+typedef Elf_SHalf  Elf64_SHalf;
+typedef Elf_Word   Elf64_Word;
+typedef Elf_Sword  Elf64_Sword;
+typedef Elf_Xword  Elf64_Xword;
+typedef Elf_Sxword Elf64_Sxword;
+
+typedef Elf_Xword  Elf64_Off;
+typedef Elf_Xword  Elf64_Addr;
+typedef Elf_Half   Elf64_Section;
+typedef Elf_Xword  Elf64_Bword;
 
 /* Dynamic header */
 
diff --git a/com32/include/sys/elfcommon.h b/com32/include/sys/elfcommon.h
index 29f20943..1ac13805 100644
--- a/com32/include/sys/elfcommon.h
+++ b/com32/include/sys/elfcommon.h
@@ -411,4 +411,12 @@
 
 #define R_X86_64_NUM		38
 
+/* Types common to all ELF variants; proof that <inttypes.h> was overdue */
+typedef uint16_t Elf_Half;
+typedef int16_t  Elf_SHalf;
+typedef uint32_t Elf_Word;
+typedef int32_t  Elf_Sword;
+typedef uint64_t Elf_Xword;
+typedef int64_t  Elf_Sxword;
+
 #endif				/* _SYS_ELFCOMMON_H */
diff --git a/com32/include/sys/module.h b/com32/include/sys/module.h
index 8e48fb2d..7c0fe373 100644
--- a/com32/include/sys/module.h
+++ b/com32/include/sys/module.h
@@ -7,20 +7,21 @@
 #ifndef MODULE_H_
 #define MODULE_H_
 
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <elf.h>
-#include <stdint.h>
+#include <elfutils.h>
 #include <setjmp.h>
-#include <stdbool.h>
 #include <linux/list.h>
 
-#if __SIZEOF_POINTER__ == 4
-#include "module32.h"
-#elif __SIZEOF_POINTER__ == 8
-#include "module64.h"
-#else
-#error "unsupported architecture"
-#endif
+#define MODULE_ELF_CLASS		ELF_CLASS
+#define MODULE_ELF_CLASS_SIZE		ELF_CLASS_SIZE
+#define MODULE_ELF_DATA			ELF_DATA
+#define MODULE_ELF_VERSION		ELF_VERSION
+#define MODULE_ELF_MACHINE		ELF_MACHINE
+#define MODULE_ELF_TYPE			ET_DYN
 
 /*
  * The maximum length of the module file name (including path), stored
@@ -36,6 +37,20 @@
 
 #define MAX_NR_DEPS			64
 
+/**
+ * elf_malloc - Allocates memory to be used by ELF module contents.
+ * @memptr: pointer to a variable to hold the address of the allocated block.
+ * @alignment: alignment constraints of the block
+ * @size: the required size of the block
+ */
+extern int elf_malloc(void **memptr, size_t alignment, size_t size);
+
+/**
+ * elf_free - Releases memory previously allocated by elf_malloc.
+ * @memptr: the address of the allocated block
+ */
+extern void elf_free(void *memptr);
+
 /*
  * Initialization and finalization function signatures
  */
@@ -153,7 +168,7 @@ struct module_dep {
  */
 extern struct elf_module *unload_modules_since(const char *name);
 
-extern FILE *findpath(char *name);
+extern FILE *findpath(const char *name);
 
 
 /**
diff --git a/com32/include/sys/module32.h b/com32/include/sys/module32.h
deleted file mode 100644
index 21988ead..00000000
--- a/com32/include/sys/module32.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * syslinux/module.h
- *
- * Dynamic ELF modules definitions and services.
- */
-
-#ifndef I386_MODULE_H_
-#define I386_MODULE_H_
-
-#include <elf.h>
-
-/*
- * Accepted values for various ELF header parameters found in an ELF dynamic
- * object.
- */
-#define MODULE_ELF_CLASS		ELFCLASS32		// 32-bit modules
-#define MODULE_ELF_CLASS_SIZE		32			// Size of a word value
-#define MODULE_ELF_DATA			ELFDATA2LSB		// Word endianess
-#define MODULE_ELF_VERSION		EV_CURRENT		// Object version
-#define MODULE_ELF_TYPE			ET_DYN			// Executable type (shared object - .so)
-#define MODULE_ELF_MACHINE		EM_386			// Target architecture
-
-#define ELF_MOD_SYS		"32 bit"
-
-typedef Elf32_Addr		Elf_Addr;
-typedef Elf32_Dyn		Elf_Dyn;
-typedef Elf32_Word		Elf_Word;
-typedef Elf32_Off		Elf_Off;
-typedef Elf32_Sym		Elf_Sym;
-typedef Elf32_Ehdr		Elf_Ehdr;
-typedef Elf32_Phdr		Elf_Phdr;
-typedef Elf32_Rel		Elf_Rel;
-typedef Elf32_Word		Elf_Bword;
-
-#endif // I386_MODULE_H_
diff --git a/com32/include/sys/module64.h b/com32/include/sys/module64.h
deleted file mode 100644
index 203a6cd0..00000000
--- a/com32/include/sys/module64.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * syslinux/module.h
- *
- * Dynamic ELF64 modules definitions and services.
- */
-
-#ifndef _X86_64_MODULE_H_
-#define _X86_64_MODULE_H_
-
-#include <elf.h>
-
-/*
- * Accepted values for various ELF header parameters found in an ELF dynamic
- * object.
- */
-#define MODULE_ELF_CLASS		ELFCLASS64		// 64-bit modules
-#define MODULE_ELF_CLASS_SIZE		64			// Size of a word value
-#define MODULE_ELF_DATA			ELFDATA2LSB		// Word endianess
-#define MODULE_ELF_VERSION		EV_CURRENT		// Object version
-#define MODULE_ELF_TYPE			ET_DYN			// Executable type (shared object - .so)
-#define MODULE_ELF_MACHINE		EM_X86_64		// Target architecture
-
-#define ELF_MOD_SYS		"64 bit"
-
-typedef Elf64_Addr		Elf_Addr;
-typedef Elf64_Dyn		Elf_Dyn;
-typedef Elf64_Word		Elf_Word;
-typedef Elf64_Off		Elf_Off;
-typedef Elf64_Sym		Elf_Sym;
-typedef Elf64_Ehdr		Elf_Ehdr;
-typedef Elf64_Phdr		Elf_Phdr;
-typedef Elf64_Rel		Elf_Rel;
-typedef Elf64_Xword		Elf_Bword;
-
-#endif // _X86_64_MODULE_H_
diff --git a/com32/include/syslinux/argv.h b/com32/include/syslinux/argv.h
new file mode 100644
index 00000000..5ef0d121
--- /dev/null
+++ b/com32/include/syslinux/argv.h
@@ -0,0 +1,8 @@
+#ifndef _SYSLINUX_ARGV_H
+#define _SYSLINUX_ARGV_H
+
+#include <klibc/compiler.h>
+
+__extern int parse_argv(char ***argv, const char *str, int reserve);
+
+#endif
diff --git a/com32/include/syslinux/pxe_api.h b/com32/include/syslinux/pxe_api.h
index 37c9cfba..78a09737 100644
--- a/com32/include/syslinux/pxe_api.h
+++ b/com32/include/syslinux/pxe_api.h
@@ -585,11 +585,12 @@ typedef struct s_PXENV_UNLOAD_STACK {
 #define PXENV_STATUS_LOADER_UNDI_START			 0xca
 #define PXENV_STATUS_LOADER_BC_START			 0xcb
 
-int __weak pxe_call(int, void *);
-void __weak unload_pxe(uint16_t flags);
-uint32_t __weak pxe_dns(const char *);
+int pxe_call(int, void *);
+void unload_pxe(uint16_t flags);
+uint32_t pxe_dns(const char *);
 
-extern uint32_t __weak SendCookies;
-void __weak http_bake_cookies(void);
+extern uint32_t SendCookies;
+extern uint8_t KeepPXE;
+void http_bake_cookies(void);
 
 #endif /* _SYSLINUX_PXE_API_H */
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 6a931492..4c9ca6c9 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -2,10 +2,152 @@
 # ONLY INCLUDE MIT OR 2/3-BSD-LICENSED CODE IN THIS LIBRARY
 #
 
-# Include configuration rules
 NOGPL := 1
+include $(MAKEDIR)/elf.mk
+
+ARCH_MATH_OBJS = \
+	$(patsubst $(com32)/lib/%.c,%.o,$(wildcard $(com32)/lib/$(ARCH)/math/*.c)) \
+	$(patsubst $(com32)/lib/%.S,%.o,$(wildcard $(com32)/lib/$(ARCH)/math/*.S))
+
 VPATH = $(SRC)
-include $(MAKEDIR)/lib.mk
+LIBOTHER_OBJS = \
+	atoi.o atol.o atoll.o calloc.o creat.o		\
+	fgets.o fprintf.o fputc.o	\
+	putchar.o				\
+	getopt_common.o getopt.o getopt_long.o				\
+	lrand48.o stack.o memccpy.o memchr.o		\
+	mempcpy.o memmem.o memmove.o memswap.o	\
+	perror.o qsort.o seed48.o \
+	srand48.o sscanf.o						\
+	strerror.o errlist.o		\
+	strnlen.o							\
+	strncat.o strndup.o		\
+	stpncpy.o						\
+	strntoimax.o strsep.o strspn.o strstr.o				\
+	strtoimax.o strtok.o strtol.o strtoll.o strtoull.o		\
+	strtoumax.o vprintf.o vsprintf.o		\
+	asprintf.o vasprintf.o			\
+	vsscanf.o							\
+	skipspace.o							\
+	chrreplace.o							\
+	bufprintf.o							\
+	inet.o dhcppack.o dhcpunpack.o					\
+	strreplace.o							\
+	lstrdup.o						\
+	\
+	suffix_number.o							\
+	\
+	getcwd.o fdopendir.o	\
+	\
+	sys/line_input.o				\
+	sys/colortable.o sys/screensize.o				\
+	\
+	sys/stdcon_read.o sys/stdcon_write.o sys/rawcon_read.o		\
+	sys/rawcon_write.o		\
+	sys/null_read.o sys/null_write.o sys/serial_write.o		\
+	\
+	sys/argv.o							\
+	\
+	sys/xserial_write.o						\
+	\
+	sys/ansi.o							\
+	\
+	sys/ansicon_write.o sys/ansiserial_write.o			\
+	\
+	pci/cfgtype.o pci/scan.o pci/bios.o					\
+	pci/readb.o pci/readw.o pci/readl.o			\
+	pci/writeb.o pci/writew.o pci/writel.o	\
+	\
+	$(ARCH_MATH_OBJS)						\
+	syslinux/disk.o							\
+	\
+	syslinux/setup_data.o
+
+
+##	math/strtod.o
+
+## CORE OBJECTS, INCLUDED IN THE ROOT COM32 MODULE
+LIBENTRY_OBJS = \
+	sys/zeroregs.o	sys/sleep.o					\
+	\
+	sys/fileinfo.o sys/opendev.o sys/read.o sys/write.o sys/ftell.o \
+	sys/close.o sys/open.o sys/fileops.o				\
+	sys/openmem.o							\
+	sys/isatty.o sys/fstat.o					\
+	\
+	dprintf.o vdprintf.o						\
+	\
+	syslinux/idle.o							\
+	\
+	exit.o
+
+LIBGCC_OBJS = \
+	  $(patsubst $(com32)/lib/%.c,%.o,$(wildcard $(com32)/lib/$(ARCH)/libgcc/*.c)) \
+	  $(patsubst $(com32)/lib/%.S,%.o,$(wildcard $(com32)/lib/$(ARCH)/libgcc/*.S))
+
+LIBCONSOLE_OBJS = \
+	\
+	sys/openconsole.o sys/line_input.o				\
+	sys/colortable.o sys/screensize.o				\
+	\
+	sys/stdcon_read.o sys/rawcon_read.o		\
+	sys/rawcon_write.o						\
+	sys/null_write.o sys/serial_write.o		\
+	\
+	sys/xserial_write.o						\
+	\
+	sys/ansi.o							\
+	\
+	sys/ansicon_write.o sys/ansiserial_write.o	\
+	\
+	syslinux/serial.o
+
+LIBLOAD_OBJS = \
+	syslinux/addlist.o syslinux/freelist.o syslinux/memmap.o	\
+	syslinux/movebits.o syslinux/shuffle.o syslinux/shuffle_pm.o	\
+	syslinux/shuffle_rm.o syslinux/biosboot.o syslinux/zonelist.o	\
+	syslinux/dump_mmap.o syslinux/dump_movelist.o			\
+	\
+	syslinux/run_default.o syslinux/run_command.o			\
+	syslinux/cleanup.o syslinux/localboot.o	syslinux/runimage.o	\
+	\
+	syslinux/loadfile.o syslinux/floadfile.o syslinux/zloadfile.o	\
+	\
+	syslinux/load_linux.o syslinux/initramfs.o			\
+	syslinux/initramfs_file.o syslinux/initramfs_loadfile.o		\
+	syslinux/initramfs_archive.o
+
+LIBMODULE_OBJS = \
+	sys/module/common.o sys/module/$(ARCH)/elf_module.o		\
+	sys/module/elfutils.o	\
+	sys/module/exec.o sys/module/elf_module.o
+
+# ZIP library object files
+LIBZLIB_OBJS = \
+	zlib/adler32.o zlib/compress.o zlib/crc32.o			\
+	zlib/uncompr.o zlib/deflate.o zlib/trees.o zlib/zutil.o		\
+	zlib/inflate.o zlib/infback.o zlib/inftrees.o zlib/inffast.o	\
+	sys/zfile.o sys/zfopen.o
+
+CORELIBOBJS = \
+	errno.o memcmp.o printf.o strncmp.o vfprintf.o	\
+	strlen.o vsnprintf.o snprintf.o stpcpy.o strcmp.o strdup.o	\
+	strcpy.o strncpy.o fopen.o fread.o fread2.o puts.o	\
+	strtoul.o strntoumax.o strcasecmp.o				\
+	sprintf.o strlcat.o strchr.o strlcpy.o strncasecmp.o ctypes.o	\
+	fputs.o fwrite2.o fwrite.o fgetc.o fclose.o lmalloc.o		\
+	sys/err_read.o sys/err_write.o sys/null_read.o			\
+	sys/stdcon_write.o						\
+	syslinux/memscan.o strrchr.o strcat.o				\
+	syslinux/debug.o						\
+	$(LIBGCC_OBJS) \
+	$(LIBENTRY_OBJS) \
+	$(LIBMODULE_OBJS)
+
+ifneq ($(FWCLASS),EFI)
+# For EFI, these are part of gnu-efi
+CORELIBOBJS += $(ARCH)/setjmp.o memcpy.o memset.o
+endif
 
 ## OPTIONAL OBJECTS, AVAILABLE AS DYNAMIC LINKED MODULES
 # PNG library object files
@@ -45,7 +187,7 @@ LIBPCI_OBJS = \
 LIBSYSLINUX_OBJS = \
 	syslinux/reboot.o syslinux/keyboard.o				\
 	syslinux/version.o						\
-	syslinux/pxe_get_cached.o syslinux/pxe_get_nic.o		\
+	syslinux/nopxe.o syslinux/pxe_get_cached.o syslinux/pxe_get_nic.o \
 	syslinux/video/fontquery.o syslinux/video/reportmode.o
 
 DYNENTRY_OBJS = \
@@ -73,34 +215,34 @@ DYNLIBOBJS = \
 	$(DYNENTRY_OBJS)
 
 
-LIBOBJS = $(DYNLIBOBJS)
+LIBOBJS  = $(DYNLIBOBJS) $(MINLIBOBJS) $(CORELIBOBJS)
 
-BINDIR   = /usr/bin
-LIBDIR   = /usr/lib
-DATADIR  = /usr/share
-AUXDIR   = $(DATADIR)/syslinux
-INCDIR   = /usr/include
-COM32DIR = $(AUXDIR)/com32
+# Exported from the core; WEAKEN is the list of symbols that should be
+# marked weak as they are only present in some of the core versions.
+WEAKEN  = $(objdir)/core/libcore.weak
 
-all: makeoutputdirs libcom32.c32 libcom32min.a libcom32core.a
+TARGETS = makeoutputdirs libcom32.a
+ifndef PRECORE
+TARGETS += libcom32.c32
+endif
 
-makeoutputdirs:
-	@mkdir -p $(foreach b, \
-		$(addprefix $(OBJ)/,$(sort $(dir $(LIBOBJS) $(MINLIBOBJS) $(CORELIBOBJS)))),$(b))
+all: $(TARGETS)
 
-libcom32.elf : $(LIBOBJS)
-	rm -f $@
-	$(LD) -shared $(LDFLAGS) -soname $(patsubst %.elf,%.c32,$(@F)) -o $@ $^
+makeoutputdirs:
+	@mkdir -p  $(sort $(dir $(LIBOBJS)))
 
-libcom32min.a : $(MINLIBOBJS)
+libcom32.a: $(LIBOBJS)
 	rm -f $@
 	$(AR) cq $@ $^
 	$(RANLIB) $@
 
-libcom32core.a : $(CORELIBOBJS)
-	rm -f $@
-	$(AR) cq $@ $^
-	$(RANLIB) $@
+libcom32.elf : libcom32.a $(LIBLDLINUX) $(LIBCORE)
+	$(LD) $(LDFLAGS) $(SHARED) -o $@ \
+		--whole-archive $< --no-whole-archive $(LIBLDLINUX) $(LIBCORE)
+
+libcom32.c32: libcom32.elf $(WEAKEN)
+	$(OBJCOPY) --strip-debug --strip-unneeded \
+		   --weaken-symbols='$(WEAKEN)' $< $@
 
 tidy dist clean:
 	rm -f sys/vesa/alphatbl.c errlist.c
diff --git a/core/errno.c b/com32/lib/errno.c
similarity index 98%
copy from core/errno.c
copy to com32/lib/errno.c
index adfd92f8..b7558e65 100644
--- a/core/errno.c
+++ b/com32/lib/errno.c
@@ -1,4 +1,3 @@
 #include <klibc/compiler.h>
 #include <errno.h>
-
 __export int errno;
diff --git a/com32/lib/getopt.c b/com32/lib/getopt.c
index 806735d7..4313f1ac 100644
--- a/com32/lib/getopt.c
+++ b/com32/lib/getopt.c
@@ -8,8 +8,6 @@
 #include <unistd.h>
 #include <string.h>
 
-char *optarg;
-int optind, opterr, optopt;
 static struct getopt_private_state {
 	const char *optptr;
 	const char *last_optstring;
diff --git a/com32/lib/getopt_common.c b/com32/lib/getopt_common.c
new file mode 100644
index 00000000..5cd834e0
--- /dev/null
+++ b/com32/lib/getopt_common.c
@@ -0,0 +1,11 @@
+/*
+ * Common definitions for the various getopt variants
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+
+char *optarg;
+int optind, opterr, optopt;
diff --git a/com32/lib/getopt_long.c b/com32/lib/getopt_long.c
index e3d064b0..039f1e4f 100644
--- a/com32/lib/getopt_long.c
+++ b/com32/lib/getopt_long.c
@@ -13,8 +13,6 @@
 #include <string.h>
 #include <getopt.h>
 
-char *optarg;
-int optind, opterr, optopt;
 static struct getopt_private_state {
 	const char *optptr;
 	const char *last_optstring;
diff --git a/com32/lib/i386/libgcc/__muldi3.S b/com32/lib/i386/libgcc/__muldi3.S
index 424787c8..5f0da638 100644
--- a/com32/lib/i386/libgcc/__muldi3.S
+++ b/com32/lib/i386/libgcc/__muldi3.S
@@ -9,19 +9,8 @@
 	.globl __muldi3
 	.type __muldi3, at function
 __muldi3:
-#if __SIZEOF_POINTER__ == 4
 	/* i386 */
 	push  %esi
-#ifndef REGPARM
-	movl  8(%esp),%eax
-	movl  %eax,%esi
-	movl  16(%esp),%ecx
-	mull  %ecx
-	imull 12(%esp),%ecx
-	imull 20(%esp),%esi
-	addl  %ecx,%edx
-	addl  %esi,%edx
-#else
 	movl  %eax,%esi
 	push  %edx
 	mull  %ecx
@@ -30,54 +19,6 @@ __muldi3:
 	pop   %esi
 	imull %esi,%ecx
 	addl  %ecx,%edx
-#endif
 	pop   %esi
 	ret
-#elif __SIZEOF_POINTER__ == 8
-	/* x86_64 */
-	push  %rsi
-#ifndef REGPARM
-/*
-	movl  8(%esp),%eax
-	movl %eax,%esi
-	movl  16(%esp),%ecx
-	mull  %ecx
-	imull 12(%esp),%ecx
-	imull 20(%esp),%esi
-	addl  %ecx,%edx
-	addl  %esi,%edx
-*/
-	movq  8(%rsp),%rax
-	movq %rax,%rsi
-	movq  16(%rsp),%rcx
-	mulq  %rcx
-	imulq 12(%rsp),%rcx
-	imulq 20(%rsp),%rsi
-	addq  %rcx,%rdx
-	addq  %rsi,%rdx
-#else
-/*
-	movl  %eax,%esi
-	push  %edx
-	mull  %ecx
-	imull 8(%esp),%esi
-	addl  %esi,%edx
-	pop   %rsi
-	imull %esi,%ecx
-	addl  %ecx,%edx
-*/
-	movq  %rax,%rsi
-	pushq  %rdx
-	mulq  %rcx
-	imulq 8(%rsp),%rsi
-	addq  %rsi,%rdx
-	popq  %rsi
-	imulq %rsi,%rcx
-	addq  %rcx,%rdx
-#endif
-	pop   %rsi
-	ret
-#else
-#error "Unsupported architecture for __muldi3.S"
-#endif
 	.size __muldi3,.-__muldi3
diff --git a/com32/lib/sys/argv.c b/com32/lib/sys/argv.c
index db287c2b..da728a14 100644
--- a/com32/lib/sys/argv.c
+++ b/com32/lib/sys/argv.c
@@ -35,25 +35,26 @@
 
 #include <inttypes.h>
 #include <stddef.h>
-#include <stdio.h>
-#include <syslinux/align.h>
-#include <com32.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslinux/argv.h>
 
-extern char _end[];		/* Symbol created by linker */
-void *__mem_end = &_end;	/* Global variable for use by malloc() */
-
-int __parse_argv(char ***argv, const char *str)
+int parse_argv(char ***argv, const char *str, int reserve)
 {
     char dummy_argv0[] = "";
-    char *mem = __mem_end;
+    char *mem = NULL;
     const char *p = str;
     char *q = mem;
     char *r;
-    char **arg;
+    char **arg = NULL;
     int wasspace = 1;
-    int argc = 1;
+    int argc = reserve;
 
     /* First copy the string, turning whitespace runs into nulls */
+    mem = malloc(strlen(str) + 1);
+    if (!mem)
+	goto fail;
+
     for (p = str;; p++) {
 	if (*p <= ' ') {
 	    if (!wasspace) {
@@ -76,9 +77,12 @@ int __parse_argv(char ***argv, const char *str)
     }
 
     /* Now create argv */
-    arg = (char **)ALIGN_UP_FOR(q, char *);
-    *argv = arg;
-    *arg++ = __com32.cs_name ? (char *)__com32.cs_name : dummy_argv0; /* argv[0] */
+    arg = malloc((argc+1) * sizeof(*arg));
+    if (!arg)
+	goto fail;
+
+    memset(arg, 0, reserve * sizeof(*arg));
+    arg += reserve;
 
     q--;			/* Point q to final null */
     if (mem < q)
@@ -91,7 +95,14 @@ int __parse_argv(char ***argv, const char *str)
     }
 
     *arg++ = NULL;		/* Null pointer at the end */
-    __mem_end = arg;		/* End of memory we used */
+    *argv = arg;
 
     return argc;
+
+fail:
+    if (arg)
+	free(arg);
+    if (mem)
+	free(mem);
+    return -1;
 }
diff --git a/com32/lib/sys/cfarcall.c b/com32/lib/sys/cfarcall.c
deleted file mode 100644
index fca818b2..00000000
--- a/com32/lib/sys/cfarcall.c
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * cfarcall.c
- */
-
-#include <com32.h>
-
-int __cfarcall(uint16_t cs, uint16_t ip, const void *stack, uint32_t stack_size)
-{
-    return __com32.cs_cfarcall((cs << 16) + ip, stack, stack_size);
-}
diff --git a/com32/lib/sys/entry.S b/com32/lib/sys/entry.S
deleted file mode 100644
index 7bfde8b2..00000000
--- a/com32/lib/sys/entry.S
+++ /dev/null
@@ -1,118 +0,0 @@
-/* -----------------------------------------------------------------------
- *
- *   Copyright 2003-2008 H. Peter Anvin - All Rights Reserved
- *
- *   Permission is hereby granted, free of charge, to any person
- *   obtaining a copy of this software and associated documentation
- *   files (the "Software"), to deal in the Software without
- *   restriction, including without limitation the rights to use,
- *   copy, modify, merge, publish, distribute, sublicense, and/or
- *   sell copies of the Software, and to permit persons to whom
- *   the Software is furnished to do so, subject to the following
- *   conditions:
- *
- *   The above copyright notice and this permission notice shall
- *   be included in all copies or substantial portions of the Software.
- *
- *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *   OTHER DEALINGS IN THE SOFTWARE.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * COM32 start up code - must be linked first in the binary
- */
-
-/* Number of arguments in our version of the entry structure */
-#define COM32_ARGS 9
-
-		.section ".init","ax"
-		.globl _start
-		.type _start, @function
-_start:
-		/* This first instruction acts as COM32R magic number */
-		movl $0x21cd4cfe,%eax
-
-		/* Upwards string operations */
-		cld
-
-		/* Find our own location */
-		call 1f
-1:		popl %ebx
-		addl $_GLOBAL_OFFSET_TABLE_ + (. - 1b), %ebx
-	
-		/* Process relocations (which overlay the .bss segment) */
-		leal _edata at GOTOFF(%ebx),%esi
-		leal _start at GOTOFF(%ebx),%edx
-2:		lodsl
-		andl %eax,%eax
-		jz 3f
-		addl %edx,(%eax,%edx)
-		jmp 2b
-3:
-		/* Relocate the GOT (is this right?) */
-		leal __got_start at GOTOFF(%ebx),%esi
-		leal __got_end at GOTOFF(%ebx),%edi
-4:
-		addl %edx,(%esi)
-		addl $4,%esi
-		cmpl %edi,%esi
-		jb 4b
-	
-		/* Zero the .bss segment */
-		xorl %eax,%eax
-		leal __bss_start at GOTOFF(%ebx),%edi
-		leal _end+3 at GOTOFF(%ebx),%ecx
-		subl %edi,%ecx
-		shrl $2,%ecx
-		rep ; stosl
-
-		/* Copy COM32 invocation parameters */
-		leal 4(%esp),%esi		# Argument list
-		leal __com32 at GOTOFF(%ebx),%edi
-		movl $(COM32_ARGS),%ecx
-		movl %esp,-4(%edi)		# Save the initial stack ptr
-		cmpl (%esi),%ecx
-		jbe 5f
-		movl (%esi),%ecx
-5:		inc %ecx			# Copy the argument count, too
-		rep ; movsl
-
-		/* Parse the command line (assumes REGPARM) */
-		movl __com32+4 at GOTOFF(%ebx),%edx	# Command line
-		pushl %edx				# Make space for argv
-		movl %esp,%eax
-		call __parse_argv
-		pushl %eax				# Save argc
-
-		/* Look for library initialization functions */
-		leal __ctors_start at GOTOFF(%ebx),%esi
-		leal __ctors_end at GOTOFF(%ebx),%edi
-6:
-		cmpl %edi,%esi
-		jae 7f
-		call *(%esi)
-		addl $4,%esi
-		jmp 6b
-/*
- * Actually run main.  This assumes REGPARM is used!!!!
- */
-7:
-		popl %eax			# argc
-		popl %edx			# argv
-		call main
-		call *__exit_handler at GOTOFF(%ebx)
-		hlt
-		.size _start, .-_start
-
-		.bss
-		.globl __entry_esp
-__entry_esp:	.space 4
-		.globl __com32
-__com32:	.space 4*(COM32_ARGS+1)
diff --git a/com32/lib/sys/farcall.c b/com32/lib/sys/farcall.c
deleted file mode 100644
index 2749083e..00000000
--- a/com32/lib/sys/farcall.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * farcall.c
- */
-
-#include <com32.h>
-
-static inline uint32_t eflags(void)
-{
-    //uint32_t v;
-
-#if __SIZEOF_POINTER__ == 4
-    uint32_t v;
-    asm volatile("pushfl ; popl %0" : "=rm" (v));
-#elif __SIZEOF_POINTER__ == 8
-    uint64_t v;
-    asm volatile("pushfq ; pop %0" : "=rm" (v));
-#else
-#error "Unable to build for to-be-defined architecture type"
-#endif
-    return v;
-}
-
-void __farcall(uint16_t cs, uint16_t ip,
-	       const com32sys_t * ireg, com32sys_t * oreg)
-{
-    com32sys_t xreg = *ireg;
-
-    /* Enable interrupts if and only if they are enabled in the caller */
-    xreg.eflags.l = (xreg.eflags.l & ~EFLAGS_IF) | (eflags() & EFLAGS_IF);
-
-    __com32.cs_farcall((cs << 16) + ip, &xreg, oreg);
-}
diff --git a/core/include/localboot.h b/com32/lib/sys/file_dev.c
similarity index 87%
copy from core/include/localboot.h
copy to com32/lib/sys/file_dev.c
index 4bb79a6a..803d7da1 100644
--- a/core/include/localboot.h
+++ b/com32/lib/sys/file_dev.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 2012 Paulo Alcantara <pcacjr at zytor.com>
+ *   Copyright 2003-2008 H. Peter Anvin - All Rights Reserved
  *
  *   Permission is hereby granted, free of charge, to any person
  *   obtaining a copy of this software and associated documentation
@@ -25,9 +25,11 @@
  *
  * ----------------------------------------------------------------------- */
 
-#ifndef LOCALBOOT_H_
-#define LOCALBOOT_H_
+/*
+ * Operations structure for an ordinary file (after open)
+ */
 
-extern void local_boot(int16_t ax);
+#include <fcntl.h>
+#include <fs.h>
+#include "file.h"
 
-#endif /* LOCALBOOT_H_ */
diff --git a/com32/lib/sys/fileclose.c b/com32/lib/sys/fileclose.c
deleted file mode 100644
index 699dbe32..00000000
--- a/com32/lib/sys/fileclose.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- *   Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
- *
- *   Permission is hereby granted, free of charge, to any person
- *   obtaining a copy of this software and associated documentation
- *   files (the "Software"), to deal in the Software without
- *   restriction, including without limitation the rights to use,
- *   copy, modify, merge, publish, distribute, sublicense, and/or
- *   sell copies of the Software, and to permit persons to whom
- *   the Software is furnished to do so, subject to the following
- *   conditions:
- *
- *   The above copyright notice and this permission notice shall
- *   be included in all copies or substantial portions of the Software.
- *
- *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *   OTHER DEALINGS IN THE SOFTWARE.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * fileclose.c
- *
- * Close an ordinary file
- */
-
-#include <errno.h>
-#include <com32.h>
-#include <string.h>
-#include <fs.h>
-#include "file.h"
-
-int __file_close(struct file_info *fp)
-{
-    if (fp->i.fd.handle)
-	close_file(fp->i.fd.handle);
-
-    return 0;
-}
diff --git a/com32/lib/sys/fileread.c b/com32/lib/sys/fileops.c
similarity index 88%
rename from com32/lib/sys/fileread.c
rename to com32/lib/sys/fileops.c
index 26b0ceb6..b5c618fe 100644
--- a/com32/lib/sys/fileread.c
+++ b/com32/lib/sys/fileops.c
@@ -26,9 +26,7 @@
  * ----------------------------------------------------------------------- */
 
 /*
- * read.c
- *
- * Reading from a file
+ * Operations on an ordinary file
  */
 
 #include <errno.h>
@@ -97,3 +95,20 @@ ssize_t __file_read(struct file_info * fp, void *buf, size_t count)
 
     return n;
 }
+
+int __file_close(struct file_info *fp)
+{
+    if (fp->i.fd.handle)
+	close_file(fp->i.fd.handle);
+
+    return 0;
+}
+
+const struct input_dev __file_dev = {
+    .dev_magic = __DEV_MAGIC,
+    .flags = __DEV_FILE | __DEV_INPUT,
+    .fileflags = O_RDONLY,
+    .read = __file_read,
+    .close = __file_close,
+    .open = NULL,
+};
diff --git a/com32/lib/sys/intcall.c b/com32/lib/sys/intcall.c
deleted file mode 100644
index e97a3841..00000000
--- a/com32/lib/sys/intcall.c
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * intcall.c
- */
-
-#include <com32.h>
-
-void __intcall(uint8_t vector, const com32sys_t * ireg, com32sys_t * oreg)
-{
-    __com32.cs_intcall(vector, ireg, oreg);
-}
diff --git a/com32/lib/sys/libansi.c b/com32/lib/sys/libansi.c
index a011cb87..caf49aa2 100644
--- a/com32/lib/sys/libansi.c
+++ b/com32/lib/sys/libansi.c
@@ -116,6 +116,11 @@ void clear_entire_screen(void)
 	fputs(CSI "2J", stdout);
 }
 
+void gotoxy(int row, int col)
+{
+	printf(CSI "%d;%dH", row + 1, col + 1);
+}
+
 /**
  * cprint_vga2ansi - given a VGA attribute, print a character
  * @chr:	character to print
@@ -126,7 +131,7 @@ void clear_entire_screen(void)
  * For performance, SGR parameters are cached. To reset them,
  * call cprint_vga2ansi('0', '0').
  **/
-static void cprint_vga2ansi(const char chr, const char attr)
+static void cprint_vga2ansi(char chr, unsigned char attr)
 {
 	static const char ansi_char[8] = "04261537";
 	static uint16_t last_attr = 0x300;
@@ -209,7 +214,7 @@ void reset_colors(void)
  *
  * Note: @attr is a VGA attribute.
  **/
-void cprint(const char chr, const char attr, unsigned int times)
+void cprint(char chr, unsigned char attr, unsigned int times)
 {
 	while (times--)
 		cprint_vga2ansi(chr, attr);
@@ -220,7 +225,7 @@ void cprint(const char chr, const char attr, unsigned int times)
  * @str:	string to print
  * @attr:	VGA attribute
  **/
-void csprint(const char *str, const char attr)
+void csprint(const char *str, unsigned char attr)
 {
 	while (*str) {
 		cprint(*str, attr, 1);
@@ -234,10 +239,10 @@ void csprint(const char *str, const char attr)
  * @fillchar:			character to use to fill the region
  * @fillattr:			character attribute (VGA)
  **/
-void clearwindow(const char top, const char left, const char bot,
-		 const char right, const char fillchar, const char fillattr)
+void clearwindow(int top, int left, int bot,
+		 int right, char fillchar, unsigned char fillattr)
 {
-	char x;
+	int x;
 	for (x = top; x < bot + 1; x++) {
 		gotoxy(x, left);
 		cprint(fillchar, fillattr, right - left + 1);
diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c
index 05a27e85..bfafc1ed 100644
--- a/com32/lib/sys/module/common.c
+++ b/com32/lib/sys/module/common.c
@@ -57,7 +57,7 @@ void print_elf_symbols(struct elf_module *module) {
 }
 #endif //ELF_DEBUG
 
-FILE *findpath(char *name)
+FILE *findpath(const char *name)
 {
 	struct path_entry *entry;
 	char path[FILENAME_MAX];
diff --git a/com32/lib/sys/module/elfutils.c b/com32/lib/sys/module/elfutils.c
index b7d760b4..4dce3c82 100644
--- a/com32/lib/sys/module/elfutils.c
+++ b/com32/lib/sys/module/elfutils.c
@@ -63,9 +63,9 @@ int elf_malloc(void **memptr, size_t alignment, size_t size) {
 	return 0;
 }
 
-void elf_free(char *memptr) {
-	struct memalign_info *info = (struct memalign_info*)(memptr -
-			sizeof(struct memalign_info));
+void elf_free(void *memptr) {
+    struct memalign_info *info = (struct memalign_info*)
+	((char *)memptr - sizeof(struct memalign_info));
 
 	free(info->start_addr);
 }
diff --git a/com32/lib/sys/module/elfutils.h b/com32/lib/sys/module/elfutils.h
deleted file mode 100644
index 91bdcb3f..00000000
--- a/com32/lib/sys/module/elfutils.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef ELF_UTILS_H_
-#define ELF_UTILS_H_
-
-#include <elf.h>
-#include <stdlib.h>
-#include <sys/module.h>
-
-/**
- * elf_get_header - Returns a pointer to the ELF header structure.
- * @elf_image: pointer to the ELF file image in memory
- */
-static inline Elf_Ehdr *elf_get_header(void *elf_image) {
-	return (Elf_Ehdr*)elf_image;
-}
-
-/**
- * elf_get_pht - Returns a pointer to the first entry in the PHT.
- * @elf_image: pointer to the ELF file image in memory
- */
-static inline Elf_Phdr *elf_get_pht(void *elf_image) {
-	Elf_Ehdr *elf_hdr = elf_get_header(elf_image);
-
-	return (Elf_Phdr*)((Elf_Off)elf_hdr + elf_hdr->e_phoff);
-}
-
-//
-/**
- * elf_get_ph - Returns the element with the given index in the PTH
- * @elf_image: pointer to the ELF file image in memory
- * @index: the index of the PHT entry to look for
- */
-static inline Elf_Phdr *elf_get_ph(void *elf_image, int index) {
-	Elf_Phdr *elf_pht = elf_get_pht(elf_image);
-	Elf_Ehdr *elf_hdr = elf_get_header(elf_image);
-
-	return (Elf_Phdr*)((Elf_Off)elf_pht + index * elf_hdr->e_phentsize);
-}
-
-/**
- * elf_hash - Returns the index in a SysV hash table for the symbol name.
- * @name: the name of the symbol to look for
- */
-extern unsigned long elf_hash(const unsigned char *name);
-
-/**
- * elf_gnu_hash - Returns the index in a GNU hash table for the symbol name.
- * @name: the name of the symbol to look for
- */
-extern unsigned long elf_gnu_hash(const unsigned char *name);
-
-/**
- * elf_malloc - Allocates memory to be used by ELF module contents.
- * @memptr: pointer to a variable to hold the address of the allocated block.
- * @alignment: alignment constraints of the block
- * @size: the required size of the block
- */
-extern int elf_malloc(void **memptr, size_t alignment, size_t size);
-
-/**
- * elf_free - Releases memory previously allocated by elf_malloc.
- * @memptr: the address of the allocated block
- */
-extern void elf_free(char *memptr);
-
-#endif /*ELF_UTILS_H_*/
diff --git a/com32/lib/sys/open.c b/com32/lib/sys/open.c
index 1ed5bb4c..cde59f9a 100644
--- a/com32/lib/sys/open.c
+++ b/com32/lib/sys/open.c
@@ -42,15 +42,6 @@
 extern ssize_t __file_read(struct file_info *, void *, size_t);
 extern int __file_close(struct file_info *);
 
-const struct input_dev __file_dev = {
-    .dev_magic = __DEV_MAGIC,
-    .flags = __DEV_FILE | __DEV_INPUT,
-    .fileflags = O_RDONLY,
-    .read = __file_read,
-    .close = __file_close,
-    .open = NULL,
-};
-
 int open(const char *pathname, int flags, ...)
 {
     int fd, handle;
diff --git a/com32/lib/sys/openmem.c b/com32/lib/sys/openmem.c
index a56a4af8..8ad1c35c 100644
--- a/com32/lib/sys/openmem.c
+++ b/com32/lib/sys/openmem.c
@@ -38,8 +38,6 @@
  * Open a chunk of memory as if it was a file
  */
 
-const struct input_dev __file_dev;
-
 int openmem(const void *base, size_t len, int flags)
 {
     int fd;
diff --git a/com32/lib/syslinux/cleanup.c b/com32/lib/syslinux/cleanup.c
index 7d8581e4..0d6a5e3c 100644
--- a/com32/lib/syslinux/cleanup.c
+++ b/com32/lib/syslinux/cleanup.c
@@ -33,8 +33,6 @@
 
 void syslinux_final_cleanup(uint16_t flags)
 {
-    if (syslinux_filesystem() == SYSLINUX_FS_PXELINUX)
-	unload_pxe(flags);
-
+    unload_pxe(flags);
     cleanup_hardware();
 }
diff --git a/com32/lib/syslinux/idle.c b/com32/lib/syslinux/idle.c
index 33e8035c..722b9cf6 100644
--- a/com32/lib/syslinux/idle.c
+++ b/com32/lib/syslinux/idle.c
@@ -37,11 +37,19 @@
 #include <syslinux/pmapi.h>
 #include <syslinux/idle.h>
 
+void __weak reset_idle(void)
+{
+}
+
 void syslinux_reset_idle(void)
 {
     reset_idle();
 }
 
+void __weak __idle(void)
+{
+}
+
 void syslinux_idle(void)
 {
     __idle();
diff --git a/com32/lib/syslinux/load_linux.c b/com32/lib/syslinux/load_linux.c
index 0edb7712..f7a57dc2 100644
--- a/com32/lib/syslinux/load_linux.c
+++ b/com32/lib/syslinux/load_linux.c
@@ -49,6 +49,7 @@
 #include <syslinux/firmware.h>
 #include <syslinux/video.h>
 #include <syslinux/config.h>
+#include <syslinux/pxe_api.h>	/* For KeepPXE */
 
 #define BOOT_MAGIC 0xAA55
 #define LINUX_MAGIC ('H' + ('d' << 8) + ('r' << 16) + ('S' << 24))
@@ -202,10 +203,7 @@ int bios_boot_linux(void *kernel_buf, size_t kernel_size,
 	}
     }
 
-    if (syslinux_filesystem() == SYSLINUX_FS_PXELINUX &&
-	strstr(cmdline, "keeppxe")) {
-	extern __weak char KeepPXE;
-
+    if (strstr(cmdline, "keeppxe")) {
 	KeepPXE |= 1;		/* for pxelinux_scan_memory */
 	bootflags = 3;		/* for unload_pxe */
     }
diff --git a/com32/lib/syslinux/nopxe.c b/com32/lib/syslinux/nopxe.c
new file mode 100644
index 00000000..b96bd16c
--- /dev/null
+++ b/com32/lib/syslinux/nopxe.c
@@ -0,0 +1,31 @@
+/*
+ * Dummy implementation of the PXE API, for non-PXE cores
+ */
+
+#include <syslinux/pxe_api.h>
+
+int __weak pxe_call(int func, void *ptr)
+{
+    (void)func;
+    (void)ptr;
+
+    return PXENV_STATUS_UNSUPPORTED;
+}
+
+void __weak unload_pxe(uint16_t flags)
+{
+    (void)flags;
+}
+
+uint32_t __weak pxe_dns(const char *str)
+{
+    (void)str;
+    return 0;			/* Not found */
+}
+
+uint32_t __weak SendCookies;
+uint8_t  __weak KeepPXE;
+
+void __weak http_bake_cookies(void)
+{
+}
diff --git a/com32/lib/syslinux/version.c b/com32/lib/syslinux/version.c
index 6f0554d5..9cb53ac0 100644
--- a/com32/lib/syslinux/version.c
+++ b/com32/lib/syslinux/version.c
@@ -28,13 +28,12 @@
 #include <syslinux/config.h>
 #include <klibc/compiler.h>
 #include <core.h>
-#include <version.h>
 
 struct syslinux_version __syslinux_version;
 
 void __constructor __syslinux_get_version(void)
 {
-    __syslinux_version.version = (VERSION_MAJOR << 8) + VERSION_MINOR;
+    __syslinux_version.version = syslinux_version;
 
     /* We no longer support the COMBOOT API  */
     __syslinux_version.max_api = 0xffff;
diff --git a/com32/libupload/Makefile b/com32/libupload/Makefile
index db5a8c41..df5a5341 100644
--- a/com32/libupload/Makefile
+++ b/com32/libupload/Makefile
@@ -1,6 +1,6 @@
 # Include configuration rules
 VPATH = $(SRC)
-include $(MAKEDIR)/lib.mk
+include $(MAKEDIR)/elf.mk
 
 REQFLAGS += -I$(SRC) -I$(topdir)/core
 
diff --git a/com32/libutil/Makefile b/com32/libutil/Makefile
index 094f1ff5..6100fca4 100644
--- a/com32/libutil/Makefile
+++ b/com32/libutil/Makefile
@@ -29,7 +29,6 @@
 ## Utility companion library for the COM32 library
 ##
 
-VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
 LIBOBJS	   = ansiline.o ansiraw.o keyname.o \
@@ -37,16 +36,12 @@ LIBOBJS	   = ansiline.o ansiraw.o keyname.o \
 	     md5.o crypt-md5.o sha256crypt.o sha512crypt.o base64.o \
 	     quicksort.o
 LNXLIBOBJS = $(patsubst %.o,%.lo,$(LIBOBJS))
+DEPLIBS    = $(LIBCOM32) $(LIBLDLINUX) $(LIBCORE)
 
-all: libutil.c32 libutil_lnx.a
+all: libutil.c32
 
 libutil.elf: $(LIBOBJS)
-	$(LD) $(LDFLAGS) -soname $(patsubst %.elf,%.c32,$(@F)) -o $@ $^
-
-libutil_lnx.a: $(LNXLIBOBJS)
-	rm -f $@
-	$(AR) cq $@ $(LNXLIBOBJS)
-	$(RANLIB) $@
+	$(LD) $(LDFLAGS) $(SHARED) -o $@ $(LIBOBJS) $(DEPLIBS)
 
 tidy dist:
 	rm -f *.o *.lo *.lst *.elf .*.d *.tmp
@@ -59,7 +54,5 @@ spotless: clean
 	rm -f *~ \#*
 
 install: all
-	mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR)
-	install -m 644 libutil_lnx.a $(INSTALLROOT)$(COM32DIR)
 
 -include .*.d
diff --git a/com32/lua/src/Makefile b/com32/lua/src/Makefile
index c8a141f5..f585b6b0 100644
--- a/com32/lua/src/Makefile
+++ b/com32/lua/src/Makefile
@@ -15,7 +15,6 @@
 ## Lua Makefile
 ##
 
-VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
 LNXLIBS	   = 
@@ -38,6 +37,7 @@ TESTFILES =
 OBJS	  = lua.o
 
 LIBLUA    = liblua.c32
+EXTRALIBS = $(LIBLUA)
 
 LIBLUA_OBJS := lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o
 LIBLUA_OBJS += lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o
@@ -48,17 +48,15 @@ LIBLUA_OBJS += loslib.o lstrlib.o ltablib.o loadlib.o linit.o
 
 CFLAGS += -DLUA_ANSI
 
-all: $(MODULES) $(TESTFILES)
+all: $(LIBLUA) $(MODULES) $(TESTFILES)
 
-liblua.elf : $(LIBLUA_OBJS)
-	$(LD) $(LDFLAGS) -shared -soname $(patsubst %.elf,%.c32,$(@F)) \
-		-o $@ $^
+liblua.elf : $(LIBLUA_OBJS) $(C_LIBS)
+	$(LD) $(LDFLAGS) $(SHARED) -o $@ $^
 
-lua.elf : $(OBJS) $(LIBLUA) $(C_LIBS)
-	$(LD) $(LDFLAGS) -o $@ $^
+LIBMENU = $(objdir)/com32/cmenu/libmenu/libmenu.c32
 
 cmenu.o : CFLAGS += -I$(com32)/cmenu/libmenu
-cmenu.elf : $(objdir)/com32/cmenu/libmenu/libmenu.c32
+cmenu.elf : EXTRALIBS += $(LIBMENU)
 
 tidy dist:
 	rm -f *.o *.lo *.lst *.elf .*.d *.tmp
diff --git a/com32/lua/src/syslinux.c b/com32/lua/src/syslinux.c
index 9a2998b9..22619eb0 100644
--- a/com32/lua/src/syslinux.c
+++ b/com32/lua/src/syslinux.c
@@ -36,13 +36,12 @@
 #include "lua.h"
 #include "lauxlib.h"
 #include "lualib.h"
-#include "syslinux/boot.h"
-#include "syslinux/loadfile.h"
-#include "syslinux/linux.h"
-#include "syslinux/config.h"
-#include "syslinux/reboot.h"
-
-int __parse_argv(char ***argv, const char *str);
+#include <syslinux/boot.h>
+#include <syslinux/loadfile.h>
+#include <syslinux/linux.h>
+#include <syslinux/config.h>
+#include <syslinux/reboot.h>
+#include <syslinux/argv.h>
 
 static const char SYSLINUX_FILE[] = "syslinux_file";
 static const char SYSLINUX_INITRAMFS[] = "syslinux_initramfs";
@@ -147,7 +146,7 @@ static int sl_boot_linux(lua_State * L)
     int ret;
     char **argv, **argp, *arg, *p;
 
-    ret = __parse_argv(&argv, cmdline);
+    ret = parse_argv(&argv, cmdline, 1);
 
     newcmdline = malloc(strlen(kernel) + 12);
     if (!newcmdline)
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index c01d6338..526f5495 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -39,12 +39,8 @@ TESTFILES =
 
 all: $(MODULES) $(TESTFILES)
 
-.PRECIOUS: %.o
-dmitest.o: dmitest.c
-	$(CC) $(CFLAGS) $(GPLINCLUDE) -c -o $@ $<
-
-dmitest.elf : dmi_utils.o dmitest.o $(C_LIBS)
-	$(LD) $(LDFLAGS) -o $@ $^
+OBJS_dmitest = dmi_utils.o
+dmi_utils.elf: $(OBJS_dmitest)
 
 tidy dist:
 	rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp
diff --git a/com32/modules/zzjson.c b/com32/modules/zzjson.c
index a126b8f0..d62d70ef 100644
--- a/com32/modules/zzjson.c
+++ b/com32/modules/zzjson.c
@@ -43,7 +43,7 @@ int main(int argc, char *argv[])
         ZZJSON *tmp2;
 
         tmp = zzjson_create_array(&config,
-                zzjson_create_number_d(&config, 3.14),
+		/* zzjson_create_number_d(&config, 3.14), */
                 zzjson_create_number_i(&config, 1234LL),
                 zzjson_create_number_i(&config, -4321LL),
                 zzjson_create_true(&config),
diff --git a/com32/samples/Makefile b/com32/samples/Makefile
index 06e9684b..6dfbdfe8 100644
--- a/com32/samples/Makefile
+++ b/com32/samples/Makefile
@@ -14,16 +14,10 @@
 ## samples for syslinux users
 ##
 
-LIBS = $(objdir)/com32/libutil/libutil.c32
-
-VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
-all:	hello.c32 resolv.c32 serialinfo.c32 \
-		localboot.c32 \
-		fancyhello.c32 fancyhello.lnx \
-		keytest.c32 keytest.lnx \
-		advdump.c32 entrydump.c32
+all:	hello.c32 resolv.c32 serialinfo.c32 localboot.c32 \
+	fancyhello.c32 keytest.c32 advdump.c32 entrydump.c32
 
 tidy dist:
 	rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp
diff --git a/com32/sysdump/memory.c b/com32/sysdump/memory.c
index 5efd9ee7..3831b0ae 100644
--- a/com32/sysdump/memory.c
+++ b/com32/sysdump/memory.c
@@ -9,15 +9,12 @@
 #include "sysdump.h"
 
 static char *lowmem;
-static size_t lowmem_len;
+static const size_t lowmem_len = 640*1024;
 
 void *zero_addr;		/* Hack to keep gcc from complaining */
 
 void snapshot_lowmem(void)
 {
-    extern void _start(void);
-
-    lowmem_len = (size_t)_start;
     lowmem = malloc(lowmem_len);
     if (lowmem) {
 	printf("Snapshotting lowmem... ");
diff --git a/core/Makefile b/core/Makefile
index fc608e51..e1a34da9 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -15,20 +15,12 @@
 # Makefile for the SYSLINUX core
 #
 
-VPATH = $(SRC)
-
-# No builtin rules
-MAKEFLAGS += -r
-MAKE      += -r
-
-include $(MAKEDIR)/embedded.mk
+include $(MAKEDIR)/elf.mk
 -include $(objdir)/version.mk
 
-OPTFLAGS =
-INCLUDES = -I$(SRC)/include -I$(com32)/include -I$(com32)/include/sys \
-	   -I$(com32)/lib \
-	   -I$(SRC)/bios/lwip/src/include \
-	   -I$(SRC)/bios/lwip/src/include/ipv4 -I$(SRC)/fs/pxe
+INCLUDE  += -I$(SRC)/include -I$(com32)/lib \
+	    -I$(SRC)/bios/lwip/src/include \
+	    -I$(SRC)/bios/lwip/src/include/ipv4 -I$(SRC)/fs/pxe
 
 # This is very similar to cp437; technically it's for Norway and Denmark,
 # but it's unlikely the characters that are different will be used in
@@ -39,6 +31,12 @@ CODEPAGE = cp865
 BTARGET  = kwdhash.gen ldlinux.bss ldlinux.sys \
 	   isolinux.bin isolinux-debug.bin pxelinux.0 lpxelinux.0
 
+# The corresponding ELF files
+ETARGET  = $(patsubst $(SRC)/%-c.c,%.elf,$(wildcard $(SRC)/bios/*-c.c))
+
+# Export library files
+LIBCORE_FILES = libcore.so libcore.weak
+
 # All primary source files for the main syslinux files
 NASMSRC	 := $(sort $(shell find $(SRC) -name '*.asm' -print))
 NASMHDR	 := $(sort $(shell find $(SRC) -name '*.inc' -print))
@@ -81,18 +79,18 @@ FILTER_OBJS = $(patsubst $(SRC)/%,%/%,$(FILTER_DIRS))
 COBJS	 = $(filter-out $(FILTER_OBJS),$(COBJ))
 SOBJS	 = $(filter-out $(FILTER_OBJS),$(SOBJ))
 
-LIB	 = bios/libsyslinux.a
-LIBS	 = $(LIB) --whole-archive $(objdir)/com32/lib/libcom32core.a
-LIBDEP   = $(filter-out -% %start%,$(LIBS))
-LIBOBJS	 = $(COBJS) $(SOBJS)
-
-NASMDEBUG = -g -F dwarf
-NASMOPT  += $(NASMDEBUG)
+CORE_LIB	= bios/libsyslinux.a
+CORE_LIBS	= $(CORE_LIB) $(objdir)/com32/lib/libcom32.a
+CORE_LIBOBJS	 = $(COBJS) $(SOBJS)
 
 PREPCORE = $(OBJ)/../lzo/prepcore
 
-CFLAGS += -D__SYSLINUX_CORE__ -D__FIRMWARE_$(FIRMWARE)__ \
-	  -I$(objdir) -DLDLINUX=\"$(LDLINUX)\"
+# This makes the core quite a bit smaller, but requires that the proper
+# __export tags are in place. It would be very good to add the same things
+# to the libraries, especially libcom32, for the same reason.
+CFLAGS += -fvisibility=hidden
+
+CFLAGS += -D__SYSLINUX_CORE__ -I$(objdir)
 
 # The DATE is set on the make command line when building binaries for
 # official release.  Otherwise, substitute a hex string that is pretty much
@@ -105,9 +103,9 @@ DATE    := $(shell sh $(SRC)/../gen-id.sh $(VERSION) $(HEXDATE))
 endif
 
 ifeq ($(FWCLASS),EFI)
-all: makeoutputdirs $(filter-out %bios.o,$(COBJS) $(SOBJS)) codepage.o
+all: makeoutputdirs $(COBJS) $(SOBJS) codepage.o $(LIBCORE_FILES)
 else
-all: makeoutputdirs $(BTARGET)
+all: makeoutputdirs $(BTARGET) $(LIBCORE_FILES)
 endif
 
 makeoutputdirs:
@@ -118,33 +116,29 @@ kwdhash.gen: keywords genhash.pl
 
 ifeq ($(FWCLASS),BIOS)
 
-.PRECIOUS: %.elf
 %.raw: %.elf
-	$(OBJCOPY) -O binary -S $< $(@:.bin=.raw)
+	$(OBJCOPY) -O binary -S $< $@
 
-# GNU make 3.82 gets confused by plain %.raw; make 4.0 requires it
-.PRECIOUS: $(OBJ)/%.raw %.raw
 %.bin: %.raw $(PREPCORE)
 	$(PREPCORE) $< $@
 
-%.o: %.asm kwdhash.gen $(OBJ)/../version.gen
-	$(NASM) -f $(NASM_ELF) $(NASMOPT) -DDATE_STR="'$(DATE)'" \
-		-DHEXDATE="$(HEXDATE)" \
-		-D$(ARCH) \
-		-I$(SRC)/ -I$(SRC)/bios/ \
-		-l $(@:.o=.lsr) -o $@ -MP -MD $(@D)/.$(@F).d $<
+NASMFLAGS += -DDATE_STR="'$(DATE)'" -DHEXDATE="$(HEXDATE)" -I$(SRC)/bios/ -I$(objdir)/ -I$(OBJ)/
 
-AUXLIBS = bios/libpxelinux.a bios/liblpxelinux.a
-LDSCRIPT = $(SRC)/bios/syslinux.ld
-
-NASM_ELF = elf
+%.o: %.asm kwdhash.gen $(objdir)/version.gen
 
-%.elf: %.o %-c.o lib%.a $(LIBDEP) $(LDSCRIPT)
-	$(LD) $(LDFLAGS) -pie -Bsymbolic \
-		-T $(LDSCRIPT) \
-		--unresolved-symbols=report-all \
-		-E --hash-style=gnu -M -o $@ $< $*-c.o \
-		--start-group $(*D)/lib$(*F).a $(LIBS) --end-group \
+AUXLIBS = bios/libpxelinux.a bios/liblpxelinux.a
+CORELDSCRIPT = $(SRC)/bios/syslinux.ld
+CORELDFLAGS = $(MAIN_LDFLAGS) -pie --no-dynamic-linker \
+	--unresolved-symbols=report-all \
+	-E -M -T $(CORELDSCRIPT)
+
+# Assembly file to force certain symbols to be exported even if
+# they are not used by the core.
+EXPORT = bios/export.o
+
+$(ETARGET): %.elf: %.o %-c.o $(EXPORT) %.a $(CORE_LIBS) $(CORELDSCRIPT)
+	$(LD) $(CORELDFLAGS) -o $@ $< $*-c.o $(EXPORT) \
+		--start-group $*.a $(CORE_LIBS) --end-group \
 		> $*.map
 	if [ `$(NM) -D -u $@ | wc -l` -ne 0 ]; then \
 		$(NM) -D -u $@ 1>&2; rm -f $@; false; fi
@@ -152,14 +146,14 @@ NASM_ELF = elf
 	$(PERL) $(SRC)/lstadjust.pl $*.lsr $*.sec $*.lst
 
 # Legacy network stack
-bios/libpxelinux.a: $(CORE_PXE_OBJS) $(PXELINUX_OBJS)
+bios/pxelinux.a: $(CORE_PXE_OBJS) $(PXELINUX_OBJS)
 
 # LwIP network stack
-bios/liblpxelinux.a: $(CORE_PXE_OBJS) $(LPXELINUX_OBJS)
+bios/lpxelinux.a: $(CORE_PXE_OBJS) $(LPXELINUX_OBJS)
 
 # Otherwise, no special library needed, a null library will be created
 
-bios/lib%.a:
+bios/%.a:
 	rm -f $@
 	$(AR) cq $@ $^
 	$(RANLIB) $@
@@ -176,9 +170,19 @@ ldlinux.bss: bios/ldlinux.bin
 ldlinux.sys: bios/ldlinux.bin
 	dd if=$< of=$@ bs=512 skip=2
 
+libcore.S: $(ETARGET) $(SRC)/export.pl
+	$(PERL) '$(SRC)/export.pl' libcore.S libcore.weak $(ETARGET)
+
+libcore.weak: libcore.S
+	: $@ generated by side effect from $<
+
+# Don't use $(SHARED) here: we don't want a SONAME on libcore.so
+libcore.so: libcore.o
+	$(LD) $(LDFLAGS) -shared -o $@ $<
+
 endif # BIOS
 
-$(LIB): $(LIBOBJS)
+$(CORE_LIB): $(CORE_LIBOBJS)
 	rm -f $@
 	$(AR) cq $@ $^
 	$(RANLIB) $@
diff --git a/core/bios/adv.inc b/core/bios/adv.inc
index a18020c5..3ce7cb2f 100644
--- a/core/bios/adv.inc
+++ b/core/bios/adv.inc
@@ -44,9 +44,10 @@ ADV_LEN		equ 500				; Data bytes
 adv_retries	equ 6				; Disk retries
 
 		section .data
-		global __syslinux_adv_ptr, __syslinux_adv_size
+		export __syslinux_adv_ptr:data 4
 __syslinux_adv_ptr:
 		dd adv0.data
+		export __syslinux_adv_size:data 4
 __syslinux_adv_size:
 		dd ADV_LEN
 
@@ -70,7 +71,7 @@ adv1:
 		; This is called after config file parsing, so we know
 		; the intended location of the ADV
 		;
-		global adv_init
+		hidden adv_init
 adv_init:
 		cmp byte [ADVDrive],-1
 		jne adv_read
@@ -301,7 +302,7 @@ adv_cleanup:
 ;
 ;		Returns CF=1 if the ADV cannot be written.
 ;
-		global adv_write
+		hidden adv_write
 adv_write:
 		push eax
 		mov eax,[ADVSec0]
diff --git a/core/bios/banner.inc b/core/bios/banner.inc
new file mode 100644
index 00000000..e3e957e6
--- /dev/null
+++ b/core/bios/banner.inc
@@ -0,0 +1,24 @@
+;
+; Syslinux banner and copyright string
+;
+		section .data16
+
+		align 2, db 0
+		export __syslinux_core_version:data 2
+__syslinux_core_version:
+		db VERSION_MINOR, VERSION_MAJOR
+
+		export syslinux_banner:data (late_banner.end - syslinux_banner)
+syslinux_banner:
+		db CR, LF, MY_NAME, ' ', VERSION_STR
+late_banner	db ' ', DATE_STR, 0
+.end:
+
+		export copyright_str:data (copyright_str.end - copyright_str)
+copyright_str:
+		db ' Copyright (C) 1994-'
+		asciidec YEAR
+		db ' H. Peter Anvin et al', CR, LF, 0
+.end:
+
+		section .text16
diff --git a/core/bios/bcopyxx.inc b/core/bios/bcopyxx.inc
index 3658f097..4b59477a 100644
--- a/core/bios/bcopyxx.inc
+++ b/core/bios/bcopyxx.inc
@@ -210,7 +210,7 @@ pm_bcopy:
 ; do_raw_shuffle_and_boot is the same entry point, but with a C ABI:
 ; do_raw_shuffle_and_boot(safearea, descriptors, bytecount)
 ;
-		global do_raw_shuffle_and_boot
+		export do_raw_shuffle_and_boot:function
 do_raw_shuffle_and_boot:
 		mov edi,eax
 		mov esi,edx
@@ -325,9 +325,9 @@ RM_IDT_ptr:	dw 0FFFFh		; Length (nonsense, but matches CPU)
 bcopyxx_stack	equ 128			; We want this much stack
 
 		section .rodata
-		global __syslinux_shuffler_size
 		extern __bcopyxx_len
 		align 4
+		export __syslinux_shuffler_size:data 4
 __syslinux_shuffler_size:
 		dd __bcopyxx_len
 
diff --git a/core/bios/call16.c b/core/bios/call16.c
index 471aef96..1922b121 100644
--- a/core/bios/call16.c
+++ b/core/bios/call16.c
@@ -22,19 +22,10 @@
 
 __export const com32sys_t zero_regs;	/* Common all-zero register set */
 
-static inline uint32_t eflags(void)
+static inline unsigned long eflags(void)
 {
-    //uint32_t v;
-
-#if __SIZEOF_POINTER__ == 4
-    uint32_t v;
-    asm volatile("pushfl ; popl %0" : "=rm" (v));
-#elif __SIZEOF_POINTER__ == 8
-    uint64_t v;
-    asm volatile("pushfq ; pop %0" : "=rm" (v));
-#else
-#error "Unable to build for to-be-defined architecture type"
-#endif
+    unsigned long v;
+    asm volatile("pushf ; pop %0" : "=rm" (v));
     return v;
 }
 
@@ -46,5 +37,5 @@ __export void call16(void (*func)(void), const com32sys_t *ireg,
     /* Enable interrupts if and only if they are enabled in the caller */
     xreg.eflags.l = (xreg.eflags.l & ~EFLAGS_IF) | (eflags() & EFLAGS_IF);
 
-    core_farcall((size_t)func, &xreg, oreg);
+    ___farcall((size_t)func, &xreg, oreg);
 }
diff --git a/core/bios/callback.inc b/core/bios/callback.inc
index f1332e8e..f0ff668c 100644
--- a/core/bios/callback.inc
+++ b/core/bios/callback.inc
@@ -37,26 +37,28 @@
 ; - Return segment (== real mode cs == 0)
 ; - Return flags
 ;
-		global core_farcall:function hidden
-core_farcall:
-		mov eax,[esp+1*4]		; CS:IP
-		jmp core_syscall
-
-		global core_intcall:function hidden
-core_intcall:
-		movzx eax,byte [esp+1*4]	; INT number
+		export __intcall:function
+__intcall:
+		movzx eax,al			; INT number
 		mov eax,[eax*4]			; Get CS:IP from low memory
+		; Fall through
 
-core_syscall:
+		export ___farcall:function
+		; eax = CS:IP
+		; edx = source register structure
+		; ecx = destination register structure
+___farcall:
 		pushfd				; Save IF among other things...
 		inc dword [CallbackCtr]
 		push ebx
 		push ebp
 		push esi
 		push edi
+		push ecx			; Return register structure
 		push dword [CallbackSP]
 
 		cld
+		mov esi,edx			; Source register structure
 
 		movzx edi,word [word RealModeSSSP]
 		movzx ebx,word [word RealModeSSSP+2]
@@ -65,7 +67,6 @@ core_syscall:
 		shl ebx,4
 		add edi,ebx		; Create linear address
 
-		mov esi,[esp+8*4]	; Source regs
 		xor ecx,ecx
 		mov cl,11		; 44 bytes to copy
 		rep movsd
@@ -80,7 +81,7 @@ core_syscall:
 		stosw			; Return flags
 
 		mov bx,.rm
-		jmp enter_rm	; Go to real mode
+		jmp enter_rm		; Go to real mode
 
 		bits 16
 		section .text16
@@ -94,7 +95,7 @@ core_syscall:
 		pop ds
 		popad
 		popfd
-		retf				; Invoke routine
+		retf			; Invoke routine
 
 .rm_return:
 		; We clean up SP here because we don't know if the
@@ -117,17 +118,16 @@ core_syscall:
 .pm_return:
 		movzx esi,word [word RealModeSSSP]
 		movzx eax,word [word RealModeSSSP+2]
-		mov edi,[esp+9*4]	; Dest regs
+		pop edi			; Destination register structure
 		shl eax,4
 		add esi,eax		; Create linear address
 		and edi,edi		; NULL pointer?
-		jnz .do_copy
-.no_copy:	mov edi,esi		; Do a dummy copy-to-self
+		jz .no_copy
 .do_copy:	xor ecx,ecx
 		mov cl,11		; 44 bytes
 		rep movsd		; Copy register block
 
-		add dword [word RealModeSSSP],54
+.no_copy:	add dword [word RealModeSSSP],54
 					; Remove from stack
 
 		pop dword [CallbackSP]
@@ -147,8 +147,11 @@ core_syscall:
 ; followed by the return CS:IP and the CS:IP of the target function.
 ; The value of IF is copied from the calling routine.
 ;
-		global core_cfarcall:function hidden
-core_cfarcall:
+		export ___cfarcall:function
+		; eax = CS:IP
+		; edx = data to be put on stack
+		; ecx = size of data to be put on stack
+___cfarcall:
 		pushfd				; Save IF among other things...
 		inc dword [CallbackCtr]
 		push ebx
@@ -158,32 +161,27 @@ core_cfarcall:
 		push dword [CallbackSP]
 
 		cld
-		mov ecx,[esp+9*4]		; Size of stack frame
+		mov esi,edx
 
 		movzx edi,word [word RealModeSSSP]
-		movzx ebx,word [word RealModeSSSP+2]
 		mov [word CallbackSP],di
 		sub edi,ecx		; Allocate space for stack frame
 		and edi,~3		; Round
 		sub edi,4*3		; Return pointer, return value, EFLAGS
 		mov [word RealModeSSSP],di
+		movzx ebx,word [word RealModeSSSP+2]
 		shl ebx,4
-		add edi,ebx		; Create linear address
+		lea edi,[ebx+edi+12]	; Linear address of the arguments
 
+		mov [edi-8],eax		; CS:IP
+		mov dword [edi-4],.rm_return	; Return seg:off
 		mov eax,[esp+5*4]	; EFLAGS from entry
 		and eax,0x202		; IF only
-		stosd
-		mov eax,[esp+7*4]	; CS:IP
-		stosd			; Save to stack frame
-		mov eax,.rm_return	; Return seg:off
-		stosd
-		mov esi,[esp+8*4]	; Stack frame
-		mov eax,ecx		; Copy the stack frame
+		mov [edi-12],eax	; Real mode EFLAGS
+
+		add ecx,3		; Copy the stack frame
 		shr ecx,2
 		rep movsd
-		mov ecx,eax
-		and ecx,3
-		rep movsb
 
 		mov bx,.rm
 		jmp enter_rm
@@ -218,7 +216,7 @@ core_cfarcall:
 
 		section .bss16
 		alignb 4
-		global core_pm_hook
+		hidden core_pm_hook
 CallbackSP	resd 1			; SP saved during callback
 CallbackCtr	resd 1
 
diff --git a/core/bios/com32.inc b/core/bios/com32.inc
index 5561c720..7c6627ef 100644
--- a/core/bios/com32.inc
+++ b/core/bios/com32.inc
@@ -16,50 +16,15 @@
 ;;
 ;; Common code for running a COM32 image
 ;;
-
-		extern pm_api_vector
-
-;
-; Load a COM32 image.  A COM32 image is the 32-bit analogue to a DOS
-; .com file.  A COM32 image is loaded at address 0x101000, with %esp
-; set to the high end of usable memory.
-;
-; A COM32 image should begin with the magic bytes:
-; B8 FF 4C CD 21, which is "mov eax,0x21cd4cff" in 32-bit mode and
-; "mov ax,0x4cff; int 0x21" in 16-bit mode.  This will abort the
-; program with an error if run in 16-bit mode.
-;
-		bits 16
-		section .data16
-
-		; Ersatz com32 invocation structure, to make libcom32
-		; code run the same if linked to the core.  This is in
-		; the .data16 segment so HighMemSize can live here.
-		;
-		; Danger, Will Robinson: it's not clear the use of
-		; core_xfer_buf is safe here.
-		global __com32:data hidden
-		alignz 4
-__entry_esp:
-		dd 0				; Dummy to avoid _exit issues
-__com32:
-		dd 9				; Argument count
-		dd 0				; No command line
-		dd core_intcall			; Intcall entry point
-		dd 0				; Bounce buffer address
-		dd 0				; 64K bounce buffer
-		dd core_farcall			; Farcall entry point
-		dd core_cfarcall		; Cfarcall entry point
-HighMemSize	dd 0				; End of memory pointer (bytes)
-		dd 0				; No module name
-		dd pm_api_vector		; Protected mode functions
-
 		section .uibss
 Com32Name	resb FILENAME_MAX
 
 		section .bss16
+		alignb 4
+		hidden HighMemSize:data
+HighMemSize	resd 1			; End of memory pointer (bytes)
 %ifndef HAVE_CURRENTDIRNAME
-		global CurrentDirName:data hidden
+		hidden CurrentDirName:data
 CurrentDirName	resb FILENAME_MAX
 %endif
 
diff --git a/core/bios/common.inc b/core/bios/common.inc
index c42fc56b..d5f71889 100644
--- a/core/bios/common.inc
+++ b/core/bios/common.inc
@@ -4,6 +4,7 @@
 ; some derivatives.)
 ;
 
+%include "banner.inc"		; Copyright/version information
 %include "pm.inc"		; Protected mode
 %include "bcopy32.inc"		; 32-bit bcopy
 %include "strcpy.inc"           ; strcpy()
diff --git a/core/bios/config.inc b/core/bios/config.inc
index 999d3d91..9202c763 100644
--- a/core/bios/config.inc
+++ b/core/bios/config.inc
@@ -35,6 +35,6 @@ FILENAME_MAX	 equ (1 << FILENAME_MAX_LG2)	; Max mangled filename size
 ;
 ; Version number definitinons
 ;
-%include "../version.gen"
+%include "version.gen"
 
 %endif ; _CONFIG_INC
diff --git a/core/bios/diskboot.inc b/core/bios/diskboot.inc
index 19d6bcf7..c2674058 100644
--- a/core/bios/diskboot.inc
+++ b/core/bios/diskboot.inc
@@ -28,9 +28,11 @@
 ; reduce the code size...
 ;
 
-		global StackBuf, PartInfo, Hidden, OrigESDI, DriveNumber
-		global OrigFDCTabPtr
-StackBuf	equ STACK_TOP-44-92	; Start the stack here (grow down - 4K)
+		hidden Hidden, OrigESDI, DriveNumber
+		hidden OrigFDCTabPtr
+		export StackBuf:data
+StackBuf	equ STACK_TOP-92	; Start the stack here (grow down - 4K)
+		hidden PartInfo
 PartInfo	equ StackBuf
 .mbr		equ PartInfo
 .gptlen		equ PartInfo+16
@@ -192,7 +194,8 @@ harddisk:
 		add dx,si
 		cmp dx,4fh		; DS:SI < 50h:0 (BDA or IVT) ?
 		jbe .no_partition
-		cmp dx,(PartInfo-75)>>4	; DS:SI in overwritten memory?
+		; DS:SI in overwritten memory?
+		cmp dx,(PartInfo-75-STACK_TOP+_STACK_TOP) >> 4
 		jae .no_partition
 		test byte [di-76],7Fh	; Sanity check: "active flag" should
 		jnz .no_partition	; be 00 or 80
@@ -386,9 +389,9 @@ getonesec_cbios:
 ; kaboom: write a message and bail out.
 ;
 %ifdef BINFMT
-		global kaboom
+		hidden kaboom
 %else
-		global kaboom:function hidden
+		hidden kaboom:function
 %endif
 disk_error:
 kaboom:
diff --git a/core/bios/diskfs.inc b/core/bios/diskfs.inc
index 93016649..dc85fe36 100644
--- a/core/bios/diskfs.inc
+++ b/core/bios/diskfs.inc
@@ -41,7 +41,7 @@ MIN_SECTOR_SIZE		equ (1 << MIN_SECTOR_SHIFT)
 ; Memory below this point is reserved for the BIOS and the MBR
 ;
 		section .earlybss
-		global trackbuf:data hidden
+		hidden trackbuf:data
 trackbufsize	equ 8192
 trackbuf	resb trackbufsize	; Track buffer goes here
 		; ends at 2800h
@@ -71,16 +71,6 @@ enter_command:
 auto_boot:
 		jmp kaboom
 
-		section .bss16
-		alignb 4
-ThisKbdTo	resd 1			; Temporary holder for KbdTimeout
-ThisTotalTo	resd 1			; Temporary holder for TotalTimeout
-KernelExtPtr	resw 1			; During search, final null pointer
-FuncFlag	resb 1			; Escape sequences received from keyboard
-KernelType	resb 1			; Kernel type, from vkernel, if known
-		global KernelName
-KernelName	resb FILENAME_MAX	; Mangled name for kernel
-
 		section .text16
 ;
 ; COM32 vestigial data structure
@@ -121,10 +111,6 @@ kaboom2:
 ; -----------------------------------------------------------------------------
 
 		section .data16
-		global copyright_str
-copyright_str   db ' Copyright (C) 1994-'
-		asciidec YEAR
-		db ' H. Peter Anvin et al', CR, LF, 0
 err_bootfailed	db CR, LF, 'Boot failed: please change disks and press '
 		db 'a key to continue.', CR, LF, 0
 
diff --git a/core/bios/diskstart.inc b/core/bios/diskstart.inc
index 875b4093..e922fd32 100644
--- a/core/bios/diskstart.inc
+++ b/core/bios/diskstart.inc
@@ -92,7 +92,7 @@ BannerPtr	dw syslinux_banner - LDLINUX_SYS
 ; Base directory name and subvolume, if applicable.
 ;
 %define HAVE_CURRENTDIRNAME
-		global CurrentDirName:data hidden, SubvolName:data hidden
+		hidden CurrentDirName:data, SubvolName:data
 CurrentDirName	times CURRENTDIR_MAX db 0
 SubvolName	times SUBVOL_MAX db 0
 
@@ -142,9 +142,8 @@ print_bios:
 		call writestr_early
 
 		section .earlybss
-		global BIOSName
 		alignb 2
-%define	HAVE_BIOSNAME 1
+		export BIOSName:data 2
 BIOSName	resw 1
 
 		section .init
@@ -232,7 +231,7 @@ verify_checksum:
 ;
 ;            This routine assumes CS == DS.
 ;
-		global getlinsec:function hidden
+		hidden getlinsec:function
 getlinsec:
 		pushad
 		add eax,[Hidden]		; Add partition offset
@@ -511,12 +510,4 @@ expand_super:
 		section .bss16
 SuperInfo	resq 16			; The first 16 bytes expanded 8 times
 
-;
-; Banner information not needed in sector 1
-;
-		section .data16
-		global syslinux_banner
-syslinux_banner	db CR, LF, MY_NAME, ' ', VERSION_STR
-late_banner	db ' ', DATE_STR, 0
-
 		section .text16
diff --git a/core/bios/export.asm b/core/bios/export.asm
new file mode 100644
index 00000000..c0a66306
--- /dev/null
+++ b/core/bios/export.asm
@@ -0,0 +1,20 @@
+;  List of symbols which must be exported, but otherwise might
+;  have been omitted from the core library.
+; 
+; This creates an object file which only contains a set of undefined
+; symbols, forcing those symbols to be included in the output.
+
+%macro export 1-*.nolist
+    %rep %0
+        	extern %1
+__dummy_%1	equ %1		; Force symbol reference
+	%rotate 1
+    %endrep
+%endmacro
+
+	export local_boot
+	export __syslinux_shuffler_size
+	export __intcall, ___farcall, ___cfarcall
+	export copyright_str
+	export syslinux_banner
+	export __syslinux_core_version
diff --git a/core/bios/isolinux.asm b/core/bios/isolinux.asm
index 50d9fe1c..e4eafa21 100644
--- a/core/bios/isolinux.asm
+++ b/core/bios/isolinux.asm
@@ -43,7 +43,7 @@ ROOT_DIR_WORD	equ 0x002F
 ; Memory below this point is reserved for the BIOS and the MBR
 ;
 		section .earlybss
-		global trackbuf
+		hidden trackbuf
 trackbufsize	equ 8192
 trackbuf	resb trackbufsize	; Track buffer goes here
 ;		ends at 2800h
@@ -51,7 +51,6 @@ trackbuf	resb trackbufsize	; Track buffer goes here
 		; Some of these are touched before the whole image
 		; is loaded.  DO NOT move this to .bss16/.uibss.
 		section .earlybss
-		global BIOSName
 		alignb 4
 FirstSecSum	resd 1			; Checksum of bytes 64-2048
 ImageDwords	resd 1			; isolinux.bin size, dwords
@@ -60,18 +59,18 @@ DiskSys		resw 1			; Last INT 13h call
 ImageSectors	resw 1			; isolinux.bin size, sectors
 ; These following two are accessed as a single dword...
 GetlinsecPtr	resw 1			; The sector-read pointer
+		export BIOSName:data 2
 BIOSName	resw 1			; Display string for BIOS type
-%define HAVE_BIOSNAME 1
-		global BIOSType
+		hidden BIOSType
 BIOSType	resw 1
 DiskError	resb 1			; Error code for disk I/O
-		global DriveNumber
+		hidden DriveNumber
 DriveNumber	resb 1			; CD-ROM BIOS drive number
 ISOFlags	resb 1			; Flags for ISO directory search
 RetryCount      resb 1			; Used for disk access retries
 
 		alignb 8
-		global Hidden
+		hidden Hidden
 Hidden		resq 1			; Used in hybrid mode
 bsSecPerTrack	resw 1			; Used in hybrid mode
 bsHeads		resw 1			; Used in hybrid mode
@@ -83,7 +82,7 @@ bsHeads		resw 1			; Used in hybrid mode
 
 		alignb 8
 _spec_start	equ $
-		global spec_packet
+		hidden spec_packet
 spec_packet:	resb 1				; Size of packet
 sp_media:	resb 1				; Media type
 sp_drive:	resb 1				; Drive number
@@ -155,11 +154,11 @@ _spec_len	equ _spec_end - _spec_start
 ;; CD-ROM sector (2K) of the file, so the number one priority is actually
 ;; loading the rest.
 ;;
-		global StackBuf
-StackBuf	equ STACK_TOP-44	; 44 bytes needed for
+		export StackBuf:data
+StackBuf	equ STACK_TOP		; 44 bytes needed for
 					; the bootsector chainloading
 					; code!
-		global OrigESDI
+		hidden OrigESDI
 OrigESDI	equ StackBuf-4          ; The high dword on the stack
 StackHome	equ OrigESDI
 
@@ -174,7 +173,7 @@ _start:		; Far jump makes sure we canonicalize the address
 		; -boot-info-table option.  If not, the values in this
 		; table are default values that we can use to get us what
 		; we need, at least under a certain set of assumptions.
-		global iso_boot_info
+		hidden iso_boot_info
 iso_boot_info:
 bi_pvd:		dd 16				; LBA of primary volume descriptor
 bi_file:	dd 0				; LBA of boot file
@@ -758,7 +757,7 @@ getonesec:
 ;	ES:BX	- Target buffer
 ;	BP	- Sector count
 ;
-		global getlinsec
+		hidden getlinsec
 getlinsec:	jmp word [cs:GetlinsecPtr]
 
 %ifndef DEBUG_MESSAGES
@@ -1024,7 +1023,7 @@ xint13:		mov byte [RetryCount],retry_count
 ; kaboom: write a message and bail out.  Wait for a user keypress,
 ;	  then do a hard reboot.
 ;
-		global kaboom
+		hidden kaboom
 disk_error:
 kaboom:
 		RESET_STACK_AND_SEGS AX
@@ -1045,11 +1044,6 @@ kaboom:
 ; Data that needs to be in the first sector
 ; -----------------------------------------------------------------------------
 
-		global syslinux_banner, copyright_str
-syslinux_banner	db CR, LF, MY_NAME, ' ', VERSION_STR, ' ', DATE_STR, ' ', 0
-copyright_str   db ' Copyright (C) 1994-'
-		asciidec YEAR
-		db ' H. Peter Anvin et al', CR, LF, 0
 isolinux_str	db 'isolinux: ', 0
 %ifdef DEBUG_MESSAGES
 startup_msg:	db 'Starting up, DL = ', 0
@@ -1084,7 +1078,7 @@ bios_ebios_str	db 'EHDD' ,0
 %endif
 
 		alignz 4
-		global bios_cdrom
+		hidden bios_cdrom
 bios_cdrom:	dw getlinsec_cdrom, bios_cdrom_str
 %ifndef DEBUG_MESSAGES
 bios_cbios:	dw getlinsec_cbios, bios_cbios_str
@@ -1193,16 +1187,6 @@ debug_tracer:	pushad
 		ret
 %endif	; DEBUG_TRACERS
 
-		section .bss16
-		alignb 4
-ThisKbdTo	resd 1			; Temporary holder for KbdTimeout
-ThisTotalTo	resd 1			; Temporary holder for TotalTimeout
-KernelExtPtr	resw 1			; During search, final null pointer
-FuncFlag	resb 1			; Escape sequences received from keyboard
-KernelType	resb 1			; Kernel type, from vkernel, if known
-		global KernelName
-KernelName	resb FILENAME_MAX	; Mangled name for kernel
-
 		section .text16
 ;
 ; COM32 vestigial data structure
@@ -1228,5 +1212,5 @@ KernelName	resb FILENAME_MAX	; Mangled name for kernel
 err_disk_image	db 'Cannot load disk image (invalid file)?', CR, LF, 0
 
 		section .bss16
-		global OrigFDCTabPtr
+		hidden OrigFDCTabPtr
 OrigFDCTabPtr	resd 1			; Keep bios_cleanup_hardware() honest
diff --git a/core/bios/layout.inc b/core/bios/layout.inc
index bb7cb333..f4d78bad 100644
--- a/core/bios/layout.inc
+++ b/core/bios/layout.inc
@@ -20,9 +20,6 @@
 		; Default to 16-bit code
 		bits 16
 
-; Memory below 0800h is reserved for the BIOS and the MBR.
-BSS_START	equ 0800h
-
 ; Text starts at the load address of 07C00h.
 TEXT_START	equ 7C00h
 
@@ -34,20 +31,15 @@ TEXT_START	equ 7C00h
 ; handle localboot properly), so avoid that immediate memory region.
 ; The range that is known to be bad is approximately 75E8..7C00; the
 ; lower bound is tight.
-; 
-		global STACK_LEN, STACK_TOP, STACK_BASE
+;
 STACK_LEN	equ 4096
 %if IS_PXELINUX
-STACK_TOP	equ 7000h
+_STACK_TOP	equ 7000h
 %else
-STACK_TOP	equ 7c00h
+_STACK_TOP	equ 7c00h
 %endif
-STACK_BASE	equ STACK_TOP - STACK_LEN
-
-; The secondary BSS section, above the text; we really wish we could
-; just make it follow .bcopy32 or hang off the end,
-; but it doesn't seem to work that way.
-LATEBSS_START	equ 0B800h
+		global _STACK_BASE
+_STACK_BASE	equ STACK_TOP - STACK_LEN
 
 ;
 ; 32-bit stack layout
@@ -66,6 +58,10 @@ STACK32_LEN	equ 64*1024
 		section .replacestub	exec write progbits align=16
 		section .gentextnr	exec write nobits align=16
 		section .stack16	write nobits align=16
+		hidden STACK_BASE, STACK_TOP
+STACK_BASE:
+		resb STACK_LEN
+STACK_TOP:
 
 		; Use .bss16 for things that doesn't have to be in low memory;
 		; .earlybss should be used for things that absolutely have
@@ -119,7 +115,7 @@ RBFG_brainfuck:	resb 2048		; Bigger than an Ethernet packet...
 
 		extern free_high_memory
 
-		global _start
+		hidden _start
 
 		section .text16
 
@@ -137,7 +133,7 @@ serial_buf_size	equ 4096		; Should be a power of 2
 ;
 		extern	xfer_buf_seg
 		section .xfer_buf	write nobits align=65536
-		global	core_xfer_buf:data hidden
+		hidden	core_xfer_buf:data
 core_xfer_buf	resb 65536
 
 ;
diff --git a/core/bios/localboot.c b/core/bios/localboot.c
index d0c289d0..2d64887b 100644
--- a/core/bios/localboot.c
+++ b/core/bios/localboot.c
@@ -35,7 +35,7 @@ extern void local_boot16(void);
  * Boot a specified local disk.  AX specifies the BIOS disk number; or
  * -1 in case we should execute INT 18h ("next device.")
  */
-__export void __attribute__((weak)) local_boot(int16_t ax)
+__export void __weak local_boot(int16_t ax)
 {
 	com32sys_t ireg, oreg;
 	int i;
diff --git a/core/bios/localboot.inc b/core/bios/localboot.inc
index b7840427..e66b523d 100644
--- a/core/bios/localboot.inc
+++ b/core/bios/localboot.inc
@@ -1,5 +1,5 @@
 		section .text16
-		global local_boot16:function hidden
+		hidden local_boot16:function
 local_boot16:
 		mov cx,0
 		mov ss,cx
diff --git a/core/bios/lwip/thread/sem_asm.S b/core/bios/lwip/thread/sem_asm.S
index ce67471a..5cfd8cd5 100644
--- a/core/bios/lwip/thread/sem_asm.S
+++ b/core/bios/lwip/thread/sem_asm.S
@@ -1,5 +1,6 @@
 	.globl	sem_down
 	.type	sem_down, @function
+	.hidden	sem_down
 sem_down:
 	decl	(%eax)
 	js	__sem_down_slow
@@ -9,6 +10,7 @@ sem_down:
 
 	.globl	sem_up
 	.type	sem_up, @function
+	.hidden	sem_up
 sem_up:
 	incl	(%eax)
 	jle	__sem_up_slow
diff --git a/core/bios/lwip/thread/thread_asm.S b/core/bios/lwip/thread/thread_asm.S
index ec3e0add..30c62f72 100644
--- a/core/bios/lwip/thread/thread_asm.S
+++ b/core/bios/lwip/thread/thread_asm.S
@@ -1,5 +1,6 @@
 	.globl	__switch_to
 	.type	__switch_to, @function
+	.hidden	__switch_to
 __switch_to:
 	movl	__current, %edx
 	pushl	%ebx
@@ -23,6 +24,7 @@ __switch_to:
 
 	.globl	__start_thread
 	.type	__start_thread, @function
+	.hidden	__start_thread
 __start_thread:
 	movl	%edi, %eax		/* Thread function argument */
 
diff --git a/core/bios/macros.inc b/core/bios/macros.inc
index c8fbe8de..62c6acef 100644
--- a/core/bios/macros.inc
+++ b/core/bios/macros.inc
@@ -118,4 +118,48 @@ LF		equ 10		; Line Feed
 FF		equ 12		; Form Feed
 BS		equ  8		; Backspace
 
+;
+; Define hidden symbols as either hidden or exported (default or protected)
+;
+%ifdef NO_PLT
+  %define exported protected
+%else
+  %define exported default
+%endif
+
+%macro declare_global 2.nolist
+  %ifnidn __OUTPUT_FORMAT__, bin
+    %iftoken %1
+      global %1:data %2
+    %else
+      global %1 %2
+    %endif
+  %endif
+%endmacro
+
+%macro export 1-*.nolist
+  %rep %0
+    declare_global %1, exported
+    %rotate 1
+  %endrep
+%endmacro
+
+%macro hidden 1-*.nolist
+  %rep %0
+    declare_global %1, hidden
+    %rotate 1
+  %endrep
+%endmacro
+
+;
+; Most versions of NASM don't support setting the visibility on EQU'd
+; symbols, so tell NASM they are symbols in the absolute section
+; instead
+;
+%macro defabs 1.nolist
+    [absolute %1]
+%00:
+    __SECT__
+%endmacro
+
 %endif ; _MACROS_INC
diff --git a/core/bios/pm.inc b/core/bios/pm.inc
index 7b98944f..e62fa6e7 100644
--- a/core/bios/pm.inc
+++ b/core/bios/pm.inc
@@ -222,13 +222,13 @@ pm_irq:
 ; threaded derivatives to run the scheduler, or examine the result from
 ; interrupt routines.
 ;
-		global core_pm_null_hook
+		hidden core_pm_null_hook
 core_pm_null_hook:
 		ret
 
 		section .data16
 		alignz 4
-		global core_pm_hook
+		hidden core_pm_hook
 core_pm_hook:	dd core_pm_null_hook
 
 		bits 16
@@ -460,7 +460,7 @@ pm_init:
 		section .earlybss
 		alignb 8
 IDT:		resq 256
-		global RealModeSSSP
+		hidden RealModeSSSP
 RealModeSSSP	resd 1			; Real-mode SS:SP
 
 		section .gentextnr	; Autogenerated 32-bit code
diff --git a/core/bios/prefix.inc b/core/bios/prefix.inc
index 9c8724b5..983aadb9 100644
--- a/core/bios/prefix.inc
+++ b/core/bios/prefix.inc
@@ -1,4 +1,4 @@
-;
+
 ; The prefix is a small structure that prefaces the actual code;
 ; it gives the compression program necessary information.
 ;
diff --git a/core/bios/pxeisr.inc b/core/bios/pxeisr.inc
index 93c73ed5..9644d2d5 100644
--- a/core/bios/pxeisr.inc
+++ b/core/bios/pxeisr.inc
@@ -5,7 +5,7 @@
 
 PXEIRQ_MAX	equ 100		; Max spurious interrupts in a timer tick
 
-		global pxe_isr
+		hidden pxe_isr
 pxe_isr:
 		cld
 		pusha
@@ -73,7 +73,7 @@ pxe_isr:
 		pop ds
 		popa
 		jmp 0:0
-		global pxe_irq_chain
+		hidden pxe_irq_chain
 pxe_irq_chain	equ $-4
 
 .reset_timeout:
@@ -101,7 +101,7 @@ pxe_irq_chain	equ $-4
 
 
 ; Emulate a PXE interrupt from the polling thread
-		global pxe_poll
+		hidden pxe_poll
 pxe_poll:
 		pushf
 		cli
@@ -159,13 +159,13 @@ pxenv_undi_isr_buf:
 pxeirq_last	resw 1
 pxeirq_deadman	resw 1
 
-		global pxe_irq_count
+		hidden pxe_irq_count
 pxe_irq_count	resd 1			; PXE IRQ counter
-		global pxe_irq_vector
+		hidden pxe_irq_vector
 pxe_irq_vector	resb 1			; PXE IRQ vector
-		global pxe_irq_pending
+		hidden pxe_irq_pending
 pxe_irq_pending	resb 1			; IRQ pending flag
-		global pxe_need_poll
+		hidden pxe_need_poll
 pxe_need_poll	resb 1			; Bit 0 = need polling
 					; Bit 1 = polling active
 
diff --git a/core/bios/pxelinux.inc b/core/bios/pxelinux.inc
index be786369..48ce0c0a 100644
--- a/core/bios/pxelinux.inc
+++ b/core/bios/pxelinux.inc
@@ -47,14 +47,14 @@ SECTOR_SIZE	equ TFTP_BLOCKSIZE
 ; Memory below this point is reserved for the BIOS and the MBR
 ;
 		section .earlybss
-                global trackbuf
+                hidden trackbuf
 trackbufsize	equ 8192
 trackbuf	resb trackbufsize	; Track buffer goes here
 		; ends at 2800h
 
 		; These fields save information from before the time
 		; .bss is zeroed... must be in .earlybss
-		global InitStack
+		hidden InitStack
 InitStack	resd 1
 
 		section .bss16
@@ -62,15 +62,14 @@ InitStack	resd 1
 PXEStack	resd 1			; Saved stack during PXE call
 
 		alignb 4
-                global DHCPMagic, RebootTime, BIOSName
+                hidden DHCPMagic, RebootTime
 RebootTime	resd 1			; Reboot timeout, if set by option
 LocalBootType	resw 1			; Local boot return code
 DHCPMagic	resb 1			; PXELINUX magic flags
-BIOSName	resw 1			; Dummy variable - always 0
 
 		section .text16
-		global StackBuf
-StackBuf	equ STACK_TOP-44	; Base of stack if we use our own
+		export StackBuf:data
+StackBuf	equ STACK_TOP		; Base of stack if we use our own
 StackHome	equ StackBuf
 
 		; PXE loads the whole file, but assume it can't be more
@@ -93,7 +92,7 @@ _start:
 hcdhcp_magic	dd 0x2983c8ac		; Magic number
 hcdhcp_len	dd 7*4			; Size of this structure
 hcdhcp_flags	dd 0			; Reserved for the future
-		global bdhcp_len, adhcp_len
+		hidden bdhcp_len, adhcp_len
 		; Parameters to be parsed before the ones from PXE
 bdhcp_offset	dd 0			; Offset (entered by patcher)
 bdhcp_len	dd 0			; Length (entered by patcher)
@@ -211,7 +210,7 @@ ROOT_FS_OPS:
 		bits 32
 
 		section .savedata
-		global bdhcp_data, adhcp_data
+		hidden bdhcp_data, adhcp_data
 bdhcp_data:	resb MAX_DHCP_OPTS
 adhcp_data:	resb MAX_DHCP_OPTS
 
@@ -249,23 +248,13 @@ adhcp_copy:
 		bits 16
 
 ; As core/ui.inc used to be included here in core/pxelinux.asm, and it's no
-; longer used, its global variables that were previously used by
+; longer used, its hidden variables that were previously used by
 ; core/pxelinux.asm are now declared here.
 		section .bss16
 		alignb 4
 Kernel_EAX	resd 1
 Kernel_SI	resw 1
 
-		section .bss16
-		alignb 4
-ThisKbdTo	resd 1			; Temporary holder for KbdTimeout
-ThisTotalTo	resd 1			; Temporary holder for TotalTimeout
-KernelExtPtr	resw 1			; During search, final null pointer
-FuncFlag	resb 1			; Escape sequences received from keyboard
-KernelType	resb 1			; Kernel type, from vkernel, if known
-		global KernelName
-KernelName	resb FILENAME_MAX	; Mangled name for kernel
-
 		section .text16
 ;
 ; COM32 vestigial data structure
@@ -273,7 +262,7 @@ KernelName	resb FILENAME_MAX	; Mangled name for kernel
 %include "com32.inc"
 
 		section .text16
-		global local_boot16:function hidden
+		hidden local_boot16:function
 local_boot16:
 		mov [LocalBootType],ax
 		lss sp,[InitStack]
@@ -299,7 +288,7 @@ local_boot16:
 ;
 ;         Note: use BIOS_timer here; we may not have jiffies set up.
 ;
-                global kaboom
+                hidden kaboom
 kaboom:
 		RESET_STACK_AND_SEGS AX
 .patch:		mov si,bailmsg
@@ -346,7 +335,7 @@ kaboom:
 ;
 ; While we're at it, save and restore all registers.
 ;
-                global pxenv
+                hidden pxenv
 pxenv:
 		pushfd
 		pushad
@@ -418,7 +407,7 @@ pxenv:
 		ret
 
 ; Must be after function def due to NASM bug
-                global PXEEntry
+                hidden PXEEntry
 PXEEntry	equ pxenv.jump+1
 
 ;
@@ -440,7 +429,7 @@ PXEStatus	resb 2
 ; Invoke INT 1Ah on the PXE stack.  This is used by the "Plan C" method
 ; for finding the PXE entry point.
 ;
-                global pxe_int1a
+                hidden pxe_int1a
 pxe_int1a:
 		mov [cs:PXEStack],sp
 		mov [cs:PXEStack+2],ss
@@ -456,7 +445,7 @@ pxe_int1a:
 ; gPXE to the ROM PXE stack.
 ;
 %if GPXE
-		global gpxe_unload
+		hidden gpxe_unload
 gpxe_unload:
 		mov bx,PXENV_FILE_EXIT_HOOK
 		mov di,pxe_file_exit_hook
@@ -545,24 +534,22 @@ pxe_file_exit_hook:
 ; -----------------------------------------------------------------------------
 
 		section .data16
-
-		global copyright_str, syslinux_banner
-copyright_str   db 'Copyright (C) 1994-'
-		asciidec YEAR
-		db ' H. Peter Anvin et al', CR, LF, 0
 err_bootfailed	db CR, LF, 'Boot failed: press a key to retry, or wait for reset...', CR, LF, 0
 bailmsg		equ err_bootfailed
 localboot_msg	db 'Booting from local disk...', CR, LF, 0
-syslinux_banner	db CR, LF, MY_NAME, ' ', VERSION_STR, ' ', MY_TYPE, ' '
-		db DATE_STR, ' ', 0
+pxebios_name	db 'PXE', 0
 
 ;
 ; Misc initialized (data) variables
 ;
-		section .data16
-                global KeepPXE
+		align 2, db 0
+		export BIOSName:data 2
+BIOSName	dw pxebios_name		; Dummy variable - always 0
+
+section .data16
+                hidden KeepPXE
 KeepPXE		db 0			; Should PXE be kept around?
 
 		section .bss16
-		global OrigFDCTabPtr
+		hidden OrigFDCTabPtr
 OrigFDCTabPtr	resd 1			; Keep bios_cleanup_hardware() honest
diff --git a/core/bios/stack.inc b/core/bios/stack.inc
index 838d6bab..13ef9fd7 100644
--- a/core/bios/stack.inc
+++ b/core/bios/stack.inc
@@ -38,7 +38,7 @@
 
 		section .data16
 		alignz 4
-		global BaseStack:data hidden
+		hidden BaseStack:data
 BaseStack	dd StackHome		; ESP of the "home" stack pointer
 		dw 0			; SS of the "home" stack pointer
 
diff --git a/core/bios/syslinux.ld b/core/bios/syslinux.ld
index e8d32dd9..6290a1bc 100644
--- a/core/bios/syslinux.ld
+++ b/core/bios/syslinux.ld
@@ -35,82 +35,82 @@ SECTIONS
 	. = 0x1000;
 
 	.earlybss (NOLOAD) : {
-		__earlybss_start = .;
+		HIDDEN(__earlybss_start = .);
 		*(.earlybss)
-		__earlybss_end = .;
+		HIDDEN(__earlybss_end = .);
 	}
-	__earlybss_len = ABSOLUTE(__earlybss_end) - ABSOLUTE(__earlybss_start);
-	__earlybss_dwords = (__earlybss_len + 3) >> 2;
+	HIDDEN(__earlybss_len = ABSOLUTE(__earlybss_end) - ABSOLUTE(__earlybss_start));
+	HIDDEN(__earlybss_dwords = (__earlybss_len + 3) >> 2);
 
 	. = ALIGN(4);
 	.bss16 (NOLOAD) : {
-		__bss16_start = .;
+		HIDDEN(__bss16_start = .);
 		*(.bss16)
-		__bss16_end = .;
+		HIDDEN(__bss16_end = .);
 	}
-	__bss16_len = ABSOLUTE(__bss16_end) - ABSOLUTE(__bss16_start);
-	__bss16_dwords = (__bss16_len + 3) >> 2;
+	HIDDEN(__bss16_len = ABSOLUTE(__bss16_end) - ABSOLUTE(__bss16_start));
+	HIDDEN(__bss16_dwords = (__bss16_len + 3) >> 2);
 
 	. = ALIGN(4);
  	.config : AT (__config_lma) {
-		__config_start = .;
+		HIDDEN(__config_start = .);
 		*(.config)
-		__config_end = .;
+		HIDDEN(__config_end = .);
 	}
-	__config_len = ABSOLUTE(__config_end) - ABSOLUTE(__config_start);
-	__config_dwords = (__config_len + 3) >> 2;
+	HIDDEN(__config_len = ABSOLUTE(__config_end) - ABSOLUTE(__config_start));
+	HIDDEN(__config_dwords = (__config_len + 3) >> 2);
 
 	/* Generated and/or copied code */
 
 	. = ALIGN(128);		/* Minimum separation from mutable data */
  	.replacestub : AT (__replacestub_lma) {
-		__replacestub_start = .;
+		HIDDEN(__replacestub_start = .);
 		*(.replacestub)
-		__replacestub_end = .;
+		HIDDEN(__replacestub_end = .);
 	}
-	__replacestub_len = ABSOLUTE(__replacestub_end) - ABSOLUTE(__replacestub_start);
-	__replacestub_dwords = (__replacestub_len + 3) >> 2;
+	HIDDEN(__replacestub_len = ABSOLUTE(__replacestub_end) - ABSOLUTE(__replacestub_start));
+	HIDDEN(__replacestub_dwords = (__replacestub_len + 3) >> 2);
 
 	. = ALIGN(16);
-	__gentextnr_lma = .;
+	HIDDEN(__gentextnr_lma = .);
 	.gentextnr : AT(__gentextnr_lma) {
-		__gentextnr_start = .;
+		HIDDEN(__gentextnr_start = .);
 		*(.gentextnr)
-		__gentextnr_end = .;
+		HIDDEN(__gentextnr_end = .);
 	}
-	__gentextnr_len = ABSOLUTE(__gentextnr_end) - ABSOLUTE(__gentextnr_start);
-	__gentextnr_dwords = (__gentextnr_len + 3) >> 2;
+	HIDDEN(__gentextnr_len = ABSOLUTE(__gentextnr_end) - ABSOLUTE(__gentextnr_start));
+	HIDDEN(__gentextnr_dwords = (__gentextnr_len + 3) >> 2);
 
-	. = STACK_BASE;
-	.stack16 : AT(STACK_BASE) {
-		__stack16_start = .;
-		. += STACK_LEN;
-		__stack16_end = .;
+	. = _STACK_BASE;
+	.stack16 : AT(_STACK_BASE) {
+		HIDDEN(__stack16_start = .);
+		*(.stack16)
+		HIDDEN(__stack16_end = .);
 	}
-	__stack16_len = ABSOLUTE(__stack16_end) - ABSOLUTE(__stack16_start);
-	__stack16_dwords = (__stack16_len + 3) >> 2;
+	HIDDEN(__stack16_len = ABSOLUTE(__stack16_end) - ABSOLUTE(__stack16_start));
+	HIDDEN(__stack16_dwords = (__stack16_len + 3) >> 2);
 
 	/* Initialized sections */
 
 	. = 0x7c00;
 	.init : {
 		FILL(0x90909090)
-		__init_start = .;
+		HIDDEN(__init_start = .);
 		*(.init)
-		__init_end = .;
+		HIDDEN(__init_end = .);
 	}
-	__init_len = ABSOLUTE(__init_end) - ABSOLUTE(__init_start);
-	__init_dwords = (__init_len + 3) >> 2;
+	HIDDEN(__init_len = ABSOLUTE(__init_end) - ABSOLUTE(__init_start));
+	HIDDEN(__init_dwords = (__init_len + 3) >> 2);
 
 	. = ALIGN(4);
 	.text16 : {
 		FILL(0x90909090)
-		__text16_start = .;
+		HIDDEN(__text16_start = .);
 		*(.text16)
-		__text16_end = .;
+		HIDDEN(__text16_end = .);
 	}
-	__text16_len = ABSOLUTE(__text16_end) - ABSOLUTE(__text16_start);
-	__text16_dwords = (__text16_len + 3) >> 2;
+	HIDDEN(__text16_len = ABSOLUTE(__text16_end) - ABSOLUTE(__text16_start));
+	HIDDEN(__text16_dwords = (__text16_len + 3) >> 2);
 
 	/*
 	 * .textnr is used for 32-bit code that is used on the code
@@ -119,83 +119,83 @@ SECTIONS
 	. = ALIGN(16);
 	.textnr : {
 		FILL(0x90909090)
-		__textnr_start = .;
+		HIDDEN(__textnr_start = .);
 		*(.textnr)
-		__textnr_end = .;
+		HIDDEN(__textnr_end = .);
 	}
-	__textnr_len = ABSOLUTE(__textnr_end) - ABSOLUTE(__textnr_start);
-	__textnr_dwords = (__textnr_len + 3) >> 2;
+	HIDDEN(__textnr_len = ABSOLUTE(__textnr_end) - ABSOLUTE(__textnr_start));
+	HIDDEN(__textnr_dwords = (__textnr_len + 3) >> 2);
 
 	. = ALIGN(16);
-	__bcopyxx_start = .;
+	HIDDEN(__bcopyxx_start = .);
 
 	.bcopyxx.text : {
 		FILL(0x90909090)
-		__bcopyxx_text_start = .;
+		HIDDEN(__bcopyxx_text_start = .);
 		*(.bcopyxx.text)
-		__bcopyxx_text_end = .;
+		HIDDEN(__bcopyxx_text_end = .);
 	}
-	__bcopyxx_text_len = ABSOLUTE(__bcopyxx_text_end) - ABSOLUTE(__bcopyxx_text_start);
-	__bcopyxx_text_dwords = (__bcopyxx_text_len + 3) >> 2;
+	HIDDEN(__bcopyxx_text_len = ABSOLUTE(__bcopyxx_text_end) - ABSOLUTE(__bcopyxx_text_start));
+	HIDDEN(__bcopyxx_text_dwords = (__bcopyxx_text_len + 3) >> 2);
 
 	.bcopyxx.data : {
-		__bcopyxx_data_start = .;
+		HIDDEN(__bcopyxx_data_start = .);
 		*(.bcopyxx.text)
-		__bcopyxx_data_end = .;
+		HIDDEN(__bcopyxx_data_end = .);
 	}
-	__bcopyxx_data_len = ABSOLUTE(__bcopyxx_data_end) - ABSOLUTE(__bcopyxx_data_start);
-	__bcopyxx_data_dwords = (__bcopyxx_data_len + 3) >> 2;
+	HIDDEN(__bcopyxx_data_len = ABSOLUTE(__bcopyxx_data_end) - ABSOLUTE(__bcopyxx_data_start));
+	HIDDEN(__bcopyxx_data_dwords = (__bcopyxx_data_len + 3) >> 2);
 
 	__bcopyxx_end = .;
-	__bcopyxx_len = ABSOLUTE(__bcopyxx_end) - ABSOLUTE(__bcopyxx_start);
-	__bcopyxx_dwords = (__bcopyxx_len + 3) >> 2;
+	HIDDEN(__bcopyxx_len = ABSOLUTE(__bcopyxx_end) - ABSOLUTE(__bcopyxx_start));
+	HIDDEN(__bcopyxx_dwords = (__bcopyxx_len + 3) >> 2);
 
 	. = ALIGN(4);
 	.data16 : {
-	      __data16_start = .;
+	      HIDDEN(__data16_start = .);
 	      *(.data16)
-	      __data16_end = .;
+	      HIDDEN(__data16_end = .);
 	}
-	__data16_len = ABSOLUTE(__data16_end) - ABSOLUTE(__data16_start);
-	__data16_dwords = (__data16_len + 3) >> 2;
+	HIDDEN(__data16_len = ABSOLUTE(__data16_end) - ABSOLUTE(__data16_start));
+	HIDDEN(__data16_dwords = (__data16_len + 3) >> 2);
 
 	. = ALIGN(4);
-	__config_lma = ABSOLUTE(.);
+	HIDDEN(__config_lma = ABSOLUTE(.));
 	. += SIZEOF(.config);
 
 	. = ALIGN(4);
-	__replacestub_lma = ABSOLUTE(.);
+	HIDDEN(__replacestub_lma = ABSOLUTE(.));
 	. += SIZEOF(.replacestub);
 
 	/* The 32-bit code loads above the non-progbits sections */
 
 	. = ALIGN(16);
-	__pm_code_lma = ABSOLUTE(.);
+	HIDDEN(__pm_code_lma = ABSOLUTE(.));
 
-	__high_clear_start = .;
+	HIDDEN(__high_clear_start = .);
 
 	. = ALIGN(512);
 	.adv (NOLOAD) : {
-		__adv_start = .;
+		HIDDEN(__adv_start = .);
 		*(.adv)
-		__adv_end = .;
+		HIDDEN(__adv_end = .);
 	}
-	__adv_len = ABSOLUTE(__adv_end) - ABSOLUTE(__adv_start);
-	__adv_dwords = (__adv_len + 3) >> 2;
+	HIDDEN(__adv_len = ABSOLUTE(__adv_end) - ABSOLUTE(__adv_start));
+	HIDDEN(__adv_dwords = (__adv_len + 3) >> 2);
 
 	/* Late uninitialized sections */
 
 	. = ALIGN(4);
 	.uibss (NOLOAD) : {
-		__uibss_start = .;
+		HIDDEN(__uibss_start = .);
 		*(.uibss)
-		__uibss_end = .;
+		HIDDEN(__uibss_end = .);
 	}
-	__uibss_len = ABSOLUTE(__uibss_end) - ABSOLUTE(__uibss_start);
-	__uibss_dwords = (__uibss_len + 3) >> 2;
+	HIDDEN(__uibss_len = ABSOLUTE(__uibss_end) - ABSOLUTE(__uibss_start));
+	HIDDEN(__uibss_dwords = (__uibss_len + 3) >> 2);
 
-	_end16 = .;
-	__assert_end16 = ASSERT(_end16 <= 0x10000, "64K overflow");
+	HIDDEN(_end16 = .);
+	HIDDEN(__assert_end16 = ASSERT(_end16 <= 0x10000, "64K overflow"));
 
 	/*
 	 * Special 16-bit segments
@@ -204,7 +204,7 @@ SECTIONS
 	.xfer_buf (NOLOAD) : {
 		*(.xfer_buf)
 	}
-	xfer_buf_seg = core_xfer_buf >> 4;
+	HIDDEN(xfer_buf_seg = core_xfer_buf >> 4);
 
 	/*
 	 * The auxiliary data segment is used by the 16-bit code
@@ -213,33 +213,33 @@ SECTIONS
 
 	. = ALIGN(16);
 	.auxseg (NOLOAD) : {
-		__auxseg_start = .;
+		HIDDEN(__auxseg_start = .);
 		*(.auxseg)
-		__auxseg_end = .;
+		HIDDEN(__auxseg_end = .);
 	}
-	__auxseg_len = ABSOLUTE(__auxseg_end) - ABSOLUTE(__auxseg_start);
-	__auxseg_dwords = (__auxseg_len + 3) >> 2;
-	aux_seg = __auxseg_start >> 4;
+	HIDDEN(__auxseg_len = ABSOLUTE(__auxseg_end) - ABSOLUTE(__auxseg_start));
+	HIDDEN(__auxseg_dwords = (__auxseg_len + 3) >> 2);
+	HIDDEN(aux_seg = __auxseg_start >> 4);
 
 	/*
 	 * Used to allocate lowmem buffers from 32-bit code
 	 */
 	.lowmem (NOLOAD) : {
-		__lowmem_start = .;
+		HIDDEN(__lowmem_start = .);
 		*(.lowmem)
-		__lowmem_end = .;
+		HIDDEN(__lowmem_end = .);
 	}
-	__lowmem_len = ABSOLUTE(__lowmem_end) - ABSOLUTE(__lowmem_start);
-	__lowmem_dwords = (__lowmem_len + 3) >> 2;
+	HIDDEN(__lowmem_len = ABSOLUTE(__lowmem_end) - ABSOLUTE(__lowmem_start));
+	HIDDEN(__lowmem_dwords = (__lowmem_len + 3) >> 2);
 
-	__high_clear_end = .;
+	HIDDEN(__high_clear_end = .);
 
-	__high_clear_len = ABSOLUTE(__high_clear_end) - ABSOLUTE(__high_clear_start);
-	__high_clear_dwords = (__high_clear_len + 3) >> 2;
+	HIDDEN(__high_clear_len = ABSOLUTE(__high_clear_end) - ABSOLUTE(__high_clear_start));
+	HIDDEN(__high_clear_dwords = (__high_clear_len + 3) >> 2);
 
 	/* Start of the lowmem heap */
 	. = ALIGN(16);
-	__lowmem_heap = .;
+	HIDDEN(__lowmem_heap = .);
 
 	/*
 	 * 32-bit code.  This is a hack for the moment due to the
@@ -248,133 +248,133 @@ SECTIONS
 
 	. = 0x100000;
 
-	__pm_code_start = .;
-	__vma_to_lma = ABSOLUTE(__pm_code_lma - __pm_code_start);
+	HIDDEN(__pm_code_start = .);
+	HIDDEN(__vma_to_lma = ABSOLUTE(__pm_code_lma - __pm_code_start));
 
 	.text : AT(ADDR(.text) + __vma_to_lma) {
 		FILL(0x90909090)
-		__text_start = .;
+		HIDDEN(__text_start = .);
 		*(.text)
 		*(.text.*)
-		__text_end = .;
+		HIDDEN(__text_end = .);
 	}
 
 	.rodata : AT(ADDR(.rodata) + __vma_to_lma) {
-		__rodata_start = .;
+		HIDDEN(__rodata_start = .);
 		*(.rodata)
 		*(.rodata.*)
-		__rodata_end = .;
+		HIDDEN(__rodata_end = .);
 	}
 
 	.ctors : AT(ADDR(.ctors) + __vma_to_lma) {
-		__ctors_start = .;
+		HIDDEN(__ctors_start = .);
 		KEEP (*(SORT(.ctors.*)))
 		KEEP (*(.ctors))
-		__ctors_end = .;
+		HIDDEN(__ctors_end = .);
 	}
 
 	.dtors : AT(ADDR(.dtors) + __vma_to_lma) {
-		__dtors_start = .;
+		HIDDEN(__dtors_start = .);
 		KEEP (*(SORT(.dtors.*)))
 		KEEP (*(.dtors))
-		__dtors_end = .;
+		HIDDEN(__dtors_end = .);
 	}
 
 	.dynsym : AT(ADDR(.dynsym) + __vma_to_lma) {
-		__dynsym_start = .;
+		HIDDEN(__dynsym_start = .);
 		KEEP (*(.dynsym))
-		__dynsym_end = .;
+		HIDDEN(__dynsym_end = .);
 	}
-	__dynsym_len = __dynsym_end - __dynsym_start;
+	HIDDEN(__dynsym_len = __dynsym_end - __dynsym_start);
 
 	.dynstr : AT(ADDR(.dynstr) + __vma_to_lma) {
-		__dynstr_start = .;
+		HIDDEN(__dynstr_start = .);
 		KEEP (*(.dynstr))
-		__dynstr_end = .;
+		HIDDEN(__dynstr_end = .);
 	}
-	__dynstr_len = __dynstr_end - __dynstr_start;
+	HIDDEN(__dynstr_len = __dynstr_end - __dynstr_start);
 
 	.gnu.hash : AT(ADDR(.gnu.hash) + __vma_to_lma) {
-		__gnu_hash_start = .;
+		HIDDEN(__gnu_hash_start = .);
 		KEEP (*(.gnu.hash))
-		__gnu_hash_end = .;
+		HIDDEN(__gnu_hash_end = .);
 	}
 
 
 	.dynlink : AT(ADDR(.dynlink) + __vma_to_lma) {
-		__dynlink_start = .;
+		HIDDEN(__dynlink_start = .);
 		KEEP (*(.dynlink))
-		__dynlink_end = .;
+		HIDDEN(__dynlink_end = .);
 	}
 
 	.got : AT(ADDR(.got) + __vma_to_lma) {
-		__got_start = .;
+		HIDDEN(__got_start = .);
 		KEEP (*(.got))
 		KEEP (*(.got.plt))
-		__got_end = .;
+		HIDDEN(__got_end = .);
 	}
 
 	.dynamic : AT(ADDR(.dynamic) + __vma_to_lma) {
-		__dynamic_start = .;
+		HIDDEN(__dynamic_start = .);
 		KEEP (*(.dynamic))
-		__dynamic_end = .;
+		HIDDEN(__dynamic_end = .);
 	}
 
 	.data : AT(ADDR(.data) + __vma_to_lma) {
-		__data_start = .;
+		HIDDEN(__data_start = .);
 		*(.data)
 		*(.data.*)
-		__data_end = .;
+		HIDDEN(__data_end = .);
 	}
 
-	__pm_code_end = .;
-	__pm_code_len = ABSOLUTE(__pm_code_end) - ABSOLUTE(__pm_code_start);
-	__pm_code_dwords = (__pm_code_len + 3) >> 2;
+	HIDDEN(__pm_code_end = .);
+	HIDDEN(__pm_code_len = ABSOLUTE(__pm_code_end) - ABSOLUTE(__pm_code_start));
+	HIDDEN(__pm_code_dwords = (__pm_code_len + 3) >> 2);
 
 	. = ALIGN(128);
 
-	__bss_vma = .;
-	__bss_lma = ABSOLUTE(.);		/* Dummy */
+	HIDDEN(__bss_vma = .);
+	HIDDEN(__bss_lma = ABSOLUTE(.));	/* Dummy */
 	.bss (NOLOAD) : AT (__bss_lma) {
-		__bss_start = .;
+		HIDDEN(__bss_start = .);
 		*(.bss)
 		*(.bss.*)
 		*(COMMON)
-		__bss_end = .;
+		HIDDEN(__bss_end = .);
 	}
-	__bss_len = ABSOLUTE(__bss_end) - ABSOLUTE(__bss_start);
-	__bss_dwords = (__bss_len + 3) >> 2;
+	HIDDEN(__bss_len = ABSOLUTE(__bss_end) - ABSOLUTE(__bss_start));
+	HIDDEN(__bss_dwords = (__bss_len + 3) >> 2);
 
 	/* Very large objects which don't need to be zeroed */
 
-	__hugebss_vma = .;
-	__hugebss_lma = ABSOLUTE(.);		/* Dummy */
+	HIDDEN(__hugebss_vma = .);
+	HIDDEN(__hugebss_lma = ABSOLUTE(.));	/* Dummy */
 	.hugebss (NOLOAD) : AT (__hugebss_lma) {
-		__hugebss_start = .;
+		HIDDEN(__hugebss_start = .);
 		*(.hugebss)
 		*(.hugebss.*)
-		__hugebss_end = .;
+		HIDDEN(__hugebss_end = .);
 	}
-	__hugebss_len = ABSOLUTE(__hugebss_end) - ABSOLUTE(__hugebss_start);
-	__hugebss_dwords = (__hugebss_len + 3) >> 2;
+	HIDDEN(__hugebss_len = ABSOLUTE(__hugebss_end) - ABSOLUTE(__hugebss_start));
+	HIDDEN(__hugebss_dwords = (__hugebss_len + 3) >> 2);
 
 
 	/* XXX: This stack should be unified with the COM32 stack */
-	__stack_vma = .;
-	__stack_lma = ABSOLUTE(.);		/* Dummy */
+	HIDDEN(__stack_vma = .);
+	HIDDEN(__stack_lma = ABSOLUTE(.));	/* Dummy */
 	.stack (NOLOAD) : AT(__stack_lma) {
-		__stack_start = .;
+		HIDDEN(__stack_start = .);
 		*(.stack)
-		__stack_end = .;
+		HIDDEN(__stack_end = .);
 	}
-	__stack_len = ABSOLUTE(__stack_end) - ABSOLUTE(__stack_start);
-	__stack_dwords = (__stack_len + 3) >> 2;
+	HIDDEN(__stack_len = ABSOLUTE(__stack_end) - ABSOLUTE(__stack_start));
+	HIDDEN(__stack_dwords = (__stack_len + 3) >> 2);
 
-	_end = .;
+	HIDDEN(_end = .);
 
 	/* The first block of the heap is here */
 	. = ALIGN(4096);
-	free_high_memory = .;
+	HIDDEN(free_high_memory = .);
 
 	/* Stuff we don't need... */
 	/DISCARD/ : {
diff --git a/core/bios/timer.inc b/core/bios/timer.inc
index 80647983..1abef441 100644
--- a/core/bios/timer.inc
+++ b/core/bios/timer.inc
@@ -32,7 +32,7 @@ timer_init:
 		mov dword [BIOS_timer_hook],timer_irq
 		ret
 
-		global bios_timer_cleanup:function hidden
+		hidden bios_timer_cleanup:function
 bios_timer_cleanup:
 		; Unhook INT 1Ch
 		mov eax,[BIOS_timer_next]
@@ -43,18 +43,19 @@ bios_timer_cleanup:
 ; The specified frequency is 14.31818 MHz/12/65536; this turns out
 ; to be a period of 54.92542 ms, or 0x36.ece8(187c) hexadecimal.
 ;
-		global timer_irq:function hidden
+		hidden timer_irq:function
 timer_irq:
 		inc dword [cs:__jiffies]
 		add word  [cs:__ms_timer_adj],0xece8
 		adc dword [cs:__ms_timer],0x36
 		jmp 0:0
-		global BIOS_timer_next:data hidden
+		hidden BIOS_timer_next:data
 BIOS_timer_next	equ $-4
 
 		section .data16
 		alignz 4
-		global __jiffies:data hidden, __ms_timer
+		hidden __jiffies:data
+		hidden __ms_timer:data 4
 __jiffies	dd 0			; Clock tick timer
 __ms_timer	dd 0			; Millisecond timer
 __ms_timer_adj	dw 0			; Millisecond timer correction factor
diff --git a/core/codepage.S b/core/codepage.S
index 4f1d4836..6fb046f6 100644
--- a/core/codepage.S
+++ b/core/codepage.S
@@ -1,5 +1,6 @@
 	.section ".rodata","a"
 	.globl	codepage
+	.hidden	codepage
 codepage:
 	.incbin "codepage.cp"
 	.size	codepage, .-codepage
diff --git a/core/elflink/elfutils.h b/core/elflink/elfutils.h
deleted file mode 100644
index f641b119..00000000
--- a/core/elflink/elfutils.h
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef ELF_UTILS_H_
-#define ELF_UTILS_H_
-
-#include <elf.h>
-#include <stdlib.h>
-
-/**
- * elf_get_header - Returns a pointer to the ELF header structure.
- * @elf_image: pointer to the ELF file image in memory
- */
-static inline Elf_Ehdr *elf_get_header(void *elf_image)
-{
-    return (Elf_Ehdr *) elf_image;
-}
-
-/**
- * elf_get_pht - Returns a pointer to the first entry in the PHT.
- * @elf_image: pointer to the ELF file image in memory
- */
-static inline Elf_Phdr *elf_get_pht(void *elf_image)
-{
-    Elf_Ehdr *elf_hdr = elf_get_header(elf_image);
-
-    return (Elf_Phdr *) ((Elf_Off) elf_hdr + elf_hdr->e_phoff);
-}
-
-//
-/**
- * elf_get_ph - Returns the element with the given index in the PTH
- * @elf_image: pointer to the ELF file image in memory
- * @index: the index of the PHT entry to look for
- */
-static inline Elf_Phdr *elf_get_ph(void *elf_image, int index)
-{
-    Elf_Phdr *elf_pht = elf_get_pht(elf_image);
-    Elf_Ehdr *elf_hdr = elf_get_header(elf_image);
-
-    return (Elf_Phdr *) ((Elf_Off) elf_pht + index * elf_hdr->e_phentsize);
-}
-
-/**
- * elf_hash - Returns the index in a SysV hash table for the symbol name.
- * @name: the name of the symbol to look for
- */
-extern unsigned long elf_hash(const unsigned char *name);
-
-/**
- * elf_gnu_hash - Returns the index in a GNU hash table for the symbol name.
- * @name: the name of the symbol to look for
- */
-extern unsigned long elf_gnu_hash(const unsigned char *name);
-
-/**
- * elf_malloc - Allocates memory to be used by ELF module contents.
- * @memptr: pointer to a variable to hold the address of the allocated block.
- * @alignment: alignment constraints of the block
- * @size: the required size of the block
- */
-extern int elf_malloc(void **memptr, size_t alignment, size_t size);
-
-/**
- * elf_free - Releases memory previously allocated by elf_malloc.
- * @memptr: the address of the allocated block
- */
-extern void elf_free(void *memptr);
-
-#endif /*ELF_UTILS_H_ */
diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c
index 3d54a8b7..1457bf3d 100644
--- a/core/elflink/load_env32.c
+++ b/core/elflink/load_env32.c
@@ -157,7 +157,7 @@ void load_env32(com32sys_t * regs __unused)
 {
 	struct file_info *fp;
 	int fd;
-	char *argv[] = { LDLINUX, NULL };
+	const char * const argv[] = { LDLINUX, NULL };
 	char realname[FILENAME_MAX];
 	size_t size;
 
@@ -175,7 +175,7 @@ void load_env32(com32sys_t * regs __unused)
 		NULL
 	};
 
-	dprintf("Starting %s elf module subsystem...\n", ELF_MOD_SYS);
+	dprintf("Starting %d-bit ELF module subsystem...\n", ELF_CLASS_SIZE);
 
 	if (strlen(CurrentDirName) && !path_add(CurrentDirName)) {
 		printf("Couldn't allocate memory for PATH\n");
diff --git a/core/export.pl b/core/export.pl
new file mode 100755
index 00000000..16c63dbf
--- /dev/null
+++ b/core/export.pl
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+#
+# Script to generate an export library .a file and list of symbols to
+# be weakened from a set of executables or shared libraries (with a
+# dynamic symbol section.)
+#
+
+use strict;
+
+sub getint($) {
+    my($s) = @_;
+
+    return ($s =~ /^0/) ? oct $s : $s+0;
+}
+
+my ($outfile, $weakfile, @infiles) = @ARGV;
+
+my %nsyms;			# Number of files in which this symbol occurs
+my %syms;			# Symbol information
+my %fsyms;			# Files in which this symbol occurs
+
+my $readelf = $ENV{'READELF'} || 'readelf';
+
+foreach my $infile (@infiles) {
+    open(my $in, '-|', $readelf, '--dyn-syms', $infile)
+	or die "$0: $infile: $!\n";
+
+    while (my $line = <$in>) {
+	$line =~ s/^\s+//;
+	$line =~ s/\s+$//;
+
+	next unless ($line =~ /^[0-9]+\:/);
+	
+	my ($n,$addr,$size,$type,$link,$vis,$sec,$name) = split(/\s+/, $line);
+
+	next if ($name eq '');	# Null symbol
+
+	$addr = hex $addr;
+	$size = getint($size);
+	if ($nsyms{$name}++ == 0) {
+	    $fsyms{$name} = [$infile];
+	} else {
+	    push(@{$fsyms{$name}}, $infile);
+	}
+	$syms{$name} = [$addr,$size,$type,$link,$vis];
+    }
+
+    close($in);
+}
+	
+my $nfiles = scalar(@infiles);
+
+open(my $out, '>', $outfile)
+    or die "$0: $outfile: $!\n";
+open(my $weak, '>', $weakfile)
+    or die "$0: $weakfile: $!\n";
+
+foreach my $sym (sort(keys(%nsyms))) {
+    if ($nsyms{$sym} == $nfiles) {
+	# It is an exportable symbol common to all inputs
+	
+	my($addr,$size,$type,$link,$vis) = @{$syms{$sym}};
+	printf $out "\t.globl\t%s\n", $sym;
+	printf $out "%s\t= 0x%08x\n", $sym, $addr;
+	printf $out "\t.type\t%s, STT_%s\n", $sym, $type;
+	printf $out "\t.size\t%s, %u\n", $sym, $size;
+	if ($vis ne 'DEFAULT') {
+	    printf $out "\t.%s\t%s\n", "\L$vis", $sym;
+	}
+    } else {
+	# It is a symbol present in at least one input, should
+	# be made weak in the dynamic library if present
+
+	print $weak '# ', join(' ', @{$fsyms{$sym}}), "\n";
+	print $weak $sym, "\n";
+    }
+}
+
+close($out);
+close($weak);
+
+exit 0;
+
diff --git a/core/fs/fs.c b/core/fs/fs.c
index 41618487..fc496324 100644
--- a/core/fs/fs.c
+++ b/core/fs/fs.c
@@ -117,7 +117,7 @@ __export void mangle_name(char *dst, const char *src)
     this_fs->fs_ops->mangle_name(dst, src);
 }
 
-size_t pmapi_read_file(uint16_t *handle, void *buf, size_t sectors)
+__export size_t pmapi_read_file(uint16_t *handle, void *buf, size_t sectors)
 {
     bool have_more;
     size_t bytes_read;
diff --git a/core/include/core.h b/core/include/core.h
index 4783d75f..a92a5dfa 100644
--- a/core/include/core.h
+++ b/core/include/core.h
@@ -24,8 +24,10 @@ extern char ConfigName[];
 extern char config_cwd[];
 extern char cmd_line[];
 extern char ConfigFile[];
-extern char syslinux_banner[];
-extern char copyright_str[];
+extern const uint16_t __syslinux_core_version;
+extern const char syslinux_banner[];
+extern const char copyright_str[];
+extern char StackBuf[];
 
 extern const size_t __syslinux_shuffler_size;
 
@@ -34,17 +36,23 @@ static inline size_t syslinux_shuffler_size(void)
     return __syslinux_shuffler_size;
 }
 
-/*
- * Mark symbols that are only used by BIOS as __weak until we can move
- * all references out of the generic (EFI + BIOS) code and into
- * BIOS-specific code.
- */
-extern __weak uint16_t BIOSName;
-extern __weak char KernelName[];
-extern __weak char StackBuf[];
+#ifdef __FIRMWARE_BIOS__
+static inline const char *bios_name(void)
+{
+    extern const uint16_t BIOSName;
+    return BIOSName ? (const char *)(size_t)BIOSName : "";
+}
+#else
+static inline const char *bios_name(void)
+{
+    return "";
+}
+#endif
 
 extern uint8_t KbdMap[256];
 
+extern size_t HighMemSize;
+
 extern const uint16_t IPAppends[];
 extern size_t numIPAppends;
 
@@ -93,10 +101,6 @@ extern uint32_t SysAppends;
 extern void sysappend_set_uuid(const uint8_t *uuid);
 extern void sysappend_set_fs_uuid(void);
 
-void __cdecl core_intcall(uint8_t, const com32sys_t *, com32sys_t *);
-void __cdecl core_farcall(uint32_t, const com32sys_t *, com32sys_t *);
-int __cdecl core_cfarcall(uint32_t, const void *, uint32_t);
-
 extern const com32sys_t zero_regs;
 void call16(void (*)(void), const com32sys_t *, com32sys_t *);
 
diff --git a/core/mem/init.c b/core/mem/init.c
index 246d2e0c..4f2ae70c 100644
--- a/core/mem/init.c
+++ b/core/mem/init.c
@@ -26,9 +26,9 @@ int scan_highmem_area(void *data, addr_t start, addr_t len,
 			     || type != SMT_FREE)
 		return 0;
 
-	if (start < __com32.cs_memsize) {
-		len -= __com32.cs_memsize - start;
-		start = __com32.cs_memsize;
+	if (start < HighMemSize) {
+		len -= HighMemSize - start;
+		start = HighMemSize;
 	}
 	if (len > E820_MEM_MAX - start)
 		len = E820_MEM_MAX - start;
@@ -44,7 +44,7 @@ int scan_highmem_area(void *data, addr_t start, addr_t len,
 		__inject_free_block(fp);
 	}
 
-	__com32.cs_memsize = start + len; /* update the HighMemSize */
+	HighMemSize = start + len; /* update the HighMemSize */
 	return 0;
 }
 
@@ -99,6 +99,6 @@ void mem_init(void)
 	__inject_free_block(fp);
 
 	/* Initialize the main heap */
-	__com32.cs_memsize = (size_t)free_high_memory;
+	HighMemSize = (size_t)free_high_memory;
 	syslinux_scan_memory(scan_highmem_area, NULL);
 }
diff --git a/diag/geodsp/Makefile b/diag/geodsp/Makefile
index 92d6be2d..2561d3d6 100644
--- a/diag/geodsp/Makefile
+++ b/diag/geodsp/Makefile
@@ -25,8 +25,8 @@ VPATH = $(SRC)
 BTARGET = geodsp1s.bin geodsp1s_f.bin geodspms.bin \
 	geodsp1s.img.xz geodspms.img.xz
 
-NASMOPT = -i $(coredir)/ -i $(SRC)/ -Ox -f bin -dBINFMT
-NASMOPT += -w+orphan-labels
+NASMFLAGS = -i $(coredir)/ -i $(SRC)/ -Ox -f bin -dBINFMT
+NASMFLAGS += -w+orphan-labels
 CFLAGS = -g -O
 LIBS = $(wildcard $(coredir)/*.inc)
 
@@ -44,10 +44,10 @@ all: $(BTARGET)
 	$(PERL) $(SRC)/mk-lba-img.pl $< > $@ || ( rm -f $@ ; false )
 
 %.bin: %.asm $(LIBS)
-	$(NASM) $(NASMOPT) -o $@ -l $(@:.bin=.lst) $<
+	$(NASM) $(NASMFLAGS) -o $@ -l $(@:.bin=.lst) $<
 
 %_f.bin: %.asm $(LIBS)
-	$(NASM) $(NASMOPT) -o $@ -dFORCE_80 -l $(@:.bin=.lst) $<
+	$(NASM) $(NASMFLAGS) -o $@ -dFORCE_80 -l $(@:.bin=.lst) $<
 
 mk-lba-img: mk-lba-img.c
 	$(CC) $(CFLAGS) -o $@ $<
diff --git a/diag/geodsp/geodspms.asm b/diag/geodsp/geodspms.asm
index a5521fe4..d8e3d9e8 100644
--- a/diag/geodsp/geodspms.asm
+++ b/diag/geodsp/geodspms.asm
@@ -44,6 +44,8 @@
 %include "macros.inc"
 ; %include "layout.inc"
 
+_STACK_TOP	equ 7c00h
+
 m_CHS0		equ 00534843h		;'CHS',0
 m_EDD0		equ 00444445h		;'EDD',0
 m_EDD_SP	equ 20444445h		;'EDD '
diff --git a/diag/mbr/Makefile b/diag/mbr/Makefile
index 5b7153c9..1e58b773 100644
--- a/diag/mbr/Makefile
+++ b/diag/mbr/Makefile
@@ -24,7 +24,6 @@ all:	handoff.bin
 %.o: %.S
 	$(CC) $(MAKEDEPS) $(SFLAGS) -Wa,-a=$*.lst -c -o $@ $<
 
-.PRECIOUS: %.elf
 %.elf: %.o $(mbrdir)/mbr.ld
 	$(LD) $(LDFLAGS) -T $(mbrdir)/$(ARCH)/mbr.ld -e _start -o $@ $<
 
diff --git a/doc/pxelinux.txt b/doc/pxelinux.txt
index 4dbb152e..59ceaf79 100644
--- a/doc/pxelinux.txt
+++ b/doc/pxelinux.txt
@@ -121,7 +121,6 @@ option (RFC 1784/RFC 2349).  The "tftp-hpa" TFTP server, which support
 options, is available at:
 
 	http://www.kernel.org/pub/software/network/tftp/
-	ftp://www.kernel.org/pub/software/network/tftp/
 
 ... and on any kernel.org mirror (see http://www.kernel.org/mirrors/).
 
diff --git a/dos/Makefile b/dos/Makefile
index 4c930d19..1ab69826 100644
--- a/dos/Makefile
+++ b/dos/Makefile
@@ -72,8 +72,8 @@ syslinux.com: syslinux.elf
 		true
 
 %.com: %.asm
-	$(NASM) $(NASMOPT) -f bin -o $@ -MP -MD .$@.d -l $*.lst $<
+	$(NASM) $(NASMFLAGS) -f bin -o $@ -MP -MD .$@.d -l $*.lst $<
 
-ldlinux.o: ldlinux.S $(OBJ)/../core/ldlinux.sys
+ldlinux.o: ldlinux.S $(objdir)/core/ldlinux.sys $(objdir)/ldlinux/ldlinux.c32
 
 -include .*.d
diff --git a/dos/ldlinux.S b/dos/ldlinux.S
index 9145bd7b..ce448c7d 100644
--- a/dos/ldlinux.S
+++ b/dos/ldlinux.S
@@ -12,7 +12,7 @@ syslinux_ldlinux_size	= . - syslinux_ldlinux
 	.size	syslinux_ldlinux, .-syslinux_ldlinux
 	.globl	syslinux_ldlinuxc32, syslinux_ldlinuxc32_size
 syslinux_ldlinuxc32:
-	.incbin "../com32/elflink/ldlinux/ldlinux.c32"
+	.incbin "../ldlinux/ldlinux.c32"
 	.space ((syslinux_ldlinuxc32 - .) & 511)
 syslinux_ldlinuxc32_size = . - syslinux_ldlinuxc32
 	.size	syslinux_ldlinuxc32, .-syslinux_ldlinuxc32
diff --git a/dosutil/Makefile b/dosutil/Makefile
index 69fc58ad..5ed3384e 100644
--- a/dosutil/Makefile
+++ b/dosutil/Makefile
@@ -13,7 +13,7 @@ WCL_IS_GOOD := $(shell $(WCL) $(WCLOPT) \
 UPX     = upx
 
 NASM    = nasm
-NASMOPT = -Ox
+NASMFLAGS = -Ox
 
 WCTARGETS = mdiskchk.com
 NSTARGETS = eltorito.sys copybs.com
@@ -33,7 +33,7 @@ TARGETS   = $(WCTARGETS) $(NSTARGETS)
 	chmod a-x $@
 
 %.sys: %.asm
-	$(NASM) $(NASMOPT) -f bin -o $@ -l $*.lst $<
+	$(NASM) $(NASMFLAGS) -f bin -o $@ -l $*.lst $<
 	$(UPX) --ultra-brute --lzma $@ || \
 		$(UPX) --ultra-brute $@ || \
 		true
@@ -41,7 +41,7 @@ TARGETS   = $(WCTARGETS) $(NSTARGETS)
 	chmod a-x $@
 
 %.com: %.asm
-	$(NASM) $(NASMOPT) -f bin -o $@ -l $*.lst $<
+	$(NASM) $(NASMFLAGS) -f bin -o $@ -l $*.lst $<
 	$(UPX) --ultra-brute --lzma $@ || \
 		$(UPX) --ultra-brute $@ || \
 		true
diff --git a/efi/Makefile b/efi/Makefile
index 00fab618..780ff18d 100644
--- a/efi/Makefile
+++ b/efi/Makefile
@@ -11,7 +11,7 @@
 ## -----------------------------------------------------------------------
 
 VPATH = $(SRC)
-include $(MAKEDIR)/lib.mk
+include $(MAKEDIR)/elf.mk
 include $(MAKEDIR)/efi.mk
 
 CC_FOR_BUILD ?= $(CC)
diff --git a/efi/main.c b/efi/main.c
index 6a748412..5c302744 100644
--- a/efi/main.c
+++ b/efi/main.c
@@ -483,7 +483,7 @@ struct boot_params {
 #define BOOT_PARAM_BLKSIZE	EFI_SIZE_TO_PAGES(sizeof(struct boot_params)) * EFI_PAGE_SIZE
 
 /* Routines in support of efi boot loader were obtained from
- * http://git.kernel.org/?p=boot/efilinux/efilinux.git:
+ * https://git.kernel.org/?p=boot/efilinux/efilinux.git:
  * kernel_jump(), handover_jump(),
  * emalloc()/efree, alloc_pages/free_pages
  * allocate_pool()/free_pool()
diff --git a/com32/elflink/ldlinux/Makefile b/ldlinux/Makefile
similarity index 55%
rename from com32/elflink/ldlinux/Makefile
rename to ldlinux/Makefile
index 87c0d362..9b9302c8 100644
--- a/com32/elflink/ldlinux/Makefile
+++ b/ldlinux/Makefile
@@ -1,6 +1,6 @@
 ## -----------------------------------------------------------------------
 ##
-##   Copyright 2011-2013 Intel Corporation - All Rights Reserved
+##   Copyright 2011-2019 Intel Corporation - All Rights Reserved
 ##
 ##   This program is free software; you can redistribute it and/or modify
 ##   it under the terms of the GNU General Public License as published by
@@ -10,30 +10,34 @@
 ##
 ## -----------------------------------------------------------------------
 
-VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
-CFLAGS += -I$(topdir)/core/elflink -I$(topdir)/core/include -I$(topdir)/com32/lib -fvisibility=hidden
-LIBS = --whole-archive $(objdir)/com32/lib/libcom32min.a
+INCLUDE += -I$(topdir)/core/elflinux -I$(topdir)/core/include \
+	   -I$(com32)/lib
 
-OBJS = ldlinux.o cli.o readconfig.o refstr.o colors.o getadv.o adv.o \
+LDLINUX_LIBS = $(objdir)/com32/lib/libcom32.a $(LIBCORE)
+
+# This makes the core quite a bit smaller, but requires that the proper
+# __export tags are in place. It would be very good to add the same things
+# to the libraries, especially libcom32, for the same reason.
+CFLAGS += -fvisibility=hidden
+
+CFLAGS += -D__LDLINUX__
+
+OBJS = main.o cli.o readconfig.o refstr.o colors.o getadv.o adv.o \
 	execute.o chainboot.o kernel.o get_key.o advwrite.o setadv.o \
 	loadhigh.o msg.o
 
-BTARGET = $(LDLINUX)
+# For some reason ldlinux.elf is deleted even with .PRECIOUS, which
+# breaks the dependencies later on. List it explicitly in the all target
+# to force it to be kept.
+all: $(LDLINUX) ldlinux.elf ldlinux_lnx.a
 
-ifeq ($(FWCLASS),EFI)
-%.e$(BITS): %.elf
-	$(OBJCOPY) --strip-debug --strip-unneeded $< $@
-SONAME = $(patsubst %.elf,%.e$(BITS),$(@F))
-else
-SONAME = $(patsubst %.elf,%.c32,$(@F))
-endif
-
-all: $(BTARGET) ldlinux_lnx.a
+ldlinux.elf: $(OBJS) $(LDLINUX_LIBS)
+	$(LD) $(LDFLAGS) $(SHARED) -soname '$(LDLINUX)' -o $@ $(OBJS) $(LDLINUX_LIBS)
 
-ldlinux.elf : $(OBJS)
-	$(LD) $(LDFLAGS) -soname $(SONAME) -o $@ $^ $(LIBS)
+$(LDLINUX): ldlinux.elf
+	$(OBJCOPY) --strip-debug --strip-unneeded $< $@
 
 LNXCFLAGS += -D__export='__attribute__((visibility("default")))'
 LNXLIBOBJS = get_key.lo
diff --git a/com32/elflink/ldlinux/adv.c b/ldlinux/adv.c
similarity index 100%
rename from com32/elflink/ldlinux/adv.c
rename to ldlinux/adv.c
diff --git a/com32/elflink/ldlinux/advwrite.c b/ldlinux/advwrite.c
similarity index 100%
rename from com32/elflink/ldlinux/advwrite.c
rename to ldlinux/advwrite.c
diff --git a/com32/elflink/ldlinux/chainboot.c b/ldlinux/chainboot.c
similarity index 98%
rename from com32/elflink/ldlinux/chainboot.c
rename to ldlinux/chainboot.c
index 1b9217f5..10803f71 100644
--- a/com32/elflink/ldlinux/chainboot.c
+++ b/ldlinux/chainboot.c
@@ -124,7 +124,7 @@ void chainboot_file(const char *file, uint32_t type)
     } else {
 	const uint16_t *esdi = (const uint16_t *)sdi->disk.esdi_ptr;
 
-	regs.esp.l = (uint16_t)(unsigned long)StackBuf + 44;
+	regs.esp.l = (uint16_t)(size_t)StackBuf;
 
 	/*
 	 * DON'T DO THIS FOR PXELINUX...
diff --git a/com32/elflink/ldlinux/cli.c b/ldlinux/cli.c
similarity index 98%
rename from com32/elflink/ldlinux/cli.c
rename to ldlinux/cli.c
index 3119b11f..f6df2384 100644
--- a/com32/elflink/ldlinux/cli.c
+++ b/ldlinux/cli.c
@@ -421,12 +421,7 @@ const char *edit_cmdline(const char *input, int top /*, int width */ ,
 		break;
 	    }
 	case KEY_CTRL('V'):
-	    if (BIOSName)
-		printf("%s%s%s", syslinux_banner,
-		       (char *)MK_PTR(0, BIOSName), copyright_str);
-	    else
-		printf("%s%s", syslinux_banner, copyright_str);
-
+	    printf("%s%s%s", syslinux_banner, bios_name(), copyright_str);
 	    redraw = 1;
 	    break;
 
diff --git a/com32/elflink/ldlinux/colors.c b/ldlinux/colors.c
similarity index 100%
rename from com32/elflink/ldlinux/colors.c
rename to ldlinux/colors.c
diff --git a/com32/elflink/ldlinux/config.h b/ldlinux/config.h
similarity index 100%
rename from com32/elflink/ldlinux/config.h
rename to ldlinux/config.h
diff --git a/com32/elflink/ldlinux/execute.c b/ldlinux/execute.c
similarity index 100%
rename from com32/elflink/ldlinux/execute.c
rename to ldlinux/execute.c
diff --git a/com32/elflink/ldlinux/get_key.c b/ldlinux/get_key.c
similarity index 100%
rename from com32/elflink/ldlinux/get_key.c
rename to ldlinux/get_key.c
diff --git a/com32/elflink/ldlinux/getadv.c b/ldlinux/getadv.c
similarity index 100%
rename from com32/elflink/ldlinux/getadv.c
rename to ldlinux/getadv.c
diff --git a/com32/elflink/ldlinux/kernel.c b/ldlinux/kernel.c
similarity index 100%
rename from com32/elflink/ldlinux/kernel.c
rename to ldlinux/kernel.c
diff --git a/com32/elflink/ldlinux/loadhigh.c b/ldlinux/loadhigh.c
similarity index 100%
rename from com32/elflink/ldlinux/loadhigh.c
rename to ldlinux/loadhigh.c
diff --git a/com32/elflink/ldlinux/ldlinux.c b/ldlinux/main.c
similarity index 100%
rename from com32/elflink/ldlinux/ldlinux.c
rename to ldlinux/main.c
diff --git a/com32/elflink/ldlinux/msg.c b/ldlinux/msg.c
similarity index 100%
rename from com32/elflink/ldlinux/msg.c
rename to ldlinux/msg.c
diff --git a/com32/elflink/ldlinux/readconfig.c b/ldlinux/readconfig.c
similarity index 99%
rename from com32/elflink/ldlinux/readconfig.c
rename to ldlinux/readconfig.c
index 3d6aa27e..f05f60ca 100644
--- a/com32/elflink/ldlinux/readconfig.c
+++ b/ldlinux/readconfig.c
@@ -88,6 +88,8 @@ const char *ontimeout = NULL;	//"ontimeout" command line
 
 __export const char *default_cmd = NULL;	//"default" command line
 
+static char KernelName[FILENAME_MAX];
+
 /* Empty refstring */
 const char *empty_string;
 
@@ -767,8 +769,8 @@ extern void write_serial_str(char *);
 extern void loadfont(const char *);
 extern void loadkeys(const char *);
 
-extern char syslinux_banner[];
-extern char copyright_str[];
+extern const char syslinux_banner[];
+extern const char copyright_str[];
 
 /*
  * PATH-based lookup
diff --git a/com32/elflink/ldlinux/refstr.c b/ldlinux/refstr.c
similarity index 100%
rename from com32/elflink/ldlinux/refstr.c
rename to ldlinux/refstr.c
diff --git a/com32/elflink/ldlinux/setadv.c b/ldlinux/setadv.c
similarity index 100%
rename from com32/elflink/ldlinux/setadv.c
rename to ldlinux/setadv.c
diff --git a/libinstaller/Makefile b/libinstaller/Makefile
index 48a8fd3a..30a3b456 100644
--- a/libinstaller/Makefile
+++ b/libinstaller/Makefile
@@ -8,21 +8,21 @@ VPATH = $(SRC)
 
 all: installer
 
-bootsect_bin.c: $(OBJ)/../core/ldlinux.bss bin2c.pl
+installer: $(BINFILES)
+
+bootsect_bin.c: $(objdir)/core/ldlinux.bss bin2c.pl
 	$(PERL) $(SRC)/bin2c.pl syslinux_bootsect < $< > $@
 
-ldlinux_bin.c: $(OBJ)/../core/ldlinux.sys bin2c.pl
+ldlinux_bin.c: $(objdir)/core/ldlinux.sys bin2c.pl
 	$(PERL) $(SRC)/bin2c.pl syslinux_ldlinux 512 < $< > $@
 
-mbr_bin.c: $(OBJ)/../mbr/mbr.bin bin2c.pl
+mbr_bin.c: $(objdir)/mbr/mbr.bin bin2c.pl
 	$(PERL) $(SRC)/bin2c.pl syslinux_mbr < $< > $@
 
-gptmbr_bin.c: $(OBJ)/../mbr/gptmbr.bin bin2c.pl
+gptmbr_bin.c: $(objdir)/mbr/gptmbr.bin bin2c.pl
 	$(PERL) $(SRC)/bin2c.pl syslinux_gptmbr < $< > $@
 
-installer: $(BINFILES)
-
-ldlinuxc32_bin.c: $(OBJ)/../com32/elflink/ldlinux/ldlinux.c32 bin2c.pl
+ldlinuxc32_bin.c: $(objdir)/ldlinux/ldlinux.c32 bin2c.pl
 	$(PERL) $(SRC)/bin2c.pl syslinux_ldlinuxc32 < $< > $@
 
 tidy:
diff --git a/man/syslinux2ansi.1 b/man/syslinux2ansi.1
index 063e357c..89a05aed 100644
--- a/man/syslinux2ansi.1
+++ b/man/syslinux2ansi.1
@@ -15,8 +15,8 @@ Help and version command line options would be useful.
 The ability to put input and output filenames on the command line might
 be good as well.
 .SS Bug reports
-I would appreciate hearing of any problems you have with SYSLINUX.  I
-would also like to hear from you if you have successfully used SYSLINUX,
+I would appreciate hearing of any problems you have with Syslinux.  I
+would also like to hear from you if you have successfully used Syslinux,
 especially if you are using it for a distribution.
 .PP
 If you are reporting problems, please include all possible information
@@ -24,14 +24,14 @@ about your system and your BIOS; the vast majority of all problems
 reported turn out to be BIOD or hardware bugs, and I need as much
 information as possible in order to diagnose the problems.
 .PP
-There is a mailing list for discussion among SYSLINUX users and for
+There is a mailing list for discussion among Syslinux users and for
 announcements of new and test versions.   To join, send a message to
 majordomo at linux.kernel.org with the line:
 .PP
 .B subscribe syslinux
 .PP
 in the body of the message.  The submission address is
-syslinux at linux.kernel.org.
+syslinux at zytor.com.
 .SH "SEE ALSO"
 .BR syslinux(1),
 .BR perl(1)
diff --git a/mbr/Makefile b/mbr/Makefile
index be2bded7..f39616f9 100644
--- a/mbr/Makefile
+++ b/mbr/Makefile
@@ -32,7 +32,6 @@ all:	mbr.bin   altmbr.bin   gptmbr.bin   isohdpfx.bin   isohdppx.bin \
 %_f.o: %.S
 	$(CC) $(MAKEDEPS) $(SFLAGS) -Wa,-a=$*_f.lst -DFORCE_80 -c -o $@ $<
 
-.PRECIOUS: %.elf
 #%.elf: %.o mbr.ld
 %.elf: %.o $(SRC)/$(ARCH)/mbr.ld
 	$(LD) $(LDFLAGS) -T $(SRC)/$(ARCH)/mbr.ld -e _start -o $@ $<
diff --git a/memdisk/Makefile b/memdisk/Makefile
index ccd5738b..30f91900 100644
--- a/memdisk/Makefile
+++ b/memdisk/Makefile
@@ -12,13 +12,12 @@
 ## -----------------------------------------------------------------------
 
 include $(MAKEDIR)/embedded.mk
--include $(topdir)/version.mk
 
 INCLUDES = -I$(topdir)/com32/include -I$(objdir)
 CFLAGS  += -D__MEMDISK__ -DDATE='"$(DATE)"' -mregparm=3 -DREGPARM=3
 LDFLAGS  = $(GCCOPT) -g
 NASM     = nasm
-NASMOPT  = -Ox
+NASMFLAGS  = -Ox
 NFLAGS   = -dDATE='"$(DATE)"'
 NINCLUDE = -I$(SRC)/
 
@@ -70,12 +69,11 @@ memdisk16.o: memdisk16.asm
 
 memdisk16.o: memdisk16.asm
 	( $(NASM) -M -DDEPEND $(NFLAGS) $(NINCLUDE) -o $@ $< ; echo '' ) > .$@.d ; true
-	$(NASM) -f elf $(NASMOPT) $(NFLAGS) $(NINCLUDE) -o $@ -l $*.lst $<
+	$(NASM) -f elf $(NASMFLAGS) $(NFLAGS) $(NINCLUDE) -o $@ -l $*.lst $<
 
-.PRECIOUS: %.bin
 %.bin: %.asm
 	( $(NASM) -M -DDEPEND $(NFLAGS) $(NINCLUDE) -o $@ $< ; echo '' ) > .$@.d ; true
-	$(NASM) -f bin $(NASMOPT) $(NFLAGS) $(NINCLUDE) -o $@ -l $*.lst $<
+	$(NASM) -f bin $(NASMFLAGS) $(NFLAGS) $(NINCLUDE) -o $@ -l $*.lst $<
 
 memdisk_%.o: memdisk_%.bin
 	$(LD) --oformat elf32-i386 -r -b binary -o $@ $<
diff --git a/mk/efi.mk b/mk/efi.mk
index f097ad22..18346b44 100644
--- a/mk/efi.mk
+++ b/mk/efi.mk
@@ -54,11 +54,9 @@ $(LIBEFI):
 
 %.o: %.c
 
-.PRECIOUS: %.o
 %.o: %.S $(LIBEFI)
 	$(CC) $(SFLAGS) -c -o $@ $<
 
-.PRECIOUS: %.o
 %.o: %.c $(LIBEFI)
 	$(CC) $(CFLAGS) -c -o $@ $<
 
diff --git a/mk/elf.mk b/mk/elf.mk
index b46dbd06..8e7f4dba 100644
--- a/mk/elf.mk
+++ b/mk/elf.mk
@@ -42,68 +42,95 @@ GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0)
 GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0)
 GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0)
 GCCOPT += $(call gcc_ok,-falign-loops=0,-malign-loops=0)
+GCCOPT += $(call gcc_ok,-DNO_PLT -fno-plt -fvisibility=protected)
+
+ifeq ($(FWCLASS),EFI)
+GCCOPT += -mno-red-zone
+else
+GCCOPT += -mregparm=3 -DREGPARM=3
+endif
 
 com32 = $(topdir)/com32
 core = $(topdir)/core
 
+STRIP	= strip --strip-all -R .comment -R .note
+
 ifneq ($(NOGPL),1)
-GPLLIB     = $(objdir)/com32/gpllib/libgpl.c32
+LIBGPL     = $(objdir)/com32/gpllib/libgpl.c32
 GPLINCLUDE = -I$(com32)/gplinclude
 else
-GPLLIB     =
+LIBGPL     =
 GPLINCLUDE =
 endif
-
-CFLAGS     = $(GCCOPT) $(GCCWARN) -W -Wall \
-	     -fomit-frame-pointer -D__COM32__ -D__FIRMWARE_$(FIRMWARE)__ -DDYNAMIC_MODULE \
-	     -nostdinc -iwithprefix include \
+# Core symbol export library
+LIBCORE = $(objdir)/core/libcore.so
+# ldlinux.* library
+LIBLDLINUX = $(objdir)/ldlinux/$(LDLINUX)
+# Libraries used for most things
+LIBCOM32  = $(objdir)/com32/lib/libcom32.c32
+LIBUTIL   = $(objdir)/com32/libutil/libutil.c32
+
+INCLUDE =  -nostdinc -iwithprefix include -I$(SRC) \
 	     -I$(com32)/libutil/include -I$(com32)/include \
-		-I$(com32)/include/sys $(GPLINCLUDE) -I$(core)/include \
-		-I$(objdir) -DLDLINUX=\"$(LDLINUX)\"
-ifeq ($(FWCLASS),EFI)
-GCCOPT += -mno-red-zone
+	     -I$(com32)/include/sys $(GPLINCLUDE) -I$(core)/include \
+	     -I$(objdir)
+
+OPTFLAGS  = -Os -march=$(ARCH) -falign-functions=0 -falign-jumps=0 \
+	    -falign-labels=0 -ffast-math -fomit-frame-pointer
+WARNFLAGS = $(GCCWARN) -Wpointer-arith -Wwrite-strings \
+	    -Wstrict-prototypes -Winline
+
+REQFLAGS  = $(GCCOPT) -g -D__COM32__ -D__FIRMWARE_$(FIRMWARE)__ \
+	     -DLDLINUX=\"$(LDLINUX)\" $(INCLUDE)
+
+CFLAGS     = $(REQFLAGS) $(OPTFLAGS) $(WARNFLAGS)
+
+SFLAGS     = $(REQFLAGS) -D__ASSEMBLY__
+LDSCRIPT   	= $(com32)/lib/$(ARCH)/elf.ld
+MAIN_LDFLAGS	= -m elf_$(ARCH) -Bsymbolic --hash-style=gnu \
+		  -z combreloc -z now -z defs \
+		  --no-allow-shlib-undefined \
+		  --as-needed -nostdlib --copy-dt-needed-entries
+LDFLAGS    = $(MAIN_LDFLAGS) -T $(LDSCRIPT)
+
+ifeq ($(ARCH),i386)
+NASMFLAGS += -f elf
 else
-GCCOPT += -mregparm=3 -DREGPARM=3
+NASMFLAGS += -f elf64
 endif
-
-SFLAGS     = $(GCCOPT) -D__COM32__ -D__FIRMWARE_$(FIRMWARE)__ 
-LDFLAGS    = -m elf_$(ARCH) -shared --hash-style=gnu -T $(com32)/lib/$(ARCH)/elf.ld --as-needed
-LIBGCC    := $(shell $(CC) $(GCCOPT) --print-libgcc)
+NASMDEBUG  = -g -F dwarf
+NASMFLAGS += $(NASMDEBUG) -D__$(ARCH)__ -I$(SRC)/ $(filter -D%,$(CFLAGS))
 
 LNXCFLAGS  = -I$(com32)/libutil/include -W -Wall -O -g -D_GNU_SOURCE
 LNXSFLAGS  = -g
 LNXLDFLAGS = -g
 
-C_LIBS	   += $(objdir)/com32/libutil/libutil.c32 $(GPLLIB) \
-	     $(objdir)/com32/lib/libcom32.c32
+C_LIBS	   += $(LIBUTIL) $(LIBGPL) $(LIBCOM32) $(LIBLDLINUX) $(LIBCORE)
 C_LNXLIBS  = $(objdir)/com32/libutil/libutil_lnx.a \
 	     $(objdir)/com32/elflink/ldlinux/ldlinux_lnx.a
 
-.SUFFIXES: .lss .c .o
+# Add to ldflags when creating a shared library
+# The \ are escaped so their expansion is deferred
+SHARED = -shared -soname '$(patsubst %.elf,%.c32,$(@F))'
+
+%.o: %.asm
+	$(NASM) $(NASMFLAGS) -l $*.lsr -o $@ -MP -MD $(@D)/.$(@F).d $<
 
-.PRECIOUS: %.o
 %.o: %.S
 	$(CC) $(SFLAGS) -c -o $@ $<
 
-.PRECIOUS: %.o
-%.o: %.c
-	$(CC) $(CFLAGS) -c -o $@ $<
-
-.PRECIOUS: %.lo
-%.lo: %.S
-	$(CC) $(LNXSFLAGS) -c -o $@ $<
+%.s: %.c
+	$(CC) $(CFLAGS) -S -o $@ $<
 
-.PRECIOUS: %.lo
-%.lo: %.c
-	$(CC) $(LNXCFLAGS) -c -o $@ $<
+%.i: %.c
+	$(CC) $(CFLAGS) -E -o $@ $<
 
-.PRECIOUS: %.lnx
-%.lnx: %.lo $(LNXLIBS) $(C_LNXLIBS)
-	$(CC) $(LNXCFLAGS) -o $@ $^
+%.o: %.c
+	$(CC) $(CFLAGS) -c -o $@ $<
 
-.PRECIOUS: %.elf
-%.elf: %.o $(C_LIBS)
-	$(LD) $(LDFLAGS) -o $@ $^
+%.elf: %.o $(EXTRALIBS) $(C_LIBS)
+	$(LD) $(LDFLAGS) $(SHARED) -o $@ $< $(OBJS_$(*F)) $(LIBS_$(*F)) \
+		$(EXTRALIBS) $(C_LIBS)
 
 %.c32: %.elf
 	$(OBJCOPY) --strip-debug --strip-unneeded $< $@
diff --git a/mk/embedded.mk b/mk/embedded.mk
index 488dc0fc..0ab56332 100644
--- a/mk/embedded.mk
+++ b/mk/embedded.mk
@@ -50,7 +50,7 @@ GCCOPT	  += $(call gcc_ok,-falign-functions=0,-malign-functions=0)
 GCCOPT    += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0)
 GCCOPT    += $(call gcc_ok,-falign-labels=0,-malign-labels=0)
 GCCOPT    += $(call gcc_ok,-falign-loops=0,-malign-loops=0)
-GCCOPT    += $(call gcc_ok,-fvisibility=hidden)
+#GCCOPT    += $(call gcc_ok,-fvisibility=hidden)
 
 LIBGCC    := $(shell $(CC) $(GCCOPT) --print-libgcc)
 
diff --git a/mk/lib.mk b/mk/lib.mk
deleted file mode 100644
index f8591e56..00000000
--- a/mk/lib.mk
+++ /dev/null
@@ -1,252 +0,0 @@
-# -*- makefile -*-
-
-include $(MAKEDIR)/syslinux.mk
-
-# Support IA32 and x86_64 platforms with one build
-# Set up architecture specifics; for cross compilation, set ARCH as apt
-GCCOPT := $(call gcc_ok,-std=gnu99,)
-ifeq ($(ARCH),i386)
-	GCCOPT += $(call gcc_ok,-m32,)
-	GCCOPT += $(call gcc_ok,-mpreferred-stack-boundary=2,)
-	MARCH = i386
-endif
-ifeq ($(ARCH),x86_64)
-	GCCOPT += $(call gcc_ok,-m64,)
-	#let preferred-stack-boundary be default(=4)
-	MARCH = x86-64
-endif
-GCCOPT += $(call gcc_ok,-fno-stack-protector,)
-GCCOPT += $(call gcc_ok,-fwrapv,)
-GCCOPT += $(call gcc_ok,-freg-struct-return,)
-# Note -fPIE does not work with ld on x86_64, try -fPIC instead
-# Does BIOS build require -fPIE?
-GCCOPT += $(call gcc_ok,-fPIC)
-GCCOPT += $(call gcc_ok,-fno-exceptions,)
-GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,)
-GCCOPT += $(call gcc_ok,-fno-strict-aliasing,)
-GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0)
-GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0)
-GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0)
-GCCOPT += $(call gcc_ok,-falign-loops=0,-malign-loops=0)
-
-INCLUDE	= -I$(SRC)
-STRIP	= strip --strip-all -R .comment -R .note
-
-# zlib configuration flags
-LIBFLAGS = -DDYNAMIC_CRC_TABLE
-
-# We need some features in libpng which apparently aren't available in the
-# fixed-point versions.  It's OK, because we have to have a non-graphical
-# fallback anyway, just use that on old machines...
-# LIBFLAGS += -DPNG_NO_FLOATING_POINT_SUPPORTED
-
-REQFLAGS  = $(GCCOPT) -g -D__COM32__ -D__FIRMWARE_$(FIRMWARE)__ \
-	    -nostdinc -iwithprefix include -I. -I$(SRC)/sys \
-	    -I$(SRC)/../include -I$(com32)/include/sys \
-	    -I$(topdir)/core/include -I$(com32)/lib/ \
-	    -I$(com32)/lib/sys/module -I$(OBJ)/../..
-OPTFLAGS  = -Os -march=$(MARCH) -falign-functions=0 -falign-jumps=0 \
-	    -falign-labels=0 -ffast-math -fomit-frame-pointer
-WARNFLAGS = $(GCCWARN) -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Winline
-
-CFLAGS  = $(OPTFLAGS) $(REQFLAGS) $(WARNFLAGS) $(LIBFLAGS)
-
-ifeq ($(FWCLASS),EFI)
-CFLAGS += -mno-red-zone
-else
-CFLAGS += -mregparm=3 -DREGPARM=3
-endif
-
-ARCH_MATH_OBJS = \
-	$(patsubst $(com32)/lib/%.c,%.o,$(wildcard $(com32)/lib/$(ARCH)/math/*.c)) \
-	$(patsubst $(com32)/lib/%.S,%.o,$(wildcard $(com32)/lib/$(ARCH)/math/*.S))
-
-VPATH = $(SRC)
-LIBOTHER_OBJS = \
-	atoi.o atol.o atoll.o calloc.o creat.o		\
-	fgets.o fprintf.o fputc.o	\
-	putchar.o				\
-	getopt.o getopt_long.o						\
-	lrand48.o stack.o memccpy.o memchr.o		\
-	mempcpy.o memmem.o memmove.o memswap.o	\
-	perror.o qsort.o seed48.o \
-	srand48.o sscanf.o						\
-	strerror.o errlist.o		\
-	strnlen.o							\
-	strncat.o strndup.o		\
-	stpncpy.o						\
-	strntoimax.o strsep.o strspn.o strstr.o				\
-	strtoimax.o strtok.o strtol.o strtoll.o strtoull.o		\
-	strtoumax.o vprintf.o vsprintf.o		\
-	asprintf.o vasprintf.o			\
-	vsscanf.o							\
-	skipspace.o							\
-	chrreplace.o							\
-	bufprintf.o							\
-	inet.o dhcppack.o dhcpunpack.o					\
-	strreplace.o							\
-	lstrdup.o						\
-	\
-	suffix_number.o							\
-	\
-	getcwd.o fdopendir.o	\
-	\
-	sys/line_input.o				\
-	sys/colortable.o sys/screensize.o				\
-	\
-	sys/stdcon_read.o sys/stdcon_write.o sys/rawcon_read.o		\
-	sys/rawcon_write.o		\
-	sys/null_read.o sys/null_write.o sys/serial_write.o		\
-	\
-	sys/xserial_write.o						\
-	\
-	sys/ansi.o							\
-	\
-	sys/ansicon_write.o sys/ansiserial_write.o			\
-	\
-	pci/cfgtype.o pci/scan.o pci/bios.o					\
-	pci/readb.o pci/readw.o pci/readl.o			\
-	pci/writeb.o pci/writew.o pci/writel.o	\
-	\
-	math/strtod.o							\
-	$(ARCH_MATH_OBJS)						\
-	syslinux/disk.o							\
-	\
-	syslinux/setup_data.o
-
-## CORE OBJECTS, INCLUDED IN THE ROOT COM32 MODULE
-LIBENTRY_OBJS = \
-	sys/intcall.o sys/farcall.o sys/cfarcall.o sys/zeroregs.o	\
-	sys/argv.o sys/sleep.o						\
-	sys/fileinfo.o sys/opendev.o sys/read.o sys/write.o sys/ftell.o \
-	sys/close.o sys/open.o sys/fileread.o sys/fileclose.o		\
-	sys/openmem.o					\
-	sys/isatty.o sys/fstat.o					\
-	\
-	dprintf.o vdprintf.o						\
-	\
-	syslinux/idle.o							\
-	\
-	exit.o
-
-LIBGCC_OBJS = \
-	  $(patsubst $(com32)/lib/%.c,%.o,$(wildcard $(com32)/lib/$(ARCH)/libgcc/*.c)) \
-	  $(patsubst $(com32)/lib/%.S,%.o,$(wildcard $(com32)/lib/$(ARCH)/libgcc/*.S))
-
-LIBCONSOLE_OBJS = \
-	\
-	sys/openconsole.o sys/line_input.o				\
-	sys/colortable.o sys/screensize.o				\
-	\
-	sys/stdcon_read.o sys/rawcon_read.o		\
-	sys/rawcon_write.o						\
-	sys/null_write.o sys/serial_write.o		\
-	\
-	sys/xserial_write.o						\
-	\
-	sys/ansi.o							\
-	\
-	sys/ansicon_write.o sys/ansiserial_write.o	\
-	\
-	syslinux/serial.o
-
-LIBLOAD_OBJS = \
-	syslinux/addlist.o syslinux/freelist.o syslinux/memmap.o	\
-	syslinux/movebits.o syslinux/shuffle.o syslinux/shuffle_pm.o	\
-	syslinux/shuffle_rm.o syslinux/biosboot.o syslinux/zonelist.o	\
-	syslinux/dump_mmap.o syslinux/dump_movelist.o			\
-	\
-	syslinux/run_default.o syslinux/run_command.o			\
-	syslinux/cleanup.o syslinux/localboot.o	syslinux/runimage.o	\
-	\
-	syslinux/loadfile.o syslinux/floadfile.o syslinux/zloadfile.o	\
-	\
-	syslinux/load_linux.o syslinux/initramfs.o			\
-	syslinux/initramfs_file.o syslinux/initramfs_loadfile.o		\
-	syslinux/initramfs_archive.o
-
-LIBMODULE_OBJS = \
-	sys/module/common.o sys/module/$(ARCH)/elf_module.o		\
-	sys/module/elfutils.o	\
-	sys/module/exec.o sys/module/elf_module.o
-
-# ZIP library object files
-LIBZLIB_OBJS = \
-	zlib/adler32.o zlib/compress.o zlib/crc32.o			\
-	zlib/uncompr.o zlib/deflate.o zlib/trees.o zlib/zutil.o		\
-	zlib/inflate.o zlib/infback.o zlib/inftrees.o zlib/inffast.o	\
-	sys/zfile.o sys/zfopen.o
-
-MINLIBOBJS = \
-	$(addprefix $(OBJ)/,syslinux/ipappend.o \
-	syslinux/dsinfo.o \
-	$(LIBOTHER_OBJS) \
-	$(LIBGCC_OBJS) \
-	$(LIBCONSOLE_OBJS) \
-	$(LIBLOAD_OBJS) \
-	$(LIBZLIB_OBJS))
-#	$(LIBVESA_OBJS)
-
-CORELIBOBJS = \
-	memcmp.o printf.o strncmp.o vfprintf.o	\
-	strlen.o vsnprintf.o snprintf.o stpcpy.o strcmp.o strdup.o	\
-	strcpy.o strncpy.o fopen.o fread.o fread2.o puts.o	\
-	strtoul.o strntoumax.o strcasecmp.o				\
-	sprintf.o strlcat.o strchr.o strlcpy.o strncasecmp.o ctypes.o	\
-	fputs.o fwrite2.o fwrite.o fgetc.o fclose.o lmalloc.o		\
-	sys/err_read.o sys/err_write.o sys/null_read.o			\
-	sys/stdcon_write.o						\
-	syslinux/memscan.o strrchr.o strcat.o				\
-	syslinux/debug.o						\
-	$(LIBGCC_OBJS) \
-	$(LIBENTRY_OBJS) \
-	$(LIBMODULE_OBJS)
-
-ifneq ($(FWCLASS),EFI)
-# For EFI, these are part of gnu-efi
-CORELIBOBJS += $(ARCH)/setjmp.o memcpy.o memset.o
-endif
-
-LDFLAGS	= -m elf_$(ARCH) --hash-style=gnu -T $(com32)/lib/$(ARCH)/elf.ld
-
-.SUFFIXES: .c .o .a .so .lo .i .S .s .ls .ss .lss
-
-% : %.c # Cancel default rule
-
-% : %.S
-
-%.o: %.c
-	$(CC) $(MAKEDEPS) $(CFLAGS) -c -o $@ $<
-
-.c.i:
-	$(CC) $(MAKEDEPS) $(CFLAGS) -E -o $@ $<
-
-%.s: %.c
-	$(CC) $(MAKEDEPS) $(CFLAGS) -S -o $@ $<
-
-%.o: %.S
-	$(CC) $(MAKEDEPS) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $<
-
-.S.s:
-	$(CC) $(MAKEDEPS) $(CFLAGS) -D__ASSEMBLY__ -E -o $@ $<
-
-.S.lo:
-	$(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -c -o $@ $<
-
-.S.ls:
-	$(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -E -o $@ $<
-
-%(OBJ)/%.o: $(SRC)/%.s
-	$(CC) $(MAKEDEPS) $(CFLAGS) -x assembler -c -o $@ $<
-
-.ls.lo:
-	$(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -x assembler -c -o $@ $<
-
-.c.lo:
-	$(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -c -o $@ $<
-
-.c.ls:
-	$(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -S -o $@ $<
-
-%.c32: %.elf
-	$(OBJCOPY) --strip-debug --strip-unneeded $< $@
diff --git a/mk/syslinux.mk b/mk/syslinux.mk
index 593ff75f..7154ceb4 100644
--- a/mk/syslinux.mk
+++ b/mk/syslinux.mk
@@ -18,6 +18,11 @@
 MAKEFLAGS += -r
 MAKE      += -r
 
+# Preserve intermediate files
+.SECONDARY:
+
+VPATH    = $(SRC)
+
 BINDIR   = /usr/bin
 SBINDIR  = /sbin
 LIBDIR   = /usr/lib
@@ -38,7 +43,7 @@ DEBUGOPT = -DDEBUG=$(DEBUG)
 endif
 
 NASM	 = nasm
-NASMOPT  = -Ox $(DEBUGOPT)
+NASMFLAGS  = -Ox $(DEBUGOPT)
 
 PERL	 = perl
 PYTHON	 = python
@@ -92,6 +97,9 @@ MAKEDEPS = -MT $@ -MD -MF $(@D)/.$(@F).d
 # header files from the platform.
 UMAKEDEPS = -MT $@ -MMD -MF $(@D)/.$(@F).d
 
+# Version number
+-include $(topdir)/version.mk
+
 # Items that are only appropriate during development; this file is
 # removed when tarballs are generated.
 -include $(MAKEDIR)/devel.mk
diff --git a/txt/Makefile b/txt/Makefile
index dd9c7999..228fc802 100644
--- a/txt/Makefile
+++ b/txt/Makefile
@@ -68,7 +68,6 @@ syslinux.cfg.txt:	com-bug.txt com-rpt.txt
 
 # During 'make all', *.xml is kept but deleted at the end; do we _really_
 #	need the XML longer?
-.PRECIOUS:	%.xml
 
 # %.html:	%.txt
 # 	asciidoc -D html $<
diff --git a/txt/pxelinux.txt b/txt/pxelinux.txt
index 77d34fdd..53ffdd86 100644
--- a/txt/pxelinux.txt
+++ b/txt/pxelinux.txt
@@ -187,10 +187,7 @@ For best results, use a TFTP server which supports the "tsize" TFTP
 option (RFC 1784/RFC 2349).  The "tftp-hpa" TFTP server, which support
 options, is available at:
 
-	http://www.kernel.org/pub/software/network/tftp/
-	ftp://www.kernel.org/pub/software/network/tftp/
-
-and on any kernel.org mirror (see http://www.kernel.org/mirrors/).
+	https://www.kernel.org/pub/software/network/tftp/
 
 Another TFTP server which supports this is atftp by Jean-Pierre
 Lefebvre:
diff --git a/version b/version
index 405a2fa9..0e350186 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-6.04 2015
+6.04 2019


More information about the Syslinux-commits mailing list