Merge tag 'syslinux-5.01' into firmware

Conflicts:
	Makefile
	NEWS
	com32/cmenu/Makefile
	com32/elflink/ldlinux/Makefile
	com32/gfxboot/Makefile
	com32/gpllib/Makefile
	com32/include/sys/module.h
	com32/lib/Makefile
	com32/lib/sys/module/elf_module.c
	com32/menu/Makefile
	com32/rosh/Makefile
	com32/samples/Makefile
	core/init.c
	mk/elf.mk

Signed-off-by: Matt Fleming <matt.fleming@intel.com>
diff --git a/Makefile b/Makefile
index 7add22e..e7d89d9 100644
--- a/Makefile
+++ b/Makefile
@@ -162,15 +162,15 @@
 
 ifdef EFI_BUILD
 
-BSUBDIRS = codepage com32 lzo core mbr sample efi
+BSUBDIRS = codepage com32 lzo core mbr sample efi txt
 ISUBDIRS = efi utils
 
 INSTALLSUBDIRS = efi
 
 else
 
-BSUBDIRS = codepage com32 lzo core memdisk sample diag mbr memdump dos \
-	   gpxe libinstaller win32 win64 dosutil
+BSUBDIRS = codepage com32 lzo core memdisk mbr memdump gpxe sample \
+	   diag libinstaller dos win32 win64 dosutil txt
 
 ITARGET  =
 IOBJECTS = $(ITARGET) \
diff --git a/NEWS b/NEWS
index 37c0e54..11e692d 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,22 @@
 Changes in 6.00:
 	* Add support for booting from EFI.
 
+Changes in 5.01:
+	* txt/: A new AsciiDoc documentation set (work-in-progress)
+	  (Gene Cumm).
+	* core: Fix a bug in the realloc() implementation that caused
+	  machines to appear to run out of free memory.
+	* ldlinux: Fix multiple buffer overflows in cmdline parsing
+	  code that resulted in files failing to run and cmdlines
+	  being truncated.
+	* core: Fix debug build by tagging __bad_SEG() with __export.
+	* com32: Restrict library filenames to 8.3 format.
+	* EXTLINUX: Fix installation and subdirectory patching.
+	* ISOLINUX: Fix booting isohybrid images that are over 32K.
+	* com32: Strip modules to reduce their size.
+	* XFS: Implement directory block cache and fix
+          shortform-directory lookup (Paulo Alcantara).
+
 Changes in 5.00:
 	* com32: Switched from the COM32 object format to ELF as it is
 	  a much more powerful format that allows undefined symbols to
diff --git a/com32/chain/Makefile b/com32/chain/Makefile
index 3238550..1a7ac9e 100644
--- a/com32/chain/Makefile
+++ b/com32/chain/Makefile
@@ -18,7 +18,7 @@
 
 all: chain.c32
 
-chain.c32: $(OBJS) $(C_LIBS)
+chain.elf: $(OBJS) $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
 %.o: %.c
diff --git a/com32/cmenu/Makefile b/com32/cmenu/Makefile
index 7ff1ff6..f432136 100644
--- a/com32/cmenu/Makefile
+++ b/com32/cmenu/Makefile
@@ -18,7 +18,7 @@
 NOGPL := 1
 
 LIBS  = libmenu/libmenu.c32 \
-        $(objdir)/com32/libutil/libutil_com.c32 \
+        $(objdir)/com32/libutil/libutil.c32 \
         $(objdir)/com32/lib/libcom32.c32
 
 VPATH = $(SRC)
@@ -26,7 +26,7 @@
 
 CFLAGS	  += -I$(SRC)/libmenu
 
-LIBMENU = $(objdir)/com32/libutil/libutil_com.c32 \
+LIBMENU = $(objdir)/com32/libutil/libutil.c32 \
 	$(objdir)/com32/lib/libcom32.c32 \
 	libmenu/syslnx.o libmenu/com32io.o libmenu/tui.o \
 	libmenu/menu.o libmenu/passwords.o libmenu/des.o libmenu/help.o
@@ -47,14 +47,15 @@
 makeoutputdirs:
 	@mkdir -p $(OBJ)/libmenu
 
-libmenu/libmenu.c32: $(LIBMENU)
-	$(LD) -shared $(LDFLAGS) -o $@ $^
+libmenu/libmenu.elf: $(LIBMENU)
+	$(LD) -shared $(LDFLAGS) -soname $(patsubst %.elf,%.c32,$(@F)) \
+		-o $@ $^
 
 tidy dist:
-	rm -f *.o *.lo *.c32 *.lst *.elf .*.d */.*.d
+	rm -f *.o *.lo *.lst *.elf */*.o */*.elf .*.d */.*.d
 
 libclean:
-	rm -f libmenu/*.o libmenu/*.c32
+	rm -f libmenu/*.c32
 
 clean: tidy menuclean libclean
 	rm -f *.lss *.c32 *.com
diff --git a/com32/cmenu/menugen.py b/com32/cmenu/menugen.py
index 70ec1f8..da64d93 100644
--- a/com32/cmenu/menugen.py
+++ b/com32/cmenu/menugen.py
@@ -72,9 +72,9 @@
        self.init_entry()
        self.init_menu()
        self.init_system()
-       self.vtypes = " OR ".join(self.types.keys())
-       self.vattrs = " OR ".join(filter(lambda x: x[0] != "_", self.entry.keys()))
-       self.mattrs = " OR ".join(filter(lambda x: x[0] != "_", self.menu.keys()))
+       self.vtypes = " OR ".join(list(self.types.keys()))
+       self.vattrs = " OR ".join([x for x in list(self.entry.keys()) if x[0] != "_"])
+       self.mattrs = " OR ".join([x for x in list(self.menu.keys()) if x[0] != "_"])
 
    def init_entry(self):
        self.entry = self.entry_init.copy()
@@ -100,27 +100,27 @@
           if not self.entry["info"]:
              self.entry["info"] = self.entry["data"]
           if not self.menus:
-             print "Error before line %d" % self.lineno
-             print "REASON: menu must be declared before a menu item is declared"
+             print("Error before line %d" % self.lineno)
+             print("REASON: menu must be declared before a menu item is declared")
              sys.exit(1)
           self.menus[-1][1].append(self.entry)
        self.init_entry()
 
    def set_item(self,name,value):
-       if not self.entry.has_key(name):
+       if name not in self.entry:
           msg = ["Unknown attribute %s in line %d" % (name,self.lineno)]
           msg.append("REASON: Attribute must be one of %s" % self.vattrs)
           return "\n".join(msg)
-       if name=="type" and not self.types.has_key(value):
+       if name=="type" and value not in self.types:
           msg = [ "Unrecognized type %s in line %d" % (value,self.lineno)]
           msg.append("REASON: Valid types are %s" % self.vtypes)
           return "\n".join(msg)
        if name=="shortcut":
-          if (value <> "-1") and not re.match("^[A-Za-z0-9]$",value):
+          if (value != "-1") and not re.match("^[A-Za-z0-9]$",value):
              msg = [ "Invalid shortcut char '%s' in line %d" % (value,self.lineno) ]
              msg.append("REASON: Valid values are [A-Za-z0-9]")
              return "\n".join(msg)
-          elif value <> "-1": value = "'%s'" % value
+          elif value != "-1": value = "'%s'" % value
        elif name in ["state","helpid","ipappend"]:
           try:
               value = int(value)
@@ -131,14 +131,14 @@
        return ""
 
    def set_menu(self,name,value):
-       if not self.menu.has_key(name):
+       if name not in self.menu:
           return "Error: Unknown keyword %s" % name
        self.menu[name] = value
        self.menu["_updated"] = 1
        return ""
 
    def set_system(self,name,value):
-       if not self.system.has_key(name):
+       if name not in self.system:
           return "Error: Unknown keyword %s" % name
        if name == "skipcondn":
           try: # is skipcondn a number?
@@ -146,7 +146,7 @@
           except: # it is a "-" delimited sequence
              value = value.lower()
              parts = [ self.shift_flags.get(x.strip(),None) for x in value.split("-") ]
-             self.system["skipcondn"] = " | ".join(filter(None, parts))
+             self.system["skipcondn"] = " | ".join([_f for _f in parts if _f])
        else:
           self.system[name] = value
 
@@ -169,7 +169,7 @@
        if not err: return
 
        # all errors so return item's error message
-       print err
+       print(err)
        sys.exit(1)
 
    def print_entry(self,entry,fd):
@@ -211,9 +211,9 @@
 
        missing = None
        for x in self.reqd_templates:
-           if not self.templates.has_key(x): missing = x
+           if x not in self.templates: missing = x
        if missing:
-           print "Template %s required but not defined in %s" % (missing,self.code_template_filename)
+           print("Template %s required but not defined in %s" % (missing,self.code_template_filename))
 
        if filename == "-":
           fd = sys.stdout
@@ -227,8 +227,8 @@
        fd.write(self.templates["footer"])
        fd.close()
        if not self.foundmain:
-          print "main menu not found"
-          print self.menus
+          print("main menu not found")
+          print(self.menus)
           sys.exit(1)
 
    def input(self,filename):
@@ -259,26 +259,26 @@
            # add property of current entry
            pos = line.find("=") # find the first = in string
            if pos < 0:
-              print "Syntax error in line %d" % self.lineno
-              print "REASON: non-section lines must be of the form ATTRIBUTE=VALUE"
+              print("Syntax error in line %d" % self.lineno)
+              print("REASON: non-section lines must be of the form ATTRIBUTE=VALUE")
               sys.exit(1)
            attr = line[:pos].strip().lower()
            value = line[pos+1:].strip()
            self.set(attr,value)
          except:
-            print "Error while parsing line %d: %s" % (self.lineno,line)
+            print("Error while parsing line %d: %s" % (self.lineno,line))
             raise
        fd.close()
        self.add_item()
 
 def usage():
-    print sys.argv[0]," [options]"
-    print "--input=<file>    is the name of the .menu file declaring the menu structure"
-    print "--output=<file>   is the name of generated C source"
-    print "--template=<file> is the name of template to be used"
-    print
-    print "input and output default to - (stdin and stdout respectively)"
-    print "template defaults to adv_menu.tpl"
+    print(sys.argv[0]," [options]")
+    print("--input=<file>    is the name of the .menu file declaring the menu structure")
+    print("--output=<file>   is the name of generated C source")
+    print("--template=<file> is the name of template to be used")
+    print()
+    print("input and output default to - (stdin and stdout respectively)")
+    print("template defaults to adv_menu.tpl")
     sys.exit(1)
 
 def main():
@@ -287,7 +287,7 @@
     ofile = "-"
     opts,args = getopt.getopt(sys.argv[1:], "hi:o:t:",["input=","output=","template=","help"])
     if args:
-       print "Unknown options %s" % args
+       print("Unknown options %s" % args)
        usage()
     for o,a in opts:
         if o in ["-i","--input"]:
diff --git a/com32/elflink/ldlinux/Makefile b/com32/elflink/ldlinux/Makefile
index 659aa40..bfec450 100644
--- a/com32/elflink/ldlinux/Makefile
+++ b/com32/elflink/ldlinux/Makefile
@@ -1,6 +1,6 @@
 ## -----------------------------------------------------------------------
 ##
-##   Copyright 2011 Intel Corporation - All Rights Reserved
+##   Copyright 2011-2013 Intel Corporation - 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
@@ -18,14 +18,14 @@
 
 OBJS = ldlinux.o cli.o readconfig.o refstr.o colors.o getadv.o adv.o \
 	execute.o chainboot.o kernel.o get_key.o advwrite.o setadv.o \
-	eprintf.o loadhigh.o msg.o
+	loadhigh.o msg.o
 
 BTARGET = ldlinux.c32
 
 all: $(BTARGET) ldlinux_lnx.a
 
-ldlinux.c32 : $(OBJS)
-	$(LD) $(LDFLAGS) -soname $(@F) -o $@ $^ $(LIBS)
+ldlinux.elf : $(OBJS)
+	$(LD) $(LDFLAGS) -soname $(patsubst %.elf,%.c32,$(@F)) -o $@ $^ $(LIBS)
 
 LNXCFLAGS += -D__export='__attribute__((visibility("default")))'
 LNXLIBOBJS = get_key.lo
diff --git a/com32/elflink/ldlinux/cli.c b/com32/elflink/ldlinux/cli.c
index b94c683..b85357b 100644
--- a/com32/elflink/ldlinux/cli.c
+++ b/com32/elflink/ldlinux/cli.c
@@ -71,7 +71,7 @@
 
     memset(buf, 0, MAX_CMDLINE_LEN);
 
-    eprintf("\033[1G\033[1;36m(reverse-i-search)`': \033[0m");
+    printf("\033[1G\033[1;36m(reverse-i-search)`': \033[0m");
     while (1) {
 	key = mygetkey_timeout(kbd_to, tto);
 
@@ -105,11 +105,11 @@
             *cursor = p - last_good->command;
 	}
 
-	eprintf("\033[?7l\033[?25l");
+	printf("\033[?7l\033[?25l");
 	/* Didn't handle the line wrap case here */
-	eprintf("\033[1G\033[1;36m(reverse-i-search)\033[0m`%s': %s",
+	printf("\033[1G\033[1;36m(reverse-i-search)\033[0m`%s': %s",
 		buf, last_good->command ? : "");
-	eprintf("\033[K\r");
+	printf("\033[K\r");
     }
 
     return last_good ? last_good->command : NULL;
@@ -147,7 +147,7 @@
      * so that it follows whatever text has been written to the screen
      * previously.
      */
-    eprintf("%s ", input);
+    printf("%s ", input);
 
     while (!done) {
 	if (redraw > 1) {
@@ -158,7 +158,7 @@
 	    if (pDraw_Menu)
 		    (*pDraw_Menu) (-1, top, 1);
 	    prev_len = 0;
-	    eprintf("\033[2J\033[H");
+	    printf("\033[2J\033[H");
 	    // printf("\033[0m\033[2J\033[H");
 	}
 
@@ -168,8 +168,8 @@
 	    prev_len = max(len, prev_len);
 
 	    /* Redraw the command line */
-	    eprintf("\033[?7l\033[?25l");
-	    eprintf("\033[1G%s ", input);
+	    printf("\033[?7l\033[?25l");
+	    printf("\033[1G%s ", input);
 
 	    x = strlen(input);
 	    y = 0;
@@ -179,23 +179,23 @@
 		at++;
 		x++;
 		if (x >= width) {
-		    eprintf("\r\n");
+		    printf("\r\n");
 		    x = 0;
 		    y++;
 		}
 	    }
-	    eprintf("\033[K\r");
+	    printf("\033[K\r");
 
 	    dy = y - (cursor + strlen(input) + 1) / width;
 	    x = (cursor + strlen(input) + 1) % width;
 
 	    if (dy) {
-		eprintf("\033[%dA", dy);
+		printf("\033[%dA", dy);
 		y -= dy;
 	    }
 	    if (x)
-		eprintf("\033[%dC", x);
-	    eprintf("\033[?25h");
+		printf("\033[%dC", x);
+	    printf("\033[?25h");
 	    prev_len = len;
 	    redraw = 0;
 	}
@@ -288,7 +288,7 @@
 		cursor++;
 		x++;
 		if (x >= width) {
-		    eprintf("\r\n");
+		    printf("\r\n");
 		    y++;
 		    x = 0;
 		}
@@ -418,10 +418,10 @@
 	    }
 	case KEY_CTRL('V'):
 	    if (BIOSName)
-		eprintf("%s%s%s", syslinux_banner,
-			MK_PTR(0, BIOSName), copyright_str);
+		printf("%s%s%s", syslinux_banner,
+		       (char *)MK_PTR(0, BIOSName), copyright_str);
 	    else
-		eprintf("%s%s", syslinux_banner, copyright_str);
+		printf("%s%s", syslinux_banner, copyright_str);
 
 	    redraw = 1;
 	    break;
@@ -435,7 +435,7 @@
 		    cursor++;
 		    x++;
 		    if (x >= width) {
-			eprintf("\r\n\033[K");
+			printf("\r\n\033[K");
 			y++;
 			x = 0;
 		    }
@@ -452,7 +452,7 @@
 	}
     }
 
-    eprintf("\033[?7h");
+    printf("\033[?7h");
 
     /* Add the command to the history */
     comm_counter = malloc(sizeof(struct cli_command));
diff --git a/com32/elflink/ldlinux/config.h b/com32/elflink/ldlinux/config.h
index c551fb1..242b7dc 100644
--- a/com32/elflink/ldlinux/config.h
+++ b/com32/elflink/ldlinux/config.h
@@ -41,8 +41,6 @@
 extern struct menu_entry *find_label(const char *str);
 extern void print_labels(const char *prefix, size_t len);
 
-extern void eprintf(const char *filename, ...);
-
 extern int new_linux_kernel(char *okernel, char *ocmdline);
 
 extern void pm_load_high(com32sys_t *regs);
diff --git a/com32/elflink/ldlinux/eprintf.c b/com32/elflink/ldlinux/eprintf.c
deleted file mode 100644
index f15edc6..0000000
--- a/com32/elflink/ldlinux/eprintf.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <core.h>
-
-#define BUFFER_SIZE	4096
-
-static void veprintf(const char *format, va_list ap)
-{
-    int rv, _rv;
-    char buffer[BUFFER_SIZE];
-    char *p;
-
-    _rv = rv = vsnprintf(buffer, BUFFER_SIZE, format, ap);
-
-    if (rv < 0)
-	return;
-
-    if (rv > BUFFER_SIZE - 1)
-	rv = BUFFER_SIZE - 1;
-
-    p = buffer;
-    while (rv--)
-	    write_serial(*p++);
-
-    _fwrite(buffer, _rv, stdout);
-}
-
-void eprintf(const char *format, ...)
-{
-    va_list ap;
-
-    va_start(ap, format);
-    veprintf(format, ap);
-    va_end(ap);
-}
diff --git a/com32/elflink/ldlinux/execute.c b/com32/elflink/ldlinux/execute.c
index 727df50..5c53b99 100644
--- a/com32/elflink/ldlinux/execute.c
+++ b/com32/elflink/ldlinux/execute.c
@@ -55,11 +55,9 @@
 
 	memset(&ireg, 0, sizeof ireg);
 
-	/* for parameter will be passed to __intcall, we need use
-	 * lmalloc a block of low memory */
-	q = lmalloc(128);
+	q = malloc(strlen(cmdline) + 2);
 	if (!q) {
-		printf("%s(): Fail to lmalloc a buffer to exec %s\n",
+		printf("%s(): Fail to malloc a buffer to exec %s\n",
 			__func__, cmdline);
 		return;
 	}
@@ -147,7 +145,7 @@
 		new_linux_kernel((char *)kernel, (char *)cmdline);
 	}
 
-	lfree((void *)kernel);
+	free((void *)kernel);
 
 	/* If this returns, something went bad; return to menu */
 }
diff --git a/com32/elflink/ldlinux/ldlinux.c b/com32/elflink/ldlinux/ldlinux.c
index 6f9f20f..a8b1b38 100644
--- a/com32/elflink/ldlinux/ldlinux.c
+++ b/com32/elflink/ldlinux/ldlinux.c
@@ -12,6 +12,7 @@
 #include "config.h"
 #include "syslinux/adv.h"
 #include "syslinux/boot.h"
+#include "syslinux/config.h"
 
 #include <sys/module.h>
 
@@ -290,6 +291,8 @@
 
 	parse_configs(config_argv);
 
+	__syslinux_set_serial_console_info();
+
 	adv = syslinux_getadv(ADV_BOOTONCE, &count);
 	if (adv && count) {
 		/*
diff --git a/com32/elflink/ldlinux/msg.c b/com32/elflink/ldlinux/msg.c
index 2efcc79..9ded33e 100644
--- a/com32/elflink/ldlinux/msg.c
+++ b/com32/elflink/ldlinux/msg.c
@@ -4,7 +4,7 @@
 #include <graphics.h>
 
 static uint8_t TextAttribute;	/* Text attribute for message file */
-static uint8_t DisplayMask;	/* Display modes mask */
+extern uint8_t DisplayMask;	/* Display modes mask */
 
 /* Routine to interpret next print char */
 static void (*NextCharJump)(uint8_t);
@@ -42,27 +42,27 @@
 		if (ch == 0x1A)
 			break;
 
-		/*
-		 * 01h = text mode
-		 * 02h = graphics mode
-		 */
-		UsingVGA &= 0x1;
-		UsingVGA += 1;
-
 		NextCharJump(ch);	/* Do what shall be done */
 	}
 
+	DisplayMask = 0x07;
+
 	fclose(f);
 	return 0;
 }
 
