aboutsummaryrefslogtreecommitdiffstats
path: root/com32
diff options
context:
space:
mode:
Diffstat (limited to 'com32')
-rw-r--r--com32/MCONFIG35
-rw-r--r--com32/Makefile2
-rw-r--r--com32/include/com32.h13
-rw-r--r--com32/include/dev.h1
-rw-r--r--com32/include/dirent.h18
-rw-r--r--com32/include/netinet/in.h48
-rw-r--r--com32/include/string.h1
-rw-r--r--com32/include/sys/cpu.h26
-rw-r--r--com32/include/sys/dirent.h45
-rw-r--r--com32/include/syslinux/boot.h2
-rw-r--r--com32/include/syslinux/idle.h1
-rw-r--r--com32/include/syslinux/pmapi.h70
-rw-r--r--com32/include/syslinux/pxe.h485
-rw-r--r--com32/include/syslinux/pxe_api.h571
-rw-r--r--com32/lib/MCONFIG17
-rw-r--r--com32/lib/Makefile35
-rw-r--r--com32/lib/closedir.c30
-rw-r--r--com32/lib/com32.ld68
-rw-r--r--com32/lib/fprintf.c2
-rw-r--r--com32/lib/lmalloc.c57
-rw-r--r--com32/lib/lstrdup.c18
-rw-r--r--com32/lib/memmove.S31
-rw-r--r--com32/lib/opendir.c41
-rw-r--r--com32/lib/printf.c2
-rw-r--r--com32/lib/qsort.c4
-rw-r--r--com32/lib/readdir.c57
-rw-r--r--com32/lib/strpcpy.c20
-rw-r--r--com32/lib/sys/entry.S60
-rw-r--r--com32/lib/sys/file.h18
-rw-r--r--com32/lib/sys/fileclose.c11
-rw-r--r--com32/lib/sys/fileread.c51
-rw-r--r--com32/lib/sys/fstat.c4
-rw-r--r--com32/lib/sys/gpxe.c25
-rw-r--r--com32/lib/sys/open.c28
-rw-r--r--com32/lib/sys/openmem.c61
-rw-r--r--com32/lib/sys/readdir.c30
-rw-r--r--com32/lib/sys/stdcon_write.c19
-rw-r--r--com32/lib/sys/vesa/initvesa.c52
-rw-r--r--com32/lib/sys/zfile.c8
-rw-r--r--com32/lib/syslinux/idle.c24
-rw-r--r--com32/lib/syslinux/memscan.c9
-rw-r--r--com32/lib/syslinux/pxe_dns.c13
-rw-r--r--com32/lib/syslinux/pxe_get_cached.c37
-rw-r--r--com32/lib/syslinux/pxe_get_nic.c14
-rw-r--r--com32/lib/syslinux/run_command.c17
-rw-r--r--com32/lib/syslinux/runimage.c26
-rw-r--r--com32/lib/vdprintf.c77
-rw-r--r--com32/mboot/mboot.c2
-rw-r--r--com32/modules/Makefile4
-rw-r--r--com32/modules/dir.c177
-rw-r--r--com32/modules/host.c42
-rw-r--r--com32/rosh/rosh.c19
-rw-r--r--com32/rosh/rosh.h2
-rw-r--r--com32/sysdump/cpuid.c7
-rw-r--r--com32/sysdump/ctime.c7
-rw-r--r--com32/tools/.gitignore1
-rw-r--r--com32/tools/Makefile30
-rw-r--r--com32/tools/relocs.c693
58 files changed, 2332 insertions, 936 deletions
diff --git a/com32/MCONFIG b/com32/MCONFIG
index 0e152de3..0b774d4f 100644
--- a/com32/MCONFIG
+++ b/com32/MCONFIG
@@ -1,5 +1,5 @@
## -*- makefile -*- -------------------------------------------------------
-##
+##
## Copyright 2008-2009 H. Peter Anvin - All Rights Reserved
## Copyright 2009 Intel Corporation; author: H. Peter Anvin
##
@@ -17,17 +17,25 @@
include $(topdir)/MCONFIG
-GCCOPT := $(call gcc_ok,-std=gnu99,) \
- $(call gcc_ok,-m32,) \
- $(call gcc_ok,-fno-stack-protector,) \
- $(call gcc_ok,-falign-functions=0,-malign-functions=0) \
- $(call gcc_ok,-falign-jumps=0,-malign-jumps=0) \
- $(call gcc_ok,-falign-loops=0,-malign-loops=0) \
- $(call gcc_ok,-mpreferred-stack-boundary=2,) \
- $(call gcc_ok,-mincoming-stack-boundary=2,) \
- -march=i386 -Os -fomit-frame-pointer -mregparm=3 -DREGPARM=3
-
-com32 = $(topdir)/com32
+GCCOPT := $(call gcc_ok,-std=gnu99,)
+GCCOPT += $(call gcc_ok,-m32,)
+GCCOPT += $(call gcc_ok,-fno-stack-protector,)
+GCCOPT += $(call gcc_ok,-fwrapv,)
+GCCOPT += $(call gcc_ok,-freg-struct-return,)
+GCCOPT += -mregparm=3 -DREGPARM=3 -march=i386 -Os
+GCCOPT += $(call gcc_ok,-fPIE,-fPIC)
+GCCOPT += $(call gcc_ok,-fno-exceptions,)
+GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,)
+GCCOPT += $(call gcc_ok,-fno-strict-aliasing,)
+GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0)
+GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0)
+GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0)
+GCCOPT += $(call gcc_ok,-falign-loops=0,-malign-loops=0)
+GCCOPT += $(call gcc_ok,-mpreferred-stack-boundary=2,)
+GCCOPT += $(call gcc_ok,-incoming-stack-boundary=2,)
+
+com32 := $(topdir)/com32
+RELOCS := $(com32)/tools/relocs
ifneq ($(NOGPL),1)
GPLLIB = $(com32)/gpllib/libcom32gpl.a
@@ -47,7 +55,7 @@ SFLAGS = $(GCCOPT) $(GCCWARN) -march=i386 \
-I$(com32)/libutil/include -I$(com32)/include $(GPLINCLUDE)
COM32LD = $(com32)/lib/com32.ld
-LDFLAGS = -m elf_i386 -T $(COM32LD)
+LDFLAGS = -m elf_i386 --emit-relocs -T $(COM32LD)
LIBGCC := $(shell $(CC) $(GCCOPT) --print-libgcc)
LNXCFLAGS = -I$(com32)/libutil/include $(GCCWARN) -O -g -D_GNU_SOURCE
@@ -86,3 +94,4 @@ C_LNXLIBS = $(com32)/libutil/libutil_lnx.a
%.c32: %.elf
$(OBJCOPY) -O binary $< $@
+ $(RELOCS) $< >> $@ || ( rm -f $@ ; false )
diff --git a/com32/Makefile b/com32/Makefile
index 3821e581..4f95017a 100644
--- a/com32/Makefile
+++ b/com32/Makefile
@@ -1,4 +1,4 @@
-SUBDIRS = lib gpllib libutil modules mboot menu samples rosh cmenu \
+SUBDIRS = tools lib gpllib libutil modules mboot menu samples rosh cmenu \
hdt gfxboot sysdump
all tidy dist clean spotless install:
set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done
diff --git a/com32/include/com32.h b/com32/include/com32.h
index 665fa0bf..6b142082 100644
--- a/com32/include/com32.h
+++ b/com32/include/com32.h
@@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 2002-2009 H. Peter Anvin - All Rights Reserved
- * Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2009-2010 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
@@ -92,6 +92,8 @@ typedef struct {
#define EFLAGS_VIP 0x00100000
#define EFLAGS_ID 0x00200000
+struct com32_pmapi;
+
extern struct com32_sys_args {
uint32_t cs_sysargs;
char *cs_cmdline;
@@ -102,6 +104,7 @@ extern struct com32_sys_args {
int __cdecl (*cs_cfarcall)(uint32_t, const void *, uint32_t);
uint32_t cs_memsize;
const char *cs_name;
+ const struct com32_pmapi *cs_pm;
} __com32;
/*
@@ -115,6 +118,14 @@ int __cfarcall(uint16_t __cs, uint16_t __ip,
extern const com32sys_t __com32_zero_regs;
/*
+ * Lowmem allocation functions
+ */
+void *lmalloc(size_t);
+void *lzalloc(size_t);
+void lfree(void *);
+char *lstrdup(const char *);
+
+/*
* These functions convert between linear pointers in the range
* 0..0xFFFFF and real-mode style SEG:OFFS pointers. Note that a
* 32-bit linear pointer is not compatible with a SEG:OFFS pointer
diff --git a/com32/include/dev.h b/com32/include/dev.h
index 7809fb56..70b3165c 100644
--- a/com32/include/dev.h
+++ b/com32/include/dev.h
@@ -41,6 +41,7 @@ struct input_dev;
struct output_dev;
__extern int opendev(const struct input_dev *, const struct output_dev *, int);
+__extern int openmem(const void *, size_t, int);
/* Common generic devices */
diff --git a/com32/include/dirent.h b/com32/include/dirent.h
index d99b21fb..c4aca4f0 100644
--- a/com32/include/dirent.h
+++ b/com32/include/dirent.h
@@ -10,23 +10,7 @@
#include <stddef.h>
#include <sys/types.h>
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-struct dirent {
- long d_ino; /* Inode/File number */
- off_t d_size; /* Size of file */
- mode_t d_mode; /* Type of file */
- char d_name[NAME_MAX + 1];
-};
-
-typedef struct {
- short dd_stat; /* status return from last lookup */
- uint16_t dd_fd;
- size_t dd_sect;
- char dd_name[NAME_MAX + 1]; /* directory */
-} DIR;
+#include <sys/dirent.h>
__extern DIR *opendir(const char *);
__extern struct dirent *readdir(DIR *);
diff --git a/com32/include/netinet/in.h b/com32/include/netinet/in.h
index 051cc08f..ccf04750 100644
--- a/com32/include/netinet/in.h
+++ b/com32/include/netinet/in.h
@@ -4,37 +4,47 @@
/* COM32 will be running on an i386 platform */
#include <stdint.h>
+#include <klibc/compiler.h>
-static inline uint16_t __htons(uint16_t v)
+#define __htons_macro(v) ((uint16_t) \
+ (((uint16_t)(v) << 8) | \
+ ((uint16_t)(v) >> 8)))
+
+static inline __constfunc uint16_t __htons(uint16_t v)
{
- return ((v) << 8) | ((v) >> 8);
+ return __htons_macro(v);
}
-#define htons(x) __htons(x)
-#define ntohs(x) __htons(x)
+#define htons(x) (__builtin_constant_p(x) ? __htons_macro(x) : __htons(x))
+#define ntohs(x) htons(x)
+
+#define __htonl_macro(v) ((uint32_t) \
+ ((((uint32_t)(v) & 0x000000ff) << 24) | \
+ (((uint32_t)(v) & 0x0000ff00) << 8) | \
+ (((uint32_t)(v) & 0x00ff0000) >> 8) | \
+ (((uint32_t)(v) & 0xff000000) >> 24)))
-static inline uint32_t __htonl(uint32_t v)
+static inline __constfunc uint32_t __htonl(uint32_t v)
{
- if (__builtin_constant_p(v)) {
- return (((v) & 0x000000ff) << 24) |
- (((v) & 0x0000ff00) << 8) |
- (((v) & 0x00ff0000) >> 8) | (((v) & 0xff000000) >> 24);
- } else {
-asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0":"+abcd"(v));
- return v;
- }
+ asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0"
+ : "+q" (v));
+ return v;
}
-#define htonl(x) __htonl(x)
-#define ntohl(x) __htonl(x)
+#define htonl(x) (__builtin_constant_p(x) ? __htonl_macro(x) : __htonl(x))
+#define ntohl(x) htonl(x)
+
+#define __htonq_macro(v) ((uint64_t) \
+ (((uint64_t)__htonl_macro((uint32_t)(v)) << 32) | \
+ (__htonl_macro((uint32_t)((uint64_t)(v) >> 32)))))
-static inline uint64_t __htonq(uint64_t v)
+static inline __constfunc uint64_t __htonq(uint64_t v)
{
- return ((uint64_t) __htonl(v) << 32) | __htonl(v >> 32);
+ return ((uint64_t)__htonl(v) << 32) | __htonl(v >> 32);
}
-#define htonq(x) __htonq(x)
-#define ntohq(x) __htonq(x)
+#define htonq(x) (__builtin_constant_p(x) ? __htonq_macro(x) : __htonq(x))
+#define ntohq(x) htonq(x)
typedef uint32_t in_addr_t;
typedef uint16_t in_port_t;
diff --git a/com32/include/string.h b/com32/include/string.h
index c964ee3b..af9792b6 100644
--- a/com32/include/string.h
+++ b/com32/include/string.h
@@ -23,7 +23,6 @@ __extern char *strcat(char *, const char *);
__extern char *strchr(const char *, int);
__extern int strcmp(const char *, const char *);
__extern char *strcpy(char *, const char *);
-__extern char *strpcpy(char *, const char *);
__extern size_t strcspn(const char *, const char *);
__extern char *strdup(const char *);
__extern char *strndup(const char *, size_t);
diff --git a/com32/include/sys/cpu.h b/com32/include/sys/cpu.h
index dfba02e7..a798a840 100644
--- a/com32/include/sys/cpu.h
+++ b/com32/include/sys/cpu.h
@@ -23,21 +23,26 @@ static inline void cpuid_count(uint32_t op, uint32_t cnt,
uint32_t * eax, uint32_t * ebx,
uint32_t * ecx, uint32_t * edx)
{
-asm("cpuid":"=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
+asm("pushl %%ebx ; cpuid ; movl %%ebx,%0 ; popl %%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);
+asm("pushl %%ebx ; cpuid ; movl %%ebx,%0 ; popl %%ebx":"=a"(*eax), "=SD"(*ebx), "=c"(*ecx),
+ "=d"(*edx)
+: "a"(op));
}
static inline __constfunc uint32_t cpuid_eax(uint32_t level)
{
uint32_t v;
-asm("cpuid": "=a"(v): "a"(level):"ebx", "ecx", "edx");
+asm("pushl %%ebx ; cpuid ; popl %%ebx":"=a"(v)
+: "a"(level)
+: "ecx", "edx");
return v;
}
@@ -45,7 +50,9 @@ static inline __constfunc uint32_t cpuid_ebx(uint32_t level)
{
uint32_t v;
-asm("cpuid": "=b"(v), "+a"(level): :"ecx", "edx");
+asm("pushl %%ebx ; cpuid ; movl %%ebx,%0 ; popl %%ebx":"=a"(v)
+: "a"(level)
+: "ecx", "edx");
return v;
}
@@ -53,7 +60,8 @@ static inline __constfunc uint32_t cpuid_ecx(uint32_t level)
{
uint32_t v;
-asm("cpuid": "=c"(v), "+a"(level): :"ebx", "edx");
+asm("pushl %%ebx ; cpuid ; popl %%ebx":"=c"(v), "+a"(level)
+: : "edx");
return v;
}
@@ -61,7 +69,8 @@ static inline __constfunc uint32_t cpuid_edx(uint32_t level)
{
uint32_t v;
-asm("cpuid": "=d"(v), "+a"(level): :"ebx", "ecx");
+asm("pushl %%ebx ; cpuid ; popl %%ebx":"=d"(v), "+a"(level)
+: : "ecx");
return v;
}
@@ -96,7 +105,10 @@ static inline void cpu_relax(void)
asm volatile ("rep ; nop");
}
-/* These are local cli/sti; not SMP-safe!!! */
+static inline void hlt(void)
+{
+ asm volatile ("hlt");
+}
static inline void cli(void)
{
diff --git a/com32/include/sys/dirent.h b/com32/include/sys/dirent.h
new file mode 100644
index 00000000..bb5e52c7
--- /dev/null
+++ b/com32/include/sys/dirent.h
@@ -0,0 +1,45 @@
+/*
+ * sys/dirent.h
+ */
+
+#ifndef DIRENT_H
+#define DIRENT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+struct dirent {
+ uint32_t d_ino;
+ uint32_t d_off;
+ uint16_t d_reclen;
+ uint16_t d_type;
+ char d_name[NAME_MAX + 1];
+};
+
+enum dirent_type {
+ DT_UNKNOWN = 0,
+ DT_FIFO = 1,
+ DT_CHR = 2,
+ DT_DIR = 4,
+ DT_BLK = 6,
+ DT_REG = 8,
+ DT_LNK = 10,
+ DT_SOCK = 12,
+ DT_WHT = 14,
+};
+
+/*
+ * Convert between stat structure mode types and directory types.
+ * The stat structure mode types are the same as in Linux.
+ */
+#define IFTODT(mode) (((mode) & 0170000) >> 12)
+#define DTTOIF(dt) ((dt) << 12)
+
+struct _DIR_;
+typedef struct _DIR_ DIR;
+
+#endif /* sys/dirent.h */
diff --git a/com32/include/syslinux/boot.h b/com32/include/syslinux/boot.h
index 87c05e99..21bea01a 100644
--- a/com32/include/syslinux/boot.h
+++ b/com32/include/syslinux/boot.h
@@ -37,7 +37,7 @@
#include <stdint.h>
#include <klibc/compiler.h>
-__noreturn syslinux_run_command(const char *);
+int syslinux_run_command(const char *);
__noreturn syslinux_run_default(void);
void syslinux_local_boot(uint16_t flags);
diff --git a/com32/include/syslinux/idle.h b/com32/include/syslinux/idle.h
index 4c5947b7..6a45236e 100644
--- a/com32/include/syslinux/idle.h
+++ b/com32/include/syslinux/idle.h
@@ -33,5 +33,6 @@
#define _SYSLINUX_IDLE_H
void syslinux_idle(void);
+void syslinux_reset_idle(void);
#endif
diff --git a/com32/include/syslinux/pmapi.h b/com32/include/syslinux/pmapi.h
new file mode 100644
index 00000000..f583deae
--- /dev/null
+++ b/com32/include/syslinux/pmapi.h
@@ -0,0 +1,70 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2002-2009 H. Peter Anvin - All Rights Reserved
+ * Copyright 2009 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * pmapi.h
+ *
+ * Definitions for the Syslinux 4 protected-mode ABI
+ */
+
+#ifndef _SYSLINUX_PMAPI_H
+#define _SYSLINUX_PMAPI_H
+
+#include <stddef.h>
+#include <inttypes.h>
+
+/*
+ * Note: add new members to this structure only at the end.
+ * The position of elements in this structure is an ABI.
+ */
+struct _DIR_;
+struct dirent;
+
+struct com32_filedata {
+ size_t size; /* File size */
+ int blocklg2; /* log2(block size) */
+ uint16_t handle; /* File handle */
+};
+
+struct com32_pmapi {
+ void *(*lmalloc)(size_t);
+ void (*lfree)(void *);
+
+ int (*open_file)(const char *, struct com32_filedata *);
+ size_t (*read_file)(uint16_t *, void *, size_t);
+ void (*close_file)(uint16_t);
+
+ struct _DIR_ *(*opendir)(const char *);
+ struct dirent *(*readdir)(struct _DIR_ *);
+ int (*closedir)(struct _DIR_ *);
+
+ void (*idle)(void);
+ void (*reset_idle)(void);
+};
+
+#endif /* _SYSLINUX_PMAPI_H */
diff --git a/com32/include/syslinux/pxe.h b/com32/include/syslinux/pxe.h
index 6e2a769b..4e8a3369 100644
--- a/com32/include/syslinux/pxe.h
+++ b/com32/include/syslinux/pxe.h
@@ -34,491 +34,10 @@
#ifndef _SYSLINUX_PXE_H
#define _SYSLINUX_PXE_H
-#include <stdint.h>
-#include <netinet/in.h>
-#include <klibc/compiler.h>
-#include <com32.h>
-
-/* PXE spec structures and definitions. These mostly follow the PXE
- spec, except when the PXE spec is unnecessarily stupid. Of course,
- that is most of the time. */
-
-/* Basic types; use Unix-like _t convention instead of SCREAMING; also
- re-use types we already have, like in_addr_t. */
-
-typedef uint16_t pxenv_status_t;
-
-#define MAC_ADDR_LEN 16
-typedef uint8_t mac_addr_t[MAC_ADDR_LEN];
-
-/* "Protected mode segment descriptor" according to PXE... */
-typedef struct {
- uint16_t segaddr;
- uint32_t physaddr;
- uint16_t segsize;
-} __packed pxe_segdesc_t;
-
-typedef far_ptr_t segoff16_t;
-
-typedef struct {
- uint8_t opcode;
-#define BOOTP_REQ 1
-#define BOOTP_REP 2
- uint8_t Hardware;
- uint8_t Hardlen;
- uint8_t Gatehops;
- uint32_t ident;
- uint16_t seconds;
- uint16_t Flags;
-#define BOOTP_BCAST 0x8000
- in_addr_t cip; /* Client IP address */
- in_addr_t yip; /* You IP address */
- in_addr_t sip; /* next server IP address */
- in_addr_t gip; /*relay agent IP address */
- mac_addr_t CAddr;
- uint8_t Sname[64];
- uint8_t bootfile[128];
- union {
-#define BOOTP_DHCPVEND 1024
- uint8_t d[BOOTP_DHCPVEND];
- struct {
- uint8_t magic[4];
-#define VM_RFC1048 0x63825363L
- uint32_t flags;
- uint8_t pad[56];
- } v;
- } vendor;
-} __packed pxe_bootp_t;
-
-/* Function calling structures and constants */
-
-typedef struct s_PXENV_GET_CACHED_INFO {
- pxenv_status_t Status;
- uint16_t PacketType;
-#define PXENV_PACKET_TYPE_DHCP_DISCOVER 1
-#define PXENV_PACKET_TYPE_DHCP_ACK 2
-#define PXENV_PACKET_TYPE_CACHED_REPLY 3
- uint16_t BufferSize;
- segoff16_t Buffer;
- uint16_t BufferLimit;
-} __packed t_PXENV_GET_CACHED_INFO;
-
-typedef struct s_PXENV_START_UNDI {
- pxenv_status_t Status;
- uint16_t AX;
- uint16_t BX;
- uint16_t DX;
- uint16_t DI;
- uint16_t ES;
-} __packed t_PXENV_START_UNDI;
-
-typedef struct s_PXENV_STOP_UNDI {
- pxenv_status_t Status;
-} __packed t_PXENV_STOP_UNDI;
-
-typedef struct s_PXENV_START_BASE {
- pxenv_status_t Status;
-} __packed t_PXENV_START_BASE;
-
-typedef struct s_PXENV_STOP_BASE {
- pxenv_status_t Status;
-} __packed t_PXENV_STOP_BASE;
-
-typedef struct s_PXENV_TFTP_OPEN {
- pxenv_status_t Status;
- in_addr_t ServerIPAddress;
- in_addr_t GatewayIPAddress;
- uint8_t FileName[128];
- in_port_t TFTPPort;
- uint16_t PacketSize;
-} __packed t_PXENV_TFTP_OPEN;
-
-typedef struct s_PXENV_TFTP_CLOSE {
- pxenv_status_t Status;
-} __packed t_PXENV_TFTP_CLOSE;
-
-typedef struct s_PXENV_TFTP_READ {
- pxenv_status_t Status;
- uint16_t PacketNumber;
- uint16_t BufferSize;
- segoff16_t Buffer;
-} __packed t_PXENV_TFTP_READ;
-
-typedef struct s_PXENV_TFTP_READ_FILE {
- pxenv_status_t Status;
- uint8_t FileName[128];
- uint32_t BufferSize;
- void *Buffer;
- in_addr_t ServerIPAddress;
- in_addr_t GatewayIPAddress;
- in_addr_t McastIPAddress;
- in_port_t TFTPClntPort;
- in_port_t TFTPSrvPort;
- uint16_t TFTPOpenTimeOut;
- uint16_t TFTPReopenDelay;
-} __packed t_PXENV_TFTP_READ_FILE;
-
-typedef struct s_PXENV_TFTP_GET_FSIZE {
- pxenv_status_t Status;
- in_addr_t ServerIPAddress;
- in_addr_t GatewayIPAddress;
- uint8_t FileName[128];
- uint32_t FileSize;
-} __packed t_PXENV_TFTP_GET_FSIZE;
-
-typedef struct s_PXENV_UDP_OPEN {
- pxenv_status_t status;
- in_addr_t src_ip;
-} __packed t_PXENV_UDP_OPEN;
-
-typedef struct s_PXENV_UDP_CLOSE {
- pxenv_status_t status;
-} __packed t_PXENV_UDP_CLOSE;
-
-typedef struct s_PXENV_UDP_WRITE {
- pxenv_status_t status;
- in_addr_t ip;
- in_addr_t gw;
- in_port_t src_port;
- in_port_t dst_port;
- uint16_t buffer_size;
- segoff16_t buffer;
-} __packed t_PXENV_UDP_WRITE;
-
-typedef struct s_PXENV_UDP_READ {
- pxenv_status_t status;
- in_addr_t src_ip;
- in_addr_t dest_ip;
- in_port_t s_port;
- in_port_t d_port;
- uint16_t buffer_size;
- segoff16_t buffer;
-} __packed t_PXENV_UDP_READ;
-
-typedef struct s_PXENV_UNDI_STARTUP {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_STARTUP;
-
-typedef struct s_PXENV_UNDI_CLEANUP {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_CLEANUP;
-
-typedef struct s_PXENV_UNDI_INITIALIZE {
- pxenv_status_t Status;
- void *ProtocolIni;
- uint8_t reserved[8];
-} __packed t_PXENV_UNDI_INITIALIZE;
-
-#define MAXNUM_MCADDR 8
-typedef struct s_PXENV_UNDI_MCAST_ADDRESS {
- uint16_t MCastAddrCount;
- mac_addr_t McastAddr[MAXNUM_MCADDR];
-} __packed t_PXENV_UNDI_MCAST_ADDRESS;
-
-typedef struct s_PXENV_UNDI_RESET {
- pxenv_status_t Status;
- t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
-} __packed t_PXENV_UNDI_RESET;
-
-typedef struct s_PXENV_UNDI_SHUTDOWN {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_SHUTDOWN;
-
-typedef struct s_PXENV_UNDI_OPEN {
- pxenv_status_t Status;
- uint16_t OpenFlag;
- uint16_t PktFilter;
-#define FLTR_DIRECTED 0x0001
-#define FLTR_BRDCST 0x0002
-#define FLTR_PRMSCS 0x0004
-#define FLTR_SRC_RTG 0x0008
- t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
-} __packed t_PXENV_UNDI_OPEN;
-
-typedef struct s_PXENV_UNDI_CLOSE {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_CLOSE;
-
-typedef struct s_PXENV_UNDI_TRANSMIT {
- pxenv_status_t Status;
- uint8_t Protocol;
-#define P_UNKNOWN 0
-#define P_IP 1
-#define P_ARP 2
-#define P_RARP 3
- uint8_t XmitFlag;
-#define XMT_DESTADDR 0x0000
-#define XMT_BROADCAST 0x0001
- segoff16_t DestAddr;
- segoff16_t TBD;
- uint32_t Reserved[2];
-} __packed t_PXENV_UNDI_TRANSMIT;
-#define MAX_DATA_BLKS 8
-typedef struct s_PXENV_UNDI_TBD {
- uint16_t ImmedLength;
- segoff16_t Xmit;
- uint16_t DataBlkCount;
- struct DataBlk {
- uint8_t TDPtrType;
- uint8_t TDRsvdByte;
- uint16_t TDDataLen;
- segoff16_t TDDataPtr;
- } DataBlock[MAX_DATA_BLKS];
-} __packed t_PXENV_UNDI_TBD;
-
-typedef struct s_PXENV_UNDI_SET_MCAST_ADDRESS {
- pxenv_status_t Status;
- t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
-} __packed t_PXENV_UNDI_SET_MCAST_ADDR;
-
-typedef struct s_PXENV_UNDI_SET_STATION_ADDRESS {
- pxenv_status_t Status;
- mac_addr_t StationAddress;
-} __packed t_PXENV_UNDI_SET_STATION_ADDR;
-
-typedef struct s_PXENV_UNDI_SET_PACKET_FILTER {
- pxenv_status_t Status;
- uint8_t filter;
-} __packed t_PXENV_UNDI_SET_PACKET_FILTER;
-
-typedef struct s_PXENV_UNDI_GET_INFORMATION {
- pxenv_status_t Status;
- uint16_t BaseIo;
- uint16_t IntNumber;
- uint16_t MaxTranUnit;
- uint16_t HwType;
-#define ETHER_TYPE 1
-#define EXP_ETHER_TYPE 2
-#define IEEE_TYPE 6
-#define ARCNET_TYPE 7
- uint16_t HwAddrLen;
- mac_addr_t CurrentNodeAddress;
- mac_addr_t PermNodeAddress;
- uint16_t ROMAddress;
- uint16_t RxBufCt;
- uint16_t TxBufCt;
-} __packed t_PXENV_UNDI_GET_INFORMATION;
-
-typedef struct s_PXENV_UNDI_GET_STATISTICS {
- pxenv_status_t Status;
- uint32_t XmtGoodFrames;
- uint32_t RcvGoodFrames;
- uint32_t RcvCRCErrors;
- uint32_t RcvResourceErrors;
-} __packed t_PXENV_UNDI_GET_STATISTICS;
-
-typedef struct s_PXENV_UNDI_CLEAR_STATISTICS {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_CLEAR_STATISTICS;
-
-typedef struct s_PXENV_UNDI_INITIATE_DIAGS {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_INITIATE_DIAGS;
-
-typedef struct s_PXENV_UNDI_FORCE_INTERRUPT {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_FORCE_INTERRUPT;
-
-typedef struct s_PXENV_UNDI_GET_MCAST_ADDRESS {
- pxenv_status_t Status;
- in_addr_t InetAddr;
- mac_addr_t MediaAddr;
-} __packed t_PXENV_UNDI_GET_MCAST_ADDR;
-
-typedef struct s_PXENV_UNDI_GET_NIC_TYPE {
- pxenv_status_t Status;
- uint8_t NicType;
-#define PCI_NIC 2
-#define PnP_NIC 3
-#define CardBus_NIC 4
- union {
- struct {
- uint16_t Vendor_ID;
- uint16_t Dev_ID;
- uint8_t Base_Class;
- uint8_t Sub_Class;
- uint8_t Prog_Intf;
- uint8_t Rev;
- uint16_t BusDevFunc;
- uint16_t SubVendor_ID;
- uint16_t SubDevice_ID;
- } pci, cardbus;
- struct {
- uint32_t EISA_Dev_ID;
- uint8_t Base_Class;
- uint8_t Sub_Class;
- uint8_t Prog_Intf;
- uint16_t CardSelNum;
- } __packed pnp;
- } __packed info;
-} __packed t_PXENV_UNDI_GET_NIC_TYPE;
-
-typedef struct s_PXENV_UNDI_GET_IFACE_INFO {
- pxenv_status_t Status;
- uint8_t IfaceType[16];
- uint32_t LinkSpeed;
- uint32_t ServiceFlags;
- uint32_t Reserved[4];
-} __packed t_PXENV_UNDI_GET_NDIS_INFO;
-
-typedef struct s_PXENV_UNDI_GET_STATE {
-#define PXE_UNDI_GET_STATE_STARTED 1
-#define PXE_UNDI_GET_STATE_INITIALIZED 2
-#define PXE_UNDI_GET_STATE_OPENED 3
- pxenv_status_t Status;
- uint8_t UNDIstate;
-} __packed t_PXENV_UNDI_GET_STATE;
-
-typedef struct s_PXENV_UNDI_ISR {
- pxenv_status_t Status;
- uint16_t FuncFlag;
- uint16_t BufferLength;
- uint16_t FrameLength;
- uint16_t FrameHeaderLength;
- segoff16_t Frame;
- uint8_t ProtType;
- uint8_t PktType;
-} __packed t_PXENV_UNDI_ISR;
-#define PXENV_UNDI_ISR_IN_START 1
-#define PXENV_UNDI_ISR_IN_PROCESS 2
-#define PXENV_UNDI_ISR_IN_GET_NEXT 3
-/* One of these will be returned for
- PXENV_UNDI_ISR_IN_START */
-#define PXENV_UNDI_ISR_OUT_OURS 0
-#define PXENV_UNDI_USR_OUT_NOT_OURS 1
-/* One of these will be returned for
- PXENV_UNDI_ISR_IN_PROCESS and
- PXENV_UNDI_ISR_IN_GET_NEXT */
-#define PXENV_UNDI_ISR_OUT_DONE 0
-#define PXENV_UNDI_ISR_OUT_TRANSMIT 2
-#define PXENV_UNDI_ISR_OUT_RECEIVE 3
-#define PXENV_UNDI_ISR_OUT_BUSY 4
-
-/* Function numbers and error codes */
-
-#define PXENV_TFTP_OPEN 0x0020
-#define PXENV_TFTP_CLOSE 0x0021
-#define PXENV_TFTP_READ 0x0022
-#define PXENV_TFTP_READ_FILE 0x0023
-#define PXENV_TFTP_READ_FILE_PMODE 0x0024
-#define PXENV_TFTP_GET_FSIZE 0x0025
-
-#define PXENV_UDP_OPEN 0x0030
-#define PXENV_UDP_CLOSE 0x0031
-#define PXENV_UDP_READ 0x0032
-#define PXENV_UDP_WRITE 0x0033
-
-#define PXENV_START_UNDI 0x0000
-#define PXENV_UNDI_STARTUP 0x0001
-#define PXENV_UNDI_CLEANUP 0x0002
-#define PXENV_UNDI_INITIALIZE 0x0003
-#define PXENV_UNDI_RESET_NIC 0x0004
-#define PXENV_UNDI_SHUTDOWN 0x0005
-#define PXENV_UNDI_OPEN 0x0006
-#define PXENV_UNDI_CLOSE 0x0007
-#define PXENV_UNDI_TRANSMIT 0x0008
-#define PXENV_UNDI_SET_MCAST_ADDR 0x0009
-#define PXENV_UNDI_SET_STATION_ADDR 0x000A
-#define PXENV_UNDI_SET_PACKET_FILTER 0x000B
-#define PXENV_UNDI_GET_INFORMATION 0x000C
-#define PXENV_UNDI_GET_STATISTICS 0x000D
-#define PXENV_UNDI_CLEAR_STATISTICS 0x000E
-#define PXENV_UNDI_INITIATE_DIAGS 0x000F
-#define PXENV_UNDI_FORCE_INTERRUPT 0x0010
-#define PXENV_UNDI_GET_MCAST_ADDR 0x0011
-#define PXENV_UNDI_GET_NIC_TYPE 0x0012
-#define PXENV_UNDI_GET_IFACE_INFO 0x0013
-#define PXENV_UNDI_ISR 0x0014
-#define PXENV_STOP_UNDI 0x0015 /* Overlap...? */
-#define PXENV_UNDI_GET_STATE 0x0015 /* Overlap...? */
-
-#define PXENV_UNLOAD_STACK 0x0070
-#define PXENV_GET_CACHED_INFO 0x0071
-#define PXENV_RESTART_DHCP 0x0072
-#define PXENV_RESTART_TFTP 0x0073
-#define PXENV_MODE_SWITCH 0x0074
-#define PXENV_START_BASE 0x0075
-#define PXENV_STOP_BASE 0x0076
-
-#define PXENV_EXIT_SUCCESS 0x0000
-#define PXENV_EXIT_FAILURE 0x0001
-
-#define PXENV_STATUS_SUCCESS 0x00
-#define PXENV_STATUS_FAILURE 0x01
-#define PXENV_STATUS_BAD_FUNC 0x02
-#define PXENV_STATUS_UNSUPPORTED 0x03
-#define PXENV_STATUS_KEEP_UNDI 0x04
-#define PXENV_STATUS_KEEP_ALL 0x05
-#define PXENV_STATUS_OUT_OF_RESOURCES 0x06
-#define PXENV_STATUS_ARP_TIMEOUT 0x11
-#define PXENV_STATUS_UDP_CLOSED 0x18
-#define PXENV_STATUS_UDP_OPEN 0x19
-#define PXENV_STATUS_TFTP_CLOSED 0x1A
-#define PXENV_STATUS_TFTP_OPEN 0x1B
-#define PXENV_STATUS_MCOPY_PROBLEM 0x20
-#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21
-#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22
-#define PXENV_STATUS_BIS_INIT_FAILURE 0x23
-#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24
-#define PXENV_STATUS_BIS_GBOA_FAILURE 0x25
-#define PXENV_STATUS_BIS_FREE_FAILURE 0x26
-#define PXENV_STATUS_BIS_GSI_FAILURE 0x27
-#define PXENV_STATUS_BIS_BAD_CKSUM 0x28
-#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30
-#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32
-
-#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33
-#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35
-#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36
-#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38
-#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39
-#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3A
-#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3B
-#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3C
-#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3D
-#define PXENV_STATUS_TFTP_NO_FILESIZE 0x3E
-#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3F
-#define PXENV_STATUS_DHCP_TIMEOUT 0x51
-#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52
-#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53
-#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54
-#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60
-#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61
-#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62
-#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63
-#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64
-#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65
-#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66
-#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67
-#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68
-#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69
-#define PXENV_STATUS_UNDI_INVALID_STATE 0x6A
-#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6B
-#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6C
-#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74
-#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76
-#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77
-#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78
-#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79
-#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xA0
-#define PXENV_STATUS_BINL_NO_PXE_SERVER 0xA1
-#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xA2
-#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xA3
-#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xB0
-#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xC0
-#define PXENV_STATUS_LOADER_NO_BC_ROMID 0xC1
-#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xC2
-#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xC3
-#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xC4
-#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xC5
-#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xC6
-#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xC8
-#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xC9
-#define PXENV_STATUS_LOADER_UNDI_START 0xCA
-#define PXENV_STATUS_LOADER_BC_START 0xCB
+#include <syslinux/pxe_api.h>
/* SYSLINUX-defined PXE utility functions */
-int pxe_get_cached_info(int level, void **buf, size_t * len);
+int pxe_get_cached_info(int level, void **buf, size_t *len);
int pxe_get_nic_type(t_PXENV_UNDI_GET_NIC_TYPE * gnt);
uint32_t pxe_dns(const char *hostname);
diff --git a/com32/include/syslinux/pxe_api.h b/com32/include/syslinux/pxe_api.h
new file mode 100644
index 00000000..27166b0b
--- /dev/null
+++ b/com32/include/syslinux/pxe_api.h
@@ -0,0 +1,571 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * syslinux/pxe_api.h
+ *
+ * PXE type and constant definitions for SYSLINUX
+ */
+
+#ifndef _SYSLINUX_PXE_API_H
+#define _SYSLINUX_PXE_API_H
+
+#include <stdint.h>
+#include <netinet/in.h>
+#include <klibc/compiler.h>
+#include <com32.h>
+
+/* PXE spec structures and definitions. These mostly follow the PXE
+ spec, except when the PXE spec is unnecessarily stupid. Of course,
+ that is most of the time. */
+
+/* Basic types; use Unix-like _t convention instead of SCREAMING; also
+ re-use types we already have, like in_addr_t. */
+
+typedef uint16_t pxenv_status_t;
+
+#define MAC_ADDR_LEN 16
+typedef uint8_t mac_addr_t[MAC_ADDR_LEN];
+
+/* "Protected mode segment descriptor" according to PXE... */
+typedef struct {
+ uint16_t sel;
+ uint32_t base;
+ uint16_t size;
+} __packed pxe_segdesc_t;
+
+typedef far_ptr_t segoff16_t;
+
+typedef struct {
+ uint8_t opcode;
+#define BOOTP_REQ 1
+#define BOOTP_REP 2
+ uint8_t Hardware;
+ uint8_t Hardlen;
+ uint8_t Gatehops;
+ uint32_t ident;
+ uint16_t seconds;
+ uint16_t Flags;
+#define BOOTP_BCAST 0x8000
+ in_addr_t cip; /* Client IP address */
+ in_addr_t yip; /* You IP address */
+ in_addr_t sip; /* next server IP address */
+ in_addr_t gip; /*relay agent IP address */
+ mac_addr_t CAddr;
+ uint8_t Sname[64];
+ uint8_t bootfile[128];
+ union {
+#define BOOTP_DHCPVEND 1024
+ uint8_t d[BOOTP_DHCPVEND];
+ struct {
+ uint8_t magic[4];
+#define VM_RFC1048 0x63825363L
+ uint32_t flags;
+ uint8_t pad[56];
+ } v;
+ } vendor;
+} __packed pxe_bootp_t;
+
+/* Function calling structures and constants */
+
+typedef struct s_PXENV_GET_CACHED_INFO {
+ pxenv_status_t Status;
+ uint16_t PacketType;
+#define PXENV_PACKET_TYPE_DHCP_DISCOVER 1
+#define PXENV_PACKET_TYPE_DHCP_ACK 2
+#define PXENV_PACKET_TYPE_CACHED_REPLY 3
+ uint16_t BufferSize;
+ segoff16_t Buffer;
+ uint16_t BufferLimit;
+} __packed t_PXENV_GET_CACHED_INFO;
+
+typedef struct s_PXENV_START_UNDI {
+ pxenv_status_t Status;
+ uint16_t AX;
+ uint16_t BX;
+ uint16_t DX;
+ uint16_t DI;
+ uint16_t ES;
+} __packed t_PXENV_START_UNDI;
+
+typedef struct s_PXENV_STOP_UNDI {
+ pxenv_status_t Status;
+} __packed t_PXENV_STOP_UNDI;
+
+typedef struct s_PXENV_START_BASE {
+ pxenv_status_t Status;
+} __packed t_PXENV_START_BASE;
+
+typedef struct s_PXENV_STOP_BASE {
+ pxenv_status_t Status;
+} __packed t_PXENV_STOP_BASE;
+
+typedef struct s_PXENV_TFTP_OPEN {
+ pxenv_status_t Status;
+ in_addr_t ServerIPAddress;
+ in_addr_t GatewayIPAddress;
+ uint8_t FileName[128];
+ in_port_t TFTPPort;
+ uint16_t PacketSize;
+} __packed t_PXENV_TFTP_OPEN;
+
+typedef struct s_PXENV_TFTP_CLOSE {
+ pxenv_status_t Status;
+} __packed t_PXENV_TFTP_CLOSE;
+
+typedef struct s_PXENV_TFTP_READ {
+ pxenv_status_t Status;
+ uint16_t PacketNumber;
+ uint16_t BufferSize;
+ segoff16_t Buffer;
+} __packed t_PXENV_TFTP_READ;
+
+typedef struct s_PXENV_TFTP_READ_FILE {
+ pxenv_status_t Status;
+ uint8_t FileName[128];
+ uint32_t BufferSize;
+ void *Buffer;
+ in_addr_t ServerIPAddress;
+ in_addr_t GatewayIPAddress;
+ in_addr_t McastIPAddress;
+ in_port_t TFTPClntPort;
+ in_port_t TFTPSrvPort;
+ uint16_t TFTPOpenTimeOut;
+ uint16_t TFTPReopenDelay;
+} __packed t_PXENV_TFTP_READ_FILE;
+
+typedef struct s_PXENV_TFTP_GET_FSIZE {
+ pxenv_status_t Status;
+ in_addr_t ServerIPAddress;
+ in_addr_t GatewayIPAddress;
+ uint8_t FileName[128];
+ uint32_t FileSize;
+} __packed t_PXENV_TFTP_GET_FSIZE;
+
+typedef struct s_PXENV_UDP_OPEN {
+ pxenv_status_t status;
+ in_addr_t src_ip;
+} __packed t_PXENV_UDP_OPEN;
+
+typedef struct s_PXENV_UDP_CLOSE {
+ pxenv_status_t status;
+} __packed t_PXENV_UDP_CLOSE;
+
+typedef struct s_PXENV_UDP_WRITE {
+ pxenv_status_t status;
+ in_addr_t ip;
+ in_addr_t gw;
+ in_port_t src_port;
+ in_port_t dst_port;
+ uint16_t buffer_size;
+ segoff16_t buffer;
+} __packed t_PXENV_UDP_WRITE;
+
+typedef struct s_PXENV_UDP_READ {
+ pxenv_status_t status;
+ in_addr_t src_ip;
+ in_addr_t dest_ip;
+ in_port_t s_port;
+ in_port_t d_port;
+ uint16_t buffer_size;
+ segoff16_t buffer;
+} __packed t_PXENV_UDP_READ;
+
+typedef struct s_PXENV_UNDI_STARTUP {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_STARTUP;
+
+typedef struct s_PXENV_UNDI_CLEANUP {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_CLEANUP;
+
+typedef struct s_PXENV_UNDI_INITIALIZE {
+ pxenv_status_t Status;
+ void *ProtocolIni;
+ uint8_t reserved[8];
+} __packed t_PXENV_UNDI_INITIALIZE;
+
+#define MAXNUM_MCADDR 8
+typedef struct s_PXENV_UNDI_MCAST_ADDRESS {
+ uint16_t MCastAddrCount;
+ mac_addr_t McastAddr[MAXNUM_MCADDR];
+} __packed t_PXENV_UNDI_MCAST_ADDRESS;
+
+typedef struct s_PXENV_UNDI_RESET {
+ pxenv_status_t Status;
+ t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
+} __packed t_PXENV_UNDI_RESET;
+
+typedef struct s_PXENV_UNDI_SHUTDOWN {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_SHUTDOWN;
+
+typedef struct s_PXENV_UNDI_OPEN {
+ pxenv_status_t Status;
+ uint16_t OpenFlag;
+ uint16_t PktFilter;
+#define FLTR_DIRECTED 0x0001
+#define FLTR_BRDCST 0x0002
+#define FLTR_PRMSCS 0x0004
+#define FLTR_SRC_RTG 0x0008
+ t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
+} __packed t_PXENV_UNDI_OPEN;
+
+typedef struct s_PXENV_UNDI_CLOSE {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_CLOSE;
+
+typedef struct s_PXENV_UNDI_TRANSMIT {
+ pxenv_status_t Status;
+ uint8_t Protocol;
+#define P_UNKNOWN 0
+#define P_IP 1
+#define P_ARP 2
+#define P_RARP 3
+ uint8_t XmitFlag;
+#define XMT_DESTADDR 0x0000
+#define XMT_BROADCAST 0x0001
+ segoff16_t DestAddr;
+ segoff16_t TBD;
+ uint32_t Reserved[2];
+} __packed t_PXENV_UNDI_TRANSMIT;
+#define MAX_DATA_BLKS 8
+typedef struct s_PXENV_UNDI_TBD {
+ uint16_t ImmedLength;
+ segoff16_t Xmit;
+ uint16_t DataBlkCount;
+ struct DataBlk {
+ uint8_t TDPtrType;
+ uint8_t TDRsvdByte;
+ uint16_t TDDataLen;
+ segoff16_t TDDataPtr;
+ } DataBlock[MAX_DATA_BLKS];
+} __packed t_PXENV_UNDI_TBD;
+
+typedef struct s_PXENV_UNDI_SET_MCAST_ADDRESS {
+ pxenv_status_t Status;
+ t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
+} __packed t_PXENV_UNDI_SET_MCAST_ADDR;
+
+typedef struct s_PXENV_UNDI_SET_STATION_ADDRESS {
+ pxenv_status_t Status;
+ mac_addr_t StationAddress;
+} __packed t_PXENV_UNDI_SET_STATION_ADDR;
+
+typedef struct s_PXENV_UNDI_SET_PACKET_FILTER {
+ pxenv_status_t Status;
+ uint8_t filter;
+} __packed t_PXENV_UNDI_SET_PACKET_FILTER;
+
+typedef struct s_PXENV_UNDI_GET_INFORMATION {
+ pxenv_status_t Status;
+ uint16_t BaseIo;
+ uint16_t IntNumber;
+ uint16_t MaxTranUnit;
+ uint16_t HwType;
+#define ETHER_TYPE 1
+#define EXP_ETHER_TYPE 2
+#define IEEE_TYPE 6
+#define ARCNET_TYPE 7
+ uint16_t HwAddrLen;
+ mac_addr_t CurrentNodeAddress;
+ mac_addr_t PermNodeAddress;
+ uint16_t ROMAddress;
+ uint16_t RxBufCt;
+ uint16_t TxBufCt;
+} __packed t_PXENV_UNDI_GET_INFORMATION;
+
+typedef struct s_PXENV_UNDI_GET_STATISTICS {
+ pxenv_status_t Status;
+ uint32_t XmtGoodFrames;
+ uint32_t RcvGoodFrames;
+ uint32_t RcvCRCErrors;
+ uint32_t RcvResourceErrors;
+} __packed t_PXENV_UNDI_GET_STATISTICS;
+
+typedef struct s_PXENV_UNDI_CLEAR_STATISTICS {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_CLEAR_STATISTICS;
+
+typedef struct s_PXENV_UNDI_INITIATE_DIAGS {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_INITIATE_DIAGS;
+
+typedef struct s_PXENV_UNDI_FORCE_INTERRUPT {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_FORCE_INTERRUPT;
+
+typedef struct s_PXENV_UNDI_GET_MCAST_ADDRESS {
+ pxenv_status_t Status;
+ in_addr_t InetAddr;
+ mac_addr_t MediaAddr;
+} __packed t_PXENV_UNDI_GET_MCAST_ADDR;
+
+typedef struct s_PXENV_UNDI_GET_NIC_TYPE {
+ pxenv_status_t Status;
+ uint8_t NicType;
+#define PCI_NIC 2
+#define PnP_NIC 3
+#define CardBus_NIC 4
+ union {
+ struct {
+ uint16_t Vendor_ID;
+ uint16_t Dev_ID;
+ uint8_t Base_Class;
+ uint8_t Sub_Class;
+ uint8_t Prog_Intf;
+ uint8_t Rev;
+ uint16_t BusDevFunc;
+ uint16_t SubVendor_ID;
+ uint16_t SubDevice_ID;
+ } pci, cardbus;
+ struct {
+ uint32_t EISA_Dev_ID;
+ uint8_t Base_Class;
+ uint8_t Sub_Class;
+ uint8_t Prog_Intf;
+ uint16_t CardSelNum;
+ } __packed pnp;
+ } __packed info;
+} __packed t_PXENV_UNDI_GET_NIC_TYPE;
+
+typedef struct s_PXENV_UNDI_GET_IFACE_INFO {
+ pxenv_status_t Status;
+ uint8_t IfaceType[16];
+ uint32_t LinkSpeed;
+ uint32_t ServiceFlags;
+ uint32_t Reserved[4];
+} __packed t_PXENV_UNDI_GET_NDIS_INFO;
+
+typedef struct s_PXENV_UNDI_GET_STATE {
+#define PXE_UNDI_GET_STATE_STARTED 1
+#define PXE_UNDI_GET_STATE_INITIALIZED 2
+#define PXE_UNDI_GET_STATE_OPENED 3
+ pxenv_status_t Status;
+ uint8_t UNDIstate;
+} __packed t_PXENV_UNDI_GET_STATE;
+
+typedef struct s_PXENV_UNDI_ISR {
+ pxenv_status_t Status;
+ uint16_t FuncFlag;
+ uint16_t BufferLength;
+ uint16_t FrameLength;
+ uint16_t FrameHeaderLength;
+ segoff16_t Frame;
+ uint8_t ProtType;
+ uint8_t PktType;
+} __packed t_PXENV_UNDI_ISR;
+
+typedef struct s_PXENV_FILE_API_CHECK {
+ pxenv_status_t Status;
+ uint16_t Size;
+ uint32_t Magic;
+ uint32_t Provider;
+ uint32_t APIMask;
+ uint32_t Flags;
+} __packed t_PXENV_FILE_API_CHECK;
+
+typedef struct s_PXENV_FILE_READ {
+ pxenv_status_t Status;
+ uint16_t FileHandle;
+ uint16_t BufferSize;
+ segoff16_t Buffer;
+} __packed t_PXENV_FILE_READ;
+
+typedef struct s_PXENV_FILE_OPEN {
+ pxenv_status_t Status;
+ uint16_t FileHandle;
+ segoff16_t FileName;
+ uint32_t Reserved;
+} __packed t_PXENV_FILE_OPEN;
+
+typedef struct s_PXENV_FILE_CLOSE {
+ pxenv_status_t Status;
+ uint16_t FileHandle;
+} __packed t_PXENV_FILE_CLOSE;
+
+typedef struct s_PXENV_GET_FILE_SIZE {
+ pxenv_status_t Status;
+ uint16_t FileHandle;
+ uint32_t FileSize;
+} __packed t_PXENV_GET_FILE_SIZE;
+
+typedef struct s_PXENV_UNLOAD_STACK {
+ pxenv_status_t Status;
+ uint8_t reserved[10];
+} __packed t_PXENV_UNLOAD_STACK;
+
+#define PXENV_UNDI_ISR_IN_START 1
+#define PXENV_UNDI_ISR_IN_PROCESS 2
+#define PXENV_UNDI_ISR_IN_GET_NEXT 3
+/* One of these will be returned for
+ PXENV_UNDI_ISR_IN_START */
+#define PXENV_UNDI_ISR_OUT_OURS 0
+#define PXENV_UNDI_USR_OUT_NOT_OURS 1
+/* One of these will be returned for
+ PXENV_UNDI_ISR_IN_PROCESS and
+ PXENV_UNDI_ISR_IN_GET_NEXT */
+#define PXENV_UNDI_ISR_OUT_DONE 0
+#define PXENV_UNDI_ISR_OUT_TRANSMIT 2
+#define PXENV_UNDI_ISR_OUT_RECEIVE 3
+#define PXENV_UNDI_ISR_OUT_BUSY 4
+
+/* Function numbers and error codes */
+
+#define PXENV_TFTP_OPEN 0x0020
+#define PXENV_TFTP_CLOSE 0x0021
+#define PXENV_TFTP_READ 0x0022
+#define PXENV_TFTP_READ_FILE 0x0023
+#define PXENV_TFTP_READ_FILE_PMODE 0x0024
+#define PXENV_TFTP_GET_FSIZE 0x0025
+
+#define PXENV_UDP_OPEN 0x0030
+#define PXENV_UDP_CLOSE 0x0031
+#define PXENV_UDP_READ 0x0032
+#define PXENV_UDP_WRITE 0x0033
+
+#define PXENV_START_UNDI 0x0000
+#define PXENV_UNDI_STARTUP 0x0001
+#define PXENV_UNDI_CLEANUP 0x0002
+#define PXENV_UNDI_INITIALIZE 0x0003
+#define PXENV_UNDI_RESET_NIC 0x0004
+#define PXENV_UNDI_SHUTDOWN 0x0005
+#define PXENV_UNDI_OPEN 0x0006
+#define PXENV_UNDI_CLOSE 0x0007
+#define PXENV_UNDI_TRANSMIT 0x0008
+#define PXENV_UNDI_SET_MCAST_ADDR 0x0009
+#define PXENV_UNDI_SET_STATION_ADDR 0x000A
+#define PXENV_UNDI_SET_PACKET_FILTER 0x000B
+#define PXENV_UNDI_GET_INFORMATION 0x000C
+#define PXENV_UNDI_GET_STATISTICS 0x000D
+#define PXENV_UNDI_CLEAR_STATISTICS 0x000E
+#define PXENV_UNDI_INITIATE_DIAGS 0x000F
+#define PXENV_UNDI_FORCE_INTERRUPT 0x0010
+#define PXENV_UNDI_GET_MCAST_ADDR 0x0011
+#define PXENV_UNDI_GET_NIC_TYPE 0x0012
+#define PXENV_UNDI_GET_IFACE_INFO 0x0013
+#define PXENV_UNDI_ISR 0x0014
+#define PXENV_STOP_UNDI 0x0015 /* Overlap...? */
+#define PXENV_UNDI_GET_STATE 0x0015 /* Overlap...? */
+
+#define PXENV_UNLOAD_STACK 0x0070
+#define PXENV_GET_CACHED_INFO 0x0071
+#define PXENV_RESTART_DHCP 0x0072
+#define PXENV_RESTART_TFTP 0x0073
+#define PXENV_MODE_SWITCH 0x0074
+#define PXENV_START_BASE 0x0075
+#define PXENV_STOP_BASE 0x0076
+
+/* gPXE extensions... */
+#define PXENV_FILE_OPEN 0x00e0
+#define PXENV_FILE_CLOSE 0x00e1
+#define PXENV_FILE_SELECT 0x00e2
+#define PXENV_FILE_READ 0x00e3
+#define PXENV_GET_FILE_SIZE 0x00e4
+#define PXENV_FILE_EXEC 0x00e5
+#define PXENV_FILE_API_CHECK 0x00e6
+
+/* Exit codes */
+#define PXENV_EXIT_SUCCESS 0x0000
+#define PXENV_EXIT_FAILURE 0x0001
+
+/* Status codes */
+#define PXENV_STATUS_SUCCESS 0x00
+#define PXENV_STATUS_FAILURE 0x01
+#define PXENV_STATUS_BAD_FUNC 0x02
+#define PXENV_STATUS_UNSUPPORTED 0x03
+#define PXENV_STATUS_KEEP_UNDI 0x04
+#define PXENV_STATUS_KEEP_ALL 0x05
+#define PXENV_STATUS_OUT_OF_RESOURCES 0x06
+#define PXENV_STATUS_ARP_TIMEOUT 0x11
+#define PXENV_STATUS_UDP_CLOSED 0x18
+#define PXENV_STATUS_UDP_OPEN 0x19
+#define PXENV_STATUS_TFTP_CLOSED 0x1a
+#define PXENV_STATUS_TFTP_OPEN 0x1b
+#define PXENV_STATUS_MCOPY_PROBLEM 0x20
+#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21
+#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22
+#define PXENV_STATUS_BIS_INIT_FAILURE 0x23
+#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24
+#define PXENV_STATUS_BIS_GBOA_FAILURE 0x25
+#define PXENV_STATUS_BIS_FREE_FAILURE 0x26
+#define PXENV_STATUS_BIS_GSI_FAILURE 0x27
+#define PXENV_STATUS_BIS_BAD_CKSUM 0x28
+#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30
+#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32
+
+#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33
+#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35
+#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36
+#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38
+#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39
+#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3a
+#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3b
+#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3c
+#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3d
+#define PXENV_STATUS_TFTP_NO_FILESIZE 0x3e
+#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3f
+#define PXENV_STATUS_DHCP_TIMEOUT 0x51
+#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52
+#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53
+#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54
+#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60
+#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61
+#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64
+#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65
+#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66
+#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67
+#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68
+#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69
+#define PXENV_STATUS_UNDI_INVALID_STATE 0x6a
+#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6b
+#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6c
+#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74
+#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76
+#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77
+#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78
+#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79
+#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xa0
+#define PXENV_STATUS_BINL_NO_PXE_SERVER 0xa1
+#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xa2
+#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xa3
+#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xb0
+#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xc0
+#define PXENV_STATUS_LOADER_NO_BC_ROMID 0xc1
+#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xc2
+#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xc3
+#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xc4
+#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xc5
+#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xc6
+#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xc8
+#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xc9
+#define PXENV_STATUS_LOADER_UNDI_START 0xca
+#define PXENV_STATUS_LOADER_BC_START 0xcb
+
+#endif /* _SYSLINUX_PXE_API_H */
diff --git a/com32/lib/MCONFIG b/com32/lib/MCONFIG
index 1ae83bc7..44278bd1 100644
--- a/com32/lib/MCONFIG
+++ b/com32/lib/MCONFIG
@@ -2,9 +2,20 @@
include $(topdir)/MCONFIG
-GCCOPT := $(call gcc_ok,-std=gnu99,) \
- $(call gcc_ok,-m32,) \
- $(call gcc_ok,-fno-stack-protector,) \
+GCCOPT := $(call gcc_ok,-std=gnu99,)
+GCCOPT += $(call gcc_ok,-m32,)
+GCCOPT += $(call gcc_ok,-fno-stack-protector,)
+GCCOPT += $(call gcc_ok,-fwrapv,)
+GCCOPT += $(call gcc_ok,-freg-struct-return,)
+GCCOPT += $(call gcc_ok,-fPIE,-fPIC)
+GCCOPT += $(call gcc_ok,-fno-exceptions,)
+GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,)
+GCCOPT += $(call gcc_ok,-fno-strict-aliasing,)
+GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0)
+GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0)
+GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0)
+GCCOPT += $(call gcc_ok,-falign-loops=0,-malign-loops=0)
+GCCOPT += $(call gcc_ok,-mpreferred-stack-boundary=2,)
INCLUDE = -I.
STRIP = strip --strip-all -R .comment -R .note
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 250c3962..93643ce2 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -17,7 +17,7 @@ LIBOBJS = \
exit.o onexit.o \
perror.o printf.o puts.o qsort.o realloc.o seed48.o snprintf.o \
sprintf.o srand48.o sscanf.o stack.o strcasecmp.o strcat.o \
- strchr.o strcmp.o strcpy.o strpcpy.o strdup.o strlen.o \
+ strchr.o strcmp.o strcpy.o strdup.o strlen.o \
strerror.o strnlen.o \
strncasecmp.o strncat.o strncmp.o strncpy.o strndup.o \
stpcpy.o stpncpy.o \
@@ -27,11 +27,13 @@ LIBOBJS = \
asprintf.o vasprintf.o strlcpy.o strlcat.o \
vsscanf.o zalloc.o \
\
+ lmalloc.o lstrdup.o \
+ \
dprintf.o vdprintf.o \
\
- opendir.o readdir.o closedir.o getcwd.o chdir.o fdopendir.o \
+ sys/readdir.o getcwd.o chdir.o fdopendir.o \
\
- libgcc/__ashldi3.o libgcc/__udivdi3.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 \
@@ -40,6 +42,7 @@ LIBOBJS = \
sys/entry.o sys/exit.o sys/argv.o sys/times.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 \
\
sys/zfile.o sys/zfopen.o \
@@ -117,6 +120,25 @@ LIBOBJS = \
syslinux/video/fontquery.o syslinux/video/forcetext.o \
syslinux/video/reportmode.o
+# These are the objects which are also imported into the core
+LIBCOREOBJS = \
+ memcpy.o mempcpy.o memset.o memcmp.o memmove.o \
+ strlen.o stpcpy.o strcpy.o strcmp.o strlcpy.o strlcat.o \
+ strchr.o strncmp.o strncpy.o \
+ \
+ snprintf.o sprintf.o vsnprintf.o \
+ \
+ dprintf.o vdprintf.o \
+ \
+ zalloc.o strdup.o \
+ \
+ sys/intcall.o sys/farcall.o sys/cfarcall.o sys/zeroregs.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
+
BINDIR = /usr/bin
LIBDIR = /usr/lib
DATADIR = /usr/share
@@ -124,13 +146,18 @@ AUXDIR = $(DATADIR)/syslinux
INCDIR = /usr/include
COM32DIR = $(AUXDIR)/com32
-all: libcom32.a
+all: libcom32.a libcomcore.a
libcom32.a : $(LIBOBJS)
rm -f $@
$(AR) cq $@ $^
$(RANLIB) $@
+libcomcore.a : $(LIBCOREOBJS)
+ rm -f $@
+ $(AR) cq $@ $^
+ $(RANLIB) $@
+
tidy dist clean:
rm -f sys/vesa/alphatbl.c
find . \( -name \*.o -o -name \*.a -o -name .\*.d -o -name \*.tmp \) -print0 | \
diff --git a/com32/lib/closedir.c b/com32/lib/closedir.c
deleted file mode 100644
index a2d11105..00000000
--- a/com32/lib/closedir.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * closedir.c
- */
-
-#include <dirent.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include <com32.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-
-int closedir(DIR * dir)
-{
- int rv;
- com32sys_t regs;
- if (dir == NULL) {
- rv = 0;
- } else {
- memset(&regs, 0, sizeof regs); /* ?Needed? */
- regs.eax.w[0] = 0x0022;
- regs.esi.w[0] = dir->dd_fd;
- __com32.cs_intcall(0x22, &regs, &regs);
- free(dir); /* garbage collection? */
- rv = 0;
- }
- return rv;
-}
diff --git a/com32/lib/com32.ld b/com32/lib/com32.ld
index 36d5b6ed..37ee46cf 100644
--- a/com32/lib/com32.ld
+++ b/com32/lib/com32.ld
@@ -11,8 +11,9 @@ ENTRY(_start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
- . = 0x101000;
+ . = 0;
PROVIDE (__executable_start = .);
+ PROVIDE (_stext = .);
.init :
{
@@ -28,40 +29,52 @@ SECTIONS
{
KEEP (*(.fini))
} =0x90909090
- PROVIDE (__etext = .);
PROVIDE (_etext = .);
- PROVIDE (etext = .);
+
+ __rodata_start = .;
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
+ __rodata_end = .;
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
the linker would then create the section even if it turns out to
be empty, which isn't pretty. */
. = ALIGN(4);
- PROVIDE (__preinit_array_start = .);
- .preinit_array : { *(.preinit_array) }
- PROVIDE (__preinit_array_end = .);
- PROVIDE (__init_array_start = .);
- .init_array : { *(.init_array) }
- PROVIDE (__init_array_end = .);
- PROVIDE (__fini_array_start = .);
- .fini_array : { *(.fini_array) }
- PROVIDE (__fini_array_end = .);
- PROVIDE (__ctors_start = .);
- .ctors :
- {
+ .preinit_array : {
+ PROVIDE (__preinit_array_start = .);
+ *(.preinit_array)
+ PROVIDE (__preinit_array_end = .);
+ }
+ .init_array : {
+ PROVIDE (__init_array_start = .);
+ *(.init_array)
+ PROVIDE (__init_array_end = .);
+ }
+ .fini_array : {
+ PROVIDE (__fini_array_start = .);
+ *(.fini_array)
+ PROVIDE (__fini_array_end = .);
+ }
+ .ctors : {
+ PROVIDE (__ctors_start = .);
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
+ PROVIDE (__ctors_end = .);
}
- PROVIDE (__ctors_end = .);
- PROVIDE (__dtors_start = .);
- .dtors :
- {
+ .dtors : {
+ PROVIDE (__dtors_start = .);
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
+ PROVIDE (__dtors_end = .);
+ }
+
+ .got : {
+ PROVIDE (__got_start = .);
+ KEEP (*(.got.plt))
+ KEEP (*(.got))
+ PROVIDE (__got_end = .);
}
- PROVIDE (__dtors_end = .);
/* Adjust the address for the data segment. Avoid mixing code and
data within same 128-byte chunk. */
@@ -69,12 +82,14 @@ SECTIONS
.data :
{
- *(.data .data.* .gnu.linkonce.d.*)
+ _sdata = .;
+ KEEP(*(.data .data.* .gnu.linkonce.d.*))
SORT(CONSTRUCTORS)
+ *(.data1)
+ . = ALIGN(4);
+ _edata = .;
}
- .data1 : { *(.data1) }
- _edata = .;
- PROVIDE (edata = .);
+
__bss_start = .;
.bss :
{
@@ -84,11 +99,10 @@ SECTIONS
/* 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. */
- . = ALIGN(32 / 8);
+ . = ALIGN(4);
}
- . = ALIGN(32 / 8);
+ . = ALIGN(4);
_end = .;
- PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
diff --git a/com32/lib/fprintf.c b/com32/lib/fprintf.c
index 36b86265..5eb8e079 100644
--- a/com32/lib/fprintf.c
+++ b/com32/lib/fprintf.c
@@ -5,8 +5,6 @@
#include <stdio.h>
#include <stdarg.h>
-#define BUFFER_SIZE 16384
-
int fprintf(FILE * file, const char *format, ...)
{
va_list ap;
diff --git a/com32/lib/lmalloc.c b/com32/lib/lmalloc.c
new file mode 100644
index 00000000..a646556c
--- /dev/null
+++ b/com32/lib/lmalloc.c
@@ -0,0 +1,57 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2010 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <com32.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslinux/pmapi.h>
+
+void *lmalloc(size_t size)
+{
+ void *p;
+ p = __com32.cs_pm->lmalloc(size);
+ if (!p)
+ errno = ENOMEM;
+ return p;
+}
+
+void *lzalloc(size_t size)
+{
+ void *p;
+ p = __com32.cs_pm->lmalloc(size);
+ if (!p)
+ errno = ENOMEM;
+ else
+ memset(p, 0, size);
+ return p;
+}
+
+void lfree(void *ptr)
+{
+ __com32.cs_pm->lfree(ptr);
+}
diff --git a/com32/lib/lstrdup.c b/com32/lib/lstrdup.c
new file mode 100644
index 00000000..d11efe7e
--- /dev/null
+++ b/com32/lib/lstrdup.c
@@ -0,0 +1,18 @@
+/*
+ * lstrdup.c
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <com32.h>
+
+char *lstrdup(const char *s)
+{
+ int l = strlen(s) + 1;
+ char *d = lmalloc(l);
+
+ if (d)
+ memcpy(d, s, l);
+
+ return d;
+}
diff --git a/com32/lib/memmove.S b/com32/lib/memmove.S
index b7ac6767..e97299f2 100644
--- a/com32/lib/memmove.S
+++ b/com32/lib/memmove.S
@@ -1,6 +1,7 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 2008 H. Peter Anvin - All Rights Reserved
+ * Copyright 2010 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
@@ -36,7 +37,7 @@
.type memmove,@function
.text
memmove:
- jecxz 3f
+ jecxz 4f
pushl %esi
pushl %edi
@@ -46,11 +47,12 @@ memmove:
movl %edx,%esi
cmpl %edi,%esi
- jb 1f
+ jb 2f
/* source >= dest, forwards move */
/* Initial alignment */
+1:
movl %edi,%edx
shrl $1,%edx
jnc 11f
@@ -81,14 +83,24 @@ memmove:
jz 15f
movsb
15:
- jmp 2f
+ /* Common exit stub */
+3:
+ popl %eax /* Return value */
+ popl %edi
+ popl %esi
+4:
+ ret
-1:
- /* source < dest, backwards move */
+2:
+ /* source < dest, backwards move if overlap */
+ leal -1(%ecx,%esi),%eax
+ cmpl %eax,%edi
+ ja 1b /* No overlap, after all... */
+
std
- leal -1(%ecx,%esi),%esi
leal -1(%ecx,%edi),%edi
+ movl %eax,%esi
/* Initial alignment */
movl %edi,%edx
@@ -129,11 +141,6 @@ memmove:
movsb
25:
cld
-2:
- popl %eax /* Return value */
- popl %edi
- popl %esi
-3:
- ret
+ jmp 3b
.size memmove, .-memmove
diff --git a/com32/lib/opendir.c b/com32/lib/opendir.c
deleted file mode 100644
index 21fe91d4..00000000
--- a/com32/lib/opendir.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * opendir.c
- */
-
-#include <dirent.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include <com32.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-
-DIR *opendir(const char *pathname)
-{
- DIR *newdir;
- com32sys_t regs;
-
- newdir = NULL;
-
- strlcpy(__com32.cs_bounce, pathname, __com32.cs_bounce_size);
-
- regs.eax.w[0] = 0x0020;
- regs.esi.w[0] = OFFS(__com32.cs_bounce);
- regs.es = SEG(__com32.cs_bounce);
-
- __com32.cs_intcall(0x22, &regs, &regs);
-
- if (!(regs.eflags.l & EFLAGS_CF)) {
- /* Initialization: malloc() then zero */
- newdir = calloc(1, sizeof(DIR));
- strcpy(newdir->dd_name, pathname);
- newdir->dd_fd = regs.esi.w[0];
- newdir->dd_sect = regs.eax.l;
- newdir->dd_stat = 0;
- }
-
- /* We're done */
- return newdir;
-}
diff --git a/com32/lib/printf.c b/com32/lib/printf.c
index a6f5b508..86c2b767 100644
--- a/com32/lib/printf.c
+++ b/com32/lib/printf.c
@@ -5,8 +5,6 @@
#include <stdio.h>
#include <stdarg.h>
-#define BUFFER_SIZE 16384
-
int printf(const char *format, ...)
{
va_list ap;
diff --git a/com32/lib/qsort.c b/com32/lib/qsort.c
index a67866d3..a9d646ce 100644
--- a/com32/lib/qsort.c
+++ b/com32/lib/qsort.c
@@ -6,6 +6,7 @@
*/
#include <stddef.h>
+#include <stdlib.h>
#include <string.h>
static inline size_t newgap(size_t gap)
@@ -27,6 +28,9 @@ void qsort(void *base, size_t nmemb, size_t size,
char *p1, *p2;
int swapped;
+ if (!nmemb)
+ return;
+
do {
gap = newgap(gap);
swapped = 0;
diff --git a/com32/lib/readdir.c b/com32/lib/readdir.c
deleted file mode 100644
index 3737d1ad..00000000
--- a/com32/lib/readdir.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * readdir.c
- */
-
-#include <dirent.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include <com32.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-
-struct dirent *readdir(DIR * dir)
-{
- struct dirent *newde;
- com32sys_t regs;
-
- newde = NULL;
- if ((dir != NULL) && (dir->dd_fd != 0) && (dir->dd_stat >= 0)) {
- memset(__com32.cs_bounce, 0, 32);
- memset(&regs, 0, sizeof(regs));
-
- regs.eax.w[0] = 0x0021;
- regs.esi.w[0] = dir->dd_fd;
- regs.edi.w[0] = OFFS(__com32.cs_bounce);
- regs.es = SEG(__com32.cs_bounce);
-
- __com32.cs_intcall(0x22, &regs, &regs);
-
-#if 0
- /* Don't do this as we won't be able to rewind. */
- dir->dd_fd = regs.esi.w[0]; /* Shouldn't be needed? */
-#endif
- if ((!(regs.eflags.l & EFLAGS_CF)) && (regs.esi.w[0] != 0)) {
- newde = calloc(1, sizeof(newde));
- if (newde != NULL) {
- strcpy(newde->d_name, __com32.cs_bounce);
- newde->d_mode = regs.edx.b[0];
- newde->d_size = regs.eax.l;
- newde->d_ino = regs.ebx.l;
- dir->dd_stat = 1;
- } else {
- dir->dd_stat = -2;
- errno = ENOMEM;
- }
- } else {
- dir->dd_stat = -1;
- errno = EIO; /* Is this the right nmber? */
- }
- } else {
- errno = EBADF;
- }
-
- return newde;
-}
diff --git a/com32/lib/strpcpy.c b/com32/lib/strpcpy.c
deleted file mode 100644
index a4fd2a06..00000000
--- a/com32/lib/strpcpy.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * strpcpy.c
- *
- * strpcpy() - strcpy() which returns a pointer to the final null
- */
-
-#include <string.h>
-
-char *strpcpy(char *dst, const char *src)
-{
- char *q = dst;
- const char *p = src;
- char ch;
-
- do {
- *q++ = ch = *p++;
- } while (ch);
-
- return q - 1;
-}
diff --git a/com32/lib/sys/entry.S b/com32/lib/sys/entry.S
index c34dbdf4..7bfde8b2 100644
--- a/com32/lib/sys/entry.S
+++ b/com32/lib/sys/entry.S
@@ -30,60 +30,84 @@
*/
/* Number of arguments in our version of the entry structure */
-#define COM32_ARGS 8
+#define COM32_ARGS 9
.section ".init","ax"
.globl _start
.type _start, @function
_start:
- /* This first instruction acts as COM32 magic number */
- movl $0x21cd4cff,%eax
+ /* This first instruction acts as COM32R magic number */
+ movl $0x21cd4cfe,%eax
/* Upwards string operations */
cld
+ /* Find our own location */
+ call 1f
+1: popl %ebx
+ addl $_GLOBAL_OFFSET_TABLE_ + (. - 1b), %ebx
+
+ /* Process relocations (which overlay the .bss segment) */
+ leal _edata@GOTOFF(%ebx),%esi
+ leal _start@GOTOFF(%ebx),%edx
+2: lodsl
+ andl %eax,%eax
+ jz 3f
+ addl %edx,(%eax,%edx)
+ jmp 2b
+3:
+ /* Relocate the GOT (is this right?) */
+ leal __got_start@GOTOFF(%ebx),%esi
+ leal __got_end@GOTOFF(%ebx),%edi
+4:
+ addl %edx,(%esi)
+ addl $4,%esi
+ cmpl %edi,%esi
+ jb 4b
+
/* Zero the .bss segment */
xorl %eax,%eax
- movl $__bss_start,%edi # Symbol provided by linker
- movl $_end+3,%ecx # Symbol provided by linker
+ leal __bss_start@GOTOFF(%ebx),%edi
+ leal _end+3@GOTOFF(%ebx),%ecx
subl %edi,%ecx
shrl $2,%ecx
rep ; stosl
/* Copy COM32 invocation parameters */
leal 4(%esp),%esi # Argument list
- movl $__com32,%edi
+ leal __com32@GOTOFF(%ebx),%edi
movl $(COM32_ARGS),%ecx
movl %esp,-4(%edi) # Save the initial stack ptr
cmpl (%esi),%ecx
- jbe 1f
+ jbe 5f
movl (%esi),%ecx
-1: inc %ecx # Copy the argument count, too
+5: inc %ecx # Copy the argument count, too
rep ; movsl
/* Parse the command line (assumes REGPARM) */
- movl __com32+4,%edx # Command line
- pushl %edx # Make space for argv
+ movl __com32+4@GOTOFF(%ebx),%edx # Command line
+ pushl %edx # Make space for argv
movl %esp,%eax
call __parse_argv
- pushl %eax # Save argc
+ pushl %eax # Save argc
/* Look for library initialization functions */
- movl $__ctors_start, %esi
-2:
- cmpl $__ctors_end, %esi
- jae 3f
+ leal __ctors_start@GOTOFF(%ebx),%esi
+ leal __ctors_end@GOTOFF(%ebx),%edi
+6:
+ cmpl %edi,%esi
+ jae 7f
call *(%esi)
addl $4,%esi
- jmp 2b
+ jmp 6b
/*
* Actually run main. This assumes REGPARM is used!!!!
*/
-3:
+7:
popl %eax # argc
popl %edx # argv
call main
- call *(__exit_handler)
+ call *__exit_handler@GOTOFF(%ebx)
hlt
.size _start, .-_start
diff --git a/com32/lib/sys/file.h b/com32/lib/sys/file.h
index fff91b19..e984f160 100644
--- a/com32/lib/sys/file.h
+++ b/com32/lib/sys/file.h
@@ -39,6 +39,7 @@
#include <sys/types.h>
#include <dev.h>
#include <fcntl.h>
+#include <syslinux/pmapi.h>
/* Device structure; contains the relevant operations */
@@ -56,18 +57,18 @@ struct input_dev {
uint16_t dev_magic; /* Magic number */
uint16_t flags; /* Flags */
int fileflags; /* Permitted file flags */
- ssize_t(*read) (struct file_info *, void *, size_t);
- int (*close) (struct file_info *);
- int (*open) (struct file_info *);
+ ssize_t (*read)(struct file_info *, void *, size_t);
+ int (*close)(struct file_info *);
+ int (*open)(struct file_info *);
};
struct output_dev {
uint16_t dev_magic; /* Magic number */
uint16_t flags; /* Flags */
int fileflags;
- ssize_t(*write) (struct file_info *, const void *, size_t);
- int (*close) (struct file_info *);
- int (*open) (struct file_info *);
+ ssize_t (*write)(struct file_info *, const void *, size_t);
+ int (*close)(struct file_info *);
+ int (*open)(struct file_info *);
const struct output_dev *fallback; /* Fallback option for certain consoles */
};
@@ -87,11 +88,8 @@ struct file_info {
/* Structure used for input blocking */
struct {
- int blocklg2; /* Blocksize log 2 */
+ struct com32_filedata fd;
size_t offset; /* Current file offset */
- size_t length; /* Total file length */
- uint16_t filedes; /* File descriptor */
- uint16_t _filler; /* Unused */
size_t nbytes; /* Number of bytes available in buffer */
char *datap; /* Current data pointer */
void *pvt; /* Private pointer for driver */
diff --git a/com32/lib/sys/fileclose.c b/com32/lib/sys/fileclose.c
index e005567e..e2c929f2 100644
--- a/com32/lib/sys/fileclose.c
+++ b/com32/lib/sys/fileclose.c
@@ -38,15 +38,8 @@
int __file_close(struct file_info *fp)
{
- com32sys_t regs;
-
- if (fp->i.filedes) {
- memset(&regs, 0, sizeof regs);
- regs.eax.w[0] = 0x0008; /* Close file */
- regs.esi.w[0] = fp->i.filedes;
-
- __com32.cs_intcall(0x22, &regs, NULL);
- }
+ if (fp->i.fd.handle)
+ __com32.cs_pm->close_file(fp->i.fd.handle);
return 0;
}
diff --git a/com32/lib/sys/fileread.c b/com32/lib/sys/fileread.c
index 54ff7115..aab99c80 100644
--- a/com32/lib/sys/fileread.c
+++ b/com32/lib/sys/fileread.c
@@ -34,32 +34,23 @@
#include <errno.h>
#include <string.h>
#include <com32.h>
+#include <syslinux/pmapi.h>
#include <minmax.h>
#include "file.h"
int __file_get_block(struct file_info *fp)
{
- com32sys_t ireg, oreg;
+ ssize_t bytes_read;
- memset(&ireg, 0, sizeof ireg);
- ireg.eax.w[0] = 0x0007; /* Read file */
- ireg.ebx.w[0] = OFFS(__com32.cs_bounce);
- ireg.es = SEG(__com32.cs_bounce);
- ireg.esi.w[0] = fp->i.filedes;
- ireg.ecx.w[0] = MAXBLOCK >> fp->i.blocklg2;
-
- __intcall(0x22, &ireg, &oreg);
-
- if (oreg.eflags.l & EFLAGS_CF) {
+ bytes_read = __com32.cs_pm->read_file(&fp->i.fd.handle, fp->i.buf,
+ MAXBLOCK >> fp->i.fd.blocklg2);
+ if (!bytes_read) {
errno = EIO;
return -1;
}
-
- fp->i.filedes = oreg.esi.w[0];
- fp->i.nbytes = oreg.ecx.l;
- fp->i.datap = fp->i.buf;
- memcpy(fp->i.buf, __com32.cs_bounce, fp->i.nbytes);
-
+
+ fp->i.nbytes = bytes_read;
+ fp->i.datap = fp->i.buf;
return 0;
}
@@ -71,22 +62,36 @@ ssize_t __file_read(struct file_info * fp, void *buf, size_t count)
while (count) {
if (fp->i.nbytes == 0) {
- if (fp->i.offset >= fp->i.length || !fp->i.filedes)
+ if (fp->i.offset >= fp->i.fd.size || !fp->i.fd.handle)
return n; /* As good as it gets... */
- if (__file_get_block(fp))
- return n ? n : -1;
+ if (count > MAXBLOCK) {
+ /* Large transfer: copy directly, without buffering */
+ ncopy = __com32.cs_pm->read_file(&fp->i.fd.handle, bufp,
+ count >> fp->i.fd.blocklg2);
+ if (!ncopy) {
+ errno = EIO;
+ return n ? n : -1;
+ }
+
+ goto got_data;
+ } else {
+ if (__file_get_block(fp))
+ return n ? n : -1;
+ }
}
ncopy = min(count, fp->i.nbytes);
memcpy(bufp, fp->i.datap, ncopy);
- n += ncopy;
- bufp += ncopy;
- count -= ncopy;
fp->i.datap += ncopy;
fp->i.offset += ncopy;
fp->i.nbytes -= ncopy;
+
+ got_data:
+ n += ncopy;
+ bufp += ncopy;
+ count -= ncopy;
}
return n;
diff --git a/com32/lib/sys/fstat.c b/com32/lib/sys/fstat.c
index 6a853933..0ce8cadb 100644
--- a/com32/lib/sys/fstat.c
+++ b/com32/lib/sys/fstat.c
@@ -45,14 +45,14 @@ int fstat(int fd, struct stat *buf)
}
if (fp->iop->flags & __DEV_FILE) {
- if (fp->i.length == (uint32_t) - 1) {
+ if (fp->i.fd.size == (uint32_t) - 1) {
/* File of unknown length, report it as a socket
(it probably really is, anyway!) */
buf->st_mode = S_IFSOCK | 0444;
buf->st_size = 0;
} else {
buf->st_mode = S_IFREG | 0444;
- buf->st_size = fp->i.length;
+ buf->st_size = fp->i.fd.size;
}
} else {
buf->st_mode = S_IFCHR | 0666;
diff --git a/com32/lib/sys/gpxe.c b/com32/lib/sys/gpxe.c
index fae03f8f..d86da42a 100644
--- a/com32/lib/sys/gpxe.c
+++ b/com32/lib/sys/gpxe.c
@@ -7,39 +7,44 @@ bool is_gpxe(void)
const struct syslinux_version *sv;
com32sys_t reg;
struct s_PXENV_FILE_CHECK_API *fca;
+ bool gpxe;
sv = syslinux_version();
if (sv->filesystem != SYSLINUX_FS_PXELINUX)
return false; /* Not PXELINUX */
- fca = __com32.cs_bounce;
- memset(fca, 0, sizeof *fca);
+ fca = lzalloc(sizeof *fca);
+ if (!fca)
+ return false;
fca->Size = sizeof *fca;
fca->Magic = 0x91d447b2;
memset(&reg, 0, sizeof reg);
reg.eax.w[0] = 0x0009;
reg.ebx.w[0] = 0x00e6; /* PXENV_FILE_API_CHECK */
- reg.edi.w[0] = OFFS(fca);
+ /* reg.edi.w[0] = OFFS(fca); */
reg.es = SEG(fca);
__intcall(0x22, &reg, &reg);
+ gpxe = true;
+
if (reg.eflags.l & EFLAGS_CF)
- return false; /* Cannot invoke PXE stack */
+ gpxe = false; /* Cannot invoke PXE stack */
if (reg.eax.w[0] || fca->Status)
- return false; /* PXE failure */
+ gpxe = false; /* PXE failure */
if (fca->Magic != 0xe9c17b20)
- return false; /* Incorrect magic */
+ gpxe = false; /* Incorrect magic */
if (fca->Size < sizeof *fca)
- return false; /* Short return */
+ gpxe = false; /* Short return */
+ /* XXX: The APIs to test for should be a passed-in option */
if (!(fca->APIMask & (1 << 5)))
- return false; /* No FILE EXEC */
+ gpxe = false; /* No FILE EXEC */
- return true;
+ lfree(fca);
+ return gpxe;
}
-
diff --git a/com32/lib/sys/open.c b/com32/lib/sys/open.c
index aac5e6f4..cb7c1b4d 100644
--- a/com32/lib/sys/open.c
+++ b/com32/lib/sys/open.c
@@ -41,7 +41,7 @@
extern ssize_t __file_read(struct file_info *, void *, size_t);
extern int __file_close(struct file_info *);
-static const struct input_dev file_dev = {
+const struct input_dev __file_dev = {
.dev_magic = __DEV_MAGIC,
.flags = __DEV_FILE | __DEV_INPUT,
.fileflags = O_RDONLY,
@@ -52,38 +52,20 @@ static const struct input_dev file_dev = {
int open(const char *pathname, int flags, ...)
{
- com32sys_t regs;
- int fd;
+ int fd, handle;
struct file_info *fp;
- fd = opendev(&file_dev, NULL, flags);
+ fd = opendev(&__file_dev, NULL, flags);
if (fd < 0)
return -1;
fp = &__file_info[fd];
- strlcpy(__com32.cs_bounce, pathname, __com32.cs_bounce_size);
-
- regs.eax.w[0] = 0x0006;
- regs.esi.w[0] = OFFS(__com32.cs_bounce);
- regs.es = SEG(__com32.cs_bounce);
-
- __com32.cs_intcall(0x22, &regs, &regs);
-
- if ((regs.eflags.l & EFLAGS_CF) || regs.esi.w[0] == 0) {
- close(fd);
- errno = ENOENT;
+ handle = __com32.cs_pm->open_file(pathname, &fp->i.fd);
+ if (handle < 0)
return -1;
- }
- {
- uint16_t blklg2;
- asm("bsrw %1,%0" : "=r" (blklg2) : "rm" (regs.ecx.w[0]));
- fp->i.blocklg2 = blklg2;
- }
- fp->i.length = regs.eax.l;
- fp->i.filedes = regs.esi.w[0];
fp->i.offset = 0;
fp->i.nbytes = 0;
diff --git a/com32/lib/sys/openmem.c b/com32/lib/sys/openmem.c
new file mode 100644
index 00000000..a56a4af8
--- /dev/null
+++ b/com32/lib/sys/openmem.c
@@ -0,0 +1,61 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2003-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <errno.h>
+#include <com32.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "file.h"
+
+/*
+ * openmem.c
+ *
+ * Open a chunk of memory as if it was a file
+ */
+
+const struct input_dev __file_dev;
+
+int openmem(const void *base, size_t len, int flags)
+{
+ int fd;
+ struct file_info *fp;
+
+ fd = opendev(&__file_dev, NULL, flags);
+
+ if (fd < 0)
+ return -1;
+
+ fp = &__file_info[fd];
+
+ fp->i.fd.size = fp->i.nbytes = len;
+ fp->i.datap = (void *)base;
+ fp->i.fd.handle = 0; /* No actual file */
+ fp->i.offset = 0;
+
+ return fd;
+}
diff --git a/com32/lib/sys/readdir.c b/com32/lib/sys/readdir.c
new file mode 100644
index 00000000..d2a8c039
--- /dev/null
+++ b/com32/lib/sys/readdir.c
@@ -0,0 +1,30 @@
+/*
+ * readdir.c
+ */
+
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <com32.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include <syslinux/pmapi.h>
+
+DIR *opendir(const char *pathname)
+{
+ return __com32.cs_pm->opendir(pathname);
+}
+
+struct dirent *readdir(DIR *dir)
+{
+ return __com32.cs_pm->readdir(dir);
+}
+
+int closedir(DIR *dir)
+{
+ return __com32.cs_pm->closedir(dir);
+}
diff --git a/com32/lib/sys/stdcon_write.c b/com32/lib/sys/stdcon_write.c
index 8cc6b5f5..9cb2f7db 100644
--- a/com32/lib/sys/stdcon_write.c
+++ b/com32/lib/sys/stdcon_write.c
@@ -37,6 +37,23 @@
#include <minmax.h>
#include "file.h"
+#define BIOS_ROWS (*(uint8_t *)0x484) /* Minus one; if zero use 24 (= 25 lines) */
+#define BIOS_COLS (*(uint16_t *)0x44A)
+
+static int __stdcon_open(struct file_info *fp)
+{
+ fp->o.rows = BIOS_ROWS + 1;
+ fp->o.cols = BIOS_COLS;
+
+ /* Sanity check */
+ if (fp->o.rows < 12)
+ fp->o.rows = 24;
+ if (fp->o.cols < 40)
+ fp->o.cols = 80;
+
+ return 0;
+}
+
static ssize_t __stdcon_write(struct file_info *fp, const void *buf,
size_t count)
{
@@ -68,5 +85,5 @@ const struct output_dev dev_stdcon_w = {
.fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND,
.write = __stdcon_write,
.close = NULL,
- .open = NULL,
+ .open = __stdcon_open,
};
diff --git a/com32/lib/sys/vesa/initvesa.c b/com32/lib/sys/vesa/initvesa.c
index 0a436f4c..9a1ae384 100644
--- a/com32/lib/sys/vesa/initvesa.c
+++ b/com32/lib/sys/vesa/initvesa.c
@@ -95,9 +95,13 @@ 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;
+
+ debug("Hello, World!\r\n");
/* Free any existing data structures */
if (__vesacon_background) {
@@ -110,13 +114,15 @@ static int vesacon_set_mode(int x, int y)
}
/* Allocate space in the bounce buffer for these structures */
- gi = &((struct vesa_info *)__com32.cs_bounce)->gi;
- mi = &((struct vesa_info *)__com32.cs_bounce)->mi;
-
- debug("Hello, World!\r\n");
+ vi = lzalloc(sizeof *vi);
+ if (!vi) {
+ err = 10; /* Out of memory */
+ goto exit;
+ }
+ gi = &vi->gi;
+ mi = &vi->mi;
memset(&rm, 0, sizeof rm);
- memset(gi, 0, sizeof *gi);
gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */
rm.eax.w[0] = 0x4F00; /* Get SVGA general information */
@@ -124,12 +130,18 @@ static int vesacon_set_mode(int x, int y)
rm.es = SEG(gi);
__intcall(0x10, &rm, &rm);
- if (rm.eax.w[0] != 0x004F)
- return 1; /* Function call failed */
- if (gi->signature != VESA_MAGIC)
- return 2; /* No magic */
- if (gi->version < 0x0102)
- return 3; /* VESA 1.2+ required */
+ 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);
@@ -232,8 +244,10 @@ static int vesacon_set_mode(int x, int y)
}
}
- if (bestpxf == PXF_NONE)
- return 4; /* No mode found */
+ if (bestpxf == PXF_NONE) {
+ err = 4; /* No mode found */
+ goto exit;
+ }
mi = &__vesa_info.mi;
mode = bestmode;
@@ -260,8 +274,10 @@ static int vesacon_set_mode(int x, int y)
mode |= 0x4000; /* Request linear framebuffer if supported */
rm.ebx.w[0] = mode;
__intcall(0x10, &rm, &rm);
- if (rm.eax.w[0] != 0x004F)
- return 9; /* Failed to set mode */
+ 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);
@@ -279,7 +295,11 @@ static int vesacon_set_mode(int x, int y)
__vesacon_pixel_format = bestpxf;
- return 0;
+exit:
+ if (vi)
+ lfree(vi);
+
+ return err;
}
static int init_text_display(void)
diff --git a/com32/lib/sys/zfile.c b/com32/lib/sys/zfile.c
index a1213a94..0e6ba916 100644
--- a/com32/lib/sys/zfile.c
+++ b/com32/lib/sys/zfile.c
@@ -75,7 +75,7 @@ static int gzip_file_init(struct file_info *fp)
}
fp->iop = &gzip_file_dev;
- fp->i.length = -1; /* Unknown */
+ fp->i.fd.size = -1; /* Unknown */
return 0;
}
@@ -92,7 +92,7 @@ static ssize_t gzip_file_read(struct file_info *fp, void *ptr, size_t n)
zs->next_out = p;
zs->avail_out = n;
- if (!zs->avail_in && fp->i.filedes) {
+ if (!zs->avail_in && fp->i.fd.handle) {
if (__file_get_block(fp))
return nout ? nout : -1;
@@ -154,7 +154,9 @@ int zopen(const char *pathname, int flags, ...)
if (__file_get_block(fp))
goto err;
- if (fp->i.nbytes >= 14 && (uint8_t) fp->i.buf[0] == 037 && (uint8_t) fp->i.buf[1] == 0213 && /* gzip */
+ if (fp->i.nbytes >= 14 &&
+ (uint8_t) fp->i.buf[0] == 037 &&
+ (uint8_t) fp->i.buf[1] == 0213 && /* gzip */
fp->i.buf[2] == 8) /* deflate */
rv = gzip_file_init(fp);
else
diff --git a/com32/lib/syslinux/idle.c b/com32/lib/syslinux/idle.c
index 8a0d206c..ddaa7fcd 100644
--- a/com32/lib/syslinux/idle.c
+++ b/com32/lib/syslinux/idle.c
@@ -33,25 +33,15 @@
#include <stddef.h>
#include <com32.h>
-#include <sys/cpu.h>
+#include <syslinux/pmapi.h>
#include <syslinux/idle.h>
-void syslinux_idle(void)
+void syslinux_reset_idle(void)
{
- static int do_idle = 1;
- static const com32sys_t sys_idle = {
- .eax.l = 0x0013,
- };
- com32sys_t idle_result;
-
- /* This call isn't supported on SYSLINUX < 3.08, but all it does
- is return an error, so we don't care. */
-
- if (do_idle) {
- __intcall(0x22, &sys_idle, &idle_result);
-
- do_idle = ~idle_result.eflags.l & EFLAGS_CF;
- }
+ __com32.cs_pm->reset_idle();
+}
- cpu_relax();
+void syslinux_idle(void)
+{
+ __com32.cs_pm->idle();
}
diff --git a/com32/lib/syslinux/memscan.c b/com32/lib/syslinux/memscan.c
index 95580257..fc676cbf 100644
--- a/com32/lib/syslinux/memscan.c
+++ b/com32/lib/syslinux/memscan.c
@@ -51,7 +51,7 @@ int syslinux_scan_memory(scan_memory_callback_t callback, void *data)
{
static com32sys_t ireg;
com32sys_t oreg;
- struct e820_entry *e820buf = __com32.cs_bounce;
+ struct e820_entry *e820buf;
uint64_t start, len, maxlen;
int memfound = 0;
int rv;
@@ -74,13 +74,16 @@ int syslinux_scan_memory(scan_memory_callback_t callback, void *data)
return rv;
/* First try INT 15h AX=E820h */
+ e820buf = lzalloc(sizeof *e820buf);
+ if (!e820buf)
+ return -1;
+
ireg.eax.l = 0xe820;
ireg.edx.l = 0x534d4150;
ireg.ebx.l = 0;
ireg.ecx.l = sizeof(*e820buf);
ireg.es = SEG(e820buf);
ireg.edi.w[0] = OFFS(e820buf);
- memset(e820buf, 0, sizeof *e820buf);
do {
__intcall(0x15, &ireg, &oreg);
@@ -120,6 +123,8 @@ int syslinux_scan_memory(scan_memory_callback_t callback, void *data)
ireg.ebx.l = oreg.ebx.l;
} while (oreg.ebx.l);
+ lfree(e820buf);
+
if (memfound)
return 0;
diff --git a/com32/lib/syslinux/pxe_dns.c b/com32/lib/syslinux/pxe_dns.c
index 9ab95137..6620396f 100644
--- a/com32/lib/syslinux/pxe_dns.c
+++ b/com32/lib/syslinux/pxe_dns.c
@@ -48,21 +48,26 @@ uint32_t pxe_dns(const char *hostname)
unsigned char b[4];
uint32_t ip;
} q;
+ char *lm_hostname;
/* Is this a dot-quad? */
if (sscanf(hostname, "%hhu.%hhu.%hhu.%hhu",
&q.b[0], &q.b[1], &q.b[2], &q.b[3]) == 4)
return q.ip;
+ lm_hostname = lstrdup(hostname);
+ if (!lm_hostname)
+ return 0;
+
memset(&regs, 0, sizeof regs);
regs.eax.w[0] = 0x0010;
- regs.es = SEG(__com32.cs_bounce);
- regs.ebx.w[0] = OFFS(__com32.cs_bounce);
-
- strcpy((char *)__com32.cs_bounce, hostname);
+ regs.es = SEG(lm_hostname);
+ /* regs.ebx.w[0] = OFFS(lm_hostname); */
__intcall(0x22, &regs, &regs);
+ lfree(lm_hostname);
+
if (regs.eflags.l & EFLAGS_CF)
return 0;
diff --git a/com32/lib/syslinux/pxe_get_cached.c b/com32/lib/syslinux/pxe_get_cached.c
index 2e8349fe..47040378 100644
--- a/com32/lib/syslinux/pxe_get_cached.c
+++ b/com32/lib/syslinux/pxe_get_cached.c
@@ -42,40 +42,55 @@
or -1 on invocation failure */
int pxe_get_cached_info(int level, void **buf, size_t * len)
{
+ const int max_dhcp_packet = 2048;
com32sys_t regs;
- t_PXENV_GET_CACHED_INFO *gci = __com32.cs_bounce;
+ t_PXENV_GET_CACHED_INFO *gci;
void *bbuf, *nbuf;
+ int err;
+
+ gci = lmalloc(sizeof *gci + max_dhcp_packet);
+ if (!gci)
+ return -1;
memset(&regs, 0, sizeof regs);
regs.eax.w[0] = 0x0009;
regs.ebx.w[0] = PXENV_GET_CACHED_INFO;
regs.es = SEG(gci);
- regs.edi.w[0] = OFFS(gci);
+ /* regs.edi.w[0] = OFFS(gci); */
bbuf = &gci[1];
gci->Status = PXENV_STATUS_FAILURE;
gci->PacketType = level;
- gci->BufferSize = gci->BufferLimit = 65536 - sizeof(*gci);
+ gci->BufferSize = gci->BufferLimit = max_dhcp_packet;
gci->Buffer.seg = SEG(bbuf);
gci->Buffer.offs = OFFS(bbuf);
__intcall(0x22, &regs, &regs);
- if (regs.eflags.l & EFLAGS_CF)
- return -1;
+ if (regs.eflags.l & EFLAGS_CF) {
+ err = -1;
+ goto exit;
+ }
- if (gci->Status)
- return gci->Status;
+ if (gci->Status) {
+ err = gci->Status;
+ goto exit;
+ }
- nbuf = malloc(gci->BufferSize); /* malloc() does not use the bounce buffer */
- if (!nbuf)
- return -1;
+ nbuf = malloc(gci->BufferSize);
+ if (!nbuf) {
+ err = -1;
+ goto exit;
+ }
memcpy(nbuf, bbuf, gci->BufferSize);
*buf = nbuf;
*len = gci->BufferSize;
+ err = 0;
- return 0;
+exit:
+ lfree(gci);
+ return err;
}
diff --git a/com32/lib/syslinux/pxe_get_nic.c b/com32/lib/syslinux/pxe_get_nic.c
index 704a0d79..b301a75a 100644
--- a/com32/lib/syslinux/pxe_get_nic.c
+++ b/com32/lib/syslinux/pxe_get_nic.c
@@ -40,19 +40,25 @@
/* Returns the status code from PXE (0 on success),
or -1 on invocation failure */
-int pxe_get_nic_type(t_PXENV_UNDI_GET_NIC_TYPE * gnt)
+int pxe_get_nic_type(t_PXENV_UNDI_GET_NIC_TYPE *gnt)
{
com32sys_t regs;
+ t_PXENV_UNDI_GET_NIC_TYPE *lgnt;
+
+ lgnt = lzalloc(sizeof *lgnt);
+ if (!lgnt)
+ return -1;
memset(&regs, 0, sizeof regs);
regs.eax.w[0] = 0x0009;
regs.ebx.w[0] = PXENV_UNDI_GET_NIC_TYPE;
- regs.es = SEG(__com32.cs_bounce);
- regs.edi.w[0] = OFFS(__com32.cs_bounce);
+ regs.es = SEG(lgnt);
+ /* regs.edi.w[0] = OFFS(lgnt); */
__intcall(0x22, &regs, &regs);
- memcpy(gnt, __com32.cs_bounce, sizeof(t_PXENV_UNDI_GET_NIC_TYPE));
+ memcpy(gnt, lgnt, sizeof(t_PXENV_UNDI_GET_NIC_TYPE));
+ lfree(lgnt);
if (regs.eflags.l & EFLAGS_CF)
return -1;
diff --git a/com32/lib/syslinux/run_command.c b/com32/lib/syslinux/run_command.c
index 4693e16d..a0ac9a0d 100644
--- a/com32/lib/syslinux/run_command.c
+++ b/com32/lib/syslinux/run_command.c
@@ -30,18 +30,21 @@
#include <string.h>
#include <com32.h>
-__noreturn syslinux_run_command(const char *command)
+int syslinux_run_command(const char *command)
{
static com32sys_t ireg;
+ char *lm_command = lstrdup(command);
- strcpy(__com32.cs_bounce, command);
-
+ if (!lm_command)
+ return -1;
+
ireg.eax.w[0] = 0x0003;
- ireg.es = SEG(__com32.cs_bounce);
- ireg.ebx.w[0] = OFFS(__com32.cs_bounce);
+ ireg.es = SEG(lm_command);
+ /* ireg.ebx.w[0] = OFFS(lm_command); */
__intcall(0x22, &ireg, NULL);
- /* Should not return even on failure */
- for (;;) ;
+ /* Should not return even on failure, but in case... */
+ lfree(lm_command);
+ return -1;
}
diff --git a/com32/lib/syslinux/runimage.c b/com32/lib/syslinux/runimage.c
index 0184df37..29e9aadd 100644
--- a/com32/lib/syslinux/runimage.c
+++ b/com32/lib/syslinux/runimage.c
@@ -40,26 +40,32 @@ void syslinux_run_kernel_image(const char *filename, const char *cmdline,
uint32_t ipappend_flags, uint32_t type)
{
static com32sys_t ireg;
- char *bbfilename, *bbcmdline, *bbptr;
+ char *bbfilename = NULL;
+ char *bbcmdline = NULL;
int bytes;
- bbptr = __com32.cs_bounce;
+ bbfilename = lstrdup(filename);
+ if (!bbfilename)
+ goto fail;
- bytes = strlen(filename) + 1;
- memcpy(bbfilename = bbptr, filename, bytes);
- bbptr += bytes;
+ bbcmdline = lstrdup(cmdline);
+ if (!bbcmdline)
+ goto fail;
- bytes = strlen(cmdline) + 1;
- memcpy(bbcmdline = bbptr, filename, bytes);
- bbptr += bytes;
ireg.eax.w[0] = 0x0016;
ireg.ds = SEG(bbfilename);
- ireg.esi.w[0] = OFFS(bbfilename);
+ /* ireg.esi.w[0] = OFFS(bbfilename); */
ireg.es = SEG(bbcmdline);
- ireg.ebx.w[0] = OFFS(bbcmdline);
+ /* ireg.ebx.w[0] = OFFS(bbcmdline); */
ireg.ecx.l = ipappend_flags;
ireg.edx.l = type;
__intcall(0x22, &ireg, 0);
+
+fail:
+ if (bbcmdline)
+ lfree(bbcmdline);
+ if (bbfilename)
+ lfree(bbfilename);
}
diff --git a/com32/lib/vdprintf.c b/com32/lib/vdprintf.c
index ea9e0488..330279b3 100644
--- a/com32/lib/vdprintf.c
+++ b/com32/lib/vdprintf.c
@@ -14,15 +14,41 @@
#define DEBUG 1
#include <dprintf.h>
-#define BUFFER_SIZE 32768
+#define BUFFER_SIZE 4096
+enum serial_port_regs {
+ THR = 0,
+ RBR = 0,
+ DLL = 0,
+ DLM = 1,
+ IER = 1,
+ IIR = 2,
+ FCR = 2,
+ LCR = 3,
+ MCR = 4,
+ LSR = 5,
+ MSR = 6,
+ SCR = 7,
+};
static const uint16_t debug_base = 0x03f8; /* I/O base address */
+static void debug_putc(char c)
+{
+ if (c == '\n')
+ debug_putc('\r');
+
+ while ((inb(debug_base + LSR) & 0x20) == 0)
+ cpu_relax();
+ outb(c, debug_base + THR);
+}
+
void vdprintf(const char *format, va_list ap)
{
int rv;
char buffer[BUFFER_SIZE];
char *p;
+ static bool debug_init = false;
+ static bool debug_ok = false;
rv = vsnprintf(buffer, BUFFER_SIZE, format, ap);
@@ -37,10 +63,49 @@ void vdprintf(const char *format, va_list ap)
* if one is enabled or not (this means we don't have to enable the real
* serial console and therefore get conflicting output.)
*/
- p = buffer;
- while (rv--) {
- while ((inb(debug_base+5) & 0x20) == 0)
- cpu_relax();
- outb(*p++, debug_base);
+ if (__unlikely(!debug_init)) {
+ uint8_t dll, dlm, lcr;
+
+ debug_init = true;
+
+ cli();
+
+ /* Initialize the serial port to 115200 n81 with FIFOs enabled */
+ outb(0x83, debug_base + LCR);
+ outb(0x01, debug_base + DLL);
+ outb(0x00, debug_base + DLM);
+ (void)inb(debug_base + IER); /* Synchronize */
+ dll = inb(debug_base + DLL);
+ dlm = inb(debug_base + DLM);
+ lcr = inb(debug_base + LCR);
+
+ outb(0x03, debug_base + LCR);
+ (void)inb(debug_base + IER); /* Synchronize */
+
+ outb(0x00, debug_base + IER);
+ (void)inb(debug_base + IER); /* Synchronize */
+
+ sti();
+
+ if (dll != 0x01 || dlm != 0x00 || lcr != 0x83) {
+ /* No serial port present */
+ return;
+ }
+
+ outb(0x01, debug_base + FCR);
+ (void)inb(debug_base + IER); /* Synchronize */
+ if (inb(debug_base + IIR) < 0xc0) {
+ outb(0x00, debug_base + FCR); /* Disable non-functional FIFOs */
+ (void)inb(debug_base + IER); /* Synchronize */
+ }
+
+ debug_ok = true;
}
+
+ if (!debug_ok)
+ return;
+
+ p = buffer;
+ while (rv--)
+ debug_putc(*p++);
}
diff --git a/com32/mboot/mboot.c b/com32/mboot/mboot.c
index 915c7857..35450e03 100644
--- a/com32/mboot/mboot.c
+++ b/com32/mboot/mboot.c
@@ -135,7 +135,7 @@ static int get_modules(char **argv, struct module_data **mdp)
char *p;
mp->cmdline = p = malloc(arglen);
for (; *argp && strcmp(*argp, module_separator); argp++) {
- p = strpcpy(p, *argp);
+ p = stpcpy(p, *argp);
*p++ = ' ';
}
*--p = '\0';
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index 44bc1dfb..40df0c86 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -21,8 +21,8 @@ include ../MCONFIG
MODULES = chain.c32 config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \
disk.c32 pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 \
meminfo.c32 sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 \
- kbdmap.c32 cmd.c32 vpdtest.c32 gpxecmd.c32 ifcpu.c32 \
- cpuid.c32
+ kbdmap.c32 cmd.c32 vpdtest.c32 host.c32 dir.c32 gpxecmd.c32 \
+ ifcpu.c32 cpuid.c32
TESTFILES =
diff --git a/com32/modules/dir.c b/com32/modules/dir.c
new file mode 100644
index 00000000..c9d93708
--- /dev/null
+++ b/com32/modules/dir.c
@@ -0,0 +1,177 @@
+/*
+ * Display directory contents
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <console.h>
+#include <string.h>
+#include <com32.h>
+#include <dirent.h>
+#include <minmax.h>
+#include <unistd.h>
+#include <getkey.h>
+
+static int rows, cols; /* Screen parameters */
+
+#define DIR_CHUNK 1024
+
+static const char *type_str(int type)
+{
+ switch (type) {
+ case DT_FIFO:
+ return "[fif]";
+ case DT_CHR:
+ return "[chr]";
+ case DT_DIR:
+ return "[dir]";
+ case DT_BLK:
+ return "[blk]";
+ case DT_UNKNOWN:
+ case DT_REG:
+ return "";
+ case DT_LNK:
+ return "[lnk]";
+ case DT_SOCK:
+ return "[sck]";
+ case DT_WHT:
+ return "[wht]";
+ default:
+ return "[???]";
+ }
+}
+
+static void free_dirents(struct dirent **dex, size_t n_de)
+{
+ size_t i;
+
+ for (i = 0; i < n_de; i++)
+ free(dex[i]);
+
+ free(dex);
+}
+
+static int compare_dirent(const void *p_de1, const void *p_de2)
+{
+ const struct dirent *de1 = *(const struct dirent **)p_de1;
+ const struct dirent *de2 = *(const struct dirent **)p_de2;
+ int ndir1, ndir2;
+
+ ndir1 = de1->d_type != DT_DIR;
+ ndir2 = de2->d_type != DT_DIR;
+
+ if (ndir1 != ndir2)
+ return ndir1 - ndir2;
+
+ return strcmp(de1->d_name, de2->d_name);
+}
+
+static int display_directory(const char *dirname)
+{
+ DIR *dir;
+ struct dirent *de;
+ struct dirent **dex = NULL;
+ size_t n_dex = 0, n_de = 0;
+ size_t i, j, k;
+ size_t nrows, ncols, perpage;
+ size_t endpage;
+ int maxlen = 0;
+ int pos, tpos, colwidth;
+
+ dir = opendir(dirname);
+ if (!dir) {
+ printf("Unable to read directory: %s\n", dirname);
+ return -1;
+ }
+
+ while ((de = readdir(dir)) != NULL) {
+ struct dirent *nde;
+
+ if (n_de >= n_dex) {
+ struct dirent **ndex;
+
+ ndex = realloc(dex, (n_dex + DIR_CHUNK) * sizeof *dex);
+ if (!ndex)
+ goto nomem;
+
+ dex = ndex;
+ n_dex += DIR_CHUNK;
+ }
+
+ nde = malloc(de->d_reclen);
+ if (!nde)
+ goto nomem;
+
+ memcpy(nde, de, de->d_reclen);
+ dex[n_de++] = nde;
+
+ maxlen = max(maxlen, de->d_reclen);
+ }
+
+ closedir(dir);
+
+ qsort(dex, n_de, sizeof *dex, compare_dirent);
+
+ maxlen -= offsetof(struct dirent, d_name) + 1;
+ ncols = (cols + 2)/(maxlen + 8);
+ ncols = min(ncols, n_de);
+ ncols = max(ncols, 1U);
+ colwidth = (cols + 2)/ncols;
+ perpage = ncols * (rows - 1);
+
+ for (i = 0; i < n_de; i += perpage) {
+ /* Rows on this page */
+ endpage = min(i+perpage, n_de);
+ nrows = ((endpage-i) + ncols - 1)/ncols;
+
+ for (j = 0; j < nrows; j++) {
+ pos = tpos = 0;
+ for (k = i+j; k < endpage; k += nrows) {
+ pos += printf("%*s%-5s %s",
+ (tpos - pos), "",
+ type_str(dex[k]->d_type),
+ dex[k]->d_name);
+ tpos += colwidth;
+ }
+ printf("\n");
+ }
+
+ if (endpage >= n_de)
+ break;
+
+ get_key(stdin, 0);
+ }
+
+ free_dirents(dex, n_de);
+ return 0;
+
+nomem:
+ closedir(dir);
+ printf("Out of memory error!\n");
+ free_dirents(dex, n_de);
+ return -1;
+}
+
+int main(int argc, char *argv[])
+{
+ int rv;
+
+ openconsole(&dev_rawcon_r, &dev_stdcon_w);
+
+ if (getscreensize(1, &rows, &cols)) {
+ /* Unknown screen size? */
+ rows = 24;
+ cols = 80;
+ }
+
+ if (argc < 2)
+ rv = display_directory(".");
+ else if (argc == 2)
+ rv = display_directory(argv[1]);
+ else {
+ printf("Usage: dir directory\n");
+ rv = 1;
+ }
+
+ return rv ? 1 : 0;
+}
+
diff --git a/com32/modules/host.c b/com32/modules/host.c
new file mode 100644
index 00000000..94ca876d
--- /dev/null
+++ b/com32/modules/host.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+#include <console.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <com32.h>
+
+static struct in_addr dnsresolve(const char *hostname)
+{
+ com32sys_t regs;
+ struct in_addr addr;
+
+ strcpy(__com32.cs_bounce, hostname);
+
+ regs.eax.w[0] = 0x0010;
+ regs.es = SEG(__com32.cs_bounce);
+ regs.ebx.w[0] = OFFS(__com32.cs_bounce);
+ __intcall(0x22, &regs, &regs);
+
+ addr.s_addr = regs.eax.l;
+ return addr;
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ struct in_addr addr;
+
+ openconsole(&dev_null_r, &dev_stdcon_w);
+
+ for (i = 1; i < argc; i++) {
+ addr = dnsresolve(argv[i]);
+
+ printf("%-39s %08X %d.%d.%d.%d\n",
+ argv[i], ntohl(addr.s_addr),
+ ((uint8_t *)&addr.s_addr)[0],
+ ((uint8_t *)&addr.s_addr)[1],
+ ((uint8_t *)&addr.s_addr)[2],
+ ((uint8_t *)&addr.s_addr)[3]);
+ }
+
+ return 0;
+}
diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c
index 720d8644..aa3e4532 100644
--- a/com32/rosh/rosh.c
+++ b/com32/rosh/rosh.c
@@ -389,12 +389,12 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr)
ROSH_DEBUG("--'%s'\n", filestr);
}
fd = open(filestr, O_RDONLY);
- if (fd != -1) {
+ if (fd == -1) {
status = fstat(fd, &fdstat);
- if (S_ISDIR(fdstat.st_mode)) {
+ if (S_ISDIR(fdstat.st_mode)) {
ROSH_DEBUG("PATH '%s' is a directory\n", ifilstr);
d = fdopendir(fd);
- de = readdir(d);
+ de = readdir(d);
while (de != NULL) {
#ifdef DO_DEBUG
filestr2[0] = 0;
@@ -423,19 +423,18 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr)
}
} else {
#ifdef __COM32__
- if (filestr[strlen(filestr) - 1] == SEP) {
+ if (filestr[strlen(filestr) - 1] == SEP) {
/* Directory */
filepos = 0;
- d = opendir(filestr);
+ d = opendir(filestr);
if (d != NULL) {
- printf("DIR:'%s' %8d %8d\n", d->dd_name, d->dd_fd,
- d->dd_sect);
+ //printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect, d->dd_offset);
de = readdir(d);
while (de != NULL) {
filepos++;
#ifdef DO_DEBUG
// if (strlen(de->d_name) > 25) de->d_name[25] = 0;
- switch (de->d_mode) {
+ switch (de->d_type) {
case 16:
ty = 'D';
break;
@@ -445,8 +444,6 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr)
default:
ty = '*';
}
- printf("@%8d:%8d:%4d ", (int)de->d_ino, (int)de->d_size,
- de->d_mode);
#endif /* DO_DEBUG */
// printf("%s\n", de->d_name);
printf("'%s'\n", de->d_name);
@@ -454,11 +451,9 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr)
// inchar = fgetc(stdin);
// fgets(instr, ROSH_CMD_SZ, stdin);
#endif /* DO_DEBUG */
- free(de);
de = readdir(d);
// if(filepos>15){ de = NULL; printf("Force Break\n");}
}
- printf("Dir.dd_fd: '%8d'\n", d->dd_fd);
closedir(d);
} else {
rosh_error(0, "dir:NULL", filestr);
diff --git a/com32/rosh/rosh.h b/com32/rosh/rosh.h
index 64b0564c..0c41bac9 100644
--- a/com32/rosh/rosh.h
+++ b/com32/rosh/rosh.h
@@ -47,6 +47,8 @@
#error SYSLINUX (I believe) requires __GNUC__
#endif /* __GNUC__ */
+#define DO_DEBUG 1
+
#ifdef DO_DEBUG
#define ROSH_DEBUG(f, ...) printf (f, ## __VA_ARGS__)
#ifdef DO_DEBUG2
diff --git a/com32/sysdump/cpuid.c b/com32/sysdump/cpuid.c
index 40b20618..ac80f229 100644
--- a/com32/sysdump/cpuid.c
+++ b/com32/sysdump/cpuid.c
@@ -39,11 +39,10 @@ static bool has_eflag(uint32_t flag)
return !!((f0^f1) & flag);
}
-static inline void get_cpuid(uint32_t eax, uint32_t ecx,
- struct cpuid_data *data)
+static void get_cpuid(uint32_t eax, uint32_t ecx, struct cpuid_data *data)
{
- asm("cpuid"
- : "=a" (data->eax), "=b" (data->ebx),
+ 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));
}
diff --git a/com32/sysdump/ctime.c b/com32/sysdump/ctime.c
index 5af85666..56c8efb6 100644
--- a/com32/sysdump/ctime.c
+++ b/com32/sysdump/ctime.c
@@ -58,6 +58,13 @@ uint32_t posix_time(void)
mo += 12;
}
+ /*
+ * Just in case: if the month is nonsense, don't read off the end
+ * of the table...
+ */
+ if (mo-3 > 11)
+ return 0;
+
t = y*365 + y/4 - y/100 + y/400 + yday[mo-3] + d - 719469;
t *= 24;
t += h;
diff --git a/com32/tools/.gitignore b/com32/tools/.gitignore
new file mode 100644
index 00000000..b5397de4
--- /dev/null
+++ b/com32/tools/.gitignore
@@ -0,0 +1 @@
+/relocs
diff --git a/com32/tools/Makefile b/com32/tools/Makefile
new file mode 100644
index 00000000..e34296b4
--- /dev/null
+++ b/com32/tools/Makefile
@@ -0,0 +1,30 @@
+## -*- makefile -*- ------------------------------------------------------
+##
+## Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+## Boston MA 02111-1307, USA; either version 2 of the License, or
+## (at your option) any later version; incorporated herein by reference.
+##
+## -----------------------------------------------------------------------
+
+topdir = ../..
+include $(topdir)/MCONFIG.build
+
+BINS = relocs
+
+all : $(BINS)
+
+relocs : relocs.o
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+tidy dist clean spotless:
+ rm -f $(BINS)
+ rm -f *.o *.a .*.d
+ rm -f */*.o */*.a */.*.d
+
+install installer:
+
+-include .*.d */.*.d
diff --git a/com32/tools/relocs.c b/com32/tools/relocs.c
new file mode 100644
index 00000000..be57bf7e
--- /dev/null
+++ b/com32/tools/relocs.c
@@ -0,0 +1,693 @@
+/*
+ * This file is taken from the Linux kernel and is distributed under GPL v2.
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <elf.h>
+#include <byteswap.h>
+#define USE_BSD
+#include <endian.h>
+#include <regex.h>
+#include <sys/types.h>
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+static Elf32_Ehdr ehdr;
+static unsigned long reloc_count, reloc_idx;
+static unsigned long *relocs;
+
+struct section {
+ Elf32_Shdr shdr;
+ struct section *link;
+ Elf32_Sym *symtab;
+ Elf32_Rel *reltab;
+ char *strtab;
+};
+static struct section *secs;
+
+static void die(char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ exit(1);
+}
+
+/*
+ * Following symbols have been audited. Don't warn user about
+ * absolute relocations present w.r.t these symbols.
+ */
+
+/* True absolute relocations */
+
+static const char safe_abs_regex[] =
+"^(__.*_len|__.*_dwords)$";
+static regex_t safe_abs_regex_c;
+
+static int is_safe_abs_reloc(const char *sym_name)
+{
+ return !regexec(&safe_abs_regex_c, sym_name, 0, NULL, 0);
+}
+
+/* These are relative even though the linker marks them absolute */
+
+static const char safe_rel_regex[] =
+"^(__.*_start|__.*_end|_end|_[se](text|data))$";
+static regex_t safe_rel_regex_c;
+
+static int is_safe_rel_reloc(const char *sym_name)
+{
+ return !regexec(&safe_rel_regex_c, sym_name, 0, NULL, 0);
+}
+
+static void regex_init(void)
+{
+ char errbuf[128];
+ int err;
+
+ err = regcomp(&safe_abs_regex_c, safe_abs_regex,
+ REG_EXTENDED|REG_NOSUB);
+ if (err) {
+ regerror(err, &safe_abs_regex_c, errbuf, sizeof errbuf);
+ die("%s", errbuf);
+ }
+
+ err = regcomp(&safe_rel_regex_c, safe_rel_regex,
+ REG_EXTENDED|REG_NOSUB);
+ if (err) {
+ regerror(err, &safe_rel_regex_c, errbuf, sizeof errbuf);
+ die("%s", errbuf);
+ }
+}
+
+static const char *sym_type(unsigned type)
+{
+ static const char *type_name[] = {
+#define SYM_TYPE(X) [X] = #X
+ SYM_TYPE(STT_NOTYPE),
+ SYM_TYPE(STT_OBJECT),
+ SYM_TYPE(STT_FUNC),
+ SYM_TYPE(STT_SECTION),
+ SYM_TYPE(STT_FILE),
+ SYM_TYPE(STT_COMMON),
+ SYM_TYPE(STT_TLS),
+#undef SYM_TYPE
+ };
+ const char *name = "unknown sym type name";
+ if (type < ARRAY_SIZE(type_name)) {
+ name = type_name[type];
+ }
+ return name;
+}
+
+static const char *sym_bind(unsigned bind)
+{
+ static const char *bind_name[] = {
+#define SYM_BIND(X) [X] = #X
+ SYM_BIND(STB_LOCAL),
+ SYM_BIND(STB_GLOBAL),
+ SYM_BIND(STB_WEAK),
+#undef SYM_BIND
+ };
+ const char *name = "unknown sym bind name";
+ if (bind < ARRAY_SIZE(bind_name)) {
+ name = bind_name[bind];
+ }
+ return name;
+}
+
+static const char *sym_visibility(unsigned visibility)
+{
+ static const char *visibility_name[] = {
+#define SYM_VISIBILITY(X) [X] = #X
+ SYM_VISIBILITY(STV_DEFAULT),
+ SYM_VISIBILITY(STV_INTERNAL),
+ SYM_VISIBILITY(STV_HIDDEN),
+ SYM_VISIBILITY(STV_PROTECTED),
+#undef SYM_VISIBILITY
+ };
+ const char *name = "unknown sym visibility name";
+ if (visibility < ARRAY_SIZE(visibility_name)) {
+ name = visibility_name[visibility];
+ }
+ return name;
+}
+
+static const char *rel_type(unsigned type)
+{
+ static const char *type_name[] = {
+#define REL_TYPE(X) [X] = #X
+ REL_TYPE(R_386_NONE),
+ REL_TYPE(R_386_32),
+ REL_TYPE(R_386_PC32),
+ REL_TYPE(R_386_GOT32),
+ REL_TYPE(R_386_PLT32),
+ REL_TYPE(R_386_COPY),
+ REL_TYPE(R_386_GLOB_DAT),
+ REL_TYPE(R_386_JMP_SLOT),
+ REL_TYPE(R_386_RELATIVE),
+ REL_TYPE(R_386_GOTOFF),
+ REL_TYPE(R_386_GOTPC),
+#undef REL_TYPE
+ };
+ const char *name = NULL;
+ if (type < ARRAY_SIZE(type_name))
+ name = type_name[type];
+ if (!name)
+ name = "unknown";
+ return name;
+}
+
+static const char *sec_name(unsigned shndx)
+{
+ const char *sec_strtab;
+ const char *name;
+ sec_strtab = secs[ehdr.e_shstrndx].strtab;
+ name = "<noname>";
+ if (shndx < ehdr.e_shnum) {
+ name = sec_strtab + secs[shndx].shdr.sh_name;
+ }
+ else if (shndx == SHN_ABS) {
+ name = "ABSOLUTE";
+ }
+ else if (shndx == SHN_COMMON) {
+ name = "COMMON";
+ }
+ return name;
+}
+
+static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym)
+{
+ const char *name;
+ name = "<noname>";
+ if (sym->st_name) {
+ name = sym_strtab + sym->st_name;
+ }
+ else {
+ name = sec_name(secs[sym->st_shndx].shdr.sh_name);
+ }
+ return name;
+}
+
+
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define le16_to_cpu(val) (val)
+#define le32_to_cpu(val) (val)
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+#define le16_to_cpu(val) bswap_16(val)
+#define le32_to_cpu(val) bswap_32(val)
+#endif
+
+static uint16_t elf16_to_cpu(uint16_t val)
+{
+ return le16_to_cpu(val);
+}
+
+static uint32_t elf32_to_cpu(uint32_t val)
+{
+ return le32_to_cpu(val);
+}
+
+static void read_ehdr(FILE *fp)
+{
+ if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) {
+ die("Cannot read ELF header: %s\n",
+ strerror(errno));
+ }
+ if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) {
+ die("No ELF magic\n");
+ }
+ if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) {
+ die("Not a 32 bit executable\n");
+ }
+ if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) {
+ die("Not a LSB ELF executable\n");
+ }
+ if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
+ die("Unknown ELF version\n");
+ }
+ /* Convert the fields to native endian */
+ ehdr.e_type = elf16_to_cpu(ehdr.e_type);
+ ehdr.e_machine = elf16_to_cpu(ehdr.e_machine);
+ ehdr.e_version = elf32_to_cpu(ehdr.e_version);
+ ehdr.e_entry = elf32_to_cpu(ehdr.e_entry);
+ ehdr.e_phoff = elf32_to_cpu(ehdr.e_phoff);
+ ehdr.e_shoff = elf32_to_cpu(ehdr.e_shoff);
+ ehdr.e_flags = elf32_to_cpu(ehdr.e_flags);
+ ehdr.e_ehsize = elf16_to_cpu(ehdr.e_ehsize);
+ ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize);
+ ehdr.e_phnum = elf16_to_cpu(ehdr.e_phnum);
+ ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize);
+ ehdr.e_shnum = elf16_to_cpu(ehdr.e_shnum);
+ ehdr.e_shstrndx = elf16_to_cpu(ehdr.e_shstrndx);
+
+ if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) {
+ die("Unsupported ELF header type\n");
+ }
+ if (ehdr.e_machine != EM_386) {
+ die("Not for x86\n");
+ }
+ if (ehdr.e_version != EV_CURRENT) {
+ die("Unknown ELF version\n");
+ }
+ if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) {
+ die("Bad Elf header size\n");
+ }
+ if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) {
+ die("Bad program header entry\n");
+ }
+ if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) {
+ die("Bad section header entry\n");
+ }
+ if (ehdr.e_shstrndx >= ehdr.e_shnum) {
+ die("String table index out of bounds\n");
+ }
+}
+
+static void read_shdrs(FILE *fp)
+{
+ int i;
+ Elf32_Shdr shdr;
+
+ secs = calloc(ehdr.e_shnum, sizeof(struct section));
+ if (!secs) {
+ die("Unable to allocate %d section headers\n",
+ ehdr.e_shnum);
+ }
+ if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) {
+ die("Seek to %d failed: %s\n",
+ ehdr.e_shoff, strerror(errno));
+ }
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ if (fread(&shdr, sizeof shdr, 1, fp) != 1)
+ die("Cannot read ELF section headers %d/%d: %s\n",
+ i, ehdr.e_shnum, strerror(errno));
+ sec->shdr.sh_name = elf32_to_cpu(shdr.sh_name);
+ sec->shdr.sh_type = elf32_to_cpu(shdr.sh_type);
+ sec->shdr.sh_flags = elf32_to_cpu(shdr.sh_flags);
+ sec->shdr.sh_addr = elf32_to_cpu(shdr.sh_addr);
+ sec->shdr.sh_offset = elf32_to_cpu(shdr.sh_offset);
+ sec->shdr.sh_size = elf32_to_cpu(shdr.sh_size);
+ sec->shdr.sh_link = elf32_to_cpu(shdr.sh_link);
+ sec->shdr.sh_info = elf32_to_cpu(shdr.sh_info);
+ sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign);
+ sec->shdr.sh_entsize = elf32_to_cpu(shdr.sh_entsize);
+ if (sec->shdr.sh_link < ehdr.e_shnum)
+ sec->link = &secs[sec->shdr.sh_link];
+ }
+
+}
+
+static void read_strtabs(FILE *fp)
+{
+ int i;
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ if (sec->shdr.sh_type != SHT_STRTAB) {
+ continue;
+ }
+ sec->strtab = malloc(sec->shdr.sh_size);
+ if (!sec->strtab) {
+ die("malloc of %d bytes for strtab failed\n",
+ sec->shdr.sh_size);
+ }
+ if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
+ die("Seek to %d failed: %s\n",
+ sec->shdr.sh_offset, strerror(errno));
+ }
+ if (fread(sec->strtab, 1, sec->shdr.sh_size, fp)
+ != sec->shdr.sh_size) {
+ die("Cannot read symbol table: %s\n",
+ strerror(errno));
+ }
+ }
+}
+
+static void read_symtabs(FILE *fp)
+{
+ int i,j;
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ if (sec->shdr.sh_type != SHT_SYMTAB) {
+ continue;
+ }
+ sec->symtab = malloc(sec->shdr.sh_size);
+ if (!sec->symtab) {
+ die("malloc of %d bytes for symtab failed\n",
+ sec->shdr.sh_size);
+ }
+ if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
+ die("Seek to %d failed: %s\n",
+ sec->shdr.sh_offset, strerror(errno));
+ }
+ if (fread(sec->symtab, 1, sec->shdr.sh_size, fp)
+ != sec->shdr.sh_size) {
+ die("Cannot read symbol table: %s\n",
+ strerror(errno));
+ }
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
+ Elf32_Sym *sym = &sec->symtab[j];
+ sym->st_name = elf32_to_cpu(sym->st_name);
+ sym->st_value = elf32_to_cpu(sym->st_value);
+ sym->st_size = elf32_to_cpu(sym->st_size);
+ sym->st_shndx = elf16_to_cpu(sym->st_shndx);
+ }
+ }
+}
+
+
+static void read_relocs(FILE *fp)
+{
+ int i,j;
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ if (sec->shdr.sh_type != SHT_REL) {
+ continue;
+ }
+ sec->reltab = malloc(sec->shdr.sh_size);
+ if (!sec->reltab) {
+ die("malloc of %d bytes for relocs failed\n",
+ sec->shdr.sh_size);
+ }
+ if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
+ die("Seek to %d failed: %s\n",
+ sec->shdr.sh_offset, strerror(errno));
+ }
+ if (fread(sec->reltab, 1, sec->shdr.sh_size, fp)
+ != sec->shdr.sh_size) {
+ die("Cannot read symbol table: %s\n",
+ strerror(errno));
+ }
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
+ Elf32_Rel *rel = &sec->reltab[j];
+ rel->r_offset = elf32_to_cpu(rel->r_offset);
+ rel->r_info = elf32_to_cpu(rel->r_info);
+ }
+ }
+}
+
+
+static void print_absolute_symbols(void)
+{
+ int i;
+ printf("Absolute symbols\n");
+ printf(" Num: Value Size Type Bind Visibility Name\n");
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ char *sym_strtab;
+ Elf32_Sym *sh_symtab;
+ int j;
+
+ if (sec->shdr.sh_type != SHT_SYMTAB) {
+ continue;
+ }
+ sh_symtab = sec->symtab;
+ sym_strtab = sec->link->strtab;
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
+ Elf32_Sym *sym;
+ const char *name;
+ sym = &sec->symtab[j];
+ name = sym_name(sym_strtab, sym);
+ if (sym->st_shndx != SHN_ABS) {
+ continue;
+ }
+ printf("%5d %08x %5d %10s %10s %12s %s\n",
+ j, sym->st_value, sym->st_size,
+ sym_type(ELF32_ST_TYPE(sym->st_info)),
+ sym_bind(ELF32_ST_BIND(sym->st_info)),
+ sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)),
+ name);
+ }
+ }
+ printf("\n");
+}
+
+static int print_absolute_relocs(FILE *f)
+{
+ int i, printed = 0;
+
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ struct section *sec_applies, *sec_symtab;
+ char *sym_strtab;
+ Elf32_Sym *sh_symtab;
+ int j;
+ if (sec->shdr.sh_type != SHT_REL) {
+ continue;
+ }
+ sec_symtab = sec->link;
+ sec_applies = &secs[sec->shdr.sh_info];
+ if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
+ continue;
+ }
+ sh_symtab = sec_symtab->symtab;
+ sym_strtab = sec_symtab->link->strtab;
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
+ Elf32_Rel *rel;
+ Elf32_Sym *sym;
+ const char *name;
+ rel = &sec->reltab[j];
+ sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
+ name = sym_name(sym_strtab, sym);
+ if (sym->st_shndx != SHN_ABS) {
+ continue;
+ }
+
+ /* Absolute symbols are not relocated if bzImage is
+ * loaded at a non-compiled address. Display a warning
+ * to user at compile time about the absolute
+ * relocations present.
+ *
+ * User need to audit the code to make sure
+ * some symbols which should have been section
+ * relative have not become absolute because of some
+ * linker optimization or wrong programming usage.
+ *
+ * Before warning check if this absolute symbol
+ * relocation is harmless.
+ */
+ if (is_safe_abs_reloc(name) ||
+ is_safe_rel_reloc(name))
+ continue;
+
+ if (!printed) {
+ fprintf(f, "Unknown absolute relocations present\n");
+ fprintf(f, "Offset Info Type Sym.Value Sym.Name\n");
+ printed = 1;
+ }
+
+ fprintf(f, "%08x %08x %10s %08x %s\n",
+ rel->r_offset,
+ rel->r_info,
+ rel_type(ELF32_R_TYPE(rel->r_info)),
+ sym->st_value,
+ name);
+ }
+ }
+
+ if (printed)
+ fputc('\n', f);
+
+ return printed;
+}
+
+static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
+{
+ int i;
+ /* Walk through the relocations */
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ char *sym_strtab;
+ Elf32_Sym *sh_symtab;
+ struct section *sec_applies, *sec_symtab;
+ int j;
+ struct section *sec = &secs[i];
+
+ if (sec->shdr.sh_type != SHT_REL) {
+ continue;
+ }
+ sec_symtab = sec->link;
+ sec_applies = &secs[sec->shdr.sh_info];
+ if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
+ continue;
+ }
+ sh_symtab = sec_symtab->symtab;
+ sym_strtab = sec_symtab->link->strtab;
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
+ Elf32_Rel *rel;
+ Elf32_Sym *sym;
+ unsigned r_type;
+ rel = &sec->reltab[j];
+ sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
+ r_type = ELF32_R_TYPE(rel->r_info);
+ /* Don't visit relocations to absolute symbols */
+ if (sym->st_shndx == SHN_ABS &&
+ !is_safe_rel_reloc(sym_name(sym_strtab, sym)))
+ continue;
+
+ switch (r_type) {
+ case R_386_NONE:
+ case R_386_PC32:
+ case R_386_GOTPC:
+ case R_386_GOTOFF:
+ case R_386_GOT32:
+ case R_386_PLT32:
+ /* Relative relocations don't need to
+ be adjusted */
+ break;
+ case R_386_32:
+ /* Visit relocations that need adjustment */
+ visit(rel, sym);
+ break;
+ default:
+ die("Unsupported relocation type: %s (%d)\n",
+ rel_type(r_type), r_type);
+ }
+ }
+ }
+}
+
+static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
+{
+ (void)rel; (void)sym;
+ reloc_count += 1;
+}
+
+static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
+{
+ (void)sym;
+
+ /* Remember the address that needs to be adjusted. */
+ relocs[reloc_idx++] = rel->r_offset;
+}
+
+static int cmp_relocs(const void *va, const void *vb)
+{
+ const unsigned long *a, *b;
+ a = va; b = vb;
+ return (*a == *b)? 0 : (*a > *b)? 1 : -1;
+}
+
+static void emit_relocs(int as_text)
+{
+ int i;
+ /* Count how many relocations I have and allocate space for them. */
+ reloc_count = 0;
+ walk_relocs(count_reloc);
+ relocs = malloc(reloc_count * sizeof(relocs[0]));
+ if (!relocs) {
+ die("malloc of %d entries for relocs failed\n",
+ reloc_count);
+ }
+ /* Collect up the relocations */
+ reloc_idx = 0;
+ walk_relocs(collect_reloc);
+
+ /* Order the relocations for more efficient processing */
+ qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs);
+
+ /* Print the relocations */
+ if (as_text) {
+ /* Print the relocations in a form suitable that
+ * gas will like.
+ */
+ printf(".section \".data.reloc\",\"a\"\n");
+ printf(".balign 4\n");
+ for (i = 0; i < reloc_count; i++) {
+ printf("\t .long 0x%08lx\n", relocs[i]);
+ }
+ printf("\n");
+ }
+ else {
+ unsigned char buf[4];
+ /* Now print each relocation */
+ for (i = 0; i < reloc_count; i++) {
+ buf[0] = (relocs[i] >> 0) & 0xff;
+ buf[1] = (relocs[i] >> 8) & 0xff;
+ buf[2] = (relocs[i] >> 16) & 0xff;
+ buf[3] = (relocs[i] >> 24) & 0xff;
+ fwrite(buf, 4, 1, stdout);
+ }
+ /* Print a stop */
+ memset(buf, 0, sizeof buf);
+ fwrite(buf, 4, 1, stdout);
+ }
+}
+
+static void usage(void)
+{
+ die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n");
+}
+
+int main(int argc, char **argv)
+{
+ int show_absolute_syms, show_absolute_relocs;
+ int as_text;
+ const char *fname;
+ FILE *fp;
+ int i;
+ int err = 0;
+
+ show_absolute_syms = 0;
+ show_absolute_relocs = 0;
+ as_text = 0;
+ fname = NULL;
+ for (i = 1; i < argc; i++) {
+ char *arg = argv[i];
+ if (*arg == '-') {
+ if (strcmp(argv[1], "--abs-syms") == 0) {
+ show_absolute_syms = 1;
+ continue;
+ }
+
+ if (strcmp(argv[1], "--abs-relocs") == 0) {
+ show_absolute_relocs = 1;
+ continue;
+ }
+ else if (strcmp(argv[1], "--text") == 0) {
+ as_text = 1;
+ continue;
+ }
+ }
+ else if (!fname) {
+ fname = arg;
+ continue;
+ }
+ usage();
+ }
+ if (!fname) {
+ usage();
+ }
+
+
+ regex_init();
+
+ fp = fopen(fname, "r");
+ if (!fp) {
+ die("Cannot open %s: %s\n",
+ fname, strerror(errno));
+ }
+ read_ehdr(fp);
+ read_shdrs(fp);
+ read_strtabs(fp);
+ read_symtabs(fp);
+ read_relocs(fp);
+ if (show_absolute_syms) {
+ print_absolute_symbols();
+ return 0;
+ }
+ if (show_absolute_relocs) {
+ print_absolute_relocs(stdout);
+ return 0;
+ }
+ err = print_absolute_relocs(stderr);
+ emit_relocs(as_text);
+ return err;
+}