With this patch it is possible to write an mbr partition table to the mci block device. By setting the device property "dos_partitions" of the mmc device node, it is possible to write back the new partition layout in the common cmdlinepart notation. The property can also be read back. Signed-off-by: Michael Grzeschik <m.grzeschik@xxxxxxxxxxxxxx> --- drivers/mci/mci-core.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 4e176f7..c0013a1 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -33,9 +33,11 @@ #include <asm-generic/div64.h> #include <asm/byteorder.h> #include <block.h> +#include <fcntl.h> #include <disks.h> #include <of.h> #include <linux/err.h> +#include <cmdlinepart.h> #define MAX_BUFFER_NUMBER 0xffffffff @@ -1527,6 +1529,122 @@ static void mci_info(struct device_d *dev) extract_mtd_year(mci)); } +static char *print_size(uint64_t s) +{ + if (!(s & ((1 << 20) - 1))) + return basprintf("%lldM", s >> 20); + if (!(s & ((1 << 10) - 1))) + return basprintf("%lldk", s >> 10); + return basprintf("0x%lld", s); +} + +static int print_part(char *buf, int bufsize, struct cdev *cdev, int is_last) +{ + char *size = print_size(cdev->size); + int ret; + + if (!size) { + ret = -ENOMEM; + goto out; + } + + ret = snprintf(buf, bufsize, "%s(%s)%s", size, + cdev->partname, + is_last ? "" : ","); +out: + free(size); + + return ret; +} + +static int print_parts(char *buf, int bufsize, struct mci *mci) +{ + struct cdev *cdev, *ct; + int ret = 0; + + list_for_each_entry_safe(cdev, ct, &mci->dev.cdevs, devices_list) { + if ((cdev->flags & DEVFS_IS_PARTITION) && + (cdev->flags & DEVFS_PARTITION_IN_PT)) { + int now; + int is_last = 0; + struct list_head *nh = (cdev)->devices_list.next; + struct cdev *next = container_of(nh, typeof(*(cdev)), devices_list); + + if (list_is_last(&cdev->devices_list, &mci->dev.cdevs) || + !(next->flags & DEVFS_PARTITION_IN_PT)) + is_last = 1; + + now = print_part(buf, bufsize, cdev, is_last); + if (now < 0) + return now; + + if (buf && bufsize) { + buf += now; + bufsize -= now; + } + ret += now; + } + } + + return ret; +} + +static const char *mci_partition_get(struct device_d *dev, struct param_d *p) +{ + struct mci *mci = container_of(dev, struct mci, dev); + int len = 0; + + free(p->value); + + len = print_parts(NULL, 0, mci); + p->value = xzalloc(len + 1); + print_parts(p->value, len + 1, mci); + + return p->value; +} + +#ifdef CONFIG_BLOCK_WRITE +static int mci_partition_set(struct device_d *dev, struct param_d *p, const char *val) +{ + struct mci *mci = container_of(dev, struct mci, dev); + struct cdev *cdev, *ct; + int ret; + + if (!val) + return -EINVAL; + + /* remove all partition cdevs with DEVFS_IS_PARTITION set */ + list_for_each_entry_safe(cdev, ct, &mci->dev.cdevs, devices_list) { + if ((cdev->flags & DEVFS_IS_PARTITION) && + (cdev->flags & DEVFS_PARTITION_IN_PT)) + ret = devfs_del_partition(cdev->name); + if (ret) + return ret; + } + + /* read back the prepared partition layot from dos_partitions param */ + ret = cmdlinepart_do_parse(mci->cdevname, val, mci->capacity, + CMDLINEPART_ADD_DEVNAME | CMDLINEPART_ADD_TO_PT); + if (ret) + return ret; + + /* write the MBR partition layout based on cdevs with DEVFS_IS_PARTITION set */ + for (int i = 0; i < mci->nr_parts; i++) { + struct mci_part *part = &mci->part[i]; + if (part->area_type == MMC_BLK_DATA_AREA_MAIN) { + ret = write_dos_partition_table(&part->blk, + &mci->dev.cdevs); + if (ret != 0) { + dev_warn(&mci->dev, "Could not write partition table\n"); + return ret; + } + } + } + + return ret; +} +#endif + /** * Check if the MCI card is already probed * @param mci MCI device instance @@ -1786,6 +1904,10 @@ int mci_register(struct mci_host *host) mci->param_probe = dev_add_param_bool(&mci->dev, "probe", mci_set_probe, NULL, &mci->probe, mci); +#ifdef CONFIG_BLOCK_WRITE + dev_add_param(&mci->dev, "dos_partitions", mci_partition_set, mci_partition_get, 0); +#endif + if (IS_ERR(mci->param_probe) && PTR_ERR(mci->param_probe) != -ENOSYS) { ret = PTR_ERR(mci->param_probe); dev_dbg(&mci->dev, "Failed to add 'probe' parameter to the MCI device\n"); -- 2.9.3 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox