summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kexec/arch/ppc/Makefile1
-rw-r--r--kexec/arch/ppc/include/arch/options.h3
-rw-r--r--kexec/arch/ppc/kexec-elf-ppc.c44
-rw-r--r--kexec/arch/ppc/kexec-ppc.c11
-rw-r--r--kexec/arch/ppc/kexec-ppc.h2
-rw-r--r--kexec/arch/ppc/kexec-uImage-ppc.c68
6 files changed, 121 insertions, 8 deletions
diff --git a/kexec/arch/ppc/Makefile b/kexec/arch/ppc/Makefile
index d4f04ec..3dba7cf 100644
--- a/kexec/arch/ppc/Makefile
+++ b/kexec/arch/ppc/Makefile
@@ -17,6 +17,7 @@ ppc_KEXEC_SRCS += kexec/kexec-uImage.c
libfdt_SRCS = kexec/arch/ppc/libfdt-wrapper.c
libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/arch/ppc/libfdt/%)
+ppc_ARCH_REUSE_INITRD =
CPPFLAGS+=-I$(srcdir)/kexec/arch/$(ARCH)/libfdt
diff --git a/kexec/arch/ppc/include/arch/options.h b/kexec/arch/ppc/include/arch/options.h
index f646ccc..0c00ea7 100644
--- a/kexec/arch/ppc/include/arch/options.h
+++ b/kexec/arch/ppc/include/arch/options.h
@@ -8,6 +8,7 @@
#define OPT_GAMECUBE (OPT_ARCH_MAX+1)
#define OPT_DTB (OPT_ARCH_MAX+2)
#define OPT_NODES (OPT_ARCH_MAX+3)
+#define OPT_RAMDISK (OPT_ARCH_MAX+4)
/* Options relevant to the architecture (excluding loader-specific ones),
* in this case none:
@@ -35,6 +36,8 @@
KEXEC_ARCH_OPTIONS \
{"command-line", 1, 0, OPT_APPEND},\
{"append", 1, 0, OPT_APPEND},\
+ {"ramdisk", 1, 0, OPT_APPEND},\
+ {"initrd", 1, 0, OPT_APPEND},\
{"gamecube", 1, 0, OPT_GAMECUBE},\
{"dtb", 1, 0, OPT_DTB},\
{"reuse-node", 1, 0, OPT_NODES},\
diff --git a/kexec/arch/ppc/kexec-elf-ppc.c b/kexec/arch/ppc/kexec-elf-ppc.c
index f17a5aa..daf7a34 100644
--- a/kexec/arch/ppc/kexec-elf-ppc.c
+++ b/kexec/arch/ppc/kexec-elf-ppc.c
@@ -127,6 +127,8 @@ static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{"command-line", 1, 0, OPT_APPEND},
{"append", 1, 0, OPT_APPEND},
+ {"ramdisk", 1, 0, OPT_RAMDISK},
+ {"initrd", 1, 0, OPT_RAMDISK},
{"gamecube", 1, 0, OPT_GAMECUBE},
{"dtb", 1, 0, OPT_DTB},
{"reuse-node", 1, 0, OPT_NODES},
@@ -139,10 +141,12 @@ void elf_ppc_usage(void)
printf(
" --command-line=STRING Set the kernel command line to STRING.\n"
" --append=STRING Set the kernel command line to STRING.\n"
+ " --ramdisk=<filename> Initial RAM disk.\n"
+ " --initrd=<filename> same as --ramdisk\n"
" --gamecube=1|0 Enable/disable support for ELFs with changed\n"
" addresses suitable for the GameCube.\n"
- " --dtb=<filename> Specify device tree blob file.\n"
- " --reuse-node=node Specify nodes which should be taken from /proc/device-tree.\n"
+ " --dtb=<filename> Specify device tree blob file.\n"
+ " --reuse-node=node Specify nodes which should be taken from /proc/device-tree.\n"
" Can be set multiple times.\n"
);
}
@@ -177,7 +181,7 @@ int elf_ppc_load(int argc, char **argv, const char *buf, off_t len,
unsigned long my_kernel, my_dt_offset;
unsigned long my_stack, my_backup_start;
unsigned int slave_code[256 / sizeof(unsigned int)], master_entry;
- unsigned char *seg_buf = NULL;
+ char *seg_buf = NULL;
off_t seg_size = 0;
int target_is_gamecube = 0;
unsigned int addr;
@@ -193,6 +197,8 @@ int elf_ppc_load(int argc, char **argv, const char *buf, off_t len,
dtb = NULL;
max_addr = LONG_MAX;
hole_addr = 0;
+ kernel_addr = 0;
+ ramdisk = 0;
while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
switch (opt) {
@@ -207,6 +213,9 @@ int elf_ppc_load(int argc, char **argv, const char *buf, off_t len,
case OPT_APPEND:
command_line = optarg;
break;
+ case OPT_RAMDISK:
+ ramdisk = optarg;
+ break;
case OPT_GAMECUBE:
target_is_gamecube = atoi(optarg);
break;
@@ -234,6 +243,9 @@ int elf_ppc_load(int argc, char **argv, const char *buf, off_t len,
command_line_len = strlen(command_line) + 1;
}
+ if (ramdisk && reuse_initrd)
+ die("Can't specify --ramdisk or --initrd with --reuseinitrd\n");
+
fixup_nodes[cur_fixup] = NULL;
/* Need to append some command line parameters internally in case of
@@ -339,6 +351,32 @@ int elf_ppc_load(int argc, char **argv, const char *buf, off_t len,
elf_rel_build_load(info, &info->rhdr, (const char *)purgatory,
purgatory_size, 0, elf_max_addr(&ehdr), 1, 0);
+ if (ramdisk)
+ {
+ seg_buf = slurp_file(ramdisk, &seg_size);
+ hole_addr = add_buffer(info, seg_buf, seg_size, seg_size,
+ 0, 0, max_addr, 1);
+ ramdisk_base = hole_addr;
+ ramdisk_size = seg_size;
+ }
+ if (reuse_initrd)
+ {
+ ramdisk_base = initrd_base;
+ ramdisk_size = initrd_size;
+ }
+
+ if (info->kexec_flags & KEXEC_ON_CRASH && ramdisk_base != 0) {
+ if ( (ramdisk_base < crash_base) ||
+ (ramdisk_base > crash_base + crash_size) )
+ {
+ printf("WARNING: ramdisk is above crashkernel region!\n");
+ }
+ else if (ramdisk_base + initrd_size > crash_base + crash_size)
+ {
+ printf("WARNING: ramdisk overflows crashkernel region!\n");
+ }
+ }
+
if (dtb) {
char *blob_buf;
off_t blob_size = 0;
diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
index e1547a8..c36c7b3 100644
--- a/kexec/arch/ppc/kexec-ppc.c
+++ b/kexec/arch/ppc/kexec-ppc.c
@@ -27,10 +27,17 @@
#include "config.h"
uint64_t rmo_top;
-unsigned long long crash_base, crash_size;
-unsigned long long initrd_base, initrd_size;
+unsigned long long crash_base = 0, crash_size = 0;
+unsigned long long initrd_base = 0, initrd_size = 0;
+unsigned long long ramdisk_base = 0, ramdisk_size = 0;
unsigned int rtas_base, rtas_size;
int max_memory_ranges;
+const char *ramdisk;
+
+void arch_reuse_initrd(void)
+{
+ reuse_initrd = 1;
+}
#ifdef WITH_GAMECUBE
#define MAX_MEMORY_RANGES 64
diff --git a/kexec/arch/ppc/kexec-ppc.h b/kexec/arch/ppc/kexec-ppc.h
index fc0471f..d25138a 100644
--- a/kexec/arch/ppc/kexec-ppc.h
+++ b/kexec/arch/ppc/kexec-ppc.h
@@ -65,7 +65,9 @@ typedef struct mem_rgns {
extern mem_rgns_t usablemem_rgns;
extern int max_memory_ranges;
extern unsigned long long initrd_base, initrd_size;
+extern unsigned long long ramdisk_base, ramdisk_size;
extern unsigned char reuse_initrd;
+extern const char *ramdisk;
#define COMMAND_LINE_SIZE 512 /* from kernel */
/*fs2dt*/
void reserve(unsigned long long where, unsigned long long length);
diff --git a/kexec/arch/ppc/kexec-uImage-ppc.c b/kexec/arch/ppc/kexec-uImage-ppc.c
index 21a7c1b..310d6c3 100644
--- a/kexec/arch/ppc/kexec-uImage-ppc.c
+++ b/kexec/arch/ppc/kexec-uImage-ppc.c
@@ -14,12 +14,16 @@
#include "kexec-ppc.h"
#include "fixup_dtb.h"
#include <kexec-uImage.h>
+#include "crashdump-powerpc.h"
+#include <limits.h>
/* See options.h -- add any more there, too. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{"command-line", 1, 0, OPT_APPEND},
{"append", 1, 0, OPT_APPEND},
+ {"ramdisk", 1, 0, OPT_RAMDISK},
+ {"initrd", 1, 0, OPT_RAMDISK},
{"dtb", 1, 0, OPT_DTB},
{"reuse-node", 1, 0, OPT_NODES},
{0, 0, 0, 0},
@@ -31,8 +35,10 @@ void uImage_ppc_usage(void)
printf(
" --command-line=STRING Set the kernel command line to STRING.\n"
" --append=STRING Set the kernel command line to STRING.\n"
- " --dtb=<filename> Specify device tree blob file.\n"
- " --reuse-node=node Specify nodes which should be taken from /proc/device-tree.\n"
+ " --ramdisk=<filename> Initial RAM disk.\n"
+ " --initrd=<filename> same as --ramdisk\n"
+ " --dtb=<filename> Specify device tree blob file.\n"
+ " --reuse-node=node Specify nodes which should be taken from /proc/device-tree.\n"
" Can be set multiple times.\n"
);
}
@@ -46,7 +52,7 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
off_t len, struct kexec_info *info, unsigned int load_addr,
unsigned int ep)
{
- char *command_line, *cmdline_buf;
+ char *command_line, *cmdline_buf, *crash_cmdline;
int command_line_len;
char *dtb;
unsigned int addr;
@@ -56,10 +62,15 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
int cur_fixup = 0;
int opt;
int ret;
+ char *seg_buf = NULL;
+ off_t seg_size = 0;
+ unsigned long long hole_addr;
+ unsigned long max_addr;
cmdline_buf = NULL;
command_line = NULL;
dtb = NULL;
+ max_addr = LONG_MAX;
while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
switch (opt) {
@@ -75,6 +86,10 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
command_line = optarg;
break;
+ case OPT_RAMDISK:
+ ramdisk = optarg;
+ break;
+
case OPT_DTB:
dtb = optarg;
break;
@@ -90,6 +105,9 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
}
}
+ if (ramdisk && reuse_initrd)
+ die("Can't specify --ramdisk or --initrd with --reuseinitrd\n");
+
command_line_len = 0;
if (command_line) {
command_line_len = strlen(command_line) + 1;
@@ -114,10 +132,54 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
}
add_segment(info, buf, len, load_addr, len + (1 * 1024 * 1024));
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ crash_cmdline = xmalloc(COMMAND_LINE_SIZE);
+ memset((void *)crash_cmdline, 0, COMMAND_LINE_SIZE);
+ } else
+ crash_cmdline = NULL;
+
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ ret = load_crashdump_segments(info, crash_cmdline,
+ max_addr, 0);
+ if (ret < 0) {
+ return -1;
+ }
+ }
+
cmdline_buf = xmalloc(COMMAND_LINE_SIZE);
memset((void *)cmdline_buf, 0, COMMAND_LINE_SIZE);
if (command_line)
strncat(cmdline_buf, command_line, command_line_len);
+ if (crash_cmdline)
+ strncat(cmdline_buf, crash_cmdline,
+ sizeof(crash_cmdline) -
+ strlen(crash_cmdline) - 1);
+
+ if (ramdisk)
+ {
+ seg_buf = slurp_file(ramdisk, &seg_size);
+ hole_addr = add_buffer(info, seg_buf, seg_size, seg_size,
+ 0, 0, max_addr, 1);
+ ramdisk_base = hole_addr;
+ ramdisk_size = seg_size;
+ }
+ if (reuse_initrd)
+ {
+ ramdisk_base = initrd_base;
+ ramdisk_size = initrd_size;
+ }
+
+ if (info->kexec_flags & KEXEC_ON_CRASH && ramdisk_base != 0) {
+ if ( (ramdisk_base < crash_base) ||
+ (ramdisk_base > crash_base + crash_size) )
+ {
+ printf("WARNING: ramdisk is above crashkernel region!\n");
+ }
+ else if (ramdisk_base + ramdisk_size > crash_base + crash_size)
+ {
+ printf("WARNING: ramdisk overflows crashkernel region!\n");
+ }
+ }
if (dtb) {
char *blob_buf;