All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] a.out support for multiboot and freebsd
@ 2008-02-09 18:41 Bean
  2008-02-09 21:57 ` walt
  0 siblings, 1 reply; 37+ messages in thread
From: Bean @ 2008-02-09 18:41 UTC (permalink / raw)
  To: The development of GRUB 2

Hi,

This patch add a.out support for multiboot. It also support the boot2
loader (a.out format) of freebsd:

set root=(hd0,0,a)
aout_freebsd /boot/loader
boot

2008-02-10  Bean  <bean123ch@gmail.com>

	* conf/i386-pc.rmk (pkglib_MODULES): Add aout.mod _aout_freebsd.mod and
	aout_freebsd.mod.
	(aout_mod_SOURCES): New variable.
	(aout_mod_CFLAGS): Likewise.
	(aout_mod_LDFLAGS): Likewise.
	(_aout_freebsd_mod_SOURCES): New variable.
	(_aout_freebsd_mod_CFLAGS): Likewise.
	(_aout_freebsd_mod_LDFLAGS): Likewise.
	(aout_freebsd_mod_SOURCES): New variable.
	(aout_freebsd_mod_CFLAGS): Likewise.
	(aout_freebsd_mod_LDFLAGS): Likewise.

	* include/grub/aout.h: New file.

	* include/grub/i386/loader.h (grub_freebsd_real_boot): New function.
	(grub_rescue_cmd_aout_freebsd): Likewise.

	* kern/i386/loader.S (grub_freebsd_real_boot): New function.

	* loader/aout.c: New file.

	* loader/i386/pc/aout_freebsd.c: New file.

	* loader/i386/pc/aout_freebsd_normal.c: New file.

	* loader/i386/pc/multiboot.c (grub_multiboot): Handle a.out format.

diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 78e4f00..6a9c167 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -146,7 +146,8 @@ pkglib_MODULES = biosdisk.mod _chain.mod
_linux.mod linux.mod normal.mod \
 	_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod	\
 	vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
 	videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod	\
-	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod
+	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \
+	aout.mod _aout_freebsd.mod aout_freebsd.mod

 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -298,4 +299,19 @@ lspci_mod_SOURCES = commands/lspci.c
 lspci_mod_CFLAGS = $(COMMON_CFLAGS)
 lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)

+# For aout.mod
+aout_mod_SOURCES = loader/aout.c
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _aout_freebsd.mod
+_aout_freebsd_mod_SOURCES = loader/i386/pc/aout_freebsd.c
+_aout_freebsd_mod_CFLAGS = $(COMMON_CFLAGS)
+_aout_freebsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For aout_freebsd.mod
+aout_freebsd_mod_SOURCES = loader/i386/pc/aout_freebsd_normal.c
+aout_freebsd_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_freebsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff --git a/include/grub/aout.h b/include/grub/aout.h
new file mode 100755
index 0000000..3243b82
--- /dev/null
+++ b/include/grub/aout.h
@@ -0,0 +1,91 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_AOUT_HEADER
+#define GRUB_AOUT_HEADER 1
+
+#include <grub/types.h>
+
+struct grub_aout32_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint32_t a_text;		/* text segment size */
+  grub_uint32_t a_data;		/* initialized data size */
+  grub_uint32_t a_bss;		/* uninitialized data size */
+  grub_uint32_t a_syms;		/* symbol table size */
+  grub_uint32_t a_entry;	/* entry point */
+  grub_uint32_t a_trsize;	/* text relocation size */
+  grub_uint32_t a_drsize;	/* data relocation size */
+};
+
+struct grub_aout64_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint64_t a_text;		/* text segment size */
+  grub_uint64_t a_data;		/* initialized data size */
+  grub_uint64_t a_bss;		/* uninitialized data size */
+  grub_uint64_t a_syms;		/* symbol table size */
+  grub_uint64_t a_entry;	/* entry point */
+  grub_uint64_t a_trsize;	/* text relocation size */
+  grub_uint64_t a_drsize;	/* data relocation size */
+};
+
+union grub_aout_header
+{
+  struct grub_aout32_header aout32;
+  struct grub_aout64_header aout64;
+};
+
+#define AOUT_TYPE_NONE		0
+#define AOUT_TYPE_AOUT32	1
+#define AOUT_TYPE_AOUT64	6
+
+#define	AOUT32_OMAGIC		0x107	/* 0407 old impure format */
+#define	AOUT32_NMAGIC		0x108	/* 0410 read-only text */
+#define	AOUT32_ZMAGIC		0x10b	/* 0413 demand load format */
+#define AOUT32_QMAGIC		0xcc	/* 0314 "compact" demand load format */
+
+#define AOUT64_OMAGIC		0x1001
+#define AOUT64_ZMAGIC		0x1002
+#define AOUT64_NMAGIC		0x1003
+
+#define	AOUT_MID_ZERO		0	/* unknown - implementation dependent */
+#define	AOUT_MID_SUN010		1	/* sun 68010/68020 binary */
+#define	AOUT_MID_SUN020		2	/* sun 68020-only binary */
+#define AOUT_MID_I386		134	/* i386 BSD binary */
+#define AOUT_MID_SPARC		138	/* sparc */
+#define	AOUT_MID_HP200		200	/* hp200 (68010) BSD binary */
+#define	AOUT_MID_HP300		300	/* hp300 (68020+68881) BSD binary */
+#define	AOUT_MID_HPUX		0x20C	/* hp200/300 HP-UX binary */
+#define	AOUT_MID_HPUX800	0x20B	/* hp800 HP-UX binary */
+
+#define AOUT_FLAG_PIC		0x10	/* contains position independant code */
+#define AOUT_FLAG_DYNAMIC	0x20	/* contains run-time link-edit info */
+#define AOUT_FLAG_DPMASK	0x30	/* mask for the above */
+
+#define AOUT_GETMAGIC(header) ((header).a_midmag & 0xffff)
+#define AOUT_GETMID(header) ((header).a_midmag >> 16) & 0x03ff)
+#define AOUT_GETFLAG(header) ((header).a_midmag >> 26) & 0x3f)
+
+int EXPORT_FUNC(grub_aout_get_type) (union grub_aout_header *header);
+
+grub_err_t EXPORT_FUNC(grub_aout_load) (grub_file_t file, int offset,
+                                        grub_addr_t load_addr, int load_size,
+                                        grub_addr_t bss_end_addr);
+
+#endif /* ! GRUB_AOUT_HEADER */
diff --git a/include/grub/i386/loader.h b/include/grub/i386/loader.h
index 45a1652..a7d5124 100644
--- a/include/grub/i386/loader.h
+++ b/include/grub/i386/loader.h
@@ -39,10 +39,16 @@ void EXPORT_FUNC(grub_multiboot_real_boot)
(grub_addr_t entry,
 void EXPORT_FUNC(grub_multiboot2_real_boot) (grub_addr_t entry,
                                              struct grub_multiboot_info *mbi)
      __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_freebsd_real_boot) (grub_addr_t entry,
+                                          grub_uint32_t bootdrv,
+                                          void *bootinfo)
+     __attribute__ ((noreturn));
+

 /* It is necessary to export these functions, because normal mode commands
    reuse rescue mode commands.  */
 void grub_rescue_cmd_linux (int argc, char *argv[]);
 void grub_rescue_cmd_initrd (int argc, char *argv[]);
+void grub_rescue_cmd_aout_freebsd (int argc, char *argv[]);

 #endif /* ! GRUB_LOADER_CPU_HEADER */
diff --git a/kern/i386/loader.S b/kern/i386/loader.S
index 266f4ef..6c5a5c1 100644
--- a/kern/i386/loader.S
+++ b/kern/i386/loader.S
@@ -162,3 +162,24 @@ FUNCTION(grub_multiboot2_real_boot)
         movl    $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
         popl    %ecx
         jmp     *%ecx
+
+
+#define FREEBSD_RB_BOOTINFO	0x80000000
+
+FUNCTION(grub_freebsd_real_boot)
+	pushl	%ecx
+	xorl	%ecx, %ecx
+	pushl	%ecx
+	pushl	%ecx
+	pushl	%ecx
+        pushl   %edx
+        pushl	$FREEBSD_RB_BOOTINFO
+        pushl	%eax
+
+        call    EXT_C(grub_dl_unload_all)
+        call    EXT_C(grub_stop_floppy)
+
+        cli
+
+        popl    %ecx
+        call    *%ecx
diff --git a/loader/aout.c b/loader/aout.c
new file mode 100755
index 0000000..2c82b60
--- /dev/null
+++ b/loader/aout.c
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ *  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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+int
+grub_aout_get_type (union grub_aout_header *header)
+{
+  int magic;
+
+  magic = AOUT_GETMAGIC (header->aout32);
+  if ((magic == AOUT32_OMAGIC) || (magic == AOUT32_NMAGIC) ||
+      (magic == AOUT32_ZMAGIC) || (magic == AOUT32_QMAGIC))
+    return AOUT_TYPE_AOUT32;
+  else if ((magic == AOUT64_OMAGIC) || (magic == AOUT64_NMAGIC) ||
+	   (magic == AOUT64_ZMAGIC))
+    return AOUT_TYPE_AOUT64;
+  else
+    return AOUT_TYPE_NONE;
+}
+
+grub_err_t
+grub_aout_load (grub_file_t file, int offset,
+                grub_addr_t load_addr,
+		int load_size,
+                grub_addr_t bss_end_addr)
+{
+  if ((grub_file_seek (file, offset)) == (grub_off_t) - 1)
+    return grub_errno;
+
+  if (!load_size)
+    load_size = file->size - offset;
+
+  grub_file_read (file, (char *) load_addr, load_size);
+
+  if (grub_errno)
+    return grub_errno;
+
+  if (bss_end_addr)
+    grub_memset (load_addr + load_size, 0,
+                 bss_end_addr - load_addr - load_size);
+
+  return GRUB_ERR_NONE;
+}
diff --git a/loader/i386/pc/aout_freebsd.c b/loader/i386/pc/aout_freebsd.c
new file mode 100755
index 0000000..b757862
--- /dev/null
+++ b/loader/i386/pc/aout_freebsd.c
@@ -0,0 +1,195 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+#include <grub/aout.h>
+
+#define BOOTINFO_VERSION        1
+#define N_BIOS_GEOM             8
+#define B_DEVMAGIC		0xa0000000
+
+struct grub_freebsd_bootinfo
+{
+  grub_uint32_t bi_version;
+  grub_uint8_t *bi_kernelname;
+  struct nfs_diskless *bi_nfs_diskless;
+  grub_uint32_t bi_n_bios_used;
+  grub_uint32_t bi_bios_geom[N_BIOS_GEOM];
+  grub_uint32_t bi_size;
+  grub_uint8_t bi_memsizes_valid;
+  grub_uint8_t bi_bios_dev;
+  grub_uint8_t bi_pad[2];
+  grub_uint32_t bi_basemem;
+  grub_uint32_t bi_extmem;
+  grub_uint32_t bi_symtab;
+  grub_uint32_t bi_esymtab;
+} __attribute__ ((packed));
+
+static grub_dl_t my_mod;
+
+static grub_addr_t entry;
+
+static grub_err_t
+grub_aout_freebsd_boot (void)
+{
+  struct grub_freebsd_bootinfo bi;
+  char *p;
+  grub_uint32_t bootdev;
+
+  grub_memset (&bi, 0, sizeof (bi));
+  bi.bi_version = BOOTINFO_VERSION;
+  bi.bi_size = sizeof (bi);
+
+  /* Slice 2 (whole disk).  */
+  bootdev = B_DEVMAGIC + (2 << 20);
+
+  p = grub_env_get ("root");
+  if ((p) && ((p[0] == 'h') || (p[0] == 'f')) && (p[1] == 'd') &&
+      (p[2] >= '0') && (p[2] <= '9'))
+    {
+      if (p[0] == 'h')
+	bi.bi_bios_dev = 0x80;
+
+      bi.bi_bios_dev += grub_strtoul (p + 2, &p, 0);
+
+      if ((p) && (p[0] == ',') && (p[1] >= '0') && (p[1] <= '9'))
+	{
+	  /* Partition number.  */
+	  bootdev |= (grub_strtoul (p + 1, &p, 0)) << 8;
+
+	  if ((p) && (p[0] == ',') && (p[1] >= 'a') && (p[1] <= 'z'))
+	    {
+	      /* Unit number.  */
+	      bootdev |= (p[1] - 'a') << 8;
+	    }
+	}
+    }
+
+  grub_freebsd_real_boot (entry, bootdev, &bi);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_aout_freebsd_unload (void)
+{
+  grub_dl_unref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+void
+grub_rescue_cmd_aout_freebsd (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  union grub_aout_header ah;
+  grub_addr_t load_addr, bss_end_addr;
+  int ofs, align_4k;
+
+  grub_dl_ref (my_mod);
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (!file)
+    goto fail;
+
+  if (grub_file_read (file, (char *) &ah, sizeof (ah)) != sizeof (ah))
+    {
+      grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header");
+      goto fail;
+    }
+
+  if (grub_aout_get_type (&ah) != AOUT_TYPE_AOUT32)
+    {
+      grub_error (GRUB_ERR_READ_ERROR, "invalid a.out header");
+      goto fail;
+    }
+
+  entry = ah.aout32.a_entry & 0xFFFFFF;
+
+  if (AOUT_GETMAGIC (ah.aout32) == AOUT32_ZMAGIC)
+    {
+      load_addr = entry;
+      ofs = 0x1000;
+      align_4k = 0;
+    }
+  else
+    {
+      load_addr = entry & 0xF00000;
+      ofs = sizeof (struct grub_aout32_header);
+      align_4k = 1;
+    }
+
+  if (load_addr < 0x100000)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "load address below 1M");
+      goto fail;
+    }
+
+  if (ah.aout32.a_bss)
+    {
+      bss_end_addr = load_addr + ah.aout32.a_text + ah.aout32.a_data;
+      if (align_4k)
+	bss_end_addr = (bss_end_addr + 0xFFF) & 0xFFFFF000;
+
+      bss_end_addr += ah.aout32.a_bss;
+      if (align_4k)
+	bss_end_addr = (bss_end_addr + 0xFFF) & 0xFFFFF000;
+    }
+  else
+    bss_end_addr = 0;
+
+  if (grub_aout_load (file, ofs, load_addr,
+		      ah.aout32.a_text + ah.aout32.a_data, bss_end_addr))
+    goto fail;
+
+  grub_loader_set (grub_aout_freebsd_boot, grub_aout_freebsd_unload, 1);
+
+fail:
+
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    grub_dl_unref (my_mod);
+}
+
+GRUB_MOD_INIT (aout_freebsd)
+{
+  grub_rescue_register_command ("aout_freebsd", grub_rescue_cmd_aout_freebsd,
+				"load freebsd loader");
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI (aout_freebsd)
+{
+  grub_rescue_unregister_command ("aout_freebsd");
+}
diff --git a/loader/i386/pc/aout_freebsd_normal.c
b/loader/i386/pc/aout_freebsd_normal.c
new file mode 100755
index 0000000..d9e2b81
--- /dev/null
+++ b/loader/i386/pc/aout_freebsd_normal.c
@@ -0,0 +1,47 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+static grub_err_t
+grub_normal_aout_freebsd_command (struct grub_arg_list *state
+				  __attribute__ ((unused)), int argc,
+				  char **args)
+{
+  grub_rescue_cmd_aout_freebsd (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT (aout_freebsd_normal)
+{
+  (void) mod;			/* To stop warning.  */
+  grub_register_command ("aout_freebsd", grub_normal_aout_freebsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "aout_freebsd FILE [ARGS...]",
+			 "Load freebsd loader.", 0);
+}
+
+GRUB_MOD_FINI (aout_freebsd_normal)
+{
+  grub_unregister_command ("aout_freebsd");
+}
diff --git a/loader/i386/pc/multiboot.c b/loader/i386/pc/multiboot.c
index 011cc9a..d39f66e 100644
--- a/loader/i386/pc/multiboot.c
+++ b/loader/i386/pc/multiboot.c
@@ -36,6 +36,7 @@
 #include <grub/machine/init.h>
 #include <grub/machine/memory.h>
 #include <grub/elf.h>
+#include <grub/aout.h>
 #include <grub/file.h>
 #include <grub/err.h>
 #include <grub/rescue.h>
@@ -315,7 +316,18 @@ grub_multiboot (int argc, char *argv[])
       goto fail;
     }

-  if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
+  if (header->flags & MULTIBOOT_AOUT_KLUDGE)
+    {
+      if ((grub_aout_load (file, (char *) header - buffer, header->load_addr,
+                           ((header->load_end_addr == 0) ? 0 :
+                            header->load_end_addr - header->load_addr),
+                           header->bss_end_addr))
+          !=GRUB_ERR_NONE)
+        goto fail;
+
+      entry = header->entry_addr;
+    }
+  else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
     goto fail;

   mbi = grub_malloc (sizeof (struct grub_multiboot_info));

-- 
Bean



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-09 18:41 [PATCH] a.out support for multiboot and freebsd Bean
@ 2008-02-09 21:57 ` walt
  2008-02-10  5:33   ` Bean
  0 siblings, 1 reply; 37+ messages in thread
From: walt @ 2008-02-09 21:57 UTC (permalink / raw)
  To: grub-devel

Bean wrote:
> Hi,
>
> This patch add a.out support for multiboot. It also support the boot2
> loader (a.out format) of freebsd:
>
> set root=(hd0,0,a)
> aout_freebsd /boot/loader
> boot
>
> 2008-02-10  Bean<bean123ch@gmail.com> ...

Hi Bean, and thanks for the patch.  Unfortunately, the patch is malformed
in at least two places and also has whitespace corruption.  I did my best
to edit the patch by hand until it seemed to apply okay, but I don't trust
my results.

I have this same patch corruption problem with many of your posts.  Can
you change the way you attach patches somehow?  Maybe change email client?
Anyone else have a suggestion?

Bean, can you download your own patch from the mailing list and see if it
will apply to your own code?

Thanks!




^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-09 21:57 ` walt
@ 2008-02-10  5:33   ` Bean
  2008-02-10  9:22     ` Vesa Jääskeläinen
  2008-02-10 18:27     ` walt
  0 siblings, 2 replies; 37+ messages in thread
From: Bean @ 2008-02-10  5:33 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 983 bytes --]

On Feb 10, 2008 5:57 AM, walt <wa1ter@myrealbox.com> wrote:
> Bean wrote:
> > Hi,
> >
> > This patch add a.out support for multiboot. It also support the boot2
> > loader (a.out format) of freebsd:
> >
> > set root=(hd0,0,a)
> > aout_freebsd /boot/loader
> > boot
> >
> > 2008-02-10  Bean<bean123ch@gmail.com> ...
>
> Hi Bean, and thanks for the patch.  Unfortunately, the patch is malformed
> in at least two places and also has whitespace corruption.  I did my best
> to edit the patch by hand until it seemed to apply okay, but I don't trust
> my results.
>
> I have this same patch corruption problem with many of your posts.  Can
> you change the way you attach patches somehow?  Maybe change email client?
> Anyone else have a suggestion?
>
> Bean, can you download your own patch from the mailing list and see if it
> will apply to your own code?

i'm using the web interface to send patch, maybe it cause some
problem. here is the
raw diff file, it should be fine.

-- 
Bean

[-- Attachment #2: a3.diff --]
[-- Type: application/octet-stream, Size: 16371 bytes --]

diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 78e4f00..6a9c167 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -146,7 +146,8 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
 	_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod	\
 	vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
 	videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod	\
-	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod
+	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \
+	aout.mod _aout_freebsd.mod aout_freebsd.mod
 
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -298,4 +299,19 @@ lspci_mod_SOURCES = commands/lspci.c
 lspci_mod_CFLAGS = $(COMMON_CFLAGS)
 lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For aout.mod
+aout_mod_SOURCES = loader/aout.c
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _aout_freebsd.mod
+_aout_freebsd_mod_SOURCES = loader/i386/pc/aout_freebsd.c
+_aout_freebsd_mod_CFLAGS = $(COMMON_CFLAGS)
+_aout_freebsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For aout_freebsd.mod
+aout_freebsd_mod_SOURCES = loader/i386/pc/aout_freebsd_normal.c
+aout_freebsd_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_freebsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff --git a/include/grub/aout.h b/include/grub/aout.h
new file mode 100755
index 0000000..3243b82
--- /dev/null
+++ b/include/grub/aout.h
@@ -0,0 +1,91 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_AOUT_HEADER
+#define GRUB_AOUT_HEADER 1
+
+#include <grub/types.h>
+
+struct grub_aout32_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint32_t a_text;		/* text segment size */
+  grub_uint32_t a_data;		/* initialized data size */
+  grub_uint32_t a_bss;		/* uninitialized data size */
+  grub_uint32_t a_syms;		/* symbol table size */
+  grub_uint32_t a_entry;	/* entry point */
+  grub_uint32_t a_trsize;	/* text relocation size */
+  grub_uint32_t a_drsize;	/* data relocation size */
+};
+
+struct grub_aout64_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint64_t a_text;		/* text segment size */
+  grub_uint64_t a_data;		/* initialized data size */
+  grub_uint64_t a_bss;		/* uninitialized data size */
+  grub_uint64_t a_syms;		/* symbol table size */
+  grub_uint64_t a_entry;	/* entry point */
+  grub_uint64_t a_trsize;	/* text relocation size */
+  grub_uint64_t a_drsize;	/* data relocation size */
+};
+
+union grub_aout_header
+{
+  struct grub_aout32_header aout32;
+  struct grub_aout64_header aout64;
+};
+
+#define AOUT_TYPE_NONE		0
+#define AOUT_TYPE_AOUT32	1
+#define AOUT_TYPE_AOUT64	6
+
+#define	AOUT32_OMAGIC		0x107	/* 0407 old impure format */
+#define	AOUT32_NMAGIC		0x108	/* 0410 read-only text */
+#define	AOUT32_ZMAGIC		0x10b	/* 0413 demand load format */
+#define AOUT32_QMAGIC		0xcc	/* 0314 "compact" demand load format */
+
+#define AOUT64_OMAGIC		0x1001
+#define AOUT64_ZMAGIC		0x1002
+#define AOUT64_NMAGIC		0x1003
+
+#define	AOUT_MID_ZERO		0	/* unknown - implementation dependent */
+#define	AOUT_MID_SUN010		1	/* sun 68010/68020 binary */
+#define	AOUT_MID_SUN020		2	/* sun 68020-only binary */
+#define AOUT_MID_I386		134	/* i386 BSD binary */
+#define AOUT_MID_SPARC		138	/* sparc */
+#define	AOUT_MID_HP200		200	/* hp200 (68010) BSD binary */
+#define	AOUT_MID_HP300		300	/* hp300 (68020+68881) BSD binary */
+#define	AOUT_MID_HPUX		0x20C	/* hp200/300 HP-UX binary */
+#define	AOUT_MID_HPUX800	0x20B	/* hp800 HP-UX binary */
+
+#define AOUT_FLAG_PIC		0x10	/* contains position independant code */
+#define AOUT_FLAG_DYNAMIC	0x20	/* contains run-time link-edit info */
+#define AOUT_FLAG_DPMASK	0x30	/* mask for the above */
+
+#define AOUT_GETMAGIC(header) ((header).a_midmag & 0xffff)
+#define AOUT_GETMID(header) ((header).a_midmag >> 16) & 0x03ff)
+#define AOUT_GETFLAG(header) ((header).a_midmag >> 26) & 0x3f)
+
+int EXPORT_FUNC(grub_aout_get_type) (union grub_aout_header *header);
+
+grub_err_t EXPORT_FUNC(grub_aout_load) (grub_file_t file, int offset,
+                                        grub_addr_t load_addr, int load_size,
+                                        grub_addr_t bss_end_addr);
+
+#endif /* ! GRUB_AOUT_HEADER */
diff --git a/include/grub/i386/loader.h b/include/grub/i386/loader.h
index 45a1652..a7d5124 100644
--- a/include/grub/i386/loader.h
+++ b/include/grub/i386/loader.h
@@ -39,10 +39,16 @@ void EXPORT_FUNC(grub_multiboot_real_boot) (grub_addr_t entry,
 void EXPORT_FUNC(grub_multiboot2_real_boot) (grub_addr_t entry,
                                              struct grub_multiboot_info *mbi)
      __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_freebsd_real_boot) (grub_addr_t entry,
+                                          grub_uint32_t bootdrv,
+                                          void *bootinfo)
+     __attribute__ ((noreturn));
+
 
 /* It is necessary to export these functions, because normal mode commands
    reuse rescue mode commands.  */
 void grub_rescue_cmd_linux (int argc, char *argv[]);
 void grub_rescue_cmd_initrd (int argc, char *argv[]);
+void grub_rescue_cmd_aout_freebsd (int argc, char *argv[]);
 
 #endif /* ! GRUB_LOADER_CPU_HEADER */
diff --git a/kern/i386/loader.S b/kern/i386/loader.S
index 266f4ef..6c5a5c1 100644
--- a/kern/i386/loader.S
+++ b/kern/i386/loader.S
@@ -162,3 +162,24 @@ FUNCTION(grub_multiboot2_real_boot)
         movl    $MULTIBOOT2_BOOTLOADER_MAGIC,%eax 
         popl    %ecx
         jmp     *%ecx
+
+
+#define FREEBSD_RB_BOOTINFO	0x80000000
+
+FUNCTION(grub_freebsd_real_boot)
+	pushl	%ecx
+	xorl	%ecx, %ecx
+	pushl	%ecx
+	pushl	%ecx
+	pushl	%ecx
+        pushl   %edx
+        pushl	$FREEBSD_RB_BOOTINFO
+        pushl	%eax
+
+        call    EXT_C(grub_dl_unload_all)
+        call    EXT_C(grub_stop_floppy)
+
+        cli
+
+        popl    %ecx
+        call    *%ecx
diff --git a/loader/aout.c b/loader/aout.c
new file mode 100755
index 0000000..2c82b60
--- /dev/null
+++ b/loader/aout.c
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ *  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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+int
+grub_aout_get_type (union grub_aout_header *header)
+{
+  int magic;
+
+  magic = AOUT_GETMAGIC (header->aout32);
+  if ((magic == AOUT32_OMAGIC) || (magic == AOUT32_NMAGIC) ||
+      (magic == AOUT32_ZMAGIC) || (magic == AOUT32_QMAGIC))
+    return AOUT_TYPE_AOUT32;
+  else if ((magic == AOUT64_OMAGIC) || (magic == AOUT64_NMAGIC) ||
+	   (magic == AOUT64_ZMAGIC))
+    return AOUT_TYPE_AOUT64;
+  else
+    return AOUT_TYPE_NONE;
+}
+
+grub_err_t
+grub_aout_load (grub_file_t file, int offset,
+                grub_addr_t load_addr,
+		int load_size,
+                grub_addr_t bss_end_addr)
+{
+  if ((grub_file_seek (file, offset)) == (grub_off_t) - 1)
+    return grub_errno;
+
+  if (!load_size)
+    load_size = file->size - offset;
+
+  grub_file_read (file, (char *) load_addr, load_size);
+
+  if (grub_errno)
+    return grub_errno;
+
+  if (bss_end_addr)
+    grub_memset (load_addr + load_size, 0,
+                 bss_end_addr - load_addr - load_size);
+
+  return GRUB_ERR_NONE;
+}
diff --git a/loader/i386/pc/aout_freebsd.c b/loader/i386/pc/aout_freebsd.c
new file mode 100755
index 0000000..b757862
--- /dev/null
+++ b/loader/i386/pc/aout_freebsd.c
@@ -0,0 +1,195 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+#include <grub/aout.h>
+
+#define BOOTINFO_VERSION        1
+#define N_BIOS_GEOM             8
+#define B_DEVMAGIC		0xa0000000
+
+struct grub_freebsd_bootinfo
+{
+  grub_uint32_t bi_version;
+  grub_uint8_t *bi_kernelname;
+  struct nfs_diskless *bi_nfs_diskless;
+  grub_uint32_t bi_n_bios_used;
+  grub_uint32_t bi_bios_geom[N_BIOS_GEOM];
+  grub_uint32_t bi_size;
+  grub_uint8_t bi_memsizes_valid;
+  grub_uint8_t bi_bios_dev;
+  grub_uint8_t bi_pad[2];
+  grub_uint32_t bi_basemem;
+  grub_uint32_t bi_extmem;
+  grub_uint32_t bi_symtab;
+  grub_uint32_t bi_esymtab;
+} __attribute__ ((packed));
+
+static grub_dl_t my_mod;
+
+static grub_addr_t entry;
+
+static grub_err_t
+grub_aout_freebsd_boot (void)
+{
+  struct grub_freebsd_bootinfo bi;
+  char *p;
+  grub_uint32_t bootdev;
+
+  grub_memset (&bi, 0, sizeof (bi));
+  bi.bi_version = BOOTINFO_VERSION;
+  bi.bi_size = sizeof (bi);
+
+  /* Slice 2 (whole disk).  */
+  bootdev = B_DEVMAGIC + (2 << 20);
+
+  p = grub_env_get ("root");
+  if ((p) && ((p[0] == 'h') || (p[0] == 'f')) && (p[1] == 'd') &&
+      (p[2] >= '0') && (p[2] <= '9'))
+    {
+      if (p[0] == 'h')
+	bi.bi_bios_dev = 0x80;
+
+      bi.bi_bios_dev += grub_strtoul (p + 2, &p, 0);
+
+      if ((p) && (p[0] == ',') && (p[1] >= '0') && (p[1] <= '9'))
+	{
+	  /* Partition number.  */
+	  bootdev |= (grub_strtoul (p + 1, &p, 0)) << 8;
+
+	  if ((p) && (p[0] == ',') && (p[1] >= 'a') && (p[1] <= 'z'))
+	    {
+	      /* Unit number.  */
+	      bootdev |= (p[1] - 'a') << 8;
+	    }
+	}
+    }
+
+  grub_freebsd_real_boot (entry, bootdev, &bi);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_aout_freebsd_unload (void)
+{
+  grub_dl_unref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+void
+grub_rescue_cmd_aout_freebsd (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  union grub_aout_header ah;
+  grub_addr_t load_addr, bss_end_addr;
+  int ofs, align_4k;
+
+  grub_dl_ref (my_mod);
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (!file)
+    goto fail;
+
+  if (grub_file_read (file, (char *) &ah, sizeof (ah)) != sizeof (ah))
+    {
+      grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header");
+      goto fail;
+    }
+
+  if (grub_aout_get_type (&ah) != AOUT_TYPE_AOUT32)
+    {
+      grub_error (GRUB_ERR_READ_ERROR, "invalid a.out header");
+      goto fail;
+    }
+
+  entry = ah.aout32.a_entry & 0xFFFFFF;
+
+  if (AOUT_GETMAGIC (ah.aout32) == AOUT32_ZMAGIC)
+    {
+      load_addr = entry;
+      ofs = 0x1000;
+      align_4k = 0;
+    }
+  else
+    {
+      load_addr = entry & 0xF00000;
+      ofs = sizeof (struct grub_aout32_header);
+      align_4k = 1;
+    }
+
+  if (load_addr < 0x100000)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "load address below 1M");
+      goto fail;
+    }
+
+  if (ah.aout32.a_bss)
+    {
+      bss_end_addr = load_addr + ah.aout32.a_text + ah.aout32.a_data;
+      if (align_4k)
+	bss_end_addr = (bss_end_addr + 0xFFF) & 0xFFFFF000;
+
+      bss_end_addr += ah.aout32.a_bss;
+      if (align_4k)
+	bss_end_addr = (bss_end_addr + 0xFFF) & 0xFFFFF000;
+    }
+  else
+    bss_end_addr = 0;
+
+  if (grub_aout_load (file, ofs, load_addr,
+		      ah.aout32.a_text + ah.aout32.a_data, bss_end_addr))
+    goto fail;
+
+  grub_loader_set (grub_aout_freebsd_boot, grub_aout_freebsd_unload, 1);
+
+fail:
+
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    grub_dl_unref (my_mod);
+}
+
+GRUB_MOD_INIT (aout_freebsd)
+{
+  grub_rescue_register_command ("aout_freebsd", grub_rescue_cmd_aout_freebsd,
+				"load freebsd loader");
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI (aout_freebsd)
+{
+  grub_rescue_unregister_command ("aout_freebsd");
+}
diff --git a/loader/i386/pc/aout_freebsd_normal.c b/loader/i386/pc/aout_freebsd_normal.c
new file mode 100755
index 0000000..d9e2b81
--- /dev/null
+++ b/loader/i386/pc/aout_freebsd_normal.c
@@ -0,0 +1,47 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+static grub_err_t
+grub_normal_aout_freebsd_command (struct grub_arg_list *state
+				  __attribute__ ((unused)), int argc,
+				  char **args)
+{
+  grub_rescue_cmd_aout_freebsd (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT (aout_freebsd_normal)
+{
+  (void) mod;			/* To stop warning.  */
+  grub_register_command ("aout_freebsd", grub_normal_aout_freebsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "aout_freebsd FILE [ARGS...]",
+			 "Load freebsd loader.", 0);
+}
+
+GRUB_MOD_FINI (aout_freebsd_normal)
+{
+  grub_unregister_command ("aout_freebsd");
+}
diff --git a/loader/i386/pc/multiboot.c b/loader/i386/pc/multiboot.c
index 011cc9a..d39f66e 100644
--- a/loader/i386/pc/multiboot.c
+++ b/loader/i386/pc/multiboot.c
@@ -36,6 +36,7 @@
 #include <grub/machine/init.h>
 #include <grub/machine/memory.h>
 #include <grub/elf.h>
+#include <grub/aout.h>
 #include <grub/file.h>
 #include <grub/err.h>
 #include <grub/rescue.h>
@@ -315,7 +316,18 @@ grub_multiboot (int argc, char *argv[])
       goto fail;
     }
 
-  if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
+  if (header->flags & MULTIBOOT_AOUT_KLUDGE)
+    {
+      if ((grub_aout_load (file, (char *) header - buffer, header->load_addr,
+                           ((header->load_end_addr == 0) ? 0 :
+                            header->load_end_addr - header->load_addr),
+                           header->bss_end_addr))
+          !=GRUB_ERR_NONE)
+        goto fail;
+
+      entry = header->entry_addr;
+    }
+  else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
     goto fail;
   
   mbi = grub_malloc (sizeof (struct grub_multiboot_info));

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-10  5:33   ` Bean
@ 2008-02-10  9:22     ` Vesa Jääskeläinen
  2008-02-10  9:47       ` Bean
  2008-02-10 18:27     ` walt
  1 sibling, 1 reply; 37+ messages in thread
From: Vesa Jääskeläinen @ 2008-02-10  9:22 UTC (permalink / raw)
  To: The development of GRUB 2

Bean wrote:
> On Feb 10, 2008 5:57 AM, walt <wa1ter@myrealbox.com> wrote:
>> Bean wrote:
>>> Hi,
>>>
>>> This patch add a.out support for multiboot. It also support the boot2
>>> loader (a.out format) of freebsd:
>>>
>>> set root=(hd0,0,a)
>>> aout_freebsd /boot/loader
>>> boot
>>>
>>> 2008-02-10  Bean<bean123ch@gmail.com> ...
>> Hi Bean, and thanks for the patch.  Unfortunately, the patch is malformed
>> in at least two places and also has whitespace corruption.  I did my best
>> to edit the patch by hand until it seemed to apply okay, but I don't trust
>> my results.
>>
>> I have this same patch corruption problem with many of your posts.  Can
>> you change the way you attach patches somehow?  Maybe change email client?
>> Anyone else have a suggestion?
>>
>> Bean, can you download your own patch from the mailing list and see if it
>> will apply to your own code?
> 
> i'm using the web interface to send patch, maybe it cause some
> problem. here is the
> raw diff file, it should be fine.

Hi,

I looked differences of your patch attachments as compared with others 
that seems to be working nicely. When you copy'n'paste they will get 
broken.

Here is example from my message (mail client was Thunderbird):

Content-Type: text/plain;
  name="unknown_glyph.diff"
Content-Disposition: inline;
  filename="unknown_glyph.diff"
Content-Transfer-Encoding: Base64

And here is example from your email:

Content-Type: application/octet-stream; name=a3.diff
Content-Transfer-Encoding: base64
X-Attachment-Id: f_fch5ujm00
Content-Disposition: attachment; filename=a3.diff

With a quick check, gmail indeed does send them as binary as default 
when using Opera. Then I configured Opera to understand diff files (eg. 
that they are "text/plain"), after that gmail sent patches nicely. 
Perhaps you could add new MIME type to your web browser to handle "diff" 
file extesions as "text/plain"?

Thanks,
Vesa Jääskeläinen



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-10  9:22     ` Vesa Jääskeläinen
@ 2008-02-10  9:47       ` Bean
  0 siblings, 0 replies; 37+ messages in thread
From: Bean @ 2008-02-10  9:47 UTC (permalink / raw)
  To: The development of GRUB 2

On Feb 10, 2008 5:22 PM, Vesa Jääskeläinen <chaac@nic.fi> wrote:
>
> Bean wrote:
> > On Feb 10, 2008 5:57 AM, walt <wa1ter@myrealbox.com> wrote:
> >> Bean wrote:
> >>> Hi,
> >>>
> >>> This patch add a.out support for multiboot. It also support the boot2
> >>> loader (a.out format) of freebsd:
> >>>
> >>> set root=(hd0,0,a)
> >>> aout_freebsd /boot/loader
> >>> boot
> >>>
> >>> 2008-02-10  Bean<bean123ch@gmail.com> ...
> >> Hi Bean, and thanks for the patch.  Unfortunately, the patch is malformed
> >> in at least two places and also has whitespace corruption.  I did my best
> >> to edit the patch by hand until it seemed to apply okay, but I don't trust
> >> my results.
> >>
> >> I have this same patch corruption problem with many of your posts.  Can
> >> you change the way you attach patches somehow?  Maybe change email client?
> >> Anyone else have a suggestion?
> >>
> >> Bean, can you download your own patch from the mailing list and see if it
> >> will apply to your own code?
> >
> > i'm using the web interface to send patch, maybe it cause some
> > problem. here is the
> > raw diff file, it should be fine.
>
> Hi,
>
> I looked differences of your patch attachments as compared with others
> that seems to be working nicely. When you copy'n'paste they will get
> broken.
>
> Here is example from my message (mail client was Thunderbird):
>
> Content-Type: text/plain;
>   name="unknown_glyph.diff"
> Content-Disposition: inline;
>   filename="unknown_glyph.diff"
> Content-Transfer-Encoding: Base64
>
> And here is example from your email:
>
> Content-Type: application/octet-stream; name=a3.diff
> Content-Transfer-Encoding: base64
> X-Attachment-Id: f_fch5ujm00
> Content-Disposition: attachment; filename=a3.diff
>
> With a quick check, gmail indeed does send them as binary as default
> when using Opera. Then I configured Opera to understand diff files (eg.
> that they are "text/plain"), after that gmail sent patches nicely.
> Perhaps you could add new MIME type to your web browser to handle "diff"
> file extesions as "text/plain"?

I'm using firefox, is there a way to add MIME types ? or maybe i can
rename the patch files as *.txt.

-- 
Bean



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-10  5:33   ` Bean
  2008-02-10  9:22     ` Vesa Jääskeläinen
@ 2008-02-10 18:27     ` walt
  2008-02-10 22:28       ` Bean
  1 sibling, 1 reply; 37+ messages in thread
From: walt @ 2008-02-10 18:27 UTC (permalink / raw)
  To: grub-devel

Bean wrote:
> On Feb 10, 2008 5:57 AM, walt<wa1ter@myrealbox.com>  wrote:
>> Bean wrote:
>>> Hi,
>>>
>>> This patch add a.out support for multiboot. It also support the boot2
>>> loader (a.out format) of freebsd:
>>>
>>> set root=(hd0,0,a)
>>> aout_freebsd /boot/loader
>>> boot
>>>
> ...
> i'm using the web interface to send patch, maybe it cause some
> problem. here is the raw diff file, it should be fine.

Yes, the patch is perfect this time, thanks.  I'm still seeing
two (small?) problems with aout /boot/loader.

The FreeBSD loader has a variable 'currdev' that is not being
set correctly.  'currdev' must point to the partition containing
/boot/kernel, otherwise loader will say "can't load 'kernel'".
If I use the loader interactive shell to set currdev to the
correct partition then it will boot the kernel correctly.

Well, almost correctly :o)  The second problem is that once the
kernel starts running, the console never shows the normal dmesg
messages.  I thought the kernel had died or rebooted until I saw
the normal login prompt finally appear.  Is this maybe some setting
for the console that I can change in grub2 before starting loader?

Thanks for all your time and help with this!




^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-10 18:27     ` walt
@ 2008-02-10 22:28       ` Bean
  2008-02-11 14:11         ` walt
  0 siblings, 1 reply; 37+ messages in thread
