summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux-4.02/gpxe/src/arch/i386/core
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux-4.02/gpxe/src/arch/i386/core')
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/aout_loader.c144
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/basemem_packet.c32
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/cpu.c73
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/dumpregs.c23
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/freebsd_loader.c377
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/gdbidt.S215
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/gdbmach.c149
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/nulltrap.c51
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/pic8259.c66
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/rdtsc_timer.c89
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/relocate.c170
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/setjmp.S42
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/stack.S15
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/stack16.S15
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/timer2.c87
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/video_subr.c104
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/virtaddr.S103
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/wince_loader.c273
-rw-r--r--contrib/syslinux-4.02/gpxe/src/arch/i386/core/x86_io.c96
19 files changed, 2124 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/aout_loader.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/aout_loader.c
new file mode 100644
index 0000000..f85620e
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/aout_loader.c
@@ -0,0 +1,144 @@
+/* a.out */
+struct exec {
+ unsigned long a_midmag; /* flags<<26 | mid<<16 | magic */
+ unsigned long a_text; /* text segment size */
+ unsigned long a_data; /* initialized data size */
+ unsigned long a_bss; /* uninitialized data size */
+ unsigned long a_syms; /* symbol table size */
+ unsigned long a_entry; /* entry point */
+ unsigned long a_trsize; /* text relocation size */
+ unsigned long a_drsize; /* data relocation size */
+};
+
+struct aout_state {
+ struct exec head;
+ unsigned long curaddr;
+ int segment; /* current segment number, -1 for none */
+ unsigned long loc; /* start offset of current block */
+ unsigned long skip; /* padding to be skipped to current segment */
+ unsigned long toread; /* remaining data to be read in the segment */
+};
+
+static struct aout_state astate;
+
+static sector_t aout_download(unsigned char *data, unsigned int len, int eof);
+static inline os_download_t aout_probe(unsigned char *data, unsigned int len)
+{
+ unsigned long start, mid, end, istart, iend;
+ if (len < sizeof(astate.head)) {
+ return 0;
+ }
+ memcpy(&astate.head, data, sizeof(astate.head));
+ if ((astate.head.a_midmag & 0xffff) != 0x010BL) {
+ return 0;
+ }
+
+ printf("(a.out");
+ aout_freebsd_probe();
+ printf(")... ");
+ /* Check the aout image */
+ start = astate.head.a_entry;
+ mid = (((start + astate.head.a_text) + 4095) & ~4095) + astate.head.a_data;
+ end = ((mid + 4095) & ~4095) + astate.head.a_bss;
+ istart = 4096;
+ iend = istart + (mid - start);
+ if (!prep_segment(start, mid, end, istart, iend))
+ return dead_download;
+ astate.segment = -1;
+ astate.loc = 0;
+ astate.skip = 0;
+ astate.toread = 0;
+ return aout_download;
+}
+
+static sector_t aout_download(unsigned char *data, unsigned int len, int eof)
+{
+ unsigned int offset; /* working offset in the current data block */
+
+ offset = 0;
+
+#ifdef AOUT_LYNX_KDI
+ astate.segment++;
+ if (astate.segment == 0) {
+ astate.curaddr = 0x100000;
+ astate.head.a_entry = astate.curaddr + 0x20;
+ }
+ memcpy(phys_to_virt(astate.curaddr), data, len);
+ astate.curaddr += len;
+ return 0;
+#endif
+
+ do {
+ if (astate.segment != -1) {
+ if (astate.skip) {
+ if (astate.skip >= len - offset) {
+ astate.skip -= len - offset;
+ break;
+ }
+ offset += astate.skip;
+ astate.skip = 0;
+ }
+
+ if (astate.toread) {
+ if (astate.toread >= len - offset) {
+ memcpy(phys_to_virt(astate.curaddr), data+offset,
+ len - offset);
+ astate.curaddr += len - offset;
+ astate.toread -= len - offset;
+ break;
+ }
+ memcpy(phys_to_virt(astate.curaddr), data+offset, astate.toread);
+ offset += astate.toread;
+ astate.toread = 0;
+ }
+ }
+
+ /* Data left, but current segment finished - look for the next
+ * segment. This is quite simple for a.out files. */
+ astate.segment++;
+ switch (astate.segment) {
+ case 0:
+ /* read text */
+ astate.curaddr = astate.head.a_entry;
+ astate.skip = 4096;
+ astate.toread = astate.head.a_text;
+ break;
+ case 1:
+ /* read data */
+ /* skip and curaddr may be wrong, but I couldn't find
+ * examples where this failed. There is no reasonable
+ * documentation for a.out available. */
+ astate.skip = ((astate.curaddr + 4095) & ~4095) - astate.curaddr;
+ astate.curaddr = (astate.curaddr + 4095) & ~4095;
+ astate.toread = astate.head.a_data;
+ break;
+ case 2:
+ /* initialize bss and start kernel */
+ astate.curaddr = (astate.curaddr + 4095) & ~4095;
+ astate.skip = 0;
+ astate.toread = 0;
+ memset(phys_to_virt(astate.curaddr), '\0', astate.head.a_bss);
+ goto aout_startkernel;
+ default:
+ break;
+ }
+ } while (offset < len);
+
+ astate.loc += len;
+
+ if (eof) {
+ unsigned long entry;
+
+aout_startkernel:
+ entry = astate.head.a_entry;
+ done(1);
+
+ aout_freebsd_boot();
+#ifdef AOUT_LYNX_KDI
+ xstart32(entry);
+#endif
+ printf("unexpected a.out variant\n");
+ longjmp(restart_etherboot, -2);
+ }
+ return 0;
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/basemem_packet.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/basemem_packet.c
new file mode 100644
index 0000000..d487cce
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/basemem_packet.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * 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; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Packet buffer in base memory. Used by various components which
+ * need to pass packets to and from external real-mode code.
+ *
+ */
+
+#include <basemem_packet.h>
+
+#undef basemem_packet
+char __bss16_array ( basemem_packet, [BASEMEM_PACKET_LEN] );
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/cpu.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/cpu.c
new file mode 100644
index 0000000..c24fa4e
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/cpu.c
@@ -0,0 +1,73 @@
+#include <stdint.h>
+#include <string.h>
+#include <cpu.h>
+
+/** @file
+ *
+ * CPU identification
+ *
+ */
+
+/**
+ * Test to see if CPU flag is changeable
+ *
+ * @v flag Flag to test
+ * @ret can_change Flag is changeable
+ */
+static inline int flag_is_changeable ( unsigned int flag ) {
+ uint32_t f1, f2;
+
+ __asm__ ( "pushfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "movl %0,%1\n\t"
+ "xorl %2,%0\n\t"
+ "pushl %0\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "popfl\n\t"
+ : "=&r" ( f1 ), "=&r" ( f2 )
+ : "ir" ( flag ) );
+
+ return ( ( ( f1 ^ f2 ) & flag ) != 0 );
+}
+
+/**
+ * Get CPU information
+ *
+ * @v cpu CPU information structure to fill in
+ */
+void get_cpuinfo ( struct cpuinfo_x86 *cpu ) {
+ unsigned int cpuid_level;
+ unsigned int cpuid_extlevel;
+ unsigned int discard_1, discard_2, discard_3;
+
+ memset ( cpu, 0, sizeof ( *cpu ) );
+
+ /* Check for CPUID instruction */
+ if ( ! flag_is_changeable ( X86_EFLAGS_ID ) ) {
+ DBG ( "CPUID not supported\n" );
+ return;
+ }
+
+ /* Get features, if present */
+ cpuid ( 0x00000000, &cpuid_level, &discard_1,
+ &discard_2, &discard_3 );
+ if ( cpuid_level >= 0x00000001 ) {
+ cpuid ( 0x00000001, &discard_1, &discard_2,
+ &discard_3, &cpu->features );
+ } else {
+ DBG ( "CPUID cannot return capabilities\n" );
+ }
+
+ /* Get 64-bit features, if present */
+ cpuid ( 0x80000000, &cpuid_extlevel, &discard_1,
+ &discard_2, &discard_3 );
+ if ( ( cpuid_extlevel & 0xffff0000 ) == 0x80000000 ) {
+ if ( cpuid_extlevel >= 0x80000001 ) {
+ cpuid ( 0x80000001, &discard_1, &discard_2,
+ &discard_3, &cpu->amd_features );
+ }
+ }
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/dumpregs.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/dumpregs.c
new file mode 100644
index 0000000..82dc218
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/dumpregs.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <realmode.h>
+
+void __asmcall _dump_regs ( struct i386_all_regs *ix86 ) {
+
+ __asm__ __volatile__ (
+ TEXT16_CODE ( ".globl dump_regs\n\t"
+ "\ndump_regs:\n\t"
+ "pushl $_dump_regs\n\t"
+ "pushw %%cs\n\t"
+ "call prot_call\n\t"
+ "addr32 leal 4(%%esp), %%esp\n\t"
+ "ret\n\t" ) : : );
+
+ printf ( "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
+ "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
+ "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
+ ix86->regs.eax, ix86->regs.ebx, ix86->regs.ecx,
+ ix86->regs.edx, ix86->regs.esi, ix86->regs.edi,
+ ix86->regs.ebp, ix86->regs.esp,
+ ix86->segs.cs, ix86->segs.ss, ix86->segs.ds,
+ ix86->segs.es, ix86->segs.fs, ix86->segs.gs );
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/freebsd_loader.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/freebsd_loader.c
new file mode 100644
index 0000000..464f6d9
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/freebsd_loader.c
@@ -0,0 +1,377 @@
+/* bootinfo */
+#define BOOTINFO_VERSION 1
+#define NODEV (-1) /* non-existent device */
+#define PAGE_SHIFT 12 /* LOG2(PAGE_SIZE) */
+#define PAGE_SIZE (1<<PAGE_SHIFT) /* bytes/page */
+#define PAGE_MASK (PAGE_SIZE-1)
+#define N_BIOS_GEOM 8
+
+struct bootinfo {
+ unsigned int bi_version;
+ const unsigned char *bi_kernelname;
+ struct nfs_diskless *bi_nfs_diskless;
+ /* End of fields that are always present. */
+#define bi_endcommon bi_n_bios_used
+ unsigned int bi_n_bios_used;
+ unsigned long bi_bios_geom[N_BIOS_GEOM];
+ unsigned int bi_size;
+ unsigned char bi_memsizes_valid;
+ unsigned char bi_pad[3];
+ unsigned long bi_basemem;
+ unsigned long bi_extmem;
+ unsigned long bi_symtab;
+ unsigned long bi_esymtab;
+ /* Note that these are in the FreeBSD headers but were not here... */
+ unsigned long bi_kernend; /* end of kernel space */
+ unsigned long bi_envp; /* environment */
+ unsigned long bi_modulep; /* preloaded modules */
+};
+
+static struct bootinfo bsdinfo;
+
+#ifdef ELF_IMAGE
+static Elf32_Shdr *shdr; /* To support the FreeBSD kludge! */
+static Address symtab_load;
+static Address symstr_load;
+static int symtabindex;
+static int symstrindex;
+#endif
+
+static enum {
+ Unknown, Tagged, Aout, Elf, Aout_FreeBSD, Elf_FreeBSD,
+} image_type = Unknown;
+
+static unsigned int off;
+
+
+#ifdef ELF_IMAGE
+static void elf_freebsd_probe(void)
+{
+ image_type = Elf;
+ if ( (estate.e.elf32.e_entry & 0xf0000000) &&
+ (estate.e.elf32.e_type == ET_EXEC))
+ {
+ image_type = Elf_FreeBSD;
+ printf("/FreeBSD");
+ off = -(estate.e.elf32.e_entry & 0xff000000);
+ estate.e.elf32.e_entry += off;
+ }
+ /* Make sure we have a null to start with... */
+ shdr = 0;
+
+ /* Clear the symbol index values... */
+ symtabindex = -1;
+ symstrindex = -1;
+
+ /* ...and the load addresses of the symbols */
+ symtab_load = 0;
+ symstr_load = 0;
+}
+
+static void elf_freebsd_fixup_segment(void)
+{
+ if (image_type == Elf_FreeBSD) {
+ estate.p.phdr32[estate.segment].p_paddr += off;
+ }
+}
+
+static void elf_freebsd_find_segment_end(void)
+{
+ /* Count the bytes read even for the last block
+ * as we will need to know where the last block
+ * ends in order to load the symbols correctly.
+ * (plus it could be useful elsewhere...)
+ * Note that we need to count the actual size,
+ * not just the end of the disk image size.
+ */
+ estate.curaddr +=
+ (estate.p.phdr32[estate.segment].p_memsz -
+ estate.p.phdr32[estate.segment].p_filesz);
+}
+
+static int elf_freebsd_debug_loader(unsigned int offset)
+{
+ /* No more segments to be loaded - time to start the
+ * nasty state machine to support the loading of
+ * FreeBSD debug symbols due to the fact that FreeBSD
+ * uses/exports the kernel's debug symbols in order
+ * to make much of the system work! Amazing (arg!)
+ *
+ * We depend on the fact that for the FreeBSD kernel,
+ * there is only one section of debug symbols and that
+ * the section is after all of the loaded sections in
+ * the file. This assumes a lot but is somewhat required
+ * to make this code not be too annoying. (Where do you
+ * load symbols when the code has not loaded yet?)
+ * Since this function is actually just a callback from
+ * the network data transfer code, we need to be able to
+ * work with the data as it comes in. There is no chance
+ * for doing a seek other than forwards.
+ *
+ * The process we use is to first load the section
+ * headers. Once they are loaded (shdr != 0) we then
+ * look for where the symbol table and symbol table
+ * strings are and setup some state that we found
+ * them and fall into processing the first one (which
+ * is the symbol table) and after that has been loaded,
+ * we try the symbol strings. Note that the order is
+ * actually required as the memory image depends on
+ * the symbol strings being loaded starting at the
+ * end of the symbol table. The kernel assumes this
+ * layout of the image.
+ *
+ * At any point, if we get to the end of the load file
+ * or the section requested is earlier in the file than
+ * the current file pointer, we just end up falling
+ * out of this and booting the kernel without this
+ * information.
+ */
+
+ /* Make sure that the next address is long aligned... */
+ /* Assumes size of long is a power of 2... */
+ estate.curaddr = (estate.curaddr + sizeof(long) - 1) & ~(sizeof(long) - 1);
+
+ /* If we have not yet gotten the shdr loaded, try that */
+ if (shdr == 0)
+ {
+ estate.toread = estate.e.elf32.e_shnum * estate.e.elf32.e_shentsize;
+ estate.skip = estate.e.elf32.e_shoff - (estate.loc + offset);
+ if (estate.toread)
+ {
+#if ELF_DEBUG
+ printf("shdr *, size %lX, curaddr %lX\n",
+ estate.toread, estate.curaddr);
+#endif
+
+ /* Start reading at the curaddr and make that the shdr */
+ shdr = (Elf32_Shdr *)phys_to_virt(estate.curaddr);
+
+ /* Start to read... */
+ return 1;
+ }
+ }
+ else
+ {
+ /* We have the shdr loaded, check if we have found
+ * the indexs where the symbols are supposed to be */
+ if ((symtabindex == -1) && (symstrindex == -1))
+ {
+ int i;
+ /* Make sure that the address is page aligned... */
+ /* Symbols need to start in their own page(s)... */
+ estate.curaddr = (estate.curaddr + 4095) & ~4095;
+
+ /* Need to make new indexes... */
+ for (i=0; i < estate.e.elf32.e_shnum; i++)
+ {
+ if (shdr[i].sh_type == SHT_SYMTAB)
+ {
+ int j;
+ for (j=0; j < estate.e.elf32.e_phnum; j++)
+ {
+ /* Check only for loaded sections */
+ if ((estate.p.phdr32[j].p_type | 0x80) == (PT_LOAD | 0x80))
+ {
+ /* Only the extra symbols */
+ if ((shdr[i].sh_offset >= estate.p.phdr32[j].p_offset) &&
+ ((shdr[i].sh_offset + shdr[i].sh_size) <=
+ (estate.p.phdr32[j].p_offset + estate.p.phdr32[j].p_filesz)))
+ {
+ shdr[i].sh_offset=0;
+ shdr[i].sh_size=0;
+ break;
+ }
+ }
+ }
+ if ((shdr[i].sh_offset != 0) && (shdr[i].sh_size != 0))
+ {
+ symtabindex = i;
+ symstrindex = shdr[i].sh_link;
+ }
+ }
+ }
+ }
+
+ /* Check if we have a symbol table index and have not loaded it */
+ if ((symtab_load == 0) && (symtabindex >= 0))
+ {
+ /* No symbol table yet? Load it first... */
+
+ /* This happens to work out in a strange way.
+ * If we are past the point in the file already,
+ * we will skip a *large* number of bytes which
+ * ends up bringing us to the end of the file and
+ * an old (default) boot. Less code and lets
+ * the state machine work in a cleaner way but this
+ * is a nasty side-effect trick... */
+ estate.skip = shdr[symtabindex].sh_offset - (estate.loc + offset);
+
+ /* And we need to read this many bytes... */
+ estate.toread = shdr[symtabindex].sh_size;
+
+ if (estate.toread)
+ {
+#if ELF_DEBUG
+ printf("db sym, size %lX, curaddr %lX\n",
+ estate.toread, estate.curaddr);
+#endif
+ /* Save where we are loading this... */
+ symtab_load = estate.curaddr;
+
+ *((long *)phys_to_virt(estate.curaddr)) = estate.toread;
+ estate.curaddr += sizeof(long);
+
+ /* Start to read... */
+ return 1;
+ }
+ }
+ else if ((symstr_load == 0) && (symstrindex >= 0))
+ {
+ /* We have already loaded the symbol table, so
+ * now on to the symbol strings... */
+
+
+ /* Same nasty trick as above... */
+ estate.skip = shdr[symstrindex].sh_offset - (estate.loc + offset);
+
+ /* And we need to read this many bytes... */
+ estate.toread = shdr[symstrindex].sh_size;
+
+ if (estate.toread)
+ {
+#if ELF_DEBUG
+ printf("db str, size %lX, curaddr %lX\n",
+ estate.toread, estate.curaddr);
+#endif
+ /* Save where we are loading this... */
+ symstr_load = estate.curaddr;
+
+ *((long *)phys_to_virt(estate.curaddr)) = estate.toread;
+ estate.curaddr += sizeof(long);
+
+ /* Start to read... */
+ return 1;
+ }
+ }
+ }
+ /* all done */
+ return 0;
+}
+
+static void elf_freebsd_boot(unsigned long entry)
+{
+ if (image_type != Elf_FreeBSD)
+ return;
+
+ memset(&bsdinfo, 0, sizeof(bsdinfo));
+ bsdinfo.bi_basemem = meminfo.basememsize;
+ bsdinfo.bi_extmem = meminfo.memsize;
+ bsdinfo.bi_memsizes_valid = 1;
+ bsdinfo.bi_version = BOOTINFO_VERSION;
+ bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF);
+ bsdinfo.bi_nfs_diskless = NULL;
+ bsdinfo.bi_size = sizeof(bsdinfo);
+#define RB_BOOTINFO 0x80000000 /* have `struct bootinfo *' arg */
+ if(freebsd_kernel_env[0] != '\0'){
+ freebsd_howto |= RB_BOOTINFO;
+ bsdinfo.bi_envp = (unsigned long)freebsd_kernel_env;
+ }
+
+ /* Check if we have symbols loaded, and if so,
+ * made the meta_data needed to pass those to
+ * the kernel. */
+ if ((symtab_load !=0) && (symstr_load != 0))
+ {
+ unsigned long *t;
+
+ bsdinfo.bi_symtab = symtab_load;
+
+ /* End of symbols (long aligned...) */
+ /* Assumes size of long is a power of 2... */
+ bsdinfo.bi_esymtab = (symstr_load +
+ sizeof(long) +
+ *((long *)phys_to_virt(symstr_load)) +
+ sizeof(long) - 1) & ~(sizeof(long) - 1);
+
+ /* Where we will build the meta data... */
+ t = phys_to_virt(bsdinfo.bi_esymtab);
+
+#if ELF_DEBUG
+ printf("Metadata at %lX\n",t);
+#endif
+
+ /* Set up the pointer to the memory... */
+ bsdinfo.bi_modulep = virt_to_phys(t);
+
+ /* The metadata structure is an array of 32-bit
+ * words where we store some information about the
+ * system. This is critical, as FreeBSD now looks
+ * only for the metadata for the extended symbol
+ * information rather than in the bootinfo.
+ */
+ /* First, do the kernel name and the kernel type */
+ /* Note that this assumed x86 byte order... */
+
+ /* 'kernel\0\0' */
+ *t++=MODINFO_NAME; *t++= 7; *t++=0x6E72656B; *t++=0x00006C65;
+
+ /* 'elf kernel\0\0' */
+ *t++=MODINFO_TYPE; *t++=11; *t++=0x20666C65; *t++=0x6E72656B; *t++ = 0x00006C65;
+
+ /* Now the symbol start/end - note that they are
+ * here in local/physical address - the Kernel
+ * boot process will relocate the addresses. */
+ *t++=MODINFOMD_SSYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_symtab;
+ *t++=MODINFOMD_ESYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_esymtab;
+
+ *t++=MODINFO_END; *t++=0; /* end of metadata */
+
+ /* Since we have symbols we need to make
+ * sure that the kernel knows its own end
+ * of memory... It is not _end but after
+ * the symbols and the metadata... */
+ bsdinfo.bi_kernend = virt_to_phys(t);
+
+ /* Signal locore.s that we have a valid bootinfo
+ * structure that was completely filled in. */
+ freebsd_howto |= 0x80000000;
+ }
+
+ xstart32(entry, freebsd_howto, NODEV, 0, 0, 0,
+ virt_to_phys(&bsdinfo), 0, 0, 0);
+ longjmp(restart_etherboot, -2);
+}
+#endif
+
+#ifdef AOUT_IMAGE
+static void aout_freebsd_probe(void)
+{
+ image_type = Aout;
+ if (((astate.head.a_midmag >> 16) & 0xffff) == 0) {
+ /* Some other a.out variants have a different
+ * value, and use other alignments (e.g. 1K),
+ * not the 4K used by FreeBSD. */
+ image_type = Aout_FreeBSD;
+ printf("/FreeBSD");
+ off = -(astate.head.a_entry & 0xff000000);
+ astate.head.a_entry += off;
+ }
+}
+
+static void aout_freebsd_boot(void)
+{
+ if (image_type == Aout_FreeBSD) {
+ memset(&bsdinfo, 0, sizeof(bsdinfo));
+ bsdinfo.bi_basemem = meminfo.basememsize;
+ bsdinfo.bi_extmem = meminfo.memsize;
+ bsdinfo.bi_memsizes_valid = 1;
+ bsdinfo.bi_version = BOOTINFO_VERSION;
+ bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF);
+ bsdinfo.bi_nfs_diskless = NULL;
+ bsdinfo.bi_size = sizeof(bsdinfo);
+ xstart32(astate.head.a_entry, freebsd_howto, NODEV, 0, 0, 0,
+ virt_to_phys(&bsdinfo), 0, 0, 0);
+ longjmp(restart_etherboot, -2);
+ }
+}
+#endif
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/gdbidt.S b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/gdbidt.S
new file mode 100644
index 0000000..cd8b38a
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/gdbidt.S
@@ -0,0 +1,215 @@
+/*
+ * Interrupt Descriptor Table (IDT) setup and interrupt handlers for GDB stub.
+ */
+
+#include <librm.h>
+
+#define SIZEOF_I386_REGS 32
+#define SIZEOF_I386_FLAGS 4
+
+/****************************************************************************
+ * Interrupt Descriptor Table
+ ****************************************************************************
+ */
+ .section ".data16", "aw", @progbits
+ .globl idtr
+idtr:
+idt_limit:
+ .word idt_length - 1
+idt_base:
+ .long 0
+
+/* IDT entries have the following format:
+ * offset_lo, segment selector, flags, offset_hi
+ *
+ * Since it is not possible to specify relocations in arbitrary
+ * expressions like (int_overflow & 0xffff), we initialise the
+ * IDT with entries in an incorrect format.
+ *
+ * The entries are shuffled into the correct format in init_librm().
+ */
+#define IDT_ENTRY_EMPTY(name) .word 0, 0, 0, 0
+#define IDT_ENTRY_PRESENT(name) \
+ .long int_##name; \
+ .word 0x8e00, VIRTUAL_CS
+
+.align 16
+idt:
+ IDT_ENTRY_PRESENT(divide_error)
+ IDT_ENTRY_PRESENT(debug_trap)
+ IDT_ENTRY_EMPTY(non_maskable_interrupt)
+ IDT_ENTRY_PRESENT(breakpoint)
+ IDT_ENTRY_PRESENT(overflow)
+ IDT_ENTRY_PRESENT(bound_range_exceeded)
+ IDT_ENTRY_PRESENT(invalid_opcode)
+ IDT_ENTRY_EMPTY(device_not_available)
+ IDT_ENTRY_PRESENT(double_fault)
+ IDT_ENTRY_EMPTY(coprocessor_segment_overrun)
+ IDT_ENTRY_PRESENT(invalid_tss)
+ IDT_ENTRY_PRESENT(segment_not_present)
+ IDT_ENTRY_PRESENT(stack_segment_fault)
+ IDT_ENTRY_PRESENT(general_protection)
+ IDT_ENTRY_PRESENT(page_fault)
+idt_end:
+ .equ idt_length, idt_end - idt
+
+/* The IDT entries are fixed up (once) in init_librm() */
+idt_fixed:
+ .byte 0
+
+/****************************************************************************
+ * idt_init (real-mode near call, 16-bit real-mode near return address)
+ *
+ * Initialise the IDT, called from init_librm.
+ *
+ * Parameters:
+ * %eax : IDT base address
+ *
+ * Destroys %ax, %bx, and %di.
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+ .code16
+ .globl idt_init
+idt_init:
+ movl %eax, idt_base
+ addl $idt, idt_base
+
+ /* IDT entries are only fixed up once */
+ movb idt_fixed, %al
+ orb %al, %al
+ jnz 2f
+ movb $1, idt_fixed
+
+ /* Shuffle IDT entries into the correct format */
+ movb $(idt_length / 8), %al
+ movw $idt, %bx
+ or %al, %al
+ jz 2f
+1:
+ movw 2(%bx), %di
+ xchg %di, 6(%bx)
+ movw %di, 2(%bx)
+ addw $8, %bx
+ dec %al
+ jnz 1b
+2:
+ ret
+
+/****************************************************************************
+ * Interrupt handlers
+ ****************************************************************************
+ */
+ .section ".text", "ax", @progbits
+ .code32
+
+/* POSIX signal numbers for reporting traps to GDB */
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGBUS 7
+#define SIGFPE 8
+#define SIGSEGV 11
+#define SIGSTKFLT 16
+
+int_divide_error:
+ pushl $SIGFPE
+ jmp do_interrupt
+
+int_debug_trap:
+int_breakpoint:
+ pushl $SIGTRAP
+ jmp do_interrupt
+
+int_overflow:
+int_bound_range_exceeded:
+ pushl $SIGSTKFLT
+ jmp do_interrupt
+
+int_invalid_opcode:
+ pushl $SIGILL
+ jmp do_interrupt
+
+int_double_fault:
+ movl $SIGBUS, (%esp)
+ jmp do_interrupt
+
+int_invalid_tss:
+int_segment_not_present:
+int_stack_segment_fault:
+int_general_protection:
+int_page_fault:
+ movl $SIGSEGV, (%esp)
+ jmp do_interrupt
+
+/* When invoked, the stack contains: eflags, cs, eip, signo. */
+#define IH_OFFSET_GDB_REGS ( 0 )
+#define IH_OFFSET_GDB_EIP ( IH_OFFSET_GDB_REGS + SIZEOF_I386_REGS )
+#define IH_OFFSET_GDB_EFLAGS ( IH_OFFSET_GDB_EIP + 4 )
+#define IH_OFFSET_GDB_SEG_REGS ( IH_OFFSET_GDB_EFLAGS + SIZEOF_I386_FLAGS )
+#define IH_OFFSET_GDB_END ( IH_OFFSET_GDB_SEG_REGS + 6 * 4 )
+#define IH_OFFSET_SIGNO ( IH_OFFSET_GDB_END )
+#define IH_OFFSET_OLD_EIP ( IH_OFFSET_SIGNO + 4 )
+#define IH_OFFSET_OLD_CS ( IH_OFFSET_OLD_EIP + 4 )
+#define IH_OFFSET_OLD_EFLAGS ( IH_OFFSET_OLD_CS + 4 )
+#define IH_OFFSET_END ( IH_OFFSET_OLD_EFLAGS + 4 )
+
+/* We also access the stack whilst still storing or restoring
+ * the register snapshot. Since ESP is in flux, we need
+ * special offsets.
+ */
+#define IH_OFFSET_FLUX_OLD_CS ( IH_OFFSET_OLD_CS - 44 )
+#define IH_OFFSET_FLUX_OLD_EFLAGS ( IH_OFFSET_OLD_EFLAGS - 40 )
+#define IH_OFFSET_FLUX_OLD_EIP ( IH_OFFSET_OLD_EIP - 36 )
+#define IH_OFFSET_FLUX_END ( IH_OFFSET_END - 20 )
+do_interrupt:
+ /* Store CPU state in GDB register snapshot */
+ pushw $0
+ pushw %gs
+ pushw $0
+ pushw %fs
+ pushw $0
+ pushw %es
+ pushw $0
+ pushw %ds
+ pushw $0
+ pushw %ss
+ pushw $0
+ pushw IH_OFFSET_FLUX_OLD_CS + 2(%esp)
+ pushl IH_OFFSET_FLUX_OLD_EFLAGS(%esp)
+ pushl IH_OFFSET_FLUX_OLD_EIP(%esp)
+ pushl %edi
+ pushl %esi
+ pushl %ebp
+ leal IH_OFFSET_FLUX_END(%esp), %edi
+ pushl %edi /* old ESP */
+ pushl %ebx
+ pushl %edx
+ pushl %ecx
+ pushl %eax
+
+ /* Call GDB stub exception handler */
+ pushl %esp
+ pushl (IH_OFFSET_SIGNO + 4)(%esp)
+ call gdbmach_handler
+ addl $8, %esp
+
+ /* Restore CPU state from GDB register snapshot */
+ popl %eax
+ popl %ecx
+ popl %edx
+ popl %ebx
+ addl $4, %esp /* Changing ESP currently not supported */
+ popl %ebp
+ popl %esi
+ popl %edi
+ popl IH_OFFSET_FLUX_OLD_EIP(%esp)
+ popl IH_OFFSET_FLUX_OLD_EFLAGS(%esp)
+ popl IH_OFFSET_FLUX_OLD_CS(%esp)
+ popl %ss
+ popl %ds
+ popl %es
+ popl %fs
+ popl %gs
+
+ addl $4, %esp /* drop signo */
+ iret
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/gdbmach.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/gdbmach.c
new file mode 100644
index 0000000..97827ec
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/gdbmach.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2008 Stefan Hajnoczi <stefanha@gmail.com>.
+ *
+ * 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; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <assert.h>
+#include <gpxe/uaccess.h>
+#include <gpxe/gdbstub.h>
+#include <gdbmach.h>
+
+/** @file
+ *
+ * GDB architecture-specific bits for i386
+ *
+ */
+
+enum {
+ DR7_CLEAR = 0x00000400, /* disable hardware breakpoints */
+ DR6_CLEAR = 0xffff0ff0, /* clear breakpoint status */
+};
+
+/** Hardware breakpoint, fields stored in x86 bit pattern form */
+struct hwbp {
+ int type; /* type (1=write watchpoint, 3=access watchpoint) */
+ unsigned long addr; /* linear address */
+ size_t len; /* length (0=1-byte, 1=2-byte, 3=4-byte) */
+ int enabled;
+};
+
+static struct hwbp hwbps [ 4 ];
+static gdbreg_t dr7 = DR7_CLEAR;
+
+static struct hwbp *gdbmach_find_hwbp ( int type, unsigned long addr, size_t len ) {
+ struct hwbp *available = NULL;
+ unsigned int i;
+ for ( i = 0; i < sizeof hwbps / sizeof hwbps [ 0 ]; i++ ) {
+ if ( hwbps [ i ].type == type && hwbps [ i ].addr == addr && hwbps [ i ].len == len ) {
+ return &hwbps [ i ];
+ }
+ if ( !hwbps [ i ].enabled ) {
+ available = &hwbps [ i ];
+ }
+ }
+ return available;
+}
+
+static void gdbmach_commit_hwbp ( struct hwbp *bp ) {
+ unsigned int regnum = bp - hwbps;
+
+ /* Set breakpoint address */
+ assert ( regnum < ( sizeof hwbps / sizeof hwbps [ 0 ] ) );
+ switch ( regnum ) {
+ case 0:
+ __asm__ __volatile__ ( "movl %0, %%dr0\n" : : "r" ( bp->addr ) );
+ break;
+ case 1:
+ __asm__ __volatile__ ( "movl %0, %%dr1\n" : : "r" ( bp->addr ) );
+ break;
+ case 2:
+ __asm__ __volatile__ ( "movl %0, %%dr2\n" : : "r" ( bp->addr ) );
+ break;
+ case 3:
+ __asm__ __volatile__ ( "movl %0, %%dr3\n" : : "r" ( bp->addr ) );
+ break;
+ }
+
+ /* Set type */
+ dr7 &= ~( 0x3 << ( 16 + 4 * regnum ) );
+ dr7 |= bp->type << ( 16 + 4 * regnum );
+
+ /* Set length */
+ dr7 &= ~( 0x3 << ( 18 + 4 * regnum ) );
+ dr7 |= bp->len << ( 18 + 4 * regnum );
+
+ /* Set/clear local enable bit */
+ dr7 &= ~( 0x3 << 2 * regnum );
+ dr7 |= bp->enabled << 2 * regnum;
+}
+
+int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len, int enable ) {
+ struct hwbp *bp;
+
+ /* Check and convert breakpoint type to x86 type */
+ switch ( type ) {
+ case GDBMACH_WATCH:
+ type = 0x1;
+ break;
+ case GDBMACH_AWATCH:
+ type = 0x3;
+ break;
+ default:
+ return 0; /* unsupported breakpoint type */
+ }
+
+ /* Only lengths 1, 2, and 4 are supported */
+ if ( len != 2 && len != 4 ) {
+ len = 1;
+ }
+ len--; /* convert to x86 breakpoint length bit pattern */
+
+ /* Calculate linear address by adding segment base */
+ addr += virt_offset;
+
+ /* Set up the breakpoint */
+ bp = gdbmach_find_hwbp ( type, addr, len );
+ if ( !bp ) {
+ return 0; /* ran out of hardware breakpoints */
+ }
+ bp->type = type;
+ bp->addr = addr;
+ bp->len = len;
+ bp->enabled = enable;
+ gdbmach_commit_hwbp ( bp );
+ return 1;
+}
+
+static void gdbmach_disable_hwbps ( void ) {
+ /* Store and clear hardware breakpoints */
+ __asm__ __volatile__ ( "movl %0, %%dr7\n" : : "r" ( DR7_CLEAR ) );
+}
+
+static void gdbmach_enable_hwbps ( void ) {
+ /* Clear breakpoint status register */
+ __asm__ __volatile__ ( "movl %0, %%dr6\n" : : "r" ( DR6_CLEAR ) );
+
+ /* Restore hardware breakpoints */
+ __asm__ __volatile__ ( "movl %0, %%dr7\n" : : "r" ( dr7 ) );
+}
+
+__asmcall void gdbmach_handler ( int signo, gdbreg_t *regs ) {
+ gdbmach_disable_hwbps();
+ gdbstub_handler ( signo, regs );
+ gdbmach_enable_hwbps();
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/nulltrap.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/nulltrap.c
new file mode 100644
index 0000000..3046fbe
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/nulltrap.c
@@ -0,0 +1,51 @@
+#include <stdint.h>
+#include <stdio.h>
+
+__attribute__ (( noreturn, section ( ".text.null_trap" ) ))
+void null_function_trap ( void ) {
+ void *stack;
+
+ /* 128 bytes of NOPs; the idea of this is that if something
+ * dereferences a NULL pointer and overwrites us, we at least
+ * have some chance of still getting to execute the printf()
+ * statement.
+ */
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+
+ __asm__ __volatile__ ( "movl %%esp, %0" : "=r" ( stack ) );
+ printf ( "NULL method called from %p (stack %p)\n",
+ __builtin_return_address ( 0 ), stack );
+ DBG_HD ( stack, 256 );
+ while ( 1 ) {}
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/pic8259.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/pic8259.c
new file mode 100644
index 0000000..1e2d23c
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/pic8259.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * 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; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/io.h>
+#include <pic8259.h>
+
+/** @file
+ *
+ * Minimal support for the 8259 Programmable Interrupt Controller
+ *
+ */
+
+/**
+ * Send non-specific EOI(s)
+ *
+ * @v irq IRQ number
+ *
+ * This seems to be inherently unsafe.
+ */
+static inline void send_nonspecific_eoi ( unsigned int irq ) {
+ DBG ( "Sending non-specific EOI for IRQ %d\n", irq );
+ if ( irq >= IRQ_PIC_CUTOFF ) {
+ outb ( ICR_EOI_NON_SPECIFIC, PIC2_ICR );
+ }
+ outb ( ICR_EOI_NON_SPECIFIC, PIC1_ICR );
+}
+
+/**
+ * Send specific EOI(s)
+ *
+ * @v irq IRQ number
+ */
+static inline void send_specific_eoi ( unsigned int irq ) {
+ DBG ( "Sending specific EOI for IRQ %d\n", irq );
+ if ( irq >= IRQ_PIC_CUTOFF ) {
+ outb ( ( ICR_EOI_SPECIFIC | ICR_VALUE ( CHAINED_IRQ ) ),
+ ICR_REG ( CHAINED_IRQ ) );
+ }
+ outb ( ( ICR_EOI_SPECIFIC | ICR_VALUE ( irq ) ), ICR_REG ( irq ) );
+}
+
+/**
+ * Send End-Of-Interrupt to the PIC
+ *
+ * @v irq IRQ number
+ */
+void send_eoi ( unsigned int irq ) {
+ send_specific_eoi ( irq );
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/rdtsc_timer.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/rdtsc_timer.c
new file mode 100644
index 0000000..7667917
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/rdtsc_timer.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * 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; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * RDTSC timer
+ *
+ */
+
+#include <assert.h>
+#include <gpxe/timer.h>
+#include <gpxe/timer2.h>
+
+/**
+ * Number of TSC ticks per microsecond
+ *
+ * This is calibrated on the first use of the timer.
+ */
+static unsigned long rdtsc_ticks_per_usec;
+
+/**
+ * Delay for a fixed number of microseconds
+ *
+ * @v usecs Number of microseconds for which to delay
+ */
+static void rdtsc_udelay ( unsigned long usecs ) {
+ unsigned long start;
+ unsigned long elapsed;
+
+ /* Sanity guard, since we may divide by this */
+ if ( ! usecs )
+ usecs = 1;
+
+ start = currticks();
+ if ( rdtsc_ticks_per_usec ) {
+ /* Already calibrated; busy-wait until done */
+ do {
+ elapsed = ( currticks() - start );
+ } while ( elapsed < ( usecs * rdtsc_ticks_per_usec ) );
+ } else {
+ /* Not yet calibrated; use timer2 and calibrate
+ * based on result.
+ */
+ timer2_udelay ( usecs );
+ elapsed = ( currticks() - start );
+ rdtsc_ticks_per_usec = ( elapsed / usecs );
+ DBG ( "RDTSC timer calibrated: %ld ticks in %ld usecs "
+ "(%ld MHz)\n", elapsed, usecs,
+ ( rdtsc_ticks_per_usec << TSC_SHIFT ) );
+ }
+}
+
+/**
+ * Get number of ticks per second
+ *
+ * @ret ticks_per_sec Number of ticks per second
+ */
+static unsigned long rdtsc_ticks_per_sec ( void ) {
+
+ /* Calibrate timer, if not already done */
+ if ( ! rdtsc_ticks_per_usec )
+ udelay ( 1 );
+
+ /* Sanity check */
+ assert ( rdtsc_ticks_per_usec != 0 );
+
+ return ( rdtsc_ticks_per_usec * 1000 * 1000 );
+}
+
+PROVIDE_TIMER ( rdtsc, udelay, rdtsc_udelay );
+PROVIDE_TIMER_INLINE ( rdtsc, currticks );
+PROVIDE_TIMER ( rdtsc, ticks_per_sec, rdtsc_ticks_per_sec );
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/relocate.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/relocate.c
new file mode 100644
index 0000000..44e764f
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/relocate.c
@@ -0,0 +1,170 @@
+#include <gpxe/io.h>
+#include <registers.h>
+#include <gpxe/memmap.h>
+
+/*
+ * Originally by Eric Biederman
+ *
+ * Heavily modified by Michael Brown
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * The linker passes in the symbol _max_align, which is the alignment
+ * that we must preserve, in bytes.
+ *
+ */
+extern char _max_align[];
+#define max_align ( ( unsigned int ) _max_align )
+
+/* Linker symbols */
+extern char _textdata[];
+extern char _etextdata[];
+
+/* within 1MB of 4GB is too close.
+ * MAX_ADDR is the maximum address we can easily do DMA to.
+ *
+ * Not sure where this constraint comes from, but kept it from Eric's
+ * old code - mcb30
+ */
+#define MAX_ADDR (0xfff00000UL)
+
+/**
+ * Relocate Etherboot
+ *
+ * @v ix86 x86 register dump from prefix
+ * @ret ix86 x86 registers to return to prefix
+ *
+ * This finds a suitable location for Etherboot near the top of 32-bit
+ * address space, and returns the physical address of the new location
+ * to the prefix in %edi.
+ */
+__asmcall void relocate ( struct i386_all_regs *ix86 ) {
+ struct memory_map memmap;
+ unsigned long start, end, size, padded_size;
+ unsigned long new_start, new_end;
+ unsigned i;
+
+ /* Get memory map and current location */
+ get_memmap ( &memmap );
+ start = virt_to_phys ( _textdata );
+ end = virt_to_phys ( _etextdata );
+ size = ( end - start );
+ padded_size = ( size + max_align - 1 );
+
+ DBG ( "Relocate: currently at [%lx,%lx)\n"
+ "...need %lx bytes for %d-byte alignment\n",
+ start, end, padded_size, max_align );
+
+ /* Walk through the memory map and find the highest address
+ * below 4GB that etherboot will fit into. Ensure etherboot
+ * lies entirely within a range with A20=0. This means that
+ * even if something screws up the state of the A20 line, the
+ * etherboot code is still visible and we have a chance to
+ * diagnose the problem.
+ */
+ new_end = end;
+ for ( i = 0 ; i < memmap.count ; i++ ) {
+ struct memory_region *region = &memmap.regions[i];
+ unsigned long r_start, r_end;
+
+ DBG ( "Considering [%llx,%llx)\n", region->start, region->end);
+
+ /* Truncate block to MAX_ADDR. This will be less than
+ * 4GB, which means that we can get away with using
+ * just 32-bit arithmetic after this stage.
+ */
+ if ( region->start > MAX_ADDR ) {
+ DBG ( "...starts after MAX_ADDR=%lx\n", MAX_ADDR );
+ continue;
+ }
+ r_start = region->start;
+ if ( region->end > MAX_ADDR ) {
+ DBG ( "...end truncated to MAX_ADDR=%lx\n", MAX_ADDR );
+ r_end = MAX_ADDR;
+ } else {
+ r_end = region->end;
+ }
+
+ /* Shrink the range down to use only even megabytes
+ * (i.e. A20=0).
+ */
+ if ( ( r_end - 1 ) & 0x100000 ) {
+ /* If last byte that might be used (r_end-1)
+ * is in an odd megabyte, round down r_end to
+ * the top of the next even megabyte.
+ *
+ * Make sure that we don't accidentally wrap
+ * r_end below 0.
+ */
+ if ( r_end >= 1 ) {
+ r_end = ( r_end - 1 ) & ~0xfffff;
+ DBG ( "...end truncated to %lx "
+ "(avoid ending in odd megabyte)\n",
+ r_end );
+ }
+ } else if ( ( r_end - size ) & 0x100000 ) {
+ /* If the last byte that might be used
+ * (r_end-1) is in an even megabyte, but the
+ * first byte that might be used (r_end-size)
+ * is an odd megabyte, round down to the top
+ * of the next even megabyte.
+ *
+ * Make sure that we don't accidentally wrap
+ * r_end below 0.
+ */
+ if ( r_end >= 0x100000 ) {
+ r_end = ( r_end - 0x100000 ) & ~0xfffff;
+ DBG ( "...end truncated to %lx "
+ "(avoid starting in odd megabyte)\n",
+ r_end );
+ }
+ }
+
+ DBG ( "...usable portion is [%lx,%lx)\n", r_start, r_end );
+
+ /* If we have rounded down r_end below r_ start, skip
+ * this block.
+ */
+ if ( r_end < r_start ) {
+ DBG ( "...truncated to negative size\n" );
+ continue;
+ }
+
+ /* Check that there is enough space to fit in Etherboot */
+ if ( ( r_end - r_start ) < size ) {
+ DBG ( "...too small (need %lx bytes)\n", size );
+ continue;
+ }
+
+ /* If the start address of the Etherboot we would
+ * place in this block is higher than the end address
+ * of the current highest block, use this block.
+ *
+ * Note that this avoids overlaps with the current
+ * Etherboot, as well as choosing the highest of all
+ * viable blocks.
+ */
+ if ( ( r_end - size ) > new_end ) {
+ new_end = r_end;
+ DBG ( "...new best block found.\n" );
+ }
+ }
+
+ /* Calculate new location of Etherboot, and align it to the
+ * required alignemnt.
+ */
+ new_start = new_end - padded_size;
+ new_start += ( start - new_start ) & ( max_align - 1 );
+ new_end = new_start + size;
+
+ DBG ( "Relocating from [%lx,%lx) to [%lx,%lx)\n",
+ start, end, new_start, new_end );
+
+ /* Let prefix know what to copy */
+ ix86->regs.esi = start;
+ ix86->regs.edi = new_start;
+ ix86->regs.ecx = size;
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/setjmp.S b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/setjmp.S
new file mode 100644
index 0000000..0372714
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/setjmp.S
@@ -0,0 +1,42 @@
+/* setjmp and longjmp. Use of these functions is deprecated. */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .text
+ .arch i386
+ .code32
+
+/**************************************************************************
+SETJMP - Save stack context for non-local goto
+**************************************************************************/
+ .globl setjmp
+setjmp:
+ movl 4(%esp),%ecx /* jmpbuf */
+ movl 0(%esp),%edx /* return address */
+ movl %edx,0(%ecx)
+ movl %ebx,4(%ecx)
+ movl %esp,8(%ecx)
+ movl %ebp,12(%ecx)
+ movl %esi,16(%ecx)
+ movl %edi,20(%ecx)
+ movl $0,%eax
+ ret
+
+/**************************************************************************
+LONGJMP - Non-local jump to a saved stack context
+**************************************************************************/
+ .globl longjmp
+longjmp:
+ movl 4(%esp),%edx /* jumpbuf */
+ movl 8(%esp),%eax /* result */
+ movl 0(%edx),%ecx
+ movl 4(%edx),%ebx
+ movl 8(%edx),%esp
+ movl 12(%edx),%ebp
+ movl 16(%edx),%esi
+ movl 20(%edx),%edi
+ cmpl $0,%eax
+ jne 1f
+ movl $1,%eax
+1: movl %ecx,0(%esp)
+ ret
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/stack.S b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/stack.S
new file mode 100644
index 0000000..737ec0e
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/stack.S
@@ -0,0 +1,15 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .arch i386
+
+/****************************************************************************
+ * Internal stack
+ ****************************************************************************
+ */
+ .section ".stack", "aw", @nobits
+ .align 8
+ .globl _stack
+_stack:
+ .space 4096
+ .globl _estack
+_estack:
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/stack16.S b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/stack16.S
new file mode 100644
index 0000000..523f028
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/stack16.S
@@ -0,0 +1,15 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .arch i386
+
+/****************************************************************************
+ * Internal stack
+ ****************************************************************************
+ */
+ .section ".stack16", "aw", @nobits
+ .align 8
+ .globl _stack16
+_stack16:
+ .space 4096
+ .globl _estack16
+_estack16:
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/timer2.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/timer2.c
new file mode 100644
index 0000000..6e76b2e
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/timer2.c
@@ -0,0 +1,87 @@
+/*
+ * arch/i386/core/i386_timer.c
+ *
+ * Use the "System Timer 2" to implement the udelay callback in
+ * the BIOS timer driver. Also used to calibrate the clock rate
+ * in the RTDSC timer driver.
+ *
+ * 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; either version 2, or (at
+ * your option) any later version.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <gpxe/timer2.h>
+#include <gpxe/io.h>
+
+/* Timers tick over at this rate */
+#define TIMER2_TICKS_PER_SEC 1193180U
+
+/* Parallel Peripheral Controller Port B */
+#define PPC_PORTB 0x61
+
+/* Meaning of the port bits */
+#define PPCB_T2OUT 0x20 /* Bit 5 */
+#define PPCB_SPKR 0x02 /* Bit 1 */
+#define PPCB_T2GATE 0x01 /* Bit 0 */
+
+/* Ports for the 8254 timer chip */
+#define TIMER2_PORT 0x42
+#define TIMER_MODE_PORT 0x43
+
+/* Meaning of the mode bits */
+#define TIMER0_SEL 0x00
+#define TIMER1_SEL 0x40
+#define TIMER2_SEL 0x80
+#define READBACK_SEL 0xC0
+
+#define LATCH_COUNT 0x00
+#define LOBYTE_ACCESS 0x10
+#define HIBYTE_ACCESS 0x20
+#define WORD_ACCESS 0x30
+
+#define MODE0 0x00
+#define MODE1 0x02
+#define MODE2 0x04
+#define MODE3 0x06
+#define MODE4 0x08
+#define MODE5 0x0A
+
+#define BINARY_COUNT 0x00
+#define BCD_COUNT 0x01
+
+static void load_timer2 ( unsigned int ticks ) {
+ /*
+ * Now let's take care of PPC channel 2
+ *
+ * Set the Gate high, program PPC channel 2 for mode 0,
+ * (interrupt on terminal count mode), binary count,
+ * load 5 * LATCH count, (LSB and MSB) to begin countdown.
+ *
+ * Note some implementations have a bug where the high bits byte
+ * of channel 2 is ignored.
+ */
+ /* Set up the timer gate, turn off the speaker */
+ /* Set the Gate high, disable speaker */
+ outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
+ /* binary, mode 0, LSB/MSB, Ch 2 */
+ outb(TIMER2_SEL|WORD_ACCESS|MODE0|BINARY_COUNT, TIMER_MODE_PORT);
+ /* LSB of ticks */
+ outb(ticks & 0xFF, TIMER2_PORT);
+ /* MSB of ticks */
+ outb(ticks >> 8, TIMER2_PORT);
+}
+
+static int timer2_running ( void ) {
+ return ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
+}
+
+void timer2_udelay ( unsigned long usecs ) {
+ load_timer2 ( ( usecs * TIMER2_TICKS_PER_SEC ) / ( 1000 * 1000 ) );
+ while (timer2_running()) {
+ /* Do nothing */
+ }
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/video_subr.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/video_subr.c
new file mode 100644
index 0000000..c821cd0
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/video_subr.c
@@ -0,0 +1,104 @@
+/*
+ *
+ * modified from linuxbios code
+ * by Cai Qiang <rimy2000@hotmail.com>
+ *
+ */
+
+#include "stddef.h"
+#include "string.h"
+#include <gpxe/io.h>
+#include "console.h"
+#include <gpxe/init.h>
+#include "vga.h"
+
+struct console_driver vga_console;
+
+static char *vidmem; /* The video buffer */
+static int video_line, video_col;
+
+#define VIDBUFFER 0xB8000
+
+static void memsetw(void *s, int c, unsigned int n)
+{
+ unsigned int i;
+ u16 *ss = (u16 *) s;
+
+ for (i = 0; i < n; i++) {
+ ss[i] = ( u16 ) c;
+ }
+}
+
+static void video_init(void)
+{
+ static int inited=0;
+
+ vidmem = (char *)phys_to_virt(VIDBUFFER);
+
+ if (!inited) {
+ video_line = 0;
+ video_col = 0;
+
+ memsetw(vidmem, VGA_ATTR_CLR_WHT, 2*1024); //
+
+ inited=1;
+ }
+}
+
+static void video_scroll(void)
+{
+ int i;
+
+ memcpy(vidmem, vidmem + COLS * 2, (LINES - 1) * COLS * 2);
+ for (i = (LINES - 1) * COLS * 2; i < LINES * COLS * 2; i += 2)
+ vidmem[i] = ' ';
+}
+
+static void vga_putc(int byte)
+{
+ if (byte == '\n') {
+ video_line++;
+ video_col = 0;
+
+ } else if (byte == '\r') {
+ video_col = 0;
+
+ } else if (byte == '\b') {
+ video_col--;
+
+ } else if (byte == '\t') {
+ video_col += 4;
+
+ } else if (byte == '\a') {
+ //beep
+ //beep(500);
+
+ } else {
+ vidmem[((video_col + (video_line *COLS)) * 2)] = byte;
+ vidmem[((video_col + (video_line *COLS)) * 2) +1] = VGA_ATTR_CLR_WHT;
+ video_col++;
+ }
+ if (video_col < 0) {
+ video_col = 0;
+ }
+ if (video_col >= COLS) {
+ video_line++;
+ video_col = 0;
+ }
+ if (video_line >= LINES) {
+ video_scroll();
+ video_line--;
+ }
+ // move the cursor
+ write_crtc((video_col + (video_line *COLS)) >> 8, CRTC_CURSOR_HI);
+ write_crtc((video_col + (video_line *COLS)) & 0x0ff, CRTC_CURSOR_LO);
+}
+
+struct console_driver vga_console __console_driver = {
+ .putchar = vga_putc,
+ .disabled = 1,
+};
+
+struct init_fn video_init_fn __init_fn ( INIT_EARLY ) = {
+ .initialise = video_init,
+};
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/virtaddr.S b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/virtaddr.S
new file mode 100644
index 0000000..aae1e1e
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/virtaddr.S
@@ -0,0 +1,103 @@
+/*
+ * Functions to support the virtual addressing method of relocation
+ * that Etherboot uses.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#include "librm.h"
+
+ .arch i386
+ .text
+ .code32
+
+/****************************************************************************
+ * _virt_to_phys (virtual addressing)
+ *
+ * Switch from virtual to flat physical addresses. %esp is adjusted
+ * to a physical value. Segment registers are set to flat physical
+ * selectors. All other registers are preserved. Flags are
+ * preserved.
+ *
+ * Parameters: none
+ * Returns: none
+ ****************************************************************************
+ */
+ .globl _virt_to_phys
+_virt_to_phys:
+ /* Preserve registers and flags */
+ pushfl
+ pushl %eax
+ pushl %ebp
+
+ /* Change return address to a physical address */
+ movl virt_offset, %ebp
+ addl %ebp, 12(%esp)
+
+ /* Switch to physical code segment */
+ pushl $PHYSICAL_CS
+ leal 1f(%ebp), %eax
+ pushl %eax
+ lret
+1:
+ /* Reload other segment registers and adjust %esp */
+ movl $PHYSICAL_DS, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %fs
+ movl %eax, %gs
+ movl %eax, %ss
+ addl %ebp, %esp
+
+ /* Restore registers and flags, and return */
+ popl %ebp
+ popl %eax
+ popfl
+ ret
+
+/****************************************************************************
+ * _phys_to_virt (flat physical addressing)
+ *
+ * Switch from flat physical to virtual addresses. %esp is adjusted
+ * to a virtual value. Segment registers are set to virtual
+ * selectors. All other registers are preserved. Flags are
+ * preserved.
+ *
+ * Note that this depends on the GDT already being correctly set up
+ * (e.g. by a call to run_here()).
+ *
+ * Parameters: none
+ * Returns: none
+ ****************************************************************************
+ */
+ .globl _phys_to_virt
+_phys_to_virt:
+ /* Preserve registers and flags */
+ pushfl
+ pushl %eax
+ pushl %ebp
+
+ /* Switch to virtual code segment */
+ ljmp $VIRTUAL_CS, $1f
+1:
+ /* Reload data segment registers */
+ movl $VIRTUAL_DS, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* Reload stack segment and adjust %esp */
+ movl virt_offset, %ebp
+ movl %eax, %ss
+ subl %ebp, %esp
+
+ /* Change the return address to a virtual address */
+ subl %ebp, 12(%esp)
+
+ /* Restore registers and flags, and return */
+ popl %ebp
+ popl %eax
+ popfl
+ ret
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/wince_loader.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/wince_loader.c
new file mode 100644
index 0000000..f452b65
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/wince_loader.c
@@ -0,0 +1,273 @@
+#define LOAD_DEBUG 0
+
+static int get_x_header(unsigned char *data, unsigned long now);
+static void jump_2ep();
+static unsigned char ce_signature[] = {'B', '0', '0', '0', 'F', 'F', '\n',};
+static char ** ep;
+
+#define BOOT_ARG_PTR_LOCATION 0x001FFFFC
+
+typedef struct _BOOT_ARGS{
+ unsigned char ucVideoMode;
+ unsigned char ucComPort;
+ unsigned char ucBaudDivisor;
+ unsigned char ucPCIConfigType;
+
+ unsigned long dwSig;
+ #define BOOTARG_SIG 0x544F4F42
+ unsigned long dwLen;
+
+ unsigned char ucLoaderFlags;
+ unsigned char ucEshellFlags;
+ unsigned char ucEdbgAdapterType;
+ unsigned char ucEdbgIRQ;
+
+ unsigned long dwEdbgBaseAddr;
+ unsigned long dwEdbgDebugZone;
+ unsigned long dwDHCPLeaseTime;
+ unsigned long dwEdbgFlags;
+
+ unsigned long dwEBootFlag;
+ unsigned long dwEBootAddr;
+ unsigned long dwLaunchAddr;
+
+ unsigned long pvFlatFrameBuffer;
+ unsigned short vesaMode;
+ unsigned short cxDisplayScreen;
+ unsigned short cyDisplayScreen;
+ unsigned short cxPhysicalScreen;
+ unsigned short cyPhysicalScreen;
+ unsigned short cbScanLineLength;
+ unsigned short bppScreen;
+
+ unsigned char RedMaskSize;
+ unsigned char REdMaskPosition;
+ unsigned char GreenMaskSize;
+ unsigned char GreenMaskPosition;
+ unsigned char BlueMaskSize;
+ unsigned char BlueMaskPosition;
+} BOOT_ARGS;
+
+BOOT_ARGS BootArgs;
+
+static struct segment_info{
+ unsigned long addr; // Section Address
+ unsigned long size; // Section Size
+ unsigned long checksum; // Section CheckSum
+} X;
+
+#define PSIZE (1500) //Max Packet Size
+#define DSIZE (PSIZE+12)
+static unsigned long dbuffer_available =0;
+static unsigned long not_loadin =0;
+static unsigned long d_now =0;
+
+unsigned long entry;
+static unsigned long ce_curaddr;
+
+
+static sector_t ce_loader(unsigned char *data, unsigned int len, int eof);
+static os_download_t wince_probe(unsigned char *data, unsigned int len)
+{
+ if (strncmp(ce_signature, data, sizeof(ce_signature)) != 0) {
+ return 0;
+ }
+ printf("(WINCE)");
+ return ce_loader;
+}
+
+static sector_t ce_loader(unsigned char *data, unsigned int len, int eof)
+{
+ static unsigned char dbuffer[DSIZE];
+ int this_write = 0;
+ static int firsttime = 1;
+
+ /*
+ * new packet in, we have to
+ * [1] copy data to dbuffer,
+ *
+ * update...
+ * [2] dbuffer_available
+ */
+ memcpy( (dbuffer+dbuffer_available), data, len); //[1]
+ dbuffer_available += len; // [2]
+ len = 0;
+
+ d_now = 0;
+
+#if 0
+ printf("dbuffer_available =%ld \n", dbuffer_available);
+#endif
+
+ if (firsttime)
+ {
+ d_now = sizeof(ce_signature);
+ printf("String Physical Address = %lx \n",
+ *(unsigned long *)(dbuffer+d_now));
+
+ d_now += sizeof(unsigned long);
+ printf("Image Size = %ld [%lx]\n",
+ *(unsigned long *)(dbuffer+d_now),
+ *(unsigned long *)(dbuffer+d_now));
+
+ d_now += sizeof(unsigned long);
+ dbuffer_available -= d_now;
+
+ d_now = (unsigned long)get_x_header(dbuffer, d_now);
+ firsttime = 0;
+ }
+
+ if (not_loadin == 0)
+ {
+ d_now = get_x_header(dbuffer, d_now);
+ }
+
+ while ( not_loadin > 0 )
+ {
+ /* dbuffer do not have enough data to loading, copy all */
+#if LOAD_DEBUG
+ printf("[0] not_loadin = [%ld], dbuffer_available = [%ld] \n",
+ not_loadin, dbuffer_available);
+ printf("[0] d_now = [%ld] \n", d_now);
+#endif
+
+ if( dbuffer_available <= not_loadin)
+ {
+ this_write = dbuffer_available ;
+ memcpy(phys_to_virt(ce_curaddr), (dbuffer+d_now), this_write );
+ ce_curaddr += this_write;
+ not_loadin -= this_write;
+
+ /* reset index and available in the dbuffer */
+ dbuffer_available = 0;
+ d_now = 0;
+#if LOAD_DEBUG
+ printf("[1] not_loadin = [%ld], dbuffer_available = [%ld] \n",
+ not_loadin, dbuffer_available);
+ printf("[1] d_now = [%ld], this_write = [%d] \n",
+ d_now, this_write);
+#endif
+
+ // get the next packet...
+ return (0);
+ }
+
+ /* dbuffer have more data then loading ... , copy partital.... */
+ else
+ {
+ this_write = not_loadin;
+ memcpy(phys_to_virt(ce_curaddr), (dbuffer+d_now), this_write);
+ ce_curaddr += this_write;
+ not_loadin = 0;
+
+ /* reset index and available in the dbuffer */
+ dbuffer_available -= this_write;
+ d_now += this_write;
+#if LOAD_DEBUG
+ printf("[2] not_loadin = [%ld], dbuffer_available = [%ld] \n",
+ not_loadin, dbuffer_available);
+ printf("[2] d_now = [%ld], this_write = [%d] \n\n",
+ d_now, this_write);
+#endif
+
+ /* dbuffer not empty, proceed processing... */
+
+ // don't have enough data to get_x_header..
+ if ( dbuffer_available < (sizeof(unsigned long) * 3) )
+ {
+// printf("we don't have enough data remaining to call get_x. \n");
+ memcpy( (dbuffer+0), (dbuffer+d_now), dbuffer_available);
+ return (0);
+ }
+ else
+ {
+#if LOAD_DEBUG
+ printf("with remaining data to call get_x \n");
+ printf("dbuffer available = %ld , d_now = %ld\n",
+ dbuffer_available, d_now);
+#endif
+ d_now = get_x_header(dbuffer, d_now);
+ }
+ }
+ }
+ return (0);
+}
+
+static int get_x_header(unsigned char *dbuffer, unsigned long now)
+{
+ X.addr = *(unsigned long *)(dbuffer + now);
+ X.size = *(unsigned long *)(dbuffer + now + sizeof(unsigned long));
+ X.checksum = *(unsigned long *)(dbuffer + now + sizeof(unsigned long)*2);
+
+ if (X.addr == 0)
+ {
+ entry = X.size;
+ done(1);
+ printf("Entry Point Address = [%lx] \n", entry);
+ jump_2ep();
+ }
+
+ if (!prep_segment(X.addr, X.addr + X.size, X.addr + X.size, 0, 0)) {
+ longjmp(restart_etherboot, -2);
+ }
+
+ ce_curaddr = X.addr;
+ now += sizeof(unsigned long)*3;
+
+ /* re-calculate dbuffer available... */
+ dbuffer_available -= sizeof(unsigned long)*3;
+
+ /* reset index of this section */
+ not_loadin = X.size;
+
+#if 1
+ printf("\n");
+ printf("\t Section Address = [%lx] \n", X.addr);
+ printf("\t Size = %d [%lx]\n", X.size, X.size);
+ printf("\t Checksum = %ld [%lx]\n", X.checksum, X.checksum);
+#endif
+#if LOAD_DEBUG
+ printf("____________________________________________\n");
+ printf("\t dbuffer_now = %ld \n", now);
+ printf("\t dbuffer available = %ld \n", dbuffer_available);
+ printf("\t not_loadin = %ld \n", not_loadin);
+#endif
+
+ return now;
+}
+
+static void jump_2ep()
+{
+ BootArgs.ucVideoMode = 1;
+ BootArgs.ucComPort = 1;
+ BootArgs.ucBaudDivisor = 1;
+ BootArgs.ucPCIConfigType = 1; // do not fill with 0
+
+ BootArgs.dwSig = BOOTARG_SIG;
+ BootArgs.dwLen = sizeof(BootArgs);
+
+ if(BootArgs.ucVideoMode == 0)
+ {
+ BootArgs.cxDisplayScreen = 640;
+ BootArgs.cyDisplayScreen = 480;
+ BootArgs.cxPhysicalScreen = 640;
+ BootArgs.cyPhysicalScreen = 480;
+ BootArgs.bppScreen = 16;
+ BootArgs.cbScanLineLength = 1024;
+ BootArgs.pvFlatFrameBuffer = 0x800a0000; // ollie say 0x98000000
+ }
+ else if(BootArgs.ucVideoMode != 0xFF)
+ {
+ BootArgs.cxDisplayScreen = 0;
+ BootArgs.cyDisplayScreen = 0;
+ BootArgs.cxPhysicalScreen = 0;
+ BootArgs.cyPhysicalScreen = 0;
+ BootArgs.bppScreen = 0;
+ BootArgs.cbScanLineLength = 0;
+ BootArgs.pvFlatFrameBuffer = 0;
+ }
+
+ ep = phys_to_virt(BOOT_ARG_PTR_LOCATION);
+ *ep= virt_to_phys(&BootArgs);
+ xstart32(entry);
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/arch/i386/core/x86_io.c b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/x86_io.c
new file mode 100644
index 0000000..d2c363b
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/arch/i386/core/x86_io.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * 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; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/io.h>
+#include <gpxe/x86_io.h>
+
+/** @file
+ *
+ * gPXE I/O API for x86
+ *
+ */
+
+/**
+ * Read 64-bit qword from memory-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ *
+ * This routine uses MMX instructions.
+ */
+static uint64_t x86_readq ( volatile uint64_t *io_addr ) {
+ uint64_t data;
+ __asm__ __volatile__ ( "pushl %%edx\n\t"
+ "pushl %%eax\n\t"
+ "movq (%1), %%mm0\n\t"
+ "movq %%mm0, (%%esp)\n\t"
+ "popl %%eax\n\t"
+ "popl %%edx\n\t"
+ "emms\n\t"
+ : "=A" ( data ) : "r" ( io_addr ) );
+ return data;
+}
+
+/**
+ * Write 64-bit qword to memory-mapped device
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ *
+ * This routine uses MMX instructions.
+ */
+static void x86_writeq ( uint64_t data, volatile uint64_t *io_addr ) {
+ __asm__ __volatile__ ( "pushl %%edx\n\t"
+ "pushl %%eax\n\t"
+ "movq (%%esp), %%mm0\n\t"
+ "movq %%mm0, (%1)\n\t"
+ "popl %%eax\n\t"
+ "popl %%edx\n\t"
+ "emms\n\t"
+ : : "A" ( data ), "r" ( io_addr ) );
+}
+
+PROVIDE_IOAPI_INLINE ( x86, phys_to_bus );
+PROVIDE_IOAPI_INLINE ( x86, bus_to_phys );
+PROVIDE_IOAPI_INLINE ( x86, ioremap );
+PROVIDE_IOAPI_INLINE ( x86, iounmap );
+PROVIDE_IOAPI_INLINE ( x86, io_to_bus );
+PROVIDE_IOAPI_INLINE ( x86, readb );
+PROVIDE_IOAPI_INLINE ( x86, readw );
+PROVIDE_IOAPI_INLINE ( x86, readl );
+PROVIDE_IOAPI ( x86, readq, x86_readq );
+PROVIDE_IOAPI_INLINE ( x86, writeb );
+PROVIDE_IOAPI_INLINE ( x86, writew );
+PROVIDE_IOAPI_INLINE ( x86, writel );
+PROVIDE_IOAPI ( x86, writeq, x86_writeq );
+PROVIDE_IOAPI_INLINE ( x86, inb );
+PROVIDE_IOAPI_INLINE ( x86, inw );
+PROVIDE_IOAPI_INLINE ( x86, inl );
+PROVIDE_IOAPI_INLINE ( x86, outb );
+PROVIDE_IOAPI_INLINE ( x86, outw );
+PROVIDE_IOAPI_INLINE ( x86, outl );
+PROVIDE_IOAPI_INLINE ( x86, insb );
+PROVIDE_IOAPI_INLINE ( x86, insw );
+PROVIDE_IOAPI_INLINE ( x86, insl );
+PROVIDE_IOAPI_INLINE ( x86, outsb );
+PROVIDE_IOAPI_INLINE ( x86, outsw );
+PROVIDE_IOAPI_INLINE ( x86, outsl );
+PROVIDE_IOAPI_INLINE ( x86, iodelay );
+PROVIDE_IOAPI_INLINE ( x86, mb );