summaryrefslogtreecommitdiff
path: root/kexec/arch/s390/kexec-image.c
diff options
context:
space:
mode:
Diffstat (limited to 'kexec/arch/s390/kexec-image.c')
-rw-r--r--kexec/arch/s390/kexec-image.c137
1 files changed, 137 insertions, 0 deletions
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"
+ );
+}