[U-Boot] [PATCH v2 14/32] dm: part: Convert partition API use to linker lists

Simon Glass sjg at chromium.org
Mon Feb 29 23:25:47 CET 2016


We can use linker lists instead of explicitly declaring each function.
This makes the code shorter by avoiding switch() statements and lots of
header file declarations.

While this does clean up the code it introduces a few code issues with SPL.
SPL never needs to print partition information since this all happens from
commands. SPL mostly doesn't need to obtain information about a partition
either, except in a few cases. Add these cases so that the code will be
dropped from each partition driver when not needed. This avoids code bloat.

I think this is still a win, since it is not a bad thing to be explicit
about which features are used in SPL. But others may like to weigh in.

Signed-off-by: Simon Glass <sjg at chromium.org>
Reviewed-by: Tom Rini <trini at konsulko.com>
---

Changes in v2:
- Reorder the linker list so that EFI comes before DOS, and add a comment

 disk/part.c       | 184 +++++++++++++++++-------------------------------------
 disk/part_amiga.c |  16 +++--
 disk/part_dos.c   |   9 ++-
 disk/part_efi.c   |  15 ++++-
 disk/part_iso.c   |  16 +++--
 disk/part_mac.c   |  16 +++--
 include/part.h    |  79 ++++++++++++++---------
 7 files changed, 162 insertions(+), 173 deletions(-)

diff --git a/disk/part.c b/disk/part.c
index 255ee79..978b85c 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -7,6 +7,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <errno.h>
 #include <ide.h>
 #include <malloc.h>
 #include <part.h>
