// SPDX-License-Identifier: GPL-2.0-only1/*2* linux/lib/cmdline.c3* Helper functions generally used for parsing kernel command line4* and module options.5*6* Code and copyrights come from init/main.c and arch/i386/kernel/setup.c.7*8* GNU Indent formatting options for this file: -kr -i8 -npsl -pcs9*/1011#include <linux/export.h>12#include <linux/kernel.h>13#include <linux/string.h>14#include <linux/ctype.h>1516/*17* If a hyphen was found in get_option, this will handle the18* range of numbers, M-N. This will expand the range and insert19* the values[M, M+1, ..., N] into the ints array in get_options.20*/2122static int get_range(char **str, int *pint, int n)23{24int x, inc_counter, upper_range;2526(*str)++;27upper_range = simple_strtol((*str), NULL, 0);28inc_counter = upper_range - *pint;29for (x = *pint; n && x < upper_range; x++, n--)30*pint++ = x;31return inc_counter;32}3334/**35* get_option - Parse integer from an option string36* @str: option string37* @pint: (optional output) integer value parsed from @str38*39* Read an int from an option string; if available accept a subsequent40* comma as well.41*42* When @pint is NULL the function can be used as a validator of43* the current option in the string.44*45* Return values:46* 0 - no int in string47* 1 - int found, no subsequent comma48* 2 - int found including a subsequent comma49* 3 - hyphen found to denote a range50*51* Leading hyphen without integer is no integer case, but we consume it52* for the sake of simplification.53*/5455int get_option(char **str, int *pint)56{57char *cur = *str;58int value;5960if (!cur || !(*cur))61return 0;62if (*cur == '-')63value = -simple_strtoull(++cur, str, 0);64else65value = simple_strtoull(cur, str, 0);66if (pint)67*pint = value;68if (cur == *str)69return 0;70if (**str == ',') {71(*str)++;72return 2;73}74if (**str == '-')75return 3;7677return 1;78}79EXPORT_SYMBOL(get_option);8081/**82* get_options - Parse a string into a list of integers83* @str: String to be parsed84* @nints: size of integer array85* @ints: integer array (must have room for at least one element)86*87* This function parses a string containing a comma-separated88* list of integers, a hyphen-separated range of _positive_ integers,89* or a combination of both. The parse halts when the array is90* full, or when no more numbers can be retrieved from the91* string.92*93* When @nints is 0, the function just validates the given @str and94* returns the amount of parseable integers as described below.95*96* Returns:97*98* The first element is filled by the number of collected integers99* in the range. The rest is what was parsed from the @str.100*101* Return value is the character in the string which caused102* the parse to end (typically a null terminator, if @str is103* completely parseable).104*/105106char *get_options(const char *str, int nints, int *ints)107{108bool validate = (nints == 0);109int res, i = 1;110111while (i < nints || validate) {112int *pint = validate ? ints : ints + i;113114res = get_option((char **)&str, pint);115if (res == 0)116break;117if (res == 3) {118int n = validate ? 0 : nints - i;119int range_nums;120121range_nums = get_range((char **)&str, pint, n);122if (range_nums < 0)123break;124/*125* Decrement the result by one to leave out the126* last number in the range. The next iteration127* will handle the upper number in the range128*/129i += (range_nums - 1);130}131i++;132if (res == 1)133break;134}135ints[0] = i - 1;136return (char *)str;137}138EXPORT_SYMBOL(get_options);139140/**141* memparse - parse a string with mem suffixes into a number142* @ptr: Where parse begins143* @retptr: (output) Optional pointer to next char after parse completes144*145* Parses a string into a number. The number stored at @ptr is146* potentially suffixed with K, M, G, T, P, E.147*/148149unsigned long long memparse(const char *ptr, char **retptr)150{151char *endptr; /* local pointer to end of parsed string */152153unsigned long long ret = simple_strtoull(ptr, &endptr, 0);154155switch (*endptr) {156case 'E':157case 'e':158ret <<= 10;159fallthrough;160case 'P':161case 'p':162ret <<= 10;163fallthrough;164case 'T':165case 't':166ret <<= 10;167fallthrough;168case 'G':169case 'g':170ret <<= 10;171fallthrough;172case 'M':173case 'm':174ret <<= 10;175fallthrough;176case 'K':177case 'k':178ret <<= 10;179endptr++;180fallthrough;181default:182break;183}184185if (retptr)186*retptr = endptr;187188return ret;189}190EXPORT_SYMBOL(memparse);191192/**193* parse_option_str - Parse a string and check an option is set or not194* @str: String to be parsed195* @option: option name196*197* This function parses a string containing a comma-separated list of198* strings like a=b,c.199*200* Return true if there's such option in the string, or return false.201*/202bool parse_option_str(const char *str, const char *option)203{204while (*str) {205if (!strncmp(str, option, strlen(option))) {206str += strlen(option);207if (!*str || *str == ',')208return true;209}210211while (*str && *str != ',')212str++;213214if (*str == ',')215str++;216}217218return false;219}220221/*222* Parse a string to get a param value pair.223* You can use " around spaces, but can't escape ".224* Hyphens and underscores equivalent in parameter names.225*/226char *next_arg(char *args, char **param, char **val)227{228unsigned int i, equals = 0;229int in_quote = 0, quoted = 0;230231if (*args == '"') {232args++;233in_quote = 1;234quoted = 1;235}236237for (i = 0; args[i]; i++) {238if (isspace(args[i]) && !in_quote)239break;240if (equals == 0) {241if (args[i] == '=')242equals = i;243}244if (args[i] == '"')245in_quote = !in_quote;246}247248*param = args;249if (!equals)250*val = NULL;251else {252args[equals] = '\0';253*val = args + equals + 1;254255/* Don't include quotes in value. */256if (**val == '"') {257(*val)++;258if (args[i-1] == '"')259args[i-1] = '\0';260}261}262if (quoted && i > 0 && args[i-1] == '"')263args[i-1] = '\0';264265if (args[i]) {266args[i] = '\0';267args += i + 1;268} else269args += i;270271/* Chew up trailing spaces. */272return skip_spaces(args);273}274EXPORT_SYMBOL(next_arg);275276277