All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/5] Add pmem node for preserving distro ISO's
@ 2025-02-03 10:59 Sughosh Ganu
  2025-02-03 10:59 ` [PATCH v4 1/5] fdt: add support for adding pmem nodes Sughosh Ganu
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Sughosh Ganu @ 2025-02-03 10:59 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass, Tom Rini,
	Anton Antonov, Tobias Waldekranz, Bin Meng


When installing a distro via EFI HTTP boot some OS installers expect
the .iso image to be preserved and treat it as a "CDROM" to install
packages.

This is problematic in EFI, since U-Boot mounts the image, starts the
installer, and eventually calls ExitBootServices. At that point the
image U-Boot mounted disappears. Some distros don't care and download
the missing packages from a web archive, while others halt the
installation complaining they can't find certain packages.

If the firmware uses ACPI, this is supported by using NFIT which
provides NVDIMM ramdisks to the OS and preserves the image.
We don't have anything in place for Device Trees though. Since DT
supports persistent memory nodes (pmem) use those and preserve the
.iso for installers.

The issue can be reproduced by attempting an EFI HTTP boot with Ubuntu
live server ISO, or a Rocky Linux ISO. The installation would fail
with the failure to locate certain packages.

The earlier version had aligned the addition of pmem nodes with the
EFI HTTP boot feature. This has been changed, based on a review
comment from Heinrich to instead be done by looping through the memory
based blkmamp devices.

Changes since V3:
* Rephrased the 2MiB alignment error message as suggested by Heinrich
* Rephrased the description of fdt_fixup_pmem_region() function as
  suggested by Heinrich
* Add the map type to the blkmap slice instead of the entire blkmap
  device
* Move the definition of the helper function to the efi_helper.c
* Remove the region of the blkmap mem map device from the EFI memory
  map along with adding the pmem node



Ilias Apalodimas (2):
  efi_loader: add a function to remove memory from the EFI map
  efi_loader: preserve installer images in pmem

Masahisa Kojima (1):
  fdt: add support for adding pmem nodes

Sughosh Ganu (2):
  blkmap: store type of blkmap slice in corresponding structure
  blkmap: add pmem nodes for blkmap memory mapped slices

 boot/fdt_support.c           | 41 ++++++++++++++++-
 boot/image-fdt.c             |  9 ++++
 drivers/block/blkmap.c       | 82 +--------------------------------
 include/blkmap.h             | 87 ++++++++++++++++++++++++++++++++++++
 include/efi.h                | 13 ++++++
 include/efi_loader.h         | 11 +++--
 include/fdt_support.h        | 14 ++++++
 lib/efi_loader/efi_bootmgr.c | 22 ++++++---
 lib/efi_loader/efi_helper.c  | 52 +++++++++++++++++++++
 lib/efi_loader/efi_memory.c  | 51 +++++++++++++++------
 lib/lmb.c                    |  4 +-
 11 files changed, 281 insertions(+), 105 deletions(-)

-- 
2.34.1



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v4 1/5] fdt: add support for adding pmem nodes
  2025-02-03 10:59 [PATCH v4 0/5] Add pmem node for preserving distro ISO's Sughosh Ganu
@ 2025-02-03 10:59 ` Sughosh Ganu
  2025-02-21 18:37   ` Ilias Apalodimas
  2025-02-03 10:59 ` [PATCH v4 2/5] efi_loader: add a function to remove memory from the EFI map Sughosh Ganu
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Sughosh Ganu @ 2025-02-03 10:59 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass, Tom Rini,
	Anton Antonov, Tobias Waldekranz, Bin Meng, Masahisa Kojima,
	Sughosh Ganu

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 V3:
* Rephrased the 2MiB alignment error message as suggested by Heinrich
* Rephrased the description of fdt_fixup_pmem_region() function as
  suggested by Heinrich

 boot/fdt_support.c    | 41 ++++++++++++++++++++++++++++++++++++++++-
 include/fdt_support.h | 14 ++++++++++++++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/boot/fdt_support.c b/boot/fdt_support.c