@@ -58,6 +59,22 @@ static const struct block_drvr block_drvr[] = {
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef HAVE_BLOCK_DEVICE
+static struct part_driver *part_driver_lookup_type(int part_type)
+{
+	struct part_driver *drv =
+		ll_entry_start(struct part_driver, part_driver);
+	const int n_ents = ll_entry_count(struct part_driver, part_driver);
+	struct part_driver *entry;
+
+	for (entry = drv; entry != drv + n_ents; entry++) {
+		if (part_type == entry->part_type)
+			return entry;
+	}
+
+	/* Not found */
+	return NULL;
+}
+
 static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart)
 {
 	const struct block_drvr *drvr = block_drvr;
@@ -252,53 +269,31 @@ void dev_print (struct blk_desc *dev_desc)
 
 void init_part(struct blk_desc *dev_desc)
 {
-#ifdef CONFIG_ISO_PARTITION
-	if (test_part_iso(dev_desc) == 0) {
-		dev_desc->part_type = PART_TYPE_ISO;
-		return;
-	}
-#endif
+	struct part_driver *drv =
+		ll_entry_start(struct part_driver, part_driver);
+	const int n_ents = ll_entry_count(struct part_driver, part_driver);
+	struct part_driver *entry;
 
-#ifdef CONFIG_MAC_PARTITION
-	if (test_part_mac(dev_desc) == 0) {
-		dev_desc->part_type = PART_TYPE_MAC;
-		return;
-	}
-#endif
-
-/* must be placed before DOS partition detection */
-#ifdef CONFIG_EFI_PARTITION
-	if (test_part_efi(dev_desc) == 0) {
-		dev_desc->part_type = PART_TYPE_EFI;
-		return;
-	}
-#endif
-
-#ifdef CONFIG_DOS_PARTITION
-	if (test_part_dos(dev_desc) == 0) {
-		dev_desc->part_type = PART_TYPE_DOS;
-		return;
-	}
-#endif
-
-#ifdef CONFIG_AMIGA_PARTITION
-	if (test_part_amiga(dev_desc) == 0) {
-	    dev_desc->part_type = PART_TYPE_AMIGA;
-	    return;
-	}
-#endif
 	dev_desc->part_type = PART_TYPE_UNKNOWN;
+	for (entry = drv; entry != drv + n_ents; entry++) {
+		int ret;
+
+		ret = entry->test(dev_desc);
+		debug("%s: try '%s': ret=%d\n", __func__, entry->name, ret);
+		if (!ret) {
+			dev_desc->part_type = entry->part_type;
+			break;
+		}
+	}
 }
 
-
+static void print_part_header(const char *type, struct blk_desc *dev_desc)
+{
 #if defined(CONFIG_MAC_PARTITION) || \
 	defined(CONFIG_DOS_PARTITION) || \
 	defined(CONFIG_ISO_PARTITION) || \
 	defined(CONFIG_AMIGA_PARTITION) || \
 	defined(CONFIG_EFI_PARTITION)
-
-static void print_part_header(const char *type, struct blk_desc *dev_desc)
-{
 	puts ("\nPartition Map for ");
 	switch (dev_desc->if_type) {
 	case IF_TYPE_IDE:
@@ -331,54 +326,24 @@ static void print_part_header(const char *type, struct blk_desc *dev_desc)
 	}
 	printf (" device %d  --   Partition Type: %s\n\n",
 			dev_desc->dev, type);
-}
-
 #endif /* any CONFIG_..._PARTITION */
+}
 
 void print_part(struct blk_desc *dev_desc)
 {
+	struct part_driver *drv;
 
-		switch (dev_desc->part_type) {
-#ifdef CONFIG_MAC_PARTITION
-	case PART_TYPE_MAC:
-		PRINTF ("## Testing for valid MAC partition ##\n");
-		print_part_header ("MAC", dev_desc);
-		print_part_mac (dev_desc);
-		return;
-#endif
-#ifdef CONFIG_DOS_PARTITION
-	case PART_TYPE_DOS:
-		PRINTF ("## Testing for valid DOS partition ##\n");
-		print_part_header ("DOS", dev_desc);
-		print_part_dos (dev_desc);
-		return;
-#endif
-
-#ifdef CONFIG_ISO_PARTITION
-	case PART_TYPE_ISO:
-		PRINTF ("## Testing for valid ISO Boot partition ##\n");
-		print_part_header ("ISO", dev_desc);
-		print_part_iso (dev_desc);
-		return;
-#endif
-
-#ifdef CONFIG_AMIGA_PARTITION
-	case PART_TYPE_AMIGA:
-	    PRINTF ("## Testing for a valid Amiga partition ##\n");
-	    print_part_header ("AMIGA", dev_desc);
-	    print_part_amiga (dev_desc);
-	    return;
-#endif
-
-#ifdef CONFIG_EFI_PARTITION
-	case PART_TYPE_EFI:
-		PRINTF ("## Testing for valid EFI partition ##\n");
-		print_part_header ("EFI", dev_desc);
-		print_part_efi (dev_desc);
+	drv = part_driver_lookup_type(dev_desc->part_type);
+	if (!drv) {
+		printf("## Unknown partition table type %x\n",
+		       dev_desc->part_type);
 		return;
-#endif
 	}
-	puts ("## Unknown partition table\n");
+
+	PRINTF("## Testing for valid %s partition ##\n", drv->name);
+	print_part_header(drv->name, dev_desc);
+	if (drv->print)
+		drv->print(dev_desc);
 }
 
 #endif /* HAVE_BLOCK_DEVICE */
@@ -387,6 +352,7 @@ int get_partition_info(struct blk_desc *dev_desc, int part,
 		       disk_partition_t *info)
 {
 #ifdef HAVE_BLOCK_DEVICE
+	struct part_driver *drv;
 
 #ifdef CONFIG_PARTITION_UUIDS
 	/* The common case is no UUID support */
@@ -396,53 +362,19 @@ int get_partition_info(struct blk_desc *dev_desc, int part,
 	info->type_guid[0] = 0;
 #endif
 
-	switch (dev_desc->part_type) {
-#ifdef CONFIG_MAC_PARTITION
-	case PART_TYPE_MAC:
-		if (get_partition_info_mac(dev_desc, part, info) == 0) {
-			PRINTF("## Valid MAC partition found ##\n");
-			return 0;
-		}
-		break;
-#endif
-
-#ifdef CONFIG_DOS_PARTITION
-	case PART_TYPE_DOS:
-		if (get_partition_info_dos(dev_desc, part, info) == 0) {
-			PRINTF("## Valid DOS partition found ##\n");
-			return 0;
-		}
-		break;
-#endif
-
-#ifdef CONFIG_ISO_PARTITION
-	case PART_TYPE_ISO:
-		if (get_partition_info_iso(dev_desc, part, info) == 0) {
-			PRINTF("## Valid ISO boot partition found ##\n");
-			return 0;
-		}
-		break;
-#endif
-
-#ifdef CONFIG_AMIGA_PARTITION
-	case PART_TYPE_AMIGA:
-		if (get_partition_info_amiga(dev_desc, part, info) == 0) {
-			PRINTF("## Valid Amiga partition found ##\n");
-			return 0;
-		}
-		break;
-#endif
-
-#ifdef CONFIG_EFI_PARTITION
-	case PART_TYPE_EFI:
-		if (get_partition_info_efi(dev_desc, part, info) == 0) {
-			PRINTF("## Valid EFI partition found ##\n");
-			return 0;
-		}
-		break;
-#endif
-	default:
-		break;
+	drv = part_driver_lookup_type(dev_desc->part_type);
+	if (!drv) {
+		debug("## Unknown partition table type %x\n",
+		      dev_desc->part_type);
+		return -EPROTONOSUPPORT;
+	}
+	if (!drv->get_info) {
+		PRINTF("## Driver %s does not have the get_info() method\n");
+		return -ENOSYS;
+	}
+	if (drv->get_info(dev_desc, part, info) == 0) {
+		PRINTF("## Valid %s partition found ##\n", drv->name);
+		return 0;
 	}
 #endif /* HAVE_BLOCK_DEVICE */
 
diff --git a/disk/part_amiga.c b/disk/part_amiga.c
index 5702c95..0f569f0 100644
--- a/disk/part_amiga.c
+++ b/disk/part_amiga.c
@@ -207,7 +207,7 @@ struct bootcode_block *get_bootcode(struct blk_desc *dev_desc)
  * Test if the given partition has an Amiga partition table/Rigid
  * Disk block
  */
-int test_part_amiga(struct blk_desc *dev_desc)
+static int test_part_amiga(struct blk_desc *dev_desc)
 {
     struct rigid_disk_block *rdb;
     struct bootcode_block *bootcode;
@@ -291,8 +291,8 @@ static struct partition_block *find_partition(struct blk_desc *dev_desc,
 /*
  * Get info about a partition
  */
-int get_partition_info_amiga(struct blk_desc *dev_desc, int part,
-			     disk_partition_t *info)
+static int get_partition_info_amiga(struct blk_desc *dev_desc, int part,
+				    disk_partition_t *info)
 {
     struct partition_block *p = find_partition(dev_desc, part-1);
     struct amiga_part_geometry *g;
@@ -319,7 +319,7 @@ int get_partition_info_amiga(struct blk_desc *dev_desc, int part,
     return 0;
 }
 
-void print_part_amiga(struct blk_desc *dev_desc)
+static void print_part_amiga(struct blk_desc *dev_desc)
 {
     struct rigid_disk_block *rdb;
     struct bootcode_block *boot;
@@ -379,4 +379,12 @@ void print_part_amiga(struct blk_desc *dev_desc)
     }
 }
 
+U_BOOT_PART_TYPE(amiga) = {
+	.name		= "AMIGA",
+	.part_type	= PART_TYPE_AMIGA,
+	.get_info	= get_partition_info_amiga,
+	.print		= print_part_amiga,
+	.test		= test_part_amiga,
+};
+
 #endif
diff --git a/disk/part_dos.c b/disk/part_dos.c
index ea0315c..7567ed3 100644
--- a/disk/part_dos.c
+++ b/disk/part_dos.c
@@ -87,7 +87,7 @@ static int test_block_type(unsigned char *buffer)
 }
 
 
-int test_part_dos(struct blk_desc *dev_desc)
+static int test_part_dos(struct blk_desc *dev_desc)
 {
 	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
 
@@ -295,5 +295,12 @@ int get_partition_info_dos(struct blk_desc *dev_desc, int part,
 	return get_partition_info_extended(dev_desc, 0, 0, 1, part, info, 0);
 }
 
+U_BOOT_PART_TYPE(dos) = {
+	.name		= "DOS",
+	.part_type	= PART_TYPE_DOS,
+	.get_info	= part_get_info_ptr(get_partition_info_dos),
+	.print		= part_print_ptr(print_part_dos),
+	.test		= test_part_dos,
+};
 
 #endif
diff --git a/disk/part_efi.c b/disk/part_efi.c
index 7bd840f..3471b75 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -319,7 +319,7 @@ int get_partition_info_efi_by_name(struct blk_desc *dev_desc,
 	return -2;
 }
 
-int test_part_efi(struct blk_desc *dev_desc)
+static int test_part_efi(struct blk_desc *dev_desc)
 {
 	ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, legacymbr, 1, dev_desc->blksz);
 
@@ -953,4 +953,17 @@ static int is_pte_valid(gpt_entry * pte)
 		return 1;
 	}
 }
+
+/*
+ * Add an 'a_' prefix so it comes before 'dos' in the linker list. We need to
+ * check EFI first, since a DOS partition is often used as a 'protective MBR'
+ * with EFI.
+ */
+U_BOOT_PART_TYPE(a_efi) = {
+	.name		= "EFI",
+	.part_type	= PART_TYPE_EFI,
+	.get_info	= part_get_info_ptr(get_partition_info_efi),
+	.print		= part_print_ptr(print_part_efi),
+	.test		= test_part_efi,
+};
 #endif
diff --git a/disk/part_iso.c b/disk/part_iso.c
index 2984df5..1d72d23 100644
--- a/disk/part_iso.c
+++ b/disk/part_iso.c
@@ -217,14 +217,13 @@ found:
 	return 0;
 }
 
-int get_partition_info_iso(struct blk_desc *dev_desc, int part_num,
-			   disk_partition_t *info)
+static int get_partition_info_iso(struct blk_desc *dev_desc, int part_num,
+				  disk_partition_t *info)
 {
 	return(get_partition_info_iso_verb(dev_desc, part_num, info, 1));
 }
 
-
-void print_part_iso(struct blk_desc *dev_desc)
+static void print_part_iso(struct blk_desc *dev_desc)
 {
 	disk_partition_t info;
 	int i;
@@ -241,11 +240,18 @@ void print_part_iso(struct blk_desc *dev_desc)
 	} while (get_partition_info_iso_verb(dev_desc,i,&info,0)!=-1);
 }
 
-int test_part_iso(struct blk_desc *dev_desc)
+static int test_part_iso(struct blk_desc *dev_desc)
 {
 	disk_partition_t info;
 
 	return(get_partition_info_iso_verb(dev_desc,0,&info,0));
 }
 
+U_BOOT_PART_TYPE(iso) = {
+	.name		= "ISO",
+	.part_type	= PART_TYPE_ISO,
+	.get_info	= get_partition_info_iso,
+	.print		= print_part_iso,
+	.test		= test_part_iso,
+};
 #endif
diff --git a/disk/part_mac.c b/disk/part_mac.c
index ae83495..3fb3b16 100644
--- a/disk/part_mac.c
+++ b/disk/part_mac.c
@@ -40,7 +40,7 @@ static int part_mac_read_pdb(struct blk_desc *dev_desc, int part,
 /*
  * Test for a valid MAC partition
  */
-int test_part_mac(struct blk_desc *dev_desc)
+static int test_part_mac(struct blk_desc *dev_desc)
 {
 	ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1);
 	ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1);
@@ -64,8 +64,7 @@ int test_part_mac(struct blk_desc *dev_desc)
 	return (0);
 }
 
-
-void print_part_mac(struct blk_desc *dev_desc)
+static void print_part_mac(struct blk_desc *dev_desc)
 {
 	ulong i, n;
 	ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1);
@@ -214,8 +213,8 @@ static int part_mac_read_pdb(struct blk_desc *dev_desc, int part,
 	/* NOTREACHED */
 }
 
-int get_partition_info_mac(struct blk_desc *dev_desc, int part,
-			   disk_partition_t *info)
+static int get_partition_info_mac(struct blk_desc *dev_desc, int part,
+				  disk_partition_t *info)
 {
 	ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1);
 	ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1);
@@ -238,4 +237,11 @@ int get_partition_info_mac(struct blk_desc *dev_desc, int part,
 	return (0);
 }
 
+U_BOOT_PART_TYPE(mac) = {
+	.name		= "MAC",
+	.part_type	= PART_TYPE_MAC,
+	.get_info	= get_partition_info_mac,
+	.print		= print_part_mac,
+	.test		= test_part_mac,
+};
 #endif
diff --git a/include/part.h b/include/part.h
index 6197101..544b056 100644
--- a/include/part.h
+++ b/include/part.h
@@ -195,43 +195,62 @@ static inline int blk_get_device_part_str(const char *ifname,
 { *dev_desc = NULL; return -1; }
 #endif
 
-#ifdef CONFIG_MAC_PARTITION
-/* disk/part_mac.c */
-int get_partition_info_mac(struct blk_desc *dev_desc, int part,
-			   disk_partition_t *info);
-void print_part_mac(struct blk_desc *dev_desc);
-int test_part_mac(struct blk_desc *dev_desc);
+/*
+ * We don't support printing partition information in SPL and only support
+ * getting partition information in a few cases.
+ */
+#ifdef CONFIG_SPL_BUILD
+# define part_print_ptr(x)	NULL
+# if defined(CONFIG_SPL_EXT_SUPPORT) || \
+	defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION)
+#  define part_get_info_ptr(x)	x
+# else
+#  define part_get_info_ptr(x)	NULL
+# endif
+#else
+#define part_print_ptr(x)	x
+#define part_get_info_ptr(x)	x
 #endif
 
-#ifdef CONFIG_DOS_PARTITION
-/* disk/part_dos.c */
-int get_partition_info_dos(struct blk_desc *dev_desc, int part,
-			   disk_partition_t *info);
-void print_part_dos(struct blk_desc *dev_desc);
-int test_part_dos(struct blk_desc *dev_desc);
-#endif
 
-#ifdef CONFIG_ISO_PARTITION
-/* disk/part_iso.c */
-int get_partition_info_iso(struct blk_desc *dev_desc, int part,
-			   disk_partition_t *info);
-void print_part_iso(struct blk_desc *dev_desc);
-int test_part_iso(struct blk_desc *dev_desc);
-#endif
+struct part_driver {
+	const char *name;
+	int part_type;
 
-#ifdef CONFIG_AMIGA_PARTITION
-/* disk/part_amiga.c */
-int get_partition_info_amiga(struct blk_desc *dev_desc, int part,
-			     disk_partition_t *info);
-void print_part_amiga(struct blk_desc *dev_desc);
-int test_part_amiga(struct blk_desc *dev_desc);
-#endif
+	/**
+	 * get_info() - Get information about a partition
+	 *
+	 * @dev_desc:	Block device descriptor
+	 * @part:	Partition number (1 = first)
+	 * @info:	Returns partition information
+	 */
+	int (*get_info)(struct blk_desc *dev_desc, int part,
+			disk_partition_t *info);
+
+	/**
+	 * print() - Print partition information
+	 *
+	 * @dev_desc:	Block device descriptor
+	 */
+	void (*print)(struct blk_desc *dev_desc);
+
+	/**
+	 * test() - Test if a device contains this partition type
+	 *
+	 * @dev_desc:	Block device descriptor
+	 * @return 0 if the block device appears to contain this partition
+	 *	   type, -ve if not
+	 */
+	int (*test)(struct blk_desc *dev_desc);
+};
+
+/* Declare a new U-Boot partition 'driver' */
+#define U_BOOT_PART_TYPE(__name)					\
+	ll_entry_declare(struct part_driver, __name, part_driver)
 
 #ifdef CONFIG_EFI_PARTITION
 #include <part_efi.h>
 /* disk/part_efi.c */
-int get_partition_info_efi(struct blk_desc *dev_desc, int part,
-			   disk_partition_t *info);
 /**
  * get_partition_info_efi_by_name() - Find the specified GPT partition table entry
  *
@@ -243,8 +262,6 @@ int get_partition_info_efi(struct blk_desc *dev_desc, int part,
  */
 int get_partition_info_efi_by_name(struct blk_desc *dev_desc,
 	const char *name, disk_partition_t *info);
-void print_part_efi(struct blk_desc *dev_desc);
-int test_part_efi(struct blk_desc *dev_desc);
 
 /**
  * write_gpt_table() - Write the GUID Partition Table to disk
-- 
2.7.0.rc3.207.g0ac5344



More information about the U-Boot mailing list