summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2005-04-26 15:20:54 +0200
committerEric W. Biederman <ebiederm@xmission.com>2006-07-27 03:04:56 -0600
commit47406fd61a7eb4694a6033edd5e1ce4eeb3a6a72 (patch)
tree33a1f3dc66d3e0770ed02a69fab5df8b4572f1b1
parent5cce75bdd6a154a7bee733bcce8f7fe1baf40adf (diff)
add s390 support to kexec-tools-1.101
--===============39718348520004598== Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi Milton, first of all thanks for looking at the patches. > 1) When patching the command line, you read the string from the > optarg. While you clear the area in the kernel looking at > COMMAND_LINE_SIZE, you do not limit the length that you copy into > the kernel by this amount. This would seem like a buffer-overflow > situation that could easily be trapped. Yes, you're right. The kernel image could be damaged. Fixed. > 2) I noticed your ramdisk code is quite similar in function to > slurp_file in kexec/kexec.c. I realize this is probably a new > function. Fixed as well :) > 3) Your elf-rel loading seem to not be implemented, but your probe > returns 0 just like the image loader. I think you're talking about the function machine_verify_elf_rel(). Unlike the probe functions this one should return 0 on error, shouldn't it? > 4) You seem to have several addresses hard-coded into the kexec-s390.h > file. This would seem to limit the image you are loading, including > any panic crash kernel options using the current scheme. I don't > know your abi to know what other issues you might have with a more > generic kexec to image interface. (It appears you setup your image > to load as if it were from 0 but skipping IMAGE_READ_OFFSET bytes. The hard coded addresses are part of the kernel abi. Nothing needs to be changed here. Skipping the first 64k of the kernel image is ok too, since you usually would only find a loader routine there which would load the rest of the kernel image into ram and then start it. If you are really interested you might have a look at arch/s390/kernel/head.S in the kernel sources :) Also we do not plan to use the kdump feature. It doesn't make too much sense for the s390 architecture since we have already other mechanisms which allow to reliably dump complete memory and register contents at any given state of the system. The patch below should be better (still against 1.101). Guess I will come up with an improved kernel patch too. Thanks, Heiko diffstat: configure | 5 - kexec/arch/s390/Makefile | 6 + kexec/arch/s390/include/arch/options.h | 11 ++ kexec/arch/s390/kexec-elf-rel-s390.c | 23 +++++ kexec/arch/s390/kexec-image.c | 137 +++++++++++++++++++++++++++++++++ kexec/arch/s390/kexec-s390.c | 104 +++++++++++++++++++++++++ kexec/arch/s390/kexec-s390.h | 25 ++++++ kexec/kexec-syscall.h | 7 + purgatory/arch/s390/Makefile | 7 + purgatory/arch/s390/include/limits.h | 54 +++++++++++++ purgatory/arch/s390/include/stdint.h | 24 +++++ 11 files changed, 402 insertions(+), 1 deletion(-)
-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