From: Bean @ 2008-02-10 22:28 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 580 bytes --]

Hi,

The following patch support freebsd a.out and elf, now you can load
the kernel directly.

1. Boot through loader:

set root=(hd0,0,a)
freebsd /boot/loader

It should be able to deduce the root device from the root variable.

2. Booting directly:
freebsd (hd0,0,a)/boot/kernel/kernel
freebsd_loadenv (hd0,0,a)/boot/devices.hints
set FreeBSD.vfs.root.mountfrom=ufs:ad0s1a

environment variable for FreeBSD has the FreeBSD. prefix, the prefix
is removed before jumping to kernel code.

Please note that you need to set root device explicitly using
vfs.root.mountfrom.

-- 
Bean

[-- Attachment #2: a4.diff --]
[-- Type: text/plain, Size: 20773 bytes --]

diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 78e4f00..430055b 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -146,7 +146,8 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
 	_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod	\
 	vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
 	videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod	\
-	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod
+	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \
+	aout.mod _freebsd.mod freebsd.mod
 
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -298,4 +299,19 @@ lspci_mod_SOURCES = commands/lspci.c
 lspci_mod_CFLAGS = $(COMMON_CFLAGS)
 lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For aout.mod
+aout_mod_SOURCES = loader/aout.c
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _freebsd.mod
+_freebsd_mod_SOURCES = loader/i386/pc/freebsd.c
+_freebsd_mod_CFLAGS = $(COMMON_CFLAGS)
+_freebsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For freebsd.mod
+freebsd_mod_SOURCES = loader/i386/pc/freebsd_normal.c
+freebsd_mod_CFLAGS = $(COMMON_CFLAGS)
+freebsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff --git a/include/grub/aout.h b/include/grub/aout.h
new file mode 100755
index 0000000..3243b82
--- /dev/null
+++ b/include/grub/aout.h
@@ -0,0 +1,91 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_AOUT_HEADER
+#define GRUB_AOUT_HEADER 1
+
+#include <grub/types.h>
+
+struct grub_aout32_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint32_t a_text;		/* text segment size */
+  grub_uint32_t a_data;		/* initialized data size */
+  grub_uint32_t a_bss;		/* uninitialized data size */
+  grub_uint32_t a_syms;		/* symbol table size */
+  grub_uint32_t a_entry;	/* entry point */
+  grub_uint32_t a_trsize;	/* text relocation size */
+  grub_uint32_t a_drsize;	/* data relocation size */
+};
+
+struct grub_aout64_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint64_t a_text;		/* text segment size */
+  grub_uint64_t a_data;		/* initialized data size */
+  grub_uint64_t a_bss;		/* uninitialized data size */
+  grub_uint64_t a_syms;		/* symbol table size */
+  grub_uint64_t a_entry;	/* entry point */
+  grub_uint64_t a_trsize;	/* text relocation size */
+  grub_uint64_t a_drsize;	/* data relocation size */
+};
+
+union grub_aout_header
+{
+  struct grub_aout32_header aout32;
+  struct grub_aout64_header aout64;
+};
+
+#define AOUT_TYPE_NONE		0
+#define AOUT_TYPE_AOUT32	1
+#define AOUT_TYPE_AOUT64	6
+
+#define	AOUT32_OMAGIC		0x107	/* 0407 old impure format */
+#define	AOUT32_NMAGIC		0x108	/* 0410 read-only text */
+#define	AOUT32_ZMAGIC		0x10b	/* 0413 demand load format */
+#define AOUT32_QMAGIC		0xcc	/* 0314 "compact" demand load format */
+
+#define AOUT64_OMAGIC		0x1001
+#define AOUT64_ZMAGIC		0x1002
+#define AOUT64_NMAGIC		0x1003
+
+#define	AOUT_MID_ZERO		0	/* unknown - implementation dependent */
+#define	AOUT_MID_SUN010		1	/* sun 68010/68020 binary */
+#define	AOUT_MID_SUN020		2	/* sun 68020-only binary */
+#define AOUT_MID_I386		134	/* i386 BSD binary */
+#define AOUT_MID_SPARC		138	/* sparc */
+#define	AOUT_MID_HP200		200	/* hp200 (68010) BSD binary */
+#define	AOUT_MID_HP300		300	/* hp300 (68020+68881) BSD binary */
+#define	AOUT_MID_HPUX		0x20C	/* hp200/300 HP-UX binary */
+#define	AOUT_MID_HPUX800	0x20B	/* hp800 HP-UX binary */
+
+#define AOUT_FLAG_PIC		0x10	/* contains position independant code */
+#define AOUT_FLAG_DYNAMIC	0x20	/* contains run-time link-edit info */
+#define AOUT_FLAG_DPMASK	0x30	/* mask for the above */
+
+#define AOUT_GETMAGIC(header) ((header).a_midmag & 0xffff)
+#define AOUT_GETMID(header) ((header).a_midmag >> 16) & 0x03ff)
+#define AOUT_GETFLAG(header) ((header).a_midmag >> 26) & 0x3f)
+
+int EXPORT_FUNC(grub_aout_get_type) (union grub_aout_header *header);
+
+grub_err_t EXPORT_FUNC(grub_aout_load) (grub_file_t file, int offset,
+                                        grub_addr_t load_addr, int load_size,
+                                        grub_addr_t bss_end_addr);
+
+#endif /* ! GRUB_AOUT_HEADER */
diff --git a/include/grub/i386/loader.h b/include/grub/i386/loader.h
index 45a1652..c0b10e5 100644
--- a/include/grub/i386/loader.h
+++ b/include/grub/i386/loader.h
@@ -39,10 +39,17 @@ void EXPORT_FUNC(grub_multiboot_real_boot) (grub_addr_t entry,
 void EXPORT_FUNC(grub_multiboot2_real_boot) (grub_addr_t entry,
                                              struct grub_multiboot_info *mbi)
      __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_freebsd_real_boot) (grub_addr_t entry,
+                                          grub_uint32_t bootdrv,
+                                          void *bootinfo)
+     __attribute__ ((noreturn));
+
 
 /* It is necessary to export these functions, because normal mode commands
    reuse rescue mode commands.  */
 void grub_rescue_cmd_linux (int argc, char *argv[]);
 void grub_rescue_cmd_initrd (int argc, char *argv[]);
+void grub_rescue_cmd_freebsd (int argc, char *argv[]);
+void grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[]);
 
 #endif /* ! GRUB_LOADER_CPU_HEADER */
diff --git a/kern/elf.c b/kern/elf.c
index ca10b5b..3e90ea0 100644
--- a/kern/elf.c
+++ b/kern/elf.c
@@ -228,9 +228,9 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
     if (phdr->p_type != PT_LOAD)
       return 0;
 
-    load_addr = phdr->p_paddr;
     if (load_hook && load_hook (phdr, &load_addr))
       return 1;
+    load_addr = phdr->p_paddr;
 
     if (load_addr < load_base)
       load_base = load_addr;
@@ -407,9 +407,9 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
     if (phdr->p_type != PT_LOAD)
       return 0;
 
-    load_addr = phdr->p_paddr;
     if (load_hook && load_hook (phdr, &load_addr))
       return 1;
+    load_addr = phdr->p_paddr;
 
     if (load_addr < load_base)
       load_base = load_addr;
diff --git a/kern/i386/loader.S b/kern/i386/loader.S
index 266f4ef..6c5a5c1 100644
--- a/kern/i386/loader.S
+++ b/kern/i386/loader.S
@@ -162,3 +162,24 @@ FUNCTION(grub_multiboot2_real_boot)
         movl    $MULTIBOOT2_BOOTLOADER_MAGIC,%eax 
         popl    %ecx
         jmp     *%ecx
+
+
+#define FREEBSD_RB_BOOTINFO	0x80000000
+
+FUNCTION(grub_freebsd_real_boot)
+	pushl	%ecx
+	xorl	%ecx, %ecx
+	pushl	%ecx
+	pushl	%ecx
+	pushl	%ecx
+        pushl   %edx
+        pushl	$FREEBSD_RB_BOOTINFO
+        pushl	%eax
+
+        call    EXT_C(grub_dl_unload_all)
+        call    EXT_C(grub_stop_floppy)
+
+        cli
+
+        popl    %ecx
+        call    *%ecx
diff --git a/loader/aout.c b/loader/aout.c
new file mode 100755
index 0000000..2c82b60
--- /dev/null
+++ b/loader/aout.c
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ *  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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+int
+grub_aout_get_type (union grub_aout_header *header)
+{
+  int magic;
+
+  magic = AOUT_GETMAGIC (header->aout32);
+  if ((magic == AOUT32_OMAGIC) || (magic == AOUT32_NMAGIC) ||
+      (magic == AOUT32_ZMAGIC) || (magic == AOUT32_QMAGIC))
+    return AOUT_TYPE_AOUT32;
+  else if ((magic == AOUT64_OMAGIC) || (magic == AOUT64_NMAGIC) ||
+	   (magic == AOUT64_ZMAGIC))
+    return AOUT_TYPE_AOUT64;
+  else
+    return AOUT_TYPE_NONE;
+}
+
+grub_err_t
+grub_aout_load (grub_file_t file, int offset,
+                grub_addr_t load_addr,
+		int load_size,
+                grub_addr_t bss_end_addr)
+{
+  if ((grub_file_seek (file, offset)) == (grub_off_t) - 1)
+    return grub_errno;
+
+  if (!load_size)
+    load_size = file->size - offset;
+
+  grub_file_read (file, (char *) load_addr, load_size);
+
+  if (grub_errno)
+    return grub_errno;
+
+  if (bss_end_addr)
+    grub_memset (load_addr + load_size, 0,
+                 bss_end_addr - load_addr - load_size);
+
+  return GRUB_ERR_NONE;
+}
diff --git a/loader/i386/pc/freebsd.c b/loader/i386/pc/freebsd.c
new file mode 100755
index 0000000..3c744aa
--- /dev/null
+++ b/loader/i386/pc/freebsd.c
@@ -0,0 +1,361 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/elfload.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+#include <grub/aout.h>
+
+#define BOOTINFO_VERSION        1
+#define N_BIOS_GEOM             8
+#define B_DEVMAGIC		0xa0000000
+#define BASE_SLICE		2
+
+struct grub_freebsd_bootinfo
+{
+  grub_uint32_t bi_version;
+  grub_uint8_t *bi_kernelname;
+  struct nfs_diskless *bi_nfs_diskless;
+  grub_uint32_t bi_n_bios_used;
+  grub_uint32_t bi_bios_geom[N_BIOS_GEOM];
+  grub_uint32_t bi_size;
+  grub_uint8_t bi_memsizes_valid;
+  grub_uint8_t bi_bios_dev;
+  grub_uint8_t bi_pad[2];
+  grub_uint32_t bi_basemem;
+  grub_uint32_t bi_extmem;
+  grub_uint32_t bi_symtab;
+  grub_uint32_t bi_esymtab;
+  grub_uint32_t bi_kernend;
+  grub_uint32_t bi_envp;
+  grub_uint32_t bi_modulep;
+} __attribute__ ((packed));
+
+static grub_dl_t my_mod;
+
+static grub_addr_t entry, kernend;
+
+static grub_err_t
+grub_freebsd_boot (void)
+{
+  struct grub_freebsd_bootinfo bi;
+  char *p;
+  grub_uint32_t bootdev;
+
+  auto int iterate_env (struct grub_env_var *var);
+  int iterate_env (struct grub_env_var *var)
+  {
+    if ((!grub_memcmp (var->name, "FreeBSD.", 8)) && (var->name[8]))
+      {
+	grub_strcpy (p, &var->name[8]);
+	p += grub_strlen (p);
+	*(p++) = '=';
+	grub_strcpy (p, var->value);
+	p += grub_strlen (p) + 1;
+      }
+
+    return 0;
+  }
+
+  grub_memset (&bi, 0, sizeof (bi));
+  bi.bi_version = BOOTINFO_VERSION;
+  bi.bi_size = sizeof (bi);
+
+  bootdev = B_DEVMAGIC + (BASE_SLICE << 20);
+
+  p = grub_env_get ("root");
+  if ((p) && ((p[0] == 'h') || (p[0] == 'f')) && (p[1] == 'd') &&
+      (p[2] >= '0') && (p[2] <= '9'))
+    {
+      if (p[0] == 'h')
+	bi.bi_bios_dev = 0x80;
+
+      bi.bi_bios_dev += grub_strtoul (p + 2, &p, 0);
+
+      if ((p) && (p[0] == ',') && (p[1] >= '0') && (p[1] <= '9'))
+	{
+	  /* Partition number.  */
+	  bootdev |= (grub_strtoul (p + 1, &p, 0)) << 8;
+
+	  /* Unit number.  */
+	  bootdev |= (bi.bi_bios_dev & 0x7F) << 16;
+	}
+    }
+
+  kernend = (kernend + 3) & (~3);
+  p = (char *) kernend;
+
+  grub_env_iterate (iterate_env);
+
+  if (p != (char *) kernend)
+    {
+      *(p++) = 0;
+
+      bi.bi_envp = kernend;
+      bi.bi_kernend = ((grub_uint32_t) p + 3) & (~3);
+    }
+  else
+    bi.bi_kernend = kernend;
+
+  grub_freebsd_real_boot (entry, bootdev, &bi);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_freebsd_unload (void)
+{
+  grub_dl_unref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_load_aout (grub_file_t file, union grub_aout_header *ah)
+{
+  grub_addr_t load_addr, bss_end_addr;
+  int ofs, align_4k;
+
+  if (grub_aout_get_type (ah) != AOUT_TYPE_AOUT32)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid a.out header");
+
+  entry = ah->aout32.a_entry & 0xFFFFFF;
+
+  if (AOUT_GETMAGIC (ah->aout32) == AOUT32_ZMAGIC)
+    {
+      load_addr = entry;
+      ofs = 0x1000;
+      align_4k = 0;
+    }
+  else
+    {
+      load_addr = entry & 0xF00000;
+      ofs = sizeof (struct grub_aout32_header);
+      align_4k = 1;
+    }
+
+  if (load_addr < 0x100000)
+    return grub_error (GRUB_ERR_BAD_OS, "load address below 1M");
+
+  kernend = load_addr + ah->aout32.a_text + ah->aout32.a_data;
+  if (align_4k)
+    kernend = (kernend + 0xFFF) & 0xFFFFF000;
+
+  if (ah->aout32.a_bss)
+    {
+      kernend += ah->aout32.a_bss;
+      if (align_4k)
+	kernend = (kernend + 0xFFF) & 0xFFFFF000;
+
+      bss_end_addr = kernend;
+    }
+  else
+    bss_end_addr = 0;
+
+  return grub_aout_load (file, ofs, load_addr,
+			 ah->aout32.a_text + ah->aout32.a_data, bss_end_addr);
+}
+
+static grub_err_t
+grub_bsd_elf32_hook (Elf32_Phdr * phdr, UNUSED grub_addr_t * addr)
+{
+  Elf32_Addr paddr;
+
+  phdr->p_paddr &= 0xFFFFFF;
+  paddr = phdr->p_paddr;
+
+  if ((paddr < grub_os_area_addr)
+      || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Address 0x%x is out of range",
+		       paddr);
+
+  if (paddr + phdr->p_memsz > kernend)
+    kernend = paddr + phdr->p_memsz;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_load_elf (grub_file_t file)
+{
+  grub_elf_t elf = 0;
+  grub_err_t err;
+
+  kernend = 0;
+  elf = grub_elf_file (file);
+  if (!elf)
+    return grub_errno;
+
+  if (grub_elf_is_elf32 (elf))
+    {
+      entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF;
+      err = grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0);
+    }
+  else
+    err = grub_error (GRUB_ERR_BAD_OS, "invalid elf");
+
+  return err;
+}
+
+void
+grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  char *buf = 0, *curr, *next;
+  int len;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no filename");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if ((!file) || (!file->size))
+    goto fail;
+
+  len = file->size;
+  buf = grub_malloc (len + 1);
+  if (!buf)
+    goto fail;
+
+  if (grub_file_read (file, buf, len) != len)
+    goto fail;
+
+  buf[len] = 0;
+
+  next = buf;
+  while (next)
+    {
+      char *p;
+
+      curr = next;
+      next = grub_strchr (curr, '\n');
+      if (next)
+	{
+
+	  p = next - 1;
+	  while (p > curr)
+	    {
+	      if ((*p != '\r') && (*p != ' ') && (*p != '\t'))
+		break;
+	      p--;
+	    }
+
+	  if ((p > curr) && (*p == '"'))
+	    p--;
+
+	  *(p + 1) = 0;
+	  next++;
+	}
+
+      if (*curr == '#')
+	continue;
+
+      p = grub_strchr (curr, '=');
+      if (!p)
+	continue;
+
+      *(p++) = 0;
+
+      if (*curr)
+	{
+	  char name[grub_strlen (curr) + 8 + 1];
+
+	  if (*p == '"')
+	    p++;
+
+	  grub_sprintf (name, "FreeBSD.%s", curr);
+	  if (grub_env_set (name, p))
+	    goto fail;
+	}
+    }
+
+fail:
+  grub_free (buf);
+
+  if (file)
+    grub_file_close (file);
+}
+
+void
+grub_rescue_cmd_freebsd (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  union grub_aout_header ah;
+
+  grub_dl_ref (my_mod);
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (!file)
+    goto fail;
+
+  if (grub_file_read (file, (char *) &ah, sizeof (ah)) != sizeof (ah))
+    {
+      grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header");
+      goto fail;
+    }
+
+  if (grub_aout_get_type (&ah) == AOUT_TYPE_NONE)
+    grub_bsd_load_elf (file);
+  else
+    grub_bsd_load_aout (file, &ah);
+
+  if (grub_errno == GRUB_ERR_NONE)
+    grub_loader_set (grub_freebsd_boot, grub_freebsd_unload, 1);
+
+fail:
+
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    grub_dl_unref (my_mod);
+}
+
+GRUB_MOD_INIT (aout_freebsd)
+{
+  grub_rescue_register_command ("freebsd",
+				grub_rescue_cmd_freebsd,
+				"load freebsd loader");
+  grub_rescue_register_command ("freebsd_loadenv",
+				grub_rescue_cmd_freebsd_loadenv,
+				"load freebsd env");
+
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI (aout_freebsd)
+{
+  grub_rescue_unregister_command ("freebsd");
+  grub_rescue_unregister_command ("freebsd_loadenv");
+}
diff --git a/loader/i386/pc/freebsd_normal.c b/loader/i386/pc/freebsd_normal.c
new file mode 100755
index 0000000..f9f7d47
--- /dev/null
+++ b/loader/i386/pc/freebsd_normal.c
@@ -0,0 +1,60 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+static grub_err_t
+grub_normal_freebsd_command (struct grub_arg_list *state
+			     __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_freebsd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_freebsd_loadenv_command (struct grub_arg_list *state
+				     __attribute__ ((unused)), int argc,
+				     char **args)
+{
+  grub_rescue_cmd_freebsd_loadenv (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT (aout_freebsd_normal)
+{
+  (void) mod;			/* To stop warning.  */
+  grub_register_command ("freebsd", grub_normal_freebsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "aout_freebsd FILE [ARGS...]",
+			 "Load freebsd loader.", 0);
+  grub_register_command ("freebsd_loadenv",
+			 grub_normal_freebsd_loadenv_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "freebsd_loadenv FILE", "Load freebsd env.", 0);
+}
+
+GRUB_MOD_FINI (aout_freebsd_normal)
+{
+  grub_unregister_command ("freebsd");
+  grub_unregister_command ("freebsd_loadenv");
+}
diff --git a/loader/i386/pc/multiboot.c b/loader/i386/pc/multiboot.c
index 893f11b..e9fcc4a 100644
--- a/loader/i386/pc/multiboot.c
+++ b/loader/i386/pc/multiboot.c
@@ -36,6 +36,7 @@
 #include <grub/machine/init.h>
 #include <grub/machine/memory.h>
 #include <grub/elf.h>
+#include <grub/aout.h>
 #include <grub/file.h>
 #include <grub/err.h>
 #include <grub/rescue.h>
@@ -315,7 +316,18 @@ grub_multiboot (int argc, char *argv[])
       goto fail;
     }
 
-  if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
+  if (header->flags & MULTIBOOT_AOUT_KLUDGE)
+    {
+      if ((grub_aout_load (file, (char *) header - buffer, header->load_addr,
+                           ((header->load_end_addr == 0) ? 0 :
+                            header->load_end_addr - header->load_addr),
+                           header->bss_end_addr))
+          !=GRUB_ERR_NONE)
+        goto fail;
+
+      entry = header->entry_addr;
+    }
+  else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
     goto fail;
   
   mbi = grub_malloc (sizeof (struct grub_multiboot_info));

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-10 22:28       ` Bean
@ 2008-02-11 14:11         ` walt
  2008-02-11 14:28           ` Bean
  0 siblings, 1 reply; 37+ messages in thread
From: walt @ 2008-02-11 14:11 UTC (permalink / raw)
  To: grub-devel

Bean wrote:
> Hi,
>
> The following patch support freebsd a.out and elf, now you can load
> the kernel directly.
>
> 1. Boot through loader:
>
> set root=(hd0,0,a)
> freebsd /boot/loader
>
> It should be able to deduce the root device from the root variable.

I still see currdev=disk0s1c but that should be s1a, not s1c.

>
> 2. Booting directly:
> freebsd (hd0,0,a)/boot/kernel/kernel

At this point I see 'broken magic at 0x6b30'.  I'm running FreeBSD
CURRENT, not stable.  Could that be the problem?




^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-11 14:11         ` walt
@ 2008-02-11 14:28           ` Bean
  2008-02-11 20:45             ` Bean
  0 siblings, 1 reply; 37+ messages in thread
From: Bean @ 2008-02-11 14:28 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 938 bytes --]

On Feb 11, 2008 10:11 PM, walt <wa1ter@myrealbox.com> wrote:
> Bean wrote:
> > Hi,
> >
> > The following patch support freebsd a.out and elf, now you can load
> > the kernel directly.
> >
> > 1. Boot through loader:
> >
> > set root=(hd0,0,a)
> > freebsd /boot/loader
> >
> > It should be able to deduce the root device from the root variable.
>
> I still see currdev=disk0s1c but that should be s1a, not s1c.

i found a small bug in the root device calculation, the new patch
below should be ok.

> >
> > 2. Booting directly:
> > freebsd (hd0,0,a)/boot/kernel/kernel
>
> At this point I see 'broken magic at 0x6b30'.  I'm running FreeBSD
> CURRENT, not stable.  Could that be the problem?

I'm testing FreeBSD 6.3, the 7 series haven't been tried yet. Perhaps
you can upload the kernel file somewhere for me to check.

The patch also contain incomplete support for openbsd kernel, it's not
working yet, you can just ignore it.

-- 
Bean

[-- Attachment #2: a5.diff --]
[-- Type: text/plain, Size: 28748 bytes --]

diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 78e4f00..430055b 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -146,7 +146,8 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
 	_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod	\
 	vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
 	videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod	\
-	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod
+	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \
+	aout.mod _freebsd.mod freebsd.mod
 
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -298,4 +299,19 @@ lspci_mod_SOURCES = commands/lspci.c
 lspci_mod_CFLAGS = $(COMMON_CFLAGS)
 lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For aout.mod
+aout_mod_SOURCES = loader/aout.c
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _freebsd.mod
+_freebsd_mod_SOURCES = loader/i386/pc/freebsd.c
+_freebsd_mod_CFLAGS = $(COMMON_CFLAGS)
+_freebsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For freebsd.mod
+freebsd_mod_SOURCES = loader/i386/pc/freebsd_normal.c
+freebsd_mod_CFLAGS = $(COMMON_CFLAGS)
+freebsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff --git a/include/grub/aout.h b/include/grub/aout.h
new file mode 100755
index 0000000..3243b82
--- /dev/null
+++ b/include/grub/aout.h
@@ -0,0 +1,91 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_AOUT_HEADER
+#define GRUB_AOUT_HEADER 1
+
+#include <grub/types.h>
+
+struct grub_aout32_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint32_t a_text;		/* text segment size */
+  grub_uint32_t a_data;		/* initialized data size */
+  grub_uint32_t a_bss;		/* uninitialized data size */
+  grub_uint32_t a_syms;		/* symbol table size */
+  grub_uint32_t a_entry;	/* entry point */
+  grub_uint32_t a_trsize;	/* text relocation size */
+  grub_uint32_t a_drsize;	/* data relocation size */
+};
+
+struct grub_aout64_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint64_t a_text;		/* text segment size */
+  grub_uint64_t a_data;		/* initialized data size */
+  grub_uint64_t a_bss;		/* uninitialized data size */
+  grub_uint64_t a_syms;		/* symbol table size */
+  grub_uint64_t a_entry;	/* entry point */
+  grub_uint64_t a_trsize;	/* text relocation size */
+  grub_uint64_t a_drsize;	/* data relocation size */
+};
+
+union grub_aout_header
+{
+  struct grub_aout32_header aout32;
+  struct grub_aout64_header aout64;
+};
+
+#define AOUT_TYPE_NONE		0
+#define AOUT_TYPE_AOUT32	1
+#define AOUT_TYPE_AOUT64	6
+
+#define	AOUT32_OMAGIC		0x107	/* 0407 old impure format */
+#define	AOUT32_NMAGIC		0x108	/* 0410 read-only text */
+#define	AOUT32_ZMAGIC		0x10b	/* 0413 demand load format */
+#define AOUT32_QMAGIC		0xcc	/* 0314 "compact" demand load format */
+
+#define AOUT64_OMAGIC		0x1001
+#define AOUT64_ZMAGIC		0x1002
+#define AOUT64_NMAGIC		0x1003
+
+#define	AOUT_MID_ZERO		0	/* unknown - implementation dependent */
+#define	AOUT_MID_SUN010		1	/* sun 68010/68020 binary */
+#define	AOUT_MID_SUN020		2	/* sun 68020-only binary */
+#define AOUT_MID_I386		134	/* i386 BSD binary */
+#define AOUT_MID_SPARC		138	/* sparc */
+#define	AOUT_MID_HP200		200	/* hp200 (68010) BSD binary */
+#define	AOUT_MID_HP300		300	/* hp300 (68020+68881) BSD binary */
+#define	AOUT_MID_HPUX		0x20C	/* hp200/300 HP-UX binary */
+#define	AOUT_MID_HPUX800	0x20B	/* hp800 HP-UX binary */
+
+#define AOUT_FLAG_PIC		0x10	/* contains position independant code */
+#define AOUT_FLAG_DYNAMIC	0x20	/* contains run-time link-edit info */
+#define AOUT_FLAG_DPMASK	0x30	/* mask for the above */
+
+#define AOUT_GETMAGIC(header) ((header).a_midmag & 0xffff)
+#define AOUT_GETMID(header) ((header).a_midmag >> 16) & 0x03ff)
+#define AOUT_GETFLAG(header) ((header).a_midmag >> 26) & 0x3f)
+
+int EXPORT_FUNC(grub_aout_get_type) (union grub_aout_header *header);
+
+grub_err_t EXPORT_FUNC(grub_aout_load) (grub_file_t file, int offset,
+                                        grub_addr_t load_addr, int load_size,
+                                        grub_addr_t bss_end_addr);
+
+#endif /* ! GRUB_AOUT_HEADER */
diff --git a/include/grub/i386/bsd.h b/include/grub/i386/bsd.h
new file mode 100755
index 0000000..079a8f8
--- /dev/null
+++ b/include/grub/i386/bsd.h
@@ -0,0 +1,131 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_BSD_CPU_HEADER
+#define GRUB_BSD_CPU_HEADER	1
+
+#include <grub/types.h>
+
+#define KERNEL_TYPE_FREEBSD	0
+#define KERNEL_TYPE_OPENBSD	1
+#define KERNEL_TYPE_NETBSD	2
+
+#define FREEBSD_RB_ASKNAME	0x01	/* ask for file name to reboot from */
+#define FREEBSD_RB_SINGLE       0x02	/* reboot to single user only */
+#define FREEBSD_RB_NOSYNC       0x04	/* dont sync before reboot */
+#define FREEBSD_RB_HALT         0x08	/* don't reboot, just halt */
+#define FREEBSD_RB_INITNAME     0x10	/* name given for /etc/init (unused) */
+#define FREEBSD_RB_DFLTROOT     0x20	/* use compiled-in rootdev */
+#define FREEBSD_RB_KDB          0x40	/* give control to kernel debugger */
+#define FREEBSD_RB_RDONLY       0x80	/* mount root fs read-only */
+#define FREEBSD_RB_DUMP         0x100	/* dump kernel memory before reboot */
+#define FREEBSD_RB_MINIROOT     0x200	/* mini-root present in memory at boot time */
+#define FREEBSD_RB_CONFIG       0x400	/* invoke user configuration routing */
+#define FREEBSD_RB_VERBOSE      0x800	/* print all potentially useful info */
+#define FREEBSD_RB_SERIAL       0x1000	/* user serial port as console */
+#define FREEBSD_RB_CDROM        0x2000	/* use cdrom as root */
+#define FREEBSD_RB_GDB		0x8000	/* use GDB remote debugger instead of DDB */
+#define FREEBSD_RB_MUTE		0x10000	/* Come up with the console muted */
+#define FREENSD_RB_MULTIPLE	0x20000000 /* Use multiple consoles */
+#define FREEBSD_RB_BOOTINFO     0x80000000 /* have `struct bootinfo *' arg */
+
+#define FREEBSD_B_DEVMAGIC	0xa0000000
+#define FREEBSD_B_SLICESHIFT	20
+#define FREEBSD_B_UNITSHIFT	16
+#define FREEBSD_B_PARTSHIFT	8
+#define FREEBSD_B_TYPESHIFT	0
+
+#define FREEBSD_BOOTINFO_VERSION 1
+#define FREEBSD_N_BIOS_GEOM	8
+
+struct grub_freebsd_bootinfo
+{
+  grub_uint32_t bi_version;
+  grub_uint8_t *bi_kernelname;
+  struct nfs_diskless *bi_nfs_diskless;
+  grub_uint32_t bi_n_bios_used;
+  grub_uint32_t bi_bios_geom[FREEBSD_N_BIOS_GEOM];
+  grub_uint32_t bi_size;
+  grub_uint8_t bi_memsizes_valid;
+  grub_uint8_t bi_bios_dev;
+  grub_uint8_t bi_pad[2];
+  grub_uint32_t bi_basemem;
+  grub_uint32_t bi_extmem;
+  grub_uint32_t bi_symtab;
+  grub_uint32_t bi_esymtab;
+  grub_uint32_t bi_kernend;
+  grub_uint32_t bi_envp;
+  grub_uint32_t bi_modulep;
+} __attribute__ ((packed));
+
+#define OPENBSD_RB_ASKNAME	0x0001  /* ask for file name to reboot from */
+#define OPENBSD_RB_SINGLE	0x0002  /* reboot to single user only */
+#define OPENBSD_RB_NOSYNC	0x0004  /* dont sync before reboot */
+#define OPENBSD_RB_HALT		0x0008  /* don't reboot, just halt */
+#define OPENBSD_RB_INITNAME	0x0010  /* name given for /etc/init (unused) */
+#define OPENBSD_RB_DFLTROOT	0x0020  /* use compiled-in rootdev */
+#define OPENBSD_RB_KDB		0x0040  /* give control to kernel debugger */
+#define OPENBSD_RB_RDONLY	0x0080  /* mount root fs read-only */
+#define OPENBSD_RB_DUMP		0x0100  /* dump kernel memory before reboot */
+#define OPENBSD_RB_MINIROOT	0x0200  /* mini-root present in memory at boot time */
+#define OPENBSD_RB_CONFIG	0x0400  /* change configured devices */
+#define OPENBSD_RB_TIMEBAD	0x0800  /* don't call resettodr() in boot() */
+#define OPENBSD_RB_POWERDOWN	0x1000  /* attempt to power down machine */
+#define OPENBSD_RB_SERCONS	0x2000  /* use serial console if available */
+#define OPENBSD_RB_USERREQ	0x4000  /* boot() called at user request (e.g. ddb) */
+
+#define OPENBSD_B_DEVMAGIC	0xa0000000
+#define OPENBSD_B_ADAPTORSHIFT	24
+#define OPENBSD_B_CTRLSHIFT	20
+#define OPENBSD_B_UNITSHIFT	16
+#define OPENBSD_B_PARTSHIFT	8
+#define OPENBSD_B_TYPESHIFT	0
+
+#define OPENBSD_BOOTARG_APIVER	(OPENBSD_BAPIV_VECTOR | \
+                                 OPENBSD_BAPIV_ENV | \
+                                 OPENBSD_BAPIV_BMEMMAP)
+
+#define OPENBSD_BAPIV_ANCIENT	0x0  /* MD old i386 bootblocks */
+#define OPENBSD_BAPIV_VARS	0x1  /* MD structure w/ add info passed */
+#define OPENBSD_BAPIV_VECTOR	0x2  /* MI vector of MD structures passed */
+#define OPENBSD_BAPIV_ENV	0x4  /* MI environment vars vector */
+#define OPENBSD_BAPIV_BMEMMAP	0x8  /* MI memory map passed is in bytes */
+
+#define OPENBSD_BOOTARG_ENV	0x1000
+#define OPENBSD_BOOTARG_END	-1
+
+#define OPENBSD_BOOTARG_CONSDEV	5
+
+#define OPENBSD_MAKEDEV(x,y)    ((((x) & 0xff) << 8) | \
+                                 ((y) & 0xff) | \
+                                 (((y) & 0xffff00) << 8))
+
+struct grub_openbsd_consdev
+{
+  grub_uint32_t	consdev;
+  grub_uint32_t conspeed;
+} __attribute__ ((packed));
+
+struct grub_openbsd_bootargs
+{
+  grub_uint32_t ba_type;
+  grub_uint32_t ba_size;
+  struct grub_openbsd_bootargs *ba_next;
+} __attribute__ ((packed));
+
+#endif /* ! GRUB_BSD_CPU_HEADER */
diff --git a/include/grub/i386/loader.h b/include/grub/i386/loader.h
index 45a1652..262fd9f 100644
--- a/include/grub/i386/loader.h
+++ b/include/grub/i386/loader.h
@@ -39,10 +39,16 @@ void EXPORT_FUNC(grub_multiboot_real_boot) (grub_addr_t entry,
 void EXPORT_FUNC(grub_multiboot2_real_boot) (grub_addr_t entry,
                                              struct grub_multiboot_info *mbi)
      __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_unix_real_boot) (grub_addr_t entry, ...)
