On Feb 11, 2008 10:11 PM, walt <[EMAIL PROTECTED]> 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
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));
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to