/**
 * __update_vol_patt - update volume using a certain byte pattern
 *
 * @libubi    libubi descriptor
 * @dev_info  UBI device description
 * @test      test name
 * @func      function name
 * @line      line number
 * @node      volume character device node
 * @byte      data pattern to check
 *
 * This function returns %0 in case of success, and %-1 if in case of failure.
 */
int __update_vol_patt(libubi_t libubi, const char *test, const char *func,
		      int line, const char *node, long long bytes, uint8_t byte)
{
	int ret, fd;
	long long written = 0;
	unsigned char buf[512];

	fd = open(node, O_RDWR);
	if (fd == -1) {
		__failed(test, func, line, "open");
		__err_msg(test, func, line, "cannot open \"%s\"\n", node);
		return -1;
	}

	if (ubi_update_start(libubi, fd, bytes)) {
		__failed(test, func, line, "ubi_update_start");
		__err_msg(test, func, line, "bytes = %lld", bytes);
		goto close;
	}

	memset(buf, byte, 512);

	while (written != bytes) {
		ret = write(fd, buf, 512);
		if (ret == -1) {
			__failed(test, func, line, "write");
			__err_msg(test, func, line, "written = %lld, ret = %d",
				  written, ret);
			goto close;
		}
		written += ret;

		if (written > bytes) {
			__err_msg(test, func, line, "update length %lld bytes, "
				  "but %lld bytes are already written",
				  bytes, written);
			goto close;
		}
	}

	close(fd);
	return 0;

close:
	close(fd);
	return -1;
}
/*
 * Read bootenv from ubi volume
 */
static int
ubi_write_bootenv(uint32_t devno, uint32_t id, bootenv_t env)
{
	libubi_t ulib;
	int rc = 0;
	char path[PATH_MAX];
	FILE* fp_out = NULL;
	size_t nbytes;

	rc = bootenv_size(env, &nbytes);
	if (rc) {
		err_msg("Cannot determine size of bootenv structure\n");
		return rc;
	}
	ulib = libubi_open();
	if (ulib == NULL) {
		err_msg("Cannot allocate ubi structure\n");
		return rc;
	}

	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);

	fp_out = fopen(path, "r+");
	if (fp_out == NULL) {
		err_msg("Cannot fopen volume:%d number:%d\n", devno, id);
		rc = -EBADF;
		goto err;
	}

	rc = ubi_update_start(ulib, fileno(fp_out), nbytes);
	if (rc != 0) {
		err_msg("Cannot start update for %s\n", path);
		goto err;
	}

	rc = bootenv_write(fp_out, env);
	if (rc != 0) {
		err_msg("Cannot write bootenv to volume %d number:%d\n",
			devno, id);
		goto err;
	}
err:
	if( fp_out )
		fclose(fp_out);
	libubi_close(ulib);
	return rc;
}
extern "C" int ubiVolumeFormat(char *location)
{
    int ret = -1;
    libubi_t libubi;
    struct ubi_vol_info vol_info;
    int fd;
    libubi = libubi_open();

    if (libubi == NULL) {
        fprintf(stderr, "can not open libubi");
        goto done;
    }

    ret = ubi_get_vol_info(libubi, location, &vol_info);
    if (ret) {
        fprintf(stderr, "can not get information about UBI volume %s", location);
        goto done;
    }

    fd = open(location, O_RDWR);
    if (fd == -1) {
        fprintf(stderr, "can not open %s", location);
        goto done;
    }

    ret = ubi_update_start(libubi, fd, 0);
    if (ret) {
        fprintf(stderr, "cannot truncate volume %s", location);
        close(fd);
        goto done;
    }

    close(fd);

  done:
    return ret;
}
Exemple #4
0
/*
 * Helper function for test_rsvol().
 */