+     __attribute__ ((cdecl,noreturn));
+
 
 /* It is necessary to export these functions, because normal mode commands
    reuse rescue mode commands.  */
 void grub_rescue_cmd_linux (int argc, char *argv[]);
 void grub_rescue_cmd_initrd (int argc, char *argv[]);
+void grub_rescue_cmd_freebsd (int argc, char *argv[]);
+void grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[]);
+void grub_rescue_cmd_openbsd (int argc, char *argv[]);
 
 #endif /* ! GRUB_LOADER_CPU_HEADER */
diff --git a/kern/elf.c b/kern/elf.c
index ca10b5b..3e90ea0 100644
--- a/kern/elf.c
+++ b/kern/elf.c
@@ -228,9 +228,9 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
     if (phdr->p_type != PT_LOAD)
       return 0;
 
-    load_addr = phdr->p_paddr;
     if (load_hook && load_hook (phdr, &load_addr))
       return 1;
+    load_addr = phdr->p_paddr;
 
     if (load_addr < load_base)
       load_base = load_addr;
@@ -407,9 +407,9 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
     if (phdr->p_type != PT_LOAD)
       return 0;
 
-    load_addr = phdr->p_paddr;
     if (load_hook && load_hook (phdr, &load_addr))
       return 1;
+    load_addr = phdr->p_paddr;
 
     if (load_addr < load_base)
       load_base = load_addr;
diff --git a/kern/i386/loader.S b/kern/i386/loader.S
index 266f4ef..c8dd30a 100644
--- a/kern/i386/loader.S
+++ b/kern/i386/loader.S
@@ -162,3 +162,14 @@ FUNCTION(grub_multiboot2_real_boot)
         movl    $MULTIBOOT2_BOOTLOADER_MAGIC,%eax 
         popl    %ecx
         jmp     *%ecx
