[U-Boot] [Resend RFC PATCH v1 1/3] add support of GPT partitioning over MTD

Patrick Delaunay patrick.delaunay73 at gmail.com
Tue Nov 22 14:24:40 CET 2016


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

Signed-off-by: Patrick Delaunay <patrick.delaunay at st.com>
Signed-off-by: Patrick Delaunay <patrick.delaunay73 at 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 at 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




More information about the U-Boot mailing list