On Feb 12, 2008 4:45 AM, Bean <[EMAIL PROTECTED]> 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
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));
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to