Message ID | 20241203163605.1482152-2-sughosh.ganu@linaro.org |
---|---|
State | New |
Headers | show |
Series | Add pmem node for preserving distro ISO's | expand |
Hi Sughosh, On Tue, 3 Dec 2024 at 09:36, Sughosh Ganu <sughosh.ganu@linaro.org> wrote: > > From: Masahisa Kojima <kojima.masahisa@socionext.com> > > One of the problems OS installers face, when running in EFI, is that > the mounted ISO after calling ExitBootServices goes away. For some > distros this is a problem since they rely on finding some core packages > before continuing the installation. Distros have works around this -- > e.g Fedora has a special kernel command line parameter called > inst.stage2 [0]. > > 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 use it when launhing OS installers with EFI. > > [0] > https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/installation_guide/chap-anaconda-boot-options#sect-boot-options-installer > > Signed-off-by: Masahisa Kojima <kojima.masahisa@socionext.com> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org> > --- > Changes since V1: None > > boot/fdt_support.c | 41 +++++++++++++++++++++++++++++++++++++++-- > include/fdt_support.h | 13 +++++++++++++ > 2 files changed, 52 insertions(+), 2 deletions(-) > > diff --git a/boot/fdt_support.c b/boot/fdt_support.c > index 2392027d40b..61f725389b7 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> > @@ -463,7 +464,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 > */ > @@ -491,7 +491,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 > @@ -2221,3 +2221,40 @@ int fdt_valid(struct fdt_header **blobp) > } > return 1; > } > + > +int fdt_fixup_pmem_region(void *blob, ulong addr, u32 size) > +{ > + u64 pmem_start[2] = { 0 }; > + u64 pmem_size[2] = { 0 }; > + char pmem_node[32] = {0}; > + int nodeoffset, len; > + int err; > + u8 tmp[4 * 16]; /* Up to 64-bit address + 64-bit size */ > + > + if (!IS_ALIGNED(addr, SZ_2M) || !IS_ALIGNED(addr + size, SZ_2M)) { > + printf("Start and end address needs at 2MB alignment\n"); > + return -1; > + } > + snprintf(pmem_node, sizeof(pmem_node), "pmem@%lx", addr); > + nodeoffset = fdt_find_or_add_subnode(blob, 0, pmem_node); > + if (nodeoffset < 0) > + return nodeoffset; > + > + err = fdt_setprop_string(blob, nodeoffset, "compatible", "pmem-region"); > + if (err) > + return err; > + err = fdt_setprop_empty(blob, nodeoffset, "volatile"); > + if (err) > + return err; I believe I asked this already, but is it possible to use the ofnode interface, instead of adding more and more code which we need to migrate later? > + pmem_start[0] = addr; > + pmem_size[0] = size; > + len = fdt_pack_reg(blob, tmp, pmem_start, pmem_size, 1); > + err = fdt_setprop(blob, 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 9447a64e060..980feb27d27 100644 > --- a/include/fdt_support.h > +++ b/include/fdt_support.h > @@ -474,4 +474,17 @@ void fdt_fixup_pstore(void *blob); > */ > int fdt_kaslrseed(void *blob, bool overwrite); > > +/** > + * fdt_fixup_pmem_region() - add a pmem node on the device tree > + * > + * This functions injects a pmem node to the device tree. Usually > + * used with EFI installers to preserve installer images > + * > + * @blob: 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 *blob, ulong addr, u32 size); > + > #endif /* ifndef __FDT_SUPPORT_H */ > -- > 2.34.1 > Regards, Simon
On Wed, 4 Dec 2024 at 01:15, Simon Glass <sjg@chromium.org> wrote: > > Hi Sughosh, > > On Tue, 3 Dec 2024 at 09:36, Sughosh Ganu <sughosh.ganu@linaro.org> wrote: > > > > From: Masahisa Kojima <kojima.masahisa@socionext.com> > > > > One of the problems OS installers face, when running in EFI, is that > > the mounted ISO after calling ExitBootServices goes away. For some > > distros this is a problem since they rely on finding some core packages > > before continuing the installation. Distros have works around this -- > > e.g Fedora has a special kernel command line parameter called > > inst.stage2 [0]. > > > > 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 use it when launhing OS installers with EFI. > > > > [0] > > https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/installation_guide/chap-anaconda-boot-options#sect-boot-options-installer > > > > Signed-off-by: Masahisa Kojima <kojima.masahisa@socionext.com> > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org> > > --- > > Changes since V1: None > > > > boot/fdt_support.c | 41 +++++++++++++++++++++++++++++++++++++++-- > > include/fdt_support.h | 13 +++++++++++++ > > 2 files changed, 52 insertions(+), 2 deletions(-) > > > > diff --git a/boot/fdt_support.c b/boot/fdt_support.c > > index 2392027d40b..61f725389b7 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> > > @@ -463,7 +464,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 > > */ > > @@ -491,7 +491,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 > > @@ -2221,3 +2221,40 @@ int fdt_valid(struct fdt_header **blobp) > > } > > return 1; > > } > > + > > +int fdt_fixup_pmem_region(void *blob, ulong addr, u32 size) > > +{ > > + u64 pmem_start[2] = { 0 }; > > + u64 pmem_size[2] = { 0 }; > > + char pmem_node[32] = {0}; > > + int nodeoffset, len; > > + int err; > > + u8 tmp[4 * 16]; /* Up to 64-bit address + 64-bit size */ > > + > > + if (!IS_ALIGNED(addr, SZ_2M) || !IS_ALIGNED(addr + size, SZ_2M)) { > > + printf("Start and end address needs at 2MB alignment\n"); > > + return -1; > > + } > > + snprintf(pmem_node, sizeof(pmem_node), "pmem@%lx", addr); > > + nodeoffset = fdt_find_or_add_subnode(blob, 0, pmem_node); > > + if (nodeoffset < 0) > > + return nodeoffset; > > + > > + err = fdt_setprop_string(blob, nodeoffset, "compatible", "pmem-region"); > > + if (err) > > + return err; > > + err = fdt_setprop_empty(blob, nodeoffset, "volatile"); > > + if (err) > > + return err; > > I believe I asked this already, but is it possible to use the ofnode > interface, instead of adding more and more code which we need to > migrate later? I had spent some time understanding what exactly is happening with the livetree code. I had responded to you earlier [1] as to why I don't think using livetree would be a good fit for this use case. -sughosh [1] - https://lists.denx.de/pipermail/u-boot/2024-December/573556.html > > > + pmem_start[0] = addr; > > + pmem_size[0] = size; > > + len = fdt_pack_reg(blob, tmp, pmem_start, pmem_size, 1); > > + err = fdt_setprop(blob, 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 9447a64e060..980feb27d27 100644 > > --- a/include/fdt_support.h > > +++ b/include/fdt_support.h > > @@ -474,4 +474,17 @@ void fdt_fixup_pstore(void *blob); > > */ > > int fdt_kaslrseed(void *blob, bool overwrite); > > > > +/** > > + * fdt_fixup_pmem_region() - add a pmem node on the device tree > > + * > > + * This functions injects a pmem node to the device tree. Usually > > + * used with EFI installers to preserve installer images > > + * > > + * @blob: 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 *blob, ulong addr, u32 size); > > + > > #endif /* ifndef __FDT_SUPPORT_H */ > > -- > > 2.34.1 > > > > Regards, > Simon
diff --git a/boot/fdt_support.c b/boot/fdt_support.c index 2392027d40b..61f725389b7 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> @@ -463,7 +464,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 */ @@ -491,7 +491,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 @@ -2221,3 +2221,40 @@ int fdt_valid(struct fdt_header **blobp) } return 1; } + +int fdt_fixup_pmem_region(void *blob, ulong addr, u32 size) +{ + u64 pmem_start[2] = { 0 }; + u64 pmem_size[2] = { 0 }; + char pmem_node[32] = {0}; + int nodeoffset, len; + int err; + u8 tmp[4 * 16]; /* Up to 64-bit address + 64-bit size */ + + if (!IS_ALIGNED(addr, SZ_2M) || !IS_ALIGNED(addr + size, SZ_2M)) { + printf("Start and end address needs at 2MB alignment\n"); + return -1; + } + snprintf(pmem_node, sizeof(pmem_node), "pmem@%lx", addr); + nodeoffset = fdt_find_or_add_subnode(blob, 0, pmem_node); + if (nodeoffset < 0) + return nodeoffset; + + err = fdt_setprop_string(blob, nodeoffset, "compatible", "pmem-region"); + if (err) + return err; + err = fdt_setprop_empty(blob, nodeoffset, "volatile"); + if (err) + return err; + pmem_start[0] = addr; + pmem_size[0] = size; + len = fdt_pack_reg(blob, tmp, pmem_start, pmem_size, 1); + err = fdt_setprop(blob, 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 9447a64e060..980feb27d27 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -474,4 +474,17 @@ void fdt_fixup_pstore(void *blob); */ int fdt_kaslrseed(void *blob, bool overwrite); +/** + * fdt_fixup_pmem_region() - add a pmem node on the device tree + * + * This functions injects a pmem node to the device tree. Usually + * used with EFI installers to preserve installer images + * + * @blob: 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 *blob, ulong addr, u32 size); + #endif /* ifndef __FDT_SUPPORT_H */