All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Miller <davem@davemloft.net>
To: grub-devel@gnu.org
Subject: [PATCH 5/7]: Add sparc64 loader implementation.
Date: Tue, 03 Mar 2009 18:15:27 -0800 (PST)	[thread overview]
Message-ID: <20090303.181527.200306325.davem@davemloft.net> (raw)


2009-03-03  David S. Miller  <davem@davemloft.net>

	* include/grub/sparc64/ieee1275/loader.h: New file.
	* include/grub/sparc64/ieee1275/memory.h: Likewise.
	* include/grub/sparc64/kernel.h: Likewise.
	* loader/sparc64/ieee1275/linux.c: Likewise.
	* loader/sparc64/ieee1275/linux_normal.c: Likewise.
---
 include/grub/sparc64/ieee1275/loader.h |   27 +++
 include/grub/sparc64/ieee1275/memory.h |   24 +++
 include/grub/sparc64/kernel.h          |   28 +++
 loader/sparc64/ieee1275/linux.c        |  318 ++++++++++++++++++++++++++++++++
 loader/sparc64/ieee1275/linux_normal.c |   60 ++++++
 5 files changed, 457 insertions(+), 0 deletions(-)
 create mode 100644 include/grub/sparc64/ieee1275/loader.h
 create mode 100644 include/grub/sparc64/ieee1275/memory.h
 create mode 100644 include/grub/sparc64/kernel.h
 create mode 100644 loader/sparc64/ieee1275/linux.c
 create mode 100644 loader/sparc64/ieee1275/linux_normal.c

