Message ID | 20241025111411.165904-2-sughosh.ganu@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | Add pmem node for preserving distro ISO's | expand |
Thanks Sughosh +CC Anton who tested that On Fri, 25 Oct 2024 at 14:14, 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> > --- > 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 2392027d40..61f725389b 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 741e2360c2..63ece0de32 100644 > --- a/include/fdt_support.h > +++ b/include/fdt_support.h > @@ -473,4 +473,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 >
Hi Sughosh, On Fri, 25 Oct 2024 at 13:15, 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> > --- > boot/fdt_support.c | 41 +++++++++++++++++++++++++++++++++++++++-- > include/fdt_support.h | 13 +++++++++++++ > 2 files changed, 52 insertions(+), 2 deletions(-) Can you please use the ofnode interface for this? We are trying not to add more of this kind of fixup, as it means someone will have to port it over later. See EVT_FT_FIXUP Regards, Simon
On Sun, 27 Oct 2024 at 20:30, Simon Glass <sjg@chromium.org> wrote: > > Hi Sughosh, > > On Fri, 25 Oct 2024 at 13:15, 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> > > --- > > boot/fdt_support.c | 41 +++++++++++++++++++++++++++++++++++++++-- > > include/fdt_support.h | 13 +++++++++++++ > > 2 files changed, 52 insertions(+), 2 deletions(-) > > Can you please use the ofnode interface for this? We are trying not to > add more of this kind of fixup, as it means someone will have to port > it over later. > > See EVT_FT_FIXUP Are you suggesting using the EVT_FT_FIXUP interface for adding the pmem node? If so, how does this work on platforms which enable livetree? Looking at the code, I see that the EVT_FT_FIXUP gets called only when the livetree is not active. However, I am not able to find any place where the livetree is getting disabled. We do have a function, oftree_to_fdt() which flattens a livetree, but I don't see it getting called from anywhere except from a 'upl' command. The of_root pointer does get set in initr_of_live(), but apart from dm_test_pre_run(), I do not see where we disable the livetree and set of_root to NULL. So on platforms which do enable livetree, how does this fixup work? What am I missing? -sughosh > > Regards, > Simon
Hi Sughosh, On Mon, 28 Oct 2024 at 12:29, Sughosh Ganu <sughosh.ganu@linaro.org> wrote: > > On Sun, 27 Oct 2024 at 20:30, Simon Glass <sjg@chromium.org> wrote: > > > > Hi Sughosh, > > > > On Fri, 25 Oct 2024 at 13:15, 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> > > > --- > > > boot/fdt_support.c | 41 +++++++++++++++++++++++++++++++++++++++-- > > > include/fdt_support.h | 13 +++++++++++++ > > > 2 files changed, 52 insertions(+), 2 deletions(-) > > > > Can you please use the ofnode interface for this? We are trying not to > > add more of this kind of fixup, as it means someone will have to port > > it over later. > > > > See EVT_FT_FIXUP > > Are you suggesting using the EVT_FT_FIXUP interface for adding the > pmem node? If so, how does this work on platforms which enable > livetree? Looking at the code, I see that the EVT_FT_FIXUP gets called > only when the livetree is not active. However, I am not able to find > any place where the livetree is getting disabled. We do have a > function, oftree_to_fdt() which flattens a livetree, but I don't see > it getting called from anywhere except from a 'upl' command. The > of_root pointer does get set in initr_of_live(), but apart from > dm_test_pre_run(), I do not see where we disable the livetree and set > of_root to NULL. > > So on platforms which do enable livetree, how does this fixup work? > What am I missing? It isn't implemented yet for OF_LIVE in image_setup_libfdt(). Most of the code is there though. It just needs to be hooked up - see oftree_to_fdt() and oftree_from_fdt(). The idea would be to remove the of_live_active() check, so the event is always sent (will need to 'select EVENT' for OF_LIVE). Then in that same code, after the event, call oftree_to_fdt() and copy the fdt back to blob. If you have time, it should be a nice mini project and will allow us to migrate more things to the ofnode API. Regards, Simon
On Mon, 28 Oct 2024 at 22:32, Simon Glass <sjg@chromium.org> wrote: > > Hi Sughosh, > > On Mon, 28 Oct 2024 at 12:29, Sughosh Ganu <sughosh.ganu@linaro.org> wrote: > > > > On Sun, 27 Oct 2024 at 20:30, Simon Glass <sjg@chromium.org> wrote: > > > > > > Hi Sughosh, > > > > > > On Fri, 25 Oct 2024 at 13:15, 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> > > > > --- > > > > boot/fdt_support.c | 41 +++++++++++++++++++++++++++++++++++++++-- > > > > include/fdt_support.h | 13 +++++++++++++ > > > > 2 files changed, 52 insertions(+), 2 deletions(-) > > > > > > Can you please use the ofnode interface for this? We are trying not to > > > add more of this kind of fixup, as it means someone will have to port > > > it over later. > > > > > > See EVT_FT_FIXUP > > > > Are you suggesting using the EVT_FT_FIXUP interface for adding the > > pmem node? If so, how does this work on platforms which enable > > livetree? Looking at the code, I see that the EVT_FT_FIXUP gets called > > only when the livetree is not active. However, I am not able to find > > any place where the livetree is getting disabled. We do have a > > function, oftree_to_fdt() which flattens a livetree, but I don't see > > it getting called from anywhere except from a 'upl' command. The > > of_root pointer does get set in initr_of_live(), but apart from > > dm_test_pre_run(), I do not see where we disable the livetree and set > > of_root to NULL. > > > > So on platforms which do enable livetree, how does this fixup work? > > What am I missing? > > It isn't implemented yet for OF_LIVE in image_setup_libfdt(). Most of the code is there though. It just needs to be hooked up - see oftree_to_fdt() and oftree_from_fdt(). > > The idea would be to remove the of_live_active() check, so the event is always sent (will need to 'select EVENT' for OF_LIVE). > > Then in that same code, after the event, call oftree_to_fdt() and copy the fdt back to blob. Sorry, I got pulled into other tasks, so could not reply to this earlier. Looking at the code, I don't think that using livetree is a good use-case in this context. What is happening here is that the image_setup_libfdt() function gets called for fixing up the devicetree before the OS is called. However, in this case, we cannot assume that the FDT that is being passed to the OS is the same as the livetree. What that means is that it would be required to first convert the FDT to a livetree, apply the fixup's and then again convert the livetree back to FDT. I can understand why you would want to convert a FDT to a livetree during init, and then use the livetree for driver model init. But why do we need this transformation to and back from livetree in this context, only for adding a node to the FDT. -sughosh > > If you have time, it should be a nice mini project and will allow us to migrate more things to the ofnode API. > > Regards, > Simon
diff --git a/boot/fdt_support.c b/boot/fdt_support.c index 2392027d40..61f725389b 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 741e2360c2..63ece0de32 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -473,4 +473,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 */