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 * Simple command-line parser for early boot. 1396ae6ea0SThomas Gleixner */ 1496ae6ea0SThomas Gleixner 1596ae6ea0SThomas Gleixner #include "boot.h" 1696ae6ea0SThomas Gleixner 1796ae6ea0SThomas Gleixner static inline int myisspace(u8 c) 1896ae6ea0SThomas Gleixner { 1996ae6ea0SThomas Gleixner return c <= ' '; /* Close enough approximation */ 2096ae6ea0SThomas Gleixner } 2196ae6ea0SThomas Gleixner 2296ae6ea0SThomas Gleixner /* 2396ae6ea0SThomas Gleixner * Find a non-boolean option, that is, "option=argument". In accordance 2496ae6ea0SThomas Gleixner * with standard Linux practice, if this option is repeated, this returns 2596ae6ea0SThomas Gleixner * the last instance on the command line. 2696ae6ea0SThomas Gleixner * 2796ae6ea0SThomas Gleixner * Returns the length of the argument (regardless of if it was 2896ae6ea0SThomas Gleixner * truncated to fit in the buffer), or -1 on not found. 2996ae6ea0SThomas Gleixner */ 30f4ed2877SYinghai Lu int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize) 3196ae6ea0SThomas Gleixner { 3296ae6ea0SThomas Gleixner addr_t cptr; 3396ae6ea0SThomas Gleixner char c; 3496ae6ea0SThomas Gleixner int len = -1; 3596ae6ea0SThomas Gleixner const char *opptr = NULL; 3696ae6ea0SThomas Gleixner char *bufptr = buffer; 3796ae6ea0SThomas Gleixner enum { 3896ae6ea0SThomas Gleixner st_wordstart, /* Start of word/after whitespace */ 3996ae6ea0SThomas Gleixner st_wordcmp, /* Comparing this word */ 4096ae6ea0SThomas Gleixner st_wordskip, /* Miscompare, skip */ 4196ae6ea0SThomas Gleixner st_bufcpy /* Copying this to buffer */ 4296ae6ea0SThomas Gleixner } state = st_wordstart; 4396ae6ea0SThomas Gleixner 44*16a4baa6SYinghai Lu if (!cmdline_ptr) 45*16a4baa6SYinghai Lu return -1; /* No command line */ 4696ae6ea0SThomas Gleixner 4796ae6ea0SThomas Gleixner cptr = cmdline_ptr & 0xf; 4896ae6ea0SThomas Gleixner set_fs(cmdline_ptr >> 4); 4996ae6ea0SThomas Gleixner 5096ae6ea0SThomas Gleixner while (cptr < 0x10000 && (c = rdfs8(cptr++))) { 5196ae6ea0SThomas Gleixner switch (state) { 5296ae6ea0SThomas Gleixner case st_wordstart: 5396ae6ea0SThomas Gleixner if (myisspace(c)) 5496ae6ea0SThomas Gleixner break; 5596ae6ea0SThomas Gleixner 5696ae6ea0SThomas Gleixner /* else */ 5796ae6ea0SThomas Gleixner state = st_wordcmp; 5896ae6ea0SThomas Gleixner opptr = option; 5996ae6ea0SThomas Gleixner /* fall through */ 6096ae6ea0SThomas Gleixner 6196ae6ea0SThomas Gleixner case st_wordcmp: 6296ae6ea0SThomas Gleixner if (c == '=' && !*opptr) { 6396ae6ea0SThomas Gleixner len = 0; 6496ae6ea0SThomas Gleixner bufptr = buffer; 6596ae6ea0SThomas Gleixner state = st_bufcpy; 6696ae6ea0SThomas Gleixner } else if (myisspace(c)) { 6796ae6ea0SThomas Gleixner state = st_wordstart; 6896ae6ea0SThomas Gleixner } else if (c != *opptr++) { 6996ae6ea0SThomas Gleixner state = st_wordskip; 7096ae6ea0SThomas Gleixner } 7196ae6ea0SThomas Gleixner break; 7296ae6ea0SThomas Gleixner 7396ae6ea0SThomas Gleixner case st_wordskip: 7496ae6ea0SThomas Gleixner if (myisspace(c)) 7596ae6ea0SThomas Gleixner state = st_wordstart; 7696ae6ea0SThomas Gleixner break; 7796ae6ea0SThomas Gleixner 7896ae6ea0SThomas Gleixner case st_bufcpy: 7996ae6ea0SThomas Gleixner if (myisspace(c)) { 8096ae6ea0SThomas Gleixner state = st_wordstart; 8196ae6ea0SThomas Gleixner } else { 8296ae6ea0SThomas Gleixner if (len < bufsize-1) 8396ae6ea0SThomas Gleixner *bufptr++ = c; 8496ae6ea0SThomas Gleixner len++; 8596ae6ea0SThomas Gleixner } 8696ae6ea0SThomas Gleixner break; 8796ae6ea0SThomas Gleixner } 8896ae6ea0SThomas Gleixner } 8996ae6ea0SThomas Gleixner 9096ae6ea0SThomas Gleixner if (bufsize) 9196ae6ea0SThomas Gleixner *bufptr = '\0'; 9296ae6ea0SThomas Gleixner 9396ae6ea0SThomas Gleixner return len; 9496ae6ea0SThomas Gleixner } 9532d0b989Sdevzero@web.de 9632d0b989Sdevzero@web.de /* 9732d0b989Sdevzero@web.de * Find a boolean option (like quiet,noapic,nosmp....) 9832d0b989Sdevzero@web.de * 9932d0b989Sdevzero@web.de * Returns the position of that option (starts counting with 1) 10032d0b989Sdevzero@web.de * or 0 on not found 10132d0b989Sdevzero@web.de */ 102f4ed2877SYinghai Lu int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option) 10332d0b989Sdevzero@web.de { 10432d0b989Sdevzero@web.de addr_t cptr; 10532d0b989Sdevzero@web.de char c; 10632d0b989Sdevzero@web.de int pos = 0, wstart = 0; 10732d0b989Sdevzero@web.de const char *opptr = NULL; 10832d0b989Sdevzero@web.de enum { 10932d0b989Sdevzero@web.de st_wordstart, /* Start of word/after whitespace */ 11032d0b989Sdevzero@web.de st_wordcmp, /* Comparing this word */ 11132d0b989Sdevzero@web.de st_wordskip, /* Miscompare, skip */ 11232d0b989Sdevzero@web.de } state = st_wordstart; 11332d0b989Sdevzero@web.de 114*16a4baa6SYinghai Lu if (!cmdline_ptr) 115*16a4baa6SYinghai Lu return -1; /* No command line */ 11632d0b989Sdevzero@web.de 11732d0b989Sdevzero@web.de cptr = cmdline_ptr & 0xf; 11832d0b989Sdevzero@web.de set_fs(cmdline_ptr >> 4); 11932d0b989Sdevzero@web.de 12032d0b989Sdevzero@web.de while (cptr < 0x10000) { 12132d0b989Sdevzero@web.de c = rdfs8(cptr++); 12232d0b989Sdevzero@web.de pos++; 12332d0b989Sdevzero@web.de 12432d0b989Sdevzero@web.de switch (state) { 12532d0b989Sdevzero@web.de case st_wordstart: 12632d0b989Sdevzero@web.de if (!c) 12732d0b989Sdevzero@web.de return 0; 12832d0b989Sdevzero@web.de else if (myisspace(c)) 12932d0b989Sdevzero@web.de break; 13032d0b989Sdevzero@web.de 13132d0b989Sdevzero@web.de state = st_wordcmp; 13232d0b989Sdevzero@web.de opptr = option; 13332d0b989Sdevzero@web.de wstart = pos; 13432d0b989Sdevzero@web.de /* fall through */ 13532d0b989Sdevzero@web.de 13632d0b989Sdevzero@web.de case st_wordcmp: 13732d0b989Sdevzero@web.de if (!*opptr) 13832d0b989Sdevzero@web.de if (!c || myisspace(c)) 13932d0b989Sdevzero@web.de return wstart; 14032d0b989Sdevzero@web.de else 14132d0b989Sdevzero@web.de state = st_wordskip; 14232d0b989Sdevzero@web.de else if (!c) 14332d0b989Sdevzero@web.de return 0; 14432d0b989Sdevzero@web.de else if (c != *opptr++) 14532d0b989Sdevzero@web.de state = st_wordskip; 14632d0b989Sdevzero@web.de break; 14732d0b989Sdevzero@web.de 14832d0b989Sdevzero@web.de case st_wordskip: 14932d0b989Sdevzero@web.de if (!c) 15032d0b989Sdevzero@web.de return 0; 15132d0b989Sdevzero@web.de else if (myisspace(c)) 15232d0b989Sdevzero@web.de state = st_wordstart; 15332d0b989Sdevzero@web.de break; 15432d0b989Sdevzero@web.de } 15532d0b989Sdevzero@web.de } 15632d0b989Sdevzero@web.de 15732d0b989Sdevzero@web.de return 0; /* Buffer overrun */ 15832d0b989Sdevzero@web.de } 159