static int test_rsvol1(struct ubi_vol_info *vol_info)
{
	long long bytes;
	struct ubi_vol_info vol_info1;
	char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
	unsigned char buf[vol_info->rsvd_bytes];
	int fd, i, ret;

	/* Make the volume smaller and check basic volume I/O */
	bytes = vol_info->rsvd_bytes - vol_info->leb_size;
	if (ubi_rsvol(libubi, node, vol_info->vol_id, bytes - 1)) {
		failed("ubi_rsvol");
		return -1;
	}

	if (ubi_get_vol_info1(libubi, vol_info->dev_num, vol_info->vol_id,
			     &vol_info1)) {
		failed("ubi_get_vol_info");
		return -1;
	}

	if (vol_info1.rsvd_bytes != bytes) {
		errorm("rsvd_bytes %lld, must be %lld",
		       vol_info1.rsvd_bytes, bytes);
		return -1;
	}

	if (vol_info1.rsvd_lebs != vol_info->rsvd_lebs - 1) {
		errorm("rsvd_lebs %d, must be %d",
		       vol_info1.rsvd_lebs, vol_info->rsvd_lebs - 1);
		return -1;
	}

	/* Write data to the volume */
	sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num,
			vol_info->vol_id);

	fd = open(vol_node, O_RDWR);
	if (fd == -1) {
		failed("open");
		errorm("cannot open \"%s\"\n", vol_node);
		return -1;
	}

	bytes = vol_info->rsvd_bytes - vol_info->leb_size - 1;
	if (ubi_update_start(libubi, fd, bytes)) {
		failed("ubi_update_start");
		goto close;
	}

	for (i = 0; i < bytes; i++)
		buf[i] = (unsigned char)i;

	ret = write(fd, buf, bytes);
	if (ret != bytes) {
		failed("write");
		goto close;
	}

	close(fd);

	if (ubi_rsvol(libubi, node, vol_info->vol_id, bytes)) {
		failed("ubi_rsvol");
		return -1;
	}

	if (ubi_rsvol(libubi, node, vol_info->vol_id,
		      (long long)vol_info->leb_size * dev_info.avail_lebs)) {
		failed("ubi_rsvol");
		return -1;
	}

	fd = open(vol_node, O_RDWR);
	if (fd == -1) {
		failed("open");
		errorm("cannot open \"%s\"\n", vol_node);
		return -1;
	}

	/* Read data back */
	if (lseek(fd, 0, SEEK_SET) != 0) {
		failed("seek");
		goto close;
	}
	memset(buf, 0, bytes);
	ret = read(fd, buf, bytes);
	if (ret != bytes) {
		failed("read");
		goto close;
	}

	for (i = 0; i < bytes; i++) {
		if (buf[i] != (unsigned char)i) {
			errorm("bad data");
			goto close;
		}
	}

	close(fd);
	return 0;

close:
	close(fd);
	return -1;
}
Exemple #5
0
/**
 * the_thread - the testing thread.
 *
 * @ptr  thread number
 */
static void * the_thread(void *ptr)
{
	int fd, iter = iterations, vol_id = (int)ptr;
	unsigned char *wbuf, *rbuf;
	char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];

	wbuf = malloc(total_bytes);
	rbuf = malloc(total_bytes);
	if (!wbuf || !rbuf) {
		failed("malloc");
		goto free;
	}

	sprintf(&vol_node[0], UBI_VOLUME_PATTERN, dev_info.dev_num, vol_id);

	while (iter--) {
		int i, ret, written = 0, rd = 0;
		int bytes = (random() % (total_bytes - 1)) + 1;

		fd = open(vol_node, O_RDWR);
		if (fd == -1) {
			failed("open");
			err_msg("cannot open \"%s\"\n", node);
			goto free;
		}

		for (i = 0; i < bytes; i++)
			wbuf[i] = random() % 255;
		memset(rbuf, '\0', bytes);

		do {
			ret = ubi_update_start(libubi, fd, bytes);
			if (ret && errno != EBUSY) {
				failed("ubi_update_start");
				err_msg("vol_id %d", vol_id);
				goto close;
			}
		} while (ret);

		while (written < bytes) {
			int to_write = random() % (bytes - written);

			if (to_write == 0)
				to_write = 1;

			ret = write(fd, wbuf, to_write);
			if (ret != to_write) {
				failed("write");
				err_msg("failed to write %d bytes at offset %d "
					"of volume %d", to_write, written,
					vol_id);
				err_msg("update: %d bytes", bytes);
				goto close;
			}

			written += to_write;
		}

		close(fd);

		fd = open(vol_node, O_RDONLY);
		if (fd == -1) {
			failed("open");
			err_msg("cannot open \"%s\"\n", node);
			goto free;
		}

		/* read data back and check */
		while (rd < bytes) {
			int to_read = random() % (bytes - rd);

			if (to_read == 0)
				to_read = 1;

			ret = read(fd, rbuf, to_read);
			if (ret != to_read) {
				failed("read");
				err_msg("failed to read %d bytes at offset %d "
					"of volume %d", to_read, rd, vol_id);
				goto close;
			}

			rd += to_read;
		}

		close(fd);

	}

	free(wbuf);
	free(rbuf);
	return NULL;

close:
	close(fd);
free:
	free(wbuf);
	free(rbuf);
	return NULL;
}
Exemple #6
0
static int update_volume(libubi_t libubi, int fdsw, struct img_type *img,
	struct ubi_vol_info *vol)
{
	long long bytes;
	int fdout;
	char node[64];
	int err;
	unsigned long offset = 0;
	uint32_t checksum = 0;
	char sbuf[128];

	bytes = img->size;

	if (!libubi) {
		ERROR("Request to write into UBI, but no UBI on system");
		return -1;
	}

	if (bytes > vol->rsvd_bytes) {
		ERROR("\"%s\" (size %lld) will not fit volume \"%s\" (size %lld)",
		       img->fname, bytes, img->volname, vol->rsvd_bytes);
		return -1;
	}

