All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD
@ 2016-11-22 13:24 Patrick Delaunay
  2016-11-22 13:24 ` [U-Boot] [Resend RFC PATCH v1 1/3] add support of GPT partitioning " Patrick Delaunay
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Patrick Delaunay @ 2016-11-22 13:24 UTC (permalink / raw)
  To: u-boot


I have a request to support GPT over MTD to be able to have dynamic
MTD informations without u-Boot environment(CONFIG_ENV_IS_NOWHERE
is a other requirement of my project).

The idea is to use the GPT header to save partitioning information directly
in flash device (NOR or NAND), then the MTD variables are rebuild from
these GPT partitions and can be used by DISTRO to search bootable binary.

I make a first prototyping for this request but I want ask you if this
feature is acceptable for u-boot and if this patches, after some update
and cleanups, would be merged in u-boot mainline.
Do you see already some blocking points ?

- added code is under a new CONFIG : CONFIG_EFI_PARTITION_MTD
- for implementation details, see doc/README.gpt.mtd

TODO:
- split patch between core impact (disk/part_efi.c)
  and command update
- full support for modified command
  (today I limit the support for the command used by DISTRO macro)
- DISTRO macro update for automatic boot on GPT bootable partition
  found in MTD devices

the current level is tested manually on sandbox with :

> make O=sandbox
> sandbox/u-boot -d sandbox/arch/sandbox/dts/test.dtb

=> sf probe
SF: Detected M25P16 with page size 256 Bytes, erase size 64 KiB, total 2 MiB

=> setenv nor_part "name=part1,size=64KiB;name=part2,size=128KiB;\
   name=boot,type=linux,bootable,size=512KiB"
=> gpt write nor 0 $nor_part
Writing GPT: success!

=> part list nor 0
Part	Start LBA	End LBA		Name
	Attributes
	Type GUID
	Partition GUID
  1	0x00000080	0x000000ff	"part1"
	attrs:	0x0000000000000000
	type:	ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
	type:	data
	guid:	d117f98e-6f2c-0040-00b2-331a19f91cb2
  2	0x00000100	0x000001ff	"part2"
	attrs:	0x0000000000000000
	type:	ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
	type:	data
	guid:	25718777-d0ad-0000-8060-02cb591c9737
  3	0x00000200	0x000005ff	"boot"
	attrs:	0x0000000000000004
	type:	0fc63daf-8483-4772-8e79-3d69d8477de4
	type:	linux
	guid:	8a4bb8b4-e304-0040-0036-aff5c9c495b1

=> setenv mtdids "nor0=nor0"
=> setenv mtdparts "mtdparts="
=> mtdparts gpt nor0
=> mtdparts
device nor0 <nor0>, # parts = 3
 #: name		size		offset		mask_flags
 0: part1               0x00010000	0x00010000	0
 1: part2               0x00020000	0x00020000	0
 2: boot                0x00080000	0x00040000	0

active partition: nor0,0 - (part1) 0x00010000 @ 0x00010000

defaults:
mtdids  : none
mtdparts: none

=> part list nor 0 -bootable nor_boot_part
=> printenv nor_boot_part
nor_boot_part=3



Patrick Delaunay (3):
  add support of GPT partitioning over MTD
  uuid: remove dependency with io.h
  sandbox: GPT over MTD test

 Kconfig                   |  12 ++
 cmd/gpt.c                 |  98 +++++++--
 cmd/mtdparts.c            | 103 ++++++++-
 cmd/part.c                |  48 ++++-
 configs/sandbox_defconfig |   2 +
 disk/part_efi.c           | 526 +++++++++++++++++++++++++++++++++++++++++-----
 doc/README.gpt.mtd        | 189 +++++++++++++++++
 include/configs/sandbox.h |   7 +
 include/part.h            |  13 +-
 include/uuid.h            |   1 +
 lib/uuid.c                |  46 +++-
 11 files changed, 959 insertions(+), 86 deletions(-)
 create mode 100644 doc/README.gpt.mtd

-- 
1.9.1

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

* [U-Boot] [Resend RFC PATCH v1 1/3] add support of GPT partitioning over MTD
  2016-11-22 13:24 [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD Patrick Delaunay
@ 2016-11-22 13:24 ` Patrick Delaunay
  2016-11-24  2:20   ` Simon Glass
  2016-11-22 13:24 ` [U-Boot] [Resend RFC PATCH v1 2/3] uuid: remove dependency with io.h Patrick Delaunay
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Patrick Delaunay @ 2016-11-22 13:24 UTC (permalink / raw)
  To: u-boot

From: Patrick Delaunay <patrick.delaunay@st.com>

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Signed-off-by: Patrick Delaunay <patrick.delaunay73@gmail.com>
---

 Kconfig            |  12 ++
 cmd/gpt.c          |  98 ++++++++--
 cmd/mtdparts.c     | 103 ++++++++++-
 cmd/part.c         |  48 ++++-
 disk/part_efi.c    | 526 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 doc/README.gpt.mtd | 189 +++++++++++++++++++
 include/part.h     |  13 +-
 include/uuid.h     |   1 +
 lib/uuid.c         |  33 ++++
 9 files changed, 944 insertions(+), 79 deletions(-)
 create mode 100644 doc/README.gpt.mtd

diff --git a/Kconfig b/Kconfig
index 1263d0b..c2388e1 100644
--- a/Kconfig
+++ b/Kconfig
@@ -335,6 +335,18 @@ config ARCH_FIXUP_FDT
 
 endmenu		# Boot images
 
+config EFI_PARTITION_MTD
+	bool "Support GPT over MTD"
+	help
+	  The GPT partition is normally defined only for block device with
+	  built-in controller which manage flash translation layer
+	  This option activate the GPT partition support over RAW device
+	  using the MTD framework
+	  - manage partition over MTD devices (as flash: NOR and NAND)
+	  - extract MTD information
+	  - update command gpt, mtdparts and part
+	  NB: depends on EFI_PARTITION
+
 source "common/Kconfig"
 
 source "cmd/Kconfig"
diff --git a/cmd/gpt.c b/cmd/gpt.c
index 897596a..9e398e9 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -20,6 +20,10 @@
 #include <div64.h>
 #include <memalign.h>
 
+#ifdef CONFIG_EFI_PARTITION_MTD
+#include <linux/mtd/mtd.h>
+#endif
+
 #ifndef CONFIG_PARTITION_UUIDS
 #error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_GPT to be enabled
 #endif
@@ -168,7 +172,8 @@ static bool found_key(const char *str, const char *key)
  * @return - zero on success, otherwise error
  *
  */