+
+
+FUNCTION(grub_unix_real_boot)
+        call    EXT_C(grub_dl_unload_all)
+        call    EXT_C(grub_stop_floppy)
+
+        cli
+
+        popl    %eax
+        popl	%eax
+        call	*%eax
diff --git a/loader/aout.c b/loader/aout.c
new file mode 100755
index 0000000..2c82b60
--- /dev/null
+++ b/loader/aout.c
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ *  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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+int
+grub_aout_get_type (union grub_aout_header *header)
+{
+  int magic;
+
+  magic = AOUT_GETMAGIC (header->aout32);
+  if ((magic == AOUT32_OMAGIC) || (magic == AOUT32_NMAGIC) ||
+      (magic == AOUT32_ZMAGIC) || (magic == AOUT32_QMAGIC))
+    return AOUT_TYPE_AOUT32;
+  else if ((magic == AOUT64_OMAGIC) || (magic == AOUT64_NMAGIC) ||
+	   (magic == AOUT64_ZMAGIC))
+    return AOUT_TYPE_AOUT64;
+  else
+    return AOUT_TYPE_NONE;
+}
+
+grub_err_t
+grub_aout_load (grub_file_t file, int offset,
+                grub_addr_t load_addr,
+		int load_size,
+                grub_addr_t bss_end_addr)
+{
+  if ((grub_file_seek (file, offset)) == (grub_off_t) - 1)
+    return grub_errno;
+
+  if (!load_size)
+    load_size = file->size - offset;
+
+  grub_file_read (file, (char *) load_addr, load_size);
+
+  if (grub_errno)
+    return grub_errno;
+
+  if (bss_end_addr)
+    grub_memset (load_addr + load_size, 0,
+                 bss_end_addr - load_addr - load_size);
+
+  return GRUB_ERR_NONE;
+}
diff --git a/loader/i386/pc/freebsd.c b/loader/i386/pc/freebsd.c
new file mode 100755
index 0000000..40b88f1
--- /dev/null
+++ b/loader/i386/pc/freebsd.c
@@ -0,0 +1,430 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/machine/memory.h>
+#include <grub/cpu/bsd.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/elfload.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+#include <grub/aout.h>
+
+#define ALIGN_DWORD(a)	((a + 3) & (~3))
+#define ALIGN_PAGE(a)	((a + 4095) & (~4095))
+
+static int kernel_type;
+static grub_dl_t my_mod;
+static grub_addr_t entry, kernend;
+static grub_uint32_t bootflags;
+
+static void
+grub_bsd_get_device (grub_uint32_t *biosdev,
+                     grub_uint32_t *unit,
+                     grub_uint32_t *slice,
+                     grub_uint32_t *part)
+{
+  char *p;
+
+  *biosdev = *unit = *slice = *part = 0;
+  p = grub_env_get ("root");
+  if ((p) && ((p[0] == 'h') || (p[0] == 'f')) && (p[1] == 'd') &&
+      (p[2] >= '0') && (p[2] <= '9'))
+    {
+      if (p[0] == 'h')
+	*biosdev = 0x80;
+
+      *biosdev += grub_strtoul (p + 2, &p, 0);
+      *unit = (*biosdev & 0x7f);
+
+      if ((p) && (p[0] == ','))
+        {
+          if ((p[1] >= '0') && (p[1] <= '9'))
+            {
+              *slice = grub_strtoul (p + 1, &p, 0);
+
+              if ((p) && (p[0] == ','))
+                p++;
+            }
+
+          if ((p[0] >= 'a') && (p[0] <= 'z'))
+            *part = p[0] - 'a';
+	}
+    }
+}
+
+static grub_err_t
+grub_freebsd_boot (void)
+{
+  struct grub_freebsd_bootinfo bi;
+  char *p;
+  grub_uint32_t bootdev, biosdev, unit, slice, part;
+
+  auto int iterate_env (struct grub_env_var *var);
+  int iterate_env (struct grub_env_var *var)
+  {
+    if ((!grub_memcmp (var->name, "FreeBSD.", 8)) && (var->name[8]))
+      {
+	grub_strcpy (p, &var->name[8]);
+	p += grub_strlen (p);
+	*(p++) = '=';
+	grub_strcpy (p, var->value);
+	p += grub_strlen (p) + 1;
+      }
+
+    return 0;
+  }
+
+  grub_memset (&bi, 0, sizeof (bi));
+  bi.bi_version = FREEBSD_BOOTINFO_VERSION;
+  bi.bi_size = sizeof (bi);
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+  bootdev = (FREEBSD_B_DEVMAGIC + ((slice + 1) << FREEBSD_B_SLICESHIFT) +
+             (unit << FREEBSD_B_UNITSHIFT) + (part << FREEBSD_B_PARTSHIFT));
+
+  bi.bi_bios_dev = biosdev;
+
+  kernend = ALIGN_DWORD(kernend);
+  p = (char *) kernend;
+
+  grub_env_iterate (iterate_env);
+
+  if (p != (char *) kernend)
+    {
+      *(p++) = 0;
+
+      bi.bi_envp = kernend;
+      bi.bi_kernend = ALIGN_DWORD((grub_uint32_t) p);
+    }
+  else
+    bi.bi_kernend = kernend;
+
+  grub_unix_real_boot (entry, bootflags | FREEBSD_RB_BOOTINFO, bootdev,
+                       0, 0, 0, &bi, 0, 0);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_openbsd_boot (void)
+{
+  struct grub_openbsd_bootargs *p;
+  grub_uint32_t bootdev, biosdev, unit, slice, part;
+  struct grub_openbsd_consdev cd;
+
+  auto void NESTED_FUNC_ATTR add_bootarg (int type, int size, void *ptr);
+  void NESTED_FUNC_ATTR add_bootarg (int type, int size, void *ptr)
+    {
+      p->ba_type = type;
+      p->ba_size = sizeof (struct grub_openbsd_bootargs) + size;
+      p->ba_next = (struct grub_openbsd_bootargs *) ((char *) p + p->ba_size);
+      grub_memcpy ((char *) (p + 1), ptr, size);
+      p = p->ba_next;
+    }
+
+  kernend = ALIGN_DWORD(kernend);
+  p = (struct grub_openbsd_bootargs *) kernend;
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+  bootdev = (OPENBSD_B_DEVMAGIC + (unit << OPENBSD_B_UNITSHIFT) +
+             (part << OPENBSD_B_PARTSHIFT));
+
+  cd.consdev = OPENBSD_MAKEDEV(12, 0);
+  cd.conspeed = 9600;
+  add_bootarg (OPENBSD_BOOTARG_CONSDEV, sizeof(cd), &cd);
+
+  p->ba_type = OPENBSD_BOOTARG_END;
+  p->ba_next = 0;
+  p++;
+
+  bootflags;
+
+  //grub_unix_real_boot (entry, bootflags, bootdev,
+  //                     OPENBSD_BOOTARG_APIVER,
+  //                     0, 0, 0, (grub_uint32_t) p - kernend , kernend);
+
+  grub_unix_real_boot (entry, bootflags, bootdev, 0,
+                       0, grub_upper_mem, grub_lower_mem, 0, 0);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_unload (void)
+{
+  grub_dl_unref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_load_aout (grub_file_t file, union grub_aout_header *ah)
+{
+  grub_addr_t load_addr, bss_end_addr;
+  int ofs, align_page;
+
+  if (grub_aout_get_type (ah) != AOUT_TYPE_AOUT32)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid a.out header");
+
+  entry = ah->aout32.a_entry & 0xFFFFFF;
+
+  if (AOUT_GETMAGIC (ah->aout32) == AOUT32_ZMAGIC)
+    {
+      load_addr = entry;
+      ofs = 0x1000;
+      align_page = 0;
+    }
+  else
+    {
+      load_addr = entry & 0xF00000;
+      ofs = sizeof (struct grub_aout32_header);
+      align_page = 1;
+    }
+
+  if (load_addr < 0x100000)
+    return grub_error (GRUB_ERR_BAD_OS, "load address below 1M");
+
+  kernend = load_addr + ah->aout32.a_text + ah->aout32.a_data;
+  if (align_page)
+    kernend = ALIGN_PAGE(kernend);
+
+  if (ah->aout32.a_bss)
+    {
+      kernend += ah->aout32.a_bss;
+      if (align_page)
+	kernend = ALIGN_PAGE(kernend);
+
+      bss_end_addr = kernend;
+    }
+  else
+    bss_end_addr = 0;
+
+  return grub_aout_load (file, ofs, load_addr,
+			 ah->aout32.a_text + ah->aout32.a_data, bss_end_addr);
+}
+
+static grub_err_t
+grub_bsd_elf32_hook (Elf32_Phdr * phdr, UNUSED grub_addr_t * addr)
+{
+  Elf32_Addr paddr;
+
+  phdr->p_paddr &= 0xFFFFFF;
+  paddr = phdr->p_paddr;
+
+  if ((paddr < grub_os_area_addr)
+      || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Address 0x%x is out of range",
+		       paddr);
+
+  if (paddr + phdr->p_memsz > kernend)
+    kernend = paddr + phdr->p_memsz;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_load_elf (grub_file_t file)
+{
+  grub_elf_t elf = 0;
+  grub_err_t err;
+
+  kernend = 0;
+  elf = grub_elf_file (file);
+  if (!elf)
+    return grub_errno;
+
+  if (grub_elf_is_elf32 (elf))
+    {
+      entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF;
+      err = grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0);
+    }
+  else
+    err = grub_error (GRUB_ERR_BAD_OS, "invalid elf");
+
+  return err;
+}
+
+static grub_err_t
+grub_bsd_load (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  union grub_aout_header ah;
+
+  grub_dl_ref (my_mod);
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  bootflags = 0;
+  file = grub_gzfile_open (argv[0], 1);
+  if (!file)
+    goto fail;
+
+  if (grub_file_read (file, (char *) &ah, sizeof (ah)) != sizeof (ah))
+    {
+      grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header");
+      goto fail;
+    }
+
+  if (grub_aout_get_type (&ah) == AOUT_TYPE_NONE)
+    grub_bsd_load_elf (file);
+  else
+    grub_bsd_load_aout (file, &ah);
+
+fail:
+
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    grub_dl_unref (my_mod);
+
+  return grub_errno;
+}
+
+void
+grub_rescue_cmd_freebsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_FREEBSD;
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 1);
+}
+
+void
+grub_rescue_cmd_openbsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_OPENBSD;
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 1);
+}
+
+void
+grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  char *buf = 0, *curr, *next;
+  int len;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no filename");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if ((!file) || (!file->size))
+    goto fail;
+
+  len = file->size;
+  buf = grub_malloc (len + 1);
+  if (!buf)
+    goto fail;
+
+  if (grub_file_read (file, buf, len) != len)
+    goto fail;
+
+  buf[len] = 0;
+
+  next = buf;
+  while (next)
+    {
+      char *p;
+
+      curr = next;
+      next = grub_strchr (curr, '\n');
+      if (next)
+	{
+
+	  p = next - 1;
+	  while (p > curr)
+	    {
+	      if ((*p != '\r') && (*p != ' ') && (*p != '\t'))
+		break;
+	      p--;
+	    }
+
+	  if ((p > curr) && (*p == '"'))
+	    p--;
+
+	  *(p + 1) = 0;
+	  next++;
+	}
+
+      if (*curr == '#')
+	continue;
+
+      p = grub_strchr (curr, '=');
+      if (!p)
+	continue;
+
+      *(p++) = 0;
+
+      if (*curr)
+	{
+	  char name[grub_strlen (curr) + 8 + 1];
+
+	  if (*p == '"')
+	    p++;
+
+	  grub_sprintf (name, "FreeBSD.%s", curr);
+	  if (grub_env_set (name, p))
+	    goto fail;
+	}
+    }
+
+fail:
+  grub_free (buf);
+
+  if (file)
+    grub_file_close (file);
+}
+
+GRUB_MOD_INIT (freebsd)
+{
+  grub_rescue_register_command ("freebsd",
+				grub_rescue_cmd_freebsd,
+				"load freebsd kernel");
+  grub_rescue_register_command ("freebsd_loadenv",
+				grub_rescue_cmd_freebsd_loadenv,
+				"load freebsd env");
+  grub_rescue_register_command ("openbsd",
+				grub_rescue_cmd_openbsd,
+				"load openbsd kernel");
+
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI (freebsd)
+{
+  grub_rescue_unregister_command ("freebsd");
+  grub_rescue_unregister_command ("freebsd_loadenv");
+  grub_rescue_unregister_command ("openbsd");
+}
diff --git a/loader/i386/pc/freebsd_normal.c b/loader/i386/pc/freebsd_normal.c
new file mode 100755
index 0000000..afb6490
--- /dev/null
+++ b/loader/i386/pc/freebsd_normal.c
@@ -0,0 +1,74 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+static grub_err_t
+grub_normal_freebsd_command (struct grub_arg_list *state
+			     __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_freebsd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_freebsd_loadenv_command (struct grub_arg_list *state
+				     __attribute__ ((unused)), int argc,
+				     char **args)
+{
+  grub_rescue_cmd_freebsd_loadenv (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_openbsd_command (struct grub_arg_list *state
+			     __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_openbsd (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT (freebsd_normal)
+{
+  (void) mod;			/* To stop warning.  */
+  grub_register_command ("freebsd", grub_normal_freebsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "freebsd FILE [ARGS...]",
+			 "Load freebsd kernel.", 0);
+  grub_register_command ("freebsd_loadenv",
+			 grub_normal_freebsd_loadenv_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "freebsd_loadenv FILE",
+			 "Load freebsd env.", 0);
+  grub_register_command ("openbsd", grub_normal_openbsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "openbsd FILE [ARGS...]",
+			 "Load openbsd kernel.", 0);
+}
+
+GRUB_MOD_FINI (freebsd_normal)
+{
+  grub_unregister_command ("freebsd");
+  grub_unregister_command ("freebsd_loadenv");
+  grub_unregister_command ("openbsd");
+}
diff --git a/loader/i386/pc/multiboot.c b/loader/i386/pc/multiboot.c
index 893f11b..67959cf 100644
--- a/loader/i386/pc/multiboot.c
+++ b/loader/i386/pc/multiboot.c
@@ -36,6 +36,7 @@
 #include <grub/machine/init.h>
 #include <grub/machine/memory.h>
 #include <grub/elf.h>
+#include <grub/aout.h>
 #include <grub/file.h>
 #include <grub/err.h>
 #include <grub/rescue.h>
@@ -315,7 +316,22 @@ grub_multiboot (int argc, char *argv[])
       goto fail;
     }
 
-  if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
+  if (header->flags & MULTIBOOT_AOUT_KLUDGE)
+    {
+      int ofs;
+
+      ofs = (char *) header - buffer -
+            (header->header_addr - header->load_addr);
+      if ((grub_aout_load (file, ofs, header->load_addr,
+                           ((header->load_end_addr == 0) ? 0 :
+                            header->load_end_addr - header->load_addr),
+                           header->bss_end_addr))
+          !=GRUB_ERR_NONE)
+        goto fail;
+
+      entry = header->entry_addr;
+    }
+  else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
     goto fail;
   
   mbi = grub_malloc (sizeof (struct grub_multiboot_info));

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-11 14:28           ` Bean
@ 2008-02-11 20:45             ` Bean
  2008-02-11 20:46               ` Bean
  0 siblings, 1 reply; 37+ messages in thread
From: Bean @ 2008-02-11 20:45 UTC (permalink / raw)
  To: The development of GRUB 2

Hi,

Change in this patch:

1. support OpenBSD kernel:

set root=(hd0,3,a)
openbsd /bsd

The modules name is changed to bsd.mod.

2. Support setting kernel flags

one character represent one flag, for FreeBSD, it's "DhaCcdgmnpqrsv",
for OpenBSD, it's "abcsd".

for example, to enable ask for root device name, single user mode and
verbose output in FreeBSD:

set root=(hd0,2,a)
freebsd /boot/loader asv


-- 
Bean



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-11 20:45             ` Bean
@ 2008-02-11 20:46               ` Bean
  2008-02-11 21:28                 ` Robert Millan
  2008-02-11 21:51                 ` walt
  0 siblings, 2 replies; 37+ messages in thread
From: Bean @ 2008-02-11 20:46 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 532 bytes --]

On Feb 12, 2008 4:45 AM, Bean <bean123ch@gmail.com> wrote:
> Hi,
>
> Change in this patch:
>
> 1. support OpenBSD kernel:
>
> set root=(hd0,3,a)
> openbsd /bsd
>
> The modules name is changed to bsd.mod.
>
> 2. Support setting kernel flags
>
> one character represent one flag, for FreeBSD, it's "DhaCcdgmnpqrsv",
> for OpenBSD, it's "abcsd".
>
> for example, to enable ask for root device name, single user mode and
> verbose output in FreeBSD:
>
> set root=(hd0,2,a)
> freebsd /boot/loader asv

sorry, forget the patch.

-- 
Bean

[-- Attachment #2: a6.diff --]
[-- Type: text/plain, Size: 29983 bytes --]

diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 78e4f00..82ef90b 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -146,7 +146,8 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
 	_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod	\
 	vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
 	videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod	\
-	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod
+	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \
+	aout.mod _bsd.mod bsd.mod
 
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -298,4 +299,19 @@ lspci_mod_SOURCES = commands/lspci.c
 lspci_mod_CFLAGS = $(COMMON_CFLAGS)
 lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For aout.mod
+aout_mod_SOURCES = loader/aout.c
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _freebsd.mod
+_bsd_mod_SOURCES = loader/i386/pc/bsd.c
+_bsd_mod_CFLAGS = $(COMMON_CFLAGS)
+_bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For freebsd.mod
+bsd_mod_SOURCES = loader/i386/pc/bsd_normal.c
+bsd_mod_CFLAGS = $(COMMON_CFLAGS)
+bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff --git a/include/grub/aout.h b/include/grub/aout.h
new file mode 100755
index 0000000..3243b82
--- /dev/null
+++ b/include/grub/aout.h
@@ -0,0 +1,91 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_AOUT_HEADER
+#define GRUB_AOUT_HEADER 1
+
+#include <grub/types.h>
+
+struct grub_aout32_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint32_t a_text;		/* text segment size */
+  grub_uint32_t a_data;		/* initialized data size */
+  grub_uint32_t a_bss;		/* uninitialized data size */
+  grub_uint32_t a_syms;		/* symbol table size */
+  grub_uint32_t a_entry;	/* entry point */
+  grub_uint32_t a_trsize;	/* text relocation size */
+  grub_uint32_t a_drsize;	/* data relocation size */
+};
+
+struct grub_aout64_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint64_t a_text;		/* text segment size */
+  grub_uint64_t a_data;		/* initialized data size */
+  grub_uint64_t a_bss;		/* uninitialized data size */
+  grub_uint64_t a_syms;		/* symbol table size */
+  grub_uint64_t a_entry;	/* entry point */
+  grub_uint64_t a_trsize;	/* text relocation size */
+  grub_uint64_t a_drsize;	/* data relocation size */
+};
+
+union grub_aout_header
+{
+  struct grub_aout32_header aout32;
+  struct grub_aout64_header aout64;
+};
+
+#define AOUT_TYPE_NONE		0
+#define AOUT_TYPE_AOUT32	1
+#define AOUT_TYPE_AOUT64	6
+
+#define	AOUT32_OMAGIC		0x107	/* 0407 old impure format */
+#define	AOUT32_NMAGIC		0x108	/* 0410 read-only text */
+#define	AOUT32_ZMAGIC		0x10b	/* 0413 demand load format */
+#define AOUT32_QMAGIC		0xcc	/* 0314 "compact" demand load format */
+
+#define AOUT64_OMAGIC		0x1001
+#define AOUT64_ZMAGIC		0x1002
+#define AOUT64_NMAGIC		0x1003
+
+#define	AOUT_MID_ZERO		0	/* unknown - implementation dependent */
+#define	AOUT_MID_SUN010		1	/* sun 68010/68020 binary */
+#define	AOUT_MID_SUN020		2	/* sun 68020-only binary */
+#define AOUT_MID_I386		134	/* i386 BSD binary */
+#define AOUT_MID_SPARC		138	/* sparc */
+#define	AOUT_MID_HP200		200	/* hp200 (68010) BSD binary */
+#define	AOUT_MID_HP300		300	/* hp300 (68020+68881) BSD binary */
+#define	AOUT_MID_HPUX		0x20C	/* hp200/300 HP-UX binary */
+#define	AOUT_MID_HPUX800	0x20B	/* hp800 HP-UX binary */
+
+#define AOUT_FLAG_PIC		0x10	/* contains position independant code */
+#define AOUT_FLAG_DYNAMIC	0x20	/* contains run-time link-edit info */
+#define AOUT_FLAG_DPMASK	0x30	/* mask for the above */
+
+#define AOUT_GETMAGIC(header) ((header).a_midmag & 0xffff)
+#define AOUT_GETMID(header) ((header).a_midmag >> 16) & 0x03ff)
+#define AOUT_GETFLAG(header) ((header).a_midmag >> 26) & 0x3f)
+
+int EXPORT_FUNC(grub_aout_get_type) (union grub_aout_header *header);
+
+grub_err_t EXPORT_FUNC(grub_aout_load) (grub_file_t file, int offset,
+                                        grub_addr_t load_addr, int load_size,
+                                        grub_addr_t bss_end_addr);
+
+#endif /* ! GRUB_AOUT_HEADER */
diff --git a/include/grub/i386/bsd.h b/include/grub/i386/bsd.h
new file mode 100755
index 0000000..5d8d05d
--- /dev/null
+++ b/include/grub/i386/bsd.h
@@ -0,0 +1,137 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_BSD_CPU_HEADER
+#define GRUB_BSD_CPU_HEADER	1
+
+#include <grub/types.h>
+
+#define KERNEL_TYPE_FREEBSD	0
+#define KERNEL_TYPE_OPENBSD	1
+#define KERNEL_TYPE_NETBSD	2
+
+#define FREEBSD_RB_ASKNAME	0x1	/* ask for file name to reboot from */
+#define FREEBSD_RB_SINGLE       0x2	/* reboot to single user only */
+#define FREEBSD_RB_NOSYNC       0x4	/* dont sync before reboot */
+#define FREEBSD_RB_HALT         0x8	/* don't reboot, just halt */
+#define FREEBSD_RB_INITNAME     0x10	/* name given for /etc/init (unused) */
+#define FREEBSD_RB_DFLTROOT     0x20	/* use compiled-in rootdev */
+#define FREEBSD_RB_KDB          0x40	/* give control to kernel debugger */
+#define FREEBSD_RB_RDONLY       0x80	/* mount root fs read-only */
+#define FREEBSD_RB_DUMP         0x100	/* dump kernel memory before reboot */
+#define FREEBSD_RB_MINIROOT     0x200	/* mini-root present in memory at boot time */
+#define FREEBSD_RB_CONFIG       0x400	/* invoke user configuration routing */
+#define FREEBSD_RB_VERBOSE      0x800	/* print all potentially useful info */
+#define FREEBSD_RB_SERIAL       0x1000	/* user serial port as console */
+#define FREEBSD_RB_CDROM        0x2000	/* use cdrom as root */
+#define FREEBSD_RB_GDB		0x8000	/* use GDB remote debugger instead of DDB */
+#define FREEBSD_RB_MUTE		0x10000	/* Come up with the console muted */
+#define FREEBSD_RB_PAUSE	0x100000
+#define FREEBSD_RB_QUIET	0x200000
+#define FREEBSD_RB_NOINTR	0x10000000
+#define FREENSD_RB_MULTIPLE	0x20000000 /* Use multiple consoles */
+#define FREEBSD_RB_DUAL		FREENSD_RB_MULTIPLE
+#define FREEBSD_RB_BOOTINFO     0x80000000 /* have `struct bootinfo *' arg */
+
+#define FREEBSD_B_DEVMAGIC	0xa0000000
+#define FREEBSD_B_SLICESHIFT	20
+#define FREEBSD_B_UNITSHIFT	16
+#define FREEBSD_B_PARTSHIFT	8
+#define FREEBSD_B_TYPESHIFT	0
+
+#define FREEBSD_BOOTINFO_VERSION 1
+#define FREEBSD_N_BIOS_GEOM	8
+
+struct grub_freebsd_bootinfo
+{
+  grub_uint32_t bi_version;
+  grub_uint8_t *bi_kernelname;
+  struct nfs_diskless *bi_nfs_diskless;
+  grub_uint32_t bi_n_bios_used;
+  grub_uint32_t bi_bios_geom[FREEBSD_N_BIOS_GEOM];
+  grub_uint32_t bi_size;
+  grub_uint8_t bi_memsizes_valid;
+  grub_uint8_t bi_bios_dev;
+  grub_uint8_t bi_pad[2];
+  grub_uint32_t bi_basemem;
+  grub_uint32_t bi_extmem;
+  grub_uint32_t bi_symtab;
+  grub_uint32_t bi_esymtab;
+  grub_uint32_t bi_kernend;
+  grub_uint32_t bi_envp;
+  grub_uint32_t bi_modulep;
+} __attribute__ ((packed));
+
+#define OPENBSD_RB_ASKNAME	0x0001  /* ask for file name to reboot from */
+#define OPENBSD_RB_SINGLE	0x0002  /* reboot to single user only */
+#define OPENBSD_RB_NOSYNC	0x0004  /* dont sync before reboot */
+#define OPENBSD_RB_HALT		0x0008  /* don't reboot, just halt */
+#define OPENBSD_RB_INITNAME	0x0010  /* name given for /etc/init (unused) */
+#define OPENBSD_RB_DFLTROOT	0x0020  /* use compiled-in rootdev */
+#define OPENBSD_RB_KDB		0x0040  /* give control to kernel debugger */
+#define OPENBSD_RB_RDONLY	0x0080  /* mount root fs read-only */
+#define OPENBSD_RB_DUMP		0x0100  /* dump kernel memory before reboot */
+#define OPENBSD_RB_MINIROOT	0x0200  /* mini-root present in memory at boot time */
+#define OPENBSD_RB_CONFIG	0x0400  /* change configured devices */
+#define OPENBSD_RB_TIMEBAD	0x0800  /* don't call resettodr() in boot() */
+#define OPENBSD_RB_POWERDOWN	0x1000  /* attempt to power down machine */
+#define OPENBSD_RB_SERCONS	0x2000  /* use serial console if available */
+#define OPENBSD_RB_USERREQ	0x4000  /* boot() called at user request (e.g. ddb) */
+
+#define OPENBSD_B_DEVMAGIC	0xa0000000
+#define OPENBSD_B_ADAPTORSHIFT	24
+#define OPENBSD_B_CTRLSHIFT	20
+#define OPENBSD_B_UNITSHIFT	16
+#define OPENBSD_B_PARTSHIFT	8
+#define OPENBSD_B_TYPESHIFT	0
+
+#define OPENBSD_BOOTARG_APIVER	(OPENBSD_BAPIV_VECTOR | \
+                                 OPENBSD_BAPIV_ENV | \
+                                 OPENBSD_BAPIV_BMEMMAP)
+
+#define OPENBSD_BAPIV_ANCIENT	0x0  /* MD old i386 bootblocks */
+#define OPENBSD_BAPIV_VARS	0x1  /* MD structure w/ add info passed */
+#define OPENBSD_BAPIV_VECTOR	0x2  /* MI vector of MD structures passed */
+#define OPENBSD_BAPIV_ENV	0x4  /* MI environment vars vector */
+#define OPENBSD_BAPIV_BMEMMAP	0x8  /* MI memory map passed is in bytes */
+
+#define OPENBSD_BOOTARG_ENV	0x1000
+#define OPENBSD_BOOTARG_END	-1
+
+#define	OPENBSD_BOOTARG_MMAP	0
+
+struct grub_openbsd_bios_mmap
+{
+  grub_uint64_t addr;
+  grub_uint64_t len;
+  grub_uint32_t type;
+} bios_memmap_t;
+
+struct grub_openbsd_bootargs
+{
+  grub_uint32_t ba_type;
+  grub_uint32_t ba_size;
+  struct grub_openbsd_bootargs *ba_next;
+} __attribute__ ((packed));
+
+void grub_rescue_cmd_freebsd (int argc, char *argv[]);
+void grub_rescue_cmd_openbsd (int argc, char *argv[]);
+
+void grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[]);
+
+#endif /* ! GRUB_BSD_CPU_HEADER */
diff --git a/include/grub/i386/loader.h b/include/grub/i386/loader.h
index 45a1652..5f912cd 100644
--- a/include/grub/i386/loader.h
+++ b/include/grub/i386/loader.h
@@ -39,6 +39,9 @@ void EXPORT_FUNC(grub_multiboot_real_boot) (grub_addr_t entry,
 void EXPORT_FUNC(grub_multiboot2_real_boot) (grub_addr_t entry,
                                              struct grub_multiboot_info *mbi)
      __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_unix_real_boot) (grub_addr_t entry, ...)
+     __attribute__ ((cdecl,noreturn));
+
 
 /* It is necessary to export these functions, because normal mode commands
    reuse rescue mode commands.  */
diff --git a/include/grub/i386/pc/init.h b/include/grub/i386/pc/init.h
index 115deb4..0c6a129 100644
--- a/include/grub/i386/pc/init.h
+++ b/include/grub/i386/pc/init.h
@@ -40,7 +40,7 @@ struct grub_machine_mmap_entry
 
 /* Get a memory map entry. Return next continuation value. Zero means
    the end.  */
-grub_uint32_t grub_get_mmap_entry (struct grub_machine_mmap_entry *entry,
+grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
 				   grub_uint32_t cont);
 
 /* Turn on/off Gate A20.  */
diff --git a/kern/elf.c b/kern/elf.c
index ca10b5b..3e90ea0 100644
--- a/kern/elf.c
+++ b/kern/elf.c
@@ -228,9 +228,9 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
     if (phdr->p_type != PT_LOAD)
       return 0;
 
-    load_addr = phdr->p_paddr;
     if (load_hook && load_hook (phdr, &load_addr))
       return 1;
+    load_addr = phdr->p_paddr;
 
     if (load_addr < load_base)
       load_base = load_addr;
@@ -407,9 +407,9 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
     if (phdr->p_type != PT_LOAD)
       return 0;
 
-    load_addr = phdr->p_paddr;
     if (load_hook && load_hook (phdr, &load_addr))
       return 1;
+    load_addr = phdr->p_paddr;
 
     if (load_addr < load_base)
       load_base = load_addr;
diff --git a/kern/i386/loader.S b/kern/i386/loader.S
index 266f4ef..c8dd30a 100644
--- a/kern/i386/loader.S
+++ b/kern/i386/loader.S
@@ -162,3 +162,14 @@ FUNCTION(grub_multiboot2_real_boot)
         movl    $MULTIBOOT2_BOOTLOADER_MAGIC,%eax 
         popl    %ecx
         jmp     *%ecx
+
+
+FUNCTION(grub_unix_real_boot)
+        call    EXT_C(grub_dl_unload_all)
+        call    EXT_C(grub_stop_floppy)
+
+        cli
+
+        popl    %eax
+        popl	%eax
+        call	*%eax
diff --git a/loader/aout.c b/loader/aout.c
new file mode 100755
index 0000000..2c82b60
--- /dev/null
+++ b/loader/aout.c
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ *  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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+int
+grub_aout_get_type (union grub_aout_header *header)
+{
+  int magic;
+
+  magic = AOUT_GETMAGIC (header->aout32);
+  if ((magic == AOUT32_OMAGIC) || (magic == AOUT32_NMAGIC) ||
+      (magic == AOUT32_ZMAGIC) || (magic == AOUT32_QMAGIC))
+    return AOUT_TYPE_AOUT32;
+  else if ((magic == AOUT64_OMAGIC) || (magic == AOUT64_NMAGIC) ||
+	   (magic == AOUT64_ZMAGIC))
+    return AOUT_TYPE_AOUT64;
+  else
+    return AOUT_TYPE_NONE;
+}
+
+grub_err_t
+grub_aout_load (grub_file_t file, int offset,
+                grub_addr_t load_addr,
+		int load_size,
+                grub_addr_t bss_end_addr)
+{
+  if ((grub_file_seek (file, offset)) == (grub_off_t) - 1)
+    return grub_errno;
+
+  if (!load_size)
+    load_size = file->size - offset;
+
+  grub_file_read (file, (char *) load_addr, load_size);
+
+  if (grub_errno)
+    return grub_errno;
+
+  if (bss_end_addr)
+    grub_memset (load_addr + load_size, 0,
+                 bss_end_addr - load_addr - load_size);
+
+  return GRUB_ERR_NONE;
+}
diff --git a/loader/i386/pc/bsd.c b/loader/i386/pc/bsd.c
new file mode 100644
index 0000000..f4bddb0
--- /dev/null
+++ b/loader/i386/pc/bsd.c
@@ -0,0 +1,481 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/machine/memory.h>
+#include <grub/machine/init.h>
+#include <grub/cpu/bsd.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/elfload.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+#include <grub/aout.h>
+
+#define ALIGN_DWORD(a)	((a + 3) & (~3))
+#define ALIGN_PAGE(a)	((a + 4095) & (~4095))
+
+static int kernel_type;
+static grub_dl_t my_mod;
+static grub_addr_t entry, kernend;
+static grub_uint32_t bootflags;
+
+static const char freebsd_opts[] = "DhaCcdgmnpqrsv";
+static const grub_uint32_t freebsd_flags[] = {
+  FREEBSD_RB_DUAL, FREEBSD_RB_SERIAL, FREEBSD_RB_ASKNAME,
+  FREEBSD_RB_CDROM, FREEBSD_RB_CONFIG, FREEBSD_RB_KDB,
+  FREEBSD_RB_GDB, FREEBSD_RB_MUTE, FREEBSD_RB_NOINTR,
+  FREEBSD_RB_PAUSE, FREEBSD_RB_QUIET, FREEBSD_RB_DFLTROOT,
+  FREEBSD_RB_SINGLE, FREEBSD_RB_VERBOSE
+};
+
+static const char openbsd_opts[] = "abcsd";
+static const grub_uint32_t openbsd_flags[] = {
+  OPENBSD_RB_ASKNAME, OPENBSD_RB_HALT, OPENBSD_RB_CONFIG,
+  OPENBSD_RB_SINGLE, OPENBSD_RB_KDB
+};
+
+static void
+grub_bsd_get_device (grub_uint32_t * biosdev,
+		     grub_uint32_t * unit,
+		     grub_uint32_t * slice, grub_uint32_t * part)
+{
+  char *p;
+
+  *biosdev = *unit = *slice = *part = 0;
+  p = grub_env_get ("root");
+  if ((p) && ((p[0] == 'h') || (p[0] == 'f')) && (p[1] == 'd') &&
+      (p[2] >= '0') && (p[2] <= '9'))
+    {
+      if (p[0] == 'h')
+	*biosdev = 0x80;
+
+      *biosdev += grub_strtoul (p + 2, &p, 0);
+      *unit = (*biosdev & 0x7f);
+
+      if ((p) && (p[0] == ','))
+	{
+	  if ((p[1] >= '0') && (p[1] <= '9'))
+	    {
+	      *slice = grub_strtoul (p + 1, &p, 0);
+
+	      if ((p) && (p[0] == ','))
+		p++;
+	    }
+
+	  if ((p[0] >= 'a') && (p[0] <= 'z'))
+	    *part = p[0] - 'a';
+	}
+    }
+}
+
+static grub_err_t
+grub_freebsd_boot (void)
+{
+  struct grub_freebsd_bootinfo bi;
+  char *p;
+  grub_uint32_t bootdev, biosdev, unit, slice, part;
+
+  auto int iterate_env (struct grub_env_var *var);
+  int iterate_env (struct grub_env_var *var)
+  {
+    if ((!grub_memcmp (var->name, "FreeBSD.", 8)) && (var->name[8]))
+      {
+	grub_strcpy (p, &var->name[8]);
+	p += grub_strlen (p);
+	*(p++) = '=';
+	grub_strcpy (p, var->value);
+	p += grub_strlen (p) + 1;
+      }
+
+    return 0;
+  }
+
+  grub_memset (&bi, 0, sizeof (bi));
+  bi.bi_version = FREEBSD_BOOTINFO_VERSION;
+  bi.bi_size = sizeof (bi);
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+  bootdev = (FREEBSD_B_DEVMAGIC + ((slice + 1) << FREEBSD_B_SLICESHIFT) +
+	     (unit << FREEBSD_B_UNITSHIFT) + (part << FREEBSD_B_PARTSHIFT));
+
+  bi.bi_bios_dev = biosdev;
+
+  kernend = ALIGN_DWORD (kernend);
+  p = (char *) kernend;
+
+  grub_env_iterate (iterate_env);
+
+  if (p != (char *) kernend)
+    {
+      *(p++) = 0;
+
+      bi.bi_envp = kernend;
+      bi.bi_kernend = ALIGN_DWORD ((grub_uint32_t) p);
+    }
+  else
+    bi.bi_kernend = kernend;
+
+  grub_unix_real_boot (entry, bootflags | FREEBSD_RB_BOOTINFO, bootdev,
+		       0, 0, 0, &bi, 0, 0);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_openbsd_boot (void)
+{
+  char *buf = (char *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+  struct grub_machine_mmap_entry mmap;
+  struct grub_openbsd_bios_mmap *pm;
+  struct grub_openbsd_bootargs *pa;
+  grub_uint32_t bootdev, biosdev, unit, slice, part, cont;
+
+  pa = (struct grub_openbsd_bootargs *) buf;
+
+  pa->ba_type = OPENBSD_BOOTARG_MMAP;
+  pm = (struct grub_openbsd_bios_mmap *) (pa + 1);
+  cont = grub_get_mmap_entry (&mmap, 0);
+  if (mmap.size)
+    do
+      {
+	pm->addr = mmap.addr;
+	pm->len = mmap.len;
+	pm->type = mmap.type;
+	pm++;
+
+	if (!cont)
+	  break;
+
+	cont = grub_get_mmap_entry (&mmap, cont);
+      }
+    while (mmap.size);
+
+  pa->ba_size = (char *) pm - (char *) pa;
+  pa->ba_next = (struct grub_openbsd_bootargs *) pm;
+  pa = pa->ba_next;
+  pa->ba_type = OPENBSD_BOOTARG_END;
+  pa++;
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+  bootdev = (OPENBSD_B_DEVMAGIC + (unit << OPENBSD_B_UNITSHIFT) +
+	     (part << OPENBSD_B_PARTSHIFT));
+
+  grub_unix_real_boot (entry, bootflags, bootdev, OPENBSD_BOOTARG_APIVER,
+		       0, grub_upper_mem >> 10, grub_lower_mem >> 10,
+		       (char *) pa - buf, buf);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_unload (void)
+{
+  grub_dl_unref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_load_aout (grub_file_t file, union grub_aout_header *ah)
+{
+  grub_addr_t load_addr, bss_end_addr;
+  int ofs, align_page;
+
+  if (grub_aout_get_type (ah) != AOUT_TYPE_AOUT32)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid a.out header");
+
+  entry = ah->aout32.a_entry & 0xFFFFFF;
+
+  if (AOUT_GETMAGIC (ah->aout32) == AOUT32_ZMAGIC)
+    {
+      load_addr = entry;
+      ofs = 0x1000;
+      align_page = 0;
+    }
+  else
+    {
+      load_addr = entry & 0xF00000;
+      ofs = sizeof (struct grub_aout32_header);
+      align_page = 1;
+    }
+
+  if (load_addr < 0x100000)
+    return grub_error (GRUB_ERR_BAD_OS, "load address below 1M");
+
+  kernend = load_addr + ah->aout32.a_text + ah->aout32.a_data;
+  if (align_page)
+    kernend = ALIGN_PAGE (kernend);
+
+  if (ah->aout32.a_bss)
+    {
+      kernend += ah->aout32.a_bss;
+      if (align_page)
+	kernend = ALIGN_PAGE (kernend);
+
+      bss_end_addr = kernend;
+    }
+  else
+    bss_end_addr = 0;
+
+  return grub_aout_load (file, ofs, load_addr,
+			 ah->aout32.a_text + ah->aout32.a_data, bss_end_addr);
+}
+
+static grub_err_t
+grub_bsd_elf32_hook (Elf32_Phdr * phdr, UNUSED grub_addr_t * addr)
+{
+  Elf32_Addr paddr;
+
+  phdr->p_paddr &= 0xFFFFFF;
+  paddr = phdr->p_paddr;
+
+  if ((paddr < grub_os_area_addr)
+      || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Address 0x%x is out of range",
+		       paddr);
+
+  if (paddr + phdr->p_memsz > kernend)
+    kernend = paddr + phdr->p_memsz;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_load_elf (grub_file_t file)
+{
+  grub_elf_t elf = 0;
+  grub_err_t err;
+
+  kernend = 0;
+  elf = grub_elf_file (file);
+  if (!elf)
+    return grub_errno;
+
+  if (grub_elf_is_elf32 (elf))
+    {
+      entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF;
+      err = grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0);
+    }
+  else
+    err = grub_error (GRUB_ERR_BAD_OS, "invalid elf");
+
+  return err;
+}
+
+static grub_err_t
+grub_bsd_load (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  union grub_aout_header ah;
+
+  grub_dl_ref (my_mod);
+
+  grub_loader_unset ();
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (!file)
+    goto fail;
+
+  if (grub_file_read (file, (char *) &ah, sizeof (ah)) != sizeof (ah))
+    {
+      grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header");
+      goto fail;
+    }
+
+  if (grub_aout_get_type (&ah) == AOUT_TYPE_NONE)
+    grub_bsd_load_elf (file);
+  else
+    grub_bsd_load_aout (file, &ah);
+
+fail:
+
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    grub_dl_unref (my_mod);
+
+  return grub_errno;
+}
+
+static grub_uint32_t
+grub_bsd_parse_flags (char *str, const char *opts,
+		      const grub_uint32_t * flags)
+{
+  grub_uint32_t result = 0;
+
+  while (*str)
+    {
+      const char *po;
+      const grub_uint32_t *pf;
+
+      po = opts;
+      pf = flags;
+      while (*po)
+	{
+	  if (*str == *po)
+	    {
+	      result |= *pf;
+	      break;
+	    }
+	  po++;
+	  pf++;
+	}
+      str++;
+    }
+
+  return result;
+}
+
+void
+grub_rescue_cmd_freebsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_FREEBSD;
+  bootflags = ((argc <= 1) ? 0 :
+	       grub_bsd_parse_flags (argv[1], freebsd_opts, freebsd_flags));
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 1);
+}
+
+void
+grub_rescue_cmd_openbsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_OPENBSD;
+  bootflags = ((argc <= 1) ? 0 :
+	       grub_bsd_parse_flags (argv[1], openbsd_opts, openbsd_flags));
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 1);
+}
+
+void
+grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  char *buf = 0, *curr, *next;
+  int len;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no filename");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if ((!file) || (!file->size))
+    goto fail;
+
+  len = file->size;
+  buf = grub_malloc (len + 1);
+  if (!buf)
+    goto fail;
+
+  if (grub_file_read (file, buf, len) != len)
+    goto fail;
+
+  buf[len] = 0;
+
+  next = buf;
+  while (next)
+    {
+      char *p;
+
+      curr = next;
+      next = grub_strchr (curr, '\n');
+      if (next)
+	{
+
+	  p = next - 1;
+	  while (p > curr)
+	    {
+	      if ((*p != '\r') && (*p != ' ') && (*p != '\t'))
+		break;
+	      p--;
+	    }
+
+	  if ((p > curr) && (*p == '"'))
+	    p--;
+
+	  *(p + 1) = 0;
+	  next++;
+	}
+
+      if (*curr == '#')
+	continue;
+
+      p = grub_strchr (curr, '=');
+      if (!p)
+	continue;
+
+      *(p++) = 0;
+
+      if (*curr)
+	{
+	  char name[grub_strlen (curr) + 8 + 1];
+
+	  if (*p == '"')
+	    p++;
+
+	  grub_sprintf (name, "FreeBSD.%s", curr);
+	  if (grub_env_set (name, p))
+	    goto fail;
+	}
+    }
+
+fail:
+  grub_free (buf);
+
+  if (file)
+    grub_file_close (file);
+}
+
+GRUB_MOD_INIT (bsd)
+{
+  grub_rescue_register_command ("freebsd",
+				grub_rescue_cmd_freebsd,
+				"load freebsd kernel");
+  grub_rescue_register_command ("freebsd_loadenv",
+				grub_rescue_cmd_freebsd_loadenv,
+				"load freebsd env");
+  grub_rescue_register_command ("openbsd",
+				grub_rescue_cmd_openbsd,
+				"load openbsd kernel");
+
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI (bsd)
+{
+  grub_rescue_unregister_command ("freebsd");
+  grub_rescue_unregister_command ("freebsd_loadenv");
+  grub_rescue_unregister_command ("openbsd");
+}
diff --git a/loader/i386/pc/bsd_normal.c b/loader/i386/pc/bsd_normal.c
new file mode 100644
index 0000000..8273f2d
--- /dev/null
+++ b/loader/i386/pc/bsd_normal.c
@@ -0,0 +1,71 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+static grub_err_t
+grub_normal_freebsd_command (struct grub_arg_list *state
+			     __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_freebsd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_freebsd_loadenv_command (struct grub_arg_list *state
+				     __attribute__ ((unused)), int argc,
+				     char **args)
+{
+  grub_rescue_cmd_freebsd_loadenv (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_openbsd_command (struct grub_arg_list *state
+			     __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_openbsd (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT (bsd_normal)
+{
+  (void) mod;			/* To stop warning.  */
+  grub_register_command ("freebsd", grub_normal_freebsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "freebsd FILE [ARGS...]", "Load freebsd kernel.", 0);
+  grub_register_command ("freebsd_loadenv",
+			 grub_normal_freebsd_loadenv_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "freebsd_loadenv FILE", "Load freebsd env.", 0);
+  grub_register_command ("openbsd", grub_normal_openbsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "openbsd FILE [ARGS...]", "Load openbsd kernel.", 0);
+}
+
+GRUB_MOD_FINI (bsd_normal)
+{
+  grub_unregister_command ("freebsd");
+  grub_unregister_command ("freebsd_loadenv");
+  grub_unregister_command ("openbsd");
+}
diff --git a/loader/i386/pc/multiboot.c b/loader/i386/pc/multiboot.c
index 893f11b..67959cf 100644
--- a/loader/i386/pc/multiboot.c
+++ b/loader/i386/pc/multiboot.c
@@ -36,6 +36,7 @@
 #include <grub/machine/init.h>
 #include <grub/machine/memory.h>
 #include <grub/elf.h>
+#include <grub/aout.h>
 #include <grub/file.h>
 #include <grub/err.h>
 #include <grub/rescue.h>
@@ -315,7 +316,22 @@ grub_multiboot (int argc, char *argv[])
       goto fail;
     }
 
-  if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
+  if (header->flags & MULTIBOOT_AOUT_KLUDGE)
+    {
+      int ofs;
+
+      ofs = (char *) header - buffer -
+            (header->header_addr - header->load_addr);
+      if ((grub_aout_load (file, ofs, header->load_addr,
+                           ((header->load_end_addr == 0) ? 0 :
+                            header->load_end_addr - header->load_addr),
+                           header->bss_end_addr))
+          !=GRUB_ERR_NONE)
+        goto fail;
+
+      entry = header->entry_addr;
+    }
+  else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
     goto fail;
   
   mbi = grub_malloc (sizeof (struct grub_multiboot_info));

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-11 20:46               ` Bean
@ 2008-02-11 21:28                 ` Robert Millan
  2008-02-11 21:46                   ` Bean
  2008-02-11 21:51                 ` walt
  1 sibling, 1 reply; 37+ messages in thread
From: Robert Millan @ 2008-02-11 21:28 UTC (permalink / raw)
  To: The development of GRUB 2

On Tue, Feb 12, 2008 at 04:46:31AM +0800, Bean wrote:
> +# For _freebsd.mod
> +_bsd_mod_SOURCES = loader/i386/pc/bsd.c

You forgot to rename the commend ;-)

> +_bsd_mod_CFLAGS = $(COMMON_CFLAGS)
> +_bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> +# For freebsd.mod
> +bsd_mod_SOURCES = loader/i386/pc/bsd_normal.c
> +bsd_mod_CFLAGS = $(COMMON_CFLAGS)
> +bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)

How much pc-dependant are those?  Can we hope they will work in e.g.
i386-coreboot in the future, when *BSD kernels remove their BIOS
dependency?

> +#define FREEBSD_RB_ASKNAME	0x1	/* ask for file name to reboot from */
> +#define FREEBSD_RB_SINGLE       0x2	/* reboot to single user only */
> +#define FREEBSD_RB_NOSYNC       0x4	/* dont sync before reboot */
> +#define FREEBSD_RB_HALT         0x8	/* don't reboot, just halt */
> +#define FREEBSD_RB_INITNAME     0x10	/* name given for /etc/init (unused) */
> +#define FREEBSD_RB_DFLTROOT     0x20	/* use compiled-in rootdev */
> +#define FREEBSD_RB_KDB          0x40	/* give control to kernel debugger */
> +#define FREEBSD_RB_RDONLY       0x80	/* mount root fs read-only */
> +#define FREEBSD_RB_DUMP         0x100	/* dump kernel memory before reboot */
> +#define FREEBSD_RB_MINIROOT     0x200	/* mini-root present in memory at boot time */
> +#define FREEBSD_RB_CONFIG       0x400	/* invoke user configuration routing */
> +#define FREEBSD_RB_VERBOSE      0x800	/* print all potentially useful info */
> +#define FREEBSD_RB_SERIAL       0x1000	/* user serial port as console */
> +#define FREEBSD_RB_CDROM        0x2000	/* use cdrom as root */
> +#define FREEBSD_RB_GDB		0x8000	/* use GDB remote debugger instead of DDB */
> +#define FREEBSD_RB_MUTE		0x10000	/* Come up with the console muted */
> +#define FREEBSD_RB_PAUSE	0x100000
> +#define FREEBSD_RB_QUIET	0x200000
> +#define FREEBSD_RB_NOINTR	0x10000000
> +#define FREENSD_RB_MULTIPLE	0x20000000 /* Use multiple consoles */
> +#define FREEBSD_RB_DUAL		FREENSD_RB_MULTIPLE
> +#define FREEBSD_RB_BOOTINFO     0x80000000 /* have `struct bootinfo *' arg */

Usually we have "(1 << 0)", "(1 << 1)", etc for bitmask lists.

> +FUNCTION(grub_unix_real_boot)
> +        call    EXT_C(grub_dl_unload_all)
> +        call    EXT_C(grub_stop_floppy)
> +
> +        cli
> +
> +        popl    %eax
> +        popl	%eax
> +        call	*%eax

Why a call?  Do we need the return address in the stack here?  A comment would
be nice in that case.

> +#define ALIGN_DWORD(a)	((a + 3) & (~3))
> +#define ALIGN_PAGE(a)	((a + 4095) & (~4095))

We already have ALIGN_UP:

  ./include/grub/misc.h:#define ALIGN_UP(addr, align) ((long)((char *)addr + align - 1) & ~(align - 1))

it'd be better to reuse that, I think.

> +static const grub_uint32_t freebsd_flags[] = {
> +  FREEBSD_RB_DUAL, FREEBSD_RB_SERIAL, FREEBSD_RB_ASKNAME,
> +  FREEBSD_RB_CDROM, FREEBSD_RB_CONFIG, FREEBSD_RB_KDB,
> +  FREEBSD_RB_GDB, FREEBSD_RB_MUTE, FREEBSD_RB_NOINTR,
> +  FREEBSD_RB_PAUSE, FREEBSD_RB_QUIET, FREEBSD_RB_DFLTROOT,
> +  FREEBSD_RB_SINGLE, FREEBSD_RB_VERBOSE
> +};

We usually put a newline after the '='.

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-11 21:28                 ` Robert Millan
@ 2008-02-11 21:46                   ` Bean
  2008-02-12 11:16                     ` Robert Millan
  0 siblings, 1 reply; 37+ messages in thread
From: Bean @ 2008-02-11 21:46 UTC (permalink / raw)
  To: The development of GRUB 2

On Feb 12, 2008 5:28 AM, Robert Millan <rmh@aybabtu.com> wrote:
> On Tue, Feb 12, 2008 at 04:46:31AM +0800, Bean wrote:
> > +# For _freebsd.mod
> > +_bsd_mod_SOURCES = loader/i386/pc/bsd.c
>
> You forgot to rename the commend ;-)

oh, yes.

>
> > +_bsd_mod_CFLAGS = $(COMMON_CFLAGS)
> > +_bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
> > +
> > +# For freebsd.mod
> > +bsd_mod_SOURCES = loader/i386/pc/bsd_normal.c
> > +bsd_mod_CFLAGS = $(COMMON_CFLAGS)
> > +bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
>
> How much pc-dependant are those?  Can we hope they will work in e.g.
> i386-coreboot in the future, when *BSD kernels remove their BIOS
> dependency?

freebsd doesn't need bios at all, openbsd need the memory map, but i
guess it's easy to construct one without using int 15.

>
> > +#define FREEBSD_RB_ASKNAME   0x1     /* ask for file name to reboot from */
> > +#define FREEBSD_RB_SINGLE       0x2  /* reboot to single user only */
> > +#define FREEBSD_RB_NOSYNC       0x4  /* dont sync before reboot */
> > +#define FREEBSD_RB_HALT         0x8  /* don't reboot, just halt */
> > +#define FREEBSD_RB_INITNAME     0x10 /* name given for /etc/init (unused) */
> > +#define FREEBSD_RB_DFLTROOT     0x20 /* use compiled-in rootdev */
> > +#define FREEBSD_RB_KDB          0x40 /* give control to kernel debugger */
> > +#define FREEBSD_RB_RDONLY       0x80 /* mount root fs read-only */
> > +#define FREEBSD_RB_DUMP         0x100        /* dump kernel memory before reboot */
> > +#define FREEBSD_RB_MINIROOT     0x200        /* mini-root present in memory at boot time */
> > +#define FREEBSD_RB_CONFIG       0x400        /* invoke user configuration routing */
> > +#define FREEBSD_RB_VERBOSE      0x800        /* print all potentially useful info */
> > +#define FREEBSD_RB_SERIAL       0x1000       /* user serial port as console */
> > +#define FREEBSD_RB_CDROM        0x2000       /* use cdrom as root */
> > +#define FREEBSD_RB_GDB               0x8000  /* use GDB remote debugger instead of DDB */
> > +#define FREEBSD_RB_MUTE              0x10000 /* Come up with the console muted */
> > +#define FREEBSD_RB_PAUSE     0x100000
> > +#define FREEBSD_RB_QUIET     0x200000
> > +#define FREEBSD_RB_NOINTR    0x10000000
> > +#define FREENSD_RB_MULTIPLE  0x20000000 /* Use multiple consoles */
> > +#define FREEBSD_RB_DUAL              FREENSD_RB_MULTIPLE
> > +#define FREEBSD_RB_BOOTINFO     0x80000000 /* have `struct bootinfo *' arg */
>
> Usually we have "(1 << 0)", "(1 << 1)", etc for bitmask lists.

ok.

>
> > +FUNCTION(grub_unix_real_boot)
> > +        call    EXT_C(grub_dl_unload_all)
> > +        call    EXT_C(grub_stop_floppy)
> > +
> > +        cli
> > +
> > +        popl    %eax
> > +        popl %eax
> > +        call *%eax
>
> Why a call?  Do we need the return address in the stack here?  A comment would
> be nice in that case.

bsds using stack to pass parameter, it's like this:

void __cdecl (*func)(parm1, parm2,...);

the first pop remove the return address,  the second gets the address
of func, and then call it. the function never returns, using call just
make sure the first parameter is at esp + 4.

>
> > +#define ALIGN_DWORD(a)       ((a + 3) & (~3))
> > +#define ALIGN_PAGE(a)        ((a + 4095) & (~4095))
>
> We already have ALIGN_UP:
>
>   ./include/grub/misc.h:#define ALIGN_UP(addr, align) ((long)((char *)addr + align - 1) & ~(align - 1))
>
> it'd be better to reuse that, I think.
>
> > +static const grub_uint32_t freebsd_flags[] = {
> > +  FREEBSD_RB_DUAL, FREEBSD_RB_SERIAL, FREEBSD_RB_ASKNAME,
> > +  FREEBSD_RB_CDROM, FREEBSD_RB_CONFIG, FREEBSD_RB_KDB,
> > +  FREEBSD_RB_GDB, FREEBSD_RB_MUTE, FREEBSD_RB_NOINTR,
> > +  FREEBSD_RB_PAUSE, FREEBSD_RB_QUIET, FREEBSD_RB_DFLTROOT,
> > +  FREEBSD_RB_SINGLE, FREEBSD_RB_VERBOSE
> > +};
>
> We usually put a newline after the '='.

ok.

-- 
Bean



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-11 20:46               ` Bean
  2008-02-11 21:28                 ` Robert Millan
@ 2008-02-11 21:51                 ` walt
  2008-02-12  4:03                   ` Bean
  2008-02-12 11:19                   ` Robert Millan
  1 sibling, 2 replies; 37+ messages in thread
From: walt @ 2008-02-11 21:51 UTC (permalink / raw)
  To: grub-devel


On Tue, 2008-02-12 at 04:46 +0800, Bean wrote:
> On Feb 12, 2008 4:45 AM, Bean <bean123ch@gmail.com> wrote:
> > Hi,
> >
> > Change in this patch:
> >
> > 1. support OpenBSD kernel:
> >
> > set root=(hd0,3,a)
> > openbsd /bsd
> >
> > The modules name is changed to bsd.mod.
> >
> > 2. Support setting kernel flags
> >
> > one character represent one flag, for FreeBSD, it's "DhaCcdgmnpqrsv",
> > for OpenBSD, it's "abcsd".
> >
> > for example, to enable ask for root device name, single user mode and
> > verbose output in FreeBSD:
> >
> > set root=(hd0,2,a)
> > freebsd /boot/loader asv

Any BSD kernel I try to load, including /boot/loader, gives me a 'free 
magic broken' error.  Same with 'multiboot netbsd'.

A separate problem is that 'ls' will list the root directory of my
OpenBSD partition, but not any of the subdirectories like usr, etc,
home....  It just says 'out of disk' when I try.






^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-11 21:51                 ` walt
@ 2008-02-12  4:03                   ` Bean
  2008-02-12 11:19                   ` Robert Millan
  1 sibling, 0 replies; 37+ messages in thread
From: Bean @ 2008-02-12  4:03 UTC (permalink / raw)
  To: The development of GRUB 2

On Feb 12, 2008 5:51 AM, walt <wa1ter@myrealbox.com> wrote:
>
> Any BSD kernel I try to load, including /boot/loader, gives me a 'free
> magic broken' error.  Same with 'multiboot netbsd'.
>
> A separate problem is that 'ls' will list the root directory of my
> OpenBSD partition, but not any of the subdirectories like usr, etc,
> home....  It just says 'out of disk' when I try.

This seems like a fs problem, are you using the same system as before ?

perhaps you can copy the kernel to a fat partition and see if it can be loaded.

-- 
Bean



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-11 21:46                   ` Bean
@ 2008-02-12 11:16                     ` Robert Millan
  0 siblings, 0 replies; 37+ messages in thread
From: Robert Millan @ 2008-02-12 11:16 UTC (permalink / raw)
  To: The development of GRUB 2

On Tue, Feb 12, 2008 at 05:46:49AM +0800, Bean wrote:
> > > +_bsd_mod_CFLAGS = $(COMMON_CFLAGS)
> > > +_bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
> > > +
> > > +# For freebsd.mod
> > > +bsd_mod_SOURCES = loader/i386/pc/bsd_normal.c
> > > +bsd_mod_CFLAGS = $(COMMON_CFLAGS)
> > > +bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
> >
> > How much pc-dependant are those?  Can we hope they will work in e.g.
> > i386-coreboot in the future, when *BSD kernels remove their BIOS
> > dependency?
> 
> freebsd doesn't need bios at all, openbsd need the memory map, but i
> guess it's easy to construct one without using int 15.

In that case, loader/i386/ would be better than loader/i386/pc.  Moving files
in CVS is painful ;-)

> > > +FUNCTION(grub_unix_real_boot)
> > > +        call    EXT_C(grub_dl_unload_all)
> > > +        call    EXT_C(grub_stop_floppy)
> > > +
> > > +        cli
> > > +
> > > +        popl    %eax
> > > +        popl %eax
> > > +        call *%eax
> >
> > Why a call?  Do we need the return address in the stack here?  A comment would
> > be nice in that case.
> 
> bsds using stack to pass parameter, it's like this:
> 
> void __cdecl (*func)(parm1, parm2,...);
> 
> the first pop remove the return address,  the second gets the address
> of func, and then call it. the function never returns, using call just
> make sure the first parameter is at esp + 4.

Ok.  How about adding a comment to make this clear?  Maybe something like:

/* Use cdecl calling convention for *BSD kernels.  */
FUNCTION(grub_unix_real_boot)
	....

	/* Discard `grub_unix_real_boot' return address.  */
	popl %eax

	/* Fetch `entry' address ...  */
	popl %eax

	/* ... and put our return address in its place (the kernel will ignore
	   it, but it expects %esp to point to it.  */
	call *%eax

does this look good?

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-11 21:51                 ` walt
  2008-02-12  4:03                   ` Bean
@ 2008-02-12 11:19                   ` Robert Millan
  2008-02-12 18:47                     ` Bean
  1 sibling, 1 reply; 37+ messages in thread
From: Robert Millan @ 2008-02-12 11:19 UTC (permalink / raw)
  To: The development of GRUB 2

On Mon, Feb 11, 2008 at 01:51:49PM -0800, walt wrote:
> 
> Any BSD kernel I try to load, including /boot/loader, gives me a 'free 
> magic broken' error.  Same with 'multiboot netbsd'.

Sounds like an error I've seen before.  What is the exact error you see,
and when?

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-12 11:19                   ` Robert Millan
@ 2008-02-12 18:47                     ` Bean
  2008-02-12 19:36                       ` Robert Millan
  0 siblings, 1 reply; 37+ messages in thread
From: Bean @ 2008-02-12 18:47 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 1800 bytes --]

Hi,

The new version adds NetBSD support and data file loading in FreeBSD.
You can't load kernel modules, because they have relocation and symbol
issue which is too much to handle, however, you can load data files
like splashimage or memdisk. Examples:

1. Load freebsd loader

set root=(hd0,1,a)
freebsd /boot/loader
boot

2. Load freebsd kernel directly
set root=(hd0,1,a)
freebsd /boot/kernel/kernel
freebsd_loadenv /boot/device.hints
freebsd_module /boot/splash.bmp type=splash_image_data
set FreeBSD.vfs.root.mountfrom=ufs:ad0s1a
boot

Note that in order to show the splashimage, you need to add splash_bmp
module to the kernel.

3. Load OpenBSD kernel
set root=(hd0,2,a)
openbsd /bsd

4. Load NetBSD kernel
set root=(hd0,3,a)
netbsd /netbsd


2008-02-12  Bean  <bean123ch@gmail.com>

	* conf/i386-pc.rmk (pkglib_MODULES): Add aout.mod _bsd.mod and bsd.mod.
	(aout_mod_SOURCES): New variable.
	(aout_mod_CFLAGS): Likewise.
	(aout_mod_LDFLAGS): Likewise.
	(_bsd_mod_SOURCES): New variable.
	(_bsd_mod_CFLAGS): Likewise.
	(_bsd_mod_LDFLAGS): Likewise.
	(bsd_mod_SOURCES): New variable.
	(bsd_mod_CFLAGS): Likewise.
	(bsd_mod_LDFLAGS): Likewise.

	* include/grub/aout.h: New file.

	* include/grub/i386/loader.h (grub_unix_real_boot): New function.

	* include/grub/i386/bsd.h: New file.

	* include/grub/i386/pc/init.h (grub_get_mmap_entry): Use EXPORT_FUNC
	to make it public.

	* kern/elf.c (grub_elf32_load): Get the physical address after the hook
	function is called, so that it's possible to change it inside the hook.
	(grub_elf64_load): Likewise.

	* kern/i386/loader.S (grub_unix_real_boot): New function.

	* loader/aout.c: New file.

	* loader/i386/bsd.c: New file.

	* loader/i386/bsd_normal.c: New file.

	* loader/i386/pc/multiboot.c (grub_multiboot): Handle a.out format.

-- 
Bean

[-- Attachment #2: bsd.diff --]
[-- Type: text/plain, Size: 41814 bytes --]

diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 78e4f00..1a7ee66 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -146,7 +146,8 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
 	_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod	\
 	vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
 	videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod	\
-	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod
+	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \
+	aout.mod _bsd.mod bsd.mod
 
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -298,4 +299,19 @@ lspci_mod_SOURCES = commands/lspci.c
 lspci_mod_CFLAGS = $(COMMON_CFLAGS)
 lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For aout.mod
+aout_mod_SOURCES = loader/aout.c
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _bsd.mod
+_bsd_mod_SOURCES = loader/i386/bsd.c
+_bsd_mod_CFLAGS = $(COMMON_CFLAGS)
+_bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For bsd.mod
+bsd_mod_SOURCES = loader/i386/bsd_normal.c
+bsd_mod_CFLAGS = $(COMMON_CFLAGS)
+bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff --git a/include/grub/aout.h b/include/grub/aout.h
new file mode 100755
index 0000000..3243b82
--- /dev/null
+++ b/include/grub/aout.h
@@ -0,0 +1,91 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_AOUT_HEADER
+#define GRUB_AOUT_HEADER 1
+
+#include <grub/types.h>
+
+struct grub_aout32_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint32_t a_text;		/* text segment size */
+  grub_uint32_t a_data;		/* initialized data size */
+  grub_uint32_t a_bss;		/* uninitialized data size */
+  grub_uint32_t a_syms;		/* symbol table size */
+  grub_uint32_t a_entry;	/* entry point */
+  grub_uint32_t a_trsize;	/* text relocation size */
+  grub_uint32_t a_drsize;	/* data relocation size */
+};
+
+struct grub_aout64_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint64_t a_text;		/* text segment size */
+  grub_uint64_t a_data;		/* initialized data size */
+  grub_uint64_t a_bss;		/* uninitialized data size */
+  grub_uint64_t a_syms;		/* symbol table size */
+  grub_uint64_t a_entry;	/* entry point */
+  grub_uint64_t a_trsize;	/* text relocation size */
+  grub_uint64_t a_drsize;	/* data relocation size */
+};
+
+union grub_aout_header
+{
+  struct grub_aout32_header aout32;
+  struct grub_aout64_header aout64;
+};
+
+#define AOUT_TYPE_NONE		0
+#define AOUT_TYPE_AOUT32	1
+#define AOUT_TYPE_AOUT64	6
+
+#define	AOUT32_OMAGIC		0x107	/* 0407 old impure format */
+#define	AOUT32_NMAGIC		0x108	/* 0410 read-only text */
+#define	AOUT32_ZMAGIC		0x10b	/* 0413 demand load format */
+#define AOUT32_QMAGIC		0xcc	/* 0314 "compact" demand load format */
+
+#define AOUT64_OMAGIC		0x1001
+#define AOUT64_ZMAGIC		0x1002
+#define AOUT64_NMAGIC		0x1003
+
+#define	AOUT_MID_ZERO		0	/* unknown - implementation dependent */
+#define	AOUT_MID_SUN010		1	/* sun 68010/68020 binary */
+#define	AOUT_MID_SUN020		2	/* sun 68020-only binary */
+#define AOUT_MID_I386		134	/* i386 BSD binary */
+#define AOUT_MID_SPARC		138	/* sparc */
+#define	AOUT_MID_HP200		200	/* hp200 (68010) BSD binary */
+#define	AOUT_MID_HP300		300	/* hp300 (68020+68881) BSD binary */
+#define	AOUT_MID_HPUX		0x20C	/* hp200/300 HP-UX binary */
+#define	AOUT_MID_HPUX800	0x20B	/* hp800 HP-UX binary */
+
+#define AOUT_FLAG_PIC		0x10	/* contains position independant code */
+#define AOUT_FLAG_DYNAMIC	0x20	/* contains run-time link-edit info */
+#define AOUT_FLAG_DPMASK	0x30	/* mask for the above */
+
+#define AOUT_GETMAGIC(header) ((header).a_midmag & 0xffff)
+#define AOUT_GETMID(header) ((header).a_midmag >> 16) & 0x03ff)
+#define AOUT_GETFLAG(header) ((header).a_midmag >> 26) & 0x3f)
+
+int EXPORT_FUNC(grub_aout_get_type) (union grub_aout_header *header);
+
+grub_err_t EXPORT_FUNC(grub_aout_load) (grub_file_t file, int offset,
+                                        grub_addr_t load_addr, int load_size,
+                                        grub_addr_t bss_end_addr);
+
+#endif /* ! GRUB_AOUT_HEADER */
diff --git a/include/grub/i386/bsd.h b/include/grub/i386/bsd.h
new file mode 100755
index 0000000..f88c694
--- /dev/null
+++ b/include/grub/i386/bsd.h
@@ -0,0 +1,232 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_BSD_CPU_HEADER
+#define GRUB_BSD_CPU_HEADER	1
+
+#include <grub/types.h>
+
+#define KERNEL_TYPE_NONE	0
+#define KERNEL_TYPE_FREEBSD	1
+#define KERNEL_TYPE_OPENBSD	2
+#define KERNEL_TYPE_NETBSD	3
+
+#define GRUB_BSD_TEMP_BUFFER	0x68000
+
+#define FREEBSD_RB_ASKNAME	(1 << 0)  /* ask for file name to reboot from */
+#define FREEBSD_RB_SINGLE       (1 << 1)  /* reboot to single user only */
+#define FREEBSD_RB_NOSYNC       (1 << 2)  /* dont sync before reboot */
+#define FREEBSD_RB_HALT         (1 << 3)  /* don't reboot, just halt */
+#define FREEBSD_RB_INITNAME     (1 << 4)  /* name given for /etc/init (unused) */
+#define FREEBSD_RB_DFLTROOT     (1 << 5)  /* use compiled-in rootdev */
+#define FREEBSD_RB_KDB          (1 << 6)  /* give control to kernel debugger */
+#define FREEBSD_RB_RDONLY       (1 << 7)  /* mount root fs read-only */
+#define FREEBSD_RB_DUMP         (1 << 8)  /* dump kernel memory before reboot */
+#define FREEBSD_RB_MINIROOT     (1 << 9)  /* mini-root present in memory at boot time */
+#define FREEBSD_RB_CONFIG       (1 << 10) /* invoke user configuration routing */
+#define FREEBSD_RB_VERBOSE      (1 << 11) /* print all potentially useful info */
+#define FREEBSD_RB_SERIAL       (1 << 12) /* user serial port as console */
+#define FREEBSD_RB_CDROM        (1 << 13) /* use cdrom as root */
+#define FREEBSD_RB_GDB		(1 << 15) /* use GDB remote debugger instead of DDB */
+#define FREEBSD_RB_MUTE		(1 << 16) /* Come up with the console muted */
+#define FREEBSD_RB_PAUSE	(1 << 20)
+#define FREEBSD_RB_QUIET	(1 << 21)
+#define FREEBSD_RB_NOINTR	(1 << 28)
+#define FREENSD_RB_MULTIPLE	(1 << 29)  /* Use multiple consoles */
+#define FREEBSD_RB_DUAL		FREENSD_RB_MULTIPLE
+#define FREEBSD_RB_BOOTINFO     (1 << 31) /* have `struct bootinfo *' arg */
+
+#define FREEBSD_B_DEVMAGIC	0xa0000000
+#define FREEBSD_B_SLICESHIFT	20
+#define FREEBSD_B_UNITSHIFT	16
+#define FREEBSD_B_PARTSHIFT	8
+#define FREEBSD_B_TYPESHIFT	0
+
+#define FREEBSD_BOOTINFO_VERSION 1
+#define FREEBSD_N_BIOS_GEOM	8
+
+#define FREEBSD_MODINFO_END		0x0000	/* End of list */
+#define FREEBSD_MODINFO_NAME		0x0001	/* Name of module (string) */
+#define FREEBSD_MODINFO_TYPE		0x0002	/* Type of module (string) */
+#define FREEBSD_MODINFO_ADDR		0x0003	/* Loaded address */
+#define FREEBSD_MODINFO_SIZE		0x0004	/* Size of module */
+#define FREEBSD_MODINFO_EMPTY		0x0005	/* Has been deleted */
+#define FREEBSD_MODINFO_ARGS		0x0006	/* Parameters string */
+#define FREEBSD_MODINFO_METADATA	0x8000	/* Module-specfic */
+
+#define FREEBSD_MODINFOMD_AOUTEXEC	0x0001	/* a.out exec header */
+#define FREEBSD_MODINFOMD_ELFHDR	0x0002	/* ELF header */
+#define FREEBSD_MODINFOMD_SSYM		0x0003	/* start of symbols */
+#define FREEBSD_MODINFOMD_ESYM		0x0004	/* end of symbols */
+#define FREEBSD_MODINFOMD_DYNAMIC	0x0005	/* _DYNAMIC pointer */
+#define FREEBSD_MODINFOMD_ENVP		0x0006	/* envp[] */
+#define FREEBSD_MODINFOMD_HOWTO		0x0007	/* boothowto */
+#define FREEBSD_MODINFOMD_KERNEND	0x0008	/* kernend */
+#define FREEBSD_MODINFOMD_SHDR		0x0009	/* section header table */
+#define FREEBSD_MODINFOMD_NOCOPY	0x8000	/* don't copy this metadata to the kernel */
+
+#define FREEBSD_MODINFOMD_DEPLIST	(0x4001 | FREEBSD_MODINFOMD_NOCOPY)  /* depends on */
+
+#define FREEBSD_MODTYPE_KERNEL		"elf kernel"
+#define FREEBSD_MODTYPE_MODULE		"elf module"
+#define FREEBSD_MODTYPE_RAW		"raw"
+
+struct grub_freebsd_bootinfo
+{
+  grub_uint32_t bi_version;
+  grub_uint8_t *bi_kernelname;
+  struct nfs_diskless *bi_nfs_diskless;
+  grub_uint32_t bi_n_bios_used;
+  grub_uint32_t bi_bios_geom[FREEBSD_N_BIOS_GEOM];
+  grub_uint32_t bi_size;
+  grub_uint8_t bi_memsizes_valid;
+  grub_uint8_t bi_bios_dev;
+  grub_uint8_t bi_pad[2];
+  grub_uint32_t bi_basemem;
+  grub_uint32_t bi_extmem;
+  grub_uint32_t bi_symtab;
+  grub_uint32_t bi_esymtab;
+  grub_uint32_t bi_kernend;
+  grub_uint32_t bi_envp;
+  grub_uint32_t bi_modulep;
+} __attribute__ ((packed));
+
+#define OPENBSD_RB_ASKNAME	(1 << 0)  /* ask for file name to reboot from */
+#define OPENBSD_RB_SINGLE	(1 << 1)  /* reboot to single user only */
+#define OPENBSD_RB_NOSYNC	(1 << 2)  /* dont sync before reboot */
+#define OPENBSD_RB_HALT		(1 << 3)  /* don't reboot, just halt */
+#define OPENBSD_RB_INITNAME	(1 << 4)  /* name given for /etc/init (unused) */
+#define OPENBSD_RB_DFLTROOT	(1 << 5)  /* use compiled-in rootdev */
+#define OPENBSD_RB_KDB		(1 << 6)  /* give control to kernel debugger */
+#define OPENBSD_RB_RDONLY	(1 << 7)  /* mount root fs read-only */
+#define OPENBSD_RB_DUMP		(1 << 8)  /* dump kernel memory before reboot */
+#define OPENBSD_RB_MINIROOT	(1 << 9)  /* mini-root present in memory at boot time */
+#define OPENBSD_RB_CONFIG	(1 << 10) /* change configured devices */
+#define OPENBSD_RB_TIMEBAD	(1 << 11) /* don't call resettodr() in boot() */
+#define OPENBSD_RB_POWERDOWN	(1 << 12) /* attempt to power down machine */
+#define OPENBSD_RB_SERCONS	(1 << 13) /* use serial console if available */
+#define OPENBSD_RB_USERREQ	(1 << 14) /* boot() called at user request (e.g. ddb) */
+
+#define OPENBSD_B_DEVMAGIC	0xa0000000
+#define OPENBSD_B_ADAPTORSHIFT	24
+#define OPENBSD_B_CTRLSHIFT	20
+#define OPENBSD_B_UNITSHIFT	16
+#define OPENBSD_B_PARTSHIFT	8
+#define OPENBSD_B_TYPESHIFT	0
+
+#define OPENBSD_BOOTARG_APIVER	(OPENBSD_BAPIV_VECTOR | \
+                                 OPENBSD_BAPIV_ENV | \
+                                 OPENBSD_BAPIV_BMEMMAP)
+
+#define OPENBSD_BAPIV_ANCIENT	0x0  /* MD old i386 bootblocks */
+#define OPENBSD_BAPIV_VARS	0x1  /* MD structure w/ add info passed */
+#define OPENBSD_BAPIV_VECTOR	0x2  /* MI vector of MD structures passed */
+#define OPENBSD_BAPIV_ENV	0x4  /* MI environment vars vector */
+#define OPENBSD_BAPIV_BMEMMAP	0x8  /* MI memory map passed is in bytes */
+
+#define OPENBSD_BOOTARG_ENV	0x1000
+#define OPENBSD_BOOTARG_END	-1
+
+#define	OPENBSD_BOOTARG_MMAP	0
+
+struct grub_openbsd_bios_mmap
+{
+  grub_uint64_t addr;
+  grub_uint64_t len;
+  grub_uint32_t type;
+} bios_memmap_t;
+
+struct grub_openbsd_bootargs
+{
+  int ba_type;
+  int ba_size;
+  struct grub_openbsd_bootargs *ba_next;
+} __attribute__ ((packed));
+
+#define NETBSD_RB_AUTOBOOT	0  /* flags for system auto-booting itself */
+
+#define NETBSD_RB_ASKNAME	(1 << 0)  /* ask for file name to reboot from */
+#define NETBSD_RB_SINGLE	(1 << 1)  /* reboot to single user only */
+#define NETBSD_RB_NOSYNC	(1 << 2)  /* dont sync before reboot */
+#define NETBSD_RB_HALT		(1 << 3)  /* don't reboot, just halt */
+#define NETBSD_RB_INITNAME	(1 << 4)  /* name given for /etc/init (unused) */
+#define NETBSD_RB_UNUSED1	(1 << 5)  /* was RB_DFLTROOT, obsolete */
+#define NETBSD_RB_KDB		(1 << 6)  /* give control to kernel debugger */
+#define NETBSD_RB_RDONLY	(1 << 7)  /* mount root fs read-only */
+#define NETBSD_RB_DUMP		(1 << 8)  /* dump kernel memory before reboot */
+#define NETBSD_RB_MINIROOT	(1 << 9)  /* mini-root present in memory at boot time */
+#define NETBSD_RB_STRING	(1 << 10) /* use provided bootstr */
+#define NETBSD_RB_POWERDOWN     ((1 << 11) | RB_HALT) /* turn power off (or at least halt) */
+#define NETBSD_RB_USERCONFIG	(1 << 12) /* change configured devices */
+
+#define NETBSD_AB_NORMAL	0  /* boot normally (default) */
+
+#define NETBSD_AB_QUIET		(1 << 16) /* boot quietly */
+#define NETBSD_AB_VERBOSE	(1 << 17) /* boot verbosely */
+#define NETBSD_AB_SILENT	(1 << 18) /* boot silently */
+#define NETBSD_AB_DEBUG		(1 << 19) /* boot with debug messages */
+
+struct grub_netbsd_bootinfo
+{
+  grub_uint32_t bi_count;
+  void *bi_data[1];
+};
+
+#define NETBSD_BTINFO_BOOTPATH		0
+#define NETBSD_BTINFO_ROOTDEVICE	1
+#define NETBSD_BTINFO_BOOTDISK		3
+
+struct grub_netbsd_btinfo_common
+{
+  int len;
+  int type;
+};
+
+struct grub_netbsd_btinfo_bootpath
+{
+  struct grub_netbsd_btinfo_common common;
+  char bootpath[80];
+};
+
+struct grub_netbsd_btinfo_rootdevice
+{
+  struct grub_netbsd_btinfo_common common;
+  char devname[16];
+};
+
+struct grub_netbsd_btinfo_bootdisk
+{
+  struct grub_netbsd_btinfo_common common;
+  int labelsector;  /* label valid if != -1 */
+  struct
+    {
+      grub_uint16_t type, checksum;
+      char packname[16];
+    } label;
+  int biosdev;
+  int partition;
+};
+
+void grub_rescue_cmd_freebsd (int argc, char *argv[]);
+void grub_rescue_cmd_openbsd (int argc, char *argv[]);
+void grub_rescue_cmd_netbsd (int argc, char *argv[]);
+
+void grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[]);
+void grub_rescue_cmd_freebsd_module (int argc, char *argv[]);
+
+#endif /* ! GRUB_BSD_CPU_HEADER */
diff --git a/include/grub/i386/loader.h b/include/grub/i386/loader.h
index 45a1652..5f912cd 100644
--- a/include/grub/i386/loader.h
+++ b/include/grub/i386/loader.h
@@ -39,6 +39,9 @@ void EXPORT_FUNC(grub_multiboot_real_boot) (grub_addr_t entry,
 void EXPORT_FUNC(grub_multiboot2_real_boot) (grub_addr_t entry,
                                              struct grub_multiboot_info *mbi)
      __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_unix_real_boot) (grub_addr_t entry, ...)
+     __attribute__ ((cdecl,noreturn));
+
 
 /* It is necessary to export these functions, because normal mode commands
    reuse rescue mode commands.  */
diff --git a/include/grub/i386/pc/init.h b/include/grub/i386/pc/init.h
index 115deb4..0c6a129 100644
--- a/include/grub/i386/pc/init.h
+++ b/include/grub/i386/pc/init.h
@@ -40,7 +40,7 @@ struct grub_machine_mmap_entry
 
 /* Get a memory map entry. Return next continuation value. Zero means
    the end.  */
-grub_uint32_t grub_get_mmap_entry (struct grub_machine_mmap_entry *entry,
+grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
 				   grub_uint32_t cont);
 
 /* Turn on/off Gate A20.  */
diff --git a/kern/elf.c b/kern/elf.c
index ca10b5b..3e90ea0 100644
--- a/kern/elf.c
+++ b/kern/elf.c
@@ -228,9 +228,9 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
     if (phdr->p_type != PT_LOAD)
       return 0;
 
-    load_addr = phdr->p_paddr;
     if (load_hook && load_hook (phdr, &load_addr))
       return 1;
+    load_addr = phdr->p_paddr;
 
     if (load_addr < load_base)
       load_base = load_addr;
@@ -407,9 +407,9 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
     if (phdr->p_type != PT_LOAD)
       return 0;
 
-    load_addr = phdr->p_paddr;
     if (load_hook && load_hook (phdr, &load_addr))
       return 1;
+    load_addr = phdr->p_paddr;
 
     if (load_addr < load_base)
       load_base = load_addr;
diff --git a/kern/i386/loader.S b/kern/i386/loader.S
index 266f4ef..baf1255 100644
--- a/kern/i386/loader.S
+++ b/kern/i386/loader.S
@@ -162,3 +162,25 @@ FUNCTION(grub_multiboot2_real_boot)
         movl    $MULTIBOOT2_BOOTLOADER_MAGIC,%eax 
         popl    %ecx
         jmp     *%ecx
+
+/*
+ * Use cdecl calling convention for *BSD kernels.
+ */
+
+FUNCTION(grub_unix_real_boot)
+
+        call    EXT_C(grub_dl_unload_all)
+        call    EXT_C(grub_stop_floppy)
+
+	/* Interrupts should be disabled.  */
+        cli
+
+	/* Discard `grub_unix_real_boot' return address.  */
+        popl    %eax
+
+        /* Fetch `entry' address ...  */
+        popl	%eax
+
+        /* ... and put our return address in its place (the kernel will ignore
+          it, but it expects %esp to point to it.  */
+        call	*%eax
diff --git a/loader/aout.c b/loader/aout.c
new file mode 100755
index 0000000..2c82b60
--- /dev/null
+++ b/loader/aout.c
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ *  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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+int
+grub_aout_get_type (union grub_aout_header *header)
+{
+  int magic;
+
+  magic = AOUT_GETMAGIC (header->aout32);
+  if ((magic == AOUT32_OMAGIC) || (magic == AOUT32_NMAGIC) ||
+      (magic == AOUT32_ZMAGIC) || (magic == AOUT32_QMAGIC))
+    return AOUT_TYPE_AOUT32;
+  else if ((magic == AOUT64_OMAGIC) || (magic == AOUT64_NMAGIC) ||
+	   (magic == AOUT64_ZMAGIC))
+    return AOUT_TYPE_AOUT64;
+  else
+    return AOUT_TYPE_NONE;
+}
+
+grub_err_t
+grub_aout_load (grub_file_t file, int offset,
+                grub_addr_t load_addr,
+		int load_size,
+                grub_addr_t bss_end_addr)
+{
+  if ((grub_file_seek (file, offset)) == (grub_off_t) - 1)
+    return grub_errno;
+
+  if (!load_size)
+    load_size = file->size - offset;
+
+  grub_file_read (file, (char *) load_addr, load_size);
+
+  if (grub_errno)
+    return grub_errno;
+
+  if (bss_end_addr)
+    grub_memset (load_addr + load_size, 0,
+                 bss_end_addr - load_addr - load_size);
+
+  return GRUB_ERR_NONE;
+}
diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c
new file mode 100644
index 0000000..2bc737e
--- /dev/null
+++ b/loader/i386/bsd.c
@@ -0,0 +1,772 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/cpu/loader.h>
+#include <grub/cpu/bsd.h>
+#include <grub/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/elfload.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+#include <grub/aout.h>
+
+#define ALIGN_DWORD(a)	ALIGN_UP (a, 4)
+#define ALIGN_PAGE(a)	ALIGN_UP (a, 4096)
+
+#define MOD_BUF_ALLOC_UNIT	4096
+
+static int kernel_type;
+static grub_dl_t my_mod;
+static grub_addr_t entry, kern_start, kern_end;
+static grub_uint32_t bootflags;
+static char *mod_buf;
+static grub_uint32_t mod_buf_len, mod_buf_max;
+static int is_elf_kernel;
+
+static const char freebsd_opts[] = "DhaCcdgmnpqrsv";
+static const grub_uint32_t freebsd_flags[] =
+{
+  FREEBSD_RB_DUAL, FREEBSD_RB_SERIAL, FREEBSD_RB_ASKNAME,
+  FREEBSD_RB_CDROM, FREEBSD_RB_CONFIG, FREEBSD_RB_KDB,
+  FREEBSD_RB_GDB, FREEBSD_RB_MUTE, FREEBSD_RB_NOINTR,
+  FREEBSD_RB_PAUSE, FREEBSD_RB_QUIET, FREEBSD_RB_DFLTROOT,
+  FREEBSD_RB_SINGLE, FREEBSD_RB_VERBOSE
+};
+
+static const char openbsd_opts[] = "abcsd";
+static const grub_uint32_t openbsd_flags[] =
+{
+  OPENBSD_RB_ASKNAME, OPENBSD_RB_HALT, OPENBSD_RB_CONFIG,
+  OPENBSD_RB_SINGLE, OPENBSD_RB_KDB
+};
+
+static const char netbsd_opts[] = "abcdmqsvxz";
+static const grub_uint32_t netbsd_flags[] =
+{
+  NETBSD_RB_ASKNAME, NETBSD_RB_HALT, NETBSD_RB_USERCONFIG,
+  NETBSD_RB_KDB, NETBSD_RB_MINIROOT, NETBSD_AB_QUIET,
+  NETBSD_RB_SINGLE, NETBSD_AB_VERBOSE, NETBSD_AB_DEBUG,
+  NETBSD_AB_SILENT
+};
+
+static void
+grub_bsd_get_device (grub_uint32_t * biosdev,
+		     grub_uint32_t * unit,
+		     grub_uint32_t * slice, grub_uint32_t * part)
+{
+  char *p;
+
+  *biosdev = *unit = *slice = *part = 0;
+  p = grub_env_get ("root");
+  if ((p) && ((p[0] == 'h') || (p[0] == 'f')) && (p[1] == 'd') &&
+      (p[2] >= '0') && (p[2] <= '9'))
+    {
+      if (p[0] == 'h')
+	*biosdev = 0x80;
+
+      *unit = grub_strtoul (p + 2, &p, 0);
+      *biosdev += *unit;
+
+      if ((p) && (p[0] == ','))
+	{
+	  if ((p[1] >= '0') && (p[1] <= '9'))
+	    {
+	      *slice = grub_strtoul (p + 1, &p, 0);
+
+	      if ((p) && (p[0] == ','))
+		p++;
+	    }
+
+	  if ((p[0] >= 'a') && (p[0] <= 'z'))
+	    *part = p[0] - 'a';
+	}
+    }
+}
+
+static grub_err_t
+grub_freebsd_add_meta (grub_uint32_t type, void *data, grub_uint32_t len)
+{
+  if (mod_buf_max < mod_buf_len + len + 8)
+    {
+      char *new_buf;
+
+      do
+	{
+	  mod_buf_max += MOD_BUF_ALLOC_UNIT;
+	}
+      while (mod_buf_max < mod_buf_len + len + 8);
+
+      new_buf = grub_malloc (mod_buf_max);
+      if (!new_buf)
+	return grub_errno;
+
+      grub_memcpy (new_buf, mod_buf, mod_buf_len);
+      grub_free (mod_buf);
+
+      mod_buf = new_buf;
+    }
+
+  *((grub_uint32_t *) (mod_buf + mod_buf_len)) = type;
+  *((grub_uint32_t *) (mod_buf + mod_buf_len + 4)) = len;
+  mod_buf_len += 8;
+
+  if (len)
+    grub_memcpy (mod_buf + mod_buf_len, data, len);
+
+  mod_buf_len = ALIGN_DWORD (mod_buf_len + len);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_freebsd_add_meta_module (int is_kern, int argc, char **argv,
+			      grub_addr_t addr, grub_uint32_t size)
+{
+  char *name, *type;
+
+  name = grub_strrchr (argv[0], '/');
+  if (name)
+    name++;
+  else
+    name = argv[0];
+
+  if (grub_freebsd_add_meta (FREEBSD_MODINFO_NAME, name,
+			     grub_strlen (name) + 1))
+    return grub_errno;
+
+  argc--;
+  argv++;
+
+  if ((argc) && (!grub_memcmp (argv[0], "type=", 5)))
+    {
+      type = &argv[0][5];
+      argc--;
+      argv++;
+    }
+  else
+    type = (is_kern) ? FREEBSD_MODTYPE_KERNEL : FREEBSD_MODTYPE_RAW;
+
+  if ((grub_freebsd_add_meta (FREEBSD_MODINFO_TYPE, type,
+			      grub_strlen (type) + 1)) ||
+      (grub_freebsd_add_meta (FREEBSD_MODINFO_ADDR, &addr, sizeof (addr))) ||
+      (grub_freebsd_add_meta (FREEBSD_MODINFO_SIZE, &size, sizeof (size))))
+    return grub_errno;
+
+  if (argc)
+    {
+      int i, n;
+
+      n = 0;
+      for (i = 0; i < argc; i++)
+	{
+	  n += grub_strlen (argv[i]) + 1;
+	}
+
+      if (n)
+	{
+	  char cmdline[n], *p;
+
+	  p = cmdline;
+	  for (i = 0; i < argc; i++)
+	    {
+	      grub_strcpy (p, argv[i]);
+	      p += grub_strlen (argv[i]);
+	      *(p++) = ' ';
+	    }
+	  *p = 0;
+
+	  if (grub_freebsd_add_meta (FREEBSD_MODINFO_ARGS, cmdline, n))
+	    return grub_errno;
+	}
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_freebsd_list_modules (void)
+{
+  grub_uint32_t pos = 0;
+
+  grub_printf ("  %-18s  %-18s%14s%14s\n", "name", "type", "addr", "size");
+  while (pos < mod_buf_len)
+    {
+      grub_uint32_t type, size;
+
+      type = *((grub_uint32_t *) (mod_buf + pos));
+      size = *((grub_uint32_t *) (mod_buf + pos + 4));
+      pos += 8;
+      switch (type)
+	{
+	case FREEBSD_MODINFO_NAME:
+	case FREEBSD_MODINFO_TYPE:
+	  grub_printf ("  %-18s", mod_buf + pos);
+	  break;
+	case FREEBSD_MODINFO_ADDR:
+	  {
+	    grub_addr_t addr;
+
+	    addr = *((grub_addr_t *) (mod_buf + pos));
+	    grub_printf ("    0x%08x", addr);
+	    break;
+	  }
+	case FREEBSD_MODINFO_SIZE:
+	  {
+	    grub_uint32_t len;
+
+	    len = *((grub_uint32_t *) (mod_buf + pos));
+	    grub_printf ("    0x%08x\n", len);
+	  }
+	}
+
+      pos = ALIGN_DWORD (pos + size);
+    }
+}
+
+static grub_err_t
+grub_freebsd_boot (void)
+{
+  struct grub_freebsd_bootinfo bi;
+  char *p;
+  grub_uint32_t bootdev, biosdev, unit, slice, part;
+
+  auto int iterate_env (struct grub_env_var *var);
+  int iterate_env (struct grub_env_var *var)
+  {
+    if ((!grub_memcmp (var->name, "FreeBSD.", 8)) && (var->name[8]))
+      {
+	grub_strcpy (p, &var->name[8]);
+	p += grub_strlen (p);
+	*(p++) = '=';
+	grub_strcpy (p, var->value);
+	p += grub_strlen (p) + 1;
+      }
+
+    return 0;
+  }
+
+  grub_memset (&bi, 0, sizeof (bi));
+  bi.bi_version = FREEBSD_BOOTINFO_VERSION;
+  bi.bi_size = sizeof (bi);
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+  bootdev = (FREEBSD_B_DEVMAGIC + ((slice + 1) << FREEBSD_B_SLICESHIFT) +
+	     (unit << FREEBSD_B_UNITSHIFT) + (part << FREEBSD_B_PARTSHIFT));
+
+  bi.bi_bios_dev = biosdev;
+
+  p = (char *) kern_end;
+
+  grub_env_iterate (iterate_env);
+
+  if (p != (char *) kern_end)
+    {
+      *(p++) = 0;
+
+      bi.bi_envp = kern_end;
+      kern_end = ALIGN_PAGE ((grub_uint32_t) p);
+    }
+
+  if (is_elf_kernel)
+    {
+      if (grub_freebsd_add_meta (FREEBSD_MODINFO_END, 0, 0))
+	return grub_errno;
+
+      grub_memcpy ((char *) kern_end, mod_buf, mod_buf_len);
+      bi.bi_modulep = kern_end;
+
+      kern_end = ALIGN_PAGE (kern_end + mod_buf_len);
+    }
+
+  bi.bi_kernend = kern_end;
+
+  grub_unix_real_boot (entry, bootflags | FREEBSD_RB_BOOTINFO, bootdev,
+		       0, 0, 0, &bi, bi.bi_modulep, kern_end);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_openbsd_boot (void)
+{
+  char *buf = (char *) GRUB_BSD_TEMP_BUFFER;
+  struct grub_machine_mmap_entry mmap;
+  struct grub_openbsd_bios_mmap *pm;
+  struct grub_openbsd_bootargs *pa;
+  grub_uint32_t bootdev, biosdev, unit, slice, part, cont;
+
+  pa = (struct grub_openbsd_bootargs *) buf;
+
+  pa->ba_type = OPENBSD_BOOTARG_MMAP;
+  pm = (struct grub_openbsd_bios_mmap *) (pa + 1);
+  cont = grub_get_mmap_entry (&mmap, 0);
+  if (mmap.size)
+    do
+      {
+	pm->addr = mmap.addr;
+	pm->len = mmap.len;
+	pm->type = mmap.type;
+	pm++;
+
+	if (!cont)
+	  break;
+
+	cont = grub_get_mmap_entry (&mmap, cont);
+      }
+    while (mmap.size);
+
+  pa->ba_size = (char *) pm - (char *) pa;
+  pa->ba_next = (struct grub_openbsd_bootargs *) pm;
+  pa = pa->ba_next;
+  pa->ba_type = OPENBSD_BOOTARG_END;
+  pa++;
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+  bootdev = (OPENBSD_B_DEVMAGIC + (unit << OPENBSD_B_UNITSHIFT) +
+	     (part << OPENBSD_B_PARTSHIFT));
+
+  grub_unix_real_boot (entry, bootflags, bootdev, OPENBSD_BOOTARG_APIVER,
+		       0, grub_upper_mem >> 10, grub_lower_mem >> 10,
+		       (char *) pa - buf, buf);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_netbsd_boot (void)
+{
+  struct grub_netbsd_btinfo_rootdevice *rootdev;
+  struct grub_netbsd_bootinfo *bootinfo;
+  grub_uint32_t biosdev, unit, slice, part;
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+
+  rootdev = (struct grub_netbsd_btinfo_rootdevice *) GRUB_BSD_TEMP_BUFFER;
+
+  rootdev->common.len = sizeof (struct grub_netbsd_btinfo_rootdevice);
+  rootdev->common.type = NETBSD_BTINFO_ROOTDEVICE;
+  grub_sprintf (rootdev->devname, "%cd%d%c", (biosdev & 0x80) ? 'w' : 'f',
+		unit, 'a' + part);
+
+  bootinfo = (struct grub_netbsd_bootinfo *) (rootdev + 1);
+  bootinfo->bi_count = 1;
+  bootinfo->bi_data[0] = rootdev;
+
+  grub_unix_real_boot (entry, bootflags, 0, bootinfo,
+		       0, grub_upper_mem >> 10, grub_lower_mem >> 10);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_unload (void)
+{
+  if (mod_buf)
+    {
+      grub_free (mod_buf);
+      mod_buf = 0;
+      mod_buf_max = 0;
+    }
+
+  kernel_type = KERNEL_TYPE_NONE;
+  grub_dl_unref (my_mod);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_load_aout (grub_file_t file, union grub_aout_header *ah)
+{
+  grub_addr_t load_addr, bss_end_addr;
+  int ofs, align_page;
+
+  if (grub_aout_get_type (ah) != AOUT_TYPE_AOUT32)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid a.out header");
+
+  entry = ah->aout32.a_entry & 0xFFFFFF;
+
+  if (AOUT_GETMAGIC (ah->aout32) == AOUT32_ZMAGIC)
+    {
+      load_addr = entry;
+      ofs = 0x1000;
+      align_page = 0;
+    }
+  else
+    {
+      load_addr = entry & 0xF00000;
+      ofs = sizeof (struct grub_aout32_header);
+      align_page = 1;
+    }
+
+  if (load_addr < 0x100000)
+    return grub_error (GRUB_ERR_BAD_OS, "load address below 1M");
+
+  kern_start = load_addr;
+  kern_end = load_addr + ah->aout32.a_text + ah->aout32.a_data;
+  if (align_page)
+    kern_end = ALIGN_PAGE (kern_end);
+
+  if (ah->aout32.a_bss)
+    {
+      kern_end += ah->aout32.a_bss;
+      if (align_page)
+	kern_end = ALIGN_PAGE (kern_end);
+
+      bss_end_addr = kern_end;
+    }
+  else
+    bss_end_addr = 0;
+
+  return grub_aout_load (file, ofs, load_addr,
+			 ah->aout32.a_text + ah->aout32.a_data, bss_end_addr);
+}
+
+static grub_err_t
+grub_bsd_elf32_hook (Elf32_Phdr * phdr, UNUSED grub_addr_t * addr)
+{
+  Elf32_Addr paddr;
+
+  phdr->p_paddr &= 0xFFFFFF;
+  paddr = phdr->p_paddr;
+
+  if ((paddr < grub_os_area_addr)
+      || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Address 0x%x is out of range",
+		       paddr);
+
+  if ((!kern_start) || (paddr < kern_start))
+    kern_start = paddr;
+
+  if (paddr + phdr->p_memsz > kern_end)
+    kern_end = paddr + phdr->p_memsz;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_load_elf (grub_file_t file)
+{
+  grub_elf_t elf = 0;
+  grub_err_t err;
+
+  kern_start = kern_end = 0;
+  elf = grub_elf_file (file);
+  if (!elf)
+    return grub_errno;
+
+  if (grub_elf_is_elf32 (elf))
+    {
+      entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF;
+      err = grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0);
+    }
+  else
+    err = grub_error (GRUB_ERR_BAD_OS, "invalid elf");
+
+  return err;
+}
+
+static grub_err_t
+grub_bsd_load (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  union grub_aout_header ah;
+
+  grub_dl_ref (my_mod);
+
+  grub_loader_unset ();
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (!file)
+    goto fail;
+
+  if (grub_file_read (file, (char *) &ah, sizeof (ah)) != sizeof (ah))
+    {
+      grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header");
+      goto fail;
+    }
+
+  is_elf_kernel = (grub_aout_get_type (&ah) == AOUT_TYPE_NONE);
+  if (is_elf_kernel)
+    grub_bsd_load_elf (file);
+  else
+    grub_bsd_load_aout (file, &ah);
+
+fail:
+
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    grub_dl_unref (my_mod);
+
+  return grub_errno;
+}
+
+static grub_uint32_t
+grub_bsd_parse_flags (char *str, const char *opts,
+		      const grub_uint32_t * flags)
+{
+  grub_uint32_t result = 0;
+
+  while (*str)
+    {
+      const char *po;
+      const grub_uint32_t *pf;
+
+      po = opts;
+      pf = flags;
+      while (*po)
+	{
+	  if (*str == *po)
+	    {
+	      result |= *pf;
+	      break;
+	    }
+	  po++;
+	  pf++;
+	}
+      str++;
+    }
+
+  return result;
+}
+
+void
+grub_rescue_cmd_freebsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_FREEBSD;
+  bootflags = ((argc <= 1) ? 0 :
+	       grub_bsd_parse_flags (argv[1], freebsd_opts, freebsd_flags));
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    {
+      kern_end = ALIGN_PAGE (kern_end);
+      if ((is_elf_kernel) &&
+	  (grub_freebsd_add_meta_module (1, argc, argv, kern_start,
+					 kern_end - kern_start)))
+	return;
+      grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 1);
+    }
+}
+
+void
+grub_rescue_cmd_openbsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_OPENBSD;
+  bootflags = ((argc <= 1) ? 0 :
+	       grub_bsd_parse_flags (argv[1], openbsd_opts, openbsd_flags));
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 1);
+}
+
+void
+grub_rescue_cmd_netbsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_NETBSD;
+  bootflags = ((argc <= 1) ? 0 :
+	       grub_bsd_parse_flags (argv[1], netbsd_opts, netbsd_flags));
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 1);
+}
+
+void
+grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  char *buf = 0, *curr, *next;
+  int len;
+
+  if (kernel_type != KERNEL_TYPE_FREEBSD)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "only freebsd support environment");
+      return;
+    }
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no filename");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if ((!file) || (!file->size))
+    goto fail;
+
+  len = file->size;
+  buf = grub_malloc (len + 1);
+  if (!buf)
+    goto fail;
+
+  if (grub_file_read (file, buf, len) != len)
+    goto fail;
+
+  buf[len] = 0;
+
+  next = buf;
+  while (next)
+    {
+      char *p;
+
+      curr = next;
+      next = grub_strchr (curr, '\n');
+      if (next)
+	{
+
+	  p = next - 1;
+	  while (p > curr)
+	    {
+	      if ((*p != '\r') && (*p != ' ') && (*p != '\t'))
+		break;
+	      p--;
+	    }
+
+	  if ((p > curr) && (*p == '"'))
+	    p--;
+
+	  *(p + 1) = 0;
+	  next++;
+	}
+
+      if (*curr == '#')
+	continue;
+
+      p = grub_strchr (curr, '=');
+      if (!p)
+	continue;
+
+      *(p++) = 0;
+
+      if (*curr)
+	{
+	  char name[grub_strlen (curr) + 8 + 1];
+
+	  if (*p == '"')
+	    p++;
+
+	  grub_sprintf (name, "FreeBSD.%s", curr);
+	  if (grub_env_set (name, p))
+	    goto fail;
+	}
+    }
+
+fail:
+  grub_free (buf);
+
+  if (file)
+    grub_file_close (file);
+}
+
+void
+grub_rescue_cmd_freebsd_module (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+
+  if (kernel_type != KERNEL_TYPE_FREEBSD)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "only freebsd support module");
+      return;
+    }
+
+  if (!is_elf_kernel)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "only elf kernel support module");
+      return;
+    }
+
+  /* List the current modules if no parameter.  */
+  if (!argc)
+    {
+      grub_freebsd_list_modules ();
+      return;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if ((!file) || (!file->size))
+    goto fail;
+
+  if (kern_end + file->size > grub_os_area_addr + grub_os_area_size)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "Not enough memory for the module");
+      goto fail;
+    }
+
+  grub_file_read (file, (char *) kern_end, file->size);
+  if ((!grub_errno) &&
+      (!grub_freebsd_add_meta_module (0, argc, argv, kern_end, file->size)))
+    kern_end = ALIGN_PAGE (kern_end + file->size);
+
+fail:
+  if (file)
+    grub_file_close (file);
+}
+
+GRUB_MOD_INIT (bsd)
+{
+  grub_rescue_register_command ("freebsd",
+				grub_rescue_cmd_freebsd,
+				"load freebsd kernel");
+  grub_rescue_register_command ("openbsd",
+				grub_rescue_cmd_openbsd,
+				"load openbsd kernel");
+  grub_rescue_register_command ("netbsd",
+				grub_rescue_cmd_netbsd, "load netbsd kernel");
+
+  grub_rescue_register_command ("freebsd_loadenv",
+				grub_rescue_cmd_freebsd_loadenv,
+				"load freebsd env");
+  grub_rescue_register_command ("freebsd_module",
+				grub_rescue_cmd_freebsd_module,
+				"load freebsd module");
+
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI (bsd)
+{
+  grub_rescue_unregister_command ("freebsd");
+  grub_rescue_unregister_command ("openbsd");
+  grub_rescue_unregister_command ("netbsd");
+
+  grub_rescue_unregister_command ("freebsd_loadenv");
+  grub_rescue_unregister_command ("freebsd_module");
+
+  if (mod_buf)
+    {
+      grub_free (mod_buf);
+      mod_buf = 0;
+      mod_buf_max = 0;
+    }
+}
diff --git a/loader/i386/bsd_normal.c b/loader/i386/bsd_normal.c
new file mode 100644
index 0000000..f09cd57
--- /dev/null
+++ b/loader/i386/bsd_normal.c
@@ -0,0 +1,101 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+static grub_err_t
+grub_normal_freebsd_command (struct grub_arg_list *state
+			     __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_freebsd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_openbsd_command (struct grub_arg_list *state
+			     __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_openbsd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_netbsd_command (struct grub_arg_list *state
+			    __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_netbsd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_freebsd_loadenv_command (struct grub_arg_list *state
+				     __attribute__ ((unused)), int argc,
+				     char **args)
+{
+  grub_rescue_cmd_freebsd_loadenv (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_freebsd_module_command (struct grub_arg_list *state
+				    __attribute__ ((unused)), int argc,
+				    char **args)
+{
+  grub_rescue_cmd_freebsd_module (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT (bsd_normal)
+{
+  (void) mod;			/* To stop warning.  */
+  grub_register_command ("freebsd", grub_normal_freebsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "freebsd FILE [OPTS] [ARGS...]",
+			 "Load freebsd kernel.", 0);
+  grub_register_command ("openbsd", grub_normal_openbsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "openbsd FILE [OPTS]", "Load openbsd kernel.", 0);
+  grub_register_command ("netbsd", grub_normal_netbsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "netbsd FILE [OPTS]", "Load netbsd kernel.", 0);
+
+  grub_register_command ("freebsd_loadenv",
+			 grub_normal_freebsd_loadenv_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "freebsd_loadenv FILE", "Load freebsd env.", 0);
+  grub_register_command ("freebsd_module",
+			 grub_normal_freebsd_module_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "freebsd_module [FILE [type=module_type] [ARGS...]]",
+			 "Load freebsd module.", 0);
+}
+
+GRUB_MOD_FINI (bsd_normal)
+{
+  grub_unregister_command ("freebsd");
+  grub_unregister_command ("openbsd");
+  grub_unregister_command ("netbsd");
+
+  grub_unregister_command ("freebsd_loadenv");
+  grub_unregister_command ("freebsd_module");
+}
diff --git a/loader/i386/pc/multiboot.c b/loader/i386/pc/multiboot.c
index 893f11b..67959cf 100644
--- a/loader/i386/pc/multiboot.c
+++ b/loader/i386/pc/multiboot.c
@@ -36,6 +36,7 @@
 #include <grub/machine/init.h>
 #include <grub/machine/memory.h>
 #include <grub/elf.h>
+#include <grub/aout.h>
 #include <grub/file.h>
 #include <grub/err.h>
 #include <grub/rescue.h>
@@ -315,7 +316,22 @@ grub_multiboot (int argc, char *argv[])
       goto fail;
     }
 
-  if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
+  if (header->flags & MULTIBOOT_AOUT_KLUDGE)
+    {
+      int ofs;
+
+      ofs = (char *) header - buffer -
+            (header->header_addr - header->load_addr);
+      if ((grub_aout_load (file, ofs, header->load_addr,
+                           ((header->load_end_addr == 0) ? 0 :
+                            header->load_end_addr - header->load_addr),
+                           header->bss_end_addr))
+          !=GRUB_ERR_NONE)
+        goto fail;
+
+      entry = header->entry_addr;
+    }
+  else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
     goto fail;
   
   mbi = grub_malloc (sizeof (struct grub_multiboot_info));

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-12 18:47                     ` Bean
@ 2008-02-12 19:36                       ` Robert Millan
  2008-02-13 10:40                         ` Bean
  0 siblings, 1 reply; 37+ messages in thread
From: Robert Millan @ 2008-02-12 19:36 UTC (permalink / raw)
  To: The development of GRUB 2

On Wed, Feb 13, 2008 at 02:47:30AM +0800, Bean wrote:
> +        /* ... and put our return address in its place (the kernel will ignore
> +          it, but it expects %esp to point to it.  */
> +        call	*%eax

Unmatched parenthesis here (sorry I guess that's my fault ;-)).

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-12 19:36                       ` Robert Millan
@ 2008-02-13 10:40                         ` Bean
  2008-02-13 15:40                           ` Robert Millan
  2008-02-13 17:25                           ` walt
  0 siblings, 2 replies; 37+ messages in thread
From: Bean @ 2008-02-13 10:40 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 637 bytes --]

On Feb 13, 2008 3:36 AM, Robert Millan <rmh@aybabtu.com> wrote:
> On Wed, Feb 13, 2008 at 02:47:30AM +0800, Bean wrote:
> > +        /* ... and put our return address in its place (the kernel will ignore
> > +          it, but it expects %esp to point to it.  */
> > +        call *%eax
>
> Unmatched parenthesis here (sorry I guess that's my fault ;-)).

Ok. I also fix the alloc magic broken problem, it's caused by
grub_elf_file, which will close the file when the elf magic is not
found. However, the upper level still use that file, that cause the
memory problem.

The patch should be applied after the previous bsd.diff.

-- 
Bean

[-- Attachment #2: bsd_2.diff --]
[-- Type: text/plain, Size: 5969 bytes --]

diff --git a/kern/elf.c b/kern/elf.c
index 3e90ea0..f4a71c1 100644
--- a/kern/elf.c
+++ b/kern/elf.c
@@ -85,9 +85,8 @@ grub_elf_file (grub_file_t file)
   return elf;
 
 fail:
-  grub_error_push ();
-  grub_elf_close (elf);
-  grub_error_pop ();
+  grub_free (elf->phdrs);
+  grub_free (elf);
   return 0;
 }
 
@@ -177,8 +176,8 @@ grub_elf32_size (grub_elf_t elf)
 
   /* Run through the program headers to calculate the total memory size we
    * should claim.  */
-  auto int calcsize (grub_elf_t _elf, Elf32_Phdr *phdr, void *_arg);
-  int calcsize (grub_elf_t UNUSED _elf, Elf32_Phdr *phdr, void UNUSED *_arg)
+  auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf32_Phdr *phdr, void *_arg);
+  int NESTED_FUNC_ATTR calcsize (grub_elf_t UNUSED _elf, Elf32_Phdr *phdr, void UNUSED *_arg)
     {
       /* Only consider loadable segments.  */
       if (phdr->p_type != PT_LOAD)
@@ -355,8 +354,8 @@ grub_elf64_size (grub_elf_t elf)
 
   /* Run through the program headers to calculate the total memory size we
    * should claim.  */
-  auto int calcsize (grub_elf_t _elf, Elf64_Phdr *phdr, void *_arg);
-  int calcsize (grub_elf_t UNUSED _elf, Elf64_Phdr *phdr, void UNUSED *_arg)
+  auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf64_Phdr *phdr, void *_arg);
+  int NESTED_FUNC_ATTR calcsize (grub_elf_t UNUSED _elf, Elf64_Phdr *phdr, void UNUSED *_arg)
     {
       /* Only consider loadable segments.  */
       if (phdr->p_type != PT_LOAD)
diff --git a/kern/i386/loader.S b/kern/i386/loader.S
index baf1255..39cf6a0 100644
--- a/kern/i386/loader.S
+++ b/kern/i386/loader.S
@@ -181,6 +181,8 @@ FUNCTION(grub_unix_real_boot)
         /* Fetch `entry' address ...  */
         popl	%eax
 
-        /* ... and put our return address in its place (the kernel will ignore
-          it, but it expects %esp to point to it.  */
+        /*
+         * ... and put our return address in its place. The kernel will
+         * ignore it, but it expects %esp to point to it.
+         */
         call	*%eax
diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c
index 2bc737e..4966afa 100644
--- a/loader/i386/bsd.c
+++ b/loader/i386/bsd.c
@@ -400,17 +400,24 @@ grub_bsd_unload (void)
 }
 
 static grub_err_t
-grub_bsd_load_aout (grub_file_t file, union grub_aout_header *ah)
+grub_bsd_load_aout (grub_file_t file)
 {
   grub_addr_t load_addr, bss_end_addr;
   int ofs, align_page;
+  union grub_aout_header ah;
+
+  if ((grub_file_seek (file, 0)) == (grub_off_t) - 1)
+    return grub_errno;
 
-  if (grub_aout_get_type (ah) != AOUT_TYPE_AOUT32)
+  if (grub_file_read (file, (char *) &ah, sizeof (ah)) != sizeof (ah))
+    return grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header");
+
+  if (grub_aout_get_type (&ah) != AOUT_TYPE_AOUT32)
     return grub_error (GRUB_ERR_BAD_OS, "invalid a.out header");
 
-  entry = ah->aout32.a_entry & 0xFFFFFF;
+  entry = ah.aout32.a_entry & 0xFFFFFF;
 
-  if (AOUT_GETMAGIC (ah->aout32) == AOUT32_ZMAGIC)
+  if (AOUT_GETMAGIC (ah.aout32) == AOUT32_ZMAGIC)
     {
       load_addr = entry;
       ofs = 0x1000;
@@ -427,13 +434,13 @@ grub_bsd_load_aout (grub_file_t file, union grub_aout_header *ah)
     return grub_error (GRUB_ERR_BAD_OS, "load address below 1M");
 
   kern_start = load_addr;
-  kern_end = load_addr + ah->aout32.a_text + ah->aout32.a_data;
+  kern_end = load_addr + ah.aout32.a_text + ah.aout32.a_data;
   if (align_page)
     kern_end = ALIGN_PAGE (kern_end);
 
-  if (ah->aout32.a_bss)
+  if (ah.aout32.a_bss)
     {
-      kern_end += ah->aout32.a_bss;
+      kern_end += ah.aout32.a_bss;
       if (align_page)
 	kern_end = ALIGN_PAGE (kern_end);
 
@@ -443,7 +450,7 @@ grub_bsd_load_aout (grub_file_t file, union grub_aout_header *ah)
     bss_end_addr = 0;
 
   return grub_aout_load (file, ofs, load_addr,
-			 ah->aout32.a_text + ah->aout32.a_data, bss_end_addr);
+			 ah.aout32.a_text + ah.aout32.a_data, bss_end_addr);
 }
 
 static grub_err_t
@@ -469,32 +476,24 @@ grub_bsd_elf32_hook (Elf32_Phdr * phdr, UNUSED grub_addr_t * addr)
 }
 
 static grub_err_t
-grub_bsd_load_elf (grub_file_t file)
+grub_bsd_load_elf (grub_elf_t elf)
 {
-  grub_elf_t elf = 0;
-  grub_err_t err;
-
   kern_start = kern_end = 0;
-  elf = grub_elf_file (file);
-  if (!elf)
-    return grub_errno;
 
   if (grub_elf_is_elf32 (elf))
     {
       entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF;
-      err = grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0);
+      return grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0);
     }
   else
-    err = grub_error (GRUB_ERR_BAD_OS, "invalid elf");
-
-  return err;
+    return grub_error (GRUB_ERR_BAD_OS, "invalid elf");
 }
 
 static grub_err_t
 grub_bsd_load (int argc, char *argv[])
 {
-  grub_file_t file = 0;
-  union grub_aout_header ah;
+  grub_file_t file;
+  grub_elf_t elf;
 
   grub_dl_ref (my_mod);
 
@@ -510,23 +509,23 @@ grub_bsd_load (int argc, char *argv[])
   if (!file)
     goto fail;
 
-  if (grub_file_read (file, (char *) &ah, sizeof (ah)) != sizeof (ah))
+  elf = grub_elf_file (file);
+  if (elf)
     {
-      grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header");
-      goto fail;
+      is_elf_kernel = 1;
+      grub_bsd_load_elf (elf);
+      grub_elf_close (elf);
     }
-
-  is_elf_kernel = (grub_aout_get_type (&ah) == AOUT_TYPE_NONE);
-  if (is_elf_kernel)
-    grub_bsd_load_elf (file);
   else
-    grub_bsd_load_aout (file, &ah);
+    {
+      is_elf_kernel = 0;
+      grub_errno = 0;
+      grub_bsd_load_aout (file);
+      grub_file_close (file);
+    }
 
 fail:
 
-  if (file)
-    grub_file_close (file);
-
   if (grub_errno != GRUB_ERR_NONE)
     grub_dl_unref (my_mod);
 
diff --git a/loader/multiboot2.c b/loader/multiboot2.c
index 65fdea1..42c6fad 100644
--- a/loader/multiboot2.c
+++ b/loader/multiboot2.c
@@ -371,6 +371,7 @@ grub_multiboot2 (int argc, char *argv[])
     }
   else
     {
+      grub_errno = 0;
       grub_dprintf ("loader", "Loading non-ELF multiboot 2 file.\n");
 
       if (header)

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-13 10:40                         ` Bean
@ 2008-02-13 15:40                           ` Robert Millan
  2008-02-13 16:51                             ` Bean
  2008-02-13 17:25                           ` walt
  1 sibling, 1 reply; 37+ messages in thread
From: Robert Millan @ 2008-02-13 15:40 UTC (permalink / raw)
  To: The development of GRUB 2

On Wed, Feb 13, 2008 at 06:40:14PM +0800, Bean wrote:
> On Feb 13, 2008 3:36 AM, Robert Millan <rmh@aybabtu.com> wrote:
> > On Wed, Feb 13, 2008 at 02:47:30AM +0800, Bean wrote:
> > > +        /* ... and put our return address in its place (the kernel will ignore
> > > +          it, but it expects %esp to point to it.  */
> > > +        call *%eax
> >
> > Unmatched parenthesis here (sorry I guess that's my fault ;-)).
> 
> Ok. I also fix the alloc magic broken problem, it's caused by
> grub_elf_file, which will close the file when the elf magic is not
> found. However, the upper level still use that file, that cause the
> memory problem.
> 
> The patch should be applied after the previous bsd.diff.

You forgot the ChangeLog entry..

> --- a/loader/multiboot2.c
> +++ b/loader/multiboot2.c
> @@ -371,6 +371,7 @@ grub_multiboot2 (int argc, char *argv[])
>      }
>    else
>      {
> +      grub_errno = 0;
>        grub_dprintf ("loader", "Loading non-ELF multiboot 2 file.\n");
>  
>        if (header)

Why this?

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-13 15:40                           ` Robert Millan
@ 2008-02-13 16:51                             ` Bean
  0 siblings, 0 replies; 37+ messages in thread
From: Bean @ 2008-02-13 16:51 UTC (permalink / raw)
  To: The development of GRUB 2

On Feb 13, 2008 11:40 PM, Robert Millan <rmh@aybabtu.com> wrote:
>
> On Wed, Feb 13, 2008 at 06:40:14PM +0800, Bean wrote:
> > On Feb 13, 2008 3:36 AM, Robert Millan <rmh@aybabtu.com> wrote:
> > > On Wed, Feb 13, 2008 at 02:47:30AM +0800, Bean wrote:
> > > > +        /* ... and put our return address in its place (the kernel will ignore
> > > > +          it, but it expects %esp to point to it.  */
> > > > +        call *%eax
> > >
> > > Unmatched parenthesis here (sorry I guess that's my fault ;-)).
> >
> > Ok. I also fix the alloc magic broken problem, it's caused by
> > grub_elf_file, which will close the file when the elf magic is not
> > found. However, the upper level still use that file, that cause the
> > memory problem.
> >
> > The patch should be applied after the previous bsd.diff.
>
> You forgot the ChangeLog entry..
>
> > --- a/loader/multiboot2.c
> > +++ b/loader/multiboot2.c
> > @@ -371,6 +371,7 @@ grub_multiboot2 (int argc, char *argv[])
> >      }
> >    else
> >      {
> > +      grub_errno = 0;
> >        grub_dprintf ("loader", "Loading non-ELF multiboot 2 file.\n");
> >
> >        if (header)
>
> Why this?

After grub_elf_file have failed, the grub_errno would be set, we need
to reset it in order to test for another case.

-- 
Bean



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-13 10:40                         ` Bean
  2008-02-13 15:40                           ` Robert Millan
@ 2008-02-13 17:25                           ` walt
  2008-02-13 17:37                             ` Bean
  1 sibling, 1 reply; 37+ messages in thread
From: walt @ 2008-02-13 17:25 UTC (permalink / raw)
  To: grub-devel

Bean wrote:

> Ok. I also fix the alloc magic broken problem, it's caused by
> grub_elf_file, which will close the file when the elf magic is not
> found. However, the upper level still use that file, that cause the
> memory problem.
>
> The patch should be applied after the previous bsd.diff...

I'm very confused by the results :o/  I'm now running today's cvs
plus bsd.diff plus bsd_2.diff.  Some things work and some don't.

I can boot openbsd perfectly -- but only if I load the 'bsd' kernel
from a different filesystem e.g. FAT32.  I can't read any files from
the FFS/UFS on my openbsd partition -- I get 'outside of partition'.

I can multiboot netbsd perfectly -- but not from the netbsd partition.
If I 'multiboot /netbsd' from the netbsd partition I get 'broken magic'.
However, I can 'netbsd /netbsd' perfectly from the netbsd partition.
(See why I'm confused?)

When I 'freebsd /boot/loader' or 'freebsd /boot/kernel/kernel' from
the FreeBSD partition I get 'broken magic'.  If I 'freebsd /kernel'
from a FAT32 partition the kernel seems to load okay but then when
I 'boot' nothing prints to the console and the OS never starts.
If I 'freebsd /loader' from a FAT fs then the loader runs correctly
but of course I need to set 'currdev' by hand.

I'm wondering if you have commited all of your UFS/FFS patches to
cvs.  Seems like I'm seeing some old UFS problems that you fixed
once already(?).




^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-13 17:25                           ` walt
@ 2008-02-13 17:37                             ` Bean
  2008-02-13 20:31                               ` walt
  0 siblings, 1 reply; 37+ messages in thread
From: Bean @ 2008-02-13 17:37 UTC (permalink / raw)
  To: The development of GRUB 2

On Feb 14, 2008 1:25 AM, walt <wa1ter@myrealbox.com> wrote:
> Bean wrote:
>
> > Ok. I also fix the alloc magic broken problem, it's caused by
> > grub_elf_file, which will close the file when the elf magic is not
> > found. However, the upper level still use that file, that cause the
> > memory problem.
> >
> > The patch should be applied after the previous bsd.diff...
>
> I'm very confused by the results :o/  I'm now running today's cvs
> plus bsd.diff plus bsd_2.diff.  Some things work and some don't.
>
> I can boot openbsd perfectly -- but only if I load the 'bsd' kernel
> from a different filesystem e.g. FAT32.  I can't read any files from
> the FFS/UFS on my openbsd partition -- I get 'outside of partition'.
>
> I can multiboot netbsd perfectly -- but not from the netbsd partition.
> If I 'multiboot /netbsd' from the netbsd partition I get 'broken magic'.
> However, I can 'netbsd /netbsd' perfectly from the netbsd partition.
> (See why I'm confused?)
>
> When I 'freebsd /boot/loader' or 'freebsd /boot/kernel/kernel' from
> the FreeBSD partition I get 'broken magic'.  If I 'freebsd /kernel'
> from a FAT32 partition the kernel seems to load okay but then when
> I 'boot' nothing prints to the console and the OS never starts.
> If I 'freebsd /loader' from a FAT fs then the loader runs correctly
> but of course I need to set 'currdev' by hand.
>
> I'm wondering if you have commited all of your UFS/FFS patches to
> cvs.  Seems like I'm seeing some old UFS problems that you fixed
> once already(?).

Is it possible that your build is not clean ? you can try to run make
distclean and then configure and make, see if there is any difference.

i'm also putting my compiled version at:

http://grub4dos.sourceforge.net/grub2/g2ldr

you can load it as linux kernel, please see if it helps.

-- 
Bean



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-13 17:37                             ` Bean
@ 2008-02-13 20:31                               ` walt
  2008-02-14  2:43                                 ` Bean
  0 siblings, 1 reply; 37+ messages in thread
From: walt @ 2008-02-13 20:31 UTC (permalink / raw)
  To: grub-devel

Bean wrote:
> On Feb 14, 2008 1:25 AM, walt<wa1ter@myrealbox.com>  wrote:

>> ...
>> I'm wondering if you have commited all of your UFS/FFS patches to
>> cvs.  Seems like I'm seeing some old UFS problems that you fixed
>> once already(?).

> Is it possible that your build is not clean ? you can try to run make
> distclean and then configure and make, see if there is any difference.

Yes, I do that every time.  I'm betting that your source tree is not
the same as mine -- i.e. you have some patches I don't have.  Could
you perhaps put up a tarball of your working source tree so I can
compare it to mine?

> i'm also putting my compiled version at:
>
> http://grub4dos.sourceforge.net/grub2/g2ldr

Yes, this works perfectly except that I still can't read my openbsd
filesystem correctly.  I can list / but none of the subdirectories,
and I can't even read a small text file from /.  (I guess that also
means I can't properly read the directories in /).  Everything I try
gives me 'out of partition' or similar.

Progress! :o)






^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-13 20:31                               ` walt
@ 2008-02-14  2:43                                 ` Bean
  2008-02-15 13:29                                   ` walt
  0 siblings, 1 reply; 37+ messages in thread
From: Bean @ 2008-02-14  2:43 UTC (permalink / raw)
  To: The development of GRUB 2

On Feb 14, 2008 4:31 AM, walt <wa1ter@myrealbox.com> wrote:
> Yes, this works perfectly except that I still can't read my openbsd
> filesystem correctly.  I can list / but none of the subdirectories,
> and I can't even read a small text file from /.  (I guess that also
> means I can't properly read the directories in /).  Everything I try
> gives me 'out of partition' or similar.
>
> Progress! :o)

In that case, it should be a fs problem, what's the disk layout, how
big is your ufs partition ? It could be handy if you can make a small
image that produce similar results.

-- 
Bean



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-14  2:43                                 ` Bean
@ 2008-02-15 13:29                                   ` walt
  2008-02-15 14:03                                     ` Bean
  2008-02-15 14:14                                     ` Bean
  0 siblings, 2 replies; 37+ messages in thread
From: walt @ 2008-02-15 13:29 UTC (permalink / raw)
  To: grub-devel

Bean wrote:
> On Feb 14, 2008 4:31 AM, walt<wa1ter@myrealbox.com>  wrote:
>> Yes, this works perfectly except that I still can't read my openbsd
>> filesystem correctly.  I can list / but none of the subdirectories,
>> and I can't even read a small text file from /.  (I guess that also
>> means I can't properly read the directories in /).  Everything I try
>> gives me 'out of partition' or similar.
>>
>> Progress! :o)
>
> In that case, it should be a fs problem, what's the disk layout, how
> big is your ufs partition ? It could be handy if you can make a small
> image that produce similar results.

I made a small openbsd image to send you, but it works perfectly with
your g2ldr so there's no point in sending it :o)  I think that problem
is not worth your time or mine.

I still have the bigger problem that my grub2 doesn't work like your
g2ldr.  My version still halts with 'broken magic' or reboots instantly
when I type 'boot'.  These are bugs that I was seeing several weeks
ago and you already fixed them once, but now they are back again.

I still think that a patch or two never got committed to cvs, but I
don't know which one(s).  Could you try applying your bsd.diff and
bsd_2.diff to current cvs sources and see if it works for you?

Here is what I do:

Apply the two patches to a clean cvs tree.
./autogen.sh  [because you patched an rmk file]
mkdir build
cd build
../configure && make
rm ata.mod
./grub-mkimage -d . -o grub2 *.mod

Then I use grub legacy to boot grub2 as the 'kernel'.

Do you see any problems with the above?  Does it work properly for
you?

Thanks, Bean!







^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-15 13:29                                   ` walt
@ 2008-02-15 14:03                                     ` Bean
  2008-02-15 14:14                                     ` Bean
  1 sibling, 0 replies; 37+ messages in thread
From: Bean @ 2008-02-15 14:03 UTC (permalink / raw)
  To: The development of GRUB 2

On Fri, Feb 15, 2008 at 9:29 PM, walt <wa1ter@myrealbox.com> wrote:
>
> Bean wrote:
>  > On Feb 14, 2008 4:31 AM, walt<wa1ter@myrealbox.com>  wrote:
>  >> Yes, this works perfectly except that I still can't read my openbsd
>  >> filesystem correctly.  I can list / but none of the subdirectories,
>  >> and I can't even read a small text file from /.  (I guess that also
>  >> means I can't properly read the directories in /).  Everything I try
>  >> gives me 'out of partition' or similar.
>  >>
>  >> Progress! :o)
>  >
>  > In that case, it should be a fs problem, what's the disk layout, how
>  > big is your ufs partition ? It could be handy if you can make a small
>  > image that produce similar results.
>
>  I made a small openbsd image to send you, but it works perfectly with
>  your g2ldr so there's no point in sending it :o)  I think that problem
>  is not worth your time or mine.
>
>  I still have the bigger problem that my grub2 doesn't work like your
>  g2ldr.  My version still halts with 'broken magic' or reboots instantly
>  when I type 'boot'.  These are bugs that I was seeing several weeks
>  ago and you already fixed them once, but now they are back again.
>
>  I still think that a patch or two never got committed to cvs, but I
>  don't know which one(s).  Could you try applying your bsd.diff and
>  bsd_2.diff to current cvs sources and see if it works for you?
>
>  Here is what I do:
>
>  Apply the two patches to a clean cvs tree.
>  ./autogen.sh  [because you patched an rmk file]
>  mkdir build
>  cd build
>  ../configure && make
>  rm ata.mod
>  ./grub-mkimage -d . -o grub2 *.mod

Don't include all the modules in the kernel, you only need those
necessary to access the boot partition, for example, i use the
following command to create core.img:

./grub-mkimage -d . -o core.img biosdisk iso9660 pc fat ntfs ext2 ufs
bsd boot ls multiboot

To create g2ldr, add the lnxboot.img header:

cat lnxboot.img core.img > g2ldr

This contain enough modules to do the test, no need to load extra
module from disk.

Also, please use linux to build grub2, *bsd may compile ok, but don't
know if the result is correct.

-- 
Bean



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-15 13:29                                   ` walt
  2008-02-15 14:03                                     ` Bean
@ 2008-02-15 14:14                                     ` Bean
  2008-02-15 18:43                                       ` walt
  2008-02-15 22:43                                       ` walt
  1 sibling, 2 replies; 37+ messages in thread
From: Bean @ 2008-02-15 14:14 UTC (permalink / raw)
  To: The development of GRUB 2

On Fri, Feb 15, 2008 at 9:29 PM, walt <wa1ter@myrealbox.com> wrote:
>  I made a small openbsd image to send you, but it works perfectly with
>  your g2ldr so there's no point in sending it :o)  I think that problem
>  is not worth your time or mine.

BTW, how big is your ufs partition ? I have tested FreeBSD 6.3, NetBSD
4.0 and OpenBSD 4.2 in a 1G virtual disk, they all seems ok, perhaps
if the disk is larger, the problem would occur.

-- 
Bean



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-15 14:14                                     ` Bean
@ 2008-02-15 18:43                                       ` walt
  2008-02-15 18:58                                         ` Bean
  2008-02-16 16:43                                         ` Bean
  2008-02-15 22:43                                       ` walt
  1 sibling, 2 replies; 37+ messages in thread
From: walt @ 2008-02-15 18:43 UTC (permalink / raw)
  To: grub-devel

Bean wrote:
> On Fri, Feb 15, 2008 at 9:29 PM, walt<wa1ter@myrealbox.com>  wrote:
>>   I made a small openbsd image to send you, but it works perfectly with
>>   your g2ldr so there's no point in sending it :o)  I think that problem
>>   is not worth your time or mine.
>
> BTW, how big is your ufs partition ? I have tested FreeBSD 6.3, NetBSD
> 4.0 and OpenBSD 4.2 in a 1G virtual disk, they all seems ok, perhaps
> if the disk is larger, the problem would occur.

Your instructions to load only the needed modules works great, thanks.

My openbsd partition is 7GB, but some other ufs partitions are bigger
than that.  I suspect that I have some disklabel conflict on that disk.
I have netbsd, openbsd, freebsd all installed on the same disk, each
with its own disklabel.  I don't know why it would cause that problem
in particular, though.

I'd like to know exactly how you create your virtual disks for testing.
I've been creating appropriate-size partitions on a USB stick and then
copying whatever files I need onto it.  Then I use dd to make an img
file to run in qemu.  It's a very slow process and I'd like to do it
better.  Any hints?

Thanks.






^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-15 18:43                                       ` walt
@ 2008-02-15 18:58                                         ` Bean
  2008-02-16 16:43                                         ` Bean
  1 sibling, 0 replies; 37+ messages in thread
From: Bean @ 2008-02-15 18:58 UTC (permalink / raw)
  To: The development of GRUB 2

On Sat, Feb 16, 2008 at 2:43 AM, walt <wa1ter@myrealbox.com> wrote:
>
> Bean wrote:
>  > On Fri, Feb 15, 2008 at 9:29 PM, walt<wa1ter@myrealbox.com>  wrote:
>  >>   I made a small openbsd image to send you, but it works perfectly with
>  >>   your g2ldr so there's no point in sending it :o)  I think that problem
>  >>   is not worth your time or mine.
>  >
>  > BTW, how big is your ufs partition ? I have tested FreeBSD 6.3, NetBSD
>  > 4.0 and OpenBSD 4.2 in a 1G virtual disk, they all seems ok, perhaps
>  > if the disk is larger, the problem would occur.
>
>  Your instructions to load only the needed modules works great, thanks.
>
>  My openbsd partition is 7GB, but some other ufs partitions are bigger
>  than that.  I suspect that I have some disklabel conflict on that disk.
>  I have netbsd, openbsd, freebsd all installed on the same disk, each
>  with its own disklabel.  I don't know why it would cause that problem
>  in particular, though.
>
>  I'd like to know exactly how you create your virtual disks for testing.
>  I've been creating appropriate-size partitions on a USB stick and then
>  copying whatever files I need onto it.  Then I use dd to make an img
>  file to run in qemu.  It's a very slow process and I'd like to do it
>  better.  Any hints?

I'm creating a blank disk using qemu-img, then install using the iso file.

-- 
Bean



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-15 14:14                                     ` Bean
  2008-02-15 18:43                                       ` walt
@ 2008-02-15 22:43                                       ` walt
  2008-02-16  1:00                                         ` walt
  1 sibling, 1 reply; 37+ messages in thread
From: walt @ 2008-02-15 22:43 UTC (permalink / raw)
  To: grub-devel


On Fri, 2008-02-15 at 22:14 +0800, Bean wrote:
> On Fri, Feb 15, 2008 at 9:29 PM, walt <wa1ter@myrealbox.com> wrote:
> >  I made a small openbsd image to send you, but it works perfectly with
> >  your g2ldr so there's no point in sending it :o)  I think that problem
> >  is not worth your time or mine.
> 
> BTW, how big is your ufs partition ? I have tested FreeBSD 6.3, NetBSD
> 4.0 and OpenBSD 4.2 in a 1G virtual disk, they all seems ok, perhaps
> if the disk is larger, the problem would occur.

Hah!  I think I found the problem.  I just noticed that gparted calls my
openbsd/ufs partition an *ext2* filesystem!  I seem to recall similar
messages from other fs utility programs about the magic number being
for ext2 even though it's really ufs.  This is probably a leftover
magic number from an earlier linux or such.

I haven't found any way to change just the magic number instead of
deleting the partition and starting over.  Do you know of an easy
way to do it?  I could use a hex disc editor but I don't know where
the magic number is, exactly.

Thanks!






^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-15 22:43                                       ` walt
@ 2008-02-16  1:00                                         ` walt
  0 siblings, 0 replies; 37+ messages in thread
From: walt @ 2008-02-16  1:00 UTC (permalink / raw)
  To: grub-devel

walt wrote:
> On Fri, 2008-02-15 at 22:14 +0800, Bean wrote:
>> On Fri, Feb 15, 2008 at 9:29 PM, walt<wa1ter@myrealbox.com>  wrote:
>>>   I made a small openbsd image to send you, but it works perfectly with
>>>   your g2ldr so there's no point in sending it :o)  I think that problem
>>>   is not worth your time or mine.
>> BTW, how big is your ufs partition ? I have tested FreeBSD 6.3, NetBSD
>> 4.0 and OpenBSD 4.2 in a 1G virtual disk, they all seems ok, perhaps
>> if the disk is larger, the problem would occur.
>
> Hah!  I think I found the problem.  I just noticed that gparted calls my
> openbsd/ufs partition an *ext2* filesystem!  I seem to recall similar
> messages from other fs utility programs about the magic number being
> for ext2 even though it's really ufs.  This is probably a leftover
> magic number from an earlier linux or such.
>
> I haven't found any way to change just the magic number instead of
> deleting the partition and starting over.  Do you know of an easy
> way to do it?  I could use a hex disc editor but I don't know where
> the magic number is, exactly.

Never mind, I found the magic number and changed it.  Now I don't see
any complaints about ext2 or a bad magic number, but grub2 still can't
read any directory but / on my openbsd partition.  I'll go back to
saying that this particular problem isn't worth more of your time or mine.
(But I do learn a lot by chasing these bugs even if I can't fix them :o)




^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-15 18:43                                       ` walt
  2008-02-15 18:58                                         ` Bean
@ 2008-02-16 16:43                                         ` Bean
  2008-02-16 18:12                                           ` walt
  1 sibling, 1 reply; 37+ messages in thread
From: Bean @ 2008-02-16 16:43 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 2232 bytes --]

On Feb 16, 2008 2:43 AM, walt <wa1ter@myrealbox.com> wrote:
> I'd like to know exactly how you create your virtual disks for testing.
> I've been creating appropriate-size partitions on a USB stick and then
> copying whatever files I need onto it.  Then I use dd to make an img
> file to run in qemu.  It's a very slow process and I'd like to do it
> better.  Any hints?

i think the problem may be caused by dd. bsd disk label record the
start sector on disk, if you just copy the partition, the disk label
would be wrong, therefore cause the 'out of partition' problem, which
generally means reading beyond the end of disk. I recommend install
inside qemu to create consistent disk structure.

Anyway, i think the bsd module should be fine, here is the whole
patch, if nobody objects, i would like to commit it soon.

2008-02-16  Bean  <bean123ch@gmail.com>

	* conf/i386-pc.rmk (pkglib_MODULES): Add aout.mod _bsd.mod and bsd.mod.
	(aout_mod_SOURCES): New variable.
	(aout_mod_CFLAGS): Likewise.
	(aout_mod_LDFLAGS): Likewise.
	(_bsd_mod_SOURCES): New variable.
	(_bsd_mod_CFLAGS): Likewise.
	(_bsd_mod_LDFLAGS): Likewise.
	(bsd_mod_SOURCES): New variable.
	(bsd_mod_CFLAGS): Likewise.
	(bsd_mod_LDFLAGS): Likewise.

	* include/grub/aout.h: New file.

	* include/grub/i386/loader.h (grub_unix_real_boot): New function.

	* include/grub/i386/bsd.h: New file.

	* include/grub/i386/pc/init.h (grub_get_mmap_entry): Use EXPORT_FUNC
	to make it public.

	* kern/elf.c (grub_elf32_load): Get the physical address after the hook
	function is called, so that it's possible to change it inside the hook.
	(grub_elf64_load): Likewise.
	(grub_elf_file): Don't close the file if elf header is not found.
	(grub_elf_close): Close the file if grub_elf_file fails (The new
	grub_elf_file won't close it).
	(grub_elf32_size): Use NESTED_FUNC_ATTR for nested function calcsize.
	(grub_elf64_size): Likewise.

	* kern/i386/loader.S (grub_unix_real_boot): New function.

	* loader/aout.c: New file.

	* loader/i386/bsd.c: New file.

	* loader/i386/bsd_normal.c: New file.

	* loader/i386/pc/multiboot.c (grub_multiboot): Handle a.out format.

	* loader/multiboot2.c (grub_multiboot2): Reset grub_errno so that it
	can test othe formats.

-- 
Bean

[-- Attachment #2: bsd3.diff --]
[-- Type: text/plain, Size: 43820 bytes --]

diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index a03f721..1a0e54b 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -152,7 +152,8 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
 	_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod	\
 	vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
 	videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod	\
-	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod
+	ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \
+	aout.mod _bsd.mod bsd.mod
 
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -304,4 +305,19 @@ lspci_mod_SOURCES = commands/lspci.c
 lspci_mod_CFLAGS = $(COMMON_CFLAGS)
 lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For aout.mod
+aout_mod_SOURCES = loader/aout.c
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _bsd.mod
+_bsd_mod_SOURCES = loader/i386/bsd.c
+_bsd_mod_CFLAGS = $(COMMON_CFLAGS)
+_bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For bsd.mod
+bsd_mod_SOURCES = loader/i386/bsd_normal.c
+bsd_mod_CFLAGS = $(COMMON_CFLAGS)
+bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff --git a/include/grub/aout.h b/include/grub/aout.h
new file mode 100755
index 0000000..3243b82
--- /dev/null
+++ b/include/grub/aout.h
@@ -0,0 +1,91 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_AOUT_HEADER
+#define GRUB_AOUT_HEADER 1
+
+#include <grub/types.h>
+
+struct grub_aout32_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint32_t a_text;		/* text segment size */
+  grub_uint32_t a_data;		/* initialized data size */
+  grub_uint32_t a_bss;		/* uninitialized data size */
+  grub_uint32_t a_syms;		/* symbol table size */
+  grub_uint32_t a_entry;	/* entry point */
+  grub_uint32_t a_trsize;	/* text relocation size */
+  grub_uint32_t a_drsize;	/* data relocation size */
+};
+
+struct grub_aout64_header
+{
+  grub_uint32_t a_midmag;	/* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint64_t a_text;		/* text segment size */
+  grub_uint64_t a_data;		/* initialized data size */
+  grub_uint64_t a_bss;		/* uninitialized data size */
+  grub_uint64_t a_syms;		/* symbol table size */
+  grub_uint64_t a_entry;	/* entry point */
+  grub_uint64_t a_trsize;	/* text relocation size */
+  grub_uint64_t a_drsize;	/* data relocation size */
+};
+
+union grub_aout_header
+{
+  struct grub_aout32_header aout32;
+  struct grub_aout64_header aout64;
+};
+
+#define AOUT_TYPE_NONE		0
+#define AOUT_TYPE_AOUT32	1
+#define AOUT_TYPE_AOUT64	6
+
+#define	AOUT32_OMAGIC		0x107	/* 0407 old impure format */
+#define	AOUT32_NMAGIC		0x108	/* 0410 read-only text */
+#define	AOUT32_ZMAGIC		0x10b	/* 0413 demand load format */
+#define AOUT32_QMAGIC		0xcc	/* 0314 "compact" demand load format */
+
+#define AOUT64_OMAGIC		0x1001
+#define AOUT64_ZMAGIC		0x1002
+#define AOUT64_NMAGIC		0x1003
+
+#define	AOUT_MID_ZERO		0	/* unknown - implementation dependent */
+#define	AOUT_MID_SUN010		1	/* sun 68010/68020 binary */
+#define	AOUT_MID_SUN020		2	/* sun 68020-only binary */
+#define AOUT_MID_I386		134	/* i386 BSD binary */
+#define AOUT_MID_SPARC		138	/* sparc */
+#define	AOUT_MID_HP200		200	/* hp200 (68010) BSD binary */
+#define	AOUT_MID_HP300		300	/* hp300 (68020+68881) BSD binary */
+#define	AOUT_MID_HPUX		0x20C	/* hp200/300 HP-UX binary */
+#define	AOUT_MID_HPUX800	0x20B	/* hp800 HP-UX binary */
+
+#define AOUT_FLAG_PIC		0x10	/* contains position independant code */
+#define AOUT_FLAG_DYNAMIC	0x20	/* contains run-time link-edit info */
+#define AOUT_FLAG_DPMASK	0x30	/* mask for the above */
+
+#define AOUT_GETMAGIC(header) ((header).a_midmag & 0xffff)
+#define AOUT_GETMID(header) ((header).a_midmag >> 16) & 0x03ff)
+#define AOUT_GETFLAG(header) ((header).a_midmag >> 26) & 0x3f)
+
+int EXPORT_FUNC(grub_aout_get_type) (union grub_aout_header *header);
+
+grub_err_t EXPORT_FUNC(grub_aout_load) (grub_file_t file, int offset,
+                                        grub_addr_t load_addr, int load_size,
+                                        grub_addr_t bss_end_addr);
+
+#endif /* ! GRUB_AOUT_HEADER */
diff --git a/include/grub/i386/bsd.h b/include/grub/i386/bsd.h
new file mode 100755
index 0000000..f88c694
--- /dev/null
+++ b/include/grub/i386/bsd.h
@@ -0,0 +1,232 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_BSD_CPU_HEADER
+#define GRUB_BSD_CPU_HEADER	1
+
+#include <grub/types.h>
+
+#define KERNEL_TYPE_NONE	0
+#define KERNEL_TYPE_FREEBSD	1
+#define KERNEL_TYPE_OPENBSD	2
+#define KERNEL_TYPE_NETBSD	3
+
+#define GRUB_BSD_TEMP_BUFFER	0x68000
+
+#define FREEBSD_RB_ASKNAME	(1 << 0)  /* ask for file name to reboot from */
+#define FREEBSD_RB_SINGLE       (1 << 1)  /* reboot to single user only */
+#define FREEBSD_RB_NOSYNC       (1 << 2)  /* dont sync before reboot */
+#define FREEBSD_RB_HALT         (1 << 3)  /* don't reboot, just halt */
+#define FREEBSD_RB_INITNAME     (1 << 4)  /* name given for /etc/init (unused) */
+#define FREEBSD_RB_DFLTROOT     (1 << 5)  /* use compiled-in rootdev */
+#define FREEBSD_RB_KDB          (1 << 6)  /* give control to kernel debugger */
+#define FREEBSD_RB_RDONLY       (1 << 7)  /* mount root fs read-only */
+#define FREEBSD_RB_DUMP         (1 << 8)  /* dump kernel memory before reboot */
+#define FREEBSD_RB_MINIROOT     (1 << 9)  /* mini-root present in memory at boot time */
+#define FREEBSD_RB_CONFIG       (1 << 10) /* invoke user configuration routing */
+#define FREEBSD_RB_VERBOSE      (1 << 11) /* print all potentially useful info */
+#define FREEBSD_RB_SERIAL       (1 << 12) /* user serial port as console */
+#define FREEBSD_RB_CDROM        (1 << 13) /* use cdrom as root */
+#define FREEBSD_RB_GDB		(1 << 15) /* use GDB remote debugger instead of DDB */
+#define FREEBSD_RB_MUTE		(1 << 16) /* Come up with the console muted */
+#define FREEBSD_RB_PAUSE	(1 << 20)
+#define FREEBSD_RB_QUIET	(1 << 21)
+#define FREEBSD_RB_NOINTR	(1 << 28)
+#define FREENSD_RB_MULTIPLE	(1 << 29)  /* Use multiple consoles */
+#define FREEBSD_RB_DUAL		FREENSD_RB_MULTIPLE
+#define FREEBSD_RB_BOOTINFO     (1 << 31) /* have `struct bootinfo *' arg */
+
+#define FREEBSD_B_DEVMAGIC	0xa0000000
+#define FREEBSD_B_SLICESHIFT	20
+#define FREEBSD_B_UNITSHIFT	16
+#define FREEBSD_B_PARTSHIFT	8
+#define FREEBSD_B_TYPESHIFT	0
+
+#define FREEBSD_BOOTINFO_VERSION 1
+#define FREEBSD_N_BIOS_GEOM	8
+
+#define FREEBSD_MODINFO_END		0x0000	/* End of list */
+#define FREEBSD_MODINFO_NAME		0x0001	/* Name of module (string) */
+#define FREEBSD_MODINFO_TYPE		0x0002	/* Type of module (string) */
+#define FREEBSD_MODINFO_ADDR		0x0003	/* Loaded address */
+#define FREEBSD_MODINFO_SIZE		0x0004	/* Size of module */
+#define FREEBSD_MODINFO_EMPTY		0x0005	/* Has been deleted */
+#define FREEBSD_MODINFO_ARGS		0x0006	/* Parameters string */
+#define FREEBSD_MODINFO_METADATA	0x8000	/* Module-specfic */
+
+#define FREEBSD_MODINFOMD_AOUTEXEC	0x0001	/* a.out exec header */
+#define FREEBSD_MODINFOMD_ELFHDR	0x0002	/* ELF header */
+#define FREEBSD_MODINFOMD_SSYM		0x0003	/* start of symbols */
+#define FREEBSD_MODINFOMD_ESYM		0x0004	/* end of symbols */
+#define FREEBSD_MODINFOMD_DYNAMIC	0x0005	/* _DYNAMIC pointer */
+#define FREEBSD_MODINFOMD_ENVP		0x0006	/* envp[] */
+#define FREEBSD_MODINFOMD_HOWTO		0x0007	/* boothowto */
+#define FREEBSD_MODINFOMD_KERNEND	0x0008	/* kernend */
+#define FREEBSD_MODINFOMD_SHDR		0x0009	/* section header table */
+#define FREEBSD_MODINFOMD_NOCOPY	0x8000	/* don't copy this metadata to the kernel */
+
+#define FREEBSD_MODINFOMD_DEPLIST	(0x4001 | FREEBSD_MODINFOMD_NOCOPY)  /* depends on */
+
+#define FREEBSD_MODTYPE_KERNEL		"elf kernel"
+#define FREEBSD_MODTYPE_MODULE		"elf module"
+#define FREEBSD_MODTYPE_RAW		"raw"
+
+struct grub_freebsd_bootinfo
+{
+  grub_uint32_t bi_version;
+  grub_uint8_t *bi_kernelname;
+  struct nfs_diskless *bi_nfs_diskless;
+  grub_uint32_t bi_n_bios_used;
+  grub_uint32_t bi_bios_geom[FREEBSD_N_BIOS_GEOM];
+  grub_uint32_t bi_size;
+  grub_uint8_t bi_memsizes_valid;
+  grub_uint8_t bi_bios_dev;
+  grub_uint8_t bi_pad[2];
+  grub_uint32_t bi_basemem;
+  grub_uint32_t bi_extmem;
+  grub_uint32_t bi_symtab;
+  grub_uint32_t bi_esymtab;
+  grub_uint32_t bi_kernend;
+  grub_uint32_t bi_envp;
+  grub_uint32_t bi_modulep;
+} __attribute__ ((packed));
+
+#define OPENBSD_RB_ASKNAME	(1 << 0)  /* ask for file name to reboot from */
+#define OPENBSD_RB_SINGLE	(1 << 1)  /* reboot to single user only */
+#define OPENBSD_RB_NOSYNC	(1 << 2)  /* dont sync before reboot */
+#define OPENBSD_RB_HALT		(1 << 3)  /* don't reboot, just halt */
+#define OPENBSD_RB_INITNAME	(1 << 4)  /* name given for /etc/init (unused) */
+#define OPENBSD_RB_DFLTROOT	(1 << 5)  /* use compiled-in rootdev */
+#define OPENBSD_RB_KDB		(1 << 6)  /* give control to kernel debugger */
+#define OPENBSD_RB_RDONLY	(1 << 7)  /* mount root fs read-only */
+#define OPENBSD_RB_DUMP		(1 << 8)  /* dump kernel memory before reboot */
+#define OPENBSD_RB_MINIROOT	(1 << 9)  /* mini-root present in memory at boot time */
+#define OPENBSD_RB_CONFIG	(1 << 10) /* change configured devices */
+#define OPENBSD_RB_TIMEBAD	(1 << 11) /* don't call resettodr() in boot() */
+#define OPENBSD_RB_POWERDOWN	(1 << 12) /* attempt to power down machine */
+#define OPENBSD_RB_SERCONS	(1 << 13) /* use serial console if available */
+#define OPENBSD_RB_USERREQ	(1 << 14) /* boot() called at user request (e.g. ddb) */
+
+#define OPENBSD_B_DEVMAGIC	0xa0000000
+#define OPENBSD_B_ADAPTORSHIFT	24
+#define OPENBSD_B_CTRLSHIFT	20
+#define OPENBSD_B_UNITSHIFT	16
+#define OPENBSD_B_PARTSHIFT	8
+#define OPENBSD_B_TYPESHIFT	0
+
+#define OPENBSD_BOOTARG_APIVER	(OPENBSD_BAPIV_VECTOR | \
+                                 OPENBSD_BAPIV_ENV | \
+                                 OPENBSD_BAPIV_BMEMMAP)
+
+#define OPENBSD_BAPIV_ANCIENT	0x0  /* MD old i386 bootblocks */
+#define OPENBSD_BAPIV_VARS	0x1  /* MD structure w/ add info passed */
+#define OPENBSD_BAPIV_VECTOR	0x2  /* MI vector of MD structures passed */
+#define OPENBSD_BAPIV_ENV	0x4  /* MI environment vars vector */
+#define OPENBSD_BAPIV_BMEMMAP	0x8  /* MI memory map passed is in bytes */
+
+#define OPENBSD_BOOTARG_ENV	0x1000
+#define OPENBSD_BOOTARG_END	-1
+
+#define	OPENBSD_BOOTARG_MMAP	0
+
+struct grub_openbsd_bios_mmap
+{
+  grub_uint64_t addr;
+  grub_uint64_t len;
+  grub_uint32_t type;
+} bios_memmap_t;
+
+struct grub_openbsd_bootargs
+{
+  int ba_type;
+  int ba_size;
+  struct grub_openbsd_bootargs *ba_next;
+} __attribute__ ((packed));
+
+#define NETBSD_RB_AUTOBOOT	0  /* flags for system auto-booting itself */
+
+#define NETBSD_RB_ASKNAME	(1 << 0)  /* ask for file name to reboot from */
+#define NETBSD_RB_SINGLE	(1 << 1)  /* reboot to single user only */
+#define NETBSD_RB_NOSYNC	(1 << 2)  /* dont sync before reboot */
+#define NETBSD_RB_HALT		(1 << 3)  /* don't reboot, just halt */
+#define NETBSD_RB_INITNAME	(1 << 4)  /* name given for /etc/init (unused) */
+#define NETBSD_RB_UNUSED1	(1 << 5)  /* was RB_DFLTROOT, obsolete */
+#define NETBSD_RB_KDB		(1 << 6)  /* give control to kernel debugger */
+#define NETBSD_RB_RDONLY	(1 << 7)  /* mount root fs read-only */
+#define NETBSD_RB_DUMP		(1 << 8)  /* dump kernel memory before reboot */
+#define NETBSD_RB_MINIROOT	(1 << 9)  /* mini-root present in memory at boot time */
+#define NETBSD_RB_STRING	(1 << 10) /* use provided bootstr */
+#define NETBSD_RB_POWERDOWN     ((1 << 11) | RB_HALT) /* turn power off (or at least halt) */
+#define NETBSD_RB_USERCONFIG	(1 << 12) /* change configured devices */
+
+#define NETBSD_AB_NORMAL	0  /* boot normally (default) */
+
+#define NETBSD_AB_QUIET		(1 << 16) /* boot quietly */
+#define NETBSD_AB_VERBOSE	(1 << 17) /* boot verbosely */
+#define NETBSD_AB_SILENT	(1 << 18) /* boot silently */
+#define NETBSD_AB_DEBUG		(1 << 19) /* boot with debug messages */
+
+struct grub_netbsd_bootinfo
+{
+  grub_uint32_t bi_count;
+  void *bi_data[1];
+};
+
+#define NETBSD_BTINFO_BOOTPATH		0
+#define NETBSD_BTINFO_ROOTDEVICE	1
+#define NETBSD_BTINFO_BOOTDISK		3
+
+struct grub_netbsd_btinfo_common
+{
+  int len;
+  int type;
+};
+
+struct grub_netbsd_btinfo_bootpath
+{
+  struct grub_netbsd_btinfo_common common;
+  char bootpath[80];
+};
+
+struct grub_netbsd_btinfo_rootdevice
+{
+  struct grub_netbsd_btinfo_common common;
+  char devname[16];
+};
+
+struct grub_netbsd_btinfo_bootdisk
+{
+  struct grub_netbsd_btinfo_common common;
+  int labelsector;  /* label valid if != -1 */
+  struct
+    {
+      grub_uint16_t type, checksum;
+      char packname[16];
+    } label;
+  int biosdev;
+  int partition;
+};
+
+void grub_rescue_cmd_freebsd (int argc, char *argv[]);
+void grub_rescue_cmd_openbsd (int argc, char *argv[]);
+void grub_rescue_cmd_netbsd (int argc, char *argv[]);
+
+void grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[]);
+void grub_rescue_cmd_freebsd_module (int argc, char *argv[]);
+
+#endif /* ! GRUB_BSD_CPU_HEADER */
diff --git a/include/grub/i386/loader.h b/include/grub/i386/loader.h
index 45a1652..5f912cd 100644
--- a/include/grub/i386/loader.h
+++ b/include/grub/i386/loader.h
@@ -39,6 +39,9 @@ void EXPORT_FUNC(grub_multiboot_real_boot) (grub_addr_t entry,
 void EXPORT_FUNC(grub_multiboot2_real_boot) (grub_addr_t entry,
                                              struct grub_multiboot_info *mbi)
      __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_unix_real_boot) (grub_addr_t entry, ...)
+     __attribute__ ((cdecl,noreturn));
+
 
 /* It is necessary to export these functions, because normal mode commands
    reuse rescue mode commands.  */
diff --git a/include/grub/i386/pc/init.h b/include/grub/i386/pc/init.h
index 115deb4..0c6a129 100644
--- a/include/grub/i386/pc/init.h
+++ b/include/grub/i386/pc/init.h
@@ -40,7 +40,7 @@ struct grub_machine_mmap_entry
 
 /* Get a memory map entry. Return next continuation value. Zero means
    the end.  */
-grub_uint32_t grub_get_mmap_entry (struct grub_machine_mmap_entry *entry,
+grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
 				   grub_uint32_t cont);
 
 /* Turn on/off Gate A20.  */
diff --git a/kern/elf.c b/kern/elf.c
index ca10b5b..cb8a722 100644
--- a/kern/elf.c
+++ b/kern/elf.c
@@ -85,9 +85,8 @@ grub_elf_file (grub_file_t file)
   return elf;
 
 fail:
-  grub_error_push ();
-  grub_elf_close (elf);
-  grub_error_pop ();
+  grub_free (elf->phdrs);
+  grub_free (elf);
   return 0;
 }
 
@@ -95,12 +94,17 @@ grub_elf_t
 grub_elf_open (const char *name)
 {
   grub_file_t file;
+  grub_elf_t elf;
 
   file = grub_gzfile_open (name, 1);
   if (! file)
     return 0;
 
-  return grub_elf_file (file);
+  elf = grub_elf_file (file);
+  if (! elf)
+    grub_file_close (file);
+
+  return elf;
 }
 
 \f
@@ -177,8 +181,8 @@ grub_elf32_size (grub_elf_t elf)
 
   /* Run through the program headers to calculate the total memory size we
    * should claim.  */
-  auto int calcsize (grub_elf_t _elf, Elf32_Phdr *phdr, void *_arg);
-  int calcsize (grub_elf_t UNUSED _elf, Elf32_Phdr *phdr, void UNUSED *_arg)
+  auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf32_Phdr *phdr, void *_arg);
+  int NESTED_FUNC_ATTR calcsize (grub_elf_t UNUSED _elf, Elf32_Phdr *phdr, void UNUSED *_arg)
     {
       /* Only consider loadable segments.  */
       if (phdr->p_type != PT_LOAD)
@@ -228,9 +232,9 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
     if (phdr->p_type != PT_LOAD)
       return 0;
 
-    load_addr = phdr->p_paddr;
     if (load_hook && load_hook (phdr, &load_addr))
       return 1;
+    load_addr = phdr->p_paddr;
 
     if (load_addr < load_base)
       load_base = load_addr;
@@ -355,8 +359,8 @@ grub_elf64_size (grub_elf_t elf)
 
   /* Run through the program headers to calculate the total memory size we
    * should claim.  */
-  auto int calcsize (grub_elf_t _elf, Elf64_Phdr *phdr, void *_arg);
-  int calcsize (grub_elf_t UNUSED _elf, Elf64_Phdr *phdr, void UNUSED *_arg)
+  auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf64_Phdr *phdr, void *_arg);
+  int NESTED_FUNC_ATTR calcsize (grub_elf_t UNUSED _elf, Elf64_Phdr *phdr, void UNUSED *_arg)
     {
       /* Only consider loadable segments.  */
       if (phdr->p_type != PT_LOAD)
@@ -407,9 +411,9 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
     if (phdr->p_type != PT_LOAD)
       return 0;
 
-    load_addr = phdr->p_paddr;
     if (load_hook && load_hook (phdr, &load_addr))
       return 1;
+    load_addr = phdr->p_paddr;
 
     if (load_addr < load_base)
       load_base = load_addr;
diff --git a/kern/i386/loader.S b/kern/i386/loader.S
index 266f4ef..39cf6a0 100644
--- a/kern/i386/loader.S
+++ b/kern/i386/loader.S
@@ -162,3 +162,27 @@ FUNCTION(grub_multiboot2_real_boot)
         movl    $MULTIBOOT2_BOOTLOADER_MAGIC,%eax 
         popl    %ecx
         jmp     *%ecx
+
+/*
+ * Use cdecl calling convention for *BSD kernels.
+ */
+
+FUNCTION(grub_unix_real_boot)
+
+        call    EXT_C(grub_dl_unload_all)
+        call    EXT_C(grub_stop_floppy)
+
+	/* Interrupts should be disabled.  */
+        cli
+
+	/* Discard `grub_unix_real_boot' return address.  */
+        popl    %eax
+
+        /* Fetch `entry' address ...  */
+        popl	%eax
+
+        /*
+         * ... and put our return address in its place. The kernel will
+         * ignore it, but it expects %esp to point to it.
+         */
+        call	*%eax
diff --git a/loader/aout.c b/loader/aout.c
new file mode 100755
index 0000000..2c82b60
--- /dev/null
+++ b/loader/aout.c
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ *  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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+int
+grub_aout_get_type (union grub_aout_header *header)
+{
+  int magic;
+
+  magic = AOUT_GETMAGIC (header->aout32);
+  if ((magic == AOUT32_OMAGIC) || (magic == AOUT32_NMAGIC) ||
+      (magic == AOUT32_ZMAGIC) || (magic == AOUT32_QMAGIC))
+    return AOUT_TYPE_AOUT32;
+  else if ((magic == AOUT64_OMAGIC) || (magic == AOUT64_NMAGIC) ||
+	   (magic == AOUT64_ZMAGIC))
+    return AOUT_TYPE_AOUT64;
+  else
+    return AOUT_TYPE_NONE;
+}
+
+grub_err_t
+grub_aout_load (grub_file_t file, int offset,
+                grub_addr_t load_addr,
+		int load_size,
+                grub_addr_t bss_end_addr)
+{
+  if ((grub_file_seek (file, offset)) == (grub_off_t) - 1)
+    return grub_errno;
+
+  if (!load_size)
+    load_size = file->size - offset;
+
+  grub_file_read (file, (char *) load_addr, load_size);
+
+  if (grub_errno)
+    return grub_errno;
+
+  if (bss_end_addr)
+    grub_memset (load_addr + load_size, 0,
+                 bss_end_addr - load_addr - load_size);
+
+  return GRUB_ERR_NONE;
+}
diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c
new file mode 100644
index 0000000..4966afa
--- /dev/null
+++ b/loader/i386/bsd.c
@@ -0,0 +1,771 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/cpu/loader.h>
+#include <grub/cpu/bsd.h>
+#include <grub/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/elfload.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+#include <grub/aout.h>
+
+#define ALIGN_DWORD(a)	ALIGN_UP (a, 4)
+#define ALIGN_PAGE(a)	ALIGN_UP (a, 4096)
+
+#define MOD_BUF_ALLOC_UNIT	4096
+
+static int kernel_type;
+static grub_dl_t my_mod;
+static grub_addr_t entry, kern_start, kern_end;
+static grub_uint32_t bootflags;
+static char *mod_buf;
+static grub_uint32_t mod_buf_len, mod_buf_max;
+static int is_elf_kernel;
+
+static const char freebsd_opts[] = "DhaCcdgmnpqrsv";
+static const grub_uint32_t freebsd_flags[] =
+{
+  FREEBSD_RB_DUAL, FREEBSD_RB_SERIAL, FREEBSD_RB_ASKNAME,
+  FREEBSD_RB_CDROM, FREEBSD_RB_CONFIG, FREEBSD_RB_KDB,
+  FREEBSD_RB_GDB, FREEBSD_RB_MUTE, FREEBSD_RB_NOINTR,
+  FREEBSD_RB_PAUSE, FREEBSD_RB_QUIET, FREEBSD_RB_DFLTROOT,
+  FREEBSD_RB_SINGLE, FREEBSD_RB_VERBOSE
+};
+
+static const char openbsd_opts[] = "abcsd";
+static const grub_uint32_t openbsd_flags[] =
+{
+  OPENBSD_RB_ASKNAME, OPENBSD_RB_HALT, OPENBSD_RB_CONFIG,
+  OPENBSD_RB_SINGLE, OPENBSD_RB_KDB
+};
+
+static const char netbsd_opts[] = "abcdmqsvxz";
+static const grub_uint32_t netbsd_flags[] =
+{
+  NETBSD_RB_ASKNAME, NETBSD_RB_HALT, NETBSD_RB_USERCONFIG,
+  NETBSD_RB_KDB, NETBSD_RB_MINIROOT, NETBSD_AB_QUIET,
+  NETBSD_RB_SINGLE, NETBSD_AB_VERBOSE, NETBSD_AB_DEBUG,
+  NETBSD_AB_SILENT
+};
+
+static void
+grub_bsd_get_device (grub_uint32_t * biosdev,
+		     grub_uint32_t * unit,
+		     grub_uint32_t * slice, grub_uint32_t * part)
+{
+  char *p;
+
+  *biosdev = *unit = *slice = *part = 0;
+  p = grub_env_get ("root");
+  if ((p) && ((p[0] == 'h') || (p[0] == 'f')) && (p[1] == 'd') &&
+      (p[2] >= '0') && (p[2] <= '9'))
+    {
+      if (p[0] == 'h')
+	*biosdev = 0x80;
+
+      *unit = grub_strtoul (p + 2, &p, 0);
+      *biosdev += *unit;
+
+      if ((p) && (p[0] == ','))
+	{
+	  if ((p[1] >= '0') && (p[1] <= '9'))
+	    {
+	      *slice = grub_strtoul (p + 1, &p, 0);
+
+	      if ((p) && (p[0] == ','))
+		p++;
+	    }
+
+	  if ((p[0] >= 'a') && (p[0] <= 'z'))
+	    *part = p[0] - 'a';
+	}
+    }
+}
+
+static grub_err_t
+grub_freebsd_add_meta (grub_uint32_t type, void *data, grub_uint32_t len)
+{
+  if (mod_buf_max < mod_buf_len + len + 8)
+    {
+      char *new_buf;
+
+      do
+	{
+	  mod_buf_max += MOD_BUF_ALLOC_UNIT;
+	}
+      while (mod_buf_max < mod_buf_len + len + 8);
+
+      new_buf = grub_malloc (mod_buf_max);
+      if (!new_buf)
+	return grub_errno;
+
+      grub_memcpy (new_buf, mod_buf, mod_buf_len);
+      grub_free (mod_buf);
+
+      mod_buf = new_buf;
+    }
+
+  *((grub_uint32_t *) (mod_buf + mod_buf_len)) = type;
+  *((grub_uint32_t *) (mod_buf + mod_buf_len + 4)) = len;
+  mod_buf_len += 8;
+
+  if (len)
+    grub_memcpy (mod_buf + mod_buf_len, data, len);
+
+  mod_buf_len = ALIGN_DWORD (mod_buf_len + len);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_freebsd_add_meta_module (int is_kern, int argc, char **argv,
+			      grub_addr_t addr, grub_uint32_t size)
+{
+  char *name, *type;
+
+  name = grub_strrchr (argv[0], '/');
+  if (name)
+    name++;
+  else
+    name = argv[0];
+
+  if (grub_freebsd_add_meta (FREEBSD_MODINFO_NAME, name,
+			     grub_strlen (name) + 1))
+    return grub_errno;
+
+  argc--;
+  argv++;
+
+  if ((argc) && (!grub_memcmp (argv[0], "type=", 5)))
+    {
+      type = &argv[0][5];
+      argc--;
+      argv++;
+    }
+  else
+    type = (is_kern) ? FREEBSD_MODTYPE_KERNEL : FREEBSD_MODTYPE_RAW;
+
+  if ((grub_freebsd_add_meta (FREEBSD_MODINFO_TYPE, type,
+			      grub_strlen (type) + 1)) ||
+      (grub_freebsd_add_meta (FREEBSD_MODINFO_ADDR, &addr, sizeof (addr))) ||
+      (grub_freebsd_add_meta (FREEBSD_MODINFO_SIZE, &size, sizeof (size))))
+    return grub_errno;
+
+  if (argc)
+    {
+      int i, n;
+
+      n = 0;
+      for (i = 0; i < argc; i++)
+	{
+	  n += grub_strlen (argv[i]) + 1;
+	}
+
+      if (n)
+	{
+	  char cmdline[n], *p;
+
+	  p = cmdline;
+	  for (i = 0; i < argc; i++)
+	    {
+	      grub_strcpy (p, argv[i]);
+	      p += grub_strlen (argv[i]);
+	      *(p++) = ' ';
+	    }
+	  *p = 0;
+
+	  if (grub_freebsd_add_meta (FREEBSD_MODINFO_ARGS, cmdline, n))
+	    return grub_errno;
+	}
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_freebsd_list_modules (void)
+{
+  grub_uint32_t pos = 0;
+
+  grub_printf ("  %-18s  %-18s%14s%14s\n", "name", "type", "addr", "size");
+  while (pos < mod_buf_len)
+    {
+      grub_uint32_t type, size;
+
+      type = *((grub_uint32_t *) (mod_buf + pos));
+      size = *((grub_uint32_t *) (mod_buf + pos + 4));
+      pos += 8;
+      switch (type)
+	{
+	case FREEBSD_MODINFO_NAME:
+	case FREEBSD_MODINFO_TYPE:
+	  grub_printf ("  %-18s", mod_buf + pos);
+	  break;
+	case FREEBSD_MODINFO_ADDR:
+	  {
+	    grub_addr_t addr;
+
+	    addr = *((grub_addr_t *) (mod_buf + pos));
+	    grub_printf ("    0x%08x", addr);
+	    break;
+	  }
+	case FREEBSD_MODINFO_SIZE:
+	  {
+	    grub_uint32_t len;
+
+	    len = *((grub_uint32_t *) (mod_buf + pos));
+	    grub_printf ("    0x%08x\n", len);
+	  }
+	}
+
+      pos = ALIGN_DWORD (pos + size);
+    }
+}
+
+static grub_err_t
+grub_freebsd_boot (void)
+{
+  struct grub_freebsd_bootinfo bi;
+  char *p;
+  grub_uint32_t bootdev, biosdev, unit, slice, part;
+
+  auto int iterate_env (struct grub_env_var *var);
+  int iterate_env (struct grub_env_var *var)
+  {
+    if ((!grub_memcmp (var->name, "FreeBSD.", 8)) && (var->name[8]))
+      {
+	grub_strcpy (p, &var->name[8]);
+	p += grub_strlen (p);
+	*(p++) = '=';
+	grub_strcpy (p, var->value);
+	p += grub_strlen (p) + 1;
+      }
+
+    return 0;
+  }
+
+  grub_memset (&bi, 0, sizeof (bi));
+  bi.bi_version = FREEBSD_BOOTINFO_VERSION;
+  bi.bi_size = sizeof (bi);
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+  bootdev = (FREEBSD_B_DEVMAGIC + ((slice + 1) << FREEBSD_B_SLICESHIFT) +
+	     (unit << FREEBSD_B_UNITSHIFT) + (part << FREEBSD_B_PARTSHIFT));
+
+  bi.bi_bios_dev = biosdev;
+
+  p = (char *) kern_end;
+
+  grub_env_iterate (iterate_env);
+
+  if (p != (char *) kern_end)
+    {
+      *(p++) = 0;
+
+      bi.bi_envp = kern_end;
+      kern_end = ALIGN_PAGE ((grub_uint32_t) p);
+    }
+
+  if (is_elf_kernel)
+    {
+      if (grub_freebsd_add_meta (FREEBSD_MODINFO_END, 0, 0))
+	return grub_errno;
+
+      grub_memcpy ((char *) kern_end, mod_buf, mod_buf_len);
+      bi.bi_modulep = kern_end;
+
+      kern_end = ALIGN_PAGE (kern_end + mod_buf_len);
+    }
+
+  bi.bi_kernend = kern_end;
+
+  grub_unix_real_boot (entry, bootflags | FREEBSD_RB_BOOTINFO, bootdev,
+		       0, 0, 0, &bi, bi.bi_modulep, kern_end);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_openbsd_boot (void)
+{
+  char *buf = (char *) GRUB_BSD_TEMP_BUFFER;
+  struct grub_machine_mmap_entry mmap;
+  struct grub_openbsd_bios_mmap *pm;
+  struct grub_openbsd_bootargs *pa;
+  grub_uint32_t bootdev, biosdev, unit, slice, part, cont;
+
+  pa = (struct grub_openbsd_bootargs *) buf;
+
+  pa->ba_type = OPENBSD_BOOTARG_MMAP;
+  pm = (struct grub_openbsd_bios_mmap *) (pa + 1);
+  cont = grub_get_mmap_entry (&mmap, 0);
+  if (mmap.size)
+    do
+      {
+	pm->addr = mmap.addr;
+	pm->len = mmap.len;
+	pm->type = mmap.type;
+	pm++;
+
+	if (!cont)
+	  break;
+
+	cont = grub_get_mmap_entry (&mmap, cont);
+      }
+    while (mmap.size);
+
+  pa->ba_size = (char *) pm - (char *) pa;
+  pa->ba_next = (struct grub_openbsd_bootargs *) pm;
+  pa = pa->ba_next;
+  pa->ba_type = OPENBSD_BOOTARG_END;
+  pa++;
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+  bootdev = (OPENBSD_B_DEVMAGIC + (unit << OPENBSD_B_UNITSHIFT) +
+	     (part << OPENBSD_B_PARTSHIFT));
+
+  grub_unix_real_boot (entry, bootflags, bootdev, OPENBSD_BOOTARG_APIVER,
+		       0, grub_upper_mem >> 10, grub_lower_mem >> 10,
+		       (char *) pa - buf, buf);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_netbsd_boot (void)
+{
+  struct grub_netbsd_btinfo_rootdevice *rootdev;
+  struct grub_netbsd_bootinfo *bootinfo;
+  grub_uint32_t biosdev, unit, slice, part;
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+
+  rootdev = (struct grub_netbsd_btinfo_rootdevice *) GRUB_BSD_TEMP_BUFFER;
+
+  rootdev->common.len = sizeof (struct grub_netbsd_btinfo_rootdevice);
+  rootdev->common.type = NETBSD_BTINFO_ROOTDEVICE;
+  grub_sprintf (rootdev->devname, "%cd%d%c", (biosdev & 0x80) ? 'w' : 'f',
+		unit, 'a' + part);
+
+  bootinfo = (struct grub_netbsd_bootinfo *) (rootdev + 1);
+  bootinfo->bi_count = 1;
+  bootinfo->bi_data[0] = rootdev;
+
+  grub_unix_real_boot (entry, bootflags, 0, bootinfo,
+		       0, grub_upper_mem >> 10, grub_lower_mem >> 10);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_unload (void)
+{
+  if (mod_buf)
+    {
+      grub_free (mod_buf);
+      mod_buf = 0;
+      mod_buf_max = 0;
+    }
+
+  kernel_type = KERNEL_TYPE_NONE;
+  grub_dl_unref (my_mod);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_load_aout (grub_file_t file)
+{
+  grub_addr_t load_addr, bss_end_addr;
+  int ofs, align_page;
+  union grub_aout_header ah;
+
+  if ((grub_file_seek (file, 0)) == (grub_off_t) - 1)
+    return grub_errno;
+
+  if (grub_file_read (file, (char *) &ah, sizeof (ah)) != sizeof (ah))
+    return grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header");
+
+  if (grub_aout_get_type (&ah) != AOUT_TYPE_AOUT32)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid a.out header");
+
+  entry = ah.aout32.a_entry & 0xFFFFFF;
+
+  if (AOUT_GETMAGIC (ah.aout32) == AOUT32_ZMAGIC)
+    {
+      load_addr = entry;
+      ofs = 0x1000;
+      align_page = 0;
+    }
+  else
+    {
+      load_addr = entry & 0xF00000;
+      ofs = sizeof (struct grub_aout32_header);
+      align_page = 1;
+    }
+
+  if (load_addr < 0x100000)
+    return grub_error (GRUB_ERR_BAD_OS, "load address below 1M");
+
+  kern_start = load_addr;
+  kern_end = load_addr + ah.aout32.a_text + ah.aout32.a_data;
+  if (align_page)
+    kern_end = ALIGN_PAGE (kern_end);
+
+  if (ah.aout32.a_bss)
+    {
+      kern_end += ah.aout32.a_bss;
+      if (align_page)
+	kern_end = ALIGN_PAGE (kern_end);
+
+      bss_end_addr = kern_end;
+    }
+  else
+    bss_end_addr = 0;
+
+  return grub_aout_load (file, ofs, load_addr,
+			 ah.aout32.a_text + ah.aout32.a_data, bss_end_addr);
+}
+
+static grub_err_t
+grub_bsd_elf32_hook (Elf32_Phdr * phdr, UNUSED grub_addr_t * addr)
+{
+  Elf32_Addr paddr;
+
+  phdr->p_paddr &= 0xFFFFFF;
+  paddr = phdr->p_paddr;
+
+  if ((paddr < grub_os_area_addr)
+      || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Address 0x%x is out of range",
+		       paddr);
+
+  if ((!kern_start) || (paddr < kern_start))
+    kern_start = paddr;
+
+  if (paddr + phdr->p_memsz > kern_end)
+    kern_end = paddr + phdr->p_memsz;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_load_elf (grub_elf_t elf)
+{
+  kern_start = kern_end = 0;
+
+  if (grub_elf_is_elf32 (elf))
+    {
+      entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF;
+      return grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0);
+    }
+  else
+    return grub_error (GRUB_ERR_BAD_OS, "invalid elf");
+}
+
+static grub_err_t
+grub_bsd_load (int argc, char *argv[])
+{
+  grub_file_t file;
+  grub_elf_t elf;
+
+  grub_dl_ref (my_mod);
+
+  grub_loader_unset ();
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (!file)
+    goto fail;
+
+  elf = grub_elf_file (file);
+  if (elf)
+    {
+      is_elf_kernel = 1;
+      grub_bsd_load_elf (elf);
+      grub_elf_close (elf);
+    }
+  else
+    {
+      is_elf_kernel = 0;
+      grub_errno = 0;
+      grub_bsd_load_aout (file);
+      grub_file_close (file);
+    }
+
+fail:
+
+  if (grub_errno != GRUB_ERR_NONE)
+    grub_dl_unref (my_mod);
+
+  return grub_errno;
+}
+
+static grub_uint32_t
+grub_bsd_parse_flags (char *str, const char *opts,
+		      const grub_uint32_t * flags)
+{
+  grub_uint32_t result = 0;
+
+  while (*str)
+    {
+      const char *po;
+      const grub_uint32_t *pf;
+
+      po = opts;
+      pf = flags;
+      while (*po)
+	{
+	  if (*str == *po)
+	    {
+	      result |= *pf;
+	      break;
+	    }
+	  po++;
+	  pf++;
+	}
+      str++;
+    }
+
+  return result;
+}
+
+void
+grub_rescue_cmd_freebsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_FREEBSD;
+  bootflags = ((argc <= 1) ? 0 :
+	       grub_bsd_parse_flags (argv[1], freebsd_opts, freebsd_flags));
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    {
+      kern_end = ALIGN_PAGE (kern_end);
+      if ((is_elf_kernel) &&
+	  (grub_freebsd_add_meta_module (1, argc, argv, kern_start,
+					 kern_end - kern_start)))
+	return;
+      grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 1);
+    }
+}
+
+void
+grub_rescue_cmd_openbsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_OPENBSD;
+  bootflags = ((argc <= 1) ? 0 :
+	       grub_bsd_parse_flags (argv[1], openbsd_opts, openbsd_flags));
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 1);
+}
+
+void
+grub_rescue_cmd_netbsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_NETBSD;
+  bootflags = ((argc <= 1) ? 0 :
+	       grub_bsd_parse_flags (argv[1], netbsd_opts, netbsd_flags));
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 1);
+}
+
+void
+grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  char *buf = 0, *curr, *next;
+  int len;
+
+  if (kernel_type != KERNEL_TYPE_FREEBSD)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "only freebsd support environment");
+      return;
+    }
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no filename");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if ((!file) || (!file->size))
+    goto fail;
+
+  len = file->size;
+  buf = grub_malloc (len + 1);
+  if (!buf)
+    goto fail;
+
+  if (grub_file_read (file, buf, len) != len)
+    goto fail;
+
+  buf[len] = 0;
+
+  next = buf;
+  while (next)
+    {
+      char *p;
+
+      curr = next;
+      next = grub_strchr (curr, '\n');
+      if (next)
+	{
+
+	  p = next - 1;
+	  while (p > curr)
+	    {
+	      if ((*p != '\r') && (*p != ' ') && (*p != '\t'))
+		break;
+	      p--;
+	    }
+
+	  if ((p > curr) && (*p == '"'))
+	    p--;
+
+	  *(p + 1) = 0;
+	  next++;
+	}
+
+      if (*curr == '#')
+	continue;
+
+      p = grub_strchr (curr, '=');
+      if (!p)
+	continue;
+
+      *(p++) = 0;
+
+      if (*curr)
+	{
+	  char name[grub_strlen (curr) + 8 + 1];
+
+	  if (*p == '"')
+	    p++;
+
+	  grub_sprintf (name, "FreeBSD.%s", curr);
+	  if (grub_env_set (name, p))
+	    goto fail;
+	}
+    }
+
+fail:
+  grub_free (buf);
+
+  if (file)
+    grub_file_close (file);
+}
+
+void
+grub_rescue_cmd_freebsd_module (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+
+  if (kernel_type != KERNEL_TYPE_FREEBSD)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "only freebsd support module");
+      return;
+    }
+
+  if (!is_elf_kernel)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "only elf kernel support module");
+      return;
+    }
+
+  /* List the current modules if no parameter.  */
+  if (!argc)
+    {
+      grub_freebsd_list_modules ();
+      return;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if ((!file) || (!file->size))
+    goto fail;
+
+  if (kern_end + file->size > grub_os_area_addr + grub_os_area_size)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "Not enough memory for the module");
+      goto fail;
+    }
+
+  grub_file_read (file, (char *) kern_end, file->size);
+  if ((!grub_errno) &&
+      (!grub_freebsd_add_meta_module (0, argc, argv, kern_end, file->size)))
+    kern_end = ALIGN_PAGE (kern_end + file->size);
+
+fail:
+  if (file)
+    grub_file_close (file);
+}
+
+GRUB_MOD_INIT (bsd)
+{
+  grub_rescue_register_command ("freebsd",
+				grub_rescue_cmd_freebsd,
+				"load freebsd kernel");
+  grub_rescue_register_command ("openbsd",
+				grub_rescue_cmd_openbsd,
+				"load openbsd kernel");
+  grub_rescue_register_command ("netbsd",
+				grub_rescue_cmd_netbsd, "load netbsd kernel");
+
+  grub_rescue_register_command ("freebsd_loadenv",
+				grub_rescue_cmd_freebsd_loadenv,
+				"load freebsd env");
+  grub_rescue_register_command ("freebsd_module",
+				grub_rescue_cmd_freebsd_module,
+				"load freebsd module");
+
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI (bsd)
+{
+  grub_rescue_unregister_command ("freebsd");
+  grub_rescue_unregister_command ("openbsd");
+  grub_rescue_unregister_command ("netbsd");
+
+  grub_rescue_unregister_command ("freebsd_loadenv");
+  grub_rescue_unregister_command ("freebsd_module");
+
+  if (mod_buf)
+    {
+      grub_free (mod_buf);
+      mod_buf = 0;
+      mod_buf_max = 0;
+    }
+}
diff --git a/loader/i386/bsd_normal.c b/loader/i386/bsd_normal.c
new file mode 100644
index 0000000..f09cd57
--- /dev/null
+++ b/loader/i386/bsd_normal.c
@@ -0,0 +1,101 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+
+static grub_err_t
+grub_normal_freebsd_command (struct grub_arg_list *state
+			     __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_freebsd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_openbsd_command (struct grub_arg_list *state
+			     __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_openbsd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_netbsd_command (struct grub_arg_list *state
+			    __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_netbsd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_freebsd_loadenv_command (struct grub_arg_list *state
+				     __attribute__ ((unused)), int argc,
+				     char **args)
+{
+  grub_rescue_cmd_freebsd_loadenv (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_freebsd_module_command (struct grub_arg_list *state
+				    __attribute__ ((unused)), int argc,
+				    char **args)
+{
+  grub_rescue_cmd_freebsd_module (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT (bsd_normal)
+{
+  (void) mod;			/* To stop warning.  */
+  grub_register_command ("freebsd", grub_normal_freebsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "freebsd FILE [OPTS] [ARGS...]",
+			 "Load freebsd kernel.", 0);
+  grub_register_command ("openbsd", grub_normal_openbsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "openbsd FILE [OPTS]", "Load openbsd kernel.", 0);
+  grub_register_command ("netbsd", grub_normal_netbsd_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "netbsd FILE [OPTS]", "Load netbsd kernel.", 0);
+
+  grub_register_command ("freebsd_loadenv",
+			 grub_normal_freebsd_loadenv_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "freebsd_loadenv FILE", "Load freebsd env.", 0);
+  grub_register_command ("freebsd_module",
+			 grub_normal_freebsd_module_command,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "freebsd_module [FILE [type=module_type] [ARGS...]]",
+			 "Load freebsd module.", 0);
+}
+
+GRUB_MOD_FINI (bsd_normal)
+{
+  grub_unregister_command ("freebsd");
+  grub_unregister_command ("openbsd");
+  grub_unregister_command ("netbsd");
+
+  grub_unregister_command ("freebsd_loadenv");
+  grub_unregister_command ("freebsd_module");
+}
diff --git a/loader/i386/pc/multiboot.c b/loader/i386/pc/multiboot.c
index 893f11b..67959cf 100644
--- a/loader/i386/pc/multiboot.c
+++ b/loader/i386/pc/multiboot.c
@@ -36,6 +36,7 @@
 #include <grub/machine/init.h>
 #include <grub/machine/memory.h>
 #include <grub/elf.h>
+#include <grub/aout.h>
 #include <grub/file.h>
 #include <grub/err.h>
 #include <grub/rescue.h>
@@ -315,7 +316,22 @@ grub_multiboot (int argc, char *argv[])
       goto fail;
     }
 
-  if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
+  if (header->flags & MULTIBOOT_AOUT_KLUDGE)
+    {
+      int ofs;
+
+      ofs = (char *) header - buffer -
+            (header->header_addr - header->load_addr);
+      if ((grub_aout_load (file, ofs, header->load_addr,
+                           ((header->load_end_addr == 0) ? 0 :
+                            header->load_end_addr - header->load_addr),
+                           header->bss_end_addr))
+          !=GRUB_ERR_NONE)
+        goto fail;
+
+      entry = header->entry_addr;
+    }
+  else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
     goto fail;
   
   mbi = grub_malloc (sizeof (struct grub_multiboot_info));
diff --git a/loader/multiboot2.c b/loader/multiboot2.c
index 65fdea1..42c6fad 100644
--- a/loader/multiboot2.c
+++ b/loader/multiboot2.c
@@ -371,6 +371,7 @@ grub_multiboot2 (int argc, char *argv[])
     }
   else
     {
+      grub_errno = 0;
       grub_dprintf ("loader", "Loading non-ELF multiboot 2 file.\n");
 
       if (header)

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-16 16:43                                         ` Bean
@ 2008-02-16 18:12                                           ` walt
  2008-02-16 18:29                                             ` Bean
  0 siblings, 1 reply; 37+ messages in thread
From: walt @ 2008-02-16 18:12 UTC (permalink / raw)
  To: grub-devel


On Sun, 2008-02-17 at 00:43 +0800, Bean wrote:
> ...
> Anyway, i think the bsd module should be fine, here is the whole
> patch, if nobody objects, i would like to commit it soon...

I vote yes, thanks.  I can boot freebsd directly, openbsd directly,
netbsd directly or using multiboot.  The only problem is that 'aout'
doesn't appear as one of the commands I can choose, so I couldn't
try it.  When I used grub-mkimage I included aout.mod -- should that
be needed in addition to bsd.mod?

Great work, Bean, thanks.






^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-16 18:12                                           ` walt
@ 2008-02-16 18:29                                             ` Bean
  2008-02-19 16:41                                               ` Bean
  0 siblings, 1 reply; 37+ messages in thread
From: Bean @ 2008-02-16 18:29 UTC (permalink / raw)
  To: The development of GRUB 2

On Feb 17, 2008 2:12 AM, walt <wa1ter@myrealbox.com> wrote:
>
> On Sun, 2008-02-17 at 00:43 +0800, Bean wrote:
> > ...
> > Anyway, i think the bsd module should be fine, here is the whole
> > patch, if nobody objects, i would like to commit it soon...
>
> I vote yes, thanks.  I can boot freebsd directly, openbsd directly,
> netbsd directly or using multiboot.  The only problem is that 'aout'
> doesn't appear as one of the commands I can choose, so I couldn't
> try it.  When I used grub-mkimage I included aout.mod -- should that
> be needed in addition to bsd.mod?
>
> Great work, Bean, thanks.

aout is shared code for a.out support, bsd module use it to load the
a.out format kernel (/boot/loader in freebsd). you don't need to
specify it directly, grub-mkimage can figure out bsd depend on aout
and load it automatically.

-- 
Bean



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] a.out support for multiboot and freebsd
  2008-02-16 18:29                                             ` Bean
@ 2008-02-19 16:41                                               ` Bean
  0 siblings, 0 replies; 37+ messages in thread
From: Bean @ 2008-02-19 16:41 UTC (permalink / raw)
  To: The development of GRUB 2

On Feb 17, 2008 2:29 AM, Bean <bean123ch@gmail.com> wrote:
> On Feb 17, 2008 2:12 AM, walt <wa1ter@myrealbox.com> wrote:
> >
> > On Sun, 2008-02-17 at 00:43 +0800, Bean wrote:
> > > ...
> > > Anyway, i think the bsd module should be fine, here is the whole
> > > patch, if nobody objects, i would like to commit it soon...
> >
> > I vote yes, thanks.  I can boot freebsd directly, openbsd directly,
> > netbsd directly or using multiboot.  The only problem is that 'aout'
> > doesn't appear as one of the commands I can choose, so I couldn't
> > try it.  When I used grub-mkimage I included aout.mod -- should that
> > be needed in addition to bsd.mod?
> >
> > Great work, Bean, thanks.
>
> aout is shared code for a.out support, bsd module use it to load the
> a.out format kernel (/boot/loader in freebsd). you don't need to
> specify it directly, grub-mkimage can figure out bsd depend on aout
> and load it automatically.

Committed.

-- 
Bean



^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2008-02-19 16:41 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-09 18:41 [PATCH] a.out support for multiboot and freebsd Bean
2008-02-09 21:57 ` walt
2008-02-10  5:33   ` Bean
2008-02-10  9:22     ` Vesa Jääskeläinen
2008-02-10  9:47       ` Bean
2008-02-10 18:27     ` walt
2008-02-10 22:28       ` Bean
2008-02-11 14:11         ` walt
2008-02-11 14:28           ` Bean
2008-02-11 20:45             ` Bean
2008-02-11 20:46               ` Bean
2008-02-11 21:28                 ` Robert Millan
2008-02-11 21:46                   ` Bean
2008-02-12 11:16                     ` Robert Millan
2008-02-11 21:51                 ` walt
2008-02-12  4:03                   ` Bean
2008-02-12 11:19                   ` Robert Millan
2008-02-12 18:47                     ` Bean
2008-02-12 19:36                       ` Robert Millan
2008-02-13 10:40                         ` Bean
2008-02-13 15:40                           ` Robert Millan
2008-02-13 16:51                             ` Bean
2008-02-13 17:25                           ` walt
2008-02-13 17:37                             ` Bean
2008-02-13 20:31                               ` walt
2008-02-14  2:43                                 ` Bean
2008-02-15 13:29                                   ` walt
2008-02-15 14:03                                     ` Bean
2008-02-15 14:14                                     ` Bean
2008-02-15 18:43                                       ` walt
2008-02-15 18:58                                         ` Bean
2008-02-16 16:43                                         ` Bean
2008-02-16 18:12                                           ` walt
2008-02-16 18:29                                             ` Bean
2008-02-19 16:41                                               ` Bean
2008-02-15 22:43                                       ` walt
2008-02-16  1:00                                         ` walt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.