MIPS: generic/kexec: add support for a DTB passed in a separate buffer
authorMarcin Nowakowski <marcin.nowakowski@imgtec.com>
Wed, 23 Nov 2016 13:43:52 +0000 (14:43 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Tue, 3 Jan 2017 15:34:46 +0000 (16:34 +0100)
Signed-off-by: Marcin Nowakowski <marcin.nowakowski@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/14615/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/generic/Makefile
arch/mips/generic/kexec.c [new file with mode: 0644]

index 7c66494151db52d6d402f3f89e9e5588021e924a..acb9b6d62b16b13b786e5a339daf9efde6a6f72e 100644 (file)
@@ -13,3 +13,4 @@ obj-y += irq.o
 obj-y += proc.o
 
 obj-$(CONFIG_LEGACY_BOARD_SEAD3)       += board-sead3.o
+obj-$(CONFIG_KEXEC)                    += kexec.o
diff --git a/arch/mips/generic/kexec.c b/arch/mips/generic/kexec.c
new file mode 100644 (file)
index 0000000..e9fb735
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ * Author: Marcin Nowakowski <marcin.nowakowski@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kexec.h>
+#include <linux/libfdt.h>
+#include <linux/uaccess.h>
+
+static int generic_kexec_prepare(struct kimage *image)
+{
+       int i;
+
+       for (i = 0; i < image->nr_segments; i++) {
+               struct fdt_header fdt;
+
+               if (image->segment[i].memsz <= sizeof(fdt))
+                       continue;
+
+               if (copy_from_user(&fdt, image->segment[i].buf, sizeof(fdt)))
+                       continue;
+
+               if (fdt_check_header(&fdt))
+                       continue;
+
+               kexec_args[0] = -2;
+               kexec_args[1] = (unsigned long)
+                       phys_to_virt((unsigned long)image->segment[i].mem);
+               break;
+       }
+       return 0;
+}
+
+static int __init register_generic_kexec(void)
+{
+       _machine_kexec_prepare = generic_kexec_prepare;
+       return 0;
+}
+arch_initcall(register_generic_kexec);