📄 cmd_jffs2.c
字号:
/** * Process all devices and generate corresponding mtdparts string describing * all partitions on all devices. * * @param buf output buffer holding generated mtdparts string (output) * @param buflen buffer size * @return 0 on success, 1 otherwise */static int generate_mtdparts(char *buf, u32 buflen){ struct list_head *pentry, *dentry; struct mtd_device *dev; struct part_info *part, *prev_part; char *p = buf; char tmpbuf[32]; u32 size, offset, len, part_cnt; u32 maxlen = buflen - 1; DEBUGF("--- generate_mtdparts ---\n"); if (list_empty(&devices)) { buf[0] = '\0'; return 0; } sprintf(p, "mtdparts="); p += 9; list_for_each(dentry, &devices) { dev = list_entry(dentry, struct mtd_device, link); /* copy mtd_id */ len = strlen(dev->id->mtd_id) + 1; if (len > maxlen) goto cleanup; memcpy(p, dev->id->mtd_id, len - 1); p += len - 1; *(p++) = ':'; maxlen -= len; /* format partitions */ prev_part = NULL; part_cnt = 0; list_for_each(pentry, &dev->parts) { part = list_entry(pentry, struct part_info, link); size = part->size; offset = part->offset; part_cnt++; /* partition size */ memsize_format(tmpbuf, size); len = strlen(tmpbuf); if (len > maxlen) goto cleanup; memcpy(p, tmpbuf, len); p += len; maxlen -= len; /* add offset only when there is a gap between * partitions */ if ((!prev_part && (offset != 0)) || (prev_part && ((prev_part->offset + prev_part->size) != part->offset))) { memsize_format(tmpbuf, offset); len = strlen(tmpbuf) + 1; if (len > maxlen) goto cleanup; *(p++) = '@'; memcpy(p, tmpbuf, len - 1); p += len - 1; maxlen -= len; } /* copy name only if user supplied */ if(!part->auto_name) { len = strlen(part->name) + 2; if (len > maxlen) goto cleanup; *(p++) = '('; memcpy(p, part->name, len - 2); p += len - 2; *(p++) = ')'; maxlen -= len; } /* ro mask flag */ if (part->mask_flags && MTD_WRITEABLE_CMD) { len = 2; if (len > maxlen) goto cleanup; *(p++) = 'r'; *(p++) = 'o'; maxlen -= 2; } /* print ',' separator if there are other partitions * following */ if (dev->num_parts > part_cnt) { if (1 > maxlen) goto cleanup; *(p++) = ','; maxlen--; } prev_part = part; } /* print ';' separator if there are other devices following */ if (dentry->next != &devices) { if (1 > maxlen) goto cleanup; *(p++) = ';'; maxlen--; } } /* we still have at least one char left, as we decremented maxlen at * the begining */ *p = '\0'; return 0;cleanup: last_parts[0] = '\0'; return 1;}/** * Call generate_mtdparts to process all devices and generate corresponding * mtdparts string, save it in mtdparts environment variable. * * @param buf output buffer holding generated mtdparts string (output) * @param buflen buffer size * @return 0 on success, 1 otherwise */static int generate_mtdparts_save(char *buf, u32 buflen){ int ret; ret = generate_mtdparts(buf, buflen); if ((buf[0] != '\0') && (ret == 0)) setenv("mtdparts", buf); else setenv("mtdparts", NULL); return ret;}/** * Format and print out a partition list for each device from global device * list. */static void list_partitions(void){ struct list_head *dentry, *pentry; struct part_info *part; struct mtd_device *dev; int part_num; DEBUGF("\n---list_partitions---\n"); list_for_each(dentry, &devices) { dev = list_entry(dentry, struct mtd_device, link); printf("\ndevice %s%d <%s>, # parts = %d\n", MTD_DEV_TYPE(dev->id->type), dev->id->num, dev->id->mtd_id, dev->num_parts); printf(" #: name\t\t\tsize\t\toffset\t\tmask_flags\n"); /* list partitions for given device */ part_num = 0; list_for_each(pentry, &dev->parts) { part = list_entry(pentry, struct part_info, link); printf("%2d: %-20s0x%08x\t0x%08x\t%d\n", part_num, part->name, part->size, part->offset, part->mask_flags); part_num++; } } if (list_empty(&devices)) printf("no partitions defined\n"); /* current_dev is not NULL only when we have non empty device list */ if (current_dev) { part = jffs2_part_info(current_dev, current_partnum); if (part) { printf("\nactive partition: %s%d,%d - (%s) 0x%08lx @ 0x%08lx\n", MTD_DEV_TYPE(current_dev->id->type), current_dev->id->num, current_partnum, part->name, part->size, part->offset); } else { printf("could not get current partition info\n\n"); } } printf("\ndefaults:\n"); printf("mtdids : %s\n", mtdids_default); printf("mtdparts: %s\n", mtdparts_default);}/** * Given partition identifier in form of <dev_type><dev_num>,<part_num> find * corresponding device and verify partition number. * * @param id string describing device and partition or partition name * @param dev pointer to the requested device (output) * @param part_num verified partition number (output) * @param part pointer to requested partition (output) * @return 0 on success, 1 otherwise */int find_dev_and_part(const char *id, struct mtd_device **dev, u8 *part_num, struct part_info **part){ struct list_head *dentry, *pentry; u8 type, dnum, pnum; const char *p; DEBUGF("--- find_dev_and_part ---\nid = %s\n", id); list_for_each(dentry, &devices) { *part_num = 0; *dev = list_entry(dentry, struct mtd_device, link); list_for_each(pentry, &(*dev)->parts) { *part = list_entry(pentry, struct part_info, link); if (strcmp((*part)->name, id) == 0) return 0; (*part_num)++; } } p = id; *dev = NULL; *part = NULL; *part_num = 0; if (id_parse(p, &p, &type, &dnum) != 0) return 1; if ((*p++ != ',') || (*p == '\0')) { printf("no partition number specified\n"); return 1; } pnum = simple_strtoul(p, (char **)&p, 0); if (*p != '\0') { printf("unexpected trailing character '%c'\n", *p); return 1; } if ((*dev = device_find(type, dnum)) == NULL) { printf("no such device %s%d\n", MTD_DEV_TYPE(type), dnum); return 1; } if ((*part = jffs2_part_info(*dev, pnum)) == NULL) { printf("no such partition\n"); *dev = NULL; return 1; } *part_num = pnum; return 0;}/** * Find and delete partition. For partition id format see find_dev_and_part(). * * @param id string describing device and partition * @return 0 on success, 1 otherwise */static int delete_partition(const char *id){ u8 pnum; struct mtd_device *dev; struct part_info *part; if (find_dev_and_part(id, &dev, &pnum, &part) == 0) { DEBUGF("delete_partition: device = %s%d, partition %d = (%s) 0x%08lx@0x%08lx\n", MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum, part->name, part->size, part->offset); if (part_del(dev, part) != 0) return 1; if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) { printf("generated mtdparts too long, reseting to null\n"); return 1; } return 0; } printf("partition %s not found\n", id); return 1;}/** * Accept character string describing mtd partitions and call device_parse() * for each entry. Add created devices to the global devices list. * * @param mtdparts string specifing mtd partitions * @return 0 on success, 1 otherwise */static int parse_mtdparts(const char *const mtdparts){ const char *p = mtdparts; struct mtd_device *dev; int err = 1; DEBUGF("\n---parse_mtdparts---\nmtdparts = %s\n\n", p); /* delete all devices and partitions */ if (devices_init() != 0) { printf("could not initialise device list\n"); return err; } /* re-read 'mtdparts' variable, devices_init may be updating env */ p = getenv("mtdparts"); if (strncmp(p, "mtdparts=", 9) != 0) { printf("mtdparts variable doesn't start with 'mtdparts='\n"); return err; } p += 9; while (p && (*p != '\0')) { err = 1; if ((device_parse(p, &p, &dev) != 0) || (!dev)) break; DEBUGF("+ device: %s\t%d\t%s\n", MTD_DEV_TYPE(dev->id->type), dev->id->num, dev->id->mtd_id); /* check if parsed device is already on the list */ if (device_find(dev->id->type, dev->id->num) != NULL) { printf("device %s%d redefined, please correct mtdparts variable\n", MTD_DEV_TYPE(dev->id->type), dev->id->num); break; } list_add_tail(&dev->link, &devices); err = 0; } if (err == 1) { device_delall(&devices); return 1; } return 0;}/** * Parse provided string describing mtdids mapping (see file header for mtdids * variable format). Allocate memory for each entry and add all found entries * to the global mtdids list. * * @param ids mapping string * @return 0 on success, 1 otherwise */static int parse_mtdids(const char *const ids){ const char *p = ids; const char *mtd_id; int mtd_id_len; struct mtdids *id; struct list_head *entry, *n; struct mtdids *id_tmp; u8 type, num; u32 size; int ret = 1; DEBUGF("\n---parse_mtdids---\nmtdids = %s\n\n", ids); /* clean global mtdids list */ list_for_each_safe(entry, n, &mtdids) { id_tmp = list_entry(entry, struct mtdids, link); DEBUGF("mtdids del: %d %d\n", id_tmp->type, id_tmp->num); list_del(entry); free(id_tmp); } last_ids[0] = '\0'; INIT_LIST_HEAD(&mtdids); while(p && (*p != '\0')) { ret = 1; /* parse 'nor'|'nand'<dev-num> */ if (id_parse(p, &p, &type, &num) != 0) break; if (*p != '=') { printf("mtdids: incorrect <dev-num>\n"); break; } p++; /* check if requested device exists */ if (device_validate(type, num, &size) != 0) return 1; /* locate <mtd-id> */ mtd_id = p; if ((p = strchr(mtd_id, ',')) != NULL) { mtd_id_len = p - mtd_id + 1; p++; } else { mtd_id_len = strlen(mtd_id) + 1; } if (mtd_id_len == 0) { printf("mtdids: no <mtd-id> identifier\n"); break; } /* check if this id is already on the list */ int double_entry = 0; list_for_each(entry, &mtdids) { id_tmp = list_entry(entry, struct mtdids, link); if ((id_tmp->type == type) && (id_tmp->num == num)) { double_entry = 1; break; } } if (double_entry) { printf("device id %s%d redefined, please correct mtdids variable\n", MTD_DEV_TYPE(type), num); break; } /* allocate mtdids structure */ if (!(id = (struct mtdids *)malloc(sizeof(struct mtdids) + mtd_id_len))) { printf("out of memory\n"); break; } memset(id, 0, sizeof(struct mtdids) + mtd_id_len); id->num = num; id->type = type; id->size = size; id->mtd_id = (char *)(id + 1); strncpy(id->mtd_id, mtd_id, mtd_id_len - 1); id->mtd_id[mtd_id_len - 1] = '\0'; INIT_LIST_HEAD(&id->link); DEBUGF("+ id %s%d\t%16d bytes\t%s\n", MTD_DEV_TYPE(id->type), id->num, id->size, id->mtd_id); list_add_tail(&id->link, &mtdids); ret = 0; } if (ret == 1) { /* clean mtdids list and free allocated memory */ list_for_each_safe(entry, n, &mtdids) { id_tmp = list_entry(entry, struct mtdids, link); list_del(entry); free(id_tmp); } return 1; } return 0;}/** * Parse and initialize global mtdids mapping and create global * device/partition list. * * @return 0 on success, 1 otherwise */int mtdparts_init(void){ static int initialized = 0; const char *ids, *parts; const char *current_partition; int ids_changed; char tmp_ep[PARTITION_MAXLEN]; DEBUGF("\n---mtdparts_init---\n"); if (!initialized) { INIT_LIST_HEAD(&mtdids); INIT_LIST_HEAD(&devices); memset(last_ids, 0, MTDIDS_MAXLEN); memset(last_parts, 0, MTDPARTS_MAXLEN); memset(last_partition, 0, PARTITION_MAXLEN); initialized = 1; } /* get variables */ ids = getenv("mtdids"); parts = getenv("mtdparts"); current_partition = getenv("partition"); /* save it for later parsing, cannot rely on current partition pointer * as 'partition' variable may be updated during init */ tmp_ep[0] = '\0'; if (current_partition) strncpy(tmp_ep, current_partition, PARTITION_MAXLEN); DEBUGF("last_ids : %s\n", last_ids); DEBUGF("env_ids : %s\n", ids); DEBUGF("last_parts: %s\n", last_parts); DEBUGF("env_parts : %s\n\n", parts); DEBUGF("last_partition : %s\n", last_partition); DEBUGF("env_partition : %s\n", current_partition); /* if mtdids varible is empty try to use defaults */ if (!ids) { if (mtdids_default) { DEBUGF("mtdids variable not defined, using default\n"); ids = mtdids_default; setenv("mtdids", (char *)ids); } else { printf("mtdids not defined, no default present\n"); return 1; } } if (strlen(ids) > MTDIDS_MAXLEN - 1) { printf("mtdids too long (> %d)\n", MTDIDS_MAXLEN); return 1; } /* do no try to use defaults when mtdparts variable is not defined, * just check the length */ if (!parts) printf("mtdparts variable not set, see 'help mtdparts'\n"); if (parts && (strlen(parts) > MTDPARTS_MAXLEN - 1)) { printf("mtdparts too long (> %d)\n", MTDPARTS_MAXLEN); return 1; } /* check if we have already parsed those mtdids */ if ((last_ids[0] != '\0') && (strcmp(last_ids, ids) == 0)) { ids_changed = 0; } else { ids_changed = 1; if (parse_mtdids(ids) != 0) { devices_init(); return 1; } /* ok it's good, save new ids */ strncpy(last_ids, ids, MTDIDS_MAXLEN); } /* parse partitions if either mtdparts or mtdids were updated */ if (parts && ((last_parts[0] == '\0') || ((strcmp(last_parts, parts) != 0)) || ids_changed)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -