Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/Makefile
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/Makefile	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/Makefile	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,45 @@
+#
+# LGPL/GPL code library
+#
+
+# Include configuration rules
+include $(MAKEDIR)/lib.mk
+
+REQFLAGS += -I$(SRC)/../gplinclude -I$(SRC)/../gplinclude/zzjson
+
+GPLDIRS := $(SRC) $(addprefix $(SRC)/,disk dmi vpd acpi zzjson)
+LIBOBJS := $(subst $(SRC)/,,$(foreach dir,$(GPLDIRS),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c))))
+
+BINDIR   = /usr/bin
+LIBDIR   = /usr/lib
+DATADIR  = /usr/share
+AUXDIR   = $(DATADIR)/syslinux
+INCDIR   = /usr/include
+COM32DIR = $(AUXDIR)/com32
+
+all: makeoutputdirs libgpl.c32
+
+makeoutputdirs:
+	@mkdir -p $(foreach b, \
+		$(addprefix $(OBJ),$(sort $(dir $(LIBOBJS)))),$(b))
+
+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 | \
+		xargs -0r rm -f
+
+spotless: clean
+	rm -f *.c32
+	rm -f *~ \#* */*~ */\#*
+
+# Mixing in the GPL include files is suboptimal, but I'm not sure
+# there is a better way to do it.
+install: all
+	mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR)
+	install -m 644 libgpl.c32 $(INSTALLROOT)$(COM32DIR)
+	mkdir -p $(INSTALLROOT)$(COM32DIR)/include/
+	cp -r $(SRC)/../gplinclude $(INSTALLROOT)$(COM32DIR)/include/
+
+-include .*.d */.*.d */*/.*.d
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/acpi.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/acpi.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/acpi.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,259 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009-2011 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include "acpi/acpi.h"
+
+/* M1PS flags have to be interpreted as strings */
+char *flags_to_string(char *buffer, uint16_t flags)
+{
+    strcpy(buffer, "default");
+    if ((flags & POLARITY_ACTIVE_HIGH) == POLARITY_ACTIVE_HIGH)
+	strcpy(buffer, "high");
+    else if ((flags & POLARITY_ACTIVE_LOW) == POLARITY_ACTIVE_LOW)
+	strcpy(buffer, "low");
+    if ((flags & TRIGGER_EDGE) == TRIGGER_EDGE)
+	strncat(buffer, " edge", 5);
+    else if ((flags & TRIGGER_LEVEL) == TRIGGER_LEVEL)
+	strncat(buffer, " level", 6);
+    else
+	strncat(buffer, " default", 8);
+
+    return buffer;
+}
+
+void dbg_printf(const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	vfprintf(stderr, fmt, args);
+	va_end(args);
+}
+
+void init_acpi(s_acpi * acpi)
+{
+    memset(acpi, 0, sizeof(s_acpi));
+}
+
+int parse_acpi(s_acpi * acpi)
+{
+    int ret_val;
+    init_acpi(acpi);
+
+    /* Let's seach for RSDP table */
+    if ((ret_val = search_rsdp(acpi)) != RSDP_TABLE_FOUND)
+	return ret_val;
+
+    /* Let's seach for RSDT table
+     * That's not a big deal not having it, XSDT is far more relevant */
+    parse_rsdt(&acpi->rsdt);
+    if (parse_xsdt(acpi) != XSDT_TABLE_FOUND) {
+	    DEBUG_PRINT(("XSDT Detection failed\n"));
+	    for (int table=0; table <acpi->rsdt.entry_count; table++) {
+		parse_header((uint64_t *)acpi->rsdt.entry[table],acpi);
+	    }
+    }
+    return ACPI_FOUND;
+}
+
+void get_acpi_description_header(uint8_t * q, s_acpi_description_header * adh)
+{
+    cp_str_struct(adh->signature);
+    cp_struct(&adh->length);
+    cp_struct(&adh->revision);
+    cp_struct(&adh->checksum);
+    cp_str_struct(adh->oem_id);
+    cp_str_struct(adh->oem_table_id);
+    cp_struct(&adh->oem_revision);
+    cp_str_struct(adh->creator_id);
+    cp_struct(&adh->creator_revision);
+    DEBUG_PRINT(("acpi_header at %p = %s | %s | %s\n", q, adh->signature,adh->oem_id, adh->creator_id ));
+}
+
+bool parse_header(uint64_t *address, s_acpi *acpi) {
+	    s_acpi_description_header adh;
+	    memset(&adh, 0, sizeof(adh));
+
+	    get_acpi_description_header((uint8_t *)address, &adh);
+
+	    /* Trying to determine the pointed table */
+	    /* Looking for FADT */
+	    if (memcmp(adh.signature, FACP, sizeof(FACP) - 1) == 0) {
+		DEBUG_PRINT(("FACP table found\n"));
+		s_fadt *f = &acpi->fadt;
+		s_facs *fa = &acpi->facs;
+		s_dsdt *d = &acpi->dsdt;
+		/* This structure is valid, let's fill it */
+		f->valid = true;
+		f->address = address;
+		memcpy(&f->header, &adh, sizeof(adh));
+		parse_fadt(f);
+
+		/* FACS wasn't already detected
+		 * FADT points to it, let's try to detect it */
+		if (fa->valid == false) {
+		    fa->address = (uint64_t *)f->x_firmware_ctrl;
+		    parse_facs(fa);
+		    if (fa->valid == false) {
+			/* Let's try again */
+			fa->address = (uint64_t *)f->firmware_ctrl;
+			parse_facs(fa);
+		    }
+		}
+
+		/* DSDT wasn't already detected
+		 * FADT points to it, let's try to detect it */
+		if (d->valid == false) {
+		    s_acpi_description_header new_adh;
+		    get_acpi_description_header((uint8_t *)f->x_dsdt,
+						&new_adh);
+		    if (memcmp(new_adh.signature, DSDT, sizeof(DSDT) - 1) == 0) {
+			DEBUG_PRINT(("DSDT table found via x_dsdt\n"));
+			d->valid = true;
+			d->address = (uint64_t *)f->x_dsdt;
+			memcpy(&d->header, &new_adh, sizeof(new_adh));
+			parse_dsdt(d);
+		    } else {
+			/* Let's try again */
+			get_acpi_description_header((uint8_t *)f->dsdt_address,
+						    &new_adh);
+			if (memcmp(new_adh.signature, DSDT, sizeof(DSDT) - 1) ==
+			    0) {
+			    DEBUG_PRINT(("DSDT table found via dsdt_address\n"));
+			    d->valid = true;
+			    d->address = (uint64_t *)f->dsdt_address;
+			    memcpy(&d->header, &new_adh, sizeof(new_adh));
+			    parse_dsdt(d);
+			}
+		    }
+		}
+	    } /* Looking for MADT */
+	    else if (memcmp(adh.signature, APIC, sizeof(APIC) - 1) == 0) {
+		DEBUG_PRINT(("MADT table found\n"));
+		s_madt *m = &acpi->madt;
+		/* This structure is valid, let's fill it */
+		m->valid = true;
+		m->address =address;
+		memcpy(&m->header, &adh, sizeof(adh));
+		parse_madt(acpi);
+	    } else if (memcmp(adh.signature, DSDT, sizeof(DSDT) - 1) == 0) {
+		DEBUG_PRINT(("DSDT table found\n"));
+		s_dsdt *d = &acpi->dsdt;
+		/* This structure is valid, let's fill it */
+		d->valid = true;
+		d->address = address;
+		memcpy(&d->header, &adh, sizeof(adh));
+		parse_dsdt(d);
+		/* PSDT have to be considered as SSDT. Intel ACPI Spec @ 5.2.11.3 */
+	    } else if ((memcmp(adh.signature, SSDT, sizeof(SSDT) - 1) == 0)
+		       || (memcmp(adh.signature, PSDT, sizeof(PSDT) - 1) == 0)) {
+		
+		DEBUG_PRINT(("SSDT table found with %s \n",adh.signature));
+
+		if ((acpi->ssdt_count >= MAX_SSDT - 1))
+		    return false;
+
+		/* We can have many SSDT, so let's allocate a new one */
+		if ((acpi->ssdt[acpi->ssdt_count] =
+		     malloc(sizeof(s_ssdt))) == NULL)
+		    return false;
+		s_ssdt *s = acpi->ssdt[acpi->ssdt_count];
+
+		/* This structure is valid, let's fill it */
+		s->valid = true;
+		s->address = address;
+		memcpy(&s->header, &adh, sizeof(adh));
+
+		/* Searching how much definition blocks we must copy */
+		uint32_t definition_block_size = adh.length - ACPI_HEADER_SIZE;
+		if ((s->definition_block =
+		     malloc(definition_block_size)) != NULL) {
+		    memcpy(s->definition_block,
+			   (s->address + ACPI_HEADER_SIZE),
+			   definition_block_size);
+		}
+		/* Increment the number of ssdt we have */
+		acpi->ssdt_count++;
+	    } else if (memcmp(adh.signature, SBST, sizeof(SBST) - 1) == 0) {
+		DEBUG_PRINT(("SBST table found\n"));
+		s_sbst *s = &acpi->sbst;
+		/* This structure is valid, let's fill it */
+		s->valid = true;
+		s->address = address;
+		memcpy(&s->header, &adh, sizeof(adh));
+		parse_sbst(s);
+	    } else if (memcmp(adh.signature, ECDT, sizeof(ECDT) - 1) == 0) {
+		DEBUG_PRINT(("ECDT table found\n"));
+		s_ecdt *e = &acpi->ecdt;
+		/* This structure is valid, let's fill it */
+		e->valid = true;
+		e->address = address;
+		memcpy(&e->header, &adh, sizeof(adh));
+		parse_ecdt(e);
+	    }  else if (memcmp(adh.signature, HPET, sizeof(HPET) - 1) == 0) {
+		DEBUG_PRINT(("HPET table found\n"));
+		s_hpet *h = &acpi->hpet;
+		/* This structure is valid, let's fill it */
+		h->valid = true;
+		h->address = address;
+		memcpy(&h->header, &adh, sizeof(adh));
+	    } else if (memcmp(adh.signature, TCPA, sizeof(TCPA) - 1) == 0) {
+		DEBUG_PRINT(("TCPA table found\n"));
+		s_tcpa *t = &acpi->tcpa;
+		/* This structure is valid, let's fill it */
+		t->valid = true;
+		t->address = address;
+		memcpy(&t->header, &adh, sizeof(adh));
+	    } else if (memcmp(adh.signature, MCFG, sizeof(MCFG) - 1) == 0) {
+		DEBUG_PRINT(("MCFG table found\n"));
+		s_mcfg *m = &acpi->mcfg;
+		/* This structure is valid, let's fill it */
+		m->valid = true;
+		m->address = address;
+		memcpy(&m->header, &adh, sizeof(adh));
+	    } else if (memcmp(adh.signature, SLIC, sizeof(SLIC) - 1) == 0) {
+		DEBUG_PRINT(("SLIC table found\n"));
+		s_slic *s = &acpi->slic;
+		/* This structure is valid, let's fill it */
+		s->valid = true;
+		s->address = address;
+		memcpy(&s->header, &adh, sizeof(adh));
+	    } else if (memcmp(adh.signature, BOOT, sizeof(BOOT) - 1) == 0) {
+		DEBUG_PRINT(("BOOT table found\n"));
+		s_boot *b = &acpi->boot;
+		/* This structure is valid, let's fill it */
+		b->valid = true;
+		b->address = address;
+		memcpy(&b->header, &adh, sizeof(adh));
+	    }
+	    
+	    return true;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/dsdt.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/dsdt.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/dsdt.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,48 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009-2011 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <dprintf.h>
+#include "acpi/acpi.h"
+
+void parse_dsdt(s_dsdt * d)
+{
+    uint8_t *q;
+    q = (uint8_t *)d->address;
+    q += ACPI_HEADER_SIZE;
+
+    /* Searching how much definition blocks we must copy */
+    uint32_t definition_block_size=d->header.length-ACPI_HEADER_SIZE;
+    if ((d->definition_block=malloc(definition_block_size)) != NULL) {
+	memcpy(d->definition_block,q,definition_block_size);
+    }
+
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/ecdt.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/ecdt.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/ecdt.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,53 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009-2011 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <dprintf.h>
+#include "acpi/acpi.h"
+
+void parse_ecdt(s_ecdt * e)
+{
+    uint8_t *q;
+    q = (uint8_t *)e->address;
+    q += ACPI_HEADER_SIZE;
+
+    /* Copying remaining structs */
+    cp_struct(&e->ec_control);
+    cp_struct(&e->ec_data);
+    cp_struct(&e->uid);
+    cp_struct(&e->gpe_bit);
+
+    /* Searching ec_id size we must copy */
+    uint32_t ec_id_size = e->header.length - EC_ID_OFFSET;
+    if ((e->ec_id = malloc(ec_id_size)) != NULL) {
+	memcpy(e->ec_id, (uint64_t *) (e->address + EC_ID_OFFSET), ec_id_size);
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/facs.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/facs.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/facs.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,52 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009-2011 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <dprintf.h>
+#include "acpi/acpi.h"
+
+void parse_facs(s_facs * f)
+{
+    uint8_t *q;
+    q = (uint8_t *) f->address;
+
+    DEBUG_PRINT(("Searching FACS at %p\n",q));
+    if (memcmp(q, FACS, sizeof(FACS) - 1) == 0) {
+	f->valid = true;
+	cp_str_struct(f->signature);
+	cp_struct(&f->length);
+	cp_struct(&f->hardware_signature);
+	cp_struct(&f->firmware_waking_vector);
+	cp_struct(&f->global_lock);
+	cp_struct(&f->flags);
+	cp_struct(&f->x_firmware_waking_vector);
+	cp_struct(&f->version);
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/fadt.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/fadt.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/fadt.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,99 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009-2011 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <dprintf.h>
+#include "acpi/acpi.h"
+
+void parse_fadt(s_fadt * f)
+{
+    /* Let's seach for FADT table */
+    uint8_t *q;
+
+    /* Fixing table name */
+    memcpy(f->header.signature,FADT,sizeof(FADT));
+    
+    /* Copying remaining structs */
+    q = (uint8_t *)f->address;
+    q += ACPI_HEADER_SIZE;
+    DEBUG_PRINT(("- Parsing FADT at %p\n",q));
+
+    cp_struct(&f->firmware_ctrl);
+    cp_struct(&f->dsdt_address);
+    cp_struct(&f->reserved);
+    cp_struct(&f->prefered_pm_profile);
+    cp_struct(&f->sci_int);
+    cp_struct(&f->smi_cmd);
+    cp_struct(&f->acpi_enable);
+    cp_struct(&f->acpi_disable);
+    cp_struct(&f->s4bios_req);
+    cp_struct(&f->pstate_cnt);
+    cp_struct(&f->pm1a_evt_blk);
+    cp_struct(&f->pm1b_evt_blk);
+    cp_struct(&f->pm1a_cnt_blk);
+    cp_struct(&f->pm1b_cnt_blk);
+    cp_struct(&f->pm2_cnt_blk);
+    cp_struct(&f->pm_tmr_blk);
+    cp_struct(&f->gpe0_blk);
+    cp_struct(&f->gpe1_blk);
+    cp_struct(&f->pm1_evt_len);
+    cp_struct(&f->pm1_cnt_len);
+    cp_struct(&f->pm2_cnt_len);
+    cp_struct(&f->pm_tmr_len);
+    cp_struct(&f->gpe0_blk_len);
+    cp_struct(&f->gpe1_blk_len);
+    cp_struct(&f->gpe1_base);
+    cp_struct(&f->cst_cnt);
+    cp_struct(&f->p_lvl2_lat);
+    cp_struct(&f->p_lvl3_lat);
+    cp_struct(&f->flush_size);
+    cp_struct(&f->flush_stride);
+    cp_struct(&f->duty_offset);
+    cp_struct(&f->duty_width);
+    cp_struct(&f->day_alarm);
+    cp_struct(&f->mon_alarm);
+    cp_struct(&f->century);
+    cp_struct(&f->iapc_boot_arch);
+    cp_struct(&f->reserved_2);
+    cp_struct(&f->flags);
+    cp_struct(&f->reset_reg);
+    cp_struct(&f->reset_value);
+    cp_struct(f->reserved_3);
+    cp_struct(&f->x_firmware_ctrl);
+    cp_struct(&f->x_dsdt);
+    cp_struct(&f->x_pm1a_evt_blk);
+    cp_struct(&f->x_pm1b_evt_blk);
+    cp_struct(&f->x_pm1a_cnt_blk);
+    cp_struct(&f->x_pm1b_cnt_blk);
+    cp_struct(&f->x_pm2_cnt_blk);
+    cp_struct(&f->x_pm_tmr_blk);
+    cp_struct(&f->x_gpe0_blk);
+    cp_struct(&f->x_gpe1_blk);
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/madt.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/madt.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/madt.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,172 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009-2011 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <dprintf.h>
+#include <stdlib.h>
+#include "acpi/acpi.h"
+
+/* Parse the apic structures */
+static uint8_t *add_apic_structure(s_acpi * acpi, uint8_t * q)
+{
+    uint8_t type = *q;
+    q++;
+    uint8_t length = *q;
+    q++;
+    s_processor_local_apic *sla;
+    s_io_apic *sio;
+    s_interrupt_source_override *siso;
+    s_nmi *snmi;
+    s_local_apic_nmi *slan;
+    s_local_apic_address_override *slaao;
+    s_io_sapic *siosapic;
+    s_local_sapic *sls;
+    s_madt *madt = &acpi->madt;
+
+    switch (type) {
+    case PROCESSOR_LOCAL_APIC:
+	sla = &madt->processor_local_apic[madt->processor_local_apic_count];
+	sla->type = type;
+	sla->length = length;
+	cp_struct(&sla->acpi_id);
+	cp_struct(&sla->apic_id);
+	cp_struct(&sla->flags);
+	madt->processor_local_apic_count++;
+	break;
+    case IO_APIC:
+	sio = &madt->io_apic[madt->io_apic_count];
+	sio->type = type;
+	sio->length = length;
+	cp_struct(&sio->io_apic_id);
+	cp_struct(&sio->reserved);
+	cp_struct(&sio->io_apic_address);
+	cp_struct(&sio->global_system_interrupt_base);
+	madt->io_apic_count++;
+	break;
+    case INTERRUPT_SOURCE_OVERRIDE:
+	siso =
+	    &madt->interrupt_source_override[madt->
+					     interrupt_source_override_count];
+	siso->type = type;
+	siso->length = length;
+	siso->bus = *q;
+	q++;
+	siso->source = *q;
+	q++;
+	cp_struct(&siso->global_system_interrupt);
+	cp_struct(&siso->flags);
+	madt->interrupt_source_override_count++;
+	break;
+    case NMI:
+	snmi = &madt->nmi[madt->nmi_count];
+	snmi->type = type;
+	snmi->length = length;
+	cp_struct(&snmi->flags);
+	cp_struct(&snmi->global_system_interrupt);
+	madt->nmi_count++;
+	break;
+    case LOCAL_APIC_NMI_STRUCTURE:
+	slan = &madt->local_apic_nmi[madt->local_apic_nmi_count];
+	slan->type = type;
+	slan->length = length;
+	cp_struct(&slan->acpi_processor_id);
+	cp_struct(&slan->flags);
+	cp_struct(&slan->local_apic_lint);
+	madt->local_apic_nmi_count++;
+	break;
+    case LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE:
+	slaao =
+	    &madt->local_apic_address_override[madt->
+					       local_apic_address_override_count];
+	slaao->type = type;
+	slaao->length = length;
+	cp_struct(&slaao->reserved);
+	cp_struct(&slaao->local_apic_address);
+	madt->local_apic_address_override_count++;
+	break;
+    case IO_SAPIC:
+	siosapic = &madt->io_sapic[madt->io_sapic_count];
+	siosapic->type = type;
+	siosapic->length = length;
+	cp_struct(&siosapic->io_apic_id);
+	cp_struct(&siosapic->reserved);
+	cp_struct(&siosapic->global_system_interrupt_base);
+	cp_struct(&siosapic->io_sapic_address);
+	madt->io_sapic_count++;
+	break;
+    case LOCAL_SAPIC:
+	sls = &madt->local_sapic[madt->local_sapic_count];
+	sls->type = type;
+	sls->length = length;
+	cp_struct(&sls->acpi_processor_id);
+	cp_struct(&sls->local_sapic_id);
+	cp_struct(&sls->local_sapic_eid);
+	cp_struct(sls->reserved);
+	cp_struct(&sls->flags);
+	cp_struct(&sls->acpi_processor_uid_value);
+	if ((sls->acpi_processor_uid_string =
+	     malloc(length - ACPI_PROCESSOR_UID_STRING_OFFSET)) != NULL) {
+	    memcpy(sls->acpi_processor_uid_string, q,
+		   length - ACPI_PROCESSOR_UID_STRING_OFFSET);
+	    q += length - ACPI_PROCESSOR_UID_STRING_OFFSET;
+	}
+	madt->local_sapic_count++;
+	break;
+    default:
+	printf("Unkown APIC structure type %u, size=%u \n", type, length);
+	q += length - 2;
+	break;
+    }
+    return q;
+}
+
+void parse_madt(s_acpi * acpi)
+{
+    /* Let's seach for FADT table */
+    uint8_t *q, *max_address;
+    s_madt *m = &acpi->madt;
+
+    /* Fixing table name */
+    memcpy(m->header.signature, APIC, sizeof(APIC));
+
+    /* Copying remaining structs */
+    q = (uint8_t *)m->address;
+    q += ACPI_HEADER_SIZE;
+    
+    max_address = (uint8_t *)m->address;
+    max_address += m->header.length;
+
+    cp_struct(&m->local_apic_address);
+    cp_struct(&m->flags);
+
+    while (q <  max_address) {
+	q = add_apic_structure(acpi, q);
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/rsdp.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/rsdp.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/rsdp.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,82 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009-2011 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <dprintf.h>
+#include "acpi/acpi.h"
+
+int search_rsdp(s_acpi * acpi)
+{
+    /* Let's seach for RSDT table */
+    uint8_t *q;
+
+    /* Let's start for the base address */
+    for (q = (uint8_t *)RSDP_MIN_ADDRESS; q < (uint8_t *)RSDP_MAX_ADDRESS; q+=16 ) {
+	/* Searching for RSDP with "RSD PTR" signature */
+	if (memcmp(q, RSDP, sizeof(RSDP)-1) == 0) {
+	    s_rsdp *r = &acpi->rsdp;
+	    r->valid = true;
+	    r->address = q;
+	    cp_str_struct(r->signature);
+	    cp_struct(&r->checksum);
+	    cp_str_struct(r->oem_id);
+	    cp_struct(&r->revision);
+	    cp_struct(&r->rsdt_address);
+	    cp_struct(&r->length);
+	    cp_struct(&r->xsdt_address);
+	    cp_struct(&r->extended_checksum);
+	    q += 3;		/* reserved field */
+	    acpi->rsdt.address = r->rsdt_address;
+	    acpi->xsdt.address = r->xsdt_address;
+	    DEBUG_PRINT(("RSDT should be at %p\n",r->rsdt_address));
+	    DEBUG_PRINT(("XSDT should be at %p\n",r->xsdt_address));
+	    return RSDP_TABLE_FOUND;
+	}
+    }
+    return -RSDP_TABLE_FOUND;
+}
+
+void print_rsdp(s_acpi * acpi)
+{
+    s_rsdp *r = &acpi->rsdp;
+
+    if (!r->valid)
+	return;
+    printf("RSDP Table @ 0x%p\n", r->address);
+    printf(" signature         : %s\n", r->signature);
+    printf(" checksum          : %u\n", r->checksum);
+    printf(" oem id            : %s\n", r->oem_id);
+    printf(" revision          : %u\n", r->revision);
+    printf(" RDST address      : %p\n", r->rsdt_address);
+    printf(" length            : %u\n", r->length);
+    printf(" XSDT address      : %p\n", r->xsdt_address);
+    printf(" extended checksum : %u\n", r->extended_checksum);
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/rsdt.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/rsdt.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/rsdt.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,72 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009-2011 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <dprintf.h>
+#include "acpi/acpi.h"
+
+int parse_rsdt(s_rsdt *r)
+{
+    /* Let's seach for RSDT table */
+    uint8_t *q;
+
+    /* Let's start for the base address */
+    q = r->address;
+
+    DEBUG_PRINT(("Searching for RSDT at %p\n",q));
+    /* Searching for MADT with APIC signature */
+    if (memcmp(q, RSDT, sizeof(RSDT)-1) == 0) {
+//        DEBUG_PRINT(("RSDT : %c %c %c %c\n",q[0], q[1], q[2], q[3]));
+	r->valid = true;
+	DEBUG_PRINT(("Before \n"));
+	get_acpi_description_header(q, &r->header);
+	DEBUG_PRINT(("RSDT table at %p found with %d bytes long with %d items\n",r->address, r->header.length,(r->header.length-ACPI_HEADER_SIZE)/4));
+
+	uint32_t *start = (uint32_t *)r->address;
+	start += (ACPI_HEADER_SIZE / 4);
+	uint32_t *max = (uint32_t *)r->address;
+	max += (r->header.length / 4);
+	DEBUG_PRINT(("Searching starting at %p till %p\n",start,max));
+	uint32_t *p;
+	for (p = start ; p < max; p++) {
+            /* Let's grab the pointed table header */
+            char address[16] = { 0 };
+            sprintf(address, "%x", *p);
+            uint32_t *pointed_address = (uint32_t *)strtoul(address, NULL, 16);
+	    r->entry[r->entry_count] = (uint8_t *)pointed_address;
+	    DEBUG_PRINT(("%d : %p\n",r->entry_count, r->entry[r->entry_count]));
+	    r->entry_count++;
+	}
+	return RSDT_TABLE_FOUND;
+    }
+
+    return -RSDT_TABLE_FOUND;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/sbst.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/sbst.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/sbst.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,45 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009-2011 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <dprintf.h>
+#include "acpi/acpi.h"
+
+void parse_sbst(s_sbst * s)
+{
+    uint8_t *q;
+    q = (uint8_t *)s->address;
+    q += ACPI_HEADER_SIZE;
+
+    /* Copying remaining structs */
+    cp_struct(&s->warning_energy_level);
+    cp_struct(&s->low_energy_level);
+    cp_struct(&s->critical_energy_level);
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/xsdt.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/xsdt.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/acpi/xsdt.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,77 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009-2011 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdlib.h>
+#include "acpi/acpi.h"
+
+int parse_xsdt(s_acpi * acpi)
+{
+    /* Let's seach for XSDT table */
+    uint8_t *q;
+
+    /* Let's start for the base address */
+    q = acpi->xsdt.address;
+
+    /* If address is null return an error */
+    if (q == 0 ) {
+	DEBUG_PRINT(("XSDT is null, exiting\n"));
+    	return -XSDT_TABLE_FOUND;
+    }
+
+    DEBUG_PRINT(("Searching XSDT at %p",q));
+    /* Searching for MADT with APIC signature */
+    if (memcmp(q, XSDT, sizeof(XSDT) - 1) == 0) {
+	s_xsdt *x = &acpi->xsdt;
+	x->valid = true;
+	get_acpi_description_header(q, &x->header);
+	DEBUG_PRINT(("XSDT table found at %p : length=%d\n",x->address,x->header.length));
+	DEBUG_PRINT(("Expected Tables = %d\n",(x->header.length-ACPI_HEADER_SIZE)/8));
+
+	/* We now have a set of pointers to some tables */
+	uint64_t *p = NULL;
+	for (p = ((uint64_t *)(x->address + ACPI_HEADER_SIZE));
+	     p < ((uint64_t *)(x->address + x->header.length)); p++) {
+	    DEBUG_PRINT((" Looking for HEADER at %p = %x\n",p,*p));
+
+	    /* Let's grab the pointed table header */
+	    char address[16] = { 0 };
+	    sprintf(address, "%llx", *p);
+	    uint64_t *pointed_address = (uint64_t *)strtoul(address, NULL, 16);
+
+	    x->entry[x->entry_count] = pointed_address;
+	    if (parse_header(pointed_address, acpi)) {
+		x->entry_count++;
+	    }
+	}
+	return XSDT_TABLE_FOUND;
+    }
+    return -XSDT_TABLE_FOUND;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/cpuid.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/cpuid.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/cpuid.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,615 @@
+/*
+ * Portions of this file taken from the Linux kernel,
+ * Copyright 1991-2009 Linus Torvalds and contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include "cpuid.h"
+
+const char *cpu_flags_names[] = {
+    CPU_FLAGS(STRUCT_MEMBER_NAMES)
+};
+
+size_t cpu_flags_offset[] = {
+    CPU_FLAGS(STRUCTURE_MEMBER_OFFSETS)
+};
+
+size_t cpu_flags_count = sizeof cpu_flags_names / sizeof *cpu_flags_names;
+
+struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = { };
+
+bool get_cpu_flag_value_from_name(s_cpu *cpu, const char * flag_name) {
+    size_t i;
+    bool cpu_flag_present=false, *flag_value = &cpu_flag_present;
+
+    for (i = 0; i < cpu_flags_count; i++) {
+	if (strcmp(cpu_flags_names[i],flag_name) == 0) {
+        	flag_value = (bool *)((char *)&cpu->flags + cpu_flags_offset[i]);
+	}
+    }
+    return *flag_value;
+}
+
+
+/*
+* CPUID functions returning a single datum
+*/
+
+/* Probe for the CPUID instruction */
+static int have_cpuid_p(void)
+{
+    return cpu_has_eflag(X86_EFLAGS_ID);
+}
+
+static struct cpu_dev amd_cpu_dev = {
+    .c_vendor = "AMD",
+    .c_ident = {"AuthenticAMD"}
+};
+
+static struct cpu_dev intel_cpu_dev = {
+    .c_vendor = "Intel",
+    .c_ident = {"GenuineIntel"}
+};
+
+static struct cpu_dev cyrix_cpu_dev = {
+    .c_vendor = "Cyrix",
+    .c_ident = {"CyrixInstead"}
+};
+
+static struct cpu_dev umc_cpu_dev = {
+    .c_vendor = "UMC",
+    .c_ident = {"UMC UMC UMC"}
+
+};
+
+static struct cpu_dev nexgen_cpu_dev = {
+    .c_vendor = "Nexgen",
+    .c_ident = {"NexGenDriven"}
+};
+
+static struct cpu_dev centaur_cpu_dev = {
+    .c_vendor = "Centaur",
+    .c_ident = {"CentaurHauls"}
+};
+
+static struct cpu_dev rise_cpu_dev = {
+    .c_vendor = "Rise",
+    .c_ident = {"RiseRiseRise"}
+};
+
+static struct cpu_dev transmeta_cpu_dev = {
+    .c_vendor = "Transmeta",
+    .c_ident = {"GenuineTMx86", "TransmetaCPU"}
+};
+
+static struct cpu_dev nsc_cpu_dev = {
+    .c_vendor = "National Semiconductor",
+    .c_ident = {"Geode by NSC"}
+};
+
+static struct cpu_dev unknown_cpu_dev = {
+    .c_vendor = "Unknown Vendor",
+    .c_ident = {"Unknown CPU"}
+};
+
+/*
+ * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
+ */
+void do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
+{
+	unsigned char ccr2, ccr3;
+
+	/* we test for DEVID by checking whether CCR3 is writable */
+	ccr3 = getCx86(CX86_CCR3);
+	setCx86(CX86_CCR3, ccr3 ^ 0x80);
+	getCx86(0xc0);   /* dummy to change bus */
+
+	if (getCx86(CX86_CCR3) == ccr3) {       /* no DEVID regs. */
+		ccr2 = getCx86(CX86_CCR2);
+		setCx86(CX86_CCR2, ccr2 ^ 0x04);
+		getCx86(0xc0);  /* dummy */
+
+		if (getCx86(CX86_CCR2) == ccr2) /* old Cx486SLC/DLC */
+			*dir0 = 0xfd;
+		else {                          /* Cx486S A step */
+			setCx86(CX86_CCR2, ccr2);
+			*dir0 = 0xfe;
+		}
+	} else {
+		setCx86(CX86_CCR3, ccr3);  /* restore CCR3 */
+
+		/* read DIR0 and DIR1 CPU registers */
+		*dir0 = getCx86(CX86_DIR0);
+		*dir1 = getCx86(CX86_DIR1);
+	}
+}
+
+void init_cpu_devs(void)
+{
+    cpu_devs[X86_VENDOR_INTEL] = &intel_cpu_dev;
+    cpu_devs[X86_VENDOR_CYRIX] = &cyrix_cpu_dev;
+    cpu_devs[X86_VENDOR_AMD] = &amd_cpu_dev;
+    cpu_devs[X86_VENDOR_UMC] = &umc_cpu_dev;
+    cpu_devs[X86_VENDOR_NEXGEN] = &nexgen_cpu_dev;
+    cpu_devs[X86_VENDOR_CENTAUR] = &centaur_cpu_dev;
+    cpu_devs[X86_VENDOR_RISE] = &rise_cpu_dev;
+    cpu_devs[X86_VENDOR_TRANSMETA] = &transmeta_cpu_dev;
+    cpu_devs[X86_VENDOR_NSC] = &nsc_cpu_dev;
+    cpu_devs[X86_VENDOR_UNKNOWN] = &unknown_cpu_dev;
+}
+
+void get_cpu_vendor(struct cpuinfo_x86 *c)
+{
+    char *v = c->x86_vendor_id;
+    int i;
+    init_cpu_devs();
+    for (i = 0; i < X86_VENDOR_NUM-1; i++) {
+	if (cpu_devs[i]) {
+	    if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
+		(cpu_devs[i]->c_ident[1] &&
+		 !strcmp(v, cpu_devs[i]->c_ident[1]))) {
+		c->x86_vendor = i;
+		return;
+	    }
+	}
+    }
+
+    c->x86_vendor = X86_VENDOR_UNKNOWN;
+}
+
+int get_model_name(struct cpuinfo_x86 *c)
+{
+    unsigned int *v;
+    char *p, *q;
+
+    if (cpuid_eax(0x80000000) < 0x80000004)
+	return 0;
+
+    v = (unsigned int *)c->x86_model_id;
+    cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
+    cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
+    cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
+    c->x86_model_id[48] = 0;
+
+    /* Intel chips right-justify this string for some dumb reason;
+       undo that brain damage */
+    p = q = &c->x86_model_id[0];
+    while (*p == ' ')
+	p++;
+    if (p != q) {
+	while (*p)
+	    *q++ = *p++;
+	while (q <= &c->x86_model_id[48])
+	    *q++ = '\0';	/* Zero-pad the rest */
+    }
+
+    return 1;
+}
+
+void detect_cache(uint32_t xlvl, struct cpuinfo_x86 *c)
+{
+    uint32_t eax, ebx, ecx, edx, l2size;
+    /* Detecting L1 cache */
+    if (xlvl >= 0x80000005) {
+	cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
+	c->x86_l1_data_cache_size = ecx >> 24;
+	c->x86_l1_instruction_cache_size = edx >> 24;
+    }
+
+    /* Detecting L2 cache */
+    c->x86_l2_cache_size = 0;
+
+    if (xlvl < 0x80000006)	/* Some chips just has a large L1. */
+	return;
+
+    cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
+    l2size = ecx >> 16;
+
+    /* Vendor based fixes */
+    switch (c->x86_vendor) {
+    case X86_VENDOR_INTEL:
+	/*
+	 * Intel PIII Tualatin. This comes in two flavours.
+	 * One has 256kb of cache, the other 512. We have no way
+	 * to determine which, so we use a boottime override
+	 * for the 512kb model, and assume 256 otherwise.
+	 */
+	if ((c->x86 == 6) && (c->x86_model == 11) && (l2size == 0))
+	    l2size = 256;
+	break;
+    case X86_VENDOR_AMD:
+	/* AMD errata T13 (order #21922) */
+	if ((c->x86 == 6)) {
+	    if (c->x86_model == 3 && c->x86_mask == 0)	/* Duron Rev A0 */
+		l2size = 64;
+	    if (c->x86_model == 4 && (c->x86_mask == 0 || c->x86_mask == 1))	/* Tbird rev A1/A2 */
+		l2size = 256;
+	}
+	break;
+    }
+    c->x86_l2_cache_size = l2size;
+}
+
+void detect_cyrix(struct cpuinfo_x86 *c) {
+	unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
+        char *buf = c->x86_model_id;
+	char Cx86_cb[] = "?.5x Core/Bus Clock";
+	const char cyrix_model_mult1[] = "12??43";
+	const char cyrix_model_mult2[] = "12233445";
+        const char *p = NULL;
+
+	do_cyrix_devid(&dir0, &dir1);
+	dir0_msn = dir0 >> 4; /* identifies CPU "family"   */
+	dir0_lsn = dir0 & 0xf;                /* model or clock multiplier */
+	c->x86_model = (dir1 >> 4) + 1;
+        c->x86_mask = dir1 & 0xf;
+	switch (dir0_msn) {
+		unsigned char tmp;
+
+	        case 0: /* Cx486SLC/DLC/SRx/DRx */
+                	 p = Cx486_name[dir0_lsn & 7];
+			 break;
+	
+		case 1: /* Cx486S/DX/DX2/DX4 */
+	                 p = (dir0_lsn & 8) ? Cx486D_name[dir0_lsn & 5] : Cx486S_name[dir0_lsn & 3];
+			 break;
+
+	         case 2: /* 5x86 */
+	                 Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];
+			 p = Cx86_cb+2;
+			 break;
+
+		case 3: /* 6x86/6x86L */
+			   Cx86_cb[1] = ' ';
+			   Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];
+			   if (dir1 > 0x21) { /* 686L */
+				   Cx86_cb[0] = 'L';
+				   p = Cx86_cb;
+				   (c->x86_model)++;
+			   } else             /* 686 */
+				   p = Cx86_cb+1;
+			   
+			   c->coma_bug = 1;
+			   break;
+		case 4:
+	                   c->x86_l1_data_cache_size = 16; /* Yep 16K integrated cache thats it */
+			   if (c->cpuid_level != 2) { /* Media GX */
+				   Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
+				   p = Cx86_cb+2;
+			   }
+			   break;
+		
+		case 5: /* 6x86MX/M II */
+			   if (dir1 > 7) {
+				   dir0_msn++;  /* M II */
+			   } else {
+	                           c->coma_bug = 1;      /* 6x86MX, it has the bug. */
+			   }
+
+			   tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;
+			   Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];
+			   p = Cx86_cb+tmp;
+			   if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
+				   (c->x86_model)++;
+			   break;
+		
+		case 0xf:  /* Cyrix 486 without DEVID registers */
+			   switch (dir0_lsn) {
+				   case 0xd:  /* either a 486SLC or DLC w/o DEVID */
+					   dir0_msn = 0; 
+					   p = Cx486_name[(c->hard_math) ? 1 : 0];
+					   break;
+				   
+				   case 0xe:  /* a 486S A step */
+					   dir0_msn = 0;
+					   p = Cx486S_name[0];
+					   break;
+			   }
+			   break;
+			   
+		default:
+			   dir0_msn = 7;
+			   break;
+	}
+
+	/* If the processor is unknown, we keep the model name we got
+	 * from the generic call */
+	if (dir0_msn < 7) {	
+		strcpy(buf, Cx86_model[dir0_msn & 7]);
+		if (p) strcat(buf, p);
+	}
+}
+
+void generic_identify(struct cpuinfo_x86 *c)
+{
+    uint32_t tfms, xlvl;
+    uint32_t eax, ebx, ecx, edx;
+
+    /* Get vendor name */
+    cpuid(0x00000000,
+	  (uint32_t *) & c->cpuid_level,
+	  (uint32_t *) & c->x86_vendor_id[0],
+	  (uint32_t *) & c->x86_vendor_id[8],
+	  (uint32_t *) & c->x86_vendor_id[4]);
+
+    get_cpu_vendor(c);
+
+    /* Intel-defined flags: level 0x00000001 */
+    if (c->cpuid_level >= 0x00000001) {
+	uint32_t capability, excap;
+	cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
+	c->x86_capability[0] = capability;
+	c->x86_capability[4] = excap;
+	c->x86 = (tfms >> 8) & 15;
+	c->x86_model = (tfms >> 4) & 15;
+	if (c->x86 == 0xf)
+	    c->x86 += (tfms >> 20) & 0xff;
+	if (c->x86 >= 0x6)
+	    c->x86_model += ((tfms >> 16) & 0xF) << 4;
+	c->x86_mask = tfms & 15;
+	if (cpu_has(c, X86_FEATURE_CLFLSH))
+	    c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8;
+    } else {
+	/* Have CPUID level 0 only - unheard of */
+	c->x86 = 4;
+    }
+
+    /* AMD-defined flags: level 0x80000001 */
+    xlvl = cpuid_eax(0x80000000);
+    if ((xlvl & 0xffff0000) == 0x80000000) {
+	if (xlvl >= 0x80000001) {
+	    c->x86_capability[1] = cpuid_edx(0x80000001);
+	    c->x86_capability[6] = cpuid_ecx(0x80000001);
+	}
+	if (xlvl >= 0x80000004)
+	    get_model_name(c);	/* Default name */
+    }
+
+    /* Specific detection code */
+    switch (c->x86_vendor) {
+	    case X86_VENDOR_CYRIX:
+	    case X86_VENDOR_NSC: detect_cyrix(c); break;
+	    default: break;
+    }
+
+    /* Detecting the number of cores */
+    switch (c->x86_vendor) {
+    case X86_VENDOR_AMD:
+	if (xlvl >= 0x80000008) {
+	    c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
+	    if (c->x86_num_cores & (c->x86_num_cores - 1))
+		c->x86_num_cores = 1;
+	}
+	break;
+    case X86_VENDOR_INTEL:
+	if (c->cpuid_level >= 0x00000004) {
+	    cpuid(0x4, &eax, &ebx, &ecx, &edx);
+	    c->x86_num_cores = ((eax & 0xfc000000) >> 26) + 1;
+	}
+	break;
+    default:
+	c->x86_num_cores = 1;
+	break;
+    }
+
+    detect_cache(xlvl, c);
+}
+
+/*
+ * Checksum an MP configuration block.
+ */
+
+static int mpf_checksum(unsigned char *mp, int len)
+{
+    int sum = 0;
+
+    while (len--)
+	sum += *mp++;
+
+    return sum & 0xFF;
+}
+
+static int smp_scan_config(unsigned long base, unsigned long length)
+{
+    unsigned long *bp = (unsigned long *)base;
+    struct intel_mp_floating *mpf;
+
+//        printf("Scan SMP from %p for %ld bytes.\n", bp,length);
+    if (sizeof(*mpf) != 16) {
+	printf("Error: MPF size\n");
+	return 0;
+    }
+
+    while (length > 0) {
+	mpf = (struct intel_mp_floating *)bp;
+	if ((*bp == SMP_MAGIC_IDENT) &&
+	    (mpf->mpf_length == 1) &&
+	    !mpf_checksum((unsigned char *)bp, 16) &&
+	    ((mpf->mpf_specification == 1)
+	     || (mpf->mpf_specification == 4))) {
+	    return 1;
+	}
+	bp += 4;
+	length -= 16;
+    }
+    return 0;
+}
+
+int find_smp_config(void)
+{
+//        unsigned int address;
+
+    /*
+     * FIXME: Linux assumes you have 640K of base ram..
+     * this continues the error...
+     *
+     * 1) Scan the bottom 1K for a signature
+     * 2) Scan the top 1K of base RAM
+     * 3) Scan the 64K of bios
+     */
+    if (smp_scan_config(0x0, 0x400) ||
+	smp_scan_config(639 * 0x400, 0x400) ||
+	smp_scan_config(0xF0000, 0x10000))
+	return 1;
+    /*
+     * If it is an SMP machine we should know now, unless the
+     * configuration is in an EISA/MCA bus machine with an
+     * extended bios data area.
+     *
+     * there is a real-mode segmented pointer pointing to the
+     * 4K EBDA area at 0x40E, calculate and scan it here.
+     *
+     * NOTE! There are Linux loaders that will corrupt the EBDA
+     * area, and as such this kind of SMP config may be less
+     * trustworthy, simply because the SMP table may have been
+     * stomped on during early boot. These loaders are buggy and
+     * should be fixed.
+     *
+     * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
+     */
+
+//        address = get_bios_ebda();
+//        if (address)
+//                smp_scan_config(address, 0x400);
+    return 0;
+}
+
+void set_cpu_flags(struct cpuinfo_x86 *c, s_cpu * cpu)
+{
+    cpu->flags.fpu = cpu_has(c, X86_FEATURE_FPU);
+    cpu->flags.vme = cpu_has(c, X86_FEATURE_VME);
+    cpu->flags.de = cpu_has(c, X86_FEATURE_DE);
+    cpu->flags.pse = cpu_has(c, X86_FEATURE_PSE);
+    cpu->flags.tsc = cpu_has(c, X86_FEATURE_TSC);
+    cpu->flags.msr = cpu_has(c, X86_FEATURE_MSR);
+    cpu->flags.pae = cpu_has(c, X86_FEATURE_PAE);
+    cpu->flags.mce = cpu_has(c, X86_FEATURE_MCE);
+    cpu->flags.cx8 = cpu_has(c, X86_FEATURE_CX8);
+    cpu->flags.apic = cpu_has(c, X86_FEATURE_APIC);
+    cpu->flags.sep = cpu_has(c, X86_FEATURE_SEP);
+    cpu->flags.mtrr = cpu_has(c, X86_FEATURE_MTRR);
+    cpu->flags.pge = cpu_has(c, X86_FEATURE_PGE);
+    cpu->flags.mca = cpu_has(c, X86_FEATURE_MCA);
+    cpu->flags.cmov = cpu_has(c, X86_FEATURE_CMOV);
+    cpu->flags.pat = cpu_has(c, X86_FEATURE_PAT);
+    cpu->flags.pse_36 = cpu_has(c, X86_FEATURE_PSE36);
+    cpu->flags.psn = cpu_has(c, X86_FEATURE_PN);
+    cpu->flags.clflsh = cpu_has(c, X86_FEATURE_CLFLSH);
+    cpu->flags.dts = cpu_has(c, X86_FEATURE_DTES);
+    cpu->flags.acpi = cpu_has(c, X86_FEATURE_ACPI);
+    cpu->flags.pbe = cpu_has(c, X86_FEATURE_PBE);
+    cpu->flags.mmx = cpu_has(c, X86_FEATURE_MMX);
+    cpu->flags.fxsr = cpu_has(c, X86_FEATURE_FXSR);
+    cpu->flags.sse = cpu_has(c, X86_FEATURE_XMM);
+    cpu->flags.sse2 = cpu_has(c, X86_FEATURE_XMM2);
+    cpu->flags.ss = cpu_has(c, X86_FEATURE_SELFSNOOP);
+    cpu->flags.htt = cpu_has(c, X86_FEATURE_HT);
+    cpu->flags.acc = cpu_has(c, X86_FEATURE_ACC);
+    cpu->flags.syscall = cpu_has(c, X86_FEATURE_SYSCALL);
+    cpu->flags.mp = cpu_has(c, X86_FEATURE_MP);
+    cpu->flags.nx = cpu_has(c, X86_FEATURE_NX);
+    cpu->flags.mmxext = cpu_has(c, X86_FEATURE_MMXEXT);
+    cpu->flags.fxsr_opt = cpu_has(c, X86_FEATURE_FXSR_OPT);
+    cpu->flags.gbpages = cpu_has(c, X86_FEATURE_GBPAGES);
+    cpu->flags.rdtscp = cpu_has(c, X86_FEATURE_RDTSCP);
+    cpu->flags.lm = cpu_has(c, X86_FEATURE_LM);
+    cpu->flags.nowext = cpu_has(c, X86_FEATURE_3DNOWEXT);
+    cpu->flags.now = cpu_has(c, X86_FEATURE_3DNOW);
+    cpu->flags.smp = find_smp_config();
+    cpu->flags.pni = cpu_has(c, X86_FEATURE_XMM3);
+    cpu->flags.pclmulqd = cpu_has(c, X86_FEATURE_PCLMULQDQ);
+    cpu->flags.dtes64 = cpu_has(c, X86_FEATURE_DTES64);
+    cpu->flags.vmx = cpu_has(c, X86_FEATURE_VMX);
+    cpu->flags.smx = cpu_has(c, X86_FEATURE_SMX);
+    cpu->flags.est = cpu_has(c, X86_FEATURE_EST);
+    cpu->flags.tm2 = cpu_has(c, X86_FEATURE_TM2);
+    cpu->flags.sse3 = cpu_has(c, X86_FEATURE_SSE3);
+    cpu->flags.cid = cpu_has(c, X86_FEATURE_CID);
+    cpu->flags.fma = cpu_has(c, X86_FEATURE_FMA);
+    cpu->flags.cx16 = cpu_has(c, X86_FEATURE_CX16);
+    cpu->flags.xtpr = cpu_has(c, X86_FEATURE_XTPR);
+    cpu->flags.pdcm = cpu_has(c, X86_FEATURE_PDCM);
+    cpu->flags.dca = cpu_has(c, X86_FEATURE_DCA);
+    cpu->flags.xmm4_1 = cpu_has(c, X86_FEATURE_XMM4_1);
+    cpu->flags.xmm4_2 = cpu_has(c, X86_FEATURE_XMM4_2);
+    cpu->flags.x2apic = cpu_has(c, X86_FEATURE_X2APIC);
+    cpu->flags.movbe = cpu_has(c, X86_FEATURE_MOVBE);
+    cpu->flags.popcnt = cpu_has(c, X86_FEATURE_POPCNT);
+    cpu->flags.aes = cpu_has(c, X86_FEATURE_AES);
+    cpu->flags.xsave = cpu_has(c, X86_FEATURE_XSAVE);
+    cpu->flags.osxsave = cpu_has(c, X86_FEATURE_OSXSAVE);
+    cpu->flags.avx = cpu_has(c, X86_FEATURE_AVX);
+    cpu->flags.hypervisor = cpu_has(c, X86_FEATURE_HYPERVISOR);
+    cpu->flags.ace2 = cpu_has(c, X86_FEATURE_ACE2);
+    cpu->flags.ace2_en = cpu_has(c, X86_FEATURE_ACE2_EN);
+    cpu->flags.phe = cpu_has(c, X86_FEATURE_PHE);
+    cpu->flags.phe_en = cpu_has(c, X86_FEATURE_PHE_EN);
+    cpu->flags.pmm = cpu_has(c, X86_FEATURE_PMM);
+    cpu->flags.pmm_en = cpu_has(c, X86_FEATURE_PMM_EN);
+    cpu->flags.extapic = cpu_has(c, X86_FEATURE_EXTAPIC);
+    cpu->flags.cr8_legacy = cpu_has(c, X86_FEATURE_CR8_LEGACY);
+    cpu->flags.abm = cpu_has(c, X86_FEATURE_ABM);
+    cpu->flags.sse4a = cpu_has(c, X86_FEATURE_SSE4A);
+    cpu->flags.misalignsse = cpu_has(c, X86_FEATURE_MISALIGNSSE);
+    cpu->flags.nowprefetch = cpu_has(c, X86_FEATURE_3DNOWPREFETCH);
+    cpu->flags.osvw = cpu_has(c, X86_FEATURE_OSVW);
+    cpu->flags.ibs = cpu_has(c, X86_FEATURE_IBS);
+    cpu->flags.sse5 = cpu_has(c, X86_FEATURE_SSE5);
+    cpu->flags.skinit = cpu_has(c, X86_FEATURE_SKINIT);
+    cpu->flags.wdt = cpu_has(c, X86_FEATURE_WDT);
+    cpu->flags.ida = cpu_has(c, X86_FEATURE_IDA);
+    cpu->flags.arat = cpu_has(c, X86_FEATURE_ARAT);
+    cpu->flags.tpr_shadow = cpu_has(c, X86_FEATURE_TPR_SHADOW);
+    cpu->flags.vnmi = cpu_has(c, X86_FEATURE_VNMI);
+    cpu->flags.flexpriority = cpu_has(c, X86_FEATURE_FLEXPRIORITY);
+    cpu->flags.ept = cpu_has(c, X86_FEATURE_EPT);
+    cpu->flags.vpid = cpu_has(c, X86_FEATURE_VPID);
+    cpu->flags.svm = cpu_has(c, X86_FEATURE_SVM);
+}
+
+void set_generic_info(struct cpuinfo_x86 *c, s_cpu * cpu)
+{
+    cpu->family = c->x86;
+    cpu->vendor_id = c->x86_vendor;
+    cpu->model_id = c->x86_model;
+    cpu->stepping = c->x86_mask;
+    strlcpy(cpu->vendor, cpu_devs[c->x86_vendor]->c_vendor,
+	    sizeof(cpu->vendor));
+    strlcpy(cpu->model, c->x86_model_id, sizeof(cpu->model));
+    cpu->num_cores = c->x86_num_cores;
+    cpu->l1_data_cache_size = c->x86_l1_data_cache_size;
+    cpu->l1_instruction_cache_size = c->x86_l1_instruction_cache_size;
+    cpu->l2_cache_size = c->x86_l2_cache_size;
+}
+
+void detect_cpu(s_cpu * cpu)
+{
+    struct cpuinfo_x86 c;
+    memset(&c,0,sizeof(c));
+    c.x86_clflush_size = 32;
+    c.x86_vendor = X86_VENDOR_UNKNOWN;
+    c.cpuid_level = -1;		/* CPUID not detected */
+    c.x86_num_cores = 1;
+    memset(&cpu->flags, 0, sizeof(s_cpu_flags));
+
+    if (!have_cpuid_p())
+	return;
+
+    generic_identify(&c);
+    set_generic_info(&c, cpu);
+    set_cpu_flags(&c, cpu);
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/ata.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/ata.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/ata.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,62 @@
+#include <inttypes.h>
+#include <string.h>
+
+/**
+ *      ata_id_string - Convert IDENTIFY DEVICE page into string
+ *      @id: IDENTIFY DEVICE results we will examine
+ *      @s: string into which data is output
+ *      @ofs: offset into identify device page
+ *      @len: length of string to return. must be an even number.
+ *
+ *      The strings in the IDENTIFY DEVICE page are broken up into
+ *      16-bit chunks.  Run through the string, and output each
+ *      8-bit chunk linearly, regardless of platform.
+ *
+ *      LOCKING:
+ *      caller.
+ */
+void ata_id_string(const uint16_t * id, unsigned char *s,
+		   unsigned int ofs, unsigned int len)
+{
+    unsigned int c;
+
+    while (len > 0) {
+	c = id[ofs] >> 8;
+	*s = c;
+	s++;
+
+	c = id[ofs] & 0xff;
+	*s = c;
+	s++;
+
+	ofs++;
+	len -= 2;
+    }
+}
+
+/**
+ *      ata_id_c_string - Convert IDENTIFY DEVICE page into C string
+ *      @id: IDENTIFY DEVICE results we will examine
+ *      @s: string into which data is output
+ *      @ofs: offset into identify device page
+ *      @len: length of string to return. must be an odd number.
+ *
+ *      This function is identical to ata_id_string except that it
+ *      trims trailing spaces and terminates the resulting string with
+ *      null.  @len must be actual maximum length (even number) + 1.
+ *
+ *      LOCKING:
+ *      caller.
+ */
+void ata_id_c_string(const uint16_t * id, unsigned char *s,
+		     unsigned int ofs, unsigned int len)
+{
+    unsigned char *p;
+
+    ata_id_string(id, s, ofs, len - 1);
+
+    p = s + strnlen((const char *)s, len - 1);
+    while (p > s && p[-1] == ' ')
+	p--;
+    *p = '\0';
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/bootloaders.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/bootloaders.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/bootloaders.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,46 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer
+ *
+ *   This file is part of Syslinux, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <disk/bootloaders.h>
+#include <disk/common.h>
+#include <disk/geom.h>
+#include <disk/read.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * get_bootloader_string - return a string describing the boot code in a
+ *			   bootsector
+ * @d:			driveinfo struct describing the drive
+ * @p:	partition to scan (usually the active one)
+ * @buffer:		pre-allocated buffer
+ * @buffer_size:	@buffer size
+ **/
+int get_bootloader_string(struct driveinfo *d, const struct part_entry *p,
+			  char *buffer, const int buffer_size)
+{
+    char boot_sector[SECTOR * sizeof(char)];
+
+    if (read_sectors(d, &boot_sector, p->start_lba, 1) == -1)
+	return -1;
+    else {
+	if (!strncmp(boot_sector + 3, "SYSLINUX", 8))
+	    strlcpy(buffer, "SYSLINUX", buffer_size - 1);
+	else if (!strncmp(boot_sector + 3, "EXTLINUX", 8))
+	    strlcpy(buffer, "EXTLINUX", buffer_size - 1);
+	else if (!strncmp(boot_sector + 3, "MSWIN4.1", 8))
+	    strlcpy(buffer, "MSWIN4.1", buffer_size - 1);
+	else
+	    return -1;
+	/* Add more... */
+
+	buffer[buffer_size - 1] = '\0';
+	return 0;
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/errno_disk.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/errno_disk.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/errno_disk.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,12 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer
+ *
+ *   This file is part of Syslinux, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <disk/errno_disk.h>
+
+int errno_disk;
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/error.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/error.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/error.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,23 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer
+ *
+ *   This file is part of Syslinux, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdio.h>
+#include <string.h>
+#include <disk/errno_disk.h>
+
+/**
+ * get_error - decode a disk error status
+ * @s:	Preallocated buffer
+ *
+ * Fill @buffer_ptr with the last errno_disk
+ **/
+void get_error(const char *s)
+{
+    fprintf(stderr, "%s: error %d\n", s, errno_disk);
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/geom.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/geom.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/geom.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,278 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer
+ *
+ *   Some parts borrowed from chain.c32:
+ *
+ *   Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This file is part of Syslinux, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <com32.h>
+#include <string.h>
+#include <stdio.h>
+#include <disk/geom.h>
+
+#include <stdio.h>
+
+/**
+ * lba_to_chs - split given lba into cylinders/heads/sectors
+ **/
+void lba_to_chs(const struct driveinfo *drive_info, const int lba,
+		unsigned int *cylinder, unsigned int *head,
+		unsigned int *sector)
+{
+    unsigned int track;
+
+    /* Use EDD, if valid */
+    if (drive_info->edd_params.sectors_per_track > 0 &&
+	drive_info->edd_params.heads > 0) {
+	*cylinder = (lba % drive_info->edd_params.sectors_per_track) + 1;
+	track = lba / drive_info->edd_params.sectors_per_track;
+	*head = track % drive_info->edd_params.heads;
+	*sector = track / drive_info->edd_params.heads;
+    } else if (drive_info->cbios) {
+	*cylinder = (lba % drive_info->legacy_sectors_per_track) + 1;
+	track = lba / drive_info->legacy_sectors_per_track;
+	*head = track % (drive_info->legacy_max_head + 1);
+	*sector = track / (drive_info->legacy_max_head + 1);
+    }
+}
+
+/**
+ * detect_extensions - detect if we can use extensions
+ *
+ * INT 13 - IBM/MS INT 13 Extensions - INSTALLATION CHECK
+ *    AH = 41h
+ *    BX = 55AAh
+ *    DL = drive (80h-FFh)
+ *
+ * Return: CF set on error (extensions not supported)
+ *    AH = 01h (invalid function)
+ *    CF clear if successful
+ *    BX = AA55h if installed
+ *    AH = major version of extensions
+ *        01h = 1.x
+ *        20h = 2.0 / EDD-1.0
+ *        21h = 2.1 / EDD-1.1
+ *        30h = EDD-3.0
+ *    AL = internal use
+ *    CX = API subset support bitmap (see #00271)
+ *    DH = extension version (v2.0+ ??? -- not present in 1.x)
+ *
+ * Note: the Phoenix Enhanced Disk Drive Specification v1.0 uses version 2.0 of
+ *       the INT 13 Extensions API
+ *
+ * Bitfields for IBM/MS INT 13 Extensions API support bitmap:
+ * Bit(s)    Description    (Table 00271)
+ *     0 extended disk access functions (AH=42h-44h,47h,48h) supported
+ *     1 removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h)
+ *       supported
+ *     2 enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported
+ *       extended drive parameter table is valid (see #00273,#00278)
+ *     3-15    reserved (0)
+ **/
+static int detect_extensions(struct driveinfo *drive_info)
+{
+    com32sys_t getebios, ebios;
+
+    memset(&getebios, 0, sizeof getebios);
+    memset(&ebios, 0, sizeof ebios);
+
+    getebios.eflags.b[0] = 0x3;	/* CF set */
+    getebios.ebx.w[0] = 0x55aa;
+    getebios.edx.b[0] = drive_info->disk;
+    getebios.eax.b[1] = 0x41;
+
+    __intcall(0x13, &getebios, &ebios);
+
+    if (!(ebios.eflags.l & EFLAGS_CF) && ebios.ebx.w[0] == 0xaa55) {
+	drive_info->ebios = 1;
+	drive_info->edd_version = ebios.eax.b[1];
+	drive_info->edd_functionality_subset = ebios.ecx.w[0];
+	return 0;
+    } else
+	return -1;		/* Drive does not exist? */
+}
+
+/**
+ * get_drive_parameters_with_extensions - retrieve disk parameters via AH=48h
+ *
+ * INT 13 - IBM/MS INT 13 Extensions - GET DRIVE PARAMETERS
+ *     AH = 48h
+ *     DL = drive (80h-FFh)
+ *     DS:SI -> buffer for drive parameters
+ * Return: CF clear if successful
+ *     AH = 00h
+ *     DS:SI buffer filled
+ *     CF set on error
+ *     AH = error code (see #00234)
+ * BUG: several different Compaq BIOSes incorrectly report high-numbered
+ *     drives (such as 90h, B0h, D0h, and F0h) as present, giving them the
+ *     same geometry as drive 80h; as a workaround, scan through disk
+ *     numbers, stopping as soon as the number of valid drives encountered
+ *     equals the value in 0040h:0075h
+ **/
+static int get_drive_parameters_with_extensions(struct driveinfo *drive_info)
+{
+    com32sys_t inreg, outreg;
+    struct edd_device_parameters *dp;
+
+    memset(&inreg, 0, sizeof inreg);
+
+    /*
+     * The caller shall set this value to the maximum Result Buffer
+     * length, in bytes. If the length of this buffer is less than 30
+     * bytes, this function shall not return the pointer to Drive Parameter
+     * Table (DPT) extension. If the buffer length is 30 or greater on
+     * entry, it shall be set to 30 on exit. If the buffer length is
+     * between 26 and 29, it shall be set to 26 on exit.
+     * If the buffer length is less than 26 on entry an error shall be
+     * returned.
+     */
+    dp = lmalloc(sizeof *dp);
+    if (!dp)
+	return -1;
+
+    dp->len = sizeof(struct edd_device_parameters);
+
+    inreg.esi.w[0] = OFFS(dp);
+    inreg.ds = SEG(dp);
+    inreg.edx.b[0] = drive_info->disk;
+    inreg.eax.b[1] = 0x48;
+
+    __intcall(0x13, &inreg, &outreg);
+
+    /* CF set on error */
+    if (outreg.eflags.l & EFLAGS_CF) {
+	lfree(dp);
+	return outreg.eax.b[1];
+    }
+
+    memcpy(&drive_info->edd_params, dp, sizeof drive_info->edd_params);
+    lfree(dp);
+
+    return 0;
+}
+
+/**
+ * get_drive_parameters_without_extensions - retrieve drive parameters via AH=08h
+ *
+ * INT 13 - DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)
+ *     AH = 08h
+ *     DL = drive (bit 7 set for hard disk)
+ *
+ * Return: CF set on error
+ *     AH = status (07h) (see #00234)
+ *     CF clear if successful
+ *     AH = 00h
+ *     AL = 00h on at least some BIOSes
+ *     BL = drive type (AT/PS2 floppies only) (see #00242)
+ *     CH = low eight bits of maximum cylinder number
+ *     CL = maximum sector number (bits 5-0)
+ *          high two bits of maximum cylinder number (bits 7-6)
+ *     DH = maximum head number
+ *     DL = number of drives
+ *     ES:DI -> drive parameter table (floppies only)
+ *
+ * Notes:
+ *   - may return successful even though specified drive is greater than the
+ *     number of attached drives of that type (floppy/hard); check DL to
+ *     ensure validity
+ *   - for systems predating the IBM AT, this call is only valid for hard
+ *     disks, as it is implemented by the hard disk BIOS rather than the
+ *     ROM BIOS
+ *   - Toshiba laptops with HardRAM return DL=02h when called with DL=80h,
+ *     but fail on DL=81h. The BIOS data at 40h:75h correctly reports 01h.
+ *     may indicate only two drives present even if more are attached; to
+ *     ensure a correct count, one can use AH=15h to scan through possible
+ *     drives
+ *   - for BIOSes which reserve the last cylinder for testing purposes, the
+ *     cylinder count is automatically decremented
+ *     on PS/1s with IBM ROM DOS 4, nonexistent drives return CF clear,
+ *     BX=CX=0000h, and ES:DI = 0000h:0000h
+ *   - the PC-Tools PCFORMAT program requires that AL=00h before it will
+ *     proceed with the formatting
+ *
+ * BUG: several different Compaq BIOSes incorrectly report high-numbered
+ *      drives (such as 90h, B0h, D0h, and F0h) as present, giving them the
+ *      same geometry as drive 80h; as a workaround, scan through disk
+ *      numbers, stopping as soon as the number of valid drives encountered
+ *      equals the value in 0040h:0075h
+ *
+ * SeeAlso: AH=06h"Adaptec",AH=13h"SyQuest",AH=48h,AH=15h,INT 1E
+ * SeeAlso: INT 41"HARD DISK 0"
+ **/
+static int get_drive_parameters_without_extensions(struct driveinfo *drive_info)
+{
+    com32sys_t getparm, parm;
+
+    memset(&getparm, 0, sizeof getparm);
+    memset(&parm, 0, sizeof parm);
+
+    /* Ralf Brown recommends setting ES:DI to 0:0 */
+    getparm.esi.w[0] = 0;
+    getparm.ds = 0;
+    getparm.edx.b[0] = drive_info->disk;
+    getparm.eax.b[1] = 0x08;
+
+    __intcall(0x13, &getparm, &parm);
+
+    /* CF set on error */
+    if (parm.eflags.l & EFLAGS_CF)
+	return parm.eax.b[1];
+
+    /* DL contains the maximum drive number (it starts at 0) */
+    drive_info->legacy_max_drive = parm.edx.b[0];
+
+    // XXX broken
+    /* Drive specified greater than the bumber of attached drives */
+    //if (drive_info->disk > drive_info->drives)
+    //      return -1;
+
+    drive_info->legacy_type = parm.ebx.b[0];
+
+    /* DH contains the maximum head number (it starts at 0) */
+    drive_info->legacy_max_head = parm.edx.b[1];
+
+    /* Maximum sector number (bits 5-0) per track */
+    drive_info->legacy_sectors_per_track = parm.ecx.b[0] & 0x3f;
+
+    /*
+     * Maximum cylinder number:
+     *     CH = low eight bits of maximum cylinder number
+     *     CL = high two bits of maximum cylinder number (bits 7-6)
+     */
+    drive_info->legacy_max_cylinder = parm.ecx.b[1] +
+	((parm.ecx.b[0] & 0xc0) << 2);
+
+    if (drive_info->legacy_sectors_per_track > 0)
+	drive_info->cbios = 1;	/* Valid geometry */
+
+    return 0;
+}
+
+/**
+ * get_drive_parameters - retrieve drive parameters
+ * @drive_info:		driveinfo structure to fill
+ **/
+int get_drive_parameters(struct driveinfo *drive_info)
+{
+    int return_code;
+
+    if (detect_extensions(drive_info))
+	return -1;
+
+    return_code = get_drive_parameters_without_extensions(drive_info);
+
+    /* If geometry isn't valid, no need to try to get more info about the drive */
+    /* Looks like in can confuse some optical drives */
+    if (drive_info->ebios && drive_info->cbios)
+	get_drive_parameters_with_extensions(drive_info);
+
+    return return_code;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/labels.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/labels.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/labels.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,701 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer
+ *
+ *   This file is part of Syslinux, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <string.h>
+
+void get_label(int label, char **buffer_label)
+{
+    int buffer_size = (80 * sizeof(char));
+    char *buffer = malloc(buffer_size);
+    *buffer_label = buffer;
+
+    switch (label) {
+    case 0x01:
+	strlcpy(buffer, "DOS 12-bit fat", buffer_size);
+	break;
+    case 0x02:
+	strlcpy(buffer, "XENIX root", buffer_size);
+	break;
+    case 0x03:
+	strlcpy(buffer, "XENIX /usr", buffer_size);
+	break;
+    case 0x04:
+	strlcpy(buffer, "DOS 3.0+ 16-bit FAT (up to 32M)", buffer_size);
+	break;
+    case 0x05:
+	strlcpy(buffer, "DOS 3.3+ Extended Partition", buffer_size);
+	break;
+    case 0x06:
+	strlcpy(buffer, "DOS 3.31+ 16-bit FAT (over 32M)", buffer_size);
+	break;
+    case 0x07:
+	strlcpy(buffer, "NTFS/exFAT/HPFS", buffer_size);
+	//case 0x07: strlcpy(buffer, "Advanced Unix", buffer_size); break;
+	//case 0x07: strlcpy(buffer, "Windows NT NTFS", buffer_size); break;
+	//case 0x07: strlcpy(buffer, "QNX2.x (pre-1988)", buffer_size); break;
+	break;
+    case 0x08:
+	strlcpy(buffer, "AIX", buffer_size);
+	//case 0x08: strlcpy(buffer, "AIX boot partition", buffer_size); break;
+	//case 0x08: strlcpy(buffer, "SplitDrive", buffer_size); break;
+	//case 0x08: strlcpy(buffer, "DELL partition spanning multiple drives", buffer_size); break;
+	//case 0x08: strlcpy(buffer, "Commodore DOS", buffer_size); break;
+	//case 0x08: strlcpy(buffer, "QNX 1.x and 2.x ("qny")", buffer_size); break;
+	break;
+    case 0x09:
+	strlcpy(buffer, "AIX bootable partition", buffer_size);
+	//case 0x09: strlcpy(buffer, "Coherent filesystem", buffer_size); break;
+	//case 0x09: strlcpy(buffer, "QNX 1.x and 2.x ("qnz")", buffer_size); break;
+	break;
+    case 0x0a:
+	strlcpy(buffer, "OS/2 Boot Manager", buffer_size);
+	//case 0x0a: strlcpy(buffer, "Coherent swap partition", buffer_size); break;
+	//case 0x0a: strlcpy(buffer, "OPUS", buffer_size); break;
+	break;
+    case 0x0b:
+	strlcpy(buffer, "WIN95 OSR2 32-bit FAT", buffer_size);
+	break;
+    case 0x0c:
+	strlcpy(buffer, "WIN95 OSR2 32-bit FAT, LBA-mapped", buffer_size);
+	break;
+    case 0x0e:
+	strlcpy(buffer, "WIN95: DOS 16-bit FAT, LBA-mapped", buffer_size);
+	break;
+    case 0x0f:
+	strlcpy(buffer, "WIN95: Extended partition, LBA-mapped", buffer_size);
+	break;
+    case 0x10:
+	strlcpy(buffer, "OPUS", buffer_size);
+	break;
+    case 0x11:
+	strlcpy(buffer, "Hidden DOS 12-bit FAT", buffer_size);
+	break;
+    case 0x12:
+	strlcpy(buffer, "Compaq diagnostic partition", buffer_size);
+	break;
+    case 0x14:
+	strlcpy(buffer, "Hidden DOS 16-bit FAT <32M", buffer_size);
+	break;
+    case 0x16:
+	strlcpy(buffer, "Hidden DOS 16-bit FAT >=32M", buffer_size);
+	break;
+    case 0x17:
+	strlcpy(buffer, "Hidden HPFS/exFAT/NTFS", buffer_size);
+	break;
+    case 0x18:
+	strlcpy(buffer, "AST SmartSleep Partition", buffer_size);
+	break;
+    case 0x19:
+	strlcpy(buffer, "Unused (Claimed for Willowtech Photon COS)",
+		buffer_size);
+	break;
+    case 0x1b:
+	strlcpy(buffer, "Hidden WIN95 OSR2 32-bit FAT", buffer_size);
+	break;
+    case 0x1c:
+	strlcpy(buffer, "Hidden WIN95 OSR2 32-bit FAT, LBA-mapped",
+		buffer_size);
+	break;
+    case 0x1e:
+	strlcpy(buffer, "Hidden WIN95 16-bit FAT, LBA-mapped", buffer_size);
+	break;
+    case 0x20:
+	strlcpy(buffer, "Unused", buffer_size);
+	break;
+    case 0x21:
+	strlcpy(buffer, "Reserved", buffer_size);
+	//case 0x21: strlcpy(buffer, "Unused", buffer_size); break;
+	break;
+    case 0x22:
+	strlcpy(buffer, "Unused", buffer_size);
+	break;
+    case 0x23:
+	strlcpy(buffer, "Reserved", buffer_size);
+	break;
+    case 0x24:
+	strlcpy(buffer, "NEC DOS 3.x", buffer_size);
+	break;
+    case 0x26:
+	strlcpy(buffer, "Reserved", buffer_size);
+	break;
+    case 0x27:
+	strlcpy(buffer, "PQService (Acer laptop hidden rescue partition)", buffer_size);
+	//Windows RE hidden partition
+	//MirOS BSD partition
+	//RouterBOOT kernel partition
+	break;
+    case 0x2a:
+	strlcpy(buffer, "AtheOS File System (AFS)", buffer_size);
+	break;
+    case 0x2b:
+	strlcpy(buffer, "SyllableSecure (SylStor)", buffer_size);
+	break;
+    case 0x31:
+	strlcpy(buffer, "Reserved", buffer_size);
+	break;
+    case 0x32:
+	strlcpy(buffer, "NOS", buffer_size);
+	break;
+    case 0x33:
+	strlcpy(buffer, "Reserved", buffer_size);
+	break;
+    case 0x34:
+	strlcpy(buffer, "Reserved", buffer_size);
+	break;
+    case 0x35:
+	strlcpy(buffer, "JFS on OS/2 or eCS", buffer_size);
+	break;
+    case 0x36:
+	strlcpy(buffer, "Reserved", buffer_size);
+	break;
+    case 0x38:
+	strlcpy(buffer, "THEOS ver 3.2 2gb partition", buffer_size);
+	break;
+    case 0x39:
+	strlcpy(buffer, "Plan 9 partition", buffer_size);
+	//case 0x39: strlcpy(buffer, "THEOS ver 4 spanned partition", buffer_size); break;
+	break;
+    case 0x3a:
+	strlcpy(buffer, "THEOS ver 4 4gb partition", buffer_size);
+	break;
+    case 0x3b:
+	strlcpy(buffer, "THEOS ver 4 extended partition", buffer_size);
+	break;
+    case 0x3c:
+	strlcpy(buffer, "PartitionMagic recovery partition", buffer_size);
+	break;
+    case 0x3d:
+	strlcpy(buffer, "Hidden NetWare", buffer_size);
+	break;
+    case 0x40:
+	strlcpy(buffer, "Venix 80286", buffer_size);
+	break;
+    case 0x41:
+	strlcpy(buffer, "PPC PReP Boot", buffer_size); break;
+	//case 0x41: strlcpy(buffer, "Personal RISC Boot", buffer_size); break;
+	// strlcpy(buffer, "Linux/MINIX (sharing disk with DRDOS)", buffer_size);
+	break;
+    case 0x42:
+	strlcpy(buffer, "SFS (Secure Filesystem)", buffer_size); break;
+	// strlcpy(buffer, "Linux swap (sharing disk with DRDOS)", buffer_size);
+	//case 0x42: strlcpy(buffer, "Windows 2000 marker", buffer_size); break;
+	break;
+    case 0x43:
+	strlcpy(buffer, "Linux native (sharing disk with DRDOS)", buffer_size);
+	break;
+    case 0x44:
+	strlcpy(buffer, "GoBack partition", buffer_size);
+	break;
+    case 0x45:
+	strlcpy(buffer, "Boot-US boot manager", buffer_size);
+	//case 0x45: strlcpy(buffer, "Priam", buffer_size); break;
+	//case 0x45: strlcpy(buffer, "EUMEL/Elan", buffer_size); break;
+	break;
+    case 0x46:
+	strlcpy(buffer, "EUMEL/Elan", buffer_size);
+	break;
+    case 0x47:
+	strlcpy(buffer, "EUMEL/Elan", buffer_size);
+	break;
+    case 0x48:
+	strlcpy(buffer, "EUMEL/Elan", buffer_size);
+	break;
+    case 0x4a:
+	strlcpy(buffer, "AdaOS Aquila (Default)", buffer_size);
+	//case 0x4a: strlcpy(buffer, "ALFS/THIN lightweight filesystem for DOS", buffer_size); break;
+	break;
+    case 0x4c:
+	strlcpy(buffer, "Oberon partition", buffer_size);
+	break;
+    case 0x4d:
+	strlcpy(buffer, "QNX4.x", buffer_size);
+	break;
+    case 0x4e:
+	strlcpy(buffer, "QNX4.x 2nd part", buffer_size);
+	break;
+    case 0x4f:
+	strlcpy(buffer, "QNX4.x 3rd part", buffer_size);
+	//case 0x4f: strlcpy(buffer, "Oberon partition", buffer_size); break;
+	break;
+    case 0x50:
+	strlcpy(buffer, "OnTrack Disk Manager (older versions) RO",
+		buffer_size);
+	//case 0x50: strlcpy(buffer, "Lynx RTOS", buffer_size); break;
+	//case 0x50: strlcpy(buffer, "Native Oberon (alt)", buffer_size); break;
+	break;
+    case 0x51:
+	strlcpy(buffer, "OnTrack Disk Manager RW (DM6 Aux1)", buffer_size);
+	//case 0x51: strlcpy(buffer, "Novell", buffer_size); break;
+	break;
+    case 0x52:
+	strlcpy(buffer, "CP/M", buffer_size);
+	//case 0x52: strlcpy(buffer, "Microport SysV/AT", buffer_size); break;
+	break;
+    case 0x53:
+	strlcpy(buffer, "Disk Manager 6.0 Aux3", buffer_size);
+	break;
+    case 0x54:
+	strlcpy(buffer, "Disk Manager 6.0 Dynamic Drive Overlay", buffer_size);
+	break;
+    case 0x55:
+	strlcpy(buffer, "EZ-Drive", buffer_size);
+	break;
+    case 0x56:
+	strlcpy(buffer, "Golden Bow VFeature Partitioned Volume.", buffer_size);
+	//case 0x56: strlcpy(buffer, "DM converted to EZ-BIOS", buffer_size); break;
+	break;
+    case 0x57:
+	strlcpy(buffer, "DrivePro", buffer_size);
+	//case 0x57: strlcpy(buffer, "VNDI Partition", buffer_size); break;
+	break;
+    case 0x5c:
+	strlcpy(buffer, "Priam EDisk", buffer_size);
+	break;
+    case 0x61:
+	strlcpy(buffer, "SpeedStor", buffer_size);
+	break;
+    case 0x63:
+	strlcpy(buffer,
+		"Unix System V (SCO, ISC Unix, UnixWare, ...), Mach, GNU Hurd",
+		buffer_size);
+	break;
+    case 0x64:
+	strlcpy(buffer, "Novell Netware 286, 2.xx", buffer_size); break;
+	//strlcpy(buffer, "PC-ARMOUR protected partition", buffer_size);
+	break;
+    case 0x65:
+	strlcpy(buffer, "Novell Netware 386, 3.xx or 4.xx", buffer_size);
+	break;
+    case 0x66:
+	strlcpy(buffer, "Novell Netware SMS Partition", buffer_size);
+	break;
+    case 0x67:
+	strlcpy(buffer, "Novell", buffer_size);
+	break;
+    case 0x68:
+	strlcpy(buffer, "Novell", buffer_size);
+	break;
+    case 0x69:
+	strlcpy(buffer, "Novell Netware 5+, Novell Netware NSS Partition",
+		buffer_size);
+	break;
+    case 0x70:
+	strlcpy(buffer, "DiskSecure Multi-Boot", buffer_size);
+	break;
+    case 0x71:
+	strlcpy(buffer, "Reserved", buffer_size);
+	break;
+    case 0x72:
+	strlcpy(buffer, "V7/x86", buffer_size);
+	break;
+    case 0x73:
+	strlcpy(buffer, "Reserved", buffer_size);
+	break;
+    case 0x74:
+	//strlcpy(buffer, "Reserved", buffer_size);
+	strlcpy(buffer, "Scramdisk partition", buffer_size); break;
+    case 0x75:
+	strlcpy(buffer, "IBM PC/IX", buffer_size);
+	break;
+    case 0x76:
+	strlcpy(buffer, "Reserved", buffer_size);
+	break;
+    case 0x77:
+	strlcpy(buffer, "M2FS/M2CS partition", buffer_size);
+	break;
+	//case 0x77: strlcpy(buffer, "VNDI Partition", buffer_size); break;
+    case 0x78:
+	strlcpy(buffer, "XOSL FS", buffer_size);
+	break;
+    case 0x7E:
+	strlcpy(buffer, "Unused", buffer_size);
+	break;
+    case 0x80:
+	strlcpy(buffer, "MINIX until 1.4a", buffer_size);
+	break;
+    case 0x81:
+	strlcpy(buffer, "MINIX since 1.4b, early Linux", buffer_size);
+	//case 0x81: strlcpy(buffer, "Mitac disk manager", buffer_size); break;
+	break;
+    case 0x82:
+	strlcpy(buffer, "Linux swap", buffer_size);
+	//case 0x82: strlcpy(buffer, "Prime", buffer_size); break;
+	//case 0x82: strlcpy(buffer, "Solaris x86", buffer_size); break;
+	break;
+    case 0x83:
+	strlcpy(buffer, "Linux native (usually ext2fs)", buffer_size);
+	break;
+    case 0x84:
+	strlcpy(buffer, "OS/2 hidden C: drive", buffer_size);
+	//case 0x84: strlcpy(buffer, "Hibernation partition", buffer_size); break;
+	break;
+    case 0x85:
+	strlcpy(buffer, "Linux extended partition", buffer_size);
+	break;
+    case 0x86:
+	strlcpy(buffer, "NTFS volume set", buffer_size);
+	//case 0x86: strlcpy(buffer, "Old Linux RAID partition superblock", buffer_size); break;
+	break;
+    case 0x87:
+	strlcpy(buffer, "NTFS volume set", buffer_size);
+	break;
+    case 0x88:
+	strlcpy(buffer, "Linux Plaintext", buffer_size);
+	break;
+    case 0x8a:
+	strlcpy(buffer, "Linux Kernel Partition (used by AiR-BOOT)",
+		buffer_size);
+	break;
+    case 0x8b:
+	strlcpy(buffer, "Legacy Fault Tolerant FAT32 volume", buffer_size);
+	break;
+    case 0x8c:
+	strlcpy(buffer,
+		"Legacy Fault Tolerant FAT32 volume using BIOS extd INT 13h",
+		buffer_size);
+	break;
+    case 0x8d:
+	strlcpy(buffer, "Free FDISK hidden Primary DOS FAT12 partitition",
+		buffer_size);
+	break;
+    case 0x8e:
+	strlcpy(buffer, "Linux LVM partition", buffer_size);
+	break;
+    case 0x90:
+	strlcpy(buffer, "Free FDISK hidden Primary DOS FAT16 partitition",
+		buffer_size);
+	break;
+    case 0x91:
+	strlcpy(buffer, "Free FDISK hidden DOS extended partitition",
+		buffer_size);
+	break;
+    case 0x92:
+	strlcpy(buffer, "Free FDISK hidden Primary DOS large FAT16 partitition",
+		buffer_size);
+	break;
+    case 0x93:
+	strlcpy(buffer, "Hidden Linux native partition", buffer_size);
+	//case 0x93: strlcpy(buffer, "Amoeba", buffer_size); break;
+	break;
+    case 0x94:
+	strlcpy(buffer, "Amoeba bad block table", buffer_size);
+	break;
+    case 0x95:
+	strlcpy(buffer, "MIT EXOPC native partitions", buffer_size);
+	break;
+    case 0x96:
+	strlcpy(buffer, "CHRP ISO-9660 filesystem", buffer_size);
+	break;
+    case 0x97:
+	strlcpy(buffer, "Free FDISK hidden Primary DOS FAT32 partitition",
+		buffer_size);
+	break;
+    case 0x98:
+	strlcpy(buffer, "Free FDISK hidden Primary DOS FAT32 partitition (LBA)",
+		buffer_size);
+	break;
+    case 0x99:
+	strlcpy(buffer, "DCE376 logical drive", buffer_size);
+	break;
+    case 0x9a:
+	strlcpy(buffer, "Free FDISK hidden Primary DOS FAT16 partitition (LBA)",
+		buffer_size);
+	break;
+    case 0x9b:
+	strlcpy(buffer, "Free FDISK hidden DOS extended partitition (LBA)",
+		buffer_size);
+	break;
+    case 0x9e:
+	strlcpy(buffer, "ForthOS partition", buffer_size);
+	break;
+    case 0x9f:
+	strlcpy(buffer, "BSD/OS", buffer_size);
+	break;
+    case 0xa0:
+	strlcpy(buffer, "Laptop hibernation partition", buffer_size);
+	break;
+    case 0xa1:
+	strlcpy(buffer, "Laptop hibernation partition", buffer_size);
+	//case 0xa1: strlcpy(buffer, "HP Volume Expansion (SpeedStor variant)", buffer_size); break;
+	break;
+    case 0xa3:
+	strlcpy(buffer, "HP Volume Expansion (SpeedStor variant)", buffer_size);
+	break;
+    case 0xa4:
+	strlcpy(buffer, "HP Volume Expansion (SpeedStor variant)", buffer_size);
+	break;
+    case 0xa5:
+	strlcpy(buffer, "BSD/386, 386BSD, NetBSD, FreeBSD", buffer_size);
+	break;
+    case 0xa6:
+	strlcpy(buffer, "OpenBSD", buffer_size);
+	break;
+    case 0xa7:
+	strlcpy(buffer, "NeXTSTEP", buffer_size);
+	break;
+    case 0xa8:
+	strlcpy(buffer, "Mac OS-X", buffer_size);
+	break;
+    case 0xa9:
+	strlcpy(buffer, "NetBSD", buffer_size);
+	break;
+    case 0xaa:
+	strlcpy(buffer, "Olivetti Fat 12 1.44Mb Service Partition",
+		buffer_size);
+	break;
+    case 0xab:
+	strlcpy(buffer, "Mac OS-X Boot partition", buffer_size);
+	//case 0xab: strlcpy(buffer, "GO! partition", buffer_size); break;
+	break;
+    case 0xae:
+	strlcpy(buffer, "ShagOS filesystem", buffer_size);
+	break;
+    case 0xaf:
+	strlcpy(buffer, "ShagOS swap partition", buffer_size);
+	break;
+    case 0xb0:
+	strlcpy(buffer, "BootStar Dummy", buffer_size);
+	break;
+    case 0xb1:
+	strlcpy(buffer, "HP Volume Expansion (SpeedStor variant)", buffer_size);
+	break;
+    case 0xb2:
+	strlcpy(buffer, "QNX Neutrino Power-Safe filesystem", buffer_size);
+	break;
+    case 0xb3:
+	strlcpy(buffer, "HP Volume Expansion (SpeedStor variant)", buffer_size);
+	break;
+    case 0xb4:
+	strlcpy(buffer, "HP Volume Expansion (SpeedStor variant)", buffer_size);
+	break;
+    case 0xb6:
+	strlcpy(buffer, "HP Volume Expansion (SpeedStor variant)", buffer_size);
+	break;
+    case 0xb7:
+	strlcpy(buffer, "BSDI BSD/386 filesystem", buffer_size);
+	break;
+    case 0xb8:
+	strlcpy(buffer, "BSDI BSD/386 swap partition", buffer_size);
+	break;
+    case 0xbb:
+	strlcpy(buffer, "Boot Wizard hidden", buffer_size);
+	break;
+    case 0xbc:
+	strlcpy(buffer, "Acronis backup partition", buffer_size);
+	break;
+    case 0xbe:
+	strlcpy(buffer, "Solaris 8 boot partition", buffer_size);
+	break;
+    case 0xbf:
+	strlcpy(buffer, "Solaris partition", buffer_size);
+	break;
+    case 0xc0:
+	strlcpy(buffer, "CTOS", buffer_size);
+	//case 0xc0: strlcpy(buffer, "REAL/32 secure small partition", buffer_size); break;
+	//case 0xc0: strlcpy(buffer, "NTFT Partition", buffer_size); break;
+	break;
+    case 0xc1:
+	strlcpy(buffer, "DRDOS/secured (FAT-12)", buffer_size);
+	break;
+    case 0xc2:
+	strlcpy(buffer, "Hidden Linux", buffer_size); break;
+	//strlcpy(buffer, "Reserved for DR-DOS 7+", buffer_size);
+	break;
+    case 0xc3:
+	strlcpy(buffer, "Hidden Linux swap", buffer_size);
+	break;
+    case 0xc4:
+	strlcpy(buffer, "DRDOS/secured (FAT-16, < 32M)", buffer_size);
+	break;
+    case 0xc5:
+	strlcpy(buffer, "DRDOS/secured (extended)", buffer_size);
+	break;
+    case 0xc6:
+	strlcpy(buffer, "DRDOS/secured (FAT-16, >= 32M)", buffer_size);
+	//case 0xc6: strlcpy(buffer, "Windows NT corrupted FAT16 volume/stripe set", buffer_size); break;
+	break;
+    case 0xc7:
+	strlcpy(buffer, "Windows NT corrupted NTFS volume/stripe set",
+		buffer_size);
+	//case 0xc7: strlcpy(buffer, "Syrinx boot", buffer_size); break;
+	break;
+    case 0xc8:
+	strlcpy(buffer, "Reserved for DR-DOS 8.0+", buffer_size);
+	break;
+    case 0xc9:
+	strlcpy(buffer, "Reserved for DR-DOS 8.0+", buffer_size);
+	break;
+    case 0xca:
+	strlcpy(buffer, "Reserved for DR-DOS 8.0+", buffer_size);
+	break;
+    case 0xcb:
+	strlcpy(buffer, "reserved for DRDOS/secured (FAT32)", buffer_size);
+	break;
+    case 0xcc:
+	strlcpy(buffer, "reserved for DRDOS/secured (FAT32, LBA)", buffer_size);
+	break;
+    case 0xcd:
+	strlcpy(buffer, "CTOS Memdump?", buffer_size);
+	break;
+    case 0xce:
+	strlcpy(buffer, "reserved for DRDOS/secured (FAT16, LBA)", buffer_size);
+	break;
+    case 0xcf:
+	strlcpy(buffer, "DR-DOS 7.04+ secured EXT DOS (LBA)", buffer_size);
+	break;
+    case 0xd0:
+	strlcpy(buffer, "REAL/32 secure big partition", buffer_size);
+	break;
+    case 0xd1:
+	strlcpy(buffer, "Old Multiuser DOS secured FAT12", buffer_size);
+	break;
+    case 0xd4:
+	strlcpy(buffer, "Old Multiuser DOS secured FAT16 <32M", buffer_size);
+	break;
+    case 0xd5:
+	strlcpy(buffer, "Old Multiuser DOS secured extended partition",
+		buffer_size);
+	break;
+    case 0xd6:
+	strlcpy(buffer, "Old Multiuser DOS secured FAT16 >=32M", buffer_size);
+	break;
+    case 0xd8:
+	strlcpy(buffer, "CP/M-86", buffer_size);
+	break;
+    case 0xda:
+	strlcpy(buffer, "Non-FS Data", buffer_size);
+	break;
+    case 0xdb:
+	strlcpy(buffer,
+		"Digital Research CP/M, Concurrent CP/M, Concurrent DOS",
+		buffer_size);
+	//case 0xdb: strlcpy(buffer, "CTOS (Convergent Technologies OS -Unisys)", buffer_size); break;
+	//case 0xdb: strlcpy(buffer, "KDG Telemetry SCPU boot", buffer_size); break;
+	break;
+    case 0xdd:
+	strlcpy(buffer, "Hidden CTOS Memdump?", buffer_size);
+	break;
+    case 0xde:
+	strlcpy(buffer, "Dell PowerEdge Server utilities (FAT fs)",
+		buffer_size);
+	break;
+    case 0xdf:
+	strlcpy(buffer, "DG/UX virtual disk manager partition", buffer_size);
+	break;
+	//case 0xdf: strlcpy(buffer, "BootIt EMBRM", buffer_size); break;
+    case 0xe0:
+	strlcpy(buffer,
+		"Reserved by STMicroelectronics for a filesystem called ST AVFS.",
+		buffer_size);
+	break;
+    case 0xe1:
+	strlcpy(buffer, "DOS access or SpeedStor 12-bit FAT extended partition",
+		buffer_size);
+	break;
+    case 0xe3:
+	strlcpy(buffer, "DOS R/O or SpeedStor", buffer_size);
+	break;
+    case 0xe4:
+	strlcpy(buffer, "SpeedStor 16-bit FAT extended partition < 1024 cyl.",
+		buffer_size);
+	break;
+    case 0xe5:
+	strlcpy(buffer,
+		"Tandy DOS with logical sectored FAT (According to Powerquest.)",
+		buffer_size);
+	//case 0xe5: strlcpy(buffer, "Reserved", buffer_size); break;
+	break;
+    case 0xe6:
+	strlcpy(buffer, "Storage Dimensions SpeedStor", buffer_size);
+	break;
+    case 0xe8:
+	strlcpy(buffer, "LUKS", buffer_size);
+	break;
+    case 0xeb:
+	strlcpy(buffer, "BeOS", buffer_size);
+	break;
+    case 0xec:
+	strlcpy(buffer, "SkyOS SkyFS", buffer_size);
+	break;
+    case 0xed:
+	strlcpy(buffer, "Reserved for Matthias Paul's Sprytix", buffer_size);
+	break;
+    case 0xee:
+	strlcpy(buffer,
+		"GPT",
+		buffer_size);
+	break;
+    case 0xef:
+	strlcpy(buffer, "EFI file system",
+		buffer_size);
+	break;
+    case 0xf0:
+	strlcpy(buffer, "Linux/PA-RISC boot loader", buffer_size);
+	break;
+    case 0xf1:
+	strlcpy(buffer, "SpeedStor", buffer_size);
+	break;
+    case 0xf2:
+	strlcpy(buffer,
+		"DOS 3.3+ secondary partition (Powerquest writes: Unisys DOS with logical sectored FAT.)",
+		buffer_size);
+	break;
+    case 0xf3:
+	strlcpy(buffer,
+		"Reserved (Powerquest writes: Storage Dimensions SpeedStor.)",
+		buffer_size);
+	break;
+    case 0xf4:
+	strlcpy(buffer, "SpeedStor large partition", buffer_size);
+	//case 0xf4: strlcpy(buffer, "Prologue single-volume partition", buffer_size); break;
+	break;
+    case 0xf5:
+	strlcpy(buffer, "Prologue multi-volume partition", buffer_size);
+	break;
+    case 0xf6:
+	strlcpy(buffer,
+		"Reserved (Powerquest writes: Storage Dimensions SpeedStor. )",
+		buffer_size);
+	break;
+    case 0xf7:
+	strlcpy(buffer, "DDRdrive Solid State File System", buffer_size);
+	break;
+    case 0xf9:
+	strlcpy(buffer, "pCache", buffer_size);
+	break;
+    case 0xfa:
+	strlcpy(buffer, "Bochs", buffer_size);
+	break;
+    case 0xfb:
+	strlcpy(buffer, "VMware File System partition", buffer_size);
+	break;
+    case 0xfc:
+	strlcpy(buffer, "VMware Swap partition", buffer_size);
+	break;
+    case 0xfd:
+	strlcpy(buffer,
+		"Linux raid partition with autodetect using persistent superblock (Powerquest writes: Reserved for FreeDOS. )",
+		buffer_size);
+	break;
+    case 0xfe:
+	strlcpy(buffer, "LANstep", buffer_size); break;
+	//strlcpy(buffer, "SpeedStor > 1024 cyl.", buffer_size);
+	//case 0xfe: strlcpy(buffer, "IBM PS/2 IML (Initial Microcode Load) partition, located at the end of the disk.", buffer_size); break;
+	//case 0xfe: strlcpy(buffer, "Windows NT Disk Administrator hidden partition", buffer_size); break;
+	//case 0xfe: strlcpy(buffer, "Linux Logical Volume Manager partition (old)", buffer_size); break;
+	break;
+    case 0xff:
+	strlcpy(buffer, "Xenix Bad Block Table ", buffer_size);
+	break;
+    default:
+	strlcpy(buffer, "Unknown", buffer_size);
+	break;
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/mbrs.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/mbrs.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/mbrs.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,145 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer
+ *
+ *   This file is part of Syslinux, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <disk/common.h>
+#include <disk/geom.h>
+#include <disk/read.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+/**
+ * get_mbr_string - return a string describing the boot code
+ * @label:		first four bytes of the MBR
+ * @buffer:		pre-allocated buffer
+ * @buffer_size:	@buffer size
+ **/
+void get_mbr_string(const uint32_t label, char *buffer, const int buffer_size)
+{
+    /* 2 bytes are usually enough to identify the MBR */
+    uint16_t s_label = label >> 16;
+
+    switch (s_label) {
+    case 0x0000:
+    case 0xfabe:
+	strlcpy(buffer, "No bootloader", buffer_size - 1);
+	break;
+    case 0x0ebe:
+	strlcpy(buffer, "ThinkPad", buffer_size - 1);
+	break;
+    case 0x31c0:
+	strlcpy(buffer, "Acer 3", buffer_size - 1);
+	break;
+    case 0x33c0:
+	/* We need more than 2 bytes */
+	if (((label >> 8) & 0xff) == 0x8e)
+	    strlcpy(buffer, "Windows", buffer_size - 1);
+	else if (((label >> 8) & 0xff) == 0x90)
+	    strlcpy(buffer, "DiskCryptor", buffer_size - 1);
+	else if (((label >> 8) & 0xff) == 0xfa)
+	    strlcpy(buffer, "Syslinux", buffer_size - 1);
+	else
+	    strlcpy(buffer, "Unknown mbr", buffer_size - 1);
+	break;
+    case 0x33ed:
+	strlcpy(buffer, "Syslinux ISOhybrid", buffer_size - 1);
+	break;
+    case 0x33ff:
+	strlcpy(buffer, "HP/Gateway", buffer_size - 1);
+	break;
+    case 0xb800:
+	strlcpy(buffer, "PloP", buffer_size - 1);
+	break;
+    case 0xea05:
+	strlcpy(buffer, "XOSL", buffer_size - 1);
+	break;
+    case 0xea1e:
+	strlcpy(buffer, "Truecrypt Boot Loader", buffer_size - 1);
+	break;
+    case 0xeb04:
+	strlcpy(buffer, "Solaris", buffer_size - 1);
+	break;
+    case 0xeb31:
+	strlcpy(buffer, "Paragon", buffer_size - 1);
+	break;
+    case 0xeb48:
+	strlcpy(buffer, "Grub", buffer_size - 1);
+	break;
+    case 0xeb4c:
+	strlcpy(buffer, "Grub2 (v1.96)", buffer_size - 1);
+	break;
+    case 0xeb63:
+	strlcpy(buffer, "Grub2 (v1.97)", buffer_size - 1);
+	break;
+    case 0xeb5e:
+	/* We need more than 2 bytes */
+	if (((label >> 8) & 0xff) == 0x00)
+	    strlcpy(buffer, "fbinst", buffer_size - 1);
+	else if (((label >> 8) & 0xff) == 0x80)
+	    strlcpy(buffer, "Grub4Dos", buffer_size - 1);
+	else if (((label >> 8) & 0xff) == 0x90)
+	    strlcpy(buffer, "WEE", buffer_size - 1);
+	else
+	    strlcpy(buffer, "Unknown mbr", buffer_size - 1);
+	break;
+    case 0xfa31:
+	/* We need more than 2 bytes */
+	if (((label >> 8) & 0xff) == 0xc0)
+	    strlcpy(buffer, "Syslinux", buffer_size - 1);
+	else if (((label >> 8) & 0xff) == 0xc9)
+	    strlcpy(buffer, "Master Boot LoaDeR", buffer_size - 1);
+	else
+	    strlcpy(buffer, "Unknown mbr", buffer_size - 1);
+	break;
+    case 0xfa33:
+	strlcpy(buffer, "MS-DOS 3.30 through Windows 95 (A)", buffer_size - 1);
+	break;
+    case 0xfab8:
+	strlcpy(buffer, "FreeDOS (eXtended FDisk)", buffer_size - 1);
+	break;
+    case 0xfaeb:
+	strlcpy(buffer, "Lilo", buffer_size - 1);
+	break;
+    case 0xfc31:
+	strlcpy(buffer, "Testdisk", buffer_size - 1);
+	break;
+    case 0xfc33:
+	strlcpy(buffer, "GAG", buffer_size - 1);
+	break;
+    case 0xfceb:
+	strlcpy(buffer, "BootIT NG", buffer_size - 1);
+	break;
+    default:
+	strlcpy(buffer, "Unknown mbr", buffer_size - 1);
+	break;
+    }
+
+    buffer[buffer_size - 1] = '\0';
+}
+
+/**
+ * get_mbr_id - return the first four bytes of the MBR
+ * @d:		driveinfo struct describing the drive
+ **/
+uint32_t get_mbr_id(const struct driveinfo *d)
+{
+    char mbr[SECTOR * sizeof(char)];
+
+    if (read_mbr(d->disk, &mbr) == -1)
+	return -1;
+    else {
+	uint32_t mbr_id;
+	/* Reverse the opcodes */
+	mbr_id = (*(uint8_t *) (mbr + 3));
+	mbr_id += (*(uint8_t *) (mbr + 2) << 8);
+	mbr_id += (*(uint8_t *) (mbr + 1) << 16);
+	mbr_id += (*(uint8_t *) mbr) << 24;
+	return mbr_id;
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/msdos.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/msdos.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/msdos.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,162 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer
+ *
+ *   Some parts borrowed from chain.c32:
+ *
+ *   Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This file is part of Syslinux, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdlib.h>
+
+#include <disk/common.h>
+#include <disk/geom.h>
+#include <disk/msdos.h>
+#include <disk/partition.h>
+#include <disk/read.h>
+
+static int is_extended_partition(struct part_entry *ptab)
+{
+    return (ptab->ostype == 0x05 ||
+	    ptab->ostype == 0x0f || ptab->ostype == 0x85);
+}
+
+static int msdos_magic_present(const char *ptab)
+{
+    return (*(uint16_t *) (ptab + 0x1fe) == 0xaa55);
+}
+
+/**
+ * process_extended_partition - execute a callback for each partition contained listed in an ebr
+ * @drive_info:		driveinfo struct describing the drive
+ * @partition_offset:	Absolute start (lba) of the extended partition
+ * @ebr_offset:		Relative start (lba) of the current ebr processed within
+ *			the extended partition
+ * @callback:		Callback to execute
+ * @error:		Buffer for I/O errors
+ * @nb_part_seen:	Number of partitions found on the disk so far
+ **/
+static int process_extended_partition(struct driveinfo *drive_info,
+				      const int partition_offset,
+				      const int ebr_offset,
+				      p_callback callback, int nb_part_seen)
+{
+    int status = 0;
+    /* The ebr is located at the first sector of the extended partition */
+    char *ebr = malloc(SECTOR * sizeof(char));
+
+    if (read_sectors(drive_info, ebr, partition_offset + ebr_offset, 1) == -1)
+	goto abort;
+
+    /* Check msdos magic signature */
+    if (!msdos_magic_present(ebr))
+	goto abort;
+
+    struct part_entry *ptab =
+	(struct part_entry *)(ebr + PARTITION_TABLES_OFFSET);
+
+    for (int i = 0; i < 4; i++) {
+	if (status == -1)
+	    goto abort;
+
+	if (!is_extended_partition(&ptab[i])) {
+	    /*
+	     * This EBR partition table entry points to the
+	     * logical partition associated to that EBR
+	     */
+	    int logical_partition_start = ebr_offset + ptab[i].start_lba;
+
+	    /* Last EBR in the extended partition? */
+	    if (!logical_partition_start)
+		continue;
+
+	    /*
+	     * Check for garbage:
+	     * 3rd and 4th entries in an EBR should be zero
+	     * Some (malformed) partitioning software still add some
+	     * data partitions there.
+	     */
+	    if (ptab[i].start_lba <= 0 || ptab[i].length <= 0)
+		continue;
+
+	    nb_part_seen++;
+	    callback(drive_info,
+		     &ptab[i],
+		     partition_offset + logical_partition_start, nb_part_seen);
+	} else
+	    status = process_extended_partition(drive_info,
+						partition_offset,
+						ptab[i].start_lba,
+						callback, nb_part_seen);
+    }
+
+    free(ebr);
+    return 0;
+
+abort:
+    free(ebr);
+    return -1;
+}
+
+/**
+ * process_mbr - execute a callback for each partition contained in an {m,e}br
+ * @drive_info:	driveinfo struct describing the drive
+ * @ptab:	Pointer to the partition table
+ * @callback:	Callback to execute
+ **/
+static int process_mbr(struct driveinfo *drive_info, struct part_entry *ptab,
+		       p_callback callback)
+{
+    int status = 0;
+
+    for (int i = 0; i < 4; i++) {
+	if (status == -1)
+	    return -1;
+
+	if (ptab[i].start_sect > 0) {
+	    if (is_extended_partition(&ptab[i])) {
+		callback(drive_info, &ptab[i], ptab[i].start_lba, i + 1);
+		status =
+		    process_extended_partition(drive_info, ptab[i].start_lba, 0,
+					       callback, 4);
+	    } else
+		callback(drive_info, &ptab[i], ptab[i].start_lba, i + 1);
+	}
+    }
+
+    return 0;
+}
+
+/**
+ * parse_partition_table - execute a callback for each partition entry
+ * @d:		driveinfo struct describing the drive
+ * @callback:	Callback to execute
+ *
+ * The signature of the callback should be the following:
+ *
+ * void callback(struct driveinfo *drive_info,
+ *		 struct part_entry *ptab,
+ *		 int offset_root,
+ *		 int nb_part_seen)
+ **/
+int parse_partition_table(struct driveinfo *d, p_callback callback)
+{
+    char *mbr = malloc(SECTOR * sizeof(char));
+
+    if (read_mbr(d->disk, mbr) == -1)
+	return -1;
+    else {
+	/* Check msdos magic signature */
+	if (!msdos_magic_present(mbr))
+	    return -1;
+
+	struct part_entry *ptab =
+	    (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET);
+	return process_mbr(d, ptab, callback);
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/read.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/read.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/read.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,148 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer
+ *
+ *   Some parts borrowed from chain.c32:
+ *
+ *   Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This file is part of Syslinux, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <com32.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <disk/errno_disk.h>
+#include <disk/geom.h>
+#include <disk/read.h>
+#include <disk/util.h>
+#include <disk/common.h>
+
+/*
+ * TODO: implement file descriptors to cache metadata (geometry, ...)
+ */
+
+/**
+ * read_mbr - return a pointer to a malloced buffer containing the mbr
+ * @drive:	Drive number
+ * @buf:	Pre-allocated buffer for output
+ *
+ * Return the number of sectors read on success or -1 on failure.
+ * errno_disk contains the error number.
+ **/
+int read_mbr(int drive, void *buf)
+{
+    struct driveinfo drive_info;
+    drive_info.disk = drive;
+
+    /* MBR: lba = 0, 1 sector */
+    return read_sectors(&drive_info, buf, 0, 1);
+}
+
+/**
+ * dev_read - read from a drive
+ * @drive:	Drive number
+ * @buf:	Pre-allocated buffer for output
+ * @lba:	Position to start reading from
+ * @sectors:	Number of sectors to read
+ *
+ * High-level routine to read from a hard drive.
+ * Return the number of sectors read on success or -1 on failure.
+ * errno_disk contains the error number.
+ **/
+int dev_read(int drive, void *buf, unsigned int lba, int sectors)
+{
+    struct driveinfo drive_info;
+    drive_info.disk = drive;
+
+    return read_sectors(&drive_info, buf, lba, sectors);
+}
+
+/**
+ * read_sectors - read several sectors from disk
+ * @drive_info:		driveinfo struct describing the disk
+ * @data:		Pre-allocated buffer for output
+ * @lba:		Position to read
+ * @sectors:		Number of sectors to read
+ *
+ * Return the number of sectors read on success or -1 on failure.
+ * errno_disk contains the error number.
+ **/
+int read_sectors(struct driveinfo *drive_info, void *data,
+		 const unsigned int lba, const int sectors)
+{
+    com32sys_t inreg, outreg;
+    struct ebios_dapa *dapa;
+    void *buf;
+    char *bufp = data;
+    int rv = -1;
+
+    if (get_drive_parameters(drive_info) == -1)
+	return -1;
+
+    buf = lmalloc(sectors * SECTOR);
+    if (!buf)
+	return -1;
+
+    dapa = lmalloc(sizeof(*dapa));
+    if (!dapa)
+	goto fail;
+
+    memset(&inreg, 0, sizeof inreg);
+
+    if (drive_info->ebios) {
+	dapa->len = sizeof(*dapa);
+	dapa->count = sectors;
+	dapa->off = OFFS(buf);
+	dapa->seg = SEG(buf);
+	dapa->lba = lba;
+
+	inreg.esi.w[0] = OFFS(dapa);
+	inreg.ds = SEG(dapa);
+	inreg.edx.b[0] = drive_info->disk;
+	inreg.eax.b[1] = 0x42;	/* Extended read */
+    } else {
+	unsigned int c, h, s;
+
+	if (!drive_info->cbios) {	// XXX errno
+	    /* We failed to get the geometry */
+	    if (lba)
+		goto fail;	/* Can only read MBR */
+
+	    s = 1;
+	    h = 0;
+	    c = 0;
+	} else
+	    lba_to_chs(drive_info, lba, &s, &h, &c);
+
+	// XXX errno
+	if (s > 63 || h > 256 || c > 1023)
+	    goto fail;
+
+	inreg.eax.w[0] = 0x0201;	/* Read one sector */
+	inreg.ecx.b[1] = c & 0xff;
+	inreg.ecx.b[0] = s + (c >> 6);
+	inreg.edx.b[1] = h;
+	inreg.edx.b[0] = drive_info->disk;
+	inreg.ebx.w[0] = OFFS(buf);
+	inreg.es = SEG(buf);
+    }
+
+    /* Perform the read */
+    if (int13_retry(&inreg, &outreg)) {
+	errno_disk = outreg.eax.b[1];
+	goto fail;		/* Give up */
+    }
+
+    memcpy(bufp, buf, sectors * SECTOR);
+    rv = sectors;
+
+fail:
+    lfree(dapa);
+    lfree(buf);
+    return rv;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/swsusp.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/swsusp.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/swsusp.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,27 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <disk/swsusp.h>
+#include <disk/read.h>
+#include <disk/geom.h>
+
+/**
+ * swsusp_check - check if a (swap) partition contains the swsusp signature
+ * @drive_info:	driveinfo struct describing the disk containing the partition
+ * @ptab;	Partition table of the partition
+ **/
+int swsusp_check(struct driveinfo *drive_info, struct part_entry *ptab)
+{
+    struct swsusp_header header_p;
+    int offset;
+    int found;
+
+    /* Read first page of the swap device */
+    offset = ptab->start_lba;
+    if (read_sectors(drive_info, &header_p, offset, PAGE_SIZE / SECTOR) == -1) {
+	return -1;
+    } else {
+	found = !memcmp(SWSUSP_SIG, header_p.sig, 10);
+	return found;
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/util.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/util.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/util.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,45 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer
+ *
+ *   Some parts borrowed from chain.c32:
+ *
+ *   Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This file is part of Syslinux, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <com32.h>
+#include <stdlib.h>
+#include <string.h>
+#include <disk/geom.h>
+
+#define MAX_NB_RETRIES 6
+
+/**
+ * int13_retry - int13h with error handling
+ * @inreg:	int13h function parameters
+ * @outreg:	output registers
+ *
+ * Call int 13h, but with retry on failure.  Especially floppies need this.
+ **/
+int int13_retry(const com32sys_t * inreg, com32sys_t * outreg)
+{
+    int retry = MAX_NB_RETRIES;	/* Number of retries */
+    com32sys_t tmpregs;
+
+    if (!outreg)
+	outreg = &tmpregs;
+
+    while (retry--) {
+	__intcall(0x13, inreg, outreg);
+	if (!(outreg->eflags.l & EFLAGS_CF))
+	    return 0;		/* CF=0 => OK */
+    }
+
+    /* If we get here: error */
+    return -1;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/write.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/write.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/write.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,138 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer
+ *
+ *   Some parts borrowed from chain.c32:
+ *
+ *   Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This file is part of Syslinux, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <com32.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <disk/common.h>
+#include <disk/errno_disk.h>
+#include <disk/read.h>
+#include <disk/util.h>
+#include <disk/write.h>
+
+/**
+ * write_sectors - write several sectors from disk
+ * @drive_info:		driveinfo struct describing the disk
+ * @lba:		Position to write
+ * @data:		Buffer to write
+ * @size:		Size of the buffer (number of sectors)
+ *
+ * Return the number of sectors write on success or -1 on failure.
+ * errno_disk contains the error number.
+ **/
+int write_sectors(const struct driveinfo *drive_info, const unsigned int lba,
+		  const void *data, const int size)
+{
+    com32sys_t inreg, outreg;
+    struct ebios_dapa *dapa;
+    void *buf;
+    int rv = -1;
+
+    buf = lmalloc(size);
+    if (!buf)
+	return -1;
+
+    dapa = lmalloc(sizeof(*dapa));
+    if (!dapa)
+	goto out;
+
+    memcpy(buf, data, size);
+    memset(&inreg, 0, sizeof inreg);
+
+    if (drive_info->ebios) {
+	dapa->len = sizeof(*dapa);
+	dapa->count = size;
+	dapa->off = OFFS(buf);
+	dapa->seg = SEG(buf);
+	dapa->lba = lba;
+
+	inreg.esi.w[0] = OFFS(dapa);
+	inreg.ds = SEG(dapa);
+	inreg.edx.b[0] = drive_info->disk;
+	inreg.eax.w[0] = 0x4300;	/* Extended write */
+    } else {
+	unsigned int c, h, s;
+
+	if (!drive_info->cbios) {	// XXX errno
+	    /* We failed to get the geometry */
+	    if (lba)
+		goto out;	/* Can only write MBR */
+
+	    s = 1;
+	    h = 0;
+	    c = 0;
+	} else
+	    lba_to_chs(drive_info, lba, &s, &h, &c);
+
+	// XXX errno
+	if (s > 63 || h > 256 || c > 1023)
+	    goto out;
+
+	inreg.eax.w[0] = 0x0301;	/* Write one sector */
+	inreg.ecx.b[1] = c & 0xff;
+	inreg.ecx.b[0] = s + (c >> 6);
+	inreg.edx.b[1] = h;
+	inreg.edx.b[0] = drive_info->disk;
+	inreg.ebx.w[0] = OFFS(buf);
+	inreg.es = SEG(buf);
+    }
+
+    /* Perform the write */
+    if (int13_retry(&inreg, &outreg)) {
+	errno_disk = outreg.eax.b[1];	/* Give up */
+    } else
+	rv = size;
+out:
+    lfree(dapa);
+    lfree(buf);
+    return rv;
+}
+
+/**
+ * write_verify_sectors - write several sectors from disk
+ * @drive_info:		driveinfo struct describing the disk
+ * @lba:		Position to write
+ * @data:		Buffer to write
+ **/
+int write_verify_sector(struct driveinfo *drive_info,
+			const unsigned int lba, const void *data)
+{
+    return write_verify_sectors(drive_info, lba, data, SECTOR);
+}
+
+/**
+ * write_verify_sectors - write several sectors from disk
+ * @drive_info:		driveinfo struct describing the disk
+ * @lba:		Position to write
+ * @data:		Buffer to write
+ * @size:		Size of the buffer (number of sectors)
+ **/
+int write_verify_sectors(struct driveinfo *drive_info,
+			 const unsigned int lba,
+			 const void *data, const int size)
+{
+    char *rb = malloc(SECTOR * size * sizeof(char));
+    int status;
+
+    if (write_sectors(drive_info, lba, data, size) == -1)
+	return -1;		/* Write failure */
+
+    if (read_sectors(drive_info, rb, lba, size) == -1)
+	return -1;		/* Readback failure */
+
+    status = memcmp(data, rb, SECTOR * size);
+    free(rb);
+    return status ? -1 : 0;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,1040 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2006 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include "dmi/dmi.h"
+
+const char *out_of_spec = "<OUT OF SPEC>";
+const char *bad_index = "<BAD INDEX>";
+
+/*
+ * Misc. util stuff
+ */
+
+/*
+ * 3.3.11 On Board Devices Information (Type 10)
+ */
+
+static const char *dmi_on_board_devices_type(uint8_t code)
+{
+    /* 3.3.11.1 */
+    static const char *type[] = {
+	"Other",		/* 0x01 */
+	"Unknown",
+	"Video",
+	"SCSI Controller",
+	"Ethernet",
+	"Token Ring",
+	"Sound",
+	"PATA Controller",
+	"SATA Controller",
+	"SAS Controller"	/* 0x0A */
+    };
+
+    if (code >= 0x01 && code <= 0x0A)
+	return type[code - 0x01];
+    return out_of_spec;
+}
+
+static void dmi_on_board_devices(struct dmi_header *h, s_dmi * dmi)
+{
+    uint8_t *p = h->data + 4;
+    uint8_t count = (h->length - 0x04) / 2;
+    unsigned int i;
+
+    for (i = 0;
+	 i < count
+	 && i <
+	 sizeof dmi->base_board.devices_information /
+	 sizeof *dmi->base_board.devices_information; i++) {
+	strlcpy(dmi->base_board.devices_information[i].type,
+		dmi_on_board_devices_type(p[2 * i] & 0x7F),
+		sizeof dmi->base_board.devices_information[i].type);
+	dmi->base_board.devices_information[i].status = p[2 * i] & 0x80;
+	strlcpy(dmi->base_board.devices_information[i].description,
+		dmi_string(h, p[2 * i + 1]),
+		sizeof dmi->base_board.devices_information[i].description);
+    }
+}
+
+/*
+ * 3.3.24 System Reset (Type 23)
+ */
+
+static const char *dmi_system_reset_boot_option(uint8_t code)
+{
+    static const char *option[] = {
+	"Operating System",	/* 0x1 */
+	"System Utilities",
+	"Do Not Reboot"		/* 0x3 */
+    };
+
+    if (code >= 0x1)
+	return option[code - 0x1];
+    return out_of_spec;
+}
+
+static void dmi_system_reset_count(uint16_t code, char *array)
+{
+    if (code == 0xFFFF)
+	strlcpy(array, "Unknown", sizeof array);
+    else
+	snprintf(array, sizeof array, "%u", code);
+}
+
+static void dmi_system_reset_timer(uint16_t code, char *array)
+{
+    if (code == 0xFFFF)
+	strlcpy(array, "Unknown", sizeof array);
+    else
+	snprintf(array, sizeof array, "%u min", code);
+}
+
+/*
+ * 3.3.25 Hardware Security (Type 24)
+ */
+
+static const char *dmi_hardware_security_status(uint8_t code)
+{
+    static const char *status[] = {
+	"Disabled",		/* 0x00 */
+	"Enabled",
+	"Not Implemented",
+	"Unknown"		/* 0x03 */
+    };
+
+    return status[code];
+}
+
+/*
+ * 3.3.12 OEM Strings (Type 11)
+ */
+
+static void dmi_oem_strings(struct dmi_header *h, const char *prefix,
+			    s_dmi * dmi)
+{
+    uint8_t *p = h->data + 4;
+    uint8_t count = p[0x00];
+    int i;
+
+    for (i = 1; i <= count; i++)
+	snprintf(dmi->oem_strings, OEM_STRINGS_SIZE, "%s %s %s\n",
+		 dmi->oem_strings, prefix, dmi_string(h, i));
+}
+
+/*
+ * 3.3.13 System Configuration Options (Type 12)
+ */
+static void dmi_system_configuration_options(struct dmi_header *h,
+					     const char *prefix, s_dmi * dmi)
+{
+    uint8_t *p = h->data + 4;
+    uint8_t count = p[0x00];
+    int i;
+
+    for (i = 1; i <= count; i++)
+	snprintf(dmi->system.configuration_options,
+		 SYSTEM_CONFIGURATION_OPTIONS_SIZE, "%s %s %s\n",
+		 dmi->system.configuration_options, prefix, dmi_string(h, i));
+}
+
+static void dmi_system_boot_status(uint8_t code, char *array)
+{
+    static const char *status[] = {
+	"No errors detected",	/* 0 */
+	"No bootable media",
+	"Operating system failed to load",
+	"Firmware-detected hardware failure",
+	"Operating system-detected hardware failure",
+	"User-requested boot",
+	"System security violation",
+	"Previously-requested image",
+	"System watchdog timer expired"	/* 8 */
+    };
+
+    if (code <= 8)
+	strlcpy(array, status[code], SYSTEM_BOOT_STATUS_SIZE);
+    if (code >= 128 && code <= 191)
+	strlcpy(array, "OEM-specific", SYSTEM_BOOT_STATUS_SIZE);
+    if (code >= 192)
+	strlcpy(array, "Product-specific", SYSTEM_BOOT_STATUS_SIZE);
+}
+
+void dmi_bios_runtime_size(uint32_t code, s_dmi * dmi)
+{
+    if (code & 0x000003FF) {
+	dmi->bios.runtime_size = code;
+	strlcpy(dmi->bios.runtime_size_unit, "bytes",
+		sizeof(dmi->bios.runtime_size_unit));
+    } else {
+	dmi->bios.runtime_size = code >> 10;
+	strlcpy(dmi->bios.runtime_size_unit, "KB",
+		sizeof(dmi->bios.runtime_size_unit));
+
+    }
+}
+
+void dmi_bios_characteristics(uint64_t code, s_dmi * dmi)
+{
+    int i;
+    /*
+     * This isn't very clear what this bit is supposed to mean
+     */
+    //if(code.l&(1<<3))
+    if (code && (1 << 3)) {
+	((bool *) (&dmi->bios.characteristics))[0] = true;
+	return;
+    }
+
+    for (i = 4; i <= 31; i++)
+	//if(code.l&(1<<i))
+	if (code & (1 << i))
+	    ((bool *) (&dmi->bios.characteristics))[i - 3] = true;
+}
+
+void dmi_bios_characteristics_x1(uint8_t code, s_dmi * dmi)
+{
+    int i;
+
+    for (i = 0; i <= 7; i++)
+	if (code & (1 << i))
+	    ((bool *) (&dmi->bios.characteristics_x1))[i] = true;
+}
+
+void dmi_bios_characteristics_x2(uint8_t code, s_dmi * dmi)
+{
+    int i;
+
+    for (i = 0; i <= 2; i++)
+	if (code & (1 << i))
+	    ((bool *) (&dmi->bios.characteristics_x2))[i] = true;
+}
+
+void dmi_system_uuid(uint8_t * p, s_dmi * dmi)
+{
+    int only0xFF = 1, only0x00 = 1;
+    int i;
+
+    for (i = 0; i < 16 && (only0x00 || only0xFF); i++) {
+	if (p[i] != 0x00)
+	    only0x00 = 0;
+	if (p[i] != 0xFF)
+	    only0xFF = 0;
+    }
+
+    if (only0xFF) {
+	sprintf(dmi->system.uuid, "Not Present");
+	return;
+    }
+    if (only0x00) {
+	sprintf(dmi->system.uuid, "Not Settable");
+	return;
+    }
+
+    sprintf(dmi->system.uuid,
+	    "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+	    p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10],
+	    p[11], p[12], p[13], p[14], p[15]);
+}
+
+void dmi_system_wake_up_type(uint8_t code, s_dmi * dmi)
+{
+    /* 3.3.2.1 */
+    static const char *type[] = {
+	"Reserved",		/* 0x00 */
+	"Other",
+	"Unknown",
+	"APM Timer",
+	"Modem Ring",
+	"LAN Remote",
+	"Power Switch",
+	"PCI PME#",
+	"AC Power Restored"	/* 0x08 */
+    };
+
+    if (code <= 0x08) {
+	strlcpy(dmi->system.wakeup_type, type[code],
+		sizeof(dmi->system.wakeup_type));
+    } else {
+	strlcpy(dmi->system.wakeup_type, out_of_spec,
+		sizeof(dmi->system.wakeup_type));
+    }
+    return;
+}
+
+static void dmi_base_board_features(uint8_t code, s_dmi * dmi)
+{
+    if ((code & 0x1F) != 0) {
+	int i;
+
+	for (i = 0; i <= 4; i++)
+	    if (code & (1 << i))
+		((bool *) (&dmi->base_board.features))[i] = true;
+    }
+}
+
+static void dmi_base_board_type(uint8_t code, s_dmi * dmi)
+{
+    /* 3.3.3.2 */
+    static const char *type[] = {
+            "Unknown", /* 0x01 */
+            "Other",
+            "Server Blade",
+            "Connectivity Switch",
+            "System Management Module",
+            "Processor Module",
+            "I/O Module",
+            "Memory Module",
+            "Daughter Board",
+            "Motherboard",
+            "Processor+Memory Module",
+            "Processor+I/O Module",
+            "Interconnect Board" /* 0x0D */
+    };
+
+    if (code >= 0x01 && code <= 0x0D) {
+	strlcpy(dmi->base_board.type, type[code],
+		sizeof(dmi->base_board.type));
+    } else {
+	strlcpy(dmi->base_board.type, out_of_spec,
+		sizeof(dmi->base_board.type));
+    }
+    return;
+}
+
+static void dmi_processor_voltage(uint8_t code, s_dmi * dmi)
+{
+    /* 3.3.5.4 */
+    static const uint16_t voltage[] = {
+	5000,
+	3300,
+	2900
+    };
+    int i;
+
+    if (code & 0x80)
+	dmi->processor.voltage_mv = (code & 0x7f) * 100;
+    else {
+	for (i = 0; i <= 2; i++)
+	    if (code & (1 << i))
+		dmi->processor.voltage_mv = voltage[i];
+    }
+}
+
+static void dmi_processor_id(uint8_t type, uint8_t * p, const char *version,
+			     s_dmi * dmi)
+{
+    /*
+     * Extra flags are now returned in the ECX register when one calls
+     * the CPUID instruction. Their meaning is explained in table 6, but
+     * DMI doesn't support this yet.
+     */
+    uint32_t eax, edx;
+    int sig = 0;
+
+    /*
+     * This might help learn about new processors supporting the
+     * CPUID instruction or another form of identification.
+     */
+    sprintf(dmi->processor.id, "ID: %02X %02X %02X %02X %02X %02X %02X %02X\n",
+	    p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+
+    if (type == 0x05) {		/* 80386 */
+	uint16_t dx = WORD(p);
+	/*
+	 * 80386 have a different signature.
+	 */
+	dmi->processor.signature.type = (dx >> 12);
+	dmi->processor.signature.family = ((dx >> 8) & 0xF);
+	dmi->processor.signature.stepping = (dx >> 4) & 0xF;
+	dmi->processor.signature.minor_stepping = (dx & 0xF);
+	return;
+    }
+    if (type == 0x06) {		/* 80486 */
+	uint16_t dx = WORD(p);
+	/*
+	 * Not all 80486 CPU support the CPUID instruction, we have to find
+	 * wether the one we have here does or not. Note that this trick
+	 * works only because we know that 80486 must be little-endian.
+	 */
+	if ((dx & 0x0F00) == 0x0400
+	    && ((dx & 0x00F0) == 0x0040 || (dx & 0x00F0) >= 0x0070)
+	    && ((dx & 0x000F) >= 0x0003))
+	    sig = 1;
+	else {
+	    dmi->processor.signature.type = ((dx >> 12) & 0x3);
+	    dmi->processor.signature.family = ((dx >> 8) & 0xF);
+	    dmi->processor.signature.model = ((dx >> 4) & 0xF);
+	    dmi->processor.signature.stepping = (dx & 0xF);
+	    return;
+	}
+    } else if ((type >= 0x0B && type <= 0x13)	/* Intel, Cyrix */
+	       ||(type >= 0xB0 && type <= 0xB3)	/* Intel */
+	       ||type == 0xB5	/* Intel */
+	       || type == 0xB9)	/* Intel */
+	sig = 1;
+    else if ((type >= 0x18 && type <= 0x1D)	/* AMD */
+	     ||type == 0x1F	/* AMD */
+	     || (type >= 0xB6 && type <= 0xB7)	/* AMD */
+	     ||(type >= 0x83 && type <= 0x85))	/* AMD */
+	sig = 2;
+    else if (type == 0x01 || type == 0x02) {
+	/*
+	 * Some X86-class CPU have family "Other" or "Unknown". In this case,
+	 * we use the version string to determine if they are known to
+	 * support the CPUID instruction.
+	 */
+	if (strncmp(version, "Pentium III MMX", 15) == 0)
+	    sig = 1;
+	else if (strncmp(version, "AMD Athlon(TM)", 14) == 0
+		 || strncmp(version, "AMD Opteron(tm)", 15) == 0)
+	    sig = 2;
+	else
+	    return;
+    } else			/* not X86-class */
+	return;
+
+    eax = DWORD(p);
+    edx = DWORD(p + 4);
+    switch (sig) {
+    case 1:			/* Intel */
+	dmi->processor.signature.type = ((eax >> 12) & 0x3);
+	dmi->processor.signature.family =
+	    (((eax >> 16) & 0xFF0) + ((eax >> 8) & 0x00F));
+	dmi->processor.signature.model =
+	    (((eax >> 12) & 0xF0) + ((eax >> 4) & 0x0F));
+	dmi->processor.signature.stepping = (eax & 0xF);
+	break;
+    case 2:			/* AMD */
+	dmi->processor.signature.family =
+	    (((eax >> 8) & 0xF) == 0xF ? (eax >> 20) & 0xFF : (eax >> 8) & 0xF);
+	dmi->processor.signature.model =
+	    (((eax >> 4) & 0xF) == 0xF ? (eax >> 16) & 0xF : (eax >> 4) & 0xF);
+	dmi->processor.signature.stepping = (eax & 0xF);
+	break;
+    }
+
+    edx = DWORD(p + 4);
+    if ((edx & 0x3FF7FDFF) != 0) {
+	int i;
+	for (i = 0; i <= 31; i++)
+	    if (cpu_flags_strings[i] != NULL && edx & (1 << i))
+		((bool *) (&dmi->processor.cpu_flags))[i] = true;
+    }
+}
+
+void to_dmi_header(struct dmi_header *h, uint8_t * data)
+{
+    h->type = data[0];
+    h->length = data[1];
+    h->handle = WORD(data + 2);
+    h->data = data;
+}
+
+const char *dmi_string(struct dmi_header *dm, uint8_t s)
+{
+    char *bp = (char *)dm->data;
+    size_t i, len;
+
+    if (s == 0)
+	return "Not Specified";
+
+    bp += dm->length;
+    while (s > 1 && *bp) {
+	bp += strlen(bp);
+	bp++;
+	s--;
+    }
+
+    if (!*bp)
+	return bad_index;
+
+    /* ASCII filtering */
+    len = strlen(bp);
+    for (i = 0; i < len; i++)
+	if (bp[i] < 32 || bp[i] == 127)
+	    bp[i] = '.';
+
+    return bp;
+}
+
+int checksum(uint8_t * buf, int len)
+{
+    uint8_t sum = 0;
+    int a;
+
+    for (a = 0; a < len; a++)
+	sum += buf[a];
+    return (sum == 0);
+}
+
+static int smbios_decode(s_dmi * dmi, uint8_t * buf)
+{
+
+    dmi->dmitable.ver = (buf[0x06] << 8) + buf[0x07];
+    /* Some BIOS report weird SMBIOS version, fix that up */
+    switch (dmi->dmitable.ver) {
+    case 0x021F:
+	dmi->dmitable.ver = 0x0203;
+	break;
+    case 0x0233:
+	dmi->dmitable.ver = 0x0206;
+	break;
+    }
+    dmi->dmitable.major_version = dmi->dmitable.ver >> 8;
+    dmi->dmitable.minor_version = dmi->dmitable.ver & 0xFF;
+
+    return DMI_TABLE_PRESENT;
+}
+
+static int legacy_decode(s_dmi * dmi, uint8_t * buf)
+{
+    dmi->dmitable.num = buf[13] << 8 | buf[12];
+    dmi->dmitable.len = buf[7] << 8 | buf[6];
+    dmi->dmitable.base = buf[11] << 24 | buf[10] << 16 | buf[9] << 8 | buf[8];
+
+    /* Version already found? */
+    if (dmi->dmitable.ver > 0)
+	return DMI_TABLE_PRESENT;
+
+    dmi->dmitable.ver = (buf[0x06] << 8) + buf[0x07];
+
+    /*
+     * DMI version 0.0 means that the real version is taken from
+     * the SMBIOS version, which we don't know at this point.
+     */
+    if (buf[14] != 0) {
+	dmi->dmitable.major_version = buf[14] >> 4;
+	dmi->dmitable.minor_version = buf[14] & 0x0F;
+    } else {
+	dmi->dmitable.major_version = 0;
+	dmi->dmitable.minor_version = 0;
+    }
+    return DMI_TABLE_PRESENT;
+}
+
+int dmi_iterate(s_dmi * dmi)
+{
+    uint8_t *p, *q;
+    int found = 0;
+
+    /* Cleaning structures */
+    memset(dmi, 0, sizeof(s_dmi));
+
+    memset(&dmi->base_board, 0, sizeof(s_base_board));
+    memset(&dmi->battery, 0, sizeof(s_battery));
+    memset(&dmi->bios, 0, sizeof(s_bios));
+    memset(&dmi->chassis, 0, sizeof(s_chassis));
+    for (int i = 0; i < MAX_DMI_MEMORY_ITEMS; i++)
+	memset(&dmi->memory[i], 0, sizeof(s_memory));
+    memset(&dmi->processor, 0, sizeof(s_processor));
+    memset(&dmi->system, 0, sizeof(s_system));
+
+    /* Until we found this elements in the dmitable, we consider them as not filled */
+    dmi->base_board.filled = false;
+    dmi->battery.filled = false;
+    dmi->bios.filled = false;
+    dmi->chassis.filled = false;
+    for (int i = 0; i < MAX_DMI_MEMORY_ITEMS; i++)
+	dmi->memory[i].filled = false;
+    dmi->processor.filled = false;
+    dmi->system.filled = false;
+
+    p = (uint8_t *) 0xF0000;	/* The start address to look at the dmi table */
+    /* The anchor-string is 16-bytes aligned */
+    for (q = p; q < p + 0x10000; q += 16) {
+	/* To validate the presence of SMBIOS:
+	 * + the overall checksum must be correct
+	 * + the intermediate anchor-string must be _DMI_
+	 * + the intermediate checksum must be correct
+	 */
+	if (memcmp(q, "_SM_", 4) == 0 &&
+	    checksum(q, q[0x05]) &&
+	    memcmp(q + 0x10, "_DMI_", 5) == 0 && checksum(q + 0x10, 0x0F)) {
+	    /* Do not return, legacy_decode will need to be called
+	     * on the intermediate structure to get the table length
+	     * and address
+	     */
+	    smbios_decode(dmi, q);
+	} else if (memcmp(q, "_DMI_", 5) == 0 && checksum(q, 0x0F)) {
+	    found = 1;
+	    legacy_decode(dmi, q);
+	}
+    }
+
+    if (found)
+	return DMI_TABLE_PRESENT;
+
+    dmi->dmitable.base = 0;
+    dmi->dmitable.num = 0;
+    dmi->dmitable.ver = 0;
+    dmi->dmitable.len = 0;
+    return -ENODMITABLE;
+}
+
+void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi)
+{
+    uint8_t *data = h->data;
+
+    /*
+     * Note: DMI types 37, 38 and 39 are untested
+     */
+    switch (h->type) {
+    case 0:			/* 3.3.1 BIOS Information */
+	if (h->length < 0x12)
+	    break;
+	dmi->bios.filled = true;
+	strlcpy(dmi->bios.vendor, dmi_string(h, data[0x04]),
+		sizeof(dmi->bios.vendor));
+	strlcpy(dmi->bios.version, dmi_string(h, data[0x05]),
+		sizeof(dmi->bios.version));
+	strlcpy(dmi->bios.release_date, dmi_string(h, data[0x08]),
+		sizeof(dmi->bios.release_date));
+	dmi->bios.address = WORD(data + 0x06);
+	dmi_bios_runtime_size((0x10000 - WORD(data + 0x06)) << 4, dmi);
+	dmi->bios.rom_size = (data[0x09] + 1) << 6;
+	strlcpy(dmi->bios.rom_size_unit, "kB", sizeof(dmi->bios.rom_size_unit));
+	dmi_bios_characteristics(QWORD(data + 0x0A), dmi);
+
+	if (h->length < 0x13)
+	    break;
+	dmi_bios_characteristics_x1(data[0x12], dmi);
+	if (h->length < 0x14)
+	    break;
+	dmi_bios_characteristics_x2(data[0x13], dmi);
+	if (h->length < 0x18)
+	    break;
+	if (data[0x14] != 0xFF && data[0x15] != 0xFF)
+	    snprintf(dmi->bios.bios_revision, sizeof(dmi->bios.bios_revision),
+		     "%u.%u", data[0x14], data[0x15]);
+	if (data[0x16] != 0xFF && data[0x17] != 0xFF)
+	    snprintf(dmi->bios.firmware_revision,
+		     sizeof(dmi->bios.firmware_revision), "%u.%u", data[0x16],
+		     data[0x17]);
+	break;
+    case 1:			/* 3.3.2 System Information */
+	if (h->length < 0x08)
+	    break;
+	dmi->system.filled = true;
+	strlcpy(dmi->system.manufacturer, dmi_string(h, data[0x04]),
+		sizeof(dmi->system.manufacturer));
+	strlcpy(dmi->system.product_name, dmi_string(h, data[0x05]),
+		sizeof(dmi->system.product_name));
+	strlcpy(dmi->system.version, dmi_string(h, data[0x06]),
+		sizeof(dmi->system.version));
+	strlcpy(dmi->system.serial, dmi_string(h, data[0x07]),
+		sizeof(dmi->system.serial));
+	if (h->length < 0x19)
+	    break;
+	dmi_system_uuid(data + 0x08, dmi);
+	dmi_system_wake_up_type(data[0x18], dmi);
+	if (h->length < 0x1B)
+	    break;
+	strlcpy(dmi->system.sku_number, dmi_string(h, data[0x19]),
+		sizeof(dmi->system.sku_number));
+	strlcpy(dmi->system.family, dmi_string(h, data[0x1A]),
+		sizeof(dmi->system.family));
+	break;
+
+    case 2:			/* 3.3.3 Base Board Information */
+	if (h->length < 0x08)
+	    break;
+	dmi->base_board.filled = true;
+	strlcpy(dmi->base_board.manufacturer, dmi_string(h, data[0x04]),
+		sizeof(dmi->base_board.manufacturer));
+	strlcpy(dmi->base_board.product_name, dmi_string(h, data[0x05]),
+		sizeof(dmi->base_board.product_name));
+	strlcpy(dmi->base_board.version, dmi_string(h, data[0x06]),
+		sizeof(dmi->base_board.version));
+	strlcpy(dmi->base_board.serial, dmi_string(h, data[0x07]),
+		sizeof(dmi->base_board.serial));
+	if (h->length < 0x0F)
+	    break;
+	strlcpy(dmi->base_board.asset_tag, dmi_string(h, data[0x08]),
+		sizeof(dmi->base_board.asset_tag));
+	dmi_base_board_features(data[0x09], dmi);
+	strlcpy(dmi->base_board.location, dmi_string(h, data[0x0A]),
+		sizeof(dmi->base_board.location));
+	dmi_base_board_type(data[0x0D], dmi);
+	if (h->length < 0x0F + data[0x0E] * sizeof(uint16_t))
+	    break;
+	break;
+    case 3:			/* 3.3.4 Chassis Information */
+	if (h->length < 0x09)
+	    break;
+	dmi->chassis.filled = true;
+	strlcpy(dmi->chassis.manufacturer, dmi_string(h, data[0x04]),
+		sizeof(dmi->chassis.manufacturer));
+	strlcpy(dmi->chassis.type, dmi_chassis_type(data[0x05] & 0x7F),
+		sizeof(dmi->chassis.type));
+	strlcpy(dmi->chassis.lock, dmi_chassis_lock(data[0x05] >> 7),
+		sizeof(dmi->chassis.lock));
+	strlcpy(dmi->chassis.version, dmi_string(h, data[0x06]),
+		sizeof(dmi->chassis.version));
+	strlcpy(dmi->chassis.serial, dmi_string(h, data[0x07]),
+		sizeof(dmi->chassis.serial));
+	strlcpy(dmi->chassis.asset_tag, dmi_string(h, data[0x08]),
+		sizeof(dmi->chassis.asset_tag));
+	if (h->length < 0x0D)
+	    break;
+	strlcpy(dmi->chassis.boot_up_state, dmi_chassis_state(data[0x09]),
+		sizeof(dmi->chassis.boot_up_state));
+	strlcpy(dmi->chassis.power_supply_state,
+		dmi_chassis_state(data[0x0A]),
+		sizeof(dmi->chassis.power_supply_state));
+	strlcpy(dmi->chassis.thermal_state,
+		dmi_chassis_state(data[0x0B]),
+		sizeof(dmi->chassis.thermal_state));
+	strlcpy(dmi->chassis.security_status,
+		dmi_chassis_security_status(data[0x0C]),
+		sizeof(dmi->chassis.security_status));
+	if (h->length < 0x11)
+	    break;
+	snprintf(dmi->chassis.oem_information,
+		 sizeof(dmi->chassis.oem_information), "0x%08X",
+		 DWORD(data + 0x0D));
+	if (h->length < 0x15)
+	    break;
+	dmi->chassis.height = data[0x11];
+	dmi->chassis.nb_power_cords = data[0x12];
+	break;
+    case 4:			/* 3.3.5 Processor Information */
+	if (h->length < 0x1A)
+	    break;
+	dmi->processor.filled = true;
+	strlcpy(dmi->processor.socket_designation,
+		dmi_string(h, data[0x04]),
+		sizeof(dmi->processor.socket_designation));
+	strlcpy(dmi->processor.type,
+		dmi_processor_type(data[0x05]), sizeof(dmi->processor.type));
+	strlcpy(dmi->processor.manufacturer,
+		dmi_string(h, data[0x07]), sizeof(dmi->processor.manufacturer));
+	strlcpy(dmi->processor.family,
+		dmi_processor_family(data[0x06],
+				     dmi->processor.manufacturer),
+		sizeof(dmi->processor.family));
+	dmi_processor_id(data[0x06], data + 8, dmi_string(h, data[0x10]), dmi);
+	strlcpy(dmi->processor.version,
+		dmi_string(h, data[0x10]), sizeof(dmi->processor.version));
+	dmi_processor_voltage(data[0x11], dmi);
+	dmi->processor.external_clock = WORD(data + 0x12);
+	dmi->processor.max_speed = WORD(data + 0x14);
+	dmi->processor.current_speed = WORD(data + 0x16);
+	if (data[0x18] & (1 << 6))
+	    strlcpy(dmi->processor.status,
+		    dmi_processor_status(data[0x18] & 0x07),
+		    sizeof(dmi->processor.status));
+	else
+	    sprintf(dmi->processor.status, "Unpopulated");
+	strlcpy(dmi->processor.upgrade,
+		dmi_processor_upgrade(data[0x19]),
+		sizeof(dmi->processor.upgrade));
+	if (h->length < 0x20)
+	    break;
+	dmi_processor_cache(WORD(data + 0x1A), "L1", ver,
+			    dmi->processor.cache1);
+	dmi_processor_cache(WORD(data + 0x1C), "L2", ver,
+			    dmi->processor.cache2);
+	dmi_processor_cache(WORD(data + 0x1E), "L3", ver,
+			    dmi->processor.cache3);
+	if (h->length < 0x23)
+	    break;
+	strlcpy(dmi->processor.serial, dmi_string(h, data[0x20]),
+		sizeof(dmi->processor.serial));
+	strlcpy(dmi->processor.asset_tag, dmi_string(h, data[0x21]),
+		sizeof(dmi->processor.asset_tag));
+	strlcpy(dmi->processor.part_number, dmi_string(h, data[0x22]),
+		sizeof(dmi->processor.part_number));
+        dmi->processor.core_count = 0;
+        dmi->processor.core_enabled = 0;
+        dmi->processor.thread_count = 0;
+	if (h->length < 0x28)
+	    break;
+        dmi->processor.core_count = data[0x23];
+        dmi->processor.core_enabled = data[0x24];
+        dmi->processor.thread_count = data[0x25];
+	break;
+    case 6:			/* 3.3.7 Memory Module Information */
+	if (h->length < 0x0C)
+	    break;
+	dmi->memory_module_count++;
+	s_memory_module *module =
+	    &dmi->memory_module[dmi->memory_module_count - 1];
+	dmi->memory_module[dmi->memory_module_count - 1].filled = true;
+	strlcpy(module->socket_designation, dmi_string(h, data[0x04]),
+		sizeof(module->socket_designation));
+	dmi_memory_module_connections(data[0x05], module->bank_connections, sizeof(module->bank_connections));
+	dmi_memory_module_speed(data[0x06], module->speed);
+	dmi_memory_module_types(WORD(data + 0x07), " ", module->type, sizeof(module->type));
+	dmi_memory_module_size(data[0x09], module->installed_size, sizeof(module->installed_size));
+	dmi_memory_module_size(data[0x0A], module->enabled_size, sizeof(module->enabled_size));
+	dmi_memory_module_error(data[0x0B], "\t\t", module->error_status);
+	break;
+    case 7:			/* 3.3.8 Cache Information */
+	if (h->length < 0x0F)
+	    break;
+	dmi->cache_count++;
+	if (dmi->cache_count > MAX_DMI_CACHE_ITEMS)
+	    break;
+	strlcpy(dmi->cache[dmi->cache_count - 1].socket_designation,
+		dmi_string(h, data[0x04]),
+		sizeof(dmi->cache[dmi->cache_count - 1].socket_designation));
+	snprintf(dmi->cache[dmi->cache_count - 1].configuration,
+		 sizeof(dmi->cache[dmi->cache_count - 1].configuration),
+		 "%s, %s, %u",
+		 WORD(data + 0x05) & 0x0080 ? "Enabled" : "Disabled",
+		 WORD(data +
+		      0x05) & 0x0008 ? "Socketed" : "Not Socketed",
+		 (WORD(data + 0x05) & 0x0007) + 1);
+	strlcpy(dmi->cache[dmi->cache_count - 1].mode,
+		dmi_cache_mode((WORD(data + 0x05) >> 8) & 0x0003),
+		sizeof(dmi->cache[dmi->cache_count - 1].mode));
+	strlcpy(dmi->cache[dmi->cache_count - 1].location,
+		dmi_cache_location((WORD(data + 0x05) >> 5) & 0x0003),
+		sizeof(dmi->cache[dmi->cache_count - 1].location));
+	dmi->cache[dmi->cache_count - 1].installed_size =
+	    dmi_cache_size(WORD(data + 0x09));
+	dmi->cache[dmi->cache_count - 1].max_size =
+	    dmi_cache_size(WORD(data + 0x07));
+	dmi_cache_types(WORD(data + 0x0B), " ",
+			dmi->cache[dmi->cache_count - 1].supported_sram_types);
+	dmi_cache_types(WORD(data + 0x0D), " ",
+			dmi->cache[dmi->cache_count - 1].installed_sram_types);
+	if (h->length < 0x13)
+	    break;
+	dmi->cache[dmi->cache_count - 1].speed = data[0x0F];	/* ns */
+	strlcpy(dmi->cache[dmi->cache_count - 1].error_correction_type,
+		dmi_cache_ec_type(data[0x10]),
+		sizeof(dmi->cache[dmi->cache_count - 1].error_correction_type));
+	strlcpy(dmi->cache[dmi->cache_count - 1].system_type,
+		dmi_cache_type(data[0x11]),
+		sizeof(dmi->cache[dmi->cache_count - 1].system_type));
+	strlcpy(dmi->cache[dmi->cache_count - 1].associativity,
+		dmi_cache_associativity(data[0x12]),
+		sizeof(dmi->cache[dmi->cache_count - 1].associativity));
+	break;
+    case 10:			/* 3.3.11 On Board Devices Information */
+	dmi_on_board_devices(h, dmi);
+	break;
+    case 11:			/* 3.3.12 OEM Strings */
+	if (h->length < 0x05)
+	    break;
+	dmi_oem_strings(h, "\t", dmi);
+	break;
+    case 12:			/* 3.3.13 System Configuration Options */
+	if (h->length < 0x05)
+	    break;
+	dmi_system_configuration_options(h, "\t", dmi);
+	break;
+    case 17:			/* 3.3.18 Memory Device */
+	if (h->length < 0x15)
+	    break;
+	dmi->memory_count++;
+	if (dmi->memory_count > MAX_DMI_MEMORY_ITEMS)
+	    break;
+	s_memory *mem = &dmi->memory[dmi->memory_count - 1];
+	dmi->memory[dmi->memory_count - 1].filled = true;
+	dmi_memory_array_error_handle(WORD(data + 0x06), mem->error);
+	dmi_memory_device_width(WORD(data + 0x08), mem->total_width);
+	dmi_memory_device_width(WORD(data + 0x0A), mem->data_width);
+	dmi_memory_device_size(WORD(data + 0x0C), mem->size);
+	strlcpy(mem->form_factor,
+		dmi_memory_device_form_factor(data[0x0E]),
+		sizeof(mem->form_factor));
+	dmi_memory_device_set(data[0x0F], mem->device_set);
+	strlcpy(mem->device_locator, dmi_string(h, data[0x10]),
+		sizeof(mem->device_locator));
+	strlcpy(mem->bank_locator, dmi_string(h, data[0x11]),
+		sizeof(mem->bank_locator));
+	strlcpy(mem->type, dmi_memory_device_type(data[0x12]),
+		sizeof(mem->type));
+	dmi_memory_device_type_detail(WORD(data + 0x13), mem->type_detail, sizeof(mem->type_detail));
+	if (h->length < 0x17)
+	    break;
+	dmi_memory_device_speed(WORD(data + 0x15), mem->speed);
+	if (h->length < 0x1B)
+	    break;
+	strlcpy(mem->manufacturer, dmi_string(h, data[0x17]),
+		sizeof(mem->manufacturer));
+	strlcpy(mem->serial, dmi_string(h, data[0x18]), sizeof(mem->serial));
+	strlcpy(mem->asset_tag, dmi_string(h, data[0x19]),
+		sizeof(mem->asset_tag));
+	strlcpy(mem->part_number, dmi_string(h, data[0x1A]),
+		sizeof(mem->part_number));
+	break;
+    case 22:			/* 3.3.23 Portable Battery */
+	if (h->length < 0x10)
+	    break;
+	dmi->battery.filled = true;
+	strlcpy(dmi->battery.location, dmi_string(h, data[0x04]),
+		sizeof(dmi->battery.location));
+	strlcpy(dmi->battery.manufacturer, dmi_string(h, data[0x05]),
+		sizeof(dmi->battery.manufacturer));
+	if (data[0x06] || h->length < 0x1A)
+	    strlcpy(dmi->battery.manufacture_date,
+		    dmi_string(h, data[0x06]),
+		    sizeof(dmi->battery.manufacture_date));
+	if (data[0x07] || h->length < 0x1A)
+	    strlcpy(dmi->battery.serial, dmi_string(h, data[0x07]),
+		    sizeof(dmi->battery.serial));
+	strlcpy(dmi->battery.name, dmi_string(h, data[0x08]),
+		sizeof(dmi->battery.name));
+	if (data[0x09] != 0x02 || h->length < 0x1A)
+	    strlcpy(dmi->battery.chemistry,
+		    dmi_battery_chemistry(data[0x09]),
+		    sizeof(dmi->battery.chemistry));
+	if (h->length < 0x1A)
+	    dmi_battery_capacity(WORD(data + 0x0A), 1,
+				 dmi->battery.design_capacity);
+	else
+	    dmi_battery_capacity(WORD(data + 0x0A), data[0x15],
+				 dmi->battery.design_capacity);
+	dmi_battery_voltage(WORD(data + 0x0C), dmi->battery.design_voltage);
+	strlcpy(dmi->battery.sbds, dmi_string(h, data[0x0E]),
+		sizeof(dmi->battery.sbds));
+	dmi_battery_maximum_error(data[0x0F], dmi->battery.maximum_error);
+	if (h->length < 0x1A)
+	    break;
+	if (data[0x07] == 0)
+	    sprintf(dmi->battery.sbds_serial, "%04X", WORD(data + 0x10));
+	if (data[0x06] == 0)
+	    sprintf(dmi->battery.sbds_manufacture_date, "%u-%02u-%02u",
+		    1980 + (WORD(data + 0x12) >> 9),
+		    (WORD(data + 0x12) >> 5) & 0x0F, WORD(data + 0x12) & 0x1F);
+	if (data[0x09] == 0x02)
+	    strlcpy(dmi->battery.sbds_chemistry, dmi_string(h, data[0x14]),
+		    sizeof(dmi->battery.sbds_chemistry));
+	//      sprintf(dmi->battery.oem_info,"0x%08X",DWORD(h, data+0x16));
+	break;
+    case 23:			/* 3.3.24 System Reset */
+	if (h->length < 0x0D)
+	    break;
+	dmi->system.system_reset.filled = true;
+	dmi->system.system_reset.status = data[0x04] & (1 << 0);
+	dmi->system.system_reset.watchdog = data[0x04] & (1 << 5);
+	if (!(data[0x04] & (1 << 5)))
+	    break;
+	strlcpy(dmi->system.system_reset.boot_option,
+		dmi_system_reset_boot_option((data[0x04] >> 1) & 0x3),
+		sizeof dmi->system.system_reset.boot_option);
+	strlcpy(dmi->system.system_reset.boot_option_on_limit,
+		dmi_system_reset_boot_option((data[0x04] >> 3) & 0x3),
+		sizeof dmi->system.system_reset.boot_option_on_limit);
+	dmi_system_reset_count(WORD(data + 0x05),
+			       dmi->system.system_reset.reset_count);
+	dmi_system_reset_count(WORD(data + 0x07),
+			       dmi->system.system_reset.reset_limit);
+	dmi_system_reset_timer(WORD(data + 0x09),
+			       dmi->system.system_reset.timer_interval);
+	dmi_system_reset_timer(WORD(data + 0x0B),
+			       dmi->system.system_reset.timeout);
+	break;
+    case 24:			/* 3.3.25 Hardware Security */
+	if (h->length < 0x05)
+	    break;
+	dmi->hardware_security.filled = true;
+	strlcpy(dmi->hardware_security.power_on_passwd_status,
+		dmi_hardware_security_status(data[0x04] >> 6),
+		sizeof dmi->hardware_security.power_on_passwd_status);
+	strlcpy(dmi->hardware_security.keyboard_passwd_status,
+		dmi_hardware_security_status((data[0x04] >> 4) & 0x3),
+		sizeof dmi->hardware_security.keyboard_passwd_status);
+	strlcpy(dmi->hardware_security.administrator_passwd_status,
+		dmi_hardware_security_status((data[0x04] >> 2) & 0x3),
+		sizeof dmi->hardware_security.administrator_passwd_status);
+	strlcpy(dmi->hardware_security.front_panel_reset_status,
+		dmi_hardware_security_status(data[0x04] & 0x3),
+		sizeof dmi->hardware_security.front_panel_reset_status);
+	break;
+    case 32:			/* 3.3.33 System Boot Information */
+	if (h->length < 0x0B)
+	    break;
+	dmi_system_boot_status(data[0x0A], dmi->system.system_boot_status);
+    case 38:			/* 3.3.39 IPMI Device Information */
+	if (h->length < 0x10)
+	    break;
+	dmi->ipmi.filled = true;
+	snprintf(dmi->ipmi.interface_type,
+		 sizeof(dmi->ipmi.interface_type), "%s",
+		 dmi_ipmi_interface_type(data[0x04]));
+	dmi->ipmi.major_specification_version = data[0x05] >> 4;
+	dmi->ipmi.minor_specification_version = data[0x05] & 0x0F;
+	dmi->ipmi.I2C_slave_address = data[0x06] >> 1;
+	if (data[0x07] != 0xFF)
+	    dmi->ipmi.nv_address = data[0x07];
+	else
+	    dmi->ipmi.nv_address = 0;	/* Not Present */
+	dmi_ipmi_base_address(data[0x04], data + 0x08, &dmi->ipmi);
+	if (h->length < 0x12)
+	    break;
+	if (data[0x11] != 0x00) {
+	    dmi->ipmi.irq = data[0x11];
+	}
+	break;
+    }
+}
+
+void parse_dmitable(s_dmi * dmi)
+{
+    int i = 0;
+    uint8_t *data = NULL;
+    uint8_t buf[dmi->dmitable.len];
+    memcpy(buf, (int *)dmi->dmitable.base, sizeof(uint8_t) * dmi->dmitable.len);
+    data = buf;
+    dmi->memory_count = 0;
+    while (i < dmi->dmitable.num && data + 4 <= buf + dmi->dmitable.len) {	/* 4 is the length of an SMBIOS structure header */
+	uint8_t *next;
+	struct dmi_header h;
+	to_dmi_header(&h, data);
+	/*
+	 * If a short entry is found (less than 4 bytes), not only it
+	 * is invalid, but we cannot reliably locate the next entry.
+	 * Better stop at this point, and let the user know his/her
+	 * table is broken.
+	 */
+	if (h.length < 4) {
+	    printf
+		("Invalid entry length (%u). DMI table is broken! Stop.\n\n",
+		 (unsigned int)h.length);
+	    break;
+	}
+
+	/* loo for the next handle */
+	next = data + h.length;
+	while (next - buf + 1 < dmi->dmitable.len
+	       && (next[0] != 0 || next[1] != 0))
+	    next++;
+	next += 2;
+	if (next - buf <= dmi->dmitable.len) {
+	    dmi_decode(&h, dmi->dmitable.ver, dmi);
+	}
+	data = next;
+	i++;
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_base_board.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_base_board.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_base_board.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,37 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Pportions of this file taken from the dmidecode project
+ *
+ *   Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
+ *   Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ *   For the avoidance of doubt the "preferred form" of this code is one which
+ *   is in an open unpatent encumbered format. Where cryptographic key signing
+ *   forms part of the process of creating an executable the information
+ *   including keys needed to generate an equivalently functional executable
+ *   are deemed to be part of the source code.
+*/
+
+#include <dmi/dmi.h>
+#include <stdio.h>
+const char *base_board_features_strings[] = {
+    "Board is a hosting board",	/* 0 */
+    "Board requires at least one daughter board",
+    "Board is removable",
+    "Board is replaceable",
+    "Board is hot swappable"	/* 4 */
+};
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_battery.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_battery.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_battery.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,72 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Pportions of this file taken from the dmidecode project
+ *
+ *   Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
+ *   Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ *   For the avoidance of doubt the "preferred form" of this code is one which
+ *   is in an open unpatent encumbered format. Where cryptographic key signing
+ *   forms part of the process of creating an executable the information
+ *   including keys needed to generate an equivalently functional executable
+ *   are deemed to be part of the source code.
+*/
+
+#include <dmi/dmi.h>
+#include <stdio.h>
+const char *dmi_battery_chemistry(uint8_t code)
+{
+    /* 3.3.23.1 */
+    static const char *chemistry[] = {
+	"Other",		/* 0x01 */
+	"Unknown",
+	"Lead Acid",
+	"Nickel Cadmium",
+	"Nickel Metal Hydride",
+	"Lithium Ion",
+	"Zinc Air",
+	"Lithium Polymer"	/* 0x08 */
+    };
+
+    if (code >= 0x01 && code <= 0x08)
+	return chemistry[code - 0x01];
+    return out_of_spec;
+}
+
+void dmi_battery_capacity(uint16_t code, uint8_t multiplier, char *capacity)
+{
+    if (code == 0)
+	sprintf(capacity, "%s", "Unknown");
+    else
+	sprintf(capacity, "%u mWh", code * multiplier);
+}
+
+void dmi_battery_voltage(uint16_t code, char *voltage)
+{
+    if (code == 0)
+	sprintf(voltage, "%s", "Unknown");
+    else
+	sprintf(voltage, "%u mV", code);
+}
+
+void dmi_battery_maximum_error(uint8_t code, char *error)
+{
+    if (code == 0xFF)
+	sprintf(error, "%s", "Unknown");
+    else
+	sprintf(error, "%u%%", code);
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_bios.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_bios.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_bios.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,79 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Pportions of this file taken from the dmidecode project
+ *
+ *   Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
+ *   Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ *   For the avoidance of doubt the "preferred form" of this code is one which
+ *   is in an open unpatent encumbered format. Where cryptographic key signing
+ *   forms part of the process of creating an executable the information
+ *   including keys needed to generate an equivalently functional executable
+ *   are deemed to be part of the source code.
+*/
+
+#include <dmi/dmi.h>
+#include <stdio.h>
+
+const char *bios_charac_strings[] = {
+    "BIOS characteristics not supported",	/* 3 */
+    "ISA is supported",
+    "MCA is supported",
+    "EISA is supported",
+    "PCI is supported",
+    "PC Card (PCMCIA) is supported",
+    "PNP is supported",
+    "APM is supported",
+    "BIOS is upgradeable",
+    "BIOS shadowing is allowed",
+    "VLB is supported",
+    "ESCD support is available",
+    "Boot from CD is supported",
+    "Selectable boot is supported",
+    "BIOS ROM is socketed",
+    "Boot from PC Card (PCMCIA) is supported",
+    "EDD is supported",
+    "Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)",
+    "Japanese floppy for Toshiba 1.2 MB is supported (int 13h)",
+    "5.25\"/360 KB floppy services are supported (int 13h)",
+    "5.25\"/1.2 MB floppy services are supported (int 13h)",
+    "3.5\"/720 KB floppy services are supported (int 13h)",
+    "3.5\"/2.88 MB floppy services are supported (int 13h)",
+    "Print screen service is supported (int 5h)",
+    "8042 keyboard services are supported (int 9h)",
+    "Serial services are supported (int 14h)",
+    "Printer services are supported (int 17h)",
+    "CGA/mono video services are supported (int 10h)",
+    "NEC PC-98"			/* 31 */
+};
+
+const char *bios_charac_x1_strings[] = {
+    "ACPI is supported",	/* 0 */
+    "USB legacy is supported",
+    "AGP is supported",
+    "I2O boot is supported",
+    "LS-120 boot is supported",
+    "ATAPI Zip drive boot is supported",
+    "IEEE 1394 boot is supported",
+    "Smart battery is supported"	/* 7 */
+};
+
+const char *bios_charac_x2_strings[] = {
+    "BIOS boot specification is supported",	/* 0 */
+    "Function key-initiated network boot is supported",
+    "Targeted content distribution is supported"	/* 2 */
+};
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_cache.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_cache.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_cache.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,139 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved
+ *
+ *   Some part borrowed from DMI Decode:
+ *
+ *   (C) 2000-2002 Alan Cox <alan@redhat.com>
+ *   (C) 2002-2007 Jean Delvare <khali@linux-fr.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <dmi/dmi.h>
+#include <dmi/dmi_cache.h>
+#include <stdio.h>
+
+/*
+ * 3.3.8 Cache Information (Type 7)
+ */
+
+const char *dmi_cache_mode(uint8_t code)
+{
+    static const char *mode[] = {
+	"Write Through",	/* 0x00 */
+	"Write Back",
+	"Varies With Memory Address",
+	"Unknown"		/* 0x03 */
+    };
+
+    return mode[code];
+}
+
+const char *dmi_cache_location(uint8_t code)
+{
+    static const char *location[4] = {
+	"Internal",		/* 0x00 */
+	"External",
+	"<OUT OF SPEC",		/* 0x02 */
+	"Unknown"		/* 0x03 */
+    };
+
+    if (location[code] != NULL)
+	return location[code];
+    return out_of_spec;
+}
+
+uint16_t dmi_cache_size(uint16_t code)
+{
+    if (code & 0x8000)
+	return (code & 0x7FFF) << 6;	/* KB */
+    else
+	return code;		/* KB */
+}
+
+void dmi_cache_types(uint16_t code, const char *sep, char *array)
+{
+    /* 3.3.8.2 */
+    static const char *types[] = {
+	"Other",		/* 0 */
+	"Unknown",
+	"Non-burst",
+	"Burst",
+	"Pipeline Burst",
+	"Synchronous",
+	"Asynchronous"		/* 6 */
+    };
+
+    if ((code & 0x007F) == 0)
+	strcpy(array, "None");
+    else {
+	int i;
+
+	for (i = 0; i <= 6; i++)
+	    if (code & (1 << i))
+		sprintf(array, "%s%s", sep, types[i]);
+    }
+}
+
+const char *dmi_cache_ec_type(uint8_t code)
+{
+    /* 3.3.8.3 */
+    static const char *type[] = {
+	"Other",		/* 0x01 */
+	"Unknown",
+	"None",
+	"Parity",
+	"Single-bit ECC",
+	"Multi-bit ECC"		/* 0x06 */
+    };
+
+    if (code >= 0x01 && code <= 0x06)
+	return type[code - 0x01];
+    return out_of_spec;
+}
+
+const char *dmi_cache_type(uint8_t code)
+{
+    /* 3.3.8.4 */
+    static const char *type[] = {
+	"Other",		/* 0x01 */
+	"Unknown",
+	"Instruction",
+	"Data",
+	"Unified"		/* 0x05 */
+    };
+
+    if (code >= 0x01 && code <= 0x05)
+	return type[code - 0x01];
+    return out_of_spec;
+}
+
+const char *dmi_cache_associativity(uint8_t code)
+{
+    /* 3.3.8.5 */
+    static const char *type[] = {
+	"Other",		/* 0x01 */
+	"Unknown",
+	"Direct Mapped",
+	"2-way Set-associative",
+	"4-way Set-associative",
+	"Fully Associative",
+	"8-way Set-associative",
+	"16-way Set-associative",	/* 0x08 */
+	"12-way Set-associative",
+	"24-way Set-associative",
+	"32-way Set-associative",
+	"48-way Set-associative",
+	"64-way Set-associative"	/* 0x0D */
+    };
+
+    if (code >= 0x01 && code <= 0x0D)
+	return type[code - 0x01];
+    return out_of_spec;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_chassis.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_chassis.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_chassis.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,113 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Pportions of this file taken from the dmidecode project
+ *
+ *   Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
+ *   Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ *   For the avoidance of doubt the "preferred form" of this code is one which
+ *   is in an open unpatent encumbered format. Where cryptographic key signing
+ *   forms part of the process of creating an executable the information
+ *   including keys needed to generate an equivalently functional executable
+ *   are deemed to be part of the source code.
+*/
+
+#include <dmi/dmi.h>
+#include <stdio.h>
+
+const char *dmi_chassis_type(uint8_t code)
+{
+    /* 3.3.4.1 */
+    static const char *type[] = {
+	"Other",		/* 0x01 */
+	"Unknown",
+	"Desktop",
+	"Low Profile Desktop",
+	"Pizza Box",
+	"Mini Tower",
+	"Tower",
+	"Portable",
+	"Laptop",
+	"Notebook",
+	"Hand Held",
+	"Docking Station",
+	"All In One",
+	"Sub Notebook",
+	"Space-saving",
+	"Lunch Box",
+	"Main Server Chassis",	/* master.mif says System */
+	"Expansion Chassis",
+	"Sub Chassis",
+	"Bus Expansion Chassis",
+	"Peripheral Chassis",
+	"RAID Chassis",
+	"Rack Mount Chassis",
+	"Sealed-case PC",
+	"Multi-system",		/* 0x19 */
+	"CompactPCI",
+	"AdvancedTCA",
+	"Blade",
+	"Blade Enclosing" /* 0x1D */
+    };
+
+    if (code >= 0x01 && code <= 0x1D)
+	return type[code - 0x01];
+    return out_of_spec;
+}
+
+const char *dmi_chassis_lock(uint8_t code)
+{
+    static const char *lock[] = {
+	"Not Present",		/* 0x00 */
+	"Present"		/* 0x01 */
+    };
+
+    return lock[code];
+}
+
+const char *dmi_chassis_state(uint8_t code)
+{
+    /* 3.3.4.2 */
+    static const char *state[] = {
+	"Other",		/* 0x01 */
+	"Unknown",
+	"Safe",			/* master.mif says OK */
+	"Warning",
+	"Critical",
+	"Non-recoverable"	/* 0x06 */
+    };
+
+    if (code >= 0x01 && code <= 0x06)
+	return (state[code - 0x01]);
+    return out_of_spec;
+}
+
+const char *dmi_chassis_security_status(uint8_t code)
+{
+    /* 3.3.4.3 */
+    static const char *status[] = {
+	"Other",		/* 0x01 */
+	"Unknown",
+	"None",
+	"External Interface Locked Out",
+	"External Interface Enabled"	/* 0x05 */
+    };
+
+    if (code >= 0x01 && code <= 0x05)
+	return (status[code - 0x01]);
+    return out_of_spec;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_ipmi.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_ipmi.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_ipmi.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,55 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Portions of this file taken from the dmidecode project
+ *
+ *   Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
+ *   Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ *   For the avoidance of doubt the "preferred form" of this code is one which
+ *   is in an open unpatent encumbered format. Where cryptographic key signing
+ *   forms part of the process of creating an executable the information
+ *   including keys needed to generate an equivalently functional executable
+ *   are deemed to be part of the source code.
+*/
+
+#include <dmi/dmi.h>
+#include <stdio.h>
+
+const char *dmi_ipmi_interface_type(uint8_t code)
+{
+    /* 3.3.39.1 and IPMI 2.0, appendix C1, table C1-2 */
+    static const char *type[] = {
+	"Unknown",		/* 0x00 */
+	"KCS (Keyboard Control Style)",
+	"SMIC (Server Management Interface Chip)",
+	"BT (Block Transfer)",
+	"SSIF (SMBus System Interface)"	/* 0x04 */
+    };
+
+    if (code <= 0x04)
+	return type[code];
+    return out_of_spec;
+}
+
+void dmi_ipmi_base_address(uint8_t type, const uint8_t * p, s_ipmi * ipmi)
+{
+    if (type == 0x04) {		/* SSIF */
+	ipmi->base_address = (*p) >> 1;
+    } else {
+	ipmi->base_address = QWORD(p);
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_memory.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_memory.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_memory.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,264 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Pportions of this file taken from the dmidecode project
+ *
+ *   Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
+ *   Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ *   For the avoidance of doubt the "preferred form" of this code is one which
+ *   is in an open unpatent encumbered format. Where cryptographic key signing
+ *   forms part of the process of creating an executable the information
+ *   including keys needed to generate an equivalently functional executable
+ *   are deemed to be part of the source code.
+*/
+
+#include <dmi/dmi.h>
+#include <stdio.h>
+
+void dmi_memory_array_error_handle(uint16_t code, char *array)
+{
+    if (code == 0xFFFE)
+	sprintf(array, "%s", "Not Provided");
+    else if (code == 0xFFFF)
+	sprintf(array, "%s", "No Error");
+    else
+	sprintf(array, "0x%04X", code);
+}
+
+void dmi_memory_device_width(uint16_t code, char *width)
+{
+    /*
+     * 3.3.18 Memory Device (Type 17)
+     * If no memory module is present, width may be 0
+     */
+    if (code == 0xFFFF || code == 0)
+	sprintf(width, "%s", "Unknown");
+    else
+	sprintf(width, "%u bits", code);
+}
+
+void dmi_memory_device_size(uint16_t code, char *size)
+{
+    if (code == 0)
+	sprintf(size, "%s", "Free");
+    else if (code == 0xFFFF)
+	sprintf(size, "%s", "Unknown");
+    else {
+	if (code & 0x8000)
+	    sprintf(size, "%u kB", code & 0x7FFF);
+	else
+	    sprintf(size, "%u MB", code);
+    }
+}
+
+const char *dmi_memory_device_form_factor(uint8_t code)
+{
+    /* 3.3.18.1 */
+    static const char *form_factor[] = {
+	"Other",		/* 0x01 */
+	"Unknown",
+	"SIMM",
+	"SIP",
+	"Chip",
+	"DIP",
+	"ZIP",
+	"Proprietary Card",
+	"DIMM",
+	"TSOP",
+	"Row Of Chips",
+	"RIMM",
+	"SODIMM",
+	"SRIMM",
+	"FB-DIMM"		/* 0x0F */
+    };
+
+    if (code >= 0x01 && code <= 0x0F)
+	return form_factor[code - 0x01];
+    return out_of_spec;
+}
+
+void dmi_memory_device_set(uint8_t code, char *set)
+{
+    if (code == 0)
+	sprintf(set, "%s", "None");
+    else if (code == 0xFF)
+	sprintf(set, "%s", "Unknown");
+    else
+	sprintf(set, "%u", code);
+}
+
+const char *dmi_memory_device_type(uint8_t code)
+{
+    /* 3.3.18.2 */
+    static const char *type[] = {
+	"Other",		/* 0x01 */
+	"Unknown",
+	"DRAM",
+	"EDRAM",
+	"VRAM",
+	"SRAM",
+	"RAM",
+	"ROM",
+	"Flash",
+	"EEPROM",
+	"FEPROM",
+	"EPROM",
+	"CDRAM",
+	"3DRAM",
+	"SDRAM",
+	"SGRAM",
+	"RDRAM",
+	"DDR",
+	"DDR2",
+	"DDR2 FB-DIMM",		/* 0x14 */
+	NULL,
+	NULL,
+	NULL,
+	"DDR3",			/* 0x18 */
+	"FBD2"			/* 0x19 */
+    };
+
+    if (code >= 0x01 && code <= 0x19)
+	return type[code - 0x01];
+    return out_of_spec;
+}
+
+void dmi_memory_device_type_detail(uint16_t code, char *type_detail, int sizeof_type_detail)
+{
+    /* 3.3.18.3 */
+    static const char *detail[] = {
+	"Other",		/* 1 */
+	"Unknown",
+	"Fast-paged",
+	"Static Column",
+	"Pseudo-static",
+	"RAMBus",
+	"Synchronous",
+	"CMOS",
+	"EDO",
+	"Window DRAM",
+	"Cache DRAM",
+	"Non-Volatile"		/* 12 */
+    };
+
+    if ((code & 0x1FFE) == 0)
+	sprintf(type_detail, "%s", "None");
+    else {
+	int i;
+
+	for (i = 1; i <= 12; i++)
+	    if (code & (1 << i))
+		snprintf(type_detail, sizeof_type_detail, "%s", detail[i - 1]);
+    }
+}
+
+void dmi_memory_device_speed(uint16_t code, char *speed)
+{
+    if (code == 0)
+	sprintf(speed, "%s", "Unknown");
+    else
+	sprintf(speed, "%u MHz", code);
+}
+
+/*
+ * 3.3.7 Memory Module Information (Type 6)
+ */
+
+void dmi_memory_module_types(uint16_t code, const char *sep, char *type, int sizeof_type)
+{
+    /* 3.3.7.1 */
+    static const char *types[] = {
+	"Other",		/* 0 */
+	"Unknown",
+	"Standard",
+	"FPM",
+	"EDO",
+	"Parity",
+	"ECC",
+	"SIMM",
+	"DIMM",
+	"Burst EDO",
+	"SDRAM"			/* 10 */
+    };
+
+    if ((code & 0x07FF) == 0)
+	sprintf(type, "%s", "None");
+    else {
+	int i;
+
+	for (i = 0; i <= 10; i++)
+	    if (code & (1 << i))
+		snprintf(type, sizeof_type, "%s%s%s", type, sep, types[i]);
+    }
+}
+
+void dmi_memory_module_connections(uint8_t code, char *connection, int sizeof_connection)
+{
+    if (code == 0xFF)
+	sprintf(connection, "%s", "None");
+    else {
+	if ((code & 0xF0) != 0xF0)
+	    sprintf(connection, "%u ", code >> 4);
+	if ((code & 0x0F) != 0x0F)
+	    snprintf(connection, sizeof_connection, "%s%u", connection, code & 0x0F);
+    }
+}
+
+void dmi_memory_module_speed(uint8_t code, char *speed)
+{
+    if (code == 0)
+	sprintf(speed, "%s", "Unknown");
+    else
+	sprintf(speed, "%u ns", code);
+}
+
+void dmi_memory_module_size(uint8_t code, char *size, int sizeof_size)
+{
+    /* 3.3.7.2 */
+    switch (code & 0x7F) {
+    case 0x7D:
+	sprintf(size, "%s", "Not Determinable");
+	break;
+    case 0x7E:
+	sprintf(size, "%s", "Disabled");
+	break;
+    case 0x7F:
+	sprintf(size, "%s", "Not Installed");
+	return;
+    default:
+	sprintf(size, "%u MB", 1 << (code & 0x7F));
+    }
+
+    if (code & 0x80)
+	snprintf(size, sizeof_size, "%s %s", size, "(Double-bank Connection)");
+    else
+	snprintf(size, sizeof_size, "%s %s", size, "(Single-bank Connection)");
+}
+
+void dmi_memory_module_error(uint8_t code, const char *prefix, char *error)
+{
+    if (code & (1 << 2))
+	sprintf(error, "%s", "See Event Log\n");
+    else {
+	if ((code & 0x03) == 0)
+	    sprintf(error, "%s", "OK\n");
+	if (code & (1 << 0))
+	    sprintf(error, "%sUncorrectable Errors\n", prefix);
+	if (code & (1 << 1))
+	    sprintf(error, "%sCorrectable Errors\n", prefix);
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_processor.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_processor.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/dmi/dmi_processor.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,431 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Pportions of this file taken from the dmidecode project
+ *
+ *   Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
+ *   Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ *   For the avoidance of doubt the "preferred form" of this code is one which
+ *   is in an open unpatent encumbered format. Where cryptographic key signing
+ *   forms part of the process of creating an executable the information
+ *   including keys needed to generate an equivalently functional executable
+ *   are deemed to be part of the source code.
+*/
+
+#include <dmi/dmi.h>
+#include <stdio.h>
+
+const char *dmi_processor_type(uint8_t code)
+{
+    /* 3.3.5.1 */
+    static const char *type[] = {
+	"Other",		/* 0x01 */
+	"Unknown",
+	"Central Processor",
+	"Math Processor",
+	"DSP Processor",
+	"Video Processor"	/* 0x06 */
+    };
+
+    if (code >= 0x01 && code <= 0x06)
+	return type[code - 0x01];
+    return out_of_spec;
+}
+
+const char *dmi_processor_family(uint8_t code, char *manufacturer)
+{
+    /* 3.3.5.2 */
+    /* TODO : Need to implement code/value (see dmidecode) insteed of array to address large index */
+    static const char *family[256] = {
+	NULL,			/* 0x00 */
+	"Other",
+	"Unknown",
+	"8086",
+	"80286",
+	"80386",
+	"80486",
+	"8087",
+	"80287",
+	"80387",
+	"80487",
+	"Pentium",
+	"Pentium Pro",
+	"Pentium II",
+	"Pentium MMX",
+	"Celeron",
+	"Pentium II Xeon",
+	"Pentium III",
+	"M1",
+	"M2",
+	"Celeron M",		/* 0x14 */
+	"Pentium 4 HT",
+	NULL,
+	NULL,			/* 0x17 */
+	"Duron",
+	"K5",
+	"K6",
+	"K6-2",
+	"K6-3",
+	"Athlon",
+	"AMD2900",
+	"K6-2+",
+	"Power PC",
+	"Power PC 601",
+	"Power PC 603",
+	"Power PC 603+",
+	"Power PC 604",
+	"Power PC 620",
+	"Power PC x704",
+	"Power PC 750",
+	"Core 2 Duo",		/* 0x28 */
+	"Core 2 Duo Mobile",
+	"Core Solo Mobile",
+	"Atom",
+	NULL,
+	NULL,
+	NULL,
+	NULL,			/* 0x2F */
+	"Alpha",
+	"Alpha 21064",
+	"Alpha 21066",
+	"Alpha 21164",
+	"Alpha 21164PC",
+	"Alpha 21164a",
+	"Alpha 21264",
+	"Alpha 21364",
+	NULL,			/* 0x38 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,			/* 0x3F */
+	"MIPS",
+	"MIPS R4000",
+	"MIPS R4200",
+	"MIPS R4400",
+	"MIPS R4600",
+	"MIPS R10000",
+	NULL,			/* 0x46 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,			/* 0x4F */
+	"SPARC",
+	"SuperSPARC",
+	"MicroSPARC II",
+	"MicroSPARC IIep",
+	"UltraSPARC",
+	"UltraSPARC II",
+	"UltraSPARC IIi",
+	"UltraSPARC III",
+	"UltraSPARC IIIi",
+	NULL,			/* 0x59 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,			/* 0x5F */
+	"68040",
+	"68xxx",
+	"68000",
+	"68010",
+	"68020",
+	"68030",
+	NULL,			/* 0x66 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,			/* 0x6F */
+	"Hobbit",
+	NULL,			/* 0x71 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,			/* 0x77 */
+	"Crusoe TM5000",
+	"Crusoe TM3000",
+	"Efficeon TM8000",
+	NULL,			/* 0x7B */
+	NULL,
+	NULL,
+	NULL,
+	NULL,			/* 0x7F */
+	"Weitek",
+	NULL,			/* 0x81 */
+	"Itanium",
+	"Athlon 64",
+	"Opteron",
+	"Sempron",
+	"Turion 64",		/* 0x86 */
+	"Dual-Core Opteron",
+	"Atlhon 64 X2",
+	"Turion 64 X2",
+	"Quad-Core Opteron",
+	"Third-Generation Opteron",
+	"Phenom FX",
+	"Phenom X4",
+	"Phenom X2",
+	"Athlon X2",		/* 0x8F */
+	"PA-RISC",
+	"PA-RISC 8500",
+	"PA-RISC 8000",
+	"PA-RISC 7300LC",
+	"PA-RISC 7200",
+	"PA-RISC 7100LC",
+	"PA-RISC 7100",
+	NULL,			/* 0x97 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,			/* 0x9F */
+	"V30",
+	"Quad-Core Xeon 3200",	/* 0xA1 */
+	"Dual-Core Xeon 3000",
+	"Quad-Core Xeon 5300",
+	"Dual-Core Xeon 5100",
+	"Dual-Core Xeon 5000",
+	"Dual-Core Xeon LV",
+	"Dual-Core Xeon ULV",
+	"Dual-Core Xeon 7100",
+	"Quad-Core Xeon 5400",
+	"Quad-Core Xeon",	/* 0xAA */
+	"Dual-Core Xeon 5200",
+	"Dual-Core Xeon 7200",
+	"Quad-Core Xeon 7300",
+	"Quad-Core Xeon 7400",
+	"Multi-Core Xeon 7400",			/* 0xAF */
+	"Pentium III Xeon",
+	"Pentium III Speedstep",
+	"Pentium 4",
+	"Xeon",
+	"AS400",
+	"Xeon MP",
+	"Athlon XP",
+	"Athlon MP",
+	"Itanium 2",
+	"Pentium M",
+	"Celeron D",		/* 0xBA */
+	"Pentium D",
+	"Pentium EE",
+	"Core Solo",		/* 0xBD */
+	NULL,
+	"Core 2 Duo",
+	"Core 2 Solo",
+	"Core 2 Extreme",
+	"Core 2 Quad",
+	"Core 2 Extreme Mobile",
+	"Core 2 Duo Mobile",
+	"Core 2 Solo Mobile",
+	"Core i7",
+	"Dual-Core Celeron",		/* 0xC7 */
+	"IBM390",
+	"G4",
+	"G5",
+	"ESA/390 G6",		/* 0xCB */
+	"z/Architectur",
+	NULL,
+	NULL,
+	NULL,
+	NULL,			/*0xD0 */
+	NULL,
+	"C7-M",
+	"C7-D",
+	"C7",
+	"Eden",
+	"Multi-Core Xeon",			/*0xD6 */
+	"Dual-Core Xeon 3xxx",
+	"Quad-Core Xeon 3xxx",  /*0xD8 */
+	NULL,
+	"Dual-Core Xeon 5xxx", /*0xDA */
+	"Quad-Core Xeon 5xxx",
+	NULL,
+	"Dual-Core Xeon 7xxx", /*0xDD */
+	"Quad-Core Xeon 7xxx",
+	"Multi-Core Xeon 7xxx",
+	NULL,			/*0xE0 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	"Embedded Opteron Quad-Core",	/* 0xE6 */
+	"Phenom Triple-Core",
+	"Turion Ultra Dual-Core Mobile",
+	"Turion Dual-Core Mobile",
+	"Athlon Dual-Core",
+	"Sempron SI",		/*0xEB */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,			/* 0xF9 */
+	"i860",
+	"i960",
+	NULL,			/* 0xFC */
+	NULL,
+	NULL,
+	NULL,			/* 0xFF */
+    };
+    /* Special case for ambiguous value 0xBE */
+    if (code == 0xBE) {
+	/* Best bet based on manufacturer string */
+	if (strstr(manufacturer, "Intel") != NULL
+	    || strncasecmp(manufacturer, "Intel", 5) == 0)
+	    return "Core 2";
+	if (strstr(manufacturer, "AMD") != NULL
+	    || strncasecmp(manufacturer, "AMD", 3) == 0)
+	    return "K7";
+	return "Core 2 or K7";
+    }
+
+    if (family[code] != NULL) {
+	return family[code];
+    }
+    return out_of_spec;
+}
+
+const char *dmi_processor_status(uint8_t code)
+{
+    static const char *status[] = {
+	"Unknown",		/* 0x00 */
+	"Enabled",
+	"Disabled By User",
+	"Disabled By BIOS",
+	"Idle",			/* 0x04 */
+	"<OUT OF SPEC>",
+	"<OUT OF SPEC>",
+	"Other"			/* 0x07 */
+    };
+
+    if (code <= 0x04)
+	return status[code];
+    if (code == 0x07)
+	return status[0x05];
+    return out_of_spec;
+}
+
+const char *dmi_processor_upgrade(uint8_t code)
+{
+    /* 3.3.5.5 */
+    static const char *upgrade[] = {
+	"Other",		/* 0x01 */
+	"Unknown",
+	"Daughter Board",
+	"ZIF Socket",
+	"Replaceable Piggy Back",
+	"None",
+	"LIF Socket",
+	"Slot 1",
+	"Slot 2",
+	"370-pin Socket",
+	"Slot A",
+	"Slot M",
+	"Socket 423",
+	"Socket A (Socket 462)",
+	"Socket 478",
+	"Socket 754",
+	"Socket 940",
+	"Socket 939"		/* 0x12 */
+	"Socket mPGA604",
+	"Socket LGA771",
+	"Socket LGA775",
+	"Socket S1",
+	"Socket AM2",
+	"Socket F (1207)"
+	"Socket LGA1366"	/* 0x19 */
+    };
+
+    if (code >= 0x01 && code <= 0x19)
+	return upgrade[code - 0x01];
+    return out_of_spec;
+}
+
+void dmi_processor_cache(uint16_t code, const char *level, uint16_t ver,
+			 char *cache)
+{
+    if (code == 0xFFFF) {
+	if (ver >= 0x0203)
+	    sprintf(cache, "Not Provided");
+	else
+	    sprintf(cache, "No %s Cache", level);
+    } else
+	sprintf(cache, "0x%04X", code);
+}
+
+/* Intel AP-485 revision 28, table 5 */
+const char *cpu_flags_strings[PROCESSOR_FLAGS_ELEMENTS] = {
+    "FPU (Floating-point unit on-chip)",	/* 0 */
+    "VME (Virtual mode extension)",
+    "DE (Debugging extension)",
+    "PSE (Page size extension)",
+    "TSC (Time stamp counter)",
+    "MSR (Model specific registers)",
+    "PAE (Physical address extension)",
+    "MCE (Machine check exception)",
+    "CX8 (CMPXCHG8 instruction supported)",
+    "APIC (On-chip APIC hardware supported)",
+    NULL,			/* 10 */
+    "SEP (Fast system call)",
+    "MTRR (Memory type range registers)",
+    "PGE (Page global enable)",
+    "MCA (Machine check architecture)",
+    "CMOV (Conditional move instruction supported)",
+    "PAT (Page attribute table)",
+    "PSE-36 (36-bit page size extension)",
+    "PSN (Processor serial number present and enabled)",
+    "CLFSH (CLFLUSH instruction supported)",
+    NULL,			/* 20 */
+    "DS (Debug store)",
+    "ACPI (ACPI supported)",
+    "MMX (MMX technology supported)",
+    "FXSR (Fast floating-point save and restore)",
+    "SSE (Streaming SIMD extensions)",
+    "SSE2 (Streaming SIMD extensions 2)",
+    "SS (Self-snoop)",
+    "HTT (Hyper-threading technology)",
+    "TM (Thermal monitor supported)",
+    "IA64 (IA64 capabilities)",	/* 30 */
+    "PBE (Pending break enabled)"	/* 31 */
+};
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/memory.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/memory.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/memory.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,452 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer
+ *
+ *   Some parts borrowed from meminfo.c32:
+ *
+ *   Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   Some parts borrowed from Linux:
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ *   Interrupt list from Ralf Brown (http://www.cs.cmu.edu/~ralf/files.html)
+ *
+ *   This file is part of Syslinux, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdint.h>
+#include <com32.h>
+#include <string.h>
+#include <memory.h>
+
+const char *const e820_types[] = {
+    "usable",
+    "reserved",
+    "ACPI reclaim",
+    "ACPI NVS",
+    "unusable",
+};
+
+struct e820_ext_entry {
+    struct e820entry std;
+    uint32_t ext_flags;
+} __attribute__ ((packed));
+
+#define SMAP	0x534d4150	/* ASCII "SMAP" */
+
+void get_type(int type, char *type_ptr, int type_ptr_sz)
+{
+    unsigned int real_type = type - 1;
+    if (real_type < sizeof(e820_types) / sizeof(e820_types[0]))
+	strlcpy(type_ptr, e820_types[real_type], type_ptr_sz);
+}
+
+/**
+ *INT 15 - newer BIOSes - GET SYSTEM MEMORY MAP
+ *	AX = E820h
+ *	EAX = 0000E820h
+ *	EDX = 534D4150h ('SMAP')
+ *	EBX = continuation value or 00000000h to start at beginning of map
+ *	ECX = size of buffer for result, in bytes (should be >= 20 bytes)
+ *	ES:DI -> buffer for result (see #00581)
+ *
+ * Return: CF clear if successful
+ *	    EAX = 534D4150h ('SMAP')
+ *	    ES:DI buffer filled
+ *	    EBX = next offset from which to copy or 00000000h if all done
+ *	    ECX = actual length returned in bytes
+ *	CF set on error
+ *	    AH = error code (86h) (see #00496 at INT 15/AH=80h)
+ *
+ * Notes: originally introduced with the Phoenix BIOS v4.0, this function is
+ *	  now supported by most newer BIOSes, since various versions of Windows
+ *	  call it to find out about the system memory
+ *	a maximum of 20 bytes will be transferred at one time, even if ECX is
+ *	  higher; some BIOSes (e.g. Award Modular BIOS v4.50PG) ignore the
+ *	  value of ECX on entry, and always copy 20 bytes
+ *	some BIOSes expect the high word of EAX to be clear on entry, i.e.
+ *	  EAX=0000E820h
+ *	if this function is not supported, an application should fall back
+ *	  to AX=E802h, AX=E801h, and then AH=88h
+ *	the BIOS is permitted to return a nonzero continuation value in EBX
+ *	  and indicate that the end of the list has already been reached by
+ *	  returning with CF set on the next iteration
+ *	this function will return base memory and ISA/PCI memory contiguous
+ *	  with base memory as normal memory ranges; it will indicate
+ *	  chipset-defined address holes which are not in use and motherboard
+ *	  memory-mapped devices, and all occurrences of the system BIOS as
+ *	  reserved; standard PC address ranges will not be reported
+ **/
+void detect_memory_e820(struct e820entry *desc, int size_map, int *size_found)
+{
+    int count = 0;
+    static struct e820_ext_entry buf;	/* static so it is zeroed */
+    void *bounce;
+
+    com32sys_t ireg, oreg;
+    memset(&ireg, 0, sizeof ireg);
+
+    bounce = lmalloc(sizeof buf);
+    if (!bounce)
+	goto out;
+
+    ireg.eax.w[0] = 0xe820;
+    ireg.edx.l = SMAP;
+    ireg.ecx.l = sizeof(struct e820_ext_entry);
+    ireg.edi.w[0] = OFFS(bounce);
+    ireg.es = SEG(bounce);
+
+    /*
+     * Set this here so that if the BIOS doesn't change this field
+     * but still doesn't change %ecx, we're still okay...
+     */
+    memset(&buf, 0, sizeof buf);
+    buf.ext_flags = 1;
+
+    do {
+	memcpy(bounce, &buf, sizeof buf);
+
+	/* Important: %edx and %esi are clobbered by some BIOSes,
+	   so they must be either used for the error output
+	   or explicitly marked clobbered.  Given that, assume there
+	   is something out there clobbering %ebp and %edi, too. */
+	__intcall(0x15, &ireg, &oreg);
+
+	/* Some BIOSes stop returning SMAP in the middle of
+	   the search loop.  We don't know exactly how the BIOS
+	   screwed up the map at that point, we might have a
+	   partial map, the full map, or complete garbage, so
+	   just return failure. */
+	if (oreg.eax.l != SMAP) {
+	    count = 0;
+	    break;
+	}
+
+	if (oreg.eflags.l & EFLAGS_CF || oreg.ecx.l < 20)
+	    break;
+
+	memcpy(&buf, bounce, sizeof buf);
+
+	/*
+	 * ACPI 3.0 added the extended flags support.  If bit 0
+	 * in the extended flags is zero, we're supposed to simply
+	 * ignore the entry -- a backwards incompatible change!
+	 */
+	if (oreg.ecx.l > 20 && !(buf.ext_flags & 1))
+	    continue;
+
+	memcpy(&desc[count], &buf, sizeof buf);
+	count++;
+
+	/* Set continuation value */
+	ireg.ebx.l = oreg.ebx.l;
+    } while (ireg.ebx.l && count < size_map);
+
+out:
+    lfree(bounce);
+    *size_found = count;
+}
+
+/**
+ * detect_memory_e801
+ *
+ *INT 15 - Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS
+ *	AX = E801h
+ *
+ * Return: CF clear if successful
+ *	    AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB)
+ *	    BX = extended memory above 16M, in 64K blocks
+ *	    CX = configured memory 1M to 16M, in K
+ *	    DX = configured memory above 16M, in 64K blocks
+ *	CF set on error
+ *
+ * Notes: supported by the A03 level (6/14/94) and later XPS P90 BIOSes, as well
+ *	as the Compaq Contura, 3/8/93 DESKPRO/i, and 7/26/93 LTE Lite 386 ROM
+ *	BIOS
+ *	supported by AMI BIOSes dated 8/23/94 or later
+ *	on some systems, the BIOS returns AX=BX=0000h; in this case, use CX
+ *	  and DX instead of AX and BX
+ *	this interface is used by Windows NT 3.1, OS/2 v2.11/2.20, and is
+ *	  used as a fall-back by newer versions if AX=E820h is not supported
+ *	this function is not used by MS-DOS 6.0 HIMEM.SYS when an EISA machine
+ *	  (for example with parameter /EISA) (see also MEM F000h:FFD9h), or no
+ *	  Compaq machine was detected, or parameter /NOABOVE16 was given.
+ **/
+int detect_memory_e801(int *mem_size_below_16, int *mem_size_above_16)
+{
+    com32sys_t ireg, oreg;
+    memset(&ireg, 0, sizeof ireg);
+
+    ireg.eax.w[0] = 0xe801;
+
+    __intcall(0x15, &ireg, &oreg);
+
+    if (oreg.eflags.l & EFLAGS_CF)
+	return -1;
+
+    if (oreg.eax.w[0] > 0x3c00)
+	return -1;		/* Bogus! */
+
+    /* Linux seems to use ecx and edx by default if they are defined */
+    if (oreg.eax.w[0] || oreg.eax.w[0]) {
+	oreg.eax.w[0] = oreg.ecx.w[0];
+	oreg.ebx.w[0] = oreg.edx.w[0];
+    }
+
+    *mem_size_below_16 = oreg.eax.w[0];	/* 1K blocks */
+    *mem_size_above_16 = oreg.ebx.w[0];	/* 64K blocks */
+
+    return 0;
+}
+
+int detect_memory_88(int *mem_size)
+{
+    com32sys_t ireg, oreg;
+    memset(&ireg, 0, sizeof ireg);
+
+    ireg.eax.w[0] = 0x8800;
+
+    __intcall(0x15, &ireg, &oreg);
+
+    if (oreg.eflags.l & EFLAGS_CF)
+	return -1;
+
+    *mem_size = oreg.eax.w[0];
+    return 0;
+}
+
+/*
+ * Sanitize the BIOS e820 map.
+ *
+ * This code come from the memtest86 project. It have been adjusted to match
+ * the syslinux environement.
+ * Some e820 responses include overlapping entries.  The following 
+ * replaces the original e820 map with a new one, removing overlaps.
+ * 
+ * The following stuff could be merge once the addr_t will be set to 64bits.
+ * syslinux_scan_memory can be used for that purpose 
+ */
+int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_bios,
+		      short old_nr)
+{
+    struct change_member {
+	struct e820entry *pbios;	/* pointer to original bios entry */
+	unsigned long long addr;	/* address for this change point */
+    };
+    struct change_member change_point_list[2 * E820MAX];
+    struct change_member *change_point[2 * E820MAX];
+    struct e820entry *overlap_list[E820MAX];
+    struct e820entry biosmap[E820MAX];
+    struct change_member *change_tmp;
+    unsigned long current_type, last_type;
+    unsigned long long last_addr;
+    int chgidx, still_changing;
+    int overlap_entries;
+    int new_bios_entry;
+    int i;
+
+    /*
+       Visually we're performing the following (1,2,3,4 = memory types)...
+       Sample memory map (w/overlaps):
+       ____22__________________
+       ______________________4_
+       ____1111________________
+       _44_____________________
+       11111111________________
+       ____________________33__
+       ___________44___________
+       __________33333_________
+       ______________22________
+       ___________________2222_
+       _________111111111______
+       _____________________11_
+       _________________4______
+
+       Sanitized equivalent (no overlap):
+       1_______________________
+       _44_____________________
+       ___1____________________
+       ____22__________________
+       ______11________________
+       _________1______________
+       __________3_____________
+       ___________44___________
+       _____________33_________
+       _______________2________
+       ________________1_______
+       _________________4______
+       ___________________2____
+       ____________________33__
+       ______________________4_
+     */
+    /* First make a copy of the map */
+    for (i = 0; i < old_nr; i++) {
+	biosmap[i].addr = orig_map[i].addr;
+	biosmap[i].size = orig_map[i].size;
+	biosmap[i].type = orig_map[i].type;
+    }
+
+    /* bail out if we find any unreasonable addresses in bios map */
+    for (i = 0; i < old_nr; i++) {
+	if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
+	    return 0;
+    }
+
+    /* create pointers for initial change-point information (for sorting) */
+    for (i = 0; i < 2 * old_nr; i++)
+	change_point[i] = &change_point_list[i];
+
+    /* record all known change-points (starting and ending addresses) */
+    chgidx = 0;
+    for (i = 0; i < old_nr; i++) {
+	change_point[chgidx]->addr = biosmap[i].addr;
+	change_point[chgidx++]->pbios = &biosmap[i];
+	change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
+	change_point[chgidx++]->pbios = &biosmap[i];
+    }
+
+    /* sort change-point list by memory addresses (low -> high) */
+    still_changing = 1;
+    while (still_changing) {
+	still_changing = 0;
+	for (i = 1; i < 2 * old_nr; i++) {
+	    /* if <current_addr> > <last_addr>, swap */
+	    /* or, if current=<start_addr> & last=<end_addr>, swap */
+	    if ((change_point[i]->addr < change_point[i - 1]->addr) ||
+		((change_point[i]->addr == change_point[i - 1]->addr) &&
+		 (change_point[i]->addr == change_point[i]->pbios->addr) &&
+		 (change_point[i - 1]->addr !=
+		  change_point[i - 1]->pbios->addr))
+		) {
+		change_tmp = change_point[i];
+		change_point[i] = change_point[i - 1];
+		change_point[i - 1] = change_tmp;
+		still_changing = 1;
+	    }
+	}
+    }
+
+    /* create a new bios memory map, removing overlaps */
+    overlap_entries = 0;	/* number of entries in the overlap table */
+    new_bios_entry = 0;		/* index for creating new bios map entries */
+    last_type = 0;		/* start with undefined memory type */
+    last_addr = 0;		/* start with 0 as last starting address */
+    /* loop through change-points, determining affect on the new bios map */
+    for (chgidx = 0; chgidx < 2 * old_nr; chgidx++) {
+	/* keep track of all overlapping bios entries */
+	if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr) {
+	    /* add map entry to overlap list (> 1 entry implies an overlap) */
+	    overlap_list[overlap_entries++] = change_point[chgidx]->pbios;
+	} else {
+	    /* remove entry from list (order independent, so swap with last) */
+	    for (i = 0; i < overlap_entries; i++) {
+		if (overlap_list[i] == change_point[chgidx]->pbios)
+		    overlap_list[i] = overlap_list[overlap_entries - 1];
+	    }
+	    overlap_entries--;
+	}
+	/* if there are overlapping entries, decide which "type" to use */
+	/* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
+	current_type = 0;
+	for (i = 0; i < overlap_entries; i++)
+	    if (overlap_list[i]->type > current_type)
+		current_type = overlap_list[i]->type;
+	/* continue building up new bios map based on this information */
+	if (current_type != last_type) {
+	    if (last_type != 0) {
+		new_bios[new_bios_entry].size =
+		    change_point[chgidx]->addr - last_addr;
+		/* move forward only if the new size was non-zero */
+		if (new_bios[new_bios_entry].size != 0)
+		    if (++new_bios_entry >= E820MAX)
+			break;	/* no more space left for new bios entries */
+	    }
+	    if (current_type != 0) {
+		new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
+		new_bios[new_bios_entry].type = current_type;
+		last_addr = change_point[chgidx]->addr;
+	    }
+	    last_type = current_type;
+	}
+    }
+    return (new_bios_entry);
+}
+
+/* The following stuff could be merge once the addr_t will be set to 64bits.
+ * syslinux_scan_memory can be used for that purpose */
+unsigned long detect_memsize(void)
+{
+    unsigned long memory_size = 0;
+
+    /* Try to detect memory via e820 */
+    struct e820entry map[E820MAX];
+    int count = 0;
+    detect_memory_e820(map, E820MAX, &count);
+    memory_size = memsize_e820(map, count);
+    if (memory_size > 0)
+	return memory_size;
+
+    /*e820 failed, let's try e801 */
+    int mem_low, mem_high = 0;
+    if (!detect_memory_e801(&mem_low, &mem_high))
+	return mem_low + (mem_high << 6);
+
+    /*e801 failed, let's try e88 */
+    int mem_size = 0;
+    if (!detect_memory_88(&mem_size))
+	return mem_size;
+
+    /* We were enable to detect any kind of memory */
+    return 0;
+}
+
+/* The following stuff could be merge once the addr_t will be set to 64bits.
+ * syslinux_scan_memory can be used for that purpose */
+unsigned long memsize_e820(struct e820entry *e820, int e820_nr)
+{
+    int i, n, nr;
+    unsigned long memory_size = 0;
+    struct e820entry nm[E820MAX];
+
+    /* Clean up, adjust and copy the BIOS-supplied E820-map. */
+    nr = sanitize_e820_map(e820, nm, e820_nr);
+
+    /* If there is not a good 820 map returning 0 to indicate 
+       that we don't have any idea of the amount of ram we have */
+    if (nr < 1 || nr > E820MAX) {
+	return 0;
+    }
+
+    /* Build the memory map for testing */
+    n = 0;
+    for (i = 0; i < nr; i++) {
+	if (nm[i].type == E820_RAM || nm[i].type == E820_ACPI) {
+	    unsigned long long start;
+	    unsigned long long end;
+	    start = nm[i].addr;
+	    end = start + nm[i].size;
+
+	    /* Don't ever use memory between 640 and 1024k */
+	    if (start > RES_START && start < RES_END) {
+		if (end < RES_END) {
+		    continue;
+		}
+		start = RES_END;
+	    }
+	    if (end > RES_START && end < RES_END) {
+		end = RES_START;
+	    }
+	    memory_size += (end >> 12) - ((start + 4095) >> 12);
+	    n++;
+	} else if (nm[i].type == E820_NVS) {
+	    memory_size += nm[i].size >> 12;
+	}
+    }
+    return memory_size * 4;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/vpd/vpd.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/vpd/vpd.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/vpd/vpd.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,103 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2006 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include "vpd/vpd.h"
+
+int vpd_checksum(char *buf, int len)
+{
+    uint8_t sum = 0;
+    int a;
+
+    for (a = 0; a < len; a++)
+	sum += buf[a];
+    return (sum == 0);
+}
+
+int vpd_decode(s_vpd * vpd)
+{
+    uint8_t buf[16];
+    char *p, *q;
+
+    /* Cleaning structures */
+    memset(&vpd->base_address, 0, sizeof(vpd->base_address));
+    memset(&vpd->bios_build_id, 0, sizeof(vpd->bios_build_id));
+    memset(&vpd->box_serial_number, 0, sizeof(vpd->box_serial_number));
+    memset(&vpd->motherboard_serial_number, 0,
+	   sizeof(vpd->motherboard_serial_number));
+    memset(&vpd->machine_type_model, 0, sizeof(vpd->machine_type_model));
+    memset(&vpd->bios_release_date, 0, sizeof(vpd->bios_release_date));
+    memset(&vpd->default_flash_filename, 0,
+	   sizeof(vpd->default_flash_filename));
+    memset(&vpd->bios_version, 0, sizeof(vpd->bios_version));
+
+    /* Until we found elements in the vpdtable, we consider them as not filled */
+    vpd->filled = false;
+
+    p = (char *)0xF0000;	/* The start address to look at the dmi table */
+    for (q = p; q < p + 0x10000; q += 4) {
+	memcpy(buf, q, 5);
+	if (memcmp(buf, "\252\125VPD", 5) == 0) {
+	    snprintf(vpd->base_address, sizeof(vpd->base_address), "%p", q);
+	    if (q[5] < 0x30)
+		return -ENOVPDTABLE;
+
+	    vpd->filled = true;
+	    /* XSeries have longer records, exact length seems to vary. */
+	    if (!(q[5] >= 0x45 && vpd_checksum(q, q[5]))
+		/* Some Netvista seem to work with this. */
+		&& !(vpd_checksum(q, 0x30))
+		/* The Thinkpad/Thinkcentre checksum does *not* include the first 13 bytes. */
+		&& !(vpd_checksum(q + 0x0D, 0x30 - 0x0D))) {
+		/* A few systems have a bad checksum (xSeries 325, 330, 335
+		   and 345 with early BIOS) but the record is otherwise
+		   valid. */
+		printf("VPD: Bad checksum!\n");
+	    }
+
+	    strlcpy(vpd->bios_build_id, q + 0x0D, 9);
+	    strlcpy(vpd->box_serial_number, q + 0x16, 7);
+	    strlcpy(vpd->motherboard_serial_number, q + 0x1D, 11);
+	    strlcpy(vpd->machine_type_model, q + 0x28, 7);
+
+	    if (q[5] < 0x44)
+		return VPD_TABLE_PRESENT;
+
+	    strlcpy(vpd->bios_release_date, q + 0x30, 8);
+	    strlcpy(vpd->default_flash_filename, q + 0x38, 12);
+
+	    if (q[5] >= 0x46 && q[0x44] != 0x00) {
+		strlcpy(vpd->bios_version, q + 0x44, 255);
+	    }
+
+	    return VPD_TABLE_PRESENT;
+	}
+    }
+    return -ENOVPDTABLE;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_create.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_create.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_create.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,240 @@
+/* JSON Create ZZJSON structures
+ * ZZJSON - Copyright (C) 2008 by Ivo van Poorten
+ * License: GNU Lesser General Public License version 2.1
+ */
+
+#include "zzjson.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef CONFIG_NO_ERROR_MESSAGES
+#define ERROR(x...)
+#else
+#define ERROR(x...)     config->error(config->ehandle, ##x)
+#endif
+#define MEMERROR()      ERROR("out of memory")
+
+static ZZJSON *zzjson_create_templ(ZZJSON_CONFIG *config, ZZJSON_TYPE type) {
+    ZZJSON *zzjson = config->calloc(1, sizeof(ZZJSON));
+    if (!zzjson) MEMERROR();
+    else         zzjson->type = type;
+    return zzjson;
+}
+
+ZZJSON *zzjson_create_true(ZZJSON_CONFIG *config) {
+    return zzjson_create_templ(config, ZZJSON_TRUE);
+}
+
+ZZJSON *zzjson_create_false(ZZJSON_CONFIG *config) {
+    return zzjson_create_templ(config, ZZJSON_FALSE);
+}
+
+ZZJSON *zzjson_create_null(ZZJSON_CONFIG *config) {
+    return zzjson_create_templ(config, ZZJSON_NULL);
+}
+
+ZZJSON *zzjson_create_number_d(ZZJSON_CONFIG *config, double d) {
+    ZZJSON *zzjson = zzjson_create_templ(config, ZZJSON_NUMBER_DOUBLE);
+    if (zzjson)
+        zzjson->value.number.val.dval = d;
+    return zzjson;
+}
+
+ZZJSON *zzjson_create_number_i(ZZJSON_CONFIG *config, long long i) {
+    ZZJSON *zzjson = zzjson_create_templ(config, ZZJSON_NUMBER_NEGINT);
+    if (zzjson) {
+        zzjson->type = i<0LL ? ZZJSON_NUMBER_NEGINT : ZZJSON_NUMBER_POSINT;
+        zzjson->value.number.val.ival = llabs(i);
+    }
+    return zzjson;
+}
+
+/* sdup mimics strdup, but avoids having another function pointer in config */
+static char *sdup(ZZJSON_CONFIG *config, char *s) {
+    size_t slen = strlen(s)+1;
+    char *scopy = config->malloc(slen);
+
+    if (!scopy) MEMERROR();
+    else        memcpy(scopy, s, slen);
+    return scopy;
+}
+
+ZZJSON *zzjson_create_string(ZZJSON_CONFIG *config, char *s) {
+    ZZJSON *zzjson = NULL;
+    char *scopy;
+        
+    if (!(scopy = sdup(config,s))) return zzjson;
+
+    if ((zzjson = zzjson_create_templ(config, ZZJSON_STRING)))
+        zzjson->value.string.string = scopy;
+    else
+        config->free(scopy);
+
+    return zzjson;
+}
+
+ZZJSON *zzjson_create_array(ZZJSON_CONFIG *config, ...) {
+    ZZJSON *zzjson, *retval, *val;
+    va_list ap;
+
+    if (!(zzjson = zzjson_create_templ(config, ZZJSON_ARRAY))) return zzjson;
+    retval = zzjson;
+
+    va_start(ap, config);
+    val = va_arg(ap, ZZJSON *);
+    while (val) {
+        zzjson->value.array.val = val;
+        val = va_arg(ap, ZZJSON *);
+
+        if (val) {
+            ZZJSON *next = zzjson_create_templ(config, ZZJSON_ARRAY);
+            if (!next) {
+                while (retval) {
+                    next = retval->next;
+                    config->free(retval);
+                    retval = next;
+                }
+                break;
+            }
+            zzjson->next = next;
+            zzjson = next;
+        }
+    }
+    va_end(ap);
+    return retval;
+}
+
+ZZJSON *zzjson_create_object(ZZJSON_CONFIG *config, ...) {
+    ZZJSON *zzjson, *retval, *val;
+    char *label, *labelcopy;
+    va_list ap;
+
+    if (!(zzjson = zzjson_create_templ(config, ZZJSON_OBJECT))) return zzjson;
+    retval = zzjson;
+
+    va_start(ap, config);
+    label = va_arg(ap, char *);
+    while (label) {
+        val = va_arg(ap, ZZJSON *);
+        labelcopy = sdup(config, label);
+
+        if (!labelcopy) {
+            zzjson_free(config, retval);
+            retval = NULL;
+            break;
+        }
+
+        zzjson->value.object.label  = labelcopy;
+        zzjson->value.object.val    = val;
+
+        label = va_arg(ap, char *);
+
+        if (label) {
+            ZZJSON *next = zzjson_create_templ(config, ZZJSON_OBJECT);
+            if (!next) {
+                while (retval) {
+                    next = retval->next;
+                    config->free(retval->value.object.label);
+                    config->free(retval);
+                    retval = next;
+                }
+                break;
+            }
+            zzjson->next = next;
+            zzjson = next;
+        }
+    }
+    va_end(ap);
+    return retval;
+}
+
+ZZJSON *zzjson_array_prepend(ZZJSON_CONFIG *config, ZZJSON *array,
+                                                    ZZJSON *val) {
+    ZZJSON *zzjson;
+
+    if (!array->value.array.val) { /* empty array */
+        array->value.array.val = val;
+        return array;
+    }
+
+    zzjson = zzjson_create_templ(config, ZZJSON_ARRAY);
+    if (zzjson) {
+        zzjson->value.array.val = val;
+        zzjson->next = array;
+    }
+    return zzjson;
+}
+
+ZZJSON *zzjson_array_append(ZZJSON_CONFIG *config, ZZJSON *array,
+                                                   ZZJSON *val) {
+    ZZJSON *retval = array, *zzjson;
+
+    if (!array->value.array.val) { /* empty array */
+        array->value.array.val = val;
+        return array;
+    }
+
+    zzjson = zzjson_create_templ(config, ZZJSON_ARRAY);
+    if (!zzjson) return NULL;
+
+    while (array->next) array = array->next;
+
+    zzjson->value.array.val = val;
+    array->next = zzjson;
+
+    return retval;
+}
+
+ZZJSON *zzjson_object_prepend(ZZJSON_CONFIG *config, ZZJSON *object,
+                              char *label, ZZJSON *val) {
+    ZZJSON *zzjson = NULL;
+    char *labelcopy = sdup(config, label);
+
+    if (!labelcopy) return zzjson;
+
+    if (!object->value.object.label) { /* empty object */
+        object->value.object.label  = labelcopy;
+        object->value.object.val    = val;
+        return object;
+    }
+
+    zzjson = zzjson_create_templ(config, ZZJSON_OBJECT);
+    if (zzjson) {
+        zzjson->value.object.label  = labelcopy;
+        zzjson->value.object.val    = val;
+        zzjson->next = object;
+    } else {
+        config->free(labelcopy);
+    }
+    return zzjson;
+}
+
+ZZJSON *zzjson_object_append(ZZJSON_CONFIG *config, ZZJSON *object,
+                             char *label, ZZJSON *val) {
+    ZZJSON *retval = object, *zzjson = NULL;
+    char *labelcopy = sdup(config, label);
+
+    if (!labelcopy) return zzjson;
+
+    if (!object->value.object.label) { /* empty object */
+        object->value.object.label  = labelcopy;
+        object->value.object.val    = val;
+        return object;
+    }
+
+    zzjson = zzjson_create_templ(config, ZZJSON_OBJECT);
+    if (!zzjson) {
+        config->free(labelcopy);
+        return NULL;
+    }
+
+    while (object->next) object = object->next;
+
+    zzjson->value.object.label  = labelcopy;
+    zzjson->value.object.val    = val;
+    object->next = zzjson;
+
+    return retval;
+}
+
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_free.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_free.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_free.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,29 @@
+/* JSON free
+ * ZZJSON - Copyright (C) 2008 by Ivo van Poorten
+ * License: GNU Lesser General Public License version 2.1
+ */
+
+#include "zzjson.h"
+
+void zzjson_free(ZZJSON_CONFIG *config, ZZJSON *zzjson) {
+    while (zzjson) {
+        ZZJSON *next;
+        switch(zzjson->type) {
+            case ZZJSON_OBJECT:
+                config->free(zzjson->value.object.label);
+                zzjson_free(config, zzjson->value.object.val);
+                break;
+            case ZZJSON_ARRAY:
+                zzjson_free(config, zzjson->value.array.val);
+                break;
+            case ZZJSON_STRING:
+                config->free(zzjson->value.string.string);
+                break;
+            default:
+                break;
+        }
+        next = zzjson->next;
+        config->free(zzjson);
+        zzjson = next;
+    }
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_parse.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_parse.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_parse.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,490 @@
+/* JSON Parser
+ * ZZJSON - Copyright (C) 2008-2009 by Ivo van Poorten
+ * License: GNU Lesser General Public License version 2.1
+ */
+
+#include "zzjson.h"
+#include <ctype.h>
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+
+#define GETC()          config->getchar(config->ihandle)
+#define UNGETC(c)       config->ungetchar(c, config->ihandle)
+#define SKIPWS()        skipws(config)
+#ifdef CONFIG_NO_ERROR_MESSAGES
+#define ERROR(x...)
+#else
+#define ERROR(x...)     config->error(config->ehandle, ##x)
+#endif
+#define MEMERROR()      ERROR("out of memory")
+
+#define ALLOW_EXTRA_COMMA    (config->strictness & ZZJSON_ALLOW_EXTRA_COMMA)
+#define ALLOW_ILLEGAL_ESCAPE (config->strictness & ZZJSON_ALLOW_ILLEGAL_ESCAPE)
+#define ALLOW_CONTROL_CHARS  (config->strictness & ZZJSON_ALLOW_CONTROL_CHARS)
+#define ALLOW_GARBAGE_AT_END (config->strictness & ZZJSON_ALLOW_GARBAGE_AT_END)
+#define ALLOW_COMMENTS       (config->strictness & ZZJSON_ALLOW_COMMENTS)
+
+static ZZJSON *parse_array(ZZJSON_CONFIG *config);
+static ZZJSON *parse_object(ZZJSON_CONFIG *config);
+
+static void skipws(ZZJSON_CONFIG *config) {
+    int d, c = GETC();
+morews:
+    while (isspace(c)) c = GETC();
+    if (!ALLOW_COMMENTS) goto endws;
+    if (c != '/') goto endws;
+    d = GETC();
+    if (d != '*') goto endws; /* pushing back c will generate a parse error */
+    c = GETC();
+morecomments:
+    while (c != '*') {
+        if (c == EOF) goto endws;
+        c = GETC();
+    }
+    c = GETC();
+    if (c != '/') goto morecomments;
+    c = GETC();
+    if (isspace(c) || c == '/') goto morews;
+endws:
+    UNGETC(c);
+}
+
+static char *parse_string(ZZJSON_CONFIG *config) {
+    unsigned int len = 16, pos = 0;
+    int c;
+    char *str = NULL;
+
+    SKIPWS();
+    c = GETC();
+    if (c != '"') {
+        ERROR("string: expected \" at the start");
+        return NULL;
+    }
+
+    str = config->malloc(len);
+    if (!str) {
+        MEMERROR();
+        return NULL;
+    }
+    c = GETC();
+    while (c > 0 && c != '"') {
+        if (!ALLOW_CONTROL_CHARS && c >= 0 && c <= 31) {
+            ERROR("string: control characters not allowed");
+            goto errout;
+        }
+        if (c == '\\') {
+            c = GETC();
+            switch (c) {
+                case 'b': c = '\b'; break;
+                case 'f': c = '\f'; break;
+                case 'n': c = '\n'; break;
+                case 'r': c = '\r'; break;
+                case 't': c = '\t'; break;
+                case 'u': {
+                    UNGETC(c);    /* ignore \uHHHH, copy verbatim */
+                    c = '\\';
+                    break;
+                }
+                case '\\': case '/': case '"':
+                          break;
+                default:
+                    if (!ALLOW_ILLEGAL_ESCAPE) {
+                        ERROR("string: illegal escape character");
+                        goto errout;
+                    }
+            }
+        }
+        str[pos++] = c;
+        if (pos == len-1) {
+            void *tmp = str;
+            len *= 2;
+            str = config->realloc(str, len);
+            if (!str) {
+                MEMERROR();
+                str = tmp;
+                goto errout;
+            }
+        }
+        c = GETC();
+    }
+    if (c != '"') {
+        ERROR("string: expected \" at the end");
+        goto errout;
+    }
+    str[pos] = 0;
+    return str;
+
+errout:
+    config->free(str);
+    return NULL;
+}
+
+static ZZJSON *parse_string2(ZZJSON_CONFIG *config) {
+    ZZJSON *zzjson = NULL;
+    char *str;
+
+    str = parse_string(config);
+    if (str) {
+        zzjson = config->calloc(1, sizeof(ZZJSON));
+        if (!zzjson) {
+            MEMERROR();
+            config->free(str);
+            return NULL;
+        }
+        zzjson->type = ZZJSON_STRING;
+        zzjson->value.string.string = str;
+    }
+    return zzjson;
+}
+
+static ZZJSON *parse_number(ZZJSON_CONFIG *config) {
+    ZZJSON *zzjson;
+    unsigned long long ival = 0, expo = 0;
+    double dval = 0.0, frac = 0.0, fracshft = 10.0;
+    int c, dbl = 0, sign = 1, signexpo = 1;
+
+    SKIPWS();
+    c = GETC();
+    if (c == '-') {
+        sign = -1;
+        c = GETC();
+    }
+    if (c == '0') {
+        c = GETC();
+        goto skip;
+    }
+
+    if (!isdigit(c)) {
+        ERROR("number: digit expected");
+        return NULL;
+    }
+
+    while (isdigit(c)) {
+        ival *= 10;
+        ival += c - '0';
+        c = GETC();
+    }
+
+skip:
+    if (c != '.') goto skipfrac;
+
+    dbl = 1;
+
+    c = GETC();
+    if (!isdigit(c)) {
+        ERROR("number: digit expected");
+        return NULL;
+    }
+
+    while (isdigit(c)) {
+        frac += (double)(c - '0') / fracshft;
+        fracshft *= 10.0;
+        c = GETC();
+    }
+
+skipfrac:
+    if (c != 'e' && c != 'E') goto skipexpo;
+
+    dbl = 1;
+
+    c = GETC();
+    if (c == '+')
+        c = GETC();
+    else if (c == '-') {
+        signexpo = -1;
+        c = GETC();
+    }
+
+    if (!isdigit(c)) {
+        ERROR("number: digit expected");
+        return NULL;
+    }
+
+    while (isdigit(c)) {
+        expo *= 10;
+        expo += c - '0';
+        c = GETC();
+    }
+
+skipexpo:
+    UNGETC(c);
+
+    if (dbl) {
+        dval = sign * (long long) ival;
+        dval += sign * frac;
+        dval *= pow(10.0, (double) signexpo * expo);
+    }
+
+    zzjson = config->calloc(1, sizeof(ZZJSON));
+    if (!zzjson) {
+        MEMERROR();
+        return NULL;
+    }
+    if (dbl) {
+        zzjson->type = ZZJSON_NUMBER_DOUBLE;
+        zzjson->value.number.val.dval = dval;
+    } else {
+        zzjson->type = sign < 0 ? ZZJSON_NUMBER_NEGINT : ZZJSON_NUMBER_POSINT;
+        zzjson->value.number.val.ival = ival;
+    }
+    
+    return zzjson;
+}
+
+static ZZJSON *parse_literal(ZZJSON_CONFIG *config, char *s, ZZJSON_TYPE t) {
+    char b[strlen(s)+1];
+    unsigned int i;
+
+    for (i=0; i<strlen(s); i++) b[i] = GETC();
+    b[i] = 0;
+
+    if (!strcmp(b,s)) {
+        ZZJSON *zzjson;
+        zzjson = config->calloc(1, sizeof(ZZJSON));
+        if (!zzjson) {
+            MEMERROR();
+            return NULL;
+        }
+        zzjson->type = t;
+        return zzjson;
+    }
+    ERROR("literal: expected %s", s);
+    return NULL;
+}
+
+static ZZJSON *parse_true(ZZJSON_CONFIG *config) {
+    return parse_literal(config, (char *)"true", ZZJSON_TRUE);
+}
+
+static ZZJSON *parse_false(ZZJSON_CONFIG *config) {
+    return parse_literal(config, (char *)"false", ZZJSON_FALSE);
+}
+
+static ZZJSON *parse_null(ZZJSON_CONFIG *config) {
+    return parse_literal(config, (char *)"null", ZZJSON_NULL);
+}
+
+static ZZJSON *parse_value(ZZJSON_CONFIG *config) {
+    ZZJSON *retval = NULL;
+    int c;
+
+    SKIPWS();
+    c = GETC();
+    UNGETC(c);
+    switch (c) {
+        case '"':   retval = parse_string2(config); break;
+        case '0': case '1': case '2': case '3': case '4': case '5':
+        case '6': case '7': case '8': case '9': case '-':
+                    retval = parse_number(config); break;
+        case '{':   retval = parse_object(config); break;
+        case '[':   retval = parse_array(config); break;
+        case 't':   retval = parse_true(config); break;
+        case 'f':   retval = parse_false(config); break;
+        case 'n':   retval = parse_null(config); break;
+    }
+
+    if (!retval) {
+        ERROR("value: invalid value");
+        return retval;
+    }
+
+    return retval;
+}
+
+static ZZJSON *parse_array(ZZJSON_CONFIG *config) {
+    ZZJSON *retval = NULL, **next = &retval;
+    int c;
+
+    SKIPWS();
+    c = GETC();
+    if (c != '[') {
+        ERROR("array: expected '['");
+        return NULL;
+    }
+
+    SKIPWS();
+    c = GETC();
+    while (c > 0 && c != ']') {
+        ZZJSON *zzjson = NULL, *val = NULL;
+
+        UNGETC(c);
+
+        SKIPWS();
+        val = parse_value(config);
+        if (!val) {
+            ERROR("array: value expected");
+            goto errout;
+        }
+
+        SKIPWS();
+        c = GETC();
+        if (c != ',' && c != ']') {
+            ERROR("array: expected ',' or ']'");
+errout_with_val:
+            zzjson_free(config, val);
+            goto errout;
+        }
+        if (c == ',') {
+            SKIPWS();
+            c = GETC();
+            if (c == ']' && !ALLOW_EXTRA_COMMA) {
+                ERROR("array: expected value after ','");
+                goto errout_with_val;
+            }
+        }
+        UNGETC(c);
+
+        zzjson = config->calloc(1, sizeof(ZZJSON));
+        if (!zzjson) {
+            MEMERROR();
+            zzjson_free(config, val);
+            goto errout_with_val;
+        }
+        zzjson->type            = ZZJSON_ARRAY;
+        zzjson->value.array.val = val;
+        *next = zzjson;
+        next = &zzjson->next;
+
+        c = GETC();
+    }
+
+    if (c != ']') {
+        ERROR("array: expected ']'");
+        goto errout;
+    }
+
+    if (!retval) {  /* empty array, [ ] */
+        retval = config->calloc(1, sizeof(ZZJSON));
+        if (!retval) {
+            MEMERROR();
+            return NULL;
+        }
+        retval->type = ZZJSON_ARRAY;
+    }
+            
+    return retval;
+
+errout:
+    zzjson_free(config, retval);
+    return NULL;
+}
+
+static ZZJSON *parse_object(ZZJSON_CONFIG *config) {
+    ZZJSON *retval = NULL;
+    int c;
+    ZZJSON **next = &retval;
+
+    SKIPWS();
+    c = GETC();
+    if (c != '{') {
+        ERROR("object: expected '{'");
+        return NULL;
+    }
+
+    SKIPWS();
+    c = GETC();
+    while (c > 0 && c != '}') {
+        ZZJSON *zzjson = NULL, *val = NULL;
+        char *str;
+
+        UNGETC(c);
+
+        str = parse_string(config);
+        if (!str) {
+            ERROR("object: expected string");
+errout_with_str:
+            config->free(str);
+            goto errout;
+        }
+
+        SKIPWS();
+        c = GETC();
+        if (c != ':') {
+            ERROR("object: expected ':'");
+            goto errout_with_str;
+        }
+
+        SKIPWS();
+        val = parse_value(config);
+        if (!val) {
+            ERROR("object: value expected");
+            goto errout_with_str;
+        }
+
+        SKIPWS();
+        c = GETC();
+        if (c != ',' && c != '}') {
+            ERROR("object: expected ',' or '}'");
+errout_with_str_and_val:
+            zzjson_free(config, val);
+            goto errout_with_str;
+        }
+        if (c == ',') {
+            SKIPWS();
+            c = GETC();
+            if (c == '}' && !ALLOW_EXTRA_COMMA) {
+                ERROR("object: expected pair after ','");
+                goto errout_with_str_and_val;
+            }
+        }
+        UNGETC(c);
+
+        zzjson = config->calloc(1, sizeof(ZZJSON));
+        if (!zzjson) {
+            MEMERROR();
+            goto errout_with_str_and_val;
+        }
+        zzjson->type                = ZZJSON_OBJECT;
+        zzjson->value.object.label  = str;
+        zzjson->value.object.val    = val;
+        *next = zzjson;
+        next = &zzjson->next;
+
+        c = GETC();
+    }
+
+    if (c != '}') {
+        ERROR("object: expected '}'");
+        goto errout;
+    }
+
+    if (!retval) {  /* empty object, { } */
+        retval = config->calloc(1, sizeof(ZZJSON));
+        if (!retval) {
+            MEMERROR();
+            return NULL;
+        }
+        retval->type = ZZJSON_OBJECT;
+    }
+            
+    return retval;
+
+errout:
+    zzjson_free(config, retval);
+    return NULL;
+}
+
+ZZJSON *zzjson_parse(ZZJSON_CONFIG *config) {
+    ZZJSON *retval;
+    int c;
+
+    SKIPWS();   
+    c = GETC();
+    UNGETC(c);
+    if (c == '[')       retval = parse_array(config);
+    else if (c == '{')  retval = parse_object(config);
+    else                { ERROR("expected '[' or '{'"); return NULL; }
+
+    if (!retval) return NULL;
+
+    SKIPWS();
+    c = GETC();
+    if (c >= 0 && !ALLOW_GARBAGE_AT_END) {
+        ERROR("parse: garbage at end of file");
+        zzjson_free(config, retval);
+        return NULL;
+    }
+
+    return retval;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_print.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_print.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_print.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,110 @@
+/* JSON Printer
+ * ZZJSON - Copyright (C) 2008 by Ivo van Poorten
+ * License: GNU Lesser General Public License version 2.1
+ */
+
+#include "zzjson.h"
+
+#define PRINT(fmt...) if (config->print(config->ohandle, ##fmt) < 0) return -1;
+//#define PUTC(c)       if (config->putchar(c, config->ohandle) < 0) return -1;
+#define PUTC(c)       PRINT("%c",c)
+#define INC 4
+
+static int print_string(ZZJSON_CONFIG *config, char *s) {
+    int c, bs;
+    if (!s) return 0;
+    while ((c = *s++)) {
+        bs = 1;
+        switch (c) {
+//            case '/':                 // useless escape of forward slash
+            case '\\':
+                if (*s == 'u') bs = 0;  // copy \uHHHH verbatim
+                break;
+            case '"':               break;
+            case '\b':  c = 'b';    break;
+            case '\f':  c = 'f';    break;
+            case '\n':  c = 'n';    break;
+            case '\r':  c = 'r';    break;
+            case '\t':  c = 't';    break;
+            default:    bs = 0;     break;
+        }
+        if (bs) PUTC('\\');
+        PUTC(c);
+    }
+    return 0;
+}
+
+static int zzjson_print2(ZZJSON_CONFIG *config, ZZJSON *zzjson,
+                 unsigned int indent, unsigned int objval) {
+    char c = 0, d = 0;
+    if (!zzjson) return -1;
+
+    switch(zzjson->type) {
+        case ZZJSON_OBJECT: c = '{'; d = '}'; break;
+        case ZZJSON_ARRAY:  c = '['; d = ']'; break;
+        default: break;
+    }
+
+    if (c) PRINT("%s%*s%c", indent ? "\n" : "", indent, "", c);
+
+    while (zzjson) {
+        switch(zzjson->type) {
+        case ZZJSON_OBJECT:
+            if (zzjson->value.object.val) {
+                PRINT("\n%*s\"", indent+INC, "");
+                if (print_string(config, zzjson->value.object.label) < 0)
+                    return -1;
+                PRINT("\" :");
+                if (zzjson_print2(config, zzjson->value.object.val,
+                                                indent+INC, 1) < 0) return -1;
+            }
+            break;
+        case ZZJSON_ARRAY:
+            if (zzjson->value.array.val)
+                if (zzjson_print2(config, zzjson->value.array.val,
+                                                indent+INC, 0) < 0) return -1;
+            break;
+        case ZZJSON_STRING:
+            PRINT(objval ? " \"" : "\n%*s\"", indent, "");
+            if (print_string(config, zzjson->value.string.string)<0) return -1;
+            PUTC('"');
+            break;
+        case ZZJSON_FALSE:
+            PRINT(objval ? " false" : "\n%*sfalse", indent, "");
+            break;
+        case ZZJSON_NULL:
+            PRINT(objval ? " null" : "\n%*snull", indent, "");
+            break;
+        case ZZJSON_TRUE:
+            PRINT(objval ? " true" : "\n%*strue", indent, "");
+            break;
+        case ZZJSON_NUMBER_NEGINT:
+        case ZZJSON_NUMBER_POSINT:
+        case ZZJSON_NUMBER_DOUBLE:
+            PRINT(objval ? " " : "\n%*s", indent, "");
+            if (zzjson->type == ZZJSON_NUMBER_DOUBLE) {
+                PRINT("%16.16e", zzjson->value.number.val.dval);
+            } else {
+                if (zzjson->type == ZZJSON_NUMBER_NEGINT) PUTC('-');
+                PRINT("%llu", zzjson->value.number.val.ival);
+            }
+        default:
+            break;
+        }
+        zzjson = zzjson->next;
+        if (zzjson) PUTC(',');
+    }
+
+    if (d) PRINT("\n%*s%c", indent, "", d);
+
+    return 0;
+}
+
+int zzjson_print(ZZJSON_CONFIG *config, ZZJSON *zzjson) {
+    int retval = zzjson_print2(config, zzjson, 0, 0);
+//    if (retval >= 0) retval = config->putchar('\n', config->ohandle);
+#ifndef CONFIG_NO_ERROR_MESSAGES
+    if (retval <  0) config->error(config->ehandle, "print: unable to print");
+#endif
+    return retval;
+}
Index: bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_query.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_query.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/com32/gpllib/zzjson/zzjson_query.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,63 @@
+/* JSON query
+ * ZZJSON - Copyright (C) 2008 by Ivo van Poorten
+ * License: GNU Lesser General Public License version 2.1
+ */
+
+#include "zzjson.h"
+#include <string.h>
+#include <stdarg.h>
+
+ZZJSON *zzjson_object_find_label(ZZJSON *zzjson, char *label) {
+    if (zzjson->type != ZZJSON_OBJECT) return NULL;
+
+    while (zzjson) {
+        char *string = zzjson->value.object.label;
+
+        if (zzjson->type != ZZJSON_OBJECT) return NULL;
+        if (!string)                       return NULL;
+
+        if (!strcmp(string, label))
+            return zzjson->value.object.val;
+        zzjson = zzjson->next;
+    }
+    return NULL;
+}
+
+ZZJSON *zzjson_object_find_labels(ZZJSON *zzjson, ...) {
+    va_list ap;
+    char *lbl;
+
+    va_start(ap, zzjson);
+    lbl = va_arg(ap, char *);
+    while (lbl) {
+        zzjson = zzjson_object_find_label(zzjson, lbl);
+        if (!zzjson) break;
+        lbl = va_arg(ap, char *);
+    }
+    va_end(ap);
+
+    return zzjson;
+}
+
+unsigned int zzjson_object_count(ZZJSON *zzjson) {
+    unsigned int count = 1;
+
+    if (zzjson->type != ZZJSON_OBJECT) return 0;
+    if (!zzjson->value.object.label)   return 0; /* empty { } */
+
+    while ((zzjson = zzjson->next)) count++;
+
+    return count;
+}
+
+unsigned int zzjson_array_count(ZZJSON *zzjson) {
+    unsigned int count = 1;
+
+    if (zzjson->type != ZZJSON_ARRAY) return 0;
+    if (!zzjson->value.array.val)     return 0; /* empty [ ] */
+
+    while ((zzjson = zzjson->next)) count++;
+
+    return count;
+}
+
