123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- /*
- * Copyright (C) 2017 David Oberhollenzer - sigma star gmbh
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA.
- *
- * Author: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
- */
- #include "lsmtd.h"
- struct ubi_node *ubi_dev;
- int num_ubi_devices;
- struct mtd_node *mtd_dev;
- int num_mtd_devices;
- static int compare_mtd(const void *l, const void *r)
- {
- const struct mtd_node *a = l, *b = r;
- switch (sort_by->type) {
- case COL_DEVNAME:
- return a->info.mtd_num - b->info.mtd_num;
- case COL_DEVNUM:
- if (a->info.major == b->info.major)
- return a->info.minor - b->info.minor;
- return a->info.major - b->info.major;
- case COL_TYPE:
- return strcmp(a->info.type_str, b->info.type_str);
- case COL_NAME:
- return strcmp(a->info.name, b->info.name);
- case COL_SIZE:
- if (a->info.size < b->info.size)
- return -1;
- if (a->info.size > b->info.size)
- return 1;
- return 0;
- case COL_EBSIZE:
- return a->info.eb_size - b->info.eb_size;
- case COL_EBCOUNT:
- return a->info.eb_cnt - b->info.eb_cnt;
- case COL_MINIO:
- return a->info.min_io_size - b->info.min_io_size;
- case COL_SUBSIZE:
- return a->info.subpage_size - b->info.subpage_size;
- case COL_OOBSIZE:
- return a->info.oob_size - b->info.oob_size;
- case COL_RO:
- return !a->info.writable - !b->info.writable;
- case COL_BB:
- return a->info.bb_allowed - b->info.bb_allowed;
- case COL_REGION:
- return a->info.region_cnt - b->info.region_cnt;
- }
- return 0;
- }
- static int compare_ubi_vol(const void *l, const void *r)
- {
- const struct ubi_vol_info *a = l, *b = r;
- long long all, bll;
- switch (sort_by->type) {
- case COL_DEVNAME:
- if (a->dev_num == b->dev_num)
- return a->vol_id - b->vol_id;
- return a->dev_num - b->dev_num;
- case COL_DEVNUM:
- if (a->major == b->major)
- return a->minor - b->minor;
- return a->major - b->major;
- case COL_TYPE:
- if (a->type == b->type)
- return 0;
- return a->type == UBI_DYNAMIC_VOLUME ? 1 : -1;
- case COL_NAME:
- return strcmp(a->name, b->name);
- case COL_SIZE:
- all = a->rsvd_bytes;
- bll = b->rsvd_bytes;
- goto out_ll;
- case COL_EBSIZE:
- return a->leb_size - b->leb_size;
- case COL_EBCOUNT:
- return a->rsvd_lebs - b->rsvd_lebs;
- case COL_FREE:
- case COL_FREE_LEB:
- all = (a->rsvd_bytes - a->data_bytes);
- bll = (b->rsvd_bytes - b->data_bytes);
- goto out_ll;
- case COL_CORRUPTED:
- return a->corrupted - b->corrupted;
- }
- return 0;
- out_ll:
- return (all < bll) ? -1 : ((all > bll) ? 1 : 0);
- }
- static int scan_ubi_device(libubi_t lib_ubi, struct ubi_node *dev)
- {
- int lo = dev->info.lowest_vol_id, hi = dev->info.highest_vol_id;
- int i, idx = 0, dev_num = dev->info.dev_num;
- struct ubi_vol_info vol_info;
- if (!dev->info.vol_count)
- return 0;
- dev->vol_info = xcalloc(dev->info.vol_count, sizeof(dev->vol_info[0]));
- for (i = lo; i <= hi; ++i) {
- if (ubi_get_vol_info1(lib_ubi, dev_num, i, &vol_info)) {
- if (errno == ENOENT)
- continue;
- perror("ubi_get_vol_info1");
- return -1;
- }
- dev->vol_info[idx++] = vol_info;
- }
- if (sort_by)
- qsort(dev->vol_info, idx, sizeof(vol_info), compare_ubi_vol);
- return 0;
- }
- int scan_ubi(libubi_t lib_ubi)
- {
- struct ubi_dev_info dev_info;
- struct ubi_info info;
- int i, j;
- if (ubi_get_info(lib_ubi, &info))
- return -1;
- if (!info.dev_count)
- return 0;
- ubi_dev = xcalloc(info.dev_count, sizeof(ubi_dev[0]));
- for (i = info.lowest_dev_num; i <= info.highest_dev_num; ++i) {
- if (!ubi_dev_present(lib_ubi, i))
- continue;
- if (ubi_get_dev_info1(lib_ubi, i, &dev_info)) {
- perror("ubi_get_dev_info1");
- return -1;
- }
- for (j = 0; j < num_mtd_devices; ++j) {
- if (mtd_dev[j].info.mtd_num == dev_info.mtd_num)
- break;
- }
- if (j == num_mtd_devices) {
- fprintf(stderr, "Cannot find mtd device %d refered to "
- "by ubi device %d\n", dev_info.mtd_num,
- dev_info.dev_num);
- return -1;
- }
- ubi_dev[num_ubi_devices].info = dev_info;
- mtd_dev[j].ubi = ubi_dev + num_ubi_devices;
- if (scan_ubi_device(lib_ubi, ubi_dev + num_ubi_devices))
- return -1;
- ++num_ubi_devices;
- }
- return 0;
- }
- int scan_mtd(libmtd_t lib_mtd)
- {
- struct mtd_dev_info dev_info;
- struct mtd_info info;
- int i, idx = 0;
- if (mtd_get_info(lib_mtd, &info))
- return -1;
- if (!info.mtd_dev_cnt)
- return 0;
- mtd_dev = xcalloc(info.mtd_dev_cnt, sizeof(mtd_dev[0]));
- for (i = info.lowest_mtd_num; i <= info.highest_mtd_num; ++i) {
- if (!mtd_dev_present(lib_mtd, i))
- continue;
- if (mtd_get_dev_info1(lib_mtd, i, &dev_info)) {
- perror("mtd_get_dev_info1");
- return -1;
- }
- memcpy(&(mtd_dev[idx++].info), &dev_info, sizeof(dev_info));
- }
- num_mtd_devices = idx;
- if (sort_by)
- qsort(mtd_dev, num_mtd_devices, sizeof(*mtd_dev), compare_mtd);
- return 0;
- }
- void scan_free(void)
- {
- int i;
- for (i = 0; i < num_ubi_devices; ++i)
- free(ubi_dev[i].vol_info);
- free(ubi_dev);
- free(mtd_dev);
- }
|