diff options
author | Magnus Damm <damm@igel.co.jp> | 2008-08-27 17:33:20 +1000 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2008-08-27 17:33:20 +1000 |
commit | 6eae8c1bc4d43d07c9799b2406ba42b995f2368d (patch) | |
tree | eb14cfe5a4eb9fc83ee1b7b2abe19f14df3ea929 | |
parent | 61d60261c616d75d6bd380744a78400972dd3e46 (diff) |
sh: Add vmlinux support
Add SuperH vmlinux support through a zero-page aware elf loader. Only for
kexec at this point, in the future kdump support will be added.
Signed-off-by: Magnus Damm <damm@igel.co.jp>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r-- | kexec/arch/sh/Makefile | 1 | ||||
-rw-r--r-- | kexec/arch/sh/kexec-elf-sh.c | 114 | ||||
-rw-r--r-- | kexec/arch/sh/kexec-sh.c | 1 | ||||
-rw-r--r-- | kexec/arch/sh/kexec-sh.h | 5 |
4 files changed, 121 insertions, 0 deletions
diff --git a/kexec/arch/sh/Makefile b/kexec/arch/sh/Makefile index 9076d69..1a67dff 100644 --- a/kexec/arch/sh/Makefile +++ b/kexec/arch/sh/Makefile @@ -4,6 +4,7 @@ sh_KEXEC_SRCS += kexec/arch/sh/kexec-sh.c sh_KEXEC_SRCS += kexec/arch/sh/kexec-zImage-sh.c sh_KEXEC_SRCS += kexec/arch/sh/kexec-netbsd-sh.c +sh_KEXEC_SRCS += kexec/arch/sh/kexec-elf-sh.c sh_KEXEC_SRCS += kexec/arch/sh/kexec-elf-rel-sh.c sh_KEXEC_SRCS += kexec/arch/sh/netbsd_booter.S diff --git a/kexec/arch/sh/kexec-elf-sh.c b/kexec/arch/sh/kexec-elf-sh.c new file mode 100644 index 0000000..a5f0967 --- /dev/null +++ b/kexec/arch/sh/kexec-elf-sh.c @@ -0,0 +1,114 @@ +/* + * kexec: Linux boots Linux + * + * Copyright (C) 2008 Magnus Damm + * + * Based on x86 implementation, + * Copyright (C) 2003-2005 Eric Biederman (ebiederm@xmission.com) + * + * 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 (version 2 of the License). + * + * 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <limits.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <getopt.h> +#include <elf.h> +#include "../../kexec.h" +#include "../../kexec-syscall.h" +#include "../../kexec-elf.h" +#include "../../kexec-elf-boot.h" +#include <arch/options.h> +#include "kexec-sh.h" + +int elf_sh_probe(const char *buf, off_t len) +{ + struct mem_ehdr ehdr; + int result; + result = build_elf_exec_info(buf, len, &ehdr, 0); + if (result < 0) + goto out; + + /* Verify the architecuture specific bits */ + if (ehdr.e_machine != EM_SH) { + result = -1; + goto out; + } + + result = 0; + out: + free_elf_info(&ehdr); + return result; +} + +void elf_sh_usage(void) +{ + printf(" --append=STRING Set the kernel command line to STRING\n" + ); +} + +int elf_sh_load(int argc, char **argv, const char *buf, off_t len, + struct kexec_info *info) +{ + struct mem_ehdr ehdr; + char *command_line; + struct mem_sym sym; + int opt; + static const struct option options[] = { + KEXEC_ARCH_OPTIONS + { 0, 0, 0, 0 }, + }; + + static const char short_options[] = KEXEC_OPT_STR ""; + + /* + * Parse the command line arguments + */ + command_line = 0; + while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) { + switch(opt) { + default: + /* Ignore core options */ + if (opt < OPT_ARCH_MAX) { + break; + } + case '?': + usage(); + return -1; + case OPT_APPEND: + command_line = optarg; + break; + } + } + + /* Load the ELF executable */ + elf_exec_build_load(info, &ehdr, buf, len, 0); + info->entry = (void *)ehdr.e_entry; + + /* If we're booting a vmlinux then fill in empty_zero_page */ + if (elf_rel_find_symbol(&ehdr, "empty_zero_page", &sym) == 0) { + char *zp = (void *)ehdr.e_shdr[sym.st_shndx].sh_data; + + kexec_sh_setup_zero_page(zp, 4096, command_line); + } + + return 0; +} diff --git a/kexec/arch/sh/kexec-sh.c b/kexec/arch/sh/kexec-sh.c index b94d692..7dc95be 100644 --- a/kexec/arch/sh/kexec-sh.c +++ b/kexec/arch/sh/kexec-sh.c @@ -53,6 +53,7 @@ int get_memory_ranges(struct memory_range **range, int *ranges, /* Supported file types and callbacks */ struct file_type file_type[] = { {"zImage-sh", zImage_sh_probe, zImage_sh_load, zImage_sh_usage}, + {"elf-sh", elf_sh_probe, elf_sh_load, elf_sh_usage}, {"netbsd-sh", netbsd_sh_probe, netbsd_sh_load, netbsd_sh_usage}, }; int file_types = sizeof(file_type) / sizeof(file_type[0]); diff --git a/kexec/arch/sh/kexec-sh.h b/kexec/arch/sh/kexec-sh.h index 2b89c5c..683494d 100644 --- a/kexec/arch/sh/kexec-sh.h +++ b/kexec/arch/sh/kexec-sh.h @@ -6,6 +6,11 @@ int zImage_sh_load(int argc, char **argv, const char *buf, off_t len, struct kexec_info *info); void zImage_sh_usage(void); +int elf_sh_probe(const char *buf, off_t len); +int elf_sh_load(int argc, char **argv, const char *buf, off_t len, + struct kexec_info *info); +void elf_sh_usage(void); + int netbsd_sh_probe(const char *buf, off_t len); int netbsd_sh_load(int argc, char **argv, const char *buf, off_t len, struct kexec_info *info); |