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