Index: bootcd/isolinux/syslinux-6.03/com32/sysdump/Makefile
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/sysdump/Makefile	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/sysdump/Makefile	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,62 @@
+## -----------------------------------------------------------------------
+##
+##   Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
+##   Copyright 2010 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 menu system
+##
+
+VPATH = $(SRC)
+include $(MAKEDIR)/elf.mk
+-include $(topdir)/version.mk
+
+LIBS	   = $(objdir)/com32/libupload/libcom32upload.a
+LNXLIBS	   = $(objdir)/com32/libutil/libutil_lnx.a
+
+CFLAGS += -I$(com32) -I$(topdir)
+
+MODULES	  = sysdump.c32
+TESTFILES =
+
+SRCS = $(wildcard $(SRC)/*.c)
+OBJS = $(subst $(SRC)/,,$(patsubst %.c,%.o,$(SRCS)))
+
+# The DATE is set on the make command line when building binaries for
+# official release.  Otherwise, substitute a hex string that is pretty much
+# guaranteed to be unique to be unique from build to build.
+ifndef HEXDATE
+HEXDATE := $(shell $(PERL) $(topdir)/now.pl $(SRCS) $(wildcard *.h))
+endif
+ifndef DATE
+DATE    := $(shell sh $(topdir)/gen-id.sh $(VERSION) $(HEXDATE))
+endif
+
+CFLAGS    += -DDATE='"$(DATE)"'
+
+all: $(MODULES) $(TESTFILES)
+
+sysdump.elf : $(OBJS) $(LIBS) $(C_LIBS)
+	$(LD) $(LDFLAGS) -o $@ $^
+
+tidy dist:
+	rm -f *.o *.lo *.a *.lst .*.d *.tmp
+
+clean: tidy
+	rm -f *.lnx
+
+spotless: clean
+	rm -f *.lss *.c32 *.com
+	rm -f *~ \#*
+
+install:
+
+-include .*.d
Index: bootcd/isolinux/syslinux-6.03/com32/sysdump/acpi.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/sysdump/acpi.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/sysdump/acpi.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,258 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2010 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Dump ACPI information
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "sysdump.h"
+#include "rbtree.h"
+
+struct acpi_rsdp {
+    uint8_t  magic[8];		/* "RSD PTR " */
+    uint8_t  csum;
+    char     oemid[6];
+    uint8_t  rev;
+    uint32_t rsdt_addr;
+    uint32_t len;
+    uint64_t xsdt_addr;
+    uint8_t  xcsum;
+    uint8_t  rsvd[3];
+};
+
+struct acpi_hdr {
+    char     sig[4];		/* Signature */
+    uint32_t len;
+    uint8_t  rev;
+    uint8_t  csum;
+    char     oemid[6];
+    char     oemtblid[16];
+    uint32_t oemrev;
+    uint32_t creatorid;
+    uint32_t creatorrev;
+};
+
+struct acpi_rsdt {
+    struct acpi_hdr hdr;
+    uint32_t entry[0];
+};
+
+struct acpi_xsdt {
+    struct acpi_hdr hdr;
+    uint64_t entry[0];
+};
+
+static struct rbtree *rb_types, *rb_addrs;
+
+static bool rb_has(struct rbtree **tree, uint64_t key)
+{
+    struct rbtree *node;
+
+    node = rb_search(*tree, key);
+    if (node && node->key == key)
+	return true;
+
+    node = malloc(sizeof *node);
+    if (node) {
+	node->key = key;
+	*tree = rb_insert(*tree, node);
+    }
+    return false;
+}
+
+static inline bool addr_ok(uint64_t addr)
+{
+    /* We can only handle 32-bit addresses for now... */
+    return addr <= 0xffffffff;
+}
+
+enum tbl_errs {
+    ERR_NONE,			/* No errors */
+    ERR_CSUM,			/* Invalid checksum */
+    ERR_SIZE,			/* Impossibly large table */
+    ERR_NOSIG			/* No signature */
+};
+
+static uint8_t checksum_range(const void *start, uint32_t size)
+{
+    const uint8_t *p = start;
+    uint8_t csum = 0;
+
+    while (size--)
+	csum += *p++;
+
+    return csum;
+}
+
+static enum tbl_errs is_valid_table(const void *ptr)
+{
+    const struct acpi_hdr *hdr = ptr;
+
+    if (hdr->sig[0] == 0)
+	return ERR_NOSIG;
+
+    if (hdr->len < 10 || hdr->len > (1 << 20)) {
+	/* Either insane or too large to dump */
+	return ERR_SIZE;
+    }
+
+    return checksum_range(hdr, hdr->len) == 0 ? ERR_NONE : ERR_CSUM;
+}
+
+static const struct acpi_rsdp *scan_for_rsdp(uint32_t base, uint32_t end)
+{
+    for (base &= ~15; base < end-20; base += 16) {
+	const struct acpi_rsdp *rsdp = (const struct acpi_rsdp *)base;
+
+	if (memcmp(rsdp->magic, "RSD PTR ", 8))
+	    continue;
+
+	if (checksum_range(rsdp, 20))
+	    continue;
+
+	if (rsdp->rev > 0) {
+	    if (base + rsdp->len >= end ||
+		checksum_range(rsdp, rsdp->len))
+		continue;
+	}
+
+	return rsdp;
+    }
+
+    return NULL;
+}
+
+static const struct acpi_rsdp *find_rsdp(void)
+{
+    uint32_t ebda;
+    const struct acpi_rsdp *rsdp;
+
+    ebda = (*(uint16_t *)0x40e) << 4;
+    if (ebda >= 0x70000 && ebda < 0xa0000) {
+	rsdp = scan_for_rsdp(ebda, ebda+1024);
+
+	if (rsdp)
+	    return rsdp;
+    }
+
+    return scan_for_rsdp(0xe0000, 0x100000);
+}
+
+static void dump_table(struct upload_backend *be,
+		       const char name[], const void *ptr, uint32_t len)
+{
+    char namebuf[64];
+    uint32_t name_key = *(uint32_t *)name;
+
+    if (rb_has(&rb_addrs, (size_t)ptr))
+	return;			/* Already dumped this table */
+
+    if (!rb_has(&rb_types, name_key)) {
+	snprintf(namebuf, sizeof namebuf, "acpi/%4.4s", name);
+	cpio_mkdir(be, namebuf);
+    }
+
+    snprintf(namebuf, sizeof namebuf, "acpi/%4.4s/%08x", name, (uint32_t)ptr);
+    cpio_hdr(be, MODE_FILE, len, namebuf);
+
+    write_data(be, ptr, len);
+}
+
+static void dump_rsdt(struct upload_backend *be, const struct acpi_rsdp *rsdp)
+{
+    const struct acpi_rsdt *rsdt;
+    uint32_t i, n;
+
+    rsdt = (const struct acpi_rsdt *)rsdp->rsdt_addr;
+
+    if (memcmp(rsdt->hdr.sig, "RSDT", 4) || is_valid_table(rsdt) > ERR_CSUM)
+	return;
+
+    dump_table(be, rsdt->hdr.sig, rsdt, rsdt->hdr.len);
+
+    if (rsdt->hdr.len < 36)
+	return;
+
+    n = (rsdt->hdr.len - 36) >> 2;
+
+    for (i = 0; i < n; i++) {
+	const struct acpi_hdr *hdr = (const struct acpi_hdr *)(rsdt->entry[i]);
+
+	if (is_valid_table(hdr) <= ERR_CSUM)
+	    dump_table(be, hdr->sig, hdr, hdr->len);
+    }
+}
+
+static void dump_xsdt(struct upload_backend *be, const struct acpi_rsdp *rsdp)
+{
+    const struct acpi_xsdt *xsdt;
+    uint32_t rsdp_len = rsdp->rev > 0 ? rsdp->len : 20;
+    uint32_t i, n;
+
+    if (rsdp_len < 34)
+	return;
+
+    if (!addr_ok(rsdp->xsdt_addr))
+	return;
+
+    xsdt = (const struct acpi_xsdt *)(size_t)rsdp->xsdt_addr;
+
+    if (memcmp(xsdt->hdr.sig, "XSDT", 4) || is_valid_table(xsdt) > ERR_CSUM)
+	return;
+
+    dump_table(be, xsdt->hdr.sig, xsdt, xsdt->hdr.len);
+
+    if (xsdt->hdr.len < 36)
+	return;
+
+    n = (xsdt->hdr.len - 36) >> 3;
+
+    for (i = 0; i < n; i++) {
+	const struct acpi_hdr *hdr;
+	if (addr_ok(xsdt->entry[i])) {
+	    hdr = (const struct acpi_hdr *)(size_t)(xsdt->entry[i]);
+
+	    if (is_valid_table(hdr) <= ERR_CSUM)
+		dump_table(be, hdr->sig, hdr, hdr->len);
+	}
+    }
+}
+
+void dump_acpi(struct upload_backend *be)
+{
+    const struct acpi_rsdp *rsdp;
+    uint32_t rsdp_len;
+
+    rsdp = find_rsdp();
+
+    printf("Dumping ACPI... ");
+
+    if (!rsdp)
+	return;			/* No ACPI information found */
+
+    cpio_mkdir(be, "acpi");
+
+    rsdp_len = rsdp->rev > 0 ? rsdp->len : 20;
+
+    dump_table(be, "RSDP", rsdp, rsdp_len);
+
+    dump_rsdt(be, rsdp);
+    dump_xsdt(be, rsdp);
+
+    rb_destroy(rb_types);
+    rb_destroy(rb_addrs);
+
+    printf("done.\n");
+}
Index: bootcd/isolinux/syslinux-6.03/com32/sysdump/cpuid.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/sysdump/cpuid.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/sysdump/cpuid.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,101 @@
+/*
+ * Dump CPUID information
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <com32.h>
+#include <sys/cpu.h>
+#include "sysdump.h"
+
+struct cpuid_data {
+    uint32_t eax, ebx, ecx, edx;
+};
+
+struct cpuid_info {
+    uint32_t eax, ecx;
+    struct cpuid_data data;
+};
+
+static void get_cpuid(uint32_t eax, uint32_t ecx, struct cpuid_data *data)
+{
+#if __SIZEOF_POINTER__ == 4
+    asm("pushl %%ebx ; cpuid ; movl %%ebx,%1 ; popl %%ebx"
+	: "=a" (data->eax), "=r" (data->ebx),
+	  "=c" (data->ecx), "=d" (data->edx)
+	: "a" (eax), "c" (ecx));
+#elif __SIZEOF_POINTER__ == 8
+        asm volatile("push %%rbx; cpuid; movl %%ebx, %1; pop %%rbx"
+            : "=a" (data->eax),
+              "=b" (data->ebx),
+              "=c" (data->ecx),
+              "=d" (data->edx)
+            : "a" (eax), "c" (ecx));
+#else
+#error "unsupported architecture"
+#endif
+}
+
+#define CPUID_CHUNK 128
+
+void dump_cpuid(struct upload_backend *be)
+{
+    struct cpuid_info *buf = NULL;
+    int nentry, nalloc;
+    uint32_t region;
+    struct cpuid_data base_leaf;
+    uint32_t base, leaf, count;
+    struct cpuid_data invalid_leaf;
+    struct cpuid_data data;
+
+    if (!cpu_has_eflag(EFLAGS_ID))
+	return;
+
+    printf("Dumping CPUID... ");
+
+    nentry = nalloc = 0;
+
+    /* Find out what the CPU returns for invalid leaves */
+    get_cpuid(0, 0, &base_leaf);
+    get_cpuid(base_leaf.eax+1, 0, &invalid_leaf);
+
+    for (region = 0 ; region <= 0xffff ; region++) {
+	base = region << 16;
+
+	get_cpuid(base, 0, &base_leaf);
+	if (region && !memcmp(&base_leaf, &invalid_leaf, sizeof base_leaf))
+	    continue;
+
+	if ((base_leaf.eax ^ base) & 0xffff0000)
+	    continue;
+
+	for (leaf = base ; leaf <= base_leaf.eax ; leaf++) {
+	    get_cpuid(leaf, 0, &data);
+	    count = 0;
+
+	    do {
+		if (nentry >= nalloc) {
+		    nalloc += CPUID_CHUNK;
+		    buf = realloc(buf, nalloc*sizeof *buf);
+		    if (!buf)
+			return;		/* FAILED */
+		}
+		buf[nentry].eax = leaf;
+		buf[nentry].ecx = count;
+		buf[nentry].data = data;
+		nentry++;
+		count++;
+
+		get_cpuid(leaf, count, &data);
+	    } while (memcmp(&data, &buf[nentry-1].data, sizeof data) &&
+		     (data.eax | data.ebx | data.ecx | data.edx));
+	}
+    }
+
+    if (nentry)
+	cpio_writefile(be, "cpuid", buf, nentry*sizeof *buf);
+    free(buf);
+
+    printf("done.\n");
+}
Index: bootcd/isolinux/syslinux-6.03/com32/sysdump/dmi.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/sysdump/dmi.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/sysdump/dmi.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,125 @@
+/*
+ * Dump DMI information in a way hopefully compatible with dmidecode
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "sysdump.h"
+
+struct dmi_header {
+    char signature[5];
+    uint8_t csum;
+    uint16_t tbllen;
+    uint32_t tbladdr;
+    uint16_t nstruc;
+    uint8_t revision;
+    uint8_t reserved;
+};
+
+struct smbios_header {
+    char signature[4];
+    uint8_t csum;
+    uint8_t len;
+    uint8_t major;
+    uint8_t minor;
+    uint16_t maxsize;
+    uint8_t revision;
+    uint8_t fmt[5];
+
+    struct dmi_header dmi;
+};
+
+static uint8_t checksum(const void *buf, size_t len)
+{
+    const uint8_t *p = buf;
+    uint8_t csum = 0;
+
+    while (len--)
+	csum += *p++;
+
+    return csum;
+}
+
+static bool is_old_dmi(size_t dptr)
+{
+    const struct dmi_header *dmi = (void *)dptr;
+
+    return !memcmp(dmi->signature, "_DMI_", 5) &&
+	!checksum(dmi, 0x0f);
+    return false;
+}
+
+static bool is_smbios(size_t dptr)
+{
+    const struct smbios_header *smb = (void *)dptr;
+
+    return !memcmp(smb->signature, "_SM_", 4) &&
+	!checksum(smb, smb->len) &&
+	is_old_dmi(dptr+16);
+}
+
+static void dump_smbios(struct upload_backend *be, size_t dptr)
+{
+    const struct smbios_header *smb = (void *)dptr;
+    struct smbios_header smx = *smb;
+    char filename[32];
+
+    snprintf(filename, sizeof filename, "dmi/%05x.%08x",
+	     dptr, smb->dmi.tbladdr);
+    cpio_hdr(be, MODE_FILE, smb->dmi.tbllen + 32, filename);
+
+    /*
+     * Adjust the address of the smbios table to be 32, to
+     * make dmidecode happy.  The checksum on the smbios table is unchanged,
+     * since it includes the checksum on the dmi table.
+     */
+    smx.dmi.tbladdr = sizeof smx;
+    smx.dmi.csum -= checksum(&smx.dmi, 0x0f);
+
+    write_data(be, &smx, sizeof smx);
+    write_data(be, (const void *)smb->dmi.tbladdr, smb->dmi.tbllen);
+}
+
+static void dump_old_dmi(struct upload_backend *be, size_t dptr)
+{
+    const struct dmi_header *dmi = (void *)dptr;
+    struct fake {
+	struct dmi_header dmi;
+	char pad[16];
+    } fake;
+    char filename[32];
+
+    snprintf(filename, sizeof filename, "dmi/%05x.%08x",
+	     dptr, dmi->tbladdr);
+    cpio_hdr(be, MODE_FILE, dmi->tbllen + 32, filename);
+
+    /*
+     * Adjust the address of the smbios table to be 32, to
+     * make dmidecode happy.
+     */
+    fake.dmi = *dmi;
+    memset(&fake.pad, 0, sizeof fake.pad);
+    fake.dmi.tbladdr = sizeof fake;
+    fake.dmi.csum -= checksum(&fake.dmi, 0x0f);
+
+    write_data(be, &fake, sizeof fake);
+    write_data(be, (const void *)dmi->tbladdr, dmi->tbllen);
+}
+
+void dump_dmi(struct upload_backend *be)
+{
+    size_t dptr;
+
+    cpio_mkdir(be, "dmi");
+
+    /* Search for _SM_ or _DMI_ structure */
+    for (dptr = 0xf0000 ; dptr < 0x100000 ; dptr += 16) {
+	if (is_smbios(dptr)) {
+	    dump_smbios(be, dptr);
+	    dptr += 16;		/* Skip the subsequent DMI header */
+	} else if (is_old_dmi(dptr)) {
+	    dump_old_dmi(be, dptr);
+	}
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/sysdump/main.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/sysdump/main.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/sysdump/main.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,97 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2010 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <dprintf.h>
+#include <console.h>
+#include <sys/cpu.h>
+#include <version.h>
+#include "sysdump.h"
+
+const char program[] = "sysdump";
+const char version[] = "SYSDUMP " VERSION_STR " " DATE "\n";
+
+__noreturn die(const char *msg)
+{
+    printf("%s: %s\n", program, msg);
+    exit(1);
+}
+
+static void dump_all(struct upload_backend *be, const char *argv[])
+{
+    cpio_init(be, argv);
+
+    cpio_writefile(be, "sysdump", version, sizeof version-1);
+
+    dump_memory_map(be);
+    dump_memory(be);
+    dump_dmi(be);
+    dump_acpi(be);
+    dump_cpuid(be);
+    dump_pci(be);
+    dump_vesa_tables(be);
+
+    cpio_close(be);
+    flush_data(be);
+}
+
+static struct upload_backend *upload_backends[] =
+{
+    &upload_tftp,
+    &upload_ymodem,
+    &upload_srec,
+    NULL
+};
+
+__noreturn usage(void)
+{
+    struct upload_backend **bep, *be;
+
+    printf("Usage:\n");
+    for (bep = upload_backends ; (be = *bep) ; bep++)
+	printf("    %s %s %s\n", program, be->name, be->helpmsg);
+
+    exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+    struct upload_backend **bep, *be;
+
+    fputs(version, stdout);
+
+    if (argc < 2)
+	usage();
+
+    for (bep = upload_backends ; (be = *bep) ; bep++) {
+	if (!strcmp(be->name, argv[1]))
+	    break;
+    }
+
+    if (!be || argc < be->minargs + 2)
+	usage();
+
+    /* Do this as early as possible */
+    snapshot_lowmem();
+
+    printf("Backend: %s\n", be->name);
+
+    /* Do the actual data dump */
+    dump_all(be, (const char **)argv + 2);
+
+    return 0;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/sysdump/memmap.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/sysdump/memmap.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/sysdump/memmap.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,86 @@
+/*
+ * Dump memory map information
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <com32.h>
+#include "sysdump.h"
+
+#define E820_CHUNK 128
+struct e820_info {
+    uint32_t ebx;
+    uint32_t len;
+    uint8_t  data[24];
+};
+
+static void dump_e820(struct upload_backend *be)
+{
+    com32sys_t ireg, oreg;
+    struct e820_info *curr;
+    struct e820_info *buf, *p;
+    int nentry, nalloc;
+
+    curr = lmalloc(sizeof *curr);
+
+    buf = p = NULL;
+    nentry = nalloc = 0;
+    memset(&ireg, 0, sizeof ireg);
+    memset(&curr, 0, sizeof curr);
+
+    ireg.eax.l = 0xe820;
+    ireg.edx.l = 0x534d4150;
+    ireg.ecx.l = sizeof curr->data;
+    ireg.es = SEG(curr->data);
+    ireg.edi.w[0] = OFFS(curr->data);
+
+    do {
+	__intcall(0x15, &ireg, &oreg);
+	if ((oreg.eflags.l & EFLAGS_CF) ||
+	    oreg.eax.l != 0x534d4150)
+	    break;
+
+	if (nentry >= nalloc) {
+	    nalloc += E820_CHUNK;
+	    buf = realloc(buf, nalloc*sizeof *buf);
+	    if (!buf)
+		return;		/* FAILED */
+	}
+	memcpy(buf[nentry].data, curr->data, sizeof curr->data);
+	buf[nentry].ebx = ireg.ebx.l;
+	buf[nentry].len = oreg.ecx.l;
+	nentry++;
+
+	ireg.ebx.l = oreg.ebx.l;
+    } while (ireg.ebx.l);
+
+    if (nentry)
+	cpio_writefile(be, "memmap/15e820", buf, nentry*sizeof *buf);
+
+    free(buf);
+    lfree(curr);
+}
+
+void dump_memory_map(struct upload_backend *be)
+{
+    com32sys_t ireg, oreg;
+
+    cpio_mkdir(be, "memmap");
+
+    memset(&ireg, 0, sizeof ireg);
+    __intcall(0x12, &ireg, &oreg);
+    cpio_writefile(be, "memmap/12", &oreg, sizeof oreg);
+
+    memset(&ireg, 0, sizeof ireg);
+    ireg.eax.b[1] = 0x88;
+    __intcall(0x15, &ireg, &oreg);
+    cpio_writefile(be, "memmap/1588", &oreg, sizeof oreg);
+
+    memset(&ireg, 0, sizeof ireg);
+    ireg.eax.w[0] = 0xe801;
+    __intcall(0x15, &ireg, &oreg);
+    cpio_writefile(be, "memmap/15e801", &oreg, sizeof oreg);
+
+    dump_e820(be);
+}
Index: bootcd/isolinux/syslinux-6.03/com32/sysdump/memory.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/sysdump/memory.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/sysdump/memory.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,50 @@
+/*
+ * Dump memory
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/cpu.h>
+#include "sysdump.h"
+
+static char *lowmem;
+static size_t lowmem_len;
+
+void *zero_addr;		/* Hack to keep gcc from complaining */
+
+void snapshot_lowmem(void)
+{
+    extern void _start(void);
+
+    lowmem_len = (size_t)_start;
+    lowmem = malloc(lowmem_len);
+    if (lowmem) {
+	printf("Snapshotting lowmem... ");
+	cli();
+	memcpy(lowmem, zero_addr, lowmem_len);
+	sti();
+	printf("ok\n");
+    }
+}
+
+static void dump_memory_range(struct upload_backend *be, const void *where,
+			      const void *addr, size_t len)
+{
+    char filename[32];
+
+    sprintf(filename, "memory/%08zx", (size_t)addr);
+    cpio_writefile(be, filename, where, len);
+}
+
+void dump_memory(struct upload_backend *be)
+{
+    printf("Dumping memory... ");
+
+    cpio_mkdir(be, "memory");
+
+    if (lowmem)
+	dump_memory_range(be, lowmem, zero_addr, lowmem_len);
+
+    printf("done.\n");
+}
Index: bootcd/isolinux/syslinux-6.03/com32/sysdump/pci.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/sysdump/pci.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/sysdump/pci.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,69 @@
+/*
+ * Dump PCI device headers
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/pci.h>
+#include "sysdump.h"
+
+static void dump_pci_device(struct upload_backend *be, pciaddr_t a, uint8_t hdrtype)
+{
+    unsigned int bus  = pci_bus(a);
+    unsigned int dev  = pci_dev(a);
+    unsigned int func = pci_func(a);
+    uint8_t data[256];
+    unsigned int i;
+    char filename[32];
+
+    hdrtype &= 0x7f;
+
+    printf("Scanning PCI bus... %02x:%02x.%x\r", bus, dev, func);
+
+    /* Assume doing a full device dump is actually safe... */
+    for (i = 0; i < sizeof data; i += 4)
+	*(uint32_t *)(data+i) = pci_readl(a + i);
+
+    snprintf(filename, sizeof filename, "pci/%02x:%02x.%x",
+	     bus, dev, func);
+    cpio_writefile(be, filename, data, sizeof data);
+}
+
+void dump_pci(struct upload_backend *be)
+{
+    int cfgtype;
+    unsigned int nbus, ndev, nfunc, maxfunc;
+    pciaddr_t a;
+    uint32_t did;
+    uint8_t hdrtype;
+
+    cfgtype = pci_set_config_type(PCI_CFG_AUTO);
+    if (cfgtype == PCI_CFG_NONE)
+	return;
+
+    cpio_mkdir(be, "pci");
+
+    for (nbus = 0; nbus < MAX_PCI_BUSES; nbus++) {
+	for (ndev = 0; ndev < MAX_PCI_DEVICES; ndev++) {
+	    maxfunc = 1;	/* Assume a single-function device */
+
+	    for (nfunc = 0; nfunc < maxfunc; nfunc++) {
+		a = pci_mkaddr(nbus, ndev, nfunc, 0);
+		did = pci_readl(a);
+
+		if (did == 0xffffffff || did == 0xffff0000 ||
+		    did == 0x0000ffff || did == 0x00000000)
+		    continue;
+
+		hdrtype = pci_readb(a + 0x0e);
+		if (hdrtype & 0x80)
+		    maxfunc = MAX_PCI_FUNC;	/* Multifunction device */
+
+		dump_pci_device(be, a, hdrtype);
+	    }
+	}
+    }
+
+    printf("Scanning PCI bus... done.  \n");
+}
Index: bootcd/isolinux/syslinux-6.03/com32/sysdump/rbtree.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/sysdump/rbtree.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/sysdump/rbtree.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,132 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ *   See the file AUTHORS included with the NASM distribution for
+ *   the specific copyright holders.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following
+ *   conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *     
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * rbtree.c
+ *
+ * Simple implementation of a left-leaning red-black tree with 64-bit
+ * integer keys.  The search operation will return the highest node <=
+ * the key; only search and insert are supported, but additional
+ * standard llrbtree operations can be coded up at will.
+ *
+ * See http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf for
+ * information about left-leaning red-black trees.
+ */
+
+#include <stdlib.h>
+#include "rbtree.h"
+
+struct rbtree *rb_search(struct rbtree *tree, uint64_t key)
+{
+    struct rbtree *best = NULL;
+
+    while (tree) {
+	if (tree->key == key)
+	    return tree;
+	else if (tree->key > key)
+	    tree = tree->left;
+	else {
+	    best = tree;
+	    tree = tree->right;
+	}
+    }
+    return best;
+}
+
+static bool is_red(struct rbtree *h)
+{
+    return h && h->red;
+}
+
+static struct rbtree *rotate_left(struct rbtree *h)
+{
+    struct rbtree *x = h->right;
+    h->right = x->left;
+    x->left = h;
+    x->red = x->left->red;
+    x->left->red = true;
+    return x;
+}
+
+static struct rbtree *rotate_right(struct rbtree *h)
+{
+    struct rbtree *x = h->left;
+    h->left = x->right;
+    x->right = h;
+    x->red = x->right->red;
+    x->right->red = true;
+    return x;
+}
+
+static void color_flip(struct rbtree *h)
+{
+    h->red = !h->red;
+    h->left->red = !h->left->red;
+    h->right->red = !h->right->red;
+}
+
+struct rbtree *rb_insert(struct rbtree *tree, struct rbtree *node)
+{
+    node->left = node->right = NULL;
+    node->red = false;
+
+    if (!tree) {
+	node->red = true;
+	return node;
+    }
+
+    if (is_red(tree->left) && is_red(tree->right))
+	color_flip(tree);
+
+    if (node->key < tree->key)
+	tree->left = rb_insert(tree->left, node);
+    else
+	tree->right = rb_insert(tree->right, node);
+
+    if (is_red(tree->right))
+	tree = rotate_left(tree);
+
+    if (is_red(tree->left) && is_red(tree->left->left))
+	tree = rotate_right(tree);
+
+    return tree;
+}
+
+void rb_destroy(struct rbtree *tree)
+{
+    if (tree->left)
+	rb_destroy(tree->left);
+    if (tree->right)
+	rb_destroy(tree->right);
+    free(tree);
+}
Index: bootcd/isolinux/syslinux-6.03/com32/sysdump/rbtree.h
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/sysdump/rbtree.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/sysdump/rbtree.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,53 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ *   See the file AUTHORS included with the NASM distribution for
+ *   the specific copyright holders.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following
+ *   conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *     
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef NASM_RBTREE_H
+#define NASM_RBTREE_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+/* This structure should be embedded in a larger data structure;
+   the final output from rb_search() can then be converted back
+   to the larger data structure via container_of(). */
+struct rbtree {
+    uint64_t key;
+    struct rbtree *left, *right;
+    bool red;
+};
+
+struct rbtree *rb_insert(struct rbtree *, struct rbtree *);
+struct rbtree *rb_search(struct rbtree *, uint64_t);
+void rb_destroy(struct rbtree *);
+
+#endif /* NASM_RBTREE_H */
Index: bootcd/isolinux/syslinux-6.03/com32/sysdump/sysdump.h
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/sysdump/sysdump.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/sysdump/sysdump.h	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,15 @@
+#ifndef SYSDUMP_H
+#define SYSDUMP_H
+
+#include <libupload/upload_backend.h>
+
+void dump_memory_map(struct upload_backend *);
+void snapshot_lowmem(void);
+void dump_memory(struct upload_backend *);
+void dump_dmi(struct upload_backend *);
+void dump_acpi(struct upload_backend *);
+void dump_cpuid(struct upload_backend *);
+void dump_pci(struct upload_backend *);
+void dump_vesa_tables(struct upload_backend *);
+
+#endif /* SYSDUMP_H */
Index: bootcd/isolinux/syslinux-6.03/com32/sysdump/vesa.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/sysdump/vesa.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/sysdump/vesa.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,63 @@
+#include <string.h>
+#include <stdio.h>
+#include <lib/sys/vesa/vesa.h>
+#include "sysdump.h"
+
+void dump_vesa_tables(struct upload_backend *be)
+{
+    com32sys_t rm;
+    struct vesa_info *vip;
+    struct vesa_general_info *gip, gi;
+    struct vesa_mode_info *mip, mi;
+    uint16_t mode, *mode_ptr;
+    char modefile[64];
+
+    printf("Scanning VESA BIOS... ");
+
+    /* Allocate space in the bounce buffer for these structures */
+    vip = lmalloc(sizeof *vip);
+    gip = &vip->gi;
+    mip = &vip->mi;
+
+    memset(&rm, 0, sizeof rm);
+    memset(gip, 0, sizeof *gip);
+
+    gip->signature = VBE2_MAGIC;	/* Get VBE2 extended data */
+    rm.eax.w[0] = 0x4F00;		/* Get SVGA general information */
+    rm.edi.w[0] = OFFS(gip);
+    rm.es = SEG(gip);
+    __intcall(0x10, &rm, &rm);
+    memcpy(&gi, gip, sizeof gi);
+
+    if (rm.eax.w[0] != 0x004F)
+	return;		/* Function call failed */
+    if (gi.signature != VESA_MAGIC)
+	return;		/* No magic */
+
+    cpio_mkdir(be, "vesa");
+
+    cpio_writefile(be, "vesa/global.bin", &gi, sizeof gi);
+
+    mode_ptr = GET_PTR(gi.video_mode_ptr);
+    while ((mode = *mode_ptr++) != 0xFFFF) {
+	memset(mip, 0, sizeof *mip);
+        memset(&rm, 0, sizeof rm);
+	rm.eax.w[0] = 0x4F01;	/* Get SVGA mode information */
+	rm.ecx.w[0] = mode;
+	rm.edi.w[0] = OFFS(mip);
+	rm.es = SEG(mip);
+	__intcall(0x10, &rm, &rm);
+
+	/* Must be a supported mode */
+	if (rm.eax.w[0] != 0x004f)
+	    continue;
+
+	memcpy(&mi, mip, sizeof mi);
+
+	sprintf(modefile, "vesa/mode%04x.bin", mode);
+	cpio_writefile(be, modefile, &mi, sizeof mi);
+    }
+
+    lfree(vip);
+    printf("done.\n");
+}
