diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2016-07-11 07:58:34 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2016-07-11 07:58:34 +0200 |
commit | 50543054eb23e9b93b5be4a272d130f04bf8bc4d (patch) | |
tree | c7f2dcc723ebcf287063c1699e5d87d54733a631 | |
parent | e77acea709fb64b64ab884f5e946738d326df970 (diff) | |
parent | 2c310bd8a9e43e7023fbf7f0cebb2faaed9b03e0 (diff) | |
download | barebox-50543054eb23e9b93b5be4a272d130f04bf8bc4d.tar.gz barebox-50543054eb23e9b93b5be4a272d130f04bf8bc4d.tar.xz |
Merge branch 'for-next/ubi'
-rw-r--r-- | arch/arm/configs/am335x_defconfig | 12 | ||||
-rw-r--r-- | commands/ubi.c | 119 | ||||
-rw-r--r-- | drivers/mtd/ubi/barebox.c | 56 | ||||
-rw-r--r-- | drivers/mtd/ubi/eba.c | 11 | ||||
-rw-r--r-- | drivers/mtd/ubi/upd.c | 12 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 7 |
6 files changed, 178 insertions, 39 deletions
diff --git a/arch/arm/configs/am335x_defconfig b/arch/arm/configs/am335x_defconfig index 96c6699407..382133b8c4 100644 --- a/arch/arm/configs/am335x_defconfig +++ b/arch/arm/configs/am335x_defconfig @@ -22,6 +22,10 @@ CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y CONFIG_MENU=y # CONFIG_TIMESTAMP is not set +CONFIG_BOOTM_SHOW_TYPE=y +CONFIG_BOOTM_VERBOSE=y +CONFIG_BOOTM_INITRD=y +CONFIG_BOOTM_OFTREE=y CONFIG_BLSPEC=y CONFIG_CONSOLE_ACTIVATE_NONE=y CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y @@ -31,10 +35,6 @@ CONFIG_LONGHELP=y CONFIG_CMD_IOMEM=y CONFIG_CMD_MEMINFO=y CONFIG_CMD_ARM_MMUINFO=y -CONFIG_BOOTM_SHOW_TYPE=y -CONFIG_BOOTM_VERBOSE=y -CONFIG_BOOTM_INITRD=y -CONFIG_BOOTM_OFTREE=y # CONFIG_CMD_BOOTU is not set CONFIG_CMD_BOOTZ=y CONFIG_CMD_GO=y @@ -108,6 +108,7 @@ CONFIG_MTD_M25P80=y CONFIG_NAND=y CONFIG_NAND_OMAP_GPMC=y CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_FASTMAP=y CONFIG_USB_HOST=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y @@ -137,3 +138,6 @@ CONFIG_FS_NFS=y CONFIG_FS_FAT=y CONFIG_FS_FAT_WRITE=y CONFIG_FS_FAT_LFN=y +CONFIG_FS_UBIFS=y +CONFIG_FS_UBIFS_COMPRESSION_LZO=y +CONFIG_FS_UBIFS_COMPRESSION_ZLIB=y diff --git a/commands/ubi.c b/commands/ubi.c index 844d75dcb8..65d2d256a8 100644 --- a/commands/ubi.c +++ b/commands/ubi.c @@ -7,30 +7,134 @@ #include <getopt.h> #include <linux/mtd/mtd.h> #include <linux/kernel.h> +#include <linux/stat.h> #include <linux/mtd/mtd-abi.h> #include <mtd/ubi-user.h> #include <mtd/ubi-media.h> +static int do_ubiupdatevol(int argc, char *argv[]) +{ + int fd_img, fd_vol, ret = 0; + uint64_t size = 0; + struct stat st; + unsigned int count; + void *buf; + + if (argc - optind < 2) + return COMMAND_ERROR_USAGE; + + if (stat(argv[optind + 1], &st)) { + perror("stat image"); + return 1; + } + + size = st.st_size; + + if (size == FILESIZE_MAX) { + printf("%s has unknown filesize, this is not supported\n", + argv[optind + 1]); + return 1; + } + + fd_img = open(argv[optind + 1], O_RDONLY); + if (fd_img < 0) { + perror("open image"); + return 1; + } + + fd_vol = open(argv[optind], O_WRONLY); + if (fd_vol < 0) { + perror("open volume"); + ret = 1; + goto error_img; + } + + ret = ioctl(fd_vol, UBI_IOCVOLUP, &size); + if (ret) { + printf("failed to start update: %s\n", strerror(-ret)); + goto error; + } + + buf = xmalloc(RW_BUF_SIZE); + + while (size) { + + count = read(fd_img, buf, RW_BUF_SIZE); + if (count < 0) { + perror("read"); + ret = 1; + break; + } + + ret = write(fd_vol, buf, count); + if (ret < 0) { + perror("write"); + break; + } + + size -= count; + } + + free(buf); + +error: + close(fd_vol); +error_img: + close(fd_img); + return ret; +} + + +BAREBOX_CMD_HELP_START(ubiupdatevol) +BAREBOX_CMD_HELP_TEXT("Update UBI volume with an image.") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(ubiupdatevol) + .cmd = do_ubiupdatevol, + BAREBOX_CMD_DESC("Update an UBI volume") + BAREBOX_CMD_OPTS("UBIVOL IMAGE") + BAREBOX_CMD_GROUP(CMD_GRP_PART) + BAREBOX_CMD_HELP(cmd_ubiupdatevol_help) +BAREBOX_CMD_END + + static int do_ubimkvol(int argc, char *argv[]) { + int opt; struct ubi_mkvol_req req; int fd, ret; uint64_t size; - if (argc != 4) + req.vol_type = UBI_DYNAMIC_VOLUME; + + while ((opt = getopt(argc, argv, "t:")) > 0) { + switch (opt) { + case 't': + if (!strcmp(optarg, "dynamic")) + req.vol_type = UBI_DYNAMIC_VOLUME; + else if (!strcmp(optarg, "static")) + req.vol_type = UBI_STATIC_VOLUME; + else + return COMMAND_ERROR_USAGE; + break; + default: + return COMMAND_ERROR_USAGE; + } + } + + if (argc - optind != 3) return COMMAND_ERROR_USAGE; - size = strtoull_suffix(argv[3], NULL, 0); - req.name_len = min_t(int, strlen(argv[2]), UBI_VOL_NAME_MAX); - strncpy(req.name, argv[2], req.name_len); + size = strtoull_suffix(argv[optind+2], NULL, 0); + req.name_len = min_t(int, strlen(argv[optind+1]), UBI_VOL_NAME_MAX); + strncpy(req.name, argv[optind+1], req.name_len); req.name[req.name_len] = 0; - req.vol_type = UBI_DYNAMIC_VOLUME; req.bytes = size; req.vol_id = UBI_VOL_NUM_AUTO; req.alignment = 1; - fd = open(argv[1], O_WRONLY); + fd = open(argv[optind], O_WRONLY); if (fd < 0) { perror("open"); return 1; @@ -48,12 +152,13 @@ static int do_ubimkvol(int argc, char *argv[]) BAREBOX_CMD_HELP_START(ubimkvol) BAREBOX_CMD_HELP_TEXT("Create an UBI volume on UBIDEV with NAME and SIZE.") BAREBOX_CMD_HELP_TEXT("If SIZE is 0 all available space is used for the volume.") +BAREBOX_CMD_HELP_OPT("-t <static|dynamic>", "volume type, default is dynamic") BAREBOX_CMD_HELP_END BAREBOX_CMD_START(ubimkvol) .cmd = do_ubimkvol, BAREBOX_CMD_DESC("create an UBI volume") - BAREBOX_CMD_OPTS("UBIDEV NAME SIZE") + BAREBOX_CMD_OPTS("[-t] UBIDEV NAME SIZE") BAREBOX_CMD_GROUP(CMD_GRP_PART) BAREBOX_CMD_HELP(cmd_ubimkvol_help) BAREBOX_CMD_END diff --git a/drivers/mtd/ubi/barebox.c b/drivers/mtd/ubi/barebox.c index 085e4a76d3..fc60aaeec5 100644 --- a/drivers/mtd/ubi/barebox.c +++ b/drivers/mtd/ubi/barebox.c @@ -65,7 +65,10 @@ static ssize_t ubi_volume_cdev_write(struct cdev* cdev, const void *buf, struct ubi_device *ubi = priv->ubi; int err; - if (!priv->written) { + if (!priv->written && !vol->updating) { + if (vol->vol_type == UBI_STATIC_VOLUME) + return -EROFS; + err = ubi_start_update(ubi, vol, vol->used_bytes); if (err < 0) { ubi_err(ubi, "Cannot start volume update"); @@ -104,7 +107,7 @@ static int ubi_volume_cdev_close(struct cdev *cdev) int remaining = vol->usable_leb_size - (priv->written % vol->usable_leb_size); - if (remaining) { + if (remaining && vol->vol_type == UBI_DYNAMIC_VOLUME) { void *buf = kmalloc(remaining, GFP_KERNEL); if (!buf) @@ -122,6 +125,9 @@ static int ubi_volume_cdev_close(struct cdev *cdev) } } + if (vol->vol_type == UBI_STATIC_VOLUME) + cdev->size = priv->written; + err = ubi_finish_update(ubi, vol); if (err) return err; @@ -156,12 +162,54 @@ static loff_t ubi_volume_cdev_lseek(struct cdev *cdev, loff_t ofs) return ofs; } +static int ubi_volume_cdev_ioctl(struct cdev *cdev, int cmd, void *buf) +{ + struct ubi_volume_cdev_priv *priv = cdev->priv; + struct ubi_device *ubi = priv->ubi; + struct ubi_volume *vol = priv->vol; + int err = 0; + + switch (cmd) { + /* Volume update command */ + case UBI_IOCVOLUP: + { + int64_t bytes, rsvd_bytes; + + err = copy_from_user(&bytes, buf, sizeof(int64_t)); + if (err) { + err = -EFAULT; + break; + } + + rsvd_bytes = (long long)vol->reserved_pebs * + ubi->leb_size - vol->data_pad; + + if (bytes < 0 || bytes > rsvd_bytes) { + err = -EINVAL; + break; + } + + err = ubi_start_update(ubi, vol, bytes); + if (bytes == 0) + ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED); + + break; + } + + default: + err = -ENOTTY; + break; + } + return err; +} + static struct file_operations ubi_volume_fops = { .open = ubi_volume_cdev_open, .close = ubi_volume_cdev_close, .read = ubi_volume_cdev_read, .write = ubi_volume_cdev_write, .lseek = ubi_volume_cdev_lseek, + .ioctl = ubi_volume_cdev_ioctl, }; int ubi_volume_cdev_add(struct ubi_device *ubi, struct ubi_volume *vol) @@ -179,6 +227,10 @@ int ubi_volume_cdev_add(struct ubi_device *ubi, struct ubi_volume *vol) cdev->name = basprintf("%s.%s", ubi->cdev.name, vol->name); cdev->priv = priv; cdev->size = vol->used_bytes; + + if (vol->vol_type == UBI_STATIC_VOLUME) + cdev->flags = DEVFS_IS_CHARACTER_DEV; + cdev->dev = &vol->dev; ubi_msg(ubi, "registering %s as /dev/%s", vol->name, cdev->name); ret = devfs_create(cdev); diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index a7af247953..31dbcd29c3 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -257,16 +257,7 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) le = ltree_add_entry(ubi, vol_id, lnum); if (IS_ERR(le)) return PTR_ERR(le); - - /* Contention, cancel */ - le->users -= 1; - ubi_assert(le->users >= 0); - if (le->users == 0) { - rb_erase(&le->rb, &ubi->ltree); - kfree(le); - } - - return 1; + return 0; } /** diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 33d4dbf0bd..e3deb3e931 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -368,18 +368,6 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, } ubi_assert(vol->upd_received <= vol->upd_bytes); - if (vol->upd_received == vol->upd_bytes) { - err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL); - if (err) - return err; - /* The update is finished, clear the update marker */ - err = clear_update_marker(ubi, vol, vol->upd_bytes); - if (err) - return err; - vol->updating = 0; - err = to_write; - vfree(vol->upd_buf); - } return err; } diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 4535f2d804..f24c219819 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -183,7 +183,6 @@ static void wl_entry_destroy(struct ubi_device *ubi, struct ubi_wl_entry *e) kfree(e); } -#ifndef CONFIG_MTD_UBI_FASTMAP /** * do_work - do one pending work. * @ubi: UBI device description object @@ -221,7 +220,6 @@ static int do_work(struct ubi_device *ubi) return err; } -#endif /** * in_wl_tree - check if wear-leveling entry is present in a WL RB-tree. @@ -523,8 +521,9 @@ static void __schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk) list_add_tail(&wrk->list, &ubi->works); ubi_assert(ubi->works_count >= 0); ubi->works_count += 1; - if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled(ubi)) - wake_up_process(ubi->bgt_thread); + + /* No threading in barebox, so do work synchronously */ + do_work(ubi); } /** |