+static inline int display_mask_vga(void)
+{
+	uint8_t mask = UsingVGA & 0x1;
+	return (DisplayMask & ++mask);
+}
+
 static void msg_setbg(uint8_t data)
 {
 	if (unhexchar(&data) == 0) {
 		data <<= 4;
-		if (DisplayMask & UsingVGA) {
+		if (display_mask_vga())
 			TextAttribute = data;
-		}
 
 		NextCharJump = msg_setfg;
 	} else {
@@ -74,7 +74,7 @@
 static void msg_setfg(uint8_t data)
 {
 	if (unhexchar(&data) == 0) {
-		if (DisplayMask & UsingVGA) {
+		if (display_mask_vga()) {
 			/* setbg set foreground to 0 */
 			TextAttribute |= data;
 		}
@@ -89,6 +89,34 @@
 	NextCharJump = msg_setbg;
 }
 
+/* Convert ANSI colors to PC display attributes */
+static int convert_to_pcdisplay[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
+
+static void set_fgbg(void)
+{
+	uint8_t bg, fg;
+
+	fg = convert_to_pcdisplay[(TextAttribute & 0x7)];
+	bg = convert_to_pcdisplay[((TextAttribute >> 4) & 0x7)];
+
+	printf("\033[");
+	if (TextAttribute & 0x8)
+		printf("1;"); /* Foreground bright */
+
+	printf("3%dm\033[", fg);
+
+	if (TextAttribute & 0x80)
+		printf("5;"); /* Foreground blink */
+
+	printf("4%dm", bg);
+}
+
+static void msg_formfeed(void)
+{
+	set_fgbg();
+	printf("\033[2J\033[H\033[0m");
+}
+
 static void msg_novga(void)
 {
 	syslinux_force_text_mode();
@@ -138,36 +166,19 @@
 	VGAFilePtr = (uint16_t *)VGAFileBuf;
 }
 
-/* Convert ANSI colors to PC display attributes */
-static int convert_to_pcdisplay[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
-
 static void msg_normal(uint8_t data)
 {
-	uint8_t bg, fg;
+	/* 0x1 = text mode, 0x2 = graphics mode */
+	if (!display_mask_vga() || !(DisplayCon & 0x01)) {
+		/* Write to serial port */
+		if (DisplayMask & 0x4)
+			write_serial(data);
 
-	/* Write to serial port */
-	if (DisplayMask & 0x4)
-		write_serial(data);
-
-	if (!(DisplayMask & UsingVGA))
 		return;		/* Not screen */
+	}
 
-	if (!(DisplayCon & 0x01))
-		return;
-
-	fg = convert_to_pcdisplay[(TextAttribute & 0x7)];
-	bg = convert_to_pcdisplay[((TextAttribute >> 4) & 0x7)];
-
-	printf("\033[");
-	if (TextAttribute & 0x40)
-		printf("1;"); /* Foreground bright */
-
-	printf("3%dm\033[", fg);
-
-	if (TextAttribute & 0x80)
-		printf("5;"); /* Foreground blink */
-
-	printf("4%dm%c\033[0m", bg, data);
+	set_fgbg();
+	printf("%c\033[0m", data);
 }
 
 static void msg_modectl(uint8_t data)
@@ -191,6 +202,9 @@
 		break;
 	case 0x0D:		/* Ignore <CR> */
 		break;
+	case 0x0C:		/* <FF> = clear screen */
+		msg_formfeed();
+		break;
 	case 0x19:		/* <EM> = return to text mode */
 		msg_novga();
 		break;
diff --git a/com32/elflink/ldlinux/readconfig.c b/com32/elflink/ldlinux/readconfig.c
index 6a419c6..a2421e9 100644
--- a/com32/elflink/ldlinux/readconfig.c
+++ b/com32/elflink/ldlinux/readconfig.c
@@ -26,6 +26,7 @@
 #include <syslinux/config.h>
 #include <dprintf.h>
 #include <ctype.h>
+#include <bios.h>
 #include <core.h>
 #include <fs.h>
 
@@ -79,7 +80,6 @@
 short includelevel = 1;		//nesting level
 short defaultlevel = 0;		//the current level of default
 short vkernel = 0;		//have we seen any "label" statements?
-short displaycon = 1;		//conio.inc
 extern short NoHalt;		//idle.c
 
 const char *onerror = NULL;	//"onerror" command line
@@ -442,12 +442,12 @@
 {
     struct menu_entry *me;
 
-    eprintf("\n");
+    printf("\n");
     for (me = all_entries; me; me = me->next ) {
 	if (!strncmp(prefix, me->label, len))
-	    eprintf(" %s", me->label);
+	    printf(" %s", me->label);
     }
-    eprintf("\n");
+    printf("\n");
 }
 
 struct menu_entry *find_label(const char *str)
@@ -498,18 +498,24 @@
     return str;
 }
 
-static const char *refdup_word(char **p)
+static const char *__refdup_word(char *p, char **ref)
 {
-    char *sp = *p;
+    char *sp = p;
     char *ep = sp;
 
     while (*ep && !my_isspace(*ep))
 	ep++;
 
-    *p = ep;
+    if (ref)
+	*ref = ep;
     return refstrndup(sp, ep - sp);
 }
 
+static const char *refdup_word(char **p)
+{
+    return __refdup_word(*p, p);
+}
+
 int my_isxdigit(char c)
 {
     unsigned int uc = c;
@@ -690,7 +696,7 @@
 		return;
 
 	if (cm->fkeyhelp[fkey].textname) {
-		eprintf("\n");
+		printf("\n");
 		get_msg_file((char *)cm->fkeyhelp[fkey].textname);
 	}
 }
@@ -729,12 +735,6 @@
 extern void sirq_install(void);
 extern void write_serial_str(char *);
 
-static inline void io_delay(void)
-{
-	outb(0, 0x80);
-	outb(0, 0x80);
-}
-
 extern void loadfont(char *);
 extern void loadkeys(char *);
 
@@ -1065,8 +1065,8 @@
 	    p = skipspace(p + 5);
 	    /* when first time see "label", it will not really record anything */
 	    record(m, &ld, append);
-	    ld.label = refstrdup(p);
-	    ld.kernel = refstrdup(p);
+	    ld.label = __refdup_word(p, NULL);
+	    ld.kernel = __refdup_word(p, NULL);
 	    /* feng: this is the default type for all */
 	    ld.type = KT_KERNEL;
 	    ld.passwd = NULL;
@@ -1174,7 +1174,7 @@
 	} else if (looking_at(p, "prompt")) {
 		forceprompt = atoi(skipspace(p + 6));
 	} else if (looking_at(p, "console")) {
-		displaycon = atoi(skipspace(p + 7));
+		DisplayCon = atoi(skipspace(p + 7));
 	} else if (looking_at(p, "allowoptions")) {
 		allowoptions = atoi(skipspace(p + 12));
 	} else if (looking_at(p, "noescape")) {
@@ -1311,8 +1311,9 @@
 			write_serial_str(syslinux_banner);
 			write_serial_str(copyright_str);
 		}
+
 	} else if (looking_at(p, "say")) {
-		eprintf("%s\n", p+4);
+		printf("%s\n", p+4);
 	} else if (looking_at(p, "path")) {
 		/* PATH-based lookup */
 		const char *new_path;
@@ -1331,7 +1332,7 @@
 			free(PATH);
 			PATH = _p;
 		} else
-			eprintf("Failed to realloc PATH\n");
+			printf("Failed to realloc PATH\n");
 	}
     }
 }
@@ -1350,15 +1351,15 @@
 	if (fd < 0)
 		return fd;
 
-	f = fdopen(fd, mode);
-	parse_config_file(f);
-
 	if (config_cwd[0]) {
 		if (chdir(config_cwd) < 0)
 			printf("Failed to chdir to %s\n", config_cwd);
 		config_cwd[0] = '\0';
 	}
 
+	f = fdopen(fd, mode);
+	parse_config_file(f);
+
 	return 0;
 }
 
diff --git a/com32/gfxboot/Makefile b/com32/gfxboot/Makefile
index 98d6a03..824d7d0 100644
--- a/com32/gfxboot/Makefile
+++ b/com32/gfxboot/Makefile
@@ -20,7 +20,7 @@
 
 OBJS = gfxboot.o realmode_callback.o
 
-gfxboot.c32 : $(OBJS) $(LIBS) $(C_LIBS)
+gfxboot.elf : $(OBJS) $(LIBS) $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
 realmode_callback.o: realmode_callback.asm
diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile
index 4d0bb82..e3e30d7 100644
--- a/com32/gpllib/Makefile
+++ b/com32/gpllib/Makefile
@@ -17,14 +17,14 @@
 INCDIR   = /usr/include
 COM32DIR = $(AUXDIR)/com32
 
-all: makeoutputdirs libcom32gpl.c32
+all: makeoutputdirs libgpl.c32
 
 makeoutputdirs:
 	@mkdir -p $(foreach b, \
 		$(addprefix $(OBJ),$(sort $(dir $(LIBOBJS)))),$(b))
 
-libcom32gpl.c32 : $(LIBOBJS)
-	$(LD) -shared $(LDFLAGS) -soname $(@F) -o $@ $^
+libgpl.elf : $(LIBOBJS)
+	$(LD) -shared $(LDFLAGS) -soname $(patsubst %.elf,%.c32,$(@F)) -o $@ $^
 
 tidy dist clean:
 	find . \( -name \*.o -o -name .\*.d -o -name \*.tmp \) -print0 | \
@@ -38,7 +38,7 @@
 # there is a better way to do it.
 install: all
 	mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR)
-	install -m 644 libcom32gpl.c32 $(INSTALLROOT)$(COM32DIR)
+	install -m 644 libgpl.c32 $(INSTALLROOT)$(COM32DIR)
 	mkdir -p $(INSTALLROOT)$(COM32DIR)/include/
 	cp -r $(SRC)/../gplinclude $(INSTALLROOT)$(COM32DIR)/include/
 
diff --git a/com32/hdt/Makefile b/com32/hdt/Makefile
index 362b487..80f2d0a 100644
--- a/com32/hdt/Makefile
+++ b/com32/hdt/Makefile
@@ -51,7 +51,7 @@
 
 all: $(MODULES) $(TESTFILES)
 
-hdt.c32 : $(OBJS) $(LIBS) $(C_LIBS)
+hdt.elf : $(OBJS) $(LIBS) $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
 memtest:
