2009-03-03 David S. Miller <da...@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. --- 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 ++++++++++++++++++++++++++++++++ 4 files changed, 397 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
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..35651f1 --- /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, 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/>. + */ + +#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); +} + + + +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"); +} -- 1.6.2 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel