Back to home page

LXR

 
 

    


0001 /*
0002  * Parse command line, get partition information
0003  *
0004  * Written by Cai Zhiyong <caizhiyong@huawei.com>
0005  *
0006  */
0007 #include <linux/export.h>
0008 #include <linux/cmdline-parser.h>
0009 
0010 static int parse_subpart(struct cmdline_subpart **subpart, char *partdef)
0011 {
0012     int ret = 0;
0013     struct cmdline_subpart *new_subpart;
0014 
0015     *subpart = NULL;
0016 
0017     new_subpart = kzalloc(sizeof(struct cmdline_subpart), GFP_KERNEL);
0018     if (!new_subpart)
0019         return -ENOMEM;
0020 
0021     if (*partdef == '-') {
0022         new_subpart->size = (sector_t)(~0ULL);
0023         partdef++;
0024     } else {
0025         new_subpart->size = (sector_t)memparse(partdef, &partdef);
0026         if (new_subpart->size < (sector_t)PAGE_SIZE) {
0027             pr_warn("cmdline partition size is invalid.");
0028             ret = -EINVAL;
0029             goto fail;
0030         }
0031     }
0032 
0033     if (*partdef == '@') {
0034         partdef++;
0035         new_subpart->from = (sector_t)memparse(partdef, &partdef);
0036     } else {
0037         new_subpart->from = (sector_t)(~0ULL);
0038     }
0039 
0040     if (*partdef == '(') {
0041         int length;
0042         char *next = strchr(++partdef, ')');
0043 
0044         if (!next) {
0045             pr_warn("cmdline partition format is invalid.");
0046             ret = -EINVAL;
0047             goto fail;
0048         }
0049 
0050         length = min_t(int, next - partdef,
0051                    sizeof(new_subpart->name) - 1);
0052         strncpy(new_subpart->name, partdef, length);
0053         new_subpart->name[length] = '\0';
0054 
0055         partdef = ++next;
0056     } else
0057         new_subpart->name[0] = '\0';
0058 
0059     new_subpart->flags = 0;
0060 
0061     if (!strncmp(partdef, "ro", 2)) {
0062         new_subpart->flags |= PF_RDONLY;
0063         partdef += 2;
0064     }
0065 
0066     if (!strncmp(partdef, "lk", 2)) {
0067         new_subpart->flags |= PF_POWERUP_LOCK;
0068         partdef += 2;
0069     }
0070 
0071     *subpart = new_subpart;
0072     return 0;
0073 fail:
0074     kfree(new_subpart);
0075     return ret;
0076 }
0077 
0078 static void free_subpart(struct cmdline_parts *parts)
0079 {
0080     struct cmdline_subpart *subpart;
0081 
0082     while (parts->subpart) {
0083         subpart = parts->subpart;
0084         parts->subpart = subpart->next_subpart;
0085         kfree(subpart);
0086     }
0087 }
0088 
0089 static int parse_parts(struct cmdline_parts **parts, const char *bdevdef)
0090 {
0091     int ret = -EINVAL;
0092     char *next;
0093     int length;
0094     struct cmdline_subpart **next_subpart;
0095     struct cmdline_parts *newparts;
0096     char buf[BDEVNAME_SIZE + 32 + 4];
0097 
0098     *parts = NULL;
0099 
0100     newparts = kzalloc(sizeof(struct cmdline_parts), GFP_KERNEL);
0101     if (!newparts)
0102         return -ENOMEM;
0103 
0104     next = strchr(bdevdef, ':');
0105     if (!next) {
0106         pr_warn("cmdline partition has no block device.");
0107         goto fail;
0108     }
0109 
0110     length = min_t(int, next - bdevdef, sizeof(newparts->name) - 1);
0111     strncpy(newparts->name, bdevdef, length);
0112     newparts->name[length] = '\0';
0113     newparts->nr_subparts = 0;
0114 
0115     next_subpart = &newparts->subpart;
0116 
0117     while (next && *(++next)) {
0118         bdevdef = next;
0119         next = strchr(bdevdef, ',');
0120 
0121         length = (!next) ? (sizeof(buf) - 1) :
0122             min_t(int, next - bdevdef, sizeof(buf) - 1);
0123 
0124         strncpy(buf, bdevdef, length);
0125         buf[length] = '\0';
0126 
0127         ret = parse_subpart(next_subpart, buf);
0128         if (ret)
0129             goto fail;
0130 
0131         newparts->nr_subparts++;
0132         next_subpart = &(*next_subpart)->next_subpart;
0133     }
0134 
0135     if (!newparts->subpart) {
0136         pr_warn("cmdline partition has no valid partition.");
0137         ret = -EINVAL;
0138         goto fail;
0139     }
0140 
0141     *parts = newparts;
0142 
0143     return 0;
0144 fail:
0145     free_subpart(newparts);
0146     kfree(newparts);
0147     return ret;
0148 }
0149 
0150 void cmdline_parts_free(struct cmdline_parts **parts)
0151 {
0152     struct cmdline_parts *next_parts;
0153 
0154     while (*parts) {
0155         next_parts = (*parts)->next_parts;
0156         free_subpart(*parts);
0157         kfree(*parts);
0158         *parts = next_parts;
0159     }
0160 }
0161 EXPORT_SYMBOL(cmdline_parts_free);
0162 
0163 int cmdline_parts_parse(struct cmdline_parts **parts, const char *cmdline)
0164 {
0165     int ret;
0166     char *buf;
0167     char *pbuf;
0168     char *next;
0169     struct cmdline_parts **next_parts;
0170 
0171     *parts = NULL;
0172 
0173     next = pbuf = buf = kstrdup(cmdline, GFP_KERNEL);
0174     if (!buf)
0175         return -ENOMEM;
0176 
0177     next_parts = parts;
0178 
0179     while (next && *pbuf) {
0180         next = strchr(pbuf, ';');
0181         if (next)
0182             *next = '\0';
0183 
0184         ret = parse_parts(next_parts, pbuf);
0185         if (ret)
0186             goto fail;
0187 
0188         if (next)
0189             pbuf = ++next;
0190 
0191         next_parts = &(*next_parts)->next_parts;
0192     }
0193 
0194     if (!*parts) {
0195         pr_warn("cmdline partition has no valid partition.");
0196         ret = -EINVAL;
0197         goto fail;
0198     }
0199 
0200     ret = 0;
0201 done:
0202     kfree(buf);
0203     return ret;
0204 
0205 fail:
0206     cmdline_parts_free(parts);
0207     goto done;
0208 }
0209 EXPORT_SYMBOL(cmdline_parts_parse);
0210 
0211 struct cmdline_parts *cmdline_parts_find(struct cmdline_parts *parts,
0212                      const char *bdev)
0213 {
0214     while (parts && strncmp(bdev, parts->name, sizeof(parts->name)))
0215         parts = parts->next_parts;
0216     return parts;
0217 }
0218 EXPORT_SYMBOL(cmdline_parts_find);
0219 
0220 /*
0221  *  add_part()
0222  *    0 success.
0223  *    1 can not add so many partitions.
0224  */
0225 int cmdline_parts_set(struct cmdline_parts *parts, sector_t disk_size,
0226               int slot,
0227               int (*add_part)(int, struct cmdline_subpart *, void *),
0228               void *param)
0229 {
0230     sector_t from = 0;
0231     struct cmdline_subpart *subpart;
0232 
0233     for (subpart = parts->subpart; subpart;
0234          subpart = subpart->next_subpart, slot++) {
0235         if (subpart->from == (sector_t)(~0ULL))
0236             subpart->from = from;
0237         else
0238             from = subpart->from;
0239 
0240         if (from >= disk_size)
0241             break;
0242 
0243         if (subpart->size > (disk_size - from))
0244             subpart->size = disk_size - from;
0245 
0246         from += subpart->size;
0247 
0248         if (add_part(slot, subpart, param))
0249             break;
0250     }
0251 
0252     return slot;
0253 }
0254 EXPORT_SYMBOL(cmdline_parts_set);