index 49efeec3681..e20b9759138 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,41 @@ 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 must be 2MiB aligned\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 f0ad2e6b365..b72cd2920de 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -507,4 +507,18 @@ 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 adds/updates 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


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 2/5] efi_loader: add a function to remove memory from the EFI map
  2025-02-03 10:59 [PATCH v4 0/5] Add pmem node for preserving distro ISO's Sughosh Ganu
  2025-02-03 10:59 ` [PATCH v4 1/5] fdt: add support for adding pmem nodes Sughosh Ganu
@ 2025-02-03 10:59 ` Sughosh Ganu
  2025-02-03 10:59 ` [PATCH v4 3/5] efi_loader: preserve installer images in pmem Sughosh Ganu
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Sughosh Ganu @ 2025-02-03 10:59 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass, Tom Rini,
	Anton Antonov, Tobias Waldekranz, Bin Meng, Sughosh Ganu

From: Ilias Apalodimas <ilias.apalodimas@linaro.org>

With upcoming changes supporting pmem nodes, we need to remove the
pmem area from the EFI memory map. Add a function to do that.

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
Changes since V3: None

 include/efi_loader.h        | 11 +++++---
 lib/efi_loader/efi_memory.c | 51 +++++++++++++++++++++++++++----------
 lib/lmb.c                   |  4 +--
 3 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index dcae6a731a0..d10e3ca4895 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -853,7 +853,7 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
 efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type);
 
 /**
- * efi_add_memory_map_pg() - add pages to the memory map
+ * efi_update_memory_map() - update the memory map by adding/removing pages
  *
  * @start:			start address, must be a multiple of
  *				EFI_PAGE_SIZE
@@ -861,11 +861,14 @@ efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type);
  * @memory_type:		type of memory added
  * @overlap_conventional:	region may only overlap free(conventional)
  *				memory
+ * @remove:			remove memory map
  * Return:			status code
  */
-efi_status_t efi_add_memory_map_pg(u64 start, u64 pages,
-				   int memory_type,
-				   bool overlap_conventional);
+efi_status_t efi_update_memory_map(u64 start, u64 pages, int memory_type,
+				   bool overlap_conventional, bool remove);
+
+/* Remove memory from the EFI memory map */
+efi_status_t efi_remove_memory_map(u64 start, u64 size, int memory_type);
 
 /* Called by board init to initialize the EFI drivers */
 efi_status_t efi_driver_init(void);
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 1212772471e..2362995abf6 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -258,7 +258,7 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map,
 }
 
 /**
- * efi_add_memory_map_pg() - add pages to the memory map
+ * efi_update_memory_map() - update the memory map by adding/removing pages
  *
  * @start:			start address, must be a multiple of
  *				EFI_PAGE_SIZE
@@ -266,11 +266,11 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map,
  * @memory_type:		type of memory added
  * @overlap_conventional:	region may only overlap free(conventional)
  *				memory
+ * @remove:			remove memory map
  * Return:			status code
  */
-efi_status_t efi_add_memory_map_pg(u64 start, u64 pages,
-				   int memory_type,
-				   bool overlap_conventional)
+efi_status_t efi_update_memory_map(u64 start, u64 pages, int memory_type,
+				   bool overlap_conventional, bool remove)
 {
 	struct efi_mem_list *lmem;
 	struct efi_mem_list *newlist;
@@ -278,9 +278,9 @@ efi_status_t efi_add_memory_map_pg(u64 start, u64 pages,
 	uint64_t carved_pages = 0;
 	struct efi_event *evt;
 
-	EFI_PRINT("%s: 0x%llx 0x%llx %d %s\n", __func__,
+	EFI_PRINT("%s: 0x%llx 0x%llx %d %s %s\n", __func__,
 		  start, pages, memory_type, overlap_conventional ?
-		  "yes" : "no");
+		  "yes" : "no", remove ? "remove" : "add");
 
 	if (memory_type >= EFI_MAX_MEMORY_TYPE)
 		return EFI_INVALID_PARAMETER;
@@ -363,7 +363,10 @@ efi_status_t efi_add_memory_map_pg(u64 start, u64 pages,
 	}
 
 	/* Add our new map */
-        list_add_tail(&newlist->link, &efi_mem);
+	if (!remove)
+		list_add_tail(&newlist->link, &efi_mem);
+	else
+		free(newlist);
 
 	/* And make sure memory is listed in descending order */
 	efi_mem_sort();
@@ -400,7 +403,29 @@ efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type)
 	pages = efi_size_in_pages(size + (start & EFI_PAGE_MASK));
 	start &= ~EFI_PAGE_MASK;
 
-	return efi_add_memory_map_pg(start, pages, memory_type, false);
+	return efi_update_memory_map(start, pages, memory_type, false, false);
+}
+
+/**
+ * efi_remove_memory_map() - remove memory area to the memory map
+ *
+ * @start:		start address of the memory area
+ * @size:		length in bytes of the memory area
+ * @memory_type:	type of memory removed
+ *
+ * Return:		status code
+ *
+ * This function automatically aligns the start and size of the memory area
+ * to EFI_PAGE_SIZE.
+ */
+efi_status_t efi_remove_memory_map(u64 start, u64 size, int memory_type)
+{
+	u64 pages;
+
+	pages = efi_size_in_pages(size + (start & EFI_PAGE_MASK));
+	start &= ~EFI_PAGE_MASK;
+
+	return efi_update_memory_map(start, pages, memory_type, false, true);
 }
 
 /**
@@ -501,7 +526,7 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type,
 
 	efi_addr = (u64)(uintptr_t)map_sysmem(addr, 0);
 	/* Reserve that map in our memory maps */
-	ret = efi_add_memory_map_pg(efi_addr, pages, memory_type, true);
+	ret = efi_update_memory_map(efi_addr, pages, memory_type, true, false);
 	if (ret != EFI_SUCCESS) {
 		/* Map would overlap, bail out */
 		lmb_free_flags(addr, (u64)pages << EFI_PAGE_SHIFT, flags);
@@ -822,8 +847,8 @@ static void add_u_boot_and_runtime(void)
 		       uboot_stack_size) & ~EFI_PAGE_MASK;
 	uboot_pages = ((uintptr_t)map_sysmem(gd->ram_top - 1, 0) -
 		       uboot_start + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
-	efi_add_memory_map_pg(uboot_start, uboot_pages, EFI_BOOT_SERVICES_CODE,
-			      false);
+	efi_update_memory_map(uboot_start, uboot_pages, EFI_BOOT_SERVICES_CODE,
+			      false, false);
 #if defined(__aarch64__)
 	/*
 	 * Runtime Services must be 64KiB aligned according to the
@@ -841,8 +866,8 @@ static void add_u_boot_and_runtime(void)
 	runtime_end = (uintptr_t)__efi_runtime_stop;
 	runtime_end = (runtime_end + runtime_mask) & ~runtime_mask;
 	runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
-	efi_add_memory_map_pg(runtime_start, runtime_pages,
-			      EFI_RUNTIME_SERVICES_CODE, false);
+	efi_update_memory_map(runtime_start, runtime_pages,
+			      EFI_RUNTIME_SERVICES_CODE, false, false);
 }
 
 int efi_memory_init(void)
diff --git a/lib/lmb.c b/lib/lmb.c
index 7ca44591e1d..d5aea1ed8fe 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -455,11 +455,11 @@ static int lmb_map_update_notify(phys_addr_t addr, phys_size_t size, u8 op,
 	pages = efi_size_in_pages(size + (efi_addr & EFI_PAGE_MASK));
 	efi_addr &= ~EFI_PAGE_MASK;
 
-	status = efi_add_memory_map_pg(efi_addr, pages,
+	status = efi_update_memory_map(efi_addr, pages,
 				       op == MAP_OP_RESERVE ?
 				       EFI_BOOT_SERVICES_DATA :
 				       EFI_CONVENTIONAL_MEMORY,
-				       false);
+				       false, false);
 	if (status != EFI_SUCCESS) {
 		log_err("%s: LMB Map notify failure %lu\n", __func__,
 			status & ~EFI_ERROR_MASK);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 3/5] efi_loader: preserve installer images in pmem
  2025-02-03 10:59 [PATCH v4 0/5] Add pmem node for preserving distro ISO's Sughosh Ganu
  2025-02-03 10:59 ` [PATCH v4 1/5] fdt: add support for adding pmem nodes Sughosh Ganu
  2025-02-03 10:59 ` [PATCH v4 2/5] efi_loader: add a function to remove memory from the EFI map Sughosh Ganu
@ 2025-02-03 10:59 ` Sughosh Ganu
  2025-02-03 10:59 ` [PATCH v4 4/5] blkmap: store type of blkmap slice in corresponding structure Sughosh Ganu
  2025-02-03 10:59 ` [PATCH v4 5/5] blkmap: add pmem nodes for blkmap memory mapped slices Sughosh Ganu
  4 siblings, 0 replies; 12+ messages in thread
