diff options
Diffstat (limited to 'com32')
102 files changed, 3174 insertions, 1255 deletions
diff --git a/com32/Makefile b/com32/Makefile index c4699cfd..7ea1b01c 100644 --- a/com32/Makefile +++ b/com32/Makefile @@ -1,5 +1,22 @@ SUBDIRS = libupload tools lib elflink/ldlinux gpllib libutil modules mboot \ menu samples elflink rosh cmenu hdt gfxboot sysdump lua/src chain -all tidy dist clean spotless install: - set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done +.PHONY: subdirs $(SUBDIRS) +subdirs: $(SUBDIRS) +$(SUBDIRS): + @mkdir -p $(OBJ)/$@ + $(MAKE) -C $(OBJ)/$@ SRC="$(SRC)"/$@ OBJ="$(OBJ)"/$@/ \ + -f $(SRC)/$@/Makefile $(MAKECMDGOALS) + +all tidy dist clean spotless install: subdirs + +# Parallel dependencies +chain lua/src mboot menu: libutil gpllib +cmenu: lib libutil +elflink/ldlinux: lib +gfxboot: libutil +hdt: lib libupload cmenu gpllib libutil +modules: lib libutil gpllib +rosh: lib libutil +samples: libutil elflink/ldlinux +sysdump: libupload gpllib diff --git a/com32/chain/Makefile b/com32/chain/Makefile index 9a298fae..32385509 100644 --- a/com32/chain/Makefile +++ b/com32/chain/Makefile @@ -11,9 +11,7 @@ ## ## ----------------------------------------------------------------------- - -topdir = ../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/elf.mk OBJS = chain.o partiter.o utility.o options.o mangle.o diff --git a/com32/cmenu/Makefile b/com32/cmenu/Makefile index 181937bd..7ff1ff6e 100644 --- a/com32/cmenu/Makefile +++ b/com32/cmenu/Makefile @@ -18,31 +18,34 @@ NOGPL := 1 LIBS = libmenu/libmenu.c32 \ - $(com32)/libutil/libutil_com.c32 \ - $(com32)/lib/libcom32.c32 + $(objdir)/com32/libutil/libutil_com.c32 \ + $(objdir)/com32/lib/libcom32.c32 -topdir = ../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/elf.mk -CFLAGS += -I./libmenu +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 \ - $(com32)/libutil/libutil_com.c32 $(com32)/lib/libcom32.c32 +LIBMENU = $(objdir)/com32/libutil/libutil_com.c32 \ + $(objdir)/com32/lib/libcom32.c32 \ + 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,$(wildcard *.c)) -IMENUS = $(patsubst %.menu,%.c32,$(wildcard *.menu)) +CMENUS = $(patsubst %.c,%.c32,$(wildcard $(SRC)/*.c)) +IMENUS = $(patsubst %.menu,%.c32,$(wildcard $(SRC)/*.menu)) -MENUS = $(LIBS) $(CMENUS) $(IMENUS) +MENUS = $(LIBS) $(subst $(SRC)/,,$(CMENUS) $(IMENUS)) .SUFFIXES: .S .c .o .elf .c32 .menu .PRECIOUS: %.c %.c: %.menu adv_menu.tpl - $(PYTHON) menugen.py --input=$< --output=$@ --template=adv_menu.tpl + $(PYTHON) $(SRC)/menugen.py --input=$< --output=$@ --template=$(SRC)/adv_menu.tpl -all: menus +all: makeoutputdirs menus + +makeoutputdirs: + @mkdir -p $(OBJ)/libmenu libmenu/libmenu.c32: $(LIBMENU) $(LD) -shared $(LDFLAGS) -o $@ $^ diff --git a/com32/elflink/ldlinux/Makefile b/com32/elflink/ldlinux/Makefile index 93ca127d..aa35f475 100644 --- a/com32/elflink/ldlinux/Makefile +++ b/com32/elflink/ldlinux/Makefile @@ -10,18 +10,19 @@ ## ## ----------------------------------------------------------------------- -topdir = ../../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/elf.mk CFLAGS += -I$(topdir)/core/elflink -I$(topdir)/core/include -I$(topdir)/com32/lib -fvisibility=hidden -LIBS = --whole-archive $(com32)/lib/libcom32min.a +LIBS = --whole-archive $(objdir)/com32/lib/libcom32min.a + +OBJS = ldlinux.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 \ + eprintf.o loadhigh.o msg.o all: ldlinux.c32 ldlinux_lnx.a -ldlinux.c32 : ldlinux.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 eprintf.o loadhigh.o msg.o +ldlinux.c32 : $(OBJS) $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) LNXCFLAGS += -D__export='__attribute__((visibility("default")))' diff --git a/com32/elflink/ldlinux/adv.c b/com32/elflink/ldlinux/adv.c index 4c3ad508..677fe92d 100644 --- a/com32/elflink/ldlinux/adv.c +++ b/com32/elflink/ldlinux/adv.c @@ -32,24 +32,13 @@ */ #include <syslinux/adv.h> +#include <syslinux/firmware.h> #include <klibc/compiler.h> -#include <inttypes.h> -#include <com32.h> __export void *__syslinux_adv_ptr; __export size_t __syslinux_adv_size; -extern void adv_init(void); void __constructor __syslinux_init(void) { - static com32sys_t reg; - - /* Initialize the ADV structure */ - reg.eax.w[0] = 0x0025; - __intcall(0x22, ®, NULL); - - reg.eax.w[0] = 0x001c; - __intcall(0x22, ®, ®); - __syslinux_adv_ptr = MK_PTR(reg.es, reg.ebx.w[0]); - __syslinux_adv_size = reg.ecx.w[0]; + firmware->adv_ops->init(); } diff --git a/com32/elflink/ldlinux/advwrite.c b/com32/elflink/ldlinux/advwrite.c index 35829c1c..47e45534 100644 --- a/com32/elflink/ldlinux/advwrite.c +++ b/com32/elflink/ldlinux/advwrite.c @@ -31,15 +31,11 @@ * Write back the ADV */ -#include <syslinux/adv.h> #include <klibc/compiler.h> -#include <com32.h> +#include <syslinux/adv.h> +#include <syslinux/firmware.h> __export int syslinux_adv_write(void) { - static com32sys_t reg; - - reg.eax.w[0] = 0x001d; - __intcall(0x22, ®, ®); - return (reg.eflags.l & EFLAGS_CF) ? -1 : 0; + return firmware->adv_ops->write(); } diff --git a/com32/gfxboot/Makefile b/com32/gfxboot/Makefile index f2a73762..98d6a032 100644 --- a/com32/gfxboot/Makefile +++ b/com32/gfxboot/Makefile @@ -11,24 +11,35 @@ ## ## ----------------------------------------------------------------------- -topdir = ../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/elf.mk MODULES = gfxboot.c32 all: $(MODULES) -gfxboot.c32 : gfxboot.o realmode_callback.o $(LIBS) $(C_LIBS) +OBJS = gfxboot.o realmode_callback.o + +gfxboot.c32 : $(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 diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile index 92dd20f2..71f335da 100644 --- a/com32/gpllib/Makefile +++ b/com32/gpllib/Makefile @@ -3,14 +3,12 @@ # # Include configuration rules -topdir = ../.. -MAKEDIR = $(topdir)/mk include $(MAKEDIR)/lib.mk -REQFLAGS += -I../gplinclude -I../gplinclude/zzjson +REQFLAGS += -I$(SRC)/../gplinclude -I$(SRC)/../gplinclude/zzjson -GPLDIRS := . disk dmi vpd acpi zzjson -LIBOBJS := $(foreach dir,$(GPLDIRS),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c))) +GPLDIRS := $(SRC) $(addprefix $(SRC)/,disk dmi vpd acpi zzjson) +LIBOBJS := $(subst $(SRC)/,,$(foreach dir,$(GPLDIRS),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c)))) BINDIR = /usr/bin LIBDIR = /usr/lib @@ -19,7 +17,11 @@ AUXDIR = $(DATADIR)/syslinux INCDIR = /usr/include COM32DIR = $(AUXDIR)/com32 -all: libcom32gpl.c32 +all: makeoutputdirs libcom32gpl.c32 + +makeoutputdirs: + @mkdir -p $(foreach b, \ + $(addprefix $(OBJ),$(sort $(dir $(LIBOBJS)))),$(b)) libcom32gpl.c32 : $(LIBOBJS) $(LD) -shared $(LDFLAGS) -o $@ $^ @@ -38,6 +40,6 @@ install: all mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR) install -m 644 libcom32gpl.c32 $(INSTALLROOT)$(COM32DIR) mkdir -p $(INSTALLROOT)$(COM32DIR)/include/ - cp -r ../gplinclude $(INSTALLROOT)$(COM32DIR)/include/ + cp -r $(SRC)/../gplinclude $(INSTALLROOT)$(COM32DIR)/include/ -include .*.d */.*.d */*/.*.d diff --git a/com32/hdt/Makefile b/com32/hdt/Makefile index d264b5ba..362b4874 100644 --- a/com32/hdt/Makefile +++ b/com32/hdt/Makefile @@ -15,18 +15,17 @@ ## Hardware Detection Tool ## -topdir = ../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/elf.mk -LIBS = ../libupload/libcom32upload.a -C_LIBS += $(com32)/cmenu/libmenu/libmenu.c32 +LIBS = $(objdir)/com32/libupload/libcom32upload.a +C_LIBS += $(objdir)/com32/cmenu/libmenu/libmenu.c32 CFLAGS += -I$(com32)/cmenu/libmenu -I$(com32) MODULES = hdt.c32 TESTFILES = -OBJS = $(patsubst %.c,%.o,$(wildcard *.c)) +OBJS = $(subst $(SRC)/,,$(patsubst %.c,%.o,$(wildcard $(SRC)/*.c))) VERSION = $(shell $(SED) -n 's/\#define VERSION \"\(.*\)\"/\1/p' hdt.h) CODENAME = $(shell $(SED) -n 's/\#define CODENAME \"\(.*\)\"/\1/p' hdt.h) NODASH_VERSION = $(shell echo $(VERSION) | $(SED) -e 's/-/_/g' | $(SED) -e 's/\./_/g') diff --git a/com32/include/bitsize/limits.h b/com32/include/bitsize/limits.h index f90e524b..7129c4a6 100644 --- a/com32/include/bitsize/limits.h +++ b/com32/include/bitsize/limits.h @@ -5,10 +5,12 @@ #ifndef _BITSIZE_LIMITS_H #define _BITSIZE_LIMITS_H -#define LONG_BIT 32 - -#define LONG_MIN (-2147483647L-1) -#define LONG_MAX 2147483647L -#define ULONG_MAX 4294967295UL +#if __SIZEOF_POINTER__ == 4 +#include <bitsize32/limits.h> +#elif __SIZEOF_POINTER__ == 8 +#include <bitsize64/limits.h> +#else +#error "Unable to build for to-be-defined architecture type" +#endif #endif /* _BITSIZE_LIMITS_H */ diff --git a/com32/include/bitsize/stddef.h b/com32/include/bitsize/stddef.h index 213e8ab7..04418a04 100644 --- a/com32/include/bitsize/stddef.h +++ b/com32/include/bitsize/stddef.h @@ -1,14 +1,16 @@ /* - * bits32/stddef.h + * Include stddef.h as appropriate for architecture */ #ifndef _BITSIZE_STDDEF_H #define _BITSIZE_STDDEF_H -#define _SIZE_T -typedef unsigned int size_t; - -#define _PTRDIFF_T -typedef signed long ptrdiff_t; +#if __SIZEOF_POINTER__ == 4 +#include <bitsize32/stddef.h> +#elif __SIZEOF_POINTER__ == 8 +#include <bitsize64/stddef.h> +#else +#error "Unable to build for to-be-defined architecture type" +#endif #endif /* _BITSIZE_STDDEF_H */ diff --git a/com32/include/bitsize/stdint.h b/com32/include/bitsize/stdint.h index 8e444b6d..7e7b2355 100644 --- a/com32/include/bitsize/stdint.h +++ b/com32/include/bitsize/stdint.h @@ -8,27 +8,16 @@ typedef signed char int8_t; typedef short int int16_t; typedef int int32_t; -typedef long long int int64_t; typedef unsigned char uint8_t; typedef unsigned short int uint16_t; typedef unsigned int uint32_t; -typedef unsigned long long int uint64_t; - -typedef int int_fast16_t; -typedef int int_fast32_t; - -typedef unsigned int uint_fast16_t; -typedef unsigned int uint_fast32_t; - -typedef int intptr_t; -typedef unsigned int uintptr_t; - -#define __INT64_C(c) c ## LL -#define __UINT64_C(c) c ## ULL - -#define __PRI64_RANK "ll" -#define __PRIFAST_RANK "" -#define __PRIPTR_RANK "" +#if __SIZEOF_POINTER__ == 4 +#include <bitsize32/stdint.h> +#elif __SIZEOF_POINTER__ == 8 +#include <bitsize64/stdint.h> +#else +#error "Unable to build for to-be-defined architecture type" +#endif #endif /* _BITSIZE_STDINT_H */ diff --git a/com32/include/bitsize/stdintconst.h b/com32/include/bitsize/stdintconst.h index 7db63bdf..b2f3141a 100644 --- a/com32/include/bitsize/stdintconst.h +++ b/com32/include/bitsize/stdintconst.h @@ -1,18 +1,16 @@ /* - * bits32/stdintconst.h + * bitsize/stdintconst.h */ #ifndef _BITSIZE_STDINTCONST_H #define _BITSIZE_STDINTCONST_H -#define INT_FAST16_C(c) INT32_C(c) -#define INT_FAST32_C(c) INT32_C(c) - -#define UINT_FAST16_C(c) UINT32_C(c) -#define UINT_FAST32_C(c) UINT32_C(c) - -#define INTPTR_C(c) INT32_C(c) -#define UINTPTR_C(c) UINT32_C(c) -#define PTRDIFF_C(c) INT32_C(c) +#if __SIZEOF_POINTER__ == 4 +#include <bitsize32/stdintconst.h> +#elif __SIZEOF_POINTER__ == 8 +#include <bitsize64/stdintconst.h> +#else +#error "Unable to build for to-be-defined architecture type" +#endif #endif /* _BITSIZE_STDINTCONST_H */ diff --git a/com32/include/bitsize/stdintlimits.h b/com32/include/bitsize/stdintlimits.h index d85094d9..c342c448 100644 --- a/com32/include/bitsize/stdintlimits.h +++ b/com32/include/bitsize/stdintlimits.h @@ -1,22 +1,16 @@ /* - * bits32/stdintlimits.h + * bitsize/stdintlimits.h */ #ifndef _BITSIZE_STDINTLIMITS_H #define _BITSIZE_STDINTLIMITS_H -#define INT_FAST16_MIN INT32_MIN -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST16_MAX INT32_MAX -#define INT_FAST32_MAX INT32_MAX -#define UINT_FAST16_MAX UINT32_MAX -#define UINT_FAST32_MAX UINT32_MAX - -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX - -#define PTRDIFF_MIN INT32_MIN -#define PTRDIFF_MAX INT32_MAX +#if __SIZEOF_POINTER__ == 4 +#include <bitsize32/stdintlimits.h> +#elif __SIZEOF_POINTER__ == 8 +#include <bitsize64/stdintlimits.h> +#else +#error "Unable to build for to-be-defined architecture type" +#endif #endif /* _BITSIZE_STDINTLIMITS_H */ diff --git a/com32/include/bitsize32/limits.h b/com32/include/bitsize32/limits.h new file mode 100644 index 00000000..f19205fe --- /dev/null +++ b/com32/include/bitsize32/limits.h @@ -0,0 +1,14 @@ +/* + * bits32/limits.h + */ + +#ifndef _BITSIZE32_LIMITS_H +#define _BITSIZE32_LIMITS_H + +#define LONG_BIT 32 + +#define LONG_MIN (-2147483647L-1) +#define LONG_MAX 2147483647L +#define ULONG_MAX 4294967295UL + +#endif /* _BITSIZE_LIMITS_H */ diff --git a/com32/include/bitsize32/stddef.h b/com32/include/bitsize32/stddef.h new file mode 100644 index 00000000..c34c675c --- /dev/null +++ b/com32/include/bitsize32/stddef.h @@ -0,0 +1,9 @@ +/* + * bits32/stddef.h + */ + +#define _SIZE_T +typedef unsigned int size_t; + +#define _PTRDIFF_T +typedef signed long ptrdiff_t; diff --git a/com32/include/bitsize32/stdint.h b/com32/include/bitsize32/stdint.h new file mode 100644 index 00000000..bdc69705 --- /dev/null +++ b/com32/include/bitsize32/stdint.h @@ -0,0 +1,24 @@ +/* + * bits32/stdint.h + */ + + +typedef long long int int64_t; + +typedef unsigned long long int uint64_t; + +typedef int int_fast16_t; +typedef int int_fast32_t; + +typedef unsigned int uint_fast16_t; +typedef unsigned int uint_fast32_t; + +typedef int intptr_t; +typedef unsigned int uintptr_t; + +#define __INT64_C(c) c ## LL +#define __UINT64_C(c) c ## ULL + +#define __PRI64_RANK "ll" +#define __PRIFAST_RANK "" +#define __PRIPTR_RANK "" diff --git a/com32/include/bitsize32/stdintconst.h b/com32/include/bitsize32/stdintconst.h new file mode 100644 index 00000000..71ece423 --- /dev/null +++ b/com32/include/bitsize32/stdintconst.h @@ -0,0 +1,13 @@ +/* + * bits32/stdintconst.h + */ + +#define INT_FAST16_C(c) INT32_C(c) +#define INT_FAST32_C(c) INT32_C(c) + +#define UINT_FAST16_C(c) UINT32_C(c) +#define UINT_FAST32_C(c) UINT32_C(c) + +#define INTPTR_C(c) INT32_C(c) +#define UINTPTR_C(c) UINT32_C(c) +#define PTRDIFF_C(c) INT32_C(c) diff --git a/com32/include/bitsize32/stdintlimits.h b/com32/include/bitsize32/stdintlimits.h new file mode 100644 index 00000000..175cdcd4 --- /dev/null +++ b/com32/include/bitsize32/stdintlimits.h @@ -0,0 +1,23 @@ +/* + * bits32/stdintlimits.h + */ + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX + +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX + +/* sig_atomic_t limit */ +# define SIG_ATOMIC_MIN INT32_MIN //(-2147483647-1) +# define SIG_ATOMIC_MAX INT32_MAX //(2147483647) +/* size_t limit */ +# define SIZE_MAX UINT32_MAX //(4294967295U) diff --git a/com32/include/bitsize64/limits.h b/com32/include/bitsize64/limits.h new file mode 100644 index 00000000..1acb1bc8 --- /dev/null +++ b/com32/include/bitsize64/limits.h @@ -0,0 +1,14 @@ +/* + * bits64/limits.h + */ + +#ifndef _BITSIZE64_LIMITS_H +#define _BITSIZE64_LIMITS_H + +#define LONG_BIT 64 + +#define LONG_MIN (-9223372036854775807L-1) +#define LONG_MAX 9223372036854775807L +#define ULONG_MAX 18446744073709551615UL + +#endif /* _BITSIZE_LIMITS_H */ diff --git a/com32/include/bitsize64/stddef.h b/com32/include/bitsize64/stddef.h new file mode 100644 index 00000000..c61bf8ce --- /dev/null +++ b/com32/include/bitsize64/stddef.h @@ -0,0 +1,10 @@ +/* + * bits64/stddef.h + */ + +#define _SIZE_T +typedef unsigned long size_t; + +#define _PTRDIFF_T +typedef signed long ptrdiff_t; + diff --git a/com32/include/bitsize64/stdint.h b/com32/include/bitsize64/stdint.h new file mode 100644 index 00000000..91930003 --- /dev/null +++ b/com32/include/bitsize64/stdint.h @@ -0,0 +1,24 @@ +/* + * bits64/stdint.h + */ + + +typedef long int int64_t; + +typedef unsigned long int uint64_t; + +typedef long int int_fast16_t; +typedef long int int_fast32_t; + +typedef unsigned long int uint_fast16_t; +typedef unsigned long int uint_fast32_t; + +typedef long int intptr_t; +typedef unsigned long int uintptr_t; + +#define __INT64_C(c) c ## L +#define __UINT64_C(c) c ## UL + +#define __PRI64_RANK "l" +#define __PRIFAST_RANK "l" +#define __PRIPTR_RANK "l" diff --git a/com32/include/bitsize64/stdintconst.h b/com32/include/bitsize64/stdintconst.h new file mode 100644 index 00000000..139ab203 --- /dev/null +++ b/com32/include/bitsize64/stdintconst.h @@ -0,0 +1,13 @@ +/* + * bits64/stdintconst.h + */ + +#define INT_FAST16_C(c) INT64_C(c) +#define INT_FAST32_C(c) INT64_C(c) + +#define UINT_FAST16_C(c) UINT64_C(c) +#define UINT_FAST32_C(c) UINT64_C(c) + +#define INTPTR_C(c) INT64_C(c) +#define UINTPTR_C(c) UINT64_C(c) +#define PTRDIFF_C(c) INT64_C(c) diff --git a/com32/include/bitsize64/stdintlimits.h b/com32/include/bitsize64/stdintlimits.h new file mode 100644 index 00000000..a775a7fd --- /dev/null +++ b/com32/include/bitsize64/stdintlimits.h @@ -0,0 +1,23 @@ +/* + * bits64/stdintlimits.h + */ + +#define INT_FAST16_MIN INT64_MIN +#define INT_FAST32_MIN INT64_MIN +#define INT_FAST16_MAX INT64_MAX +#define INT_FAST32_MAX INT64_MAX +#define UINT_FAST16_MAX UINT64_MAX +#define UINT_FAST32_MAX UINT64_MAX + +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX + +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX + +/* sig_atomic_t limit */ +# define SIG_ATOMIC_MAX INT32_MAX //(2147483647) +# define SIG_ATOMIC_MIN (-SIG_ATOMIC_MAX-1) //(-2147483647-1) +/* size_t limit */ +# define SIZE_MAX UINT64_MAX diff --git a/com32/include/com32.h b/com32/include/com32.h index 148d08eb..c5d60176 100644 --- a/com32/include/com32.h +++ b/com32/include/com32.h @@ -135,7 +135,7 @@ char *lstrdup(const char *); * specific segment. OFFS_VALID() will return whether or not the * pointer is actually reachable from the target segment. */ -#if defined(DEBUG) && (defined(__COM32__) || defined(__SYSLINUX_CORE__)) +#if defined(CORE_DEBUG) && (defined(__COM32__) || defined(__SYSLINUX_CORE__)) __noreturn __bad_SEG(const volatile void *); static inline uint16_t SEG(const volatile void *__p) @@ -176,7 +176,7 @@ static inline bool _OFFS_VALID(const volatile void *__p, size_t __s, static inline void *MK_PTR(uint16_t __seg, uint16_t __offs) { - return (void *)((__seg << 4) + __offs); + return (void *)(unsigned long)((__seg << 4) + __offs); } /* Some tools to handle 16:16 far pointers in memory */ diff --git a/com32/include/dprintf.h b/com32/include/dprintf.h index 26ca734b..de4625bc 100644 --- a/com32/include/dprintf.h +++ b/com32/include/dprintf.h @@ -6,10 +6,10 @@ #define _DPRINTF_H #if !defined(DEBUG_PORT) && !defined(DEBUG_STDIO) -# undef DEBUG +# undef CORE_DEBUG #endif -#ifdef DEBUG +#ifdef CORE_DEBUG # include <stdio.h> @@ -26,9 +26,9 @@ void vdprintf(const char *, va_list); # define dprintf(fmt, ...) ((void)(0)) # define vdprintf(fmt, ap) ((void)(0)) -#endif /* DEBUG */ +#endif /* CORE_DEBUG */ -# if DEBUG >= 2 +# if CORE_DEBUG >= 2 /* Really verbose debugging... */ # define dprintf2 dprintf # define vdprintf2 vdprintf diff --git a/com32/include/klibc/i386/archsetjmp.h b/com32/include/klibc/i386/archsetjmp.h new file mode 100644 index 00000000..a0def6a1 --- /dev/null +++ b/com32/include/klibc/i386/archsetjmp.h @@ -0,0 +1,19 @@ +/* + * arch/i386/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned int __ebx; + unsigned int __esp; + unsigned int __ebp; + unsigned int __esi; + unsigned int __edi; + unsigned int __eip; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/com32/include/klibc/x86_64/archsetjmp.h b/com32/include/klibc/x86_64/archsetjmp.h new file mode 100644 index 00000000..454fc60a --- /dev/null +++ b/com32/include/klibc/x86_64/archsetjmp.h @@ -0,0 +1,21 @@ +/* + * arch/x86_64/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __rbx; + unsigned long __rsp; + unsigned long __rbp; + unsigned long __r12; + unsigned long __r13; + unsigned long __r14; + unsigned long __r15; + unsigned long __rip; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/com32/include/netinet/in.h b/com32/include/netinet/in.h index d2af351f..d3fba17f 100644 --- a/com32/include/netinet/in.h +++ b/com32/include/netinet/in.h @@ -27,8 +27,16 @@ static inline __constfunc uint16_t __htons(uint16_t v) static inline __constfunc uint32_t __htonl(uint32_t v) { +#if __SIZEOF_POINTER__ == 4 asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0" : "+q" (v)); +#elif __SIZEOF_POINTER__ == 8 + asm("bswap %0" + : "=r" (v) + : "0" (v)); +#else +#error "unable to build for architecture" +#endif return v; } diff --git a/com32/include/setjmp.h b/com32/include/setjmp.h index 11b18fbd..e7090955 100644 --- a/com32/include/setjmp.h +++ b/com32/include/setjmp.h @@ -9,7 +9,13 @@ #include <klibc/compiler.h> #include <stddef.h> -#include <klibc/archsetjmp.h> +#if __SIZEOF_POINTER__ == 4 +#include <klibc/i386/archsetjmp.h> +#elif __SIZEOF_POINTER__ == 8 +#include <klibc/x86_64/archsetjmp.h> +#else +#error "unsupported architecture" +#endif __extern int setjmp(jmp_buf); __extern __noreturn longjmp(jmp_buf, int); diff --git a/com32/include/sys/bitops.h b/com32/include/sys/bitops.h index 40e09fe7..de30d932 100644 --- a/com32/include/sys/bitops.h +++ b/com32/include/sys/bitops.h @@ -36,27 +36,11 @@ #include <klibc/compiler.h> -static inline void set_bit(long __bit, void *__bitmap) -{ - asm volatile("btsl %1,%0" - : "+m" (*(unsigned char *)__bitmap) - : "Ir" (__bit) : "memory"); -} - -static inline void clr_bit(long __bit, void *__bitmap) -{ - asm volatile("btcl %1,%0" - : "+m" (*(unsigned char *)__bitmap) - : "Ir" (__bit) : "memory"); -} - -static inline int __purefunc test_bit(long __bit, const void *__bitmap) -{ - unsigned char __r; - asm("btl %2,%1; setc %0" - : "=qm" (__r) - : "m" (*(const unsigned char *)__bitmap), "Ir" (__bit)); - return __r; -} - +#if __SIZEOF_POINTER__ == 4 +#include <i386/bitops.h> +#elif __SIZEOF_POINTER__ == 8 +#include <x86_64/bitops.h> +#else +#error "Unable to build for to-be-defined architecture type" +#endif #endif /* _BITOPS_H */ diff --git a/com32/include/sys/cpu.h b/com32/include/sys/cpu.h index 53a6250e..05c98843 100644 --- a/com32/include/sys/cpu.h +++ b/com32/include/sys/cpu.h @@ -5,138 +5,12 @@ #include <stdint.h> #include <klibc/compiler.h> -static inline uint64_t rdtsc(void) -{ - uint64_t v; - asm volatile("rdtsc" : "=A" (v)); - return v; -} - -static inline uint32_t rdtscl(void) -{ - uint32_t v; - asm volatile("rdtsc" : "=a" (v) : : "edx"); - return v; -} - -static inline void cpuid_count(uint32_t op, uint32_t cnt, - uint32_t * eax, uint32_t * ebx, - uint32_t * ecx, uint32_t * edx) -{ - asm volatile("movl %%ebx,%1 ; " - "cpuid ; " - "xchgl %1,%%ebx" - : "=a" (*eax), "=SD" (*ebx), "=c" (*ecx), "=d" (*edx) - : "a"(op), "c"(cnt)); -} - -static inline void cpuid(uint32_t op, uint32_t * eax, uint32_t * ebx, - uint32_t * ecx, uint32_t * edx) -{ - cpuid_count(op, 0, eax, ebx, ecx, edx); -} - -static inline __constfunc uint32_t cpuid_eax(uint32_t level) -{ - uint32_t v; - - asm volatile("pushl %%ebx ; " - "cpuid ; " - "popl %%ebx" - : "=a" (v) - : "a"(level) - : "ecx", "edx"); - return v; -} - -static inline __constfunc uint32_t cpuid_ebx(uint32_t level) -{ - uint32_t v; - - asm volatile("movl %%ebx,%0 ; " - "cpuid ; " - "xchgl %0,%%ebx" - : "=SD" (v), "+a" (level) - : : "ecx", "edx"); - return v; -} - -static inline __constfunc uint32_t cpuid_ecx(uint32_t level) -{ - uint32_t v; - - asm volatile("pushl %%ebx ; " - "cpuid ; " - "popl %%ebx" - : "=c" (v), "+a" (level) - : : "edx"); - return v; -} - -static inline __constfunc uint32_t cpuid_edx(uint32_t level) -{ - uint32_t v; - - asm volatile("pushl %%ebx ; " - "cpuid ; " - "popl %%ebx" - : "=d" (v), "+a" (level) - : : "ecx"); - return v; -} - -/* Standard macro to see if a specific flag is changeable */ -static inline __constfunc bool cpu_has_eflag(uint32_t flag) -{ - uint32_t f0, f1; - - asm("pushfl ; " - "pushfl ; " - "popl %0 ; " - "movl %0,%1 ; " - "xorl %2,%1 ; " - "pushl %1 ; " - "popfl ; " - "pushfl ; " - "popl %1 ; " - "popfl" - : "=&r" (f0), "=&r" (f1) - : "ri" (flag)); - - return !!((f0^f1) & flag); -} - -static inline uint64_t rdmsr(uint32_t msr) -{ - uint64_t v; - - asm volatile("rdmsr" : "=A" (v) : "c"(msr)); - return v; -} - -static inline void wrmsr(uint64_t v, uint32_t msr) -{ - asm volatile("wrmsr" : : "A" (v), "c" (msr)); -} - -static inline void cpu_relax(void) -{ - asm volatile("rep ; nop"); -} - -static inline void hlt(void) -{ - asm volatile("hlt"); -} - -static inline void cli(void) -{ - asm volatile("cli"); -} - -static inline void sti(void) -{ - asm volatile("sti"); -} +#if __SIZEOF_POINTER__ == 4 +#include <i386/cpu.h> +#elif __SIZEOF_POINTER__ == 8 +#include <x86_64/cpu.h> +#else +#error "unsupported architecture" +#endif #endif diff --git a/com32/include/sys/elfcommon.h b/com32/include/sys/elfcommon.h index 8d6ddb05..99b5ad10 100644 --- a/com32/include/sys/elfcommon.h +++ b/com32/include/sys/elfcommon.h @@ -361,4 +361,54 @@ /* Keep this the last entry. */ #define R_386_NUM 38 +/* AMD x86-64 relocations. */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ +#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset + to two GOT entries for GD symbol */ +#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset + to two GOT entries for LD symbol */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset + to GOT entry for IE symbol */ +#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ +#define R_X86_64_PC64 24 /* PC relative 64 bit */ +#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ +#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative + offset to GOT */ +#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ +#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset + to GOT entry */ +#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ +#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ +#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset + to PLT entry */ +#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ +#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ +#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ +#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS + descriptor. */ +#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ +#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ + +#define R_X86_64_NUM 38 + #endif /* _SYS_ELFCOMMON_H */ diff --git a/com32/include/sys/i386/bitops.h b/com32/include/sys/i386/bitops.h new file mode 100644 index 00000000..663b267a --- /dev/null +++ b/com32/include/sys/i386/bitops.h @@ -0,0 +1,54 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010-2011 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * i386 bitops.h + * + * Simple bitwise operations + */ +static inline void set_bit(long __bit, void *__bitmap) +{ + asm volatile("btsl %1,%0" + : "+m" (*(unsigned char *)__bitmap) + : "Ir" (__bit) : "memory"); +} + +static inline void clr_bit(long __bit, void *__bitmap) +{ + asm volatile("btcl %1,%0" + : "+m" (*(unsigned char *)__bitmap) + : "Ir" (__bit) : "memory"); +} + +static inline int __purefunc test_bit(long __bit, const void *__bitmap) +{ + unsigned char __r; + asm("btl %2,%1; setc %0" + : "=qm" (__r) + : "m" (*(const unsigned char *)__bitmap), "Ir" (__bit)); + return __r; +} diff --git a/com32/include/sys/i386/cpu.h b/com32/include/sys/i386/cpu.h new file mode 100644 index 00000000..63d0f5ed --- /dev/null +++ b/com32/include/sys/i386/cpu.h @@ -0,0 +1,135 @@ +/* i386 cpu.h */ + +static inline uint64_t rdtsc(void) +{ + uint64_t v; + asm volatile("rdtsc" : "=A" (v)); + return v; +} + +static inline uint32_t rdtscl(void) +{ + uint32_t v; + asm volatile("rdtsc" : "=a" (v) : : "edx"); + return v; +} + +static inline void cpuid_count(uint32_t op, uint32_t cnt, + uint32_t * eax, uint32_t * ebx, + uint32_t * ecx, uint32_t * edx) +{ + asm volatile("movl %%ebx,%1 ; " + "cpuid ; " + "xchgl %1,%%ebx" + : "=a" (*eax), "=SD" (*ebx), "=c" (*ecx), "=d" (*edx) + : "a"(op), "c"(cnt)); +} + +static inline void cpuid(uint32_t op, uint32_t * eax, uint32_t * ebx, + uint32_t * ecx, uint32_t * edx) +{ + cpuid_count(op, 0, eax, ebx, ecx, edx); +} + +static inline __constfunc uint32_t cpuid_eax(uint32_t level) +{ + uint32_t v; + + asm volatile("pushl %%ebx ; " + "cpuid ; " + "popl %%ebx" + : "=a" (v) + : "a"(level) + : "ecx", "edx"); + return v; +} + +static inline __constfunc uint32_t cpuid_ebx(uint32_t level) +{ + uint32_t v; + + asm volatile("movl %%ebx,%0 ; " + "cpuid ; " + "xchgl %0,%%ebx" + : "=SD" (v), "+a" (level) + : : "ecx", "edx"); + return v; +} + +static inline __constfunc uint32_t cpuid_ecx(uint32_t level) +{ + uint32_t v; + + asm volatile("pushl %%ebx ; " + "cpuid ; " + "popl %%ebx" + : "=c" (v), "+a" (level) + : : "edx"); + return v; +} + +static inline __constfunc uint32_t cpuid_edx(uint32_t level) +{ + uint32_t v; + + asm volatile("pushl %%ebx ; " + "cpuid ; " + "popl %%ebx" + : "=d" (v), "+a" (level) + : : "ecx"); + return v; +} + +/* Standard macro to see if a specific flag is changeable */ +static inline __constfunc bool cpu_has_eflag(uint32_t flag) +{ + uint32_t f0, f1; + + asm("pushfl ; " + "pushfl ; " + "popl %0 ; " + "movl %0,%1 ; " + "xorl %2,%1 ; " + "pushl %1 ; " + "popfl ; " + "pushfl ; " + "popl %1 ; " + "popfl" + : "=&r" (f0), "=&r" (f1) + : "ri" (flag)); + + return !!((f0^f1) & flag); +} + +static inline uint64_t rdmsr(uint32_t msr) +{ + uint64_t v; + + asm volatile("rdmsr" : "=A" (v) : "c"(msr)); + return v; +} + +static inline void wrmsr(uint64_t v, uint32_t msr) +{ + asm volatile("wrmsr" : : "A" (v), "c" (msr)); +} + +static inline void cpu_relax(void) +{ + asm volatile("rep ; nop"); +} + +static inline void hlt(void) +{ + asm volatile("hlt"); +} + +static inline void cli(void) +{ + asm volatile("cli"); +} + +static inline void sti(void) +{ + asm volatile("sti"); +} diff --git a/com32/include/sys/i386/module.h b/com32/include/sys/i386/module.h new file mode 100644 index 00000000..21988ead --- /dev/null +++ b/com32/include/sys/i386/module.h @@ -0,0 +1,35 @@ +/** + * 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/module.h b/com32/include/sys/module.h index ea11a88f..02778fbf 100644 --- a/com32/include/sys/module.h +++ b/com32/include/sys/module.h @@ -4,7 +4,6 @@ * Dynamic ELF modules definitions and services. */ - #ifndef MODULE_H_ #define MODULE_H_ @@ -15,6 +14,14 @@ #include <stdbool.h> #include <linux/list.h> +#if __SIZEOF_POINTER__ == 4 +#include <i386/module.h> +#elif __SIZEOF_POINTER__ == 8 +#include <x86_64/module.h> +#else +#error "unsupported architecture" +#endif + /* * The maximum length of the module file name (including path), stored * in the struct module descriptor. @@ -91,26 +98,26 @@ struct elf_module { module_main_t main_func; // The main function (for executable modules) void *module_addr; // The module location in the memory - Elf32_Addr base_addr; // The base address of the module - Elf32_Word module_size; // The module size in memory + Elf_Addr base_addr; // The base address of the module + Elf_Word module_size; // The module size in memory - Elf32_Word *hash_table; // The symbol hash table - Elf32_Word *ghash_table; // The GNU style hash table + Elf_Word *hash_table; // The symbol hash table + Elf_Word *ghash_table; // The GNU style hash table char *str_table; // The string table void *sym_table; // The symbol table void *got; // The Global Offset Table - Elf32_Dyn *dyn_table; // Dynamic loading information table + Elf_Dyn *dyn_table; // Dynamic loading information table - Elf32_Word strtable_size; // The size of the string table - Elf32_Word syment_size; // The size of a symbol entry - Elf32_Word symtable_size; // The size of the symbol table + Elf_Word strtable_size; // The size of the string table + Elf_Word syment_size; // The size of a symbol entry + Elf_Word symtable_size; // The size of the symbol table union { // Transient - Data available while the module is loading struct { FILE *_file; // The file object of the open file - Elf32_Off _cr_offset; // The current offset in the open file + Elf_Off _cr_offset; // The current offset in the open file } l; // Process execution data @@ -122,7 +129,7 @@ struct elf_module { // ELF DT_NEEDED entries for this module int nr_needed; - Elf32_Word needed[MAX_NR_DEPS]; + Elf_Word needed[MAX_NR_DEPS]; }; /** @@ -167,17 +174,6 @@ extern FILE *findpath(char *name); * This portion is included by the core COM32 module. */ -/* - * 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 - /** * Names of symbols with special meaning (treated as special cases at linking) */ @@ -255,7 +251,7 @@ extern int module_load(struct elf_module *module); * Its current use is to describe the root COM32 module to the rest of the * module subsystem. */ -extern int module_load_shallow(struct elf_module *module, Elf32_Addr base_addr); +extern int module_load_shallow(struct elf_module *module, Elf_Addr base_addr); /** * module_unload - unloads the module from the system. @@ -329,7 +325,7 @@ extern struct elf_module *module_find(const char *name); * If the symbol is found, a pointer to its descriptor structure is returned, and * NULL otherwise. */ -extern Elf32_Sym *module_find_symbol(const char *name, struct elf_module *module); +extern Elf_Sym *module_find_symbol(const char *name, struct elf_module *module); /** * global_find_symbol - searches for a symbol definition in the entire module namespace. @@ -346,7 +342,7 @@ extern Elf32_Sym *module_find_symbol(const char *name, struct elf_module *module * a pointer to the symbol descriptor structure. If the module parameter is not NULL, * it is filled with the address of the module descriptor where the symbol is defined. */ -extern Elf32_Sym *global_find_symbol(const char *name, struct elf_module **module); +extern Elf_Sym *global_find_symbol(const char *name, struct elf_module **module); /** * module_get_absolute - converts an memory address relative to a module base address @@ -356,7 +352,7 @@ extern Elf32_Sym *global_find_symbol(const char *name, struct elf_module **modul * * The function returns a pointer to the absolute memory address. */ -static inline void *module_get_absolute(Elf32_Addr addr, struct elf_module *module) { +static inline void *module_get_absolute(Elf_Addr addr, struct elf_module *module) { return (void*)(module->base_addr + addr); } diff --git a/com32/include/sys/x86_64/bitops.h b/com32/include/sys/x86_64/bitops.h new file mode 100644 index 00000000..7b1cc2b6 --- /dev/null +++ b/com32/include/sys/x86_64/bitops.h @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010-2011 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * bitops.h - i386 + * + * Simple bitwise operations + */ + +static inline void set_bit(long __bit, void *__bitmap) +{ + asm volatile("bts %1,%0" + : "+m" (*(unsigned char *)__bitmap) + : "Ir" (__bit) : "memory"); +} + +static inline void clr_bit(long __bit, void *__bitmap) +{ + asm volatile("btcl %1,%0" + : "+m" (*(unsigned char *)__bitmap) + : "Ir" (__bit) : "memory"); +} + +static inline int __purefunc test_bit(long __bit, const void *__bitmap) +{ + unsigned char __r; + asm("bt %2,%1; setc %0" + : "=qm" (__r) + : "m" (*(const unsigned char *)__bitmap), "Ir" (__bit)); + return __r; +} diff --git a/com32/include/sys/x86_64/cpu.h b/com32/include/sys/x86_64/cpu.h new file mode 100644 index 00000000..89d79154 --- /dev/null +++ b/com32/include/sys/x86_64/cpu.h @@ -0,0 +1,148 @@ +#ifndef _CPU_X86_64_H +#define _CPU_X86_64_H + +/* x86_64 cpu.h */ + +static inline uint64_t rdtsc(void) +{ + uint64_t v; + asm volatile("rdtsc" : "=A" (v)); + return v; +} + +static inline uint32_t rdtscl(void) +{ + uint32_t v; + asm volatile("rdtsc" : "=a" (v) : : "edx"); + return v; +} + +static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + /* ecx is often an input as well as an output. */ + asm volatile("cpuid" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (*eax), "2" (*ecx) + : "memory"); +} +/* + * Generic CPUID function + * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx + * resulting in stale register contents being returned. + */ +static inline void cpuid(uint32_t op, + uint32_t *eax, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx) +{ + *eax = op; + *ecx = 0; + native_cpuid(eax, ebx, ecx, edx); +} + +/* + * CPUID functions returning a single datum + */ +static inline uint32_t cpuid_eax(uint32_t op) +{ + uint32_t eax, ebx, ecx, edx; + + cpuid(op, &eax, &ebx, &ecx, &edx); + + return eax; +} + +static inline uint32_t cpuid_ebx(uint32_t op) +{ + uint32_t eax, ebx, ecx, edx; + + cpuid(op, &eax, &ebx, &ecx, &edx); + + return ebx; +} + +static inline uint32_t cpuid_ecx(uint32_t op) +{ + uint32_t eax, ebx, ecx, edx; + + cpuid(op, &eax, &ebx, &ecx, &edx); + + return ecx; +} + +static inline uint32_t cpuid_edx(uint32_t op) +{ + uint32_t eax, ebx, ecx, edx; + + cpuid(op, &eax, &ebx, &ecx, &edx); + + return edx; +} + +static inline void cpuid_count(uint32_t op, uint32_t cnt, + uint32_t * eax, uint32_t * ebx, + uint32_t * ecx, uint32_t * edx) +{ + asm volatile("movl %%ebx,%1 ; " + "cpuid ; " + "xchgl %1,%%ebx" + : "=a" (*eax), "=SD" (*ebx), "=c" (*ecx), "=d" (*edx) + : "a"(op), "c"(cnt)); +} + +/* Standard macro to see if a specific flag is changeable */ +static inline __constfunc bool cpu_has_eflag(uint32_t flag) +{ + /* x86_64 */ + uint64_t f0, f1; + asm("pushf ; " + "pushf ; " + "pop %0 ; " + "mov %0,%1 ; " + "xor %2,%1 ; " + "push %1 ; " + "popf ; " + "pushf ; " + "pop %1 ; " + "popf" + : "=&r" (f0), "=&r" (f1) + : "ri" (flag)); + return !!((f0^f1) & flag); +} + +static inline uint64_t rdmsr(uint32_t msr) +{ + uint64_t v; + + asm volatile("rdmsr" : "=A" (v) : "c"(msr)); + return v; +} + +static inline void wrmsr(uint64_t v, uint32_t msr) +{ + asm volatile("wrmsr" : : "A" (v), "c" (msr)); +} + +static inline void cpu_relax(void) +{ + asm volatile("rep ; nop"); +} + +static inline void hlt(void) +{ + asm volatile("hlt"); +} + +static inline void cli(void) +{ + asm volatile("cli"); +} + +static inline void sti(void) +{ + asm volatile("sti"); +} +#endif diff --git a/com32/include/sys/x86_64/module.h b/com32/include/sys/x86_64/module.h new file mode 100644 index 00000000..203a6cd0 --- /dev/null +++ b/com32/include/sys/x86_64/module.h @@ -0,0 +1,35 @@ +/** + * 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/firmware.h b/com32/include/syslinux/firmware.h new file mode 100644 index 00000000..13ba1591 --- /dev/null +++ b/com32/include/syslinux/firmware.h @@ -0,0 +1,72 @@ +#ifndef _SYSLINUX_FIRMWARE_H +#define _SYSLINUX_FIRMWARE_H + +#include <syslinux/memscan.h> + +struct term_state; + +struct output_ops { + void (*erase) (int, int, int, int, uint8_t); + void (*write_char) (uint8_t, uint8_t); + void (*showcursor) (const struct term_state *); + void (*scroll_up) (uint8_t, uint8_t, uint8_t); + void (*set_cursor) (int, int, bool); + void (*beep) (void); + void (*get_mode)(int *, int *); + void (*set_mode)(uint16_t); + void (*get_cursor)(int *, int *); +}; + +struct input_ops { + char (*getchar)(char *); + int (*pollchar)(void); +}; + +struct adv_ops { + void (*init)(void); + int (*write)(void); +}; + +struct vesa_info; +enum vesa_pixel_format; +struct win_info; + +struct vesa_ops { + int (*set_mode)(struct vesa_info *, int *, int *, enum vesa_pixel_format *); + void (*screencpy)(size_t, const uint32_t *, size_t, struct win_info *); + int (*font_query)(uint8_t **); +}; + +enum heap; +struct mem_ops { + void *(*malloc)(size_t, enum heap, size_t); + void *(*realloc)(void *, size_t); + void (*free)(void *); + int (*scan_memory)(scan_memory_callback_t, void *); +}; + +struct initramfs; +struct setup_data; + +struct firmware { + void (*init)(void); + void (*adjust_screen)(void); + void (*cleanup)(void); + struct disk *(*disk_init)(void *); + struct output_ops *o_ops; + struct input_ops *i_ops; + void (*get_serial_console_info)(uint16_t *, uint16_t *, uint16_t *); + bool (*ipappend_strings)(char **, int *); + struct adv_ops *adv_ops; + int (*boot_linux)(void *, size_t, struct initramfs *, + struct setup_data *, char *); + struct vesa_ops *vesa; + struct mem_ops *mem; +}; + +extern struct firmware *firmware; + +extern void syslinux_register_bios(void); +extern void init(void); + +#endif /* _SYSLINUX_FIRMWARE_H */ diff --git a/com32/include/syslinux/linux.h b/com32/include/syslinux/linux.h index f5f95fb0..a8c6f2f5 100644 --- a/com32/include/syslinux/linux.h +++ b/com32/include/syslinux/linux.h @@ -37,6 +37,7 @@ #include <stddef.h> #include <stdint.h> +#include <klibc/compiler.h> /* A chunk of an initramfs. These are kept as a doubly-linked circular list with headnode; the headnode is distinguished by @@ -68,6 +69,87 @@ struct setup_data { #define SETUP_E820_EXT 1 #define SETUP_DTB 2 +struct linux_header { + uint8_t boot_sector_1[0x0020]; + uint16_t old_cmd_line_magic; + uint16_t old_cmd_line_offset; + uint8_t boot_sector_2[0x01f1 - 0x0024]; + uint8_t setup_sects; + uint16_t root_flags; + uint32_t syssize; + uint16_t ram_size; + uint16_t vid_mode; + uint16_t root_dev; + uint16_t boot_flag; + uint16_t jump; + uint32_t header; + uint16_t version; + uint32_t realmode_swtch; + uint16_t start_sys; + uint16_t kernel_version; + uint8_t type_of_loader; + uint8_t loadflags; + uint16_t setup_move_size; + uint32_t code32_start; + uint32_t ramdisk_image; + uint32_t ramdisk_size; + uint32_t bootsect_kludge; + uint16_t heap_end_ptr; + uint16_t pad1; + uint32_t cmd_line_ptr; + uint32_t initrd_addr_max; + uint32_t kernel_alignment; + uint8_t relocatable_kernel; + uint8_t pad2[3]; + uint32_t cmdline_max_len; + uint32_t hardware_subarch; + uint64_t hardware_subarch_data; + uint32_t payload_offset; + uint32_t payload_length; + uint64_t setup_data; + uint64_t pref_address; + uint32_t init_size; +} __packed; + +struct screen_info { + uint8_t orig_x; /* 0x00 */ + uint8_t orig_y; /* 0x01 */ + uint16_t ext_mem_k; /* 0x02 */ + uint16_t orig_video_page; /* 0x04 */ + uint8_t orig_video_mode; /* 0x06 */ + uint8_t orig_video_cols; /* 0x07 */ + uint8_t flags; /* 0x08 */ + uint8_t unused2; /* 0x09 */ + uint16_t orig_video_ega_bx;/* 0x0a */ + uint16_t unused3; /* 0x0c */ + uint8_t orig_video_lines; /* 0x0e */ + uint8_t orig_video_isVGA; /* 0x0f */ + uint16_t orig_video_points;/* 0x10 */ + + /* VESA graphic mode -- linear frame buffer */ + uint16_t lfb_width; /* 0x12 */ + uint16_t lfb_height; /* 0x14 */ + uint16_t lfb_depth; /* 0x16 */ + uint32_t lfb_base; /* 0x18 */ + uint32_t lfb_size; /* 0x1c */ + uint16_t cl_magic, cl_offset; /* 0x20 */ + uint16_t lfb_linelength; /* 0x24 */ + uint8_t red_size; /* 0x26 */ + uint8_t red_pos; /* 0x27 */ + uint8_t green_size; /* 0x28 */ + uint8_t green_pos; /* 0x29 */ + uint8_t blue_size; /* 0x2a */ + uint8_t blue_pos; /* 0x2b */ + uint8_t rsvd_size; /* 0x2c */ + uint8_t rsvd_pos; /* 0x2d */ + uint16_t vesapm_seg; /* 0x2e */ + uint16_t vesapm_off; /* 0x30 */ + uint16_t pages; /* 0x32 */ + uint16_t vesa_attributes; /* 0x34 */ + uint32_t capabilities; /* 0x36 */ + uint8_t _reserved[6]; /* 0x3a */ +} __packed; + int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, struct initramfs *initramfs, struct setup_data *setup_data, @@ -89,6 +171,23 @@ int initramfs_load_file(struct initramfs *ihead, const char *src_filename, int initramfs_add_trailer(struct initramfs *ihead); int initramfs_load_archive(struct initramfs *ihead, const char *filename); +/* Get the combined size of the initramfs */ +static inline uint32_t initramfs_size(struct initramfs *initramfs) +{ + struct initramfs *ip; + uint32_t size = 0; + + if (!initramfs) + return 0; + + for (ip = initramfs->next; ip->len; ip = ip->next) { + size = (size + ip->align - 1) & ~(ip->align - 1); /* Alignment */ + size += ip->len; + } + + return size; +} + /* Setup data manipulation functions */ struct setup_data *setup_data_init(void); diff --git a/com32/include/syslinux/memscan.h b/com32/include/syslinux/memscan.h index db795439..c3ebf847 100644 --- a/com32/include/syslinux/memscan.h +++ b/com32/include/syslinux/memscan.h @@ -34,5 +34,6 @@ typedef int (*scan_memory_callback_t) (void *, addr_t, addr_t, bool); int syslinux_scan_memory(scan_memory_callback_t callback, void *data); +int bios_scan_memory(scan_memory_callback_t callback, void *data); #endif /* _SYSLINUX_MEMSCAN_H */ diff --git a/com32/include/syslinux/version.h b/com32/include/syslinux/version.h new file mode 100644 index 00000000..762db371 --- /dev/null +++ b/com32/include/syslinux/version.h @@ -0,0 +1,6 @@ +#ifndef _SYSLINUX_VERSION_H +#define _SYSLINUX_VERSION_H + +#define __STDC_VERSION__ 200000L + +#endif /* _SYSLINUX_VERSION_H */ diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 84f65c1f..46a53b5c 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -4,8 +4,7 @@ # Include configuration rules NOGPL := 1 -topdir = ../../ -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/lib.mk ## OPTIONAL OBJECTS, AVAILABLE AS DYNAMIC LINKED MODULES @@ -17,13 +16,6 @@ LIBPNG_OBJS = \ libpng/pngrtran.o libpng/pngwtran.o libpng/pngmem.o \ libpng/pngerror.o libpng/pngpread.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 - # JPG library object files LIBJPG_OBJS = \ jpeg/tinyjpeg.o jpeg/jidctflt.o jpeg/decode1.o jpeg/decode3.o \ @@ -33,7 +25,7 @@ LIBJPG_OBJS = \ LIBVESA_OBJS = \ sys/vesacon_write.o sys/vesaserial_write.o \ sys/vesa/initvesa.o sys/vesa/drawtxt.o sys/vesa/background.o \ - sys/vesa/alphatbl.o sys/vesa/screencpy.o sys/vesa/fmtpixel.o \ + sys/vesa/alphatbl.o sys/vesa/fmtpixel.o \ sys/vesa/i915resolution.o LIBMISC_OBJS = \ @@ -51,134 +43,9 @@ LIBSYSLINUX_OBJS = \ syslinux/pxe_dns.o \ syslinux/video/fontquery.o syslinux/video/reportmode.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/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 - DYNENTRY_OBJS = \ atexit.o onexit.o abort.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 - -LIBMODULE_OBJS = \ - sys/module/common.o sys/module/elf_module.o \ - sys/module/shallow_module.o sys/module/elfutils.o \ - sys/module/exec.o - -LIBGCC_OBJS = \ - libgcc/__ashldi3.o libgcc/__udivdi3.o \ - libgcc/__negdi2.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o \ - libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o \ - libgcc/__divdi3.o libgcc/__moddi3.o - -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 - -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 strcasecmp.o strcat.o \ - strerror.o errlist.o \ - strnlen.o \ - strncat.o strndup.o \ - stpncpy.o \ - strntoimax.o strntoumax.o strsep.o strspn.o strstr.o \ - strtoimax.o strtok.o strtol.o strtoll.o strtoul.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 \ - \ - sys/x86_init_fpu.o math/pow.o math/strtod.o \ - syslinux/disk.o \ - \ - syslinux/setup_data.o - -CORELIBOBJS = \ - memcpy.o memset.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 setjmp.o fopen.o fread.o fread2.o puts.o \ - sprintf.o strlcat.o strchr.o strlcpy.o strncasecmp.o ctypes.o \ - fputs.o fwrite2.o fwrite.o fgetc.o fclose.o errno.o lmalloc.o \ - sys/err_read.o sys/err_write.o sys/null_read.o \ - sys/stdcon_write.o \ - syslinux/memscan.o strrchr.o \ - libgcc/__ashldi3.o libgcc/__udivdi3.o \ - libgcc/__negdi2.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o \ - libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o \ - libgcc/__divdi3.o libgcc/__moddi3.o \ - $(LIBENTRY_OBJS) \ - $(LIBMODULE_OBJS) - MINLIBOBJS = \ syslinux/ipappend.o \ syslinux/dsinfo.o \ @@ -189,7 +56,6 @@ MINLIBOBJS = \ $(LIBZLIB_OBJS) # $(LIBVESA_OBJS) - DYNLIBOBJS = \ $(LIBZLIB_OBJS) \ $(LIBPNG_OBJS) \ @@ -202,8 +68,7 @@ DYNLIBOBJS = \ $(DYNENTRY_OBJS) -LIBOBJS = \ - $(DYNLIBOBJS) +LIBOBJS = $(DYNLIBOBJS) BINDIR = /usr/bin LIBDIR = /usr/lib @@ -212,7 +77,11 @@ AUXDIR = $(DATADIR)/syslinux INCDIR = /usr/include COM32DIR = $(AUXDIR)/com32 -all: libcom32.c32 libcom32min.a libcom32core.a +all: makeoutputdirs libcom32.c32 libcom32min.a libcom32core.a + +makeoutputdirs: + @mkdir -p $(foreach b, \ + $(addprefix $(OBJ)/,$(sort $(dir $(LIBOBJS) $(MINLIBOBJS) $(CORELIBOBJS)))),$(b)) libcom32.c32 : $(LIBOBJS) rm -f $@ @@ -239,11 +108,11 @@ spotless: clean install: all mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR) - install -m 644 com32.ld $(INSTALLROOT)$(COM32DIR) + install -m 644 $(SRC)/com32.ld $(INSTALLROOT)$(COM32DIR) -rm -rf $(INSTALLROOT)$(COM32DIR)/include - cp -r ../include $(INSTALLROOT)$(COM32DIR) + cp -r $(SRC)/../include $(INSTALLROOT)$(COM32DIR) -errlist.c: makeerrlist.pl ../include/errno.h +errlist.c: makeerrlist.pl $(SRC)/../include/errno.h $(PERL) $< $(CFLAGS) -errlist > $@ || rm -f $@ # These files are performance critical, and doesn't compile well with -Os diff --git a/com32/lib/i386/elf.ld b/com32/lib/i386/elf.ld new file mode 100644 index 00000000..fc2e7db5 --- /dev/null +++ b/com32/lib/i386/elf.ld @@ -0,0 +1,178 @@ +/* + * Linker script for ELF dynamic loaded modules. + */ + +/* Script for --shared -z combreloc: shared library, combine & sort relocs */ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", + "elf32-i386") +OUTPUT_ARCH(i386) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0 + SIZEOF_HEADERS; + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0x90909090 + .plt : { *(.plt) } + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0x90909090 + .fini : + { + KEEP (*(.fini)) + } =0x90909090 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + . = ALIGN(4); + .preinit_array : + { + KEEP (*(.preinit_array)) + } + .init_array : + { + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + } + .fini_array : + { + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + } + + .ctors : + { + __ctors_start = .; + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*(.ctors_modinit)) + KEEP (*(.ctors_modmain)) + __ctors_end = .; + } + + .dtors : + { + __dtors_start = .; + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + KEEP (*(.dtors_modexit)) + __dtors_end = .; + } + + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got) } + /*. = DATA_SEGMENT_RELRO_END (12, .); -> This gives a "invalid assignment to location counter" error */ + .got.plt : { *(.got.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + PROVIDE (edata = .); + PROVIDE (_edata = .); + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + PROVIDE (_end = .); + PROVIDE (end = .); + /*. = DATA_SEGMENT_END (.); -> This gives a "invalid assignment to location counter" error */ + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.eh_frame) } +} diff --git a/com32/lib/i386/setjmp.S b/com32/lib/i386/setjmp.S new file mode 100644 index 00000000..658df485 --- /dev/null +++ b/com32/lib/i386/setjmp.S @@ -0,0 +1,63 @@ +/* + * arch/i386/setjmp.S + * + * setjmp/longjmp for the i386 architecture + * + * + * + * The jmp_buf is assumed to contain the following, in order: + * %ebx + * %esp + * %ebp + * %esi + * %edi + * <return address> + */ + + .text + .align 4 + + .globl _setjmp + .type _setjmp, @function +_setjmp: # gcc 4.0.1 wants this as an alias? + + .globl setjmp + .type setjmp, @function +setjmp: +#ifdef REGPARM + movl %eax,%edx +#else + movl 4(%esp),%edx +#endif + popl %ecx # Return address, and adjust the stack + xorl %eax,%eax # Return value + movl %ebx,(%edx) + movl %esp,4(%edx) # Post-return %esp! + pushl %ecx # Make the call/return stack happy + movl %ebp,8(%edx) + movl %esi,12(%edx) + movl %edi,16(%edx) + movl %ecx,20(%edx) # Return address + ret + + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: +#ifdef REGPARM + xchgl %eax,%edx +#else + movl 4(%esp),%edx # jmp_ptr address + movl 8(%esp),%eax # Return value +#endif + movl (%edx),%ebx + movl 4(%edx),%esp + movl 8(%edx),%ebp + movl 12(%edx),%esi + movl 16(%edx),%edi + jmp *20(%edx) + + .size longjmp,.-longjmp diff --git a/com32/lib/libgcc/__muldi3.S b/com32/lib/libgcc/__muldi3.S index 648a88ad..424787c8 100644 --- a/com32/lib/libgcc/__muldi3.S +++ b/com32/lib/libgcc/__muldi3.S @@ -9,6 +9,8 @@ .globl __muldi3 .type __muldi3,@function __muldi3: +#if __SIZEOF_POINTER__ == 4 + /* i386 */ push %esi #ifndef REGPARM movl 8(%esp),%eax @@ -31,4 +33,51 @@ __muldi3: #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/memcpy.S b/com32/lib/memcpy.S index 6b986a0d..9b5306dd 100644 --- a/com32/lib/memcpy.S +++ b/com32/lib/memcpy.S @@ -36,6 +36,10 @@ .globl memcpy .type memcpy, @function memcpy: + movl 0xc(%esp),%ecx + movl 0x8(%esp),%edx + movl 0x4(%esp),%eax + jecxz 1f pushl %esi diff --git a/com32/lib/memcpy.c b/com32/lib/memcpy.c new file mode 100644 index 00000000..5ce206d0 --- /dev/null +++ b/com32/lib/memcpy.c @@ -0,0 +1,29 @@ +/* + * memcpy.c + */ + +#include <string.h> +#include <stdint.h> + +void *memcpy(void *dst, const void *src, size_t n) +{ + const char *p = src; + char *q = dst; +#if defined(__i386__) + size_t nl = n >> 2; + asm volatile ("cld ; rep ; movsl ; movl %3,%0 ; rep ; movsb":"+c" (nl), + "+S"(p), "+D"(q) + :"r"(n & 3)); +#elif defined(__x86_64__) + size_t nq = n >> 3; + asm volatile ("cld ; rep ; movsq ; movl %3,%%ecx ; rep ; movsb":"+c" + (nq), "+S"(p), "+D"(q) + :"r"((uint32_t) (n & 7))); +#else + while (n--) { + *q++ = *p++; + } +#endif + + return dst; +} diff --git a/com32/lib/memmove.S b/com32/lib/memmove.S index e97299f2..2094e4aa 100644 --- a/com32/lib/memmove.S +++ b/com32/lib/memmove.S @@ -37,6 +37,10 @@ .type memmove,@function .text memmove: + movl 0xc(%esp),%ecx + movl 0x8(%esp),%edx + movl 0x4(%esp),%eax + jecxz 4f pushl %esi diff --git a/com32/lib/memmove.c b/com32/lib/memmove.c new file mode 100644 index 00000000..a398cd8d --- /dev/null +++ b/com32/lib/memmove.c @@ -0,0 +1,36 @@ +/* + * memmove.c + */ + +#include <string.h> + +void *memmove(void *dst, const void *src, size_t n) +{ + const char *p = src; + char *q = dst; +#if defined(__i386__) || defined(__x86_64__) + if (q < p) { + asm volatile("cld; rep; movsb" + : "+c" (n), "+S"(p), "+D"(q)); + } else { + p += (n - 1); + q += (n - 1); + asm volatile("std; rep; movsb; cld" + : "+c" (n), "+S"(p), "+D"(q)); + } +#else + if (q < p) { + while (n--) { + *q++ = *p++; + } + } else { + p += n; + q += n; + while (n--) { + *--q = *--p; + } + } +#endif + + return dst; +} diff --git a/com32/lib/mempcpy.S b/com32/lib/mempcpy.S index cad7b983..2096f132 100644 --- a/com32/lib/mempcpy.S +++ b/com32/lib/mempcpy.S @@ -36,6 +36,10 @@ .globl mempcpy .type mempcpy, @function mempcpy: + movl 0xc(%esp),%ecx + movl 0x8(%esp),%edx + movl 0x4(%esp),%eax + jecxz 1f pushl %esi diff --git a/com32/lib/mempcpy.c b/com32/lib/mempcpy.c new file mode 100644 index 00000000..be23b667 --- /dev/null +++ b/com32/lib/mempcpy.c @@ -0,0 +1,14 @@ +/* + * mempcpy.c + */ + +#include <string.h> +#include <stdint.h> + +/* simply a wrapper around memcpy implementation */ + +void *mempcpy(void *dst, const void *src, size_t n) +{ + + return (char *)memcpy(dst, src, n) + n; +} diff --git a/com32/lib/memset.S b/com32/lib/memset.S index e641415d..fd42842a 100644 --- a/com32/lib/memset.S +++ b/com32/lib/memset.S @@ -36,6 +36,10 @@ .type memset,@function .text memset: + movl 0xc(%esp),%ecx + movl 0x8(%esp),%edx + movl 0x4(%esp),%eax + jecxz 6f pushl %edi diff --git a/com32/lib/memset.c b/com32/lib/memset.c new file mode 100644 index 00000000..aa00b5b1 --- /dev/null +++ b/com32/lib/memset.c @@ -0,0 +1,30 @@ +/* + * memset.c + */ + +#include <string.h> +#include <stdint.h> + +void *memset(void *dst, int c, size_t n) +{ + char *q = dst; + +#if defined(__i386__) + size_t nl = n >> 2; + asm volatile ("cld ; rep ; stosl ; movl %3,%0 ; rep ; stosb" + : "+c" (nl), "+D" (q) + : "a" ((unsigned char)c * 0x01010101U), "r" (n & 3)); +#elif defined(__x86_64__) + size_t nq = n >> 3; + asm volatile ("cld ; rep ; stosq ; movl %3,%%ecx ; rep ; stosb" + :"+c" (nq), "+D" (q) + : "a" ((unsigned char)c * 0x0101010101010101U), + "r" ((uint32_t) n & 7)); +#else + while (n--) { + *q++ = c; + } +#endif + + return dst; +} diff --git a/com32/lib/setjmp.S b/com32/lib/setjmp.S index 658df485..2fb5c234 100644 --- a/com32/lib/setjmp.S +++ b/com32/lib/setjmp.S @@ -13,7 +13,7 @@ * %edi * <return address> */ - +/* .text .align 4 @@ -61,3 +61,12 @@ longjmp: jmp *20(%edx) .size longjmp,.-longjmp +*/ +#if __SIZEOF_POINTER__ == 4 +#include <i386/setjmp.S> +#elif __SIZEOF_POINTER__ == 8 +#include <x86_64/setjmp.S> +#else +#error "Unable to build for to-be-defined architecture type" +#endif + diff --git a/com32/lib/sys/ansicon_write.c b/com32/lib/sys/ansicon_write.c index e5483fbc..74add717 100644 --- a/com32/lib/sys/ansicon_write.c +++ b/com32/lib/sys/ansicon_write.c @@ -35,13 +35,13 @@ #include <errno.h> #include <string.h> -#include <com32.h> #include <minmax.h> #include <colortbl.h> #include <klibc/compiler.h> #include <syslinux/config.h> #include "file.h" #include "ansi.h" +#include <syslinux/firmware.h> #include "graphics.h" static void ansicon_erase(const struct term_state *, int, int, int, int); @@ -66,23 +66,15 @@ static struct term_info ti = { .op = &__ansicon_ops }; -#define BIOS_CURXY ((struct curxy *)0x450) /* Array for each page */ -#define BIOS_ROWS (*(uint8_t *)0x484) /* Minus one; if zero use 24 (= 25 lines) */ -#define BIOS_COLS (*(uint16_t *)0x44A) -#define BIOS_PAGE (*(uint8_t *)0x462) +#define TEXT_MODE 0x0005 /* Reference counter to the screen, to keep track of if we need reinitialization. */ static int ansicon_counter = 0; -static uint16_t cursor_type; /* Saved cursor pattern */ - /* Common setup */ int __ansicon_open(struct file_info *fp) { - static com32sys_t ireg; /* Auto-initalized to all zero */ - com32sys_t oreg; - if (!ansicon_counter) { /* Are we disabled? */ if (syslinux_serial_console_info()->flowctl & 0x8000) { @@ -91,20 +83,14 @@ int __ansicon_open(struct file_info *fp) ti.cols = 80; } else { /* Force text mode */ - syslinux_force_text_mode(); + firmware->o_ops->set_mode(TEXT_MODE); /* Initial state */ - ti.rows = BIOS_ROWS ? BIOS_ROWS + 1 : 25; - ti.cols = BIOS_COLS; + firmware->o_ops->get_mode(&ti.cols, &ti.rows); __ansi_init(&ti); /* Get cursor shape and position */ - ireg.eax.b[1] = 0x03; - ireg.ebx.b[1] = BIOS_PAGE; - __intcall(0x10, &ireg, &oreg); - cursor_type = oreg.ecx.w[0]; - ti.ts->xy.x = oreg.edx.b[0]; - ti.ts->xy.y = oreg.edx.b[1]; + firmware->o_ops->get_cursor(&ti.ts->xy.x, &ti.ts->xy.y); } } @@ -155,69 +141,45 @@ static uint8_t ansicon_attribute(const struct term_state *st) static void ansicon_erase(const struct term_state *st, int x0, int y0, int x1, int y1) { - static com32sys_t ireg; - - ireg.eax.w[0] = 0x0600; /* Clear window */ - ireg.ebx.b[1] = ansicon_attribute(st); - ireg.ecx.b[0] = x0; - ireg.ecx.b[1] = y0; - ireg.edx.b[0] = x1; - ireg.edx.b[1] = y1; - __intcall(0x10, &ireg, NULL); + uint8_t attribute = ansicon_attribute(st); + + if (firmware->o_ops->erase) + firmware->o_ops->erase(x0, y0, x1, y1, attribute); } /* Show or hide the cursor */ static void ansicon_showcursor(const struct term_state *st) { - static com32sys_t ireg; - - ireg.eax.b[1] = 0x01; - ireg.ecx.w[0] = st->cursor ? cursor_type : 0x2020; - __intcall(0x10, &ireg, NULL); + firmware->o_ops->showcursor(st); } static void ansicon_set_cursor(int x, int y, bool visible) { - const int page = BIOS_PAGE; - struct curxy xy = BIOS_CURXY[page]; - static com32sys_t ireg; - - (void)visible; - - if (xy.x != x || xy.y != y) { - ireg.eax.b[1] = 0x02; - ireg.ebx.b[1] = page; - ireg.edx.b[1] = y; - ireg.edx.b[0] = x; - __intcall(0x10, &ireg, NULL); - } + firmware->o_ops->set_cursor(x, y, visible); } static void ansicon_write_char(int x, int y, uint8_t ch, const struct term_state *st) { - static com32sys_t ireg; - + uint8_t attribute = ansicon_attribute(st); ansicon_set_cursor(x, y, false); - ireg.eax.b[1] = 0x09; - ireg.eax.b[0] = ch; - ireg.ebx.b[1] = BIOS_PAGE; - ireg.ebx.b[0] = ansicon_attribute(st); - ireg.ecx.w[0] = 1; - __intcall(0x10, &ireg, NULL); + firmware->o_ops->write_char(ch, attribute); } static void ansicon_scroll_up(const struct term_state *st) { - static com32sys_t ireg; - - ireg.eax.w[0] = 0x0601; - ireg.ebx.b[1] = ansicon_attribute(st); - ireg.ecx.w[0] = 0; - ireg.edx.b[1] = ti.rows - 1; - ireg.edx.b[0] = ti.cols - 1; - __intcall(0x10, &ireg, NULL); /* Scroll */ + uint8_t rows, cols, attribute; + + /* + * Earlier code set ti.cols to 1 causing console output one char + * per line. + */ + cols = 1; + rows = ti.rows - 1; + attribute = ansicon_attribute(st); + + firmware->o_ops->scroll_up(cols, rows, attribute); } ssize_t __ansicon_write(struct file_info *fp, const void *buf, size_t count) @@ -240,11 +202,8 @@ ssize_t __ansicon_write(struct file_info *fp, const void *buf, size_t count) void __ansicon_beep(void) { - static com32sys_t ireg; - - ireg.eax.w[0] = 0x0e07; - ireg.ebx.b[1] = BIOS_PAGE; - __intcall(0x10, &ireg, NULL); + if (firmware->o_ops->beep) + firmware->o_ops->beep(); } const struct output_dev dev_ansicon_w = { diff --git a/com32/lib/sys/farcall.c b/com32/lib/sys/farcall.c index 988ee6d2..2749083e 100644 --- a/com32/lib/sys/farcall.c +++ b/com32/lib/sys/farcall.c @@ -6,9 +6,17 @@ static inline uint32_t eflags(void) { - uint32_t v; + //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; } diff --git a/com32/lib/sys/i386/x86_init_fpu.c b/com32/lib/sys/i386/x86_init_fpu.c new file mode 100644 index 00000000..cf336932 --- /dev/null +++ b/com32/lib/sys/i386/x86_init_fpu.c @@ -0,0 +1,58 @@ +/* + * x86_has_fpu.c + * + * Test for an x86 FPU, and do any necessary setup. + */ + +#include <inttypes.h> +#include <sys/fpu.h> + +static inline uint64_t get_cr0(void) +{ + uint32_t v; +asm("movl %%cr0,%0":"=r"(v)); + return v; +} + +static inline void set_cr0(uint32_t v) +{ + asm volatile ("movl %0,%%cr0"::"r" (v)); +} + +#define CR0_PE 0x00000001 +#define CR0_MP 0x00000002 +#define CR0_EM 0x00000004 +#define CR0_TS 0x00000008 +#define CR0_ET 0x00000010 +#define CR0_NE 0x00000020 +#define CR0_WP 0x00010000 +#define CR0_AM 0x00040000 +#define CR0_NW 0x20000000 +#define CR0_CD 0x40000000 +#define CR0_PG 0x80000000 + +int x86_init_fpu(void) +{ + uint32_t cr0; + uint16_t fsw = 0xffff; + uint16_t fcw = 0xffff; + + cr0 = get_cr0(); + cr0 &= ~(CR0_EM | CR0_TS); + cr0 |= CR0_MP; + set_cr0(cr0); + + asm volatile ("fninit"); + asm volatile ("fnstsw %0":"+m" (fsw)); + if (fsw != 0) + return -1; + + asm volatile ("fnstcw %0":"+m" (fcw)); + if ((fcw & 0x103f) != 0x3f) + return -1; + + /* Techically, this could be a 386 with a 287. We could add a check + for that here... */ + + return 0; +} diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c index d72dd702..5b0d9ee8 100644 --- a/com32/lib/sys/module/common.c +++ b/com32/lib/sys/module/common.c @@ -23,7 +23,7 @@ LIST_HEAD(modules_head); // User-space debugging routines #ifdef ELF_DEBUG -void print_elf_ehdr(Elf32_Ehdr *ehdr) { +void print_elf_ehdr(Elf_Ehdr *ehdr) { int i; fprintf(stderr, "Identification:\t"); @@ -38,18 +38,18 @@ void print_elf_ehdr(Elf32_Ehdr *ehdr) { fprintf(stderr, "PHT Offset:\t0x%08x\n", ehdr->e_phoff); fprintf(stderr, "SHT Offset:\t0x%08x\n", ehdr->e_shoff); //fprintf(stderr, "Flags:\t\t%u\n", ehdr->e_flags); - //fprintf(stderr, "Header size:\t%u (Structure size: %u)\n", ehdr->e_ehsize,sizeof(Elf32_Ehdr)); + //fprintf(stderr, "Header size:\t%u (Structure size: %u)\n", ehdr->e_ehsize,sizeof(Elf_Ehdr)); fprintf(stderr, "phnum: %d shnum: %d\n", ehdr->e_phnum, ehdr->e_shnum); } void print_elf_symbols(struct elf_module *module) { unsigned int i; - Elf32_Sym *crt_sym; + Elf_Sym *crt_sym; for (i = 1; i < module->symtable_size/module->syment_size; i++) { - crt_sym = (Elf32_Sym*)(module->sym_table + i*module->syment_size); + crt_sym = (Elf_Sym*)(module->sym_table + i*module->syment_size); fprintf(stderr,"%s %d\n", module->str_table + crt_sym->st_name, crt_sym->st_value); @@ -163,7 +163,7 @@ int image_skip(size_t size, struct elf_module *module) { return 0; } -int image_seek(Elf32_Off offset, struct elf_module *module) { +int image_seek(Elf_Off offset, struct elf_module *module) { if (offset < module->u.l._cr_offset) // Cannot seek backwards return -1; @@ -218,9 +218,14 @@ struct elf_module *module_find(const char *name) { } +// Mouli: This is checking the header for 32bit machine +// Support 64bit architecture as well. +// Parts of the ELF header checked are common to both ELF32 and ELF64 +// Adding simple checks for both 32bit and 64bit should work (hopefully) +// // Performs verifications on ELF header to assure that the open file is a // valid SYSLINUX ELF module. -int check_header_common(Elf32_Ehdr *elf_hdr) { +int check_header_common(Elf_Ehdr *elf_hdr) { // Check the header magic if (elf_hdr->e_ident[EI_MAG0] != ELFMAG0 || elf_hdr->e_ident[EI_MAG1] != ELFMAG1 || @@ -231,7 +236,8 @@ int check_header_common(Elf32_Ehdr *elf_hdr) { return -1; } - if (elf_hdr->e_ident[EI_CLASS] != MODULE_ELF_CLASS) { + if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32 && + elf_hdr->e_ident[EI_CLASS] != ELFCLASS64) { DBG_PRINT("Invalid ELF class code\n"); return -1; } @@ -247,7 +253,8 @@ int check_header_common(Elf32_Ehdr *elf_hdr) { return -1; } - if (elf_hdr->e_machine != MODULE_ELF_MACHINE) { + if (elf_hdr->e_machine != EM_386 && + elf_hdr->e_machine != EM_X86_64) { DBG_PRINT("Invalid ELF architecture\n"); return -1; } @@ -256,6 +263,7 @@ int check_header_common(Elf32_Ehdr *elf_hdr) { } + int enforce_dependency(struct elf_module *req, struct elf_module *dep) { struct module_dep *crt_dep; struct module_dep *new_dep; @@ -312,7 +320,7 @@ int clear_dependency(struct elf_module *req, struct elf_module *dep) { int check_symbols(struct elf_module *module) { unsigned int i; - Elf32_Sym *crt_sym = NULL, *ref_sym = NULL; + Elf_Sym *crt_sym = NULL, *ref_sym = NULL; char *crt_name; struct elf_module *crt_module; @@ -360,7 +368,6 @@ int check_symbols(struct elf_module *module) if (strong_count == 0 && weak_count == 0) { DBG_PRINT("Symbol %s is undefined\n", crt_name); - printf("Undef symbol FAIL: %s\n",crt_name); return -1; } } @@ -420,7 +427,7 @@ int _module_unload(struct elf_module *module) { int module_unload(struct elf_module *module) { module_ctor_t *dtor; - for (dtor = module->dtors; *dtor; dtor++) + for (dtor = module->dtors; dtor && *dtor; dtor++) (*dtor) (); return _module_unload(module); @@ -450,18 +457,18 @@ struct elf_module *unload_modules_since(const char *name) { return begin; } -static Elf32_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) { +static Elf_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) { unsigned long h = elf_hash((const unsigned char*)name); - Elf32_Word *cr_word = module->hash_table; + Elf_Word *cr_word = module->hash_table; - Elf32_Word nbucket = *cr_word++; + Elf_Word nbucket = *cr_word++; cr_word++; // Skip nchain - Elf32_Word *bkt = cr_word; - Elf32_Word *chn = cr_word + nbucket; + Elf_Word *bkt = cr_word; + Elf_Word *chn = cr_word + nbucket; - Elf32_Word crt_index = bkt[h % module->hash_table[0]]; - Elf32_Sym *crt_sym; + Elf_Word crt_index = bkt[h % module->hash_table[0]]; + Elf_Sym *crt_sym; while (crt_index != STN_UNDEF) { @@ -476,32 +483,32 @@ static Elf32_Sym *module_find_symbol_sysv(const char *name, struct elf_module *m return NULL; } -static Elf32_Sym *module_find_symbol_gnu(const char *name, struct elf_module *module) { +static Elf_Sym *module_find_symbol_gnu(const char *name, struct elf_module *module) { unsigned long h = elf_gnu_hash((const unsigned char*)name); // Setup code (TODO: Optimize this by computing only once) - Elf32_Word *cr_word = module->ghash_table; - Elf32_Word nbucket = *cr_word++; - Elf32_Word symbias = *cr_word++; - Elf32_Word bitmask_nwords = *cr_word++; + Elf_Word *cr_word = module->ghash_table; + Elf_Word nbucket = *cr_word++; + Elf_Word symbias = *cr_word++; + Elf_Word bitmask_nwords = *cr_word++; if ((bitmask_nwords & (bitmask_nwords - 1)) != 0) { DBG_PRINT("Invalid GNU Hash structure\n"); return NULL; } - Elf32_Word gnu_shift = *cr_word++; + Elf_Word gnu_shift = *cr_word++; - Elf32_Addr *gnu_bitmask = (Elf32_Addr*)cr_word; + Elf_Addr *gnu_bitmask = (Elf_Addr*)cr_word; cr_word += MODULE_ELF_CLASS_SIZE / 32 * bitmask_nwords; - Elf32_Word *gnu_buckets = cr_word; + Elf_Word *gnu_buckets = cr_word; cr_word += nbucket; - Elf32_Word *gnu_chain_zero = cr_word - symbias; + Elf_Word *gnu_chain_zero = cr_word - symbias; // Computations - Elf32_Word bitmask_word = gnu_bitmask[(h / MODULE_ELF_CLASS_SIZE) & + Elf_Bword bitmask_word = gnu_bitmask[(h / MODULE_ELF_CLASS_SIZE) & (bitmask_nwords - 1)]; unsigned int hashbit1 = h & (MODULE_ELF_CLASS_SIZE - 1); @@ -509,18 +516,18 @@ static Elf32_Sym *module_find_symbol_gnu(const char *name, struct elf_module *mo if ((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1) { unsigned long rem; - Elf32_Word bucket; + Elf_Word bucket; rem = h % nbucket; bucket = gnu_buckets[rem]; if (bucket != 0) { - const Elf32_Word* hasharr = &gnu_chain_zero[bucket]; + const Elf_Word* hasharr = &gnu_chain_zero[bucket]; do { if (((*hasharr ^ h ) >> 1) == 0) { - Elf32_Sym *crt_sym = symbol_get_entry(module, (hasharr - gnu_chain_zero)); + Elf_Sym *crt_sym = symbol_get_entry(module, (hasharr - gnu_chain_zero)); if (strcmp(name, module->str_table + crt_sym->st_name) == 0) { return crt_sym; @@ -533,11 +540,11 @@ static Elf32_Sym *module_find_symbol_gnu(const char *name, struct elf_module *mo return NULL; } -static Elf32_Sym *module_find_symbol_iterate(const char *name,struct elf_module *module) +static Elf_Sym *module_find_symbol_iterate(const char *name,struct elf_module *module) { unsigned int i; - Elf32_Sym *crt_sym; + Elf_Sym *crt_sym; for (i = 1; i < module->symtable_size/module->syment_size; i++) { @@ -551,8 +558,8 @@ static Elf32_Sym *module_find_symbol_iterate(const char *name,struct elf_module return NULL; } -Elf32_Sym *module_find_symbol(const char *name, struct elf_module *module) { - Elf32_Sym *result = NULL; +Elf_Sym *module_find_symbol(const char *name, struct elf_module *module) { + Elf_Sym *result = NULL; if (module->ghash_table != NULL) result = module_find_symbol_gnu(name, module); @@ -574,10 +581,10 @@ Elf32_Sym *module_find_symbol(const char *name, struct elf_module *module) { return result; } -Elf32_Sym *global_find_symbol(const char *name, struct elf_module **module) { +Elf_Sym *global_find_symbol(const char *name, struct elf_module **module) { struct elf_module *crt_module; - Elf32_Sym *crt_sym = NULL; - Elf32_Sym *result = NULL; + Elf_Sym *crt_sym = NULL; + Elf_Sym *result = NULL; for_each_module(crt_module) { crt_sym = module_find_symbol(name, crt_module); diff --git a/com32/lib/sys/module/common.h b/com32/lib/sys/module/common.h index 54f0ec4b..652c9735 100644 --- a/com32/lib/sys/module/common.h +++ b/com32/lib/sys/module/common.h @@ -15,7 +15,6 @@ #include "elfutils.h" - // Performs an operation and jumps to a given label if an error occurs #define CHECKED(res, expr, error) \ do { \ @@ -27,12 +26,12 @@ #define MIN(x,y) (((x) < (y)) ? (x) : (y)) #define MAX(x,y) (((x) > (y)) ? (x) : (y)) -static inline Elf32_Sym *symbol_get_entry(struct elf_module *module, int entry) +static inline Elf_Sym *symbol_get_entry(struct elf_module *module, int entry) { char *sym_table = (char *)module->sym_table; int index = entry * module->syment_size; - return (Elf32_Sym *)(sym_table + index); + return (Elf_Sym *)(sym_table + index); } //#define ELF_DEBUG @@ -45,7 +44,7 @@ static inline Elf32_Sym *symbol_get_entry(struct elf_module *module, int entry) // User-space debugging routines #ifdef ELF_DEBUG -extern void print_elf_ehdr(Elf32_Ehdr *ehdr); +extern void print_elf_ehdr(Elf_Ehdr *ehdr); extern void print_elf_symbols(struct elf_module *module); #endif //ELF_DEBUG @@ -58,11 +57,11 @@ extern int image_load(struct elf_module *module); extern int image_unload(struct elf_module *module); extern int image_read(void *buff, size_t size, struct elf_module *module); extern int image_skip(size_t size, struct elf_module *module); -extern int image_seek(Elf32_Off offset, struct elf_module *module); +extern int image_seek(Elf_Off offset, struct elf_module *module); extern struct module_dep *module_dep_alloc(struct elf_module *module); -extern int check_header_common(Elf32_Ehdr *elf_hdr); +extern int check_header_common(Elf_Ehdr *elf_hdr); extern int enforce_dependency(struct elf_module *req, struct elf_module *dep); extern int clear_dependency(struct elf_module *req, struct elf_module *dep); diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c index 24da2209..0d27c92b 100644 --- a/com32/lib/sys/module/elf_module.c +++ b/com32/lib/sys/module/elf_module.c @@ -20,7 +20,7 @@ #include "elfutils.h" #include "common.h" -static int check_header(Elf32_Ehdr *elf_hdr) { +static int check_header(Elf_Ehdr *elf_hdr) { int res; res = check_header_common(elf_hdr); @@ -47,162 +47,10 @@ static int check_header(Elf32_Ehdr *elf_hdr) { * in the PHT sorted by their offsets, so that only forward seeks would * be necessary. */ -static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) { - int i; - int res = 0; - char *pht = NULL; - char *sht = NULL; - Elf32_Phdr *cr_pht; - Elf32_Shdr *cr_sht; - - Elf32_Addr min_addr = 0x00000000; // Min. ELF vaddr - Elf32_Addr max_addr = 0x00000000; // Max. ELF vaddr - Elf32_Word max_align = sizeof(void*); // Min. align of posix_memalign() - Elf32_Addr min_alloc, max_alloc; // Min. and max. aligned allocables - - Elf32_Addr dyn_addr = 0x00000000; - - // Get to the PHT - image_seek(elf_hdr->e_phoff, module); - - // Load the PHT - pht = malloc(elf_hdr->e_phnum * elf_hdr->e_phentsize); - image_read(pht, elf_hdr->e_phnum * elf_hdr->e_phentsize, module); - - // Compute the memory needings of the module - for (i=0; i < elf_hdr->e_phnum; i++) { - cr_pht = (Elf32_Phdr*)(pht + i * elf_hdr->e_phentsize); - - switch (cr_pht->p_type) { - case PT_LOAD: - if (i == 0) { - min_addr = cr_pht->p_vaddr; - } else { - min_addr = MIN(min_addr, cr_pht->p_vaddr); - } - - max_addr = MAX(max_addr, cr_pht->p_vaddr + cr_pht->p_memsz); - max_align = MAX(max_align, cr_pht->p_align); - break; - case PT_DYNAMIC: - dyn_addr = cr_pht->p_vaddr; - break; - default: - // Unsupported - ignore - break; - } - } - - if (max_addr - min_addr == 0) { - // No loadable segments - DBG_PRINT("No loadable segments found\n"); - goto out; - } - - if (dyn_addr == 0) { - DBG_PRINT("No dynamic information segment found\n"); - goto out; - } - - // The minimum address that should be allocated - min_alloc = min_addr - (min_addr % max_align); - - // The maximum address that should be allocated - max_alloc = max_addr - (max_addr % max_align); - if (max_addr % max_align > 0) - max_alloc += max_align; - - - if (elf_malloc(&module->module_addr, - max_align, - max_alloc-min_alloc) != 0) { - - DBG_PRINT("Could not allocate segments\n"); - goto out; - } - - module->base_addr = (Elf32_Addr)(module->module_addr) - min_alloc; - module->module_size = max_alloc - min_alloc; - - // Zero-initialize the memory - memset(module->module_addr, 0, module->module_size); - - for (i = 0; i < elf_hdr->e_phnum; i++) { - cr_pht = (Elf32_Phdr*)(pht + i * elf_hdr->e_phentsize); - - if (cr_pht->p_type == PT_LOAD) { - // Copy the segment at its destination - if (cr_pht->p_offset < module->u.l._cr_offset) { - // The segment contains data before the current offset - // It can be discarded without worry - it would contain only - // headers - Elf32_Off aux_off = module->u.l._cr_offset - cr_pht->p_offset; - - if (image_read((char *)module_get_absolute(cr_pht->p_vaddr, module) + aux_off, - cr_pht->p_filesz - aux_off, module) < 0) { - res = -1; - goto out; - } - } else { - if (image_seek(cr_pht->p_offset, module) < 0) { - res = -1; - goto out; - } - - if (image_read(module_get_absolute(cr_pht->p_vaddr, module), - cr_pht->p_filesz, module) < 0) { - res = -1; - goto out; - } - } - - /* - DBG_PRINT("Loadable segment of size 0x%08x copied from vaddr 0x%08x at 0x%08x\n", - cr_pht->p_filesz, - cr_pht->p_vaddr, - (Elf32_Addr)module_get_absolute(cr_pht->p_vaddr, module)); - */ - } - } - - // Get to the SHT - image_seek(elf_hdr->e_shoff, module); - - // Load the SHT - sht = malloc(elf_hdr->e_shnum * elf_hdr->e_shentsize); - image_read(sht, elf_hdr->e_shnum * elf_hdr->e_shentsize, module); - - // Setup the symtable size - for (i = 0; i < elf_hdr->e_shnum; i++) { - cr_sht = (Elf32_Shdr*)(sht + i * elf_hdr->e_shentsize); - - if (cr_sht->sh_type == SHT_DYNSYM) { - module->symtable_size = cr_sht->sh_size; - break; - } - } - - free(sht); - - // Setup dynamic segment location - module->dyn_table = module_get_absolute(dyn_addr, module); - - /* - DBG_PRINT("Base address: 0x%08x, aligned at 0x%08x\n", module->base_addr, - max_align); - DBG_PRINT("Module size: 0x%08x\n", module->module_size); - */ - -out: - // Free up allocated memory - if (pht != NULL) - free(pht); - - return res; -} +extern int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr); static int prepare_dynlinking(struct elf_module *module) { - Elf32_Dyn *dyn_entry = module->dyn_table; + Elf_Dyn *dyn_entry = module->dyn_table; while (dyn_entry->d_tag != DT_NULL) { switch (dyn_entry->d_tag) { @@ -222,11 +70,11 @@ static int prepare_dynlinking(struct elf_module *module) { break; case DT_HASH: module->hash_table = - (Elf32_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module); + (Elf_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module); break; case DT_GNU_HASH: module->ghash_table = - (Elf32_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module); + (Elf_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module); break; case DT_STRTAB: module->str_table = @@ -259,168 +107,12 @@ void undefined_symbol(void) kaboom(); } -static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) { - Elf32_Word *dest = module_get_absolute(rel->r_offset, module); - - // The symbol reference index - Elf32_Word sym = ELF32_R_SYM(rel->r_info); - unsigned char type = ELF32_R_TYPE(rel->r_info); - - // The symbol definition (if applicable) - Elf32_Sym *sym_def = NULL; - struct elf_module *sym_module = NULL; - Elf32_Addr sym_addr = 0x0; - - if (sym > 0) { - // Find out details about the symbol - - // The symbol reference - Elf32_Sym *sym_ref = symbol_get_entry(module, sym); - - // The symbol definition - sym_def = - global_find_symbol(module->str_table + sym_ref->st_name, - &sym_module); - - if (sym_def == NULL) { - DBG_PRINT("Cannot perform relocation for symbol %s\n", - module->str_table + sym_ref->st_name); - - if (ELF32_ST_BIND(sym_ref->st_info) != STB_WEAK) - return -1; - - // This must be a derivative-specific - // function. We're OK as long as we never - // execute the function. - sym_def = global_find_symbol("undefined_symbol", &sym_module); - } - - // Compute the absolute symbol virtual address - sym_addr = (Elf32_Addr)module_get_absolute(sym_def->st_value, sym_module); - - if (sym_module != module) { - // Create a dependency - enforce_dependency(sym_module, module); - } - } - - switch (type) { - case R_386_NONE: - // Do nothing - break; - case R_386_32: - *dest += sym_addr; - break; - case R_386_PC32: - *dest += sym_addr - (Elf32_Addr)dest; - break; - case R_386_COPY: - if (sym_addr > 0) { - memcpy((void*)dest, (void*)sym_addr, sym_def->st_size); - } - break; - case R_386_GLOB_DAT: - case R_386_JMP_SLOT: - // Maybe TODO: Keep track of the GOT entries allocations - *dest = sym_addr; - break; - case R_386_RELATIVE: - *dest += module->base_addr; - break; - default: - DBG_PRINT("Relocation type %d not supported\n", type); - return -1; - } - - return 0; -} - -static int resolve_symbols(struct elf_module *module) { - Elf32_Dyn *dyn_entry = module->dyn_table; - unsigned int i; - int res; - - Elf32_Word plt_rel_size = 0; - char *plt_rel = NULL; - - char *rel = NULL; - Elf32_Word rel_size = 0; - Elf32_Word rel_entry = 0; - - // The current relocation - Elf32_Rel *crt_rel; - - while (dyn_entry->d_tag != DT_NULL) { - switch(dyn_entry->d_tag) { - - // PLT relocation information - case DT_PLTRELSZ: - plt_rel_size = dyn_entry->d_un.d_val; - break; - case DT_PLTREL: - if (dyn_entry->d_un.d_val != DT_REL) { - DBG_PRINT("Unsupported PLT relocation\n"); - return -1; - } - case DT_JMPREL: - plt_rel = module_get_absolute(dyn_entry->d_un.d_ptr, module); - break; - - // Standard relocation information - case DT_REL: - rel = module_get_absolute(dyn_entry->d_un.d_ptr, module); - break; - case DT_RELSZ: - rel_size = dyn_entry->d_un.d_val; - break; - case DT_RELENT: - rel_entry = dyn_entry->d_un.d_val; - break; - - // Module initialization and termination - case DT_INIT: - // TODO Implement initialization functions - break; - case DT_FINI: - // TODO Implement finalization functions - break; - } - - dyn_entry++; - } - - if (rel_size > 0) { - // Process standard relocations - for (i = 0; i < rel_size/rel_entry; i++) { - crt_rel = (Elf32_Rel*)(rel + i*rel_entry); - - res = perform_relocation(module, crt_rel); - - if (res < 0) - return res; - } - - } - - if (plt_rel_size > 0) { - // TODO: Permit this lazily - // Process PLT relocations - for (i = 0; i < plt_rel_size/sizeof(Elf32_Rel); i++) { - crt_rel = (Elf32_Rel*)(plt_rel + i*sizeof(Elf32_Rel)); - - res = perform_relocation(module, crt_rel); - - if (res < 0) - return res; - } - } - - return 0; -} +extern int perform_relocation(struct elf_module *module, Elf_Rel *rel); +extern int resolve_symbols(struct elf_module *module); static int extract_operations(struct elf_module *module) { - Elf32_Sym *ctors_start, *ctors_end; - Elf32_Sym *dtors_start, *dtors_end; + Elf_Sym *ctors_start, *ctors_end; + Elf_Sym *dtors_start, *dtors_end; module_ctor_t *ctors = NULL; module_ctor_t *dtors = NULL; @@ -489,8 +181,8 @@ static int extract_operations(struct elf_module *module) { // Loads the module into the system int module_load(struct elf_module *module) { int res; - Elf32_Sym *main_sym; - Elf32_Ehdr elf_hdr; + Elf_Sym *main_sym; + Elf_Ehdr elf_hdr; module_ctor_t *ctor; struct elf_module *head = NULL; @@ -510,7 +202,7 @@ int module_load(struct elf_module *module) { // The module is a fully featured dynamic library module->shallow = 0; - CHECKED(res, image_read(&elf_hdr, sizeof(Elf32_Ehdr), module), error); + CHECKED(res, image_read(&elf_hdr, sizeof(Elf_Ehdr), module), error); //printf("check... 1\n"); //print_elf_ehdr(&elf_hdr); @@ -596,7 +288,7 @@ int module_load(struct elf_module *module) { (module->exit_func == NULL) ? NULL : *(module->exit_func)); */ - for (ctor = module->ctors; *ctor; ctor++) + for (ctor = module->ctors; ctor && *ctor; ctor++) (*ctor) (); return 0; diff --git a/com32/lib/sys/module/elfutils.h b/com32/lib/sys/module/elfutils.h index a901ff48..91bdcb3f 100644 --- a/com32/lib/sys/module/elfutils.h +++ b/com32/lib/sys/module/elfutils.h @@ -3,23 +3,24 @@ #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 Elf32_Ehdr *elf_get_header(void *elf_image) { - return (Elf32_Ehdr*)elf_image; +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 Elf32_Phdr *elf_get_pht(void *elf_image) { - Elf32_Ehdr *elf_hdr = elf_get_header(elf_image); +static inline Elf_Phdr *elf_get_pht(void *elf_image) { + Elf_Ehdr *elf_hdr = elf_get_header(elf_image); - return (Elf32_Phdr*)((Elf32_Off)elf_hdr + elf_hdr->e_phoff); + return (Elf_Phdr*)((Elf_Off)elf_hdr + elf_hdr->e_phoff); } // @@ -28,11 +29,11 @@ static inline Elf32_Phdr *elf_get_pht(void *elf_image) { * @elf_image: pointer to the ELF file image in memory * @index: the index of the PHT entry to look for */ -static inline Elf32_Phdr *elf_get_ph(void *elf_image, int index) { - Elf32_Phdr *elf_pht = elf_get_pht(elf_image); - Elf32_Ehdr *elf_hdr = elf_get_header(elf_image); +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 (Elf32_Phdr*)((Elf32_Off)elf_pht + index * elf_hdr->e_phentsize); + return (Elf_Phdr*)((Elf_Off)elf_pht + index * elf_hdr->e_phentsize); } /** diff --git a/com32/lib/sys/module/i386/elf_module.c b/com32/lib/sys/module/i386/elf_module.c new file mode 100644 index 00000000..a3792554 --- /dev/null +++ b/com32/lib/sys/module/i386/elf_module.c @@ -0,0 +1,341 @@ +/* + * elf_module.c + * + * Created on: Aug 11, 2008 + * Author: Stefan Bucur <stefanb@zytor.com> + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <elf.h> +#include <dprintf.h> +#include <core.h> + +#include <linux/list.h> +#include <sys/module.h> +#include <sys/exec.h> + +#include "elfutils.h" +#include "../common.h" + +/* + * + * The implementation assumes that the loadable segments are present + * in the PHT sorted by their offsets, so that only forward seeks would + * be necessary. + */ +int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr) { + int i; + int res = 0; + char *pht = NULL; + char *sht = NULL; + Elf32_Phdr *cr_pht; + Elf32_Shdr *cr_sht; + + Elf32_Addr min_addr = 0x00000000; // Min. ELF vaddr + Elf32_Addr max_addr = 0x00000000; // Max. ELF vaddr + Elf32_Word max_align = sizeof(void*); // Min. align of posix_memalign() + Elf32_Addr min_alloc, max_alloc; // Min. and max. aligned allocables + + Elf32_Addr dyn_addr = 0x00000000; + + // Get to the PHT + image_seek(elf_hdr->e_phoff, module); + + // Load the PHT + pht = malloc(elf_hdr->e_phnum * elf_hdr->e_phentsize); + image_read(pht, elf_hdr->e_phnum * elf_hdr->e_phentsize, module); + + // Compute the memory needings of the module + for (i=0; i < elf_hdr->e_phnum; i++) { + cr_pht = (Elf32_Phdr*)(pht + i * elf_hdr->e_phentsize); + + switch (cr_pht->p_type) { + case PT_LOAD: + if (i == 0) { + min_addr = cr_pht->p_vaddr; + } else { + min_addr = MIN(min_addr, cr_pht->p_vaddr); + } + + max_addr = MAX(max_addr, cr_pht->p_vaddr + cr_pht->p_memsz); + max_align = MAX(max_align, cr_pht->p_align); + break; + case PT_DYNAMIC: + dyn_addr = cr_pht->p_vaddr; + break; + default: + // Unsupported - ignore + break; + } + } + + if (max_addr - min_addr == 0) { + // No loadable segments + DBG_PRINT("No loadable segments found\n"); + goto out; + } + + if (dyn_addr == 0) { + DBG_PRINT("No dynamic information segment found\n"); + goto out; + } + + // The minimum address that should be allocated + min_alloc = min_addr - (min_addr % max_align); + + // The maximum address that should be allocated + max_alloc = max_addr - (max_addr % max_align); + if (max_addr % max_align > 0) + max_alloc += max_align; + + + if (elf_malloc(&module->module_addr, + max_align, + max_alloc-min_alloc) != 0) { + + DBG_PRINT("Could not allocate segments\n"); + goto out; + } + + module->base_addr = (Elf32_Addr)(module->module_addr) - min_alloc; + module->module_size = max_alloc - min_alloc; + + // Zero-initialize the memory + memset(module->module_addr, 0, module->module_size); + + for (i = 0; i < elf_hdr->e_phnum; i++) { + cr_pht = (Elf32_Phdr*)(pht + i * elf_hdr->e_phentsize); + + if (cr_pht->p_type == PT_LOAD) { + // Copy the segment at its destination + if (cr_pht->p_offset < module->u.l._cr_offset) { + // The segment contains data before the current offset + // It can be discarded without worry - it would contain only + // headers + Elf32_Off aux_off = module->u.l._cr_offset - cr_pht->p_offset; + + if (image_read((char *)module_get_absolute(cr_pht->p_vaddr, module) + aux_off, + cr_pht->p_filesz - aux_off, module) < 0) { + res = -1; + goto out; + } + } else { + if (image_seek(cr_pht->p_offset, module) < 0) { + res = -1; + goto out; + } + + if (image_read(module_get_absolute(cr_pht->p_vaddr, module), + cr_pht->p_filesz, module) < 0) { + res = -1; + goto out; + } + } + + /* + DBG_PRINT("Loadable segment of size 0x%08x copied from vaddr 0x%08x at 0x%08x\n", + cr_pht->p_filesz, + cr_pht->p_vaddr, + (Elf32_Addr)module_get_absolute(cr_pht->p_vaddr, module)); + */ + } + } + + // Get to the SHT + image_seek(elf_hdr->e_shoff, module); + + // Load the SHT + sht = malloc(elf_hdr->e_shnum * elf_hdr->e_shentsize); + image_read(sht, elf_hdr->e_shnum * elf_hdr->e_shentsize, module); + + // Setup the symtable size + for (i = 0; i < elf_hdr->e_shnum; i++) { + cr_sht = (Elf32_Shdr*)(sht + i * elf_hdr->e_shentsize); + + if (cr_sht->sh_type == SHT_DYNSYM) { + module->symtable_size = cr_sht->sh_size; + break; + } + } + + free(sht); + + // Setup dynamic segment location + module->dyn_table = module_get_absolute(dyn_addr, module); + + /* + DBG_PRINT("Base address: 0x%08x, aligned at 0x%08x\n", module->base_addr, + max_align); + DBG_PRINT("Module size: 0x%08x\n", module->module_size); + */ + +out: + // Free up allocated memory + if (pht != NULL) + free(pht); + + return res; +} + +int perform_relocation(struct elf_module *module, Elf_Rel *rel) { + Elf32_Word *dest = module_get_absolute(rel->r_offset, module); + + // The symbol reference index + Elf32_Word sym = ELF32_R_SYM(rel->r_info); + unsigned char type = ELF32_R_TYPE(rel->r_info); + + // The symbol definition (if applicable) + Elf32_Sym *sym_def = NULL; + struct elf_module *sym_module = NULL; + Elf32_Addr sym_addr = 0x0; + + if (sym > 0) { + // Find out details about the symbol + + // The symbol reference + Elf32_Sym *sym_ref = symbol_get_entry(module, sym); + + // The symbol definition + sym_def = + global_find_symbol(module->str_table + sym_ref->st_name, + &sym_module); + + if (sym_def == NULL) { + DBG_PRINT("Cannot perform relocation for symbol %s\n", + module->str_table + sym_ref->st_name); + + if (ELF32_ST_BIND(sym_ref->st_info) != STB_WEAK) + return -1; + + // This must be a derivative-specific + // function. We're OK as long as we never + // execute the function. + sym_def = global_find_symbol("undefined_symbol", &sym_module); + } + + // Compute the absolute symbol virtual address + sym_addr = (Elf32_Addr)module_get_absolute(sym_def->st_value, sym_module); + + if (sym_module != module) { + // Create a dependency + enforce_dependency(sym_module, module); + } + } + + switch (type) { + case R_386_NONE: + // Do nothing + break; + case R_386_32: + *dest += sym_addr; + break; + case R_386_PC32: + *dest += sym_addr - (Elf32_Addr)dest; + break; + case R_386_COPY: + if (sym_addr > 0) { + memcpy((void*)dest, (void*)sym_addr, sym_def->st_size); + } + break; + case R_386_GLOB_DAT: + case R_386_JMP_SLOT: + // Maybe TODO: Keep track of the GOT entries allocations + *dest = sym_addr; + break; + case R_386_RELATIVE: + *dest += module->base_addr; + break; + default: + DBG_PRINT("Relocation type %d not supported\n", type); + return -1; + } + + return 0; +} + +int resolve_symbols(struct elf_module *module) { + Elf32_Dyn *dyn_entry = module->dyn_table; + unsigned int i; + int res; + + Elf32_Word plt_rel_size = 0; + char *plt_rel = NULL; + + char *rel = NULL; + Elf32_Word rel_size = 0; + Elf32_Word rel_entry = 0; + + // The current relocation + Elf32_Rel *crt_rel; + + while (dyn_entry->d_tag != DT_NULL) { + switch(dyn_entry->d_tag) { + + // PLT relocation information + case DT_PLTRELSZ: + plt_rel_size = dyn_entry->d_un.d_val; + break; + case DT_PLTREL: + if (dyn_entry->d_un.d_val != DT_REL) { + DBG_PRINT("Unsupported PLT relocation\n"); + return -1; + } + case DT_JMPREL: + plt_rel = module_get_absolute(dyn_entry->d_un.d_ptr, module); + break; + + // Standard relocation information + case DT_REL: + rel = module_get_absolute(dyn_entry->d_un.d_ptr, module); + break; + case DT_RELSZ: + rel_size = dyn_entry->d_un.d_val; + break; + case DT_RELENT: + rel_entry = dyn_entry->d_un.d_val; + break; + + // Module initialization and termination + case DT_INIT: + // TODO Implement initialization functions + break; + case DT_FINI: + // TODO Implement finalization functions + break; + } + + dyn_entry++; + } + + if (rel_size > 0) { + // Process standard relocations + for (i = 0; i < rel_size/rel_entry; i++) { + crt_rel = (Elf32_Rel*)(rel + i*rel_entry); + + res = perform_relocation(module, crt_rel); + + if (res < 0) + return res; + } + + } + + if (plt_rel_size > 0) { + // TODO: Permit this lazily + // Process PLT relocations + for (i = 0; i < plt_rel_size/sizeof(Elf32_Rel); i++) { + crt_rel = (Elf32_Rel*)(plt_rel + i*sizeof(Elf32_Rel)); + + res = perform_relocation(module, crt_rel); + + if (res < 0) + return res; + } + } + + return 0; +} + diff --git a/com32/lib/sys/module/i386/shallow_module.c b/com32/lib/sys/module/i386/shallow_module.c new file mode 100644 index 00000000..fbcf781b --- /dev/null +++ b/com32/lib/sys/module/i386/shallow_module.c @@ -0,0 +1,161 @@ +/* + * shallow_module.c + * + * Created on: Aug 11, 2008 + * Author: Stefan Bucur <stefanb@zytor.com> + */ + + +#include <string.h> +#include <sys/module.h> + +#include "common.h" +#include "elfutils.h" + + +static int check_header_shallow(Elf32_Ehdr *elf_hdr) { + int res; + + res = check_header_common(elf_hdr); + + if (res != 0) + return res; + + if (elf_hdr->e_shoff == 0x00000000) { + DBG_PRINT("SHT missing\n"); + return -1; + } + + return 0; +} + +static int load_shallow_sections(struct elf_module *module, Elf32_Ehdr *elf_hdr) { + int i; + int res = 0; + void *sht = NULL; + void *buffer = NULL; + Elf32_Shdr *crt_sht; + Elf32_Off buff_offset; + + Elf32_Off min_offset = 0xFFFFFFFF; + Elf32_Off max_offset = 0x00000000; + Elf32_Word max_align = 0x1; + + Elf32_Off sym_offset = 0xFFFFFFFF; + Elf32_Off str_offset = 0xFFFFFFFF; + + + char *sh_strtable; + + // We buffer the data up to the SHT + buff_offset = module->u.l._cr_offset; + + buffer = malloc(elf_hdr->e_shoff - buff_offset); + // Get to the SHT + image_read(buffer, elf_hdr->e_shoff - buff_offset, module); + + // Load the SHT + sht = malloc(elf_hdr->e_shnum * elf_hdr->e_shentsize); + image_read(sht, elf_hdr->e_shnum * elf_hdr->e_shentsize, module); + + // Get the string table of the section names + crt_sht = (Elf32_Shdr*)(sht + elf_hdr->e_shstrndx * elf_hdr->e_shentsize); + sh_strtable = (char*)(buffer + (crt_sht->sh_offset - buff_offset)); + + for (i = 0; i < elf_hdr->e_shnum; i++) { + crt_sht = (Elf32_Shdr*)(sht + i*elf_hdr->e_shentsize); + + if (strcmp(".symtab", sh_strtable + crt_sht->sh_name) == 0) { + // We found the symbol table + min_offset = MIN(min_offset, crt_sht->sh_offset); + max_offset = MAX(max_offset, crt_sht->sh_offset + crt_sht->sh_size); + max_align = MAX(max_align, crt_sht->sh_addralign); + + sym_offset = crt_sht->sh_offset; + + module->syment_size = crt_sht->sh_entsize; + module->symtable_size = crt_sht->sh_size / crt_sht->sh_entsize; + } + if (strcmp(".strtab", sh_strtable + crt_sht->sh_name) == 0) { + // We found the string table + min_offset = MIN(min_offset, crt_sht->sh_offset); + max_offset = MAX(max_offset, crt_sht->sh_offset + crt_sht->sh_size); + max_align = MAX(max_align, crt_sht->sh_addralign); + + str_offset = crt_sht->sh_offset; + + module->strtable_size = crt_sht->sh_size; + } + } + + if (elf_malloc(&module->module_addr, max_align, + max_offset - min_offset) != 0) { + DBG_PRINT("Could not allocate sections\n"); + goto out; + } + + // Copy the data + image_seek(min_offset, module); + image_read(module->module_addr, max_offset - min_offset, module); + + // Setup module information + module->module_size = max_offset - min_offset; + module->str_table = (char*)(module->module_addr + (str_offset - min_offset)); + module->sym_table = module->module_addr + (sym_offset - min_offset); + +out: + // Release the SHT + if (sht != NULL) + free(sht); + + // Release the buffer + if (buffer != NULL) + free(buffer); + + return res; +} + + +int module_load_shallow(struct elf_module *module, Elf32_Addr base_addr) { + int res; + Elf32_Ehdr elf_hdr; + + // Do not allow duplicate modules + if (module_find(module->name) != NULL) { + DBG_PRINT("Module already loaded.\n"); + return -1; + } + + res = image_load(module); + + if (res < 0) + return res; + + module->shallow = 1; + + CHECKED(res, image_read(&elf_hdr, sizeof(Elf32_Ehdr), module), error); + + // Checking the header signature and members + CHECKED(res, check_header_shallow(&elf_hdr), error); + + CHECKED(res, load_shallow_sections(module, &elf_hdr), error); + module->base_addr = base_addr; + + // Check the symbols for duplicates / missing definitions + CHECKED(res, check_symbols(module), error); + + // Add the module at the beginning of the module list + list_add(&module->list, &modules_head); + + // The file image is no longer needed + image_unload(module); + + DBG_PRINT("SHALLOW MODULE %s LOADED SUCCESSFULLY\n", module->name); + + return 0; + +error: + image_unload(module); + + return res; +} diff --git a/com32/lib/sys/module/x86_64/elf_module.c b/com32/lib/sys/module/x86_64/elf_module.c new file mode 100644 index 00000000..64404a17 --- /dev/null +++ b/com32/lib/sys/module/x86_64/elf_module.c @@ -0,0 +1,372 @@ +/* + * elf_module.c + * + * Created on: Aug 11, 2008 + * Author: Stefan Bucur <stefanb@zytor.com> + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <elf.h> +#include <dprintf.h> +#include <core.h> + +#include <linux/list.h> +#include <sys/module.h> +#include <sys/exec.h> + +#include "elfutils.h" +#include "../common.h" + +/* + * + * The implementation assumes that the loadable segments are present + * in the PHT sorted by their offsets, so that only forward seeks would + * be necessary. + */ +int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr) { + int i; + int res = 0; + char *pht = NULL; + char *sht = NULL; + Elf64_Phdr *cr_pht; + Elf64_Shdr *cr_sht; + + Elf64_Addr min_addr = 0x0000000000000000; // Min. ELF vaddr + Elf64_Addr max_addr = 0x0000000000000000; // Max. ELF vaddr + Elf64_Word max_align = sizeof(void*); // Min. align of posix_memalign() + Elf64_Addr min_alloc, max_alloc; // Min. and max. aligned allocables + + Elf64_Addr dyn_addr = 0x0000000000000000; + + // Get to the PHT + image_seek(elf_hdr->e_phoff, module); + + // Load the PHT + pht = malloc(elf_hdr->e_phnum * elf_hdr->e_phentsize); + image_read(pht, elf_hdr->e_phnum * elf_hdr->e_phentsize, module); + + // Compute the memory needings of the module + for (i=0; i < elf_hdr->e_phnum; i++) { + cr_pht = (Elf64_Phdr*)(pht + i * elf_hdr->e_phentsize); + + switch (cr_pht->p_type) { + case PT_LOAD: + if (i == 0) { + min_addr = cr_pht->p_vaddr; + } else { + min_addr = MIN(min_addr, cr_pht->p_vaddr); + } + + max_addr = MAX(max_addr, cr_pht->p_vaddr + cr_pht->p_memsz); + max_align = MAX(max_align, cr_pht->p_align); + break; + case PT_DYNAMIC: + dyn_addr = cr_pht->p_vaddr; + break; + default: + // Unsupported - ignore + break; + } + } + + if (max_addr - min_addr == 0) { + // No loadable segments + DBG_PRINT("No loadable segments found\n"); + goto out; + } + + if (dyn_addr == 0) { + DBG_PRINT("No dynamic information segment found\n"); + goto out; + } + + // The minimum address that should be allocated + min_alloc = min_addr - (min_addr % max_align); + + // The maximum address that should be allocated + max_alloc = max_addr - (max_addr % max_align); + if (max_addr % max_align > 0) + max_alloc += max_align; + + + if (elf_malloc(&module->module_addr, + max_align, + max_alloc-min_alloc) != 0) { + + DBG_PRINT("Could not allocate segments\n"); + goto out; + } + + module->base_addr = (Elf64_Addr)(module->module_addr) - min_alloc; + module->module_size = max_alloc - min_alloc; + + // Zero-initialize the memory + memset(module->module_addr, 0, module->module_size); + + for (i = 0; i < elf_hdr->e_phnum; i++) { + cr_pht = (Elf64_Phdr*)(pht + i * elf_hdr->e_phentsize); + + if (cr_pht->p_type == PT_LOAD) { + // Copy the segment at its destination + if (cr_pht->p_offset < module->u.l._cr_offset) { + // The segment contains data before the current offset + // It can be discarded without worry - it would contain only + // headers + Elf64_Off aux_off = module->u.l._cr_offset - cr_pht->p_offset; + + if (image_read((char *)module_get_absolute(cr_pht->p_vaddr, module) + aux_off, + cr_pht->p_filesz - aux_off, module) < 0) { + res = -1; + goto out; + } + } else { + if (image_seek(cr_pht->p_offset, module) < 0) { + res = -1; + goto out; + } + + if (image_read(module_get_absolute(cr_pht->p_vaddr, module), + cr_pht->p_filesz, module) < 0) { + res = -1; + goto out; + } + } + + /* + DBG_PRINT("Loadable segment of size 0x%08x copied from vaddr 0x%08x at 0x%08x\n", + cr_pht->p_filesz, + cr_pht->p_vaddr, + (Elf64_Addr)module_get_absolute(cr_pht->p_vaddr, module)); + */ + } + } + + // Get to the SHT + image_seek(elf_hdr->e_shoff, module); + + // Load the SHT + sht = malloc(elf_hdr->e_shnum * elf_hdr->e_shentsize); + image_read(sht, elf_hdr->e_shnum * elf_hdr->e_shentsize, module); + + // Setup the symtable size + for (i = 0; i < elf_hdr->e_shnum; i++) { + cr_sht = (Elf64_Shdr*)(sht + i * elf_hdr->e_shentsize); + + if (cr_sht->sh_type == SHT_DYNSYM) { + module->symtable_size = cr_sht->sh_size; + break; + } + } + + free(sht); + + // Setup dynamic segment location + module->dyn_table = module_get_absolute(dyn_addr, module); + + /* + DBG_PRINT("Base address: 0x%08x, aligned at 0x%08x\n", module->base_addr, + max_align); + DBG_PRINT("Module size: 0x%08x\n", module->module_size); + */ + +out: + // Free up allocated memory + if (pht != NULL) + free(pht); + + return res; +} + +int perform_relocation(struct elf_module *module, Elf_Rel *rel) { + Elf64_Xword *dest = module_get_absolute(rel->r_offset, module); + + // The symbol reference index + Elf64_Word sym = ELF64_R_SYM(rel->r_info); + unsigned char type = ELF64_R_TYPE(rel->r_info); + + // The symbol definition (if applicable) + Elf64_Sym *sym_def = NULL; + struct elf_module *sym_module = NULL; + Elf64_Addr sym_addr = 0x0; + + if (sym > 0) { + // Find out details about the symbol + + // The symbol reference + Elf64_Sym *sym_ref = symbol_get_entry(module, sym); + + // The symbol definition + sym_def = + global_find_symbol(module->str_table + sym_ref->st_name, + &sym_module); + + if (sym_def == NULL) { + DBG_PRINT("Cannot perform relocation for symbol %s\n", + module->str_table + sym_ref->st_name); + + if (ELF64_ST_BIND(sym_ref->st_info) != STB_WEAK) + return -1; + + // This must be a derivative-specific + // function. We're OK as long as we never + // execute the function. + sym_def = global_find_symbol("undefined_symbol", &sym_module); + } + + // Compute the absolute symbol virtual address + sym_addr = (Elf64_Addr)module_get_absolute(sym_def->st_value, sym_module); + + if (sym_module != module) { + // Create a dependency + enforce_dependency(sym_module, module); + } + } + + switch (type) { + case R_X86_64_NONE: + // Do nothing + break; + case R_X86_64_64: + *dest += sym_addr; + break; + case R_X86_64_PC32: + *dest += sym_addr - (Elf32_Addr)dest; + break; + case R_X86_64_COPY: + if (sym_addr > 0) { + memcpy((void*)dest, (void*)sym_addr, sym_def->st_size); + } + break; + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + //Maybe TODO: Keep track of the GOT entries allocations + *dest = sym_addr; + break; + case R_X86_64_RELATIVE: + *dest += module->base_addr; + break; + default: + DBG_PRINT("Relocation type %d not supported\n", type); + return -1; + } + + return 0; +} + +int resolve_symbols(struct elf_module *module) { + Elf64_Dyn *dyn_entry = module->dyn_table; + unsigned int i; + int res; + + Elf64_Word plt_rel_size = 0; + void *plt_rel = NULL; + + void *rel = NULL; + Elf64_Word rel_size = 0; + Elf64_Word rel_entry = 0; + Elf64_Xword rela_size = 0; + Elf64_Xword rela_entry = 0; + Elf64_Xword sym_ent = 0; + + // The current relocation + Elf64_Rel *crt_rel; + + while (dyn_entry->d_tag != DT_NULL) { + switch(dyn_entry->d_tag) { + + // PLT relocation information + case DT_PLTRELSZ: + plt_rel_size = dyn_entry->d_un.d_val; + break; + case DT_PLTREL: + if (dyn_entry->d_un.d_val != DT_REL && dyn_entry->d_un.d_val != DT_RELA) { + DBG_PRINT("Unsupported PLT relocation\n"); + return -1; + } + //break; + case DT_JMPREL: + plt_rel = module_get_absolute(dyn_entry->d_un.d_ptr, module); + break; + + // Standard relocation information + case DT_REL: + rel = module_get_absolute(dyn_entry->d_un.d_ptr, module); + break; + case DT_RELA: + rel = module_get_absolute(dyn_entry->d_un.d_ptr, module); + break; + case DT_RELSZ: + rel_size = dyn_entry->d_un.d_val; + break; + case DT_RELASZ: + rela_size = dyn_entry->d_un.d_val; + break; + case DT_RELENT: + rel_entry = dyn_entry->d_un.d_val; + break; + case DT_RELAENT: + rela_entry = dyn_entry->d_un.d_val; + break; + /* FIXME: We may need to rely upon SYMENT if DT_RELAENT is missing in the object file */ + case DT_SYMENT: + sym_ent = dyn_entry->d_un.d_val; + break; + + // Module initialization and termination + case DT_INIT: + // TODO Implement initialization functions + break; + case DT_FINI: + // TODO Implement finalization functions + break; + } + + dyn_entry++; + } + + if (rel_size > 0) { + // Process standard relocations + for (i = 0; i < rel_size/rel_entry; i++) { + crt_rel = (Elf64_Rel*)(rel + i*rel_entry); + + res = perform_relocation(module, crt_rel); + + if (res < 0) + return res; + } + + } + + if (rela_size > 0) { + // Process standard relocations + for (i = 0; i < rela_size/rela_entry; i++) { + crt_rel = (Elf64_Rel*)(rel + i*rela_entry); + + res = perform_relocation(module, crt_rel); + + if (res < 0) + return res; + } + } + if (plt_rel_size > 0) { + // TODO: Permit this lazily + // Process PLT relocations + /* some modules do not have DT_SYMENT, set it sym_ent in such cases */ + if (!rela_entry) rela_entry = sym_ent; + //for (i = 0; i < plt_rel_size/sizeof(Elf64_Rel); i++) { + for (i = 0; i < plt_rel_size/rela_entry; i++) { + //crt_rel = (Elf64_Rel*)(plt_rel + i*sizeof(Elf64_Rel)); + crt_rel = (Elf64_Rel*)(plt_rel + i*rela_entry); + + res = perform_relocation(module, crt_rel); + + if (res < 0) + return res; + } + } + + return 0; +} diff --git a/com32/lib/sys/module/x86_64/shallow_module.c b/com32/lib/sys/module/x86_64/shallow_module.c new file mode 100644 index 00000000..b7248150 --- /dev/null +++ b/com32/lib/sys/module/x86_64/shallow_module.c @@ -0,0 +1,161 @@ +/* + * shallow_module.c + * + * Created on: Aug 11, 2008 + * Author: Stefan Bucur <stefanb@zytor.com> + */ + + +#include <string.h> +#include <sys/module.h> + +#include "common.h" +#include "elfutils.h" + + +static int check_header_shallow(Elf64_Ehdr *elf_hdr) { + int res; + + res = check_header_common(elf_hdr); + + if (res != 0) + return res; + + if (elf_hdr->e_shoff == 0x00000000) { + DBG_PRINT("SHT missing\n"); + return -1; + } + + return 0; +} + +static int load_shallow_sections(struct elf_module *module, Elf64_Ehdr *elf_hdr) { + int i; + int res = 0; + void *sht = NULL; + void *buffer = NULL; + Elf64_Shdr *crt_sht; + Elf64_Off buff_offset; + + Elf64_Off min_offset = 0xFFFFFFFFFFFFFFFF; + Elf64_Off max_offset = 0x0000000000000000; + Elf64_Word max_align = 0x1; + + Elf64_Off sym_offset = 0xFFFFFFFFFFFFFFFF; + Elf64_Off str_offset = 0xFFFFFFFFFFFFFFFF; + + + char *sh_strtable; + + // We buffer the data up to the SHT + buff_offset = module->u.l._cr_offset; + + buffer = malloc(elf_hdr->e_shoff - buff_offset); + // Get to the SHT + image_read(buffer, elf_hdr->e_shoff - buff_offset, module); + + // Load the SHT + sht = malloc(elf_hdr->e_shnum * elf_hdr->e_shentsize); + image_read(sht, elf_hdr->e_shnum * elf_hdr->e_shentsize, module); + + // Get the string table of the section names + crt_sht = (Elf64_Shdr*)(sht + elf_hdr->e_shstrndx * elf_hdr->e_shentsize); + sh_strtable = (char*)(buffer + (crt_sht->sh_offset - buff_offset)); + + for (i = 0; i < elf_hdr->e_shnum; i++) { + crt_sht = (Elf64_Shdr*)(sht + i*elf_hdr->e_shentsize); + + if (strcmp(".symtab", sh_strtable + crt_sht->sh_name) == 0) { + // We found the symbol table + min_offset = MIN(min_offset, crt_sht->sh_offset); + max_offset = MAX(max_offset, crt_sht->sh_offset + crt_sht->sh_size); + max_align = MAX(max_align, crt_sht->sh_addralign); + + sym_offset = crt_sht->sh_offset; + + module->syment_size = crt_sht->sh_entsize; + module->symtable_size = crt_sht->sh_size / crt_sht->sh_entsize; + } + if (strcmp(".strtab", sh_strtable + crt_sht->sh_name) == 0) { + // We found the string table + min_offset = MIN(min_offset, crt_sht->sh_offset); + max_offset = MAX(max_offset, crt_sht->sh_offset + crt_sht->sh_size); + max_align = MAX(max_align, crt_sht->sh_addralign); + + str_offset = crt_sht->sh_offset; + + module->strtable_size = crt_sht->sh_size; + } + } + + if (elf_malloc(&module->module_addr, max_align, + max_offset - min_offset) != 0) { + DBG_PRINT("Could not allocate sections\n"); + goto out; + } + + // Copy the data + image_seek(min_offset, module); + image_read(module->module_addr, max_offset - min_offset, module); + + // Setup module information + module->module_size = max_offset - min_offset; + module->str_table = (char*)(module->module_addr + (str_offset - min_offset)); + module->sym_table = module->module_addr + (sym_offset - min_offset); + +out: + // Release the SHT + if (sht != NULL) + free(sht); + + // Release the buffer + if (buffer != NULL) + free(buffer); + + return res; +} + + +int module_load_shallow(struct elf_module *module, Elf64_Addr base_addr) { + int res; + Elf64_Ehdr elf_hdr; + + // Do not allow duplicate modules + if (module_find(module->name) != NULL) { + DBG_PRINT("Module already loaded.\n"); + return -1; + } + + res = image_load(module); + + if (res < 0) + return res; + + module->shallow = 1; + + CHECKED(res, image_read(&elf_hdr, sizeof(Elf64_Ehdr), module), error); + + // Checking the header signature and members + CHECKED(res, check_header_shallow(&elf_hdr), error); + + CHECKED(res, load_shallow_sections(module, &elf_hdr), error); + module->base_addr = base_addr; + + // Check the symbols for duplicates / missing definitions + CHECKED(res, check_symbols(module), error); + + // Add the module at the beginning of the module list + list_add(&module->list, &modules_head); + + // The file image is no longer needed + image_unload(module); + + DBG_PRINT("SHALLOW MODULE %s LOADED SUCCESSFULLY\n", module->name); + + return 0; + +error: + image_unload(module); + + return res; +} diff --git a/com32/lib/sys/vesa/initvesa.c b/com32/lib/sys/vesa/initvesa.c index 9a1ae384..c2721b8d 100644 --- a/com32/lib/sys/vesa/initvesa.c +++ b/com32/lib/sys/vesa/initvesa.c @@ -69,37 +69,12 @@ static void unpack_font(uint8_t * dst, uint8_t * src, int height) } } -static int __constfunc is_power_of_2(unsigned int x) +static int vesacon_set_mode(int *x, int *y) { - return x && !(x & (x - 1)); -} - -static int vesacon_paged_mode_ok(const struct vesa_mode_info *mi) -{ - int i; - - if (!is_power_of_2(mi->win_size) || - !is_power_of_2(mi->win_grain) || mi->win_grain > mi->win_size) - return 0; /* Impossible... */ - - for (i = 0; i < 2; i++) { - if ((mi->win_attr[i] & 0x05) == 0x05 && mi->win_seg[i]) - return 1; /* Usable window */ - } - - return 0; /* Nope... */ -} - -static int vesacon_set_mode(int x, int y) -{ - com32sys_t rm; uint8_t *rom_font; - uint16_t mode, bestmode, *mode_ptr; - struct vesa_info *vi; - struct vesa_general_info *gi; struct vesa_mode_info *mi; - enum vesa_pixel_format pxf, bestpxf; - int err = 0; + enum vesa_pixel_format bestpxf; + int rv; debug("Hello, World!\r\n"); @@ -113,172 +88,22 @@ static int vesacon_set_mode(int x, int y) __vesacon_shadowfb = NULL; } - /* Allocate space in the bounce buffer for these structures */ - vi = lzalloc(sizeof *vi); - if (!vi) { - err = 10; /* Out of memory */ - goto exit; - } - gi = &vi->gi; - mi = &vi->mi; - - memset(&rm, 0, sizeof rm); - - gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */ - rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ - rm.edi.w[0] = OFFS(gi); - rm.es = SEG(gi); - __intcall(0x10, &rm, &rm); - - if (rm.eax.w[0] != 0x004F) { - err = 1; /* Function call failed */ - goto exit; - } - if (gi->signature != VESA_MAGIC) { - err = 2; /* No magic */ - goto exit; - } - if (gi->version < 0x0102) { - err = 3; /* VESA 1.2+ required */ - goto exit; - } - - /* Copy general info */ - memcpy(&__vesa_info.gi, gi, sizeof *gi); - - /* Search for the proper mode with a suitable color and memory model... */ - - mode_ptr = GET_PTR(gi->video_mode_ptr); - bestmode = 0; - bestpxf = PXF_NONE; - - while ((mode = *mode_ptr++) != 0xFFFF) { - mode &= 0x1FF; /* The rest are attributes of sorts */ - - debug("Found mode: 0x%04x\r\n", mode); - - memset(mi, 0, sizeof *mi); - rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ - rm.ecx.w[0] = mode; - rm.edi.w[0] = OFFS(mi); - rm.es = SEG(mi); - __intcall(0x10, &rm, &rm); - - /* Must be a supported mode */ - if (rm.eax.w[0] != 0x004f) - continue; - - debug - ("mode_attr 0x%04x, h_res = %4d, v_res = %4d, bpp = %2d, layout = %d (%d,%d,%d)\r\n", - mi->mode_attr, mi->h_res, mi->v_res, mi->bpp, mi->memory_layout, - mi->rpos, mi->gpos, mi->bpos); - - /* Must be an LFB color graphics mode supported by the hardware. - - The bits tested are: - 4 - graphics mode - 3 - color mode - 1 - mode information available (mandatory in VBE 1.2+) - 0 - mode supported by hardware - */ - if ((mi->mode_attr & 0x001b) != 0x001b) - continue; - - /* Must be the chosen size */ - if (mi->h_res != x || mi->v_res != y) - continue; - - /* We don't support multibank (interlaced memory) modes */ - /* - * Note: The Bochs VESA BIOS (vbe.c 1.58 2006/08/19) violates the - * specification which states that banks == 1 for unbanked modes; - * fortunately it does report bank_size == 0 for those. - */ - if (mi->banks > 1 && mi->bank_size) { - debug("bad: banks = %d, banksize = %d, pages = %d\r\n", - mi->banks, mi->bank_size, mi->image_pages); - continue; - } - - /* Must be either a flat-framebuffer mode, or be an acceptable - paged mode */ - if (!(mi->mode_attr & 0x0080) && !vesacon_paged_mode_ok(mi)) { - debug("bad: invalid paged mode\r\n"); - continue; - } - - /* Must either be a packed-pixel mode or a direct color mode - (depending on VESA version ); must be a supported pixel format */ - pxf = PXF_NONE; /* Not usable */ - - if (mi->bpp == 32 && - (mi->memory_layout == 4 || - (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 && - mi->bpos == 0))) - pxf = PXF_BGRA32; - else if (mi->bpp == 24 && - (mi->memory_layout == 4 || - (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 && - mi->bpos == 0))) - pxf = PXF_BGR24; - else if (mi->bpp == 16 && - (mi->memory_layout == 4 || - (mi->memory_layout == 6 && mi->rpos == 11 && mi->gpos == 5 && - mi->bpos == 0))) - pxf = PXF_LE_RGB16_565; - else if (mi->bpp == 15 && - (mi->memory_layout == 4 || - (mi->memory_layout == 6 && mi->rpos == 10 && mi->gpos == 5 && - mi->bpos == 0))) - pxf = PXF_LE_RGB15_555; - - if (pxf < bestpxf) { - debug("Best mode so far, pxf = %d\r\n", pxf); - - /* Best mode so far... */ - bestmode = mode; - bestpxf = pxf; - - /* Copy mode info */ - memcpy(&__vesa_info.mi, mi, sizeof *mi); - } - } - - if (bestpxf == PXF_NONE) { - err = 4; /* No mode found */ - goto exit; - } + rv = firmware->vesa->set_mode(&__vesa_info, x, y, &bestpxf); + if (rv) + return rv; mi = &__vesa_info.mi; - mode = bestmode; __vesacon_bytes_per_pixel = (mi->bpp + 7) >> 3; __vesacon_format_pixels = __vesacon_format_pixels_list[bestpxf]; - /* Download the SYSLINUX- or BIOS-provided font */ + /* Download the SYSLINUX- or firmware-provided font */ __vesacon_font_height = syslinux_font_query(&rom_font); - if (!__vesacon_font_height) { - /* Get BIOS 8x16 font */ - - rm.eax.w[0] = 0x1130; /* Get Font Information */ - rm.ebx.w[0] = 0x0600; /* Get 8x16 ROM font */ - __intcall(0x10, &rm, &rm); - rom_font = MK_PTR(rm.es, rm.ebp.w[0]); - __vesacon_font_height = 16; - } + if (!__vesacon_font_height) + __vesacon_font_height = firmware->vesa->font_query(&rom_font); + unpack_font((uint8_t *) __vesacon_graphics_font, rom_font, __vesacon_font_height); - /* Now set video mode */ - rm.eax.w[0] = 0x4F02; /* Set SVGA video mode */ - if (mi->mode_attr & 0x0080) - mode |= 0x4000; /* Request linear framebuffer if supported */ - rm.ebx.w[0] = mode; - __intcall(0x10, &rm, &rm); - if (rm.eax.w[0] != 0x004F) { - err = 9; /* Failed to set mode */ - goto exit; - } - __vesacon_background = calloc(mi->h_res*mi->v_res, 4); __vesacon_shadowfb = calloc(mi->h_res*mi->v_res, 4); @@ -295,13 +120,17 @@ static int vesacon_set_mode(int x, int y) __vesacon_pixel_format = bestpxf; -exit: - if (vi) - lfree(vi); - - return err; + return 0; } +/* FIXME: + * Does init_text_display need an EFI counterpart? + * e.g. vesa_char may need to setup UNICODE char for EFI + * and the number of screen chars may need to be sized up + * accordingly. This may also require turning byte strings + * into unicode strings in the framebuffer + * Possibly, revisit vesacon_fill() for EFI. + */ static int init_text_display(void) { size_t nchars; @@ -329,7 +158,12 @@ static int init_text_display(void) return 0; } -int __vesacon_init(int x, int y) +/* + * On input, VESA initialization is passed a desirable resolution. On + * return, either the requested resolution is set or the system + * supported default resolution is set and returned to the caller. + */ +int __vesacon_init(int *x, int *y) { int rv; @@ -340,7 +174,7 @@ int __vesacon_init(int x, int y) rv = vesacon_set_mode(x, y); if (rv) { /* Try to see if we can just patch the BIOS... */ - if (__vesacon_i915resolution(x, y)) + if (__vesacon_i915resolution(*x, *y)) return rv; if (vesacon_set_mode(x, y)) return rv; diff --git a/com32/lib/sys/vesa/screencpy.c b/com32/lib/sys/vesa/screencpy.c index 32dce9e6..5c6d9151 100644 --- a/com32/lib/sys/vesa/screencpy.c +++ b/com32/lib/sys/vesa/screencpy.c @@ -34,13 +34,8 @@ #include "vesa.h" #include "video.h" -static struct win_info { - char *win_base; - size_t win_pos; - size_t win_size; - int win_gshift; - int win_num; -} wi; + +static struct win_info wi; void __vesacon_init_copy_to_screen(void) { @@ -71,47 +66,12 @@ void __vesacon_init_copy_to_screen(void) } } -static void set_window_pos(size_t win_pos) -{ - static com32sys_t ireg; - - wi.win_pos = win_pos; - - if (wi.win_num < 0) - return; /* This should never happen... */ - - ireg.eax.w[0] = 0x4F05; - ireg.ebx.b[0] = wi.win_num; - ireg.edx.w[0] = win_pos >> wi.win_gshift; - - __intcall(0x10, &ireg, NULL); -} - void __vesacon_copy_to_screen(size_t dst, const uint32_t * src, size_t npixels) { - size_t win_pos, win_off; - size_t win_size = wi.win_size; - size_t omask = win_size - 1; - char *win_base = wi.win_base; - size_t l; size_t bytes = npixels * __vesacon_bytes_per_pixel; char rowbuf[bytes + 4] __aligned(4); const char *s; s = (const char *)__vesacon_format_pixels(rowbuf, src, npixels); - - while (bytes) { - win_off = dst & omask; - win_pos = dst & ~omask; - - if (__unlikely(win_pos != wi.win_pos)) - set_window_pos(win_pos); - - l = min(bytes, win_size - win_off); - memcpy(win_base + win_off, s, l); - - bytes -= l; - s += l; - dst += l; - } + firmware->vesa->screencpy(dst, s, bytes, &wi); } diff --git a/com32/lib/sys/vesa/vesa.h b/com32/lib/sys/vesa/vesa.h index 3926c329..7a3d87ae 100644 --- a/com32/lib/sys/vesa/vesa.h +++ b/com32/lib/sys/vesa/vesa.h @@ -28,6 +28,7 @@ #ifndef LIB_SYS_VESA_H #define LIB_SYS_VESA_H +#include <syslinux/firmware.h> #include <inttypes.h> #include <com32.h> diff --git a/com32/lib/sys/vesa/video.h b/com32/lib/sys/vesa/video.h index d14494b1..f57e34f9 100644 --- a/com32/lib/sys/vesa/video.h +++ b/com32/lib/sys/vesa/video.h @@ -51,6 +51,14 @@ struct vesa_char { attr_t attr; /* Color table index */ }; +struct win_info { + char *win_base; + size_t win_pos; + size_t win_size; + int win_gshift; + int win_num; +}; + /* Pixel formats in order of decreasing preference; PXF_NONE should be last */ /* BGR24 is preferred over BGRA32 since the I/O overhead is smaller. */ enum vesa_pixel_format { @@ -81,7 +89,7 @@ extern const uint8_t __vesacon_linear_to_srgb[4080]; int __vesacon_init_background(void); int vesacon_load_background(const char *); -int __vesacon_init(int, int); +int __vesacon_init(int *, int *); void __vesacon_init_cursor(int); void __vesacon_erase(int, int, int, int, attr_t); void __vesacon_scroll_up(int, attr_t); diff --git a/com32/lib/sys/vesacon_write.c b/com32/lib/sys/vesacon_write.c index 37693177..823a66af 100644 --- a/com32/lib/sys/vesacon_write.c +++ b/com32/lib/sys/vesacon_write.c @@ -98,7 +98,8 @@ int __vesacon_open(struct file_info *fp) ti.cols = 80; } else { /* Switch mode */ - if (__vesacon_init(vesacon_resolution.x, vesacon_resolution.y)) { + /* Deal with a resolution different from default build */ + if (__vesacon_init(&vesacon_resolution.x, &vesacon_resolution.y)) { vesacon_counter = -1; return EAGAIN; } diff --git a/com32/lib/sys/x86_64/x86_init_fpu.c b/com32/lib/sys/x86_64/x86_init_fpu.c new file mode 100644 index 00000000..c5d3946c --- /dev/null +++ b/com32/lib/sys/x86_64/x86_init_fpu.c @@ -0,0 +1,58 @@ +/* + * x86_has_fpu.c + * + * Test for an x86 FPU, and do any necessary setup. + */ + +#include <inttypes.h> +#include <sys/fpu.h> + +static inline uint64_t get_cr0(void) +{ + uint64_t v; +asm("movq %%cr0,%0":"=r"(v)); + return v; +} + +static inline void set_cr0(uint32_t v) +{ + asm volatile ("movq %0,%%cr0"::"r" ((uint64_t)v)); +} + +#define CR0_PE 0x00000001 +#define CR0_MP 0x00000002 +#define CR0_EM 0x00000004 +#define CR0_TS 0x00000008 +#define CR0_ET 0x00000010 +#define CR0_NE 0x00000020 +#define CR0_WP 0x00010000 +#define CR0_AM 0x00040000 +#define CR0_NW 0x20000000 +#define CR0_CD 0x40000000 +#define CR0_PG 0x80000000 + +int x86_init_fpu(void) +{ + uint32_t cr0; + uint16_t fsw = 0xffff; + uint16_t fcw = 0xffff; + + cr0 = get_cr0(); + cr0 &= ~(CR0_EM | CR0_TS); + cr0 |= CR0_MP; + set_cr0(cr0); + + asm volatile ("fninit"); + asm volatile ("fnstsw %0":"+m" (fsw)); + if (fsw != 0) + return -1; + + asm volatile ("fnstcw %0":"+m" (fcw)); + if ((fcw & 0x103f) != 0x3f) + return -1; + + /* Techically, this could be a 386 with a 287. We could add a check + for that here... */ + + return 0; +} diff --git a/com32/lib/sys/x86_init_fpu.c b/com32/lib/sys/x86_init_fpu.c index cf336932..cacb4ea3 100644 --- a/com32/lib/sys/x86_init_fpu.c +++ b/com32/lib/sys/x86_init_fpu.c @@ -4,19 +4,40 @@ * Test for an x86 FPU, and do any necessary setup. */ +#if __SIZEOF_POINTER__ == 4 +#include <i386/x86_init_fpu.c> +#elif __SIZEOF_POINTER__ == 8 +#include <x86_64/x86_init_fpu.c> +#else +#error "Unable to build for to-be-defined architecture type" +#endif +#if 0 #include <inttypes.h> #include <sys/fpu.h> static inline uint64_t get_cr0(void) { +#if __SIZEOF_POINTER__ == 4 uint32_t v; asm("movl %%cr0,%0":"=r"(v)); +#elif __SIZEOF_POINTER__ == 8 + uint64_t v; +asm("movq %%cr0,%0":"=r"(v)); +#else +#error "Unable to build for to-be-defined architecture type" +#endif return v; } static inline void set_cr0(uint32_t v) { +#if __SIZEOF_POINTER__ == 4 asm volatile ("movl %0,%%cr0"::"r" (v)); +#elif __SIZEOF_POINTER__ == 8 + asm volatile ("movq %0,%%cr0"::"r" ((uint64_t)v)); +#else +#error "Unable to build for to-be-defined architecture type" +#endif } #define CR0_PE 0x00000001 @@ -56,3 +77,4 @@ int x86_init_fpu(void) return 0; } +#endif diff --git a/com32/lib/syslinux/cleanup.c b/com32/lib/syslinux/cleanup.c index 066f174f..7d8581e4 100644 --- a/com32/lib/syslinux/cleanup.c +++ b/com32/lib/syslinux/cleanup.c @@ -29,8 +29,6 @@ #include <syslinux/config.h> #include <syslinux/pxe_api.h> #include <stddef.h> -#include <bios.h> -#include <com32.h> #include <core.h> void syslinux_final_cleanup(uint16_t flags) diff --git a/com32/lib/syslinux/dsinfo.c b/com32/lib/syslinux/dsinfo.c index c1f02a59..f7126bfe 100644 --- a/com32/lib/syslinux/dsinfo.c +++ b/com32/lib/syslinux/dsinfo.c @@ -34,12 +34,5 @@ union syslinux_derivative_info __syslinux_derivative_info; void __constructor __syslinux_get_derivative_info(void) { - com32sys_t *const r = &__syslinux_derivative_info.rr.r; - - r->eax.w[0] = 0x000A; - __intcall(0x22, r, r); - - __syslinux_derivative_info.r.esbx = MK_PTR(r->es, r->ebx.w[0]); - __syslinux_derivative_info.r.fssi = MK_PTR(r->fs, r->esi.w[0]); - __syslinux_derivative_info.r.gsdi = MK_PTR(r->gs, r->edi.w[0]); + get_derivative_info(&__syslinux_derivative_info); } diff --git a/com32/lib/syslinux/load_linux.c b/com32/lib/syslinux/load_linux.c index c0335dc9..4a8a1fd3 100644 --- a/com32/lib/syslinux/load_linux.c +++ b/com32/lib/syslinux/load_linux.c @@ -47,48 +47,7 @@ #include <syslinux/linux.h> #include <syslinux/bootrm.h> #include <syslinux/movebits.h> - -struct linux_header { - uint8_t boot_sector_1[0x0020]; - uint16_t old_cmd_line_magic; - uint16_t old_cmd_line_offset; - uint8_t boot_sector_2[0x01f1 - 0x0024]; - uint8_t setup_sects; - uint16_t root_flags; - uint32_t syssize; - uint16_t ram_size; - uint16_t vid_mode; - uint16_t root_dev; - uint16_t boot_flag; - uint16_t jump; - uint32_t header; - uint16_t version; - uint32_t realmode_swtch; - uint16_t start_sys; - uint16_t kernel_version; - uint8_t type_of_loader; - uint8_t loadflags; - uint16_t setup_move_size; - uint32_t code32_start; - uint32_t ramdisk_image; - uint32_t ramdisk_size; - uint32_t bootsect_kludge; - uint16_t heap_end_ptr; - uint16_t pad1; - uint32_t cmd_line_ptr; - uint32_t initrd_addr_max; - uint32_t kernel_alignment; - uint8_t relocatable_kernel; - uint8_t pad2[3]; - uint32_t cmdline_max_len; - uint32_t hardware_subarch; - uint64_t hardware_subarch_data; - uint32_t payload_offset; - uint32_t payload_length; - uint64_t setup_data; - uint64_t pref_address; - uint32_t init_size; -} __packed; +#include <syslinux/firmware.h> #define BOOT_MAGIC 0xAA55 #define LINUX_MAGIC ('H' + ('d' << 8) + ('r' << 16) + ('S' << 24)) @@ -130,23 +89,6 @@ static inline uint32_t saturate32(unsigned long long v) return (v > 0xffffffff) ? 0xffffffff : (uint32_t) v; } -/* Get the combined size of the initramfs */ -static addr_t initramfs_size(struct initramfs *initramfs) -{ - struct initramfs *ip; - addr_t size = 0; - - if (!initramfs) - return 0; - - for (ip = initramfs->next; ip->len; ip = ip->next) { - size = (size + ip->align - 1) & ~(ip->align - 1); /* Alignment */ - size += ip->len; - } - - return size; -} - /* Create the appropriate mappings for the initramfs */ static int map_initramfs(struct syslinux_movelist **fraglist, struct syslinux_memmap **mmap, @@ -182,10 +124,10 @@ static int map_initramfs(struct syslinux_movelist **fraglist, return 0; } -int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, - struct initramfs *initramfs, - struct setup_data *setup_data, - char *cmdline) +int bios_boot_linux(void *kernel_buf, size_t kernel_size, + struct initramfs *initramfs, + struct setup_data *setup_data, + char *cmdline) { struct linux_header hdr, *whdr; size_t real_mode_size, prot_mode_size; @@ -534,3 +476,17 @@ bail: syslinux_free_memmap(amap); return -1; } + +int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, + struct initramfs *initramfs, + struct setup_data *setup_data, + char *cmdline) +{ + if (!firmware->boot_linux) { + printf("No linux boot function registered for firmware\n"); + return -1; + } + + firmware->boot_linux(kernel_buf, kernel_size, initramfs, + setup_data, cmdline); +} diff --git a/com32/lib/syslinux/memscan.c b/com32/lib/syslinux/memscan.c index fc676cbf..0ff25d7f 100644 --- a/com32/lib/syslinux/memscan.c +++ b/com32/lib/syslinux/memscan.c @@ -40,6 +40,7 @@ #include <com32.h> #include <syslinux/memscan.h> +#include <syslinux/firmware.h> struct e820_entry { uint64_t start; @@ -47,7 +48,7 @@ struct e820_entry { uint32_t type; }; -int syslinux_scan_memory(scan_memory_callback_t callback, void *data) +int bios_scan_memory(scan_memory_callback_t callback, void *data) { static com32sys_t ireg; com32sys_t oreg; @@ -156,3 +157,8 @@ int syslinux_scan_memory(scan_memory_callback_t callback, void *data) return 0; } + +int syslinux_scan_memory(scan_memory_callback_t callback, void *data) +{ + return firmware->mem->scan_memory(callback, data); +} diff --git a/com32/lib/syslinux/serial.c b/com32/lib/syslinux/serial.c index bb92222f..bc41acfc 100644 --- a/com32/lib/syslinux/serial.c +++ b/com32/lib/syslinux/serial.c @@ -32,24 +32,19 @@ */ #include <klibc/compiler.h> +#include <syslinux/firmware.h> #include <syslinux/config.h> #include <string.h> -#include <bios.h> -#include <core.h> struct syslinux_serial_console_info __syslinux_serial_console_info; void __constructor __syslinux_get_serial_console_info(void) { - uint16_t flowctl; + uint16_t iobase, divisor, flowctl; - __syslinux_serial_console_info.iobase = SerialPort; - __syslinux_serial_console_info.divisor = BaudDivisor; - - flowctl = FlowOutput | FlowInput | (FlowIgnore << 4); - - if (!DisplayCon) - flowctl |= (0x80 << 8); + firmware->get_serial_console_info(&iobase, &divisor, &flowctl); + __syslinux_serial_console_info.iobase = iobase; + __syslinux_serial_console_info.divisor = divisor; __syslinux_serial_console_info.flowctl = flowctl; } diff --git a/com32/lib/syslinux/shuffle.c b/com32/lib/syslinux/shuffle.c index 544915a3..d014340c 100644 --- a/com32/lib/syslinux/shuffle.c +++ b/com32/lib/syslinux/shuffle.c @@ -50,10 +50,12 @@ struct shuffle_descriptor { static int shuffler_size; -static void __constructor __syslinux_get_shuffer_size(void) +static void __syslinux_get_shuffer_size(void) { - /* +15 padding is to guarantee alignment */ - shuffler_size = __bcopyxx_len + 15; + if (!shuffler_size) { + /* +15 padding is to guarantee alignment */ + shuffler_size = __bcopyxx_len + 15; + } } /* @@ -114,6 +116,7 @@ int syslinux_do_shuffle(struct syslinux_movelist *fraglist, if (!rxmap) goto bail; + __syslinux_get_shuffer_size(); desc_blocks = (nzero + DESC_BLOCK_SIZE - 1) / DESC_BLOCK_SIZE; for (;;) { /* We want (desc_blocks) allocation blocks, plus the terminating diff --git a/com32/lib/syslinux/version.c b/com32/lib/syslinux/version.c index 1cd2efd3..6f0554d5 100644 --- a/com32/lib/syslinux/version.c +++ b/com32/lib/syslinux/version.c @@ -28,7 +28,7 @@ #include <syslinux/config.h> #include <klibc/compiler.h> #include <core.h> -#include <../../../version.h> +#include <version.h> struct syslinux_version __syslinux_version; diff --git a/com32/lib/x86_64/elf.ld b/com32/lib/x86_64/elf.ld new file mode 100644 index 00000000..4e88bcb0 --- /dev/null +++ b/com32/lib/x86_64/elf.ld @@ -0,0 +1,180 @@ +/* + * Linker script for ELF dynamic loaded modules. + * This simply mirrors the 32bit linker script with minimal x86_64 changes + */ + +/* Script for --shared -z combreloc: shared library, combine & sort relocs */ +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0 + SIZEOF_HEADERS; + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } +/* mouli: introduce alignment for various segments */ + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } + .rel.plt : { *(.rel.plt); } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0x90909090 + .plt : { *(.plt) } + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0x90909090 + .fini : + { + KEEP (*(.fini)) + } =0x90909090 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + . = ALIGN(4); + .preinit_array : + { + KEEP (*(.preinit_array)) + } + .init_array : + { + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + } + .fini_array : + { + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + } + + .ctors : + { + __ctors_start = .; + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*(.ctors_modinit)) + KEEP (*(.ctors_modmain)) + __ctors_end = .; + } + + .dtors : + { + __dtors_start = .; + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + KEEP (*(.dtors_modexit)) + __dtors_end = .; + } + + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got) } + /*. = DATA_SEGMENT_RELRO_END (12, .); -> This gives a "invalid assignment to location counter" error */ + .got.plt : { *(.got.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + PROVIDE (edata = .); + PROVIDE (_edata = .); + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + /*. = ALIGN(. != 0 ? 32 / 8 : 1);*/ + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + PROVIDE (_end = .); + PROVIDE (end = .); + /*. = DATA_SEGMENT_END (.); -> This gives a "invalid assignment to location counter" error */ + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.eh_frame) } +} diff --git a/com32/lib/x86_64/setjmp.S b/com32/lib/x86_64/setjmp.S new file mode 100644 index 00000000..45f547b4 --- /dev/null +++ b/com32/lib/x86_64/setjmp.S @@ -0,0 +1,54 @@ +# +# arch/x86_64/setjmp.S +# +# setjmp/longjmp for the x86-64 architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# %rbx +# %rsp (post-return) +# %rbp +# %r12 +# %r13 +# %r14 +# %r15 +# <return address> +# + + .text + .align 4 + .globl setjmp + .type setjmp, @function +setjmp: + pop %rsi # Return address, and adjust the stack + xorl %eax,%eax # Return value + movq %rbx,(%rdi) + movq %rsp,8(%rdi) # Post-return %rsp! + push %rsi # Make the call/return stack happy + movq %rbp,16(%rdi) + movq %r12,24(%rdi) + movq %r13,32(%rdi) + movq %r14,40(%rdi) + movq %r15,48(%rdi) + movq %rsi,56(%rdi) # Return address + ret + + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: + movl %esi,%eax # Return value (int) + movq (%rdi),%rbx + movq 8(%rdi),%rsp + movq 16(%rdi),%rbp + movq 24(%rdi),%r12 + movq 32(%rdi),%r13 + movq 40(%rdi),%r14 + movq 48(%rdi),%r15 + jmp *56(%rdi) + + .size longjmp,.-longjmp diff --git a/com32/libupload/Makefile b/com32/libupload/Makefile index 83053350..f9440c57 100644 --- a/com32/libupload/Makefile +++ b/com32/libupload/Makefile @@ -1,12 +1,10 @@ # Include configuration rules -topdir = ../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/com32.mk -REQFLAGS += -I./ +REQFLAGS += -I$(SRC) -SUBDIRS := . -LIBOBJS := $(foreach dir,$(SUBDIRS),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c))) +LIBOBJS := $(notdir $(patsubst %.c,%.o,$(wildcard $(SRC)/*.c))) BINDIR = /usr/bin LIBDIR = /usr/lib @@ -34,6 +32,6 @@ install: all mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR) install -m 644 libcom32upload.a $(INSTALLROOT)$(COM32DIR) mkdir -p $(INSTALLROOT)$(COM32DIR)/include/ - cp -r *.h $(INSTALLROOT)$(COM32DIR)/include/ + cp -r $(SRC)/*.h $(INSTALLROOT)$(COM32DIR)/include/ -include .*.d */.*.d */*/.*.d diff --git a/com32/libutil/Makefile b/com32/libutil/Makefile index 93c0c11c..535b4aba 100644 --- a/com32/libutil/Makefile +++ b/com32/libutil/Makefile @@ -29,8 +29,7 @@ ## Utility companion library for the COM32 library ## -topdir = ../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/elf.mk LIBOBJS = ansiline.o ansiraw.o keyname.o \ diff --git a/com32/lua/src/Makefile b/com32/lua/src/Makefile index 01d1f81c..70a7e808 100644 --- a/com32/lua/src/Makefile +++ b/com32/lua/src/Makefile @@ -15,8 +15,7 @@ ## Lua Makefile ## -topdir = ../../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/elf.mk LNXLIBS = diff --git a/com32/mboot/Makefile b/com32/mboot/Makefile index 02e9f49e..a3f61ba8 100644 --- a/com32/mboot/Makefile +++ b/com32/mboot/Makefile @@ -15,11 +15,10 @@ ## Multiboot module ## -topdir = ../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/elf.mk -LNXLIBS = ../libutil/libutil_lnx.a +LNXLIBS = $(objdir)/com32/libutil/libutil_lnx.a MODULES = mboot.c32 TESTFILES = diff --git a/com32/menu/Makefile b/com32/menu/Makefile index b7719456..9f7a0e46 100644 --- a/com32/menu/Makefile +++ b/com32/menu/Makefile @@ -14,24 +14,23 @@ ## Simple menu system ## -topdir = ../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/elf.mk -LNXLIBS = ../libutil/libutil_lnx.a +LNXLIBS = $(objdir)/com32/libutil/libutil_lnx.a MODULES = menu.c32 vesamenu.c32 TESTFILES = -COMMONOBJS = menumain.o readconfig.o passwd.o drain.o printmsg.o colors.o \ - background.o refstr.o +COMMONOBJS = menumain.o readconfig.o passwd.o drain.o \ + printmsg.o colors.o background.o refstr.o all: $(MODULES) $(TESTFILES) -menu.c32 : menu.o $(COMMONOBJS) $(C_LIBS) +vesamenu.c32: vesamenu.o $(COMMONOBJS) $(C_LIBS) $(LD) $(LDFLAGS) -o $@ $^ -vesamenu.c32 : vesamenu.o $(COMMONOBJS) $(C_LIBS) +menu.c32: menu.o $(COMMONOBJS) $(C_LIBS) $(LD) $(LDFLAGS) -o $@ $^ tidy dist: diff --git a/com32/modules/Makefile b/com32/modules/Makefile index 9cf4da8e..e794b3b9 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -15,8 +15,7 @@ ## COM32 standard modules ## -topdir = ../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/elf.mk MODULES = config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \ diff --git a/com32/modules/ls.c b/com32/modules/ls.c index 11c18ae0..47eacdbc 100644 --- a/com32/modules/ls.c +++ b/com32/modules/ls.c @@ -172,4 +172,4 @@ int main(int argc, char *argv[]) return rv ? 1 : 0; } - + diff --git a/com32/modules/zzjson.c b/com32/modules/zzjson.c index e2516fa1..a126b8f0 100644 --- a/com32/modules/zzjson.c +++ b/com32/modules/zzjson.c @@ -21,7 +21,13 @@ static void myerror(void *ehandle, const char *format, ...) { int main(int argc, char *argv[]) { +#if 0 + /* this hangs! */ openconsole(&dev_rawcon_r, &dev_stdcon_w); +#else + /* this works */ + openconsole(&dev_rawcon_r, &dev_ansiserial_w); +#endif (void) argc; (void) argv; ZZJSON *tmp; diff --git a/com32/rosh/Makefile b/com32/rosh/Makefile index a894c847..a4c0bc28 100644 --- a/com32/rosh/Makefile +++ b/com32/rosh/Makefile @@ -16,10 +16,10 @@ ## ROSH Read Only Shell ## -LIBS = $(com32)/libutil/libutil_com.c32 $(com32)/lib/libcom32.c32 +LIBS = $(objdir)/com32/libutil/libutil_com.c32 \ + $(objdir)/com32/lib/libcom32.c32 -topdir = ../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/rosh.mk # from com32/sysdump/Makefile @@ -36,12 +36,12 @@ endif CFLAGS += -DDATE='"$(DATE)"' LNXCFLAGS += -DDATE='"$(DATE)"' +all: rosh.c32 + rosh.o: rosh.h rosh.lo: rosh.h -all: rosh.c32 - allgrc: rosh.c32 rosh.lnx tidy dist: diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c index 68dad3f3..8198a2ba 100644 --- a/com32/rosh/rosh.c +++ b/com32/rosh/rosh.c @@ -37,7 +37,7 @@ * debugging enabled; Comment to remove. */ #include "rosh.h" -#include "../../version.h" +#include "version.h" #define APP_LONGNAME "Read-Only Shell" #define APP_NAME "rosh" diff --git a/com32/samples/Makefile b/com32/samples/Makefile index c7abaddb..ca04f644 100644 --- a/com32/samples/Makefile +++ b/com32/samples/Makefile @@ -14,17 +14,16 @@ ## samples for syslinux users ## -LIBS = $(com32)/libutil/libutil_com.c32 +LIBS = $(objdir)/com32/libutil/libutil_com.c32 -topdir = ../.. -MAKEDIR = $(topdir)/mk +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 + localboot.c32 \ + fancyhello.c32 fancyhello.lnx \ + keytest.c32 keytest.lnx \ + advdump.c32 entrydump.c32 tidy dist: rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp diff --git a/com32/samples/advdump.c b/com32/samples/advdump.c index 2c786416..83fe8381 100644 --- a/com32/samples/advdump.c +++ b/com32/samples/advdump.c @@ -27,7 +27,13 @@ int main(void) size_t s = syslinux_adv_size(); char buf[256]; +#if 0 + /* this hangs! */ openconsole(&dev_stdcon_r, &dev_stdcon_w); +#else + /* this works */ + openconsole(&dev_rawcon_r, &dev_ansiserial_w); +#endif p = syslinux_adv_ptr(); diff --git a/com32/samples/entrydump.c b/com32/samples/entrydump.c index d50859f4..56a683e3 100644 --- a/com32/samples/entrydump.c +++ b/com32/samples/entrydump.c @@ -36,7 +36,13 @@ int main(void) const union syslinux_derivative_info *di; const struct stack_frame *sf; +#if 0 + /* this hangs! */ openconsole(&dev_null_r, &dev_stdcon_w); +#else + /* this works */ + openconsole(&dev_rawcon_r, &dev_ansiserial_w); +#endif di = syslinux_derivative_info(); diff --git a/com32/samples/resolv.c b/com32/samples/resolv.c index f4a0e52a..8f062d19 100644 --- a/com32/samples/resolv.c +++ b/com32/samples/resolv.c @@ -32,7 +32,13 @@ int main(int argc, char *argv[]) { uint32_t ip; +#if 0 + /* this hangs! */ openconsole(&dev_null_r, &dev_stdcon_w); +#else + /* this works */ + openconsole(&dev_rawcon_r, &dev_ansiserial_w); +#endif if (argc < 2) { fputs("Usage: resolv hostname\n", stderr); diff --git a/com32/samples/serialinfo.c b/com32/samples/serialinfo.c index 10d02521..2936b4e5 100644 --- a/com32/samples/serialinfo.c +++ b/com32/samples/serialinfo.c @@ -25,7 +25,13 @@ int main(void) { const struct syslinux_serial_console_info *si; +#if 0 + /* this hangs! */ openconsole(&dev_null_r, &dev_stdcon_w); +#else + /* this works */ + openconsole(&dev_rawcon_r, &dev_ansiserial_w); +#endif si = syslinux_serial_console_info(); diff --git a/com32/sysdump/Makefile b/com32/sysdump/Makefile index 8763b3c8..dca5d717 100644 --- a/com32/sysdump/Makefile +++ b/com32/sysdump/Makefile @@ -15,21 +15,20 @@ ## Simple menu system ## -topdir = ../.. -MAKEDIR = $(topdir)/mk +VPATH = $(SRC) include $(MAKEDIR)/elf.mk -include $(topdir)/version.mk -LIBS = ../libupload/libcom32upload.a -LNXLIBS = ../libutil/libutil_lnx.a +LIBS = $(objdir)/com32/libupload/libcom32upload.a +LNXLIBS = $(objdir)/com32/libutil/libutil_lnx.a CFLAGS += -I$(com32) -I$(topdir) MODULES = sysdump.c32 TESTFILES = -SRCS = $(wildcard *.c) -OBJS = $(patsubst %.c,%.o,$(SRCS)) +SRCS = $(wildcard $(SRC)/*.c) +OBJS = $(subst $(SRC)/,,$(patsubst %.c,%.o,$(SRCS))) # The DATE is set on the make command line when building binaries for # official release. Otherwise, substitute a hex string that is pretty much diff --git a/com32/sysdump/cpuid.c b/com32/sysdump/cpuid.c index e7fc5767..846b5408 100644 --- a/com32/sysdump/cpuid.c +++ b/com32/sysdump/cpuid.c @@ -20,10 +20,21 @@ struct cpuid_info { static void get_cpuid(uint32_t eax, uint32_t ecx, struct cpuid_data *data) { +#if __SIZEOF_POINTER__ == 4 asm("pushl %%ebx ; cpuid ; movl %%ebx,%1 ; popl %%ebx" : "=a" (data->eax), "=r" (data->ebx), "=c" (data->ecx), "=d" (data->edx) : "a" (eax), "c" (ecx)); +#elif __SIZEOF_POINTER__ == 8 + asm volatile("push %%rbx; cpuid; movl %%ebx, %1; pop %%rbx" + : "=a" (data->eax), + "=b" (data->ebx), + "=c" (data->ecx), + "=d" (data->edx) + : "a" (eax), "c" (ecx)); +#else +#error "unsupported architecture" +#endif } #define CPUID_CHUNK 128 diff --git a/com32/tools/Makefile b/com32/tools/Makefile index 0161baf1..9c0ea708 100644 --- a/com32/tools/Makefile +++ b/com32/tools/Makefile @@ -10,12 +10,12 @@ ## ## ----------------------------------------------------------------------- -MAKEDIR = ../../mk +VPATH = $(SRC) include $(MAKEDIR)/build.mk BINS = relocs -INCLUDES += -I./include +INCLUDES += -I$(SRC)/include all : $(BINS) |