summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-04-28 15:50:24 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2021-04-28 15:50:24 -0700
commit0080665fbd0e6a771aee366bb2aa208626e43def (patch)
tree26694bbbf64ad79186da20f7c1b39c7eec851595 /arch/arm64/kernel
parent5a69e9bce9984806029926f405b4517878e703e2 (diff)
parent031cc263c037a95e5d1249cbd3d55b77021f1eb8 (diff)
Merge tag 'devicetree-for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull devicetree updates from Rob Herring: - Refactor powerpc and arm64 kexec DT handling to common code. This enables IMA on arm64. - Add kbuild support for applying DT overlays at build time. The first user are the DT unittests. - Fix kerneldoc formatting and W=1 warnings in drivers/of/ - Fix handling 64-bit flag on PCI resources - Bump dtschema version required to v2021.2.1 - Enable undocumented compatible checks for dtbs_check. This allows tracking of missing binding schemas. - DT docs improvements. Regroup the DT docs and add the example schema and DT kernel ABI docs to the doc build. - Convert Broadcom Bluetooth and video-mux bindings to schema - Add QCom sm8250 Venus video codec binding schema - Add vendor prefixes for AESOP, YIC System Co., Ltd, and Siliconfile Technologies Inc. - Cleanup of DT schema type references on common properties and standard unit properties * tag 'devicetree-for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (64 commits) powerpc: If kexec_build_elf_info() fails return immediately from elf64_load() powerpc: Free fdt on error in elf64_load() of: overlay: Fix kerneldoc warning in of_overlay_remove() of: linux/of.h: fix kernel-doc warnings of/pci: Add IORESOURCE_MEM_64 to resource flags for 64-bit memory addresses dt-bindings: bcm4329-fmac: add optional brcm,ccode-map docs: dt: update writing-schema.rst references dt-bindings: media: venus: Add sm8250 dt schema of: base: Fix spelling issue with function param 'prop' docs: dt: Add DT API documentation of: Add missing 'Return' section in kerneldoc comments of: Fix kerneldoc output formatting docs: dt: Group DT docs into relevant sub-sections docs: dt: Make 'Devicetree' wording more consistent docs: dt: writing-schema: Include the example schema in the doc build docs: dt: writing-schema: Remove spurious indentation dt-bindings: Fix reference in submitting-patches.rst to the DT ABI doc dt-bindings: ddr: Add optional manufacturer and revision ID to LPDDR3 dt-bindings: media: video-interfaces: Drop the example devicetree: bindings: clock: Minor typo fix in the file armada3700-tbg-clock.txt ...
Diffstat (limited to 'arch/arm64/kernel')
-rw-r--r--arch/arm64/kernel/machine_kexec_file.c196
1 files changed, 15 insertions, 181 deletions
diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
index 0cde47a63beb..63634b4d72c1 100644
--- a/arch/arm64/kernel/machine_kexec_file.c
+++ b/arch/arm64/kernel/machine_kexec_file.c
@@ -15,23 +15,12 @@
#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,174 +29,16 @@ 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->arch.elf_headers);
- image->arch.elf_headers = NULL;
- image->arch.elf_headers_sz = 0;
+ vfree(image->elf_headers);
+ image->elf_headers = NULL;
+ image->elf_headers_sz = 0;
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->arch.elf_headers_mem,
- image->arch.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;
@@ -284,12 +115,12 @@ int load_other_segments(struct kimage *image,
vfree(headers);
goto out_err;
}
- image->arch.elf_headers = headers;
- image->arch.elf_headers_mem = kbuf.mem;
- image->arch.elf_headers_sz = headers_sz;
+ image->elf_headers = headers;
+ image->elf_load_addr = kbuf.mem;
+ image->elf_headers_sz = headers_sz;
pr_debug("Loaded elf core header at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
- image->arch.elf_headers_mem, kbuf.bufsz, kbuf.memsz);
+ image->elf_load_addr, kbuf.bufsz, kbuf.memsz);
}
/* load initrd */
@@ -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;
}