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