mirror of the now-defunct rocklinux.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

576 lines
14 KiB

/*
* --- ROCK-COPYRIGHT-NOTE-BEGIN ---
*
* This copyright note is auto-generated by ./scripts/Create-CopyPatch.
* Please add additional copyright information _after_ the line containing
* the ROCK-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
* the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
*
* ROCK Linux: rock-src/target/bootdisk/linuxrc.c
* ROCK Linux is Copyright (C) 1998 - 2003 Clifford Wolf
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. A copy of the GNU General Public
* License can be found at Documentation/COPYING.
*
* Many people helped and are helping developing ROCK Linux. Please
* have a look at http://www.rocklinux.org/ and the Documentation/TEAM
* file for details.
*
* --- ROCK-COPYRIGHT-NOTE-END ---
*
* linuxrc.c is Copyright (C) 2003 Cliford Wolf and Rene Rebe
*
*/
#include <sys/mount.h>
#include <sys/swap.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/klog.h>
#include <fcntl.h>
#include <errno.h>
#ifndef STAGE_2_BIG_IMAGE
# define STAGE_2_BIG_IMAGE "2nd_stage.tar.gz"
#endif
#ifndef STAGE_2_SMALL_IMAGE
# define STAGE_2_SMALL_IMAGE "2nd_stage_small.tar.gz"
#endif
/* 64 MB should be enought for the tmpfs */
#define TMPFS_OPTIONS "size=67108864"
/* It seams like we need this prototype here ... */
int pivot_root(const char *new_root, const char *put_old);
int exit_linuxrc=0;
void doboot()
{
if ( mkdir("/mnt_root/old_root", 700) )
{ perror("Can't create /mnt_root/old_root"); exit_linuxrc=0; }
if ( access("/mnt_root/linuxrc", R_OK) )
{ printf("Can't find /mnt_root/linuxrc!\n"); exit_linuxrc=0; }
if ( mount("/bin", "/mnt_root/usr/local/bin", NULL, MS_BIND, NULL) ) {
perror("Can't mount /mnt_root/usr/local/bin");
if (access("/mnt_root/bin/gzip", R_OK)) {
perror("Can't find /mnt_root/bin/gzip");
exit_linuxrc=0;
}
}
if ( exit_linuxrc ) {
if ( pivot_root("/mnt_root", "/mnt_root/old_root") )
{ perror("Can't call pivot_root"); exit_linuxrc=0; }
chdir("/");
if ( mount("none", "/dev", "devfs", 0, NULL) )
perror("Can't mount /dev");
if ( mount("none", "/proc", "proc", 0, NULL) )
perror("Can't mount /proc");
} else {
if ( rmdir("/mnt_root/old_root") )
perror("Can't remove /mnt_root/old_root");
if ( umount("/mnt_root") ) perror("Can't umount /mnt_root");
if ( rmdir ("/mnt_root") ) perror("Can't remove /mnt_root");
}
}
int trymount (const char* source, const char* target)
{
return mount(source, "/mnt_source", "ext3", MS_RDONLY, NULL) &&
mount(source, target, "ext2", MS_RDONLY, NULL) &&
mount(source, target, "minix", MS_RDONLY, NULL) &&
mount(source, target, "vfat", MS_RDONLY, NULL) &&
mount(source, target, "iso9660", MS_RDONLY, NULL);
}
void httpload()
{
int fd[2];
char baseurl[200];
char filename[100];
char url[500];
printf("Enter base URL (e.g. http://1.2.3.4/rock): ");
fflush(stdout);
baseurl[0]=0; fgets(baseurl, 200, stdin); baseurl[199]=0;
if (strlen(baseurl) > 0) baseurl[strlen(baseurl)-1]=0;
if (baseurl[0] == 0) return;
printf("Select a stage 2 image file:\n\n"
" 1. %s\n 2. %s\n\n"
"Enter number or image file name (default=1): ",
STAGE_2_BIG_IMAGE, STAGE_2_SMALL_IMAGE);
filename[0]=0; fgets(filename, 100, stdin); filename[99]=0;
if (strlen(filename) > 0) filename[strlen(filename)-1]=0;
if (filename[0] == 0) strcpy(filename, STAGE_2_BIG_IMAGE);
else if (!strcmp(filename, "1")) strcpy(filename, STAGE_2_BIG_IMAGE);
else if (!strcmp(filename, "2")) strcpy(filename, STAGE_2_SMALL_IMAGE);
exit_linuxrc=1;
snprintf(url, 500, "%s/%s", baseurl, filename);
printf("[ %s ]\n", url);
setenv("ROCK_INSTALL_SOURCE_URL", baseurl, 1);
exit_linuxrc=1;
if ( mkdir("/mnt_root", 700) )
{ perror("Can't create /mnt_root"); exit_linuxrc=0; }
if ( mount("none", "/mnt_root", "tmpfs", 0, TMPFS_OPTIONS) )
{ perror("Can't mount /mnt_root"); exit_linuxrc=0; }
if ( pipe(fd) < 0 )
{ perror("Can't create pipe"); exit_linuxrc=0; }
if ( fork() == 0 ) {
dup2(fd[1],1); close(fd[0]); close(fd[1]);
execlp("wget", "wget", "-O", "-", url, NULL);
perror("wget");
_exit(1);
}
if ( fork() == 0 ) {
dup2(fd[0],0); close(fd[0]); close(fd[1]);
execlp("tar", "tar", "--use-compress-program=gzip",
"-C", "/mnt_root", "-xf", "-", NULL);
perror("tar");
_exit(1);
}
close(fd[0]); close(fd[1]);
wait(NULL); wait(NULL);
printf("finished ... now booting 2nd stage\n");
doboot();
}
void load_modules(char * dir)
{
struct dirent **namelist;
char text[100], filename[200];
char *execargs[100];
int n, m=0, len;
n = scandir(dir, &namelist, 0, alphasort);
if (n > 0) {
printf("List of available modules:\n\n ");
while(n--) {
strcpy(filename, namelist[n]->d_name);
free(namelist[n]); len = strlen(filename);
if (len > 2 && !strcmp(filename+len-2, ".o")) {
filename[len-2]=0;
printf("%-15s", filename);
if (++m % 4 == 0) printf("\n ");
}
}
if (m % 4 != 0) printf("\n");
printf("\n");
free(namelist);
} else {
printf("No modules found!\n");
if (n == 0) free(namelist);
return;
}
printf("Enter module name (and optional parameters): ");
fflush(stdout);
while (1) {
text[0]=0; fgets(text, 100, stdin); text[99]=0;
if (strlen(text) > 0) text[strlen(text)-1]=0;
if (text[0] == 0) return;
snprintf(filename, 200, "%s/%s.o", dir, strtok(text, " "));
execargs[0] = "insmod"; execargs[1] = "-v";
execargs[2] = "-f"; execargs[3] = filename;
for (n=4; (execargs[n] = strtok(NULL, " ")) != NULL; n++) ;
if ( ! access(filename, R_OK) ) break;
printf("No such module found. Try again (enter=back): ");
fflush(stdout);
}
if ( fork() == 0 ) {
execvp(execargs[0], execargs);
printf("Can't start %s!\n", execargs[0]);
exit(1);
}
wait(NULL);
return;
}
void load_ramdisk_file()
{
char *devn[10], *desc[10];
char text[100], devicefile[100];
char filename[100];
int nr=0;
int tmp_nr;
int found;
printf("Select a device for loading the 2nd stage system from: \n\n");
for (tmp_nr = 0, found = 1; found; ++tmp_nr) {
sprintf(devicefile, "/dev/cdroms/cdrom%d", tmp_nr);
sprintf(text, "CD-ROM #%d (IDE/ATAPI or SCSI)", tmp_nr+1);
if ( ! access (devicefile, R_OK) ) {
desc[nr] = strdup (text);
devn[nr++] = strdup (devicefile);
}
else {
found = 0;
}
}
tmp_nr = 0; found = 1;
for (tmp_nr = 0, found = 1; found; ++tmp_nr) {
sprintf(devicefile, "/dev/floppy/%d", tmp_nr);
sprintf(text, "FDD (Floppy Disk Drive) #%d", tmp_nr+1);
if ( ! access (devicefile, R_OK) ) {
desc[nr] = strdup (text);
devn[nr++] = strdup (devicefile);
}
else {
found = 0;
}
}
desc[nr] = devn[nr] = NULL;
for (nr=0; desc[nr]; nr++) {
printf(" %d. %s\n", nr, desc[nr]);
}
printf("\nEnter number or device file name (default=0): ");
fflush(stdout);
while (1) {
text[0]=0; fgets(text, 100, stdin); text[99]=0;
if (strlen(text) > 0)
text[strlen(text)-1]=0;
if (text[0] == 0)
strcpy (text, "0");
if ( ! access(text, R_OK) ) {
strcpy(devicefile, text);
break;
}
if (atoi(text) >= 0 && atoi(text) < nr) {
strcpy(devicefile, devn[atoi(text)]);
break;
}
printf("No such device found. Try again (enter=back): ");
fflush(stdout);
}
printf("Select a stage 2 image file:\n\n"
" 1. %s\n 2. %s\n\n"
"Enter number or image file name (default=1): ",
STAGE_2_BIG_IMAGE, STAGE_2_SMALL_IMAGE);
text[0]=0; fgets(text, 100, stdin); text[99]=0;
if (strlen(text) > 0) text[strlen(text)-1]=0;
if (text[0] == 0) strcpy(filename, STAGE_2_BIG_IMAGE);
else if (! strcmp(text, "1")) strcpy(filename, STAGE_2_BIG_IMAGE);
else if (! strcmp(text, "2")) strcpy(filename, STAGE_2_SMALL_IMAGE);
else strcpy(filename, text);
exit_linuxrc=1;
printf("Using %s:%s.\n", devicefile, filename);
if ( mkdir("/mnt_source", 700) )
{ perror("Can't create /mnt_source"); exit_linuxrc=0; }
if ( trymount (devicefile, "/mnt_source") )
{ perror("Can't mount /mnt_source"); exit_linuxrc=0; }
if ( mkdir("/mnt_root", 700) )
{ perror("Can't create /mnt_root"); exit_linuxrc=0; }
if ( mount("none", "/mnt_root", "tmpfs", 0, TMPFS_OPTIONS) )
{ perror("Can't mount /mnt_root"); exit_linuxrc=0; }
if ( fork() == 0 ) {
printf("Extracting 2nd stage filesystem to ram ...\n");
snprintf(text, 100, "/mnt_source/%s", filename);
execlp( "tar", "tar", "--use-compress-program=gzip",
"-C", "/mnt_root", "-xf", text, NULL);
printf("Can't run tar on %s!\n", filename);
exit(1);
}
wait(NULL);
if ( umount("/mnt_source") )
{ perror("Can't umount /mnt_source"); exit_linuxrc=0; }
if ( rmdir("/mnt_source") )
{ perror("Can't remove /mnt_source"); exit_linuxrc=0; }
setenv("ROCK_INSTALL_SOURCE_DEV", devicefile, 1);
setenv("ROCK_INSTALL_SOURCE_FILE", filename, 1);
doboot();
}
void activate_swap()
{
char text[100];
printf("\nEnter file name of swap device: ");
fflush(stdout);
text[0]=0; fgets(text, 100, stdin); text[99]=0;
if ( text[0] ) {
if ( swapon(text, 0) < 0 )
perror("Can't activate swap device");
}
}
void config_net()
{
char dv[100]="";
char ip[100]="";
char gw[100]="";
if ( fork() == 0 ) {
execlp("ip", "ip", "addr", NULL);
perror("ip");
exit(1);
}
wait(NULL);
printf("\n");
if ( fork() == 0 ) {
execlp("ip", "ip", "route", NULL);
perror("ip");
exit(1);
}
wait(NULL);
printf("\n");
printf("Enter interface name (eth0): ");
fflush(stdout); fgets(dv, 100, stdin); dv[99]=0;
if (strlen(dv) > 0) dv[strlen(dv)-1]=0;
if (dv[0] == 0) strcpy(dv, "eth0");
printf("Enter ip (192.168.0.254/24): ");
fflush(stdout); fgets(ip, 100, stdin); ip[99]=0;
if (strlen(ip) > 0) ip[strlen(ip)-1]=0;
if (ip[0] == 0) strcpy(ip, "192.168.0.254/24");
if ( fork() == 0 ) {
execlp("ip", "ip", "addr", "add", ip, "dev", dv, NULL);
perror("ip");
exit(1);
}
wait(NULL);
if ( fork() == 0 ) {
execlp("ip", "ip", "link", "set", dv, "up", NULL);
perror("ip");
exit(1);
}
wait(NULL);
printf("Enter default gateway (none): ");
fflush(stdout); fgets(gw, 100, stdin); gw[99]=0;
if (strlen(gw) > 0) gw[strlen(gw)-1]=0;
if (gw[0] != 0) {
if ( fork() == 0 ) {
execlp("ip", "ip", "route", "add",
"default", "via", gw, NULL);
perror("ip");
exit(1);
}
wait(NULL);
}
printf("\n");
if ( fork() == 0 ) {
execlp("ip", "ip", "addr", NULL);
perror("ip");
exit(1);
}
wait(NULL);
printf("\n");
if ( fork() == 0 ) {
execlp("ip", "ip", "route", NULL);
perror("ip");
exit(1);
}
wait(NULL);
}
void autoload_modules()
{
char line[200], cmd[200], module[200];
int fd[2], rc;
FILE *f;
if (pipe(fd) <0)
{ perror("Can't create pipe"); return; }
if ( fork() == 0 ) {
dup2(fd[1],1); close(fd[0]); close(fd[1]);
execlp("gawk", "gawk", "-f", "/bin/hwscan", NULL);
printf("Can't start >>hwscan<< program with gawk!\n");
exit(1);
}
close(fd[1]);
f = fdopen(fd[0], "r");
while ( fgets(line, 200, f) != NULL ) {
if ( sscanf(line, "%s %s", cmd, module) < 2 ) continue;
if ( !strcmp(cmd, "modprobe") || !strcmp(cmd, "insmod") ) {
printf("%s %s\n", cmd, module);
if ( (rc = fork()) == 0 ) {
execlp(cmd, cmd, module, NULL);
perror("Cant run modprobe/insmod");
exit(1);
}
waitpid(rc, NULL, 0);
}
}
fclose(f);
wait(NULL);
}
void exec_sh()
{
printf ("Quit the shell to return to the stage 1 loader!\n");
if ( fork() == 0 ) {
execl("/bin/kiss", "kiss", NULL);
perror("kiss");
_exit(1);
}
wait(NULL);
}
int main()
{
char text[100];
int input=1;
if ( mount("none", "/dev", "devfs", 0, NULL) && errno != EBUSY )
perror("Can't mount /dev");
if ( mount("none", "/proc", "proc", 0, NULL) )
perror("Can't mount /proc");
/* Only print important stuff to console */
klogctl(8, NULL, 3);
autoload_modules();
printf("\n\
============================================\n\
=== ROCK Linux 1st stage boot system ===\n\
============================================\n\
\n\
The ROCK Linux install / rescue system boots up in two stages. You\n\
are now in the first of this two stages and if everything goes right\n\
you will not spend much time here. Just load your SCSI and networking\n\
drivers (if needed) and configure the installation source so the\n\
2nd stage boot system can be loaded and you can start the installation.\n");
while (exit_linuxrc == 0)
{
printf("\n\
0. Load 2nd stage system from local device\n\
1. Load 2nd stage system from network\n\
2. Configure network interfaces (IPv4 only)\n\
3. Load kernel networking modules from this disk\n\
4. Load kernel SCSI modules from this disk\n\
5. Load kernel modules from another disk\n\
6. Activate already formatted swap device\n\
7. Execute a (kiss) shell if present (for experts!)\n\
\n\
What do you want to do [0-7] (default=0)? ");
fflush(stdout);
text[0]=0; fgets(text, 100, stdin); text[99]=0;
if (strlen(text) > 0)
text[strlen(text)-1]=0;
input=atoi(text);
switch (input) {
case 0:
load_ramdisk_file();
break;
case 1:
httpload();
break;
case 2:
config_net();
break;
case 3:
load_modules("/lib/modules/net");
break;
case 4:
load_modules("/lib/modules/scsi");
break;
case 5:
if ( mkdir("/mnt_floppy", 700) )
perror("Can't create /mnt_floppy");
if ( trymount("/dev/floppy/0", "/mnt_floppy") )
load_modules("/mnt_floppy");
if ( umount("/mnt_floppy") )
perror("Can't umount /mnt_floppy");
if ( rmdir("/mnt_floppy") )
perror("Can't remove /mnt_floppy");
break;
case 6:
activate_swap();
break;
case 7:
exec_sh();
break;
default:
perror ("No such option present!");
}
}
sleep(1);
execl("/linuxrc", "/linuxrc", NULL);
printf("\nCan't start /linuxrc!! Life sucks.\n\n");
return 0;
}