xref: /openbmc/linux/arch/x86/boot/cmdline.c (revision 32d0b9898029b7b3c7f161d31f57c4831d9049eb)
196ae6ea0SThomas Gleixner /* -*- linux-c -*- ------------------------------------------------------- *
296ae6ea0SThomas Gleixner  *
396ae6ea0SThomas Gleixner  *   Copyright (C) 1991, 1992 Linus Torvalds
496ae6ea0SThomas Gleixner  *   Copyright 2007 rPath, Inc. - All Rights Reserved
596ae6ea0SThomas Gleixner  *
696ae6ea0SThomas Gleixner  *   This file is part of the Linux kernel, and is made available under
796ae6ea0SThomas Gleixner  *   the terms of the GNU General Public License version 2.
896ae6ea0SThomas Gleixner  *
996ae6ea0SThomas Gleixner  * ----------------------------------------------------------------------- */
1096ae6ea0SThomas Gleixner 
1196ae6ea0SThomas Gleixner /*
1296ae6ea0SThomas Gleixner  * arch/i386/boot/cmdline.c
1396ae6ea0SThomas Gleixner  *
1496ae6ea0SThomas Gleixner  * Simple command-line parser for early boot.
1596ae6ea0SThomas Gleixner  */
1696ae6ea0SThomas Gleixner 
1796ae6ea0SThomas Gleixner #include "boot.h"
1896ae6ea0SThomas Gleixner 
1996ae6ea0SThomas Gleixner static inline int myisspace(u8 c)
2096ae6ea0SThomas Gleixner {
2196ae6ea0SThomas Gleixner 	return c <= ' ';	/* Close enough approximation */
2296ae6ea0SThomas Gleixner }
2396ae6ea0SThomas Gleixner 
2496ae6ea0SThomas Gleixner /*
2596ae6ea0SThomas Gleixner  * Find a non-boolean option, that is, "option=argument".  In accordance
2696ae6ea0SThomas Gleixner  * with standard Linux practice, if this option is repeated, this returns
2796ae6ea0SThomas Gleixner  * the last instance on the command line.
2896ae6ea0SThomas Gleixner  *
2996ae6ea0SThomas Gleixner  * Returns the length of the argument (regardless of if it was
3096ae6ea0SThomas Gleixner  * truncated to fit in the buffer), or -1 on not found.
3196ae6ea0SThomas Gleixner  */
3296ae6ea0SThomas Gleixner int cmdline_find_option(const char *option, char *buffer, int bufsize)
3396ae6ea0SThomas Gleixner {
3496ae6ea0SThomas Gleixner 	u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
3596ae6ea0SThomas Gleixner 	addr_t cptr;
3696ae6ea0SThomas Gleixner 	char c;
3796ae6ea0SThomas Gleixner 	int len = -1;
3896ae6ea0SThomas Gleixner 	const char *opptr = NULL;
3996ae6ea0SThomas Gleixner 	char *bufptr = buffer;
4096ae6ea0SThomas Gleixner 	enum {
4196ae6ea0SThomas Gleixner 		st_wordstart,	/* Start of word/after whitespace */
4296ae6ea0SThomas Gleixner 		st_wordcmp,	/* Comparing this word */
4396ae6ea0SThomas Gleixner 		st_wordskip,	/* Miscompare, skip */
4496ae6ea0SThomas Gleixner 		st_bufcpy	/* Copying this to buffer */
4596ae6ea0SThomas Gleixner 	} state = st_wordstart;
4696ae6ea0SThomas Gleixner 
4796ae6ea0SThomas Gleixner 	if (!cmdline_ptr || cmdline_ptr >= 0x100000)
4896ae6ea0SThomas Gleixner 		return -1;	/* No command line, or inaccessible */
4996ae6ea0SThomas Gleixner 
5096ae6ea0SThomas Gleixner 	cptr = cmdline_ptr & 0xf;
5196ae6ea0SThomas Gleixner 	set_fs(cmdline_ptr >> 4);
5296ae6ea0SThomas Gleixner 
5396ae6ea0SThomas Gleixner 	while (cptr < 0x10000 && (c = rdfs8(cptr++))) {
5496ae6ea0SThomas Gleixner 		switch (state) {
5596ae6ea0SThomas Gleixner 		case st_wordstart:
5696ae6ea0SThomas Gleixner 			if (myisspace(c))
5796ae6ea0SThomas Gleixner 				break;
5896ae6ea0SThomas Gleixner 
5996ae6ea0SThomas Gleixner 			/* else */
6096ae6ea0SThomas Gleixner 			state = st_wordcmp;
6196ae6ea0SThomas Gleixner 			opptr = option;
6296ae6ea0SThomas Gleixner 			/* fall through */
6396ae6ea0SThomas Gleixner 
6496ae6ea0SThomas Gleixner 		case st_wordcmp:
6596ae6ea0SThomas Gleixner 			if (c == '=' && !*opptr) {
6696ae6ea0SThomas Gleixner 				len = 0;
6796ae6ea0SThomas Gleixner 				bufptr = buffer;
6896ae6ea0SThomas Gleixner 				state = st_bufcpy;
6996ae6ea0SThomas Gleixner 			} else if (myisspace(c)) {
7096ae6ea0SThomas Gleixner 				state = st_wordstart;
7196ae6ea0SThomas Gleixner 			} else if (c != *opptr++) {
7296ae6ea0SThomas Gleixner 				state = st_wordskip;
7396ae6ea0SThomas Gleixner 			}
7496ae6ea0SThomas Gleixner 			break;
7596ae6ea0SThomas Gleixner 
7696ae6ea0SThomas Gleixner 		case st_wordskip:
7796ae6ea0SThomas Gleixner 			if (myisspace(c))
7896ae6ea0SThomas Gleixner 				state = st_wordstart;
7996ae6ea0SThomas Gleixner 			break;
8096ae6ea0SThomas Gleixner 
8196ae6ea0SThomas Gleixner 		case st_bufcpy:
8296ae6ea0SThomas Gleixner 			if (myisspace(c)) {
8396ae6ea0SThomas Gleixner 				state = st_wordstart;
8496ae6ea0SThomas Gleixner 			} else {
8596ae6ea0SThomas Gleixner 				if (len < bufsize-1)
8696ae6ea0SThomas Gleixner 					*bufptr++ = c;
8796ae6ea0SThomas Gleixner 				len++;
8896ae6ea0SThomas Gleixner 			}
8996ae6ea0SThomas Gleixner 			break;
9096ae6ea0SThomas Gleixner 		}
9196ae6ea0SThomas Gleixner 	}
9296ae6ea0SThomas Gleixner 
9396ae6ea0SThomas Gleixner 	if (bufsize)
9496ae6ea0SThomas Gleixner 		*bufptr = '\0';
9596ae6ea0SThomas Gleixner 
9696ae6ea0SThomas Gleixner 	return len;
9796ae6ea0SThomas Gleixner }
98*32d0b989Sdevzero@web.de 
99*32d0b989Sdevzero@web.de /*
100*32d0b989Sdevzero@web.de  * Find a boolean option (like quiet,noapic,nosmp....)
101*32d0b989Sdevzero@web.de  *
102*32d0b989Sdevzero@web.de  * Returns the position of that option (starts counting with 1)
103*32d0b989Sdevzero@web.de  * or 0 on not found
104*32d0b989Sdevzero@web.de  */
105*32d0b989Sdevzero@web.de int cmdline_find_option_bool(const char *option)
106*32d0b989Sdevzero@web.de {
107*32d0b989Sdevzero@web.de 	u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
108*32d0b989Sdevzero@web.de 	addr_t cptr;
109*32d0b989Sdevzero@web.de 	char c;
110*32d0b989Sdevzero@web.de 	int pos =0 , wstart = 0;
111*32d0b989Sdevzero@web.de 	const char *opptr = NULL;
112*32d0b989Sdevzero@web.de 	enum {
113*32d0b989Sdevzero@web.de 		st_wordstart,	/* Start of word/after whitespace */
114*32d0b989Sdevzero@web.de 		st_wordcmp,	/* Comparing this word */
115*32d0b989Sdevzero@web.de 		st_wordskip,	/* Miscompare, skip */
116*32d0b989Sdevzero@web.de 	} state = st_wordstart;
117*32d0b989Sdevzero@web.de 
118*32d0b989Sdevzero@web.de 	if (!cmdline_ptr || cmdline_ptr >= 0x100000)
119*32d0b989Sdevzero@web.de 		return -1;	/* No command line, or inaccessible */
120*32d0b989Sdevzero@web.de 
121*32d0b989Sdevzero@web.de 	cptr = cmdline_ptr & 0xf;
122*32d0b989Sdevzero@web.de 	set_fs(cmdline_ptr >> 4);
123*32d0b989Sdevzero@web.de 
124*32d0b989Sdevzero@web.de 	while (cptr < 0x10000) {
125*32d0b989Sdevzero@web.de 		c = rdfs8(cptr++);
126*32d0b989Sdevzero@web.de 		pos++;
127*32d0b989Sdevzero@web.de 
128*32d0b989Sdevzero@web.de 		switch (state) {
129*32d0b989Sdevzero@web.de 		case st_wordstart:
130*32d0b989Sdevzero@web.de 			if (!c)
131*32d0b989Sdevzero@web.de 				return 0;
132*32d0b989Sdevzero@web.de 			else if (myisspace(c))
133*32d0b989Sdevzero@web.de 				break;
134*32d0b989Sdevzero@web.de 
135*32d0b989Sdevzero@web.de 			state = st_wordcmp;
136*32d0b989Sdevzero@web.de 			opptr = option;
137*32d0b989Sdevzero@web.de 			wstart = pos;
138*32d0b989Sdevzero@web.de 			/* fall through */
139*32d0b989Sdevzero@web.de 
140*32d0b989Sdevzero@web.de 		case st_wordcmp:
141*32d0b989Sdevzero@web.de 			if (!*opptr)
142*32d0b989Sdevzero@web.de 				if (!c || myisspace(c))
143*32d0b989Sdevzero@web.de 					return wstart;
144*32d0b989Sdevzero@web.de 				else
145*32d0b989Sdevzero@web.de 					state = st_wordskip;
146*32d0b989Sdevzero@web.de 			else if (!c)
147*32d0b989Sdevzero@web.de 				return 0;
148*32d0b989Sdevzero@web.de 			else if (c != *opptr++)
149*32d0b989Sdevzero@web.de 				state = st_wordskip;
150*32d0b989Sdevzero@web.de 			break;
151*32d0b989Sdevzero@web.de 
152*32d0b989Sdevzero@web.de 		case st_wordskip:
153*32d0b989Sdevzero@web.de 			if (!c)
154*32d0b989Sdevzero@web.de 				return 0;
155*32d0b989Sdevzero@web.de 			else if (myisspace(c))
156*32d0b989Sdevzero@web.de 				state = st_wordstart;
157*32d0b989Sdevzero@web.de 			break;
158*32d0b989Sdevzero@web.de 		}
159*32d0b989Sdevzero@web.de 	}
160*32d0b989Sdevzero@web.de 
161*32d0b989Sdevzero@web.de 	return 0;	/* Buffer overrun */
162*32d0b989Sdevzero@web.de }
163