linux/arch/x86/boot/cmdline.c
<<
>>
Prefs
   1/* -*- linux-c -*- ------------------------------------------------------- *
   2 *
   3 *   Copyright (C) 1991, 1992 Linus Torvalds
   4 *   Copyright 2007 rPath, Inc. - All Rights Reserved
   5 *
   6 *   This file is part of the Linux kernel, and is made available under
   7 *   the terms of the GNU General Public License version 2.
   8 *
   9 * ----------------------------------------------------------------------- */
  10
  11/*
  12 * Simple command-line parser for early boot.
  13 */
  14
  15#include "boot.h"
  16
  17static inline int myisspace(u8 c)
  18{
  19        return c <= ' ';        /* Close enough approximation */
  20}
  21
  22/*
  23 * Find a non-boolean option, that is, "option=argument".  In accordance
  24 * with standard Linux practice, if this option is repeated, this returns
  25 * the last instance on the command line.
  26 *
  27 * Returns the length of the argument (regardless of if it was
  28 * truncated to fit in the buffer), or -1 on not found.
  29 */
  30int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize)
  31{
  32        addr_t cptr;
  33        char c;
  34        int len = -1;
  35        const char *opptr = NULL;
  36        char *bufptr = buffer;
  37        enum {
  38                st_wordstart,   /* Start of word/after whitespace */
  39                st_wordcmp,     /* Comparing this word */
  40                st_wordskip,    /* Miscompare, skip */
  41                st_bufcpy       /* Copying this to buffer */
  42        } state = st_wordstart;
  43
  44        if (!cmdline_ptr || cmdline_ptr >= 0x100000)
  45                return -1;      /* No command line, or inaccessible */
  46
  47        cptr = cmdline_ptr & 0xf;
  48        set_fs(cmdline_ptr >> 4);
  49
  50        while (cptr < 0x10000 && (c = rdfs8(cptr++))) {
  51                switch (state) {
  52                case st_wordstart:
  53                        if (myisspace(c))
  54                                break;
  55
  56                        /* else */
  57                        state = st_wordcmp;
  58                        opptr = option;
  59                        /* fall through */
  60
  61                case st_wordcmp:
  62                        if (c == '=' && !*opptr) {
  63                                len = 0;
  64                                bufptr = buffer;
  65                                state = st_bufcpy;
  66                        } else if (myisspace(c)) {
  67                                state = st_wordstart;
  68                        } else if (c != *opptr++) {
  69                                state = st_wordskip;
  70                        }
  71                        break;
  72
  73                case st_wordskip:
  74                        if (myisspace(c))
  75                                state = st_wordstart;
  76                        break;
  77
  78                case st_bufcpy:
  79                        if (myisspace(c)) {
  80                                state = st_wordstart;
  81                        } else {
  82                                if (len < bufsize-1)
  83                                        *bufptr++ = c;
  84                                len++;
  85                        }
  86                        break;
  87                }
  88        }
  89
  90        if (bufsize)
  91                *bufptr = '\0';
  92
  93        return len;
  94}
  95
  96/*
  97 * Find a boolean option (like quiet,noapic,nosmp....)
  98 *
  99 * Returns the position of that option (starts counting with 1)
 100 * or 0 on not found
 101 */
 102int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option)
 103{
 104        addr_t cptr;
 105        char c;
 106        int pos = 0, wstart = 0;
 107        const char *opptr = NULL;
 108        enum {
 109                st_wordstart,   /* Start of word/after whitespace */
 110                st_wordcmp,     /* Comparing this word */
 111                st_wordskip,    /* Miscompare, skip */
 112        } state = st_wordstart;
 113
 114        if (!cmdline_ptr || cmdline_ptr >= 0x100000)
 115                return -1;      /* No command line, or inaccessible */
 116
 117        cptr = cmdline_ptr & 0xf;
 118        set_fs(cmdline_ptr >> 4);
 119
 120        while (cptr < 0x10000) {
 121                c = rdfs8(cptr++);
 122                pos++;
 123
 124                switch (state) {
 125                case st_wordstart:
 126                        if (!c)
 127                                return 0;
 128                        else if (myisspace(c))
 129                                break;
 130
 131                        state = st_wordcmp;
 132                        opptr = option;
 133                        wstart = pos;
 134                        /* fall through */
 135
 136                case st_wordcmp:
 137                        if (!*opptr)
 138                                if (!c || myisspace(c))
 139                                        return wstart;
 140                                else
 141                                        state = st_wordskip;
 142                        else if (!c)
 143                                return 0;
 144                        else if (c != *opptr++)
 145                                state = st_wordskip;
 146                        break;
 147
 148                case st_wordskip:
 149                        if (!c)
 150                                return 0;
 151                        else if (myisspace(c))
 152                                state = st_wordstart;
 153                        break;
 154                }
 155        }
 156
 157        return 0;       /* Buffer overrun */
 158}
 159