📄 cmd_jffs2.c
字号:
if (new_pi->offset <= pi->offset) { list_add_tail(&part->link, entry); dev->num_parts++; if (curr_pi && (pi->offset <= curr_pi->offset)) { /* we are modyfing partitions for the current * device, update current */ current_partnum++; current_save(); } else { index_partitions(); } return 0; } } list_add_tail(&part->link, &dev->parts); dev->num_parts++; index_partitions(); return 0;}/** * Add provided partition to the partition list of a given device. * * @param dev device to which partition is added * @param part partition to be added * @return 0 on success, 1 otherwise */static int part_add(struct mtd_device *dev, struct part_info *part){ /* verify alignment and size */ if (part_validate(dev->id, part) != 0) return 1; /* partition is ok, add it to the list */ if (part_sort_add(dev, part) != 0) return 1; return 0;}/** * Parse one partition definition, allocate memory and return pointer to this * location in retpart. * * @param partdef pointer to the partition definition string i.e. <part-def> * @param ret output pointer to next char after parse completes (output) * @param retpart pointer to the allocated partition (output) * @return 0 on success, 1 otherwise */static int part_parse(const char *const partdef, const char **ret, struct part_info **retpart){ struct part_info *part; unsigned long size; unsigned long offset; const char *name; int name_len; unsigned int mask_flags; const char *p; p = partdef; *retpart = NULL; *ret = NULL; /* fetch the partition size */ if (*p == '-') { /* assign all remaining space to this partition */ DEBUGF("'-': remaining size assigned\n"); size = SIZE_REMAINING; p++; } else { size = memsize_parse(p, &p); if (size < MIN_PART_SIZE) { printf("partition size too small (%lx)\n", size); return 1; } } /* check for offset */ offset = OFFSET_NOT_SPECIFIED; if (*p == '@') { p++; offset = memsize_parse(p, &p); } /* now look for the name */ if (*p == '(') { name = ++p; if ((p = strchr(name, ')')) == NULL) { printf("no closing ) found in partition name\n"); return 1; } name_len = p - name + 1; if ((name_len - 1) == 0) { printf("empty partition name\n"); return 1; } p++; } else { /* 0x00000000@0x00000000 */ name_len = 22; name = NULL; } /* test for options */ mask_flags = 0; if (strncmp(p, "ro", 2) == 0) { mask_flags |= MTD_WRITEABLE_CMD; p += 2; } /* check for next partition definition */ if (*p == ',') { if (size == SIZE_REMAINING) { *ret = NULL; printf("no partitions allowed after a fill-up partition\n"); return 1; } *ret = ++p; } else if ((*p == ';') || (*p == '\0')) { *ret = p; } else { printf("unexpected character '%c' at the end of partition\n", *p); *ret = NULL; return 1; } /* allocate memory */ part = (struct part_info *)malloc(sizeof(struct part_info) + name_len); if (!part) { printf("out of memory\n"); return 1; } memset(part, 0, sizeof(struct part_info) + name_len); part->size = size; part->offset = offset; part->mask_flags = mask_flags; part->name = (char *)(part + 1); if (name) { /* copy user provided name */ strncpy(part->name, name, name_len - 1); part->auto_name = 0; } else { /* auto generated name in form of size@offset */ sprintf(part->name, "0x%08lx@0x%08lx", size, offset); part->auto_name = 1; } part->name[name_len - 1] = '\0'; INIT_LIST_HEAD(&part->link); DEBUGF("+ partition: name %-22s size 0x%08x offset 0x%08x mask flags %d\n", part->name, part->size, part->offset, part->mask_flags); *retpart = part; return 0;}#endif/* #ifdef CONFIG_JFFS2_CMDLINE *//** * Check device number to be within valid range for given device type. * * @param dev device to validate * @return 0 if device is valid, 1 otherwise */static int device_validate(u8 type, u8 num, u32 *size){ if (type == MTD_DEV_TYPE_NOR) {#if (CONFIG_COMMANDS & CFG_CMD_FLASH) if (num < CFG_MAX_FLASH_BANKS) { extern flash_info_t flash_info[]; *size = flash_info[num].size; return 0; } printf("no such FLASH device: %s%d (valid range 0 ... %d\n", MTD_DEV_TYPE(type), num, CFG_MAX_FLASH_BANKS - 1);#else printf("support for FLASH devices not present\n");#endif } else if (type == MTD_DEV_TYPE_NAND) {#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) if (num < CFG_MAX_NAND_DEVICE) {#ifndef CFG_NAND_LEGACY *size = nand_info[num].size;#else extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; *size = nand_dev_desc[num].totlen;#endif return 0; } printf("no such NAND device: %s%d (valid range 0 ... %d)\n", MTD_DEV_TYPE(type), num, CFG_MAX_NAND_DEVICE - 1);#else printf("support for NAND devices not present\n");#endif } return 1;}#ifdef CONFIG_JFFS2_CMDLINE/** * Delete all mtd devices from a supplied devices list, free memory allocated for * each device and delete all device partitions. * * @return 0 on success, 1 otherwise */static int device_delall(struct list_head *head){ struct list_head *entry, *n; struct mtd_device *dev_tmp; /* clean devices list */ list_for_each_safe(entry, n, head) { dev_tmp = list_entry(entry, struct mtd_device, link); list_del(entry); part_delall(&dev_tmp->parts); free(dev_tmp); } INIT_LIST_HEAD(&devices); return 0;}/** * If provided device exists it's partitions are deleted, device is removed * from device list and device memory is freed. * * @param dev device to be deleted * @return 0 on success, 1 otherwise */static int device_del(struct mtd_device *dev){ part_delall(&dev->parts); list_del(&dev->link); free(dev); if (dev == current_dev) { /* we just deleted current device */ if (list_empty(&devices)) { current_dev = NULL; } else { /* reset first partition from first dev from the * devices list as current */ current_dev = list_entry(devices.next, struct mtd_device, link); current_partnum = 0; } current_save(); return 0; } index_partitions(); return 0;}/** * Search global device list and return pointer to the device of type and num * specified. * * @param type device type * @param num device number * @return NULL if requested device does not exist */static struct mtd_device* device_find(u8 type, u8 num){ struct list_head *entry; struct mtd_device *dev_tmp; list_for_each(entry, &devices) { dev_tmp = list_entry(entry, struct mtd_device, link); if ((dev_tmp->id->type == type) && (dev_tmp->id->num == num)) return dev_tmp; } return NULL;}/** * Add specified device to the global device list. * * @param dev device to be added */static void device_add(struct mtd_device *dev){ u8 current_save_needed = 0; if (list_empty(&devices)) { current_dev = dev; current_partnum = 0; current_save_needed = 1; } list_add_tail(&dev->link, &devices); if (current_save_needed > 0) current_save(); else index_partitions();}/** * Parse device type, name and mtd-id. If syntax is ok allocate memory and * return pointer to the device structure. * * @param mtd_dev pointer to the device definition string i.e. <mtd-dev> * @param ret output pointer to next char after parse completes (output) * @param retdev pointer to the allocated device (output) * @return 0 on success, 1 otherwise */static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_device **retdev){ struct mtd_device *dev; struct part_info *part; struct mtdids *id; const char *mtd_id; unsigned int mtd_id_len; const char *p, *pend; LIST_HEAD(tmp_list); struct list_head *entry, *n; u16 num_parts; u32 offset; int err = 1; p = mtd_dev; *retdev = NULL; *ret = NULL; DEBUGF("===device_parse===\n"); /* fetch <mtd-id> */ mtd_id = p; if (!(p = strchr(mtd_id, ':'))) { printf("no <mtd-id> identifier\n"); return 1; } mtd_id_len = p - mtd_id + 1; p++; /* verify if we have a valid device specified */ if ((id = id_find_by_mtd_id(mtd_id, mtd_id_len - 1)) == NULL) { printf("invalid mtd device '%.*s'\n", mtd_id_len - 1, mtd_id); return 1; } DEBUGF("dev type = %d (%s), dev num = %d, mtd-id = %s\n", id->type, MTD_DEV_TYPE(id->type), id->num, id->mtd_id); pend = strchr(p, ';'); DEBUGF("parsing partitions %.*s\n", (pend ? pend - p : strlen(p)), p); /* parse partitions */ num_parts = 0; offset = 0; if ((dev = device_find(id->type, id->num)) != NULL) { /* if device already exists start at the end of the last partition */ part = list_entry(dev->parts.prev, struct part_info, link); offset = part->offset + part->size; } while (p && (*p != '\0') && (*p != ';')) { err = 1; if ((part_parse(p, &p, &part) != 0) || (!part)) break; /* calculate offset when not specified */ if (part->offset == OFFSET_NOT_SPECIFIED) part->offset = offset; else offset = part->offset; /* verify alignment and size */ if (part_validate(id, part) != 0) break; offset += part->size; /* partition is ok, add it to the list */ list_add_tail(&part->link, &tmp_list); num_parts++; err = 0; } if (err == 1) { part_delall(&tmp_list); return 1; } if (num_parts == 0) { printf("no partitions for device %s%d (%s)\n", MTD_DEV_TYPE(id->type), id->num, id->mtd_id); return 1; } DEBUGF("\ntotal partitions: %d\n", num_parts); /* check for next device presence */ if (p) { if (*p == ';') { *ret = ++p; } else if (*p == '\0') { *ret = p; } else { printf("unexpected character '%c' at the end of device\n", *p); *ret = NULL; return 1; } } /* allocate memory for mtd_device structure */ if ((dev = (struct mtd_device *)malloc(sizeof(struct mtd_device))) == NULL) { printf("out of memory\n"); return 1; } memset(dev, 0, sizeof(struct mtd_device)); dev->id = id; dev->num_parts = 0; /* part_sort_add increments num_parts */ INIT_LIST_HEAD(&dev->parts); INIT_LIST_HEAD(&dev->link); /* move partitions from tmp_list to dev->parts */ list_for_each_safe(entry, n, &tmp_list) { part = list_entry(entry, struct part_info, link); list_del(entry); if (part_sort_add(dev, part) != 0) { device_del(dev); return 1; } } *retdev = dev; DEBUGF("===\n\n"); return 0;}/** * Initialize global device list. * * @return 0 on success, 1 otherwise */static int devices_init(void){ last_parts[0] = '\0'; current_dev = NULL; current_save(); return device_delall(&devices);}/* * Search global mtdids list and find id of requested type and number. * * @return pointer to the id if it exists, NULL otherwise */static struct mtdids* id_find(u8 type, u8 num){ struct list_head *entry; struct mtdids *id; list_for_each(entry, &mtdids) { id = list_entry(entry, struct mtdids, link); if ((id->type == type) && (id->num == num)) return id; } return NULL;}/** * Search global mtdids list and find id of a requested mtd_id. * * Note: first argument is not null terminated. * * @param mtd_id string containing requested mtd_id * @param mtd_id_len length of supplied mtd_id * @return pointer to the id if it exists, NULL otherwise */static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_len){ struct list_head *entry; struct mtdids *id; DEBUGF("--- id_find_by_mtd_id: '%.*s' (len = %d)\n", mtd_id_len, mtd_id, mtd_id_len); list_for_each(entry, &mtdids) { id = list_entry(entry, struct mtdids, link); DEBUGF("entry: '%s' (len = %d)\n", id->mtd_id, strlen(id->mtd_id)); if (mtd_id_len != strlen(id->mtd_id)) continue; if (strncmp(id->mtd_id, mtd_id, mtd_id_len) == 0) return id; } return NULL;}#endif /* #ifdef CONFIG_JFFS2_CMDLINE *//** * Parse device id string <dev-id> := 'nand'|'nor'<dev-num>, return device * type and number. * * @param id string describing device id * @param ret_id output pointer to next char after parse completes (output) * @param dev_type parsed device type (output) * @param dev_num parsed device number (output) * @return 0 on success, 1 otherwise */int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num){ const char *p = id; *dev_type = 0; if (strncmp(p, "nand", 4) == 0) { *dev_type = MTD_DEV_TYPE_NAND; p += 4; } else if (strncmp(p, "nor", 3) == 0) { *dev_type = MTD_DEV_TYPE_NOR; p += 3; } else { printf("incorrect device type in %s\n", id); return 1; } if (!isdigit(*p)) { printf("incorrect device number in %s\n", id); return 1; } *dev_num = simple_strtoul(p, (char **)&p, 0); if (ret_id) *ret_id = p; return 0;}#ifdef CONFIG_JFFS2_CMDLINE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -