From: Magnus Damm <damm@xxxxxxxxxx> 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 at igel.co.jp> --- kexec/arch/sh/Makefile | 1 kexec/arch/sh/kexec-elf-sh.c | 114 ++++++++++++++++++++++++++++++++++++++++++ kexec/arch/sh/kexec-sh.c | 1 kexec/arch/sh/kexec-sh.h | 5 + 4 files changed, 121 insertions(+) --- 0004/kexec/arch/sh/Makefile +++ work/kexec/arch/sh/Makefile 2008-08-22 13:17:18.000000000 +0900 @@ -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 --- /dev/null +++ work/kexec/arch/sh/kexec-elf-sh.c 2008-08-22 14:24:31.000000000 +0900 @@ -0,0 +1,114 @@ +/* + * kexec: Linux boots Linux + * + * Copyright (C) 2008 Magnus Damm + * + * Based on x86 implementation, + * Copyright (C) 2003-2005 Eric Biederman (ebiederm at 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; + const char *command_line; + struct mem_sym sym; + int opt; + static const struct option options[] = { + KEXEC_ARCH_OPTIONS + { 0, 0, NULL, 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) { + unsigned char *zp = (void *)ehdr.e_shdr[sym.st_shndx].sh_data; + + kexec_sh_setup_zero_page(zp, 4096, command_line); + } + + return 0; +} --- 0005/kexec/arch/sh/kexec-sh.c +++ work/kexec/arch/sh/kexec-sh.c 2008-08-22 13:17:18.000000000 +0900 @@ -53,6 +53,7 @@ int get_memory_ranges(struct memory_rang /* 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]); --- 0005/kexec/arch/sh/kexec-sh.h +++ work/kexec/arch/sh/kexec-sh.h 2008-08-22 13:17:18.000000000 +0900 @@ -6,6 +6,11 @@ int zImage_sh_load(int argc, char **argv 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);