summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--com32/include/string.h1
-rw-r--r--com32/lib/Makefile5
-rw-r--r--com32/lib/stpcpy.c23
-rw-r--r--com32/lib/syslinux/dsinfo.c47
-rw-r--r--com32/lib/syslinux/version.c46
-rw-r--r--com32/modules/Makefile3
-rw-r--r--com32/modules/sanboot.c140
7 files changed, 262 insertions, 3 deletions
diff --git a/com32/include/string.h b/com32/include/string.h
index 65923723..af9792b6 100644
--- a/com32/include/string.h
+++ b/com32/include/string.h
@@ -33,6 +33,7 @@ __extern char *strncat(char *, const char *, size_t);
__extern size_t strlcat(char *, const char *, size_t);
__extern int strncmp(const char *, const char *, size_t);
__extern char *strncpy(char *, const char *, size_t);
+__extern char *stpcpy(char *, const char *);
__extern char *stpncpy(char *, const char *, size_t);
__extern size_t strlcpy(char *, const char *, size_t);
__extern char *strpbrk(const char *, const char *);
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 6c08c221..adc36605 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -13,7 +13,8 @@ LIBOBJS = \
sprintf.o srand48.o sscanf.o stack.o strcasecmp.o strcat.o \
strchr.o strcmp.o strcpy.o strdup.o strerror.o strlen.o \
strnlen.o \
- strncasecmp.o strncat.o strncmp.o strncpy.o stpncpy.o strndup.o \
+ strncasecmp.o strncat.o strncmp.o strncpy.o strndup.o \
+ stpcpy.o stpncpy.o \
strntoimax.o strntoumax.o strrchr.o strsep.o strspn.o strstr.o \
strtoimax.o strtok.o strtol.o strtoll.o strtoul.o strtoull.o \
strtoumax.o vfprintf.o vprintf.o vsnprintf.o vsprintf.o \
@@ -72,7 +73,7 @@ LIBOBJS = \
\
syslinux/idle.o syslinux/reboot.o \
syslinux/features.o syslinux/config.o syslinux/serial.o \
- syslinux/ipappend.o \
+ syslinux/ipappend.o syslinux/dsinfo.o syslinux/version.o \
\
syslinux/addlist.o syslinux/freelist.o syslinux/memmap.o \
syslinux/movebits.o syslinux/shuffle.o syslinux/shuffle_pm.o \
diff --git a/com32/lib/stpcpy.c b/com32/lib/stpcpy.c
new file mode 100644
index 00000000..85fc49d3
--- /dev/null
+++ b/com32/lib/stpcpy.c
@@ -0,0 +1,23 @@
+/*
+ * stpcpy.c
+ *
+ * stpcpy()
+ */
+
+#include <string.h>
+
+char *stpcpy(char *dst, const char *src)
+{
+ char *q = dst;
+ const char *p = src;
+ char ch;
+
+ for (;;) {
+ *q = ch = *p++;
+ if ( !ch )
+ break;
+ q++;
+ }
+
+ return q;
+}
diff --git a/com32/lib/syslinux/dsinfo.c b/com32/lib/syslinux/dsinfo.c
new file mode 100644
index 00000000..6d77a0de
--- /dev/null
+++ b/com32/lib/syslinux/dsinfo.c
@@ -0,0 +1,47 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <syslinux/config.h>
+#include <klibc/compiler.h>
+#include <com32.h>
+
+union syslinux_derivative_info __syslinux_derivative_info;
+
+void __constructor __syslinux_get_derivative_info(void)
+{
+ static com32sys_t reg;
+
+ reg.eax.w[0] = 0x000A;
+ __intcall(0x22, &reg, &reg);
+
+ __syslinux_derivative_info.r.ax = reg.eax.w[0];
+ __syslinux_derivative_info.r.cx = reg.ecx.w[0];
+ __syslinux_derivative_info.r.dx = reg.edx.w[0];
+ __syslinux_derivative_info.r.esbx = MK_PTR(reg.es, reg.ebx.w[0]);
+ __syslinux_derivative_info.r.fssi = MK_PTR(reg.fs, reg.esi.w[0]);
+ __syslinux_derivative_info.r.gsdi = MK_PTR(reg.gs, reg.edi.w[0]);
+}
diff --git a/com32/lib/syslinux/version.c b/com32/lib/syslinux/version.c
new file mode 100644
index 00000000..2131fa04
--- /dev/null
+++ b/com32/lib/syslinux/version.c
@@ -0,0 +1,46 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <syslinux/config.h>
+#include <klibc/compiler.h>
+#include <com32.h>
+
+struct syslinux_version __syslinux_version;
+
+void __constructor __syslinux_get_version(void)
+{
+ static com32sys_t reg;
+
+ reg.eax.w[0] = 0x0001;
+ __intcall(0x22, &reg, &reg);
+
+ __syslinux_version.version = reg.ecx.w[0];
+ __syslinux_version.max_api = reg.eax.w[0];
+ __syslinux_version.filesystem = reg.edx.b[0];
+ __syslinux_version.version_string = MK_PTR(reg.es, reg.esi.w[0]);
+ __syslinux_version.copyright_string = MK_PTR(reg.es, reg.edi.w[0]);
+}
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index 8a127e62..8a8827e5 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -52,7 +52,8 @@ INCDIR = /usr/include
COM32DIR = $(AUXDIR)/com32
MODULES = chain.c32 ethersel.c32 mboot.c32 dmitest.c32 cpuidtest.c32 \
- pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 meminfo.c32
+ pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 meminfo.c32 \
+ sanboot.c32
TESTFILES =
all: $(MODULES) $(TESTFILES)
diff --git a/com32/modules/sanboot.c b/com32/modules/sanboot.c
new file mode 100644
index 00000000..b8bfe25e
--- /dev/null
+++ b/com32/modules/sanboot.c
@@ -0,0 +1,140 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston MA 02110-1301, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * sanboot.c
+ *
+ * Invoke the gPXE "sanboot" command, if available.
+ */
+
+#include <alloca.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <console.h>
+#include <com32.h>
+#include <stdbool.h>
+#include <string.h>
+#include <syslinux/config.h>
+
+struct segoff16 {
+ uint16_t offs, seg;
+};
+
+struct s_PXENV_FILE_CHECK_API {
+ uint16_t Status;
+ uint16_t Size;
+ uint32_t Magic;
+ uint32_t Provider;
+ uint32_t APIMask;
+ uint32_t Flags;
+};
+
+static bool is_gpxe(void)
+{
+ const struct syslinux_version *sv;
+ com32sys_t reg;
+ struct s_PXENV_FILE_CHECK_API *fca;
+
+ sv = syslinux_version();
+ if (sv->filesystem != SYSLINUX_FS_PXELINUX)
+ return false; /* Not PXELINUX */
+
+ fca = __com32.cs_bounce;
+ memset(fca, 0, sizeof *fca);
+ fca->Size = sizeof *fca;
+ fca->Magic = 0x91d447b2;
+
+ memset(&reg, 0, sizeof reg);
+ reg.eax.w[0] = 0x0009;
+ reg.ebx.w[0] = 0x00e6; /* PXENV_FILE_API_CHECK */
+ reg.edi.w[0] = OFFS(fca);
+ reg.es = SEG(fca);
+
+ __intcall(0x22, &reg, &reg);
+
+ if (reg.eflags.l & EFLAGS_CF)
+ return false; /* Cannot invoke PXE stack */
+
+ if (reg.eax.w[0] || fca->Status)
+ return false; /* PXE failure */
+
+ if (fca->Magic != 0xe9c17b20)
+ return false; /* Incorrect magic */
+
+ if (fca->Size < sizeof *fca)
+ return false; /* Short return */
+
+ if (!(fca->APIMask & (1 << 5)))
+ return false; /* No FILE EXEC */
+
+ return true;
+}
+
+struct s_PXENV_FILE_EXEC {
+ uint16_t Status;
+ struct segoff16 Command;
+};
+
+static void sanboot(const char **args)
+{
+ char *q;
+ struct s_PXENV_FILE_EXEC *fx;
+ com32sys_t reg;
+
+ memset(&reg, 0, sizeof reg);
+
+ fx = __com32.cs_bounce;
+ q = (char *)(fx+1);
+
+ fx->Status = 1;
+ fx->Command.offs = OFFS(q);
+ fx->Command.seg = SEG(q);
+
+ q = stpcpy(q, "sanboot");
+
+ while (*args) {
+ *q++ = ' ';
+ q = stpcpy(q, *args);
+ args++;
+ }
+
+ memset(&reg, 0, sizeof reg);
+ reg.eax.w[0] = 0x0009;
+ reg.ebx.w[0] = 0x00e5; /* PXENV_FILE_EXEC */
+ reg.edi.w[0] = OFFS(fx);
+ reg.es = SEG(fx);
+
+ __intcall(0x22, &reg, &reg);
+
+ /* This should not return... */
+}
+
+int main(int argc, const char *argv[])
+{
+ openconsole(&dev_null_r, &dev_stdcon_w);
+
+ if (argc < 2) {
+ printf("Usage: sanboot rootpath\n");
+ return 1;
+ }
+
+ if (!is_gpxe()) {
+ printf("sanboot: gPXE API not detected\n");
+ return 1;
+ }
+
+ sanboot(argv+1);
+
+ /* sanboot() should not return... */
+ printf("SAN boot failed.\n");
+ return 1;
+}