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 #include +#include #include #include #include @@ -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 /* 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