LCOV - code coverage report
Current view: top level - arch/x86/lib - cmdline.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 55 62 88.7 %
Date: 2021-04-22 12:43:58 Functions: 4 4 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  *
       4             :  * Misc librarized functions for cmdline poking.
       5             :  */
       6             : #include <linux/kernel.h>
       7             : #include <linux/string.h>
       8             : #include <linux/ctype.h>
       9             : #include <asm/setup.h>
      10             : 
      11         999 : static inline int myisspace(u8 c)
      12             : {
      13         999 :         return c <= ' ';     /* Close enough approximation */
      14             : }
      15             : 
      16             : /**
      17             :  * Find a boolean option (like quiet,noapic,nosmp....)
      18             :  *
      19             :  * @cmdline: the cmdline string
      20             :  * @option: option string to look for
      21             :  *
      22             :  * Returns the position of that @option (starts counting with 1)
      23             :  * or 0 on not found.  @option will only be found if it is found
      24             :  * as an entire word in @cmdline.  For instance, if @option="car"
      25             :  * then a cmdline which contains "cart" will not match.
      26             :  */
      27             : static int
      28           5 : __cmdline_find_option_bool(const char *cmdline, int max_cmdline_size,
      29             :                            const char *option)
      30             : {
      31           5 :         char c;
      32           5 :         int pos = 0, wstart = 0;
      33           5 :         const char *opptr = NULL;
      34           5 :         enum {
      35             :                 st_wordstart = 0,       /* Start of word/after whitespace */
      36             :                 st_wordcmp,     /* Comparing this word */
      37             :                 st_wordskip,    /* Miscompare, skip */
      38           5 :         } state = st_wordstart;
      39             : 
      40           5 :         if (!cmdline)
      41             :                 return -1;      /* No command line */
      42             : 
      43             :         /*
      44             :          * This 'pos' check ensures we do not overrun
      45             :          * a non-NULL-terminated 'cmdline'
      46             :          */
      47         600 :         while (pos < max_cmdline_size) {
      48         600 :                 c = *(char *)cmdline++;
      49         600 :                 pos++;
      50             : 
      51         600 :                 switch (state) {
      52          30 :                 case st_wordstart:
      53          30 :                         if (!c)
      54             :                                 return 0;
      55          30 :                         else if (myisspace(c))
      56             :                                 break;
      57             : 
      58             :                         state = st_wordcmp;
      59             :                         opptr = option;
      60             :                         wstart = pos;
      61          30 :                         fallthrough;
      62             : 
      63          30 :                 case st_wordcmp:
      64          30 :                         if (!*opptr) {
      65             :                                 /*
      66             :                                  * We matched all the way to the end of the
      67             :                                  * option we were looking for.  If the
      68             :                                  * command-line has a space _or_ ends, then
      69             :                                  * we matched!
      70             :                                  */
      71           0 :                                 if (!c || myisspace(c))
      72           0 :                                         return wstart;
      73             :                                 /*
      74             :                                  * We hit the end of the option, but _not_
      75             :                                  * the end of a word on the cmdline.  Not
      76             :                                  * a match.
      77             :                                  */
      78          30 :                         } else if (!c) {
      79             :                                 /*
      80             :                                  * Hit the NULL terminator on the end of
      81             :                                  * cmdline.
      82             :                                  */
      83             :                                 return 0;
      84          30 :                         } else if (c == *opptr++) {
      85             :                                 /*
      86             :                                  * We are currently matching, so continue
      87             :                                  * to the next character on the cmdline.
      88             :                                  */
      89             :                                 break;
      90             :                         }
      91             :                         state = st_wordskip;
      92         600 :                         fallthrough;
      93             : 
      94         600 :                 case st_wordskip:
      95         600 :                         if (!c)
      96             :                                 return 0;
      97         595 :                         else if (myisspace(c))
      98          25 :                                 state = st_wordstart;
      99             :                         break;
     100             :                 }
     101           0 :         }
     102             : 
     103             :         return 0;       /* Buffer overrun */
     104             : }
     105             : 
     106             : /*
     107             :  * Find a non-boolean option (i.e. option=argument). In accordance with
     108             :  * standard Linux practice, if this option is repeated, this returns the
     109             :  * last instance on the command line.
     110             :  *
     111             :  * @cmdline: the cmdline string
     112             :  * @max_cmdline_size: the maximum size of cmdline
     113             :  * @option: option string to look for
     114             :  * @buffer: memory buffer to return the option argument
     115             :  * @bufsize: size of the supplied memory buffer
     116             :  *
     117             :  * Returns the length of the argument (regardless of if it was
     118             :  * truncated to fit in the buffer), or -1 on not found.
     119             :  */
     120             : static int
     121           3 : __cmdline_find_option(const char *cmdline, int max_cmdline_size,
     122             :                       const char *option, char *buffer, int bufsize)
     123             : {
     124           3 :         char c;
     125           3 :         int pos = 0, len = -1;
     126           3 :         const char *opptr = NULL;
     127           3 :         char *bufptr = buffer;
     128           3 :         enum {
     129             :                 st_wordstart = 0,       /* Start of word/after whitespace */
     130             :                 st_wordcmp,     /* Comparing this word */
     131             :                 st_wordskip,    /* Miscompare, skip */
     132             :                 st_bufcpy,      /* Copying this to buffer */
     133           3 :         } state = st_wordstart;
     134             : 
     135           3 :         if (!cmdline)
     136             :                 return -1;      /* No command line */
     137             : 
     138             :         /*
     139             :          * This 'pos' check ensures we do not overrun
     140             :          * a non-NULL-terminated 'cmdline'
     141             :          */
     142         360 :         while (pos++ < max_cmdline_size) {
     143         360 :                 c = *(char *)cmdline++;
     144         360 :                 if (!c)
     145             :                         break;
     146             : 
     147         357 :                 switch (state) {
     148          18 :                 case st_wordstart:
     149          18 :                         if (myisspace(c))
     150             :                                 break;
     151             : 
     152             :                         state = st_wordcmp;
     153             :                         opptr = option;
     154          19 :                         fallthrough;
     155             : 
     156          19 :                 case st_wordcmp:
     157          19 :                         if ((c == '=') && !*opptr) {
     158             :                                 /*
     159             :                                  * We matched all the way to the end of the
     160             :                                  * option we were looking for, prepare to
     161             :                                  * copy the argument.
     162             :                                  */
     163             :                                 len = 0;
     164             :                                 bufptr = buffer;
     165             :                                 state = st_bufcpy;
     166             :                                 break;
     167          19 :                         } else if (c == *opptr++) {
     168             :                                 /*
     169             :                                  * We are currently matching, so continue
     170             :                                  * to the next character on the cmdline.
     171             :                                  */
     172             :                                 break;
     173             :                         }
     174             :                         state = st_wordskip;
     175         356 :                         fallthrough;
     176             : 
     177         356 :                 case st_wordskip:
     178         356 :                         if (myisspace(c))
     179          15 :                                 state = st_wordstart;
     180             :                         break;
     181             : 
     182           0 :                 case st_bufcpy:
     183           0 :                         if (myisspace(c)) {
     184             :                                 state = st_wordstart;
     185             :                         } else {
     186             :                                 /*
     187             :                                  * Increment len, but don't overrun the
     188             :                                  * supplied buffer and leave room for the
     189             :                                  * NULL terminator.
     190             :                                  */
     191           0 :                                 if (++len < bufsize)
     192           0 :                                         *bufptr++ = c;
     193             :                         }
     194             :                         break;
     195             :                 }
     196           1 :         }
     197             : 
     198           3 :         if (bufsize)
     199           3 :                 *bufptr = '\0';
     200             : 
     201             :         return len;
     202             : }
     203             : 
     204           5 : int cmdline_find_option_bool(const char *cmdline, const char *option)
     205             : {
     206           5 :         return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option);
     207             : }
     208             : 
     209           3 : int cmdline_find_option(const char *cmdline, const char *option, char *buffer,
     210             :                         int bufsize)
     211             : {
     212           3 :         return __cmdline_find_option(cmdline, COMMAND_LINE_SIZE, option,
     213             :                                      buffer, bufsize);
     214             : }

Generated by: LCOV version 1.14