-static int set_gpt_info(struct blk_desc *dev_desc,
+static int set_gpt_info(unsigned int lba,
+			unsigned int blksz,
 			const char *str_part,
 			char **str_disk_guid,
 			disk_partition_t **partitions,
@@ -183,8 +188,7 @@ static int set_gpt_info(struct blk_desc *dev_desc,
 	uint64_t size_ll, start_ll;
 	lbaint_t offset = 0;
 
-	debug("%s:  lba num: 0x%x %d\n", __func__,
-	      (unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba);
+	debug("%s:  lba num: 0x%x %d\n", __func__, lba, lba);
 
 	if (str_part == NULL)
 		return -1;
@@ -302,7 +306,7 @@ static int set_gpt_info(struct blk_desc *dev_desc,
 			parts[i].size = 0;
 		} else {
 			size_ll = ustrtoull(p, &p, 0);
-			parts[i].size = lldiv(size_ll, dev_desc->blksz);
+			parts[i].size = lldiv(size_ll, blksz);
 		}
 
 		free(val);
@@ -313,7 +317,7 @@ static int set_gpt_info(struct blk_desc *dev_desc,
 			if (extract_env(val, &p))
 				p = val;
 			start_ll = ustrtoull(p, &p, 0);
-			parts[i].start = lldiv(start_ll, dev_desc->blksz);
+			parts[i].start = lldiv(start_ll, blksz);
 			free(val);
 		}
 
@@ -337,6 +341,16 @@ err:
 	return errno;
 }
 
+static void print_gpt_info_err(int ret)
+{
+	if (ret == -1)
+		printf("No partition list provided\n");
+	if (ret == -2)
+		printf("Missing disk guid\n");
+	if ((ret == -3) || (ret == -4))
+		printf("Partition list incomplete\n");
+}
+
 static int gpt_default(struct blk_desc *blk_dev_desc, const char *str_part)
 {
 	int ret;
@@ -344,16 +358,13 @@ static int gpt_default(struct blk_desc *blk_dev_desc, const char *str_part)
 	u8 part_count = 0;
 	disk_partition_t *partitions = NULL;
 
+	if (!str_part)
+		return -1;
 	/* fill partitions */
-	ret = set_gpt_info(blk_dev_desc, str_part,
+	ret = set_gpt_info(blk_dev_desc->lba, blk_dev_desc->blksz, str_part,
 			&str_disk_guid, &partitions, &part_count);
 	if (ret) {
-		if (ret == -1)
-			printf("No partition list provided\n");
-		if (ret == -2)
-			printf("Missing disk guid\n");
-		if ((ret == -3) || (ret == -4))
-			printf("Partition list incomplete\n");
+		print_gpt_info_err(ret);
 		return -1;
 	}
 
@@ -376,7 +387,7 @@ static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)
 	int ret = 0;
 
 	/* fill partitions */
-	ret = set_gpt_info(blk_dev_desc, str_part,
+	ret = set_gpt_info(blk_dev_desc->lba, blk_dev_desc->blksz, str_part,
 			&str_disk_guid, &partitions, &part_count);
 	if (ret) {
 		if (ret == -1) {
@@ -402,6 +413,35 @@ static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)
 	return ret;
 }
 
+#ifdef CONFIG_EFI_PARTITION_MTD
+static int gpt_default_mtd(struct mtd_info *mtd_info, const char *str_part)
+{
+	int ret;
+	char *str_disk_guid;
+	u8 part_count = 0;
+	disk_partition_t *partitions = NULL;
+	unsigned int lba = lldiv(mtd_info->size, MTD_LBA_SIZE);
+
+	if (!str_part)
+		return -1;
+
+	/* fill partitions */
+	ret = set_gpt_info(lba, MTD_LBA_SIZE, str_part,
+			   &str_disk_guid, &partitions, &part_count);
+	if (ret) {
+		print_gpt_info_err(ret);
+		return -1;
+	}
+
+	/* save partitions layout to disk */
+	ret = gpt_restore_mtd(mtd_info, str_disk_guid, partitions, part_count);
+	free(str_disk_guid);
+	free(partitions);
+
+	return ret;
+}
+#endif
+
 /**
  * do_gpt(): Perform GPT operations
  *
@@ -418,6 +458,10 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	int dev = 0;
 	char *ep;
 	struct blk_desc *blk_dev_desc = NULL;
+#ifdef CONFIG_EFI_PARTITION_MTD
+	struct mtd_info *mtd_info = NULL;
+	char mtd_dev[16];
+#endif
 
 	if (argc < 4 || argc > 5)
 		return CMD_RET_USAGE;
@@ -428,17 +472,38 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		return CMD_RET_USAGE;
 	}
 	blk_dev_desc = blk_get_dev(argv[2], dev);
+#ifdef CONFIG_EFI_PARTITION_MTD
 	if (!blk_dev_desc) {
+			sprintf(mtd_dev, "%s%d", argv[2], dev);
+			mtd_info = get_mtd_device_nm(mtd_dev);
+			if (IS_ERR(mtd_info))
+				ret = CMD_RET_FAILURE;
+	}
+#else
+	if (!blk_dev_desc)
+		ret = CMD_RET_FAILURE;
+#endif
+	if (ret) {
 		printf("%s: %s dev %d NOT available\n",
 		       __func__, argv[2], dev);
-		return CMD_RET_FAILURE;
+		return ret;
 	}
 
 	if ((strcmp(argv[1], "write") == 0) && (argc == 5)) {
 		printf("Writing GPT: ");
-		ret = gpt_default(blk_dev_desc, argv[4]);
+		if (blk_dev_desc)
+			ret = gpt_default(blk_dev_desc, argv[4]);
+#ifdef CONFIG_EFI_PARTITION_MTD
+		else if (mtd_info)
+			ret = gpt_default_mtd(mtd_info, argv[4]);
+#endif
+		else
+			ret = CMD_RET_FAILURE;
 	} else if ((strcmp(argv[1], "verify") == 0)) {
-		ret = gpt_verify(blk_dev_desc, argv[4]);
+		if (blk_dev_desc)
+			ret = gpt_verify(blk_dev_desc, argv[4]);
+		else
+			ret = CMD_RET_FAILURE;
 		printf("Verify GPT: ");
 	} else {
 		return CMD_RET_USAGE;
@@ -451,6 +516,7 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	printf("success!\n");
 	return CMD_RET_SUCCESS;
+
 }
 
 U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
diff --git a/cmd/mtdparts.c b/cmd/mtdparts.c
index b9b160d..ed2065f 100644
--- a/cmd/mtdparts.c
+++ b/cmd/mtdparts.c
@@ -1933,6 +1933,7 @@ static int do_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	return 0;
 }
 
+#define PART_ADD_DESC_MAXLEN 64
 /**
  * Routine implementing u-boot mtdparts command. Initialize/update default global
  * partition list and process user partition request (list, add, del).
@@ -1966,6 +1967,97 @@ static int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc,
 		}
 	}
 
+#ifdef CONFIG_EFI_PARTITION_MTD
+	/* mtdparts gpt <mtd-dev> [GUID] */
+	if ((argc == 3 || argc == 4) && (strncmp(argv[1], "gpt", 3) == 0)) {
+		char tmpbuf[PART_ADD_DESC_MAXLEN];
+		u8 type, num;
+		struct mtdids *id;
+		int part_id;
+		struct mtd_info *mtd;
+		struct mtd_device *dev;
+		struct mtd_device *dev_tmp;
+		disk_partition_t info;
+#ifdef CONFIG_PARTITION_TYPE_GUID
+		char guid_str[UUID_STR_LEN + 1];
+		char *p_guid_filter = NULL;
+#endif
+		struct part_info *p;
+
+		if (argc == 4) {
+#ifdef CONFIG_PARTITION_TYPE_GUID
+			p_guid_filter = guid_str;
+			if (uuid_guid_parse_str(argv[3], guid_str)) {
+				printf("invalid type gui %s\n", argv[3]);
+				return 1;
+			}
+			debug("filtered type gui %s (%s)\n", argv[3], guid_str);
+#else
+			puts("type GUI not support\n");
+#endif
+		}
+
+		if (mtd_id_parse(argv[2], NULL, &type, &num) != 0) {
+			printf("invalid MTD device %s\n", argv[2]);
+			return 1;
+		}
+
+		/* this may be the first run, initialize lists if needed
+		   and make sure we are in sync with env variables */
+		mtdparts_init();
+		/* don't treat error (mtdparts can be empty) */
+
+		id = id_find(type, num);
+		if (id == NULL) {
+			printf("no such device %s defined in mtdids variable\n",
+			       argv[2]);
+			return 1;
+		}
+
+		if (get_mtd_info(type, num, &mtd) || (mtd == NULL)) {
+			printf("no such MTD device %s\n", argv[2]);
+			return 1;
+		}
+
+		for (part_id = 1; part_id <= GPT_ENTRY_NUMBERS; part_id++) {
+			if (part_get_info_efi_mtd(mtd, part_id, &info))
+				break; /* Stop for first non valid partition */
+
+#ifdef CONFIG_PARTITION_TYPE_GUID
+			if (p_guid_filter &&
+			    strcmp(p_guid_filter, info.type_guid))
+				continue;
+#endif
+
+			sprintf(tmpbuf, "%s:0x%llx@0x%llx(%s)",
+				id->mtd_id,
+				(u64)(info.size * info.blksz),
+				(u64)(info.start * info.blksz),
+				info.name);
+			debug("add tmpbuf: %s\n", tmpbuf);
+
+			if ((device_parse(tmpbuf, NULL, &dev) != 0) || (!dev))
+				return 1;
+
+			debug("+ %s\t%d\t%s\n", MTD_DEV_TYPE(type), num,
+			      id->mtd_id);
+
+			p = list_entry(dev->parts.next, struct part_info, link);
+
+			dev_tmp = device_find(type, num);
+
+			if (dev_tmp == NULL)
+				device_add(dev);
+			else if (part_add(dev_tmp, p) != 0)
+				return 1;
+		}
+		if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
+			printf("generated mtdparts too long, resetting to null\n");
+			return 1;
+		}
+		return 0;
+	}
+#endif
 	/* make sure we are in sync with env variables */
 	if (mtdparts_init() != 0)
 		return 1;
@@ -1977,7 +2069,6 @@ static int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc,
 
 	/* mtdparts add <mtd-dev> <size>[@<offset>] <name> [ro] */
 	if (((argc == 5) || (argc == 6)) && (strncmp(argv[1], "add", 3) == 0)) {
-#define PART_ADD_DESC_MAXLEN 64
 		char tmpbuf[PART_ADD_DESC_MAXLEN];
 #if defined(CONFIG_CMD_MTDPARTS_SPREAD)
 		struct mtd_info *mtd;
@@ -2083,6 +2174,10 @@ static char mtdparts_help_text[] =
 	"mtdparts add.spread <mtd-dev> <size>[@<offset>] [<name>] [ro]\n"
 	"    - add partition, padding size by skipping bad blocks\n"
 #endif
+#ifdef CONFIG_EFI_PARTITION_MTD
+	"mtdparts gpt <mtd-dev> [<GUID>]\n"
+	"    - add partitions for device from gpt, filterd by GUID type\n"
+#endif
 	"mtdparts default\n"
 	"    - reset partition table to defaults\n"
 #if defined(CONFIG_CMD_MTDPARTS_SPREAD)
@@ -2112,7 +2207,11 @@ static char mtdparts_help_text[] =
 	"<size>     := standard linux memsize OR '-' to denote all remaining space\n"
 	"<offset>   := partition start offset within the device\n"
 	"<name>     := '(' NAME ')'\n"
-	"<ro-flag>  := when set to 'ro' makes partition read-only (not used, passed to kernel)";
+	"<ro-flag>  := when set to 'ro' makes partition read-only (not used, passed to kernel)"
+#ifdef CONFIG_EFI_PARTITION_MTD
+	"<GUID>     := partition guid"
+#endif
+	;
 #endif
 
 U_BOOT_CMD(
diff --git a/cmd/part.c b/cmd/part.c
index 414031e..4ea0fb2 100644
--- a/cmd/part.c
+++ b/cmd/part.c
@@ -52,11 +52,15 @@ static int do_part_uuid(int argc, char * const argv[])
 static int do_part_list(int argc, char * const argv[])
 {
 	int ret;
-	struct blk_desc *desc;
+	struct blk_desc *desc = NULL;
 	char *var = NULL;
 	bool bootable = false;
 	int i;
 
+#ifdef CONFIG_EFI_PARTITION_MTD
+	struct mtd_info *mtd = NULL;
+	char mtd_dev[16];
+#endif
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
@@ -81,10 +85,19 @@ static int do_part_list(int argc, char * const argv[])
 			return CMD_RET_USAGE;
 	}
 
-	ret = blk_get_device_by_str(argv[0], argv[1], &desc);
-	if (ret < 0)
-		return 1;
-
+#ifdef CONFIG_EFI_PARTITION_MTD
+	if ((strlen(argv[0]) + strlen(argv[1])) < sizeof(mtd_dev)) {
+		sprintf(mtd_dev, "%s%s", argv[0], argv[1]);
+		mtd = get_mtd_device_nm(mtd_dev);
+	}
+	if (IS_ERR(mtd)) {
+#endif
+		ret = blk_get_device_by_str(argv[0], argv[1], &desc);
+		if (ret < 0)
+			return 1;
+#ifdef CONFIG_EFI_PARTITION_MTD
+	}
+#endif
 	if (var != NULL) {
 		int p;
 		char str[512] = { '\0', };
@@ -92,10 +105,21 @@ static int do_part_list(int argc, char * const argv[])
 
 		for (p = 1; p < 128; p++) {
 			char t[5];
-			int r = part_get_info(desc, p, &info);
+			int r;
+			if (desc) {
+				r = part_get_info(desc, p, &info);
 
-			if (r != 0)
-				continue;
+				if (r != 0)
+					continue;
+			}
+#ifdef CONFIG_EFI_PARTITION_MTD
+			else {
+				r = part_get_info_efi_mtd(mtd, p, &info);
+				/* Stop for first non valid partition */
+				if (r != 0)
+					break;
+			}
+#endif
 
 			if (bootable && !info.bootable)
 				continue;
@@ -107,8 +131,14 @@ static int do_part_list(int argc, char * const argv[])
 		return 0;
 	}
 
+#ifndef CONFIG_EFI_PARTITION_MTD
 	part_print(desc);
-
+#else
+	if (desc)
+		part_print(desc);
+	else
+		part_print_efi_mtd(mtd);
+#endif
 	return 0;
 }
 
diff --git a/disk/part_efi.c b/disk/part_efi.c
index 1924338..6ce64f6 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -10,6 +10,7 @@
  *   when CONFIG_SYS_64BIT_LBA is not defined, lbaint_t is 32 bits; this
  *   limits the maximum size of addressable storage to < 2 Terra Bytes
  */
+
 #include <asm/unaligned.h>
 #include <common.h>
 #include <command.h>
@@ -20,6 +21,10 @@
 #include <part_efi.h>
 #include <linux/ctype.h>
 
+#ifdef CONFIG_EFI_PARTITION_MTD
+#include <linux/mtd/mtd.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef HAVE_BLOCK_DEVICE
@@ -159,11 +164,12 @@ static void prepare_backup_gpt_header(gpt_header *gpt_h)
 	uint64_t val;
 
 	/* recalculate the values for the Backup GPT Header */
-	val = le64_to_cpu(gpt_h->my_lba);
-	gpt_h->my_lba = gpt_h->alternate_lba;
-	gpt_h->alternate_lba = cpu_to_le64(val);
-	gpt_h->partition_entry_lba =
-			cpu_to_le64(le64_to_cpu(gpt_h->last_usable_lba) + 1);
+	val = le64_to_cpu(gpt_h->alternate_lba);
+	gpt_h->alternate_lba = gpt_h->my_lba;
+	gpt_h->my_lba = cpu_to_le64(val);
+	val -= (le32_to_cpu(gpt_h->num_partition_entries) *
+		le32_to_cpu(gpt_h->sizeof_partition_entry));
+	gpt_h->partition_entry_lba = cpu_to_le64(val);
 	gpt_h->header_crc32 = 0;
 
 	calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
@@ -171,36 +177,16 @@ static void prepare_backup_gpt_header(gpt_header *gpt_h)
 	gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
 }
 
+
 #ifdef CONFIG_EFI_PARTITION
-/*
- * Public Functions (include/part.h)
- */
 
-void part_print_efi(struct blk_desc *dev_desc)
+static void part_print_gpt(gpt_header *gpt_head,
+			   gpt_entry *gpt_pte)
 {
-	ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
-	gpt_entry *gpt_pte = NULL;
 	int i = 0;
 	char uuid[37];
 	unsigned char *uuid_bin;
 
-	/* This function validates AND fills in the GPT header and PTE */
-	if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
-			 gpt_head, &gpt_pte) != 1) {
-		printf("%s: *** ERROR: Invalid GPT ***\n", __func__);
-		if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
-				 gpt_head, &gpt_pte) != 1) {
-			printf("%s: *** ERROR: Invalid Backup GPT ***\n",
-			       __func__);
-			return;
-		} else {
-			printf("%s: ***        Using Backup GPT ***\n",
-			       __func__);
-		}
-	}
-
-	debug("%s: gpt-entry at %p\n", __func__, gpt_pte);
-
 	printf("Part\tStart LBA\tEnd LBA\t\tName\n");
 	printf("\tAttributes\n");
 	printf("\tType GUID\n");
@@ -227,6 +213,60 @@ void part_print_efi(struct blk_desc *dev_desc)
 		uuid_bin_to_str(uuid_bin, uuid, UUID_STR_FORMAT_GUID);
 		printf("\tguid:\t%s\n", uuid);
 	}
+}
+
+static void part_get_disk_info(int part, unsigned int blksz,
+			       gpt_entry *gpt_pte, disk_partition_t *info)
+{
+	/* The 'lbaint_t' casting may limit the maximum disk size to 2 TB */
+	info->start = (lbaint_t)le64_to_cpu(gpt_pte[part - 1].starting_lba);
+	/* The ending LBA is inclusive, to calculate size, add 1 to it */
+	info->size = (lbaint_t)le64_to_cpu(gpt_pte[part - 1].ending_lba) + 1
+		     - info->start;
+	info->blksz = blksz;
+
+	sprintf((char *)info->name, "%s", print_efiname(&gpt_pte[part - 1]));
+	strcpy((char *)info->type, "U-Boot");
+	info->bootable = is_bootable(&gpt_pte[part - 1]);
+#ifdef CONFIG_PARTITION_UUIDS
+	uuid_bin_to_str(gpt_pte[part - 1].unique_partition_guid.b, info->uuid,
+			UUID_STR_FORMAT_GUID);
+#endif
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	uuid_bin_to_str(gpt_pte[part - 1].partition_type_guid.b,
+			info->type_guid, UUID_STR_FORMAT_GUID);
+#endif
+
+	debug("%s: start 0x" LBAF ", size 0x" LBAF ", name %s\n", __func__,
+	      info->start, info->size, info->name);
+}
+
+/*
+ * Public Functions (include/part.h)
+ */
+void part_print_efi(struct blk_desc *dev_desc)
+{
+	ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
+	gpt_entry *gpt_pte = NULL;
+
+	/* This function validates AND fills in the GPT header and PTE */
+	if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
+			 gpt_head, &gpt_pte) != 1) {
+		printf("%s: *** ERROR: Invalid GPT ***\n", __func__);
+		if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
+				 gpt_head, &gpt_pte) != 1) {
+			printf("%s: *** ERROR: Invalid Backup GPT ***\n",
+			       __func__);
+			return;
+		} else {
+			printf("%s: ***        Using Backup GPT ***\n",
+			       __func__);
+		}
+	}
+
+	debug("%s: gpt-entry at %p\n", __func__, gpt_pte);
+
+	part_print_gpt(gpt_head, gpt_pte);
 
 	/* Remember to free pte */
 	free(gpt_pte);
