mboot: reimplement the Solaris DHCP hack, add compliant a.out mode
authorH. Peter Anvin <hpa@zytor.com>
Mon, 27 Apr 2009 02:52:39 +0000 (19:52 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Mon, 27 Apr 2009 02:54:54 +0000 (19:54 -0700)
Reimplement the Solaris DHCP information passing hack.

Add a spec-compliant mode for the "a.out kludge".  The spec is pretty
clear that the bit should override the ELF header (after all,
otherwise there wouldn't be any need for the bit), but Grub
disagrees.  We default to Grub-compliant mode, as Solaris seems to set
the bit even though it's an ELF kernel, but add the option to enable
spec-compliant mode, as apparently some versions of FreeBSD need it.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
com32/mboot/Makefile
com32/mboot/map.c
com32/mboot/mboot.c
com32/mboot/mboot.h
com32/mboot/solaris.c [new file with mode: 0644]

index 64c1d07..a690271 100644 (file)
@@ -24,7 +24,7 @@ LNXLIBS          = ../libutil/libutil_lnx.a
 MODULES          = mboot.c32
 TESTFILES =
 
-OBJS = mboot.o map.o mem.o apm.o
+OBJS = mboot.o map.o mem.o apm.o solaris.o
 
 all: $(MODULES) $(TESTFILES)
 
index b134a55..bdfcfcf 100644 (file)
@@ -157,7 +157,7 @@ int map_image(void *ptr, size_t len)
    * This is insane, since it makes the AOUT_KLUDGE bit functionally
    * useless, but at least Solaris apparently depends on this behavior.
    */
-  if (eh) {
+  if (eh && !(opt.aout && mbh_len && (mbh->flags & MULTIBOOT_AOUT_KLUDGE))) {
     regs.eip = eh->e_entry;
 
     ph = (Elf32_Phdr *)(cptr+eh->e_phoff);
index 3b42093..41a5ef1 100644 (file)
@@ -36,6 +36,7 @@
 
 struct multiboot_info mbinfo;
 struct syslinux_pm_regs regs;
+struct my_options opt;
 
 struct module_data {
   void *data;
@@ -152,15 +153,31 @@ int main(int argc, char *argv[])
 
   openconsole(&dev_null_r, &dev_stdcon_w);
 
-  if (argc < 2) {
-    error("Usage: mboot.c32 mboot_file args... [--- module args...]...\n");
+  argv++;
+
+  while (*argv) {
+    if (!strcmp(*argv, "-solaris"))
+      opt.solaris = true;
+    else if (!strcmp(*argv, "-aout"))
+      opt.aout = true;
+    else
+      break;
+    argv++;
+  }
+
+  if (!*argv) {
+    error("Usage: mboot.c32 [opts] mboot_file args... [--- module args...]...\n"
+         "Options:\n"
+         "  -solaris  Enable Solaris DHCP information passing\n"
+         "  -aout     Use the \"a.out kludge\" if enabled, even for ELF\n"
+         "            This matches the Multiboot spec, but differs from Grub\n");
     return 1;
   }
 
   /* Load the files */
-  nmodules = get_modules(argv+1, &modules);
+  nmodules = get_modules(argv, &modules);
   if (nmodules < 1) {
-    error("No modules found!\n");
+    error("No files found!\n");
     return 1;                  /* Failure */
   }
 
@@ -195,6 +212,8 @@ int main(int argc, char *argv[])
   /* Add auxilliary information */
   mboot_make_memmap();
   mboot_apm();
+  if (opt.solaris)
+    mboot_solaris_dhcp_hack();
 
   /* Run it */
   mboot_run(keeppxe ? 3 : 0);
index 0f33a51..c05d69f 100644 (file)
@@ -69,6 +69,10 @@ static inline void error(const char *msg)
 /* mboot.c */
 extern struct multiboot_info mbinfo;
 extern struct syslinux_pm_regs regs;
+extern struct my_options {
+  bool solaris;
+  bool aout;
+} opt;
 
 /* map.c */
 #define MAP_HIGH       1
@@ -84,4 +88,7 @@ void mboot_make_memmap(void);
 /* apm.c */
 void mboot_apm(void);
 
+/* solaris.c */
+void mboot_solaris_dhcp_hack(void);
+
 #endif /* MBOOT_H */
diff --git a/com32/mboot/solaris.c b/com32/mboot/solaris.c
new file mode 100644 (file)
index 0000000..338e9eb
--- /dev/null
@@ -0,0 +1,51 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2007-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * solaris.c
+ *
+ * Solaris DHCP hack
+ *
+ * Solaris uses a nonstandard hack to pass DHCP information from a netboot.
+ */
+
+#include "mboot.h"
+#include <syslinux/pxe.h>
+
+void mboot_solaris_dhcp_hack(void)
+{
+  void *dhcpdata;
+  size_t dhcplen;
+
+  if (!pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK, &dhcpdata, &dhcplen)) {
+    mbinfo.drives_addr = map_data(dhcpdata, dhcplen, 4, 0);
+    mbinfo.drives_length = dhcplen;
+    mbinfo.boot_device = 0x20ffffff;
+    mbinfo.flags = (mbinfo.flags & ~MB_INFO_DRIVE_INFO) | MB_INFO_BOOTDEV;
+  }
+}