1e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin/* -*- linux-c -*- ------------------------------------------------------- * 2e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * 3e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * Copyright (C) 1991, 1992 Linus Torvalds 4e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * Copyright 2007 rPath, Inc. - All Rights Reserved 5e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * 6e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * This file is part of the Linux kernel, and is made available under 7e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * the terms of the GNU General Public License version 2. 8e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * 9e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * ----------------------------------------------------------------------- */ 10e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 11e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin/* 12e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * Simple command-line parser for early boot. 13e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin */ 14e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 15e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin#include "boot.h" 16e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 17e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvinstatic inline int myisspace(u8 c) 18e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin{ 19e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin return c <= ' '; /* Close enough approximation */ 20e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin} 21e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 22e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin/* 23e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * Find a non-boolean option, that is, "option=argument". In accordance 24e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * with standard Linux practice, if this option is repeated, this returns 25e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * the last instance on the command line. 26e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * 27e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * Returns the length of the argument (regardless of if it was 28e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin * truncated to fit in the buffer), or -1 on not found. 29e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin */ 303db07e70f0b4742f8daeda5c4aa8fbe7aeb3799eYinghai Luint __cmdline_find_option(unsigned long cmdline_ptr, const char *option, char *buffer, int bufsize) 31e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin{ 32e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin addr_t cptr; 33e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin char c; 34e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin int len = -1; 35e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin const char *opptr = NULL; 36e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin char *bufptr = buffer; 37e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin enum { 38e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin st_wordstart, /* Start of word/after whitespace */ 39e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin st_wordcmp, /* Comparing this word */ 40e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin st_wordskip, /* Miscompare, skip */ 41e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin st_bufcpy /* Copying this to buffer */ 42e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin } state = st_wordstart; 43e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 4416a4baa642cf448742aaf150c4daa093f9dbebbbYinghai Lu if (!cmdline_ptr) 4516a4baa642cf448742aaf150c4daa093f9dbebbbYinghai Lu return -1; /* No command line */ 46e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 47e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin cptr = cmdline_ptr & 0xf; 48e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin set_fs(cmdline_ptr >> 4); 49e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 50e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin while (cptr < 0x10000 && (c = rdfs8(cptr++))) { 51e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin switch (state) { 52e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin case st_wordstart: 53e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin if (myisspace(c)) 54e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin break; 55e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 56e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin /* else */ 57e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin state = st_wordcmp; 58e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin opptr = option; 59e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin /* fall through */ 60e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 61e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin case st_wordcmp: 62e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin if (c == '=' && !*opptr) { 63e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin len = 0; 64e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin bufptr = buffer; 65e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin state = st_bufcpy; 66e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin } else if (myisspace(c)) { 67e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin state = st_wordstart; 68e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin } else if (c != *opptr++) { 69e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin state = st_wordskip; 70e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin } 71e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin break; 72e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 73e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin case st_wordskip: 74e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin if (myisspace(c)) 75e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin state = st_wordstart; 76e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin break; 77e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 78e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin case st_bufcpy: 79e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin if (myisspace(c)) { 80e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin state = st_wordstart; 81e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin } else { 82e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin if (len < bufsize-1) 83e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin *bufptr++ = c; 84e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin len++; 85e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin } 86e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin break; 87e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin } 88e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin } 89e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 90e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin if (bufsize) 91e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin *bufptr = '\0'; 92e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin 93e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin return len; 94e44c22f65f96217692e1a915032fbe7d22236751H. Peter Anvin} 9532d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de 9632d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de/* 9732d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de * Find a boolean option (like quiet,noapic,nosmp....) 9832d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de * 9932d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de * Returns the position of that option (starts counting with 1) 10032d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de * or 0 on not found 10132d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de */ 1023db07e70f0b4742f8daeda5c4aa8fbe7aeb3799eYinghai Luint __cmdline_find_option_bool(unsigned long cmdline_ptr, const char *option) 10332d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de{ 10432d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de addr_t cptr; 10532d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de char c; 10670d8abf5df857ca7befe02e5d61fde807420a54cH. Peter Anvin int pos = 0, wstart = 0; 10732d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de const char *opptr = NULL; 10832d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de enum { 10932d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de st_wordstart, /* Start of word/after whitespace */ 11032d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de st_wordcmp, /* Comparing this word */ 11132d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de st_wordskip, /* Miscompare, skip */ 11232d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de } state = st_wordstart; 11332d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de 11416a4baa642cf448742aaf150c4daa093f9dbebbbYinghai Lu if (!cmdline_ptr) 11516a4baa642cf448742aaf150c4daa093f9dbebbbYinghai Lu return -1; /* No command line */ 11632d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de 11732d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de cptr = cmdline_ptr & 0xf; 11832d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de set_fs(cmdline_ptr >> 4); 11932d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de 12032d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de while (cptr < 0x10000) { 12132d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de c = rdfs8(cptr++); 12232d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de pos++; 12332d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de 12432d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de switch (state) { 12532d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de case st_wordstart: 12632d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de if (!c) 12732d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de return 0; 12832d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de else if (myisspace(c)) 12932d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de break; 13032d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de 13132d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de state = st_wordcmp; 13232d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de opptr = option; 13332d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de wstart = pos; 13432d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de /* fall through */ 13532d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de 13632d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de case st_wordcmp: 13732d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de if (!*opptr) 13832d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de if (!c || myisspace(c)) 13932d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de return wstart; 14032d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de else 14132d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de state = st_wordskip; 14232d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de else if (!c) 14332d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de return 0; 14432d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de else if (c != *opptr++) 14532d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de state = st_wordskip; 14632d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de break; 14732d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de 14832d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de case st_wordskip: 14932d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de if (!c) 15032d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de return 0; 15132d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de else if (myisspace(c)) 15232d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de state = st_wordstart; 15332d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de break; 15432d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de } 15532d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de } 15632d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de 15732d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de return 0; /* Buffer overrun */ 15832d0b9898029b7b3c7f161d31f57c4831d9049ebdevzero@web.de} 159