@@ -208,12 +208,14 @@ extern int early_init_dt_scan_fw_dump(unsigned long node,
const char *uname, int depth, void *data);
extern int fadump_reserve_mem(void);
extern int setup_fadump(void);
+extern void enforce_fadump_extra_args(char *cmdline);
extern int is_fadump_active(void);
extern int should_fadump_crash(void);
extern void crash_fadump(struct pt_regs *, const char *);
extern void fadump_cleanup(void);
#else /* CONFIG_FA_DUMP */
+static inline void enforce_fadump_extra_args(char *cmdline) { }
static inline int is_fadump_active(void) { return 0; }
static inline int should_fadump_crash(void) { return 0; }
static inline void crash_fadump(struct pt_regs *regs, const char *str) { }
@@ -78,8 +78,10 @@ int __init early_init_dt_scan_fw_dump(unsigned long node,
* dump data waiting for us.
*/
fdm_active = of_get_flat_dt_prop(node, "ibm,kernel-dump", NULL);
- if (fdm_active)
+ if (fdm_active) {
+ pr_info("Firmware-assisted dump is active.\n");
fw_dump.dump_active = 1;
+ }
/* Get the sizes required to store dump data for the firmware provided
* dump sections.
@@ -339,8 +341,11 @@ int __init fadump_reserve_mem(void)
{
unsigned long base, size, memory_boundary;
- if (!fw_dump.fadump_enabled)
+ if (!fw_dump.fadump_enabled) {
+ if (fw_dump.dump_active)
+ pr_warn("Firmware-assisted dump was active but kernel booted with fadump disabled!\n");
return 0;
+ }
if (!fw_dump.fadump_supported) {
printk(KERN_INFO "Firmware-assisted dump is not supported on"
@@ -380,7 +385,6 @@ int __init fadump_reserve_mem(void)
memory_boundary = memblock_end_of_DRAM();
if (fw_dump.dump_active) {
- printk(KERN_INFO "Firmware-assisted dump is active.\n");
/*
* If last boot has crashed then reserve all the memory
* above boot_memory_size so that we don't touch it until
@@ -467,6 +471,93 @@ static int __init early_fadump_reserve_mem(char *p)
}
early_param("fadump_reserve_mem", early_fadump_reserve_mem);
+#define FADUMP_EXTRA_ARGS_PARAM "fadump_extra_args="
+#define FADUMP_EXTRA_ARGS_LEN (strlen(FADUMP_EXTRA_ARGS_PARAM) - 1)
+
+struct param_info {
+ char *cmdline;
+ char *tmp_cmdline;
+ int shortening;
+};
+
+static void __init fadump_update_params(struct param_info *param_info,
+ char *param, char *val,
+ char *currant, char *next)
+{
+ ptrdiff_t param_offset = currant - param_info->tmp_cmdline;
+ size_t vallen = val ? strlen(val) : 0;
+ char *tgt = param_info->cmdline + param_offset
+ - param_info->shortening;
+ int shortening = ((next - 1) - (currant))
+ - (FADUMP_EXTRA_ARGS_LEN + 1 + vallen);
+
+ if (!val)
+ return;
+
+ strncpy(tgt, FADUMP_EXTRA_ARGS_PARAM, FADUMP_EXTRA_ARGS_LEN);
+ tgt += FADUMP_EXTRA_ARGS_LEN;
+ *tgt++ = ' ';
+ strncpy(tgt, val, vallen);
+ tgt += vallen;
+
+ if (shortening) {
+ char *src = tgt + shortening;
+ memmove(tgt, src, strlen(src) + 1);
+ }
+
+ param_info->shortening += shortening;
+}
+
+/*
+ * Reworks command line parameters and splits 'fadump_extra_args=' param
+ * to enforce the parameters passed through it
+ */
+static int __init fadump_rework_cmdline_params(char *param, char *val,
+ char *currant, char *next,
+ const char *unused, void *arg)
+{
+ struct param_info *param_info = (struct param_info *)arg;
+
+ if (strncmp(param, FADUMP_EXTRA_ARGS_PARAM,
+ strlen(FADUMP_EXTRA_ARGS_PARAM) - 1))
+ return 0;
+
+ fadump_update_params(param_info, param, val, currant, next);
+
+ return 0;
+}
+
+/*
+ * Replace every occurrence of 'fadump_extra_args="param1 param2 param3"'
+ * in cmdline with 'fadump_extra_args param1 param2 param3' by stripping
+ * off '=' and quotes, if any. This ensures that the additional parameters
+ * passed with 'fadump_extra_args=' are enforced.
+ */
+void __init enforce_fadump_extra_args(char *cmdline)
+{
+ static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata;
+ static char init_cmdline[COMMAND_LINE_SIZE] __initdata;
+ struct param_info param_info;
+
+ if (strstr(cmdline, FADUMP_EXTRA_ARGS_PARAM) == NULL)
+ return;
+
+ pr_info("Modifying command line to enforce the additional parameters passed through 'fadump_extra_args='");
+
+ param_info.cmdline = cmdline;
+ param_info.tmp_cmdline = tmp_cmdline;
+ param_info.shortening = 0;
+
+ strlcpy(init_cmdline, cmdline, COMMAND_LINE_SIZE);
+
+ strlcpy(tmp_cmdline, cmdline, COMMAND_LINE_SIZE);
+ parse_args("fadump params", tmp_cmdline, NULL, 0, 0, 0,
+ ¶m_info, &fadump_rework_cmdline_params);
+
+ pr_info("Original command line: %s\n", init_cmdline);
+ pr_info("Modified command line: %s\n", cmdline);
+}
+
static int register_fw_dump(struct fadump_mem_struct *fdm)
{
int rc, err;
@@ -693,6 +693,13 @@ void __init early_init_devtree(void *params)
of_scan_flat_dt(early_init_dt_scan_root, NULL);
of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
+ /*
+ * Look for 'fadump_extra_args=' parameter and enfore the additional
+ * parameters passed to it if fadump is active.
+ */
+ if (is_fadump_active())
+ enforce_fadump_extra_args(boot_command_line);
+
parse_early_param();
/* make sure we've parsed cmdline for mem= before this */