Commit | Line | Data |
---|---|---|
1b1ded57 BP |
1 | /* |
2 | * This file is part of the Linux kernel, and is made available under | |
3 | * the terms of the GNU General Public License version 2. | |
4 | * | |
5 | * Misc librarized functions for cmdline poking. | |
6 | */ | |
7 | #include <linux/kernel.h> | |
8 | #include <linux/string.h> | |
9 | #include <linux/ctype.h> | |
10 | #include <asm/setup.h> | |
11 | ||
12 | static inline int myisspace(u8 c) | |
13 | { | |
14 | return c <= ' '; /* Close enough approximation */ | |
15 | } | |
16 | ||
17 | /** | |
18 | * Find a boolean option (like quiet,noapic,nosmp....) | |
19 | * | |
20 | * @cmdline: the cmdline string | |
21 | * @option: option string to look for | |
22 | * | |
23 | * Returns the position of that @option (starts counting with 1) | |
02afeaae DH |
24 | * or 0 on not found. @option will only be found if it is found |
25 | * as an entire word in @cmdline. For instance, if @option="car" | |
26 | * then a cmdline which contains "cart" will not match. | |
1b1ded57 | 27 | */ |
8c051775 DH |
28 | static int |
29 | __cmdline_find_option_bool(const char *cmdline, int max_cmdline_size, | |
30 | const char *option) | |
1b1ded57 BP |
31 | { |
32 | char c; | |
02afeaae | 33 | int pos = 0, wstart = 0; |
1b1ded57 BP |
34 | const char *opptr = NULL; |
35 | enum { | |
36 | st_wordstart = 0, /* Start of word/after whitespace */ | |
37 | st_wordcmp, /* Comparing this word */ | |
38 | st_wordskip, /* Miscompare, skip */ | |
39 | } state = st_wordstart; | |
40 | ||
41 | if (!cmdline) | |
42 | return -1; /* No command line */ | |
43 | ||
02afeaae DH |
44 | /* |
45 | * This 'pos' check ensures we do not overrun | |
46 | * a non-NULL-terminated 'cmdline' | |
47 | */ | |
8c051775 | 48 | while (pos < max_cmdline_size) { |
1b1ded57 BP |
49 | c = *(char *)cmdline++; |
50 | pos++; | |
51 | ||
52 | switch (state) { | |
53 | case st_wordstart: | |
54 | if (!c) | |
55 | return 0; | |
56 | else if (myisspace(c)) | |
57 | break; | |
58 | ||
59 | state = st_wordcmp; | |
60 | opptr = option; | |
61 | wstart = pos; | |
62 | /* fall through */ | |
63 | ||
64 | case st_wordcmp: | |
02afeaae DH |
65 | if (!*opptr) { |
66 | /* | |
67 | * We matched all the way to the end of the | |
68 | * option we were looking for. If the | |
69 | * command-line has a space _or_ ends, then | |
70 | * we matched! | |
71 | */ | |
1b1ded57 BP |
72 | if (!c || myisspace(c)) |
73 | return wstart; | |
abcdc1c6 DH |
74 | /* |
75 | * We hit the end of the option, but _not_ | |
76 | * the end of a word on the cmdline. Not | |
77 | * a match. | |
78 | */ | |
02afeaae DH |
79 | } else if (!c) { |
80 | /* | |
81 | * Hit the NULL terminator on the end of | |
82 | * cmdline. | |
83 | */ | |
1b1ded57 | 84 | return 0; |
abcdc1c6 DH |
85 | } else if (c == *opptr++) { |
86 | /* | |
87 | * We are currently matching, so continue | |
88 | * to the next character on the cmdline. | |
89 | */ | |
90 | break; | |
02afeaae | 91 | } |
abcdc1c6 DH |
92 | state = st_wordskip; |
93 | /* fall through */ | |
1b1ded57 BP |
94 | |
95 | case st_wordskip: | |
96 | if (!c) | |
97 | return 0; | |
98 | else if (myisspace(c)) | |
99 | state = st_wordstart; | |
100 | break; | |
101 | } | |
102 | } | |
103 | ||
104 | return 0; /* Buffer overrun */ | |
105 | } | |
8c051775 DH |
106 | |
107 | int cmdline_find_option_bool(const char *cmdline, const char *option) | |
108 | { | |
109 | return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option); | |
110 | } |