1*96ae6ea0SThomas Gleixner /* -*- linux-c -*- ------------------------------------------------------- * 2*96ae6ea0SThomas Gleixner * 3*96ae6ea0SThomas Gleixner * Copyright (C) 1991, 1992 Linus Torvalds 4*96ae6ea0SThomas Gleixner * Copyright 2007 rPath, Inc. - All Rights Reserved 5*96ae6ea0SThomas Gleixner * 6*96ae6ea0SThomas Gleixner * This file is part of the Linux kernel, and is made available under 7*96ae6ea0SThomas Gleixner * the terms of the GNU General Public License version 2. 8*96ae6ea0SThomas Gleixner * 9*96ae6ea0SThomas Gleixner * ----------------------------------------------------------------------- */ 10*96ae6ea0SThomas Gleixner 11*96ae6ea0SThomas Gleixner /* 12*96ae6ea0SThomas Gleixner * arch/i386/boot/cmdline.c 13*96ae6ea0SThomas Gleixner * 14*96ae6ea0SThomas Gleixner * Simple command-line parser for early boot. 15*96ae6ea0SThomas Gleixner */ 16*96ae6ea0SThomas Gleixner 17*96ae6ea0SThomas Gleixner #include "boot.h" 18*96ae6ea0SThomas Gleixner 19*96ae6ea0SThomas Gleixner static inline int myisspace(u8 c) 20*96ae6ea0SThomas Gleixner { 21*96ae6ea0SThomas Gleixner return c <= ' '; /* Close enough approximation */ 22*96ae6ea0SThomas Gleixner } 23*96ae6ea0SThomas Gleixner 24*96ae6ea0SThomas Gleixner /* 25*96ae6ea0SThomas Gleixner * Find a non-boolean option, that is, "option=argument". In accordance 26*96ae6ea0SThomas Gleixner * with standard Linux practice, if this option is repeated, this returns 27*96ae6ea0SThomas Gleixner * the last instance on the command line. 28*96ae6ea0SThomas Gleixner * 29*96ae6ea0SThomas Gleixner * Returns the length of the argument (regardless of if it was 30*96ae6ea0SThomas Gleixner * truncated to fit in the buffer), or -1 on not found. 31*96ae6ea0SThomas Gleixner */ 32*96ae6ea0SThomas Gleixner int cmdline_find_option(const char *option, char *buffer, int bufsize) 33*96ae6ea0SThomas Gleixner { 34*96ae6ea0SThomas Gleixner u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr; 35*96ae6ea0SThomas Gleixner addr_t cptr; 36*96ae6ea0SThomas Gleixner char c; 37*96ae6ea0SThomas Gleixner int len = -1; 38*96ae6ea0SThomas Gleixner const char *opptr = NULL; 39*96ae6ea0SThomas Gleixner char *bufptr = buffer; 40*96ae6ea0SThomas Gleixner enum { 41*96ae6ea0SThomas Gleixner st_wordstart, /* Start of word/after whitespace */ 42*96ae6ea0SThomas Gleixner st_wordcmp, /* Comparing this word */ 43*96ae6ea0SThomas Gleixner st_wordskip, /* Miscompare, skip */ 44*96ae6ea0SThomas Gleixner st_bufcpy /* Copying this to buffer */ 45*96ae6ea0SThomas Gleixner } state = st_wordstart; 46*96ae6ea0SThomas Gleixner 47*96ae6ea0SThomas Gleixner if (!cmdline_ptr || cmdline_ptr >= 0x100000) 48*96ae6ea0SThomas Gleixner return -1; /* No command line, or inaccessible */ 49*96ae6ea0SThomas Gleixner 50*96ae6ea0SThomas Gleixner cptr = cmdline_ptr & 0xf; 51*96ae6ea0SThomas Gleixner set_fs(cmdline_ptr >> 4); 52*96ae6ea0SThomas Gleixner 53*96ae6ea0SThomas Gleixner while (cptr < 0x10000 && (c = rdfs8(cptr++))) { 54*96ae6ea0SThomas Gleixner switch (state) { 55*96ae6ea0SThomas Gleixner case st_wordstart: 56*96ae6ea0SThomas Gleixner if (myisspace(c)) 57*96ae6ea0SThomas Gleixner break; 58*96ae6ea0SThomas Gleixner 59*96ae6ea0SThomas Gleixner /* else */ 60*96ae6ea0SThomas Gleixner state = st_wordcmp; 61*96ae6ea0SThomas Gleixner opptr = option; 62*96ae6ea0SThomas Gleixner /* fall through */ 63*96ae6ea0SThomas Gleixner 64*96ae6ea0SThomas Gleixner case st_wordcmp: 65*96ae6ea0SThomas Gleixner if (c == '=' && !*opptr) { 66*96ae6ea0SThomas Gleixner len = 0; 67*96ae6ea0SThomas Gleixner bufptr = buffer; 68*96ae6ea0SThomas Gleixner state = st_bufcpy; 69*96ae6ea0SThomas Gleixner } else if (myisspace(c)) { 70*96ae6ea0SThomas Gleixner state = st_wordstart; 71*96ae6ea0SThomas Gleixner } else if (c != *opptr++) { 72*96ae6ea0SThomas Gleixner state = st_wordskip; 73*96ae6ea0SThomas Gleixner } 74*96ae6ea0SThomas Gleixner break; 75*96ae6ea0SThomas Gleixner 76*96ae6ea0SThomas Gleixner case st_wordskip: 77*96ae6ea0SThomas Gleixner if (myisspace(c)) 78*96ae6ea0SThomas Gleixner state = st_wordstart; 79*96ae6ea0SThomas Gleixner break; 80*96ae6ea0SThomas Gleixner 81*96ae6ea0SThomas Gleixner case st_bufcpy: 82*96ae6ea0SThomas Gleixner if (myisspace(c)) { 83*96ae6ea0SThomas Gleixner state = st_wordstart; 84*96ae6ea0SThomas Gleixner } else { 85*96ae6ea0SThomas Gleixner if (len < bufsize-1) 86*96ae6ea0SThomas Gleixner *bufptr++ = c; 87*96ae6ea0SThomas Gleixner len++; 88*96ae6ea0SThomas Gleixner } 89*96ae6ea0SThomas Gleixner break; 90*96ae6ea0SThomas Gleixner } 91*96ae6ea0SThomas Gleixner } 92*96ae6ea0SThomas Gleixner 93*96ae6ea0SThomas Gleixner if (bufsize) 94*96ae6ea0SThomas Gleixner *bufptr = '\0'; 95*96ae6ea0SThomas Gleixner 96*96ae6ea0SThomas Gleixner return len; 97*96ae6ea0SThomas Gleixner } 98