1 /* 2 * (C) Copyright 2014 3 * Heiko Schocher, DENX Software Engineering, hs@denx.de. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 #include <common.h> 8 #include <linux/mtd/mtd.h> 9 #include <jffs2/jffs2.h> /* Legacy */ 10 11 /** 12 * mtd_search_alternate_name - Search an alternate name for @mtdname thanks to 13 * the mtdids legacy environment variable. 14 * 15 * The mtdids string is a list of comma-separated 'dev_id=mtd_id' tupples. 16 * Check if one of the mtd_id matches mtdname, in this case save dev_id in 17 * altname. 18 * 19 * @mtdname: Current MTD device name 20 * @altname: Alternate name to return 21 * @max_len: Length of the alternate name buffer 22 * 23 * @return 0 on success, an error otherwise. 24 */ 25 int mtd_search_alternate_name(const char *mtdname, char *altname, 26 unsigned int max_len) 27 { 28 const char *mtdids, *equal, *comma, *dev_id, *mtd_id; 29 int dev_id_len, mtd_id_len; 30 31 mtdids = env_get("mtdids"); 32 if (!mtdids) 33 return -EINVAL; 34 35 do { 36 /* Find the '=' sign */ 37 dev_id = mtdids; 38 equal = strchr(dev_id, '='); 39 if (!equal) 40 break; 41 dev_id_len = equal - mtdids; 42 mtd_id = equal + 1; 43 44 /* Find the end of the tupple */ 45 comma = strchr(mtdids, ','); 46 if (comma) 47 mtd_id_len = comma - mtd_id; 48 else 49 mtd_id_len = &mtdids[strlen(mtdids)] - mtd_id + 1; 50 51 if (!dev_id_len || !mtd_id_len) 52 return -EINVAL; 53 54 if (dev_id_len + 1 > max_len) 55 continue; 56 57 /* Compare the name we search with the current mtd_id */ 58 if (!strncmp(mtdname, mtd_id, mtd_id_len)) { 59 strncpy(altname, dev_id, dev_id_len); 60 altname[dev_id_len] = 0; 61 62 return 0; 63 } 64 65 /* Go to the next tupple */ 66 mtdids = comma + 1; 67 } while (comma); 68 69 return -EINVAL; 70 } 71 72 /* Legacy */ 73 74 static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size, 75 loff_t *maxsize, int devtype) 76 { 77 #ifdef CONFIG_CMD_MTDPARTS 78 struct mtd_device *dev; 79 struct part_info *part; 80 u8 pnum; 81 int ret; 82 83 ret = mtdparts_init(); 84 if (ret) 85 return ret; 86 87 ret = find_dev_and_part(partname, &dev, &pnum, &part); 88 if (ret) 89 return ret; 90 91 if (dev->id->type != devtype) { 92 printf("not same typ %d != %d\n", dev->id->type, devtype); 93 return -1; 94 } 95 96 *off = part->offset; 97 *size = part->size; 98 *maxsize = part->size; 99 *idx = dev->id->num; 100 101 return 0; 102 #else 103 puts("mtdparts support missing.\n"); 104 return -1; 105 #endif 106 } 107 108 int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size, 109 loff_t *maxsize, int devtype, uint64_t chipsize) 110 { 111 if (!str2off(arg, off)) 112 return get_part(arg, idx, off, size, maxsize, devtype); 113 114 if (*off >= chipsize) { 115 puts("Offset exceeds device limit\n"); 116 return -1; 117 } 118 119 *maxsize = chipsize - *off; 120 *size = *maxsize; 121 return 0; 122 } 123 124 int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off, 125 loff_t *size, loff_t *maxsize, int devtype, 126 uint64_t chipsize) 127 { 128 int ret; 129 130 if (argc == 0) { 131 *off = 0; 132 *size = chipsize; 133 *maxsize = *size; 134 goto print; 135 } 136 137 ret = mtd_arg_off(argv[0], idx, off, size, maxsize, devtype, 138 chipsize); 139 if (ret) 140 return ret; 141 142 if (argc == 1) 143 goto print; 144 145 if (!str2off(argv[1], size)) { 146 printf("'%s' is not a number\n", argv[1]); 147 return -1; 148 } 149 150 if (*size > *maxsize) { 151 puts("Size exceeds partition or device limit\n"); 152 return -1; 153 } 154 155 print: 156 printf("device %d ", *idx); 157 if (*size == chipsize) 158 puts("whole chip\n"); 159 else 160 printf("offset 0x%llx, size 0x%llx\n", 161 (unsigned long long)*off, (unsigned long long)*size); 162 return 0; 163 } 164