xref: /openbmc/linux/lib/cmdline.c (revision b34e08d5)
1 /*
2  * linux/lib/cmdline.c
3  * Helper functions generally used for parsing kernel command line
4  * and module options.
5  *
6  * Code and copyrights come from init/main.c and arch/i386/kernel/setup.c.
7  *
8  * This source code is licensed under the GNU General Public License,
9  * Version 2.  See the file COPYING for more details.
10  *
11  * GNU Indent formatting options for this file: -kr -i8 -npsl -pcs
12  *
13  */
14 
15 #include <linux/export.h>
16 #include <linux/kernel.h>
17 #include <linux/string.h>
18 
19 /*
20  *	If a hyphen was found in get_option, this will handle the
21  *	range of numbers, M-N.  This will expand the range and insert
22  *	the values[M, M+1, ..., N] into the ints array in get_options.
23  */
24 
25 static int get_range(char **str, int *pint)
26 {
27 	int x, inc_counter, upper_range;
28 
29 	(*str)++;
30 	upper_range = simple_strtol((*str), NULL, 0);
31 	inc_counter = upper_range - *pint;
32 	for (x = *pint; x < upper_range; x++)
33 		*pint++ = x;
34 	return inc_counter;
35 }
36 
37 /**
38  *	get_option - Parse integer from an option string
39  *	@str: option string
40  *	@pint: (output) integer value parsed from @str
41  *
42  *	Read an int from an option string; if available accept a subsequent
43  *	comma as well.
44  *
45  *	Return values:
46  *	0 - no int in string
47  *	1 - int found, no subsequent comma
48  *	2 - int found including a subsequent comma
49  *	3 - hyphen found to denote a range
50  */
51 
52 int get_option(char **str, int *pint)
53 {
54 	char *cur = *str;
55 
56 	if (!cur || !(*cur))
57 		return 0;
58 	*pint = simple_strtol(cur, str, 0);
59 	if (cur == *str)
60 		return 0;
61 	if (**str == ',') {
62 		(*str)++;
63 		return 2;
64 	}
65 	if (**str == '-')
66 		return 3;
67 
68 	return 1;
69 }
70 EXPORT_SYMBOL(get_option);
71 
72 /**
73  *	get_options - Parse a string into a list of integers
74  *	@str: String to be parsed
75  *	@nints: size of integer array
76  *	@ints: integer array
77  *
78  *	This function parses a string containing a comma-separated
79  *	list of integers, a hyphen-separated range of _positive_ integers,
80  *	or a combination of both.  The parse halts when the array is
81  *	full, or when no more numbers can be retrieved from the
82  *	string.
83  *
84  *	Return value is the character in the string which caused
85  *	the parse to end (typically a null terminator, if @str is
86  *	completely parseable).
87  */
88 
89 char *get_options(const char *str, int nints, int *ints)
90 {
91 	int res, i = 1;
92 
93 	while (i < nints) {
94 		res = get_option((char **)&str, ints + i);
95 		if (res == 0)
96 			break;
97 		if (res == 3) {
98 			int range_nums;
99 			range_nums = get_range((char **)&str, ints + i);
100 			if (range_nums < 0)
101 				break;
102 			/*
103 			 * Decrement the result by one to leave out the
104 			 * last number in the range.  The next iteration
105 			 * will handle the upper number in the range
106 			 */
107 			i += (range_nums - 1);
108 		}
109 		i++;
110 		if (res == 1)
111 			break;
112 	}
113 	ints[0] = i - 1;
114 	return (char *)str;
115 }
116 EXPORT_SYMBOL(get_options);
117 
118 /**
119  *	memparse - parse a string with mem suffixes into a number
120  *	@ptr: Where parse begins
121  *	@retptr: (output) Optional pointer to next char after parse completes
122  *
123  *	Parses a string into a number.  The number stored at @ptr is
124  *	potentially suffixed with %K (for kilobytes, or 1024 bytes),
125  *	%M (for megabytes, or 1048576 bytes), or %G (for gigabytes, or
126  *	1073741824).  If the number is suffixed with K, M, or G, then
127  *	the return value is the number multiplied by one kilobyte, one
128  *	megabyte, or one gigabyte, respectively.
129  */
130 
131 unsigned long long memparse(const char *ptr, char **retptr)
132 {
133 	char *endptr;	/* local pointer to end of parsed string */
134 
135 	unsigned long long ret = simple_strtoull(ptr, &endptr, 0);
136 
137 	switch (*endptr) {
138 	case 'G':
139 	case 'g':
140 		ret <<= 10;
141 	case 'M':
142 	case 'm':
143 		ret <<= 10;
144 	case 'K':
145 	case 'k':
146 		ret <<= 10;
147 		endptr++;
148 	default:
149 		break;
150 	}
151 
152 	if (retptr)
153 		*retptr = endptr;
154 
155 	return ret;
156 }
157 EXPORT_SYMBOL(memparse);
158