@@ -268,28 +308,7 @@ int part_get_info_efi(struct blk_desc *dev_desc, int part,
 		return -1;
 	}
 
-	/* The 'lbaint_t' casting may limit the maximum disk size to 2 TB */
-	info->start = (lbaint_t)le64_to_cpu(gpt_pte[part - 1].starting_lba);
-	/* The ending LBA is inclusive, to calculate size, add 1 to it */
-	info->size = (lbaint_t)le64_to_cpu(gpt_pte[part - 1].ending_lba) + 1
-		     - info->start;
-	info->blksz = dev_desc->blksz;
-
-	sprintf((char *)info->name, "%s",
-			print_efiname(&gpt_pte[part - 1]));
-	strcpy((char *)info->type, "U-Boot");
-	info->bootable = is_bootable(&gpt_pte[part - 1]);
-#ifdef CONFIG_PARTITION_UUIDS
-	uuid_bin_to_str(gpt_pte[part - 1].unique_partition_guid.b, info->uuid,
-			UUID_STR_FORMAT_GUID);
-#endif
-#ifdef CONFIG_PARTITION_TYPE_GUID
-	uuid_bin_to_str(gpt_pte[part - 1].partition_type_guid.b,
-			info->type_guid, UUID_STR_FORMAT_GUID);
-#endif
-
-	debug("%s: start 0x" LBAF ", size 0x" LBAF ", name %s\n", __func__,
-	      info->start, info->size, info->name);
+	part_get_disk_info(part, dev_desc->blksz, gpt_pte, info);
 
 	/* Remember to free pte */
 	free(gpt_pte);
@@ -945,3 +964,410 @@ U_BOOT_PART_TYPE(a_efi) = {
 	.test		= part_test_efi,
 };
 #endif