diff --git a/include/grub/sparc64/ieee1275/loader.h b/include/grub/sparc64/ieee1275/loader.h
new file mode 100644
index 0000000..12bb2a6
--- /dev/null
+++ b/include/grub/sparc64/ieee1275/loader.h
@@ -0,0 +1,27 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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_LOADER_MACHINE_HEADER
+#define GRUB_LOADER_MACHINE_HEADER	1
+
+/* The symbol shared between the normal mode and rescue mode
+   loader.  */
+void grub_rescue_cmd_linux (int argc, char *argv[]);
+void grub_rescue_cmd_initrd (int argc, char *argv[]);
+
+#endif /* ! GRUB_LOADER_MACHINE_HEADER */
diff --git a/include/grub/sparc64/ieee1275/memory.h b/include/grub/sparc64/ieee1275/memory.h
new file mode 100644
index 0000000..c997f66
--- /dev/null
+++ b/include/grub/sparc64/ieee1275/memory.h
@@ -0,0 +1,24 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009 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_MEMORY_MACHINE_HEADER
+#define GRUB_MEMORY_MACHINE_HEADER	1
+
+#define GRUB_MACHINE_MEMORY_AVAILABLE		1
+
+#endif
diff --git a/include/grub/sparc64/kernel.h b/include/grub/sparc64/kernel.h
new file mode 100644
index 0000000..5c03720
--- /dev/null
+++ b/include/grub/sparc64/kernel.h
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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_KERNEL_CPU_HEADER
+#define GRUB_KERNEL_CPU_HEADER	1
+
+#define GRUB_MOD_ALIGN 0x2000
+#define GRUB_MOD_GAP 0x8000
+
+#define GRUB_KERNEL_CPU_PREFIX		0x8
+#define GRUB_KERNEL_CPU_DATA_END	0x48
+
+#endif
diff --git a/loader/sparc64/ieee1275/linux.c b/loader/sparc64/ieee1275/linux.c
new file mode 100644
index 0000000..4ec1628
--- /dev/null
+++ b/loader/sparc64/ieee1275/linux.c
@@ -0,0 +1,318 @@
+/* linux.c - boot Linux */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003, 2004, 2005, 2007  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/elf.h>
+#include <grub/elfload.h>
+#include <grub/loader.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/rescue.h>
+#include <grub/misc.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/machine/loader.h>
+
+static grub_dl_t my_mod;
+
+static int loaded;
+
+static grub_addr_t initrd_addr;
+static grub_size_t initrd_size;
+
+static grub_addr_t linux_addr;
+static grub_size_t linux_size;
+
+static char *linux_args;
+
+typedef void (*kernel_entry_t) (unsigned long, unsigned long,
+				unsigned long, unsigned long, int (void *));
+
+struct linux_bootstr_info {
+	int len, valid;
+	char buf[];
+};
+
+struct linux_hdrs {
+	/* All HdrS versions support these fields.  */
+	unsigned int start_insns[2];
+	char magic[4]; /* "HdrS" */
+	unsigned int linux_kernel_version; /* LINUX_VERSION_CODE */
+	unsigned short hdrs_version;
+	unsigned short root_flags;
+	unsigned short root_dev;
+	unsigned short ram_flags;
+	unsigned int __deprecated_ramdisk_image;
+	unsigned int ramdisk_size;
+
+	/* HdrS versions 0x0201 and higher only */
+	char *reboot_command;
+
+	/* HdrS versions 0x0202 and higher only */
+	struct linux_bootstr_info *bootstr_info;
+
+	/* HdrS versions 0x0301 and higher only */
+	unsigned long ramdisk_image;
+};
+
+static grub_err_t
+grub_linux_boot (void)
+{
+  struct linux_bootstr_info *bp;
+  kernel_entry_t linuxmain;
+  struct linux_hdrs *hp;
+
+  hp = (struct linux_hdrs *) linux_addr;
+  bp = hp->bootstr_info;
+
+  /* Set the command line arguments, unless the kernel has been
+     built with a fixed CONFIG_CMDLINE.  */
+  if (!bp->valid)
+    {
+      int len = grub_strlen (linux_args) + 1;
+      if (bp->len < len)
+	len = bp->len;
+      memcpy(bp->buf, linux_args, len);
+      bp->buf[len-1] = '\0';
+    }
+
+  if (initrd_addr)
+    {
+      /* XXX translate XXX */
+      hp->ramdisk_image = initrd_addr;
+      hp->ramdisk_size = initrd_size;
+    }
+
+  grub_dprintf ("loader", "Entry point: 0x%lx\n", linux_addr);
+  grub_dprintf ("loader", "Initrd at: 0x%lx, size 0x%lx\n", initrd_addr,
+		initrd_size);
+  grub_dprintf ("loader", "Boot arguments: %s\n", linux_args);
+  grub_dprintf ("loader", "Jumping to Linux...\n");
+
+  /* Boot the kernel.  */
+  linuxmain = (kernel_entry_t) linux_addr;
+  linuxmain (0, 0, 0, 0, grub_ieee1275_entry_fn);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_linux_release_mem (void)
+{
+  grub_free (linux_args);
+  linux_args = 0;
+
+  if (linux_addr && grub_ieee1275_release (linux_addr, linux_size))
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Can not release memory");
+
+  if (initrd_addr && grub_ieee1275_release (initrd_addr, initrd_size))
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Can not release memory");
+
+  linux_addr = 0;
+  initrd_addr = 0;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_linux_unload (void)
+{
+  grub_err_t err;
+
+  err = grub_linux_release_mem ();
+  grub_dl_unref (my_mod);
+
+  loaded = 0;
+
+  return err;
+}
+
+static grub_err_t
+grub_linux_load64 (grub_elf_t elf)
+{
+  Elf64_Addr entry;
+  int found_addr = 0;
+
+  entry = elf->ehdr.ehdr64.e_entry;
+
+  linux_size = grub_elf64_size (elf);
+  if (linux_size == 0)
+    return grub_errno;
+
+  grub_dprintf ("loader", "Attempting to claim at 0x%lx, size 0x%lx.\n",
+		linux_addr, linux_size);
+  found_addr = grub_claimmap (linux_addr, linux_size);
+  if (found_addr == -1)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not claim memory.");
+
+  /* Now load the segments into the area we claimed.  */
+  return grub_elf64_load (elf, 0, 0, 0);
+}
+
+void
+grub_rescue_cmd_linux (int argc, char *argv[])
+{
+  grub_elf_t elf = 0;
+  int i;
+  int size;
+  char *dest;
+
+  grub_dl_ref (my_mod);
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto out;
+    }
+
+  elf = grub_elf_open (argv[0]);
+  if (! elf)
+    goto out;
+
+  if (elf->ehdr.ehdr32.e_type != ET_EXEC)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_OS,
+		  "This ELF file is not of the right type\n");
+      goto out;
+    }
+
+  /* Release the previously used memory.  */
+  grub_loader_unset ();
+
+  if (grub_elf_is_elf64 (elf))
+    grub_linux_load64 (elf);
+  else
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "Unknown ELF class");
+      goto out;
+    }
+
+  size = sizeof ("BOOT_IMAGE=") + grub_strlen (argv[0]);
+  for (i = 0; i < argc; i++)
+    size += grub_strlen (argv[i]) + 1;
+
+  linux_args = grub_malloc (size);
+  if (! linux_args)
+    goto out;
+
+  /* Specify the boot file.  */
+  dest = grub_stpcpy (linux_args, "BOOT_IMAGE=");
+  dest = grub_stpcpy (dest, argv[0]);
+  
+  for (i = 1; i < argc; i++)
+    {
+      *dest++ = ' ';
+      dest = grub_stpcpy (dest, argv[i]);
+    }
+
+out:
+
+  if (elf)
+    grub_elf_close (elf);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_linux_release_mem ();
+      grub_dl_unref (my_mod);
+      loaded = 0;
+    }
+  else
+    {
+      grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
+      initrd_addr = 0;
+      loaded = 1;
+    }
+}
+
+void
+grub_rescue_cmd_initrd (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  grub_ssize_t size;
+  grub_addr_t first_addr;
+  grub_addr_t addr;
+  int found_addr = 0;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no initrd specified");
+      goto fail;
+    }
+
+  if (!loaded)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "You need to load the kernel first.");
+      goto fail;
+    }
+
+  file = grub_file_open (argv[0]);
+  if (! file)
+    goto fail;
+
+  first_addr = linux_addr + linux_size;
+  size = grub_file_size (file);
+
+  /* Attempt to claim at a series of addresses until successful in
+     the same way that grub_rescue_cmd_linux does.  */
+  for (addr = first_addr; addr < first_addr + 200 * 0x100000; addr += 0x100000) 
+    {
+      grub_dprintf ("loader", "Attempting to claim at 0x%lx, size 0x%lx.\n", 
+		    addr, size);
+      found_addr = grub_claimmap (addr, size);
+      if (found_addr != -1)
+	break;
+    }
+
+  if (found_addr == -1)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "Can not claim memory");
+      goto fail;
+    }
+
+  grub_dprintf ("loader", "Loading initrd at 0x%lx, size 0x%lx\n", addr, size);
+
+  if (grub_file_read (file, (void *) addr, size) != size)
+    {
+      grub_ieee1275_release (addr, size);
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
+  initrd_addr = addr;
+  initrd_size = size;
+
+ fail:
+  if (file)
+    grub_file_close (file);
+}
+
+
+\f
+GRUB_MOD_INIT(linux)
+{
+  grub_rescue_register_command ("linux", grub_rescue_cmd_linux,
+				"load a linux kernel");
+  grub_rescue_register_command ("initrd", grub_rescue_cmd_initrd,
+				"load an initrd");
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(linux)
+{
+  grub_rescue_unregister_command ("linux");
+  grub_rescue_unregister_command ("initrd");
+}
diff --git a/loader/sparc64/ieee1275/linux_normal.c b/loader/sparc64/ieee1275/linux_normal.c
new file mode 100644
index 0000000..619eb33
--- /dev/null
+++ b/loader/sparc64/ieee1275/linux_normal.c
@@ -0,0 +1,60 @@
+/* linux_normal.c - boot Linux */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2007  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/normal.h>
+#include <grub/dl.h>
+#include <grub/machine/loader.h>
+
+static const struct grub_arg_option options[] =
+  {
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static grub_err_t
+grub_cmd_linux (struct grub_arg_list *state  __attribute__ ((unused)),
+		int argc, char **args)
+{
+  grub_rescue_cmd_linux (argc, args);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_initrd (struct grub_arg_list *state  __attribute__ ((unused)),
+		 int argc, char **args)
+{
+  grub_rescue_cmd_initrd (argc, args);
+  return GRUB_ERR_NONE;
+}
+
+GRUB_MOD_INIT(linux_normal)
+{
+  (void) mod;
+  grub_register_command ("linux", grub_cmd_linux, GRUB_COMMAND_FLAG_BOTH,
+			 "linux [KERNELARGS...]",
+			 "Loads linux", options);
+  grub_register_command ("initrd", grub_cmd_initrd, GRUB_COMMAND_FLAG_BOTH,
+			 "initrd FILE",
+			 "Loads initrd", options);
+}
+
+GRUB_MOD_FINI(linux_normal)
+{
+  grub_unregister_command ("linux");
+  grub_unregister_command ("initrd");
+}
-- 
1.6.1.2.253.ga34a




             reply	other threads:[~2009-03-04  2:53 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-04  2:15 David Miller [this message]
2009-03-04 11:44 ` [PATCH 5/7]: Add sparc64 loader implementation Vesa Jääskeläinen
2009-03-04 11:46   ` David Miller
2009-03-04 11:49     ` phcoder
2009-03-05 13:55       ` Jordi Mallach

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090303.181527.200306325.davem@davemloft.net \
    --to=davem@davemloft.net \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.