	snprintf(node, sizeof(node), "/dev/ubi%d_%d",
		vol->dev_num,
		vol->vol_id);

	err = ubi_probe_node(libubi, node);

	if (err == 1) {
		ERROR("\"%s\" is an UBI device node, not an UBI volume node",
			node);
		return -1;
	}
	if (err < 0) {
		if (errno == ENODEV)
			ERROR("%s is not an UBI volume node", node);
		else
			ERROR("error while probing %s", node);
		return -1;
	}

	fdout = open(node, O_RDWR);
	if (fdout < 0) {
		ERROR("cannot open UBI volume \"%s\"", node);
		return -1;
	}
	err = ubi_update_start(libubi, fdout, bytes);
	if (err) {
		ERROR("cannot start volume \"%s\" update", node);
		return -1;
	}

	snprintf(sbuf, sizeof(sbuf), "Installing image %s into volume %s(%s)",
		img->fname, node, img->volname);
	notify(RUN, RECOVERY_NO_ERROR, sbuf);

	printf("Updating UBI : %s %lld %lu\n",
			img->fname, img->size, offset);
	if (copyfile(fdsw, fdout, img->size, (unsigned long *)&img->offset, 0,
		img->compressed, &checksum) < 0) {
		ERROR("Error copying extracted file");
		err = -1;
	}
	close(fdout);
	return err;
}
/*
 * test_update1 - helper function for test_update().
 */
static int test_update1(struct ubi_vol_info *vol_info, int leb_change)
{
	long long total_len = leb_change ? vol_info->leb_size
					 : vol_info->rsvd_bytes;
	int sequences[SEQ_SZ][3] = SEQUENCES(dev_info.min_io_size,
					     leb_change ? dev_info.min_io_size * 2
					     		: vol_info->leb_size);
	char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
	unsigned char buf[total_len];
	int fd, i, j;

	sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num,
		vol_info->vol_id);

	fd = open(vol_node, O_RDWR);
	if (fd == -1) {
		failed("open");
		err_msg("cannot open \"%s\"\n", node);
		return -1;
	}

	for (i = 0; i < SEQ_SZ; i++) {
		int ret, stop = 0, len = 0;
		off_t off = 0;
		long long test_len;
		unsigned char buf1[total_len];

		/*
		 * test_len is LEB size (if we test atomic LEB change) or
		 * volume size (if we test update). For better test coverage,
		 * use a little smaller LEB change/update length.
		 */
		test_len = total_len - (rand() % (total_len / 10));

		if (leb_change) {
			if (ubi_leb_change_start(libubi, fd, 0, test_len,
						 UBI_SHORTTERM)) {
				failed("ubi_update_start");
				goto close;
			}
		} else {
			if (ubi_update_start(libubi, fd, test_len)) {
				failed("ubi_update_start");
				goto close;
			}
		}

		for (j = 0; off < test_len; j++) {
			int n, rnd_len, l;

			if (!stop) {
				if (sequences[i][j] != 0)
					l = len = sequences[i][j];
				else
					stop = 1;
			}

			/*
			 * Fill some part of the write buffer with random data,
			 * and the other part with 0xFFs to test how UBI
			 * stripes 0xFFs multiple of I/O unit size.
			 */
			if (off + l > test_len)
				l = test_len - off;
			rnd_len = rand() % (l + 1);
			for (n = 0; n < rnd_len; n++)
				buf[off + n] = (unsigned char)rand();
				memset(buf + off + rnd_len, 0xFF, l - rnd_len);

			/*
			 * Deliberately pass len instead of l (len may be
			 * greater then l if this is the last chunk) because
			 * UBI have to read only l bytes anyway.
			 */
			ret = write(fd, buf + off, len);
			if (ret < 0) {
				failed("write");
				err_msg("failed to write %d bytes at offset "
					"%lld", len, (long long)off);
				goto close;
			}
			len = l;
			if (ret != len) {
				err_msg("failed to write %d bytes at offset "
					"%lld, wrote %d", len, (long long)off, ret);
				goto close;
			}
			off += len;
		}

		/* Check data */
		if ((ret = lseek(fd, SEEK_SET, 0)) != 0) {
			failed("lseek");
			err_msg("cannot seek to 0");
			goto close;
		}

		memset(buf1, 0x01, test_len);

		if (vol_info->type == UBI_STATIC_VOLUME)
			/*
			 * Static volume must not let use read more then it
			 * contains.
			 */
			ret = read(fd, buf1, test_len + 100);
		else
			ret = read(fd, buf1, test_len);
		if (ret < 0) {
			failed("read");
			err_msg("failed to read %d bytes", test_len);
			goto close;
		}
		if (ret != test_len) {
			err_msg("failed to read %d bytes, read %d", test_len, ret);
			goto close;
		}
		if (memcmp(buf, buf1, test_len)) {
			err_msg("data corruption");
			goto close;
		}
	}

	close(fd);
	return 0;

close:
	close(fd);
	return -1;
}