[syslinux:elflink] elflink: add new files

syslinux-bot for Feng Tang feng.tang at intel.com
Thu Aug 12 21:03:57 PDT 2010


Commit-ID:  ff6ef23ed4e8459dbe6e97d0a016e8f89f5da258
Gitweb:     http://syslinux.zytor.com/commit/ff6ef23ed4e8459dbe6e97d0a016e8f89f5da258
Author:     Feng Tang <feng.tang at intel.com>
AuthorDate: Wed, 14 Jul 2010 11:08:06 +0800
Committer:  Feng Tang <feng.tang at intel.com>
CommitDate: Tue, 20 Jul 2010 11:10:04 +0800

elflink: add new files

new file:   com32/include/getopt.h
new file:   com32/include/ilog2.h
new file:   com32/lib/getopt_long.c
new file:   com32/lib/sys/sleep.c
new file:   com32/sysdump/acpi.c
new file:   com32/sysdump/be_srec.c
new file:   com32/sysdump/rbtree.c
new file:   com32/sysdump/rbtree.h
new file:   dos/getsetsl.c
new file:   dos/memmove.S
new file:   libinstaller/advio.c
new file:   libinstaller/fat.c
new file:   libinstaller/linuxioctl.h
new file:   memdisk/compiler.h
new file:   memdisk/mstructs.h
new file:   utils/memdiskfind.c


---
 com32/include/getopt.h                      |   22 +++
 com32/{mboot/syslinux.c => include/ilog2.h} |   27 ++--
 com32/lib/{getopt.c => getopt_long.c}       |   67 +++++++-
 com32/lib/sys/sleep.c                       |   22 +++
 com32/sysdump/acpi.c                        |  259 +++++++++++++++++++++++++++
 com32/sysdump/be_srec.c                     |   85 +++++++++
 com32/sysdump/rbtree.c                      |  132 ++++++++++++++
 com32/sysdump/rbtree.h                      |   53 ++++++
 dos/getsetsl.c                              |  100 ++++++++++
 dos/memmove.S                               |   36 ++++
 libinstaller/advio.c                        |  162 +++++++++++++++++
 libinstaller/fat.c                          |  129 +++++++++++++
 libinstaller/linuxioctl.h                   |   47 +++++
 memdisk/compiler.h                          |    9 +
 memdisk/mstructs.h                          |  178 ++++++++++++++++++
 utils/memdiskfind.c                         |  158 ++++++++++++++++
 16 files changed, 1468 insertions(+), 18 deletions(-)

diff --git a/com32/include/getopt.h b/com32/include/getopt.h
new file mode 100644
index 0000000..71c41cd
--- /dev/null
+++ b/com32/include/getopt.h
@@ -0,0 +1,22 @@
+#ifndef _GETOPT_H
+#define _GETOPT_H
+
+#include <klibc/extern.h>
+
+struct option {
+	const char *name;
+	int has_arg;
+	int *flag;
+	int val;
+};
+
+enum {
+	no_argument	  = 0,
+	required_argument = 1,
+	optional_argument = 2,
+};
+
+__extern int getopt_long(int, char *const *, const char *,
+			 const struct option *, int *);
+
+#endif /* _GETOPT_H */
diff --git a/com32/mboot/syslinux.c b/com32/include/ilog2.h
similarity index 79%
copy from com32/mboot/syslinux.c
copy to com32/include/ilog2.h
index 7de3853..91a5057 100644
--- a/com32/mboot/syslinux.c
+++ b/com32/include/ilog2.h
@@ -25,21 +25,24 @@
  *
  * ----------------------------------------------------------------------- */
 
+#ifndef _ILOG2_H
+#define _ILOG2_H
+
 /*
- * syslinux.c
- *
- * Syslinux-specific information for the kernel
+ * Computes floor(log2(x)) -- undefined for x = 0.
  */
 
-#include <syslinux/config.h>
-#include "mboot.h"
+#include <klibc/compiler.h>
+#include <stdint.h>
 
