diff --git a/arch/arm/configs/am335x_defconfig b/arch/arm/configs/am335x_defconfig index 96c6699..382133b 100644 --- a/arch/arm/configs/am335x_defconfig +++ b/arch/arm/configs/am335x_defconfig @@ -22,6 +22,10 @@ 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_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_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_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 844d75d..65d2d25 100644 --- a/commands/ubi.c +++ b/commands/ubi.c @@ -7,30 +7,134 @@ #include #include #include +#include #include #include #include +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 @@ 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 ", "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 085e4a7..fc60aae 100644 --- a/drivers/mtd/ubi/barebox.c +++ b/drivers/mtd/ubi/barebox.c @@ -65,7 +65,10 @@ 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 @@ 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 @@ } } + 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 @@ 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 @@ 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 a7af247..31dbcd2 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -257,16 +257,7 @@ 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 33d4dbf..e3deb3e 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -368,18 +368,6 @@ } 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 4535f2d..f24c219 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -183,7 +183,6 @@ kfree(e); } -#ifndef CONFIG_MTD_UBI_FASTMAP /** * do_work - do one pending work. * @ubi: UBI device description object @@ -221,7 +220,6 @@ return err; } -#endif /** * in_wl_tree - check if wear-leveling entry is present in a WL RB-tree. @@ -523,8 +521,9 @@ 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); } /**