From: Sughosh Ganu @ 2025-02-03 10:59 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass, Tom Rini,
	Anton Antonov, Tobias Waldekranz, Bin Meng, Sughosh Ganu

From: Ilias Apalodimas <ilias.apalodimas@linaro.org>

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.

It's worth noting that for linux to instantiate the /dev/pmemX device,
the memory described in the pmem node has to be omitted from the EFI
memory map we hand over to the OS if ZONE_DEVICES and SPARSEMEM is
enabled. With those enabled the pmem driver ends up calling
devm_memremap_pages() instead of devm_memremap(). The latter works
whether the memory is omitted or marked as reserved, but mapping pages
only works if the memory is omitted.

On top of that, depending on how the kernel is configured, that memory
area must be page aligned or 2MB aligned. PowerPC is an exception here
and requires 16MB alignment, but since we don't have EFI support for
it, limit the alignment to 2MB.

Ensure that the ISO image is 2MB aligned and remove the region
occupied by the image from the EFI memory map.

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
Changes since V3: None

 lib/efi_loader/efi_bootmgr.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index c6124c590d9..081eff057f4 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -18,6 +18,8 @@
 #include <efi_loader.h>
 #include <efi_variable.h>
 #include <asm/unaligned.h>
+#include <linux/kernel.h>
+#include <linux/sizes.h>
 
 static const struct efi_boot_services *bs;
 static const struct efi_runtime_services *rs;
@@ -362,13 +364,16 @@ static efi_status_t prepare_loaded_image(u16 *label, ulong addr, ulong size,
 	}
 
 	/*
-	 * TODO: expose the ramdisk to OS.
-	 * Need to pass the ramdisk information by the architecture-specific
-	 * methods such as 'pmem' device-tree node.
+	 * Linux supports 'pmem' which allows OS installers to find, reclaim
+	 * the mounted images and continue the installation since the contents
+	 * of the pmem region are treated as local media.
+	 *
+	 * The memory regions used for it needs to be carved out of the EFI
+	 * memory map.
 	 */
-	ret = efi_add_memory_map(addr, size, EFI_RESERVED_MEMORY_TYPE);
+	ret = efi_remove_memory_map(addr, size, EFI_CONVENTIONAL_MEMORY);
 	if (ret != EFI_SUCCESS) {
-		log_err("Memory reservation failed\n");
+		log_err("Failed to reserve memory\n");
 		goto err;
 	}
 
@@ -490,6 +495,13 @@ static efi_status_t try_load_from_uri_path(struct efi_device_path_uri *uridp,
 		ret = EFI_INVALID_PARAMETER;
 		goto err;
 	}
