Message ID | 20250317083402.412310-4-sughosh.ganu@linaro.org |
---|---|
State | New |
Headers | show |
Series | Add pmem node for preserving distro ISO's | expand |
On Mon, 17 Mar 2025 at 10:34, Sughosh Ganu <sughosh.ganu@linaro.org> wrote: > > From: Masahisa Kojima <kojima.masahisa@socionext.com> > > One of the problems an OS may face, when running in EFI, is that > a mounted ISO, after calling ExitBootServices goes away, if that ISO > is resident in RAM memory as a ramdisk. > > ACPI has NFIT and NVDIMM support to provide ramdisks to the OS, but we > don't have anything in place for DTs. Linux and device trees have support > for persistent memory devices. So add a function that can inject a pmem > node in a DT, so we can pass information on the ramdisk the OS. > > Signed-off-by: Masahisa Kojima <kojima.masahisa@socionext.com> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org> Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> > --- > Changes since V8: > * Re-word the commit message to indicate that the ramdisk information > is being passed to the OS through pmem node > * Change the type of addr and size parameters to the > fdt_fixup_pmem_region() as u64 > * Rename the first parameter of fdt_fixup_pmem_region() as fdt instead > of blob > * Modify the format specifier of snprintf() call in > fdt_fixup_pmem_region() accordingly > * Remove pmem_start and pmem_size array variables in > fdt_fixup_pmem_region() > * s/pmem_node/node_name/g > * Do not initialise node_name variable > > boot/fdt_support.c | 39 ++++++++++++++++++++++++++++++++++++++- > include/fdt_support.h | 14 ++++++++++++++ > 2 files changed, 52 insertions(+), 1 deletion(-) > > diff --git a/boot/fdt_support.c b/boot/fdt_support.c > index 49efeec3681..92f2f534ee0 100644 > --- a/boot/fdt_support.c > +++ b/boot/fdt_support.c > @@ -18,6 +18,7 @@ > #include <dm/ofnode.h> > #include <linux/ctype.h> > #include <linux/types.h> > +#include <linux/sizes.h> > #include <asm/global_data.h> > #include <asm/unaligned.h> > #include <linux/libfdt.h> > @@ -464,7 +465,6 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat, > do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create); > } > > -#ifdef CONFIG_ARCH_FIXUP_FDT_MEMORY > /* > * fdt_pack_reg - pack address and size array into the "reg"-suitable stream > */ > @@ -493,6 +493,7 @@ static int fdt_pack_reg(const void *fdt, void *buf, u64 *address, u64 *size, > return p - (char *)buf; > } > > +#ifdef CONFIG_ARCH_FIXUP_FDT_MEMORY > #if CONFIG_NR_DRAM_BANKS > 4 > #define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS > #else > @@ -2222,3 +2223,39 @@ int fdt_valid(struct fdt_header **blobp) > } > return 1; > } > + > +int fdt_fixup_pmem_region(void *fdt, u64 pmem_start, u64 pmem_size) > +{ > + char node_name[32]; > + int nodeoffset, len; > + int err; > + u8 tmp[4 * 16]; /* Up to 64-bit address + 64-bit size */ > + > + if (!IS_ALIGNED(pmem_start, SZ_2M) || > + !IS_ALIGNED(pmem_start + pmem_size, SZ_2M)) { > + printf("Start and end address must be 2MiB aligned\n"); > + return -1; > + } > + > + snprintf(node_name, sizeof(node_name), "pmem@%llx", pmem_start); > + nodeoffset = fdt_find_or_add_subnode(fdt, 0, node_name); > + if (nodeoffset < 0) > + return nodeoffset; > + > + err = fdt_setprop_string(fdt, nodeoffset, "compatible", "pmem-region"); > + if (err) > + return err; > + err = fdt_setprop_empty(fdt, nodeoffset, "volatile"); > + if (err) > + return err; > + > + len = fdt_pack_reg(fdt, tmp, &pmem_start, &pmem_size, 1); > + err = fdt_setprop(fdt, nodeoffset, "reg", tmp, len); > + if (err < 0) { > + printf("WARNING: could not set pmem %s %s.\n", "reg", > + fdt_strerror(err)); > + return err; > + } > + > + return 0; > +} > diff --git a/include/fdt_support.h b/include/fdt_support.h > index f0ad2e6b365..049190cf3d7 100644 > --- a/include/fdt_support.h > +++ b/include/fdt_support.h > @@ -471,6 +471,20 @@ int fdt_valid(struct fdt_header **blobp); > */ > int fdt_get_cells_len(const void *blob, char *nr_cells_name); > > +/** > + * fdt_fixup_pmem_region() - add a pmem node on the device tree > + * > + * This functions adds/updates a pmem node to the device tree. > + * Usually used with EFI installers to preserve installer > + * images > + * > + * @fdt: device tree provided by caller > + * @addr: start address of the pmem node > + * @size: size of the memory of the pmem node > + * Return: 0 on success or < 0 on failure > + */ > +int fdt_fixup_pmem_region(void *fdt, u64 pmem_start, u64 pmem_size); > + > #endif /* !USE_HOSTCC */ > > #ifdef USE_HOSTCC > -- > 2.34.1 >
diff --git a/boot/fdt_support.c b/boot/fdt_support.c index 49efeec3681..92f2f534ee0 100644 --- a/boot/fdt_support.c +++ b/boot/fdt_support.c @@ -18,6 +18,7 @@ #include <dm/ofnode.h> #include <linux/ctype.h> #include <linux/types.h> +#include <linux/sizes.h> #include <asm/global_data.h> #include <asm/unaligned.h> #include <linux/libfdt.h> @@ -464,7 +465,6 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat, do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create); } -#ifdef CONFIG_ARCH_FIXUP_FDT_MEMORY /* * fdt_pack_reg - pack address and size array into the "reg"-suitable stream */ @@ -493,6 +493,7 @@ static int fdt_pack_reg(const void *fdt, void *buf, u64 *address, u64 *size, return p - (char *)buf; } +#ifdef CONFIG_ARCH_FIXUP_FDT_MEMORY #if CONFIG_NR_DRAM_BANKS > 4 #define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS #else @@ -2222,3 +2223,39 @@ int fdt_valid(struct fdt_header **blobp) } return 1; } + +int fdt_fixup_pmem_region(void *fdt, u64 pmem_start, u64 pmem_size) +{ + char node_name[32]; + int nodeoffset, len; + int err; + u8 tmp[4 * 16]; /* Up to 64-bit address + 64-bit size */ + + if (!IS_ALIGNED(pmem_start, SZ_2M) || + !IS_ALIGNED(pmem_start + pmem_size, SZ_2M)) { + printf("Start and end address must be 2MiB aligned\n"); + return -1; + } + + snprintf(node_name, sizeof(node_name), "pmem@%llx", pmem_start); + nodeoffset = fdt_find_or_add_subnode(fdt, 0, node_name); + if (nodeoffset < 0) + return nodeoffset; + + err = fdt_setprop_string(fdt, nodeoffset, "compatible", "pmem-region"); + if (err) + return err; + err = fdt_setprop_empty(fdt, nodeoffset, "volatile"); + if (err) + return err; + + len = fdt_pack_reg(fdt, tmp, &pmem_start, &pmem_size, 1); + err = fdt_setprop(fdt, nodeoffset, "reg", tmp, len); + if (err < 0) { + printf("WARNING: could not set pmem %s %s.\n", "reg", + fdt_strerror(err)); + return err; + } + + return 0; +} diff --git a/include/fdt_support.h b/include/fdt_support.h index f0ad2e6b365..049190cf3d7 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -471,6 +471,20 @@ int fdt_valid(struct fdt_header **blobp); */ int fdt_get_cells_len(const void *blob, char *nr_cells_name); +/** + * fdt_fixup_pmem_region() - add a pmem node on the device tree + * + * This functions adds/updates a pmem node to the device tree. + * Usually used with EFI installers to preserve installer + * images + * + * @fdt: device tree provided by caller + * @addr: start address of the pmem node + * @size: size of the memory of the pmem node + * Return: 0 on success or < 0 on failure + */ +int fdt_fixup_pmem_region(void *fdt, u64 pmem_start, u64 pmem_size); + #endif /* !USE_HOSTCC */ #ifdef USE_HOSTCC