+#ifdef CONFIG_EFI_PARTITION_MTD
+/*
+ * Private function prototypes
+ */
+
+static int is_gpt_valid_mtd(struct mtd_info *mtd,
+			    void **buf,
+			    gpt_header **pgpt_head,
+			    gpt_entry **pgpt_pte);
+
+static int gpt_fill_header_mtd(struct mtd_info *mtd, gpt_header *gpt_h,
+			       char *str_guid, int parts_count);
+
+/**
+ * is_gpt_valid_mtd() - tests one GPT header and PTEs for validity
+ *
+ * lba is the logical block address of the GPT header to test
+ * pgpt_head is a GPT header ptr, filled on return.
+ * pgpt_pte is a PTEs ptr, filled on return.
+ *
+ * Description: returns 1 if valid,  0 on error.
+ * If valid, returns pointers to PTEs.
+ */
+
+static int is_gpt_valid_mtd(struct mtd_info *mtd,
+			    void **buf,
+			    gpt_header **pgpt_head,
+			    gpt_entry **pgpt_pte)
+{
+	gpt_header *gpt_h;
+	gpt_entry *gpt_e;
+	uint32_t size;
+	uint64_t offset;
+	int ret;
+	size_t retlen;
+	lbaint_t lba, my_lba;
+	u32 gpt_e_size = PAD_SIZE(GPT_ENTRY_NUMBERS * sizeof(gpt_entry),
+				  MTD_LBA_SIZE);
+
+	if (!mtd || !pgpt_head || !pgpt_pte) {
+		printf("%s: Invalid Argument(s)\n", __func__);
+		return 0;
+	}
+	*pgpt_head = NULL;
+	*pgpt_pte = NULL;
+	size = gpt_e_size + 2 * MTD_LBA_SIZE;
+	*buf = malloc(size);
+
+	/* skip bad block */
+	offset = 0;
+	while (mtd_block_isbad(mtd, offset)) {
+		printf("bad block at 0x%llx\n", offset);
+		offset += mtd->erasesize;
+		if (offset >= mtd->size)
+			goto error;
+	}
+
+	debug("primary offset = 0x%llx\n", offset);
+	/* Read primary GPT from device */
+	ret = mtd_read(mtd, offset, size, &retlen, *buf);
+	if (ret || (retlen != size)) {
+		printf("*** ERROR: Can't read primary GPT ***\n");
+		goto error;
+	}
+
+	lba = lldiv(mtd->size, MTD_LBA_SIZE);
+
+	/* determine start of GPT Header & Entries in the buffer */
+	gpt_h = *buf + (1 * MTD_LBA_SIZE);
+	gpt_e = *buf + (2 * MTD_LBA_SIZE);
+	my_lba = lldiv(offset, MTD_LBA_SIZE) + GPT_PRIMARY_PARTITION_TABLE_LBA;
+
+	if (!validate_gpt_header(gpt_h, my_lba, lba) &&
+	    !validate_gpt_entries(gpt_h, gpt_e))
+		goto end;
+
+	printf("%s: *** ERROR: Invalid GPT ***\n", __func__);
+
+	/* skip bad block */
+	offset = mtd->size;
+	while (mtd_block_isbad(mtd, offset - mtd->erasesize)) {
+		offset -= mtd->erasesize;
+		printf("bad block at 0x%llx\n", offset);
+		if (offset <= mtd->erasesize)
+			goto error;
+	}
+
+	/* Read backup GPT from device : end of the last valid block */
+	my_lba = lldiv(offset, MTD_LBA_SIZE) - 1;
+	size = gpt_e_size + MTD_LBA_SIZE;
+	offset -= size;
+
+	debug("backup offset = 0x%llx\n", offset);
+	ret = mtd_read(mtd, offset, size, &retlen, *buf);
+	if (ret || (retlen != size)) {
+		printf("*** ERROR: Can't read backup GPT ***\n");
+		goto error;
+	}
+
+	/* determine start of GPT Header & Entries in the buffer */
+	gpt_h = *buf + gpt_e_size;
+	gpt_e = *buf;
+
+	if (validate_gpt_header(gpt_h, my_lba, lba) ||
+	    validate_gpt_entries(gpt_h, gpt_e)) {
+		printf("%s: *** ERROR: Invalid Backup GPT ***\n",
+		       __func__);
+		goto error;
+	}
+	printf("%s: ***        Using Backup GPT ***\n",
+	       __func__);
+
+end:
+	/* We're done, all's well */
+	*pgpt_head = gpt_h;
+	*pgpt_pte = gpt_e;
+	return 1;
+
+error:
+	free(*buf);
+	return 0;
+}
+
+
+static int gpt_fill_header_mtd(struct mtd_info *mtd, gpt_header *gpt_h,
+			       char *str_guid, int parts_count)
+{
+	uint32_t erasesize;
+	uint64_t offset_p_gpt, offset_s_gpt;
+	__le64 my_lba;
+	__le64 alternate_lba;
+	u32 gpt_e_size = PAD_SIZE(GPT_ENTRY_NUMBERS * sizeof(gpt_entry),
+				  MTD_LBA_SIZE);
+
+	/* one mtd block is not enought for MBR and GPT */
+	if ((gpt_e_size + 2 * MTD_LBA_SIZE) > mtd->erasesize)
+		return -1;
+
+	erasesize = lldiv(mtd->erasesize, MTD_LBA_SIZE);
+
+	/* GPT location : skip bad block */
+	offset_p_gpt = 0;
+	while (mtd_block_isbad(mtd, offset_p_gpt)) {
+		printf("bad block at 0x%llx\n", offset_p_gpt);
+		offset_p_gpt += mtd->erasesize;
+		if (offset_p_gpt >= mtd->size)
+			return -1;
+	}
+	/* primary GPT : 17 first LBA of last good block */
+	my_lba = lldiv(offset_p_gpt, MTD_LBA_SIZE) + 1;
+
+	offset_s_gpt = mtd->size;
+	while (mtd_block_isbad(mtd, offset_s_gpt - mtd->erasesize)) {
+		offset_s_gpt -= mtd->erasesize;
+		printf("bad block at 0x%llx\n", offset_s_gpt);
+		if (offset_s_gpt <= mtd->erasesize)
+			return -1;
+	}
+	/* secondary GPT : 16 LBA of last good block */
+	alternate_lba = lldiv(offset_s_gpt, MTD_LBA_SIZE) - 1;
+
+	/* only one good block (primary and secondary on same block) */
+	if (offset_p_gpt == ((offset_s_gpt - mtd->erasesize)))
+		return -1;
+
+	gpt_h->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
+	gpt_h->revision = cpu_to_le32(GPT_HEADER_REVISION_V1);
+	gpt_h->header_size = cpu_to_le32(sizeof(gpt_header));
+	gpt_h->my_lba = cpu_to_le64(my_lba);
+	gpt_h->alternate_lba = cpu_to_le64(alternate_lba);
+	gpt_h->first_usable_lba = cpu_to_le64(my_lba - 1 + erasesize);
+	gpt_h->last_usable_lba = cpu_to_le64(alternate_lba - erasesize);
+	gpt_h->partition_entry_lba = cpu_to_le64(my_lba + 1);
+	gpt_h->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS);
+	gpt_h->sizeof_partition_entry = cpu_to_le32(sizeof(gpt_entry));
+	gpt_h->header_crc32 = 0;
+	gpt_h->partition_entry_array_crc32 = 0;
+
+	if (uuid_str_to_bin(str_guid, gpt_h->disk_guid.b, UUID_STR_FORMAT_GUID))
+		return -1;
+
+	return 0;
+}
+
+static int mtd_erase_write_block(struct mtd_info *mtd,
+				 uint64_t offset,
+				 void *buf,
+				 size_t len)
+{
+	struct erase_info erase;
+	int ret;
+	size_t retlen;
+	u_char *verify_buf;
+
+	erase.mtd = mtd;
+	erase.len  = mtd->erasesize;
+	erase.addr = offset & ~(mtd->erasesize - 1); /* aligned erase offset */
+	erase.callback = NULL;
+
+	debug(" erase at 0x%llx\n", erase.addr);
+	ret = mtd_erase(mtd, &erase);
+	if (ret != 0) {
+		printf("** mark bad block 0x%llx on MTD device %s **\n",
+		       erase.addr, mtd->name);
+		ret = mtd_block_markbad(mtd, erase.addr);
+		if (ret)
+			error("cannot mark bad at offset 0x%llx, error %d",
+			      offset, ret);
+		return -1;
+	}
+
+	/* mtd write */
+	ret = mtd_write(mtd, offset, len, &retlen, buf);
+	if (ret != 0 || retlen != len) {
+		error("Write error %d\n", ret);
+		return -2;
+	}
+
+	verify_buf = malloc(len);
+	ret = mtd_read(mtd, offset, len, &retlen, verify_buf);
+	if (ret) {
+		error("Read failed 0x%x, %d\n", (u32)offset, ret);
+		free(verify_buf);
+		return -3;
+	}
+
+	if (memcmp(buf, verify_buf, len)) {
+		error("Verify failed at 0x%x\n", (u32)offset);
+		return -4;
+	}
+
+	free(verify_buf);
+
+	return 0;
+}
+
+static int write_gpt_table_mtd(struct mtd_info *mtd,
+			       gpt_header *gpt_h, gpt_entry *gpt_e)
+{
+	const int pte_blk_cnt = PAD_COUNT((gpt_h->num_partition_entries
+					   * sizeof(gpt_entry)), MTD_LBA_SIZE);
+	u32 calc_crc32;
+	uint64_t offset;
+	void *buf;
+	legacy_mbr *p_mbr;
+	u32 gpt_e_size = PAD_SIZE(GPT_ENTRY_NUMBERS * sizeof(gpt_entry),
+				  MTD_LBA_SIZE);
+	u32 buf_size, p_size, s_size;
+
+	p_size = gpt_e_size + 2 * MTD_LBA_SIZE;
+	s_size = roundup(gpt_e_size + MTD_LBA_SIZE, mtd->writesize);
+	buf_size = max(p_size, s_size);
+	buf = malloc(buf_size);
+
+	/* Generate CRC for the Primary GPT Header */
+	calc_crc32 = efi_crc32((const unsigned char *)gpt_e,
+			      le32_to_cpu(gpt_h->num_partition_entries) *
+			      le32_to_cpu(gpt_h->sizeof_partition_entry));
+	gpt_h->partition_entry_array_crc32 = cpu_to_le32(calc_crc32);
+
+	calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
+			      le32_to_cpu(gpt_h->header_size));
+	gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
+
+	memset(buf, 0x0, p_size);
+
+	/* Setup the Protective MBR */
+	p_mbr = buf;
+	p_mbr->signature = MSDOS_MBR_SIGNATURE;
+	p_mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
+	p_mbr->partition_record[0].start_sect = 1;
+	p_mbr->partition_record[0].nr_sects = (u32) lldiv(mtd->size,
+					      MTD_LBA_SIZE) - 1;
+
+	/* GPT Header (1 block) */
+	memcpy(buf + (GPT_PRIMARY_PARTITION_TABLE_LBA * MTD_LBA_SIZE),
+	       gpt_h, sizeof(*gpt_h));
+	memcpy(buf + ((GPT_PRIMARY_PARTITION_TABLE_LBA + 1) * MTD_LBA_SIZE),
+	       gpt_e, sizeof(gpt_entry) * pte_blk_cnt);
+
+	offset = ALIGN(le64_to_cpu(gpt_h->my_lba -
+				   GPT_PRIMARY_PARTITION_TABLE_LBA)
+		       * MTD_LBA_SIZE,
+		       mtd->erasesize);
+
+	debug("primary offset = 0x%llx\n", offset);
+
+	if (mtd_erase_write_block(mtd, offset, buf, p_size))
+		goto err;
+
+	/* backup GPT */
+	prepare_backup_gpt_header(gpt_h);
+
+	memset(buf, 0x0, s_size);
+
+	offset = (le64_to_cpu(gpt_h->my_lba) + 1) * MTD_LBA_SIZE - s_size;
+	memcpy(buf + s_size - MTD_LBA_SIZE, gpt_h, sizeof(*gpt_h));
+	memcpy(buf + s_size - MTD_LBA_SIZE - gpt_e_size,
+	       gpt_e, sizeof(gpt_entry) * pte_blk_cnt);
+
+
+	debug("backup offset = 0x%llx\n", offset);
+
+	if (mtd_erase_write_block(mtd, offset, buf, s_size))
+		goto err;
+
+	free(buf);
+	debug("GPT successfully written to MTD device!\n");
+	return 0;
+
+ err:
+	free(buf);
+	printf("** Can't write to MTD device %s **\n", mtd->name);
+	return -1;
+}
+
+/*
+ * Public Functions (include/part.h)
+ */
+
+int gpt_restore_mtd(struct mtd_info *mtd, char *str_disk_guid,
+		    disk_partition_t *partitions, int parts_count)
+{
+	int ret;
+	gpt_header *gpt_h = calloc(1, PAD_SIZE(sizeof(gpt_header),
+					       MTD_LBA_SIZE));
+	gpt_entry *gpt_e;
+
+	if (gpt_h == NULL) {
+		printf("%s: calloc failed!\n", __func__);
+		return -1;
+	}
+
+	gpt_e = calloc(1, PAD_SIZE(GPT_ENTRY_NUMBERS
+				   * sizeof(gpt_entry),
+				   MTD_LBA_SIZE));
+	if (gpt_e == NULL) {
+		printf("%s: calloc failed!\n", __func__);
+		free(gpt_h);
+		return -1;
+	}
+
+	/* Generate Primary GPT header (LBA1) */
+	ret = gpt_fill_header_mtd(mtd, gpt_h, str_disk_guid, parts_count);
+	if (ret)
+		goto err;
+
+	/* Generate partition entries */
+	ret = gpt_fill_pte(gpt_h, gpt_e, partitions, parts_count);
+	if (ret)
+		goto err;
+
+	/* Write GPT partition table */
+	ret = write_gpt_table_mtd(mtd, gpt_h, gpt_e);
+
+err:
+	free(gpt_e);
+	free(gpt_h);
+	return ret;
+}
+
+void part_print_efi_mtd(struct mtd_info *mtd)
+{
+	    void *buf;
+	    gpt_header *gpt_head;
+	    gpt_entry *gpt_pte;
+
+	if (!is_gpt_valid_mtd(mtd, &buf, &gpt_head, &gpt_pte))
+			return;
+
+	part_print_gpt(gpt_head, gpt_pte);
+
+	/* Remember to free buffer */
+	free(buf);
+	return;
+}
+
+int part_get_info_efi_mtd(struct mtd_info *mtd, int part,
+			  disk_partition_t *info)
+{
+	void *buf;
+	gpt_header *gpt_head;
+	gpt_entry *gpt_pte;
+
+	if (!mtd || !info || part < 1) {
+		printf("%s: Invalid Argument(s)\n", __func__);
+		return -1;
+	}
+
+	if (!is_gpt_valid_mtd(mtd, &buf, &gpt_head, &gpt_pte))
+			return -1;
+
+	if (part > le32_to_cpu(gpt_head->num_partition_entries) ||
+	    !is_pte_valid(&gpt_pte[part - 1])) {
+		debug("%s: *** ERROR: Invalid partition number %d ***\n",
+		      __func__, part);
+		free(buf);
+		return -1;
+	}
+
+	part_get_disk_info(part, MTD_LBA_SIZE, gpt_pte, info);
+
+	/* Remember to free buffer */
+	free(buf);
+	return 0;
+}
+#endif /* CONFIG_EFI_PARTITION_MTD */
diff --git a/doc/README.gpt.mtd b/doc/README.gpt.mtd
new file mode 100644
index 0000000..d7b21f3
--- /dev/null
+++ b/doc/README.gpt.mtd
@@ -0,0 +1,189 @@
+#
+#
+# SPDX-License-Identifier:	GPL-2.0+
+
+Glossary:
+========
+- GPT (GUID Partition Table) - it is the EFI standard part
+- MTD (Memory Technology Device) - abstraction layer for RAW flah device
+
+Introduction:
+=============
+This document describes the GPT support on MTD and usage of
+the associated command in u-boot.
+
+The GPT is normally defined only for block device with built-in controller
+which manage flash translation layer (FTL) as MMC, SD, USB or ATA.
+
+For raw flash device, the MTD partionning are usally defined in U-Boot
+environment and provided to kernel (see mtdparts command).
+
+U-Boot support GPT for MTD device to save the partition informations of
+raw flash device directly in this device (usefull for CONFIG_ENV_IS_NOWHERE)
+and to use these informations to support MTD devices in DISTRO without
+hardcoded MTD partitioning in U-Boot environment
+
+The GPT support on top of MTD is defined under CONFIG_EFI_PARTITION_MTD.
+
+PS: DISTRO boot cmd is no yet updated
+
+GPT on MTD brief explanation:
+=============================
+
+The GPT standard is respected (header and field meaning).
+
+The GPT header and each partition need to be eraseblock-align to allow
+individual udpate for header or partiton.
+
+The primary and the backup GPT header are located in the first and
+the last -not bad- eraseblock.
+
+We assume that one eraseblock is enought for MBR and GPT header
+(size = 17 KB for 128 entry)
+
+So it not compatible with the feature CONFIG_SPI_FLASH_USE_4K_SECTORS
+
+	Layout:
+	-------
+
+	----------------------------------------------------------
+	LBA 0-33       |Protective MBR + Primary GPT     | 1rst eraseblock
+	--------------------------------------------------
+	LBA 34	       | (not used)                      |
+	LBA N-1	       |                                 |
+	----------------------------------------------------------
+	LBA N          |Partition 1                      | 2nd eraseblock
+	               |                                 | = first usable
+	               -----------------------------------
+	               |Partition 2                      |
+	               |                                 |
+	                ----------------------------------- last-1 eraseblock
+	LBA M	       |Partition n                      | = last usable
+	----------------------------------------------------------
+	LBA M+1	       | (not used)                      | last eraseblock
+	LBA -35	       |                                 |
+	--------------------------------------------------
+	LBA -1 to -34  |Backup GPT Header                |
+	----------------------------------------------------------
+
+	NB: this layout change (LBA0 and LBA-1) if bad block are present
+
+	GPT header:
+	-----------
+
+	for details of GPT header, see README.gpt
+
+	"Current LBA" and "Backup LBA" give the location of the primary and
+	secondary GPT header.
+
+	All the bad block are detected and skipped when the GPT header is build.
+
+	For Primary GPT:
+
+	- Current LBA = 2nd LBA of the first good eraseblock
+
+	- Backup LBA = Last LBA of the last good block
+
+	- First usable LBA = First LBA of the first usable eraseblock
+	                     i.e. the block after primary GPT one
+	                     Current LBA - 1 + erase block size
+
+	- Last usable LBA = Last LBA of the last usable eraseblock
+	                    i.e. the block before backup GPT one
+	                    Backup LBA - erase block size
+
+	Bad Block management (NAND):
+	---------------------------
+	As the bad blocks are skipped, Current LBA and Backup LBA give the real
+	location of primary and backup GPT header
+
+	warning: the first and the last usable LBA are not guarantee
+	         to be in a good block
+
+
+	Typically, the last 4 erase blocks for NAND are used for the bad block
+	table (BBT, see bbt_options and NAND_BBT_USE_FLASH).
+	They are indicated bad by MTD framework and they are also skipped.
+	So the layout for NAND with bad :
+
+	NAND layout with bad blocks:
+	----------------------------------------------------------
+	N * BAD (*)   |                                 | skipped bad
+	-----------------------------------------------------------
+	               |Protective MBR                   | 1rst good eraseblock
+	               |Primary GPT Header               |
+	               |                                 |
+	               -------------------------------------------
+	               |                                 | = first usable
+	               |                                 |
+	               |  Partitions                     |
+	               |                                 |
+	               |                                 | = last usable
+	               -------------------------------------------
+	               |                                 |
+	               |Backup GPT Header                | last good eraseblock
+	----------------------------------------------------------
+	M * BAD (*)    |                                 | skipped bad
+	----------------------------------------------------------
+	BBT => BAD (*) |                                 | skipped 4 blocks
+	----------------------------------------------------------
+	(*) BBT and block marked bad are skipped
+
+
+Drawbacks:
+==========
+1.  2 eraseblocks are used in the device just to save the GPT headers
+    (primary and backup)
+
+2.  for device with back block (NAND), any read request can disturb the device
+    so the GPT header should be refreshed when one fixable bit-flip ECC error is
+    detected...
+    but it is not the case today
+
+3.  for gpt write the eraseblock for the primary or backup GPT header
+    (expected good) can become bad for the erase request
+
+    And then u-boot will mark this block bad
+
+    In this case the first / last usable LBA need to change and to skip the new
+    bad block, so header need to be recomputed
+    => the requested gpt write command failed to force new request
+       PS: the next request will work (skip the new bad block)
+
+    And as the first / last usable LBA can change the same partionning after
+    the block is marked bad
+
+GPT on MTD commands:
+====================
+some command are modified to support GPT on MTD devices under CONFIG_EFI_PARTITION_MTD
+
+	Creating GPT on MTD partitions:
+	-------------------------------
+
+	1. Define partition layout in the environment.
+	     "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...;
+		name=kernel,size=60MiB,uuid=...;"
+
+	2. From u-boot prompt type:
+	   gpt write nand 0 $partitions
+	   gpt write nor 0 $partitions
+
+	List GPT partition on MTD:
+	---------------------------------
+	part list nand 0
+	part list nor 0
+
+	to find bootable partition (used for distro):
+
+	part list nand 0 -bootable nand_boot_part
+	part list nor 0 -bootable nor_boot_part
+
+	NB: bootable partition can be used with UBIFS
+
+	Generate MTD partitions from GPT:
+	---------------------------------
+	mtdparts gpt nand0
+	mtdparts gpt nor0
+
+	Then to check mtd partition created with:
+	mtdparts
diff --git a/include/part.h b/include/part.h
index 0979005..0660c27 100644
--- a/include/part.h
+++ b/include/part.h
@@ -9,6 +9,7 @@
 
 #include <blk.h>
 #include <ide.h>
