Blame view

lib/cmdline.c 5.1 KB
40b0b3f8f   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
  /*
   * linux/lib/cmdline.c
   * Helper functions generally used for parsing kernel command line
   * and module options.
   *
   * Code and copyrights come from init/main.c and arch/i386/kernel/setup.c.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
   * GNU Indent formatting options for this file: -kr -i8 -npsl -pcs
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
   */
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
11
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
  #include <linux/kernel.h>
  #include <linux/string.h>
f51b17c8d   Baoquan He   boot/param: Move ...
14
  #include <linux/ctype.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15

22f2e2801   Derek Fults   [PATCH] get_optio...
16
17
18
19
20
  /*
   *	If a hyphen was found in get_option, this will handle the
   *	range of numbers, M-N.  This will expand the range and insert
   *	the values[M, M+1, ..., N] into the ints array in get_options.
   */
a91e0f680   Ilya Matveychikov   lib/cmdline.c: fi...
21
  static int get_range(char **str, int *pint, int n)
22f2e2801   Derek Fults   [PATCH] get_optio...
22
23
24
25
26
27
  {
  	int x, inc_counter, upper_range;
  
  	(*str)++;
  	upper_range = simple_strtol((*str), NULL, 0);
  	inc_counter = upper_range - *pint;
a91e0f680   Ilya Matveychikov   lib/cmdline.c: fi...
28
  	for (x = *pint; n && x < upper_range; x++, n--)
22f2e2801   Derek Fults   [PATCH] get_optio...
29
30
31
  		*pint++ = x;
  	return inc_counter;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
36
37
38
39
40
41
  
  /**
   *	get_option - Parse integer from an option string
   *	@str: option string
   *	@pint: (output) integer value parsed from @str
   *
   *	Read an int from an option string; if available accept a subsequent
   *	comma as well.
   *
   *	Return values:
72fd4a35a   Robert P. J. Day   [PATCH] Numerous ...
42
43
44
45
   *	0 - no int in string
   *	1 - int found, no subsequent comma
   *	2 - int found including a subsequent comma
   *	3 - hyphen found to denote a range
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
   */
9fd430544   Felipe Contreras   lib/cmdline.c: fi...
47
  int get_option(char **str, int *pint)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
51
52
  {
  	char *cur = *str;
  
  	if (!cur || !(*cur))
  		return 0;
9fd430544   Felipe Contreras   lib/cmdline.c: fi...
53
  	*pint = simple_strtol(cur, str, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
59
  	if (cur == *str)
  		return 0;
  	if (**str == ',') {
  		(*str)++;
  		return 2;
  	}
22f2e2801   Derek Fults   [PATCH] get_optio...
60
61
  	if (**str == '-')
  		return 3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
64
  
  	return 1;
  }
ff6f9bbb5   Felipe Contreras   lib/cmdline.c: de...
65
  EXPORT_SYMBOL(get_option);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
70
71
72
73
  
  /**
   *	get_options - Parse a string into a list of integers
   *	@str: String to be parsed
   *	@nints: size of integer array
   *	@ints: integer array
   *
   *	This function parses a string containing a comma-separated
22f2e2801   Derek Fults   [PATCH] get_optio...
74
75
   *	list of integers, a hyphen-separated range of _positive_ integers,
   *	or a combination of both.  The parse halts when the array is
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
78
79
80
81
82
   *	full, or when no more numbers can be retrieved from the
   *	string.
   *
   *	Return value is the character in the string which caused
   *	the parse to end (typically a null terminator, if @str is
   *	completely parseable).
   */
9fd430544   Felipe Contreras   lib/cmdline.c: fi...
83

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
87
88
  char *get_options(const char *str, int nints, int *ints)
  {
  	int res, i = 1;
  
  	while (i < nints) {
9fd430544   Felipe Contreras   lib/cmdline.c: fi...
89
  		res = get_option((char **)&str, ints + i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
  		if (res == 0)
  			break;
22f2e2801   Derek Fults   [PATCH] get_optio...
92
93
  		if (res == 3) {
  			int range_nums;
a91e0f680   Ilya Matveychikov   lib/cmdline.c: fi...
94
  			range_nums = get_range((char **)&str, ints + i, nints - i);
22f2e2801   Derek Fults   [PATCH] get_optio...
95
96
97
98
99
100
101
102
103
  			if (range_nums < 0)
  				break;
  			/*
  			 * Decrement the result by one to leave out the
  			 * last number in the range.  The next iteration
  			 * will handle the upper number in the range
  			 */
  			i += (range_nums - 1);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
107
108
109
110
  		i++;
  		if (res == 1)
  			break;
  	}
  	ints[0] = i - 1;
  	return (char *)str;
  }
ff6f9bbb5   Felipe Contreras   lib/cmdline.c: de...
111
  EXPORT_SYMBOL(get_options);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
114
115
  
  /**
   *	memparse - parse a string with mem suffixes into a number
   *	@ptr: Where parse begins
fd1938297   Robert P. J. Day   lib: allow mempar...
116
   *	@retptr: (output) Optional pointer to next char after parse completes
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
   *
   *	Parses a string into a number.  The number stored at @ptr is
e004f3c77   Gui Hecheng   lib/cmdline.c: ad...
119
   *	potentially suffixed with K, M, G, T, P, E.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
   */
d974ae379   Jeremy Fitzhardinge   generic, memparse...
121
  unsigned long long memparse(const char *ptr, char **retptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
  {
fd1938297   Robert P. J. Day   lib: allow mempar...
123
  	char *endptr;	/* local pointer to end of parsed string */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124

fd1938297   Robert P. J. Day   lib: allow mempar...
125
126
127
  	unsigned long long ret = simple_strtoull(ptr, &endptr, 0);
  
  	switch (*endptr) {
e004f3c77   Gui Hecheng   lib/cmdline.c: ad...
128
129
130
  	case 'E':
  	case 'e':
  		ret <<= 10;
6a9dc5fd6   Gustavo A. R. Silva   lib: Revert use o...
131
  		/* fall through */
e004f3c77   Gui Hecheng   lib/cmdline.c: ad...
132
133
134
  	case 'P':
  	case 'p':
  		ret <<= 10;
6a9dc5fd6   Gustavo A. R. Silva   lib: Revert use o...
135
  		/* fall through */
e004f3c77   Gui Hecheng   lib/cmdline.c: ad...
136
137
138
  	case 'T':
  	case 't':
  		ret <<= 10;
6a9dc5fd6   Gustavo A. R. Silva   lib: Revert use o...
139
  		/* fall through */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
  	case 'G':
  	case 'g':
  		ret <<= 10;
6a9dc5fd6   Gustavo A. R. Silva   lib: Revert use o...
143
  		/* fall through */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
146
  	case 'M':
  	case 'm':
  		ret <<= 10;
6a9dc5fd6   Gustavo A. R. Silva   lib: Revert use o...
147
  		/* fall through */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
150
  	case 'K':
  	case 'k':
  		ret <<= 10;
fd1938297   Robert P. J. Day   lib: allow mempar...
151
  		endptr++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
  	default:
  		break;
  	}
fd1938297   Robert P. J. Day   lib: allow mempar...
155
156
157
  
  	if (retptr)
  		*retptr = endptr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
  EXPORT_SYMBOL(memparse);
6ccc72b87   Dave Young   lib: Add a generi...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  
  /**
   *	parse_option_str - Parse a string and check an option is set or not
   *	@str: String to be parsed
   *	@option: option name
   *
   *	This function parses a string containing a comma-separated list of
   *	strings like a=b,c.
   *
   *	Return true if there's such option in the string, or return false.
   */
  bool parse_option_str(const char *str, const char *option)
  {
  	while (*str) {
  		if (!strncmp(str, option, strlen(option))) {
  			str += strlen(option);
  			if (!*str || *str == ',')
  				return true;
  		}
  
  		while (*str && *str != ',')
  			str++;
  
  		if (*str == ',')
  			str++;
  	}
  
  	return false;
  }
f51b17c8d   Baoquan He   boot/param: Move ...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  
  /*
   * Parse a string to get a param value pair.
   * You can use " around spaces, but can't escape ".
   * Hyphens and underscores equivalent in parameter names.
   */
  char *next_arg(char *args, char **param, char **val)
  {
  	unsigned int i, equals = 0;
  	int in_quote = 0, quoted = 0;
  	char *next;
  
  	if (*args == '"') {
  		args++;
  		in_quote = 1;
  		quoted = 1;
  	}
  
  	for (i = 0; args[i]; i++) {
  		if (isspace(args[i]) && !in_quote)
  			break;
  		if (equals == 0) {
  			if (args[i] == '=')
  				equals = i;
  		}
  		if (args[i] == '"')
  			in_quote = !in_quote;
  	}
  
  	*param = args;
  	if (!equals)
  		*val = NULL;
  	else {
  		args[equals] = '\0';
  		*val = args + equals + 1;
  
  		/* Don't include quotes in value. */
  		if (**val == '"') {
  			(*val)++;
  			if (args[i-1] == '"')
  				args[i-1] = '\0';
  		}
  	}
  	if (quoted && args[i-1] == '"')
  		args[i-1] = '\0';
  
  	if (args[i]) {
  		args[i] = '\0';
  		next = args + i + 1;
  	} else
  		next = args + i;
  
  	/* Chew up trailing spaces. */
  	return skip_spaces(next);
f51b17c8d   Baoquan He   boot/param: Move ...
244
  }