/** * __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; }
/* * 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; }
/** * 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; }
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; }