grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] a.out support for multiboot and freebsd


From: Bean
Subject: [PATCH] a.out support for multiboot and freebsd
Date: Sun, 10 Feb 2008 02:41:50 +0800

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  <address@hidden>

        * 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]