spl: allow boot from first bootable partition

This was implemented in order to get dual-slot bootloader
partitions on the BeagleBone Black, whose MLO boots from
the first bootable partition: MLO chainloads u-boot in the
same way.

Signed-off-by: Jérôme Carretero <cJ-uboot@zougloub.eu>
Reviewed-by: Tom Rini <trini@konsulko.com>
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index a3a6f31..ac61b25 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -668,7 +668,8 @@
 	default 1
 	help
 	  Partition on the MMC to load U-Boot from when the MMC is being
-	  used in fs mode
+	  used in fs mode.
+	  Use -1 as a special value to use the first bootable partition.
 
 config SPL_MMC_TINY
 	bool "Tiny MMC framework in SPL"
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index 1bb785a..6116a68 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -280,16 +280,40 @@
 {
 	int err = -ENOSYS;
 
+	__maybe_unused int partition = CONFIG_SYS_MMCSD_FS_BOOT_PARTITION;
+
+#if CONFIG_SYS_MMCSD_FS_BOOT_PARTITION == -1
+	{
+		struct disk_partition info;
+		debug("Checking for the first MBR bootable partition\n");
+		for (int type_part = 1; type_part <= DOS_ENTRY_NUMBERS; type_part++) {
+			err = part_get_info(mmc_get_blk_desc(mmc), type_part, &info);
+			if (err)
+				continue;
+			debug("Partition %d is of type %d and bootable=%d\n", type_part, info.sys_ind, info.bootable);
+			if (info.bootable != 0) {
+				debug("Partition %d is bootable, using it\n", type_part);
+				partition = type_part;
+				break;
+			}
+		}
+		printf("Using first bootable partition: %d\n", partition);
+		if (partition == CONFIG_SYS_MMCSD_FS_BOOT_PARTITION) {
+			return -ENOSYS;
+		}
+	}
+#endif
+
 #ifdef CONFIG_SPL_FS_FAT
 	if (!spl_start_uboot()) {
 		err = spl_load_image_fat_os(spl_image, bootdev, mmc_get_blk_desc(mmc),
-			CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
+			partition);
 		if (!err)
 			return err;
 	}
 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
 	err = spl_load_image_fat(spl_image, bootdev, mmc_get_blk_desc(mmc),
-				 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
+				 partition,
 				 filename);
 	if (!err)
 		return err;
@@ -298,13 +322,13 @@
 #ifdef CONFIG_SPL_FS_EXT4
 	if (!spl_start_uboot()) {
 		err = spl_load_image_ext_os(spl_image, bootdev, mmc_get_blk_desc(mmc),
-			CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
+			partition);
 		if (!err)
 			return err;
 	}
 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
 	err = spl_load_image_ext(spl_image, bootdev, mmc_get_blk_desc(mmc),
-				 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
+				 partition,
 				 filename);
 	if (!err)
 		return err;