Skip to content

Commit e505371

Browse files
tlendackyIngo Molnar
authored andcommitted
x86/boot: Add early cmdline parsing for options with arguments
Add a cmdline_find_option() function to look for cmdline options that take arguments. The argument is returned in a supplied buffer and the argument length (regardless of whether it fits in the supplied buffer) is returned, with -1 indicating not found. Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Cc: Alexander Potapenko <glider@google.com> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Borislav Petkov <bp@alien8.de> Cc: Brijesh Singh <brijesh.singh@amd.com> Cc: Dave Young <dyoung@redhat.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: Larry Woodman <lwoodman@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Matt Fleming <matt@codeblueprint.co.uk> Cc: Michael S. Tsirkin <mst@redhat.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Radim Krčmář <rkrcmar@redhat.com> Cc: Rik van Riel <riel@redhat.com> Cc: Toshimitsu Kani <toshi.kani@hpe.com> Cc: kasan-dev@googlegroups.com Cc: kvm@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: linux-efi@vger.kernel.org Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/36b5f97492a9745dce27682305f990fc20e5cf8a.1500319216.git.thomas.lendacky@amd.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 6ebcb06 commit e505371

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

arch/x86/include/asm/cmdline.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,7 @@
22
#define _ASM_X86_CMDLINE_H
33

44
int cmdline_find_option_bool(const char *cmdline_ptr, const char *option);
5+
int cmdline_find_option(const char *cmdline_ptr, const char *option,
6+
char *buffer, int bufsize);
57

68
#endif /* _ASM_X86_CMDLINE_H */

arch/x86/lib/cmdline.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,112 @@ __cmdline_find_option_bool(const char *cmdline, int max_cmdline_size,
104104
return 0; /* Buffer overrun */
105105
}
106106

107+
/*
108+
* Find a non-boolean option (i.e. option=argument). In accordance with
109+
* standard Linux practice, if this option is repeated, this returns the
110+
* last instance on the command line.
111+
*
112+
* @cmdline: the cmdline string
113+
* @max_cmdline_size: the maximum size of cmdline
114+
* @option: option string to look for
115+
* @buffer: memory buffer to return the option argument
116+
* @bufsize: size of the supplied memory buffer
117+
*
118+
* Returns the length of the argument (regardless of if it was
119+
* truncated to fit in the buffer), or -1 on not found.
120+
*/
121+
static int
122+
__cmdline_find_option(const char *cmdline, int max_cmdline_size,
123+
const char *option, char *buffer, int bufsize)
124+
{
125+
char c;
126+
int pos = 0, len = -1;
127+
const char *opptr = NULL;
128+
char *bufptr = buffer;
129+
enum {
130+
st_wordstart = 0, /* Start of word/after whitespace */
131+
st_wordcmp, /* Comparing this word */
132+
st_wordskip, /* Miscompare, skip */
133+
st_bufcpy, /* Copying this to buffer */
134+
} state = st_wordstart;
135+
136+
if (!cmdline)
137+
return -1; /* No command line */
138+
139+
/*
140+
* This 'pos' check ensures we do not overrun
141+
* a non-NULL-terminated 'cmdline'
142+
*/
143+
while (pos++ < max_cmdline_size) {
144+
c = *(char *)cmdline++;
145+
if (!c)
146+
break;
147+
148+
switch (state) {
149+
case st_wordstart:
150+
if (myisspace(c))
151+
break;
152+
153+
state = st_wordcmp;
154+
opptr = option;
155+
/* fall through */
156+
157+
case st_wordcmp:
158+
if ((c == '=') && !*opptr) {
159+
/*
160+
* We matched all the way to the end of the
161+
* option we were looking for, prepare to
162+
* copy the argument.
163+
*/
164+
len = 0;
165+
bufptr = buffer;
166+
state = st_bufcpy;
167+
break;
168+
} else if (c == *opptr++) {
169+
/*
170+
* We are currently matching, so continue
171+
* to the next character on the cmdline.
172+
*/
173+
break;
174+
}
175+
state = st_wordskip;
176+
/* fall through */
177+
178+
case st_wordskip:
179+
if (myisspace(c))
180+
state = st_wordstart;
181+
break;
182+
183+
case st_bufcpy:
184+
if (myisspace(c)) {
185+
state = st_wordstart;
186+
} else {
187+
/*
188+
* Increment len, but don't overrun the
189+
* supplied buffer and leave room for the
190+
* NULL terminator.
191+
*/
192+
if (++len < bufsize)
193+
*bufptr++ = c;
194+
}
195+
break;
196+
}
197+
}
198+
199+
if (bufsize)
200+
*bufptr = '\0';
201+
202+
return len;
203+
}
204+
107205
int cmdline_find_option_bool(const char *cmdline, const char *option)
108206
{
109207
return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option);
110208
}
209+
210+
int cmdline_find_option(const char *cmdline, const char *option, char *buffer,
211+
int bufsize)
212+
{
213+
return __cmdline_find_option(cmdline, COMMAND_LINE_SIZE, option,
214+
buffer, bufsize);
215+
}

0 commit comments

Comments
 (0)