Index: bootcd/isolinux/syslinux-6.03/memdisk/Makefile
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/Makefile	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/Makefile	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,103 @@
+## -----------------------------------------------------------------------
+##
+##   Copyright 2001-2009 H. Peter Anvin - All Rights Reserved
+##   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+##
+##   This program is free software; you can redistribute it and/or modify
+##   it under the terms of the GNU General Public License as published by
+##   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+##   Boston MA 02111-1307, USA; either version 2 of the License, or
+##   (at your option) any later version; incorporated herein by reference.
+##
+## -----------------------------------------------------------------------
+
+include $(MAKEDIR)/embedded.mk
+-include $(topdir)/version.mk
+
+INCLUDES = -I$(topdir)/com32/include -I$(objdir)
+CFLAGS  += -D__MEMDISK__ -DDATE='"$(DATE)"' -mregparm=3 -DREGPARM=3
+LDFLAGS  = $(GCCOPT) -g
+NASM     = nasm
+NASMOPT  = -Ox
+NFLAGS   = -dDATE='"$(DATE)"'
+NINCLUDE = -I$(SRC)/
+
+VPATH = $(SRC)
+SRCS	 = $(wildcard *.asm *.c *.h)
+
+# The DATE is set on the make command line when building binaries for
+# official release.  Otherwise, substitute a hex string that is pretty much
+# guaranteed to be unique to be unique from build to build.
+ifndef HEXDATE
+HEXDATE := $(shell $(PERL) $(SRC)/../now.pl $(SRCS))
+endif
+ifndef DATE
+DATE    := $(shell sh $(SRC)/../gen-id.sh $(VERSION) $(HEXDATE))
+endif
+
+# Important: init.o16 must be first!!
+OBJS16   = init.o16 init32.o
+OBJS32   = start32.o setup.o msetup.o e820func.o conio.o memcpy.o memset.o \
+	   memmove.o unzip.o dskprobe.o eltorito.o \
+	   ctypes.o strntoumax.o strtoull.o suffix_number.o \
+	   memdisk_chs_512.o memdisk_edd_512.o \
+	   memdisk_iso_512.o memdisk_iso_2048.o
+
+CSRC     = setup.c msetup.c e820func.c conio.c unzip.c dskprobe.c eltorito.c \
+	   ctypes.c strntoumax.c strtoull.c suffix_number.c
+SSRC     = start32.S memcpy.S memset.S memmove.S
+NASMSRC  = memdisk_chs_512.asm memdisk_edd_512.asm \
+	   memdisk_iso_512.asm memdisk_iso_2048.asm \
+	   memdisk16.asm
+
+all: memdisk # e820test
+
+# tidy, clean removes everything except the final binary
+tidy dist:
+	rm -f *.o *.s *.tmp *.o16 *.s16 *.bin *.lst *.elf e820test .*.d
+	rm -f *.map
+
+clean: tidy
+
+# spotless also removes the product binary
+spotless: clean
+	rm -f memdisk .depend
+
+memdisk16.o: memdisk16.asm
+
+# Cancel rule
+%.o: %.asm
+
+memdisk16.o: memdisk16.asm
+	( $(NASM) -M -DDEPEND $(NFLAGS) $(NINCLUDE) -o $@ $< ; echo '' ) > .$@.d ; true
+	$(NASM) -f elf $(NASMOPT) $(NFLAGS) $(NINCLUDE) -o $@ -l $*.lst $<
+
+.PRECIOUS: %.bin
+%.bin: %.asm
+	( $(NASM) -M -DDEPEND $(NFLAGS) $(NINCLUDE) -o $@ $< ; echo '' ) > .$@.d ; true
+	$(NASM) -f bin $(NASMOPT) $(NFLAGS) $(NINCLUDE) -o $@ -l $*.lst $<
+
+memdisk_%.o: memdisk_%.bin
+	$(LD) -r -b binary -o $@ $<
+
+memdisk16.elf: $(OBJS16)
+	$(LD) -Ttext 0 -o $@ $^
+
+#memdisk32.elf: memdisk.ld $(OBJS32)
+memdisk32.elf: $(ARCH)/memdisk.ld $(OBJS32)
+	$(LD) -o $@ -T $^
+
+%.bin: %.elf
+	$(OBJCOPY) -O binary $< $@
+
+memdisk: memdisk16.bin memdisk32.bin postprocess.pl
+	$(PERL) $(SRC)/postprocess.pl $@ memdisk16.bin memdisk32.bin
+
+e820test: e820test.c e820func.c msetup.c
+	$(CC) -m32 -g $(GCCWARN) -DTEST -o $@ $^
+
+# This file contains the version number, so add a dependency for it
+setup.s: ../version
+
+# Include dependencies file
+-include .*.d
Index: bootcd/isolinux/syslinux-6.03/memdisk/acpi.h
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/acpi.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/acpi.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ * This file derived almost in its entirety from gPXE.
+ *
+ * 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
+ *
+ * ACPI data structures
+ *
+ */
+
+#include <stdint.h>
+
+/**
+ * An ACPI description header
+ *
+ * This is the structure common to the start of all ACPI system
+ * description tables.
+ */
+MEMDISK_PACKED_PREFIX
+struct acpi_description_header {
+	/** ACPI signature (4 ASCII characters) */
+	char signature[4];
+	/** Length of table, in bytes, including header */
+	uint32_t length;
+	/** ACPI Specification minor version number */
+	uint8_t revision;
+	/** To make sum of entire table == 0 */
+	uint8_t checksum;
+	/** OEM identification */
+	char oem_id[6];
+	/** OEM table identification */
+	char oem_table_id[8];
+	/** OEM revision number */
+	uint32_t oem_revision;
+	/** ASL compiler vendor ID */
+	char asl_compiler_id[4];
+	/** ASL compiler revision number */
+	uint32_t asl_compiler_revision;
+} MEMDISK_PACKED_POSTFIX;
+
Index: bootcd/isolinux/syslinux-6.03/memdisk/bda.h
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/bda.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/bda.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,56 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2001-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdint.h>
+
+/* Addresses in the zero page */
+#define BIOS_INT13	(0x13*4)	/* INT 13h vector */
+#define BIOS_INT15	(0x15*4)	/* INT 15h vector */
+#define BIOS_INT1E	(0x1E*4)	/* INT 1Eh vector */
+#define BIOS_INT40	(0x40*4)	/* INT 13h vector */
+#define BIOS_INT41	(0x41*4)	/* INT 41h vector */
+#define BIOS_INT46	(0x46*4)	/* INT 46h vector */
+#define BIOS_BASEMEM	0x413		/* Amount of DOS memory */
+#define BIOS_EQUIP	0x410		/* BIOS equipment list */
+#define BIOS_HD_COUNT	0x475		/* Number of hard drives present */
+
+/* Access to objects in the zero page */
+static inline void wrz_8(uint32_t addr, uint8_t data)
+{
+    *((uint8_t *) addr) = data;
+}
+
+static inline void wrz_16(uint32_t addr, uint16_t data)
+{
+    *((uint16_t *) addr) = data;
+}
+
+static inline void wrz_32(uint32_t addr, uint32_t data)
+{
+    *((uint32_t *) addr) = data;
+}
+
+static inline uint8_t rdz_8(uint32_t addr)
+{
+    return *((uint8_t *) addr);
+}
+
+static inline uint16_t rdz_16(uint32_t addr)
+{
+    return *((uint16_t *) addr);
+}
+
+static inline uint32_t rdz_32(uint32_t addr)
+{
+    return *((uint32_t *) addr);
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/compiler.h
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/compiler.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/compiler.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,9 @@
+
+#ifdef __WATCOMC__
+# define MEMDISK_PACKED_PREFIX _Packed
+# define MEMDISK_PACKED_POSTFIX
+#else
+/* Assume GNU C for now */
+# define MEMDISK_PACKED_PREFIX
+# define MEMDISK_PACKED_POSTFIX __attribute__((packed))
+#endif
Index: bootcd/isolinux/syslinux-6.03/memdisk/conio.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/conio.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/conio.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,395 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * conio.c
+ *
+ * Output to the screen
+ */
+
+#include <stdint.h>
+#include "memdisk.h"
+#include "conio.h"
+
+int putchar(int ch)
+{
+    com32sys_t regs;
+    memset(&regs, 0, sizeof regs);
+
+    if (ch == '\n') {
+	/* \n -> \r\n */
+	putchar('\r');
+    }
+
+    regs.eax.w[0] = 0x0e00 | (ch & 0xff);
+    intcall(0x10, &regs, NULL);
+
+    return ch;
+}
+
+int puts(const char *s)
+{
+    int count = 0;
+
+    while (*s) {
+	putchar(*s);
+	count++;
+	s++;
+    }
+
+    return count;
+}
+
+/*
+ * Oh, it's a waste of space, but oh-so-yummy for debugging.  It's just
+ * initialization code anyway, so it doesn't take up space when we're
+ * actually running.  This version of printf() does not include 64-bit
+ * support.  "Live with it."
+ *
+ * Most of this code was shamelessly snarfed from the Linux kernel, then
+ * modified.
+ */
+
+static inline int isdigit(int ch)
+{
+    return (ch >= '0') && (ch <= '9');
+}
+
+static int skip_atoi(const char **s)
+{
+    int i = 0;
+
+    while (isdigit(**s))
+	i = i * 10 + *((*s)++) - '0';
+    return i;
+}
+
+unsigned int atou(const char *s)
+{
+    unsigned int i = 0;
+    while (isdigit(*s))
+	i = i * 10 + (*s++ - '0');
+    return i;
+}
+
+static int strnlen(const char *s, int maxlen)
+{
+    const char *es = s;
+    while (*es && maxlen) {
+	es++;
+	maxlen--;
+    }
+
+    return (es - s);
+}
+
+#define ZEROPAD	1		/* pad with zero */
+#define SIGN	2		/* unsigned/signed long */
+#define PLUS	4		/* show plus */
+#define SPACE	8		/* space if plus */
+#define LEFT	16		/* left justified */
+#define SPECIAL	32		/* 0x */
+#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+static char *number(char *str, long num, int base, int size, int precision,
+		    int type)
+{
+    char c, sign, tmp[66];
+    const char *digits = "0123456789abcdef";
+    int i;
+
+    if (type & LARGE)
+	digits = "0123456789ABCDEF";
+    if (type & LEFT)
+	type &= ~ZEROPAD;
+    if (base < 2 || base > 36)
+	return 0;
+    c = (type & ZEROPAD) ? '0' : ' ';
+    sign = 0;
+    if (type & SIGN) {
+	if (num < 0) {
+	    sign = '-';
+	    num = -num;
+	    size--;
+	} else if (type & PLUS) {
+	    sign = '+';
+	    size--;
+	} else if (type & SPACE) {
+	    sign = ' ';
+	    size--;
+	}
+    }
+    if (type & SPECIAL) {
+	if (base == 16)
+	    size -= 2;
+	else if (base == 8)
+	    size--;
+    }
+    i = 0;
+    if (num == 0)
+	tmp[i++] = '0';
+    else
+	while (num != 0)
+	    tmp[i++] = digits[do_div(num, base)];
+    if (i > precision)
+	precision = i;
+    size -= precision;
+    if (!(type & (ZEROPAD + LEFT)))
+	while (size-- > 0)
+	    *str++ = ' ';
+    if (sign)
+	*str++ = sign;
+    if (type & SPECIAL) {
+	if (base == 8)
+	    *str++ = '0';
+	else if (base == 16) {
+	    *str++ = '0';
+	    *str++ = digits[33];
+	}
+    }
+    if (!(type & LEFT))
+	while (size-- > 0)
+	    *str++ = c;
+    while (i < precision--)
+	*str++ = '0';
+    while (i-- > 0)
+	*str++ = tmp[i];
+    while (size-- > 0)
+	*str++ = ' ';
+    return str;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+    int len;
+    unsigned long num;
+    int i, base;
+    char *str;
+    const char *s;
+
+    int flags;			/* flags to number() */
+
+    int field_width;		/* width of output field */
+    int precision;		/* min. # of digits for integers; max
+				   number of chars for from string */
+    int qualifier;		/* 'h', 'l', or 'L' for integer fields */
+
+    for (str = buf; *fmt; ++fmt) {
+	if (*fmt != '%') {
+	    *str++ = *fmt;
+	    continue;
+	}
+
+	/* process flags */
+	flags = 0;
+repeat:
+	++fmt;			/* this also skips first '%' */
+	switch (*fmt) {
+	case '-':
+	    flags |= LEFT;
+	    goto repeat;
+	case '+':
+	    flags |= PLUS;
+	    goto repeat;
+	case ' ':
+	    flags |= SPACE;
+	    goto repeat;
+	case '#':
+	    flags |= SPECIAL;
+	    goto repeat;
+	case '0':
+	    flags |= ZEROPAD;
+	    goto repeat;
+	}
+
+	/* get field width */
+	field_width = -1;
+	if (isdigit(*fmt))
+	    field_width = skip_atoi(&fmt);
+	else if (*fmt == '*') {
+	    ++fmt;
+	    /* it's the next argument */
+	    field_width = va_arg(args, int);
+	    if (field_width < 0) {
+		field_width = -field_width;
+		flags |= LEFT;
+	    }
+	}
+
+	/* get the precision */
+	precision = -1;
+	if (*fmt == '.') {
+	    ++fmt;
+	    if (isdigit(*fmt))
+		precision = skip_atoi(&fmt);
+	    else if (*fmt == '*') {
+		++fmt;
+		/* it's the next argument */
+		precision = va_arg(args, int);
+	    }
+	    if (precision < 0)
+		precision = 0;
+	}
+
+	/* get the conversion qualifier */
+	qualifier = -1;
+	if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+	    qualifier = *fmt;
+	    ++fmt;
+	}
+
+	/* default base */
+	base = 10;
+
+	switch (*fmt) {
+	case 'c':
+	    if (!(flags & LEFT))
+		while (--field_width > 0)
+		    *str++ = ' ';
+	    *str++ = (unsigned char)va_arg(args, int);
+	    while (--field_width > 0)
+		*str++ = ' ';
+	    continue;
+
+	case 's':
+	    s = va_arg(args, char *);
+	    len = strnlen(s, precision);
+
+	    if (!(flags & LEFT))
+		while (len < field_width--)
+		    *str++ = ' ';
+	    for (i = 0; i < len; ++i)
+		*str++ = *s++;
+	    while (len < field_width--)
+		*str++ = ' ';
+	    continue;
+
+	case 'p':
+	    if (field_width == -1) {
+		field_width = 2 * sizeof(void *);
+		flags |= ZEROPAD;
+	    }
+	    str = number(str,
+			 (unsigned long)va_arg(args, void *), 16,
+			 field_width, precision, flags);
+	    continue;
+
+	case 'n':
+	    if (qualifier == 'l') {
+		long *ip = va_arg(args, long *);
+		*ip = (str - buf);
+	    } else {
+		int *ip = va_arg(args, int *);
+		*ip = (str - buf);
+	    }
+	    continue;
+
+	case '%':
+	    *str++ = '%';
+	    continue;
+
+	    /* integer number formats - set up the flags and "break" */
+	case 'o':
+	    base = 8;
+	    break;
+
+	case 'X':
+	    flags |= LARGE;
+	case 'x':
+	    base = 16;
+	    break;
+
+	case 'd':
+	case 'i':
+	    flags |= SIGN;
+	case 'u':
+	    break;
+
+	default:
+	    *str++ = '%';
+	    if (*fmt)
+		*str++ = *fmt;
+	    else
+		--fmt;
+	    continue;
+	}
+	if (qualifier == 'l')
+	    num = va_arg(args, unsigned long);
+	else if (qualifier == 'h') {
+	    num = (unsigned short)va_arg(args, int);
+	    if (flags & SIGN)
+		num = (short)num;
+	} else if (flags & SIGN)
+	    num = va_arg(args, int);
+	else
+	    num = va_arg(args, unsigned int);
+	str = number(str, num, base, field_width, precision, flags);
+    }
+    *str = '\0';
+    return str - buf;
+}
+
+#if 0
+int sprintf(char *buf, const char *fmt, ...)
+{
+    va_list args;
+    int i;
+
+    va_start(args, fmt);
+    i = vsprintf(buf, fmt, args);
+    va_end(args);
+    return i;
+}
+#endif
+
+int vprintf(const char *fmt, va_list args)
+{
+    char printf_buf[2048];
+    int printed;
+
+    printed = vsprintf(printf_buf, fmt, args);
+    puts(printf_buf);
+    return printed;
+}
+
+int printf(const char *fmt, ...)
+{
+    va_list args;
+    int printed;
+
+    va_start(args, fmt);
+    printed = vprintf(fmt, args);
+    va_end(args);
+    return printed;
+}
+
+/*
+ * Jump here if all hope is gone...
+ */
+void __attribute__ ((noreturn)) die(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    va_end(ap);
+
+    sti();
+    for (;;)
+	asm volatile("hlt");
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/conio.h
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/conio.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/conio.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,33 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * conio.h
+ *
+ * Limited console I/O
+ */
+
+#ifndef CONIO_H
+#define CONIO_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdarg.h>
+
+int putchar(int);
+int puts(const char *);
+int vprintf(const char *, va_list ap);
+int printf(const char *, ...);
+void __attribute__((noreturn)) die(const char *, ...);
+unsigned int atou(const char *);
+
+#endif
Index: bootcd/isolinux/syslinux-6.03/memdisk/ctypes.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/ctypes.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/ctypes.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,1 @@
+#include "../com32/lib/ctypes.c"
Index: bootcd/isolinux/syslinux-6.03/memdisk/dskprobe.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/dskprobe.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/dskprobe.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,228 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Shao Miller - 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * dskprobe.c
+ *
+ * Routines for probing BIOS disk drives
+ */
+
+/* Change to 1 for debugging */
+#define DBG_DSKPROBE 0
+
+#include <stdint.h>
+#include "memdisk.h"
+#include "bda.h"
+#include "conio.h"
+
+/* Function type for printf() */
+typedef int (f_printf) (const char *, ...);
+
+/* Dummy printf() that does nothing */
+static f_printf no_printf;
+static f_printf *dskprobe_printfs[] = { no_printf, printf };
+
+#define dskprobe_printf (dskprobe_printfs[DBG_DSKPROBE])
+
+static void dskprobe_pause(com32sys_t *);
+
+/* Probe routine function type */
+typedef int (f_probe) (uint8_t, com32sys_t *);
+static f_probe probe_int13h_08h, probe_int13h_15h, probe_int13h_41h;
+
+/* We will probe a BIOS drive number using INT 0x13, AH == func */
+static void probe_any(uint8_t func, uint8_t drive, com32sys_t * regs)
+{
+    regs->eax.b[1] = func;	/* AH == sub-function for probe */
+    regs->edx.b[0] = drive;	/* DL == drive number to probe */
+    intcall(0x13, regs, regs);
+    return;
+}
+
+/**
+ * Determine if the return from probe_int13h_01h indicates a failure; a
+ * return of zero indicates no known failure.
+ */
+static int probe_int13h_01h_fail(int istatus)
+{
+    int status = 0;
+
+    if (istatus >= 256)
+	status = istatus;
+    else
+	switch (istatus) {
+	case 1: status = istatus;
+	}
+    return status;
+}
+
+/**
+ * INT 0x13, AH == 0x01: Get status of last command.
+ */
+static int probe_int13h_01h(uint8_t drive)
+{
+    int status;
+    com32sys_t regs;
+
+    memset(&regs, 0, sizeof regs);
+    probe_any(0x01, drive, &regs);
+    status = (regs.eflags.l & 1) * 256 + regs.eax.b[1];
+    dskprobe_printf("  AH01: CF%d AH%02x", regs.eflags.l & 1, regs.eax.b[1]);
+    return status;
+}
+
+/**
+ * INT 0x13, AH == 0x08: Get drive parameters.
+ */
+static int probe_int13h_08h(uint8_t drive, com32sys_t * regs)
+{
+    int present;
+    int status;
+
+    memset(regs, 0, sizeof *regs);
+    probe_any(0x08, drive, regs);
+    dskprobe_printf("  AH08: CF%d AH%02x AL%02x BL%02x DL%02x    ",
+		    regs->eflags.l & 1, regs->eax.b[1], regs->eax.b[0],
+		    regs->ebx.b[0], regs->edx.b[0]);
+    present = !(regs->eflags.l & 1) && !regs->eax.b[1];
+    status = probe_int13h_01h(drive);
+    present = present && !(probe_int13h_01h_fail(status));
+    dskprobe_printf("  P%d\n",  present);
+    return present;
+}
+
+/**
+ * INT 0x13, AH == 0x15: Get disk type.
+ */
+static int probe_int13h_15h(uint8_t drive, com32sys_t * regs)
+{
+    int present;
+    int status;
+
+    memset(regs, 0, sizeof *regs);
+    probe_any(0x15, drive, regs);
+    dskprobe_printf("  AH15: CF%d AH%02x AL%02x CX%04x DX%04x",
+		    regs->eflags.l & 1, regs->eax.b[1], regs->eax.b[0],
+		    regs->ecx.w[0], regs->edx.w[0]);
+    present = !(regs->eflags.l & 1) && regs->eax.b[1];
+    status = probe_int13h_01h(drive);
+    present = present && !(probe_int13h_01h_fail(status));
+    dskprobe_printf("  P%d\n",  present);
+    return present;
+}
+
+/**
+ * INT 0x13, AH == 0x41: INT 0x13 extensions installation check.
+ */
+static int probe_int13h_41h(uint8_t drive, com32sys_t * regs)
+{
+    int present;
+    int status;
+
+    memset(regs, 0, sizeof *regs);
+    regs->ebx.w[0] = 0x55AA;	/* BX == 0x55AA */
+    probe_any(0x41, drive, regs);
+    dskprobe_printf("  AH41: CF%d AH%02x BX%04x CX%04x DH%02x",
+		    regs->eflags.l & 1, regs->eax.b[1], regs->ebx.w[0],
+		    regs->ecx.w[0], regs->edx.b[1]);
+    present = !(regs->eflags.l & 1) && (regs->ebx.w[0] == 0xAA55);
+    status = probe_int13h_01h(drive);
+    present = present && !(probe_int13h_01h_fail(status));
+    dskprobe_printf("  P%d\n",  present);
+    return present;
+}
+
+/*
+ * We will probe the BIOS Data Area and count the drives found there.
+ * This heuristic then assumes that all drives of 'drive's type are
+ * found in a contiguous range, and returns 1 if the probed drive
+ * is less than or equal to the BDA count.
+ * This particular function's code is derived from code in setup.c by
+ * H. Peter Anvin.  Please respect that file's copyright for this function
+ */
+int probe_bda_drive(uint8_t drive)
+{
+    int bios_drives;
+    int err;
+
+    if (drive & 0x80) {
+	bios_drives = rdz_8(BIOS_HD_COUNT);	/* HDD count */
+    } else {
+	uint8_t equip = rdz_8(BIOS_EQUIP);
+	if (equip & 1)
+	    bios_drives = (equip >> 6) + 1;	/* Floppy count */
+	else
+	    bios_drives = 0;
+    }
+    err = (drive - (drive & 0x80)) >= bios_drives ? 0 : 1;
+    dskprobe_printf("BDA drive %02x? %d, total count: %d\n", drive, err,
+		    bios_drives);
+    return err;
+}
+
+/*
+ * We will probe a drive with a few different methods, returning
+ * the count of succesful probes
+ */
+int multi_probe_drive(uint8_t drive)
+{
+    int c = 0;
+    com32sys_t regs;
+
+    dskprobe_printf("INT 13 DL%02x:\n", drive);
+    /* Only probe the BDA for floppies */
+    if (drive & 0x80) {
+
+	c += probe_int13h_08h(drive, &regs);
+	c += probe_int13h_15h(drive, &regs);
+	c += probe_int13h_41h(drive, &regs);
+    }
+    c += probe_bda_drive(drive);
+    dskprobe_pause(&regs);
+    return c;
+}
+
+/*
+ * We will probe a contiguous range of BIOS drive, starting with drive
+ * number 'start'.  We probe with a few different methods, and return
+ * the first drive which doesn't respond to any of the probes.
+ */
+uint8_t probe_drive_range(uint8_t start)
+{
+    uint8_t drive = start;
+    while (multi_probe_drive(drive)) {
+	drive++;
+	/* Check for passing the floppy/HDD boundary */
+	if ((drive & 0x7F) == 0)
+	    break;
+    }
+    return drive;
+}
+
+/* Dummy printf() that does nothing */
+static int no_printf(const char *ignored, ...)
+{
+    (void)ignored;
+    return 0;
+}
+
+/* Pause if we are in debug-mode */
+static void dskprobe_pause(com32sys_t * regs)
+{
+    if (!DBG_DSKPROBE)
+	return;
+    dskprobe_printf("Press a key to continue...\n");
+    memset(regs, 0, sizeof *regs);
+    regs->eax.w[0] = 0;
+    intcall(0x16, regs, NULL);
+    return;
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/dskprobe.h
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/dskprobe.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/dskprobe.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,21 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Shao Miller - 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * dskprobe.h
+ *
+ * Routines for probing BIOS disk drives
+ */
+
+#include <stdint.h>
+
+extern uint8_t probe_drive_range(uint8_t);
Index: bootcd/isolinux/syslinux-6.03/memdisk/e820.h
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/e820.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/e820.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,33 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * e820.h
+ *
+ * Common routines for e820 memory map management
+ */
+
+#include <stdint.h>
+
+struct e820range {
+    uint64_t start;
+    uint32_t type;
+} __attribute__ ((packed));
+
+extern struct e820range ranges[];
+extern int nranges;
+extern uint32_t dos_mem, low_mem, high_mem;
+
+extern void e820map_init(void);
+extern void insertrange(uint64_t, uint64_t, uint32_t);
+extern void get_mem(void);
+extern void parse_mem(void);
Index: bootcd/isolinux/syslinux-6.03/memdisk/e820data
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/e820data	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/e820data	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,15 @@
+0000000000000000 000000000009bc00 1 1
+000000000009bc00 0000000000004400 2 1
+00000000000e9800 0000000000016800 2 1
+00000000000e9800 000000000000b400 2 1
+00000000000f5000 000000000000b000 2 9
+0000000000100000 0000000006ee0000 1 1
+0000000006fe0000 000000000000fc00 3 1
+0000000006fefc00 0000000000000400 4 1
+0000000006ff0000 0000000000002000 2 1
+0000000006ff2000 000000000000e000 1 1
+0000000007000000 0000000000100000 2 1
+00000000fff00000 0000000000100000 2 1
+
+0000000000586000 0000000000168000 2 1
+000000000009ba00 0000000000000200 2 1
Index: bootcd/isolinux/syslinux-6.03/memdisk/e820func.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/e820func.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/e820func.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,107 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * e820func.c
+ *
+ * E820 range database manager
+ */
+
+#include <stdint.h>
+#ifdef TEST
+#include <string.h>
+#else
+#include "memdisk.h"		/* For memset() */
+#endif
+#include "e820.h"
+
+#define MAXRANGES	1024
+/* All of memory starts out as one range of "indeterminate" type */
+struct e820range ranges[MAXRANGES];
+int nranges;
+
+void e820map_init(void)
+{
+    memset(ranges, 0, sizeof(ranges));
+    nranges = 1;
+    ranges[1].type = -1U;
+}
+
+static void insertrange_at(int where, uint64_t start, uint32_t type)
+{
+    int i;
+
+    for (i = nranges; i > where; i--)
+	ranges[i] = ranges[i - 1];
+
+    ranges[where].start = start;
+    ranges[where].type = type;
+
+    nranges++;
+    ranges[nranges].start = 0ULL;
+    ranges[nranges].type = -1U;
+}
+
+void insertrange(uint64_t start, uint64_t len, uint32_t type)
+{
+    uint64_t last;
+    uint32_t oldtype;
+    int i, j;
+
+    /* Remove this to make len == 0 mean all of memory */
+    if (len == 0)
+	return;			/* Nothing to insert */
+
+    last = start + len - 1;	/* May roll over */
+
+    i = 0;
+    oldtype = -2U;
+    while (start > ranges[i].start && ranges[i].type != -1U) {
+	oldtype = ranges[i].type;
+	i++;
+    }
+
+    /* Consider the replacement policy.  This current one is "overwrite." */
+
+    if (start < ranges[i].start || ranges[i].type == -1U)
+	insertrange_at(i++, start, type);
+
+    while (i == 0 || last > ranges[i].start - 1) {
+	oldtype = ranges[i].type;
+	ranges[i].type = type;
+	i++;
+    }
+
+    if (last < ranges[i].start - 1)
+	insertrange_at(i, last + 1, oldtype);
+
+    /* Now the map is correct, but quite possibly not optimal.  Scan the
+       map for ranges which are redundant and remove them. */
+    i = j = 1;
+    oldtype = ranges[0].type;
+    while (i < nranges) {
+	if (ranges[i].type == oldtype) {
+	    i++;
+	} else {
+	    oldtype = ranges[i].type;
+	    if (i != j)
+		ranges[j] = ranges[i];
+	    i++;
+	    j++;
+	}
+    }
+
+    if (i != j) {
+	ranges[j] = ranges[i];	/* Termination sentinel copy */
+	nranges -= (i - j);
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/e820test.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/e820test.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/e820test.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,88 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * e820hack.c
+ *
+ * Test of INT 15:E820 canonicalization/manipulation routine
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include "e820.h"
+
+void *sys_bounce;		/* Dummy */
+
+extern void parse_mem(void);
+extern uint32_t dos_mem, low_mem, high_mem;
+
+void __attribute__ ((noreturn)) die(void)
+{
+    abort();
+}
+
+void printranges(void)
+{
+    int i;
+
+    for (i = 0; i < nranges; i++) {
+	printf("%016llx %016llx %d\n",
+	       ranges[i].start,
+	       ranges[i + 1].start - ranges[i].start, ranges[i].type);
+    }
+}
+
+int main(void)
+{
+    uint64_t start, len;
+    uint32_t type;
+    char line[BUFSIZ], *p;
+
+    e820map_init();
+    printranges();
+
+    while (fgets(line, BUFSIZ, stdin)) {
+	p = strchr(line, ':');
+	p = p ? p + 1 : line;
+	if (sscanf(p, " %llx %llx %d", &start, &len, &type) == 3) {
+	    putchar('\n');
+	    printf("%016llx %016llx %d <-\n", start, len, type);
+	    putchar('\n');
+	    insertrange(start, len, type);
+	    printranges();
+	}
+    }
+
+    parse_mem();
+
+    putchar('\n');
+    printf("DOS  mem = %#10x (%u K)\n", dos_mem, dos_mem >> 10);
+    printf("Low  mem = %#10x (%u K)\n", low_mem, low_mem >> 10);
+    printf("High mem = %#10x (%u K)\n", high_mem, high_mem >> 10);
+    putchar('\n');
+
+    /* Now, steal a chunk (2K) of DOS memory and make sure it registered OK */
+    insertrange(dos_mem - 2048, 2048, 2, 1);	/* Type 2 = reserved */
+
+    printranges();
+    parse_mem();
+
+    putchar('\n');
+    printf("DOS  mem = %#10x (%u K)\n", dos_mem, dos_mem >> 10);
+    printf("Low  mem = %#10x (%u K)\n", low_mem, low_mem >> 10);
+    printf("High mem = %#10x (%u K)\n", high_mem, high_mem >> 10);
+    putchar('\n');
+
+    return 0;
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/eltorito.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/eltorito.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/eltorito.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,58 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Shao Miller - 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * eltorito.c
+ *
+ * EDD-4 El Torito structures and debugging routines
+ */
+
+#include <stdint.h>
+#include "memdisk.h"
+#include "conio.h"
+#include "eltorito.h"
+
+#ifdef DBG_ELTORITO
+void eltorito_dump(uint32_t image)
+{
+    printf("-- El Torito dump --\n", image);
+
+    /* BVD starts at sector 17. */
+    struct edd4_bvd *bvd = (struct edd4_bvd *)(image + 17 * 2048);
+
+    printf("bvd.boot_rec_ind: 0x%02x\n", bvd->boot_rec_ind);
+    printf("bvd.iso9660_id: %c%c%c%c%c\n", bvd->iso9660_id[0],
+	   bvd->iso9660_id[1], bvd->iso9660_id[2], bvd->iso9660_id[3],
+	   bvd->iso9660_id[4]);
+    printf("bvd.ver: 0x%02x\n", bvd->ver);
+    printf("bvd.eltorito: %s\n", bvd->eltorito);
+    printf("bvd.boot_cat: 0x%08x\n", bvd->boot_cat);
+
+    struct edd4_bootcat *boot_cat =
+	(struct edd4_bootcat *)(image + bvd->boot_cat * 2048);
+
+    printf("boot_cat.validation_entry\n");
+    printf("  .header_id: 0x%02x\n", boot_cat->validation_entry.header_id);
+    printf("  .platform_id: 0x%02x\n", boot_cat->validation_entry.platform_id);
+    printf("  .id_string: %s\n", boot_cat->validation_entry.id_string);
+    printf("  .checksum: 0x%04x\n", boot_cat->validation_entry.checksum);
+    printf("  .key55: 0x%02x\n", boot_cat->validation_entry.key55);
+    printf("  .keyAA: 0x%02x\n", boot_cat->validation_entry.keyAA);
+    printf("boot_cat.initial_entry\n");
+    printf("  .header_id: 0x%02x\n", boot_cat->initial_entry.header_id);
+    printf("  .media_type: 0x%02x\n", boot_cat->initial_entry.media_type);
+    printf("  .load_seg: 0x%04x\n", boot_cat->initial_entry.load_seg);
+    printf("  .system_type: 0x%02x\n", boot_cat->initial_entry.system_type);
+    printf("  .sect_count: %d\n", boot_cat->initial_entry.sect_count);
+    printf("  .load_block: 0x%08x\n", boot_cat->initial_entry.load_block);
+}
+#endif
Index: bootcd/isolinux/syslinux-6.03/memdisk/eltorito.h
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/eltorito.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/eltorito.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,80 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009-2010 Shao Miller - 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * eltorito.h
+ *
+ * EDD-4 El Torito structures and debugging routines
+ */
+
+#include <stdint.h>
+#include "compiler.h"
+
+/* EDD-4 Bootable Optical Disc Drive Boot Volume Descriptor */
+MEMDISK_PACKED_PREFIX
+struct edd4_bvd {
+    uint8_t boot_rec_ind;	/* Boot Record Indicator */
+    uint8_t iso9660_id[5];	/* ISO9660 ID            */
+    uint8_t ver;		/* Descriptor Version    */
+    uint8_t eltorito[32];	/* "EL TORITO" etc.      */
+    uint8_t res1[32];		/* Reserved              */
+    uint32_t boot_cat;		/* Boot catalog sector   */
+    uint8_t res2[1973];		/* Reserved              */
+} MEMDISK_PACKED_POSTFIX;
+
+MEMDISK_PACKED_PREFIX
+struct validation_entry {
+    uint8_t header_id;		/* Header ID                      */
+    uint8_t platform_id;	/* Platform ID                    */
+    uint16_t res1;		/* Reserved                       */
+    uint8_t id_string[24];	/* Manufacturer                   */
+    uint16_t checksum;		/* Sums with whole record to zero */
+    uint8_t key55;		/* Key byte 0x55                  */
+    uint8_t keyAA;		/* Key byte 0xAA                  */
+} MEMDISK_PACKED_POSTFIX;
+
+MEMDISK_PACKED_PREFIX
+struct initial_entry {
+    uint8_t header_id;		/* Header ID                */
+    uint8_t media_type;		/* Media type               */
+    uint16_t load_seg;		/* Load segment             */
+    uint8_t system_type;	/* (Filesystem ID)          */
+    uint8_t res1;		/* Reserved                 */
+    uint16_t sect_count;	/* Emulated sectors to load */
+    uint32_t load_block;	/* Starting sector of image */
+    uint8_t res2[4];		/* Reserved                 */
+} MEMDISK_PACKED_POSTFIX;
+
+/* EDD-4 Bootable Optical Disc Drive Boot Catalog (fixed-size portions) */
+MEMDISK_PACKED_PREFIX
+struct edd4_bootcat {
+    struct validation_entry validation_entry;
+    struct initial_entry initial_entry;
+} MEMDISK_PACKED_POSTFIX;
+
+/* EDD-4 CD Specification Packet */
+MEMDISK_PACKED_PREFIX
+struct edd4_cd_pkt {
+    uint8_t size;		/* Packet size                     */
+    uint8_t type;		/* Boot media type (flags)         */
+    uint8_t driveno;		/* INT 13h drive number            */
+    uint8_t controller;		/* Controller index                */
+    uint32_t start;		/* Starting LBA of image           */
+    uint16_t devno;		/* Device number                   */
+    uint16_t userbuf;		/* User buffer segment             */
+    uint16_t load_seg;		/* Load segment                    */
+    uint16_t sect_count;	/* Emulated sectors to load        */
+    uint8_t geom1;		/* Cylinders bits 0 thru 7         */
+    uint8_t geom2;		/* Sects/track 0 thru 5, cyls 8, 9 */
+    uint8_t geom3;		/* Heads                           */
+} MEMDISK_PACKED_POSTFIX;
+
Index: bootcd/isolinux/syslinux-6.03/memdisk/fdgeo.pl
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/fdgeo.pl	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/fdgeo.pl	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,56 @@
+#!/usr/bin/perl
+#
+# Try automatic generation of geometries
+#
+
+($k) = @ARGV;
+$sec = int($k*2+0.5);
+
+if ($sec < 320*2) {
+    $c = 40;
+    $h = 1;
+    $type = 1;
+} elsif ($sec < 640*2) {
+    $c = 40;
+    $h = 2;
+    $type = 1;
+} elsif ($sec < 1200*2) {
+    $c = 80;
+    $h = 2;
+    $type = 3;
+} elsif ($sec < 1440*2) {
+    $c = 80;
+    $h = 2;
+    $type = 2;
+} elsif ($sec < 2880*2) {
+    $c = 80;
+    $h = 2;
+    $type = 4;
+} elsif ($sec < 4096*2) {
+    $c = 80;
+    $h = 2;
+    $type = 6;
+} else {
+    printf "%.1fK, %d sectors: ", $sec/2, $sec;
+    print "Considered a hard disk\n";
+    exit 2;
+}
+
+$ok = 0;
+while ($c < 256) {
+    $s = int($sec/($c*$h)+0.5);
+    if ($s <= 63 && $sec == $c*$h*$s) {
+	$ok = 1;
+	last;
+    }
+    $c++;
+}
+
+printf "%.1fK, %d sectors: ", $sec/2, $sec;
+if ($ok) {
+    print "c=$c, h=$h, s=$s, type=$type\n";
+    exit 0;
+} else {
+    print "No valid geometry found (MEMDISK will fake it)\n";
+    exit 1;
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/i386/memdisk.ld
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/i386/memdisk.ld	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/i386/memdisk.ld	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,140 @@
+/* -----------------------------------------------------------------------
+ *   
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Linker script for MEMDISK
+ */
+
+/* Script for -z combreloc: combine and sort reloc sections */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+EXTERN(_start)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0x100000;
+  PROVIDE (__executable_start = .);
+
+  .init           :
+  {
+    KEEP (*(.init))
+  } =0x90909090
+  .text           :
+  {
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0x90909090
+  .fini           :
+  {
+    KEEP (*(.fini))
+  } =0x90909090
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1        : { *(.rodata1) }
+
+  /* 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          :
+  {
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  PROVIDE (__ctors_end = .);
+  PROVIDE (__dtors_start = .);
+  .dtors          :
+  {
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  PROVIDE (__dtors_end = .);
+
+  /* Adjust the address for the data segment.  Avoid mixing code and
+     data within same 128-byte chunk. */
+  . = ALIGN(128);
+
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .;
+  PROVIDE (edata = .);
+  . = ALIGN(16);
+  .bss            :
+  {
+   __bss_start = .;
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.  */
+   . = ALIGN(4);
+   __bss_end = .;
+  }
+  _end = .;
+  PROVIDE (end = .);
+
+
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /DISCARD/ : { *(.note.GNU-stack) }
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/inflate.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/inflate.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/inflate.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,1026 @@
+#define DEBG(x)
+#define DEBG1(x)
+/* inflate.c -- Not copyrighted 1992 by Mark Adler
+   version c10p1, 10 January 1993 */
+
+/*
+ * Adapted for booting Linux by Hannu Savolainen 1993
+ * based on gzip-1.0.3
+ *
+ * Nicolas Pitre <nico@cam.org>, 1999/04/14 :
+ *   Little mods for all variable to reside either into rodata or bss segments
+ *   by marking constant variables with 'const' and initializing all the others
+ *   at run-time only.  This allows for the kernel uncompressor to run
+ *   directly from Flash or ROM memory on embedded systems.
+ *
+ * Adapted for MEMDISK by H. Peter Anvin, April 2003
+ */
+
+/*
+   Inflate deflated (PKZIP's method 8 compressed) data.  The compression
+   method searches for as much of the current string of bytes (up to a
+   length of 258) in the previous 32 K bytes.  If it doesn't find any
+   matches (of at least length 3), it codes the next byte.  Otherwise, it
+   codes the length of the matched string and its distance backwards from
+   the current position.  There is a single Huffman code that codes both
+   single bytes (called "literals") and match lengths.  A second Huffman
+   code codes the distance information, which follows a length code.  Each
+   length or distance code actually represents a base value and a number
+   of "extra" (sometimes zero) bits to get to add to the base value.  At
+   the end of each deflated block is a special end-of-block (EOB) literal/
+   length code.  The decoding process is basically: get a literal/length
+   code; if EOB then done; if a literal, emit the decoded byte; if a
+   length then get the distance and emit the referred-to bytes from the
+   sliding window of previously emitted data.
+
+   There are (currently) three kinds of inflate blocks: stored, fixed, and
+   dynamic.  The compressor deals with some chunk of data at a time, and
+   decides which method to use on a chunk-by-chunk basis.  A chunk might
+   typically be 32 K or 64 K.  If the chunk is incompressible, then the
+   "stored" method is used.  In this case, the bytes are simply stored as
+   is, eight bits per byte, with none of the above coding.  The bytes are
+   preceded by a count, since there is no longer an EOB code.
+
+   If the data is compressible, then either the fixed or dynamic methods
+   are used.  In the dynamic method, the compressed data is preceded by
+   an encoding of the literal/length and distance Huffman codes that are
+   to be used to decode this block.  The representation is itself Huffman
+   coded, and so is preceded by a description of that code.  These code
+   descriptions take up a little space, and so for small blocks, there is
+   a predefined set of codes, called the fixed codes.  The fixed method is
+   used if the block codes up smaller that way (usually for quite small
+   chunks), otherwise the dynamic method is used.  In the latter case, the
+   codes are customized to the probabilities in the current block, and so
+   can code it much better than the pre-determined fixed codes.
+
+   The Huffman codes themselves are decoded using a multi-level table
+   lookup, in order to maximize the speed of decoding plus the speed of
+   building the decoding tables.  See the comments below that precede the
+   lbits and dbits tuning parameters.
+ */
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarly, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "#Id: inflate.c,v 0.14 1993/06/10 13:27:04 jloup Exp #";
+#endif
+
+#define slide window
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model).
+   Valid extra bits are 0..13.  e == 15 is EOB (end of block), e == 16
+   means that v is a literal, 16 < e < 32 means that v is a pointer to
+   the next table, which codes e - 16 bits, and lastly e == 99 indicates
+   an unused code.  If a code with e == 99 is looked up, this implies an
+   error in the data. */
+struct huft {
+    uch e;			/* number of extra bits or operation */
+    uch b;			/* number of bits in this code or subcode */
+    union {
+	ush n;			/* literal, length base, or distance base */
+	struct huft *t;		/* pointer to next level of table */
+    } v;
+};
+
+/* Function prototypes */
+STATIC int huft_build OF((unsigned *, unsigned, unsigned,
+			  const ush *, const ush *, struct huft **, int *));
+STATIC int huft_free OF((struct huft *));
+STATIC int inflate_codes OF((struct huft *, struct huft *, int, int));
+STATIC int inflate_stored OF((void));
+STATIC int inflate_fixed OF((void));
+STATIC int inflate_dynamic OF((void));
+STATIC int inflate_block OF((int *));
+STATIC int inflate OF((void));
+
+/* The inflate algorithm uses a sliding 32 K byte window on the uncompressed
+   stream to find repeated byte strings.  This is implemented here as a
+   circular buffer.  The index is updated simply by incrementing and then
+   ANDing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32 K area.  It is assumed
+   to be usable as if it were declared "uch slide[32768];" or as just
+   "uch *slide;" and then malloc'ed in the latter case.  The definition
+   must be in unzip.h, included above. */
+/* unsigned wp;             current position in slide */
+#define wp outcnt
+#define flush_output(w) (wp=(w),flush_window())
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static const unsigned border[] = {	/* Order of the bit length code lengths */
+    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+};
+
+static const ush cplens[] = {	/* Copy lengths for literal codes 257..285 */
+    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+    35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+};
+
+	/* note: see note #13 above about the 258 in this list. */
+static const ush cplext[] = {	/* Extra bits for literal codes 257..285 */
+    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+    3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
+};				/* 99==invalid */
+
+static const ush cpdist[] = {	/* Copy offsets for distance codes 0..29 */
+    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+    257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+    8193, 12289, 16385, 24577
+};
+
+static const ush cpdext[] = {	/* Extra bits for distance codes */
+    0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+    7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+    12, 12, 13, 13
+};
+
+/* Macros for inflate() bit peeking and grabbing.
+   The usage is:
+
+        NEEDBITS(j)
+        x = b & mask_bits[j];
+        DUMPBITS(j)
+
+   where NEEDBITS makes sure that b has at least j bits in it, and
+   DUMPBITS removes the bits from b.  The macros use the variable k
+   for the number of bits in b.  Normally, b and k are register
+   variables for speed, and are initialized at the beginning of a
+   routine that uses these macros from a global bit buffer and count.
+
+   If we assume that EOB will be the longest code, then we will never
+   ask for bits with NEEDBITS that are beyond the end of the stream.
+   So, NEEDBITS should not read any more bytes than are needed to
+   meet the request.  Then no bytes need to be "returned" to the buffer
+   at the end of the last block.
+
+   However, this assumption is not true for fixed blocks--the EOB code
+   is 7 bits, but the other literal/length codes can be 8 or 9 bits.
+   (The EOB code is shorter than other codes because fixed blocks are
+   generally short.  So, while a block always has an EOB, many other
+   literal/length codes have a significantly lower probability of
+   showing up at all.)  However, by making the first table have a
+   lookup of seven bits, the EOB code will be found in that first
+   lookup, and so will not require that too many bits be pulled from
+   the stream.
+ */
+
+STATIC ulg bb;			/* bit buffer */
+STATIC unsigned bk;		/* bits in bit buffer */
+
+STATIC const ush mask_bits[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+#define NEXTBYTE()  (uch)get_byte()
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+STATIC const int lbits = 9;	/* bits in base literal/length lookup table */
+STATIC const int dbits = 6;	/* bits in base distance lookup table */
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16			/* maximum bit length of any code (16 for explode) */
+#define N_MAX 288		/* maximum number of codes in any set */
+
+STATIC unsigned hufts;		/* track memory usage */
+
+STATIC int huft_build(b, n, s, d, e, t, m)
+unsigned *b;			/* code lengths in bits (all assumed <= BMAX) */
+unsigned n;			/* number of codes (assumed <= N_MAX) */
+unsigned s;			/* number of simple-valued codes (0..s-1) */
+const ush *d;			/* list of base values for non-simple codes */
+const ush *e;			/* list of extra bits for non-simple codes */
+struct huft **t;		/* result: starting table */
+int *m;				/* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return zero on success, one if
+   the given code set is incomplete (the tables are still built in this
+   case), two if the input is invalid (all zero length codes or an
+   oversubscribed set of lengths), and three if not enough memory. */
+{
+    unsigned a;			/* counter for codes of length k */
+    unsigned c[BMAX + 1];	/* bit length count table */
+    unsigned f;			/* i repeats in table every f entries */
+    int g;			/* maximum code length */
+    int h;			/* table level */
+    register unsigned i;	/* counter, current code */
+    register unsigned j;	/* counter */
+    register int k;		/* number of bits in current code */
+    int l;			/* bits per table (returned in m) */
+    register unsigned *p;	/* pointer into c[], b[], or v[] */
+    register struct huft *q;	/* points to current table */
+    struct huft r;		/* table entry for structure assignment */
+    struct huft *u[BMAX];	/* table stack */
+    unsigned v[N_MAX];		/* values in order of bit length */
+    register int w;		/* bits before this table == (l * h) */
+    unsigned x[BMAX + 1];	/* bit offsets, then code stack */
+    unsigned *xp;		/* pointer into x */
+    int y;			/* number of dummy codes added */
+    unsigned z;			/* number of entries in current table */
+
+    DEBG("huft1 ");
+
+    /* Generate counts for each bit length */
+    memzero(c, sizeof(c));
+    p = b;
+    i = n;
+    do {
+	Tracecv(*p,
+		(stderr,
+		 (n - i >= ' '
+		  && n - i <= '~' ? "%c %d\n" : "0x%x %d\n"), n - i, *p));
+	c[*p]++;		/* assume all entries <= BMAX */
+	p++;			/* Can't combine with above line (Solaris bug) */
+    } while (--i);
+    if (c[0] == n) {		/* null input--all zero length codes */
+	*t = (struct huft *)NULL;
+	*m = 0;
+	return 0;
+    }
+
+    DEBG("huft2 ");
+
+    /* Find minimum and maximum length, bound *m by those */
+    l = *m;
+    for (j = 1; j <= BMAX; j++)
+	if (c[j])
+	    break;
+    k = j;			/* minimum code length */
+    if ((unsigned)l < j)
+	l = j;
+    for (i = BMAX; i; i--)
+	if (c[i])
+	    break;
+    g = i;			/* maximum code length */
+    if ((unsigned)l > i)
+	l = i;
+    *m = l;
+
+    DEBG("huft3 ");
+
+    /* Adjust last length count to fill out codes, if needed */
+    for (y = 1 << j; j < i; j++, y <<= 1)
+	if ((y -= c[j]) < 0)
+	    return 2;		/* bad input: more codes than bits */
+    if ((y -= c[i]) < 0)
+	return 2;
+    c[i] += y;
+
+    DEBG("huft4 ");
+
+    /* Generate starting offsets into the value table for each length */
+    x[1] = j = 0;
+    p = c + 1;
+    xp = x + 2;
+    while (--i) {		/* note that i == g from above */
+	*xp++ = (j += *p++);
+    }
+
+    DEBG("huft5 ");
+
+    /* Make a table of values in order of bit lengths */
+    p = b;
+    i = 0;
+    do {
+	if ((j = *p++) != 0)
+	    v[x[j]++] = i;
+    } while (++i < n);
+
+    DEBG("h6 ");
+
+    /* Generate the Huffman codes and for each, make the table entries */
+    x[0] = i = 0;		/* first Huffman code is zero */
+    p = v;			/* grab values in bit order */
+    h = -1;			/* no tables yet--level -1 */
+    w = -l;			/* bits decoded == (l * h) */
+    u[0] = (struct huft *)NULL;	/* just to keep compilers happy */
+    q = (struct huft *)NULL;	/* ditto */
+    z = 0;			/* ditto */
+    DEBG("h6a ");
+
+    /* go through the bit lengths (k already is bits in shortest code) */
+    for (; k <= g; k++) {
+	DEBG("h6b ");
+	a = c[k];
+	while (a--) {
+	    DEBG("h6b1 ");
+	    /* here i is the Huffman code of length k bits for value *p */
+	    /* make tables up to required level */
+	    while (k > w + l) {
+		DEBG1("1 ");
+		h++;
+		w += l;		/* previous table always l bits */
+
+		/* compute minimum size table less than or equal to l bits */
+		z = (z = g - w) > (unsigned)l ? l : z;	/* upper limit on table size */
+		if ((f = 1 << (j = k - w)) > a + 1) {	/* try a k-w bit table *//* too few codes for k-w bit table */
+		    DEBG1("2 ");
+		    f -= a + 1;	/* deduct codes from patterns left */
+		    xp = c + k;
+		    while (++j < z) {	/* try smaller tables up to z bits */
+			if ((f <<= 1) <= *++xp)
+			    break;	/* enough codes to use up j bits */
+			f -= *xp;	/* else deduct codes from patterns */
+		    }
+		}
+		DEBG1("3 ");
+		z = 1 << j;	/* table entries for j-bit table */
+
+		/* allocate and link in new table */
+		if ((q =
+		     (struct huft *)malloc((z + 1) * sizeof(struct huft))) ==
+		    (struct huft *)NULL) {
+		    if (h)
+			huft_free(u[0]);
+		    return 3;	/* not enough memory */
+		}
+		DEBG1("4 ");
+		hufts += z + 1;	/* track memory usage */
+		*t = q + 1;	/* link to list for huft_free() */
+		*(t = &(q->v.t)) = (struct huft *)NULL;
+		u[h] = ++q;	/* table starts after link */
+
+		DEBG1("5 ");
+		/* connect to last table, if there is one */
+		if (h) {
+		    x[h] = i;	/* save pattern for backing up */
+		    r.b = (uch) l;	/* bits to dump before this table */
+		    r.e = (uch) (16 + j);	/* bits in this table */
+		    r.v.t = q;	/* pointer to this table */
+		    j = i >> (w - l);	/* (get around Turbo C bug) */
+		    u[h - 1][j] = r;	/* connect to last table */
+		}
+		DEBG1("6 ");
+	    }
+	    DEBG("h6c ");
+
+	    /* set up table entry in r */
+	    r.b = (uch) (k - w);
+	    if (p >= v + n)
+		r.e = 99;	/* out of values--invalid code */
+	    else if (*p < s) {
+		r.e = (uch) (*p < 256 ? 16 : 15);	/* 256 is end-of-block code */
+		r.v.n = (ush) (*p);	/* simple code is just the value */
+		p++;		/* one compiler does not like *p++ */
+	    } else {
+		r.e = (uch) e[*p - s];	/* non-simple--look up in lists */
+		r.v.n = d[*p++ - s];
+	    }
+	    DEBG("h6d ");
+
+	    /* fill code-like entries with r */
+	    f = 1 << (k - w);
+	    for (j = i >> w; j < z; j += f)
+		q[j] = r;
+
+	    /* backwards increment the k-bit code i */
+	    for (j = 1 << (k - 1); i & j; j >>= 1)
+		i ^= j;
+	    i ^= j;
+
+	    /* backup over finished tables */
+	    while ((i & ((1 << w) - 1)) != x[h]) {
+		h--;		/* don't need to update q */
+		w -= l;
+	    }
+	    DEBG("h6e ");
+	}
+	DEBG("h6f ");
+    }
+
+    DEBG("huft7 ");
+
+    /* Return true (1) if we were given an incomplete table */
+    return y != 0 && g != 1;
+}
+
+STATIC int huft_free(t)
+struct huft *t;			/* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+   list of the tables it made, with the links in a dummy first entry of
+   each table. */
+{
+    register struct huft *p, *q;
+
+    /* Go through linked list, freeing from the malloced (t[-1]) address. */
+    p = t;
+    while (p != (struct huft *)NULL) {
+	q = (--p)->v.t;
+	free((char *)p);
+	p = q;
+    }
+    return 0;
+}
+
+STATIC int inflate_codes(tl, td, bl, bd)
+struct huft *tl, *td;		/* literal/length and distance decoder tables */
+int bl, bd;			/* number of bits decoded by tl[] and td[] */
+/* inflate (decompress) the codes in a deflated (compressed) block.
+   Return an error code or zero if it all goes ok. */
+{
+    register unsigned e;	/* table entry flag/number of extra bits */
+    unsigned n, d;		/* length and index for copy */
+    unsigned w;			/* current window position */
+    struct huft *t;		/* pointer to table entry */
+    unsigned ml, md;		/* masks for bl and bd bits */
+    register ulg b;		/* bit buffer */
+    register unsigned k;	/* number of bits in bit buffer */
+
+    /* make local copies of globals */
+    b = bb;			/* initialize bit buffer */
+    k = bk;
+    w = wp;			/* initialize window position */
+
+    /* inflate the coded data */
+    ml = mask_bits[bl];		/* precompute masks for speed */
+    md = mask_bits[bd];
+    for (;;) {			/* do until end of block */
+	NEEDBITS((unsigned)bl)
+	    if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
+	    do {
+		if (e == 99)
+		    return 1;
+		DUMPBITS(t->b)
+		    e -= 16;
+		NEEDBITS(e)
+	    } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+	DUMPBITS(t->b)
+	    if (e == 16) {	/* then it's a literal */
+	    slide[w++] = (uch) t->v.n;
+	    Tracevv((stderr, "%c", slide[w - 1]));
+	    if (w == WSIZE) {
+		flush_output(w);
+		w = 0;
+	    }
+	} else {		/* it's an EOB or a length */
+
+	    /* exit if end of block */
+	    if (e == 15)
+		break;
+
+	    /* get length of block to copy */
+	    NEEDBITS(e)
+		n = t->v.n + ((unsigned)b & mask_bits[e]);
+	    DUMPBITS(e);
+
+	    /* decode distance of block to copy */
+	    NEEDBITS((unsigned)bd)
+		if ((e = (t = td + ((unsigned)b & md))->e) > 16)
+		do {
+		    if (e == 99)
+			return 1;
+		    DUMPBITS(t->b)
+			e -= 16;
+		    NEEDBITS(e)
+		} while ((e =
+			  (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+	    DUMPBITS(t->b)
+		NEEDBITS(e)
+		d = w - t->v.n - ((unsigned)b & mask_bits[e]);
+	    DUMPBITS(e)
+		Tracevv((stderr, "\\[%d,%d]", w - d, n));
+
+	    /* do the copy */
+	    do {
+		n -= (e =
+		      (e = WSIZE - ((d &= WSIZE - 1) > w ? d : w)) > n ? n : e);
+#if !defined(NOMEMCPY) && !defined(DEBUG)
+		if (w - d >= e) {	/* (this test assumes unsigned comparison) */
+		    memcpy(slide + w, slide + d, e);
+		    w += e;
+		    d += e;
+		} else		/* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+		    do {
+			slide[w++] = slide[d++];
+			Tracevv((stderr, "%c", slide[w - 1]));
+		    } while (--e);
+		if (w == WSIZE) {
+		    flush_output(w);
+		    w = 0;
+		}
+	    } while (n);
+	}
+    }
+
+    /* restore the globals from the locals */
+    wp = w;			/* restore global window pointer */
+    bb = b;			/* restore global bit buffer */
+    bk = k;
+
+    /* done */
+    return 0;
+}
+
+STATIC int inflate_stored()
+/* "decompress" an inflated type 0 (stored) block. */
+{
+    unsigned n;			/* number of bytes in block */
+    unsigned w;			/* current window position */
+    register ulg b;		/* bit buffer */
+    register unsigned k;	/* number of bits in bit buffer */
+
+    DEBG("<stor");
+
+    /* make local copies of globals */
+    b = bb;			/* initialize bit buffer */
+    k = bk;
+    w = wp;			/* initialize window position */
+
+    /* go to byte boundary */
+    n = k & 7;
+    DUMPBITS(n);
+
+    /* get the length and its complement */
+    NEEDBITS(16)
+	n = ((unsigned)b & 0xffff);
+    DUMPBITS(16)
+	NEEDBITS(16)
+	if (n != (unsigned)((~b) & 0xffff))
+	return 1;		/* error in compressed data */
+    DUMPBITS(16)
+
+	/* read and output the compressed data */
+	while (n--) {
+	NEEDBITS(8)
+	    slide[w++] = (uch) b;
+	if (w == WSIZE) {
+	    flush_output(w);
+	    w = 0;
+	}
+	DUMPBITS(8)
+    }
+
+    /* restore the globals from the locals */
+    wp = w;			/* restore global window pointer */
+    bb = b;			/* restore global bit buffer */
+    bk = k;
+
+    DEBG(">");
+    return 0;
+}
+
+STATIC int inflate_fixed()
+/* decompress an inflated type 1 (fixed Huffman codes) block.  We should
+   either replace this with a custom decoder, or at least precompute the
+   Huffman tables. */
+{
+    int i;			/* temporary variable */
+    struct huft *tl;		/* literal/length code table */
+    struct huft *td;		/* distance code table */
+    int bl;			/* lookup bits for tl */
+    int bd;			/* lookup bits for td */
+    unsigned l[288];		/* length list for huft_build */
+
+    DEBG("<fix");
+
+    /* set up literal table */
+    for (i = 0; i < 144; i++)
+	l[i] = 8;
+    for (; i < 256; i++)
+	l[i] = 9;
+    for (; i < 280; i++)
+	l[i] = 7;
+    for (; i < 288; i++)	/* make a complete, but wrong code set */
+	l[i] = 8;
+    bl = 7;
+    if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
+	return i;
+
+    /* set up distance table */
+    for (i = 0; i < 30; i++)	/* make an incomplete code set */
+	l[i] = 5;
+    bd = 5;
+    if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) {
+	huft_free(tl);
+
+	DEBG(">");
+	return i;
+    }
+
+    /* decompress until an end-of-block code */
+    if (inflate_codes(tl, td, bl, bd))
+	return 1;
+
+    /* free the decoding tables, return */
+    huft_free(tl);
+    huft_free(td);
+    return 0;
+}
+
+STATIC int inflate_dynamic()
+/* decompress an inflated type 2 (dynamic Huffman codes) block. */
+{
+    int i;			/* temporary variables */
+    unsigned j;
+    unsigned l;			/* last length */
+    unsigned m;			/* mask for bit lengths table */
+    unsigned n;			/* number of lengths to get */
+    struct huft *tl;		/* literal/length code table */
+    struct huft *td;		/* distance code table */
+    int bl;			/* lookup bits for tl */
+    int bd;			/* lookup bits for td */
+    unsigned nb;		/* number of bit length codes */
+    unsigned nl;		/* number of literal/length codes */
+    unsigned nd;		/* number of distance codes */
+#ifdef PKZIP_BUG_WORKAROUND
+    unsigned ll[288 + 32];	/* literal/length and distance code lengths */
+#else
+    unsigned ll[286 + 30];	/* literal/length and distance code lengths */
+#endif
+    register ulg b;		/* bit buffer */
+    register unsigned k;	/* number of bits in bit buffer */
+
+    DEBG("<dyn");
+
+    /* make local bit buffer */
+    b = bb;
+    k = bk;
+
+    /* read in table lengths */
+    NEEDBITS(5)
+	nl = 257 + ((unsigned)b & 0x1f);	/* number of literal/length codes */
+    DUMPBITS(5)
+	NEEDBITS(5)
+	nd = 1 + ((unsigned)b & 0x1f);	/* number of distance codes */
+    DUMPBITS(5)
+	NEEDBITS(4)
+	nb = 4 + ((unsigned)b & 0xf);	/* number of bit length codes */
+    DUMPBITS(4)
+#ifdef PKZIP_BUG_WORKAROUND
+	if (nl > 288 || nd > 32)
+#else
+	if (nl > 286 || nd > 30)
+#endif
+	return 1;		/* bad lengths */
+
+    DEBG("dyn1 ");
+
+    /* read in bit-length-code lengths */
+    for (j = 0; j < nb; j++) {
+	NEEDBITS(3)
+	    ll[border[j]] = (unsigned)b & 7;
+	DUMPBITS(3)
+    }
+    for (; j < 19; j++)
+	ll[border[j]] = 0;
+
+    DEBG("dyn2 ");
+
+    /* build decoding table for trees--single level, 7 bit lookup */
+    bl = 7;
+    if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) {
+	if (i == 1)
+	    huft_free(tl);
+	return i;		/* incomplete code set */
+    }
+
+    DEBG("dyn3 ");
+
+    /* read in literal and distance code lengths */
+    n = nl + nd;
+    m = mask_bits[bl];
+    i = l = 0;
+    while ((unsigned)i < n) {
+	NEEDBITS((unsigned)bl)
+	    j = (td = tl + ((unsigned)b & m))->b;
+	DUMPBITS(j)
+	    j = td->v.n;
+	if (j < 16)		/* length of code in bits (0..15) */
+	    ll[i++] = l = j;	/* save last length in l */
+	else if (j == 16) {	/* repeat last length 3 to 6 times */
+	    NEEDBITS(2)
+		j = 3 + ((unsigned)b & 3);
+	    DUMPBITS(2)
+		if ((unsigned)i + j > n)
+		return 1;
+	    while (j--)
+		ll[i++] = l;
+	} else if (j == 17) {	/* 3 to 10 zero length codes */
+	    NEEDBITS(3)
+		j = 3 + ((unsigned)b & 7);
+	    DUMPBITS(3)
+		if ((unsigned)i + j > n)
+		return 1;
+	    while (j--)
+		ll[i++] = 0;
+	    l = 0;
+	} else {		/* j == 18: 11 to 138 zero length codes */
+
+	    NEEDBITS(7)
+		j = 11 + ((unsigned)b & 0x7f);
+	    DUMPBITS(7)
+		if ((unsigned)i + j > n)
+		return 1;
+	    while (j--)
+		ll[i++] = 0;
+	    l = 0;
+	}
+    }
+
+    DEBG("dyn4 ");
+
+    /* free decoding table for trees */
+    huft_free(tl);
+
+    DEBG("dyn5 ");
+
+    /* restore the global bit buffer */
+    bb = b;
+    bk = k;
+
+    DEBG("dyn5a ");
+
+    /* build the decoding tables for literal/length and distance codes */
+    bl = lbits;
+    if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) {
+	DEBG("dyn5b ");
+	if (i == 1) {
+	    error(" incomplete literal tree");
+	    huft_free(tl);
+	}
+	return i;		/* incomplete code set */
+    }
+    DEBG("dyn5c ");
+    bd = dbits;
+    if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) {
+	DEBG("dyn5d ");
+	if (i == 1) {
+	    error(" incomplete distance tree");
+#ifdef PKZIP_BUG_WORKAROUND
+	    i = 0;
+	}
+#else
+	    huft_free(td);
+	}
+	huft_free(tl);
+	return i;		/* incomplete code set */
+#endif
+    }
+
+    DEBG("dyn6 ");
+
+    /* decompress until an end-of-block code */
+    if (inflate_codes(tl, td, bl, bd))
+	return 1;
+
+    DEBG("dyn7 ");
+
+    /* free the decoding tables, return */
+    huft_free(tl);
+    huft_free(td);
+
+    DEBG(">");
+    return 0;
+}
+
+STATIC int inflate_block(e)
+int *e;				/* last block flag */
+/* decompress an inflated block */
+{
+    unsigned t;			/* block type */
+    register ulg b;		/* bit buffer */
+    register unsigned k;	/* number of bits in bit buffer */
+
+    DEBG("<blk");
+
+    /* make local bit buffer */
+    b = bb;
+    k = bk;
+
+    /* read in last block bit */
+    NEEDBITS(1)
+	* e = (int)b & 1;
+    DUMPBITS(1)
+
+	/* read in block type */
+	NEEDBITS(2)
+	t = (unsigned)b & 3;
+    DUMPBITS(2)
+
+	/* restore the global bit buffer */
+	bb = b;
+    bk = k;
+
+    /* inflate that block type */
+    if (t == 2)
+	return inflate_dynamic();
+    if (t == 0)
+	return inflate_stored();
+    if (t == 1)
+	return inflate_fixed();
+
+    DEBG(">");
+
+    /* bad block type */
+    return 2;
+}
+
+STATIC int inflate()
+/* decompress an inflated entry */
+{
+    int e;			/* last block flag */
+    int r;			/* result code */
+    unsigned h;			/* maximum struct huft's malloc'ed */
+    void *ptr;
+
+    /* initialize window, bit buffer */
+    wp = 0;
+    bk = 0;
+    bb = 0;
+
+    /* decompress until the last block */
+    h = 0;
+    do {
+	hufts = 0;
+	gzip_mark(&ptr);
+	if ((r = inflate_block(&e)) != 0) {
+	    gzip_release(&ptr);
+	    return r;
+	}
+	gzip_release(&ptr);
+	if (hufts > h)
+	    h = hufts;
+    } while (!e);
+
+    /* Undo too much lookahead. The next read will be byte aligned so we
+     * can discard unused bits in the last meaningful byte.
+     */
+    while (bk >= 8) {
+	bk -= 8;
+	unget_byte();
+    }
+
+    /* flush out slide */
+    flush_output(wp);
+
+    /* return success */
+#ifdef DEBUG
+    fprintf(stderr, "<%u> ", h);
+#endif /* DEBUG */
+    return 0;
+}
+
+/**********************************************************************
+ *
+ * The following are support routines for inflate.c
+ *
+ **********************************************************************/
+
+static ulg crc_32_tab[256];
+static ulg crc;			/* initialized in makecrc() so it'll reside in bss */
+#define CRC_VALUE (crc ^ 0xffffffffL)
+
+/*
+ * Code to compute the CRC-32 table. Borrowed from
+ * gzip-1.0.3/makecrc.c.
+ */
+
+static void makecrc(void)
+{
+/* Not copyrighted 1990 Mark Adler	*/
+
+    unsigned long c;		/* crc shift register */
+    unsigned long e;		/* polynomial exclusive-or pattern */
+    int i;			/* counter for all possible eight bit values */
+    int k;			/* byte being shifted into crc apparatus */
+
+    /* terms of polynomial defining this crc (except x^32): */
+    static const int p[] = { 0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26 };
+
+    /* Make exclusive-or pattern from polynomial */
+    e = 0;
+    for (i = 0; i < sizeof(p) / sizeof(int); i++)
+	e |= 1L << (31 - p[i]);
+
+    crc_32_tab[0] = 0;
+
+    for (i = 1; i < 256; i++) {
+	c = 0;
+	for (k = i | 256; k != 1; k >>= 1) {
+	    c = c & 1 ? (c >> 1) ^ e : c >> 1;
+	    if (k & 1)
+		c ^= e;
+	}
+	crc_32_tab[i] = c;
+    }
+
+    /* this is initialized here so this code could reside in ROM */
+    crc = (ulg) 0xffffffffL;	/* shift register contents */
+}
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01	/* bit 0 set: file probably ASCII text */
+#define CONTINUATION 0x02	/* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04	/* bit 2 set: extra field present */
+#define ORIG_NAME    0x08	/* bit 3 set: original file name present */
+#define COMMENT      0x10	/* bit 4 set: file comment present */
+#define ENCRYPTED    0x20	/* bit 5 set: file is encrypted */
+#define RESERVED     0xC0	/* bit 6,7:   reserved */
+
+/*
+ * Do the uncompression!
+ */
+int gunzip(void)
+{
+    int res;
+
+    /* Decompress */
+    if ((res = inflate())) {
+	switch (res) {
+	case 0:
+	    break;
+	case 1:
+	    error("invalid compressed format (err=1)");
+	    break;
+	case 2:
+	    error("invalid compressed format (err=2)");
+	    break;
+	case 3:
+	    error("out of memory");
+	    break;
+	default:
+	    error("invalid compressed format (other)");
+	}
+	return -1;
+    }
+
+    return 0;
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/memcpy.S
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memcpy.S	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memcpy.S	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,86 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * memcpy.S
+ *
+ * Reasonably efficient memcpy, using aligned transfers at least
+ * for the destination operand.
+ */
+
+	.text
+	.globl	memcpy
+	.type	memcpy, @function
+memcpy:
+	jecxz	1f
+
+	pushl	%esi
+	pushl	%edi
+	pushl	%eax		/* Return value */
+
+	movl	%eax,%edi
+	movl	%edx,%esi
+
+	/* Initial alignment */
+	movl	%edi,%edx
+	shrl	$1,%edx
+	jnc	11f
+	movsb
+	decl	%ecx
+11:
+	movb	%cl,%al
+	cmpl	$2,%ecx
+	jb	13f
+
+	shrl	$1,%edx
+	jnc	12f
+	movsw
+	subl	$2,%ecx
+12:
+	/* Bulk transfer */
+	movb	%cl,%al
+	shrl	$2,%ecx
+	rep; movsl
+
+	/* Final alignment */
+	testb	$2,%al
+	jz	14f
+	movsw
+13:
+14:
+	testb	$1,%al
+	jz	15f
+	movsb
+15:
+
+	popl	%eax		/* Return value */
+	popl	%edi
+	popl	%esi
+1:
+	ret
+
+	.size	memcpy, .-memcpy
Index: bootcd/isolinux/syslinux-6.03/memdisk/memcpy.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memcpy.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memcpy.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,29 @@
+/*
+ * memcpy.c
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+void *memcpy(void *dst, const void *src, size_t n)
+{
+	const char *p = src;
+	char *q = dst;
+#if defined(__i386__)
+	size_t nl = n >> 2;
+	asm volatile ("cld ; rep ; movsl ; movl %3,%0 ; rep ; movsb":"+c" (nl),
+		      "+S"(p), "+D"(q)
+		      :"r"(n & 3));
+#elif defined(__x86_64__)
+	size_t nq = n >> 3;
+	asm volatile ("cld ; rep ; movsq ; movl %3,%%ecx ; rep ; movsb":"+c"
+		      (nq), "+S"(p), "+D"(q)
+		      :"r"((uint32_t) (n & 7)));
+#else
+	while (n--) {
+		*q++ = *p++;
+	}
+#endif
+
+	return dst;
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/memdisk.h
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memdisk.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memdisk.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,140 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * memdisk.h
+ *
+ * Miscellaneous header definitions
+ */
+
+#ifndef MEMDISK_H
+#define MEMDISK_H
+
+#include <stddef.h>
+
+/* We use the com32 interface for calling 16-bit code */
+#include <com32.h>
+
+/* define it only for i386 */
+#if __SIZEOF_POINTER__ == 4
+#define __cdecl __attribute__((cdecl,regparm(0)))
+#endif
+
+void __cdecl intcall(uint8_t, com32sys_t *, com32sys_t *);
+
+/* Structure passed in from the real-mode code */
+struct real_mode_args {
+    uint32_t rm_return;
+    uint32_t rm_intcall;
+    uint32_t rm_bounce;
+    uint32_t rm_base;
+    uint32_t rm_handle_interrupt;
+    uint32_t rm_gdt;
+    uint32_t rm_size;
+    uint32_t rm_pmjmp;
+    uint32_t rm_rmjmp;
+};
+extern struct real_mode_args rm_args;
+#define sys_bounce ((void *)rm_args.rm_bounce)
+
+/* This is the header in the boot sector/setup area */
+struct setup_header {
+    char cmdline[0x1f1];
+    uint8_t setup_secs;
+    uint16_t syssize;
+    uint16_t swap_dev;
+    uint16_t ram_size;
+    uint16_t vid_mode;
+    uint16_t root_dev;
+    uint16_t boot_flag;
+    uint16_t jump;
+    char header[4];
+    uint16_t version;
+    uint32_t realmode_swtch;
+    uint32_t start_sys;
+    uint8_t type_of_loader;
+    uint8_t loadflags;
+    uint16_t setup_move_size;
+    uint32_t code32_start;
+    uint32_t ramdisk_image;
+    uint32_t ramdisk_size;
+    uint32_t bootsect_kludge;
+    uint16_t head_end_ptr;
+    uint16_t pad1;
+    uint32_t cmd_line_ptr;
+    uint32_t initrd_addr_max;
+    uint32_t esdi;
+    uint32_t edx;
+    uint32_t sssp;
+    uint32_t csip;
+};
+#define shdr ((struct setup_header *)rm_args.rm_base)
+
+/* Standard routines */
+void *memcpy(void *, const void *, size_t);
+void *memset(void *, int, size_t);
+void *memmove(void *, const void *, size_t);
+
+#define strcpy(a,b)   __builtin_strcpy(a,b)
+
+static inline size_t strlen(const char *__a)
+{
+    const char *__D;
+    size_t __c;
+
+asm("repne;scasb":"=D"(__D), "=c"(__c)
+:	"D"(__a), "c"(-1), "a"(0), "m"(*__a));
+
+    return __D - __a - 1;
+}
+
+/* memcpy() but returns a pointer to end of buffer */
+static inline void *mempcpy(void *__d, const void *__s, unsigned int __n)
+{
+    memcpy(__d, __s, __n);
+    return (void *)((char *)__d + __n);
+}
+
+/* memcmp() */
+static inline int memcmp(const void *__a, const void *__b, unsigned int __n)
+{
+    const unsigned char *__aa = __a;
+    const unsigned char *__bb = __b;
+    int __d;
+
+    while (__n--) {
+	__d = *__bb++ - *__aa++;
+	if (__d)
+	    return __d;
+    }
+
+    return 0;
+}
+
+static inline void sti(void)
+{
+    asm volatile("sti");
+}
+
+static inline void cli(void)
+{
+    asm volatile("cli");
+}
+
+/* Decompression */
+extern int check_zip(void *indata, uint32_t size, uint32_t * zbytes_p,
+		     uint32_t * dbytes_p, uint32_t * orig_crc,
+		     uint32_t * offset_p);
+extern void *unzip(void *indata, uint32_t zbytes, uint32_t dbytes,
+		   uint32_t orig_crc, void *target);
+
+#endif
Index: bootcd/isolinux/syslinux-6.03/memdisk/memdisk.inc
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memdisk.inc	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memdisk.inc	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,1189 @@
+; -*- fundamental -*- (asm-mode sucks)
+; ****************************************************************************
+;
+;  memdisk.inc
+;
+;  A program to emulate an INT 13h disk BIOS from a "disk" in extended
+;  memory.
+;
+;   Copyright 2001-2009 H. Peter Anvin - All Rights Reserved
+;   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+;   Portions copyright 2009 Shao Miller [El Torito code, mBFT, safe hook]
+;
+;  This program is free software; you can redistribute it and/or modify
+;  it under the terms of the GNU General Public License as published by
+;  the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+;  Boston MA 02111-1307, USA; either version 2 of the License, or
+;  (at your option) any later version; incorporated herein by reference.
+;
+; ****************************************************************************
+
+%include "../version.gen"
+
+; %define DEBUG_TRACERS			; Uncomment to get debugging tracers
+
+%ifdef DEBUG_TRACERS
+
+%macro TRACER	1
+	call debug_tracer
+	db %1
+%endmacro
+%macro WRITEHEX2 0-1 al
+%ifnidni %1,al
+	push ax
+	mov al,%1
+	call writehex2
+	pop ax
+%else
+	call writehex2
+%endif
+%endmacro
+%macro WRITEHEX4 0-1 ax
+%ifnidni %1,ax
+	push ax
+	mov ax,%1
+	call writehex4
+	pop ax
+%else
+	call writehex4
+%endif
+%endmacro
+%macro WRITEHEX8 0-1 eax
+%ifnidni %1,eax
+	push eax
+	mov eax,%1
+	call writehex8
+	pop eax
+%else
+	call writehex8
+%endif
+%endmacro
+
+%else	; DEBUG_TRACERS
+
+%macro	TRACER	1
+%endmacro
+%macro WRITEHEX2 0-1
+%endmacro
+%macro WRITEHEX4 0-1
+%endmacro
+%macro WRITEHEX8 0-1
+%endmacro
+
+%endif	; DEBUG_TRACERS
+
+; Flags we test our configuration against
+%define CONFIG_READONLY	0x01
+%define CONFIG_RAW	0x02
+%define CONFIG_SAFEINT	0x04
+%define CONFIG_BIGRAW	0x08		; MUST be 8!
+
+		org 0h
+
+%define	SECTORSIZE	(1 << SECTORSIZE_LG2)
+
+		; Parameter registers definition; this is the definition
+		; of the stack frame.
+%define		P_DS		word [bp+34]
+%define		P_ES		word [bp+32]
+%define		P_EAX		dword [bp+28]
+%define		P_HAX		word [bp+30]
+%define		P_AX		word [bp+28]
+%define		P_AL		byte [bp+28]
+%define		P_AH		byte [bp+29]
+%define		P_ECX		dword [bp+24]
+%define		P_HCX		word [bp+26]
+%define		P_CX		word [bp+24]
+%define		P_CL		byte [bp+24]
+%define		P_CH		byte [bp+25]
+%define		P_EDX		dword [bp+20]
+%define		P_HDX		word [bp+22]
+%define		P_DX		word [bp+20]
+%define		P_DL		byte [bp+20]
+%define		P_DH		byte [bp+21]
+%define		P_EBX		dword [bp+16]
+%define		P_HBX		word [bp+18]
+%define		P_HBXL		byte [bp+18]
+%define		P_BX		word [bp+16]
+%define		P_BL		byte [bp+16]
+%define		P_BH		byte [bp+17]
+%define		P_EBP		dword [bp+8]
+%define		P_BP		word [bp+8]
+%define		P_ESI		dword [bp+4]
+%define		P_SI		word [bp+4]
+%define		P_EDI		dword [bp]
+%define		P_DI		word [bp]
+
+		section .text
+		; These pointers are used by the installer and
+		; must be first in the binary
+Pointers:	dw Int13Start
+		dw Int15Start
+		dw MemDisk_Info		; Portions are patched by installer
+		dw TotalSize
+		dw IretPtr
+
+IretPtr		equ Int13Start.iret
+Int13Start:
+		jmp strict near .SafeHookEnd ; 3-byte jump
+		db '$INT13SF'		; Signature for "safe hook"
+		db 'MEMDISK '		; Vendor ID
+		dd 0			; SEG:OFF of previous INT 13h hook
+					; Must be filled in by installer
+		dd 0			; "Safe hook" flags
+; ---- "Safe hook" structure ends here ---
+
+; This next field should be guaranteed at this position after the
+; "safe hook" structure.  This allows for a MEMDISK OS driver to
+; immediately find out the particular parameters using the mBFT
+; and MDI structures.  This binary will have the offset to the mBFT
+; in this field to begin with, so the installer knows where the mBFT
+; is.  This is akin to the "Pointers" section above.  The installer
+; will refill this field with the physical address of the mBFT for
+; future consumers, such as OS drivers.
+		dd mBFT			; Offset from hook to the mBFT
+
+.SafeHookEnd:
+		cmp word [cs:Recursive],0
+		jne recursive
+
+		; Swap stack
+		mov [cs:Stack],esp
+		mov [cs:Stack+4],ss
+		mov [cs:SavedAX],ax
+		mov ax,cs
+		mov ss,ax
+		mov sp,[cs:MyStack]
+
+%if ELTORITO
+		cmp word [cs:SavedAX],4a00h	; El Torito function?
+		jae our_drive			; We grab it
+%endif
+		; See if DL points to our class of device (FD, HD)
+		push dx
+		push dx
+		xor dl,[cs:DriveNo]
+		pop dx
+		js .nomatch		; If SF=0, we have a class match here
+					; 0x00 the sign bit for FD
+					; 0x80 the sign bit for HD
+		jz our_drive		; If ZF=1, we have an exact match
+		cmp dl,[cs:DriveNo]
+		jb .nomatch		; Drive < Our drive
+		cmp dl,[cs:DriveShiftLimit]
+		jae .nomatch		; Drive > The maximum drive
+					; number that we will shift for.
+					; This leaves any higher-up BIOS
+					; drives alone, such as an optical
+					; disc drive 0xA0 or 0xE0
+		dec dl			; Drive > Our drive, adjust drive #
+.nomatch:
+		TRACER '!'
+		WRITEHEX2 dl
+		TRACER ','
+		mov ax,[cs:SavedAX]
+		WRITEHEX4
+		inc word [cs:Recursive]
+		pushf
+		call far [cs:OldInt13]
+		pushf
+		dec word [cs:Recursive]
+		push bp
+		mov bp,sp
+		cmp byte [cs:SavedAX+1],08h	; Get drive params function?
+		je .norestoredl			; DL = number of drives
+		cmp byte [cs:SavedAX+1],15h	; Get disk type function?
+		jne .restoredl
+		test byte [bp+4],80h		; Hard disk?
+		jnz .norestoredl		; CX:DX = size of device
+.restoredl:
+		mov dl,[bp+4]
+.norestoredl:
+		push ax
+		push ebx
+		push ds
+		mov ax,[bp+2]		; Flags
+		lds ebx,[cs:Stack]
+		mov [bx+4],al		; Arithmetic flags
+		pop ds
+		pop ebx
+		pop ax
+		pop bp
+		lss esp,[cs:Stack]
+.iret:		iret
+
+recursive:
+		TRACER '@'
+jmp_oldint13:
+		jmp far [cs:OldInt13]
+
+our_drive:
+		; Set up standard entry frame
+		push ds
+		push es
+		mov ds,ax
+		mov es,ax
+		mov ax,[SavedAX]
+		pushad
+		mov bp,sp		; Point BP to the entry stack frame
+		TRACER 'F'
+		WRITEHEX4
+		; Note: AX == P_AX here
+		cmp ah,Int13FuncsCnt-1
+		ja Invalid_jump
+%if ELTORITO
+		mov al,[CD_PKT.type]	; Check if we are in
+		cmp al,0		; El Torito no emulation mode
+		ja .emulation		; No.  We support the function
+		cmp ah,3fh		; Yes.  We must not support functions
+		jbe Invalid_jump	; 0 through 3Fh.  Check and decide
+.emulation:
+%endif
+		xor al,al		; AL = 0 is standard entry condition
+		mov di,ax
+		shr di,7		; Convert AH to an offset in DI
+		call [Int13Funcs+di]
+
+Done:		; Standard routine for return
+		mov P_AX,ax
+DoneWeird:
+		TRACER 'D'
+		xor bx,bx
+		mov es,bx
+		mov bx,[StatusPtr]
+		mov [es:bx],ah		; Save status
+		and ah,ah
+
+		lds ebx,[Stack]
+		; This sets the low byte (the arithmetic flags) of the
+		; FLAGS on stack to either 00h (no flags) or 01h (CF)
+		; depending on if AH was zero or not.
+		setnz [bx+4]		; Set CF iff error
+		popad
+		pop es
+		pop ds
+		lss esp,[cs:Stack]
+		iret
+
+Reset:
+		; Reset affects multiple drives, so we need to pass it on
+		TRACER 'R'
+		xor ax,ax		; Bottom of memory
+		mov es,ax
+		test dl,dl		; Always pass it on if we are
+					; resetting HD
+		js .hard_disk		; Bit 7 set
+		; Some BIOSes get very unhappy if we pass a reset floppy
+		; command to them and don't actually have any floppies.
+		; This is a bug, but we have to deal with it nontheless.
+		; Therefore, if we are the *ONLY* floppy drive, and the
+		; user didn't request HD reset, then just drop the command.
+		; BIOS equipment byte, top two bits + 1 == total # of floppies
+		test byte [es:0x410],0C0h
+		jz success
+		jmp .pass_on		; ... otherwise pass it to the BIOS
+.hard_disk:
+		; ... same thing for hard disks, sigh ...
+		cmp byte [es:0x475],1	; BIOS variable for number of hard
+					; disks
+		jbe success
+
+.pass_on:
+		pop ax			; Drop return address
+		popad			; Restore all registers
+		pop es
+		pop ds
+		lss esp,[cs:Stack]	; Restore the stack
+		and dl,80h		; Clear all but the type bit
+		jmp jmp_oldint13
+
+
+Invalid:
+		pop dx			; Drop return address
+Invalid_jump:
+		TRACER 'I'
+		mov ah,01h		; Unsupported function
+		jmp short Done
+
+GetDriveType:
+		test byte [DriveNo],80h
+		mov bl,02h		; Type 02h = floppy with changeline
+		jz .floppy
+		; Hard disks only!  DO NOT set CX:DX for floppies...
+		; it apparently causes Win98SE DOS to go into an loop
+		; resetting the drive over and over.  Sigh.
+		inc bx			; Type = 03h
+		mov dx,[DiskSize]	; Return the disk size in sectors
+		mov P_DX,dx
+		mov cx,[DiskSize+2]
+		mov P_CX,cx
+.floppy:
+		mov P_AH,bl		; 02h floppy, 03h hard disk
+		pop ax			; Drop return address
+		xor ax,ax		; Success...
+		jmp DoneWeird		; But don't stick it into P_AX
+
+GetStatus:
+		xor ax,ax
+		mov es,ax
+		mov bx,[StatusPtr]
+		mov ah,[bx]		; Copy last status
+		ret
+
+ReadMult:
+		TRACER 'm'
+Read:
+		TRACER 'R'
+		call setup_regs
+do_copy:
+		TRACER '<'
+		call bcopy
+		TRACER '>'
+		movzx ax,P_AL		; AH = 0, AL = transfer count
+		ret
+
+WriteMult:
+		TRACER 'M'
+Write:
+		TRACER 'W'
+		test byte [ConfigFlags],CONFIG_READONLY
+		jnz .readonly
+		call setup_regs
+		xchg esi,edi		; Opposite direction of a Read!
+		jmp short do_copy
+.readonly:	mov ah,03h		; Write protected medium
+		ret
+
+		; Verify integrity; just bounds-check
+Seek:
+Verify:
+		call setup_regs		; Returns error if appropriate
+		; And fall through to success
+
+CheckIfReady:				; These are always-successful noop functions
+Recalibrate:
+InitWithParms:
+DetectChange:
+EDDDetectChange:
+EDDLock:
+SetMode:
+success:
+		xor ax,ax		; Always successful
+		ret
+
+GetParms:
+		TRACER 'G'
+		mov dl,[DriveCnt]	; Cached data
+		mov P_DL,dl
+		test byte [DriveNo],80h
+		jnz .hd
+		mov P_DI,DPT
+		mov P_ES,cs
+		mov bl,[DriveType]
+		mov P_BL,bl
+.hd:
+		mov ax,[Cylinders]
+		dec ax			; We report the highest #, not the count
+		xchg al,ah
+		shl al,6
+		or al,[Sectors]
+		mov P_CX,ax
+		mov ax,[Heads]
+		dec ax
+		mov P_DH,al
+
+		;
+		; Is this MEMDISK installation check?
+		;
+		cmp P_HAX,'ME'
+		jne .notic
+		cmp P_HCX,'MD'
+		jne .notic
+		cmp P_HDX,'IS'
+		jne .notic
+		cmp P_HBX,'K?'
+		jne .notic
+
+		; MEMDISK installation check...
+		mov P_HAX,'!M'
+		mov P_HCX,'EM'
+		mov P_HDX,'DI'
+		mov P_HBX,'SK'
+		mov P_ES,cs
+		mov P_DI,MemDisk_Info
+
+.notic:
+		xor ax,ax
+		ret
+;
+; EDD functions -- only if enabled
+;
+%if EDD
+EDDPresence:
+		TRACER 'E'
+		TRACER 'c'
+
+		cmp P_BX,55AAh
+		jne Invalid
+		mov P_BX,0AA55h		; EDD signature
+		mov P_AX,03000h		; EDD 3.0
+		mov P_CX,0007h		; Bit 0 - Fixed disk access subset
+					; Bit 1 - Locking and ejecting subset
+					; Bit 2 - EDD subset
+		pop ax			; Drop return address
+		xor ax,ax		; Success
+		jmp DoneWeird		; Success, but AH != 0, sigh...
+
+EDDRead:
+		TRACER 'E'
+		TRACER 'r'
+
+		call edd_setup_regs
+		call bcopy
+		xor ax,ax
+		ret
+
+EDDWrite:
+		TRACER 'E'
+		TRACER 'w'
+
+		call edd_setup_regs
+		xchg esi,edi		; Opposite direction of a Read!
+		call bcopy
+		xor ax,ax
+		ret
+
+EDDVerify:
+EDDSeek:
+		call edd_setup_regs	; Just bounds checking
+		xor ax,ax
+		ret
+
+EDDGetParms:
+		TRACER 'E'
+		TRACER 'p'
+
+		mov es,P_DS
+		mov di,P_SI
+		mov si,EDD_DPT
+
+		lodsw			; Length of our DPT
+		mov cx,[es:di]
+		cmp cx,26		; Minimum size
+		jb .overrun
+
+		cmp cx,ax
+		jb .oksize
+		mov cx,ax
+
+.oksize:
+		mov ax,cx
+		stosw
+		dec cx
+		dec cx
+		rep movsb
+
+		xor ax,ax
+		ret
+
+.overrun:
+		mov ax,0100h
+		ret
+%endif ; EDD
+
+		; Set up registers as for a "Read", and compares against disk
+		; size.
+		; WARNING: This fails immediately, even if we can transfer some
+		; sectors.  This isn't really the correct behaviour.
+setup_regs:
+
+		; Convert a CHS address in P_CX/P_DH into an LBA in eax
+		; CH = cyl[7:0]
+		; CL[0:5] = sector (1-based)  CL[7:6] = cyl[9:8]
+		; DH = head
+		movzx ecx,P_CX
+		movzx ebx,cl		; Sector number
+		and bl,3Fh
+		dec ebx			; Sector number is 1-based
+		cmp bx,[Sectors]
+		jae .overrun
+		movzx edi,P_DH		; Head number
+		movzx eax,word [Heads]
+		cmp di,ax
+		jae .overrun
+		shr cl,6
+		xchg cl,ch		; Now (E)CX <- cylinder number
+		mul ecx			; eax <- Heads*cyl# (edx <- 0)
+		add eax,edi
+		mul dword [Sectors]
+		add eax,ebx
+		; Now eax = LBA, edx = 0
+
+		;
+		; setup_regs continues...
+		;
+		; Note: edi[31:16] and ecx[31:16] = 0 already
+		mov di,P_BX		; Get linear address of target buffer
+		mov cx,P_ES
+		shl ecx,4
+		add edi,ecx		; EDI = address to fetch to
+		movzx ecx,P_AL		; Sector count
+		mov esi,eax
+		add eax,ecx		; LBA of final sector + 1
+		shl esi,SECTORSIZE_LG2	; LBA -> byte offset
+		add esi,[DiskBuf]	; Get address in high memory
+		cmp eax,[DiskSize]	; Check the high mark against limit
+		ja .overrun
+		shl ecx,SECTORSIZE_LG2-2 ; Convert count to dwords
+		ret
+
+.overrun:	pop ax			; Drop setup_regs return address
+		mov ax,0200h		; Missing address mark
+		ret			; Return to Done
+
+		; Set up registers as for an EDD Read, and compares against disk size.
+%if EDD
+edd_setup_regs:
+		push es
+		mov si,P_SI		; DS:SI -> DAPA
+		mov es,P_DS
+
+		mov dx,[es:si]
+		cmp dx,16
+		jb .baddapa
+
+		cmp dword [es:si+4],-1
+		je .linear_address
+
+		movzx ebx,word [es:si+4]	; Offset
+		movzx edi,word [es:si+6]	; Segment
+		shl edi,4
+		add ebx,edi
+		jmp .got_address
+
+.linear_address:
+		cmp dx,24		; Must be large enough to hold
+					; linear address
+		jb .baddapa
+
+		cmp dword [es:si+20],0	; > 4 GB addresses not supported
+		mov ax,0900h		; "Data boundary error" - bogus, but
+					; no really better code available
+		jne .error
+
+		mov ebx,[es:si+16]
+
+.got_address:
+		cmp dword [es:si+12],0		; LBA too large?
+		jne .overrun
+
+		movzx ecx, word [es:si+2]	; Sectors to transfer
+		mov esi,[es:si+8]		; Starting sector
+		mov eax,esi
+		add eax,ecx
+		jc .overrun
+		cmp eax,[DiskSize]
+		ja .overrun
+
+		shl ecx,SECTORSIZE_LG2-2	; Convert to dwords
+		shl esi,SECTORSIZE_LG2		; Convert to an offset
+		add esi,[DiskBuf]
+		mov edi,ebx
+		pop es
+		ret
+
+.baddapa:
+		mov ax,0100h		; Invalid command
+		pop es
+		pop ax			; Drop setup_regs return address
+		ret
+
+.overrun:
+		mov ax,0200h		; "Address mark not found" =
+					; LBA beyond end of disk
+.error:
+		and word [es:si+2],0	; No sectors transferred
+		pop es
+		pop ax
+		ret
+
+EDDEject:
+		mov ax,0B200h		; Volume Not Removable
+		ret
+%if ELTORITO
+ElToritoTerminate:
+		TRACER 'T'
+		mov ax,[cs:SavedAX]
+		cmp al,1		; We only support query, not terminate
+		jne ElToritoErr		; Fail
+		cmp dl,7fh		; Terminate all?
+		je .doit
+		cmp dl,[cs:DriveNo]	; Terminate our drive?
+		je .doit
+		jmp ElToritoErr		; Fail
+.doit:		mov es,P_DS		; Caller's DS:SI pointed to packet
+		mov di,P_SI		; We'll use ES:DI
+		mov si,CD_PKT.size	; First byte is packet size
+		xor cx,0		; Empty our count
+		;mov cl,[ds:si]		; We'll copy that many bytes
+		mov cl,13h
+		rep movsb		; Copy until CX is zero
+		mov ax,0		; Success
+		ret
+ElToritoEmulate:
+ElToritoBoot:
+ElToritoCatalog:
+ElToritoErr:
+		TRACER '!'
+		mov ax,100h		; Invalid parameter
+		ret
+%endif ; ELTORITO
+%endif ; EDD
+
+;
+; INT 15h intercept routines
+;
+int15_e820:
+		cmp edx,534D4150h	; "SMAP"
+		jne oldint15
+		cmp ecx,20		; Need 20 bytes
+		jb err86
+		push ds
+		push cs
+		pop ds
+		push edx		; "SMAP"
+		and ebx,ebx
+		jne .renew
+		mov ebx,E820Table
+.renew:
+		add bx,12		; Advance to next
+		mov eax,[bx-4]		; Type
+		and eax,eax		; Null type?
+		jz .renew		; If so advance to next
+		mov [es:di+16],eax
+		mov eax,[bx-12]		; Start addr (low)
+		mov edx,[bx-8]		; Start addr (high)
+		mov [es:di],eax
+		mov [es:di+4],edx
+		mov eax,[bx]		; End addr (low)
+		mov edx,[bx+4]		; End addr (high)
+		sub eax,[bx-12]		; Derive the length
+		sbb edx,[bx-8]
+		mov [es:di+8],eax	; Length (low)
+		mov [es:di+12],edx	; Length (high)
+		cmp dword [bx+8],-1	; Type of next = end?
+		jne .notdone
+		xor ebx,ebx		; Done with table
+.notdone:
+		pop eax			; "SMAP"
+		mov edx,eax		; Some systems expect eax = edx = SMAP
+		mov ecx,20		; Bytes loaded
+		pop ds
+int15_success:
+		mov byte [bp+6], 02h	; Clear CF
+		pop bp
+		iret
+
+err86:
+		mov byte [bp+6], 03h	; Set CF
+		mov ah,86h
+		pop bp
+		iret
+
+Int15Start:
+		push bp
+		mov bp,sp
+		cmp ax,0E820h
+		je near int15_e820
+		cmp ax,0E801h
+		je int15_e801
+		cmp ax,0E881h
+		je int15_e881
+		cmp ah,88h
+		je int15_88
+oldint15:	pop bp
+		jmp far [cs:OldInt15]
+
+int15_e801:				; Get mem size for > 64 MB config
+		mov ax,[cs:Mem1MB]
+		mov cx,ax
+		mov bx,[cs:Mem16MB]
+		mov dx,bx
+		jmp short int15_success
+
+int15_e881:				; Get mem size for > 64 MB config
+					; 32-bit code
+		mov eax,[cs:Mem1MB]
+		mov ecx,eax
+		mov ebx,[cs:Mem16MB]
+		mov edx,ebx
+		jmp short int15_success
+
+int15_88:				; Get extended mem size
+		mov ax,[cs:MemInt1588]
+		jmp short int15_success
+
+;
+; Routine to copy in/out of high memory
+; esi = linear source address
+; edi = linear target address
+; ecx = 32-bit word count
+;
+; Assumes cs = ds = es
+;
+bcopy:
+		push eax
+		push ebx
+		push edx
+		push ebp
+
+		mov bx, real_int15_stub
+
+		test byte [ConfigFlags], CONFIG_RAW|CONFIG_SAFEINT
+		jz .anymode		; Always do the real INT 15h
+
+		smsw ax			; Unprivileged!
+		test al,01h
+		jnz .protmode		; Protmode -> do real INT 15h
+
+.realmode:
+		; Raw or Safeint mode, and we're in real mode...
+
+		test byte [ConfigFlags], CONFIG_SAFEINT
+		jnz .fakeint15
+
+.raw:
+		TRACER 'r'
+		; We're in real mode, do it outselves
+
+		pushfd			; <A>
+		push ds			; <B>
+		push es			; <C>
+
+		cli
+		cld
+
+		xor ebx,ebx
+		mov bx,cs
+		shl ebx,4
+		lea edx,[Shaker+ebx]
+		mov [Shaker+2],edx
+
+		; Test to see if A20 is enabled or not
+		xor ax,ax
+		mov ds,ax
+		dec ax
+		mov es,ax
+
+		mov ax,[0]
+		mov bx,ax
+		xor bx,[es:10h]
+		not ax
+		mov [0],ax
+		mov dx,ax
+		xor dx,[es:10h]
+		not ax
+		mov [0],ax
+
+		or dx,bx
+		push dx			; <D> Save A20 status
+		jnz .skip_a20e
+
+		mov ax,2401h		; Enable A20
+		int 15h
+.skip_a20e:
+		mov dl,[ConfigFlags]
+		and dx,CONFIG_BIGRAW
+		add dx,8
+		; DX = 16 for BIGRAW, 8 for RAW
+		;  8 is selector for a 64K flat segment,
+		; 16 is selector for a 4GB flat segment.
+
+		lgdt [cs:Shaker]
+		mov eax,cr0
+		or al,01h
+		mov cr0,eax
+
+		mov bx,16		; Large flat segment
+		mov ds,bx
+		mov es,bx
+
+		a32 rep movsd
+
+		; DX has the appropriate value to put in
+		; the registers on return
+		mov ds,dx
+		mov es,dx
+
+		and al,~01h
+		mov cr0,eax
+
+		pop dx			; <D> A20 status
+		pop es			; <C>
+		pop ds			; <B>
+
+		and dx,dx
+		jnz .skip_a20d
+		mov ax,2400h		; Disable A20
+		int 15h
+.skip_a20d:
+		popfd			; <A>
+		jmp .done
+
+.fakeint15:
+		; We're in real mode with CONFIG_SAFEINT, invoke the
+		; original INT 15h vector.  We used to test for the
+		; INT 15h vector being unchanged here, but that is
+		; *us*; however, the test was wrong for years (always
+		; negative) so instead of fixing the test do what we
+		; tested and don't bother probing.
+		mov bx, fake_int15_stub
+
+.protmode:
+		TRACER 'p'
+.anymode:
+
+.copy_loop:
+		push esi
+		push edi
+		push ecx
+		cmp ecx,4000h
+		jna .safe_size
+		mov ecx,4000h
+.safe_size:
+		push ecx	; Transfer size this cycle
+		mov eax, esi
+		mov [Mover_src1], si
+		shr eax, 16
+		mov [Mover_src1+2], al
+		mov [Mover_src2], ah
+		mov eax, edi
+		mov [Mover_dst1], di
+		shr eax, 16
+		mov [Mover_dst1+2], al
+		mov [Mover_dst2], ah
+		mov si,Mover
+		mov ah, 87h
+		shl cx,1	; Convert to 16-bit words
+		call bx		; INT 15h stub
+		pop eax		; Transfer size this cycle
+		pop ecx
+		pop edi
+		pop esi
+		jc .error
+		lea esi,[esi+4*eax]
+		lea edi,[edi+4*eax]
+		sub ecx, eax
+		jnz .copy_loop
+		; CF = 0
+.error:
+.done:
+		pop ebp
+		pop edx
+		pop ebx
+		pop eax
+		ret
+
+real_int15_stub:
+		int 15h
+		cli		; Some BIOSes enable interrupts on INT 15h
+		ret
+
+fake_int15_stub:
+		pushf
+		call far [OldInt15]
+		cli
+		ret
+
+%ifdef DEBUG_TRACERS
+debug_tracer:	pushad
+		pushfd
+		mov bp,sp
+		mov bx,[bp+9*4]
+		mov al,[cs:bx]
+		inc word [bp+9*4]
+		mov ah,0Eh
+		mov bx,7
+		int 10h
+		popfd
+		popad
+		ret
+
+writehex2:	pushad
+		pushfd
+		mov cx,2
+		ror eax,4
+		jmp writehex_common
+writehex4:	pushad
+		pushfd
+		mov cx,4
+		ror eax,12
+		jmp writehex_common
+writehex8:	pushad
+		pushfd
+		mov cx,8
+		ror eax,28
+writehex_common:
+.loop:		push cx
+		push eax
+		and al,0Fh
+		cmp al,10
+		jb .isdec
+		add al,'a'-'0'-10
+.isdec:		add al,'0'
+		mov ah,0Eh
+		mov bx,7
+		int 10h
+		pop eax
+		rol eax,4
+		pop cx
+		loop .loop
+		popfd
+		popad
+		ret
+%endif
+
+		section .data align=16
+		alignb 2
+Int13Funcs	dw Reset		; 00h - RESET
+		dw GetStatus		; 01h - GET STATUS
+		dw Read			; 02h - READ
+		dw Write		; 03h - WRITE
+		dw Verify		; 04h - VERIFY
+		dw Invalid		; 05h - FORMAT TRACK
+		dw Invalid		; 06h - FORMAT TRACK AND SET BAD FLAGS
+		dw Invalid		; 07h - FORMAT DRIVE AT TRACK
+		dw GetParms		; 08h - GET PARAMETERS
+		dw InitWithParms	; 09h - INITIALIZE CONTROLLER WITH
+					;	DRIVE PARAMETERS
+		dw Invalid		; 0Ah
+		dw Invalid		; 0Bh
+		dw Seek			; 0Ch - SEEK TO CYLINDER
+		dw Reset		; 0Dh - RESET HARD DISKS
+		dw Invalid		; 0Eh
+		dw Invalid		; 0Fh
+		dw CheckIfReady		; 10h - CHECK IF READY
+		dw Recalibrate		; 11h - RECALIBRATE
+		dw Invalid		; 12h
+		dw Invalid		; 13h
+		dw Invalid		; 14h
+		dw GetDriveType		; 15h - GET DRIVE TYPE
+		dw DetectChange		; 16h - DETECT DRIVE CHANGE
+%if EDD
+		dw Invalid		; 17h
+		dw Invalid		; 18h
+		dw Invalid		; 19h
+		dw Invalid		; 1Ah
+		dw Invalid		; 1Bh
+		dw Invalid		; 1Ch
+		dw Invalid		; 1Dh
+		dw Invalid		; 1Eh
+		dw Invalid		; 1Fh
+		dw Invalid		; 20h
+		dw ReadMult		; 21h - READ MULTIPLE
+		dw WriteMult		; 22h - WRITE MULTIPLE
+		dw SetMode		; 23h - SET CONTROLLER FEATURES
+		dw SetMode		; 24h - SET MULTIPLE MODE
+		dw Invalid		; 25h - IDENTIFY DRIVE
+		dw Invalid		; 26h
+		dw Invalid		; 27h
+		dw Invalid		; 28h
+		dw Invalid		; 29h
+		dw Invalid		; 2Ah
+		dw Invalid		; 2Bh
+		dw Invalid		; 2Ch
+		dw Invalid		; 2Dh
+		dw Invalid		; 2Eh
+		dw Invalid		; 2Fh
+		dw Invalid		; 30h
+		dw Invalid		; 31h
+		dw Invalid		; 32h
+		dw Invalid		; 33h
+		dw Invalid		; 34h
+		dw Invalid		; 35h
+		dw Invalid		; 36h
+		dw Invalid		; 37h
+		dw Invalid		; 38h
+		dw Invalid		; 39h
+		dw Invalid		; 3Ah
+		dw Invalid		; 3Bh
+		dw Invalid		; 3Ch
+		dw Invalid		; 3Dh
+		dw Invalid		; 3Eh
+		dw Invalid		; 3Fh
+		dw Invalid		; 40h
+		dw EDDPresence		; 41h - EDD PRESENCE DETECT
+		dw EDDRead		; 42h - EDD READ
+		dw EDDWrite		; 43h - EDD WRITE
+		dw EDDVerify		; 44h - EDD VERIFY
+		dw EDDLock		; 45h - EDD LOCK/UNLOCK MEDIA
+		dw EDDEject		; 46h - EDD EJECT
+		dw EDDSeek		; 47h - EDD SEEK
+		dw EDDGetParms		; 48h - EDD GET PARAMETERS
+		dw EDDDetectChange	; 49h - EDD MEDIA CHANGE STATUS
+%if ELTORITO				; EDD El Torito Functions
+					; ELTORITO _must_ also have EDD
+		dw ElToritoEmulate	; 4Ah - Initiate Disk Emulation
+		dw ElToritoTerminate	; 4Bh - Terminate Disk Emulation
+		dw ElToritoBoot		; 4Ch - Initiate Disk Emu. and Reboot
+		dw ElToritoCatalog	; 4Dh - Return Boot Catalog
+%endif ; ELTORITO
+%endif ; EDD
+
+Int13FuncsEnd	equ $
+Int13FuncsCnt	equ (Int13FuncsEnd-Int13Funcs) >> 1
+
+
+		alignb 8, db 0
+Shaker		dw ShakerEnd-$-1	; Descriptor table limit
+		dd 0			; Pointer to self
+		dw 0
+
+Shaker_RMDS:	dd 0x0000ffff		; 64K data segment
+		dd 0x00009300
+
+Shaker_DS:	dd 0x0000ffff		; 4GB data segment
+		dd 0x008f9300
+
+ShakerEnd	equ $
+
+		alignb 8, db 0
+
+Mover		dd 0, 0, 0, 0		; Must be zero
+		dw 0ffffh		; 64 K segment size
+Mover_src1:	db 0, 0, 0		; Low 24 bits of source addy
+		db 93h			; Access rights
+		db 00h			; Extended access rights
+Mover_src2:	db 0			; High 8 bits of source addy
+		dw 0ffffh		; 64 K segment size
+Mover_dst1:	db 0, 0, 0		; Low 24 bits of target addy
+		db 93h			; Access rights
+		db 00h			; Extended access rights
+Mover_dst2:	db 0			; High 8 bits of source addy
+Mover_dummy2:	dd 0, 0, 0, 0		; More space for the BIOS
+
+		alignb 16, db 0
+mBFT:
+; Fields common to all ACPI tables
+		dd '    '		; ACPI signature ("mBFT")
+					; This is filled-in by the installer
+					; to avoid an accidentally valid mBFT
+		dd mBFT_Len		; ACPI table length
+		db 1			; ACPI revision
+		db 0			; ACPI table checksum
+		db 'MEMDSK'		; ACPI OEM ID
+		db 'Syslinux'		; ACPI OEM table ID
+		dd 0			; ACPI OEM revision
+		dd 0			; ACPI ASL compiler vendor ID
+		dd 0			; ACPI ASL compiler revision
+; The next field is mBFT-specific and filled-in by the installer
+		dd 0			; "Safe hook" physical address
+
+; Note that the above ends on a DWORD boundary.
+; The MDI has always started at such a boundary.
+; Portions of the MDI are patched by the installer
+MemDisk_Info	equ $			; Pointed to by installation check
+MDI_Bytes	dw MDI_Len		; Total bytes in MDI structure
+MDI_Version	db VERSION_MINOR, VERSION_MAJOR	; MEMDISK version
+
+DiskBuf		dd 0			; Linear address of high memory disk
+DiskSize	dd 0			; Size of disk in blocks
+CommandLine	dw 0, 0			; Far pointer to saved command line
+
+OldInt13	dd 0			; INT 13h in chain
+OldInt15	dd 0			; INT 15h in chain
+
+OldDosMem	dw 0			; Old position of DOS mem end
+BootLoaderID	db 0			; Boot loader ID from header
+		db 0			; pad
+
+DPT_ptr		dw 0			; If nonzero, pointer to DPT
+					; Original DPT pointer follows
+
+MDI_Len		equ $-MemDisk_Info
+mBFT_Len	equ $-mBFT		; mBFT includes the MDI
+
+; ---- MDI structure ends here ---
+DriveShiftLimit	db 0ffh			; Installer will probe for
+					; a range of contiguous drives.
+					; Any BIOS drives above this region
+					; shall not be impacted by our
+					; shifting behaviour
+		db 0			; pad to a DWORD
+		dw 0			; pad to a QWORD
+MemInt1588	dw 0			; 1MB-65MB memory amount (1K)
+
+Cylinders	dw 0			; Cylinder count
+Heads		dw 0			; Head count
+Sectors		dd 0			; Sector count (zero-extended)
+
+Mem1MB		dd 0			; 1MB-16MB memory amount (1K)
+Mem16MB		dd 0			; 16MB-4G memory amount (64K)
+
+DriveNo		db 0			; Our drive number
+DriveType	db 0			; Our drive type (floppies)
+DriveCnt	db 0			; Drive count (from the BIOS)
+
+ConfigFlags	db 0			; Bit 0 - readonly
+
+MyStack		dw 0			; Offset of stack
+StatusPtr	dw 0			; Where to save status (zeroseg ptr)
+
+DPT		times 16 db 0		; BIOS parameter table pointer (floppies)
+OldInt1E	dd 0			; Previous INT 1E pointer (DPT)
+
+%if EDD
+EDD_DPT:
+.length		dw 30
+.info		dw 0029h
+		; Bit 0 - DMA boundaries handled transparently
+		; Bit 3 - Device supports write verify
+		; Bit 5 - Media is lockable
+.cylinders	dd 0			; Filled in by installer
+.heads		dd 0			; Filled in by installer
+.sectors	dd 0			; Filled in by installer
+.totalsize	dd 0, 0			; Filled in by installer
+.bytespersec	dw SECTORSIZE
+.eddtable	dw -1, -1		; Invalid DPTE pointer
+.dpikey		dw 0BEDDh		; Device Path Info magic
+.dpilen		db 2ch			; DPI len
+.res1		db 0			; Reserved
+.res2		dw 0			; Reserved
+.bustype	dd 'MEM '		; Host bus type (4 bytes, space padded)
+.inttype	dd 'MEMORY  '		; Interface type (8 bytes, spc. padded)
+.intpath	dd 0, 0			; Interface path
+.devpath	dd 0, 0, 0, 0		; Device path
+.res3		db 0			; Reserved
+.chksum		db 0			; DPI checksum
+
+%if ELTORITO
+; El Torito CD Specification Packet - mostly filled in by installer
+CD_PKT:
+.size		db 13h	; Packet size (19 bytes)
+.type		db 0	; Boot media type (flags)
+.driveno	db 0E0h	; INT 13h drive number
+.controller	db 0	; Controller index
+.start		dd 0	; Starting LBA of image
+.devno		dw 0	; Device number
+.user_buf	dw 0	; User buffer segment
+.load_seg	dw 0	; Load segment
+.sect_count	dw 0	; Emulated sectors to load
+.geom1		db 0	; Cylinders bits 0 thru 7
+.geom2		db 0	; Sects/track 0 thru 5, cyls 8, 9
+.geom3		db 0	; Heads
+%endif ; ELTORITO
+
+%endif ; EDD
+
+; End patch area
+
+		alignb 4, db 0
+Stack		dd 0			; Saved SS:ESP on invocation
+		dw 0
+SavedAX		dw 0			; AX saved on invocation
+Recursive	dw 0			; Recursion counter
+
+		alignb 4, db 0		; We *MUST* end on a dword boundary
+
+E820Table	equ $			; The installer loads the E820 table here
+TotalSize	equ $			; End pointer
Index: bootcd/isolinux/syslinux-6.03/memdisk/memdisk.ld
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memdisk.ld	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memdisk.ld	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,140 @@
+/* -----------------------------------------------------------------------
+ *   
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Linker script for MEMDISK
+ */
+
+/* Script for -z combreloc: combine and sort reloc sections */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+EXTERN(_start)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0x100000;
+  PROVIDE (__executable_start = .);
+
+  .init           :
+  {
+    KEEP (*(.init))
+  } =0x90909090
+  .text           :
+  {
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0x90909090
+  .fini           :
+  {
+    KEEP (*(.fini))
+  } =0x90909090
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1        : { *(.rodata1) }
+
+  /* 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          :
+  {
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  PROVIDE (__ctors_end = .);
+  PROVIDE (__dtors_start = .);
+  .dtors          :
+  {
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  PROVIDE (__dtors_end = .);
+
+  /* Adjust the address for the data segment.  Avoid mixing code and
+     data within same 128-byte chunk. */
+  . = ALIGN(128);
+
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .;
+  PROVIDE (edata = .);
+  . = ALIGN(16);
+  .bss            :
+  {
+   __bss_start = .;
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.  */
+   . = ALIGN(4);
+   __bss_end = .;
+  }
+  _end = .;
+  PROVIDE (end = .);
+
+
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /DISCARD/ : { *(.note.GNU-stack) }
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/memdisk16.asm
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memdisk16.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memdisk16.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,793 @@
+;; -*- fundamental -*-
+;; -----------------------------------------------------------------------
+;;
+;;   Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
+;;   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+;;
+;;   This program is free software; you can redistribute it and/or modify
+;;   it under the terms of the GNU General Public License as published by
+;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+;;   Boston MA 02111-1307, USA; either version 2 of the License, or
+;;   (at your option) any later version; incorporated herein by reference.
+;;
+;; -----------------------------------------------------------------------
+
+;;
+;; init16.asm
+;;
+;; Routine to initialize and to trampoline into 32-bit
+;; protected memory.  This code is derived from bcopy32.inc and
+;; com32.inc in the main SYSLINUX distribution.
+;;
+
+%include '../version.gen'
+
+MY_CS		equ 0x0800		; Segment address to use
+CS_BASE		equ (MY_CS << 4)	; Corresponding address
+
+; Low memory bounce buffer
+BOUNCE_SEG	equ (MY_CS+0x1000)
+
+%define DO_WBINVD 0
+
+		section .rodata align=16
+		section .data   align=16
+		section .bss    align=16
+		section .stack	align=16 nobits
+stack		resb 512
+stack_end	equ $
+
+;; -----------------------------------------------------------------------
+;;  Kernel image header
+;; -----------------------------------------------------------------------
+
+		section .text		; Must be first in image
+		bits 16
+
+cmdline		times 497 db 0		; We put the command line here
+setup_sects	db 0
+root_flags	dw 0
+syssize		dw 0
+swap_dev	dw 0
+ram_size	dw 0
+vid_mode	dw 0
+root_dev	dw 0
+boot_flag	dw 0xAA55
+
+_start:		jmp short start
+
+		db "HdrS"		; Header signature
+		dw 0x0203		; Header version number
+
+realmode_swtch	dw 0, 0			; default_switch, SETUPSEG
+start_sys_seg	dw 0x1000		; obsolete
+version_ptr	dw memdisk_version-0x200	; version string ptr
+type_of_loader	db 0			; Filled in by boot loader
+loadflags	db 1			; Please load high
+setup_move_size	dw 0			; Unused
+code32_start	dd 0x100000		; 32-bit start address
+ramdisk_image	dd 0			; Loaded ramdisk image address
+ramdisk_size	dd 0			; Size of loaded ramdisk
+bootsect_kludge	dw 0, 0
+heap_end_ptr	dw 0
+pad1		dw 0
+cmd_line_ptr	dd 0			; Command line
+ramdisk_max	dd 0xffffffff		; Highest allowed ramdisk address
+
+;
+; These fields aren't real setup fields, they're poked in by the
+; 32-bit code.
+;
+b_esdi		dd 0			; ES:DI for boot sector invocation
+b_edx		dd 0			; EDX for boot sector invocation
+b_sssp		dd 0			; SS:SP on boot sector invocation
+b_csip		dd 0			; CS:IP on boot sector invocation
+
+		section .rodata
+memdisk_version:
+		db "MEMDISK ", VERSION_STR, " ", DATE, 0
+
+;; -----------------------------------------------------------------------
+;;  End kernel image header
+;; -----------------------------------------------------------------------
+
+;
+; Move ourselves down into memory to reduce the risk of conflicts;
+; then canonicalize CS to match the other segments.
+;
+		section .text
+		bits 16
+start:
+		mov ax,MY_CS
+		mov es,ax
+		movzx cx,byte [setup_sects]
+		inc cx			; Add one for the boot sector
+		shl cx,7		; Convert to dwords
+		xor si,si
+		xor di,di
+		mov fs,si		; fs <- 0
+		cld
+		rep movsd
+		mov ds,ax
+		mov ss,ax
+		mov esp,stack_end
+		jmp MY_CS:.next
+.next:
+
+;
+; Copy the command line, if there is one
+;
+copy_cmdline:
+		xor di,di		; Bottom of our own segment (= "boot sector")
+		mov eax,[cmd_line_ptr]
+		and eax,eax
+		jz .endcmd		; No command line
+		mov si,ax
+		shr eax,4		; Convert to segment
+		and si,0x000F		; Starting offset only
+		mov gs,ax
+		mov cx,496		; Max number of bytes
+.copycmd:
+		gs lodsb
+		and al,al
+		jz .endcmd
+		stosb
+		loop .copycmd
+.endcmd:
+		xor al,al
+		stosb
+
+;
+; Now jump to 32-bit code
+;
+		sti
+		call init32
+;
+; When init32 returns, we have been set up, the new boot sector loaded,
+; and we should go and and run the newly loaded boot sector.
+;
+; The setup function will have poked values into the setup area.
+;
+		movzx edi,word [cs:b_esdi]
+		mov es,word [cs:b_esdi+2]
+		mov edx,[cs:b_edx]
+
+		cli
+		xor esi,esi		; No partition table involved
+		mov ds,si		; Make all the segments consistent
+		mov fs,si
+		mov gs,si
+		lss sp,[cs:b_sssp]
+		movzx esp,sp
+		jmp far [cs:b_csip]
+
+;
+; We enter protected mode, set up a flat 32-bit environment, run rep movsd
+; and then exit.  IMPORTANT: This code assumes cs == MY_CS.
+;
+; This code is probably excessively anal-retentive in its handling of
+; segments, but this stuff is painful enough as it is without having to rely
+; on everything happening "as it ought to."
+;
+DummyTSS	equ  0x580		; Hopefully safe place in low mmoery
+
+		section .data
+
+	; desc base, limit, flags
+%macro	desc 3
+	dd (%2 & 0xffff) | ((%1 & 0xffff) << 16)
+	dd (%1 & 0xff000000) | (%2 & 0xf0000) | ((%3 & 0xf0ff) << 8) | ((%1 & 0x00ff0000) >> 16)
+%endmacro
+
+		align 8, db 0
+call32_gdt:	dw call32_gdt_size-1	; Null descriptor - contains GDT
+.adj1:		dd call32_gdt+CS_BASE	; pointer for LGDT instruction
+		dw 0
+
+		; 0008: Dummy TSS to make Intel VT happy
+		; Should never be actually accessed...
+		desc DummyTSS, 103, 0x8089
+
+		; 0010: Code segment, use16, readable, dpl 0, base CS_BASE, 64K
+		desc CS_BASE, 0xffff, 0x009b
+
+		; 0018: Data segment, use16, read/write, dpl 0, base CS_BASE, 64K
+		desc CS_BASE, 0xffff, 0x0093
+
+		; 0020: Code segment, use32, read/write, dpl 0, base 0, 4G
+		desc 0, 0xfffff, 0xc09b
+
+		; 0028: Data segment, use32, read/write, dpl 0, base 0, 4G
+		desc 0, 0xfffff, 0xc093
+
+call32_gdt_size:	equ $-call32_gdt
+
+err_a20:	db 'ERROR: A20 gate not responding!',13,10,0
+
+		section .bss
+		alignb 4
+Return		resd 1			; Return value
+SavedSP		resw 1			; Place to save SP
+A20Tries	resb 1
+
+		section .data
+		align 4, db 0
+Target		dd 0			; Target address
+Target_Seg	dw 20h			; Target CS
+
+A20Type		dw 0			; Default = unknown
+
+		section .text
+		bits 16
+;
+; Routines to enable and disable (yuck) A20.  These routines are gathered
+; from tips from a couple of sources, including the Linux kernel and
+; http://www.x86.org/.  The need for the delay to be as large as given here
+; is indicated by Donnie Barnes of RedHat, the problematic system being an
+; IBM ThinkPad 760EL.
+;
+; We typically toggle A20 twice for every 64K transferred.
+;
+%define	io_delay	call _io_delay
+%define IO_DELAY_PORT	80h		; Invalid port (we hope!)
+%define disable_wait	32		; How long to wait for a disable
+
+%define A20_DUNNO	0		; A20 type unknown
+%define A20_NONE	1		; A20 always on?
+%define A20_BIOS	2		; A20 BIOS enable
+%define A20_KBC		3		; A20 through KBC
+%define A20_FAST	4		; A20 through port 92h
+
+		align 2, db 0
+A20List		dw a20_dunno, a20_none, a20_bios, a20_kbc, a20_fast
+A20DList	dw a20d_dunno, a20d_none, a20d_bios, a20d_kbc, a20d_fast
+a20_adjust_cnt	equ ($-A20List)/2
+
+slow_out:	out dx, al		; Fall through
+
+_io_delay:	out IO_DELAY_PORT,al
+		out IO_DELAY_PORT,al
+		ret
+
+enable_a20:
+		pushad
+		mov byte [A20Tries],255 ; Times to try to make this work
+
+try_enable_a20:
+
+;
+; Flush the caches
+;
+%if DO_WBINVD
+		call try_wbinvd
+%endif
+
+;
+; If the A20 type is known, jump straight to type
+;
+		mov bp,[A20Type]
+		add bp,bp			; Convert to word offset
+.adj4:		jmp word [bp+A20List]
+
+;
+; First, see if we are on a system with no A20 gate
+;
+a20_dunno:
+a20_none:
+		mov byte [A20Type], A20_NONE
+		call a20_test
+		jnz a20_done
+
+;
+; Next, try the BIOS (INT 15h AX=2401h)
+;
+a20_bios:
+		mov byte [A20Type], A20_BIOS
+		mov ax,2401h
+		pushf				; Some BIOSes muck with IF
+		int 15h
+		popf
+
+		call a20_test
+		jnz a20_done
+
+;
+; Enable the keyboard controller A20 gate
+;
+a20_kbc:
+		mov dl, 1			; Allow early exit
+		call empty_8042
+		jnz a20_done			; A20 live, no need to use KBC
+
+		mov byte [A20Type], A20_KBC	; Starting KBC command sequence
+
+		mov al,0D1h			; Write output port
+		out 064h, al
+		call empty_8042_uncond
+
+		mov al,0DFh			; A20 on
+		out 060h, al
+		call empty_8042_uncond
+
+		; Apparently the UHCI spec assumes that A20 toggle
+		; ends with a null command (assumed to be for sychronization?)
+		; Put it here to see if it helps anything...
+		mov al,0FFh			; Null command
+		out 064h, al
+		call empty_8042_uncond
+
+		; Verify that A20 actually is enabled.  Do that by
+		; observing a word in low memory and the same word in
+		; the HMA until they are no longer coherent.  Note that
+		; we don't do the same check in the disable case, because
+		; we don't want to *require* A20 masking (SYSLINUX should
+		; work fine without it, if the BIOS does.)
+.kbc_wait:	push cx
+		xor cx,cx
+.kbc_wait_loop:
+		call a20_test
+		jnz a20_done_pop
+		loop .kbc_wait_loop
+
+		pop cx
+;
+; Running out of options here.  Final attempt: enable the "fast A20 gate"
+;
+a20_fast:
+		mov byte [A20Type], A20_FAST	; Haven't used the KBC yet
+		in al, 092h
+		or al,02h
+		and al,~01h			; Don't accidentally reset the machine!
+		out 092h, al
+
+.fast_wait:	push cx
+		xor cx,cx
+.fast_wait_loop:
+		call a20_test
+		jnz a20_done_pop
+		loop .fast_wait_loop
+
+		pop cx
+
+;
+; Oh bugger.  A20 is not responding.  Try frobbing it again; eventually give up
+; and report failure to the user.
+;
+
+		dec byte [A20Tries]
+		jnz try_enable_a20
+
+
+		; Error message time
+		mov si,err_a20
+print_err:
+		lodsb
+		and al,al
+		jz die
+		mov bx,7
+		mov ah,0xe
+		int 10h
+		jmp print_err
+
+
+die:
+		sti
+.hlt:		hlt
+		jmp short .hlt
+
+;
+; A20 unmasked, proceed...
+;
+a20_done_pop:	pop cx
+a20_done:	popad
+		ret
+
+;
+; This routine tests if A20 is enabled (ZF = 0).  This routine
+; must not destroy any register contents.
+;
+
+; This is the INT 1Fh vector, which is standard PCs is used by the
+; BIOS when the screen is in graphics mode.  Even if it is, it points to
+; data, not code, so it should be safe enough to fiddle with.
+A20Test		equ (1Fh*4)
+
+a20_test:
+		push ds
+		push es
+		push cx
+		push eax
+		xor ax,ax
+		mov ds,ax		; DS == 0
+		dec ax
+		mov es,ax		; ES == 0FFFFh
+		mov cx,32		; Loop count
+		mov eax,[A20Test]
+		cmp eax,[es:A20Test+10h]
+		jne .a20_done
+		push eax
+.a20_wait:
+		inc eax
+		mov [A20Test],eax
+		io_delay
+		cmp eax,[es:A20Test+10h]
+		loopz .a20_wait
+		pop dword [A20Test]	; Restore original value
+.a20_done:
+		pop eax
+		pop cx
+		pop es
+		pop ds
+		ret
+
+disable_a20:
+		pushad
+;
+; Flush the caches
+;
+%if DO_WBINVD
+		call try_wbinvd
+%endif
+
+		mov bp,[A20Type]
+		add bp,bp			; Convert to word offset
+.adj5:		jmp word [bp+A20DList]
+
+a20d_bios:
+		mov ax,2400h
+		pushf				; Some BIOSes muck with IF
+		int 15h
+		popf
+		jmp short a20d_snooze
+
+;
+; Disable the "fast A20 gate"
+;
+a20d_fast:
+		in al, 092h
+		and al,~03h
+		out 092h, al
+		jmp short a20d_snooze
+
+;
+; Disable the keyboard controller A20 gate
+;
+a20d_kbc:
+		call empty_8042_uncond
+
+		mov al,0D1h
+		out 064h, al		; Write output port
+		call empty_8042_uncond
+
+		mov al,0DDh		; A20 off
+		out 060h, al
+		call empty_8042_uncond
+
+		mov al,0FFh		; Null command/synchronization
+		out 064h, al
+		call empty_8042_uncond
+
+		; Wait a bit for it to take effect
+a20d_snooze:
+		push cx
+		mov cx, disable_wait
+.delayloop:	call a20_test
+		jz .disabled
+		loop .delayloop
+.disabled:	pop cx
+a20d_dunno:
+a20d_none:
+		popad
+		ret
+
+;
+; Routine to empty the 8042 KBC controller.  If dl != 0
+; then we will test A20 in the loop and exit if A20 is
+; suddenly enabled.
+;
+empty_8042_uncond:
+		xor dl,dl
+empty_8042:
+		call a20_test
+		jz .a20_on
+		and dl,dl
+		jnz .done
+.a20_on:	io_delay
+		in al, 064h		; Status port
+		test al,1
+		jz .no_output
+		io_delay
+		in al, 060h		; Read input
+		jmp short empty_8042
+.no_output:
+		test al,2
+		jnz empty_8042
+		io_delay
+.done:		ret
+
+;
+; Execute a WBINVD instruction if possible on this CPU
+;
+%if DO_WBINVD
+try_wbinvd:
+		wbinvd
+		ret
+%endif
+
+		section .bss
+		alignb 4
+PMESP		resd 1			; Protected mode %esp
+
+		section .idt nobits align=4096
+		alignb 4096
+pm_idt		resb 4096		; Protected-mode IDT, followed by interrupt stubs
+
+
+
+
+pm_entry:	equ 0x100000
+
+		section .rodata
+		align 2, db 0
+call32_rmidt:
+		dw 0ffffh		; Limit
+		dd 0			; Address
+
+		section .data
+		alignb 2
+call32_pmidt:
+		dw 8*256		; Limit
+		dd 0			; Address (entered later)
+
+		section .text
+;
+; This is the main entrypoint in this function
+;
+init32:
+		mov bx,call32_call_start	; Where to go in PM
+
+;
+; Enter protected mode.  BX contains the entry point relative to the
+; real-mode CS.
+;
+call32_enter_pm:
+		mov ax,cs
+		mov ds,ax
+		movzx ebp,ax
+		shl ebp,4		; EBP <- CS_BASE
+		movzx ebx,bx
+		add ebx,ebp		; entry point += CS_BASE
+		cli
+		mov [SavedSP],sp
+		cld
+		call enable_a20
+		mov byte [call32_gdt+8+5],89h	; Mark TSS unbusy
+		o32 lgdt [call32_gdt]	; Set up GDT
+		o32 lidt [call32_pmidt]	; Set up IDT
+		mov eax,cr0
+		or al,1
+		mov cr0,eax		; Enter protected mode
+		jmp 20h:strict dword .in_pm+CS_BASE
+.pm_jmp		equ $-6
+
+
+		bits 32
+.in_pm:
+		xor eax,eax		; Available for future use...
+		mov fs,eax
+		mov gs,eax
+		lldt ax
+
+		mov al,28h		; Set up data segments
+		mov es,eax
+		mov ds,eax
+		mov ss,eax
+
+		mov al,08h
+		ltr ax
+
+		mov esp,[ebp+PMESP]	; Load protmode %esp if available
+		jmp ebx			; Go to where we need to go
+
+;
+; This is invoked before first dispatch of the 32-bit code, in 32-bit mode
+;
+call32_call_start:
+		;
+		; Set up a temporary stack in the bounce buffer;
+		; start32.S will override this to point us to the real
+		; high-memory stack.
+		;
+		mov esp, (BOUNCE_SEG << 4) + 0x10000
+
+		push dword call32_enter_rm.rm_jmp+CS_BASE
+		push dword call32_enter_pm.pm_jmp+CS_BASE
+		push dword stack_end		; RM size
+		push dword call32_gdt+CS_BASE
+		push dword call32_handle_interrupt+CS_BASE
+		push dword CS_BASE		; Segment base
+		push dword (BOUNCE_SEG << 4)	; Bounce buffer address
+		push dword call32_syscall+CS_BASE ; Syscall entry point
+
+		call pm_entry-CS_BASE		; Run the program...
+
+		; ... fall through to call32_exit ...
+
+call32_exit:
+		mov bx,call32_done	; Return to command loop
+
+call32_enter_rm:
+		; Careful here... the PM code may have relocated the
+		; entire RM code, so we need to figure out exactly
+		; where we are executing from.  If the PM code has
+		; relocated us, it *will* have adjusted the GDT to
+		; match, though.
+		call .here
+.here:		pop ebp
+		sub ebp,.here
+		o32 sidt [ebp+call32_pmidt]
+		cli
+		cld
+		mov [ebp+PMESP],esp	; Save exit %esp
+		xor esp,esp		; Make sure the high bits are zero
+		jmp 10h:.in_pm16	; Return to 16-bit mode first
+
+		bits 16
+.in_pm16:
+		mov ax,18h		; Real-mode-like segment
+		mov es,ax
+		mov ds,ax
+		mov ss,ax
+		mov fs,ax
+		mov gs,ax
+
+		lidt [call32_rmidt]	; Real-mode IDT (rm needs no GDT)
+		mov eax,cr0
+		and al,~1
+		mov cr0,eax
+		jmp MY_CS:.in_rm
+.rm_jmp		equ $-2
+
+.in_rm:					; Back in real mode
+		mov ax,cs
+		mov ds,ax
+		mov es,ax
+		mov fs,ax
+		mov gs,ax
+		mov ss,ax
+		mov sp,[SavedSP]	; Restore stack
+		jmp bx			; Go to whereever we need to go...
+
+call32_done:
+		call disable_a20
+		sti
+		ret
+
+;
+; 16-bit support code
+;
+		bits 16
+
+;
+; 16-bit interrupt-handling code
+;
+call32_int_rm:
+		pushf				; Flags on stack
+		push cs				; Return segment
+		push word .cont			; Return address
+		push dword edx			; Segment:offset of IVT entry
+		retf				; Invoke IVT routine
+.cont:		; ... on resume ...
+		mov bx,call32_int_resume
+		jmp call32_enter_pm		; Go back to PM
+
+;
+; 16-bit system call handling code
+;
+call32_sys_rm:
+		pop gs
+		pop fs
+		pop es
+		pop ds
+		popad
+		popfd
+		retf				; Invoke routine
+.return:
+		pushfd
+		pushad
+		push ds
+		push es
+		push fs
+		push gs
+		mov bx,call32_sys_resume
+		jmp call32_enter_pm
+
+;
+; 32-bit support code
+;
+		bits 32
+
+;
+; This is invoked on getting an interrupt in protected mode.  At
+; this point, we need to context-switch to real mode and invoke
+; the interrupt routine.
+;
+; When this gets invoked, the registers are saved on the stack and
+; AL contains the register number.
+;
+call32_handle_interrupt:
+		movzx eax,al
+		xor ebx,ebx		; Actually makes the code smaller
+		mov edx,[ebx+eax*4]	; Get the segment:offset of the routine
+		mov bx,call32_int_rm
+		jmp call32_enter_rm	; Go to real mode
+
+call32_int_resume:
+		popad
+		iret
+
+;
+; Syscall invocation.  We manifest a structure on the real-mode stack,
+; containing the call32sys_t structure from <call32.h> as well as
+; the following entries (from low to high address):
+; - Target offset
+; - Target segment
+; - Return offset
+; - Return segment (== real mode cs)
+; - Return flags
+;
+call32_syscall:
+		pushfd			; Save IF among other things...
+		pushad			; We only need to save some, but...
+		cld
+		call .here
+.here:		pop ebp
+		sub ebp,.here
+
+		movzx edi,word [ebp+SavedSP]
+		sub edi,54		; Allocate 54 bytes
+		mov [ebp+SavedSP],di
+		add edi,ebp		; Create linear address
+
+		mov esi,[esp+11*4]	; Source regs
+		xor ecx,ecx
+		mov cl,11		; 44 bytes to copy
+		rep movsd
+
+		movzx eax,byte [esp+10*4] ; Interrupt number
+		; ecx == 0 here; adding it to the EA makes the
+		; encoding smaller
+		mov eax,[ecx+eax*4]	; Get IVT entry
+		stosd			; Save in stack frame
+		mov ax,call32_sys_rm.return	; Return offset
+		stosw				; Save in stack frame
+		mov eax,ebp
+		shr eax,4			; Return segment
+		stosw				; Save in stack frame
+		mov eax,[edi-12]	; Return flags
+		and eax,0x200cd7	; Mask (potentially) unsafe flags
+		mov [edi-12],eax	; Primary flags entry
+		stosw			; Return flags
+
+		mov bx,call32_sys_rm
+		jmp call32_enter_rm	; Go to real mode
+
+		; On return, the 44-byte return structure is on the
+		; real-mode stack.  call32_enter_pm will leave ebp
+		; pointing to the real-mode base.
+call32_sys_resume:
+		movzx esi,word [ebp+SavedSP]
+		mov edi,[esp+12*4]	; Dest regs
+		add esi,ebp		; Create linear address
+		and edi,edi		; NULL pointer?
+		jnz .do_copy
+.no_copy:	mov edi,esi		; Do a dummy copy-to-self
+.do_copy:	xor ecx,ecx
+		mov cl,11		; 44 bytes
+		rep movsd		; Copy register block
+
+		add word [ebp+SavedSP],44	; Remove from stack
+
+		popad
+		popfd
+		ret			; Return to 32-bit program
Index: bootcd/isolinux/syslinux-6.03/memdisk/memdisk_chs_512.asm
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memdisk_chs_512.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memdisk_chs_512.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,5 @@
+	[map all memdisk_chs_512.map]
+%define EDD 0
+%define ELTORITO 0
+%define SECTORSIZE_LG2 9	; log2(sector size)
+%include "memdisk.inc"
Index: bootcd/isolinux/syslinux-6.03/memdisk/memdisk_edd_512.asm
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memdisk_edd_512.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memdisk_edd_512.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,5 @@
+	[map all memdisk_edd_512.map]
+%define EDD 1
+%define ELTORITO 0
+%define SECTORSIZE_LG2 9	; log2(sector size)
+%include "memdisk.inc"
Index: bootcd/isolinux/syslinux-6.03/memdisk/memdisk_iso_2048.asm
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memdisk_iso_2048.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memdisk_iso_2048.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,5 @@
+	[map all memdisk_iso_2048.map]
+%define EDD 1
+%define ELTORITO 1
+%define SECTORSIZE_LG2 11	; log2(sector size)
+%include "memdisk.inc"
Index: bootcd/isolinux/syslinux-6.03/memdisk/memdisk_iso_512.asm
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memdisk_iso_512.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memdisk_iso_512.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,5 @@
+	[map all memdisk_iso_512.map]
+%define EDD 1
+%define ELTORITO 1
+%define SECTORSIZE_LG2 9	; log2(sector size)
+%include "memdisk.inc"
Index: bootcd/isolinux/syslinux-6.03/memdisk/memmove.S
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memmove.S	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memmove.S	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,139 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * memmove.S
+ *
+ * Reasonably efficient memmove, using aligned transfers at least
+ * for the destination operand.
+ */
+
+	.globl	memmove
+	.type	memmove,@function
+	.text
+memmove:
+	jecxz	3f
+
+	pushl	%esi
+	pushl	%edi
+	pushl	%eax		/* Return value */
+
+	movl	%eax,%edi
+	movl	%edx,%esi
+
+	cmpl	%edi,%esi
+	jb	1f
+
+	/* source >= dest, forwards move */
+
+	/* Initial alignment */
+	movl	%edi,%edx
+	shrl	$1,%edx
+	jnc	11f
+	movsb
+	decl	%ecx
+11:
+	movb	%cl,%al
+	cmpl	$2,%ecx
+	jb	13f
+
+	shrl	$1,%edx
+	jnc	12f
+	movsw
+	subl	$2,%ecx
+12:
+	/* Bulk transfer */
+	movb	%cl,%al
+	shrl	$2,%ecx
+	rep; movsl
+
+	/* Final alignment */
+	testb	$2,%al
+	jz	14f
+	movsw
+13:
+14:
+	testb	$1,%al
+	jz	15f
+	movsb
+15:
+	jmp	2f
+
+
+1:
+	/* source < dest, backwards move */
+	std
+	leal	-1(%ecx,%esi),%esi
+	leal	-1(%ecx,%edi),%edi
+
+	/* Initial alignment */
+	movl	%edi,%edx
+	shrl	$1,%edx
+	jc	21f
+	movsb
+	decl	%ecx
+21:
+	decl	%esi
+	decl	%edi
+	movb	%cl,%al
+	cmpl	$2,%ecx
+	jb	23f
+	shrl	$1,%edx
+	jc	22f
+	movsw
+	subl	$2,%ecx
+22:
+	/* Bulk transfer */
+	subl	$2,%esi
+	subl	$2,%edi
+	movb	%cl,%al
+	shrl	$2,%ecx
+	rep; movsl
+
+	/* Final alignment */
+	addl	$2,%esi
+	addl	$2,%edi
+	testb	$2,%al
+	jz	24f
+	movsw
+23:
+24:
+	incl	%esi
+	incl	%edi
+	testb	$1,%al
+	jz	25f
+	movsb
+25:
+	cld
+2:
+	popl	%eax		/* Return value */
+	popl	%edi
+	popl	%esi
+3:
+	ret
+
+	.size	memmove, .-memmove
Index: bootcd/isolinux/syslinux-6.03/memdisk/memmove.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memmove.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memmove.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,36 @@
+/*
+ * memmove.c
+ */
+
+#include <string.h>
+
+void *memmove(void *dst, const void *src, size_t n)
+{
+	const char *p = src;
+	char *q = dst;
+#if defined(__i386__) || defined(__x86_64__)
+	if (q < p) {
+		asm volatile("cld; rep; movsb"
+			     : "+c" (n), "+S"(p), "+D"(q));
+	} else {
+		p += (n - 1);
+		q += (n - 1);
+		asm volatile("std; rep; movsb; cld"
+			     : "+c" (n), "+S"(p), "+D"(q));
+	}
+#else
+	if (q < p) {
+		while (n--) {
+			*q++ = *p++;
+		}
+	} else {
+		p += n;
+		q += n;
+		while (n--) {
+			*--q = *--p;
+		}
+	}
+#endif
+
+	return dst;
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/memset.S
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memset.S	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memset.S	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,86 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * memset.S
+ *
+ * Reasonably efficient memset, using aligned transfers at least
+ * for the destination operand.
+ */
+
+	.globl	memset
+	.type	memset,@function
+	.text
+memset:
+	jecxz	6f
+
+	pushl	%edi
+	pushl	%ebx
+	pushl	%eax		/* Return value */
+
+	movl	%eax,%edi
+	movb	%dl,%dh
+	movzwl	%dx,%eax
+	shll	$16,%edx
+	orl	%edx,%eax
+
+	/* Initial alignment */
+	movl	%edi,%edx
+	shrl	$1,%edx
+	jnc	1f
+	stosb
+	decl	%ecx
+1:
+	movb	%cl,%bl
+	cmpl	$2,%ecx
+	jb	3f
+	shrl	$1,%edx
+	jnc	2f
+	stosw
+	subl	$2,%ecx
+2:
+	/* Bulk transfer */
+	movb	%cl,%bl
+	shrl	$2,%ecx
+	rep; stosl
+
+	testb	$2,%bl
+	jz	4f
+	stosw
+3:
+4:
+	testb	$1,%bl
+	jz	5f
+	stosb
+5:
+	popl	%eax		/* Return value */
+	popl	%ebx
+	popl	%edi
+6:
+	ret
+
+	.size	memset, .-memset
Index: bootcd/isolinux/syslinux-6.03/memdisk/memset.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/memset.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/memset.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,30 @@
+/*
+ * memset.c
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+void *memset(void *dst, int c, size_t n)
+{
+	char *q = dst;
+
+#if defined(__i386__)
+	size_t nl = n >> 2;
+	asm volatile ("cld ; rep ; stosl ; movl %3,%0 ; rep ; stosb"
+		      : "+c" (nl), "+D" (q)
+		      : "a" ((unsigned char)c * 0x01010101U), "r" (n & 3));
+#elif defined(__x86_64__)
+	size_t nq = n >> 3;
+	asm volatile ("cld ; rep ; stosq ; movl %3,%%ecx ; rep ; stosb"
+		      :"+c" (nq), "+D" (q)
+		      : "a" ((unsigned char)c * 0x0101010101010101U),
+			"r" ((uint32_t) n & 7));
+#else
+	while (n--) {
+		*q++ = c;
+	}
+#endif
+
+	return dst;
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/msetup.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/msetup.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/msetup.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,178 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * msetup.c
+ *
+ * Initialization code for memory-based disk
+ */
+
+#include <stdint.h>
+#ifdef TEST
+# include <string.h>
+# include <stdio.h>
+#else
+# include "memdisk.h"
+# include "conio.h"
+#endif
+#include "e820.h"
+
+uint32_t dos_mem = 0;		/* 0-1MB */
+uint32_t low_mem = 0;		/* 1-16MB */
+uint32_t high_mem = 0;		/* 16+ MB */
+
+#ifndef TEST
+
+static inline int get_e820(void)
+{
+    struct e820_info {
+	uint64_t base;
+	uint64_t len;
+	uint32_t type;
+    } *buf = sys_bounce;
+    uint32_t copied;
+    int range_count = 0;
+    com32sys_t regs;
+
+    memset(&regs, 0, sizeof regs);
+    memset(buf, 0, sizeof *buf);
+
+    do {
+	regs.eax.l = 0x0000e820;
+	regs.ecx.l = sizeof(*buf);
+	regs.edx.l = 0x534d4150;
+	regs.edi.w[0] = OFFS(buf);
+	regs.es = SEG(buf);
+
+	intcall(0x15, &regs, &regs);
+	copied = (regs.eflags.l & 1) ? 0 : regs.ecx.l;
+
+	if (regs.eax.l != 0x534d4150 || copied < 20)
+	    break;
+
+	printf("e820: %08x%08x %08x%08x %d\n",
+	       (uint32_t) (buf->base >> 32), (uint32_t) buf->base,
+	       (uint32_t) (buf->len >> 32), (uint32_t) buf->len, buf->type);
+
+	insertrange(buf->base, buf->len, buf->type);
+	range_count++;
+
+    } while (regs.ebx.l);
+
+    return !range_count;
+}
+
+static inline void get_dos_mem(void)
+{
+    com32sys_t regs;
+
+    memset(&regs, 0, sizeof regs);
+    intcall(0x12, &regs, &regs);
+    insertrange(0, (uint64_t) ((uint32_t) regs.eax.w[0] << 10), 1);
+    printf(" DOS: %d K\n", regs.eax.w[0]);
+}
+
+static inline int get_e801(void)
+{
+    int err;
+    com32sys_t regs;
+
+    memset(&regs, 0, sizeof regs);
+
+    regs.eax.w[0] = 0xe801;
+    intcall(0x15, &regs, &regs);
+
+    if (!(err = regs.eflags.l & 1)) {
+	if (regs.eax.w[0]) {
+	    insertrange(0x100000, (uint64_t) ((uint32_t) regs.eax.w[0] << 10),
+			1);
+	}
+	if (regs.ebx.w[0]) {
+	    insertrange(0x1000000, (uint64_t) ((uint32_t) regs.ebx.w[0] << 16),
+			1);
+	}
+
+	printf("e801: %04x %04x\n", regs.eax.w[0], regs.ebx.w[0]);
+    }
+
+    return err;
+}
+
+static inline int get_88(void)
+{
+    com32sys_t regs;
+    int err;
+
+    memset(&regs, 0, sizeof regs);
+
+    regs.eax.b[1] = 0x88;
+    intcall(0x15, &regs, &regs);
+
+    if (!(err = regs.eflags.l & 1)) {
+	if (regs.eax.w[0]) {
+	    insertrange(0x100000, (uint64_t) ((uint32_t) regs.eax.w[0] << 10),
+			1);
+	}
+
+	printf("  88: %04x\n", regs.eax.w[0]);
+    }
+
+    return err;
+}
+
+void get_mem(void)
+{
+    if (get_e820()) {
+	get_dos_mem();
+	if (get_e801()) {
+	    if (get_88()) {
+		die("MEMDISK: Unable to obtain memory map\n");
+	    }
+	}
+    }
+}
+
+#endif /* TEST */
+
+#define PW(x) (1ULL << (x))
+
+void parse_mem(void)
+{
+    struct e820range *ep;
+
+    dos_mem = low_mem = high_mem = 0;
+
+    /* Derive "dos mem", "high mem", and "low mem" from the range array */
+    for (ep = ranges; ep->type != -1U; ep++) {
+	if (ep->type == 1) {
+	    /* Only look at memory ranges */
+	    if (ep->start == 0) {
+		if (ep[1].start > PW(20))
+		    dos_mem = PW(20);
+		else
+		    dos_mem = ep[1].start;
+	    }
+	    if (ep->start <= PW(20) && ep[1].start > PW(20)) {
+		if (ep[1].start > PW(24))
+		    low_mem = PW(24) - PW(20);
+		else
+		    low_mem = ep[1].start - PW(20);
+	    }
+	    if (ep->start <= PW(24) && ep[1].start > PW(24)) {
+		if (ep[1].start > PW(32))
+		    high_mem = PW(32) - PW(24);
+		else
+		    high_mem = ep[1].start - PW(24);
+	    }
+	}
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/mstructs.h
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/mstructs.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/mstructs.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,178 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2001-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ *   Portions copyright 2009-2010 Shao Miller
+ *				  [El Torito code, mBFT, "safe hook"]
+ *
+ *   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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/* These structures are common to MEMDISK and MDISKCHK.COM */
+
+#include <stdint.h>
+#include "compiler.h"
+
+struct seg_off {
+    uint16_t offset;
+    uint16_t segment;
+};
+
+typedef union {
+    struct seg_off seg_off;
+    uint32_t uint32;
+} real_addr_t;
+
+/* Forward declaration */
+struct mBFT;
+
+MEMDISK_PACKED_PREFIX
+struct safe_hook {
+    uint8_t jump[3];		/* Max. three bytes for jump */
+    uint8_t signature[8];	/* "$INT13SF" */
+    uint8_t vendor[8];		/* "MEMDISK " */
+    real_addr_t old_hook;	/* SEG:OFF for previous INT 13h hook */
+    uint32_t flags;		/* "Safe hook" flags */
+    /* The next field is a MEMDISK extension to the "safe hook" structure */
+    uint32_t mbft;
+} MEMDISK_PACKED_POSTFIX;
+
+struct memdisk_header {
+    uint16_t int13_offs;
+    uint16_t int15_offs;
+    uint16_t patch_offs;
+    uint16_t total_size;
+    uint16_t iret_offs;
+    struct safe_hook safe_hook;
+};
+
+MEMDISK_PACKED_PREFIX
+/* EDD disk parameter table */
+struct edd_dpt {
+    uint16_t len;		/* Length of table */
+    uint16_t flags;		/* Information flags */
+    uint32_t c;			/* Physical cylinders (count!) */
+    uint32_t h;			/* Physical heads (count!) */
+    uint32_t s;			/* Physical sectors/track (count!) */
+    uint64_t sectors;		/* Total sectors */
+    uint16_t bytespersec;	/* Bytes/sector */
+    real_addr_t dpte;		/* DPTE pointer */
+    uint16_t dpikey;		/* Device Path Info magic */
+    uint8_t  dpilen;		/* Device Path Info length */
+    uint8_t  res1;		/* Reserved */
+    uint16_t res2;		/* Reserved */
+    uint8_t  bustype[4];	/* Host bus type */
+    uint8_t  inttype[8];	/* Interface type */
+    uint64_t intpath;		/* Interface path */
+    uint64_t devpath[2];	/* Device path (double QuadWord!) */
+    uint8_t  res3;		/* Reserved */
+    uint8_t  chksum;		/* DPI checksum */
+} MEMDISK_PACKED_POSTFIX;
+
+/* Requirement for struct edd4_cd_pkt */
+#include "../memdisk/eltorito.h"
+
+/* Official MEMDISK Info structure ("MDI") */
+MEMDISK_PACKED_PREFIX
+struct mdi {
+    const uint16_t bytes;
+    const uint8_t version_minor;
+    const uint8_t version_major;
+
+    uint32_t diskbuf;
+    uint32_t disksize;
+    real_addr_t cmdline;
+
+    real_addr_t oldint13;
+    real_addr_t oldint15;
+
+    uint16_t olddosmem;
+    uint8_t bootloaderid;
+    uint8_t sector_shift;
+
+    uint16_t dpt_ptr;
+} MEMDISK_PACKED_POSTFIX;
+
+/* Requirement for struct acpi_description_header */
+#include "../memdisk/acpi.h"
+
+MEMDISK_PACKED_PREFIX
+struct mBFT {
+    struct acpi_description_header acpi;
+    uint32_t safe_hook;		/* "Safe hook" physical address */
+    struct mdi mdi;
+} MEMDISK_PACKED_POSTFIX;
+
+/* The Disk Parameter Table may be required */
+typedef union {
+    struct hd_dpt {
+	uint16_t max_cyl;	/* Max cylinder */
+	uint8_t max_head;	/* Max head */
+	uint8_t junk1[5];	/* Obsolete junk, leave at zero */
+	uint8_t ctrl;		/* Control byte */
+	uint8_t junk2[7];	/* More obsolete junk */
+    } hd;
+    struct fd_dpt {
+	uint8_t specify1;	/* "First specify byte" */
+	uint8_t specify2;	/* "Second specify byte" */
+	uint8_t delay;		/* Delay until motor turn off */
+	uint8_t bps;		/* Bytes/sector (02h = 512) */
+
+	uint8_t sectors;	/* Sectors/track */
+	uint8_t isgap;		/* Length of intersector gap */
+	uint8_t dlen;		/* Data length (0FFh) */
+	uint8_t fgap;		/* Formatting gap */
+
+	uint8_t ffill;		/* Format fill byte */
+	uint8_t settle;		/* Head settle time (ms) */
+	uint8_t mstart;		/* Motor start time */
+	uint8_t maxtrack;	/* Maximum track number */
+
+	uint8_t rate;		/* Data transfer rate */
+	uint8_t cmos;		/* CMOS type */
+	uint8_t pad[2];
+
+	uint32_t old_fd_dpt;	/* Extension: pointer to old INT 1Eh */
+    } fd;
+} dpt_t;
+
+MEMDISK_PACKED_PREFIX
+struct patch_area {
+    struct mdi mdi;
+
+    uint8_t driveshiftlimit;	/* Do not shift drives above this region */
+    uint8_t _pad2;		/* Pad to DWORD */
+    uint16_t _pad3;		/* Pad to QWORD */
+
+    uint16_t memint1588;
+
+    uint16_t cylinders;
+    uint16_t heads;
+    uint32_t sectors;
+
+    uint32_t mem1mb;
+    uint32_t mem16mb;
+
+    uint8_t driveno;
+    uint8_t drivetype;
+    uint8_t drivecnt;
+    uint8_t configflags;
+
+#define CONFIG_READONLY	0x01
+#define CONFIG_RAW	0x02
+#define CONFIG_SAFEINT	0x04
+#define CONFIG_BIGRAW	0x08	/* MUST be 8! */
+#define CONFIG_MODEMASK	0x0e
+
+    uint16_t mystack;
+    uint16_t statusptr;
+
+    dpt_t dpt;
+    struct edd_dpt edd_dpt;
+    struct edd4_cd_pkt cd_pkt;	/* Only really in a memdisk_iso_* hook */
+} MEMDISK_PACKED_POSTFIX;
Index: bootcd/isolinux/syslinux-6.03/memdisk/postprocess.pl
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/postprocess.pl	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/postprocess.pl	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,58 @@
+#!/usr/bin/perl
+## -----------------------------------------------------------------------
+##
+##   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.
+##
+## -----------------------------------------------------------------------
+
+#
+# Postprocess the memdisk binary.  Used during the 'make' process.
+# We write memdisk16.bin out to the final memdisk kernel, pad it to an
+# integral 512-byte sector length, write this number of sectors into the
+# kernel header field "setup_sects", then append memdisk32.bin
+
+eval { use bytes; };
+
+($out,$file16,$file32) = @ARGV;
+
+open(OUT, "> $out\0") or die "$0: Cannot create file: $out\n";
+eval { binmode OUT; };
+open(FILE, "< $file16\0") or die "$0: Cannot open file: $file16\n";
+eval { binmode FILE };
+
+@info = stat(FILE);
+$size = $info[7];
+
+$sectors = ($size + 511) >> 9;
+$xsize = $sectors << 9;
+
+read(FILE, $f16, $size);
+
+print OUT $f16;
+
+if ( $size != $xsize ) {
+    # Pad to a sector boundary
+    print OUT "\0" x ($xsize-$size);
+}
+
+seek(OUT, 0x1f1, SEEK_SET);	# setup_sects
+# All sectors are setup except the first
+print OUT pack("C", $sectors-1);
+
+seek(OUT, $xsize, SEEK_SET);
+close(FILE);
+
+open(FILE, "+< $file32\0") or die "$0: Cannot open file: $file32\n";
+
+while ( ($n = read(FILE, $f32, 65536)) > 0 ) {
+    print OUT $f32;
+}
+
+close(FILE);
+close(OUT);
Index: bootcd/isolinux/syslinux-6.03/memdisk/setup.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/setup.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/setup.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,1237 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2001-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ *   Portions copyright 2009-2010 Shao Miller
+ *				  [El Torito code, mBFT, "safe hook"]
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdint.h>
+#include <minmax.h>
+#include <suffix_number.h>
+#include "bda.h"
+#include "dskprobe.h"
+#include "e820.h"
+#include "conio.h"
+#include "version.h"
+#include "memdisk.h"
+#include <version.h>
+
+const char memdisk_version[] = "MEMDISK " VERSION_STR " " DATE;
+const char copyright[] =
+    "Copyright " FIRSTYEAR "-" YEAR_STR " H. Peter Anvin et al";
+
+extern const char _binary_memdisk_chs_512_bin_start[];
+extern const char _binary_memdisk_chs_512_bin_end[];
+extern const char _binary_memdisk_chs_512_bin_size[];
+extern const char _binary_memdisk_edd_512_bin_start[];
+extern const char _binary_memdisk_edd_512_bin_end[];
+extern const char _binary_memdisk_edd_512_bin_size[];
+extern const char _binary_memdisk_iso_512_bin_start[];
+extern const char _binary_memdisk_iso_512_bin_end[];
+extern const char _binary_memdisk_iso_512_bin_size[];
+extern const char _binary_memdisk_iso_2048_bin_start[];
+extern const char _binary_memdisk_iso_2048_bin_end[];
+extern const char _binary_memdisk_iso_2048_bin_size[];
+
+/* Pull in structures common to MEMDISK and MDISKCHK.COM */
+#include "mstructs.h"
+
+/* An EDD disk packet */
+struct edd_dsk_pkt {
+    uint8_t size;		/* Packet size        */
+    uint8_t res1;		/* Reserved           */
+    uint16_t count;		/* Count to transfer  */
+    uint32_t buf;		/* Buffer pointer     */
+    uint64_t start;		/* LBA to start from  */
+    uint64_t buf64;		/* 64-bit buf pointer */
+} __attribute__ ((packed));
+
+/* Change to 1 for El Torito debugging */
+#define DBG_ELTORITO 0
+
+#if DBG_ELTORITO
+extern void eltorito_dump(uint32_t);
+#endif
+
+/*
+ * Routine to seek for a command-line item and return a pointer
+ * to the data portion, if present
+ */
+
+/* Magic return values */
+#define CMD_NOTFOUND   ((char *)-1)	/* Not found */
+#define CMD_BOOL       ((char *)-2)	/* Found boolean option */
+#define CMD_HASDATA(X) ((int)(X) >= 0)
+
+static const char *getcmditem(const char *what)
+{
+    const char *p;
+    const char *wp = what;
+    int match = 0;
+
+    for (p = shdr->cmdline; *p; p++) {
+	switch (match) {
+	case 0:		/* Ground state */
+	    if (*p == ' ')
+		break;
+
+	    wp = what;
+	    match = 1;
+	    /* Fall through */
+
+	case 1:		/* Matching */
+	    if (*wp == '\0') {
+		if (*p == '=')
+		    return p + 1;
+		else if (*p == ' ')
+		    return CMD_BOOL;
+		else {
+		    match = 2;
+		    break;
+		}
+	    }
+	    if (*p != *wp++)
+		match = 2;
+	    break;
+
+	case 2:		/* Mismatch, skip rest of option */
+	    if (*p == ' ')
+		match = 0;	/* Next option */
+	    break;
+	}
+    }
+
+    /* Check for matching string at end of line */
+    if (match == 1 && *wp == '\0')
+	return CMD_BOOL;
+
+    return CMD_NOTFOUND;
+}
+
+/*
+ * Check to see if this is a gzip image
+ */
+#define UNZIP_ALIGN 512
+
+extern const char _end[];		/* Symbol signalling end of data */
+
+void unzip_if_needed(uint32_t * where_p, uint32_t * size_p)
+{
+    uint32_t where = *where_p;
+    uint32_t size = *size_p;
+    uint32_t zbytes;
+    uint32_t startrange, endrange;
+    uint32_t gzdatasize, gzwhere;
+    uint32_t orig_crc, offset;
+    uint32_t target = 0;
+    int i, okmem;
+
+    /* Is it a gzip image? */
+    if (check_zip((void *)where, size, &zbytes, &gzdatasize,
+		  &orig_crc, &offset) == 0) {
+
+	if (offset + zbytes > size) {
+	    /*
+	     * Assertion failure; check_zip is supposed to guarantee this
+	     * never happens.
+	     */
+	    die("internal error: check_zip returned nonsense\n");
+	}
+
+	/*
+	 * Find a good place to put it: search memory ranges in descending
+	 * order until we find one that is legal and fits
+	 */
+	okmem = 0;
+	for (i = nranges - 1; i >= 0; i--) {
+	    /*
+	     * We can't use > 4G memory (32 bits only.)  Truncate to 2^32-1
+	     * so we don't have to deal with funny wraparound issues.
+	     */
+
+	    /* Must be memory */
+	    if (ranges[i].type != 1)
+		continue;
+
+	    /* Range start */
+	    if (ranges[i].start >= 0xFFFFFFFF)
+		continue;
+
+	    startrange = (uint32_t) ranges[i].start;
+
+	    /* Range end (0 for end means 2^64) */
+	    endrange = ((ranges[i + 1].start >= 0xFFFFFFFF ||
+			 ranges[i + 1].start == 0)
+			? 0xFFFFFFFF : (uint32_t) ranges[i + 1].start);
+
+	    /* Make sure we don't overwrite ourselves */
+	    if (startrange < (uint32_t) _end)
+		startrange = (uint32_t) _end;
+
+	    /* Allow for alignment */
+	    startrange =
+		(ranges[i].start + (UNZIP_ALIGN - 1)) & ~(UNZIP_ALIGN - 1);
+
+	    /* In case we just killed the whole range... */
+	    if (startrange >= endrange)
+		continue;
+
+	    /*
+	     * Must be large enough... don't rely on gzwhere for this
+	     * (wraparound)
+	     */
+	    if (endrange - startrange < gzdatasize)
+		continue;
+
+	    /*
+	     * This is where the gz image would be put if we put it in this
+	     * range...
+	     */
+	    gzwhere = (endrange - gzdatasize) & ~(UNZIP_ALIGN - 1);
+
+	    /* Cast to uint64_t just in case we're flush with the top byte */
+	    if ((uint64_t) where + size >= gzwhere && where < endrange) {
+		/*
+		 * Need to move source data to avoid compressed/uncompressed
+		 * overlap
+		 */
+		uint32_t newwhere;
+
+		if (gzwhere - startrange < size)
+		    continue;	/* Can't fit both old and new */
+
+		newwhere = (gzwhere - size) & ~(UNZIP_ALIGN - 1);
+		printf("Moving compressed data from 0x%08x to 0x%08x\n",
+		       where, newwhere);
+
+		memmove((void *)newwhere, (void *)where, size);
+		where = newwhere;
+	    }
+
+	    target = gzwhere;
+	    okmem = 1;
+	    break;
+	}
+
+	if (!okmem)
+	    die("Not enough memory to decompress image (need 0x%08x bytes)\n",
+		gzdatasize);
+
+	printf("gzip image: decompressed addr 0x%08x, len 0x%08x: ",
+	       target, gzdatasize);
+
+	*size_p = gzdatasize;
+	*where_p = (uint32_t) unzip((void *)(where + offset), zbytes,
+				    gzdatasize, orig_crc, (void *)target);
+    }
+}
+
+/*
+ * Figure out the "geometry" of the disk in question
+ */
+struct geometry {
+    uint32_t sectors;		/* Sector count */
+    uint32_t c, h, s;		/* C/H/S geometry */
+    uint32_t offset;		/* Byte offset for disk */
+    uint32_t boot_lba;		/* LBA of bootstrap code */
+    uint8_t type;		/* Type byte for INT 13h AH=08h */
+    uint8_t driveno;		/* Drive no */
+    uint8_t sector_shift;	/* Sector size as a power of 2 */
+    const char *hsrc, *ssrc;	/* Origins of H and S geometries */
+};
+
+/* Format of a DOS partition table entry */
+struct ptab_entry {
+    uint8_t active;
+    uint8_t start_h, start_s, start_c;
+    uint8_t type;
+    uint8_t end_h, end_s, end_c;
+    uint32_t start;
+    uint32_t size;
+} __attribute__ ((packed));
+
+/* Format of a FAT filesystem superblock */
+struct fat_extra {
+    uint8_t bs_drvnum;
+    uint8_t bs_resv1;
+    uint8_t bs_bootsig;
+    uint32_t bs_volid;
+    char bs_vollab[11];
+    char bs_filsystype[8];
+} __attribute__ ((packed));
+struct fat_super {
+    uint8_t bs_jmpboot[3];
+    char bs_oemname[8];
+    uint16_t bpb_bytspersec;
+    uint8_t bpb_secperclus;
+    uint16_t bpb_rsvdseccnt;
+    uint8_t bpb_numfats;
+    uint16_t bpb_rootentcnt;
+    uint16_t bpb_totsec16;
+    uint8_t bpb_media;
+    uint16_t bpb_fatsz16;
+    uint16_t bpb_secpertrk;
+    uint16_t bpb_numheads;
+    uint32_t bpb_hiddsec;
+    uint32_t bpb_totsec32;
+    union {
+	struct {
+	    struct fat_extra extra;
+	} fat16;
+	struct {
+	    uint32_t bpb_fatsz32;
+	    uint16_t bpb_extflags;
+	    uint16_t bpb_fsver;
+	    uint32_t bpb_rootclus;
+	    uint16_t bpb_fsinfo;
+	    uint16_t bpb_bkbootsec;
+	    char bpb_reserved[12];
+	    /* Clever, eh?  Same fields, different offset... */
+	    struct fat_extra extra;
+	} fat32 __attribute__ ((packed));
+    } x;
+} __attribute__ ((packed));
+
+/* Format of a DOSEMU header */
+struct dosemu_header {
+    uint8_t magic[7];		/* DOSEMU\0 */
+    uint32_t h;
+    uint32_t s;
+    uint32_t c;
+    uint32_t offset;
+    uint8_t pad[105];
+} __attribute__ ((packed));
+
+#define FOUR(a,b,c,d) (((a) << 24)|((b) << 16)|((c) << 8)|(d))
+
+static const struct geometry *get_disk_image_geometry(uint32_t where,
+						      uint32_t size)
+{
+    static struct geometry hd_geometry;
+    struct dosemu_header dosemu;
+    unsigned int sectors, xsectors, v;
+    unsigned int offset;
+    int i;
+    const char *p;
+
+    printf("command line: %s\n", shdr->cmdline);
+
+    hd_geometry.sector_shift = 9;	/* Assume floppy/HDD at first */
+
+    offset = 0;
+    if (CMD_HASDATA(p = getcmditem("offset")) && (v = atou(p)))
+	offset = v;
+
+    sectors = xsectors = (size - offset) >> hd_geometry.sector_shift;
+
+    hd_geometry.hsrc = "guess";
+    hd_geometry.ssrc = "guess";
+    hd_geometry.sectors = sectors;
+    hd_geometry.offset = offset;
+
+    if ((p = getcmditem("iso")) != CMD_NOTFOUND) {
+#if DBG_ELTORITO
+	eltorito_dump(where);
+#endif
+	struct edd4_bvd *bvd = (struct edd4_bvd *)(where + 17 * 2048);
+	/* Tiny sanity check */
+	if ((bvd->boot_rec_ind != 0) || (bvd->ver != 1))
+	    printf("El Torito BVD sanity check failed.\n");
+	struct edd4_bootcat *boot_cat =
+	    (struct edd4_bootcat *)(where + bvd->boot_cat * 2048);
+	/* Another tiny sanity check */
+	if ((boot_cat->validation_entry.platform_id != 0) ||
+	    (boot_cat->validation_entry.key55 != 0x55) ||
+	    (boot_cat->validation_entry.keyAA != 0xAA))
+	    printf("El Torito boot catalog sanity check failed.\n");
+	/* If we have an emulation mode, set the offset to the image */
+	if (boot_cat->initial_entry.media_type)
+	    hd_geometry.offset += boot_cat->initial_entry.load_block * 2048;
+	else
+	    /* We're a no-emulation mode, so we will boot to an offset */
+	    hd_geometry.boot_lba = boot_cat->initial_entry.load_block * 4;
+	if (boot_cat->initial_entry.media_type < 4) {
+	    /* We're a floppy emulation mode or our params will be
+	     * overwritten by the no emulation mode case
+	     */
+	    hd_geometry.driveno = 0x00;
+	    hd_geometry.c = 80;
+	    hd_geometry.h = 2;
+	}
+	switch (boot_cat->initial_entry.media_type) {
+	case 0:		/* No emulation   */
+	    hd_geometry.driveno = 0xE0;
+	    hd_geometry.type = 10;	/* ATAPI removable media device */
+	    hd_geometry.c = 65535;
+	    hd_geometry.h = 255;
+	    hd_geometry.s = 15;
+	    /* 2048-byte sectors, so adjust the size and count */
+	    hd_geometry.sector_shift = 11;
+	    break;
+	case 1:		/* 1.2 MB floppy  */
+	    hd_geometry.s = 15;
+	    hd_geometry.type = 2;
+	    sectors = 2400;
+	    break;
+	case 2:		/* 1.44 MB floppy */
+	    hd_geometry.s = 18;
+	    hd_geometry.type = 4;
+	    sectors = 2880;
+	    break;
+	case 3:		/* 2.88 MB floppy */
+	    hd_geometry.s = 36;
+	    hd_geometry.type = 6;
+	    sectors = 5760;
+	    break;
+	case 4:
+	    hd_geometry.driveno = 0x80;
+	    hd_geometry.type = 0;
+	    break;
+	}
+	sectors = (size - hd_geometry.offset) >> hd_geometry.sector_shift;
+
+	/* For HDD emulation, we figure out the geometry later. Otherwise: */
+	if (hd_geometry.s) {
+	    hd_geometry.hsrc = hd_geometry.ssrc = "El Torito";
+	}
+	hd_geometry.sectors = sectors;
+    }
+
+    /* Do we have a DOSEMU header? */
+    memcpy(&dosemu, (char *)where + hd_geometry.offset, sizeof dosemu);
+    if (!memcmp("DOSEMU", dosemu.magic, 7)) {
+	/* Always a hard disk unless overruled by command-line options */
+	hd_geometry.driveno = 0x80;
+	hd_geometry.type = 0;
+	hd_geometry.c = dosemu.c;
+	hd_geometry.h = dosemu.h;
+	hd_geometry.s = dosemu.s;
+	hd_geometry.offset += dosemu.offset;
+	sectors = (size - hd_geometry.offset) >> hd_geometry.sector_shift;
+
+	hd_geometry.hsrc = hd_geometry.ssrc = "DOSEMU";
+    }
+
+    if (CMD_HASDATA(p = getcmditem("c")) && (v = atou(p)))
+	hd_geometry.c = v;
+    if (CMD_HASDATA(p = getcmditem("h")) && (v = atou(p))) {
+	hd_geometry.h = v;
+	hd_geometry.hsrc = "cmd";
+    }
+    if (CMD_HASDATA(p = getcmditem("s")) && (v = atou(p))) {
+	hd_geometry.s = v;
+	hd_geometry.ssrc = "cmd";
+    }
+
+    if (!hd_geometry.h || !hd_geometry.s) {
+	int h, s, max_h, max_s;
+
+	max_h = hd_geometry.h;
+	max_s = hd_geometry.s;
+
+	if (!(max_h | max_s)) {
+	    /* Look for a FAT superblock and if we find something that looks
+	       enough like one, use geometry from that.  This takes care of
+	       megafloppy images and unpartitioned hard disks. */
+	    const struct fat_extra *extra = NULL;
+	    const struct fat_super *fs = (const struct fat_super *)
+		((char *)where + hd_geometry.offset);
+
+	    if ((fs->bpb_media == 0xf0 || fs->bpb_media >= 0xf8) &&
+		(fs->bs_jmpboot[0] == 0xe9 || fs->bs_jmpboot[0] == 0xeb) &&
+		fs->bpb_bytspersec == 512 &&
+		fs->bpb_numheads >= 1 && fs->bpb_numheads <= 256 &&
+		fs->bpb_secpertrk >= 1 && fs->bpb_secpertrk <= 63) {
+		extra =
+		    fs->bpb_fatsz16 ? &fs->x.fat16.extra : &fs->x.fat32.extra;
+		if (!
+		    (extra->bs_bootsig == 0x29 && extra->bs_filsystype[0] == 'F'
+		     && extra->bs_filsystype[1] == 'A'
+		     && extra->bs_filsystype[2] == 'T'))
+		    extra = NULL;
+	    }
+	    if (extra) {
+		hd_geometry.driveno = extra->bs_drvnum & 0x80;
+		max_h = fs->bpb_numheads;
+		max_s = fs->bpb_secpertrk;
+		hd_geometry.hsrc = hd_geometry.ssrc = "FAT";
+	    }
+	}
+
+	if (!(max_h | max_s)) {
+	    /* No FAT filesystem found to steal geometry from... */
+	    if ((sectors < 4096 * 2) && (hd_geometry.sector_shift == 9)) {
+		int ok = 0;
+		unsigned int xsectors = sectors;
+
+		hd_geometry.driveno = 0;	/* Assume floppy */
+
+		while (!ok) {
+		    /* Assume it's a floppy drive, guess a geometry */
+		    unsigned int type, track;
+		    int c, h, s = 0;
+
+		    if (xsectors < 320 * 2) {
+			c = 40;
+			h = 1;
+			type = 1;
+		    } else if (xsectors < 640 * 2) {
+			c = 40;
+			h = 2;
+			type = 1;
+		    } else if (xsectors < 1200 * 2) {
+			c = 80;
+			h = 2;
+			type = 3;
+		    } else if (xsectors < 1440 * 2) {
+			c = 80;
+			h = 2;
+			type = 2;
+		    } else if (xsectors < 2880 * 2) {
+			c = 80;
+			h = 2;
+			type = 4;
+		    } else {
+			c = 80;
+			h = 2;
+			type = 6;
+		    }
+		    track = c * h;
+		    while (c < 256) {
+			s = xsectors / track;
+			if (s < 63 && (xsectors % track) == 0) {
+			    ok = 1;
+			    break;
+			}
+			c++;
+			track += h;
+		    }
+		    if (ok) {
+			max_h = h;
+			max_s = s;
+			hd_geometry.hsrc = hd_geometry.ssrc = "fd";
+		    } else {
+			/* No valid floppy geometry, fake it by simulating broken
+			   sectors at the end of the image... */
+			xsectors++;
+		    }
+
+		    hd_geometry.type = type;
+		}
+	    } else {
+		/* Assume it is a hard disk image and scan for a partition table */
+		const struct ptab_entry *ptab = (const struct ptab_entry *)
+		    ((char *)where + hd_geometry.offset + (512 - 2 - 4 * 16));
+
+		/* Assume hard disk */
+		if (!hd_geometry.driveno)
+		    hd_geometry.driveno = 0x80;
+
+		if (*(uint16_t *) ((char *)where + hd_geometry.offset + 512 - 2) == 0xaa55) {
+		    for (i = 0; i < 4; i++) {
+			if (ptab[i].type && !(ptab[i].active & 0x7f)) {
+			    s = (ptab[i].start_s & 0x3f);
+			    h = ptab[i].start_h + 1;
+
+			    if (max_h < h)
+				max_h = h;
+			    if (max_s < s)
+				max_s = s;
+
+			    s = (ptab[i].end_s & 0x3f);
+			    h = ptab[i].end_h + 1;
+
+			    if (max_h < h) {
+				max_h = h;
+				hd_geometry.hsrc = "MBR";
+			    }
+			    if (max_s < s) {
+				max_s = s;
+				hd_geometry.ssrc = "MBR";
+			    }
+			}
+		    }
+		}
+
+		hd_geometry.type = 0;
+	    }
+	}
+
+	if (!max_h)
+	    max_h = xsectors > 2097152 ? 255 : 64;
+	if (!max_s)
+	    max_s = xsectors > 2097152 ? 63 : 32;
+
+	hd_geometry.h    = max_h;
+	hd_geometry.s    = max_s;
+    }
+
+    if (!hd_geometry.c)
+	hd_geometry.c = xsectors / (hd_geometry.h * hd_geometry.s);
+
+    if ((p = getcmditem("floppy")) != CMD_NOTFOUND) {
+	hd_geometry.driveno = CMD_HASDATA(p) ? atou(p) & 0x7f : 0;
+    } else if ((p = getcmditem("harddisk")) != CMD_NOTFOUND) {
+	hd_geometry.driveno = CMD_HASDATA(p) ? atou(p) | 0x80 : 0x80;
+    }
+
+    if (hd_geometry.driveno & 0x80) {
+	hd_geometry.type = 0;	/* Type = hard disk */
+    } else {
+	if (hd_geometry.type == 0)
+	    hd_geometry.type = 0x10;	/* ATAPI floppy, e.g. LS-120 */
+    }
+
+    if ((size - hd_geometry.offset) & 0x1ff) {
+	puts("MEMDISK: Image has fractional end sector\n");
+    }
+    if (sectors % (hd_geometry.h * hd_geometry.s)) {
+	puts("MEMDISK: Image seems to have fractional end cylinder\n");
+    }
+    if ((hd_geometry.c * hd_geometry.h * hd_geometry.s) > sectors) {
+	puts("MEMDISK: Image appears to be truncated\n");
+    }
+
+    return &hd_geometry;
+}
+
+/*
+ * Find a $PnP installation check structure; return (ES << 16) + DI value
+ */
+static uint32_t pnp_install_check(void)
+{
+    uint32_t *seg;
+    unsigned char *p, csum;
+    int i, len;
+
+    for (seg = (uint32_t *) 0xf0000; seg < (uint32_t *) 0x100000; seg += 4) {
+	if (*seg == ('$' + ('P' << 8) + ('n' << 16) + ('P' << 24))) {
+	    p = (unsigned char *)seg;
+	    len = p[5];
+	    if (len < 0x21)
+		continue;
+	    csum = 0;
+	    for (i = len; i; i--)
+		csum += *p++;
+	    if (csum != 0)
+		continue;
+
+	    return (0xf000 << 16) + (uint16_t) (unsigned long)seg;
+	}
+    }
+
+    return 0;
+}
+
+/*
+ * Relocate the real-mode code to a new segment
+ */
+struct gdt_ptr {
+    uint16_t limit;
+    uint32_t base;
+} __attribute__ ((packed));
+
+static void set_seg_base(uint32_t gdt_base, int seg, uint32_t v)
+{
+    *(uint16_t *) (gdt_base + seg + 2) = v;
+    *(uint8_t *) (gdt_base + seg + 4) = v >> 16;
+    *(uint8_t *) (gdt_base + seg + 7) = v >> 24;
+}
+
+static void relocate_rm_code(uint32_t newbase)
+{
+    uint32_t gdt_base;
+    uint32_t oldbase = rm_args.rm_base;
+    uint32_t delta = newbase - oldbase;
+
+    cli();
+    memmove((void *)newbase, (void *)oldbase, rm_args.rm_size);
+
+    rm_args.rm_return += delta;
+    rm_args.rm_intcall += delta;
+    rm_args.rm_bounce += delta;
+    rm_args.rm_base += delta;
+    rm_args.rm_gdt += delta;
+    rm_args.rm_pmjmp += delta;
+    rm_args.rm_rmjmp += delta;
+
+    gdt_base = rm_args.rm_gdt;
+
+    *(uint32_t *) (gdt_base + 2) = gdt_base;	/* GDT self-pointer */
+
+    /* Segments 0x10 and 0x18 are real-mode-based */
+    set_seg_base(gdt_base, 0x10, rm_args.rm_base);
+    set_seg_base(gdt_base, 0x18, rm_args.rm_base);
+
+#if __SIZEOF_POINTER__ == 4
+    asm volatile ("lgdtl %0"::"m" (*(char *)gdt_base));
+#elif __SIZEOF_POINTER__ == 8
+    asm volatile ("lgdt %0"::"m" (*(char *)gdt_base));
+#else
+#error "unsupported architecture"
+#endif
+
+    *(uint32_t *) rm_args.rm_pmjmp += delta;
+    *(uint16_t *) rm_args.rm_rmjmp += delta >> 4;
+
+    rm_args.rm_handle_interrupt += delta;
+
+    sti();
+}
+
+static uint8_t checksum_buf(const void *buf, int count)
+{
+    const uint8_t *p = buf;
+    uint8_t c = 0;
+
+    while (count--)
+	c += *p++;
+
+    return c;
+}
+
+static int stack_needed(void)
+{
+  const unsigned int min_stack = 128;	/* Minimum stack size */
+  const unsigned int def_stack = 512;	/* Default stack size */
+  unsigned int v = 0;
+  const char *p;
+
+  if (CMD_HASDATA(p = getcmditem("stack")))
+    v = atou(p);
+
+  if (!v)
+    v = def_stack;
+
+  if (v < min_stack)
+    v = min_stack;
+
+  return v;
+}
+
+/*
+ * Set max memory by reservation
+ * Adds reservations to data in INT15h to prevent access to the top of RAM
+ * if there's any above the point specified.
+ */
+void setmaxmem(unsigned long long restop_ull)
+{
+    uint32_t restop;
+    struct e820range *ep;
+    const int int15restype = 2;
+
+    /* insertrange() works on uint32_t */
+    restop = min(restop_ull, UINT32_MAX);
+    /* printf("  setmaxmem  '%08x%08x'  => %08x\n",
+	(unsigned int)(restop_ull>>32), (unsigned int)restop_ull, restop); */
+
+    for (ep = ranges; ep->type != -1U; ep++) {
+	if (ep->type == 1) {	/* Only if available */
+	    if (ep->start >= restop) {
+		/* printf("  %08x -> 2\n", ep->start); */
+		ep->type = int15restype;
+	    } else if (ep[1].start > restop) {
+		/* printf("  +%08x =2; cut %08x\n", restop, ep->start); */
+		insertrange(restop, (ep[1].start - restop), int15restype);
+	    }
+	}
+    }
+    parse_mem();
+}
+
+struct real_mode_args rm_args;
+
+/*
+ * Actual setup routine
+ * Returns the drive number (which is then passed in %dl to the
+ * called routine.)
+ */
+void setup(const struct real_mode_args *rm_args_ptr)
+{
+    unsigned int bin_size;
+    char *memdisk_hook;
+    struct memdisk_header *hptr;
+    struct patch_area *pptr;
+    struct mBFT *mbft;
+    uint16_t driverseg;
+    uint32_t driverptr, driveraddr;
+    uint16_t dosmem_k;
+    uint32_t stddosmem;
+    const struct geometry *geometry;
+    unsigned int total_size;
+    unsigned int cmdline_len, stack_len, e820_len;
+    const struct edd4_bvd *bvd;
+    const struct edd4_bootcat *boot_cat = 0;
+    com32sys_t regs;
+    uint32_t ramdisk_image, ramdisk_size;
+    uint32_t boot_base, rm_base;
+    int bios_drives;
+    int do_edd = 1;		/* 0 = no, 1 = yes, default is yes */
+    int do_eltorito = 0;	/* default is no */
+    int no_bpt;			/* No valid BPT presented */
+    uint32_t boot_seg = 0;	/* Meaning 0000:7C00 */
+    uint32_t boot_len = 512;	/* One sector */
+    const char *p;
+
+    /* We need to copy the rm_args into their proper place */
+    memcpy(&rm_args, rm_args_ptr, sizeof rm_args);
+    sti();			/* ... then interrupts are safe */
+
+    /* Show signs of life */
+    printf("%s  %s\n", memdisk_version, copyright);
+
+    if (!shdr->ramdisk_image || !shdr->ramdisk_size)
+	die("MEMDISK: No ramdisk image specified!\n");
+
+    ramdisk_image = shdr->ramdisk_image;
+    ramdisk_size = shdr->ramdisk_size;
+
+    e820map_init();		/* Initialize memory data structure */
+    get_mem();			/* Query BIOS for memory map */
+    parse_mem();		/* Parse memory map */
+
+    printf("Ramdisk at 0x%08x, length 0x%08x\n", ramdisk_image, ramdisk_size);
+
+    unzip_if_needed(&ramdisk_image, &ramdisk_size);
+
+    geometry = get_disk_image_geometry(ramdisk_image, ramdisk_size);
+
+    if (getcmditem("edd") != CMD_NOTFOUND ||
+	getcmditem("ebios") != CMD_NOTFOUND)
+	do_edd = 1;
+    else if (getcmditem("noedd") != CMD_NOTFOUND ||
+	     getcmditem("noebios") != CMD_NOTFOUND ||
+	     getcmditem("cbios") != CMD_NOTFOUND)
+	do_edd = 0;
+    else
+	do_edd = (geometry->driveno & 0x80) ? 1 : 0;
+
+    if (getcmditem("iso") != CMD_NOTFOUND) {
+	do_eltorito = 1;
+	do_edd = 1;		/* Mandatory */
+    }
+
+    /* Choose the appropriate installable memdisk hook */
+    if (do_eltorito) {
+	if (geometry->sector_shift == 11) {
+	    bin_size = (int)&_binary_memdisk_iso_2048_bin_size;
+	    memdisk_hook = (char *)&_binary_memdisk_iso_2048_bin_start;
+	} else {
+	    bin_size = (int)&_binary_memdisk_iso_512_bin_size;
+	    memdisk_hook = (char *)&_binary_memdisk_iso_512_bin_start;
+	}
+    } else {
+	if (do_edd) {
+	    bin_size = (int)&_binary_memdisk_edd_512_bin_size;
+	    memdisk_hook = (char *)&_binary_memdisk_edd_512_bin_start;
+	} else {
+	    bin_size = (int)&_binary_memdisk_chs_512_bin_size;
+	    memdisk_hook = (char *)&_binary_memdisk_chs_512_bin_start;
+	}
+    }
+
+    /* Reserve the ramdisk memory */
+    insertrange(ramdisk_image, ramdisk_size, 2);
+    parse_mem();		/* Recompute variables */
+
+    /* Figure out where it needs to go */
+    hptr = (struct memdisk_header *)memdisk_hook;
+    pptr = (struct patch_area *)(memdisk_hook + hptr->patch_offs);
+
+    dosmem_k = rdz_16(BIOS_BASEMEM);
+    pptr->mdi.olddosmem = dosmem_k;
+    stddosmem = dosmem_k << 10;
+    /* If INT 15 E820 and INT 12 disagree, go with the most conservative */
+    if (stddosmem > dos_mem)
+	stddosmem = dos_mem;
+
+    pptr->driveno = geometry->driveno;
+    pptr->drivetype = geometry->type;
+    pptr->cylinders = geometry->c;	/* Possible precision loss */
+    pptr->heads = geometry->h;
+    pptr->sectors = geometry->s;
+    pptr->mdi.disksize = geometry->sectors;
+    pptr->mdi.diskbuf = ramdisk_image + geometry->offset;
+    pptr->mdi.sector_shift = geometry->sector_shift;
+    pptr->statusptr = (geometry->driveno & 0x80) ? 0x474 : 0x441;
+
+    pptr->mdi.bootloaderid = shdr->type_of_loader;
+
+    pptr->configflags = CONFIG_SAFEINT;	/* Default */
+    /* Set config flags */
+    if (getcmditem("ro") != CMD_NOTFOUND) {
+	pptr->configflags |= CONFIG_READONLY;
+    }
+    if (getcmditem("raw") != CMD_NOTFOUND) {
+	pptr->configflags &= ~CONFIG_MODEMASK;
+	pptr->configflags |= CONFIG_RAW;
+    }
+    if (getcmditem("bigraw") != CMD_NOTFOUND) {
+	pptr->configflags &= ~CONFIG_MODEMASK;
+	pptr->configflags |= CONFIG_BIGRAW | CONFIG_RAW;
+    }
+    if (getcmditem("int") != CMD_NOTFOUND) {
+	pptr->configflags &= ~CONFIG_MODEMASK;
+	/* pptr->configflags |= 0; */
+    }
+    if (getcmditem("safeint") != CMD_NOTFOUND) {
+	pptr->configflags &= ~CONFIG_MODEMASK;
+	pptr->configflags |= CONFIG_SAFEINT;
+    }
+
+    printf("Disk is %s%d, %u%s K, C/H/S = %u/%u/%u (%s/%s), EDD %s, %s\n",
+	   (geometry->driveno & 0x80) ? "hd" : "fd",
+	   geometry->driveno & 0x7f,
+	   geometry->sectors >> 1,
+	   (geometry->sectors & 1) ? ".5" : "",
+	   geometry->c, geometry->h, geometry->s,
+	   geometry->hsrc, geometry->ssrc,
+	   do_edd ? "on" : "off",
+	   pptr->configflags & CONFIG_READONLY ? "ro" : "rw");
+
+    puts("Using ");
+    switch (pptr->configflags & CONFIG_MODEMASK) {
+    case 0:
+	puts("standard INT 15h");
+	break;
+    case CONFIG_SAFEINT:
+	puts("safe INT 15h");
+	break;
+    case CONFIG_RAW:
+	puts("raw");
+	break;
+    case CONFIG_RAW | CONFIG_BIGRAW:
+	puts("big real mode raw");
+	break;
+    default:
+	printf("unknown %#x", pptr->configflags & CONFIG_MODEMASK);
+	break;
+    }
+    puts(" access to high memory\n");
+
+    /* Set up a drive parameter table */
+    if (geometry->driveno & 0x80) {
+	/* Hard disk */
+	pptr->dpt.hd.max_cyl = geometry->c - 1;
+	pptr->dpt.hd.max_head = geometry->h - 1;
+	pptr->dpt.hd.ctrl = (geometry->h > 8) ? 0x08 : 0;
+    } else {
+	/* Floppy - most of these fields are bogus and mimic
+	   a 1.44 MB floppy drive */
+	pptr->dpt.fd.specify1 = 0xdf;
+	pptr->dpt.fd.specify2 = 0x02;
+	pptr->dpt.fd.delay = 0x25;
+	pptr->dpt.fd.sectors = geometry->s;
+	pptr->dpt.fd.bps = 0x02;
+	pptr->dpt.fd.isgap = 0x12;
+	pptr->dpt.fd.dlen = 0xff;
+	pptr->dpt.fd.fgap = 0x6c;
+	pptr->dpt.fd.ffill = 0xf6;
+	pptr->dpt.fd.settle = 0x0f;
+	pptr->dpt.fd.mstart = 0x05;
+	pptr->dpt.fd.maxtrack = geometry->c - 1;
+	pptr->dpt.fd.cmos = geometry->type > 5 ? 5 : geometry->type;
+
+	pptr->dpt.fd.old_fd_dpt = rdz_32(BIOS_INT1E);
+    }
+
+    /* Set up an EDD drive parameter table */
+    if (do_edd) {
+	pptr->edd_dpt.sectors = geometry->sectors;
+	/* The EDD spec has this as <= 15482880  sectors (1024x240x63);
+	   this seems to make very little sense.  Try for something saner. */
+	if (geometry->c <= 1024 && geometry->h <= 255 && geometry->s <= 63) {
+	    pptr->edd_dpt.c = geometry->c;
+	    pptr->edd_dpt.h = geometry->h;
+	    pptr->edd_dpt.s = geometry->s;
+	    /* EDD-4 states that invalid geometry should be returned
+	     * for INT 0x13, AH=0x48 "EDD Get Disk Parameters" call on an
+	     * El Torito ODD.  Check for 2048-byte sector size
+	     */
+	    if (geometry->sector_shift != 11)
+		pptr->edd_dpt.flags |= 0x0002;	/* Geometry valid */
+	}
+	if (!(geometry->driveno & 0x80)) {
+	    /* Floppy drive.  Mark it as a removable device with
+	       media change notification; media is present. */
+	    pptr->edd_dpt.flags |= 0x0014;
+	}
+
+	pptr->edd_dpt.devpath[0] = pptr->mdi.diskbuf;
+	pptr->edd_dpt.chksum = -checksum_buf(&pptr->edd_dpt.dpikey, 73 - 30);
+    }
+
+    if (do_eltorito) {
+	bvd = (struct edd4_bvd *)(ramdisk_image + 17 * 2048);
+	boot_cat =
+	    (struct edd4_bootcat *)(ramdisk_image + bvd->boot_cat * 2048);
+	pptr->cd_pkt.type = boot_cat->initial_entry.media_type;	/* Cheat */
+	pptr->cd_pkt.driveno = geometry->driveno;
+	pptr->cd_pkt.start = boot_cat->initial_entry.load_block;
+	boot_seg = pptr->cd_pkt.load_seg = boot_cat->initial_entry.load_seg;
+	pptr->cd_pkt.sect_count = boot_cat->initial_entry.sect_count;
+	boot_len = pptr->cd_pkt.sect_count * 512;
+	pptr->cd_pkt.geom1 = (uint8_t)(pptr->cylinders) & 0xFF;
+	pptr->cd_pkt.geom2 =
+	    (uint8_t)(pptr->sectors) | (uint8_t)((pptr->cylinders >> 2) & 0xC0);
+	pptr->cd_pkt.geom3 = (uint8_t)(pptr->heads);
+    }
+
+    if ((p = getcmditem("mem")) != CMD_NOTFOUND) {
+	setmaxmem(suffix_number(p));
+    }
+
+    /* The size is given by hptr->total_size plus the size of the E820
+       map -- 12 bytes per range; we may need as many as 2 additional
+       ranges (each insertrange() can worst-case turn 1 area into 3)
+       plus the terminating range, over what nranges currently show. */
+    total_size = hptr->total_size;	/* Actual memdisk code */
+    e820_len = (nranges + 3) * sizeof(ranges[0]);
+    total_size += e820_len;		/* E820 memory ranges */
+    cmdline_len = strlen(shdr->cmdline) + 1;
+    total_size += cmdline_len;		/* Command line */
+    stack_len = stack_needed();
+    total_size += stack_len;		/* Stack */
+    printf("Code %u, meminfo %u, cmdline %u, stack %u\n",
+	   hptr->total_size, e820_len, cmdline_len, stack_len);
+    printf("Total size needed = %u bytes, allocating %uK\n",
+	   total_size, (total_size + 0x3ff) >> 10);
+
+    if (total_size > dos_mem)
+	die("MEMDISK: Insufficient low memory\n");
+
+    driveraddr = stddosmem - total_size;
+    driveraddr &= ~0x3FF;
+
+    printf("Old dos memory at 0x%05x (map says 0x%05x), loading at 0x%05x\n",
+	   stddosmem, dos_mem, driveraddr);
+
+    /* Reserve this range of memory */
+    wrz_16(BIOS_BASEMEM, driveraddr >> 10);
+    insertrange(driveraddr, dos_mem - driveraddr, 2);
+    parse_mem();
+
+    pptr->mem1mb = low_mem >> 10;
+    pptr->mem16mb = high_mem >> 16;
+    if (low_mem == (15 << 20)) {
+	/* lowmem maxed out */
+	uint32_t int1588mem = (high_mem >> 10) + (low_mem >> 10);
+	pptr->memint1588 = (int1588mem > 0xffff) ? 0xffff : int1588mem;
+    } else {
+	pptr->memint1588 = low_mem >> 10;
+    }
+
+    printf("1588: 0x%04x  15E801: 0x%04x 0x%04x\n",
+	   pptr->memint1588, pptr->mem1mb, pptr->mem16mb);
+
+    driverseg = driveraddr >> 4;
+    driverptr = driverseg << 16;
+
+    /* Anything beyond the end is for the stack */
+    pptr->mystack = (uint16_t) (stddosmem - driveraddr);
+
+    pptr->mdi.oldint13.uint32 = rdz_32(BIOS_INT13);
+    pptr->mdi.oldint15.uint32 = rdz_32(BIOS_INT15);
+
+    /* Adjust the E820 table: if there are null ranges (type 0)
+       at the end, change them to type end of list (-1).
+       This is necessary for the driver to be able to report end
+       of list correctly. */
+    while (nranges && ranges[nranges - 1].type == 0) {
+	ranges[--nranges].type = -1;
+    }
+
+    if (getcmditem("nopassany") != CMD_NOTFOUND) {
+	printf("nopassany specified - we're the only drive of any kind\n");
+	bios_drives = 0;
+	pptr->drivecnt = 0;
+	no_bpt = 1;
+	pptr->mdi.oldint13.uint32 = driverptr + hptr->iret_offs;
+	wrz_8(BIOS_EQUIP, rdz_8(BIOS_EQUIP) & ~0xc1);
+	wrz_8(BIOS_HD_COUNT, 0);
+    } else if (getcmditem("nopass") != CMD_NOTFOUND) {
+	printf("nopass specified - we're the only drive\n");
+	bios_drives = 0;
+	pptr->drivecnt = 0;
+	no_bpt = 1;
+    } else {
+	/* Query drive parameters of this type */
+	memset(&regs, 0, sizeof regs);
+	regs.es = 0;
+	regs.eax.b[1] = 0x08;
+	regs.edx.b[0] = geometry->driveno & 0x80;
+	intcall(0x13, &regs, &regs);
+
+	/* Note: per suggestion from the Interrupt List, consider
+	   INT 13 08 to have failed if the sector count in CL is zero. */
+	if ((regs.eflags.l & 1) || !(regs.ecx.b[0] & 0x3f)) {
+	    printf("INT 13 08: Failure, assuming this is the only drive\n");
+	    pptr->drivecnt = 0;
+	    no_bpt = 1;
+	} else {
+	    printf("INT 13 08: Success, count = %u, BPT = %04x:%04x\n",
+		   regs.edx.b[0], regs.es, regs.edi.w[0]);
+	    pptr->drivecnt = regs.edx.b[0];
+	    no_bpt = !(regs.es | regs.edi.w[0]);
+	}
+
+	/* Compare what INT 13h returned with the appropriate equipment byte */
+	if (geometry->driveno & 0x80) {
+	    bios_drives = rdz_8(BIOS_HD_COUNT);
+	} else {
+	    uint8_t equip = rdz_8(BIOS_EQUIP);
+
+	    if (equip & 1)
+		bios_drives = (equip >> 6) + 1;
+	    else
+		bios_drives = 0;
+	}
+
+	if (pptr->drivecnt > bios_drives) {
+	    printf("BIOS equipment byte says count = %d, go with that\n",
+		   bios_drives);
+	    pptr->drivecnt = bios_drives;
+	}
+    }
+
+    /* Add ourselves to the drive count */
+    pptr->drivecnt++;
+
+    /* Discontiguous drive space.  There is no really good solution for this. */
+    if (pptr->drivecnt <= (geometry->driveno & 0x7f))
+	pptr->drivecnt = (geometry->driveno & 0x7f) + 1;
+
+    /* Probe for contiguous range of BIOS drives starting with driveno */
+    pptr->driveshiftlimit = probe_drive_range(geometry->driveno) + 1;
+    if ((pptr->driveshiftlimit & 0x80) != (geometry->driveno & 0x80))
+	printf("We lost the last drive in our class of drives.\n");
+    printf("Drive probing gives drive shift limit: 0x%02x\n",
+	pptr->driveshiftlimit);
+
+    /* Pointer to the command line */
+    pptr->mdi.cmdline.seg_off.offset = bin_size + (nranges + 1) * sizeof(ranges[0]);
+    pptr->mdi.cmdline.seg_off.segment = driverseg;
+
+    /* Copy driver followed by E820 table followed by command line */
+    {
+	unsigned char *dpp = (unsigned char *)(driverseg << 4);
+
+	/* Adjust these pointers to point to the installed image */
+	/* Careful about the order here... the image isn't copied yet! */
+	pptr = (struct patch_area *)(dpp + hptr->patch_offs);
+	hptr = (struct memdisk_header *)dpp;
+
+	/* Actually copy to low memory */
+	dpp = mempcpy(dpp, memdisk_hook, bin_size);
+	dpp = mempcpy(dpp, ranges, (nranges + 1) * sizeof(ranges[0]));
+	dpp = mempcpy(dpp, shdr->cmdline, cmdline_len);
+    }
+
+    /* Note the previous INT 13h hook in the "safe hook" structure */
+    hptr->safe_hook.old_hook.uint32 = pptr->mdi.oldint13.uint32;
+
+    /* Re-fill the "safe hook" mBFT field with the physical address */
+    mbft = (struct mBFT *)(((const char *)hptr) + hptr->safe_hook.mbft);
+    hptr->safe_hook.mbft = (size_t)mbft;
+
+    /* Update various BIOS magic data areas (gotta love this shit) */
+
+    if (geometry->driveno & 0x80) {
+	/* Update BIOS hard disk count */
+	uint8_t nhd = pptr->drivecnt;
+
+	if (nhd > 128)
+	    nhd = 128;
+
+	if (!do_eltorito)
+	    wrz_8(BIOS_HD_COUNT, nhd);
+    } else {
+	/* Update BIOS floppy disk count */
+	uint8_t equip = rdz_8(BIOS_EQUIP);
+	uint8_t nflop = pptr->drivecnt;
+
+	if (nflop > 4)		/* Limit of equipment byte */
+	    nflop = 4;
+
+	equip &= 0x3E;
+	if (nflop)
+	    equip |= ((nflop - 1) << 6) | 0x01;
+
+	wrz_8(BIOS_EQUIP, equip);
+
+	/* Install DPT pointer if this was the only floppy */
+	if (getcmditem("dpt") != CMD_NOTFOUND ||
+	    ((nflop == 1 || no_bpt) && getcmditem("nodpt") == CMD_NOTFOUND)) {
+	    /* Do install a replacement DPT into INT 1Eh */
+	    pptr->mdi.dpt_ptr =
+		hptr->patch_offs + offsetof(struct patch_area, dpt);
+	}
+    }
+
+    /* Complete the mBFT */
+    mbft->acpi.signature[0] = 'm';	/* "mBFT" */
+    mbft->acpi.signature[1] = 'B';
+    mbft->acpi.signature[2] = 'F';
+    mbft->acpi.signature[3] = 'T';
+    mbft->safe_hook = (size_t)&hptr->safe_hook;
+    mbft->acpi.checksum = -checksum_buf(mbft, mbft->acpi.length);
+
+    /* Install the interrupt handlers */
+    printf("old: int13 = %08x  int15 = %08x  int1e = %08x\n",
+	   rdz_32(BIOS_INT13), rdz_32(BIOS_INT15), rdz_32(BIOS_INT1E));
+
+    wrz_32(BIOS_INT13, driverptr + hptr->int13_offs);
+    wrz_32(BIOS_INT15, driverptr + hptr->int15_offs);
+    if (pptr->mdi.dpt_ptr)
+	wrz_32(BIOS_INT1E, driverptr + pptr->mdi.dpt_ptr);
+
+    printf("new: int13 = %08x  int15 = %08x  int1e = %08x\n",
+	   rdz_32(BIOS_INT13), rdz_32(BIOS_INT15), rdz_32(BIOS_INT1E));
+
+    /* Figure out entry point */
+    if (!boot_seg) {
+	boot_base = 0x7c00;
+	shdr->sssp = 0x7c00;
+	shdr->csip = 0x7c00;
+    } else {
+	boot_base = boot_seg << 4;
+	shdr->sssp = boot_seg << 16;
+	shdr->csip = boot_seg << 16;
+    }
+
+    /* Relocate the real-mode code to below the stub */
+    rm_base = (driveraddr - rm_args.rm_size) & ~15;
+    if (rm_base < boot_base + boot_len)
+	die("MEMDISK: bootstrap too large to load\n");
+
+    relocate_rm_code(rm_base);
+
+    /* Reboot into the new "disk" */
+    puts("Loading boot sector... ");
+
+    memcpy((void *)boot_base,
+	   (char *)pptr->mdi.diskbuf + geometry->boot_lba * 512,
+	   boot_len);
+
+    if (getcmditem("pause") != CMD_NOTFOUND) {
+	puts("press any key to boot... ");
+	memset(&regs, 0, sizeof regs);
+	regs.eax.w[0] = 0;
+	intcall(0x16, &regs, NULL);
+    }
+
+    puts("booting...\n");
+
+    /* On return the assembly code will jump to the boot vector */
+    shdr->esdi = pnp_install_check();
+    shdr->edx = geometry->driveno;
+}
+
Index: bootcd/isolinux/syslinux-6.03/memdisk/start32.S
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/start32.S	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/start32.S	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,107 @@
+/* -----------------------------------------------------------------------
+ *
+ *   Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Simple stub to get us to the right point in the 32-bit code;
+ * this module must be linked first
+ */
+
+	.section ".init", "ax"
+	.globl _start
+_start:
+	/* Zero the bss */
+	cld
+	movl	$__bss_start, %edi
+	movl	$__bss_end, %ecx
+	subl	%edi, %ecx
+	xorl	%eax, %eax
+	shrl	$2, %ecx
+	rep ; stosl
+
+	/* Set up the protected-mode IDT and the interrupt jump buffers */
+	movl	$idt, %edi
+	movl	$ijb, %eax
+	movl	$0xee000000, %ebx	/* Interrupt gate */
+	movw	%cs, %bx		/* Target segment */
+
+	/* Make the IDT */
+	movl	$256, %ecx
+1:
+	stosl
+	stosl
+	movl	%ebx, -6(%edi)
+	addl	$8, %eax
+	loop	1b
+
+	/*
+	 * Each entry in the interrupt jump buffer contains the following
+	 * instructions:
+	 *
+	 * 60		pushal
+	 * b0xx		movb $xx, %al		# interrupt number
+	 * e9xxxxxxxx	jmp handle_interrupt
+	 */
+	movl	$0xe900b060, %eax
+	movl	$256, %ecx
+1:
+	movl	%eax, (%edi)
+	addl	$(1 << 16), %eax
+	movl	$handle_interrupt-8, %edx
+	subl	%edi, %edx
+	movl	%edx, 4(%edi)
+	addl	$8, %edi
+	loop	1b
+
+#if __SIZEOF_POINTER__ == 4
+	lidtl	idt_ptr
+#elif __SIZEOF_POINTER__ == 8
+	lidt	idt_ptr
+#else
+#error "unsupported architecture"
+#endif
+	
+	/* Save arguments, switch stacks */
+	movl	%esp, %eax		/* Pointer to arguments */
+	movl	$__stack_end, %esp
+	
+	call	setup
+	jmp	*(rm_args)		/* First argument is return */
+
+	.section ".text","ax"
+	.globl	intcall
+	.type	intcall, @function
+intcall:
+	jmp	*(rm_args+1*4)		/* Intcall is argument 1 */
+	.size	intcall, .-intcall
+
+	.type	handle_interrupt, @function
+handle_interrupt:
+	jmp	*(rm_args+4*4)		/* Interrupt pointer is argument 4 */
+	.size	handle_interrupt, .-handle_interrupt
+
+	.section ".rodata","a"
+idt_ptr:
+	.word	8*256-1
+	.long	idt
+	.word	0
+
+	.section ".bss.large","aw"
+	.balign 2048
+idt:
+	.space	8*256
+ijb:
+	.space	8*256
+
+__stack:
+	.space	65536
+__stack_end:
Index: bootcd/isolinux/syslinux-6.03/memdisk/strntoumax.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/strntoumax.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/strntoumax.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,1 @@
+#include "../com32/lib/strntoumax.c"
Index: bootcd/isolinux/syslinux-6.03/memdisk/strtoull.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/strtoull.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/strtoull.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,1 @@
+#include "../com32/lib/strtoull.c"
Index: bootcd/isolinux/syslinux-6.03/memdisk/strtox.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/strtox.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/strtox.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,1 @@
+#include "../com32/lib/strtox.c"
Index: bootcd/isolinux/syslinux-6.03/memdisk/suffix_number.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/suffix_number.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/suffix_number.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,1 @@
+#include "../com32/lib/suffix_number.c"
Index: bootcd/isolinux/syslinux-6.03/memdisk/testdata1
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/testdata1	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/testdata1	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,13 @@
+0000000000000000 000000000009bc00 1
+000000000009bc00 0000000000004400 2
+00000000000e9800 0000000000016800 2
+0000000000100000 0000000006ee0000 1
+0000000006fe0000 000000000000fc00 3
+0000000006fefc00 0000000000000400 4
+0000000006ff0000 0000000000002000 2
+0000000006ff2000 000000000000e000 1
+0000000007000000 0000000000100000 2
+00000000fff00000 0000000000100000 2
+
+0000000000586000 0000000000168000 2
+000000000009ba00 0000000000000200 2
Index: bootcd/isolinux/syslinux-6.03/memdisk/testdata2
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/testdata2	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/testdata2	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,10 @@
+0000000000000000 000000000009bc00 1
+000000000009bc00 0000000000004400 2
+00000000000e9800 0000000000016800 2
+0000000000100000 0000000006ee0000 1
+0000000006fe0000 000000000000fc00 3
+0000000006fefc00 0000000000000400 4
+0000000006ff0000 0000000000002000 2
+0000000006ff2000 000000000000e000 1
+0000000007000000 0000000000100000 2
+00000000fff00000 0000000000100000 2
Index: bootcd/isolinux/syslinux-6.03/memdisk/testdata3
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/testdata3	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/testdata3	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,14 @@
+0000000000000000 000000000009bc00 1
+000000000009bc00 0000000000004400 2
+00000000000e9800 0000000000016800 2
+0000000000100000 0000000006ee0000 1
+0000000006fe0000 000000000000fc00 3
+0000000006fefc00 0000000000000400 4
+0000002000000000 0000001000000000 1
+0000000006ff0000 0000000000002000 2
+0000000006ff2000 000000000000e000 1
+0000000007000000 0000000000100000 2
+00000000fff00000 0000000000100000 2
+
+0000000000586000 0000000000168000 2
+000000000009ba00 0000000000000200 2
Index: bootcd/isolinux/syslinux-6.03/memdisk/unzip.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/unzip.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/unzip.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,391 @@
+/*
+ * unzip.c
+ *
+ * This is a collection of several routines from gzip-1.0.3
+ * adapted for Linux.
+ *
+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ * puts by Nick Holloway 1993, better puts by Martin Mares 1995
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+ *
+ * Adapted for MEMDISK by H. Peter Anvin, April 2003
+ */
+
+#include <stdint.h>
+#include "memdisk.h"
+#include "conio.h"
+
+#undef DEBUG			/* Means something different for this file */
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+#define STATIC static
+
+#define memzero(s, n)     memset ((s), 0, (n))
+
+typedef uint8_t uch;
+typedef uint16_t ush;
+typedef uint32_t ulg;
+
+#define WSIZE 0x8000		/* Window size must be at least 32k, */
+				/* and a power of two */
+
+static uch *inbuf;		/* input pointer */
+static uch window[WSIZE];	/* sliding output window buffer */
+
+static unsigned insize;		/* total input bytes read */
+static unsigned inbytes;	/* valid bytes in inbuf */
+static unsigned outcnt;		/* bytes in output buffer */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01	/* bit 0 set: file probably ASCII text */
+#define CONTINUATION 0x02	/* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04	/* bit 2 set: extra field present */
+#define ORIG_NAME    0x08	/* bit 3 set: original file name present */
+#define COMMENT      0x10	/* bit 4 set: file comment present */
+#define ENCRYPTED    0x20	/* bit 5 set: file is encrypted */
+#define RESERVED     0xC0	/* bit 6,7:   reserved */
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+static int fill_inbuf(void);
+static void flush_window(void);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+
+static ulg crc_32_tab[256];
+
+/* Get byte from input buffer */
+static inline uch get_byte(void)
+{
+    if (inbytes) {
+	uch b = *inbuf++;
+	inbytes--;
+	return b;
+    } else {
+	return fill_inbuf();	/* Input buffer underrun */
+    }
+}
+
+/* Unget byte from input buffer */
+static inline void unget_byte(void)
+{
+    inbytes++;
+    inbuf--;
+}
+
+static ulg bytes_out = 0;	/* Number of bytes output */
+static uch *output_data;	/* Output data pointer */
+static ulg output_size;		/* Number of output bytes expected */
+
+static void *malloc(int size);
+static void free(void *where);
+
+static ulg free_mem_ptr, free_mem_end_ptr;
+
+#include "inflate.c"
+
+static void *malloc(int size)
+{
+    void *p;
+
+    if (size < 0)
+	error("malloc error");
+
+    free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
+
+    p = (void *)free_mem_ptr;
+    free_mem_ptr += size;
+
+    if (free_mem_ptr >= free_mem_end_ptr)
+	error("out of memory");
+
+    return p;
+}
+
+static void free(void *where)
+{
+    /* Don't care */
+    (void)where;
+}
+
+static void gzip_mark(void **ptr)
+{
+    *ptr = (void *)free_mem_ptr;
+}
+
+static void gzip_release(void **ptr)
+{
+    free_mem_ptr = (long)*ptr;
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf(void)
+{
+    /* This should never happen.  We have already pointed the algorithm
+       to all the data we have. */
+    die("failed\nDecompression error: ran out of input data\n");
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void flush_window(void)
+{
+    ulg c = crc;		/* temporary variable */
+    unsigned n;
+    uch *in, *out, ch;
+
+    if (bytes_out + outcnt > output_size)
+	error("output buffer overrun");
+
+    in = window;
+    out = output_data;
+    for (n = 0; n < outcnt; n++) {
+	ch = *out++ = *in++;
+	c = crc_32_tab[(c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    output_data = out;
+    bytes_out += (ulg) outcnt;
+    outcnt = 0;
+}
+
+static void error(char *x)
+{
+    die("failed\nDecompression error: %s\n", x);
+}
+
+/* GZIP header */
+struct gzip_header {
+    uint16_t magic;
+    uint8_t method;
+    uint8_t flags;
+    uint32_t timestamp;
+    uint8_t extra_flags;
+    uint8_t os_type;
+} __attribute__ ((packed));
+/* (followed by optional and variable length "extra", "original name",
+   and "comment" fields) */
+
+struct gzip_trailer {
+    uint32_t crc;
+    uint32_t dbytes;
+} __attribute__ ((packed));
+
+/* PKZIP header.  See
+ * <http://www.pkware.com/products/enterprise/white_papers/appnote.html>.
+ */
+struct pkzip_header {
+    uint32_t magic;
+    uint16_t version;
+    uint16_t flags;
+    uint16_t method;
+    uint16_t modified_time;
+    uint16_t modified_date;
+    uint32_t crc;
+    uint32_t zbytes;
+    uint32_t dbytes;
+    uint16_t filename_len;
+    uint16_t extra_len;
+} __attribute__ ((packed));
+/* (followed by optional and variable length "filename" and "extra"
+   fields) */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01	/* bit 0 set: file probably ASCII text */
+#define CONTINUATION 0x02	/* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04	/* bit 2 set: extra field present */
+#define ORIG_NAME    0x08	/* bit 3 set: original file name present */
+#define COMMENT      0x10	/* bit 4 set: file comment present */
+#define ENCRYPTED    0x20	/* bit 5 set: file is encrypted */
+#define RESERVED     0xC0	/* bit 6,7:   reserved */
+
+/* pkzip flag byte */
+#define PK_ENCRYPTED     0x01	/* bit 0 set: file is encrypted */
+#define PK_DATADESC       0x08	/* bit 3 set: file has trailing "data
+				   descriptor" */
+#define PK_UNSUPPORTED    0xFFF0	/* All other bits must be zero */
+
+/* Return 0 if (indata, size) points to a ZIP file, and fill in
+   compressed data size, uncompressed data size, CRC, and offset of
+   data.
+
+   If indata is not a ZIP file, return -1. */
+int check_zip(void *indata, uint32_t size, uint32_t * zbytes_p,
+	      uint32_t * dbytes_p, uint32_t * orig_crc, uint32_t * offset_p)
+{
+    struct gzip_header *gzh = (struct gzip_header *)indata;
+    struct pkzip_header *pkzh = (struct pkzip_header *)indata;
+    uint32_t offset;
+
+    if (gzh->magic == 0x8b1f) {
+	struct gzip_trailer *gzt = indata + size - sizeof(struct gzip_trailer);
+	/* We only support method #8, DEFLATED */
+	if (gzh->method != 8) {
+	    error("gzip file uses invalid method");
+	    return -1;
+	}
+	if (gzh->flags & ENCRYPTED) {
+	    error("gzip file is encrypted; not supported");
+	    return -1;
+	}
+	if (gzh->flags & CONTINUATION) {
+	    error("gzip file is a continuation file; not supported");
+	    return -1;
+	}
+	if (gzh->flags & RESERVED) {
+	    error("gzip file has unsupported flags");
+	    return -1;
+	}
+	offset = sizeof(*gzh);
+	if (gzh->flags & EXTRA_FIELD) {
+	    /* Skip extra field */
+	    unsigned len = *(unsigned *)(indata + offset);
+	    offset += 2 + len;
+	}
+	if (gzh->flags & ORIG_NAME) {
+	    /* Discard the old name */
+	    uint8_t *p = indata;
+	    while (p[offset] != 0 && offset < size) {
+		offset++;
+	    }
+	    offset++;
+	}
+
+	if (gzh->flags & COMMENT) {
+	    /* Discard the comment */
+	    uint8_t *p = indata;
+	    while (p[offset] != 0 && offset < size) {
+		offset++;
+	    }
+	    offset++;
+	}
+
+	if (offset > size) {
+	    error("gzip file corrupt");
+	    return -1;
+	}
+	*zbytes_p = size - offset - sizeof(struct gzip_trailer);
+	*dbytes_p = gzt->dbytes;
+	*orig_crc = gzt->crc;
+	*offset_p = offset;
+	return 0;
+    } else if (pkzh->magic == 0x04034b50UL) {
+	/* Magic number matches pkzip file. */
+
+	offset = sizeof(*pkzh);
+	if (pkzh->flags & PK_ENCRYPTED) {
+	    error("pkzip file is encrypted; not supported");
+	    return -1;
+	}
+	if (pkzh->flags & PK_DATADESC) {
+	    error("pkzip file uses data_descriptor field; not supported");
+	    return -1;
+	}
+	if (pkzh->flags & PK_UNSUPPORTED) {
+	    error("pkzip file has unsupported flags");
+	    return -1;
+	}
+
+	/* We only support method #8, DEFLATED */
+	if (pkzh->method != 8) {
+	    error("pkzip file uses invalid method");
+	    return -1;
+	}
+	/* skip header */
+	offset = sizeof(*pkzh);
+	/* skip filename */
+	offset += pkzh->filename_len;
+	/* skip extra field */
+	offset += pkzh->extra_len;
+
+	if (offset + pkzh->zbytes > size) {
+	    error("pkzip file corrupt");
+	    return -1;
+	}
+
+	*zbytes_p = pkzh->zbytes;
+	*dbytes_p = pkzh->dbytes;
+	*orig_crc = pkzh->crc;
+	*offset_p = offset;
+	return 0;
+    } else {
+	/* Magic number does not match. */
+	return -1;
+    }
+
+    error("Internal error in check_zip");
+    return -1;
+}
+
+/*
+ * Decompress the image, trying to flush the end of it as close
+ * to end_mem as possible.  Return a pointer to the data block,
+ * and change datalen.
+ */
+extern void _end;
+
+static char heap[65536];
+
+void *unzip(void *indata, uint32_t zbytes, uint32_t dbytes,
+	    uint32_t orig_crc, void *target)
+{
+    /* Set up the heap; it is simply a chunk of bss memory */
+    free_mem_ptr     = (size_t)heap;
+    free_mem_end_ptr = (size_t)heap + sizeof heap;
+
+    /* Set up input buffer */
+    inbuf = indata;
+    /* Sometimes inflate() looks beyond the end of the compressed data,
+       but it always backs up before it is done.  So we give it 4 bytes
+       of slack. */
+    insize = inbytes = zbytes + 4;
+
+    /* Set up output buffer */
+    outcnt = 0;
+    output_data = target;
+    output_size = dbytes;
+    bytes_out = 0;
+
+    makecrc();
+    gunzip();
+
+    /* Verify that gunzip() consumed the entire input. */
+    if (inbytes != 4)
+	error("compressed data length error");
+
+    /* Check the uncompressed data length and CRC. */
+    if (bytes_out != dbytes)
+	error("uncompressed data length error");
+
+    if (orig_crc != CRC_VALUE)
+	error("crc error");
+
+    puts("ok\n");
+
+    return target;
+}
Index: bootcd/isolinux/syslinux-6.03/memdisk/version.h
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/version.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/version.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,25 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2002-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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * version.h
+ *
+ * MEMDISK version data
+ */
+
+#ifndef MEMDISK_VERSION_H
+#define MEMDISK_VERSION_H
+
+#define FIRSTYEAR "2001"
+#define COPYYEAR  "2008"
+
+#endif
Index: bootcd/isolinux/syslinux-6.03/memdisk/x86_64/memdisk.ld
===================================================================
--- bootcd/isolinux/syslinux-6.03/memdisk/x86_64/memdisk.ld	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/memdisk/x86_64/memdisk.ld	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,140 @@
+/* -----------------------------------------------------------------------
+ *   
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Linker script for MEMDISK
+ */
+
+/* Script for -z combreloc: combine and sort reloc sections */
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+EXTERN(_start)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0x100000;
+  PROVIDE (__executable_start = .);
+
+  .init           :
+  {
+    KEEP (*(.init))
+  } =0x90909090
+  .text           :
+  {
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0x90909090
+  .fini           :
+  {
+    KEEP (*(.fini))
+  } =0x90909090
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1        : { *(.rodata1) }
+
+  /* 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          :
+  {
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  PROVIDE (__ctors_end = .);
+  PROVIDE (__dtors_start = .);
+  .dtors          :
+  {
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  PROVIDE (__dtors_end = .);
+
+  /* Adjust the address for the data segment.  Avoid mixing code and
+     data within same 128-byte chunk. */
+  . = ALIGN(128);
+
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .;
+  PROVIDE (edata = .);
+  . = ALIGN(16);
+  .bss            :
+  {
+   __bss_start = .;
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.  */
+   . = ALIGN(4);
+   __bss_end = .;
+  }
+  _end = .;
+  PROVIDE (end = .);
+
+
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /DISCARD/ : { *(.note.GNU-stack) }
+}
