diff options
Diffstat (limited to 'urunlevel/my_linux/linuxrc.c')
-rw-r--r-- | urunlevel/my_linux/linuxrc.c | 829 |
1 files changed, 829 insertions, 0 deletions
diff --git a/urunlevel/my_linux/linuxrc.c b/urunlevel/my_linux/linuxrc.c new file mode 100644 index 0000000..15fba1a --- /dev/null +++ b/urunlevel/my_linux/linuxrc.c | |||
@@ -0,0 +1,829 @@ | |||
1 | /* | ||
2 | * Mini linuxrc implementation for busybox. | ||
3 | * An implementation of the linuxrc boot script. | ||
4 | * | ||
5 | * Copyright (C) 2004 by David Seikel won_fang@yahoo.com.au | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
20 | * 02111-1307 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <dirent.h> | ||
25 | #include <fcntl.h> | ||
26 | #include <unistd.h> | ||
27 | #include <errno.h> | ||
28 | #include <signal.h> | ||
29 | #include <string.h> | ||
30 | #include <sys/poll.h> | ||
31 | #include <sys/wait.h> | ||
32 | #include <sys/utsname.h> /* for uname(2) */ | ||
33 | |||
34 | #include "busybox.h" | ||
35 | #include "lib_init_d.h" | ||
36 | #include "my_linux.h" | ||
37 | |||
38 | |||
39 | const static char *directories[] = | ||
40 | { | ||
41 | "boot", | ||
42 | "dev/pts", | ||
43 | "dev/input", | ||
44 | "lib", | ||
45 | "media/ROOT", | ||
46 | "media/cdrom", | ||
47 | "media/floppy", | ||
48 | "mnt", | ||
49 | "opt", | ||
50 | "proc", | ||
51 | "sbin", | ||
52 | "sys", | ||
53 | "udev", | ||
54 | "usr/bin", | ||
55 | "usr/etc/init.d", | ||
56 | "usr/lib", | ||
57 | "usr/sbin", | ||
58 | "var/cache", | ||
59 | "var/etc/network/if-down.d", | ||
60 | "var/etc/network/if-post-down.d", | ||
61 | "var/etc/network/if-pre-up.d", | ||
62 | "var/etc/network/if-up.d", | ||
63 | "var/etc/sysconfig", | ||
64 | "var/home/root", | ||
65 | "var/lib/misc", | ||
66 | "var/lib/network", | ||
67 | "var/lib/my_linux/init.m/done", | ||
68 | "var/lib/my_linux/pkg", | ||
69 | "var/lib/my_linux/config", | ||
70 | "var/lib/my_linux/contents", | ||
71 | "var/log", | ||
72 | "var/spool/cron/crontabs", | ||
73 | "var/temp", | ||
74 | "var/tmp", | ||
75 | #ifdef CONFIG_FEATURE_FULL_LSB | ||
76 | "boot/grub", | ||
77 | "bin", | ||
78 | "dev/net", | ||
79 | "etc/X11", | ||
80 | "etc/cron.d", | ||
81 | "etc/cron.daily", | ||
82 | "etc/cron.fortnightly", | ||
83 | "etc/cron.hourly", | ||
84 | "etc/cron.monthly", | ||
85 | "etc/cron.weekly", | ||
86 | "etc/cups", | ||
87 | "etc/opt", | ||
88 | "etc/sgml", | ||
89 | "etc/udev", | ||
90 | "lib/lsb", | ||
91 | "lib/modules/2.6.9/kernel", | ||
92 | "opt/bin", | ||
93 | "opt/doc", | ||
94 | "opt/include", | ||
95 | "opt/info", | ||
96 | "opt/lib", | ||
97 | "opt/man", | ||
98 | "usr/X11R6", | ||
99 | "usr/X11R6/bin", | ||
100 | "usr/X11R6/include/X11", | ||
101 | "usr/X11R6/lib/X11", | ||
102 | "usr/X11R6/man/en/man8", | ||
103 | "usr/doc", | ||
104 | "usr/games", | ||
105 | "usr/i386-linux-uclibc/include", | ||
106 | "usr/i386-linux-uclibc/lib", | ||
107 | "usr/i386-linux-uclibc/games", | ||
108 | "usr/i386-linux-uclibc/lsb", | ||
109 | "usr/include/bsd", | ||
110 | "usr/local/bin", | ||
111 | "usr/local/games", | ||
112 | "usr/local/i386-linux-uclibc/include", | ||
113 | "usr/local/i386-linux-uclibc/lib", | ||
114 | "usr/local/include", | ||
115 | "usr/local/lib", | ||
116 | "usr/local/man/en/man8", | ||
117 | "usr/local/sbin", | ||
118 | "usr/local/share", | ||
119 | "usr/local/src", | ||
120 | "usr/share/dict", | ||
121 | "usr/share/doc", | ||
122 | "usr/share/games", | ||
123 | "usr/share/ghostscript", | ||
124 | "usr/share/groff", | ||
125 | "usr/share/info", | ||
126 | "usr/share/kbd", | ||
127 | "usr/share/locale", | ||
128 | "usr/share/man/en/man8", | ||
129 | "usr/share/misc/getopt", | ||
130 | "usr/share/nls", | ||
131 | "usr/share/perl", | ||
132 | "usr/share/sgml/docbook", | ||
133 | "usr/share/sgml/html/dtd", | ||
134 | "usr/share/sgml/tei", | ||
135 | "usr/share/terminfo", | ||
136 | "usr/share/texmf", | ||
137 | "usr/share/zoneinfo", | ||
138 | "usr/src/linux-2.6.9/include", | ||
139 | "usr/src/packages/BUILD", | ||
140 | "usr/src/packages/RPMS/athlon", | ||
141 | "usr/src/packages/RPMS/i386", | ||
142 | "usr/src/packages/RPMS/i486", | ||
143 | "usr/src/packages/RPMS/i586", | ||
144 | "usr/src/packages/RPMS/i686", | ||
145 | "usr/src/packages/RPMS/noarch", | ||
146 | "usr/src/packages/SOURCES", | ||
147 | "usr/src/packages/SPECS", | ||
148 | "usr/src/packages/SRPMS", | ||
149 | "var/account", | ||
150 | "var/backups", | ||
151 | "var/cache/fonts", | ||
152 | "var/cache/man/en/man8", | ||
153 | "var/cache/www", | ||
154 | "var/cron", | ||
155 | "var/games", | ||
156 | "var/lib/hwclock", | ||
157 | "var/lib/xdm", | ||
158 | "var/local", | ||
159 | "var/msgs", | ||
160 | "var/nis", | ||
161 | "var/opt", | ||
162 | "var/preserve", | ||
163 | "var/spool/lpd", | ||
164 | "var/spool/mail", | ||
165 | "var/spool/mqueue", | ||
166 | "var/spool/news", | ||
167 | "var/spool/rwho", | ||
168 | "var/spool/uucp", | ||
169 | "var/yp", | ||
170 | #endif | ||
171 | NULL | ||
172 | }; | ||
173 | |||
174 | |||
175 | const static nodes_t nodes[] = | ||
176 | { | ||
177 | {"initctl", S_IFIFO, 0, 0, 0}, | ||
178 | {"log", S_IFIFO, 0, 0, 0}, | ||
179 | {"mem", S_IFCHR, 1, 1, 0}, | ||
180 | {"kmem", S_IFCHR, 1, 2, 0}, | ||
181 | {"port", S_IFCHR, 1, 4, 0}, | ||
182 | {"zero", S_IFCHR, 1, 5, 0}, | ||
183 | {"full", S_IFCHR, 1, 7, 0}, | ||
184 | {"random", S_IFCHR, 1, 8, 0}, | ||
185 | {"urandom", S_IFCHR, 1, 9, 0}, | ||
186 | {"tty", S_IFCHR, 5, 0, 0}, | ||
187 | {"psaux", S_IFCHR, 10, 1, 0}, | ||
188 | {"hda", S_IFBLK, 3, 0, 0}, | ||
189 | {"hdb", S_IFBLK, 3, 64, 0}, | ||
190 | {"hdc", S_IFBLK, 22, 0, 0}, | ||
191 | {"hdd", S_IFBLK, 22, 64, 0}, | ||
192 | {"ram", S_IFBLK, 1, 0, 9}, | ||
193 | {"fd", S_IFBLK, 2, 0, 1}, | ||
194 | {"tty", S_IFCHR, 4, 0,12}, | ||
195 | {"ttyS", S_IFCHR, 4, 64,47}, | ||
196 | {"loop", S_IFBLK, 7, 0,63}, | ||
197 | {"cloop", S_IFBLK, 240, 0, 7}, | ||
198 | {"vcs", S_IFBLK, 7, 0, 9}, | ||
199 | {"vcsa", S_IFBLK, 7, 0, 9}, | ||
200 | {"input/keyboard", S_IFCHR, 10,150, 0}, | ||
201 | {"input/js", S_IFCHR, 13, 0, 31}, | ||
202 | {"input/mouse", S_IFCHR, 13, 32, 30}, | ||
203 | {"input/mice", S_IFCHR, 13, 63, 0}, | ||
204 | {"input/event", S_IFCHR, 13, 64, 63}, | ||
205 | #ifdef CONFIG_FEATURE_FULL_LSB | ||
206 | {"net/tun", S_IFCHR, 10,200, 0}, | ||
207 | {"fb0", S_IFCHR, 29, 0, 0}, | ||
208 | {"fb1", S_IFCHR, 29, 32, 0}, | ||
209 | {"fb2", S_IFCHR, 29, 64, 0}, | ||
210 | {"fb3", S_IFCHR, 29, 96, 0}, | ||
211 | #endif | ||
212 | {0, 0, 0, 0, 0} | ||
213 | }; | ||
214 | |||
215 | |||
216 | const static char *files[][2] = | ||
217 | { | ||
218 | {"/var/etc/crontab", ""}, | ||
219 | // {"/var/etc/fstab", "none\t/dev/shm\tshm\tdefaults\t0 0\n/\t/dev/ram0\tminix\tdefaults\t0 0\n"}, | ||
220 | {"/var/etc/fstab", ""}, | ||
221 | {"/var/etc/group", "root:x:0:\ndaemon:x:2:\nshadow:x:42:\nusers:x:100:\nnogroup:x:65534:\n"}, | ||
222 | {"/var/etc/host.conf", "order hosts,bind\nmulti on\n"}, | ||
223 | {"/var/etc/hosts", "127.0.0.1 localhost\n"}, | ||
224 | {"/var/etc/inittab", "::sysinit:/sbin/rcS\ntty1::respawn:/bin/ash\ntty9::once:/sbin/rc 1\ntty11::once:/bin/dmesg\n::ctrlaltdel:/sbin/reboot\n::shutdown:/sbin/rc 0\n::shutdown:/sbin/swapoff -a\n::shutdown:/bin/umount -a -r\n::restart:/sbin/init\n"}, | ||
225 | {"/var/etc/ld.so.conf", ""}, | ||
226 | {"/var/etc/network/interfaces", "auto lo eth0\niface lo inet loopback\niface eth0 inet dhcp\n"}, | ||
227 | {"/var/etc/passwd", "root::0:0:My Linux Root:/root:/bin/sh\nftp:x:40:2:ftp:/tmp:/bin/sh\nsshd:x:41:2:sshd:/tmp:/bin/sh\nnobody:x:65534:65534:nobody:/tmp:/bin/sh\n"}, | ||
228 | {"/var/etc/resolv.conf", "search cluster.meeting.humbug.org.au\nnameserver 192.168.254.254\n"}, | ||
229 | {"/var/etc/securetty", "tty1\n"}, | ||
230 | {"/var/etc/shells", "/bin/ash\n/bin/hush\n/bin/lash\n/bin/msh\n/bin/sh\n"}, | ||
231 | #ifdef CONFIG_FEATURE_FULL_LSB | ||
232 | {"/boot/grub/device.map", "(hd0)\t/dev/hda\n(hd1)\t/dev/hdb\n(hd2)\t/dev/hdc\n(hd3)\t/dev/hdd\n(fd0)\t/dev/fd0\n"}, | ||
233 | #endif | ||
234 | {NULL, NULL} | ||
235 | }; | ||
236 | |||
237 | |||
238 | const static char *scripts[][2] = | ||
239 | { | ||
240 | {"/sbin/shownet", "#!/bin/sh\necho \"\"\nifconfig\nroute\nip addr list\nip link list\nip route list\necho \"\"\n"}, | ||
241 | {"/var/etc/profile", "#!/bin/sh\nPATH=/usr/bin:/usr/sbin:/bin:/sbin\nexport PATH\n"}, | ||
242 | #ifdef CONFIG_FEATURE_FULL_LSB | ||
243 | #endif | ||
244 | {NULL, NULL} | ||
245 | }; | ||
246 | |||
247 | |||
248 | const static char *links[][2] = | ||
249 | { | ||
250 | {"/proc/kcore", "/dev/core"}, | ||
251 | {"/dev/ram1", "/dev/ram"}, | ||
252 | {"/dev/vcs0", "/dev/vcs"}, | ||
253 | {"/dev/vcsa0", "/dev/vcsa"}, | ||
254 | {"/var/home", "/home"}, | ||
255 | {"/home/root", "/root"}, | ||
256 | {"/bin/busybox", "/sbin/init"}, | ||
257 | {"/bin/busybox", "/sbin/local_fs"}, | ||
258 | {"/bin/busybox", "/sbin/network"}, | ||
259 | {"/var/temp", "/tmp"}, | ||
260 | {"/sbin/local_fs", "/usr/etc/init.d/local_fs" }, | ||
261 | {"/sbin/boot_named", "/usr/etc/init.d/boot_named"}, | ||
262 | {"/sbin/network", "/usr/etc/init.d/network"}, | ||
263 | {"/sbin/boot_portmap", "/usr/etc/init.d/boot_portmap"}, | ||
264 | {"/sbin/remote_fs", "/usr/etc/init.d/remote_fs" }, | ||
265 | {"/sbin/boot_syslog", "/usr/etc/init.d/boot_syslog"}, | ||
266 | {"/sbin/boot_time", "/usr/etc/init.d/boot_time"}, | ||
267 | {"/usr/sbin/install_initd", "/usr/lib/lsb/install_initd" }, | ||
268 | {"/usr/sbin/remove_initd", "/usr/lib/lsb/remove_initd" }, | ||
269 | {"/usr/etc/init.d", "/var/etc/init.d"}, | ||
270 | {"/usr/etc/protocols", "/var/etc/protocols"}, | ||
271 | {"/usr/etc/rpc", "/var/etc/rpc"}, | ||
272 | {"/usr/etc/services", "/var/etc/services"}, | ||
273 | {"/var/lib/my_linux", "/var/etc/tux"}, | ||
274 | {"/.mc", "/var/home/root/.mc"}, | ||
275 | {"/tmp", "/var/lock"}, | ||
276 | {"/tmp", "/var/run"}, | ||
277 | #ifdef CONFIG_FEATURE_FULL_LSB | ||
278 | #endif | ||
279 | {NULL, NULL} | ||
280 | }; | ||
281 | |||
282 | |||
283 | const static char *modules[] = | ||
284 | { | ||
285 | // "af_packet", | ||
286 | // Should try all NICS instead. | ||
287 | // "mii", | ||
288 | // "ne2k-pci", | ||
289 | // "nfs", | ||
290 | NULL | ||
291 | }; | ||
292 | |||
293 | |||
294 | llist_t *floppies_list = NULL; | ||
295 | llist_t *cdroms_list = NULL; | ||
296 | llist_t *hard_disks_list = NULL; | ||
297 | static void find_all_drives(void) | ||
298 | { | ||
299 | int count; | ||
300 | struct dirent **dir; | ||
301 | |||
302 | if ((floppies_list == NULL) && (cdroms_list == NULL) && (hard_disks_list == NULL)) | ||
303 | { | ||
304 | // This is hard coded for now. | ||
305 | floppies_list = llist_add_to(floppies_list, "fd0"); | ||
306 | if ((count = scandir("/proc/ide", &dir, 0, alphasort))) | ||
307 | { | ||
308 | int n; | ||
309 | |||
310 | for (n = 0; n < count; n++) | ||
311 | { | ||
312 | struct dirent *script = dir[n]; | ||
313 | struct stat script_stat; | ||
314 | char *info_text = NULL; | ||
315 | |||
316 | bb_xasprintf(&info_text, "/proc/ide/%s", script->d_name); | ||
317 | if (stat(info_text, &script_stat) == 0) | ||
318 | { | ||
319 | if (strncmp(info_text, "/proc/ide/hd", 12) == 0) | ||
320 | { | ||
321 | char *text = NULL; | ||
322 | char *name = NULL; | ||
323 | |||
324 | bb_xasprintf(&text, "%s", doit(REDIR, "cat %s/media", info_text)); | ||
325 | bb_xasprintf(&name, "%s", script->d_name); | ||
326 | if (strcmp(text, "disk") == 0) | ||
327 | { | ||
328 | // Should add partitions instead. | ||
329 | hard_disks_list = llist_add_to(hard_disks_list, name); | ||
330 | } | ||
331 | else | ||
332 | cdroms_list = llist_add_to(cdroms_list, name); | ||
333 | } | ||
334 | free(info_text); | ||
335 | } | ||
336 | free(dir[n]); | ||
337 | } | ||
338 | free(dir); | ||
339 | } | ||
340 | } | ||
341 | } | ||
342 | |||
343 | |||
344 | static int is_boot_device(char *device, char *image, char **type); | ||
345 | static int find_boot_device_in_list(llist_t *disks, char *image, char **device, char **type) | ||
346 | { | ||
347 | int result = 0; | ||
348 | char *original = *device; | ||
349 | llist_t *current = disks; | ||
350 | |||
351 | while (current) | ||
352 | { | ||
353 | char *disc = current->data; | ||
354 | |||
355 | bb_printf("Checking %s for %s\n", disc, image); | ||
356 | bb_xasprintf(device, "/dev/%s", disc); | ||
357 | if (is_boot_device(*device, image, type)) | ||
358 | { | ||
359 | result = 1; | ||
360 | free(*device); | ||
361 | bb_xasprintf(device, "/dev/%s", disc); | ||
362 | *device = concat_path_file(*device, image); | ||
363 | break; | ||
364 | } | ||
365 | current = current->link; | ||
366 | free(*device); | ||
367 | *device = original; | ||
368 | } | ||
369 | return result; | ||
370 | } | ||
371 | |||
372 | |||
373 | static int is_boot_device(char *device, char *image, char **type) | ||
374 | { | ||
375 | int result = 0; | ||
376 | |||
377 | if (*type == NULL) | ||
378 | { | ||
379 | // Should try to detect it. | ||
380 | *type = "auto"; | ||
381 | } | ||
382 | quick_mount(*type, device, "/boot", "-o ro"); | ||
383 | if (errno == 0) | ||
384 | { | ||
385 | char *dest = concat_path_file("/boot", image); | ||
386 | |||
387 | if (stat(dest, &path_stat) == 0) | ||
388 | { | ||
389 | if (stat("/boot/bootrc", &path_stat) == 0) | ||
390 | result = 1; | ||
391 | } | ||
392 | if (result == 0) | ||
393 | doit(QUIET, "umount /boot"); | ||
394 | free(dest); | ||
395 | } | ||
396 | |||
397 | return result; | ||
398 | } | ||
399 | |||
400 | |||
401 | static void pivot_dir(char *place, const char *root) | ||
402 | { | ||
403 | char *dest = concat_path_file(root, place); | ||
404 | |||
405 | remove_file(place, FILEUTILS_FORCE | FILEUTILS_RECUR); | ||
406 | symlink(dest, place); | ||
407 | free(dest); | ||
408 | } | ||
409 | |||
410 | |||
411 | static int rebuild_fs(char *root) | ||
412 | { | ||
413 | int result = 0; | ||
414 | char *check = concat_path_file(root, "var/lib/distro"); | ||
415 | |||
416 | if (stat(check, &path_stat) == 0) | ||
417 | { | ||
418 | free(check); | ||
419 | bb_printf("Rebuilding root fs from %s.\n", root); | ||
420 | check = concat_path_file(root, "bootrc"); | ||
421 | copy_file(check, "/bootrc", FILEUTILS_FORCE | FILEUTILS_PRESERVE_STATUS); | ||
422 | free(check); | ||
423 | pivot_dir("/boot", root); | ||
424 | pivot_dir("/etc", root); | ||
425 | remove_file("/var/etc", FILEUTILS_FORCE | FILEUTILS_RECUR); | ||
426 | pivot_dir("/opt", root); | ||
427 | pivot_dir("/sbin", root); | ||
428 | pivot_dir("/usr", root); | ||
429 | // Should pivot dev and var if root is writable. | ||
430 | check = concat_path_file(root, "dev"); | ||
431 | copy_file(check, "/dev", FILEUTILS_FORCE | FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS); | ||
432 | free(check); | ||
433 | check = concat_path_file(root, "var"); | ||
434 | copy_file(check, "/var", FILEUTILS_FORCE | FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS); | ||
435 | // doit(QUIET, "ln -sf %s/lib/* /lib", root); | ||
436 | pivot_dir("/lib", root); | ||
437 | doit(0, "/sbin/ldconfig"); | ||
438 | pivot_dir("/bin", root); | ||
439 | result = 1; | ||
440 | } | ||
441 | |||
442 | free(check); | ||
443 | return result; | ||
444 | } | ||
445 | |||
446 | |||
447 | void set_boot_env(char *token); | ||
448 | void read_bootrc(void) | ||
449 | { | ||
450 | if (stat("/bootrc", &path_stat) == 0) | ||
451 | { | ||
452 | char *line; | ||
453 | FILE *contents; | ||
454 | |||
455 | contents = fopen("/bootrc", "r"); | ||
456 | if (contents != NULL) | ||
457 | { | ||
458 | char *buffer = (char *) xmalloc(sizeof (char) * 256); | ||
459 | |||
460 | bb_printf("Parsing configuration.\n"); | ||
461 | do | ||
462 | { | ||
463 | line = fgets(buffer, 255, contents); | ||
464 | if (line != NULL) | ||
465 | set_boot_env(buffer); | ||
466 | } while (line != NULL); | ||
467 | } | ||
468 | } | ||
469 | } | ||
470 | |||
471 | |||
472 | void set_boot_env(char *token) | ||
473 | { | ||
474 | int i; | ||
475 | char *eq = NULL; | ||
476 | char *ha = NULL; | ||
477 | |||
478 | //bb_printf("$$ %s\n", token); | ||
479 | for(i = 0; token[i] != '\0'; i++) | ||
480 | { | ||
481 | switch (token[i]) | ||
482 | { | ||
483 | case '=' : if (eq == NULL) eq = &token[i]; break; | ||
484 | case '#' : if (ha == NULL) ha = &token[i]; break; | ||
485 | } | ||
486 | } | ||
487 | |||
488 | if ((eq != token) && (ha != token)) | ||
489 | { | ||
490 | char *name = (char *) xmalloc(sizeof (char) * (i + 5)); | ||
491 | |||
492 | if (eq != NULL) | ||
493 | *eq = '\0'; | ||
494 | if (ha != NULL) | ||
495 | *ha = '\0'; | ||
496 | sprintf(name, "%s", token); | ||
497 | trim(name); | ||
498 | if (name[0] != '\0') | ||
499 | { | ||
500 | if (eq != NULL) | ||
501 | { | ||
502 | setenv(name, &eq[1], 1); | ||
503 | //bb_printf(" SET %s=%s\n", name, &eq[1]); | ||
504 | } | ||
505 | else | ||
506 | { | ||
507 | setenv(name, "", 1); | ||
508 | //bb_printf(" SET %s=\n", name); | ||
509 | } | ||
510 | } | ||
511 | free(name); | ||
512 | if (eq != NULL) | ||
513 | *eq = '='; | ||
514 | if (ha != NULL) | ||
515 | *ha = '#'; | ||
516 | } | ||
517 | } | ||
518 | |||
519 | |||
520 | int linuxrc_main(int argc, char **argv) | ||
521 | { | ||
522 | int i; | ||
523 | int root_write = 0; | ||
524 | long MEMORY = 0; | ||
525 | char *CMDLINE = 0; | ||
526 | char *BOOT = 0; | ||
527 | char *ROOT = 0; | ||
528 | char *ROOT_TYPE = "auto"; | ||
529 | char *BOOTFS = 0; | ||
530 | char *ROOT_MOUNT = "/media/ROOT"; | ||
531 | // char *PKGSRC = "network"; | ||
532 | int TMPFS = 0; | ||
533 | int USR = 0; | ||
534 | int VAR = 0; | ||
535 | char *NFSADDR = 0; | ||
536 | char temp[32]; | ||
537 | char *token; | ||
538 | char *strtok_temp; | ||
539 | struct sysinfo info; | ||
540 | struct utsname name; | ||
541 | |||
542 | mkrootfs(directories, nodes, files, scripts, links); | ||
543 | |||
544 | for (i = 0; modules[i] != 0; i++) | ||
545 | { | ||
546 | //bb_printf("\n\n modprobe %s\n\n\n", modules[i]); | ||
547 | doit(0, "modprobe %s", modules[i]); | ||
548 | } | ||
549 | // quick_mount("usbfs", "usbfs", "/proc/bus/usb", ""); | ||
550 | |||
551 | |||
552 | doit(0, "dmesg >/var/log/dmesg.txt"); | ||
553 | |||
554 | sysinfo(&info); | ||
555 | /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ | ||
556 | if (info.mem_unit==0) { | ||
557 | info.mem_unit=1; | ||
558 | } | ||
559 | if ( info.mem_unit == 1 ) { | ||
560 | info.mem_unit=1024; | ||
561 | |||
562 | /* TODO: Make all this stuff not overflow when mem >= 4 Gib */ | ||
563 | info.totalram/=info.mem_unit; | ||
564 | } else { | ||
565 | info.mem_unit/=1024; | ||
566 | /* TODO: Make all this stuff not overflow when mem >= 4 Gib */ | ||
567 | info.totalram*=info.mem_unit; | ||
568 | } | ||
569 | MEMORY = info.totalram; | ||
570 | USR = MEMORY / 2.5; | ||
571 | VAR = MEMORY / 16; | ||
572 | |||
573 | if (uname(&name) == -1) | ||
574 | bb_perror_msg_and_die("cannot get system information"); | ||
575 | if (atof(name.release) > 2.4) | ||
576 | TMPFS = 1; | ||
577 | |||
578 | make_ram_disk(VAR, 2, "/var", TMPFS); | ||
579 | |||
580 | bb_xasprintf(&CMDLINE, "%s", doit(REDIR, "cat /proc/cmdline")); | ||
581 | //bb_printf("%s\n", CMDLINE); | ||
582 | for (token = strtok_r(CMDLINE, " \t\n\r", &strtok_temp); token != NULL; token = strtok_r(NULL, " \t\n\r", &strtok_temp)) | ||
583 | { | ||
584 | if (strcmp(token, "RW") == 0) | ||
585 | { | ||
586 | root_write = 1; | ||
587 | sprintf(temp, "ROOT_MODE=RW"); | ||
588 | set_boot_env(temp); | ||
589 | } | ||
590 | else if (strcmp(token, "RO") == 0) | ||
591 | { | ||
592 | root_write = 0; | ||
593 | sprintf(temp, "ROOT_MODE=RO"); | ||
594 | set_boot_env(temp); | ||
595 | } | ||
596 | } | ||
597 | |||
598 | BOOT = getenv("BOOT_IMAGE"); | ||
599 | if (BOOT != NULL) | ||
600 | { | ||
601 | #define CDROM 1 | ||
602 | #define FLOPPY 2 | ||
603 | #define HD 3 | ||
604 | #define NETWORK 4 | ||
605 | int type = 0; | ||
606 | int disk = -1; | ||
607 | int part = -1; | ||
608 | char *image = BOOT; | ||
609 | char device[16]; | ||
610 | |||
611 | /* | ||
612 | * BOOT_IMAGE=(hd0,4)/boot/bzImage | ||
613 | * BOOT_IMAGE=(hd3)/boot/bzImage | ||
614 | * BOOT_IMAGE=(hdx,y)/boot/bzImage | ||
615 | * translate to /dev/hd(x+1)(y+1) | ||
616 | * BOOT_IMAGE=(cd)/boot/bzImage | ||
617 | * scan cd drives | ||
618 | * BOOT_IMAGE=/boot/bzImage | ||
619 | * try to avoid this, but scan all disks | ||
620 | * BOOT_IMAGE=bzImage | ||
621 | * probably syslinux, assume floppy boot (see next) | ||
622 | * BOOT_IMAGE=(fd0)/bzImage | ||
623 | * try to find bootrc on first floppy | ||
624 | * BOOT_IMAGE=(nd)/tftpboot/vmlinux | ||
625 | * try to tftp bootrc from network | ||
626 | */ | ||
627 | if ((BOOT[0] == '(') && (BOOT[2] == 'd') ) /* This is a grub boot, based on my BOOT_IMAGE patch for grub1. */ | ||
628 | { | ||
629 | while (image[0] != '\0') | ||
630 | { | ||
631 | if (image[0] == ')') | ||
632 | { | ||
633 | image++; | ||
634 | break; | ||
635 | } | ||
636 | image++; | ||
637 | } | ||
638 | switch (BOOT[1]) | ||
639 | { | ||
640 | case 'c' : type = CDROM; break; | ||
641 | case 'f' : type = FLOPPY; break; | ||
642 | case 'h' : type = HD; break; | ||
643 | case 'n' : type = NETWORK; break; | ||
644 | } | ||
645 | if (BOOT[3] != ')') | ||
646 | { | ||
647 | disk = atoi(&BOOT[3]) + 1; | ||
648 | if (BOOT[4] == ',') | ||
649 | part = atoi(&BOOT[5]) + 1; | ||
650 | } | ||
651 | } | ||
652 | |||
653 | device[0] = '\0'; | ||
654 | switch (type) | ||
655 | { | ||
656 | case FLOPPY : | ||
657 | sprintf(device, "/dev/fd%d", disk - 1); | ||
658 | break; | ||
659 | |||
660 | case HD : | ||
661 | sprintf(device, "/dev/hd%c%d", 'a' + disk, part); | ||
662 | break; | ||
663 | |||
664 | case NETWORK : | ||
665 | sprintf(device, "tftp:/"); | ||
666 | break; | ||
667 | } | ||
668 | |||
669 | if (device[0] == '\0') | ||
670 | { | ||
671 | find_all_drives(); | ||
672 | if (type == CDROM) | ||
673 | { | ||
674 | BOOTFS="iso9660"; | ||
675 | bb_printf("Scanning all CD and DVD drives for %s.\n", image); | ||
676 | if (find_boot_device_in_list(cdroms_list, image, &BOOT, &BOOTFS) == 0) | ||
677 | BOOTFS=NULL; | ||
678 | } | ||
679 | else | ||
680 | { | ||
681 | BOOTFS="vfat"; | ||
682 | bb_printf("Scanning all drives for %s.\n", image); | ||
683 | if (find_boot_device_in_list(floppies_list, image, &BOOT, &BOOTFS) == 0) | ||
684 | { | ||
685 | BOOTFS="iso9660"; | ||
686 | if (find_boot_device_in_list(cdroms_list, image, &BOOT, &BOOTFS) == 0) | ||
687 | { | ||
688 | BOOTFS=NULL; | ||
689 | if (find_boot_device_in_list(hard_disks_list, image, &BOOT, &BOOTFS) == 0) | ||
690 | BOOTFS=NULL; | ||
691 | } | ||
692 | } | ||
693 | } | ||
694 | } | ||
695 | else | ||
696 | { | ||
697 | if (type == NETWORK) | ||
698 | { | ||
699 | bb_xasprintf(&BOOT, "%s%s", device, image); | ||
700 | BOOTFS="Network"; | ||
701 | bb_printf("Kicking network into life.\n"); | ||
702 | doit(0, "rc network start"); | ||
703 | if (stat("/var/lib/network/tftpaddr", &path_stat) == 0) | ||
704 | { | ||
705 | bb_printf("\nDownloading configuration from network.\n"); | ||
706 | doit(QUIET, "tftp -gr /tftpboot/bootrc -l /bootrc %s", quick_read("/var/lib/network/tftpaddr")); | ||
707 | } | ||
708 | else if (stat("/var/lib/network/nfsaddr", &path_stat) == 0) | ||
709 | { | ||
710 | bb_printf("\nDownloading configuration from network.\n"); | ||
711 | doit(QUIET, "tftp -gr /tftpboot/bootrc -l /bootrc %s", quick_read("/var/lib/network/nfsaddr")); | ||
712 | } | ||
713 | } | ||
714 | else | ||
715 | { | ||
716 | bb_xasprintf(&BOOT, "%s%s", device, image); | ||
717 | if (is_boot_device(device, image, &BOOTFS)) | ||
718 | BOOT=device; | ||
719 | } | ||
720 | } | ||
721 | |||
722 | if (BOOTFS == NULL) | ||
723 | BOOTFS = "Unknown"; | ||
724 | |||
725 | if (stat("/boot/bootrc", &path_stat) == 0) | ||
726 | { | ||
727 | bb_printf("Copying configuration from boot filesystem.\n"); | ||
728 | copy_file("/boot/bootrc", "/bootrc", FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS); | ||
729 | doit(QUIET, "umount /boot"); | ||
730 | } | ||
731 | } | ||
732 | else | ||
733 | { | ||
734 | BOOT = ""; | ||
735 | BOOTFS = ""; | ||
736 | } | ||
737 | |||
738 | read_bootrc(); | ||
739 | |||
740 | ROOT = getenv("ROOT"); | ||
741 | if (ROOT == 0) | ||
742 | { | ||
743 | if (strncmp(BOOT, "/dev/", 5) == 0) | ||
744 | { | ||
745 | bb_xasprintf(&ROOT, "%s", BOOT); | ||
746 | for (i = 5; ROOT[i] != '\0'; i++) | ||
747 | { | ||
748 | if (ROOT[i] == '/') | ||
749 | { | ||
750 | ROOT[i] = '\0'; | ||
751 | ROOT_TYPE = BOOTFS; | ||
752 | break; | ||
753 | } | ||
754 | } | ||
755 | } | ||
756 | } | ||
757 | |||
758 | /* | ||
759 | #VERSION=`cat /boot/version 2> /dev/null` | ||
760 | #PS1="My Linux $VERSION> " | ||
761 | */ | ||
762 | |||
763 | bb_printf("================================\n"); | ||
764 | bb_printf("Kernel: %s %s\n", name.release, TMPFS ? "- tmpfs capable" : ""); | ||
765 | bb_printf("RAM: %li MB %s\n", MEMORY / 1024, (MEMORY < (16 * 1024)) ? "< 16 MB, you may run into problems" : "" ); | ||
766 | bb_printf("Boot: %s - %s\n", BOOT, BOOTFS); | ||
767 | bb_printf("Root: %s - %s\n", ROOT, root_write ? "read/write" : "read only"); | ||
768 | bb_printf("================================\n"); | ||
769 | |||
770 | /* | ||
771 | ROOT=/dev/hda6 | ||
772 | ROOT=nfs://REAL/MDS/TEST | ||
773 | */ | ||
774 | if (ROOT == 0) | ||
775 | { | ||
776 | ; | ||
777 | } | ||
778 | else | ||
779 | { | ||
780 | if (strncmp(ROOT, "/dev/", 5) == 0) | ||
781 | { | ||
782 | // PKGSRC=BOOT; | ||
783 | // Should fsck this partition first. | ||
784 | bb_printf("Mounting %s \n on %s as type %s\n", ROOT, ROOT_MOUNT, ROOT_TYPE); | ||
785 | make_disk(&ROOT[5], nodes); | ||
786 | quick_mount(ROOT_TYPE, ROOT, ROOT_MOUNT, root_write ? "-o rw" : "-o ro"); | ||
787 | } | ||
788 | else if (strncmp(ROOT, "nfs://", 5) == 0) | ||
789 | { | ||
790 | doit(0, "rc network start"); | ||
791 | if (stat("/var/lib/network/ipaddr", &path_stat) == 0) | ||
792 | NFSADDR = quick_read("/var/lib/network/nfsaddr"); | ||
793 | if ((NFSADDR != 0) && (NFSADDR[0] != '\0')) | ||
794 | { | ||
795 | char *NFSMOUNT = 0; | ||
796 | |||
797 | ROOT_TYPE = "nfs"; | ||
798 | if (NFSMOUNT == 0) | ||
799 | bb_xasprintf(&NFSMOUNT, "%s:%s", NFSADDR, &ROOT[5]); | ||
800 | bb_printf("Mounting %s \n on %s as type %s\n", NFSMOUNT, ROOT_MOUNT, ROOT_TYPE); | ||
801 | quick_mount(ROOT_TYPE, NFSMOUNT, ROOT_MOUNT, root_write ? "-o nolock,rw" : "-o nolock,ro"); | ||
802 | |||
803 | free(NFSMOUNT); | ||
804 | } | ||
805 | free(NFSADDR); | ||
806 | } | ||
807 | } | ||
808 | |||
809 | if (root_write) | ||
810 | copy_file("/bin/busybox", "/media/ROOT/bin/busybox", FILEUTILS_FORCE | FILEUTILS_PRESERVE_STATUS); | ||
811 | |||
812 | if (!rebuild_fs(ROOT_MOUNT)) | ||
813 | { | ||
814 | // make_ram_disk(USR, 3, "/usr", TMPFS); | ||
815 | // doit(0, "getpkg"); | ||
816 | } | ||
817 | else | ||
818 | { | ||
819 | read_bootrc(); | ||
820 | } | ||
821 | |||
822 | doit(0, "/sbin/ldconfig"); | ||
823 | |||
824 | free(CMDLINE); | ||
825 | |||
826 | execl("/sbin/init", "/sbin/init"); | ||
827 | return EXIT_FAILURE; | ||
828 | } | ||
829 | |||