diff --git a/com32/hdt/hdt.c b/com32/hdt/hdt.c
index 653995d..67b3ab0 100644
--- a/com32/hdt/hdt.c
+++ b/com32/hdt/hdt.c
@@ -48,7 +48,7 @@
 int main(const int argc, const char *argv[])
 {
     char version_string[256];
-    struct s_hardware hardware;
+    static struct s_hardware hardware;
 
     snprintf(version_string, sizeof version_string, "%s %s (%s)",
 	     PRODUCT_NAME, VERSION, CODENAME);
diff --git a/com32/include/sys/exec.h b/com32/include/sys/exec.h
index ac05c27..f4559d1 100644
--- a/com32/include/sys/exec.h
+++ b/com32/include/sys/exec.h
@@ -34,27 +34,6 @@
 extern int spawn_load(const char *name, int argc, char **argv);
 
 /**
- * exec_init - Initialize the dynamic execution environment.
- *
- * Among others, it initializes the module subsystem and loads the root
- * module into memory. You should note the difference between the module
- * management API, and the execution API:
- *  - the module system is a static one - it only manages the data structures
- *  and their relationship. It does not describe the way modules are executed,
- *  when and how they are loaded/unloaded, etc. It acts as a service layer for
- *  the execution API.
- *  - the execution environment is the dynamic part of the SYSLINUX dynamic
- *  module API - it implements the behavior of the modules: it
- *  triggers the execution of initialization and termination functions for
- *  libraries, executes the modules marked as executable, handles dynamic
- *  memory cleanup, etc. In other words, at this layer the code and data
- *  loaded by the lower module layer gets to be executed by the CPU,
- *  thus becoming part of the SYSLINUX environment.
- */
-extern int exec_init(void);
-
-
-/**
  * spawnv - Executes a program in the current environment.
  * @name:	the name of the program to spawn, including the extension
  * 			(e.g. 'hello.c32')
diff --git a/com32/include/sys/module.h b/com32/include/sys/module.h
index 02778fb..c1d4253 100644
--- a/com32/include/sys/module.h
+++ b/com32/include/sys/module.h
@@ -199,6 +199,17 @@
 	list_for_each_entry_safe(m, n, &modules_head, list)
 
 /**
+ * module_current - return the module at the head of the module list.
+ */
+static inline struct elf_module *module_current(void)
+{
+	struct elf_module *head;
+
+	head = list_entry((&modules_head)->next, typeof(*head), list);
+	return head;
+}
+
+/**
  * modules_init - initialize the module subsystem.
  *
  * This function must be called before any module operation is to be performed.
@@ -242,18 +253,6 @@
 
 
 /**
- * module_load_shallow - loads a shallow ELF module into memory.
- * @module:	the module descriptor returned by module_alloc.
- *
- * The function reads the module file, checks whether the file has a valid
- * structure, then loads into memory the module metadata. The metadata currently
- * contains a symbol table that describes code & data allocated by other means.
- * Its current use is to describe the root COM32 module to the rest of the
- * module subsystem.
- */
-extern int module_load_shallow(struct elf_module *module, Elf_Addr base_addr);
-
-/**
  * module_unload - unloads the module from the system.
  * @module: the module descriptor structure.
  *
diff --git a/com32/include/syslinux/config.h b/com32/include/syslinux/config.h
index 7bdcdd6..8f4124c 100644
--- a/com32/include/syslinux/config.h
+++ b/com32/include/syslinux/config.h
@@ -156,6 +156,8 @@
     uint16_t flowctl;
 };
 
+extern void __syslinux_set_serial_console_info(void);
+
 extern __nocommon struct syslinux_serial_console_info
     __syslinux_serial_console_info;
 static inline const struct syslinux_serial_console_info
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 2a47fc6..1624ae7 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -89,9 +89,9 @@
 	@mkdir -p $(foreach b, \
 		$(addprefix $(OBJ)/,$(sort $(dir $(LIBOBJS) $(MINLIBOBJS) $(CORELIBOBJS)))),$(b))
 
-libcom32.c32 : $(LIBOBJS)
+libcom32.elf : $(LIBOBJS)
 	rm -f $@
-	$(LD) -shared $(LDFLAGS) -soname $(@F) -o $@ $^
+	$(LD) -shared $(LDFLAGS) -soname $(patsubst %.elf,%.c32,$(@F)) -o $@ $^
 
 libcom32min.a : $(MINLIBOBJS)
 	rm -f $@
@@ -109,7 +109,7 @@
 		xargs -0r rm -f
 
 spotless: clean
-	rm -f *.a
+	rm -f *.a *.c32
 	rm -f *~ \#* */*~ */\#*
 
 install: all
diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c
index 2ecc9e5..4c83789 100644
--- a/com32/lib/sys/module/common.c
+++ b/com32/lib/sys/module/common.c
@@ -185,6 +185,11 @@
 struct elf_module *module_alloc(const char *name) {
 	struct elf_module *result = malloc(sizeof(struct elf_module));
 
+	if (!result) {
+	    dprintf("module: Failed to alloc elf_module\n");
+	    return NULL;
+	}
+
 	memset(result, 0, sizeof(struct elf_module));
 
 	INIT_LIST_HEAD(&result->list);
diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c
index 0d27c92..e3d9928 100644
--- a/com32/lib/sys/module/elf_module.c
+++ b/com32/lib/sys/module/elf_module.c
@@ -218,7 +218,7 @@
 	CHECKED(res, prepare_dynlinking(module), error);
 	//printf("check... 4\n");
 
-	head =  list_entry((&modules_head)->next, typeof(*head), list);
+	head = module_current();
 
 	/* Find modules we need to load as dependencies */
 	if (module->str_table) {
diff --git a/com32/lib/sys/module/exec.c b/com32/lib/sys/module/exec.c
index 559bafc..18c8306 100644
--- a/com32/lib/sys/module/exec.c
+++ b/com32/lib/sys/module/exec.c
@@ -18,32 +18,8 @@
 
 #define DBG_PRINT(fmt, args...) dprintf("[EXEC] " fmt, ##args)
 
-static struct elf_module    *mod_root = NULL;
 struct elf_module *__syslinux_current = NULL;
 
-int exec_init(void)
-{
-	int res;
-
-	res = modules_init();
-	if (res != 0)
-		return res;
-
-	// Load the root module
-	mod_root = module_alloc(EXEC_ROOT_NAME);
-
-	if (mod_root == NULL)
-		return -1;
-
-	res = module_load_shallow(mod_root, 0);
-	if (res != 0) {
-		mod_root = NULL;
-		return res;
-	}
-
-	return 0;
-}
-
 int get_module_type(struct elf_module *module)
 {
 	if(module->main_func) return EXEC_MODULE;
@@ -161,8 +137,6 @@
 }
 #endif
 
-struct elf_module *cur_module;
-
 /*
  * Load a module and runs its start function.
  *
@@ -185,7 +159,7 @@
 	struct elf_module *previous;
 	//malloc_tag_t prev_mem_tag;
 	struct elf_module *module = module_alloc(name);
-	struct elf_module *prev_module;
+	struct elf_module *cur_module;
 	int type;
 
 	dprintf("enter: name = %s", name);
@@ -200,23 +174,11 @@
 		}
 	}
 
+	cur_module = module_current();
 	if (!strcmp(cur_module->name, module->name)) {
 		dprintf("We is running this module %s already!", module->name);
 
-		/*
-		 * If we're already running the module and it's of
-		 * type EXEC_MODULE, then just return. We don't reload
-		 * the module because that might cause us to re-run
-		 * the init functions, which will cause us to run the
-		 * main function, which will take control of this
-		 * process.
-		 *
-		 * This can happen if some other EXEC_MODULE is
-		 * resolving a symbol that is exported by the current
-		 * EXEC_MODULE.
-		 */
-		if (get_module_type(module) == EXEC_MODULE)
-			return 0;
+		module_unload(cur_module);
 	}
 
 	res = module_load(module);
@@ -224,11 +186,9 @@
 		goto out;
 
 	type = get_module_type(module);
-	prev_module = cur_module;
-	cur_module = module;
 
 	dprintf("type = %d, prev = %s, cur = %s",
-		type, prev_module->name, cur_module->name);
+		type, cur_module->name, module->name);
 
 	if(type==EXEC_MODULE)
 	{
@@ -256,7 +216,6 @@
 		// Restore the process context
 		__syslinux_current = previous;
 
-		cur_module = prev_module;
 		res = module_unload(module);
 
 		if (res != 0)
diff --git a/com32/lib/sys/module/i386/elf_module.c b/com32/lib/sys/module/i386/elf_module.c
index a379255..d30f4ce 100644
--- a/com32/lib/sys/module/i386/elf_module.c
+++ b/com32/lib/sys/module/i386/elf_module.c
@@ -46,6 +46,9 @@
 
 	// Load the PHT
 	pht = malloc(elf_hdr->e_phnum * elf_hdr->e_phentsize);
+	if (!pht)
+		return -1;
+
 	image_read(pht, elf_hdr->e_phnum * elf_hdr->e_phentsize, module);
 
 	// Compute the memory needings of the module
@@ -149,6 +152,11 @@
 
 	// Load the SHT
 	sht = malloc(elf_hdr->e_shnum * elf_hdr->e_shentsize);
+	if (!sht) {
+		res = -1;
+		goto out;
+	}
+
 	image_read(sht, elf_hdr->e_shnum * elf_hdr->e_shentsize, module);
 
 	// Setup the symtable size
diff --git a/com32/lib/sys/module/i386/shallow_module.c b/com32/lib/sys/module/i386/shallow_module.c
deleted file mode 100644
index fbcf781..0000000
--- a/com32/lib/sys/module/i386/shallow_module.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * shallow_module.c
- *
- *  Created on: Aug 11, 2008
- *      Author: Stefan Bucur <stefanb@zytor.com>
- */
-
-
-#include <string.h>
-#include <sys/module.h>
-
-#include "common.h"
-#include "elfutils.h"
-
-
-static int check_header_shallow(Elf32_Ehdr *elf_hdr) {
-	int res;
-
-	res = check_header_common(elf_hdr);
-
-	if (res != 0)
-		return res;
-
-	if (elf_hdr->e_shoff == 0x00000000) {
-		DBG_PRINT("SHT missing\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int load_shallow_sections(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
-	int i;
-	int res = 0;
-	void *sht = NULL;
-	void *buffer = NULL;
-	Elf32_Shdr *crt_sht;
-	Elf32_Off buff_offset;
-
-	Elf32_Off min_offset = 0xFFFFFFFF;
-	Elf32_Off max_offset = 0x00000000;
-	Elf32_Word max_align = 0x1;
-
-	Elf32_Off sym_offset = 0xFFFFFFFF;
-	Elf32_Off str_offset = 0xFFFFFFFF;
-
-
-	char *sh_strtable;
-
-	// We buffer the data up to the SHT
-	buff_offset = module->u.l._cr_offset;
-
-	buffer = malloc(elf_hdr->e_shoff - buff_offset);
-	// Get to the SHT
-	image_read(buffer, elf_hdr->e_shoff - buff_offset, module);
-
-	// Load the SHT
-	sht = malloc(elf_hdr->e_shnum * elf_hdr->e_shentsize);
-	image_read(sht, elf_hdr->e_shnum * elf_hdr->e_shentsize, module);
-
-	// Get the string table of the section names
-	crt_sht = (Elf32_Shdr*)(sht + elf_hdr->e_shstrndx * elf_hdr->e_shentsize);
-	sh_strtable = (char*)(buffer + (crt_sht->sh_offset - buff_offset));
-
-	for (i = 0; i < elf_hdr->e_shnum; i++) {
-		crt_sht = (Elf32_Shdr*)(sht + i*elf_hdr->e_shentsize);
-
-		if (strcmp(".symtab", sh_strtable + crt_sht->sh_name) == 0) {
-			// We found the symbol table
-			min_offset = MIN(min_offset, crt_sht->sh_offset);
-			max_offset = MAX(max_offset, crt_sht->sh_offset + crt_sht->sh_size);
-			max_align = MAX(max_align, crt_sht->sh_addralign);
-
-			sym_offset = crt_sht->sh_offset;
-
-			module->syment_size = crt_sht->sh_entsize;
-			module->symtable_size = crt_sht->sh_size / crt_sht->sh_entsize;
-		}
-		if (strcmp(".strtab", sh_strtable + crt_sht->sh_name) == 0) {
-			// We found the string table
-			min_offset = MIN(min_offset, crt_sht->sh_offset);
-			max_offset = MAX(max_offset, crt_sht->sh_offset + crt_sht->sh_size);
-			max_align = MAX(max_align, crt_sht->sh_addralign);
-
-			str_offset = crt_sht->sh_offset;
-
-			module->strtable_size = crt_sht->sh_size;
-		}
-	}
-
-	if (elf_malloc(&module->module_addr, max_align,
-			max_offset - min_offset) != 0) {
-		DBG_PRINT("Could not allocate sections\n");
-		goto out;
-	}
-
-	// Copy the data
-	image_seek(min_offset, module);
-	image_read(module->module_addr, max_offset - min_offset, module);
-
-	// Setup module information
-	module->module_size = max_offset - min_offset;
-	module->str_table = (char*)(module->module_addr + (str_offset - min_offset));
-	module->sym_table = module->module_addr + (sym_offset - min_offset);
-
-out:
-	// Release the SHT
-	if (sht != NULL)
-		free(sht);
-
-	// Release the buffer
-	if (buffer != NULL)
-		free(buffer);
-
-	return res;
-}
-
-
-int module_load_shallow(struct elf_module *module, Elf32_Addr base_addr) {
-	int res;
-	Elf32_Ehdr elf_hdr;
-
-	// Do not allow duplicate modules
-	if (module_find(module->name) != NULL) {
-		DBG_PRINT("Module already loaded.\n");
-		return -1;
-	}
-
-	res = image_load(module);
-
-	if (res < 0)
-		return res;
-
-	module->shallow = 1;
-
-	CHECKED(res, image_read(&elf_hdr, sizeof(Elf32_Ehdr), module), error);
-
-	// Checking the header signature and members
-	CHECKED(res, check_header_shallow(&elf_hdr), error);
-
-	CHECKED(res, load_shallow_sections(module, &elf_hdr), error);
-	module->base_addr = base_addr;
-
-	// Check the symbols for duplicates / missing definitions
-	CHECKED(res, check_symbols(module), error);
-
-	// Add the module at the beginning of the module list
-	list_add(&module->list, &modules_head);
-
-	// The file image is no longer needed
-	image_unload(module);
-
-	DBG_PRINT("SHALLOW MODULE %s LOADED SUCCESSFULLY\n", module->name);
-
-	return 0;
-
-error:
-	image_unload(module);
-
-	return res;
-}
diff --git a/com32/lib/sys/module/shallow_module.c b/com32/lib/sys/module/shallow_module.c
deleted file mode 100644
index 8a88e40..0000000
--- a/com32/lib/sys/module/shallow_module.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * shallow_module.c
- *
- *  Created on: Aug 11, 2008
- *      Author: Stefan Bucur <stefanb@zytor.com>
- */
-
-
-#include <string.h>
-#include <sys/module.h>
-
-#include "common.h"
-#include "elfutils.h"
-
-
-static int check_header_shallow(Elf32_Ehdr *elf_hdr) {
-	int res;
-
-	res = check_header_common(elf_hdr);
-
-	if (res != 0)
-		return res;
-
-	if (elf_hdr->e_shoff == 0x00000000) {
-		DBG_PRINT("SHT missing\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int load_shallow_sections(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
-	int i;
-	int res = 0;
-	char *sht = NULL;
-	char *buffer = NULL;
-	Elf32_Shdr *crt_sht;
-	Elf32_Off buff_offset;
-
-	Elf32_Off min_offset = 0xFFFFFFFF;
-	Elf32_Off max_offset = 0x00000000;
-	Elf32_Word max_align = 0x1;
-
-	Elf32_Off sym_offset = 0xFFFFFFFF;
-	Elf32_Off str_offset = 0xFFFFFFFF;
-
-
-	char *sh_strtable;
-
-	// We buffer the data up to the SHT
-	buff_offset = module->u.l._cr_offset;
-
-	buffer = malloc(elf_hdr->e_shoff - buff_offset);
-	// Get to the SHT
-	image_read(buffer, elf_hdr->e_shoff - buff_offset, module);
-
-	// Load the SHT
-	sht = malloc(elf_hdr->e_shnum * elf_hdr->e_shentsize);
-	image_read(sht, elf_hdr->e_shnum * elf_hdr->e_shentsize, module);
-
-	// Get the string table of the section names
-	crt_sht = (Elf32_Shdr*)(sht + elf_hdr->e_shstrndx * elf_hdr->e_shentsize);
-	sh_strtable = (char*)(buffer + (crt_sht->sh_offset - buff_offset));
-
-	for (i = 0; i < elf_hdr->e_shnum; i++) {
-		crt_sht = (Elf32_Shdr*)(sht + i*elf_hdr->e_shentsize);
-
-		if (strcmp(".symtab", sh_strtable + crt_sht->sh_name) == 0) {
-			// We found the symbol table
-			min_offset = MIN(min_offset, crt_sht->sh_offset);
-			max_offset = MAX(max_offset, crt_sht->sh_offset + crt_sht->sh_size);
-			max_align = MAX(max_align, crt_sht->sh_addralign);
-
-			sym_offset = crt_sht->sh_offset;
-
-			module->syment_size = crt_sht->sh_entsize;
-			module->symtable_size = crt_sht->sh_size / crt_sht->sh_entsize;
-		}
-		if (strcmp(".strtab", sh_strtable + crt_sht->sh_name) == 0) {
-			// We found the string table
-			min_offset = MIN(min_offset, crt_sht->sh_offset);
-			max_offset = MAX(max_offset, crt_sht->sh_offset + crt_sht->sh_size);
-			max_align = MAX(max_align, crt_sht->sh_addralign);
-
-			str_offset = crt_sht->sh_offset;
-
-			module->strtable_size = crt_sht->sh_size;
-		}
-	}
-
-	if (elf_malloc(&module->module_addr, max_align,
-			max_offset - min_offset) != 0) {
-		DBG_PRINT("Could not allocate sections\n");
-		goto out;
-	}
-
-	// Copy the data
-	image_seek(min_offset, module);
-	image_read(module->module_addr, max_offset - min_offset, module);
-
-	// Setup module information
-	module->module_size = max_offset - min_offset;
-	module->str_table = (char *)module->module_addr + (str_offset - min_offset);
-	module->sym_table = (char *)module->module_addr + (sym_offset - min_offset);
-
-out:
-	// Release the SHT
-	if (sht != NULL)
-		free(sht);
-
-	// Release the buffer
-	if (buffer != NULL)
-		free(buffer);
-
-	return res;
-}
-
-
-int module_load_shallow(struct elf_module *module, Elf32_Addr base_addr) {
-	int res;
-	Elf32_Ehdr elf_hdr;
-
-	// Do not allow duplicate modules
-	if (module_find(module->name) != NULL) {
-		DBG_PRINT("Module already loaded.\n");
-		return -1;
-	}
-
-	res = image_load(module);
-
-	if (res < 0)
-		return res;
-
-	module->shallow = 1;
-
-	CHECKED(res, image_read(&elf_hdr, sizeof(Elf32_Ehdr), module), error);
-
-	// Checking the header signature and members
-	CHECKED(res, check_header_shallow(&elf_hdr), error);
-
-	CHECKED(res, load_shallow_sections(module, &elf_hdr), error);
-	module->base_addr = base_addr;
-
-	// Check the symbols for duplicates / missing definitions
-	CHECKED(res, check_symbols(module), error);
-
-	// Add the module at the beginning of the module list
-	list_add(&module->list, &modules_head);
-
-	// The file image is no longer needed
-	image_unload(module);
-
-	DBG_PRINT("SHALLOW MODULE %s LOADED SUCCESSFULLY\n", module->name);
-
-	return 0;
-
-error:
-	image_unload(module);
-
-	return res;
-}
diff --git a/com32/lib/sys/module/x86_64/elf_module.c b/com32/lib/sys/module/x86_64/elf_module.c
index 64404a1..dd24bd1 100644
--- a/com32/lib/sys/module/x86_64/elf_module.c
+++ b/com32/lib/sys/module/x86_64/elf_module.c
@@ -46,6 +46,9 @@
 
 	// Load the PHT
 	pht = malloc(elf_hdr->e_phnum * elf_hdr->e_phentsize);
+	if (!pht)
+		return -1;
+
 	image_read(pht, elf_hdr->e_phnum * elf_hdr->e_phentsize, module);
 
 	// Compute the memory needings of the module
@@ -149,6 +152,11 @@
 
 	// Load the SHT
 	sht = malloc(elf_hdr->e_shnum * elf_hdr->e_shentsize);
+	if (!sht) {
+		res = -1;
+		goto out;
+	}
+
 	image_read(sht, elf_hdr->e_shnum * elf_hdr->e_shentsize, module);
 
 	// Setup the symtable size
diff --git a/com32/lib/sys/module/x86_64/shallow_module.c b/com32/lib/sys/module/x86_64/shallow_module.c
deleted file mode 100644
index b724815..0000000
--- a/com32/lib/sys/module/x86_64/shallow_module.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * shallow_module.c
- *
- *  Created on: Aug 11, 2008
- *      Author: Stefan Bucur <stefanb@zytor.com>
- */
-
-
-#include <string.h>
-#include <sys/module.h>
-
-#include "common.h"
-#include "elfutils.h"
-
-
-static int check_header_shallow(Elf64_Ehdr *elf_hdr) {
-	int res;
-
-	res = check_header_common(elf_hdr);
-
-	if (res != 0)
-		return res;
-
-	if (elf_hdr->e_shoff == 0x00000000) {
-		DBG_PRINT("SHT missing\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int load_shallow_sections(struct elf_module *module, Elf64_Ehdr *elf_hdr) {
-	int i;
-	int res = 0;
-	void *sht = NULL;
-	void *buffer = NULL;
-	Elf64_Shdr *crt_sht;
-	Elf64_Off buff_offset;
-
-	Elf64_Off min_offset = 0xFFFFFFFFFFFFFFFF;
-	Elf64_Off max_offset = 0x0000000000000000;
-	Elf64_Word max_align = 0x1;
-
-	Elf64_Off sym_offset = 0xFFFFFFFFFFFFFFFF;
-	Elf64_Off str_offset = 0xFFFFFFFFFFFFFFFF;
-
-
-	char *sh_strtable;
-
-	// We buffer the data up to the SHT
-	buff_offset = module->u.l._cr_offset;
-
-	buffer = malloc(elf_hdr->e_shoff - buff_offset);
-	// Get to the SHT
-	image_read(buffer, elf_hdr->e_shoff - buff_offset, module);
-
-	// Load the SHT
-	sht = malloc(elf_hdr->e_shnum * elf_hdr->e_shentsize);
-	image_read(sht, elf_hdr->e_shnum * elf_hdr->e_shentsize, module);
-
-	// Get the string table of the section names
-	crt_sht = (Elf64_Shdr*)(sht + elf_hdr->e_shstrndx * elf_hdr->e_shentsize);
-	sh_strtable = (char*)(buffer + (crt_sht->sh_offset - buff_offset));
-
-	for (i = 0; i < elf_hdr->e_shnum; i++) {
-		crt_sht = (Elf64_Shdr*)(sht + i*elf_hdr->e_shentsize);
-
-		if (strcmp(".symtab", sh_strtable + crt_sht->sh_name) == 0) {
-			// We found the symbol table
-			min_offset = MIN(min_offset, crt_sht->sh_offset);
-			max_offset = MAX(max_offset, crt_sht->sh_offset + crt_sht->sh_size);
-			max_align = MAX(max_align, crt_sht->sh_addralign);
-
-			sym_offset = crt_sht->sh_offset;
-
-			module->syment_size = crt_sht->sh_entsize;
-			module->symtable_size = crt_sht->sh_size / crt_sht->sh_entsize;
-		}
-		if (strcmp(".strtab", sh_strtable + crt_sht->sh_name) == 0) {
-			// We found the string table
-			min_offset = MIN(min_offset, crt_sht->sh_offset);
-			max_offset = MAX(max_offset, crt_sht->sh_offset + crt_sht->sh_size);
-			max_align = MAX(max_align, crt_sht->sh_addralign);
-
-			str_offset = crt_sht->sh_offset;
-
-			module->strtable_size = crt_sht->sh_size;
-		}
-	}
-
-	if (elf_malloc(&module->module_addr, max_align,
-			max_offset - min_offset) != 0) {
-		DBG_PRINT("Could not allocate sections\n");
-		goto out;
-	}
-
-	// Copy the data
-	image_seek(min_offset, module);
-	image_read(module->module_addr, max_offset - min_offset, module);
-
-	// Setup module information
-	module->module_size = max_offset - min_offset;
-	module->str_table = (char*)(module->module_addr + (str_offset - min_offset));
-	module->sym_table = module->module_addr + (sym_offset - min_offset);
-
-out:
-	// Release the SHT
-	if (sht != NULL)
-		free(sht);
-
-	// Release the buffer
-	if (buffer != NULL)
-		free(buffer);
-
-	return res;
-}
-
-
-int module_load_shallow(struct elf_module *module, Elf64_Addr base_addr) {
-	int res;
-	Elf64_Ehdr elf_hdr;
-
-	// Do not allow duplicate modules
-	if (module_find(module->name) != NULL) {
-		DBG_PRINT("Module already loaded.\n");
-		return -1;
-	}
-
-	res = image_load(module);
-
-	if (res < 0)
-		return res;
-
-	module->shallow = 1;
-
-	CHECKED(res, image_read(&elf_hdr, sizeof(Elf64_Ehdr), module), error);
-
-	// Checking the header signature and members
-	CHECKED(res, check_header_shallow(&elf_hdr), error);
-
-	CHECKED(res, load_shallow_sections(module, &elf_hdr), error);
-	module->base_addr = base_addr;
-
-	// Check the symbols for duplicates / missing definitions
-	CHECKED(res, check_symbols(module), error);
-
-	// Add the module at the beginning of the module list
-	list_add(&module->list, &modules_head);
-
-	// The file image is no longer needed
-	image_unload(module);
-
-	DBG_PRINT("SHALLOW MODULE %s LOADED SUCCESSFULLY\n", module->name);
-
-	return 0;
-
-error:
-	image_unload(module);
-
-	return res;
-}
diff --git a/com32/lib/syslinux/serial.c b/com32/lib/syslinux/serial.c
index bc41acf..041e850 100644
--- a/com32/lib/syslinux/serial.c
+++ b/com32/lib/syslinux/serial.c
@@ -38,7 +38,7 @@
 
 struct syslinux_serial_console_info __syslinux_serial_console_info;
 
-void __constructor __syslinux_get_serial_console_info(void)
+void __syslinux_set_serial_console_info(void)
 {
     uint16_t iobase, divisor, flowctl;
 
diff --git a/com32/libutil/Makefile b/com32/libutil/Makefile
index 5e94165..094f1ff 100644
--- a/com32/libutil/Makefile
+++ b/com32/libutil/Makefile
@@ -38,10 +38,10 @@
 	     quicksort.o
 LNXLIBOBJS = $(patsubst %.o,%.lo,$(LIBOBJS))
 
-all: libutil_com.c32 libutil_lnx.a
+all: libutil.c32 libutil_lnx.a
 
-libutil_com.c32: $(LIBOBJS)
-	$(LD) $(LDFLAGS) -soname $(@F) -o $@ $^
+libutil.elf: $(LIBOBJS)
+	$(LD) $(LDFLAGS) -soname $(patsubst %.elf,%.c32,$(@F)) -o $@ $^
 
 libutil_lnx.a: $(LNXLIBOBJS)
 	rm -f $@
diff --git a/com32/lua/src/Makefile b/com32/lua/src/Makefile
index 70a7e80..f3625e1 100644
--- a/com32/lua/src/Makefile
+++ b/com32/lua/src/Makefile
@@ -49,10 +49,11 @@
 
 all: $(MODULES) $(TESTFILES)
 
-$(LIBLUA) : $(LIBLUA_OBJS)
-	$(LD) -shared $(LDFLAGS) -o $@ $^
+liblua.elf : $(LIBLUA_OBJS)
+	$(LD) $(LDFLAGS) -shared -soname $(patsubst %.elf,%.c32,$(@F)) \
+		-o $@ $^
 
-lua.c32 : $(OBJS) $(LIBLUA) $(C_LIBS)
+lua.elf : $(OBJS) $(LIBLUA) $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
 tidy dist:
diff --git a/com32/mboot/Makefile b/com32/mboot/Makefile
index a3f61ba..e916436 100644
--- a/com32/mboot/Makefile
+++ b/com32/mboot/Makefile
@@ -27,7 +27,7 @@
 
 all: $(MODULES) $(TESTFILES)
 
-mboot.c32 : $(OBJS) $(C_LIBS)
+mboot.elf : $(OBJS) $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
 tidy dist:
diff --git a/com32/menu/Makefile b/com32/menu/Makefile
index 9f7a0e4..7c2d592 100644
--- a/com32/menu/Makefile
+++ b/com32/menu/Makefile
@@ -27,10 +27,10 @@
 
 all: $(MODULES) $(TESTFILES)
 
-vesamenu.c32: vesamenu.o $(COMMONOBJS) $(C_LIBS)
+menu.elf : menu.o $(COMMONOBJS) $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
-menu.c32: menu.o $(COMMONOBJS) $(C_LIBS)
+vesamenu.elf : vesamenu.o $(COMMONOBJS) $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
 tidy dist:
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index e794b3b..8965f5f 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -34,7 +34,7 @@
 dmitest.o: dmitest.c
 	$(CC) $(CFLAGS) $(GPLINCLUDE) -c -o $@ $<
 
-dmitest.c32 :  dmi_utils.o dmitest.o $(C_LIBS)
+dmitest.elf : dmi_utils.o dmitest.o $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
 tidy dist:
diff --git a/com32/rosh/Makefile b/com32/rosh/Makefile
index a4c0bc2..4d900f4 100644
--- a/com32/rosh/Makefile
+++ b/com32/rosh/Makefile
@@ -16,7 +16,7 @@
 ## ROSH Read Only Shell
 ##
 
-LIBS = $(objdir)/com32/libutil/libutil_com.c32 \
+LIBS = $(objdir)/com32/libutil/libutil.c32 \
 	$(objdir)/com32/lib/libcom32.c32
 
 VPATH = $(SRC)
diff --git a/com32/samples/Makefile b/com32/samples/Makefile
index ca04f64..06e9684 100644
--- a/com32/samples/Makefile
+++ b/com32/samples/Makefile
@@ -14,7 +14,7 @@
 ## samples for syslinux users
 ##
 
-LIBS = $(objdir)/com32/libutil/libutil_com.c32
+LIBS = $(objdir)/com32/libutil/libutil.c32
 
 VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
diff --git a/com32/sysdump/Makefile b/com32/sysdump/Makefile
index dca5d71..240edaa 100644
--- a/com32/sysdump/Makefile
+++ b/com32/sysdump/Makefile
@@ -44,7 +44,7 @@
 
 all: $(MODULES) $(TESTFILES)
 
-sysdump.c32 : $(OBJS) $(LIBS) $(C_LIBS)
+sysdump.elf : $(OBJS) $(LIBS) $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
 tidy dist:
diff --git a/core/bios.c b/core/bios.c
index 1becd28..bd8b4d8 100644
--- a/core/bios.c
+++ b/core/bios.c
@@ -537,7 +537,6 @@
 
 	/* Init the memory subsystem */
 	bios_free_mem = (uint16_t *)0x413;
-	mem_init();
 
 	/* CPU-dependent initialization and related checks. */
 	check_escapes();
diff --git a/core/conio.c b/core/conio.c
index a351fd1..5587203 100644
--- a/core/conio.c
+++ b/core/conio.c
@@ -45,6 +45,8 @@
 __export uint16_t DisplayCon = 0x01;	/* Display console enabled */
 __export uint8_t FlowOutput = 0;	/* Output to assert for serial flow */
 
+__export uint8_t DisplayMask = 0x07;	/* Display modes mask */
+
 uint8_t ScrollAttribute = 0x07; /* Grey on white (normal text color) */
 
 /*
@@ -75,6 +77,9 @@
 	if (!SerialPort)
 		return;
 
+	if (!(DisplayMask & 0x04))
+		return;
+
 	while (1) {
 		char ch;
 
@@ -162,21 +167,22 @@
 		/* Already-queued input? */
 		if (SerialTail == SerialHead) {
 			/* LSR */
-			data = inb(SerialPort + 5) & 1;
-			if (data) {
+			data = !(inb(SerialPort + 5) & 1);
+			if (!data) {
 				/* MSR */
 				data = inb(SerialPort + 6);
 
 				/* Required status bits */
-				if (data) {
-					data &= FlowIgnore;
-					if (data != FlowIgnore)
-						data = 0;
-					else
-						data = 1;
-				}
-			}
-		}
+				data &= FlowIgnore;
+
+				if (data == FlowIgnore)
+					data = 1;
+				else
+					data = 0;
+			} else
+				data = 1;
+		} else
+			data = 1;
 		sti();
 	}
 
@@ -221,7 +227,8 @@
 				sti(); /* We already know we'll consume data */
 				data = *SerialTail++;
 
-				SerialTail = (char *)((unsigned long)SerialTail & (serial_buf_size - 1));
+				if (SerialTail > SerialHead + serial_buf_size)
+					SerialTail = SerialHead;
 			} else {
 				/* LSR */
 				data = inb(SerialPort + 5) & 1;
diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c
index 1fa43bd..b277877 100644
--- a/core/elflink/load_env32.c
+++ b/core/elflink/load_env32.c
@@ -48,10 +48,10 @@
 };
 
 /*
-	Initializes the module subsystem by taking the core module ( shallow module ) and placing
-	it on top of the modules_head_list. Since the core module is initialized when declared
-	we technically don't need the exec_init() and module_load_shallow() procedures
-*/
+ * Initializes the module subsystem by taking the core module
+ * (preinitialized shallow module) and placing it on top of the
+ * modules_head_list.
+ */
 void init_module_subsystem(struct elf_module *module)
 {
     list_add(&module->list, &modules_head);
@@ -126,7 +126,7 @@
 	PATH = malloc(strlen(CurrentDirName) + 1);
 	if (!PATH) {
 		printf("Couldn't allocate memory for PATH\n");
-		return;
+		goto out;
 	}
 
 	strcpy(PATH, CurrentDirName);
@@ -147,15 +147,36 @@
 	 * a bit harder to find LDLINUX. If search_dirs() succeeds
 	 * in finding LDLINUX it will set the cwd.
 	 */
+	free(PATH);
 	fd = opendev(&__file_dev, NULL, O_RDONLY);
 	if (fd < 0)
 		return;
 
 	fp = &__file_info[fd];
 
-	if (!search_dirs(&fp->i.fd, search_directories, filenames, realname))
-		start_ldlinux(argv);
+	if (!search_dirs(&fp->i.fd, search_directories, filenames, realname)) {
+		char path[FILENAME_MAX];
 
+		/*
+		 * search_dirs() sets the current working directory if
+		 * it successfully opens the file. Set PATH to the
+		 * directory in which we found ldlinux.c32.
+		 */
+		if (!core_getcwd(path, sizeof(path)))
+			goto out;
+
+		PATH = malloc(strlen(path) + 1);
+		if (!PATH) {
+			printf("Couldn't allocate memory for PATH\n");
+			goto out;
+		}
+
+		strcpy(PATH, path);
+
+		start_ldlinux(argv);
+	}
+
+out:
 	writestr("\nFailed to load ldlinux.c32");
 }
 
diff --git a/core/fs/fs.c b/core/fs/fs.c
index 40f97d5..adcee91 100644
--- a/core/fs/fs.c
+++ b/core/fs/fs.c
@@ -40,9 +40,13 @@
  */
 void put_inode(struct inode *inode)
 {
-    while (inode && --inode->refcnt == 0) {
+    while (inode) {
 	struct inode *dead = inode;
-	inode = inode->parent;
+	int refcnt = --(dead->refcnt);
+	dprintf("put_inode %p name %s refcnt %u\n", dead, dead->name, refcnt);
+	if (refcnt)
+	    break;		/* We still have references */
+	inode = dead->parent;
 	if (dead->name)
 	    free((char *)dead->name);
 	free(dead);
@@ -108,77 +112,11 @@
     return fd;
 }
 
-void pm_mangle_name(com32sys_t *regs)
-{
-    const char *src = MK_PTR(regs->ds, regs->esi.w[0]);
-    char       *dst = MK_PTR(regs->es, regs->edi.w[0]);
-
-    mangle_name(dst, src);
-}
-
 __export void mangle_name(char *dst, const char *src)
 {
     this_fs->fs_ops->mangle_name(dst, src);
 }
 
-void getfssec(com32sys_t *regs)
-{
-    int sectors;
-    bool have_more;
-    uint32_t bytes_read;
-    char *buf;
-    struct file *file;
-    uint16_t handle;
-
-    sectors = regs->ecx.w[0];
-
-    handle = regs->esi.w[0];
-    file = handle_to_file(handle);
-
-    buf = MK_PTR(regs->es, regs->ebx.w[0]);
-    bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more);
-
-    /*
-     * If we reach EOF, the filesystem driver will have already closed
-     * the underlying file... this really should be cleaner.
-     */
-    if (!have_more) {
-	_close_file(file);
-        regs->esi.w[0] = 0;
-    }
-
-    regs->ecx.l = bytes_read;
-}
-
-void getfsbytes(com32sys_t *regs)
-{
-    int sectors;
-    bool have_more;
-    uint32_t bytes_read;
-    char *buf;
-    struct file *file;
-    uint16_t handle;
-
-    handle = regs->esi.w[0];
-    file = handle_to_file(handle);
-
-    sectors = regs->ecx.w[0] >> SECTOR_SHIFT(file->fs);
-
-    buf = MK_PTR(regs->es, regs->ebx.w[0]);
-    bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more);
-
-    /*
-     * If we reach EOF, the filesystem driver will have already closed
-     * the underlying file... this really should be cleaner.
-     */
-    if (!have_more) {
-	_close_file(file);
-        regs->esi.w[0] = 0;
-    }
-
-    regs->ecx.l = bytes_read;
-}
-
 size_t pmapi_read_file(uint16_t *handle, void *buf, size_t sectors)
 {
     bool have_more;
@@ -200,23 +138,6 @@
     return bytes_read;
 }
 
-void pm_searchdir(com32sys_t *regs)
-{
-    char *name = MK_PTR(regs->ds, regs->edi.w[0]);
-    int rv;
-
-    rv = searchdir(name);
-    if (rv < 0) {
-	regs->esi.w[0]  = 0;
-	regs->eax.l     = 0;
-	regs->eflags.l |= EFLAGS_ZF;
-    } else {
-	regs->esi.w[0]  = rv;
-	regs->eax.l     = handle_to_file(rv)->inode->size;
-	regs->eflags.l &= ~EFLAGS_ZF;
-    }
-}
-
 int searchdir(const char *name)
 {
     static char root_name[] = "/";
@@ -444,28 +365,6 @@
     return rv;
 }
 
-void pm_open_file(com32sys_t *regs)
-{
-    int rv;
-    struct file *file;
-    const char *name = MK_PTR(regs->es, regs->esi.w[0]);
-    char mangled_name[FILENAME_MAX];
-
-    dprintf("pm_open_file %s\n", name);
-
-    mangle_name(mangled_name, name);
-    rv = searchdir(mangled_name);
-    if (rv < 0) {
-	regs->eflags.l |= EFLAGS_CF;
-    } else {
-	file = handle_to_file(rv);
-	regs->eflags.l &= ~EFLAGS_CF;
-	regs->eax.l = file->inode->size;
-	regs->ecx.w[0] = SECTOR_SIZE(file->fs);
-	regs->esi.w[0] = rv;
-    }
-}
-
 __export void close_file(uint16_t handle)
 {
     struct file *file;
@@ -476,11 +375,6 @@
     }
 }
 
-void pm_close_file(com32sys_t *regs)
-{
-    close_file(regs->esi.w[0]);
-}
-
 /*
  * it will do:
  *    initialize the memory management function;
diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c
index fda0f81..184bacb 100644
--- a/core/fs/pxe/dnsresolv.c
+++ b/core/fs/pxe/dnsresolv.c
@@ -170,7 +170,7 @@
  *
  * XXX: probably need some caching here.
  */
-uint32_t dns_resolv(const char *name)
+__export uint32_t dns_resolv(const char *name)
 {
     static char __lowmem DNSSendBuf[PKTBUF_SIZE];
     static char __lowmem DNSRecvBuf[PKTBUF_SIZE];
diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c
index 1127004..ae44cff 100644
--- a/core/fs/pxe/pxe.c
+++ b/core/fs/pxe/pxe.c
@@ -254,7 +254,7 @@
  * the ASM pxenv function wrapper, return 1 if error, or 0
  *
  */
-int pxe_call(int opcode, void *data)
+__export int pxe_call(int opcode, void *data)
 {
     extern void pxenv(void);
     com32sys_t regs;
@@ -1656,7 +1656,7 @@
  * This function unloads the PXE and UNDI stacks and
  * unclaims the memory.
  */
-void unload_pxe(uint16_t flags)
+__export void unload_pxe(uint16_t flags)
 {
     /* PXE unload sequences */
     static const uint8_t new_api_unload[] = {
diff --git a/core/fs/xfs/xfs.c b/core/fs/xfs/xfs.c
index 89a9aef..b6a396a 100644
--- a/core/fs/xfs/xfs.c
+++ b/core/fs/xfs/xfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Paulo Alcantara <pcacjr@zytor.com>
+ * Copyright (c) 2012-2013 Paulo Alcantara <pcacjr@zytor.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -38,29 +38,26 @@
 #include "xfs_readdir.h"
 
 static inline int xfs_fmt_local_readdir(struct file *file,
-					struct dirent *dirent, xfs_dinode_t *core)
+					struct dirent *dirent,
+					xfs_dinode_t *core)
 {
-    return xfs_readdir_dir2_block(file, dirent, core);
+    return xfs_readdir_dir2_local(file, dirent, core);
 }
 
 static inline int xfs_fmt_extents_readdir(struct file *file,
 					  struct dirent *dirent,
 					  xfs_dinode_t *core)
 {
-    int retval;
-
     if (be32_to_cpu(core->di_nextents) <= 1) {
 	/* Single-block Directories */
-	retval = xfs_readdir_dir2_block(file, dirent, core);
+	return xfs_readdir_dir2_block(file, dirent, core);
     } else if (xfs_dir2_isleaf(file->fs, core)) {
 	/* Leaf Directory */
-	retval = xfs_readdir_dir2_leaf(file, dirent, core);
+	return xfs_readdir_dir2_leaf(file, dirent, core);
     } else {
 	/* Node Directory */
-	retval = xfs_readdir_dir2_node(file, dirent, core);
+	return xfs_readdir_dir2_node(file, dirent, core);
     }
-
-    return retval;
 }
 
 static int xfs_readdir(struct file *file, struct dirent *dirent)
@@ -68,7 +65,8 @@
     struct fs_info *fs = file->fs;
     xfs_dinode_t *core;
     struct inode *inode = file->inode;
-    int retval = -1;
+
+    xfs_debug("file %p dirent %p");
 
     core = xfs_dinode_get_core(fs, inode->ino);
     if (!core) {
@@ -77,11 +75,11 @@
     }
 
     if (core->di_format == XFS_DINODE_FMT_LOCAL)
-	retval = xfs_fmt_local_readdir(file, dirent, core);
+	return xfs_fmt_local_readdir(file, dirent, core);
     else if (core->di_format == XFS_DINODE_FMT_EXTENTS)
-	retval = xfs_fmt_extents_readdir(file, dirent, core);
+	return xfs_fmt_extents_readdir(file, dirent, core);
 
-    return retval;
+    return -1;
 }
 
 static uint32_t xfs_getfssec(struct file *file, char *buf, int sectors,
@@ -106,6 +104,8 @@
 
     (void)lstart;
 
+    xfs_debug("inode %p lstart %lu", inode, lstart);
+
     core = xfs_dinode_get_core(fs, inode->ino);
     if (!core) {
 	xfs_error("Failed to get dinode from disk (ino %llx)", inode->ino);
@@ -190,20 +190,16 @@
 						       struct inode *parent,
 						       xfs_dinode_t *core)
 {
-    struct inode *inode;
-
     if (be32_to_cpu(core->di_nextents) <= 1) {
-        /* Single-block Directories */
-        inode = xfs_dir2_block_find_entry(dname, parent, core);
+	/* Single-block Directories */
+	return xfs_dir2_block_find_entry(dname, parent, core);
     } else if (xfs_dir2_isleaf(parent->fs, core)) {
-        /* Leaf Directory */
-	inode = xfs_dir2_leaf_find_entry(dname, parent, core);
+	/* Leaf Directory */
+	return xfs_dir2_leaf_find_entry(dname, parent, core);
     } else {
-        /* Node Directory */
-        inode = xfs_dir2_node_find_entry(dname, parent, core);
+	/* Node Directory */
+	return xfs_dir2_node_find_entry(dname, parent, core);
     }
-
-    return inode;
 }
 
 static inline struct inode *xfs_fmt_btree_find_entry(const char *dname,
@@ -233,11 +229,6 @@
         inode = xfs_fmt_extents_find_entry(dname, parent, core);
     } else if (core->di_format == XFS_DINODE_FMT_BTREE) {
         inode = xfs_fmt_btree_find_entry(dname, parent, core);
-    } else {
-	xfs_debug("format %hhu", core->di_format);
-	xfs_debug("TODO: format \"local\" and \"extents\" are the only "
-		  "supported ATM");
-	goto out;
     }
 
     if (!inode) {
@@ -266,7 +257,9 @@
     int pathlen = -1;
     xfs_bmbt_irec_t rec;
     block_t db;
-    char *dir_buf;
+    const char *dir_buf;
+
+    xfs_debug("inode %p buf %p", inode, buf);
 
     core = xfs_dinode_get_core(fs, inode->ino);
     if (!core) {
@@ -289,7 +282,7 @@
     } else if (core->di_format == XFS_DINODE_FMT_EXTENTS) {
 	bmbt_irec_get(&rec, (xfs_bmbt_rec_t *)&core->di_literal_area[0]);
 	db = fsblock_to_bytes(fs, rec.br_startblock) >> BLOCK_SHIFT(fs);
-	dir_buf = xfs_dir2_get_dirblks(fs, db, rec.br_blockcount);
+	dir_buf = xfs_dir2_dirblks_get_cached(fs, db, rec.br_blockcount);
 
         /*
          * Syslinux only supports filesystem block size larger than or equal to
@@ -297,7 +290,6 @@
 	 * symbolic link file content, which is only 1024 bytes long.
          */
 	memcpy(buf, dir_buf, pathlen);
-	free(dir_buf);
     }
 
 out:
diff --git a/core/fs/xfs/xfs.h b/core/fs/xfs/xfs.h
index da57221..0d953d8 100644
--- a/core/fs/xfs/xfs.h
+++ b/core/fs/xfs/xfs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Paulo Alcantara <pcacjr@zytor.com>
+ * Copyright (c) 2012-2013 Paulo Alcantara <pcacjr@zytor.com>
  *
  * Some parts borrowed from Linux kernel tree (linux/fs/xfs):
  *
@@ -30,11 +30,16 @@
 #include "xfs_types.h"
 #include "xfs_ag.h"
 
-#define xfs_error(fmt, args...) \
-    printf("xfs: " fmt "\n", ## args);
+#define xfs_error(fmt, args...)						\
+    ({									\
+	printf("%s:%u: xfs - [ERROR] " fmt "\n", __func__, __LINE__, ## args); \
+    })
 
-#define xfs_debug(fmt, args...) \
-    dprintf("%s: " fmt "\n", __func__, ## args);
+#define xfs_debug(fmt, args...)						\
+    ({									\
+	dprintf("%s:%u: xfs - [DEBUG] " fmt "\n", __func__, __LINE__,	\
+		## args);						\
+    })
 
 struct xfs_fs_info;
 
diff --git a/core/fs/xfs/xfs_dinode.c b/core/fs/xfs/xfs_dinode.c
index 8e2d8d0..55be6e2 100644
--- a/core/fs/xfs/xfs_dinode.c
+++ b/core/fs/xfs/xfs_dinode.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Paulo Alcantara <pcacjr@zytor.com>
+ * Copyright (c) 2012-2013 Paulo Alcantara <pcacjr@zytor.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -33,7 +33,7 @@
     xfs_dinode_t *core;
     uint64_t offset;
 
-    xfs_debug("ino %lu", ino);
+    xfs_debug("fs %p ino %lu", fs, ino);
 
     blk = ino_to_bytes(fs, ino) >> BLOCK_SHIFT(fs);
     offset = XFS_INO_TO_OFFSET(XFS_INFO(fs), ino) << XFS_INFO(fs)->inode_shift;
diff --git a/core/fs/xfs/xfs_dir2.c b/core/fs/xfs/xfs_dir2.c
index c52196a..de37ef7 100644
--- a/core/fs/xfs/xfs_dir2.c
+++ b/core/fs/xfs/xfs_dir2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Paulo Alcantara <pcacjr@zytor.com>
+ * Copyright (c) 2012-2013 Paulo Alcantara <pcacjr@zytor.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -28,23 +28,16 @@
 
 #include "xfs_dir2.h"
 
-char *xfs_dir2_get_entry_name(uint8_t *start, uint8_t *end)
-{
-    char *s;
-    char *p;
+#define XFS_DIR2_DIRBLKS_CACHE_SIZE 128
 
-    s = malloc(end - start + 1);
-    if (!s)
-	malloc_error("string");
+struct xfs_dir2_dirblks_cache {
+    block_t        dc_startblock;
+    xfs_filblks_t  dc_blkscount;
+    void          *dc_area;
+};
 
-    p = s;
-    while (start < end)
-	*p++ = *start++;
-
-    *p = '\0';
-
-    return s;
-}
+static struct xfs_dir2_dirblks_cache dirblks_cache[XFS_DIR2_DIRBLKS_CACHE_SIZE];
+static unsigned char                 dirblks_cached_count = 0;
 
 uint32_t xfs_dir2_da_hashname(const uint8_t *name, int namelen)
 {
@@ -73,8 +66,8 @@
     }
 }
 
-void *xfs_dir2_get_dirblks(struct fs_info *fs, block_t startblock,
-			   xfs_filblks_t c)
+static void *get_dirblks(struct fs_info *fs, block_t startblock,
+			 xfs_filblks_t c)
 {
     int count = c << XFS_INFO(fs)->dirblklog;
     uint8_t *p;
@@ -96,6 +89,85 @@
     return buf;
 }
 
+const void *xfs_dir2_dirblks_get_cached(struct fs_info *fs, block_t startblock,
+					xfs_filblks_t c)
+{
+    unsigned char i;
+    void *buf;
+
+    xfs_debug("fs %p startblock %llu (0x%llx) blkscount %lu", fs, startblock,
+	      startblock, c);
+
+    if (!dirblks_cached_count) {
+	buf = get_dirblks(fs, startblock, c);
+
+	dirblks_cache[dirblks_cached_count].dc_startblock = startblock;
+	dirblks_cache[dirblks_cached_count].dc_blkscount = c;
+	dirblks_cache[dirblks_cached_count].dc_area = buf;
+
+	return dirblks_cache[dirblks_cached_count++].dc_area;
+    } else if (dirblks_cached_count == XFS_DIR2_DIRBLKS_CACHE_SIZE) {
+	for (i = 0; i < XFS_DIR2_DIRBLKS_CACHE_SIZE / 2; i++) {
+	    unsigned char k = XFS_DIR2_DIRBLKS_CACHE_SIZE - (i + 1);
+
+	    free(dirblks_cache[i].dc_area);
+	    dirblks_cache[i] = dirblks_cache[k];
+	    memset(&dirblks_cache[k], 0, sizeof(dirblks_cache[k]));
+	}
+
+	buf = get_dirblks(fs, startblock, c);
+
+	dirblks_cache[XFS_DIR2_DIRBLKS_CACHE_SIZE / 2].dc_startblock =
+	    startblock;
+	dirblks_cache[XFS_DIR2_DIRBLKS_CACHE_SIZE / 2].dc_blkscount = c;
+	dirblks_cache[XFS_DIR2_DIRBLKS_CACHE_SIZE / 2].dc_area = buf;
+
+	dirblks_cached_count = XFS_DIR2_DIRBLKS_CACHE_SIZE / 2;
+
+	return dirblks_cache[dirblks_cached_count++].dc_area;
+    } else {
+	block_t block;
+	xfs_filblks_t count;
+
+	block = dirblks_cache[dirblks_cached_count - 1].dc_startblock;
+	count = dirblks_cache[dirblks_cached_count - 1].dc_blkscount;
+
+	if (block == startblock && count == c) {
+	    return dirblks_cache[dirblks_cached_count - 1].dc_area;
+	} else {
+	    for (i = 0; i < dirblks_cached_count; i++) {
+		block = dirblks_cache[i].dc_startblock;
+		count = dirblks_cache[i].dc_blkscount;
+
+		if (block == startblock && count == c)
+		    return dirblks_cache[i].dc_area;
+	    }
+
+	    buf = get_dirblks(fs, startblock, c);
+
+	    dirblks_cache[dirblks_cached_count].dc_startblock = startblock;
+	    dirblks_cache[dirblks_cached_count].dc_blkscount = c;
+	    dirblks_cache[dirblks_cached_count].dc_area = buf;
+
+	    return dirblks_cache[dirblks_cached_count++].dc_area;
+	}
+    }
+
+    return NULL;
+}
+
+void xfs_dir2_dirblks_flush_cache(void)
+{
+    unsigned char i;
+
+    for (i = 0; i < dirblks_cached_count; i++) {
+	free(dirblks_cache[i].dc_area);
+	memset(&dirblks_cache[i], 0, sizeof(dirblks_cache[i]));
+    }
+
+    dirblks_cached_count = 0;
+}
+
 struct inode *xfs_dir2_local_find_entry(const char *dname, struct inode *parent,
 					xfs_dinode_t *core)
 {
@@ -107,6 +179,7 @@
     xfs_intino_t ino;
     xfs_dinode_t *ncore = NULL;
 
+    xfs_debug("dname %s parent %p core %p", dname, parent, core);
     xfs_debug("count %hhu i8count %hhu", sf->hdr.count, sf->hdr.i8count);
 
     sf_entry = (xfs_dir2_sf_entry_t *)((uint8_t *)&sf->list[0] -
@@ -114,19 +187,12 @@
     while (count--) {
 	uint8_t *start_name = &sf_entry->name[0];
 	uint8_t *end_name = start_name + sf_entry->namelen;
-	char *name;
 
-	name = xfs_dir2_get_entry_name(start_name, end_name);
-
-	xfs_debug("entry name: %s", name);
-
-	if (!strncmp(name, dname, strlen(dname))) {
-	    free(name);
+	if (!xfs_dir2_entry_name_cmp(start_name, end_name, dname)) {
+	    xfs_debug("Found entry %s", dname);
 	    goto found;
 	}
 
-	free(name);
-
 	sf_entry = (xfs_dir2_sf_entry_t *)((uint8_t *)sf_entry +
 					   offsetof(struct xfs_dir2_sf_entry,
 						    name[0]) +
@@ -184,7 +250,7 @@
     xfs_bmbt_irec_t r;
     block_t dir_blk;
     struct fs_info *fs = parent->fs;
-    uint8_t *dirblk_buf;
+    const uint8_t *dirblk_buf;
     uint8_t *p, *endp;
     xfs_dir2_data_hdr_t *hdr;
     struct inode *inode = NULL;
@@ -194,10 +260,12 @@
     xfs_intino_t ino;
     xfs_dinode_t *ncore;
 
+    xfs_debug("dname %s parent %p core %p", dname, parent, core);
+
     bmbt_irec_get(&r, (xfs_bmbt_rec_t *)&core->di_literal_area[0]);
     dir_blk = fsblock_to_bytes(fs, r.br_startblock) >> BLOCK_SHIFT(fs);
 
-    dirblk_buf = xfs_dir2_get_dirblks(fs, dir_blk, r.br_blockcount);
+    dirblk_buf = xfs_dir2_dirblks_get_cached(fs, dir_blk, r.br_blockcount);
     hdr = (xfs_dir2_data_hdr_t *)dirblk_buf;
     if (be32_to_cpu(hdr->magic) != XFS_DIR2_BLOCK_MAGIC) {
         xfs_error("Block directory header's magic number does not match!");
@@ -213,7 +281,6 @@
     while (p < endp) {
         uint8_t *start_name;
         uint8_t *end_name;
-        char *name;
 
         dup = (xfs_dir2_data_unused_t *)p;
         if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
@@ -225,20 +292,16 @@
 
         start_name = &dep->name[0];
         end_name = start_name + dep->namelen;
-        name = xfs_dir2_get_entry_name(start_name, end_name);
 
-        if (!strncmp(name, dname, strlen(dname))) {
-            free(name);
+	if (!xfs_dir2_entry_name_cmp(start_name, end_name, dname)) {
+	    xfs_debug("Found entry %s", dname);
             goto found;
         }
 
-        free(name);
 	p += xfs_dir2_data_entsize(dep->namelen);
     }
 
 out:
-    free(dirblk_buf);
-
     return NULL;
 
 found:
@@ -274,12 +337,10 @@
 
     xfs_debug("entry inode's number %lu", ino);
 
-    free(dirblk_buf);
     return inode;
 
 failed:
     free(inode);
-    free(dirblk_buf);
 
     return NULL;
 }
@@ -302,25 +363,26 @@
     xfs_dir2_data_hdr_t *data_hdr;
     uint8_t *start_name;
     uint8_t *end_name;
-    char *name;
     xfs_intino_t ino;
     xfs_dinode_t *ncore;
-    uint8_t *buf = NULL;
+    const uint8_t *buf = NULL;
+
+    xfs_debug("dname %s parent %p core %p", dname, parent, core);
 
     bmbt_irec_get(&irec, ((xfs_bmbt_rec_t *)&core->di_literal_area[0]) +
 					be32_to_cpu(core->di_nextents) - 1);
     leaf_blk = fsblock_to_bytes(parent->fs, irec.br_startblock) >>
 	    BLOCK_SHIFT(parent->fs);
 
-    leaf = (xfs_dir2_leaf_t *)xfs_dir2_get_dirblks(parent->fs, leaf_blk,
-						   irec.br_blockcount);
+    leaf = (xfs_dir2_leaf_t *)xfs_dir2_dirblks_get_cached(parent->fs, leaf_blk,
+							  irec.br_blockcount);
     if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAF1_MAGIC) {
         xfs_error("Single leaf block header's magic number does not match!");
         goto out;
     }
 
     if (!leaf->hdr.count)
-        goto out;
+	goto out;
 
     hashwant = xfs_dir2_da_hashname((uint8_t *)dname, strlen(dname));
 
@@ -355,18 +417,16 @@
 
         newdb = xfs_dir2_dataptr_to_db(parent->fs, be32_to_cpu(lep->address));
         if (newdb != curdb) {
-            if (buf)
-                free(buf);
-
             bmbt_irec_get(&irec,
 		  ((xfs_bmbt_rec_t *)&core->di_literal_area[0]) + newdb);
             dir_blk = fsblock_to_bytes(parent->fs, irec.br_startblock) >>
+
 		      BLOCK_SHIFT(parent->fs);
-            buf = xfs_dir2_get_dirblks(parent->fs, dir_blk, irec.br_blockcount);
+            buf = xfs_dir2_dirblks_get_cached(parent->fs, dir_blk, irec.br_blockcount);
             data_hdr = (xfs_dir2_data_hdr_t *)buf;
             if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC) {
                 xfs_error("Leaf directory's data magic No. does not match!");
-                goto out1;
+                goto out;
             }
 
             curdb = newdb;
@@ -377,21 +437,14 @@
 
         start_name = &dep->name[0];
         end_name = start_name + dep->namelen;
-        name = xfs_dir2_get_entry_name(start_name, end_name);
 
-        if (!strncmp(name, dname, strlen(dname))) {
-            free(name);
+	if (!xfs_dir2_entry_name_cmp(start_name, end_name, dname)) {
+	    xfs_debug("Found entry %s", dname);
             goto found;
         }
-
-        free(name);
     }
 
-out1:
-    free(buf);
 out:
-    free(leaf);
-
     return NULL;
 
 found:
@@ -428,15 +481,10 @@
 
     xfs_debug("entry inode's number %lu", ino);
 
-    free(buf);
-    free(leaf);
-
     return ip;
 
 failed:
     free(ip);
-    free(buf);
-    free(leaf);
 
     return ip;
 }
@@ -560,14 +608,15 @@
     struct inode *ip;
     uint8_t *start_name;
     uint8_t *end_name;
-    char *name;
     int low;
     int high;
     int mid = 0;
     uint32_t newdb, curdb = -1;
     xfs_intino_t ino;
     xfs_dinode_t *ncore;
-    uint8_t *buf = NULL;
+    const uint8_t *buf = NULL;
+
+    xfs_debug("dname %s parent %p core %p", dname, parent, core);
 
     hashwant = xfs_dir2_da_hashname((uint8_t *)dname, strlen(dname));
 
@@ -579,7 +628,8 @@
         return NULL;
     }
 
-    node = (xfs_da_intnode_t *)xfs_dir2_get_dirblks(parent->fs, fsblkno, 1);
+    node = (xfs_da_intnode_t *)xfs_dir2_dirblks_get_cached(parent->fs, fsblkno,
+							   1);
     if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC) {
         xfs_error("Node's magic number does not match!");
         goto out;
@@ -630,9 +680,8 @@
             goto out;
         }
 
-        free(node);
-        node = (xfs_da_intnode_t *)xfs_dir2_get_dirblks(parent->fs,
-                                                        fsblkno, 1);
+        node = (xfs_da_intnode_t *)xfs_dir2_dirblks_get_cached(parent->fs,
+							       fsblkno, 1);
     } while(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
 
     leaf = (xfs_dir2_leaf_t*)node;
@@ -675,20 +724,17 @@
 
         newdb = xfs_dir2_dataptr_to_db(parent->fs, be32_to_cpu(lep->address));
         if (newdb != curdb) {
-            if (buf)
-                free(buf);
-
             fsblkno = xfs_dir2_get_right_blk(parent->fs, core, newdb, &error);
             if (error) {
                 xfs_error("Cannot find data block!");
                 goto out;
             }
 
-            buf = xfs_dir2_get_dirblks(parent->fs, fsblkno, 1);
+            buf = xfs_dir2_dirblks_get_cached(parent->fs, fsblkno, 1);
             data_hdr = (xfs_dir2_data_hdr_t *)buf;
             if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC) {
                 xfs_error("Leaf directory's data magic No. does not match!");
-                goto out1;
+                goto out;
             }
 
             curdb = newdb;
@@ -699,21 +745,14 @@
 
         start_name = &dep->name[0];
         end_name = start_name + dep->namelen;
-        name = xfs_dir2_get_entry_name(start_name, end_name);
-        if (!strncmp(name, dname, strlen(dname))) {
-            free(name);
-            goto found;
-        }
 
-        free(name);
+	if (!xfs_dir2_entry_name_cmp(start_name, end_name, dname)) {
+	    xfs_debug("Found entry %s", dname);
+	    goto found;
+        }
     }
 
-out1:
-    free(buf);
-
 out:
-    free(node);
-
     return NULL;
 
 found:
@@ -745,15 +784,10 @@
 
     xfs_debug("entry inode's number %lu", ino);
 
-    free(buf);
-    free(node);
-
     return ip;
 
 failed:
     free(ip);
-    free(buf);
-    free(node);
 
     return NULL;
 }
diff --git a/core/fs/xfs/xfs_dir2.h b/core/fs/xfs/xfs_dir2.h
index e1b9622..158cf44 100644
--- a/core/fs/xfs/xfs_dir2.h
+++ b/core/fs/xfs/xfs_dir2.h
@@ -23,10 +23,12 @@
 
 #include "xfs.h"
 
-char *xfs_dir2_get_entry_name(uint8_t *start, uint8_t *end);
-void *xfs_dir2_get_dirblks(struct fs_info *fs, block_t startblock,
-			   xfs_filblks_t c);
+const void *xfs_dir2_dirblks_get_cached(struct fs_info *fs, block_t startblock,
+					xfs_filblks_t c);
+void xfs_dir2_dirblks_flush_cache(void);
+
 uint32_t xfs_dir2_da_hashname(const uint8_t *name, int namelen);
+
 block_t xfs_dir2_get_right_blk(struct fs_info *fs, xfs_dinode_t *core,
 			       block_t fsblkno, int *error);
 
@@ -51,4 +53,17 @@
     return (last == XFS_INFO(fs)->dirleafblk + (1 << XFS_INFO(fs)->dirblklog));
 }
 
+static inline int xfs_dir2_entry_name_cmp(uint8_t *start, uint8_t *end,
+					  const char *name)
+{
+    if (!name || (strlen(name) != end - start))
+	return -1;
+
+    while (start < end)
+	if (*start++ != *name++)
+	    return -1;
+
+    return 0;
+}
+
 #endif /* XFS_DIR2_H_ */
diff --git a/core/fs/xfs/xfs_readdir.c b/core/fs/xfs/xfs_readdir.c
index 0e013e5..86c8a77 100644
--- a/core/fs/xfs/xfs_readdir.c
+++ b/core/fs/xfs/xfs_readdir.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Paulo Alcantara <pcacjr@zytor.com>
+ * Copyright (c) 2012-2013 Paulo Alcantara <pcacjr@zytor.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -35,6 +35,9 @@
 {
     xfs_dinode_t *core;
 
+    xfs_debug("fs %p, dirent %p offset %lu ino %llu name %s namelen %llu", fs,
+	      dirent, offset, ino, name, namelen);
+
     dirent->d_ino = ino;
     dirent->d_off = offset;
     dirent->d_reclen = offsetof(struct dirent, d_name) + namelen + 1;
@@ -52,7 +55,8 @@
     else if (be16_to_cpu(core->di_mode) & S_IFLNK)
         dirent->d_type = DT_LNK;
 
-    memcpy(dirent->d_name, name, namelen + 1);
+    memcpy(dirent->d_name, name, namelen);
+    dirent->d_name[namelen] = '\0';
 
     return 0;
 }
@@ -66,15 +70,15 @@
     uint32_t offset = file->offset;
     uint8_t *start_name;
     uint8_t *end_name;
-    char *name;
     xfs_ino_t ino;
     struct fs_info *fs = file->fs;
     int retval = 0;
 
+    xfs_debug("file %p dirent %p core %p", file, dirent, core);
     xfs_debug("count %hhu i8count %hhu", sf->hdr.count, sf->hdr.i8count);
 
     if (file->offset + 1 > count)
-	return -1;
+	goto out;
 
     file->offset++;
 
@@ -96,22 +100,23 @@
     start_name = &sf_entry->name[0];
     end_name = start_name + sf_entry->namelen;
 
-    name = xfs_dir2_get_entry_name(start_name, end_name);
-
     ino = xfs_dir2_sf_get_inumber(sf, (xfs_dir2_inou_t *)(
 				      (uint8_t *)sf_entry +
 				      offsetof(struct xfs_dir2_sf_entry,
 					       name[0]) +
 				      sf_entry->namelen));
 
-    retval = fill_dirent(fs, dirent, file->offset, ino, (char *)name,
+    retval = fill_dirent(fs, dirent, file->offset, ino, (char *)start_name,
 			 end_name - start_name);
     if (retval)
 	xfs_error("Failed to fill in dirent structure");
 
-    free(name);
-
     return retval;
+
+out:
+    xfs_dir2_dirblks_flush_cache();
+
+    return -1;
 }
 
 int xfs_readdir_dir2_block(struct file *file, struct dirent *dirent,
@@ -120,7 +125,7 @@
     xfs_bmbt_irec_t r;
     block_t dir_blk;
     struct fs_info *fs = file->fs;
-    uint8_t *dirblk_buf;
+    const uint8_t *dirblk_buf;
     uint8_t *p;
     uint32_t offset;
     xfs_dir2_data_hdr_t *hdr;
@@ -129,28 +134,26 @@
     xfs_dir2_data_entry_t *dep;
     uint8_t *start_name;
     uint8_t *end_name;
-    char *name;
     xfs_ino_t ino;
     int retval = 0;
 
+    xfs_debug("file %p dirent %p core %p", file, dirent, core);
+
     bmbt_irec_get(&r, (xfs_bmbt_rec_t *)&core->di_literal_area[0]);
     dir_blk = fsblock_to_bytes(fs, r.br_startblock) >> BLOCK_SHIFT(fs);
 
-    dirblk_buf = xfs_dir2_get_dirblks(fs, dir_blk, r.br_blockcount);
+    dirblk_buf = xfs_dir2_dirblks_get_cached(fs, dir_blk, r.br_blockcount);
     hdr = (xfs_dir2_data_hdr_t *)dirblk_buf;
     if (be32_to_cpu(hdr->magic) != XFS_DIR2_BLOCK_MAGIC) {
         xfs_error("Block directory header's magic number does not match!");
         xfs_debug("hdr->magic: 0x%lx", be32_to_cpu(hdr->magic));
-
-	free(dirblk_buf);
-
-	return -1;
+	goto out;
     }
 
     btp = xfs_dir2_block_tail_p(XFS_INFO(fs), hdr);
 
     if (file->offset + 1 > be32_to_cpu(btp->count))
-	return -1;
+	goto out;
 
     file->offset++;
 
@@ -175,19 +178,20 @@
 
     start_name = &dep->name[0];
     end_name = start_name + dep->namelen;
-    name = xfs_dir2_get_entry_name(start_name, end_name);
 
     ino = be64_to_cpu(dep->inumber);
 
-    retval = fill_dirent(fs, dirent, file->offset, ino, name,
+    retval = fill_dirent(fs, dirent, file->offset, ino, (char *)start_name,
 			 end_name - start_name);
     if (retval)
 	xfs_error("Failed to fill in dirent structure");
 
-    free(dirblk_buf);
-    free(name);
-
     return retval;
+
+out:
+    xfs_dir2_dirblks_flush_cache();
+
+    return -1;
 }
 
 int xfs_readdir_dir2_leaf(struct file *file, struct dirent *dirent,
@@ -204,18 +208,19 @@
     xfs_dir2_data_hdr_t *data_hdr;
     uint8_t *start_name;
     uint8_t *end_name;
-    char *name;
     xfs_intino_t ino;
-    uint8_t *buf = NULL;
+    const uint8_t *buf = NULL;
     int retval = 0;
 
+    xfs_debug("file %p dirent %p core %p", file, dirent, core);
+
     bmbt_irec_get(&irec, ((xfs_bmbt_rec_t *)&core->di_literal_area[0]) +
 					be32_to_cpu(core->di_nextents) - 1);
     leaf_blk = fsblock_to_bytes(fs, irec.br_startblock) >>
 					BLOCK_SHIFT(file->fs);
 
-    leaf = (xfs_dir2_leaf_t *)xfs_dir2_get_dirblks(fs, leaf_blk,
-						   irec.br_blockcount);
+    leaf = (xfs_dir2_leaf_t *)xfs_dir2_dirblks_get_cached(fs, leaf_blk,
+							  irec.br_blockcount);
     if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAF1_MAGIC) {
         xfs_error("Single leaf block header's magic number does not match!");
         goto out;
@@ -239,11 +244,11 @@
 
     dir_blk = fsblock_to_bytes(fs, irec.br_startblock) >> BLOCK_SHIFT(fs);
 
-    buf = xfs_dir2_get_dirblks(fs, dir_blk, irec.br_blockcount);
+    buf = xfs_dir2_dirblks_get_cached(fs, dir_blk, irec.br_blockcount);
     data_hdr = (xfs_dir2_data_hdr_t *)buf;
     if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC) {
 	xfs_error("Leaf directory's data magic number does not match!");
-	goto out1;
+	goto out;
     }
 
     offset = xfs_dir2_dataptr_to_off(fs, be32_to_cpu(lep->address));
@@ -252,26 +257,18 @@
 
     start_name = &dep->name[0];
     end_name = start_name + dep->namelen;
-    name = xfs_dir2_get_entry_name(start_name, end_name);
 
     ino = be64_to_cpu(dep->inumber);
 
-    retval = fill_dirent(fs, dirent, file->offset, ino, name,
+    retval = fill_dirent(fs, dirent, file->offset, ino, (char *)start_name,
 			 end_name - start_name);
     if (retval)
 	xfs_error("Failed to fill in dirent structure");
 
-    free(name);
-    free(buf);
-    free(leaf);
-
     return retval;
 
-out1:
-    free(buf);
-
 out:
-    free(leaf);
+    xfs_dir2_dirblks_flush_cache();
 
     return -1;
 }
@@ -293,11 +290,12 @@
     xfs_dir2_data_entry_t *dep;
     uint8_t *start_name;
     uint8_t *end_name;
-    char *name;
     uint32_t db;
-    uint8_t *buf = NULL;
+    const uint8_t *buf = NULL;
     int retval = 0;
 
+    xfs_debug("file %p dirent %p core %p", file, dirent, core);
+
     do {
         bmbt_irec_get(&irec, (xfs_bmbt_rec_t *)&core->di_literal_area[0] +
 								++node_off);
@@ -305,7 +303,7 @@
 
     fsblkno = fsblock_to_bytes(fs, irec.br_startblock) >> BLOCK_SHIFT(fs);
 
-    node = (xfs_da_intnode_t *)xfs_dir2_get_dirblks(fs, fsblkno, 1);
+    node = (xfs_da_intnode_t *)xfs_dir2_dirblks_get_cached(fs, fsblkno, 1);
     if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC) {
         xfs_error("Node's magic number does not match!");
         goto out;
@@ -314,7 +312,7 @@
 try_next_btree:
     if (!node->hdr.count ||
 	XFS_PVT(inode)->i_btree_offset >= be16_to_cpu(node->hdr.count))
-        goto out;
+	goto out;
 
     fsblkno = be32_to_cpu(node->btree[XFS_PVT(inode)->i_btree_offset].before);
     fsblkno = xfs_dir2_get_right_blk(fs, core, fsblkno, &error);
@@ -323,17 +321,16 @@
         goto out;
     }
 
-    leaf = (xfs_dir2_leaf_t*)xfs_dir2_get_dirblks(fs, fsblkno, 1);
+    leaf = (xfs_dir2_leaf_t*)xfs_dir2_dirblks_get_cached(fs, fsblkno, 1);
     if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAFN_MAGIC) {
         xfs_error("Leaf's magic number does not match!");
-        goto out1;
+        goto out;
     }
 
     if (!leaf->hdr.count ||
 	XFS_PVT(inode)->i_leaf_ent_offset >= be16_to_cpu(leaf->hdr.count)) {
 	XFS_PVT(inode)->i_btree_offset++;
 	XFS_PVT(inode)->i_leaf_ent_offset = 0;
-	free(leaf);
 	goto try_next_btree;
     }
 
@@ -347,7 +344,6 @@
     if (XFS_PVT(inode)->i_leaf_ent_offset == be16_to_cpu(leaf->hdr.count)) {
 	XFS_PVT(inode)->i_btree_offset++;
 	XFS_PVT(inode)->i_leaf_ent_offset = 0;
-	free(leaf);
 	goto try_next_btree;
     } else {
 	XFS_PVT(inode)->i_leaf_ent_offset++;
@@ -358,14 +354,14 @@
     fsblkno = xfs_dir2_get_right_blk(fs, core, db, &error);
     if (error) {
 	xfs_error("Cannot find data block!");
-	goto out1;
+	goto out;
     }
 
-    buf = xfs_dir2_get_dirblks(fs, fsblkno, 1);
+    buf = xfs_dir2_dirblks_get_cached(fs, fsblkno, 1);
     data_hdr = (xfs_dir2_data_hdr_t *)buf;
     if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC) {
 	xfs_error("Leaf directory's data magic No. does not match!");
-	goto out2;
+	goto out;
     }
 
     offset = xfs_dir2_dataptr_to_off(fs, be32_to_cpu(lep->address));
@@ -374,28 +370,16 @@
 
     start_name = &dep->name[0];
     end_name = start_name + dep->namelen;
-    name = xfs_dir2_get_entry_name(start_name, end_name);
 
-    retval = fill_dirent(fs, dirent, 0, be64_to_cpu(dep->inumber), name,
-			 end_name - start_name);
+    retval = fill_dirent(fs, dirent, 0, be64_to_cpu(dep->inumber),
+			 (char *)start_name, end_name - start_name);
     if (retval)
 	xfs_error("Failed to fill in dirent structure");
 
-    free(name);
-    free(buf);
-    free(leaf);
-    free(node);
-
     return retval;
 
-out2:
-    free(buf);
-
-out1:
-    free(leaf);
-
 out:
-    free(node);
+    xfs_dir2_dirblks_flush_cache();
 
     XFS_PVT(inode)->i_btree_offset = 0;
     XFS_PVT(inode)->i_leaf_ent_offset = 0;
diff --git a/core/include/bios.h b/core/include/bios.h
index 9334c41..7bbd274 100644
--- a/core/include/bios.h
+++ b/core/include/bios.h
@@ -20,6 +20,8 @@
 #ifndef _BIOS_H
 #define _BIOS_H
 
+#include <sys/io.h>
+
 /*
  * Interrupt vectors
  */
diff --git a/core/include/fs.h b/core/include/fs.h
index 554dc97..560458b 100644
--- a/core/include/fs.h
+++ b/core/include/fs.h
@@ -7,6 +7,7 @@
 #include <com32.h>
 #include <stdio.h>
 #include <sys/dirent.h>
+#include <dprintf.h>
 #include "core.h"
 #include "disk.h"
 
@@ -158,6 +159,8 @@
 static inline struct inode *get_inode(struct inode *inode)
 {
     inode->refcnt++;
+    dprintf("get_inode %p name %s refcnt %d\n",
+	    inode, inode->name, inode->refcnt);
     return inode;
 }
 
diff --git a/core/init.inc b/core/init.inc
index 995f982..b74cf30 100644
--- a/core/init.inc
+++ b/core/init.inc
@@ -47,17 +47,17 @@
 ;
 ; The code to decompress the PM code and initialize other segments.
 ;
-		extern _lzo1x_decompress_asm_fast
+		extern _lzo1x_decompress_asm_fast_safe
 
 		section .textnr
 		bits 32
 pm_decompress:
-		push 0				; Space for decompressed size
+		push __pm_code_len + 16		; Space for decompressed size
 		push esp			; Pointer to previous word
 		push __pm_code_start		; Target address
 		push dword [lzo_data_size]	; Compressed size
 		push dword __pm_code_lma
-		call _lzo1x_decompress_asm_fast
+		call _lzo1x_decompress_asm_fast_safe
 		add esp,16
 		pop RM_EAX			; Decompressed size
 
diff --git a/core/isolinux.asm b/core/isolinux.asm
index 673134b..b54beb4 100644
--- a/core/isolinux.asm
+++ b/core/isolinux.asm
@@ -433,7 +433,9 @@
 .ok:
 		xor bx,bx
 		push bp
+		push eax
 		call getlinsec
+		pop eax
 		pop cx
 		mov dx,cx
 		pop bp
@@ -441,6 +443,7 @@
 
 		shl cx,SECTOR_SHIFT - 4
 		add bx,cx
+		add eax,edx
 		sub bp,dx
 		jnz .more
 
diff --git a/core/lzo/enter.ash b/core/lzo/enter.ash
index e865c4c..dc7782f 100644
--- a/core/lzo/enter.ash
+++ b/core/lzo/enter.ash
@@ -2,6 +2,9 @@
 
    This file is part of the LZO real-time data compression library.
 
+   Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
diff --git a/core/lzo/leave.ash b/core/lzo/leave.ash
index f77e2ef..cc48ce6 100644
--- a/core/lzo/leave.ash
+++ b/core/lzo/leave.ash
@@ -2,6 +2,9 @@
 
    This file is part of the LZO real-time data compression library.
 
+   Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
diff --git a/core/lzo/lzo1c_d.ash b/core/lzo/lzo1c_d.ash
index 9969c86..56622ab 100644
--- a/core/lzo/lzo1c_d.ash
+++ b/core/lzo/lzo1c_d.ash
@@ -2,6 +2,9 @@
 
    This file is part of the LZO real-time data compression library.
 
+   Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
diff --git a/core/lzo/lzo1f_d.ash b/core/lzo/lzo1f_d.ash
index aa9279e..97a103c 100644
--- a/core/lzo/lzo1f_d.ash
+++ b/core/lzo/lzo1f_d.ash
@@ -2,6 +2,9 @@
 
    This file is part of the LZO real-time data compression library.
 
+   Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
diff --git a/core/lzo/lzo1x_d.ash b/core/lzo/lzo1x_d.ash
index aa13835..782b47f 100644
--- a/core/lzo/lzo1x_d.ash
+++ b/core/lzo/lzo1x_d.ash
@@ -2,6 +2,9 @@
 
    This file is part of the LZO real-time data compression library.
 
+   Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
diff --git a/core/lzo/lzo1x_f1.S b/core/lzo/lzo1x_f2.S
similarity index 80%
rename from core/lzo/lzo1x_f1.S
rename to core/lzo/lzo1x_f2.S
index 8360e34..8cc26b8 100644
--- a/core/lzo/lzo1x_f1.S
+++ b/core/lzo/lzo1x_f2.S
@@ -1,7 +1,10 @@
-/* lzo1x_f1.S -- fast LZO1X decompression in assembler (i386 + gcc)
+/* lzo1x_f2.S -- fast LZO1X decompression in assembler (i386 + gcc)
 
    This file is part of the LZO real-time data compression library.
 
+   Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
@@ -44,17 +47,21 @@
 
 #define LZO_FAST
 
+#define LZO_TEST_DECOMPRESS_OVERRUN_INPUT
+#define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT
+#define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND
+
 #include "lzo_asm.h"
 
     .section ".textnr","ax"
 
-    LZO_PUBLIC(lzo1x_decompress_asm_fast)
+    LZO_PUBLIC(lzo1x_decompress_asm_fast_safe)
 
 #include "enter.ash"
 #include "lzo1x_d.ash"
 #include "leave.ash"
 
-    LZO_PUBLIC_END(lzo1x_decompress_asm_fast)
+    LZO_PUBLIC_END(lzo1x_decompress_asm_fast_safe)
 
 
 /*
diff --git a/core/lzo/lzo_asm.h b/core/lzo/lzo_asm.h
index 5e870b8..663ca1a 100644
--- a/core/lzo/lzo_asm.h
+++ b/core/lzo/lzo_asm.h
@@ -2,6 +2,9 @@
 
    This file is part of the LZO real-time data compression library.
 
+   Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
    Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
@@ -54,17 +57,17 @@
 #else
    /* manual configuration - see defaults below */
 #  if defined(__ELF__)
-#    define MFX_ASM_HAVE_TYPE
-#    define MFX_ASM_NAME_NO_UNDERSCORES
+#    define MFX_ASM_HAVE_TYPE 1
+#    define MFX_ASM_NAME_NO_UNDERSCORES 1
 #  elif defined(__linux__)              /* Linux a.out */
-#    define MFX_ASM_ALIGN_PTWO
+#    define MFX_ASM_ALIGN_PTWO 1
 #  elif defined(__DJGPP__)
-#    define MFX_ASM_ALIGN_PTWO
+#    define MFX_ASM_ALIGN_PTWO 1
 #  elif defined(__GO32__)               /* djgpp v1 */
-#    define MFX_ASM_CANNOT_USE_EBP
+#    define MFX_ASM_CANNOT_USE_EBP 1
 #  elif defined(__EMX__)
-#    define MFX_ASM_ALIGN_PTWO
-#    define MFX_ASM_CANNOT_USE_EBP
+#    define MFX_ASM_ALIGN_PTWO 1
+#    define MFX_ASM_CANNOT_USE_EBP 1
 #  endif
 #endif
 #endif
@@ -125,7 +128,7 @@
 ************************************************************************/
 
 #if !defined(MFX_ASM_ALIGN_BYTES) && !defined(MFX_ASM_ALIGN_PTWO)
-#  define MFX_ASM_ALIGN_BYTES
+#  define MFX_ASM_ALIGN_BYTES 1
 #endif
 
 #if !defined(LZO_ASM_ALIGN)
@@ -147,10 +150,10 @@
 
 #if !defined(MFX_ASM_CANNOT_USE_EBP)
 #  if 1 && !defined(N_3_EBP) && !defined(N_255_EBP)
-#    define N_3_EBP
+#    define N_3_EBP 1
 #  endif
 #  if 0 && !defined(N_3_EBP) && !defined(N_255_EBP)
-#    define N_255_EBP
+#    define N_255_EBP 1
 #  endif
 #endif
 
diff --git a/core/mem/malloc.c b/core/mem/malloc.c
index a3d6b45..c439dcb 100644
--- a/core/mem/malloc.c
+++ b/core/mem/malloc.c
@@ -175,6 +175,8 @@
 		ARENA_TYPE_SET(nah->a.attrs, ARENA_TYPE_FREE);
 		ARENA_SIZE_SET(nah->a.attrs, xsize - newsize);
 		ARENA_SIZE_SET(ah->a.attrs, newsize);
+		ARENA_HEAP_SET(nah->a.attrs, ARENA_HEAP_GET(ah->a.attrs));
+
 		//nah->a.type = ARENA_TYPE_FREE;
 		//nah->a.size = xsize - newsize;
 		//ah->a.size = newsize;
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index 95f7661..841f69f 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -289,10 +289,12 @@
 		global KernelName
 KernelName	resb FILENAME_MAX	; Mangled name for kernel
 		section .data16
-		extern IPOption
+		extern IPOption, BOOTIFStr, SYSUUIDStr
 		global IPAppends, numIPAppends
 		alignz 2
 IPAppends	dw IPOption
+		dw BOOTIFStr
+		dw SYSUUIDStr
 numIPAppends	equ ($-IPAppends)/2
 
 		section .text16
diff --git a/dos/argv.c b/dos/argv.c
index 056aae5..da28366 100644
--- a/dos/argv.c
+++ b/dos/argv.c
@@ -1,6 +1,7 @@
 /* ----------------------------------------------------------------------- *
  *
  *   Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2013 Intel Corporation; author: H. Peter Anvin
  *
  *   Permission is hereby granted, free of charge, to any person
  *   obtaining a copy of this software and associated documentation
@@ -28,48 +29,81 @@
 /*
  * argv.c
  *
- * Parse a single C string into argc and argv (argc is return value.)
+ * Parse the MS-DOS command line into argc and argv (argc is return value.)
  * memptr points to available memory.
  */
 
 #include <inttypes.h>
 #include <stddef.h>
-#include <stdio.h>
+#include <stdbool.h>
+#include "mystuff.h"
 
 #define ALIGN_UP(p,t)       ((t *)(((uintptr_t)(p) + (sizeof(t)-1)) & ~(sizeof(t)-1)))
 
 extern char __heap_start[];
 void *__mem_end = &__heap_start;	/* Global variable for use by malloc() */
 
-int __parse_argv(char ***argv, const char *str)
+int __parse_argv(char ***argv)
 {
     char *mem = __mem_end;
-    const char *p = str;
+    const char *str, *p;
     char *q = mem;
-    char *r;
+    char c, *r;
     char **arg;
-    int wasspace = 0;
-    int argc = 1;
+    bool wasspace;
+    int argc;
+    int len;
+    size_t offs;
+    int nulls;
+    uint16_t nstr;
 
-    /* First copy the string, turning whitespace runs into nulls */
+    /* Find and copy argv[0] after the environment block */
+    set_fs(_PSP.environment);
+    offs = 0;
+    nulls = 0;
+    do {
+	if (get_8_fs(offs++) == '\0')
+	    nulls++;
+	else
+	    nulls = 0;
+    } while (nulls < 2);
+
+    nstr = get_16_fs(offs);
+    offs += 2;
+
+    /* Copy the null-terminated filename string */
+    if (nstr >= 1) {
+	while ((c = get_8_fs(offs++)))
+	    *q++ = c;
+    }
+    *q++ = '\0';
+
+    /* Now for the command line tail... */
+
+    len = _PSP.cmdlen;
+    str = _PSP.cmdtail;
+    argc = 1;
+    wasspace = true;
+
+    /* Copy the command tail, turning whitespace runs into nulls */
     for (p = str;; p++) {
-	if (*p <= ' ') {
+	if (!len || *p <= ' ') {
 	    if (!wasspace) {
-		wasspace = 1;
+		wasspace = true;
 		*q++ = '\0';
 	    }
 	} else {
 	    if (wasspace) {
 		argc++;
-		wasspace = 0;
+		wasspace = false;
 	    }
 	    *q++ = *p;
 	}
 
-	/* This test is AFTER we have processed the null byte;
+	/* This test is AFTER we have processed the end byte;
 	   we treat it as a whitespace character so it terminates
 	   the last argument */
-	if (!*p)
+	if (!len--)
 	    break;
     }
 
@@ -78,7 +112,7 @@
     *argv = arg;
     *arg++ = mem;		/* argv[0] */
 
-    q--;			/* Point q to final null */
+    q--;			/* Point q to terminal character */
     for (r = mem; r < q; r++) {
 	if (*r == '\0') {
 	    *arg++ = r + 1;
diff --git a/dos/crt0.S b/dos/crt0.S
index 3be5712..66b52c0 100644
--- a/dos/crt0.S
+++ b/dos/crt0.S
@@ -9,7 +9,7 @@
 	.type _start,@function
 _start:
 	# Align the stack and make sure the high half is zero
-	andl $0xfff8,%esp
+	andl $0xfffc,%esp
 
 	# DS, ES points to the PSP at this point
 	pushw %es		# Save PSP pointer
@@ -26,16 +26,27 @@
 	shrw $2,%cx
 	rep ; stosl
 
-	# Copy the command line into our own segment
+	# Copy the PSP into our own segment
 	popw %fs		# FS -> PSP
-	movw $_cmdline,%di
-	movzbw %fs:0x80,%cx
-	movw $0x81,%si
-	fs ; rep ; movsb
-	# Already zero-terminated since we're writing into clean bss
+	movw $_PSP,%di
+	xorw %si,%si
+	movw $0x40,%cx
+	fs ; rep ; movsl
 
+	# Verify that this is a supportable DOS version
+	movw $0x3001,%ax
+	int $0x21
+	xchgb %ah,%al
+	movw %ax,dos_version
+	cmpw $0x0314,%ax	# DOS >= 3.20?
+	jae 1f			# If so, okay
+	movw $bad_dos,%dx	# Print error message
+	movb $0x09,%ah
+	int $0x21
+	int $0x20		# Die
+
+1:
 	# Compute argc and argv (assumes REGPARM)
-	movl $_cmdline,%edx
 	pushl %eax		# Make space for argv
 	movl %esp,%eax
 	calll __parse_argv
@@ -44,7 +55,7 @@
 	# Initialize malloc
 	calll __init_memory_arena
 
-	# Now call main... (NOTE: gcc forces main to be regparm 0)
+	# Now call main
 	popl %eax		# argc
 	popl %edx		# argv
 	calll main
@@ -63,8 +74,18 @@
 	jmp 1b
 	.size exit,.-exit
 
+	.section ".rodata","a"
+bad_dos:
+	.ascii "Unsupported DOS version\r\n$"
+	.size bad_dos,.-bad_dos
+
 	.section ".bss","aw"
-	.balign 4
-_cmdline:
-	.space 128
-	.size _cmdline,.-_cmdline
+	.balign 16
+	.globl _PSP
+_PSP:
+	.space 256
+	.size _PSP, .-_PSP
+
+	/* Purely for sanity */
+	.section ".null","a"
+	.long 0,0,0,0
diff --git a/dos/dosexe.ld b/dos/dosexe.ld
index bd6ad8b..733f73d 100644
--- a/dos/dosexe.ld
+++ b/dos/dosexe.ld
@@ -35,16 +35,23 @@
 	__payload_len = ABSOLUTE(__payload_end) - ABSOLUTE(__payload_start);
 	__payload_dwords = __payload_len >> 2;
 
-	__text_lma = __payload_lma + syslinux_size;
-	__payload_sseg = (__payload_lma - __text_lma) >> 4;
-	_exe_text_seg  = (__text_lma - __header_size) >> 4;
+	__dgroup_lma = __payload_lma + syslinux_size;
+	__payload_sseg = (__payload_lma - __dgroup_lma) >> 4;
+	_exe_text_seg  = (__dgroup_lma - __header_size) >> 4;
 
 /*
  *	__assert1 = ASSERT((__payload_len == syslinux_ldlinux_size),
  *	"syslinux_size must equal the size of .payload");
  */
 	. = 0;
-	.text : AT (__text_lma) {
+	__null = .;
+	.null : AT(__dgroup_lma) {
+		*(.null)
+	}
+
+	. = ALIGN(16);
+	__text_vma = .;
+	.text : AT (__text_vma + __dgroup_lma) {
 		*(.text .stub .text.* .gnu.linkonce.t.*)
 		*(.gnu.warning)
 	} =0x90909090
@@ -52,7 +59,7 @@
 
 	. = ALIGN(16);
 	__rodata_vma = .;
-	.rodata : AT (__rodata_vma + __text_lma) {
+	.rodata : AT (__rodata_vma + __dgroup_lma) {
 		*(.rodata .rodata.* .gnu.linkonce.r.*)
 	}
 
@@ -60,15 +67,15 @@
 	   data within same 128-byte chunk. */
 	. = ALIGN(128);
 	__data_vma = .;
-	.data : AT (__data_vma + __text_lma) {
+	.data : AT (__data_vma + __dgroup_lma) {
 		*(.data .data.* .gnu.linkonce.d.*)
 		SORT(CONSTRUCTORS)
 	}
 	.data1 : { *(.data1) }
 	_edata = .;
 
-	_exe_edata_low    = ((_edata + __text_lma) & 511);
-	_exe_edata_blocks = ((_edata + __text_lma) + 511) >> 9;
+	_exe_edata_low    = ((_edata + __dgroup_lma) & 511);
+	_exe_edata_blocks = ((_edata + __dgroup_lma) + 511) >> 9;
 
 	.bss (NOLOAD) : {
 		__bss_start = .;
diff --git a/dos/getsetsl.c b/dos/getsetsl.c
index 67e954d..fadef43 100644
--- a/dos/getsetsl.c
+++ b/dos/getsetsl.c
@@ -11,15 +11,23 @@
 #include <stdlib.h>
 
 #include "syslxint.h"
+#include "mystuff.h"
 
-#define __noinline __attribute__((noinline))
+static inline void *set_fs_sl(const void *p)
+{
+    uint16_t seg;
+
+    seg = ds() + ((size_t) p >> 4);
+    set_fs(seg);
+    return (void *)((size_t) p & 0xf);
+}
 
 #if 0				/* unused */
 uint8_t get_8_sl(const uint8_t * p)
 {
     uint8_t v;
 
-    p = set_fs(p);
+    p = set_fs_sl(p);
     asm volatile("movb %%fs:%1,%0":"=q" (v):"m"(*p));
     return v;
 }
@@ -29,7 +37,7 @@
 {
     uint16_t v;
 
-    p = set_fs(p);
+    p = set_fs_sl(p);
     asm volatile("movw %%fs:%1,%0":"=r" (v):"m"(*p));
     return v;
 }
@@ -38,7 +46,7 @@
 {
     uint32_t v;
 
-    p = set_fs(p);
+    p = set_fs_sl(p);
     asm volatile("movl %%fs:%1,%0":"=r" (v):"m"(*p));
     return v;
 }
@@ -47,7 +55,7 @@
 uint64_t get_64_sl(const uint64_t * p)
 {
     uint32_t v0, v1;
-    const uint32_t *pp = (const uint32_t *)set_fs(p);
+    const uint32_t *pp = (const uint32_t *)set_fs_sl(p);
 
     asm volatile("movl %%fs:%1,%0" : "=r" (v0) : "m" (pp[0]));
     asm volatile("movl %%fs:%1,%0" : "=r" (v1) : "m" (pp[1]));
@@ -58,26 +66,26 @@
 #if 0				/* unused */
 void set_8_sl(uint8_t * p, uint8_t v)
 {
-    p = set_fs(p);
+    p = set_fs_sl(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);
+    p = set_fs_sl(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);
+    p = set_fs_sl(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);
+    uint32_t *pp = (uint32_t *)set_fs_sl(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)));
 }
diff --git a/dos/mystuff.h b/dos/mystuff.h
index 2534441..2d9574d 100644
--- a/dos/mystuff.h
+++ b/dos/mystuff.h
@@ -2,8 +2,7 @@
 #define MYSTUFF_H
 
 #include <inttypes.h>
-
-#define NULL ((void *)0)
+#include <stddef.h>
 
 unsigned int skip_atou(const char **s);
 unsigned int atou(const char *s);
@@ -21,4 +20,60 @@
 int int25_read_sector(unsigned char drive, struct diskio *dio);
 int int26_write_sector(unsigned char drive, struct diskio *dio);
 
+struct psp {
+    uint16_t	int20;
+    uint16_t	nextpara;
+    uint8_t	resv1;
+    uint8_t	dispatcher[5];
+    uint32_t	termvector;
+    uint32_t	ctrlcvector;
+    uint32_t	criterrvector;
+    uint16_t	resv2[11];
+    uint16_t	environment;
+    uint16_t	resv3[23];
+    uint8_t	fcb[2][16];
+    uint32_t	resv4;
+    uint8_t	cmdlen;
+    char	cmdtail[127];
+} __attribute__((packed));
+
+extern struct psp _PSP;
+
+static inline __attribute__((const))
+uint16_t ds(void)
+{
+    uint16_t v;
+    asm("movw %%ds,%0":"=rm"(v));
+    return v;
+}
+
+static inline void set_fs(uint16_t seg)
+{
+    asm volatile("movw %0,%%fs"::"rm" (seg));
+}
+
+static inline uint8_t get_8_fs(size_t offs)
+{
+    uint8_t v;
+    asm volatile("movb %%fs:%1,%0"
+		 : "=q" (v) : "m" (*(const uint8_t *)offs));
+    return v;
+}
+
+static inline uint16_t get_16_fs(size_t offs)
+{
+    uint16_t v;
+    asm volatile("movw %%fs:%1,%0"
+		 : "=r" (v) : "m" (*(const uint16_t *)offs));
+    return v;
+}
+
+static inline uint32_t get_32_fs(size_t offs)
+{
+    uint32_t v;
+    asm volatile("movl %%fs:%1,%0"
+		 : "=r" (v) : "m" (*(const uint32_t *)offs));
+    return v;
+}
+
 #endif /* MYSTUFF_H */
diff --git a/dos/syslinux.c b/dos/syslinux.c
index eb8bace..63a3a85 100644
--- a/dos/syslinux.c
+++ b/dos/syslinux.c
@@ -41,7 +41,7 @@
 void pause(void)
 {
     uint16_t ax;
-    
+
     asm volatile("int $0x16" : "=a" (ax) : "a" (0));
 }
 #else
@@ -187,7 +187,7 @@
     dio.sectors = nsecs;
     dio.bufoffs = (uintptr_t) buf;
     dio.bufseg = data_segment();
-    
+
     if (dos_version >= 0x070a) {
 	/* Try FAT32-aware system call first */
 	asm volatile("int $0x21 ; jc 1f ; xorw %0,%0\n"
@@ -220,7 +220,7 @@
     dio.sectors = nsecs;
     dio.bufoffs = (uintptr_t) buf;
     dio.bufseg = data_segment();
-    
+
     if (dos_version >= 0x070a) {
 	/* Try FAT32-aware system call first */
 	asm volatile("int $0x21 ; jc 1f ; xorw %0,%0\n"
@@ -402,14 +402,6 @@
 
 static inline void get_dos_version(void)
 {
-    uint16_t ver;
-
-    asm("int $0x21 ; xchgb %%ah,%%al"
-	: "=a" (ver) 
-	: "a" (0x3001)
-	: "ebx", "ecx");
-    dos_version = ver;
-
     dprintf("DOS version %d.%d\n", (dos_version >> 8), dos_version & 0xff);
 }
 
@@ -475,7 +467,7 @@
     if (hard_lock) {
 	/* Hard locking, only level 4 supported */
 	/* This is needed for Win9x in DOS mode */
-	
+
 	err = do_lock(4);
 	if (err) {
 	    if (err == 0x0001) {
diff --git a/extlinux/main.c b/extlinux/main.c
index e925a1d..9ee9abb 100644
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -440,13 +440,11 @@
     return 0;
 }
 
-static int rewrite_boot_image(int devfd, const char *filename)
+static int rewrite_boot_image(int devfd, const char *path, const char *filename)
 {
     int fd;
     int ret;
     int modbytes;
-    char path[PATH_MAX];
-    char slash;
 
     /* Let's create LDLINUX.SYS file again (if it already exists, of course) */
     fd = open(filename,  O_WRONLY | O_TRUNC | O_CREAT | O_SYNC,
@@ -470,8 +468,6 @@
 	goto error;
     }
 
-    sscanf(filename, "%s%cldlinux.sys", path, &slash);
-
     /* Map the file, and patch the initial sector accordingly */
     modbytes = patch_file_and_bootblock(fd, path, devfd);
 
@@ -525,7 +521,7 @@
     }
     close(fd);
 
-    fd = rewrite_boot_image(devfd, file);
+    fd = rewrite_boot_image(devfd, path, file);
     if (fd < 0)
 	goto bail;
 
@@ -648,12 +644,16 @@
  */
 static int xfs_install_file(const char *path, int devfd, struct stat *rst)
 {
-    static char file[PATH_MAX];
+    static char file[PATH_MAX + 1];
+    static char c32file[PATH_MAX + 1];
     int dirfd = -1;
     int fd = -1;
+    int retval;
 
-    snprintf(file, PATH_MAX, "%s%sldlinux.sys",
-	     path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
+    snprintf(file, PATH_MAX + 1, "%s%sldlinux.sys", path,
+	     path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
+    snprintf(c32file, PATH_MAX + 1, "%s%sldlinux.c32", path,
+	     path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
 
     dirfd = open(path, O_RDONLY | O_DIRECTORY);
     if (dirfd < 0) {
@@ -673,7 +673,7 @@
 
     close(fd);
 
-    fd = rewrite_boot_image(devfd, file);
+    fd = rewrite_boot_image(devfd, path, file);
     if (fd < 0)
 	goto bail;
 
@@ -689,6 +689,26 @@
     close(dirfd);
     close(fd);
 
+    dirfd = -1;
+    fd = -1;
+
+    fd = open(c32file, O_WRONLY | O_TRUNC | O_CREAT | O_SYNC,
+	      S_IRUSR | S_IRGRP | S_IROTH);
+    if (fd < 0) {
+	perror(c32file);
+	goto bail;
+    }
+
+    retval = xpwrite(fd, syslinux_ldlinuxc32, syslinux_ldlinuxc32_len, 0);
+    if (retval != (int)syslinux_ldlinuxc32_len) {
+	fprintf(stderr, "%s: write failure on %s\n", program, file);
+	goto bail;
+    }
+
+    close(fd);
+
+    sync();
+
     return 0;
 
 bail:
diff --git a/libinstaller/syslxint.h b/libinstaller/syslxint.h
index e5428b7..59e3e5e 100644
--- a/libinstaller/syslxint.h
+++ b/libinstaller/syslxint.h
@@ -124,23 +124,6 @@
  */
 #ifdef __MSDOS__
 
-static inline __attribute__ ((const))
-uint16_t ds(void)
-{
-    uint16_t v;
-    asm("movw %%ds,%0":"=rm"(v));
-    return v;
-}
-
-static inline void *set_fs(const void *p)
-{
-    uint16_t seg;
-
-    seg = ds() + ((size_t) p >> 4);
-    asm volatile ("movw %0,%%fs"::"rm" (seg));
-    return (void *)((size_t) p & 0xf);
-}
-
 uint8_t get_8_sl(const uint8_t * p);
 uint16_t get_16_sl(const uint16_t * p);
 uint32_t get_32_sl(const uint32_t * p);
diff --git a/mk/elf.mk b/mk/elf.mk
index 76b5487..bd8775c 100644
--- a/mk/elf.mk
+++ b/mk/elf.mk
@@ -47,7 +47,7 @@
 core = $(topdir)/core
 
 ifneq ($(NOGPL),1)
-GPLLIB     = $(objdir)/com32/gpllib/libcom32gpl.c32
+GPLLIB     = $(objdir)/com32/gpllib/libgpl.c32
 GPLINCLUDE = -I$(com32)/gplinclude
 else
 GPLLIB     =
@@ -68,7 +68,7 @@
 LNXSFLAGS  = -g
 LNXLDFLAGS = -g
 
-C_LIBS	   = $(objdir)/com32/libutil/libutil_com.c32 $(GPLLIB) \
+C_LIBS	   = $(objdir)/com32/libutil/libutil.c32 $(GPLLIB) \
 	     $(objdir)/com32/lib/libcom32.c32
 C_LNXLIBS  = $(objdir)/com32/libutil/libutil_lnx.a \
 	     $(objdir)/com32/elflink/ldlinux/ldlinux_lnx.a
@@ -95,5 +95,9 @@
 %.lnx: %.lo $(LNXLIBS) $(C_LNXLIBS)
 	$(CC) $(LNXCFLAGS) -o $@ $^
 
-%.c32: %.o $(C_LIBS)
+.PRECIOUS: %.elf
+%.elf: %.o $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
+
+%.c32: %.elf
+	$(OBJCOPY) --strip-debug --strip-unneeded $< $@
diff --git a/mk/lib.mk b/mk/lib.mk
index 499a13b..9450277 100644
--- a/mk/lib.mk
+++ b/mk/lib.mk
@@ -161,7 +161,7 @@
 
 LIBMODULE_OBJS = \
 	sys/module/common.o sys/module/$(ARCH)/elf_module.o		\
-	sys/module/$(ARCH)/shallow_module.o	sys/module/elfutils.o	\
+	sys/module/elfutils.o	\
 	sys/module/exec.o sys/module/elf_module.o
 
 # ZIP library object files
@@ -237,3 +237,6 @@
 
 .c.ls:
 	$(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -S -o $@ $<
+
+%.c32: %.elf
+	$(OBJCOPY) --strip-debug --strip-unneeded $< $@
diff --git a/txt/.gitignore b/txt/.gitignore
new file mode 100644
index 0000000..55c6041
--- /dev/null
+++ b/txt/.gitignore
@@ -0,0 +1,7 @@
+*.1
+*.5
+*.html
+*.pdf
+*.text
+*.xml
+docbook-xsl.css
diff --git a/txt/Makefile b/txt/Makefile
new file mode 100644
index 0000000..0e4cfb4
--- /dev/null
+++ b/txt/Makefile
@@ -0,0 +1,113 @@
+## -----------------------------------------------------------------------
+##
+##   Copyright 2012 Gene Cumm
+##
+##   Some logic from win32/Makefile:
+##     Copyright 1998-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.
+##
+## -----------------------------------------------------------------------
+
+##
+## AsciiDoc documentation for syslinux
+##
+
+topdir = ..
+MAKEDIR = $(topdir)/mk
+# include $(MAKEDIR)/embedded.mk
+
+VPATH = $(SRC)
+
+A2X_OPTS	 = -k
+# A2X_OPTS	+= -v
+A2X_MAN_OPTS	 = -D man -f manpage
+
+DOCS 		 = syslinux.txt syslinux-cli.txt syslinux.cfg.txt
+MAN_DOCS	 = man/syslinux.1 man/syslinux-cli.1 man/syslinux.cfg.5
+HTML_DOCS	:= $(patsubst %.txt,html/%.html,$(DOCS)) 
+XHTML_DOCS	:= $(patsubst %.txt,%.html,$(DOCS))
+# MAN_DOCS	:= $(patsubst %.txt,man/%.1,$(DOCS1)) $(patsubst %.txt,man/%.5,$(DOCS5))
+TEXT_DOCS	:= $(patsubst %.txt,%.text,$(DOCS))
+PDF_DOCS	:= $(patsubst %.txt,%.pdf,$(DOCS))
+TARGETS		 =
+
+# ASCIIDOC_OK := $(shell which asciidoc 2>&1 ; echo $$?)
+ASCIIDOC_OK	:= $(shell which asciidoc > /dev/null ; echo $$?)
+A2X_XML_OK	:= $(shell a2x $(A2X_OPTS) -f docbook hello.txt 2>&1 ; echo $$?)
+ifeq ($(A2X_XML_OK),0)
+A2X_MAN_OK	:= $(shell [ ! -d man ] && mkdir man ; a2x $(A2X_MAN_OPTS) hello.txt 2>&1 ; echo $$?)
+A2X_XHTML_OK	:= $(shell a2x $(A2X_OPTS) -f xhtml hello.xml 2>&1 ; echo $$?)
+A2X_TEXT_OK	:= $(shell a2x $(A2X_OPTS) -f text hello.xml 2>&1 ; echo $$?)
+endif
+
+ifeq ($(ASCIIDOC_OK),0)
+TARGETS		+= $(HTML_DOCS)
+endif
+ifeq ($(A2X_MAN_OK),0)
+TARGETS		+= $(MAN_DOCS)
+endif
+ifeq ($(A2X_XHTML_OK),0)
+TARGETS		+= $(XHTML_DOCS)
+endif
+ifeq ($(A2X_TEXT_OK),0)
+TARGETS		+= $(TEXT_DOCS)
+endif
+
+# $(HTML_DOCS) $(MAN_DOCS) $(XHTML_DOCS) $(TEXT_DOCS)
+all:	$(TARGETS)
+
+syslinux.cfg.txt:	com-bug.txt com-rpt.txt
+
+# During 'make all', *.xml is kept but deleted at the end; do we _really_
+#	need the XML longer?
+.PRECIOUS:	%.xml
+
+# %.html:	%.txt
+# 	asciidoc -D html $<
+
+html/ man/ text/ xhtml/:
+	mkdir $@
+
+html/%.html:	%.txt html/
+	asciidoc -o $@ $<
+
+# As of AsciiDoc-8.5.2, altering the output filename for a2x does not appear possible
+# xhtml/%.html:	%.txt
+# 	a2x $(A2X_OPTS) -D xhtml -f xhtml $<
+# text/%.text:	%.xml %.txt
+# 	a2x $(A2X_OPTS) -D text -f text $<
+
+%.xml:	%.txt
+	a2x $(A2X_OPTS) -f docbook $<
+
+# when %.xml is missing, an update to %.txt must force regeneration
+%.html:	%.xml %.txt
+	a2x $(A2X_OPTS) -f xhtml $<
+
+man/%.1:	%.txt man/
+	a2x $(A2X_MAN_OPTS) $<
+
+man/%.5:	%.txt man/
+	a2x $(A2X_MAN_OPTS) $<
+
+%.text:	%.xml %.txt
+	a2x $(A2X_OPTS) -f text $<
+
+%.pdf:	%.xml %.txt
+	a2x $(A2X_OPTS) -f pdf $<
+
+tidy dist:
+	rm -f *~ *.xml *.text.html text/*.text.html text/*.xml xhtml/*.xml
+
+clean: tidy
+
+spotless: clean
+	rm -f *.1 *.5 *.css *.html *.text html/*.html man/*.1 man/*.5 text/*.text xhtml/*.html xhtml/*.css
+
+-include .*.d
diff --git a/txt/com-bug.txt b/txt/com-bug.txt
new file mode 100644
index 0000000..f16139a
--- /dev/null
+++ b/txt/com-bug.txt
@@ -0,0 +1,11 @@
+
+// == KNOWN BUGS ==
+
+Several known bugs/common problems are listed at
+http://www.syslinux.org/wiki/index.php/Common_Problems and known
+hardware compatibility issues are listed at
+http://www.syslinux.org/wiki/index.php/Hardware_Compatibility with
+filename translation difficulty and early PXE stacks being some of the
+most common.  Reporting of other encountered issues is welcome and
+appreciated.
+
diff --git a/txt/com-name.txt b/txt/com-name.txt
new file mode 100644
index 0000000..b24811f
--- /dev/null
+++ b/txt/com-name.txt
@@ -0,0 +1,12 @@
+
+// == NAMING CONVENTION ==
+
+As of 3.73, a standard for naming conventions was adopted to more
+clearly distinguish different aspects.  The moniker "The *Syslinux*
+Project", in standard proper noun capitalization, shall be used to refer
+to the project as a whole. The all-caps form shall be used to refer to a
+particular loader variant such as "*SYSLINUX*" for the standard disk
+(floppy/hard disk; formerly just FAT) loader.  The all-lower case form
+should be used to refer to a particular installer such as
+"syslinux-mtools" for the mtools-based installer for *SYSLINUX*.
+
diff --git a/txt/com-rpt.txt b/txt/com-rpt.txt
new file mode 100644
index 0000000..fe368ee
--- /dev/null
+++ b/txt/com-rpt.txt
@@ -0,0 +1,22 @@
+
+// == BUG REPORTS ==
+
+I would appreciate hearing of any problems you have with Syslinux.  I
+would also like to hear from you if you have successfully used Syslinux,
+*especially* if you are using it for a distribution.
+
+If you are reporting problems, please include all possible information
+about your system and your BIOS; the vast majority of all problems
+reported turn out to be BIOS or hardware bugs, and I need as much
+information as possible in order to diagnose the problems.
+
+There is a mailing list for discussion among Syslinux users and for
+announcements of new and test versions.  To join, or to browse the
+archive, go to:
+
+http://www.zytor.com/mailman/listinfo/syslinux
+
+Please DO NOT send HTML messages or attachments to the mailing list
+(including multipart/alternative or similar.)  All such messages will be
+bounced.
+
diff --git a/txt/hello.txt b/txt/hello.txt
new file mode 100644
index 0000000..3757627
--- /dev/null
+++ b/txt/hello.txt
@@ -0,0 +1,16 @@
+= hello(1) =
+:doctype: manpage
+:author: World Greeter
+:author-email: hello@domain.local
+:revdate: 1970-01-01
+:data-uri:
+
+
+== NAME ==
+hello - hello world
+
+== SYNOPSIS ==
+hello
+
+== Description ==
+Say hello and greet the world
diff --git a/txt/syslinux-cli.txt b/txt/syslinux-cli.txt
new file mode 100644
index 0000000..fa6a4dc
--- /dev/null
+++ b/txt/syslinux-cli.txt
@@ -0,0 +1,65 @@
+= syslinux-cli(1) =
+:doctype: manpage
+:revdate: 2012-11-10
+:author: H. Peter Anvin
+:author-email: hpa@zytor.com
+:editor1: Gene Cumm
+:editor1-email: gene.cumm@gmail.com
+:editor1-revlast: 2012-11-10
+:data-uri:
+
+== NAME ==
+syslinux-cli - *Syslinux* boot prompt/command line interface
+
+
+== DESCRIPTION ==
+*Syslinux*'s boot prompt provides a very simplistic command line
+interface for loading modules and booting kernels.
+
+
+== BOOT PROMPT ==
+=== COMMAND LINE KEYSTROKES ===
+The command line prompt supports the following keystrokes:
+
+  <Enter>		boot specified command line
+  <BackSpace>		erase one character
+  <Ctrl-U>		erase the whole line
+  <Ctrl-V>		display the current Syslinux version
+  <Ctrl-W>		erase one word
+  <Ctrl-X>		force text mode
+  <Tab>			list matching labels
+  <F1>..<F12>		help screens (if configured)
+  <Ctrl-F><digit>	equivalent to F1..F10
+  <Ctrl-C>		interrupt boot in progress
+  <Esc>			interrupt boot in progress
+  <Ctrl-N>		display network information (PXELINUX only)
+
+
+=== WORKING DIRECTORY ===
+At start, the initial working directory for *SYSLINUX*/*ISOLINUX* will
+be the directory containing the initial configuration file.  If no
+configuration file is found, *SYSLINUX* should default to the
+install-time working directory, however this is a known issue with some
+versions including 4.06.
+
+At start, the initial working directory for *PXELINUX* will be the
+parent directory of pxelinux.0 unless overridden with DHCP option 210. 
+If no configuration file is found, *PXELINUX* will start a timer to
+reboot the system in an attempt to restart the boot process and resolve
+a possible transient issue.
+
+
+=== ALTERNATE FILENAMES ===
+For kernel-like file names given on the command line, *Syslinux* will
+attempt to append file name extensions to the specified file name when
+the file is not found in the following order: .0[*PXELINUX* only],
+.bin[*ISOLINUX* only], .bs[*SYSLINUX* only], .bss[*SYSLINUX* only],
+.c32, .cbt[Up to 4.06], .com[Up to 4.06] and .img[*ISOLINUX* 1.65-4.04 only].
+
+// Is this true of file names specified in a config?  As of when?
+
+
+== AUTHOR ==
+This AsciiDoc derived document is a modified version of the original
+*SYSLINUX* documentation by {author} <{author-email}>.  The conversion
+to an AsciiDoc was made by {editor1} <{editor1-email}>
diff --git a/txt/syslinux.cfg.txt b/txt/syslinux.cfg.txt
new file mode 100644
index 0000000..16abe0e
--- /dev/null
+++ b/txt/syslinux.cfg.txt
@@ -0,0 +1,572 @@
+= syslinux.cfg(5) =
+:doctype: manpage
+:revdate: 2012-10-28
+:author: H. Peter Anvin
+:author-email: hpa@zytor.com
+:editor1: Gene Cumm
+:editor1-email: gene.cumm@gmail.com
+:editor1-revlast: 2012-10-28
+:nbsp8: &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
+:nbsp32: {nbsp8}{nbsp8}{nbsp8}{nbsp8}
+:data-uri:
+
+== NAME ==
+syslinux.cfg - *Syslinux* configuration file
+
+
+== DESCRIPTION ==
+Configuration for the boot behavior and user experience of *Syslinux*
+boot loaders, the format of display files and the boot prompt behavior.
+
+Blank lines are ignored.
+
+Note that the configuration file is not completely decoded.  Syntax
+different from the one described above may still work correctly in this
+version of *Syslinux*, but may break in a future one.
+
+
+== LOCATION/NAME ==
+*SYSLINUX* (before 4.00) used the configuration filename of
+syslinux.cfg.  *EXTLINUX* (merged into *SYSLINUX* as of 4.00) used the
+filename extlinux.conf.  Both default to searching for the config file
+in the installed directory (containing ldlinux.sys/extlinux.sys).  As of
+4.00, *SYSLINUX* will search for extlinux.conf then syslinux.cfg in each
+directory before falling back to the next directory.
+
+As of 3.35, *SYSLINUX* also searches /boot/syslinux, /syslinux and /.
+
+*ISOLINUX* (before 4.02) used the configuration filename of
+isolinux.cfg, searching  /boot/isolinux (starting 2.00), then /isolinux
+and /.  As of 4.02, *ISOLINUX* will search for isolinux.cfg then
+syslinux.cfg in /boot/isolinux before searching for the same files in
+/isolinux, /boot/syslinux, /syslinux, and /.
+
+
+== GLOBAL DIRECTIVES - MAIN ==
+*#* comment::
+A line comment.  As of version 3.10, the space between the *#* and the
+comment is no longer required.
+
+*MENU* any string::
+(3.00+) A directive for the simple menu system, treated as a comment
+outside the menu.  See menu.txt.
+
+*INCLUDE* 'filename'::
+Inserts the contents of another file at this point in the configuration
+file. Files can currently be nested up to 16 levels deep, but it is not
+guaranteed that more than 8 levels will be supported in the future.
+
+*DEFAULT* 'kernel' 'options...'::
+Sets the default command line.  If *Syslinux* boots automatically, it
+will act just as if the entries after *DEFAULT* had been typed in at the
+'boot:' prompt.  Multiple uses will result in an override.
++
+If no configuration file is present, or no *DEFAULT* or *UI* entry is
+present in the config file, an error message is displayed and the
+'boot:' prompt is shown (3.85+).
+
+*UI* 'module' 'options...'::
+Selects a specific user interface 'module' (typically menu.c32 or
+vesamenu.c32).  The command-line interface treats this as a directive
+that overrides the *DEFAULT* directive to load this module instead at
+startup and for an empty command line and *PROMPT* directive to not
+prompt.  Multiple uses will result in an override.
+
+*LABEL* 'mylabel'::
+Begin a new *LABEL* clause.  If 'mylabel' is entered as the kernel to
+boot, *Syslinux* should instead boot "image" (specified by a directive
+from *KERNEL-LIKE DIRECTIVES*) with any specified *DUAL-PURPOSE
+DIRECTIVES* being used instead of the global instance.
++
+'mylabel' must be unique.  Currently the first instance is used but may
+result in an error or undesired behavior.  'mylabel' ends at the first
+character that is not a non-white-space printable character and should
+be restricted to non-white-space typeable characters.  Prior to version
+3.32, this would transformed to a DOS compatible format of 8.3 with a
+restricted character set.  A *LABEL* clause must contain exactly 1 of
+the *KERNEL-LIKE DIRECTIVES* and may contain 1 each of the *LABEL-ONLY
+DIRECTIVES* or *DUAL-PURPOSE DIRECTIVES*.
++
+Within a *LABEL*, using multiple *KERNEL-LIKE DIRECTIVES* or reuse of
+*LABEL-ONLY DIRECTIVES* or *DUAL-PURPOSE DIRECTIVES* will result in an
+override.  Otherwise, multiple instances of the same directive will
+result in the last being effective.
+
+
+== DUAL-PURPOSE DIRECTIVES ==
+Use of any of the *DUAL-PURPOSE DIRECTIVES* as *GLOBAL DIRECTIVES* is
+discouraged if there will be any non-Linux images loaded as *ALL* images
+will get these, including those manually entered at the 'boot:' prompt.
+
+*APPEND* 'options...'::
+Add one or more options to the kernel command line.  These are added
+both for automatic and manual boots.  The options are added at the very
+beginning of the kernel command line, usually permitting explicitly
+entered kernel options to override them.  This is the equivalent of the
+LILO "append" option.
++
+Use of the parameter 'initrd=' supports multiple filenames separated by
+commas (ie 'initrd=initrd_file1,initrd_file2') within a single instance.
+This is mostly useful for initramfs, which can be composed of multiple
+separate cpio or cpio.gz archives.
++
+Note: all initrd files except the last one are zero-padded to a 4K page
+boundary.  This should not affect initramfs.
++
+Note: Only the last effective 'initrd=' parameter is used for loading
+initrd files.
+
+*APPEND* -::
+Append nothing.  *APPEND* with a single hyphen as argument in a *LABEL*
+section can be used to override a global *APPEND*.
+
+//[FIXME: Shorten subdefinitions]
+*IPAPPEND* 'flag_val'::
+(*PXELINUX* only) The *IPAPPEND* option is available only on *PXELINUX*.
+ The flag_val is an OR (sum) of the following integer options:
+
+ifndef::doctype-manpage[[horizontal]]
+*1*::: An option of the following format should be generated, based on
+the input from the DHCP/BOOTP or PXE boot server and added to the kernel
+command line(see note below):
++
+----
+ip=<client-ip>:<boot-server-ip>:<gw-ip>:<netmask>
+----
++
+NOTE:  The use of option 1 is no substitute for running a DHCP client in
+the booted system and should instead only be used to seed the client for
+a request.  Without regular renewals, the lease acquired by the PXE BIOS
+will expire, making the IP address available for reuse by the DHCP
+server.
++
+*2*::: An option of the following format should be generated, in
+dash-separated hexadecimal with leading hardware type (same as for the
+configuration file; see pxelinux.txt.) and added to the kernel command
+line, allowing an initrd program to determine from which interface the
+system booted:
++
+----
+BOOTIF=<hardware-address-of-boot-interface>
+----
++
+*4*::: An option of the following format should be generated, in lower
+case hexadecimal in the format normally used for UUIDs (same as for the
+configuration file; see pxelinux.txt.) and added to the kernel command
+line:
++
+----
+SYSUUID=<system uuid>
+----
+
+
+== KERNEL-LIKE DIRECTIVES ==
+// Alpha sort after KERNEL and LINUX
+*KERNEL* 'image'::
+Load a kernel-like file 'image' with automatic filetype detection based
+on file extension, listed under the non-auto-detecting directives,
+defaulting to *LINUX*.
+
+//[FIXME: Should "'image' as " be removed entirely or added to all? 
+*LINUX* is used as an example]
+*LINUX* 'image'::
+Load 'image' as a Linux-like kernel. MEMDISK is an example of a
+non-Linux kernel loaded in a Linux-like fashion.
+
+*BOOT* 'image'::
+(*ISOLINUX* only: .bin; *SYSLINUX* only: .bs) Load a boot sector.  .bin
+is a "CD boot sector" and .bs is a regular disk boot sector.
+
+*BSS* 'image'::
+(*SYSLINUX* only: .bss) Load a BSS image, a .bs image with the DOS
+superblock patched in.
+
+*COMBOOT* 'image'::
+(.com, .cbt; Removed as of 5.00) Load a *Syslinux* COMBOOT image.  .com
+images may also be runnable from DOS while .cbt images are not.  See
+also *comboot.txt*
+
+*COM32* 'image'::
+(.c32) Load a *Syslinux* COM32 (32-bit *COMBOOT*) image.  See also
+*comboot.txt*
+
+*CONFIG* 'image'::
+Load a new configuration file.  The configuration file is read, the
+working directory is changed (if specified via an *APPEND*), then the
+configuration file is parsed.
+
+*FDIMAGE* 'image'::
+(Removed as of 4.05, added 1.65; *ISOLINUX* only: .img) Load a disk
+image.
+
+*LOCALBOOT* 'type'::
+(*PXELINUX* 1.53+; *ISOLINUX* ??3.10+; *SYSLINUX* 3.70+)Attempt a
+different local boot method.  The special value -1 causes the boot
+loader to report failure to the BIOS, which, on recent BIOSes, should
+mean that the next boot device in the boot sequence should be activated.
+ Values other than those documented may produce undesired results.
++
+On *PXELINUX*, 'type' 0 means perform a normal boot.  'type' 4 will
+perform a local boot with the Universal Network Driver Interface (UNDI)
+driver still resident in memory.  Finally, 'type' 5 will perform a local
+boot with the entire PXE stack, including the UNDI driver, still
+resident in memory. All other values are undefined.  If you don't know
+what the UNDI or PXE stacks are, don't worry -- you don't want them,
+just specify 0.
++
+On *ISOLINUX*/*SYSLINUX*, the 'type' specifies the local drive number to
+boot from; 0x00 is the primary floppy drive and 0x80 is the primary hard
+drive.
+
+*PXE* 'image'::
+(*PXELINUX* only: .0) Load a PXE NBP (Network Boot Program) image.  The
+PXE protocol does not provide any means for specifiying or using a
+command line or initrd.
+
+
+== LABEL-ONLY DIRECTIVES ==
+*INITRD* 'initrd_file'::
+(3.71+) An initrd can be specified in a separate statement (INITRD)
+instead of as part of the *APPEND* statement; this functionally appends
+"initrd=initrd_file" to the kernel command line.  Like 'initrd=', this
+also supports multiple comma separated file names (see *APPEND*).
+
+
+== GLOBAL DIRECTIVES - SECONDARY ==
+These are global directives that are of lesser importance, often
+affecting the user experience and not the boot process.
+
+*ALLOWOPTIONS* 'flag_val'::
+If 'flag_val' is 0, the user is not allowed to specify any arguments on
+the kernel command line.  The only options recognized are those
+specified in an *APPEND*) statement.  The default is 1.
+
+*IMPLICIT* 'flag_val'::
+If 'flag_val' is 0, do not load a kernel image unless it has been
+explicitly named in a *LABEL* statement.  The default is 1.
+
+*TIMEOUT* 'timeout'::
+Indicates how long to wait at the 'boot:' prompt until booting
+automatically, in units of 1/10 s.  The timeout is cancelled as soon as
+the user types anything on the keyboard, the assumption being that the
+user will complete the command line already begun.  A timeout of zero
+(the default) will disable the timeout completely.
+
+*TOTALTIMEOUT* 'timeout'::
+Indicates how long to wait until booting automatically, in units of
+1/10 s.  This timeout is *not* cancelled by user input, and can thus be
+used to deal with serial port glitches or "the user walked away" type
+situations.  A timeout of zero will disable the timeout completely, this
+is also the default.
++
+Both *TIMEOUT* and *TOTALTIMEOUT* can be used together, for example:
++
+----
+# Wait 5 seconds unless the user types something, but
+# always boot after 15 minutes.
+TIMEOUT 50
+TOTALTIMEOUT 9000
+----
+
+// FIXME: be consistent
+*ONTIMEOUT* 'kernel options...'::
+Sets the command line invoked on a timeout.  Normally this is the same
+thing as invoked by 'DEFAULT'.  If this is specified, then 'DEFAULT' is
+used only if the user presses <Enter> to boot.
+
+*ONERROR* 'kernel options...'::
+If a kernel image is not found (either due to it not existing, or
+because *IMPLICIT* is set), run the specified command.  The faulty
+command line is appended to the specified options, so if the *ONERROR*
+directive reads as:
++
+----
+ONERROR xyzzy plugh
+----
++
+and the command line as entered by the user is:
++
+----
+foo bar baz
+----
++
+*Syslinux* will execute the following as if entered by the user:
++
+----
+xyzzy plugh foo bar baz
+----
+
+*SERIAL* 'port [[baudrate] flowcontrol]'::
+Enables a serial port to act as the console.  'port' is a number (0 =
+/dev/ttyS0 = COM1, etc.) or an I/O port address (e.g. 0x3F8); if
+'baudrate' is omitted, the baud rate defaults to 9600 bps.  The serial
+parameters are hardcoded to be 8 bits, no parity, 1 stop bit.
++
+'flowcontrol' is a combination of the following bits:
++
+....
+0x001 - Assert DTR
+0x002 - Assert RTS
+0x008 - Enable interrupts
+0x010 - Wait for CTS assertion
+0x020 - Wait for DSR assertion
+0x040 - Wait for RI assertion
+0x080 - Wait for DCD assertion
+0x100 - Ignore input unless CTS asserted
+0x200 - Ignore input unless DSR asserted
+0x400 - Ignore input unless RI asserted
+0x800 - Ignore input unless DCD asserted
+....
++
+All other bits are reserved.
++
+Typical values are:
++
+....
+    0 - No flow control (default)
+0x303 - Null modem cable detect
+0x013 - RTS/CTS flow control
+0x813 - RTS/CTS flow control, modem input
+0x023 - DTR/DSR flow control
+0x083 - DTR/DCD flow control
+....
++
+For the *SERIAL* directive to be guaranteed to work properly, it should
+be the first directive in the configuration file.
++
+NOTE: 'port' values from 0 to 3 means the first four serial ports
+detected by the BIOS.  They may or may not correspond to the legacy port
+values 0x3F8, 0x2F8, 0x3E8, 0x2E8.
++
+Enabling interrupts (setting the 0x008 bit) may give better
+responsiveness without setting the *NOHALT* option, but could
+potentially cause problems with buggy BIOSes.
+
+*NOHALT* 'flag_val'::
+If 'flag_val' is 1, don't halt the processor while idle. Halting the
+processor while idle significantly reduces the power consumption, but
+can cause poor responsiveness to the serial console, especially when
+using scripts to drive the serial console, as opposed to human
+interaction.
+
+*CONSOLE* 'flag_val'::
+If 'flag_val' is 0, disable output to the normal video console. If
+'flag_val' is 1, enable output to the video console (this is the
+default.)
++
+Some BIOSes try to forward this to the serial console and sometimes make
+a total mess thereof, so this option lets you disable the video console
+on these systems.
+
+*FONT* 'filename'::
+Load a font in .psf format before displaying any output (except the
+copyright line, which is output as ldlinux.sys itself is loaded.) 
+*Syslinux* only loads the font onto the video card; if the .psf file
+contains a Unicode table it is ignored.  This only works on EGA and VGA
+cards; hopefully it should do nothing on others.
+
+*KBDMAP* 'keymap'::
+Install a simple keyboard map.  The keyboard remapper used is *very*
+simplistic (it simply remaps the keycodes received from the BIOS, which
+means that only the key combinations relevant in the default layout --
+usually U.S. English -- can be mapped) but should at least help people
+with AZERTY keyboard layout and the locations of = and , (two special
+characters used heavily on the Linux kernel command line.)
++
+The included program keytab-lilo.pl from the LILO distribution can be
+used to create such keymaps.  The file keytab-lilo.txt contains the
+documentation for this program.
+
+*DISPLAY* 'filename'::
+Displays the indicated file on the screen at boot time (before the boot:
+prompt, if displayed).  Please see the section below on *DISPLAY* files.
++
+NOTE: If the file is missing, this option is simply ignored.
+
+*SAY* 'message'::
+Prints the message on the screen.
+
+*PROMPT* 'flag_val'::
+If 'flag_val' is 0, display the boot: prompt only if the Shift or Alt
+key is pressed, or Caps Lock or Scroll lock is set (this is the
+default).  If 'flag_val' is 1, always display the boot: prompt.
+
+*NOESCAPE* 'flag_val'::
+If 'flag_val' is set to 1, ignore the Shift/Alt/Caps Lock/Scroll Lock
+escapes.  Use this (together with PROMPT 0) to force the default boot
+alternative.
+
+*NOCOMPLETE* 'flag_val'::
+If 'flag_val' is set to 1, the Tab key does not display labels at the
+boot: prompt.
+
+//   ...etc...
+*F1* 'filename'::
+*F2* 'filename'::
+*F3* 'filename'::
+*F4* 'filename'::
+*F5* 'filename'::
+*F6* 'filename'::
+*F7* 'filename'::
+*F8* 'filename'::
+*F9* 'filename'::
+*F10* 'filename'::
+*F11* 'filename'::
+*F12* 'filename'::
+Displays the indicated file on the screen when a function key is pressed
+at the boot: prompt.  This can be used to implement pre-boot online help
+(presumably for the kernel command line options.)  Please see the
+section below on DISPLAY files.
++
+When using the serial console, press <Ctrl-F><digit> to get to the help
+screens, e.g. <Ctrl-F><2> to get to the F2 screen. For F10-F12, hit
+<Ctrl-F><A>, <Ctrl-F>B, <Ctrl-F>C.  For compatibility with earlier
+versions, F10 can also be entered as <Ctrl-F>0.
+
+*PATH* 'path'::
+(5.00+) Specify a colon-separated (':') list of directories to search when
+attempting to load modules. This directive is useful for specifying the
+directories containing the lib*.c32 library files as other modules may
+be dependent on these files, but may not reside in the same directory.
+
+
+== DISPLAY FILE FORMAT ==
+DISPLAY and function-key help files are text files in either DOS or UNIX
+format (with or without <CR>).  In addition, the following special codes
+are interpreted:
+
+//[FIXME]: #1 doesn't break; #2 as-is; #3 broken but not on right; #4
+identical to #3
+// horizontal extends the line's label, reducing the definition
+// tab or space to shift explanation ?  align beginning or end?
+
+// ifndef::doctype-manpage[[horizontal]]
+*<FF>*:: {nbsp32} 				= <Ctrl-L> = ASCII 12 +
+Clear the screen, home the cursor.  Note that the screen is filled with
+the current display color.
+
+*<FF>*::
+= <Ctrl-L> = ASCII 12; Clear the screen, home the cursor.  Note that the
+screen is filled with the current display color.
+
+*<FF>*::                                      <FF> = <Ctrl-L> = ASCII 12
++
+Clear the screen, home the cursor.  Note that the screen is filled with
+the current display color.
+
+*<FF>*::
+<FF> = <Ctrl-L> = ASCII 12 +
+Clear the screen, home the cursor.  Note that the screen is filled with
+the current display color.
+
+*<SI>*'<bg><fg>'::                            <SI> = <Ctrl-O> = ASCII 15
++
+Set the display colors to the specified background and foreground
+colors, where <bg> and <fg> are the 2 hex digits representing 1 byte,
+corresponding to the standard PC display attributes:
++
+        0 = black               8 = dark grey
+        1 = dark blue           9 = bright blue
+        2 = dark green          a = bright green
+        3 = dark cyan           b = bright cyan
+        4 = dark red            c = bright red
+        5 = dark purple         d = bright purple
+        6 = brown               e = yellow
+        7 = light grey          f = white
++
+Picking a bright color (8-f) for the background results in the
+corresponding dark color (0-7), with the foreground flashing.
++
+Colors are not visible over the serial console.
+
+*<CAN>*'filename<newline>'::                 <CAN> = <Ctrl-X> = ASCII 24
++
+If a VGA display is present, enter graphics mode and display the graphic
+included in the specified file.  The file format is an ad hoc format
+called LSS16; the included Perl program "ppmtolss16" can be used to
+produce these images.  This Perl program also includes the file format
+specification.
++
+The image is displayed in 640x480 16-color mode.  Once in graphics mode,
+the display attributes (set by <SI> code sequences) work slightly
+differently: the background color is ignored, and the foreground colors
+are the 16 colors specified in the image file.  For that reason,
+ppmtolss16 allows you to specify that certain colors should be assigned
+to specific color indicies.
++
+Color indicies 0 and 7, in particular, should be chosen with care: 0 is
+the background color, and 7 is the color used for the text printed by
+*Syslinux* itself.
+
+*<EM>*::				<EM> = <Ctrl-Y> = ASCII 25 +
+If we are currently in graphics mode, return to text mode.
+
+*<DLE>*..*<ETB>*::			<Ctrl-P>..<Ctrl-W> = ASCII 16-23
++
+These codes can be used to select which modes to print a certain part of
+the message file in.  Each of these control characters select a specific
+set of modes (text screen, graphics screen, serial port) for which the
+output is actually displayed:
++
+	Character			Text	Graph	Serial
+	------------------------------------------------------
+	<DLE> = <Ctrl-P> = ASCII 16	No	No	No
+	<DC1> = <Ctrl-Q> = ASCII 17	Yes	No	No
+	<DC2> = <Ctrl-R> = ASCII 18	No	Yes	No
+	<DC3> = <Ctrl-S> = ASCII 19	Yes	Yes	No
+	<DC4> = <Ctrl-T> = ASCII 20	No	No	Yes
+	<NAK> = <Ctrl-U> = ASCII 21	Yes	No	Yes
+	<SYN> = <Ctrl-V> = ASCII 22	No	Yes	Yes
+	<ETB> = <Ctrl-W> = ASCII 23	Yes	Yes	Yes
++
+For example, the following will actually print out which mode the
+console is in:
++
+	<DC1>Text mode<DC2>Graphics mode<DC4>Serial port<ETB>
+
+*<SUB>*::                                   <SUB> = <Ctrl-Z> = ASCII 26
++
+End of file (DOS convention).
+
+*<BEL>*::				<BEL> = <Ctrl-G> = ASCII 7 +
+Beep the speaker.
+
+
+== BOOT LOADER IDS USED ==
+The Linux boot protocol supports a "boot loader ID", a single byte where
+the upper nybble specifies a boot loader family (3 = *Syslinux*) and the
+lower nybble is version or, in the case of *Syslinux*, media:
+
+	0x31 (49) = SYSLINUX
+	0x32 (50) = PXELINUX
+	0x33 (51) = ISOLINUX
+	0x34 (52) = EXTLINUX
+
+In recent versions of Linux, this ID is available as
+/proc/sys/kernel/bootloader_type.
+
+
+== NOVICE PROTECTION ==
+*Syslinux* will attempt to detect booting on a machine with too little
+memory, which means the Linux boot sequence cannot complete.  If so, a
+message is displayed and the boot sequence aborted.  Holding down the
+Ctrl key while booting disables this feature.
+
+Any file that *Syslinux* uses can be marked hidden, system or readonly
+if so is convenient; *Syslinux* ignores all file attributes.  The
+*SYSLINUX* installer automatically sets the readonly/hidden/system
+attributes on LDLINUX.SYS.
+
+
+== KNOWN BUGS ==
+include::com-bug.txt[]
+
+
+== BUG REPORTS ==
+include::com-rpt.txt[]
+
+
+== AUTHOR ==
+This AsciiDoc derived document is a modified version of the original
+*SYSLINUX* documentation by {author} <{author-email}>.  The conversion
+to an AsciiDoc was made by {editor1} <{editor1-email}>
diff --git a/txt/syslinux.txt b/txt/syslinux.txt
new file mode 100644
index 0000000..33b03d7
--- /dev/null
+++ b/txt/syslinux.txt
@@ -0,0 +1,217 @@
+= syslinux(1) =
+:doctype: manpage
+:revdate: 2012-10-28
+:author: H. Peter Anvin
+:author-email: hpa@zytor.com
+:editor1: Gene Cumm
+:editor1-email: gene.cumm@gmail.com
+:editor1-revlast: 2012-10-28
+
+
+== NAME ==
+syslinux - Install SYSLINUX to a file system
+
+
+== SYNOPSIS ==
+[verse]
+*syslinux* ['OPTIONS'] 'DEVICE'
+*extlinux* ['OPTIONS'] 'PATH'
+*syslinux* [-h | --help]
+*extlinux* [-h | --help]
+
+
+== DESCRIPTION ==
+Install *SYSLINUX* to the 'DEVICE'/'PATH', altering the boot sector and
+installing the 'ldlinux.sys' boot loader file.  For the Linux installer
+extlinux, 'PATH' is the desired path for the control files on a mounted,
+supported file system and sets the install-time working directory.  For
+all others, 'DEVICE' must specify a FAT12/FAT16/FAT32 file system.  For
+the Linux installers syslinux and syslinux-mtools, 'DEVICE' should be an
+unmounted file system.  For the DOS/Win32/Win64 installers, 'DEVICE'
+should be a drive like 'a:' (case insensitive).
+
+For versions ~4.00 and later, either -i/--install or -U/--update must be
+specified unless modifying the ADV of an existing install (options
+tagged with 'ADV') or requesting the help/usage or version info, .
+
+If, during boot, the Shift or Alt keys are held down, or the Caps or
+Scroll locks are set, *Syslinux* will display a *lilo*(8) -style "boot:"
+prompt. The user can then type a kernel file name followed by any kernel
+parameters. The *Syslinux* bootloader does not need to know about the
+kernel or config files in advance.
+
+*Syslinux* supports the loading of initial ramdisks (initrd) and the
+bzImage kernel format.
+
+Please note, the ldlinux.sys boot loader file is flagged as immutable
+(where applicable) and is modified after copying in to help ensure
+boot-time integrity.  File systems with a sufficiently large boot loader
+reserved area, like btrfs, will have ldlinux.sys installed there rather
+than as a normal file.
+
+
+== OPTIONS ==
+// "See"/"See also" notes should reference long options.
+=== Standalone options ===
+*-i*, *--install*::
+(~4.00+) Install SYSLINUX, regardless of an existing install.
+
+*-U*, *--update*::
+(~4.00+) Update an existing SYSLINUX/EXTLINUX install.  If no Syslinux
+boot loader is present, return an error.
+
+*-h*, *--help*::
+Display help/usage information.
+
+*-v*, *--version*::
+Display version information and exit immediately.
+
+=== Regular Options ===
+// Sorted generally by short argument
+*-a*, *--active*::
+(DOS/Win32/Win64 ONLY) Mark the install target file system's partition
+active.
+
+*-d*, *--directory* 'subdirectory'::
+(Not necessary for extlinux as it is implied by 'PATH') Install the
+*SYSLINUX* control files in a subdirectory with the specified name
+(relative to the root directory on the device).
+
+*--device* 'DEVICE'::
+(extlinux ONLY; 4.06+) Force use of a specific block device (experts
+only).
+
+*-f*, *--force*::
+Force install even if it appears unsafe.  Before 4.00, -f was used for
+--offset in the Linux installers.
+
+*-H*, *--heads* 'head-count'::
+Override the detected number of heads for the geometry.  See also
+*--sector*.
+
+*-m*, *--mbr*:
+(DOS/Win32/Win64 ONLY) Install the regular Syslinux MBR code to the MBR.
+
+*-M*, *--menu-save*::
+(4.00+; ADV) Set the label to select as default on the next boot.
+
+*-o*, *--once* 'command'::
+(ADV) Declare a boot command to be tried on the first boot only.  The
+use of *-o* for the Linux installers syslinux or syslinux-mtools has
+been deprecated as of \~4.00 and is no longer valid as of ~4.02.
+
+*-O*, *--clear-once*::
+Clear the boot-once command.  See also *--once*.
+
+*-r*, *--raid*::
+(ADV) RAID mode.  If boot fails, tell the BIOS to boot the next device
+in the boot sequence (usually the next hard disk) instead of stopping
+with an error message.  This is useful for RAID-1 booting.
+
+*--reset-adv*::
+(ADV) Reset auxilliary data vector.
+
+*-S*, *--sectors* 'sector-count'::
+Override the detected number of sectors for the geometry.  See also
+*--head*.
+
+*-s*, *--stupid*::
+Install a "safe, slow and stupid" version of *SYSLINUX*. This version
+may work on some very buggy BIOSes on which *SYSLINUX* would otherwise
+fail. If you find a machine on which the -s option is required to make
+it boot reliably, please send as much info about your machine as you
+can, and include the failure mode.
+
+*-t*, *--offset* 'offset'::
+(Linux syslinux/syslinux-mtools ONLY) Indicates that the filesystem is
+at an offset from the base of the device or file.
+
+*-z*, *--zipdrive*
+Assume zipdrive geometry ('--heads 64 --sectors 32').  See also *--head*
+and *--sector*.
+
+
+== EXAMPLES ==
+=== Booting DOS ===
+For booting DOS and other similar operating systems, there is an easy
+and generally reliable solution to substitute in SYSLINUX as the primary
+boot loader.
+
+- Make a DOS-bootable disk;  The following are possible commands:
+
+	format a: /s
+	sys a:
+
+- Copy the DOS boot sector off using Linux or copybs.com:
+
+	dd if=/dev/fd0 of=dos.bss bs=512 count=1
+	copybs a: a:dos.bss
+
+- Install SYSLINUX using one of:
+
+	syslinux a:
+	syslinux /dev/fd0		(before 4.00)
+	syslinux -i /dev/fd0		(4.00+)
+
+- For Linux, mount the disk and copy the dos.bss to the disk:
+
+	mount -t msdos /dev/fd0 /mnt
+	cp dos.bss /mnt
+
+- Copy a Linux kernel image and initrd payload files:
+*Linux:*::
+	cp vmlinux /mnt
+	cp initrd.gz /mnt
+*DOS/Windows:*::
+	copy vmlinux a:
+	copy initrd.gz a:
+
+- For Linux, umount the disk (if applicable):
+
+	umount /mnt
+
+=== MBR ===
+In order to boot from a hard disk (or hard disk-like device) in BIOS
+mode, an appropriate MBR boot block must also be installed in the MBR
+(first sector or 512 bytes of the disk), occupying at most 440 bytes.
+
+*DOS/Windows:*::
+If using FDISK, FDISK or a similar application must also be used to mark
+the partition as active.
++
+	fdisk /mbr
+    OR
+	syslinux -ma c:
+
+*Linux:*::
++
+	dd bs=440 count=1 conv=notrunc if=mbr/mbr.bin of=/dev/sda
++
+For altmbr.bin, an easy way to overwrite the MBR boot block and specify
+the partion number is:
++
+  printf '\1' | cat altmbr.bin - | dd bs=440 count=1 iflag=fullblock conv=notrunc of=/dev/sda
++
+Note: using 'cat' for writing the MBR can under some circumstances cause
+data loss or overwritting.  For this reason, using 'dd' is recommended
+for all situations.
+
+//[FIXME]: any clean way to handle the above long command for manpage?
+
+
+== SEE ALSO ==
+*syslinux.cfg*(5), *syslinux-cli*(1), *lilo*(8), *keytab-lilo.pl*(8),
+*fdisk*(8), *mkfs*(8), *superformat*(1).
+
+
+== AUTHOR ==
+This AsciiDoc derived document is a modified version of the original
+*SYSLINUX* documentation by {author} <{author-email}>. The conversion to
+a manpage was made by Arthur Korn <arthur@korn.ch>.  The conversion to
+an AsciiDoc was made by {editor1} <{editor1-email}>
+
+
+== COPYRIGHT ==
+Copyright \(C) 1994-2012 {author}. Free use of this software is granted
+under the terms of the GNU General Public License (GPL), version 2
+(GPLv2) (or, at your option, any later version).