-void mboot_syslinux_info(void)
+static inline __constfunc uint32_t ilog2(uint32_t __v)
 {
-    const struct syslinux_version *sv;
-
-    sv = syslinux_version();
-    mbinfo.boot_loader_name = map_string(sv->version_string);
-    if (mbinfo.boot_loader_name)
-	mbinfo.flags |= MB_INFO_BOOT_LOADER_NAME;
+# if __GNUC__ >= 4
+    return __builtin_clz(__v) ^ 31;
+# else
+    asm("bsrl %1,%0" : "=r" (__v) : "rm" (__v));
+    return __v;
+# endif
 }
+
+#endif /* _ILOG2_H */
diff --git a/com32/lib/getopt.c b/com32/lib/getopt_long.c
similarity index 60%
copy from com32/lib/getopt.c
copy to com32/lib/getopt_long.c
index 806735d..e3d064b 100644
--- a/com32/lib/getopt.c
+++ b/com32/lib/getopt_long.c
@@ -1,12 +1,17 @@
 /*
  * getopt.c
  *
- * Simple POSIX getopt(), no GNU extensions...
+ * getopt_long(), or at least a common subset thereof:
+ *
+ * - Option reordering is not supported
+ * - -W foo is not supported
+ * - First optstring character "-" not supported.
  */
 
 #include <stdint.h>
 #include <unistd.h>
 #include <string.h>
+#include <getopt.h>
 
 char *optarg;
 int optind, opterr, optopt;
@@ -16,7 +21,22 @@ static struct getopt_private_state {
 	char *const *last_argv;
 } pvt;
 
