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