+#include <linux/mtd/mtd.h>
 
 struct block_drvr {
 	char *name;
@@ -308,7 +309,6 @@ int gpt_fill_header(struct blk_desc *dev_desc, gpt_header *gpt_h,
  */
 int gpt_restore(struct blk_desc *dev_desc, char *str_disk_guid,
 		disk_partition_t *partitions, const int parts_count);
-
 /**
  * is_valid_gpt_buf() - Ensure that the Primary GPT information is valid
  *
@@ -363,7 +363,16 @@ int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head,
 int gpt_verify_partitions(struct blk_desc *dev_desc,
 			  disk_partition_t *partitions, int parts,
 			  gpt_header *gpt_head, gpt_entry **gpt_pte);
-#endif
+
+#ifdef CONFIG_EFI_PARTITION_MTD
+#define MTD_LBA_SIZE	512
+int gpt_restore_mtd(struct mtd_info *mtd, char *str_disk_guid,
+		    disk_partition_t *partitions, int parts_count);
+void part_print_efi_mtd(struct mtd_info *mtd_info);
+int part_get_info_efi_mtd(struct mtd_info *mtd, int part,
+			       disk_partition_t *info);
+#endif /* CONFIG_EFI_PARTITION_MTD */
+#endif /* CONFIG_EFI_PARTITION */
 
 #ifdef CONFIG_DOS_PARTITION
 /**
diff --git a/include/uuid.h b/include/uuid.h
index c3f423f..f444095 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -40,6 +40,7 @@ void uuid_bin_to_str(unsigned char *uuid_bin, char *uuid_str, int str_format);
 int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 int uuid_guid_get_str(unsigned char *guid_bin, char *guid_str);
 #endif
+int uuid_guid_parse_str(const char *str, char *guid_str);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index c8584ed..eb8d8eb 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -136,6 +136,39 @@ int uuid_guid_get_str(unsigned char *guid_bin, char *guid_str)
 #endif
 
 /*
+ * uuid_guid_parse_str() - this function parse string for GUID.
+ *
+ * @param guid_str - pointer to string with partition type guid [37B]
+ *                   or GUID shorcut
+ * @param guid_str - pointer to allocated partition type string [37B]
+ */
+int uuid_guid_parse_str(const char *str, char *guid_str)
+{
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	int i;
+#endif
+
+	if (guid_str == NULL)
+		return -ENODEV;
+
+	if (uuid_str_valid(str)) {
+		memcpy(guid_str, str, UUID_STR_LEN + 1);
+		return 0;
+	}
+
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	for (i = 0; i < ARRAY_SIZE(list_guid); i++) {
+		if (!strcmp(list_guid[i].string, str)) {
+			uuid_bin_to_str((unsigned char *)list_guid[i].guid.b,
+					guid_str, UUID_STR_FORMAT_GUID);
+			return 0;
+		}
+	}
+#endif
+	return -ENODEV;
+}
+
+/*
  * uuid_str_to_bin() - convert string UUID or GUID to big endian binary data.
  *
  * @param uuid_str - pointer to UUID or GUID string [37B] or GUID shorcut
-- 
1.9.1

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

* [U-Boot] [Resend RFC PATCH v1 2/3] uuid: remove dependency with io.h
  2016-11-22 13:24 [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD Patrick Delaunay
  2016-11-22 13:24 ` [U-Boot] [Resend RFC PATCH v1 1/3] add support of GPT partitioning " Patrick Delaunay
@ 2016-11-22 13:24 ` Patrick Delaunay
  2016-11-22 13:24 ` [U-Boot] [Resend RFC PATCH v1 3/3] sandbox: GPT over MTD test Patrick Delaunay
  2016-11-22 14:57 ` [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD Ladislav Michl
  3 siblings, 0 replies; 13+ messages in thread
From: Patrick Delaunay @ 2016-11-22 13:24 UTC (permalink / raw)
  To: u-boot

From: Patrick Delaunay <patrick.delaunay@st.com>

io.h is only used for CONFIG_RANDOM_UUID
- for clrsetbits_be16
- for clrsetbits_8
available only for some target (but not for SANDBOX)

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Signed-off-by: Patrick Delaunay <patrick.delaunay73@gmail.com>
---

 lib/uuid.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/lib/uuid.c b/lib/uuid.c
index eb8d8eb..47646e3 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -8,7 +8,6 @@
 #include <linux/ctype.h>
 #include <errno.h>
 #include <common.h>
-#include <asm/io.h>
 #include <part_efi.h>
 #include <malloc.h>
 
@@ -276,13 +275,13 @@ void gen_rand_uuid(unsigned char *uuid_bin)
 	for (i = 0; i < sizeof(struct uuid) / sizeof(*ptr); i++)
 		*(ptr + i) = cpu_to_be32(rand());
 
-	clrsetbits_be16(&uuid.time_hi_and_version,
-			UUID_VERSION_MASK,
-			UUID_VERSION << UUID_VERSION_SHIFT);
+	/* UUID is big endian */
+	uuid.time_hi_and_version |= ~cpu_to_be16(UUID_VERSION_MASK);
+	uuid.time_hi_and_version &=
+		cpu_to_be16(UUID_VERSION << UUID_VERSION_SHIFT);
 
-	clrsetbits_8(&uuid.clock_seq_hi_and_reserved,
-		     UUID_VARIANT_MASK,
-		     UUID_VARIANT << UUID_VARIANT_SHIFT);
+	uuid.clock_seq_hi_and_reserved |= ~UUID_VARIANT_MASK;
+	uuid.clock_seq_hi_and_reserved &= UUID_VARIANT << UUID_VARIANT_SHIFT;
 
 	memcpy(uuid_bin, &uuid, sizeof(struct uuid));
 }
-- 
1.9.1

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

* [U-Boot] [Resend RFC PATCH v1 3/3] sandbox: GPT over MTD test
  2016-11-22 13:24 [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD Patrick Delaunay
  2016-11-22 13:24 ` [U-Boot] [Resend RFC PATCH v1 1/3] add support of GPT partitioning " Patrick Delaunay
  2016-11-22 13:24 ` [U-Boot] [Resend RFC PATCH v1 2/3] uuid: remove dependency with io.h Patrick Delaunay
@ 2016-11-22 13:24 ` Patrick Delaunay
  2016-11-22 14:57 ` [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD Ladislav Michl
  3 siblings, 0 replies; 13+ messages in thread
From: Patrick Delaunay @ 2016-11-22 13:24 UTC (permalink / raw)
  To: u-boot

From: Patrick Delaunay <patrick.delaunay@st.com>

activate needed feature in sandbox to allow test GPT over MTD
- EFI_PARTITION_MTD
- SPI_FLASH_MTD
- CMD_MTDPARTS
- MTD_PARTITIONS
- MTD_DEVICE

activate 2 features useful for test
- RANDOM_UUID
- PARTITION_TYPE_GUID

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Signed-off-by: Patrick Delaunay <patrick.delaunay73@gmail.com>
---

 configs/sandbox_defconfig | 2 ++
 include/configs/sandbox.h | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 380d4fe..1ba8d2a 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -5,6 +5,7 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_SPL_LOAD_FIT=y
+CONFIG_EFI_PARTITION_MTD=y
 CONFIG_BOOTSTAGE=y
 CONFIG_BOOTSTAGE_REPORT=y
 CONFIG_BOOTSTAGE_USER_COUNT=0x20
@@ -110,6 +111,7 @@ CONFIG_SPI_FLASH_SPANSION=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_SST=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
 CONFIG_DM_ETH=y
 CONFIG_PCI=y
 CONFIG_DM_PCI=y
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 2daf02d..66707e3 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -49,13 +49,20 @@
 #define CONFIG_CMD_MD5SUM
 
 #define CONFIG_CMD_GPT
+#define CONFIG_RANDOM_UUID
 #define CONFIG_PARTITION_UUIDS
+#define CONFIG_PARTITION_TYPE_GUID
 #define CONFIG_AMIGA_PARTITION
 #define CONFIG_DOS_PARTITION
 #define CONFIG_EFI_PARTITION
 #define CONFIG_ISO_PARTITION
 #define CONFIG_MAC_PARTITION
 
+/* Dynamic MTD partition support */
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_MTD_DEVICE
+
 /*
  * Size of malloc() pool, before and after relocation
  */
-- 
1.9.1

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

* [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD
  2016-11-22 13:24 [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD Patrick Delaunay
                   ` (2 preceding siblings ...)
  2016-11-22 13:24 ` [U-Boot] [Resend RFC PATCH v1 3/3] sandbox: GPT over MTD test Patrick Delaunay
@ 2016-11-22 14:57 ` Ladislav Michl
  2016-11-24 14:14   ` Patrick DELAUNAY
  3 siblings, 1 reply; 13+ messages in thread
From: Ladislav Michl @ 2016-11-22 14:57 UTC (permalink / raw)
  To: u-boot

Hi,

On Tue, Nov 22, 2016 at 02:24:39PM +0100, Patrick Delaunay wrote:
> 
> I have a request to support GPT over MTD to be able to have dynamic
> MTD informations without u-Boot environment(CONFIG_ENV_IS_NOWHERE
> is a other requirement of my project).

I'm just curious, could you provide some reasoning, why this is a requirement?

> The idea is to use the GPT header to save partitioning information directly
> in flash device (NOR or NAND), then the MTD variables are rebuild from
> these GPT partitions and can be used by DISTRO to search bootable binary.

Ok, so you stored partitioning information on flash... That seems to be some
kind of limited environment saved :-)

> I make a first prototyping for this request but I want ask you if this
> feature is acceptable for u-boot and if this patches, after some update
> and cleanups, would be merged in u-boot mainline.
> Do you see already some blocking points ?

Is there any reason why you cannot use UBI?

> - added code is under a new CONFIG : CONFIG_EFI_PARTITION_MTD
> - for implementation details, see doc/README.gpt.mtd
> 
> TODO:
> - split patch between core impact (disk/part_efi.c)
>   and command update
> - full support for modified command
>   (today I limit the support for the command used by DISTRO macro)
> - DISTRO macro update for automatic boot on GPT bootable partition
>   found in MTD devices

Best regards,
	ladis

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

* [U-Boot] [Resend RFC PATCH v1 1/3] add support of GPT partitioning over MTD
  2016-11-22 13:24 ` [U-Boot] [Resend RFC PATCH v1 1/3] add support of GPT partitioning " Patrick Delaunay
@ 2016-11-24  2:20   ` Simon Glass
  2016-11-24 10:27     ` Patrick DELAUNAY
  0 siblings, 1 reply; 13+ messages in thread
From: Simon Glass @ 2016-11-24  2:20 UTC (permalink / raw)
  To: u-boot

Hi Patrick,

On 22 November 2016 at 06:24, Patrick Delaunay
<patrick.delaunay73@gmail.com> wrote:
> From: Patrick Delaunay <patrick.delaunay@st.com>
>
> Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
> Signed-off-by: Patrick Delaunay <patrick.delaunay73@gmail.com>
> ---
>
>  Kconfig            |  12 ++
>  cmd/gpt.c          |  98 ++++++++--
>  cmd/mtdparts.c     | 103 ++++++++++-
>  cmd/part.c         |  48 ++++-
>  disk/part_efi.c    | 526 ++++++++++++++++++++++++++++++++++++++++++++++++-----
>  doc/README.gpt.mtd | 189 +++++++++++++++++++
>  include/part.h     |  13 +-
>  include/uuid.h     |   1 +
>  lib/uuid.c         |  33 ++++
>  9 files changed, 944 insertions(+), 79 deletions(-)
>  create mode 100644 doc/README.gpt.mtd

General comments:

- use 'U-Boot' consistently rather than variations
- can you split your large function up a bit?
- can you make a precursor patch to refactor things, so reducing the
size of this one?
- nice README!

>
> diff --git a/Kconfig b/Kconfig
> index 1263d0b..c2388e1 100644
> --- a/Kconfig
> +++ b/Kconfig
> @@ -335,6 +335,18 @@ config ARCH_FIXUP_FDT
>
>  endmenu                # Boot images
>
> +config EFI_PARTITION_MTD
> +       bool "Support GPT over MTD"
> +       help
> +         The GPT partition is normally defined only for block device with
> +         built-in controller which manage flash translation layer
> +         This option activate the GPT partition support over RAW device
> +         using the MTD framework
> +         - manage partition over MTD devices (as flash: NOR and NAND)
> +         - extract MTD information
> +         - update command gpt, mtdparts and part
> +         NB: depends on EFI_PARTITION

So do you want 'depends on EFI_PARTITION'?

Regards,
Simon

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

* [U-Boot] [Resend RFC PATCH v1 1/3] add support of GPT partitioning over MTD
  2016-11-24  2:20   ` Simon Glass
@ 2016-11-24 10:27     ` Patrick DELAUNAY
  2016-11-27 17:02       ` Simon Glass
  0 siblings, 1 reply; 13+ messages in thread
From: Patrick DELAUNAY @ 2016-11-24 10:27 UTC (permalink / raw)
  To: u-boot

Hi Simon,

> 
> Hi Patrick,
> 
> On 22 November 2016 at 06:24, Patrick Delaunay
> <patrick.delaunay73@gmail.com> wrote:
> > From: Patrick Delaunay <patrick.delaunay@st.com>
> >
> > Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
> > Signed-off-by: Patrick Delaunay <patrick.delaunay73@gmail.com>
> > ---
> >
> >  Kconfig            |  12 ++
> >  cmd/gpt.c          |  98 ++++++++--
> >  cmd/mtdparts.c     | 103 ++++++++++-
> >  cmd/part.c         |  48 ++++-
> >  disk/part_efi.c    | 526
> ++++++++++++++++++++++++++++++++++++++++++++++++-----
> >  doc/README.gpt.mtd | 189 +++++++++++++++++++
> >  include/part.h     |  13 +-
> >  include/uuid.h     |   1 +
> >  lib/uuid.c         |  33 ++++
> >  9 files changed, 944 insertions(+), 79 deletions(-)  create mode
> > 100644 doc/README.gpt.mtd
> 
> General comments:
> 
> - use 'U-Boot' consistently rather than variations
> - can you split your large function up a bit?
> - can you make a precursor patch to refactor things, so reducing the size of
> this one?

Yes, I will do this split in v2 to reduce each patch size:
- one patch to uuid new function
- one precursor for efi part : refactor
- one patch for GPT over MTD in part_efi.c
	& I will split large function
- one patch for each command update

> - nice README!
> 
> >
> > diff --git a/Kconfig b/Kconfig
> > index 1263d0b..c2388e1 100644
> > --- a/Kconfig
> > +++ b/Kconfig
> > @@ -335,6 +335,18 @@ config ARCH_FIXUP_FDT
> >
> >  endmenu                # Boot images
> >
> > +config EFI_PARTITION_MTD
> > +       bool "Support GPT over MTD"
> > +       help
> > +         The GPT partition is normally defined only for block device with
> > +         built-in controller which manage flash translation layer
> > +         This option activate the GPT partition support over RAW device
> > +         using the MTD framework
> > +         - manage partition over MTD devices (as flash: NOR and NAND)
> > +         - extract MTD information
> > +         - update command gpt, mtdparts and part
> > +         NB: depends on EFI_PARTITION
> 
> So do you want 'depends on EFI_PARTITION'?

Yes I expect it, I try to add 
	depends on EFI_PARTITION
but is not working as it is not (yet ?)  one KCONFIG option.
I add this comment to add this line when part lib will integrate KCONFIG

> 
> Regards,
> Simon

Regards,
Patrick

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

* [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD
  2016-11-22 14:57 ` [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD Ladislav Michl
@ 2016-11-24 14:14   ` Patrick DELAUNAY
  2016-11-25 12:21     ` Ladislav Michl
  0 siblings, 1 reply; 13+ messages in thread
From: Patrick DELAUNAY @ 2016-11-24 14:14 UTC (permalink / raw)
  To: u-boot

Hi Ladislav,

> 
> Hi,
> 
> On Tue, Nov 22, 2016 at 02:24:39PM +0100, Patrick Delaunay wrote:
> >
> > I have a request to support GPT over MTD to be able to have dynamic
> > MTD informations without u-Boot
> environment(CONFIG_ENV_IS_NOWHERE is a
> > other requirement of my project).
> 
> I'm just curious, could you provide some reasoning, why this is a
> requirement?

One platform requirement is to boot from any supported device (NOR, NAND, eMMC, ...) with the same boot chain (including SPL and U-Boot) WITHOUT recompilation and only by changing the hardware boot configuration (OTP).

So I can't use environment (CONFIG_ENV_IS_NOWHERE), because I don't know which device is expected for tests (boot from NAND,  eMMC, NOR).
PS: I agree that in final client board, the u-boot will be optimized and u-boot env could be used.

For  block device(eMMC), it is not an issue
	-  first boot stage uses the GPT header in block device,  to found, load and execute SPL and U-Boot.
                -  U-Boot Generic Distro feature is used in U-Boot to load kernel (found extlinux.conf in bootable partition)

For Flash Device, the offset for SPL and U-Boot can't be determined easily by first boot stage.
It is why GPT is re-used to save MTD partition offset without hardcoded part in first boot stage or in SPL (and without U-Boot env).
=> partition offsets are determined dynamically

So it should be easier to have the same behavior, based on GPT, for every boot device, block or flash.
And the same tools (programmer) or command in U-Boot will use to update/read every device, based on GPT header. 

> > The idea is to use the GPT header to save partitioning information
> > directly in flash device (NOR or NAND), then the MTD variables are
> > rebuild from these GPT partitions and can be used by DISTRO to search
> bootable binary.
> 
> Ok, so you stored partitioning information on flash... That seems to be some
> kind of limited environment saved :-)

Yes I use standard GPT to save partitioning information, to save offset of MTD partition in flash device.
So it is limited environment :-) but limited to partition offset and it can be discovered dynamically by first boot stage.

> > I make a first prototyping for this request but I want ask you if this
> > feature is acceptable for u-boot and if this patches, after some
> > update and cleanups, would be merged in u-boot mainline.
> > Do you see already some blocking points ?
> 
> Is there any reason why you cannot use UBI?

UBIFS will be used in U-Boot not in previous boot stage
Kernel and device tree will be found in a UBIFS volume

> > - added code is under a new CONFIG : CONFIG_EFI_PARTITION_MTD
> > - for implementation details, see doc/README.gpt.mtd
> >
> > TODO:
> > - split patch between core impact (disk/part_efi.c)
> >   and command update
> > - full support for modified command
> >   (today I limit the support for the command used by DISTRO macro)
> > - DISTRO macro update for automatic boot on GPT bootable partition
> >   found in MTD devices
> 
> Best regards,
> 	ladis

Best regards
	Patrick

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

* [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD
  2016-11-24 14:14   ` Patrick DELAUNAY
@ 2016-11-25 12:21     ` Ladislav Michl
  2016-11-28 15:02       ` Patrick DELAUNAY
  0 siblings, 1 reply; 13+ messages in thread
From: Ladislav Michl @ 2016-11-25 12:21 UTC (permalink / raw)
  To: u-boot

Hi Patrick,

On Thu, Nov 24, 2016 at 02:14:22PM +0000, Patrick DELAUNAY wrote:
> Hi Ladislav,
> 
> > 
> > Hi,
> > 
> > On Tue, Nov 22, 2016 at 02:24:39PM +0100, Patrick Delaunay wrote:
> > >
> > > I have a request to support GPT over MTD to be able to have dynamic
> > > MTD informations without u-Boot
> > environment(CONFIG_ENV_IS_NOWHERE is a
> > > other requirement of my project).
> > 
> > I'm just curious, could you provide some reasoning, why this is a
> > requirement?
> 
> One platform requirement is to boot from any supported device (NOR, NAND, eMMC, ...) with the same boot chain (including SPL and U-Boot) WITHOUT recompilation and only by changing the hardware boot configuration (OTP).

Ok, the very same requirement here...

> So I can't use environment (CONFIG_ENV_IS_NOWHERE), because I don't know which device is expected for tests (boot from NAND,  eMMC, NOR).
> PS: I agree that in final client board, the u-boot will be optimized and u-boot env could be used.
> 
> For  block device(eMMC), it is not an issue
> 	-  first boot stage uses the GPT header in block device,  to found, load and execute SPL and U-Boot.
>                 -  U-Boot Generic Distro feature is used in U-Boot to load kernel (found extlinux.conf in bootable partition)
> 
> For Flash Device, the offset for SPL and U-Boot can't be determined easily by first boot stage.

Offset of SPL? Isn't that determined by boot ROM code? So you actually
cannot do much with that. What hardware are you planning to use your
solution with?

> It is why GPT is re-used to save MTD partition offset without hardcoded part in first boot stage or in SPL (and without U-Boot env).
> => partition offsets are determined dynamically

As SPL offset is given and only U-Boot offset can be changed (is that
assumption right?), you can store U-Boot in UBI volume.

> So it should be easier to have the same behavior, based on GPT, for every boot device, block or flash.
> And the same tools (programmer) or command in U-Boot will use to update/read every device, based on GPT header. 

I have to admit, that UBI solution would not let you use the same
scenario for eMMC and NAND in terms of U-Boot commands used, but otherwise
it is more robust.

> > > The idea is to use the GPT header to save partitioning information
> > > directly in flash device (NOR or NAND), then the MTD variables are
> > > rebuild from these GPT partitions and can be used by DISTRO to search
> > bootable binary.
> > 
> > Ok, so you stored partitioning information on flash... That seems to be some
> > kind of limited environment saved :-)
> 
> Yes I use standard GPT to save partitioning information, to save offset of MTD partition in flash device.
> So it is limited environment :-) but limited to partition offset and it can be discovered dynamically by first boot stage.

First boot stage is SPL here?

> > > I make a first prototyping for this request but I want ask you if this
> > > feature is acceptable for u-boot and if this patches, after some
> > > update and cleanups, would be merged in u-boot mainline.
> > > Do you see already some blocking points ?
> > 
> > Is there any reason why you cannot use UBI?
> 
> UBIFS will be used in U-Boot not in previous boot stage

Just to make it completely clear: UBIFS is a filesystem used
on the top of UBI volume...

> Kernel and device tree will be found in a UBIFS volume

...so kernel and DTB are stored as a files inside UBIFS
(filesystem)?

Both SPL and U-Boot can load images from UBI volumes. Also you'll get
Falcon mode for free :-)

Best regards,
	ladis

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

* [U-Boot] [Resend RFC PATCH v1 1/3] add support of GPT partitioning over MTD
  2016-11-24 10:27     ` Patrick DELAUNAY
@ 2016-11-27 17:02       ` Simon Glass
  2016-11-28 15:06         ` Patrick DELAUNAY
  2016-11-30 10:45         ` Patrick DELAUNAY
  0 siblings, 2 replies; 13+ messages in thread
From: Simon Glass @ 2016-11-27 17:02 UTC (permalink / raw)
  To: u-boot

Hi Patrick,

On 24 November 2016 at 03:27, Patrick DELAUNAY <patrick.delaunay@st.com> wrote:
> Hi Simon,
>
>>
>> Hi Patrick,
>>
>> On 22 November 2016 at 06:24, Patrick Delaunay
>> <patrick.delaunay73@gmail.com> wrote:
>> > From: Patrick Delaunay <patrick.delaunay@st.com>
>> >
>> > Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
>> > Signed-off-by: Patrick Delaunay <patrick.delaunay73@gmail.com>
>> > ---
>> >
>> >  Kconfig            |  12 ++
>> >  cmd/gpt.c          |  98 ++++++++--
>> >  cmd/mtdparts.c     | 103 ++++++++++-
>> >  cmd/part.c         |  48 ++++-
>> >  disk/part_efi.c    | 526
>> ++++++++++++++++++++++++++++++++++++++++++++++++-----
>> >  doc/README.gpt.mtd | 189 +++++++++++++++++++
>> >  include/part.h     |  13 +-
>> >  include/uuid.h     |   1 +
>> >  lib/uuid.c         |  33 ++++
>> >  9 files changed, 944 insertions(+), 79 deletions(-)  create mode
>> > 100644 doc/README.gpt.mtd
>>
>> General comments:
>>
>> - use 'U-Boot' consistently rather than variations
>> - can you split your large function up a bit?
>> - can you make a precursor patch to refactor things, so reducing the size of
>> this one?
>
> Yes, I will do this split in v2 to reduce each patch size:
> - one patch to uuid new function
> - one precursor for efi part : refactor
> - one patch for GPT over MTD in part_efi.c
>         & I will split large function
> - one patch for each command update
>
>> - nice README!
>>
>> >
>> > diff --git a/Kconfig b/Kconfig
>> > index 1263d0b..c2388e1 100644
>> > --- a/Kconfig
>> > +++ b/Kconfig
>> > @@ -335,6 +335,18 @@ config ARCH_FIXUP_FDT
>> >
>> >  endmenu                # Boot images
>> >
>> > +config EFI_PARTITION_MTD
>> > +       bool "Support GPT over MTD"
>> > +       help
>> > +         The GPT partition is normally defined only for block device with
>> > +         built-in controller which manage flash translation layer
>> > +         This option activate the GPT partition support over RAW device
>> > +         using the MTD framework
>> > +         - manage partition over MTD devices (as flash: NOR and NAND)
>> > +         - extract MTD information
>> > +         - update command gpt, mtdparts and part
>> > +         NB: depends on EFI_PARTITION
>>
>> So do you want 'depends on EFI_PARTITION'?
>
> Yes I expect it, I try to add
>         depends on EFI_PARTITION
> but is not working as it is not (yet ?)  one KCONFIG option.
> I add this comment to add this line when part lib will integrate KCONFIG

I see. Well if you have the energy you could use moveconfig.py to convert it.

Regards,
Simon

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

* [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD
  2016-11-25 12:21     ` Ladislav Michl
@ 2016-11-28 15:02       ` Patrick DELAUNAY
  0 siblings, 0 replies; 13+ messages in thread
From: Patrick DELAUNAY @ 2016-11-28 15:02 UTC (permalink / raw)
  To: u-boot

Hi Ladislav,

> 
> Hi Patrick,
> 
> On Thu, Nov 24, 2016 at 02:14:22PM +0000, Patrick DELAUNAY wrote:
> > Hi Ladislav,
> >
> > >
> > > Hi,
> > >
> > > On Tue, Nov 22, 2016 at 02:24:39PM +0100, Patrick Delaunay wrote:
> > > >
> > > > I have a request to support GPT over MTD to be able to have
> > > > dynamic MTD informations without u-Boot
> > > environment(CONFIG_ENV_IS_NOWHERE is a
> > > > other requirement of my project).
> > >
> > > I'm just curious, could you provide some reasoning, why this is a
> > > requirement?
> >
> > One platform requirement is to boot from any supported device (NOR,
> NAND, eMMC, ...) with the same boot chain (including SPL and U-Boot)
> WITHOUT recompilation and only by changing the hardware boot
> configuration (OTP).
> 
> Ok, the very same requirement here...
> 
> > So I can't use environment (CONFIG_ENV_IS_NOWHERE), because I don't
> know which device is expected for tests (boot from NAND,  eMMC, NOR).
> > PS: I agree that in final client board, the u-boot will be optimized and u-
> boot env could be used.
> >
> > For  block device(eMMC), it is not an issue
> > 	-  first boot stage uses the GPT header in block device,  to found, load
> and execute SPL and U-Boot.
> >                 -  U-Boot Generic Distro feature is used in U-Boot to
> > load kernel (found extlinux.conf in bootable partition)
> >
> > For Flash Device, the offset for SPL and U-Boot can't be determined easily
> by first boot stage.
> 
> Offset of SPL? Isn't that determined by boot ROM code? So you actually
> cannot do much with that. What hardware are you planning to use your
> solution with?

Not necessarily, we may have a first stage boot loader (let's say ARM Trusted Firmware) loaded by the ROM code before SPL execution.
Then SPL is executed as plugin, without Flash driver only to initialize DDR (as FEL for sunxi platform or bootrom plugin for mvebu) 
The HW used is a board based on the STMicroelectronics 96Board with STiH410 soc (ARM core).

> > It is why GPT is re-used to save MTD partition offset without hardcoded
> part in first boot stage or in SPL (and without U-Boot env).
> > => partition offsets are determined dynamically
> 
> As SPL offset is given and only U-Boot offset can be changed (is that
> assumption right?), you can store U-Boot in UBI volume.
> 

With SPL executed as plugin, U-Boot is loaded by first boot loader, which support GPT but not UBI...

> > So it should be easier to have the same behavior, based on GPT, for every
> boot device, block or flash.
> > And the same tools (programmer) or command in U-Boot will use to
> update/read every device, based on GPT header.
> 
> I have to admit, that UBI solution would not let you use the same scenario for
> eMMC and NAND in terms of U-Boot commands used, but otherwise it is
> more robust.
> 
> > > > The idea is to use the GPT header to save partitioning information
> > > > directly in flash device (NOR or NAND), then the MTD variables are
> > > > rebuild from these GPT partitions and can be used by DISTRO to
> > > > search
> > > bootable binary.
> > >
> > > Ok, so you stored partitioning information on flash... That seems to
> > > be some kind of limited environment saved :-)
> >
> > Yes I use standard GPT to save partitioning information, to save offset of
> MTD partition in flash device.
> > So it is limited environment :-) but limited to partition offset and it can be
> discovered dynamically by first boot stage.
> 
> First boot stage is SPL here?

Not necessary, SPL is loaded and executed as plugin by first boot stage...

> 
> > > > I make a first prototyping for this request but I want ask you if
> > > > this feature is acceptable for u-boot and if this patches, after
> > > > some update and cleanups, would be merged in u-boot mainline.
> > > > Do you see already some blocking points ?
> > >
> > > Is there any reason why you cannot use UBI?
> >
> > UBIFS will be used in U-Boot not in previous boot stage
> 
> Just to make it completely clear: UBIFS is a filesystem used on the top of UBI
> volume...
> 
> > Kernel and device tree will be found in a UBIFS volume
> 
> ...so kernel and DTB are stored as a files inside UBIFS (filesystem)?
> 
> Both SPL and U-Boot can load images from UBI volumes. Also you'll get
> Falcon mode for free :-)

In our case, when SPL is loaded as plugin, without file system and flash driver support, the FALCON mode is not possible :-<

The expected Flash layout is 

	MTD partition1 => First Boot stage (with Flash driver / GPT support)
	MTD partition2 => U-Boot SPL (only DDR init)
	MTD partition3 => U-Boot (UBI / UBIFS stage)
	MTD partition4 => UBI (several volume : boot, kernel used by u-boot)

- First boot stage is loaded by ROM in internal RAM
- SPL is loaded as plugin to initialize DDR
- Uboot is loaded in DDR by First Boot Stage / found UBI volume 

=> my issue is : how to found MTD offset if they are not hardcoded in U-Boot and First Boot Stage ?

> Best regards,
> 	ladis

Best Regards
Patrick

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

* [U-Boot] [Resend RFC PATCH v1 1/3] add support of GPT partitioning over MTD
  2016-11-27 17:02       ` Simon Glass
@ 2016-11-28 15:06         ` Patrick DELAUNAY
  2016-11-30 10:45         ` Patrick DELAUNAY
  1 sibling, 0 replies; 13+ messages in thread
From: Patrick DELAUNAY @ 2016-11-28 15:06 UTC (permalink / raw)
  To: u-boot

Hi Simon,

> 
> Hi Patrick,
> 
> On 24 November 2016 at 03:27, Patrick DELAUNAY
> <patrick.delaunay@st.com> wrote:
> > Hi Simon,
> >
> >>
> >> Hi Patrick,
> >>
> >> On 22 November 2016 at 06:24, Patrick Delaunay
> >> <patrick.delaunay73@gmail.com> wrote:
> >> > From: Patrick Delaunay <patrick.delaunay@st.com>
> >> >
> >> > Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
> >> > Signed-off-by: Patrick Delaunay <patrick.delaunay73@gmail.com>
> >> > ---
> >> >
> >> >  Kconfig            |  12 ++
> >> >  cmd/gpt.c          |  98 ++++++++--
> >> >  cmd/mtdparts.c     | 103 ++++++++++-
> >> >  cmd/part.c         |  48 ++++-
> >> >  disk/part_efi.c    | 526
> >> ++++++++++++++++++++++++++++++++++++++++++++++++-----
> >> >  doc/README.gpt.mtd | 189 +++++++++++++++++++
> >> >  include/part.h     |  13 +-
> >> >  include/uuid.h     |   1 +
> >> >  lib/uuid.c         |  33 ++++
> >> >  9 files changed, 944 insertions(+), 79 deletions(-)  create mode
> >> > 100644 doc/README.gpt.mtd
> >>
> >> General comments:
> >>
> >> - use 'U-Boot' consistently rather than variations
> >> - can you split your large function up a bit?
> >> - can you make a precursor patch to refactor things, so reducing the
> >> size of this one?
> >
> > Yes, I will do this split in v2 to reduce each patch size:
> > - one patch to uuid new function
> > - one precursor for efi part : refactor
> > - one patch for GPT over MTD in part_efi.c
> >         & I will split large function
> > - one patch for each command update
> >
> >> - nice README!
> >>
> >> >
> >> > diff --git a/Kconfig b/Kconfig
> >> > index 1263d0b..c2388e1 100644
> >> > --- a/Kconfig
> >> > +++ b/Kconfig
> >> > @@ -335,6 +335,18 @@ config ARCH_FIXUP_FDT
> >> >
> >> >  endmenu                # Boot images
> >> >
> >> > +config EFI_PARTITION_MTD
> >> > +       bool "Support GPT over MTD"
> >> > +       help
> >> > +         The GPT partition is normally defined only for block device with
> >> > +         built-in controller which manage flash translation layer
> >> > +         This option activate the GPT partition support over RAW device
> >> > +         using the MTD framework
> >> > +         - manage partition over MTD devices (as flash: NOR and NAND)
> >> > +         - extract MTD information
> >> > +         - update command gpt, mtdparts and part
> >> > +         NB: depends on EFI_PARTITION
> >>
> >> So do you want 'depends on EFI_PARTITION'?
> >
> > Yes I expect it, I try to add
> >         depends on EFI_PARTITION
> > but is not working as it is not (yet ?)  one KCONFIG option.
> > I add this comment to add this line when part lib will integrate
> > KCONFIG
> 
> I see. Well if you have the energy you could use moveconfig.py to convert it.

I will try to propose something (first usage of moveconfig.py script...)
if I have no issue with cross-compilation

=>  Create "disk/Kconfig" with PARTITIONS all associated option
(MAC_PARTITION, DOS_PARTITION, ISO_PARTITION, AMIGA_PARTITION, EFI_PARTITION)


> Regards,
> Simon

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

* [U-Boot] [Resend RFC PATCH v1 1/3] add support of GPT partitioning over MTD
  2016-11-27 17:02       ` Simon Glass
  2016-11-28 15:06         ` Patrick DELAUNAY
@ 2016-11-30 10:45         ` Patrick DELAUNAY
  1 sibling, 0 replies; 13+ messages in thread
From: Patrick DELAUNAY @ 2016-11-30 10:45 UTC (permalink / raw)
  To: u-boot

Hi Simon,

> 
> Hi Simon,
> 
> >
> > Hi Patrick,
> >
> > On 24 November 2016 at 03:27, Patrick DELAUNAY
> > <patrick.delaunay@st.com> wrote:
> > > Hi Simon,
> > >
> > >>
> > >> Hi Patrick,
> > >>
> > >> On 22 November 2016 at 06:24, Patrick Delaunay
> > >> <patrick.delaunay73@gmail.com> wrote:
> > >> > From: Patrick Delaunay <patrick.delaunay@st.com>
> > >> >
> > >> > Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
> > >> > Signed-off-by: Patrick Delaunay <patrick.delaunay73@gmail.com>
> > >> > ---
> > >> >
> > >> >  Kconfig            |  12 ++
> > >> >  cmd/gpt.c          |  98 ++++++++--
> > >> >  cmd/mtdparts.c     | 103 ++++++++++-
> > >> >  cmd/part.c         |  48 ++++-
> > >> >  disk/part_efi.c    | 526
> > >> ++++++++++++++++++++++++++++++++++++++++++++++++-----
> > >> >  doc/README.gpt.mtd | 189 +++++++++++++++++++
> > >> >  include/part.h     |  13 +-
> > >> >  include/uuid.h     |   1 +
> > >> >  lib/uuid.c         |  33 ++++
> > >> >  9 files changed, 944 insertions(+), 79 deletions(-)  create mode
> > >> > 100644 doc/README.gpt.mtd
> > >>
> > >> General comments:
> > >>
> > >> - use 'U-Boot' consistently rather than variations
> > >> - can you split your large function up a bit?
> > >> - can you make a precursor patch to refactor things, so reducing
> > >> the size of this one?
> > >
> > > Yes, I will do this split in v2 to reduce each patch size:
> > > - one patch to uuid new function
> > > - one precursor for efi part : refactor
> > > - one patch for GPT over MTD in part_efi.c
> > >         & I will split large function
> > > - one patch for each command update
> > >
> > >> - nice README!
> > >>
> > >> >
> > >> > diff --git a/Kconfig b/Kconfig
> > >> > index 1263d0b..c2388e1 100644
> > >> > --- a/Kconfig
> > >> > +++ b/Kconfig
> > >> > @@ -335,6 +335,18 @@ config ARCH_FIXUP_FDT
> > >> >
> > >> >  endmenu                # Boot images
> > >> >
> > >> > +config EFI_PARTITION_MTD
> > >> > +       bool "Support GPT over MTD"
> > >> > +       help
> > >> > +         The GPT partition is normally defined only for block device with
> > >> > +         built-in controller which manage flash translation layer
> > >> > +         This option activate the GPT partition support over RAW device
> > >> > +         using the MTD framework
> > >> > +         - manage partition over MTD devices (as flash: NOR and NAND)
> > >> > +         - extract MTD information
> > >> > +         - update command gpt, mtdparts and part
> > >> > +         NB: depends on EFI_PARTITION
> > >>
> > >> So do you want 'depends on EFI_PARTITION'?
> > >
> > > Yes I expect it, I try to add
> > >         depends on EFI_PARTITION
> > > but is not working as it is not (yet ?)  one KCONFIG option.
> > > I add this comment to add this line when part lib will integrate
> > > KCONFIG
> >
> > I see. Well if you have the energy you could use moveconfig.py to convert
> it.
> 
> I will try to propose something (first usage of moveconfig.py script...) if I have
> no issue with cross-compilation
> 
> =>  Create "disk/Kconfig" with PARTITIONS all associated option
> (MAC_PARTITION, DOS_PARTITION, ISO_PARTITION, AMIGA_PARTITION,
> EFI_PARTITION)

I push today the proposed patch for move disk  to Kconfig in mailing list (after some issue for target with SPL)
And I will rebase this RFC for GPT over MTD only when I will really push it on master branch.

> 
> 
> > Regards,
> > Simon

Regards Patrick

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

end of thread, other threads:[~2016-11-30 10:45 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-22 13:24 [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD Patrick Delaunay
2016-11-22 13:24 ` [U-Boot] [Resend RFC PATCH v1 1/3] add support of GPT partitioning " Patrick Delaunay
2016-11-24  2:20   ` Simon Glass
2016-11-24 10:27     ` Patrick DELAUNAY
2016-11-27 17:02       ` Simon Glass
2016-11-28 15:06         ` Patrick DELAUNAY
2016-11-30 10:45         ` Patrick DELAUNAY
2016-11-22 13:24 ` [U-Boot] [Resend RFC PATCH v1 2/3] uuid: remove dependency with io.h Patrick Delaunay
2016-11-22 13:24 ` [U-Boot] [Resend RFC PATCH v1 3/3] sandbox: GPT over MTD test Patrick Delaunay
2016-11-22 14:57 ` [U-Boot] [Resend RFC PATCH v1 0/3] GPT over MTD Ladislav Michl
2016-11-24 14:14   ` Patrick DELAUNAY
2016-11-25 12:21     ` Ladislav Michl
2016-11-28 15:02       ` Patrick DELAUNAY

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.