root/block/cmdline-parser.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. parse_subpart
  2. free_subpart
  3. parse_parts
  4. cmdline_parts_free
  5. cmdline_parts_parse
  6. cmdline_parts_find
  7. cmdline_parts_set

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Parse command line, get partition information
   4  *
   5  * Written by Cai Zhiyong <caizhiyong@huawei.com>
   6  *
   7  */
   8 #include <linux/export.h>
   9 #include <linux/cmdline-parser.h>
  10 
  11 static int parse_subpart(struct cmdline_subpart **subpart, char *partdef)
  12 {
  13         int ret = 0;
  14         struct cmdline_subpart *new_subpart;
  15 
  16         *subpart = NULL;
  17 
  18         new_subpart = kzalloc(sizeof(struct cmdline_subpart), GFP_KERNEL);
  19         if (!new_subpart)
  20                 return -ENOMEM;
  21 
  22         if (*partdef == '-') {
  23                 new_subpart->size = (sector_t)(~0ULL);
  24                 partdef++;
  25         } else {
  26                 new_subpart->size = (sector_t)memparse(partdef, &partdef);
  27                 if (new_subpart->size < (sector_t)PAGE_SIZE) {
  28                         pr_warn("cmdline partition size is invalid.");
  29                         ret = -EINVAL;
  30                         goto fail;
  31                 }
  32         }
  33 
  34         if (*partdef == '@') {
  35                 partdef++;
  36                 new_subpart->from = (sector_t)memparse(partdef, &partdef);
  37         } else {
  38                 new_subpart->from = (sector_t)(~0ULL);
  39         }
  40 
  41         if (*partdef == '(') {
  42                 int length;
  43                 char *next = strchr(++partdef, ')');
  44 
  45                 if (!next) {
  46                         pr_warn("cmdline partition format is invalid.");
  47                         ret = -EINVAL;
  48                         goto fail;
  49                 }
  50 
  51                 length = min_t(int, next - partdef,
  52                                sizeof(new_subpart->name) - 1);
  53                 strncpy(new_subpart->name, partdef, length);
  54                 new_subpart->name[length] = '\0';
  55 
  56                 partdef = ++next;
  57         } else
  58                 new_subpart->name[0] = '\0';
  59 
  60         new_subpart->flags = 0;
  61 
  62         if (!strncmp(partdef, "ro", 2)) {
  63                 new_subpart->flags |= PF_RDONLY;
  64                 partdef += 2;
  65         }
  66 
  67         if (!strncmp(partdef, "lk", 2)) {
  68                 new_subpart->flags |= PF_POWERUP_LOCK;
  69                 partdef += 2;
  70         }
  71 
  72         *subpart = new_subpart;
  73         return 0;
  74 fail:
  75         kfree(new_subpart);
  76         return ret;
  77 }
  78 
  79 static void free_subpart(struct cmdline_parts *parts)
  80 {
  81         struct cmdline_subpart *subpart;
  82 
  83         while (parts->subpart) {
  84                 subpart = parts->subpart;
  85                 parts->subpart = subpart->next_subpart;
  86                 kfree(subpart);
  87         }
  88 }
  89 
  90 static int parse_parts(struct cmdline_parts **parts, const char *bdevdef)
  91 {
  92         int ret = -EINVAL;
  93         char *next;
  94         int length;
  95         struct cmdline_subpart **next_subpart;
  96         struct cmdline_parts *newparts;
  97         char buf[BDEVNAME_SIZE + 32 + 4];
  98 
  99         *parts = NULL;
 100 
 101         newparts = kzalloc(sizeof(struct cmdline_parts), GFP_KERNEL);
 102         if (!newparts)
 103                 return -ENOMEM;
 104 
 105         next = strchr(bdevdef, ':');
 106         if (!next) {
 107                 pr_warn("cmdline partition has no block device.");
 108                 goto fail;
 109         }
 110 
 111         length = min_t(int, next - bdevdef, sizeof(newparts->name) - 1);
 112         strncpy(newparts->name, bdevdef, length);
 113         newparts->name[length] = '\0';
 114         newparts->nr_subparts = 0;
 115 
 116         next_subpart = &newparts->subpart;
 117 
 118         while (next && *(++next)) {
 119                 bdevdef = next;
 120                 next = strchr(bdevdef, ',');
 121 
 122                 length = (!next) ? (sizeof(buf) - 1) :
 123                         min_t(int, next - bdevdef, sizeof(buf) - 1);
 124 
 125                 strncpy(buf, bdevdef, length);
 126                 buf[length] = '\0';
 127 
 128                 ret = parse_subpart(next_subpart, buf);
 129                 if (ret)
 130                         goto fail;
 131 
 132                 newparts->nr_subparts++;
 133                 next_subpart = &(*next_subpart)->next_subpart;
 134         }
 135 
 136         if (!newparts->subpart) {
 137                 pr_warn("cmdline partition has no valid partition.");
 138                 ret = -EINVAL;
 139                 goto fail;
 140         }
 141 
 142         *parts = newparts;
 143 
 144         return 0;
 145 fail:
 146         free_subpart(newparts);
 147         kfree(newparts);
 148         return ret;
 149 }
 150 
 151 void cmdline_parts_free(struct cmdline_parts **parts)
 152 {
 153         struct cmdline_parts *next_parts;
 154 
 155         while (*parts) {
 156                 next_parts = (*parts)->next_parts;
 157                 free_subpart(*parts);
 158                 kfree(*parts);
 159                 *parts = next_parts;
 160         }
 161 }
 162 EXPORT_SYMBOL(cmdline_parts_free);
 163 
 164 int cmdline_parts_parse(struct cmdline_parts **parts, const char *cmdline)
 165 {
 166         int ret;
 167         char *buf;
 168         char *pbuf;
 169         char *next;
 170         struct cmdline_parts **next_parts;
 171 
 172         *parts = NULL;
 173 
 174         next = pbuf = buf = kstrdup(cmdline, GFP_KERNEL);
 175         if (!buf)
 176                 return -ENOMEM;
 177 
 178         next_parts = parts;
 179 
 180         while (next && *pbuf) {
 181                 next = strchr(pbuf, ';');
 182                 if (next)
 183                         *next = '\0';
 184 
 185                 ret = parse_parts(next_parts, pbuf);
 186                 if (ret)
 187                         goto fail;
 188 
 189                 if (next)
 190                         pbuf = ++next;
 191 
 192                 next_parts = &(*next_parts)->next_parts;
 193         }
 194 
 195         if (!*parts) {
 196                 pr_warn("cmdline partition has no valid partition.");
 197                 ret = -EINVAL;
 198                 goto fail;
 199         }
 200 
 201         ret = 0;
 202 done:
 203         kfree(buf);
 204         return ret;
 205 
 206 fail:
 207         cmdline_parts_free(parts);
 208         goto done;
 209 }
 210 EXPORT_SYMBOL(cmdline_parts_parse);
 211 
 212 struct cmdline_parts *cmdline_parts_find(struct cmdline_parts *parts,
 213                                          const char *bdev)
 214 {
 215         while (parts && strncmp(bdev, parts->name, sizeof(parts->name)))
 216                 parts = parts->next_parts;
 217         return parts;
 218 }
 219 EXPORT_SYMBOL(cmdline_parts_find);
 220 
 221 /*
 222  *  add_part()
 223  *    0 success.
 224  *    1 can not add so many partitions.
 225  */
 226 int cmdline_parts_set(struct cmdline_parts *parts, sector_t disk_size,
 227                       int slot,
 228                       int (*add_part)(int, struct cmdline_subpart *, void *),
 229                       void *param)
 230 {
 231         sector_t from = 0;
 232         struct cmdline_subpart *subpart;
 233 
 234         for (subpart = parts->subpart; subpart;
 235              subpart = subpart->next_subpart, slot++) {
 236                 if (subpart->from == (sector_t)(~0ULL))
 237                         subpart->from = from;
 238                 else
 239                         from = subpart->from;
 240 
 241                 if (from >= disk_size)
 242                         break;
 243 
 244                 if (subpart->size > (disk_size - from))
 245                         subpart->size = disk_size - from;
 246 
 247                 from += subpart->size;
 248 
 249                 if (add_part(slot, subpart, param))
 250                         break;
 251         }
 252 
 253         return slot;
 254 }
 255 EXPORT_SYMBOL(cmdline_parts_set);

/* [<][>][^][v][top][bottom][index][help] */