arm64: Use common of_kexec_alloc_and_setup_fdt()
authorRob Herring <robh@kernel.org>
Sun, 21 Feb 2021 17:49:23 +0000 (09:49 -0800)
committerRob Herring <robh@kernel.org>
Mon, 8 Mar 2021 19:06:29 +0000 (12:06 -0700)
The code for setting up the /chosen node in the device tree
and updating the memory reservation for the next kernel has been
moved to of_kexec_alloc_and_setup_fdt() defined in "drivers/of/kexec.c".

Use the common of_kexec_alloc_and_setup_fdt() to setup the device tree
and update the memory reservation for kexec for arm64.

Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
Reviewed-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20210221174930.27324-7-nramas@linux.microsoft.com
arch/arm64/kernel/machine_kexec_file.c

index 471b52f..63634b4 100644 (file)
 #include <linux/kexec.h>
 #include <linux/libfdt.h>
 #include <linux/memblock.h>
+#include <linux/of.h>
 #include <linux/of_fdt.h>
-#include <linux/random.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/vmalloc.h>
-#include <asm/byteorder.h>
-
-/* relevant device tree properties */
-#define FDT_PROP_KEXEC_ELFHDR  "linux,elfcorehdr"
-#define FDT_PROP_MEM_RANGE     "linux,usable-memory-range"
-#define FDT_PROP_INITRD_START  "linux,initrd-start"
-#define FDT_PROP_INITRD_END    "linux,initrd-end"
-#define FDT_PROP_BOOTARGS      "bootargs"
-#define FDT_PROP_KASLR_SEED    "kaslr-seed"
-#define FDT_PROP_RNG_SEED      "rng-seed"
-#define RNG_SEED_SIZE          128
 
 const struct kexec_file_ops * const kexec_file_loaders[] = {
        &kexec_image_ops,
@@ -40,7 +29,7 @@ const struct kexec_file_ops * const kexec_file_loaders[] = {
 
 int arch_kimage_file_post_load_cleanup(struct kimage *image)
 {
-       vfree(image->arch.dtb);
+       kvfree(image->arch.dtb);
        image->arch.dtb = NULL;
 
        vfree(image->elf_headers);
@@ -50,164 +39,6 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
        return kexec_image_post_load_cleanup_default(image);
 }
 
-static int setup_dtb(struct kimage *image,
-                    unsigned long initrd_load_addr, unsigned long initrd_len,
-                    char *cmdline, void *dtb)
-{
-       int off, ret;
-
-       ret = fdt_path_offset(dtb, "/chosen");
-       if (ret < 0)
-               goto out;
-
-       off = ret;
-
-       ret = fdt_delprop(dtb, off, FDT_PROP_KEXEC_ELFHDR);
-       if (ret && ret != -FDT_ERR_NOTFOUND)
-               goto out;
-       ret = fdt_delprop(dtb, off, FDT_PROP_MEM_RANGE);
-       if (ret && ret != -FDT_ERR_NOTFOUND)
-               goto out;
-
-       if (image->type == KEXEC_TYPE_CRASH) {
-               /* add linux,elfcorehdr */
-               ret = fdt_appendprop_addrrange(dtb, 0, off,
-                               FDT_PROP_KEXEC_ELFHDR,
-                               image->elf_load_addr,
-                               image->elf_headers_sz);
-               if (ret)
-                       return (ret == -FDT_ERR_NOSPACE ? -ENOMEM : -EINVAL);
-
-               /* add linux,usable-memory-range */
-               ret = fdt_appendprop_addrrange(dtb, 0, off,
-                               FDT_PROP_MEM_RANGE,
-                               crashk_res.start,
-                               crashk_res.end - crashk_res.start + 1);
-               if (ret)
-                       return (ret == -FDT_ERR_NOSPACE ? -ENOMEM : -EINVAL);
-       }
-
-       /* add bootargs */
-       if (cmdline) {
-               ret = fdt_setprop_string(dtb, off, FDT_PROP_BOOTARGS, cmdline);
-               if (ret)
-                       goto out;
-       } else {
-               ret = fdt_delprop(dtb, off, FDT_PROP_BOOTARGS);
-               if (ret && (ret != -FDT_ERR_NOTFOUND))
-                       goto out;
-       }
-
-       /* add initrd-* */
-       if (initrd_load_addr) {
-               ret = fdt_setprop_u64(dtb, off, FDT_PROP_INITRD_START,
-                                     initrd_load_addr);
-               if (ret)
-                       goto out;
-
-               ret = fdt_setprop_u64(dtb, off, FDT_PROP_INITRD_END,
-                                     initrd_load_addr + initrd_len);
-               if (ret)
-                       goto out;
-       } else {
-               ret = fdt_delprop(dtb, off, FDT_PROP_INITRD_START);
-               if (ret && (ret != -FDT_ERR_NOTFOUND))
-                       goto out;
-
-               ret = fdt_delprop(dtb, off, FDT_PROP_INITRD_END);
-               if (ret && (ret != -FDT_ERR_NOTFOUND))
-                       goto out;
-       }
-
-       /* add kaslr-seed */
-       ret = fdt_delprop(dtb, off, FDT_PROP_KASLR_SEED);
-       if (ret == -FDT_ERR_NOTFOUND)
-               ret = 0;
-       else if (ret)
-               goto out;
-
-       if (rng_is_initialized()) {
-               u64 seed = get_random_u64();
-               ret = fdt_setprop_u64(dtb, off, FDT_PROP_KASLR_SEED, seed);
-               if (ret)
-                       goto out;
-       } else {
-               pr_notice("RNG is not initialised: omitting \"%s\" property\n",
-                               FDT_PROP_KASLR_SEED);
-       }
-
-       /* add rng-seed */
-       if (rng_is_initialized()) {
-               void *rng_seed;
-               ret = fdt_setprop_placeholder(dtb, off, FDT_PROP_RNG_SEED,
-                               RNG_SEED_SIZE, &rng_seed);
-               if (ret)
-                       goto out;
-               get_random_bytes(rng_seed, RNG_SEED_SIZE);
-       } else {
-               pr_notice("RNG is not initialised: omitting \"%s\" property\n",
-                               FDT_PROP_RNG_SEED);
-       }
-
-out:
-       if (ret)
-               return (ret == -FDT_ERR_NOSPACE) ? -ENOMEM : -EINVAL;
-
-       return 0;
-}
-
-/*
- * More space needed so that we can add initrd, bootargs, kaslr-seed,
- * rng-seed, userable-memory-range and elfcorehdr.
- */
-#define DTB_EXTRA_SPACE 0x1000
-
-static int create_dtb(struct kimage *image,
-                     unsigned long initrd_load_addr, unsigned long initrd_len,
-                     char *cmdline, void **dtb)
-{
-       void *buf;
-       size_t buf_size;
-       size_t cmdline_len;
-       int ret;
-
-       cmdline_len = cmdline ? strlen(cmdline) : 0;
-       buf_size = fdt_totalsize(initial_boot_params)
-                       + cmdline_len + DTB_EXTRA_SPACE;
-
-       for (;;) {
-               buf = vmalloc(buf_size);
-               if (!buf)
-                       return -ENOMEM;
-
-               /* duplicate a device tree blob */
-               ret = fdt_open_into(initial_boot_params, buf, buf_size);
-               if (ret) {
-                       vfree(buf);
-                       return -EINVAL;
-               }
-
-               ret = setup_dtb(image, initrd_load_addr, initrd_len,
-                               cmdline, buf);
-               if (ret) {
-                       vfree(buf);
-                       if (ret == -ENOMEM) {
-                               /* unlikely, but just in case */
-                               buf_size += DTB_EXTRA_SPACE;
-                               continue;
-                       } else {
-                               return ret;
-                       }
-               }
-
-               /* trim it */
-               fdt_pack(buf);
-               *dtb = buf;
-
-               return 0;
-       }
-}
-
 static int prepare_elf_headers(void **addr, unsigned long *sz)
 {
        struct crash_mem *cmem;
@@ -314,12 +145,15 @@ int load_other_segments(struct kimage *image,
        }
 
        /* load dtb */
-       ret = create_dtb(image, initrd_load_addr, initrd_len, cmdline, &dtb);
-       if (ret) {
+       dtb = of_kexec_alloc_and_setup_fdt(image, initrd_load_addr,
+                                          initrd_len, cmdline, 0);
+       if (!dtb) {
                pr_err("Preparing for new dtb failed\n");
                goto out_err;
        }
 
+       /* trim it */
+       fdt_pack(dtb);
        dtb_len = fdt_totalsize(dtb);
        kbuf.buffer = dtb;
        kbuf.bufsz = dtb_len;
@@ -343,6 +177,6 @@ int load_other_segments(struct kimage *image,
 
 out_err:
        image->nr_segments = orig_segments;
-       vfree(dtb);
+       kvfree(dtb);
        return ret;
 }