summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure5
-rw-r--r--kexec/arch/s390/Makefile6
-rw-r--r--kexec/arch/s390/include/arch/options.h11
-rw-r--r--kexec/arch/s390/kexec-elf-rel-s390.c23
-rw-r--r--kexec/arch/s390/kexec-image.c137
-rw-r--r--kexec/arch/s390/kexec-s390.c104
-rw-r--r--kexec/arch/s390/kexec-s390.h25
-rw-r--r--kexec/kexec-syscall.h7
-rw-r--r--purgatory/arch/s390/Makefile7
-rw-r--r--purgatory/arch/s390/include/limits.h54
-rw-r--r--purgatory/arch/s390/include/stdint.h24
11 files changed, 402 insertions, 1 deletions
diff --git a/configure b/configure
index d4267f1..5370f5e 100755
--- a/configure
+++ b/configure
@@ -1384,12 +1384,15 @@ case $host_cpu in
powerpc )
host_cpu="ppc"
;;
+ s390x )
+ host_cpu="s390"
+ ;;
* )
host_cpu="$host_cpu"
;;
esac
case $host_cpu in
- i386|ppc|x86_64|alpha|ppc64|ia64)
+ i386|ppc|x86_64|alpha|ppc64|ia64|s390)
;;
* )
{ { echo "$as_me:$LINENO: error: unsupported architecture $host_cpu" >&5
diff --git a/kexec/arch/s390/Makefile b/kexec/arch/s390/Makefile
new file mode 100644
index 0000000..1d26e81
--- /dev/null
+++ b/kexec/arch/s390/Makefile
@@ -0,0 +1,6 @@
+#
+# kexec s390 (linux booting linux)
+#
+KEXEC_C_SRCS+= kexec/arch/s390/kexec-s390.c
+KEXEC_C_SRCS+= kexec/arch/s390/kexec-image.c
+KEXEC_C_SRCS+= kexec/arch/s390/kexec-elf-rel-s390.c
diff --git a/kexec/arch/s390/include/arch/options.h b/kexec/arch/s390/include/arch/options.h
new file mode 100644
index 0000000..2979617
--- /dev/null
+++ b/kexec/arch/s390/include/arch/options.h
@@ -0,0 +1,11 @@
+#ifndef KEXEC_ARCH_S390_OPTIONS_H
+#define KEXEC_ARCH_S390_OPTIONS_H
+
+#define OPT_ARCH_MAX (OPT_MAX+0)
+
+#define KEXEC_ARCH_OPTIONS \
+ KEXEC_OPTIONS \
+
+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
+
+#endif /* KEXEC_ARCH_S390_OPTIONS_H */
diff --git a/kexec/arch/s390/kexec-elf-rel-s390.c b/kexec/arch/s390/kexec-elf-rel-s390.c
new file mode 100644
index 0000000..823b91c
--- /dev/null
+++ b/kexec/arch/s390/kexec-elf-rel-s390.c
@@ -0,0 +1,23 @@
+/*
+ * kexec/arch/s390/kexec-elf-rel-s390.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ *
+ */
+
+#include <stdio.h>
+#include <elf.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+
+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
+{
+ return 0;
+}
+
+void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
+ void *location, unsigned long address, unsigned long value)
+{
+}
diff --git a/kexec/arch/s390/kexec-image.c b/kexec/arch/s390/kexec-image.c
new file mode 100644
index 0000000..e1849f0
--- /dev/null
+++ b/kexec/arch/s390/kexec-image.c
@@ -0,0 +1,137 @@
+/*
+ * kexec/arch/s390/kexec-image.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ * Heiko Carstens <heiko.carstens@de.ibm.com>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <getopt.h>
+#include "../../kexec.h"
+#include "kexec-s390.h"
+
+#define OPT_APPEND OPT_MAX+0
+#define OPT_RAMDISK OPT_MAX+1
+
+int
+image_s390_load(int argc, char **argv, const char *kernel_buf,
+ off_t kernel_size, struct kexec_info *info)
+{
+ void *krnl_buffer;
+ char *rd_buffer;
+ const char *command_line;
+ const char *ramdisk;
+ int command_line_len;
+ off_t ramdisk_len;
+ unsigned int ramdisk_origin;
+ int opt;
+
+ static const struct option options[] =
+ {
+ KEXEC_OPTIONS
+ {"command-line", 1, 0, OPT_APPEND},
+ {"initrd", 1, 0, OPT_RAMDISK},
+ {0, 0, 0, 0},
+ };
+ static const char short_options[] = KEXEC_OPT_STR "";
+
+ ramdisk = NULL;
+ command_line = NULL;
+ ramdisk_len = 0;
+ ramdisk_origin = 0;
+
+ while ((opt = getopt_long(argc,argv,short_options,options,0)) != -1) {
+ switch(opt) {
+ case '?':
+ usage();
+ return -1;
+ break;
+ case OPT_APPEND:
+ command_line = optarg;
+ break;
+ case OPT_RAMDISK:
+ ramdisk = optarg;
+ break;
+ }
+ }
+
+ /* Process a given command_line: */
+ if (command_line) {
+ command_line_len = strlen(command_line) + 1; /* Remember the '\0' */
+ if (command_line_len > COMMAND_LINESIZE) {
+ fprintf(stderr, "Command line too long.\n");
+ return -1;
+ }
+ }
+
+ /* Add kernel segment */
+ add_segment(info, kernel_buf + IMAGE_READ_OFFSET,
+ kernel_size - IMAGE_READ_OFFSET, IMAGE_READ_OFFSET,
+ kernel_size - IMAGE_READ_OFFSET);
+
+ /* We do want to change the kernel image */
+ krnl_buffer = (void *) kernel_buf + IMAGE_READ_OFFSET;
+
+ /* Load ramdisk if present */
+ if (ramdisk) {
+ rd_buffer = slurp_file(ramdisk, &ramdisk_len);
+ if (rd_buffer == NULL) {
+ fprintf(stderr, "Could not read ramdisk.\n");
+ return -1;
+ }
+ ramdisk_origin = RAMDISK_ORIGIN_ADDR;
+ add_segment(info, rd_buffer, ramdisk_len, RAMDISK_ORIGIN_ADDR, ramdisk_len);
+ }
+
+ /* Register the ramdisk in the kernel. */
+ {
+ unsigned long long *tmp;
+
+ tmp = krnl_buffer + INITRD_START_OFFS;
+ *tmp = (unsigned long long) ramdisk_origin;
+
+ tmp = krnl_buffer + INITRD_SIZE_OFFS;
+ *tmp = (unsigned long long) ramdisk_len;
+ }
+
+ /*
+ * We will write a probably given command line.
+ * First, erase the old area, then setup the new parameters:
+ */
+ if (command_line) {
+ memset(krnl_buffer + COMMAND_LINE_OFFS, 0, COMMAND_LINESIZE);
+ memcpy(krnl_buffer + COMMAND_LINE_OFFS, command_line, strlen(command_line));
+ }
+
+ info->entry = (void *) IMAGE_READ_OFFSET;
+
+ return 0;
+}
+
+int
+image_s390_probe(const char *kernel_buf, off_t kernel_size)
+{
+ /*
+ * Can't reliably tell if an image is valid,
+ * therefore everything is valid.
+ */
+ return 0;
+}
+
+void
+image_s390_usage(void)
+{
+ printf("--command-line=STRING Pass a custom command line STRING to the kernel.\n"
+ "--initrd=FILENAME Use the file FILENAME as a ramdisk.\n"
+ );
+}
diff --git a/kexec/arch/s390/kexec-s390.c b/kexec/arch/s390/kexec-s390.c
new file mode 100644
index 0000000..04d8ccc
--- /dev/null
+++ b/kexec/arch/s390/kexec-s390.c
@@ -0,0 +1,104 @@
+/*
+ * kexec/arch/s390/kexec-s390.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/utsname.h>
+#include "../../kexec.h"
+#include "../../kexec-syscall.h"
+#include "kexec-s390.h"
+#include <arch/options.h>
+
+#define MAX_MEMORY_RANGES 64
+static struct memory_range memory_range[MAX_MEMORY_RANGES];
+
+/*
+ * get_memory_ranges:
+ * Return a list of memory ranges by parsing /proc/iomem
+ *
+ * INPUT:
+ * - Pointer to an array of memory_range structures.
+ * - Pointer to an integer with holds the number of memory ranges.
+ *
+ * RETURN:
+ * - 0 on normal execution.
+ * - (-1) if something went wrong.
+ */
+
+int get_memory_ranges(struct memory_range **range, int *ranges)
+{
+ char sys_ram[] = "System RAM\n";
+ char iomem[] = "/proc/iomem";
+ FILE *fp;
+ char line[80];
+ int current_range = 0;
+
+ fp = fopen(iomem,"r");
+ if(fp == 0) {
+ fprintf(stderr,"Unable to open %s: %s\n",iomem,strerror(errno));
+ return -1;
+ }
+
+ /* Setup the compare string properly. */
+ while(fgets(line,sizeof(line),fp) != 0) {
+ unsigned long long start, end;
+ int cons;
+ char *str;
+
+ if (current_range == MAX_MEMORY_RANGES)
+ break;
+
+ sscanf(line,"%Lx-%Lx : %n", &start, &end, &cons);
+ str = line+cons;
+ if(memcmp(str,sys_ram,strlen(sys_ram)) == 0) {
+ memory_range[current_range].start = start;
+ memory_range[current_range].end = end;
+ memory_range[current_range].type = RANGE_RAM;
+ current_range++;
+ }
+ else {
+ continue;
+ }
+ }
+ fclose(fp);
+ *range = memory_range;
+ *ranges = current_range;
+
+ return 0;
+}
+
+/* Supported file types and callbacks */
+struct file_type file_type[] = {
+ { "image", image_s390_probe, image_s390_load, image_s390_usage},
+};
+int file_types = sizeof(file_type) / sizeof(file_type[0]);
+
+
+void arch_usage(void)
+{
+}
+
+int arch_process_options(int argc, char **argv)
+{
+ return 0;
+}
+
+int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+{
+ return 0;
+}
+
+void arch_update_purgatory(struct kexec_info *info)
+{
+}
diff --git a/kexec/arch/s390/kexec-s390.h b/kexec/arch/s390/kexec-s390.h
new file mode 100644
index 0000000..1159ceb
--- /dev/null
+++ b/kexec/arch/s390/kexec-s390.h
@@ -0,0 +1,25 @@
+/*
+ * kexec/arch/s390/kexec-s390.h
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ *
+ */
+
+#ifndef KEXEC_S390_H
+#define KEXEC_S390_H
+
+#define IMAGE_READ_OFFSET 0x10000
+
+#define RAMDISK_ORIGIN_ADDR 0x800000
+#define INITRD_START_OFFS 0x408
+#define INITRD_SIZE_OFFS 0x410
+#define COMMAND_LINE_OFFS 0x480
+#define COMMAND_LINESIZE 896
+
+extern int image_s390_load(int, char **, const char *, off_t, struct kexec_info *);
+extern int image_s390_probe(const char *, off_t);
+extern void image_s390_usage(void);
+
+#endif /* KEXEC_IA64_H */
diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
index 7b2670c..3de05eb 100644
--- a/kexec/kexec-syscall.h
+++ b/kexec/kexec-syscall.h
@@ -37,6 +37,12 @@
#ifdef __x86_64__
#define __NR_kexec_load 246
#endif
+#ifdef __s390x__
+#define __NR_kexec_load 277
+#endif
+#ifdef __s390__
+#define __NR_kexec_load 277
+#endif
#ifndef __NR_kexec_load
#error Unknown processor architecture. Needs a kexec_load syscall number.
#endif
@@ -67,6 +73,7 @@ static inline long kexec_reboot(void)
#define KEXEC_ARCH_PPC (20 << 16)
#define KEXEC_ARCH_PPC64 (21 << 16)
#define KEXEC_ARCH_IA_64 (50 << 16)
+#define KEXEC_ARCH_S390 (22 << 16)
#define KEXEC_MAX_SEGMENTS 8
diff --git a/purgatory/arch/s390/Makefile b/purgatory/arch/s390/Makefile
new file mode 100644
index 0000000..63dac9d
--- /dev/null
+++ b/purgatory/arch/s390/Makefile
@@ -0,0 +1,7 @@
+#
+# Purgatory s390
+#
+
+PURGATORY_C_SRCS+=
+PURGATORY_S_SRCS+=
+
diff --git a/purgatory/arch/s390/include/limits.h b/purgatory/arch/s390/include/limits.h
new file mode 100644
index 0000000..3424298
--- /dev/null
+++ b/purgatory/arch/s390/include/limits.h
@@ -0,0 +1,54 @@
+#ifndef _LIMITS_H_
+#define _LIMITS_H_
+
+/* 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
+
+# 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 int' 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 long int' can hold. */
+#ifdef __s390x__
+# define LONG_MAX 9223372036854775807L
+#else
+# define LONG_MAX 2147483647L
+#endif
+
+# define LONG_MIN (-LONG_MAX - 1L)
+
+/* Maximum value an `unsigned long int' can hold. (Minimum is 0.) */
+#ifdef __s390x__
+# define ULONG_MAX 18446744073709551615UL
+#else
+# define ULONG_MAX 4294967295UL
+#endif
+
+/* Minimum and maximum values a `signed long long int' can hold. */
+# define LLONG_MAX 9223372036854775807LL
+# define LLONG_MIN (-LLONG_MAX - 1LL)
+
+/* Maximum value an `unsigned long long int' can hold. (Minimum is 0.) */
+# define ULLONG_MAX 18446744073709551615ULL
+
+#endif /* !_LIMITS_H_ */
diff --git a/purgatory/arch/s390/include/stdint.h b/purgatory/arch/s390/include/stdint.h
new file mode 100644
index 0000000..a713cf5
--- /dev/null
+++ b/purgatory/arch/s390/include/stdint.h
@@ -0,0 +1,24 @@
+#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;
+#ifdef __s390x__
+typedef unsigned long uint64_t;
+#else
+typedef unsigned long long uint64_t;
+#endif
+
+typedef signed char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+#ifdef __s390x__
+typedef long int64_t;
+#else
+typedef long long int64_t;
+#endif
+
+#endif