summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/stage1.c
diff options
context:
space:
mode:
Diffstat (limited to 'mdk-stage1/stage1.c')
-rw-r--r--mdk-stage1/stage1.c338
1 files changed, 193 insertions, 145 deletions
diff --git a/mdk-stage1/stage1.c b/mdk-stage1/stage1.c
index 2faa35256..94bb1e0df 100644
--- a/mdk-stage1/stage1.c
+++ b/mdk-stage1/stage1.c
@@ -1,9 +1,7 @@
/*
- * Guillaume Cottenceau (gc@mandrakesoft.com)
+ * Guillaume Cottenceau (gc)
*
- * Copyright 2000 MandrakeSoft
- *
- * View the homepage: http://us.mandrakesoft.com/~gc/html/stage1.html
+ * Copyright 2000-2004 Mandriva
*
*
* This software may be freely redistributed under the terms of the GNU
@@ -22,19 +20,21 @@
*
*/
-#include <sys/mount.h>
+#include <stdlib.h>
+#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <signal.h>
-
-#include <stdlib.h>
#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <linux/unistd.h>
+#include <libldetect.h>
#include "stage1.h"
@@ -43,9 +43,10 @@
#include "frontend.h"
#include "modules.h"
#include "tools.h"
+#include "utils.h"
#include "automatic.h"
#include "mount.h"
-#include "insmod.h"
+#include "thirdparty.h"
#ifdef ENABLE_PCMCIA
#include "pcmcia/pcmcia.h"
@@ -64,9 +65,9 @@
#endif
-/* globals */
+/************************************************************
+ * globals */
-char * method_name;
void fatal_error(char *msg)
@@ -76,12 +77,51 @@ void fatal_error(char *msg)
}
-/* spawns a shell on console #2 */
-static void spawn_shell(void)
+/************************************************************
+ * special frontend functs
+ * (the principle is to not pollute frontend code with stage1-specific stuff) */
+
+void stg1_error_message(char *msg, ...)
{
+ va_list args;
+ va_start(args, msg);
+ unset_automatic();
+ verror_message(msg, args);
+ va_end(args);
+}
+
+void stg1_fatal_message(char *msg, ...)
+{
+ va_list args;
+ va_start(args, msg);
+ unset_automatic();
+ verror_message(msg, args);
+ va_end(args);
+ exit(1);
+}
+
+void stg1_info_message(char *msg, ...)
+{
+ va_list args;
+ va_start(args, msg);
+ if (IS_AUTOMATIC) {
+ vlog_message(msg, args);
+ return;
+ }
+ vinfo_message(msg, args);
+ va_end(args);
+}
+
+
#ifdef SPAWN_SHELL
+static pid_t shell_pid = 0;
+
+/************************************************************
+ * spawns a shell on console #2 */
+static void spawn_shell(void)
+{
int fd;
- char * shell_name = "/sbin/sash";
+ char * shell_name[] = { "/bin/sh", NULL };
log_message("spawning a shell");
@@ -91,12 +131,12 @@ static void spawn_shell(void)
log_message("cannot open /dev/tty2 -- no shell will be provided");
return;
}
- else if (access(shell_name, X_OK)) {
- log_message("cannot open shell - %s doesn't exist", shell_name);
+ else if (access(shell_name[0], X_OK)) {
+ log_message("cannot open shell - %s doesn't exist", shell_name[0]);
return;
}
- if (!fork()) {
+ if (!(shell_pid = fork())) {
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
@@ -106,23 +146,23 @@ static void spawn_shell(void)
if (ioctl(0, TIOCSCTTY, NULL))
log_perror("could not set new controlling tty");
- execl(shell_name, shell_name, NULL);
- log_message("execl of %s failed: %s", shell_name, strerror(errno));
+ execv(shell_name[0], shell_name);
+ log_message("execve of %s failed: %s", shell_name[0], strerror(errno));
+ exit(-1);
}
close(fd);
}
-#endif
}
+#endif
-
+#ifdef SPAWN_INTERACTIVE
char * interactive_fifo = "/tmp/stage1-fifo";
static pid_t interactive_pid = 0;
/* spawns my small interactive on console #6 */
static void spawn_interactive(void)
{
-#ifdef SPAWN_INTERACTIVE
int fd;
char * dev = "/dev/tty6";
@@ -153,7 +193,7 @@ static void spawn_interactive(void)
perror("could not set new controlling tty");
fif_out = open(interactive_fifo, O_WRONLY);
- printf("Please enter your command (availables: [+,-] [rescue,expert]).\n");
+ printf("Please enter your command (availables: [+,-] [rescue]).\n");
while (1) {
char s[50];
@@ -171,87 +211,53 @@ static void spawn_interactive(void)
close(fd);
}
-#endif
}
+#endif
-static void expert_third_party_modules(void)
+#ifdef ENABLE_PCMCIA
+static void handle_pcmcia(void)
{
- enum return_type results;
- char * floppy_mount_location = "/tmp/floppy";
- char ** modules;
- char final_name[500] = "/tmp/floppy/";
- char * choice;
- int rc;
- char * questions[] = { "Options", NULL };
- static char ** answers = NULL;
-
- results = ask_yes_no("If you want to insert third-party kernel modules, insert "
- "a Linux (ext2fs) formatted floppy containing the modules and confirm. Otherwise, select \"no\".");;
- if (results != RETURN_OK)
- return;
-
- my_insmod("floppy", ANY_DRIVER_TYPE, NULL);
+ char * pcmcia_adapter;
- if (my_mount("/dev/fd0", floppy_mount_location, "ext2") == -1) {
- error_message("I can't find a Linux ext2 floppy in first floppy drive.");
- return expert_third_party_modules();
- }
-
- modules = list_directory(floppy_mount_location);
-
- if (!modules || !*modules) {
- error_message("No modules found on floppy disk.");
- umount(floppy_mount_location);
- return expert_third_party_modules();
- }
-
- results = ask_from_list("Which driver would you like to insmod?", modules, &choice);
- if (results != RETURN_OK) {
- umount(floppy_mount_location);
+ pcmcia_adapter = pcmcia_probe();
+ if (!pcmcia_adapter) {
+ log_message("no pcmcia adapter found");
return;
}
+ my_modprobe("pcmcia_core", ANY_DRIVER_TYPE, NULL);
+ my_modprobe(pcmcia_adapter, ANY_DRIVER_TYPE, NULL);
+ /* ds is an alias for pcmcia in recent 2.6 kernels
+ but we don't have modules.alias in install, so try to load both */
+ my_modprobe("ds", ANY_DRIVER_TYPE, NULL);
+ my_modprobe("pcmcia", ANY_DRIVER_TYPE, NULL);
+
+ /* setup a dynamic resource database for non statically mapped PCMCIA sockets */
+ pcmcia_socket_startup(-1);
- strcat(final_name, choice);
-
- results = ask_from_entries("Please enter the options:", questions, &answers, 24, NULL);
- if (results != RETURN_OK) {
- umount(floppy_mount_location);
- return expert_third_party_modules();
- }
+ add_to_env("PCMCIA", pcmcia_adapter);
+}
+#endif
- rc = insmod_call(final_name, answers[0]);
- umount(floppy_mount_location);
+#ifndef ENABLE_NETWORK_STANDALONE
+static void handle_hid(void)
+{
+ struct hid_entries entry_list;
+ unsigned int i;
- if (rc) {
- log_message("\tfailed");
- error_message("Insmod failed.");
+ entry_list = hid_probe();
+ for (i = 0; i < entry_list.nb; i++) {
+ if (entry_list.entries[i].module != NULL)
+ my_modprobe(entry_list.entries[i].module, ANY_DRIVER_TYPE, NULL);
}
-
- return expert_third_party_modules();
+ my_modprobe("hid_generic", ANY_DRIVER_TYPE, NULL);
}
-static void handle_pcmcia(char ** pcmcia_adapter)
-{
-#ifdef ENABLE_PCMCIA
- *pcmcia_adapter = pcmcia_probe();
- if (!*pcmcia_adapter) {
- log_message("no pcmcia adapter found");
- return;
- }
- my_insmod("pcmcia_core", ANY_DRIVER_TYPE, NULL);
- my_insmod(*pcmcia_adapter, ANY_DRIVER_TYPE, NULL);
- my_insmod("ds", ANY_DRIVER_TYPE, NULL);
-
- /* call to cardmgr takes time, let's use the wait message */
- wait_message("Enabling PCMCIA extension cards...");
- log_message("cardmgr rc: %d", cardmgr_call());
- remove_wait_message();
-#endif
-}
+/************************************************************
+ */
-static enum return_type method_select_and_prepare(void)
+static void method_select_and_prepare(void)
{
enum return_type results;
char * choice;
@@ -268,13 +274,20 @@ static enum return_type method_select_and_prepare(void)
char * network_nfs_install = "NFS server"; char * network_nfs_install_auto = "nfs";
char * network_ftp_install = "FTP server"; char * network_ftp_install_auto = "ftp";
char * network_http_install = "HTTP server"; char * network_http_install_auto = "http";
+#ifndef DISABLE_KA
+ char * network_ka_install = "KA server"; char * network_ka_install_auto = "ka";
#endif
+#endif
+ char * thirdparty_install = "Load third party modules"; char * thirdparty_install_auto = "thirdparty";
i = 0;
#ifndef DISABLE_NETWORK
means[i] = network_nfs_install; means_auto[i++] = network_nfs_install_auto;
means[i] = network_ftp_install; means_auto[i++] = network_ftp_install_auto;
means[i] = network_http_install; means_auto[i++] = network_http_install_auto;
+#ifndef DISABLE_KA
+ means[i] = network_ka_install; means_auto[i++] = network_ka_install_auto;
+#endif
#endif
#ifndef DISABLE_CDROM
means[i] = cdrom_install; means_auto[i++] = cdrom_install_auto;
@@ -282,14 +295,15 @@ static enum return_type method_select_and_prepare(void)
#ifndef DISABLE_DISK
means[i] = disk_install; means_auto[i++] = disk_install_auto;
#endif
+ means[i] = thirdparty_install; means_auto[i++] = thirdparty_install_auto;
means[i] = NULL;
- results = ask_from_list_auto("Please choose the mean of installation.", means, &choice, "method", means_auto);
+ unlink(IMAGE_LOCATION);
- if (results != RETURN_OK)
- return method_select_and_prepare();
+ results = ask_from_list_auto("Please choose the installation method.", means, &choice, "method", means_auto);
- results = RETURN_ERROR;
+ if (results != RETURN_OK)
+ return method_select_and_prepare();
#ifndef DISABLE_CDROM
if (!strcmp(choice, cdrom_install))
@@ -304,92 +318,126 @@ static enum return_type method_select_and_prepare(void)
#ifndef DISABLE_NETWORK
if (!strcmp(choice, network_nfs_install))
results = nfs_prepare();
-
+
if (!strcmp(choice, network_ftp_install))
results = ftp_prepare();
if (!strcmp(choice, network_http_install))
results = http_prepare();
+
+#ifndef DISABLE_KA
+ if (!strcmp(choice, network_ka_install))
+ results = ka_prepare();
+#endif
#endif
+ if (!strcmp(choice, thirdparty_install)) {
+ thirdparty_load_modules();
+ return method_select_and_prepare();
+ }
+
if (results != RETURN_OK)
return method_select_and_prepare();
- return RETURN_OK;
+ /* try to find third party modules on the install media */
+ thirdparty_load_media_modules();
}
+#endif
+void finish_preparing(void)
+{
+#ifdef SPAWN_SHELL
+ if (shell_pid != 0) {
+ int fd;
+ const char *clear = "\033[H\033[J";
+ kill(shell_pid, 9);
+ log_message("killed shell");
+ fd = open("/dev/tty2", O_RDWR);
+ write(fd, clear, strlen(clear));
+ close(fd);
+ }
+#endif
+}
-int main(int argc, char **argv, char **env)
+int main(int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)), char **env)
{
- enum return_type ret;
- char ** argptr;
- char * stage2_args[30];
- char * pcmcia_adapter = NULL;
+#ifdef ENABLE_NETWORK_STANDALONE
+ open_log();
+ init_frontend("");
+
+ unlink("/etc/resolv.conf"); /* otherwise it is read-only */
+ set_param(MODE_AUTOMATIC);
+ grab_automatic_params("network:dhcp");
- if (getpid() > 50)
+ intf_select_and_up();
+ finish_frontend();
+ return 0;
+#else
+ if (getenv("DEBUGSTAGE1")) {
+ set_param(MODE_DEBUGSTAGE1);
set_param(MODE_TESTING);
+ }
+#ifdef SPAWN_INTERACTIVE
spawn_interactive();
+#endif
open_log();
- log_message("welcome to the " DISTRIB_NAME " install (stage1, version " VERSION " built " __DATE__ " " __TIME__")");
+ log_message("welcome to the " DISTRIB_NAME " install (mdk-stage1, version " DISTRIB_VERSION " built " __DATE__ " " __TIME__")");
process_cmdline();
- handle_env(env);
+#ifdef SPAWN_SHELL
spawn_shell();
+#endif
init_modules_insmoding();
- init_frontend();
+ init_frontend("Welcome to " DISTRIB_DESCR ", " __DATE__ " " __TIME__);
- if (IS_EXPERT)
- expert_third_party_modules();
+ probe_that_type(VIRTIO_DEVICES, BUS_ANY);
- handle_pcmcia(&pcmcia_adapter);
+ /* load usb interface as soon as possible, helps usb mouse detection in stage2 */
+ probe_that_type(USB_CONTROLLERS, BUS_USB);
- ret = method_select_and_prepare();
+ if (IS_THIRDPARTY)
+ thirdparty_load_modules();
- finish_frontend();
- close_log();
+#ifdef ENABLE_PCMCIA
+ if (!IS_NOAUTO)
+ handle_pcmcia();
+#endif
+
+ handle_hid();
- if (ret != RETURN_OK)
- fatal_error("could not select an installation method");
+ if (IS_CHANGEDISK)
+ stg1_info_message("You are starting the installation with an alternate booting method. "
+ "Please change your disk, and insert the Installation disk.");
- if (!IS_RAMDISK) {
- if (symlink(IMAGE_LOCATION LIVE_LOCATION, STAGE2_LOCATION) != 0) {
- printf("symlink from " IMAGE_LOCATION LIVE_LOCATION " to " STAGE2_LOCATION " failed");
- fatal_error(strerror(errno));
- }
+ if (IS_RESCUE && total_memory() < MEM_LIMIT_RESCUE) {
+ stg1_error_message("You are starting the rescue with a low memory configuration. "
+ "Our experience shows that your system may crash at any point "
+ "or lock up for no apparent reason. Continue at "
+ "your own risk. Alternatively, you may reboot your system now.");
}
+ method_select_and_prepare();
+
+ thirdparty_destroy();
+
+ if (access(STAGE2_LOCATION, R_OK) != 0)
+ if (symlink(IMAGE_LOCATION_REL "/" LIVE_LOCATION_REL, STAGE2_LOCATION) != 0)
+ log_perror("symlink from " IMAGE_LOCATION_REL "/" LIVE_LOCATION_REL " to " STAGE2_LOCATION " failed");
+
+#ifdef SPAWN_INTERACTIVE
if (interactive_pid != 0)
kill(interactive_pid, 9);
-
- if (IS_RESCUE) {
- int fd = open("/proc/sys/kernel/real-root-dev", O_RDWR);
-#if defined(__powerpc__) || defined (__sparc__)
- write(fd, "0x1030000", sizeof("0x1030000")); /* ram3 or sparc */
-#else
- write(fd, "0x103", sizeof("0x103")); /* ram3 */
#endif
- close(fd);
- return 66;
- }
- if (IS_TESTING)
- return 0;
+ finish_preparing();
- argptr = stage2_args;
- *argptr++ = "/usr/bin/runinstall2";
- *argptr++ = "--method";
- *argptr++ = method_name;
- if (pcmcia_adapter) {
- *argptr++ = "--pcmcia";
- *argptr++ = pcmcia_adapter;
- }
- *argptr++ = NULL;
+ finish_frontend();
+ close_log();
- execve(stage2_args[0], stage2_args, grab_env());
+ if (IS_RESCUE)
+ return 66; /* ask init to exec new init */
- printf("error in exec of stage2 :-(\n");
- fatal_error(strerror(errno));
-
- return 0; /* shut up compiler (we can't get here anyway!) */
+ return 0;
+#endif
}