diff options
author | Simon Horman <horms@verge.net.au> | 2007-02-01 17:09:16 +0900 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2007-02-01 17:16:53 +0900 |
commit | 35917b5e76e8aef49920cc9693c94863f4ae507b (patch) | |
tree | 79aac9b8ea813e3809e44b940d10b4f4d6ef257b | |
parent | 17aef86b03edc9867f990434bc30be0ac498376d (diff) |
kexec-tools: Add sh support
Patch found on
http://eggplant.ddo.jp/www/download/debian26/source/kexec-tools/kexec-tools_1.101-2sh.diff.gz
According to Paul Mundt <lethal@linux-sh.org> it was originally by
kogiidena <kogiidena@eggplant.ddo.jp>
Signed-off-by: Simon Horman <horms@verge.net.au>
Acked-by: Magnus Damm <magnus.damm@gmail.com>
-rw-r--r-- | kexec/arch/sh/Makefile | 8 | ||||
-rw-r--r-- | kexec/arch/sh/include/arch/options.h | 22 | ||||
-rw-r--r-- | kexec/arch/sh/kexec-elf-rel-sh.c | 18 | ||||
-rw-r--r-- | kexec/arch/sh/kexec-netbsd-sh.c | 153 | ||||
-rw-r--r-- | kexec/arch/sh/kexec-sh.c | 166 | ||||
-rw-r--r-- | kexec/arch/sh/kexec-sh.h | 17 | ||||
-rw-r--r-- | kexec/arch/sh/kexec-zImage-sh.c | 107 | ||||
-rw-r--r-- | kexec/arch/sh/netbsd_booter.S | 47 | ||||
-rw-r--r-- | kexec/kexec-syscall.h | 3 | ||||
-rw-r--r-- | purgatory/arch/sh/Makefile | 7 | ||||
-rw-r--r-- | purgatory/arch/sh/include/limits.h | 58 | ||||
-rw-r--r-- | purgatory/arch/sh/include/stdint.h | 16 |
12 files changed, 622 insertions, 0 deletions
diff --git a/kexec/arch/sh/Makefile b/kexec/arch/sh/Makefile new file mode 100644 index 0000000..8cf52e3 --- /dev/null +++ b/kexec/arch/sh/Makefile @@ -0,0 +1,8 @@ +# +# kexec sh (linux booting linux) +# +KEXEC_C_SRCS+= kexec/arch/sh/kexec-sh.c +KEXEC_C_SRCS+= kexec/arch/sh/kexec-zImage-sh.c +KEXEC_C_SRCS+= kexec/arch/sh/kexec-netbsd-sh.c +KEXEC_C_SRCS+= kexec/arch/sh/kexec-elf-rel-sh.c +KEXEC_S_SRCS+= kexec/arch/sh/netbsd_booter.S diff --git a/kexec/arch/sh/include/arch/options.h b/kexec/arch/sh/include/arch/options.h new file mode 100644 index 0000000..e02960d --- /dev/null +++ b/kexec/arch/sh/include/arch/options.h @@ -0,0 +1,22 @@ +#ifndef KEXEC_ARCH_SH_OPTIONS_H +#define KEXEC_ARCH_SH_OPTIONS_H + +#define OPT_ARCH_MAX (OPT_MAX+0) +#define OPT_APPEND (OPT_ARCH_MAX+1) +#define OPT_EMPTYZERO (OPT_ARCH_MAX+2) +#define OPT_NBSD_HOWTO (OPT_ARCH_MAX+3) +#define OPT_NBSD_MROOT (OPT_ARCH_MAX+4) + + +#define KEXEC_ARCH_OPTIONS \ + KEXEC_OPTIONS \ + {"command-line", 1, 0, OPT_APPEND}, \ + {"append", 1, 0, OPT_APPEND}, \ + {"empty-zero", 1, 0, OPT_APPEND}, \ + {"howto", 1, 0, OPT_NBSD_HOWTO}, \ + {"miniroot", 1, 0, OPT_NBSD_MROOT}, \ + + +#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" + +#endif /* KEXEC_ARCH_SH_OPTIONS_H */ diff --git a/kexec/arch/sh/kexec-elf-rel-sh.c b/kexec/arch/sh/kexec-elf-rel-sh.c new file mode 100644 index 0000000..3e16b28 --- /dev/null +++ b/kexec/arch/sh/kexec-elf-rel-sh.c @@ -0,0 +1,18 @@ +#include <stdio.h> +#include <elf.h> +#include "../../kexec.h" +#include "../../kexec-elf.h" + +int machine_verify_elf_rel(struct mem_ehdr *ehdr) +{ + + die("machine_verify_elf_rel is not implemented\n"); + return 0; +} + +void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, + void *location, unsigned long address, unsigned long value) +{ + die("Unknown rela relocation: %lu\n", r_type); + return; +} diff --git a/kexec/arch/sh/kexec-netbsd-sh.c b/kexec/arch/sh/kexec-netbsd-sh.c new file mode 100644 index 0000000..935338e --- /dev/null +++ b/kexec/arch/sh/kexec-netbsd-sh.c @@ -0,0 +1,153 @@ +/* + * kexec-netbsd-sh.c - kexec netbsd loader for the SH + * Copyright (C) 2005 kogiidena@eggplant.ddo.jp + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#define _GNU_SOURCE +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <unistd.h> +#include <getopt.h> +#include <elf.h> +#include <boot/elf_boot.h> +#include <ip_checksum.h> +#include "../../kexec.h" +#include "../../kexec-elf.h" +#include <arch/options.h> +#include <asm/page.h> + +static const int probe_debug = 0; +const extern unsigned char netbsd_booter[]; + +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) + +/* + * netbsd_sh_probe - sanity check the elf image + * + * Make sure that the file image has a reasonable chance of working. + */ +int netbsd_sh_probe(const char *buf, off_t len) +{ + Elf32_Ehdr *ehdr; + + ehdr = (Elf32_Ehdr *)buf; + if(memcmp(buf, ELFMAG, SELFMAG) != 0){ + return -1; + } + if (ehdr->e_machine != EM_SH) { + return -1; + } + return 0; +} + +void netbsd_sh_usage(void) +{ + printf( + " --howto=VALUE NetBSD kernel boot option.\n" + " --miniroot=FILE NetBSD miniroot ramdisk.\n\n"); +} + +int netbsd_sh_load(int argc, char **argv, const char *buf, off_t len, + struct kexec_info *info) +{ + const char *howto, *miniroot; + unsigned long entry, start, size; + char *miniroot_buf; + off_t miniroot_length; + unsigned int howto_value; + unsigned char *param; + unsigned long *paraml; + unsigned char *img; + + int opt; + + static const struct option options[] = { + KEXEC_ARCH_OPTIONS + {0, 0, 0, 0}, + }; + + static const char short_options[] = KEXEC_ARCH_OPT_STR ""; + + howto = miniroot = 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_NBSD_HOWTO: + howto = optarg; + break; + case OPT_NBSD_MROOT: + miniroot = optarg; + break; + } + } + + /* howto */ + howto_value = 0; + if(howto){ + howto_value = strtol(howto, NULL, 0); + } + + /* Parse the Elf file */ + { + Elf32_Ehdr *ehdr; + Elf32_Phdr *phdr; + unsigned long bbs; + ehdr = (Elf32_Ehdr *)buf; + phdr = (Elf32_Phdr *)&buf[ehdr->e_phoff]; + + entry = ehdr->e_entry; + img = (unsigned char *)&buf[phdr->p_offset]; + start = (phdr->p_paddr) & 0x1fffffff; + bbs = phdr->p_filesz; + size = phdr->p_memsz; + + if(size < bbs){ + size = bbs; + } + size = PAGE_ALIGN(size); + memset(&img[bbs], 0, size-bbs); + add_segment(info, img, size, start, size); + start += size; + } + + /* miniroot file */ + miniroot_buf = 0; + if (miniroot) { + miniroot_buf = slurp_file(miniroot, &miniroot_length); + howto_value |= 0x200; + size = PAGE_ALIGN(miniroot_length); + add_segment(info, miniroot_buf, size, start, size); + start += size; + } + + /* howto & bootinfo */ + param = xmalloc(4096); + memset(param, 0, 4096); + paraml = (unsigned long *) ¶m[256]; + memcpy(param, netbsd_booter, 256); + paraml[0] = entry; + paraml[1] = howto_value; + add_segment(info, param, 4096, start, 4096); + + /* For now we don't have arguments to pass :( */ + info->entry = (void *) (start | 0xa0000000); + return 0; +} diff --git a/kexec/arch/sh/kexec-sh.c b/kexec/arch/sh/kexec-sh.c new file mode 100644 index 0000000..6b485d1 --- /dev/null +++ b/kexec/arch/sh/kexec-sh.c @@ -0,0 +1,166 @@ +/* + * kexec-sh.c - kexec for the SH + * Copyright (C) 2004 kogiidena@eggplant.ddo.jp + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#define _GNU_SOURCE +#include <stddef.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <sys/utsname.h> +#include "../../kexec.h" +#include "../../kexec-syscall.h" +#include "kexec-sh.h" +#include <arch/options.h> + +#define MAX_MEMORY_RANGES 64 +#define MAX_LINE 160 +static struct memory_range memory_range[MAX_MEMORY_RANGES]; + +/* Return a sorted list of available memory ranges. */ +int get_memory_ranges(struct memory_range **range, int *ranges) +{ + int memory_ranges; + + memory_ranges = 0; + memory_range[memory_ranges].start = 0x08000000; + memory_range[memory_ranges].end = 0x10000000; + memory_range[memory_ranges].type = RANGE_RAM; + memory_ranges++; + *range = memory_range; + *ranges = memory_ranges; + return 0; +} + +/* Supported file types and callbacks */ +struct file_type file_type[] = { + {"zImage-sh", zImage_sh_probe, zImage_sh_load, zImage_sh_usage}, + {"netbsd-sh", netbsd_sh_probe, netbsd_sh_load, netbsd_sh_usage}, +}; +int file_types = sizeof(file_type) / sizeof(file_type[0]); + + +void arch_usage(void) +{ + + printf( + " none\n\n" + "Default options:\n" + " --append=\"%s\"\n" + " --empty-zero=0x%08x\n\n" + " STRING of --appned is set form /proc/cmdline as default.\n" + " ADDRESS of --empty-zero can be set SHELL environment variable\n" + " KEXEC_EMPTY_ZERO as default.\n\n" + " ADDRESS can be get in the following method in your system. \n" + " 1) \"grep empty_zero /proc/kallsyms\". \n" + " 2) \"grep empty_zero System.map\". \n" + " 3) CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET in your kernel\n" + " config file.\n" + ,get_append(), (unsigned int) get_empty_zero(NULL)); + +} + +static struct { +} arch_options = { +}; +int arch_process_options(int argc, char **argv) +{ + static const struct option options[] = { + KEXEC_ARCH_OPTIONS + { 0, 0, NULL, 0 }, + }; + static const char short_options[] = KEXEC_ARCH_OPT_STR; + int opt; + + opterr = 0; /* Don't complain about unrecognized options here */ + while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) { + switch(opt) { + default: + /* Ignore core options */ + if (opt < OPT_MAX) { + break; + } + case '?': + usage(); + return -1; + case OPT_APPEND: + case OPT_NBSD_HOWTO: + case OPT_NBSD_MROOT: + ; + } + } + /* Reset getopt for the next pass; called in other source modules */ + opterr = 1; + optind = 1; + return 0; +} + +int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags) +{ + int result; + struct utsname utsname; + result = uname(&utsname); + if (result < 0) { + fprintf(stderr, "uname failed: %s\n", + strerror(errno)); + return -1; + } + if ( (strcmp(utsname.machine, "sh3") == 0) || + (strcmp(utsname.machine, "sh4") == 0)) + + { + /* For compatibility with older patches + * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_IA64 here. + */ + *flags |= KEXEC_ARCH_DEFAULT; + } + else { + fprintf(stderr, "Unsupported machine type: %s\n", + utsname.machine); + return -1; + } + return 0; +} + +void arch_update_purgatory(struct kexec_info *info) +{ +} + + +unsigned long get_empty_zero(char *s) +{ + char *env; + + env = getenv("KEXEC_EMPTY_ZERO"); + + if(s){ + env = s; + }else if(!env){ + env = "0x0c001000"; + } + return 0x1fffffff & strtoul(env,(char **)NULL,0); +} + +char append_buf[256]; + +char *get_append(void) +{ + FILE *fp; + int len; + if((fp = fopen("/proc/cmdline", "r")) == NULL){ + printf("/proc/cmdline file open error !!\n"); + exit(1); + } + fgets(append_buf, 256, fp); + len = strlen(append_buf); + append_buf[len-1] = 0; + fclose(fp); + return append_buf; +} diff --git a/kexec/arch/sh/kexec-sh.h b/kexec/arch/sh/kexec-sh.h new file mode 100644 index 0000000..ee73d8c --- /dev/null +++ b/kexec/arch/sh/kexec-sh.h @@ -0,0 +1,17 @@ +#ifndef KEXEC_SH_H +#define KEXEC_SH_H + +int zImage_sh_probe(const char *buf, off_t len); +int zImage_sh_load(int argc, char **argv, const char *buf, off_t len, + struct kexec_info *info); +void zImage_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); +void netbsd_sh_usage(void); + +char *get_append(void); +unsigned long get_empty_zero(char *s); + +#endif /* KEXEC_SH_H */ diff --git a/kexec/arch/sh/kexec-zImage-sh.c b/kexec/arch/sh/kexec-zImage-sh.c new file mode 100644 index 0000000..9527fb6 --- /dev/null +++ b/kexec/arch/sh/kexec-zImage-sh.c @@ -0,0 +1,107 @@ +/* + * kexec-zImage-sh.c - kexec zImage loader for the SH + * Copyright (C) 2005 kogiidena@eggplant.ddo.jp + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#define _GNU_SOURCE +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <unistd.h> +#include <getopt.h> +#include <elf.h> +#include <boot/elf_boot.h> +#include <ip_checksum.h> +#include "../../kexec.h" +#include "../../kexec-elf.h" +#include <arch/options.h> +#include "kexec-sh.h" + +static const int probe_debug = 0; + +/* + * zImage_sh_probe - sanity check the elf image + * + * Make sure that the file image has a reasonable chance of working. + */ +int zImage_sh_probe(const char *buf, off_t len) +{ + if (memcmp(&buf[0x202], "HdrS", 4) != 0) { + fprintf(stderr, "Not a zImage\n"); + return -1; + } + return 0; +} + +void zImage_sh_usage(void) +{ + printf( + + " --append=STRING Set the kernel command line to STRING.\n" + " --empty-zero=ADDRESS Set the kernel top ADDRESS. \n\n"); + +} + +int zImage_sh_load(int argc, char **argv, const char *buf, off_t len, + struct kexec_info *info) +{ + char *command_line; + int opt; + unsigned long empty_zero, area; + unsigned char *param; + unsigned long *paraml; + + static const struct option options[] = { + KEXEC_ARCH_OPTIONS + {0, 0, 0, 0}, + }; + + static const char short_options[] = KEXEC_ARCH_OPT_STR ""; + + command_line = 0; + empty_zero = get_empty_zero(NULL); + 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; + case OPT_EMPTYZERO: + empty_zero = get_empty_zero(optarg); + break; + } + } + param = xmalloc(4096); + memset(param, 0, 4096); + area = empty_zero & 0x1c000000; + if (!command_line) { + command_line = get_append(); + } + strncpy(¶m[256], command_line, strlen(command_line)); + paraml = (unsigned long *)param; + // paraml[0] = 1; // readonly flag is set as default + + add_segment(info, param, 4096, empty_zero, 4096); + add_segment(info, buf, len, (area | 0x00210000), len); + + /* For now we don't have arguments to pass :( */ + info->entry = (void *)(0x80210000 | area); + return 0; +} diff --git a/kexec/arch/sh/netbsd_booter.S b/kexec/arch/sh/netbsd_booter.S new file mode 100644 index 0000000..e660b3d --- /dev/null +++ b/kexec/arch/sh/netbsd_booter.S @@ -0,0 +1,47 @@ + .globl netbsd_booter +netbsd_booter: + mov.l ccr,r0 + mov #0,r1 + mov.l r1,@r0 + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + mova netbsd_start,r0 + mov.l @r0,r1 + add #4,r0 + mov.l @r0,r4 ! howto + add #4,r0 + mov r0,r5 ! bootinfo + jmp @r1 + nop + nop + nop + .align 4 +ccr: .long 0xff00001c + + .align 8 +netbsd_start: + .long 0x8c001000 + .long 0x200 ! howto + .long 0 ! bootinfo + .long 0 ! bootinfo + .long 0 ! bootinfo + .long 0 ! bootinfo + .long 0 ! bootinfo + .long 0 ! bootinfo + .long 0 ! bootinfo + .long 0 ! bootinfo + .long 0 ! bootinfo + .long 0 ! bootinfo + .long 0 ! bootinfo + .long 0 ! bootinfo + .long 0 ! bootinfo + .long 0 ! bootinfo + diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h index 37e2bb1..0ca3984 100644 --- a/kexec/kexec-syscall.h +++ b/kexec/kexec-syscall.h @@ -25,6 +25,9 @@ #ifdef __i386__ #define __NR_kexec_load 283 #endif +#ifdef __sh__ +#define __NR_kexec_load 283 +#endif #ifdef __ia64__ #define __NR_kexec_load 1268 #endif diff --git a/purgatory/arch/sh/Makefile b/purgatory/arch/sh/Makefile new file mode 100644 index 0000000..a626bbd --- /dev/null +++ b/purgatory/arch/sh/Makefile @@ -0,0 +1,7 @@ +# +# Purgatory alpha +# + +PURGATORY_C_SRCS+= +PURGATORY_S_SRCS+= + diff --git a/purgatory/arch/sh/include/limits.h b/purgatory/arch/sh/include/limits.h new file mode 100644 index 0000000..d5a5a02 --- /dev/null +++ b/purgatory/arch/sh/include/limits.h @@ -0,0 +1,58 @@ +#ifndef LIMITS_H +#define LIMITS_H 1 + + +/* Number of bits in a `char' */ +#define CHAR_BIT 8 + +/* Minimum and maximum values a `signed char' can hold */ +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 + +/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */ +#define UCHAR_MAX 255 + +/* Minimum and maximum values a `char' can hold */ +#define CHAR_MIN SCHAR_MIN +#define CHAR_MAX SCHAR_MAX + +/* Minimum and maximum values a `signed short int' can hold */ +#define SHRT_MIN (-32768) +#define SHRT_MAX 32767 + +/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */ +#define USHRT_MAX 65535 + + +/* Minimum and maximum values a `signed int' can hold */ +#define INT_MIN (-INT_MAX - 1) +#define INT_MAX 2147483647 + +/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ +#define UINT_MAX 4294967295U + + +/* Minimum and maximum values a `signed int' can hold */ +#define INT_MIN (-INT_MAX - 1) +#define INT_MAX 2147483647 + +/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ +#define UINT_MAX 4294967295U + +/* Minimum and maximum values a `signed long' can hold */ +#define LONG_MAX 2147483647L +#define LONG_MIN (-LONG_MAX - 1L) + +/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */ +#define ULONG_MAX 4294967295UL + +/* Minimum and maximum values a `signed long long' can hold */ +#define LLONG_MAX 9223372036854775807LL +#define LLONG_MIN (-LONG_MAX - 1LL) + + +/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */ +#define ULLONG_MAX 18446744073709551615ULL + + +#endif /* LIMITS_H */ diff --git a/purgatory/arch/sh/include/stdint.h b/purgatory/arch/sh/include/stdint.h new file mode 100644 index 0000000..79262c2 --- /dev/null +++ b/purgatory/arch/sh/include/stdint.h @@ -0,0 +1,16 @@ +#ifndef STDINT_H +#define STDINT_H + +typedef unsigned long size_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; +typedef signed long long int64_t; + +#endif /* STDINT_H */ |