static int do_ubiformat(int argc, char *argv[]) { int err, fd; struct ubiformat_args args; char *node = NULL; struct mtd_info_user mtd_user; err = parse_opt(argc, argv, &args, &node); if (err) return err; fd = open(node, O_RDWR); if (fd < 0) return sys_errmsg("cannot open \"%s\"", node); err = ioctl(fd, MEMGETINFO, &mtd_user); if (err) { sys_errmsg("MEMGETINFO ioctl request failed"); goto out_close; } err = ubiformat(mtd_user.mtd, &args); out_close: close(fd); return err; }
static int open_file(off_t *sz) { int fd; if (!strcmp(args.image, "-")) { if (args.image_sz == 0) return errmsg("must use '-S' with non-zero value when reading from stdin"); *sz = args.image_sz; fd = dup(STDIN_FILENO); if (fd < 0) return sys_errmsg("failed to dup stdin"); } else { struct stat st; if (stat(args.image, &st)) return sys_errmsg("cannot open \"%s\"", args.image); *sz = st.st_size; fd = open(args.image, O_RDONLY); if (fd == -1) return sys_errmsg("cannot open \"%s\"", args.image); } return fd; }
int legacy_get_mtd_oobavail(const char *node) { struct stat st; struct nand_ecclayout_user usrlay; int fd, ret; if (stat(node, &st)) return sys_errmsg("cannot open \"%s\"", node); if (!S_ISCHR(st.st_mode)) { errno = EINVAL; return errmsg("\"%s\" is not a character device", node); } fd = open(node, O_RDONLY); if (fd == -1) return sys_errmsg("cannot open \"%s\"", node); ret = ioctl(fd, ECCGETLAYOUT, &usrlay); if (ret < 0) { if (errno == EOPNOTSUPP) goto out_close; sys_errmsg("ECCGETLAYOUT ioctl request failed"); goto out_close; } ret = usrlay.oobavail; out_close: close(fd); return ret; }
int mtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs, void *buf, int len) { int ret, rd = 0; off_t seek; if (eb < 0 || eb >= mtd->eb_cnt) { errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks", eb, mtd->dev_num, mtd->eb_cnt); errno = EINVAL; return -1; } if (offs < 0 || offs + len > mtd->eb_size) { errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d", offs, len, mtd->dev_num, mtd->eb_size); errno = EINVAL; return -1; } /* Seek to the beginning of the eraseblock */ seek = (off_t)eb * mtd->eb_size + offs; if (lseek(fd, seek, SEEK_SET) != seek) return sys_errmsg("cannot seek mtd%d to offset %llu", mtd->dev_num, (unsigned long long)seek); while (rd < len) { ret = read(fd, buf, len); if (ret < 0) return sys_errmsg("cannot read %d bytes from mtd%d (eraseblock %d, offset %d)", len, mtd->dev_num, eb, offs); rd += ret; } return 0; }
static void print_region_map(const struct mtd_dev_info *mtd, int fd, const region_info_t *reginfo) { unsigned long start; int i, width; int ret_locked, errno_locked, ret_bad, errno_bad; printf("Eraseblock map:\n"); /* Figure out the number of spaces to pad w/out libm */ for (i = 1, width = 0; i < reginfo->numblocks; i *= 10, ++width) continue; /* If we don't have a fd to query, just show the bare map */ if (fd == -1) { ret_locked = ret_bad = -1; errno_locked = errno_bad = ENODEV; } else ret_locked = ret_bad = errno_locked = errno_bad = 0; for (i = 0; i < reginfo->numblocks; ++i) { start = reginfo->offset + i * reginfo->erasesize; printf(" %*i: %08lx ", width, i, start); if (ret_locked != -1) { ret_locked = mtd_is_locked(mtd, fd, i); if (ret_locked == 1) printf("RO "); else errno_locked = errno; } if (ret_locked != 1) printf(" "); if (ret_bad != -1) { ret_bad = mtd_is_bad(mtd, fd, i); if (ret_bad == 1) printf("BAD "); else errno_bad = errno; } if (ret_bad != 1) printf(" "); if (((i + 1) % 4) == 0) printf("\n"); } if (i % 4) printf("\n"); if (ret_locked == -1 && errno_locked != EOPNOTSUPP) { errno = errno_locked; sys_errmsg("could not read locked block info"); } if (mtd->bb_allowed && ret_bad == -1 && errno_bad != EOPNOTSUPP) { errno = errno_bad; sys_errmsg("could not read bad block info"); } }
/** * refill_wl_pool - refills all the fastmap pool used by the * WL sub-system and ubi_wl_get_peb. * @ubi: UBI device description object */ static void ubi_refill_pools(struct ubigen_info *ui, int fd) { struct ubi_fm_pool *pool = &ui->fm_wl_pool; int start = ui->used_peb; off_t seek; char *outbuf; outbuf = malloc(ui->peb_size); memset(outbuf, 0xFF, ui->peb_size); ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ui->ec); printf("Start PEB %d for wl pool size %d\n", start, pool->max_size); for (pool->size = 0; pool->size < pool->max_size; pool->size++) { if (ui->peb_count - start < 5) break; seek = start * ui->peb_size; if (lseek(fd, seek, SEEK_SET) != seek) { sys_errmsg("cannot seek output file"); break; } if (write(fd, outbuf, ui->peb_size) != ui->peb_size) { sys_errmsg("cannot write %d bytes to the output file", ui->peb_size); break; } pool->pebs[pool->size] = start; start++; } printf( "End PEB %d for wl pool\n", start-1); printf( "found %d PEB for wl pool\n", pool->size); pool->used = 0; pool = &ui->fm_pool; printf( "Start PEB %d for user wl pool size %d\n", start, pool->max_size); for (pool->size = 0; pool->size < pool->max_size; pool->size++) { if (ui->peb_count - start < 1) break; seek = start * ui->peb_size; if (lseek(fd, seek, SEEK_SET) != seek) { sys_errmsg("cannot seek output file"); break; } if (write(fd, outbuf, ui->peb_size) != ui->peb_size) { sys_errmsg("cannot write %d bytes to the output file", ui->peb_size); break; } pool->pebs[pool->size] = start; start++; } printf( "End PEB %d for user wl pool\n", start-1); printf( "found %d PEB for wl pool\n", pool->size); pool->used = 0; }
/** * ubigen_write_volume - write UBI volume. * @ui: libubigen information * @vi: volume information * @ec: erase coutner value to put to EC headers * @bytes: volume size in bytes * @in: input file descriptor (has to be properly seeked) * @out: output file descriptor * * This function reads the contents of the volume from the input file @in and * writes the UBI volume to the output file @out. Returns zero on success and * %-1 on failure. */ int ubigen_write_volume(const struct ubigen_info *ui, const struct ubigen_vol_info *vi, long long ec, long long bytes, int in, int out) { int len = vi->usable_leb_size, rd, lnum = 0; char inbuf[ui->leb_size], outbuf[ui->peb_size]; if (vi->id >= ui->max_volumes) return errmsg("too high volume id %d, max. volumes is %d", vi->id, ui->max_volumes); if (vi->alignment >= ui->leb_size) return errmsg("too large alignment %d, max is %d (LEB size)", vi->alignment, ui->leb_size); memset(outbuf, 0xFF, ui->data_offs); ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec); while (bytes) { int l; struct ubi_vid_hdr *vid_hdr; if (bytes < len) len = bytes; bytes -= len; l = len; do { rd = read(in, inbuf + len - l, l); if (rd != l) return sys_errmsg("cannot read %d bytes from the input file", l); l -= rd; } while (l); vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]); init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len); memcpy(outbuf + ui->data_offs, inbuf, len); memset(outbuf + ui->data_offs + len, 0xFF, ui->peb_size - ui->data_offs - len); if (write(out, outbuf, ui->peb_size) != ui->peb_size) return sys_errmsg("cannot write %d bytes to the output file", ui->peb_size); lnum += 1; } return 0; }
static int open_file(off_t *sz) { int fd; struct stat st; if (stat(args.image, &st)) return sys_errmsg("cannot open \"%s\"", args.image); *sz = st.st_size; fd = open(args.image, O_RDONLY); if (fd < 0) return sys_errmsg("cannot open \"%s\"", args.image); return fd; }
/** * vol_node2nums - find UBI device number and volume ID by volume device node * file. * @lib: UBI library descriptor * @node: UBI character device node name * @dev_num: UBI device number is returned here * @vol_id: volume ID is returned hers * * This function returns zero in case of succes and %-1 in case of failure. */ static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num, int *vol_id) { struct stat st; struct ubi_info info; int i, fd, major, minor; char file[strlen(lib->ubi_vol) + 100]; if (stat(node, &st)) return sys_errmsg("cannot get information about \"%s\"", node); if (!S_ISCHR(st.st_mode)) { errno = EINVAL; return errmsg("\"%s\" is not a character device", node); } major = major(st.st_rdev); minor = minor(st.st_rdev); if (minor == 0) { errno = EINVAL; return errmsg("\"%s\" is not a volume character device", node); } if (ubi_get_info((libubi_t *)lib, &info)) return -1; for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { int major1, minor1, ret; ret = dev_get_major(lib, i, &major1, &minor1); if (ret) { if (errno == ENOENT) continue; return -1; } if (major1 == major) break; } if (i > info.highest_dev_num) { errno = ENODEV; return -1; } /* Make sure this UBI volume exists */ sprintf(file, lib->ubi_vol, i, minor - 1); fd = open(file, O_RDONLY); if (fd == -1) { errno = ENODEV; return -1; } *dev_num = i; *vol_id = minor - 1; errno = 0; return 0; }
int ubi_rmvol(libubi_t desc, const char *node, int vol_id) { int fd, ret; desc = desc; fd = open(node, O_RDONLY); if (fd == -1) return sys_errmsg("cannot open \"%s\"", node); ret = ioctl(fd, UBI_IOCRMVOL, &vol_id); if (ret == -1) { close(fd); return ret; } close(fd); #ifdef UDEV_SETTLE_HACK // if (system("udevsettle") == -1) // return -1; usleep(100000); #endif return 0; }
int ubi_attach_mtd(libubi_t desc, const char *node, struct ubi_attach_request *req) { int fd, ret; struct ubi_attach_req r; memset(&r, sizeof(struct ubi_attach_req), '\0'); desc = desc; r.ubi_num = req->dev_num; r.mtd_num = req->mtd_num; r.vid_hdr_offset = req->vid_hdr_offset; fd = open(node, O_RDONLY); if (fd == -1) return sys_errmsg("cannot open \"%s\"", node); ret = ioctl(fd, UBI_IOCATT, &r); close(fd); if (ret == -1) return -1; req->dev_num = r.ubi_num; #ifdef UDEV_SETTLE_HACK if (system("udevsettle") == -1) return -1; #endif return ret; }
static int proc_parse_start(struct proc_parse_info *pi) { int fd, ret; fd = open(MTD_PROC_FILE, O_RDONLY); if (fd == -1) return -1; pi->buf = xmalloc(PROC_MTD_MAX_LEN); ret = read(fd, pi->buf, PROC_MTD_MAX_LEN); if (ret == -1) { sys_errmsg("cannot read \"%s\"", MTD_PROC_FILE); goto out_free; } if (ret < PROC_MTD_FIRST_LEN || memcmp(pi->buf, PROC_MTD_FIRST, PROC_MTD_FIRST_LEN)) { errmsg("\"%s\" does not start with \"%s\"", MTD_PROC_FILE, PROC_MTD_FIRST); goto out_free; } pi->data_size = ret; pi->next = pi->buf + PROC_MTD_FIRST_LEN; close(fd); return 0; out_free: free(pi->buf); close(fd); return -1; }
int main(int argc, char * const argv[]) { int err; libmtd_t libmtd; struct mtd_info mtd_info; err = parse_opt(argc, argv); if (err) return -1; libmtd = libmtd_open(); if (libmtd == NULL) { if (errno == 0) return errmsg("MTD is not present in the system"); return sys_errmsg("cannot open libmtd"); } err = mtd_get_info(libmtd, &mtd_info); if (err) { if (errno == ENODEV) return errmsg("MTD is not present"); return sys_errmsg("cannot get MTD information"); } if (!args.all && args.node) { int mtdn; /* * A character device was specified, translate this to MTD * device number. */ mtdn = translate_dev(libmtd, args.node); if (mtdn < 0) goto out_libmtd; err = print_dev_info(libmtd, &mtd_info, mtdn); } else err = print_general_info(libmtd, &mtd_info, args.all); if (err) goto out_libmtd; libmtd_close(libmtd); return 0; out_libmtd: libmtd_close(libmtd); return -1; }
int ubi_probe_node(libubi_t desc, const char *node) { struct stat st; struct ubi_info info; int i, fd, major, minor; struct libubi *lib = (struct libubi *)desc; char file[strlen(lib->ubi_vol) + 100]; if (stat(node, &st)) return sys_errmsg("cannot get information about \"%s\"", node); if (!S_ISCHR(st.st_mode)) { errmsg("\"%s\" is not a character device", node); errno = EINVAL; return -1; } major = major(st.st_rdev); minor = minor(st.st_rdev); if (ubi_get_info((libubi_t *)lib, &info)) return -1; for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { int major1, minor1, ret; ret = dev_get_major(lib, i, &major1, &minor1); if (ret) { if (errno == ENOENT) continue; if (!errno) goto out_not_ubi; return -1; } if (major1 == major) break; } if (i > info.highest_dev_num) goto out_not_ubi; if (minor == 0) return 1; /* This is supposdely an UBI volume device node */ sprintf(file, lib->ubi_vol, i, minor - 1); fd = open(file, O_RDONLY); if (fd == -1) goto out_not_ubi; return 2; out_not_ubi: errmsg("\"%s\" has major:minor %d:%d, but this does not correspond to " "any existing UBI device or volume", node, major, minor); errno = ENODEV; return -1; }
/** * read_data - read data from a file. * @file: the file to read from * @buf: the buffer to read to * @buf_len: buffer length * * This function returns number of read bytes in case of success and %-1 in * case of failure. Note, if the file contains more then @buf_len bytes of * date, this function fails with %EINVAL error code. */ static int read_data(const char *file, void *buf, int buf_len) { int fd, rd, tmp, tmp1; fd = open(file, O_RDONLY); if (fd == -1) return -1; rd = read(fd, buf, buf_len); if (rd == -1) { sys_errmsg("cannot read \"%s\"", file); goto out_error; } if (rd == buf_len) { errmsg("contents of \"%s\" is too long", file); errno = EINVAL; goto out_error; } ((char *)buf)[rd] = '\0'; /* Make sure all data is read */ tmp1 = read(fd, &tmp, 1); if (tmp1 == 1) { sys_errmsg("cannot read \"%s\"", file); goto out_error; } if (tmp1) { errmsg("file \"%s\" contains too much data (> %d bytes)", file, buf_len); errno = EINVAL; goto out_error; } if (close(fd)) { sys_errmsg("close failed on \"%s\"", file); return -1; } return rd; out_error: close(fd); return -1; }
int mtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs, void *buf, int len) { int ret; off_t seek; if (eb < 0 || eb >= mtd->eb_cnt) { errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks", eb, mtd->dev_num, mtd->eb_cnt); errno = EINVAL; return -1; } if (offs < 0 || offs + len > mtd->eb_size) { errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d", offs, len, mtd->dev_num, mtd->eb_size); errno = EINVAL; return -1; } if (offs % mtd->subpage_size) { errmsg("write offset %d is not aligned to mtd%d min. I/O size %d", offs, mtd->dev_num, mtd->subpage_size); errno = EINVAL; return -1; } if (len % mtd->subpage_size) { errmsg("write length %d is not aligned to mtd%d min. I/O size %d", len, mtd->dev_num, mtd->subpage_size); errno = EINVAL; return -1; } /* Seek to the beginning of the eraseblock */ seek = (off_t)eb * mtd->eb_size + offs; if (lseek(fd, seek, SEEK_SET) != seek) return sys_errmsg("cannot seek mtd%d to offset %llu", mtd->dev_num, (unsigned long long)seek); ret = write(fd, buf, len); if (ret != len) return sys_errmsg("cannot write %d bytes to mtd%d (eraseblock %d, offset %d)", len, mtd->dev_num, eb, offs); return 0; }
/** * read_hex_ll - read a hex 'long long' value from a file. * @file: the file to read from * @value: the result is stored here * * This function reads file @file and interprets its contents as hexadecimal * 'long long' integer. If this is not true, it fails with %EINVAL error code. * Returns %0 in case of success and %-1 in case of failure. */ static int read_hex_ll(const char *file, long long *value) { int fd, rd; char buf[50]; fd = open(file, O_RDONLY); if (fd == -1) return -1; rd = read(fd, buf, sizeof(buf)); if (rd == -1) { sys_errmsg("cannot read \"%s\"", file); goto out_error; } if (rd == sizeof(buf)) { errmsg("contents of \"%s\" is too long", file); errno = EINVAL; goto out_error; } buf[rd] = '\0'; if (sscanf(buf, "%llx\n", value) != 1) { errmsg("cannot read integer from \"%s\"\n", file); errno = EINVAL; goto out_error; } if (*value < 0) { errmsg("negative value %lld in \"%s\"", *value, file); errno = EINVAL; goto out_error; } if (close(fd)) return sys_errmsg("close failed on \"%s\"", file); return 0; out_error: close(fd); return -1; }
/** * read_positive_ll - read a positive 'long long' value from a file. * @file: the file to read from * @value: the result is stored here * * This function reads file @file and interprets its contents as a positive * 'long long' integer. If this is not true, it fails with %EINVAL error code. * Returns %0 in case of success and %-1 in case of failure. */ static int read_positive_ll(const char *file, long long *value) { int fd, rd; char buf[50]; fd = open(file, O_RDONLY); if (fd == -1) return -1; rd = read(fd, buf, 50); if (rd == -1) { sys_errmsg("cannot read \"%s\"", file); goto out_error; } if (rd == 50) { errmsg("contents of \"%s\" is too long", file); errno = EINVAL; goto out_error; } if (sscanf(buf, "%lld\n", value) != 1) { /* This must be a UBI bug */ errmsg("cannot read integer from \"%s\"\n", file); errno = EINVAL; goto out_error; } if (*value < 0) { errmsg("negative value %lld in \"%s\"", *value, file); errno = EINVAL; goto out_error; } if (close(fd)) return sys_errmsg("close failed on \"%s\"", file); return 0; out_error: close(fd); return -1; }
static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int mtdn) { int err; struct mtd_dev_info mtd; err = mtd_get_dev_info1(libmtd, mtdn, &mtd); if (err) { if (errno == ENODEV) return errmsg("mtd%d does not correspond to any " "existing MTD device", mtdn); return sys_errmsg("cannot get information about MTD device %d", mtdn); } printf("mtd%d\n", mtd.mtd_num); printf("Name: %s\n", mtd.name); printf("Type: %s\n", mtd.type_str); printf("Eraseblock size: "); ubiutils_print_bytes(mtd.eb_size, 0); printf("\n"); printf("Amount of eraseblocks: %d (", mtd.eb_cnt); ubiutils_print_bytes(mtd.size, 0); printf(")\n"); printf("Minimum input/output unit size: %d %s\n", mtd.min_io_size, mtd.min_io_size > 1 ? "bytes" : "byte"); if (mtd_info->sysfs_supported) printf("Sub-page size: %d %s\n", mtd.subpage_size, mtd.subpage_size > 1 ? "bytes" : "byte"); else if (mtd.type == MTD_NANDFLASH || mtd.type == MTD_MLCNANDFLASH) printf("Sub-page size: unknown\n"); if (mtd.oob_size > 0) printf("OOB size: %d bytes\n", mtd.oob_size); if (mtd.region_cnt > 0) printf("Additional erase regions: %d\n", mtd.oob_size); if (mtd_info->sysfs_supported) printf("Character device major/minor: %d:%d\n", mtd.major, mtd.minor); printf("Bad blocks are allowed: %s\n", mtd.bb_allowed ? "true" : "false"); printf("Device is writable: %s\n", mtd.writable ? "true" : "false"); if (args.ubinfo) print_ubi_info(mtd_info, &mtd); print_region_info(&mtd); printf("\n"); return 0; }
/** * legacy_procfs_is_supported - legacy version of 'sysfs_is_supported()'. * * Check if we can access the procfs files for the MTD subsystem. */ int legacy_procfs_is_supported(void) { if (access(MTD_PROC_FILE, R_OK) != 0) { if (errno == ENOENT) { errno = 0; } else { sys_errmsg("cannot read \"%s\"", MTD_PROC_FILE); } return 0; } return 1; }
/** * dev_node2num - find UBI device number by its character device node. * @lib: UBI library descriptor * @node: UBI character device node name * * This function returns positive UBI device number in case of success and %-1 * in case of failure. */ static int dev_node2num(struct libubi *lib, const char *node, int *dev_num) { struct stat st; struct ubi_info info; int i, major, minor; if (stat(node, &st)) return sys_errmsg("cannot get information about \"%s\"", node); if (!S_ISCHR(st.st_mode)) { errno = EINVAL; return errmsg("\"%s\" is not a character device", node); } major = major(st.st_rdev); minor = minor(st.st_rdev); if (minor != 0) { errno = EINVAL; return errmsg("\"%s\" is not an UBI character device", node); } if (ubi_get_info((libubi_t *)lib, &info)) return -1; for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { int major1, minor1, ret; ret = dev_get_major(lib, i, &major1, &minor1); if (ret) { if (errno == ENOENT) continue; return -1; } if (major1 == major) { if (minor1 != 0) { errmsg("UBI character device minor number is " "%d, but must be 0", minor1); errno = EINVAL; return -1; } errno = 0; *dev_num = i; return 0; } } errno = ENODEV; return -1; }
int main(int argc, char * const argv[]) { int err = 0; uint32_t crc = UBI_CRC32_INIT; char buf[BUFSIZE]; FILE *fp; if (argc > 1) { fp = fopen(argv[1], "r"); if (!fp) return sys_errmsg("cannot open \"%s\"", argv[1]); } else fp = stdin; err = parse_opt(argc, argv); if (err) return err; while (!feof(fp)) { size_t read; read = fread(buf, 1, BUFSIZE, fp); if (ferror(fp)) { sys_errmsg("cannot read input file"); err = -1; goto out_close; } crc = crc32(crc, buf, read); } printf("0x%08x\n", crc); out_close: if (fp != stdin) fclose(fp); return err; }
/** * mtd_node_to_num - converts device node to MTD number. * @mtd_dev_node: path to device node to convert * * This function converts given @mtd_dev_node to MTD device number. * @mtd_dev_node should contain path to the MTD device node. Returns MTD device * number in case of success and %-1 in case of failure (errno is set). */ static int mtd_node_to_num(const char *mtd_dev_node) { int major_dev, minor_dev; struct stat sb; if (stat(mtd_dev_node, &sb) < 0) return sys_errmsg("cannot stat \"%s\"", mtd_dev_node); if (!S_ISCHR(sb.st_mode)) { errno = EINVAL; return sys_errmsg("\"%s\" is not a character device", mtd_dev_node); } major_dev = major(sb.st_rdev); minor_dev = minor(sb.st_rdev); if (major != MTD_CHAR_MAJOR) { errno = EINVAL; return sys_errmsg("\"%s\" is not an MTD device", mtd_dev_node); } return minor_dev / 2; }
static int answer_is_yes(void) { char buf[4]; while (1) { if (scanf("%3s", buf) == EOF) { sys_errmsg("scanf returned unexpected EOF, assume \"no\""); return 0; } if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1)) return 1; if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1)) return 0; } }
static int translate_dev(libmtd_t libmtd, const char *node) { int err; struct mtd_dev_info mtd; err = mtd_get_dev_info(libmtd, node, &mtd); if (err) { if (errno == ENODEV) return errmsg("\"%s\" does not correspond to any " "existing MTD device", node); return sys_errmsg("cannot get information about MTD " "device \"%s\"", node); } return mtd.mtd_num; }
static int want_exit(void) { char buf[4]; while (1) { normsg_cont("continue? (yes/no) "); if (scanf("%3s", buf) == EOF) { sys_errmsg("scanf returned unexpected EOF, assume \"yes\""); return 1; } if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1)) return 0; if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1)) return 1; } }
static int print_general_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int all) { int i, err, first = 1; struct mtd_dev_info mtd; printf("Count of MTD devices: %d\n", mtd_info->mtd_dev_cnt); if (mtd_info->mtd_dev_cnt == 0) return 0; for (i = mtd_info->lowest_mtd_num; i <= mtd_info->highest_mtd_num; i++) { err = mtd_get_dev_info1(libmtd, i, &mtd); if (err == -1) { if (errno == ENODEV) continue; return sys_errmsg("libmtd failed to get MTD device %d " "information", i); } if (!first) printf(", mtd%d", i); else { printf("Present MTD devices: mtd%d", i); first = 0; } } printf("\n"); printf("Sysfs interface supported: %s\n", mtd_info->sysfs_supported ? "yes" : "no"); if (!all) return 0; printf("\n"); for (i = mtd_info->lowest_mtd_num; i <= mtd_info->highest_mtd_num; i++) { if (!mtd_dev_present(libmtd, i)) continue; err = print_dev_info(libmtd, mtd_info, i); if (err) return err; } return 0; }
static void print_region_info(const struct mtd_dev_info *mtd) { region_info_t reginfo; int r, fd; /* * If we don't have any region info, just return * * FIXME: We can't get region_info (via ioctl) without having the MTD * node path. This is a problem for `mtdinfo -a', for example, * since it doesn't provide any filepath information. */ if (!args.node || (!args.map && mtd->region_cnt == 0)) return; /* First open the device so we can query it */ fd = open(args.node, O_RDONLY | O_CLOEXEC); if (fd == -1) { sys_errmsg("couldn't open MTD dev: %s", args.node); if (mtd->region_cnt) return; } /* Walk all the regions and show the map for them */ if (mtd->region_cnt) { for (r = 0; r < mtd->region_cnt; ++r) { printf("Eraseblock region %i: ", r); if (mtd_regioninfo(fd, r, ®info) == 0) { printf(" offset: %#x size: %#x numblocks: %#x\n", reginfo.offset, reginfo.erasesize, reginfo.numblocks); if (args.map) print_region_map(mtd, fd, ®info); } else printf(" info is unavailable\n"); } } else { reginfo.offset = 0; reginfo.erasesize = mtd->eb_size; reginfo.numblocks = mtd->eb_cnt; reginfo.regionindex = 0; print_region_map(mtd, fd, ®info); } if (fd != -1) close(fd); }
int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes) { int fd, ret; struct ubi_rsvol_req req; desc = desc; fd = open(node, O_RDONLY); if (fd == -1) return sys_errmsg("cannot open \"%s\"", node); req.bytes = bytes; req.vol_id = vol_id; ret = ioctl(fd, UBI_IOCRSVOL, &req); close(fd); return ret; }
static int read_all(int fd, void *buf, size_t len) { while (len > 0) { ssize_t l = read(fd, buf, len); if (l == 0) return errmsg("eof reached; %zu bytes remaining", len); else if (l > 0) { buf += l; len -= l; } else if (errno == EINTR || errno == EAGAIN) continue; else return sys_errmsg("reading failed; %zu bytes remaining", len); } return 0; }