-int getopt(int argc, char *const *argv, const char *optstring)
+static inline const char *option_matches(const char *arg_str,
+					 const char *opt_name)
+{
+	while (*arg_str != '\0' && *arg_str != '=') {
+		if (*arg_str++ != *opt_name++)
+			return NULL;
+	}
+
+	if (*opt_name)
+		return NULL;
+
+	return arg_str;
+}
+
+int getopt_long(int argc, char *const *argv, const char *optstring,
+		const struct option *longopts, int *longindex)
 {
 	const char *carg;
 	const char *osptr;
@@ -42,13 +62,48 @@ int getopt(int argc, char *const *argv, const char *optstring)
 
 	/* First, eliminate all non-option cases */
 
-	if (!carg || carg[0] != '-' || !carg[1]) {
+	if (!carg || carg[0] != '-' || !carg[1])
 		return -1;
-	}
 
-	if (carg[1] == '-' && !carg[2]) {
+	if (carg[1] == '-') {
+		const struct option *lo;
+		const char *opt_end = NULL;
+
 		optind++;
-		return -1;
+
+		/* Either it's a long option, or it's -- */
+		if (!carg[2]) {
+			/* It's -- */
+			return -1;
+		}
+
+		for (lo = longopts; lo->name; lo++) {
+			if ((opt_end = option_matches(carg+2, lo->name)))
+			    break;
+		}
+		if (!opt_end)
+			return '?';
+
+		if (longindex)
+			*longindex = lo-longopts;
+
+		if (*opt_end == '=') {
+			if (lo->has_arg)
+				optarg = (char *)opt_end+1;
+			else
+				return '?';
+		} else if (lo->has_arg == 1) {
+			if (!(optarg = argv[optind]))
+				return '?';
+			optind++;
+		}
+
+		if (lo->flag) {
+			*lo->flag = lo->val;
+			return 0;
+		} else {
+			return lo->val;
+		}
 	}
 
 	if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) {
diff --git a/com32/lib/sys/sleep.c b/com32/lib/sys/sleep.c
new file mode 100644
index 0000000..8a51c1c
--- /dev/null
+++ b/com32/lib/sys/sleep.c
@@ -0,0 +1,22 @@
+/*
+ * sys/sleep.c
+ */
+
+#include <unistd.h>
+#include <sys/times.h>
+#include <syslinux/idle.h>
+
+unsigned int msleep(unsigned int msec)
+{
+    clock_t start = times(NULL);
+
+    while (times(NULL) - start < msec)
+	syslinux_idle();
+
+    return 0;
+}
+
+unsigned int sleep(unsigned int seconds)
+{
+    return msleep(seconds * 1000);
+}
diff --git a/com32/sysdump/acpi.c b/com32/sysdump/acpi.c
new file mode 100644
index 0000000..8671fc8
--- /dev/null
+++ b/com32/sysdump/acpi.c
@@ -0,0 +1,259 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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 "backend.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 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 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 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 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");
+}
diff --git a/com32/sysdump/be_srec.c b/com32/sysdump/be_srec.c
new file mode 100644
index 0000000..fc69c88
--- /dev/null
+++ b/com32/sysdump/be_srec.c
@@ -0,0 +1,85 @@
+/*
+ * S-records dump routine -- dumps S-records on the console
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <minmax.h>
+#include "backend.h"
+
+/* Write a single S-record */
+static int write_srecord(unsigned int len,  unsigned int alen,
+                         uint32_t addr, uint8_t type, const void *data)
+{
+    char buf[2+2+8+255*2+2+2];
+    char *p = buf;
+    uint8_t csum;
+    const uint8_t *dptr = data;
+    unsigned int i;
+
+    switch (alen) {
+    case 2:
+        addr &= 0xffff;
+        break;
+    case 3:
+        addr &= 0xffffff;
+        break;
+    case 4:
+        break;
+    }
+
+    csum = (len+alen+1) + addr + (addr >> 8) + (addr >> 16) + (addr >> 24);
+    for (i = 0; i < len; i++)
+        csum += dptr[i];
+    csum = 0xff-csum;
+
+    p += sprintf(p, "S%c%02X%0*X", type, len+alen+1, alen*2, addr);
+    for (i = 0; i < len; i++)
+        p += sprintf(p, "%02X", dptr[i]);
+    p += sprintf(p, "%02X\n", csum);
+
+    fputs(buf, stdout);
+    return 0;
+}
+
+static int be_srec_write(struct backend *be)
+{
+    char name[33];
+    const char *buf;
+    size_t len, chunk, offset, hdrlen;
+
+    buf = be->outbuf;
+    len = be->zbytes;
+
+    putchar('\n');
+
+    hdrlen = snprintf(name, sizeof name, "%.32s",
+		      be->argv[0] ? be->argv[0] : "");
+
+    /* Write head record */
+    write_srecord(hdrlen, 2, 0, '0', name);
+
+    /* Write data records */
+    offset = 0;
+    while (len) {
+	chunk = min(len, (size_t)32);
+
+	write_srecord(chunk, 4, offset, '3', buf);
+	buf += chunk;
+	len -= chunk;
+	offset += chunk;
+    }
+
+    /* Write termination record */
+    write_srecord(0, 4, 0, '7', NULL);
+
+    return 0;
+}
+
+struct backend be_srec = {
+    .name       = "srec",
+    .helpmsg    = "[filename]",
+    .minargs    = 0,
+    .write      = be_srec_write,
+};
diff --git a/com32/sysdump/rbtree.c b/com32/sysdump/rbtree.c
new file mode 100644
index 0000000..1d10e09
--- /dev/null
+++ b/com32/sysdump/rbtree.c
@@ -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);
+}
diff --git a/com32/sysdump/rbtree.h b/com32/sysdump/rbtree.h
new file mode 100644
index 0000000..dcdcd6b
--- /dev/null
+++ b/com32/sysdump/rbtree.h
@@ -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 */
diff --git a/dos/getsetsl.c b/dos/getsetsl.c
new file mode 100644
index 0000000..a48f3df
--- /dev/null
+++ b/dos/getsetsl.c
@@ -0,0 +1,100 @@
+/*
+ * Special handling for the MS-DOS derivative: syslinux_ldlinux
+ * is a "far" object...
+ */
+
+#define _XOPEN_SOURCE 500	/* Required on glibc 2.x */
+#define _BSD_SOURCE
+#include <inttypes.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "syslxint.h"
+
+#define __noinline __attribute__((noinline))
+
+#if 0				/* unused */
+uint8_t get_8_sl(const uint8_t * p)
+{
+    uint8_t v;
+
+    p = set_fs(p);
+    asm volatile("movb %%fs:%1,%0":"=q" (v):"m"(*p));
+    return v;
+}
+#endif
+
+uint16_t get_16_sl(const uint16_t * p)
+{
+    uint16_t v;
+
+    p = set_fs(p);
+    asm volatile("movw %%fs:%1,%0":"=r" (v):"m"(*p));
+    return v;
+}
+
+uint32_t get_32_sl(const uint32_t * p)
+{
+    uint32_t v;
+
+    p = set_fs(p);
+    asm volatile("movl %%fs:%1,%0":"=r" (v):"m"(*p));
+    return v;
+}
+
+#if 0				/* unused */
+uint64_t get_64_sl(const uint64_t * p)
+{
+    uint32_t v0, v1;
+    const uint32_t *pp = (const uint32_t *)set_fs(p);
+
+    asm volatile("movl %%fs:%1,%0" : "=r" (v0) : "m" (pp[0]));
+    asm volatile("movl %%fs:%1,%0" : "=r" (v1) : "m" (pp[1]));
+    return v0 + ((uint64_t)v1 << 32);
+}
+#endif
+
+#if 0				/* unused */
+void set_8_sl(uint8_t * p, uint8_t v)
+{
+    p = set_fs(p);
+    asm volatile("movb %1,%%fs:%0":"=m" (*p):"qi"(v));
+}
+#endif
+
+void set_16_sl(uint16_t * p, uint16_t v)
+{
+    p = set_fs(p);
+    asm volatile("movw %1,%%fs:%0":"=m" (*p):"ri"(v));
+}
+
+void set_32_sl(uint32_t * p, uint32_t v)
+{
+    p = set_fs(p);
+    asm volatile("movl %1,%%fs:%0":"=m" (*p):"ri"(v));
+}
+
+void set_64_sl(uint64_t * p, uint64_t v)
+{
+    uint32_t *pp = (uint32_t *)set_fs(p);
+    asm volatile("movl %1,%%fs:%0" : "=m" (pp[0]) : "ri"((uint32_t)v));
+    asm volatile("movl %1,%%fs:%0" : "=m" (pp[1]) : "ri"((uint32_t)(v >> 32)));
+}
+
+void memcpy_to_sl(void *dst, const void *src, size_t len)
+{
+    uint16_t seg;
+    uint16_t off;
+
+    seg = ldlinux_seg + ((size_t)dst >> 4);
+    off = (size_t)dst & 15;
+
+    asm volatile("pushw %%es ; "
+		 "movw %3,%%es ; "
+		 "rep ; movsb ; "
+		 "popw %%es"
+		 : "+D" (off), "+S" (src), "+c" (len)
+		 : "r" (seg)
+		 : "memory");
+}
diff --git a/dos/memmove.S b/dos/memmove.S
new file mode 100644
index 0000000..1ab2cb2
--- /dev/null
+++ b/dos/memmove.S
@@ -0,0 +1,36 @@
+#
+# memmove.S
+#
+# Simple 16-bit memmove() implementation
+#
+
+	.text
+	.code16gcc
+	.globl memmove
+	.type memmove, @function
+memmove:
+	pushw %di
+	pushw %si
+	movw %ax,%di
+	movw %dx,%si
+	cmpw %si,%di
+	ja 1f
+	# The third argument is already in cx
+	cld
+	rep ; movsb
+2:
+	popw %si
+	popw %di
+	ret
+
+1:	/* si <= di, need reverse copy */
+	add %cx,%di
+	add %cx,%si
+	dec %di
+	dec %si
+	std
+	rep ; movsb
+	cld
+	jmp 2b
+
+	.size memmove,.-memmove
diff --git a/libinstaller/advio.c b/libinstaller/advio.c
new file mode 100644
index 0000000..56f607d
--- /dev/null
+++ b/libinstaller/advio.c
@@ -0,0 +1,162 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * advio.c
+ *
+ * Linux ADV I/O
+ *
+ * Return 0 on success, -1 on error, and set errno.
+ *
+ */
+#define  _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "syslxint.h"
+#include "syslxcom.h"
+
+/*
+ * Read the ADV from an existing instance, or initialize if invalid.
+ * Returns -1 on fatal errors, 0 if ADV is okay, 1 if the ADV is
+ * invalid, and 2 if the file does not exist.
+ */
+int read_adv(const char *path, const char *cfg)
+{
+    char *file;
+    int fd = -1;
+    struct stat st;
+    int err = 0;
+    int rv;
+
+    rv = asprintf(&file, "%s%s%s", path,
+		  path[0] && path[strlen(path) - 1] == '/' ? "" : "/", cfg);
+
+    if (rv < 0 || !file) {
+	perror(program);
+	return -1;
+    }
+
+    fd = open(file, O_RDONLY);
+    if (fd < 0) {
+	if (errno != ENOENT) {
+	    err = -1;
+	} else {
+	    syslinux_reset_adv(syslinux_adv);
+	    err = 2;		/* Nonexistence is not a fatal error */
+	}
+    } else if (fstat(fd, &st)) {
+	err = -1;
+    } else if (st.st_size < 2 * ADV_SIZE) {
+	/* Too small to be useful */
+	syslinux_reset_adv(syslinux_adv);
+	err = 0;		/* Nothing to read... */
+    } else if (xpread(fd, syslinux_adv, 2 * ADV_SIZE,
+		      st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
+	err = -1;
+    } else {
+	/* We got it... maybe? */
+	err = syslinux_validate_adv(syslinux_adv) ? 1 : 0;
+    }
+
+    if (err < 0)
+	perror(file);
+
+    if (fd >= 0)
+	close(fd);
+
+    free(file);
+
+    return err;
+}
+
+/*
+ * Update the ADV in an existing installation.
+ */
+int write_adv(const char *path, const char *cfg)
+{
+    unsigned char advtmp[2 * ADV_SIZE];
+    char *file;
+    int fd = -1;
+    struct stat st, xst;
+    int err = 0;
+    int rv;
+
+    rv = asprintf(&file, "%s%s%s", path,
+		  path[0] && path[strlen(path) - 1] == '/' ? "" : "/", cfg);
+
+    if (rv < 0 || !file) {
+	perror(program);
+	return -1;
+    }
+
+    fd = open(file, O_RDONLY);
+    if (fd < 0) {
+	err = -1;
+    } else if (fstat(fd, &st)) {
+	err = -1;
+    } else if (st.st_size < 2 * ADV_SIZE) {
+	/* Too small to be useful */
+	err = -2;
+    } else if (xpread(fd, advtmp, 2 * ADV_SIZE,
+		      st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
+	err = -1;
+    } else {
+	/* We got it... maybe? */
+	err = syslinux_validate_adv(advtmp) ? -2 : 0;
+	if (!err) {
+	    /* Got a good one, write our own ADV here */
+	    clear_attributes(fd);
+
+	    /* Need to re-open read-write */
+	    close(fd);
+	    fd = open(file, O_RDWR | O_SYNC);
+	    if (fd < 0) {
+		err = -1;
+	    } else if (fstat(fd, &xst) || xst.st_ino != st.st_ino ||
+		       xst.st_dev != st.st_dev || xst.st_size != st.st_size) {
+		fprintf(stderr, "%s: race condition on write\n", file);
+		err = -2;
+	    }
+	    /* Write our own version ... */
+	    if (xpwrite(fd, syslinux_adv, 2 * ADV_SIZE,
+			st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
+		err = -1;
+	    }
+
+	    sync();
+	    set_attributes(fd);
+	}
+    }
+
+    if (err == -2)
+	fprintf(stderr, "%s: cannot write auxilliary data (need --update)?\n",
+		file);
+    else if (err == -1)
+	perror(file);
+
+    if (fd >= 0)
+	close(fd);
+    if (file)
+	free(file);
+
+    return err;
+}
diff --git a/libinstaller/fat.c b/libinstaller/fat.c
new file mode 100644
index 0000000..e210135
--- /dev/null
+++ b/libinstaller/fat.c
@@ -0,0 +1,129 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009-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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * fat.c - Initial sanity check for FAT-based installers
+ */
+
+#define _XOPEN_SOURCE 500	/* Required on glibc 2.x */
+#define _BSD_SOURCE
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "syslinux.h"
+#include "syslxint.h"
+
+void syslinux_make_bootsect(void *bs)
+{
+    struct boot_sector *bootsect = bs;
+    const struct boot_sector *sbs =
+	(const struct boot_sector *)boot_sector;
+
+    memcpy(&bootsect->bsHead, &sbs->bsHead, bsHeadLen);
+    memcpy(&bootsect->bsCode, &sbs->bsCode, bsCodeLen);
+}
+
+/*
+ * Check to see that what we got was indeed an MS-DOS boot sector/superblock;
+ * Return NULL if OK and otherwise an error message;
+ */
+const char *syslinux_check_bootsect(const void *bs)
+{
+    int veryold;
+    int sectorsize;
+    long long sectors, fatsectors, dsectors;
+    long long clusters;
+    int rootdirents, clustersize;
+    const struct boot_sector *sectbuf = bs;
+
+    veryold = 0;
+
+    /* Must be 0xF0 or 0xF8..0xFF */
+    if (get_8(&sectbuf->bsMedia) != 0xF0 && get_8(&sectbuf->bsMedia) < 0xF8)
+	return "invalid media signature (not a FAT filesystem?)";
+
+    sectorsize = get_16(&sectbuf->bsBytesPerSec);
+    if (sectorsize == SECTOR_SIZE)
+	;			/* ok */
+    else if (sectorsize >= 512 && sectorsize <= 4096 &&
+	     (sectorsize & (sectorsize - 1)) == 0)
+	return "unsupported sectors size";
+    else
+	return "impossible sector size";
+
+    clustersize = get_8(&sectbuf->bsSecPerClust);
+    if (clustersize == 0 || (clustersize & (clustersize - 1)))
+	return "impossible cluster size";
+
+    sectors = get_16(&sectbuf->bsSectors);
+    sectors = sectors ? sectors : get_32(&sectbuf->bsHugeSectors);
+
+    dsectors = sectors - get_16(&sectbuf->bsResSectors);
+
+    fatsectors = get_16(&sectbuf->bsFATsecs);
+    fatsectors = fatsectors ? fatsectors : get_32(&sectbuf->bs32.FATSz32);
+    fatsectors *= get_8(&sectbuf->bsFATs);
+    dsectors -= fatsectors;
+
+    rootdirents = get_16(&sectbuf->bsRootDirEnts);
+    dsectors -= (rootdirents + sectorsize / 32 - 1) / sectorsize;
+
+    if (dsectors < 0)
+	return "negative number of data sectors";
+
+    if (fatsectors == 0)
+	return "zero FAT sectors";
+
+    clusters = dsectors / clustersize;
+
+    if (clusters < 0xFFF5) {
+	/* FAT12 or FAT16 */
+
+	if (!get_16(&sectbuf->bsFATsecs))
+	    return "zero FAT sectors (FAT12/16)";
+
+	if (get_8(&sectbuf->bs16.BootSignature) == 0x29) {
+	    if (!memcmp(&sectbuf->bs16.FileSysType, "FAT12   ", 8)) {
+		if (clusters >= 0xFF5)
+		    return "more than 4084 clusters but claims FAT12";
+	    } else if (!memcmp(&sectbuf->bs16.FileSysType, "FAT16   ", 8)) {
+		if (clusters < 0xFF5)
+		    return "less than 4084 clusters but claims FAT16";
+	    } else if (!memcmp(&sectbuf->bs16.FileSysType, "FAT32   ", 8)) {
+		    return "less than 65525 clusters but claims FAT32";
+	    } else if (memcmp(&sectbuf->bs16.FileSysType, "FAT     ", 8)) {
+		static char fserr[] =
+		    "filesystem type \"????????\" not supported";
+		memcpy(fserr + 17, &sectbuf->bs16.FileSysType, 8);
+		return fserr;
+	    }
+	}
+    } else if (clusters < 0x0FFFFFF5) {
+	/*
+	 * FAT32...
+	 *
+	 * Moving the FileSysType and BootSignature was a lovely stroke
+	 * of M$ idiocy...
+	 */
+	if (get_8(&sectbuf->bs32.BootSignature) != 0x29 ||
+	    memcmp(&sectbuf->bs32.FileSysType, "FAT32   ", 8))
+	    return "missing FAT32 signature";
+    } else {
+	return "impossibly large number of clusters";
+    }
+
+    return NULL;
+}
diff --git a/libinstaller/linuxioctl.h b/libinstaller/linuxioctl.h
new file mode 100644
index 0000000..7ef919a
--- /dev/null
+++ b/libinstaller/linuxioctl.h
@@ -0,0 +1,47 @@
+/*
+ * linuxioctl.h
+ *
+ * Wrapper for Linux ioctl definitions, including workarounds
+ */
+
+#ifndef LIBINSTALLER_LINUXIOCTL_H
+#define LIBINSTALLER_LINUXIOCTL_H
+
+#include <sys/ioctl.h>
+
+#define statfs _kernel_statfs	/* HACK to deal with broken 2.4 distros */
+
+#include <linux/fd.h>		/* Floppy geometry */
+#include <linux/hdreg.h>	/* Hard disk geometry */
+
+#include <linux/fs.h>		/* FIGETBSZ, FIBMAP, FS_IOC_FIEMAP */
+#include <linux/msdos_fs.h>	/* FAT_IOCTL_SET_ATTRIBUTES */
+
+#undef SECTOR_SIZE		/* Defined in msdos_fs.h for no good reason */
+#undef SECTOR_BITS
+#include <linux/ext2_fs.h>	/* EXT2_IOC_* */
+
+#ifndef FAT_IOCTL_GET_ATTRIBUTES
+# define FAT_IOCTL_GET_ATTRIBUTES	_IOR('r', 0x10, __u32)
+#endif
+
+#ifndef FAT_IOCTL_SET_ATTRIBUTES
+# define FAT_IOCTL_SET_ATTRIBUTES	_IOW('r', 0x11, __u32)
+#endif
+
+#include <linux/fiemap.h>	/* FIEMAP definitions */
+
+#ifndef FS_IOC_FIEMAP
+# define FS_IOC_FIEMAP		_IOWR('f', 11, struct fiemap)
+#endif
+
+#undef statfs
+
+#if defined(__linux__) && !defined(BLKGETSIZE64)
+/* This takes a u64, but the size field says size_t.  Someone screwed big. */
+# define BLKGETSIZE64 _IOR(0x12,114,size_t)
+#endif
+
+#include <linux/loop.h>
+
+#endif /* LIBINSTALLER_LINUXIOCTL_H */
diff --git a/memdisk/compiler.h b/memdisk/compiler.h
new file mode 100644
index 0000000..d1b03e0
--- /dev/null
+++ b/memdisk/compiler.h
@@ -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
diff --git a/memdisk/mstructs.h b/memdisk/mstructs.h
new file mode 100644
index 0000000..fecbff4
--- /dev/null
+++ b/memdisk/mstructs.h
@@ -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 sectors;	/* Sectors/track */
+
+	uint8_t bps;		/* Bytes/sector (02h = 512) */
+	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;
diff --git a/utils/memdiskfind.c b/utils/memdiskfind.c
new file mode 100644
index 0000000..decc788
--- /dev/null
+++ b/utils/memdiskfind.c
@@ -0,0 +1,158 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * memdiskfind.c
+ *
+ * Simple utility to search for a MEMDISK instance and output the parameters
+ * needed to use the "phram" driver in Linux to map it.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include "../memdisk/mstructs.h"
+
+#define MBFT_MIN_LENGTH	(36+4+26)
+
+static bool valid_mbft(const struct mBFT *mbft, size_t space)
+{
+    uint8_t csum;
+    size_t i;
+
+    if (memcmp(mbft->acpi.signature, "mBFT", 4))
+	return false;
+
+    if (mbft->acpi.length < MBFT_MIN_LENGTH)
+	return false;
+
+    if (mbft->acpi.length > space)
+	return false;
+
+    if ((size_t)mbft->acpi.length != (size_t)mbft->mdi.bytes + 36+4)
+	return false;
+
+    csum = 0;
+    for (i = 0; i < mbft->acpi.length; i++)
+	csum += ((const uint8_t *)mbft)[i];
+
+    if (csum)
+	return false;
+
+    return true;
+}
+
+static void output_params(const struct mBFT *mbft)
+{
+    int sector_shift = mbft->mdi.sector_shift;
+
+    if (!sector_shift)
+	sector_shift = 9;
+
+    printf("%#x,%#x\n",
+	   mbft->mdi.diskbuf, mbft->mdi.disksize << sector_shift);
+}
+
+static size_t memlimit(void)
+{
+    char txtline[256], user[256];
+    size_t maxram = 0;
+    unsigned long long start, end;
+    FILE *iomem;
+
+    iomem = fopen("/proc/iomem", "r");
+    if (!iomem)
+	return 0;
+
+    while (fgets(txtline, sizeof txtline, iomem) != NULL) {
+	if (sscanf(txtline, "%llx-%llx : %[^\n]", &start, &end, user) != 3)
+	    continue;
+	if (strcmp(user, "System RAM"))
+	    continue;
+	if (start >= 0xa0000)
+	    continue;
+	maxram = (end >= 0xa0000) ? 0xa0000 : end+1;
+    }
+    fclose(iomem);
+
+    return maxram;
+}
+
+int main(int argc, char *argv[])
+{
+    const char *map;
+    int memfd;
+    size_t fbm;
+    const char *ptr, *end;
+    size_t page = sysconf(_SC_PAGESIZE);
+    size_t mapbase, maplen;
+    int err = 1;
+
+    (void)argc;
+
+    mapbase = memlimit() & ~(page - 1);
+    if (!mapbase)
+	return 2;
+
+    memfd = open("/dev/mem", O_RDONLY);
+    if (memfd < 0) {
+	fprintf(stderr, "%s: cannot open /dev/mem: %s\n",
+		argv[0], strerror(errno));
+	return 2;
+    }
+
+    map = mmap(NULL, page, PROT_READ, MAP_SHARED, memfd, 0);
+    if (map == MAP_FAILED) {
+	fprintf(stderr, "%s: cannot map page 0: %s\n",
+		argv[0], strerror(errno));
+	return 2;
+    }
+
+    fbm = *(uint16_t *)(map + 0x413) << 10;
+    if (fbm < mapbase)
+	fbm = mapbase;
+
+    munmap((void *)map, page);
+
+    if (fbm < 64*1024 || fbm >= 640*1024)
+	return 1;
+
+    maplen  = 0xa0000 - mapbase;
+    map = mmap(NULL, maplen, PROT_READ, MAP_SHARED, memfd, mapbase);
+    if (map == MAP_FAILED) {
+	fprintf(stderr, "%s: cannot map base memory: %s\n",
+		argv[0], strerror(errno));
+	return 2;
+    }
+
+    ptr = map + (fbm - mapbase);
+    end = map + (0xa0000 - mapbase);
+    while (ptr < end) {
+	if (valid_mbft((const struct mBFT *)ptr, end-ptr)) {
+	    output_params((const struct mBFT *)ptr);
+	    err = 0;
+	    break;
+	}
+	ptr += 16;
+    }
+
+    munmap((void *)map, maplen);
+
+    return err;
+}



More information about the Syslinux-commits mailing list