X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=disk%2Fpart.c;h=cb9b86156d3cbe7b45e0a3fd565cb0a6c84e1d12;hb=f18fa31cdcfeecaf56e61224eb18d2f2b6d39d85;hp=ecc5e7e0bfa0c9292cc83bc6d205f9374f47448b;hpb=c23154aab5825fec81d5500c53eaa686646c76b5;p=platform%2Fkernel%2Fu-boot.git diff --git a/disk/part.c b/disk/part.c index ecc5e7e..cb9b861 100644 --- a/disk/part.c +++ b/disk/part.c @@ -7,9 +7,11 @@ #include #include +#include #include #include #include +#include #undef PART_DEBUG @@ -19,98 +21,57 @@ #define PRINTF(fmt,args...) #endif -struct block_drvr { - char *name; - block_dev_desc_t* (*get_dev)(int dev); - int (*select_hwpart)(int dev_num, int hwpart); -}; - -static const struct block_drvr block_drvr[] = { -#if defined(CONFIG_CMD_IDE) - { .name = "ide", .get_dev = ide_get_dev, }, -#endif -#if defined(CONFIG_CMD_SATA) - {.name = "sata", .get_dev = sata_get_dev, }, -#endif -#if defined(CONFIG_CMD_SCSI) - { .name = "scsi", .get_dev = scsi_get_dev, }, -#endif -#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) - { .name = "usb", .get_dev = usb_stor_get_dev, }, -#endif -#if defined(CONFIG_MMC) - { - .name = "mmc", - .get_dev = mmc_get_dev, - .select_hwpart = mmc_select_hwpart, - }, -#endif -#if defined(CONFIG_SYSTEMACE) - { .name = "ace", .get_dev = systemace_get_dev, }, -#endif -#if defined(CONFIG_SANDBOX) - { .name = "host", .get_dev = host_get_dev, }, -#endif - { }, -}; - DECLARE_GLOBAL_DATA_PTR; #ifdef HAVE_BLOCK_DEVICE -block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart) +static struct part_driver *part_driver_lookup_type(int part_type) { - const struct block_drvr *drvr = block_drvr; - block_dev_desc_t* (*reloc_get_dev)(int dev); - int (*select_hwpart)(int dev_num, int hwpart); - char *name; + 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) +{ + struct blk_desc *dev_desc; int ret; - if (!ifname) + dev_desc = blk_get_devnum_by_typename(ifname, dev); + if (!dev_desc) { + debug("%s: No device for iface '%s', dev %d\n", __func__, + ifname, dev); return NULL; - - name = drvr->name; -#ifdef CONFIG_NEEDS_MANUAL_RELOC - name += gd->reloc_off; -#endif - while (drvr->name) { - name = drvr->name; - reloc_get_dev = drvr->get_dev; - select_hwpart = drvr->select_hwpart; -#ifdef CONFIG_NEEDS_MANUAL_RELOC - name += gd->reloc_off; - reloc_get_dev += gd->reloc_off; - if (select_hwpart) - select_hwpart += gd->reloc_off; -#endif - if (strncmp(ifname, name, strlen(name)) == 0) { - block_dev_desc_t *dev_desc = reloc_get_dev(dev); - if (!dev_desc) - return NULL; - if (hwpart == 0 && !select_hwpart) - return dev_desc; - if (!select_hwpart) - return NULL; - ret = select_hwpart(dev_desc->dev, hwpart); - if (ret < 0) - return NULL; - return dev_desc; - } - drvr++; } - return NULL; + ret = blk_dselect_hwpart(dev_desc, hwpart); + if (ret) { + debug("%s: Failed to select h/w partition: err-%d\n", __func__, + ret); + return NULL; + } + + return dev_desc; } -block_dev_desc_t *get_dev(const char *ifname, int dev) +struct blk_desc *blk_get_dev(const char *ifname, int dev) { return get_dev_hwpart(ifname, dev, 0); } #else -block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart) +struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) { return NULL; } -block_dev_desc_t *get_dev(const char *ifname, int dev) +struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } @@ -133,7 +94,7 @@ typedef lbaint_t lba512_t; * Overflowless variant of (block_count * mul_by / div_by) * when div_by > mul_by */ -static lba512_t lba512_muldiv (lba512_t block_count, lba512_t mul_by, lba512_t div_by) +static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by, lba512_t div_by) { lba512_t bc_quot, bc_rem; @@ -143,7 +104,7 @@ static lba512_t lba512_muldiv (lba512_t block_count, lba512_t mul_by, lba512_t d return bc_quot * mul_by + (bc_rem * mul_by) / div_by; } -void dev_print (block_dev_desc_t *dev_desc) +void dev_print (struct blk_desc *dev_desc) { lba512_t lba512; /* number of blocks if 512bytes block size */ @@ -215,7 +176,8 @@ void dev_print (block_dev_desc_t *dev_desc) lba512 = (lba * (dev_desc->blksz/512)); /* round to 1 digit */ - mb = lba512_muldiv(lba512, 10, 2048); /* 2048 = (1024 * 1024) / 512 MB */ + /* 2048 = (1024 * 1024) / 512 MB */ + mb = lba512_muldiv(lba512, 10, 2048); mb_quot = mb / 10; mb_rem = mb - (10 * mb_quot); @@ -228,13 +190,13 @@ void dev_print (block_dev_desc_t *dev_desc) printf (" Supports 48-bit addressing\n"); #endif #if defined(CONFIG_SYS_64BIT_LBA) - printf (" Capacity: %ld.%ld MB = %ld.%ld GB (%Ld x %ld)\n", + printf (" Capacity: %lu.%lu MB = %lu.%lu GB (%llu x %lu)\n", mb_quot, mb_rem, gb_quot, gb_rem, lba, dev_desc->blksz); #else - printf (" Capacity: %ld.%ld MB = %ld.%ld GB (%ld x %ld)\n", + printf (" Capacity: %lu.%lu MB = %lu.%lu GB (%lu x %lu)\n", mb_quot, mb_rem, gb_quot, gb_rem, (ulong)lba, @@ -248,55 +210,35 @@ void dev_print (block_dev_desc_t *dev_desc) #ifdef HAVE_BLOCK_DEVICE -void init_part (block_dev_desc_t * dev_desc) +void part_init(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 + blkcache_invalidate(dev_desc->if_type, dev_desc->devnum); -#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; + } + } } - -#if defined(CONFIG_MAC_PARTITION) || \ +static void print_part_header(const char *type, struct blk_desc *dev_desc) +{ +#if CONFIG_IS_ENABLED(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, block_dev_desc_t * dev_desc) -{ puts ("\nPartition Map for "); switch (dev_desc->if_type) { case IF_TYPE_IDE: @@ -328,124 +270,65 @@ static void print_part_header (const char *type, block_dev_desc_t * dev_desc) break; } printf (" device %d -- Partition Type: %s\n\n", - dev_desc->dev, type); -} - + dev_desc->devnum, type); #endif /* any CONFIG_..._PARTITION */ +} -void print_part(block_dev_desc_t * dev_desc) +void part_print(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); + drv = part_driver_lookup_type(dev_desc->part_type); + if (!drv) { + printf("## Unknown partition table type %x\n", + dev_desc->part_type); 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); - 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 */ -int get_partition_info(block_dev_desc_t *dev_desc, int part, +int part_get_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 */ info->uuid[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; +#ifdef CONFIG_PARTITION_TYPE_GUID + info->type_guid[0] = 0; #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", + drv->name); + 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 */ return -1; } -int get_device(const char *ifname, const char *dev_hwpart_str, - block_dev_desc_t **dev_desc) +int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, + struct blk_desc **dev_desc) { char *ep; char *dup_str = NULL; @@ -467,7 +350,7 @@ int get_device(const char *ifname, const char *dev_hwpart_str, if (*ep) { printf("** Bad device specification %s %s **\n", ifname, dev_str); - dev = -1; + dev = -EINVAL; goto cleanup; } @@ -476,7 +359,7 @@ int get_device(const char *ifname, const char *dev_hwpart_str, if (*ep) { printf("** Bad HW partition specification %s %s **\n", ifname, hwpart_str); - dev = -1; + dev = -EINVAL; goto cleanup; } } @@ -484,10 +367,20 @@ int get_device(const char *ifname, const char *dev_hwpart_str, *dev_desc = get_dev_hwpart(ifname, dev, hwpart); if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) { printf("** Bad device %s %s **\n", ifname, dev_hwpart_str); - dev = -1; + dev = -ENOENT; goto cleanup; } +#ifdef HAVE_BLOCK_DEVICE + /* + * Updates the partition table for the specified hw partition. + * Does not need to be done for hwpart 0 since it is default and + * already loaded. + */ + if(hwpart != 0) + part_init(*dev_desc); +#endif + cleanup: free(dup_str); return dev; @@ -496,8 +389,8 @@ cleanup: #define PART_UNSPECIFIED -2 #define PART_AUTO -1 #define MAX_SEARCH_PARTITIONS 16 -int get_device_and_partition(const char *ifname, const char *dev_part_str, - block_dev_desc_t **dev_desc, +int blk_get_device_part_str(const char *ifname, const char *dev_part_str, + struct blk_desc **dev_desc, disk_partition_t *info, int allow_whole_dev) { int ret = -1; @@ -510,6 +403,7 @@ int get_device_and_partition(const char *ifname, const char *dev_part_str, int part; disk_partition_t tmpinfo; +#ifdef CONFIG_SANDBOX /* * Special-case a pseudo block device "hostfs", to allow access to the * host's own filesystem. @@ -525,9 +419,35 @@ int get_device_and_partition(const char *ifname, const char *dev_part_str, #ifdef CONFIG_PARTITION_UUIDS info->uuid[0] = 0; #endif +#ifdef CONFIG_PARTITION_TYPE_GUID + info->type_guid[0] = 0; +#endif + + return 0; + } +#endif + +#ifdef CONFIG_CMD_UBIFS + /* + * Special-case ubi, ubi goes through a mtd, rathen then through + * a regular block device. + */ + if (0 == strcmp(ifname, "ubi")) { + if (!ubifs_is_mounted()) { + printf("UBIFS not mounted, use ubifsmount to mount volume first!\n"); + return -1; + } + *dev_desc = NULL; + memset(info, 0, sizeof(*info)); + strcpy((char *)info->type, BOOT_PART_TYPE); + strcpy((char *)info->name, "UBI"); +#ifdef CONFIG_PARTITION_UUIDS + info->uuid[0] = 0; +#endif return 0; } +#endif /* If no dev_part_str, use bootdevice environment variable */ if (!dev_part_str || !strlen(dev_part_str) || @@ -552,7 +472,7 @@ int get_device_and_partition(const char *ifname, const char *dev_part_str, } /* Look up the device */ - dev = get_device(ifname, dev_str, dev_desc); + dev = blk_get_device_by_str(ifname, dev_str, dev_desc); if (dev < 0) goto cleanup; @@ -609,6 +529,9 @@ int get_device_and_partition(const char *ifname, const char *dev_part_str, #ifdef CONFIG_PARTITION_UUIDS info->uuid[0] = 0; #endif +#ifdef CONFIG_PARTITION_TYPE_GUID + info->type_guid[0] = 0; +#endif ret = 0; goto cleanup; @@ -626,7 +549,7 @@ int get_device_and_partition(const char *ifname, const char *dev_part_str, * other than "auto", use that partition number directly. */ if (part != PART_AUTO) { - ret = get_partition_info(*dev_desc, part, info); + ret = part_get_info(*dev_desc, part, info); if (ret) { printf("** Invalid partition %d **\n", part); goto cleanup; @@ -638,7 +561,7 @@ int get_device_and_partition(const char *ifname, const char *dev_part_str, */ part = 0; for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) { - ret = get_partition_info(*dev_desc, p, info); + ret = part_get_info(*dev_desc, p, info); if (ret) continue; @@ -692,3 +615,61 @@ cleanup: free(dup_str); return ret; } + +int part_get_info_by_name(struct blk_desc *dev_desc, const char *name, + disk_partition_t *info) +{ + struct part_driver *first_drv = + ll_entry_start(struct part_driver, part_driver); + const int n_drvs = ll_entry_count(struct part_driver, part_driver); + struct part_driver *part_drv; + + for (part_drv = first_drv; part_drv != first_drv + n_drvs; part_drv++) { + int ret; + int i; + for (i = 1; i < part_drv->max_entries; i++) { + ret = part_drv->get_info(dev_desc, i, info); + if (ret != 0) { + /* no more entries in table */ + break; + } + if (strcmp(name, (const char *)info->name) == 0) { + /* matched */ + return 0; + } + } + } + return -1; +} + +void part_set_generic_name(const struct blk_desc *dev_desc, + int part_num, char *name) +{ + char *devtype; + + switch (dev_desc->if_type) { + case IF_TYPE_IDE: + case IF_TYPE_SATA: + case IF_TYPE_ATAPI: + devtype = "hd"; + break; + case IF_TYPE_SCSI: + devtype = "sd"; + break; + case IF_TYPE_USB: + devtype = "usbd"; + break; + case IF_TYPE_DOC: + devtype = "docd"; + break; + case IF_TYPE_MMC: + case IF_TYPE_SD: + devtype = "mmcsd"; + break; + default: + devtype = "xx"; + break; + } + + sprintf(name, "%s%c%d", devtype, 'a' + dev_desc->devnum, part_num); +}