lkml.org 
[lkml]   [2017]   [Jun]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v6 33/34] x86/boot: Add early cmdline parsing for options with arguments
    Date
    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>
    ---
    arch/x86/include/asm/cmdline.h | 2 +
    arch/x86/lib/cmdline.c | 105 ++++++++++++++++++++++++++++++++++++++++
    2 files changed, 107 insertions(+)

    diff --git a/arch/x86/include/asm/cmdline.h b/arch/x86/include/asm/cmdline.h
    index e01f7f7..84ae170 100644
    --- a/arch/x86/include/asm/cmdline.h
    +++ b/arch/x86/include/asm/cmdline.h
    @@ -2,5 +2,7 @@
    #define _ASM_X86_CMDLINE_H

    int cmdline_find_option_bool(const char *cmdline_ptr, const char *option);
    +int cmdline_find_option(const char *cmdline_ptr, const char *option,
    + char *buffer, int bufsize);

    #endif /* _ASM_X86_CMDLINE_H */
    diff --git a/arch/x86/lib/cmdline.c b/arch/x86/lib/cmdline.c
    index 5cc78bf..3261abb 100644
    --- a/arch/x86/lib/cmdline.c
    +++ b/arch/x86/lib/cmdline.c
    @@ -104,7 +104,112 @@ static inline int myisspace(u8 c)
    return 0; /* Buffer overrun */
    }

    +/*
    + * Find a non-boolean option (i.e. option=argument). In accordance with
    + * standard Linux practice, if this option is repeated, this returns the
    + * last instance on the command line.
    + *
    + * @cmdline: the cmdline string
    + * @max_cmdline_size: the maximum size of cmdline
    + * @option: option string to look for
    + * @buffer: memory buffer to return the option argument
    + * @bufsize: size of the supplied memory buffer
    + *
    + * Returns the length of the argument (regardless of if it was
    + * truncated to fit in the buffer), or -1 on not found.
    + */
    +static int
    +__cmdline_find_option(const char *cmdline, int max_cmdline_size,
    + const char *option, char *buffer, int bufsize)
    +{
    + char c;
    + int pos = 0, len = -1;
    + const char *opptr = NULL;
    + char *bufptr = buffer;
    + enum {
    + st_wordstart = 0, /* Start of word/after whitespace */
    + st_wordcmp, /* Comparing this word */
    + st_wordskip, /* Miscompare, skip */
    + st_bufcpy, /* Copying this to buffer */
    + } state = st_wordstart;
    +
    + if (!cmdline)
    + return -1; /* No command line */
    +
    + /*
    + * This 'pos' check ensures we do not overrun
    + * a non-NULL-terminated 'cmdline'
    + */
    + while (pos++ < max_cmdline_size) {
    + c = *(char *)cmdline++;
    + if (!c)
    + break;
    +
    + switch (state) {
    + case st_wordstart:
    + if (myisspace(c))
    + break;
    +
    + state = st_wordcmp;
    + opptr = option;
    + /* fall through */
    +
    + case st_wordcmp:
    + if ((c == '=') && !*opptr) {
    + /*
    + * We matched all the way to the end of the
    + * option we were looking for, prepare to
    + * copy the argument.
    + */
    + len = 0;
    + bufptr = buffer;
    + state = st_bufcpy;
    + break;
    + } else if (c == *opptr++) {
    + /*
    + * We are currently matching, so continue
    + * to the next character on the cmdline.
    + */
    + break;
    + }
    + state = st_wordskip;
    + /* fall through */
    +
    + case st_wordskip:
    + if (myisspace(c))
    + state = st_wordstart;
    + break;
    +
    + case st_bufcpy:
    + if (myisspace(c)) {
    + state = st_wordstart;
    + } else {
    + /*
    + * Increment len, but don't overrun the
    + * supplied buffer and leave room for the
    + * NULL terminator.
    + */
    + if (++len < bufsize)
    + *bufptr++ = c;
    + }
    + break;
    + }
    + }
    +
    + if (bufsize)
    + *bufptr = '\0';
    +
    + return len;
    +}
    +
    int cmdline_find_option_bool(const char *cmdline, const char *option)
    {
    return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option);
    }
    +
    +int cmdline_find_option(const char *cmdline, const char *option, char *buffer,
    + int bufsize)
    +{
    + return __cmdline_find_option(cmdline, COMMAND_LINE_SIZE, option,
    + buffer, bufsize);
    +}
    \
     
     \ /
      Last update: 2017-06-12 01:11    [W:3.245 / U:0.360 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site