+	/*
+	 * Depending on the kernel configuration, pmem memory area must be page
+	 * aligned or 2MB aligned. PowerPC is an exception here and requires
+	 * 16MB alignment, but since we don't have EFI support for it, limit
+	 * the alignment to 2MB.
+	 */
+	image_size = ALIGN(image_size, SZ_2M);
 
 	/*
 	 * If the file extension is ".iso" or ".img", mount it and try to load
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 4/5] blkmap: store type of blkmap slice in corresponding structure
  2025-02-03 10:59 [PATCH v4 0/5] Add pmem node for preserving distro ISO's Sughosh Ganu
                   ` (2 preceding siblings ...)
  2025-02-03 10:59 ` [PATCH v4 3/5] efi_loader: preserve installer images in pmem Sughosh Ganu
@ 2025-02-03 10:59 ` Sughosh Ganu
  2025-02-21 18:39   ` Ilias Apalodimas
  2025-02-03 10:59 ` [PATCH v4 5/5] blkmap: add pmem nodes for blkmap memory mapped slices Sughosh Ganu
  4 siblings, 1 reply; 12+ messages in thread
From: Sughosh Ganu @ 2025-02-03 10:59 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass, Tom Rini,
	Anton Antonov, Tobias Waldekranz, Bin Meng, Sughosh Ganu

Add information about the type of blkmap slice in the corresponding
slice structure. Put information in the blkmap slice structure to
identify if it is associated with a memory or linear mapped
device. Which can then be used to take specific action based on the
type of the blkmap slice.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
Changes since V3:
* Add the map type to the blkmap slice instead of the entire blkmap
  device

 drivers/block/blkmap.c | 4 ++++
 include/blkmap.h       | 6 ++++++
 2 files changed, 10 insertions(+)

diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c
index 34eed1380dc..4c71ec784e0 100644
--- a/drivers/block/blkmap.c
+++ b/drivers/block/blkmap.c
@@ -25,12 +25,14 @@ struct blkmap;
  * @node: List node used to associate this slice with a blkmap
  * @blknr: Start block number of the mapping
  * @blkcnt: Number of blocks covered by this mapping
+ * @type: Type of blkmap slice
  */
 struct blkmap_slice {
 	struct list_head node;
 
 	lbaint_t blknr;
 	lbaint_t blkcnt;
+	enum blkmap_slice_type type;
 
 	/**
 	 * @read: - Read from slice
@@ -169,6 +171,7 @@ int blkmap_map_linear(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
 		.slice = {
 			.blknr = blknr,
 			.blkcnt = blkcnt,
+			.type = BLKMAP_SLICE_LINEAR,
 
 			.read = blkmap_linear_read,
 			.write = blkmap_linear_write,
@@ -248,6 +251,7 @@ int __blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
 		.slice = {
 			.blknr = blknr,
 			.blkcnt = blkcnt,
+			.type = BLKMAP_SLICE_MEM,
 
 			.read = blkmap_mem_read,
 			.write = blkmap_mem_write,
diff --git a/include/blkmap.h b/include/blkmap.h
index d53095437fa..c7b4bf13c4e 100644
--- a/include/blkmap.h
+++ b/include/blkmap.h
@@ -9,6 +9,12 @@
 
 #include <dm/lists.h>
 
+/* Type of blkmap slice, Linear or Memory */
+enum blkmap_slice_type {
+	BLKMAP_SLICE_LINEAR = 1,
+	BLKMAP_SLICE_MEM,
+};
+
 /**
  * struct blkmap - Block map
  *
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 5/5] blkmap: add pmem nodes for blkmap memory mapped slices
  2025-02-03 10:59 [PATCH v4 0/5] Add pmem node for preserving distro ISO's Sughosh Ganu
                   ` (3 preceding siblings ...)
  2025-02-03 10:59 ` [PATCH v4 4/5] blkmap: store type of blkmap slice in corresponding structure Sughosh Ganu
@ 2025-02-03 10:59 ` Sughosh Ganu
  2025-02-21 18:55   ` Ilias Apalodimas
  4 siblings, 1 reply; 12+ messages in thread
From: Sughosh Ganu @ 2025-02-03 10:59 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass, Tom Rini,
	Anton Antonov, Tobias Waldekranz, Bin Meng, Sughosh Ganu

The EFI HTTP boot puts the ISO installer image at some location in
memory which needs to be added to the devicetree as persistent
memory (pmem) node. The OS installer then gets information about the
presence of this ISO image through the pmem node and proceeds with the
installation.

In U-Boot, this ISO image gets mounted as a blkmap device, with a
memory mapped slice. Add a helper function which iterates through all
such memory mapped blkmap slices, and calls the FDT fixup function to
add the pmem node. Invoke this helper function as part of the DT fixup
which happens before booting the OS.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
Changes since V3:
* Move the definition of the helper function to the efi_helper.c
* Remove the region of the blkmap mem map device from the EFI memory
  map along with adding the pmem node

 boot/image-fdt.c            |  9 ++++
 drivers/block/blkmap.c      | 82 -------------------------------------
 include/blkmap.h            | 81 ++++++++++++++++++++++++++++++++++++
 include/efi.h               | 13 ++++++
 lib/efi_loader/efi_helper.c | 52 +++++++++++++++++++++++
 5 files changed, 155 insertions(+), 82 deletions(-)

diff --git a/boot/image-fdt.c b/boot/image-fdt.c
index 9d1598b1a93..e64243af88e 100644
--- a/boot/image-fdt.c
+++ b/boot/image-fdt.c
@@ -8,6 +8,7 @@
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  */
 
+#include <blkmap.h>
 #include <command.h>
 #include <fdt_support.h>
 #include <fdtdec.h>
@@ -649,6 +650,14 @@ int image_setup_libfdt(struct bootm_headers *images, void *blob, bool lmb)
 	if (!ft_verify_fdt(blob))
 		goto err;
 
+	if (CONFIG_IS_ENABLED(BLKMAP) && CONFIG_IS_ENABLED(EFI_LOADER)) {
+		fdt_ret = fdt_efi_pmem_setup(blob);
+		if (fdt_ret) {
+			log_err("pmem node fixup failed\n");
+			goto err;
+		}
+	}
+
 	/* after here we are using a livetree */
 	if (!of_live_active() && CONFIG_IS_ENABLED(EVENT)) {
 		struct event_ft_fixup fixup;
diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c
index 4c71ec784e0..2c7f4966ae9 100644
--- a/drivers/block/blkmap.c
+++ b/drivers/block/blkmap.c
@@ -14,59 +14,6 @@
 #include <dm/lists.h>
 #include <dm/root.h>
 
-struct blkmap;
-
-/**
- * struct blkmap_slice - Region mapped to a blkmap
- *
- * Common data for a region mapped to a blkmap, specialized by each
- * map type.
- *
- * @node: List node used to associate this slice with a blkmap
- * @blknr: Start block number of the mapping
- * @blkcnt: Number of blocks covered by this mapping
- * @type: Type of blkmap slice
- */
-struct blkmap_slice {
-	struct list_head node;
-
-	lbaint_t blknr;
-	lbaint_t blkcnt;
-	enum blkmap_slice_type type;
-
-	/**
-	 * @read: - Read from slice
-	 *
-	 * @read.bm: Blkmap to which this slice belongs
-	 * @read.bms: This slice
-	 * @read.blknr: Start block number to read from
-	 * @read.blkcnt: Number of blocks to read
-	 * @read.buffer: Buffer to store read data to
-	 */
-	ulong (*read)(struct blkmap *bm, struct blkmap_slice *bms,
-		      lbaint_t blknr, lbaint_t blkcnt, void *buffer);
-
-	/**
-	 * @write: - Write to slice
-	 *
-	 * @write.bm: Blkmap to which this slice belongs
-	 * @write.bms: This slice
-	 * @write.blknr: Start block number to write to
-	 * @write.blkcnt: Number of blocks to write
-	 * @write.buffer: Data to be written
-	 */
-	ulong (*write)(struct blkmap *bm, struct blkmap_slice *bms,
-		       lbaint_t blknr, lbaint_t blkcnt, const void *buffer);
-
-	/**
-	 * @destroy: - Tear down slice
-	 *
-	 * @read.bm: Blkmap to which this slice belongs
-	 * @read.bms: This slice
-	 */
-	void (*destroy)(struct blkmap *bm, struct blkmap_slice *bms);
-};
-
 static bool blkmap_slice_contains(struct blkmap_slice *bms, lbaint_t blknr)
 {
 	return (blknr >= bms->blknr) && (blknr < (bms->blknr + bms->blkcnt));
@@ -116,20 +63,6 @@ static int blkmap_slice_add(struct blkmap *bm, struct blkmap_slice *new)
 	return 0;
 }
 
-/**
- * struct blkmap_linear - Linear mapping to other block device
- *
- * @slice: Common map data
- * @blk: Target block device of this mapping
- * @blknr: Start block number of the target device
- */
-struct blkmap_linear {
-	struct blkmap_slice slice;
-
-	struct udevice *blk;
-	lbaint_t blknr;
-};
-
 static ulong blkmap_linear_read(struct blkmap *bm, struct blkmap_slice *bms,
 				lbaint_t blknr, lbaint_t blkcnt, void *buffer)
 {
@@ -188,21 +121,6 @@ int blkmap_map_linear(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
 	return err;
 }
 
-/**
- * struct blkmap_mem - Memory mapping
- *
- * @slice: Common map data
- * @addr: Target memory region of this mapping
- * @remapped: True if @addr is backed by a physical to virtual memory
- * mapping that must be torn down at the end of this mapping's
- * lifetime.
- */
-struct blkmap_mem {
-	struct blkmap_slice slice;
-	void *addr;
-	bool remapped;
-};
-
 static ulong blkmap_mem_read(struct blkmap *bm, struct blkmap_slice *bms,
 			     lbaint_t blknr, lbaint_t blkcnt, void *buffer)
 {
diff --git a/include/blkmap.h b/include/blkmap.h
index c7b4bf13c4e..e5e2d971548 100644
--- a/include/blkmap.h
+++ b/include/blkmap.h
@@ -7,6 +7,7 @@
 #ifndef _BLKMAP_H
 #define _BLKMAP_H
 
+#include <blk.h>
 #include <dm/lists.h>
 
 /* Type of blkmap slice, Linear or Memory */
@@ -30,6 +31,86 @@ struct blkmap {
 	struct list_head slices;
 };
 
+/**
+ * struct blkmap_slice - Region mapped to a blkmap
+ *
+ * Common data for a region mapped to a blkmap, specialized by each
+ * map type.
+ *
+ * @node: List node used to associate this slice with a blkmap
+ * @blknr: Start block number of the mapping
+ * @blkcnt: Number of blocks covered by this mapping
+ * @type: Type of blkmap slice
+ */
+struct blkmap_slice {
+	struct list_head node;
+
+	lbaint_t blknr;
+	lbaint_t blkcnt;
+	enum blkmap_slice_type type;
+
+	/**
+	 * @read: - Read from slice
+	 *
+	 * @read.bm: Blkmap to which this slice belongs
+	 * @read.bms: This slice
+	 * @read.blknr: Start block number to read from
+	 * @read.blkcnt: Number of blocks to read
+	 * @read.buffer: Buffer to store read data to
+	 */
+	ulong (*read)(struct blkmap *bm, struct blkmap_slice *bms,
+		      lbaint_t blknr, lbaint_t blkcnt, void *buffer);
+
+	/**
+	 * @write: - Write to slice
+	 *
+	 * @write.bm: Blkmap to which this slice belongs
+	 * @write.bms: This slice
+	 * @write.blknr: Start block number to write to
+	 * @write.blkcnt: Number of blocks to write
+	 * @write.buffer: Data to be written
+	 */
+	ulong (*write)(struct blkmap *bm, struct blkmap_slice *bms,
+		       lbaint_t blknr, lbaint_t blkcnt, const void *buffer);
+
+	/**
+	 * @destroy: - Tear down slice
+	 *
+	 * @read.bm: Blkmap to which this slice belongs
+	 * @read.bms: This slice
+	 */
+	void (*destroy)(struct blkmap *bm, struct blkmap_slice *bms);
+};
+
+/**
+ * struct blkmap_mem - Memory mapping
+ *
+ * @slice: Common map data
+ * @addr: Target memory region of this mapping
+ * @remapped: True if @addr is backed by a physical to virtual memory
+ * mapping that must be torn down at the end of this mapping's
+ * lifetime.
+ */
+struct blkmap_mem {
+	struct blkmap_slice slice;
+	void *addr;
+	bool remapped;
+};
+
+/**
+ * struct blkmap_linear - Linear mapping to other block device
+ *
+ * @slice: Common map data
+ * @blk: Target block device of this mapping
+ * @blknr: Start block number of the target device
+ */
+struct blkmap_linear {
+	struct blkmap_slice slice;
+
+	struct udevice *blk;
+	lbaint_t blknr;
+};
+
 /**
  * blkmap_map_linear() - Map region of other block device
  *
diff --git a/include/efi.h b/include/efi.h
index d005cb6181e..f9bbb175c3a 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -705,4 +705,17 @@ static inline bool efi_use_host_arch(void)
  */
 int efi_get_pxe_arch(void);
 
+/**
+ * fdt_efi_pmem_setup() - Pmem setup in DT and EFI memory map
+ * @fdt: Devicetree to add the pmem nodes to
+ *
+ * Iterate through all the blkmap devices, look for BLKMAP_MEM devices,
+ * and add pmem nodes corresponding to the blkmap slice to the
+ * devicetree along with removing the corresponding region from the
+ * EFI memory map.
+ *
+ * Returns: 0 on success, negative error on failure
+ */
+int fdt_efi_pmem_setup(void *fdt);
+
 #endif /* _LINUX_EFI_H */
diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c
index 04b2efc4a3b..1050ed1f952 100644
--- a/lib/efi_loader/efi_helper.c
+++ b/lib/efi_loader/efi_helper.c
@@ -5,6 +5,7 @@
 
 #define LOG_CATEGORY LOGC_EFI
 
+#include <blkmap.h>
 #include <bootm.h>
 #include <env.h>
 #include <image.h>
@@ -19,6 +20,8 @@
 #include <efi_loader.h>
 #include <efi_variable.h>
 #include <host_arch.h>
+#include <dm/uclass.h>
+#include <linux/kernel.h>
 #include <linux/libfdt.h>
 #include <linux/list.h>
 
@@ -680,3 +683,52 @@ out:
 
 	return ret;
 }
+
+static int add_blkmap_pmem_nodes(void *fdt, struct blkmap *bm)
+{
+	int ret;
+	u32 size;
+	ulong addr;
+	efi_status_t status;
+	struct blkmap_mem *bmm;
+	struct blkmap_slice *bms;
+	struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
+
+	list_for_each_entry(bms, &bm->slices, node) {
+		if (bms->type != BLKMAP_SLICE_MEM)
+			continue;
+
+		bmm = container_of(bms, struct blkmap_mem, slice);
+
+		addr = (ulong)(uintptr_t)bmm->addr;
+		size = (u32)bms->blkcnt << bd->log2blksz;
+
+		ret = fdt_fixup_pmem_region(fdt, addr, size);
+		if (ret)
+			return ret;
+
+		status = efi_remove_memory_map(addr, size,
+					       EFI_CONVENTIONAL_MEMORY);
+		if (status != EFI_SUCCESS)
+			return -1;
+	}
+
+	return 0;
+}
+
+int fdt_efi_pmem_setup(void *fdt)
+{
+	int ret;
+	struct udevice *dev;
+	struct uclass *uc;
+	struct blkmap *bm;
+
+	uclass_id_foreach_dev(UCLASS_BLKMAP, dev, uc) {
+		bm = dev_get_plat(dev);
+		ret = add_blkmap_pmem_nodes(fdt, bm);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 1/5] fdt: add support for adding pmem nodes
  2025-02-03 10:59 ` [PATCH v4 1/5] fdt: add support for adding pmem nodes Sughosh Ganu
@ 2025-02-21 18:37   ` Ilias Apalodimas
  0 siblings, 0 replies; 12+ messages in thread
From: Ilias Apalodimas @ 2025-02-21 18:37 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Tom Rini, Anton Antonov,
	Tobias Waldekranz, Bin Meng, Masahisa Kojima

On Mon, 3 Feb 2025 at 12:59, 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 V3:
> * Rephrased the 2MiB alignment error message as suggested by Heinrich
> * Rephrased the description of fdt_fixup_pmem_region() function as
>   suggested by Heinrich
>
>  boot/fdt_support.c    | 41 ++++++++++++++++++++++++++++++++++++++++-
>  include/fdt_support.h | 14 ++++++++++++++
>  2 files changed, 54 insertions(+), 1 deletion(-)
>
> diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> index 49efeec3681..e20b9759138 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,41 @@ 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 must be 2MiB aligned\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 f0ad2e6b365..b72cd2920de 100644
> --- a/include/fdt_support.h
> +++ b/include/fdt_support.h
> @@ -507,4 +507,18 @@ 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 adds/updates 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
>

Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 4/5] blkmap: store type of blkmap slice in corresponding structure
  2025-02-03 10:59 ` [PATCH v4 4/5] blkmap: store type of blkmap slice in corresponding structure Sughosh Ganu
@ 2025-02-21 18:39   ` Ilias Apalodimas
  0 siblings, 0 replies; 12+ messages in thread
From: Ilias Apalodimas @ 2025-02-21 18:39 UTC (permalink / raw)
  To: Sughosh Ganu, Tobias Waldekranz
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Tom Rini, Anton Antonov,
	Bin Meng

Hi Tobias,

This looks ok to me, but OTOH I haven't been involved with blkmap too much.

On Mon, 3 Feb 2025 at 12:59, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> Add information about the type of blkmap slice in the corresponding
> slice structure. Put information in the blkmap slice structure to
> identify if it is associated with a memory or linear mapped
> device. Which can then be used to take specific action based on the
> type of the blkmap slice.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
> Changes since V3:
> * Add the map type to the blkmap slice instead of the entire blkmap
>   device
>
>  drivers/block/blkmap.c | 4 ++++
>  include/blkmap.h       | 6 ++++++
>  2 files changed, 10 insertions(+)
>
> diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c
> index 34eed1380dc..4c71ec784e0 100644
> --- a/drivers/block/blkmap.c
> +++ b/drivers/block/blkmap.c
> @@ -25,12 +25,14 @@ struct blkmap;
>   * @node: List node used to associate this slice with a blkmap
>   * @blknr: Start block number of the mapping
>   * @blkcnt: Number of blocks covered by this mapping
> + * @type: Type of blkmap slice
>   */
>  struct blkmap_slice {
>         struct list_head node;
>
>         lbaint_t blknr;
>         lbaint_t blkcnt;
> +       enum blkmap_slice_type type;
>
>         /**
>          * @read: - Read from slice
> @@ -169,6 +171,7 @@ int blkmap_map_linear(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
>                 .slice = {
>                         .blknr = blknr,
>                         .blkcnt = blkcnt,
> +                       .type = BLKMAP_SLICE_LINEAR,
>
>                         .read = blkmap_linear_read,
>                         .write = blkmap_linear_write,
> @@ -248,6 +251,7 @@ int __blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
>                 .slice = {
>                         .blknr = blknr,
>                         .blkcnt = blkcnt,
> +                       .type = BLKMAP_SLICE_MEM,
>
>                         .read = blkmap_mem_read,
>                         .write = blkmap_mem_write,
> diff --git a/include/blkmap.h b/include/blkmap.h
> index d53095437fa..c7b4bf13c4e 100644
> --- a/include/blkmap.h
> +++ b/include/blkmap.h
> @@ -9,6 +9,12 @@
>
>  #include <dm/lists.h>
>
> +/* Type of blkmap slice, Linear or Memory */
> +enum blkmap_slice_type {
> +       BLKMAP_SLICE_LINEAR = 1,
> +       BLKMAP_SLICE_MEM,
> +};
> +
>  /**
>   * struct blkmap - Block map
>   *
> --
> 2.34.1
>

Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 5/5] blkmap: add pmem nodes for blkmap memory mapped slices
  2025-02-03 10:59 ` [PATCH v4 5/5] blkmap: add pmem nodes for blkmap memory mapped slices Sughosh Ganu
@ 2025-02-21 18:55   ` Ilias Apalodimas
  2025-02-21 19:22     ` Heinrich Schuchardt
  2025-02-21 21:31     ` Tobias Waldekranz
  0 siblings, 2 replies; 12+ messages in thread
From: Ilias Apalodimas @ 2025-02-21 18:55 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Tom Rini, Anton Antonov,
	Tobias Waldekranz, Bin Meng

Hi Sughosh

This generally looks ok, but I don't love the idea of unconditionally
preserving all slices regardless of their usage.
Basically, if a user doesn't unmap that slice it will end in kernel
memory. My fear is that someone will forget device sensitive data in a
blkmap....

On Mon, 3 Feb 2025 at 12:59, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> The EFI HTTP boot puts the ISO installer image at some location in
> memory which needs to be added to the devicetree as persistent
> memory (pmem) node. The OS installer then gets information about the
> presence of this ISO image through the pmem node and proceeds with the
> installation.
>
> In U-Boot, this ISO image gets mounted as a blkmap device, with a
> memory mapped slice. Add a helper function which iterates through all
> such memory mapped blkmap slices, and calls the FDT fixup function to
> add the pmem node. Invoke this helper function as part of the DT fixup
> which happens before booting the OS.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
> Changes since V3:
> * Move the definition of the helper function to the efi_helper.c
> * Remove the region of the blkmap mem map device from the EFI memory
>   map along with adding the pmem node
>

[...]

> @@ -680,3 +683,52 @@ out:
>
>         return ret;
>  }
> +
> +static int add_blkmap_pmem_nodes(void *fdt, struct blkmap *bm)
> +{
> +       int ret;
> +       u32 size;
> +       ulong addr;
> +       efi_status_t status;
> +       struct blkmap_mem *bmm;
> +       struct blkmap_slice *bms;
> +       struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
> +
> +       list_for_each_entry(bms, &bm->slices, node) {
> +               if (bms->type != BLKMAP_SLICE_MEM)
> +                       continue;

Can we convert the 'type' to 'preserve' and teach
blkmap_create_ramdisk() to pass that flag?
This way we can unconditionally pass it from EFI HTTP installers, and
let the command line users decide if they want to preserve it.


> +
> +               bmm = container_of(bms, struct blkmap_mem, slice);
> +
> +               addr = (ulong)(uintptr_t)bmm->addr;
> +               size = (u32)bms->blkcnt << bd->log2blksz;
> +
> +               ret = fdt_fixup_pmem_region(fdt, addr, size);
> +               if (ret)
> +                       return ret;
> +
> +               status = efi_remove_memory_map(addr, size,
> +                                              EFI_CONVENTIONAL_MEMORY);
> +               if (status != EFI_SUCCESS)
> +                       return -1;
> +       }
> +
> +       return 0;
> +}
> +


Thanks
/Ilias

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 5/5] blkmap: add pmem nodes for blkmap memory mapped slices
  2025-02-21 18:55   ` Ilias Apalodimas
@ 2025-02-21 19:22     ` Heinrich Schuchardt
  2025-02-21 19:33       ` Ilias Apalodimas
  2025-02-21 21:31     ` Tobias Waldekranz
  1 sibling, 1 reply; 12+ messages in thread
From: Heinrich Schuchardt @ 2025-02-21 19:22 UTC (permalink / raw)
  To: Ilias Apalodimas, Sughosh Ganu
  Cc: u-boot, Simon Glass, Tom Rini, Anton Antonov, Tobias Waldekranz,
	Bin Meng

Am 21. Februar 2025 19:55:03 MEZ schrieb Ilias Apalodimas <ilias.apalodimas@linaro.org>:
>Hi Sughosh
>
>This generally looks ok, but I don't love the idea of unconditionally
>preserving all slices regardless of their usage.
>Basically, if a user doesn't unmap that slice it will end in kernel
>memory. My fear is that someone will forget device sensitive data in a
>blkmap....

I don't that you can easily determine which blkmap and which blkmap slice was created why.

But can we realisticly assume that a device that U-Boot reads from is secure against reading at kernel runtime. I don't believe so as U-Boot runs at the same exception level as the kernel. U-Boot and the kernel do not empty RAM. You always have to assume that whatever is in U-Boot memory is dicoverable at kernel runtime.

If you load sensitive data, you must overwrite it before booting.

Best regards

Heinrich



>
>On Mon, 3 Feb 2025 at 12:59, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>>
>> The EFI HTTP boot puts the ISO installer image at some location in
>> memory which needs to be added to the devicetree as persistent
>> memory (pmem) node. The OS installer then gets information about the
>> presence of this ISO image through the pmem node and proceeds with the
>> installation.
>>
>> In U-Boot, this ISO image gets mounted as a blkmap device, with a
>> memory mapped slice. Add a helper function which iterates through all
>> such memory mapped blkmap slices, and calls the FDT fixup function to
>> add the pmem node. Invoke this helper function as part of the DT fixup
>> which happens before booting the OS.
>>
>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
>> ---
>> Changes since V3:
>> * Move the definition of the helper function to the efi_helper.c
>> * Remove the region of the blkmap mem map device from the EFI memory
>>   map along with adding the pmem node
>>
>
>[...]
>
>> @@ -680,3 +683,52 @@ out:
>>
>>         return ret;
>>  }
>> +
>> +static int add_blkmap_pmem_nodes(void *fdt, struct blkmap *bm)
>> +{
>> +       int ret;
>> +       u32 size;
>> +       ulong addr;
>> +       efi_status_t status;
>> +       struct blkmap_mem *bmm;
>> +       struct blkmap_slice *bms;
>> +       struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
>> +
>> +       list_for_each_entry(bms, &bm->slices, node) {
>> +               if (bms->type != BLKMAP_SLICE_MEM)
>> +                       continue;
>
>Can we convert the 'type' to 'preserve' and teach
>blkmap_create_ramdisk() to pass that flag?
>This way we can unconditionally pass it from EFI HTTP installers, and
>let the command line users decide if they want to preserve it.
>
>
>> +
>> +               bmm = container_of(bms, struct blkmap_mem, slice);
>> +
>> +               addr = (ulong)(uintptr_t)bmm->addr;
>> +               size = (u32)bms->blkcnt << bd->log2blksz;
>> +
>> +               ret = fdt_fixup_pmem_region(fdt, addr, size);
>> +               if (ret)
>> +                       return ret;
>> +
>> +               status = efi_remove_memory_map(addr, size,
>> +                                              EFI_CONVENTIONAL_MEMORY);
>> +               if (status != EFI_SUCCESS)
>> +                       return -1;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>
>
>Thanks
>/Ilias


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 5/5] blkmap: add pmem nodes for blkmap memory mapped slices
  2025-02-21 19:22     ` Heinrich Schuchardt
@ 2025-02-21 19:33       ` Ilias Apalodimas
  0 siblings, 0 replies; 12+ messages in thread
From: Ilias Apalodimas @ 2025-02-21 19:33 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Sughosh Ganu, u-boot, Simon Glass, Tom Rini, Anton Antonov,
	Tobias Waldekranz, Bin Meng

On Fri, 21 Feb 2025 at 21:22, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> Am 21. Februar 2025 19:55:03 MEZ schrieb Ilias Apalodimas <ilias.apalodimas@linaro.org>:
> >Hi Sughosh
> >
> >This generally looks ok, but I don't love the idea of unconditionally
> >preserving all slices regardless of their usage.
> >Basically, if a user doesn't unmap that slice it will end in kernel
> >memory. My fear is that someone will forget device sensitive data in a
> >blkmap....
>
> I don't that you can easily determine which blkmap and which blkmap slice was created why.
>
> But can we realisticly assume that a device that U-Boot reads from is secure against reading at kernel runtime. I don't believe so as U-Boot runs at the same exception level as the kernel. U-Boot and the kernel do not empty RAM. You always have to assume that whatever is in U-Boot memory is dicoverable at kernel runtime.
>
> If you load sensitive data, you must overwrite it before booting.

Fair enough. I am not against this patch, I am just to figure out if
we can restrict what we preserve a bit more

Thanks
/Ilias
>
> Best regards
>
> Heinrich
>
>
>
> >
> >On Mon, 3 Feb 2025 at 12:59, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> >>
> >> The EFI HTTP boot puts the ISO installer image at some location in
> >> memory which needs to be added to the devicetree as persistent
> >> memory (pmem) node. The OS installer then gets information about the
> >> presence of this ISO image through the pmem node and proceeds with the
> >> installation.
> >>
> >> In U-Boot, this ISO image gets mounted as a blkmap device, with a
> >> memory mapped slice. Add a helper function which iterates through all
> >> such memory mapped blkmap slices, and calls the FDT fixup function to
> >> add the pmem node. Invoke this helper function as part of the DT fixup
> >> which happens before booting the OS.
> >>
> >> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> >> ---
> >> Changes since V3:
> >> * Move the definition of the helper function to the efi_helper.c
> >> * Remove the region of the blkmap mem map device from the EFI memory
> >>   map along with adding the pmem node
> >>
> >
> >[...]
> >
> >> @@ -680,3 +683,52 @@ out:
> >>
> >>         return ret;
> >>  }
> >> +
> >> +static int add_blkmap_pmem_nodes(void *fdt, struct blkmap *bm)
> >> +{
> >> +       int ret;
> >> +       u32 size;
> >> +       ulong addr;
> >> +       efi_status_t status;
> >> +       struct blkmap_mem *bmm;
> >> +       struct blkmap_slice *bms;
> >> +       struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
> >> +
> >> +       list_for_each_entry(bms, &bm->slices, node) {
> >> +               if (bms->type != BLKMAP_SLICE_MEM)
> >> +                       continue;
> >
> >Can we convert the 'type' to 'preserve' and teach
> >blkmap_create_ramdisk() to pass that flag?
> >This way we can unconditionally pass it from EFI HTTP installers, and
> >let the command line users decide if they want to preserve it.
> >
> >
> >> +
> >> +               bmm = container_of(bms, struct blkmap_mem, slice);
> >> +
> >> +               addr = (ulong)(uintptr_t)bmm->addr;
> >> +               size = (u32)bms->blkcnt << bd->log2blksz;
> >> +
> >> +               ret = fdt_fixup_pmem_region(fdt, addr, size);
> >> +               if (ret)
> >> +                       return ret;
> >> +
> >> +               status = efi_remove_memory_map(addr, size,
> >> +                                              EFI_CONVENTIONAL_MEMORY);
> >> +               if (status != EFI_SUCCESS)
> >> +                       return -1;
> >> +       }
> >> +
> >> +       return 0;
> >> +}
> >> +
> >
> >
> >Thanks
> >/Ilias
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 5/5] blkmap: add pmem nodes for blkmap memory mapped slices
  2025-02-21 18:55   ` Ilias Apalodimas
  2025-02-21 19:22     ` Heinrich Schuchardt
@ 2025-02-21 21:31     ` Tobias Waldekranz
  1 sibling, 0 replies; 12+ messages in thread
From: Tobias Waldekranz @ 2025-02-21 21:31 UTC (permalink / raw)
  To: Ilias Apalodimas, Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Tom Rini, Anton Antonov,
	Bin Meng

On fre, feb 21, 2025 at 20:55, Ilias Apalodimas <ilias.apalodimas@linaro.org> wrote:
> Hi Sughosh
>
> This generally looks ok, but I don't love the idea of unconditionally
> preserving all slices regardless of their usage.
> Basically, if a user doesn't unmap that slice it will end in kernel
> memory. My fear is that someone will forget device sensitive data in a
> blkmap....
>
> On Mon, 3 Feb 2025 at 12:59, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>>
>> The EFI HTTP boot puts the ISO installer image at some location in
>> memory which needs to be added to the devicetree as persistent
>> memory (pmem) node. The OS installer then gets information about the
>> presence of this ISO image through the pmem node and proceeds with the
>> installation.
>>
>> In U-Boot, this ISO image gets mounted as a blkmap device, with a
>> memory mapped slice. Add a helper function which iterates through all
>> such memory mapped blkmap slices, and calls the FDT fixup function to
>> add the pmem node. Invoke this helper function as part of the DT fixup
>> which happens before booting the OS.
>>
>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
>> ---
>> Changes since V3:
>> * Move the definition of the helper function to the efi_helper.c
>> * Remove the region of the blkmap mem map device from the EFI memory
>>   map along with adding the pmem node
>>
>
> [...]
>
>> @@ -680,3 +683,52 @@ out:
>>
>>         return ret;
>>  }
>> +
>> +static int add_blkmap_pmem_nodes(void *fdt, struct blkmap *bm)
>> +{
>> +       int ret;
>> +       u32 size;
>> +       ulong addr;
>> +       efi_status_t status;
>> +       struct blkmap_mem *bmm;
>> +       struct blkmap_slice *bms;
>> +       struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
>> +
>> +       list_for_each_entry(bms, &bm->slices, node) {
>> +               if (bms->type != BLKMAP_SLICE_MEM)
>> +                       continue;
>
> Can we convert the 'type' to 'preserve' and teach
> blkmap_create_ramdisk() to pass that flag?
> This way we can unconditionally pass it from EFI HTTP installers, and
> let the command line users decide if they want to preserve it.

This seems like the most reasonable approach to me as well.

Then we could add a single API like this:

int blkmap_foreach_pmem_slice(int (*cb)(void *ctx, void *addr, size_t size),
                              void *ctx);

Rather than exporting all internal details of every slice's
implementation in blkmap.h.

I.e., let the blkmap code deal with how to locate the slices of
interest, and keep the internal details away from the consumer of the
data.

With that added to blkmap.c, I think the rest of this patch reduces to
something like:

int add_pmem_node(void *fdt, void *addr, size_t size)
{
        return fdt_fixup_pmem_region(fdt, (ulong)addr, size);
}

int fdt_efi_pmem_setup(void *fdt)
{
        return blkmap_foreach_pmem_slice(add_pmem_node, fdt);
}


>
>> +
>> +               bmm = container_of(bms, struct blkmap_mem, slice);
>> +
>> +               addr = (ulong)(uintptr_t)bmm->addr;
>> +               size = (u32)bms->blkcnt << bd->log2blksz;
>> +
>> +               ret = fdt_fixup_pmem_region(fdt, addr, size);
>> +               if (ret)
>> +                       return ret;
>> +
>> +               status = efi_remove_memory_map(addr, size,
>> +                                              EFI_CONVENTIONAL_MEMORY);
>> +               if (status != EFI_SUCCESS)
>> +                       return -1;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>
>
> Thanks
> /Ilias

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2025-02-21 21:31 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-03 10:59 [PATCH v4 0/5] Add pmem node for preserving distro ISO's Sughosh Ganu
2025-02-03 10:59 ` [PATCH v4 1/5] fdt: add support for adding pmem nodes Sughosh Ganu
2025-02-21 18:37   ` Ilias Apalodimas
2025-02-03 10:59 ` [PATCH v4 2/5] efi_loader: add a function to remove memory from the EFI map Sughosh Ganu
2025-02-03 10:59 ` [PATCH v4 3/5] efi_loader: preserve installer images in pmem Sughosh Ganu
2025-02-03 10:59 ` [PATCH v4 4/5] blkmap: store type of blkmap slice in corresponding structure Sughosh Ganu
2025-02-21 18:39   ` Ilias Apalodimas
2025-02-03 10:59 ` [PATCH v4 5/5] blkmap: add pmem nodes for blkmap memory mapped slices Sughosh Ganu
2025-02-21 18:55   ` Ilias Apalodimas
2025-02-21 19:22     ` Heinrich Schuchardt
2025-02-21 19:33       ` Ilias Apalodimas
2025-02-21 21:31     ` Tobias Waldekranz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.