pull master
[hh.org.git] / lab / lab-main.c
blobeb0fa983b802ac20718db9b602cf9a0a7ae3371d
1 /*
2 * Linux As Bootloader main entry point
4 * Authors: Andrew Zabolotny <zap@homelink.ru>
5 * Joshua Wise
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file COPYING in the main directory of this archive for
9 * more details.
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/version.h>
16 #include <linux/fs.h>
17 #include <linux/syscalls.h>
18 #include <linux/lab/lab.h>
19 #include <linux/lab/commands.h>
21 void lab_runfile(char *source, char *sourcefile);
23 int globfail;
24 EXPORT_SYMBOL (globfail);
26 static int cmdline = 0;
28 static int __init forcecli_setup(char *__unused)
30 printk ("lab: Skipping autoboot due to forcecli parameter.\n");
31 cmdline = 1;
32 return 1;
34 __setup("forcecli", forcecli_setup);
36 static void print_version (void)
38 lab_puts ("LAB - Linux As Bootloader, " UTS_RELEASE "\r\n");
41 static void print_banner (void)
43 print_version ();
44 lab_puts ("Contact: bootldr@handhelds.org\r\n\r\n");
46 lab_puts ("Copyright (c) 2003-2004 Joshua Wise, Andrew Zabolotny and others.\r\n");
47 lab_puts ("Based on Linux kernel, which is copyright (c) Linus Torvalds and others.\r\n");
48 lab_puts ("Partially based on OHH bootldr, which is copyright (c) COMPAQ Computer Corporation.\r\n");
49 lab_puts ("This program is provided with NO WARRANTY under the terms of the\r\nGNU General Public License.\r\n");
52 enum ParseState {
53 PS_WHITESPACE,
54 PS_TOKEN,
55 PS_STRING,
56 PS_ESCAPE
59 static void parseargs (char *argstr, int *argc_p, char **argv, char **resid)
61 int argc = 0;
62 char c;
63 enum ParseState lastState = PS_WHITESPACE;
64 enum ParseState stackedState = PS_WHITESPACE;
66 /* tokenize the argstr */
67 while ((c = *argstr) != 0) {
68 enum ParseState newState;
70 if ((c == ';' || c == '\n') && lastState != PS_STRING && lastState != PS_ESCAPE)
71 break;
73 if (lastState == PS_ESCAPE) {
74 newState = stackedState;
75 } else if (lastState == PS_STRING) {
76 if (c == '"') {
77 newState = PS_WHITESPACE;
78 *argstr = 0;
79 } else {
80 newState = PS_STRING;
82 } else if ((c == ' ') || (c == '\t')) {
83 /* whitespace character */
84 *argstr = 0;
85 newState = PS_WHITESPACE;
86 } else if (c == '"') {
87 newState = PS_STRING;
88 *argstr = 0;
89 argv[argc++] = argstr + 1;
90 } else if (c == '\\') {
91 stackedState = lastState;
92 newState = PS_ESCAPE;
93 } else {
94 /* token */
95 if (lastState == PS_WHITESPACE) {
96 argv[argc++] = argstr;
98 newState = PS_TOKEN;
101 lastState = newState;
102 argstr++;
105 argv [argc] = NULL;
106 if (argc_p != NULL)
107 *argc_p = argc;
109 if (*argstr == ';' || *argstr == '\n')
110 *argstr++ = 0;
112 *resid = argstr;
115 #if 0
116 // Commented out until we find a use for it -- zap
118 // this is getting more compliacated, this function will averride any of the
119 // args in argstr with tthe args from argv. this will allow you to override the
120 // param linuxargs from the commandline. e.g. init=/myRC will override
121 // init=linuxRC from the params.
122 static void unparseargs(char *argstr, int argc, const char **argv)
124 int i;
125 char *cutStart;
126 char *cutEnd;
127 char *paramEnd;
128 int delta;
129 int j;
131 for (i = 0; i < argc; i++) {
132 if (argv[i] != NULL) {
133 // we have an a=b arg
134 if ((paramEnd = strchr(argv[i],'='))) {
135 int argstrlen = strlen(argstr);
136 int needlelen = 0;
137 char needle[256];
138 paramEnd++;
139 lab_puts("haystack = <");
140 lab_puts(argstr);
141 lab_puts(">\r\n");
143 needlelen = (int)(paramEnd - argv[i]);
144 strncpy(needle, argv[i], needlelen);
145 needle[needlelen] = 0;
146 lab_puts("needle = <");
147 putnstr(needle,needlelen);
148 lab_puts(">\r\n");
150 if ((cutStart = (char *)strstr(argstr, needle)) != NULL){
151 // found a match
152 if (!(cutEnd = strchr(cutStart,' '))) {
153 cutEnd = argstr + argstrlen;
154 } else {
155 cutEnd++; // skip the space
157 delta = (int)(cutEnd - cutStart);
158 for (j=(int) (cutEnd - argstr); j < argstrlen; j++)
159 argstr[j-delta] = argstr[j];
160 // new end of argstr
161 argstr[argstrlen - delta] = '\0';
165 strcat(argstr, " ");
166 strcat(argstr, argv[i]);
170 #endif
172 void lab_exec_string (char *buf)
174 int argc;
175 char *argv[256];
176 char *resid;
178 while (*buf) {
179 memset (argv, 0, sizeof (argv));
180 parseargs (buf, &argc, argv, &resid);
181 if (argc > 0)
182 lab_execcommand (argc, (char**) argv);
183 else
184 lab_exec_string ("help");
185 buf = resid;
188 EXPORT_SYMBOL (lab_exec_string);
190 static char *blockdevs[] = {
191 "/dev/mmcblk0p1", "ext2", "root=/dev/mmcblk0p1",
192 "/dev/mmcblk0p2", "ext2", "root=/dev/mmcblk0p2",
193 "/dev/mmcblk0p3", "ext2", "root=/dev/mmcblk0p3",
194 "/dev/mmcblk0p4", "ext2", "root=/dev/mmcblk0p4",
195 "/dev/hda1", "ext2", "root=/dev/hda1 rootdelay=5",
196 "/dev/hda2", "ext2", "root=/dev/hda2 rootdelay=5",
197 "/dev/hda3", "ext2", "root=/dev/hda3 rootdelay=5",
198 "/dev/hda4", "ext2", "root=/dev/hda4 rootdelay=5",
199 "/dev/hda5", "ext2", "root=/dev/hda5 rootdelay=5",
200 "/dev/hda6", "ext2", "root=/dev/hda6 rootdelay=5",
201 "/dev/hda7", "ext2", "root=/dev/hda7 rootdelay=5",
202 "/dev/mtdblock3", "jffs2", "root=/dev/mtdblock3 rootfstype=jffs2",
203 NULL
207 void lab_main (int cmdline)
209 char cmdbuff [512];
211 print_banner ();
212 if (!cmdline) {
213 char **blockdev;
214 unsigned char *contents;
215 int tleft;
217 for (tleft = 3; tleft > 0; tleft--)
219 lab_printf("\r>> LAB autoboot starting in %d seconds - press a key to abort", tleft);
221 if (lab_getc_seconds(NULL, 1))
223 lab_printf("\r\n>> Autoboot aborted\r\n");
224 goto domenu;
227 if (lab_initconsole())
229 lab_printf("\r>> LAB autoboot delayed due to new console\n");
230 tleft = 5+1; // give the user time to open a console and hit a key
233 lab_puts ("\r\n"
234 ">> Booting now.\r\n");
235 sys_mkdir("/mnt", 0000);
236 sys_mount("/dev", "/dev", "devfs", 0, "");
237 lab_puts (">> Looking for filesystems...\r\n");
238 blockdev = blockdevs;
239 while (*blockdev) {
241 struct stat sstat;
243 lab_printf(" >> Trying \"%s\"... ", blockdev[0]);
244 if (sys_mount(blockdev[0], "/mnt", blockdev[1],
245 MS_RDONLY, "") < 0) {
247 lab_printf("failed\r\n");
248 blockdev += 3;
249 continue;
252 lab_printf("ok");
254 if (sys_newstat("/mnt/boot/labrun", &sstat) >= 0) {
255 lab_printf(".\r\n");
256 lab_printf(">> Executing labrun... ");
257 lab_runfile("fs", "/mnt/boot/labrun");
258 lab_printf("done\r\n");
259 break;
261 lab_printf("; no labrun");
263 if (sys_newstat("/mnt/boot/zImage", &sstat) >= 0) {
264 lab_printf("; found zImage\r\n");
265 lab_printf(">> Copying zImage... ");
266 lab_copy("fs", "/mnt/boot/zImage", "fs", "/zImage");
267 lab_printf("done\r\n>> Unmounting filesystem... ");
268 sys_oldumount("/mnt");
269 lab_printf("done\r\n>> Booting kernel.\r\n");
270 lab_armboot("fs", "/zImage", blockdev[2]);
271 break;
273 lab_printf(", no zImage.\r\n");
274 sys_oldumount("/mnt");
275 blockdev += 3;
276 continue;
278 if (!*blockdev)
279 lab_printf(">> No bootable filesystems found!\r\n");
282 domenu:
283 while (1) {
284 lab_puts("boot> ");
285 lab_readline (cmdbuff, sizeof cmdbuff);
287 if (cmdbuff [0])
288 lab_exec_string (cmdbuff);
292 extern void lab_cmd_showlogo(int argc,const char** argv);
294 void lab_run (void)
296 int err;
298 #ifdef CONFIG_LAB_BOOTLOGO
299 lab_cmd_showlogo(0, NULL);
300 #endif
302 printk (KERN_INFO "lab: Starting LAB [Linux As Bootloader]\n");
303 err = sys_mount ("none", "/root", "ramfs", 0, "");
304 if (err) {
305 printk (KERN_ERR "lab: Failed to mount ramfs! err=%d, halting\n", err);
306 while (1) ;
309 err = sys_chdir ("/root");
310 if (err) {
311 printk (KERN_ERR "lab: chdir /root failed for some reason, halting\n");
312 while (1) ;
315 lab_initconsole ();
317 printk (KERN_INFO "lab: running.\n");
318 lab_main (cmdline);
319 while (1) ;