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