/* * Guillaume Cottenceau (gc@mandrakesoft.com) * * Copyright 2000 MandrakeSoft * * This software may be freely redistributed under the terms of the GNU * public license. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * Portions from Erik Troan (ewt@redhat.com) * * Copyright 1996 Red Hat Software * */ #include #include #include #include #include #include #include #include #include "stage1.h" #include "frontend.h" #include "modules.h" #include "probing.h" #include "log.h" #include "mount.h" #include "cdrom.h" #include "init.h" extern char *udevtrigger_add[]; extern char version[]; static int mount_iso9660(char * dev_name) { return my_mount(dev_name, IMAGE_LOCATION, "iso9660", 0); } static int mount_that_cd_device(char * dev_name) { char device_fullname[64] = "/dev/"; strcat(device_fullname, dev_name); char * p = device_fullname + strlen(device_fullname); if (islower(p[-1])) { int ret; p[0] = '1'; p[1] = '\0'; ret = mount_iso9660(device_fullname); if (ret != -1) return ret; p[0] = '\0'; } return mount_iso9660(device_fullname); } /* test_that_cd() returns 0 on success */ static int test_that_cd(int no_digest) { if (IS_VERIFICATION && !no_digest) return verify_ramdisk_digest(get_ramdisk_path(NULL), get_param_valued("hash")) == RETURN_ERROR; log_message("test file on cd: %s\n", get_ramdisk_path(NULL)); return access(get_ramdisk_path(NULL), R_OK); } static enum return_type try_with_device(char * dev_name, char * dev_model); static enum return_type do_with_device(char * dev_name, char * dev_model) { struct stat st; char msg[256]; char * ramdisk_path; if (test_that_cd(0)) { enum return_type results; umount(IMAGE_LOCATION); if (IS_VERIFICATION) snprintf(msg, sizeof(msg), "ISO on /dev/%s does not seem to contain proper %s" " media:\nhash verification failed.\nTry another media in that drive?", dev_name, version); else snprintf(msg, sizeof(msg), "That ISO does not seem like proper %s" " media.\nTry another media in that drive?", version); results = ask_yes_no(msg); if (results == RETURN_OK) return try_with_device(dev_name, dev_model); return results; } log_message("found %s ISO9660 media, good news!", version); if (IS_RESCUE) { load_ramdisk(NULL); umount(IMAGE_LOCATION); } ramdisk_path = get_ramdisk_path(NULL); stat(ramdisk_path, &st); if (S_ISDIR(st.st_mode)) { mount(ramdisk_path, STAGE2_LOCATION, NULL, MS_BIND, NULL); } else { do_losetup(LIVE_DEVICE,ramdisk_path); my_mount(LIVE_DEVICE, STAGE2_LOCATION, (IS_LIVE) ? LIVEFS : STAGE2FS, 0); } method_name = strdup("cdrom"); add_to_env("METHOD", method_name); add_to_env("PREFIX", "/"); return RETURN_OK; } static enum return_type try_with_device(char * dev_name, char * dev_model) { wait_message("Trying to access media in drive %s", dev_model); if (mount_that_cd_device(dev_name) == -1) { enum return_type results; char msg[500]; unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */ remove_wait_message(); snprintf(msg, sizeof(msg), "I can't access %s media in drive %s.\nRetry?", version, dev_model); results = ask_yes_no(msg); if (results == RETURN_OK) return try_with_device(dev_name, dev_model); return results; } remove_wait_message(); return do_with_device(dev_name, dev_model); } #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) int try_automatic(char ** medias, char ** medias_models) { static char * already_tried[50] = { NULL }; char ** model = medias_models; char ** ptr = medias; int i = 0; if (!medias) { for (; i < ARRAY_SIZE(already_tried); ++i) { if (!already_tried[i]) break; free(already_tried[i]); already_tried[i] = NULL; } return -1; } while (ptr && *ptr) { char ** p; for (p = already_tried; p && *p; p++) if (streq(*p, *ptr)) goto try_automatic_already_tried; *p = strdup(*ptr); *(p+1) = NULL; wait_message("Trying to access media in drive %s", *model); if (mount_that_cd_device(*ptr) != -1) { if (!test_that_cd(1)) { remove_wait_message(); return i; } else umount(IMAGE_LOCATION); } remove_wait_message(); try_automatic_already_tried: ptr++; model++; i++; } return -1; } enum return_type cdrom_prepare(void) { char ** medias, ** ptr, ** medias_models; char * choice; int i, count = 0; enum return_type results; int timeout=32; int period=5; update_splash("prepare"); fprintf(stderr,"%c[1A",27); for(i=0; i 1 ? "s" : ""); sleep(1); /* drop medias */ for (ptr = medias; *ptr; ++ptr) free(*ptr); free(medias); /* drop medias_models */ for (ptr = medias_models; *ptr; ++ptr) free(*ptr); free(medias_models); /* drop already_tried */ try_automatic(NULL, NULL); /* refill medias and medias_models; note that get_medias() leaks memory */ get_medias(CDROM, &medias, &medias_models); remove_wait_message(); } if ((i = try_automatic(medias, medias_models)) != -1) { if (j) { log_message("found /dev/%s %s after %d seconds of waiting", medias[i], medias_models[i], j); remove_wait_message(); } return do_with_device(medias[i], medias_models[i]); } } ptr = medias; while (ptr && *ptr) { count++; ptr++; } if (count == 0) { stg1_error_message("No CD/DVD/Pendrive found."); i = ask_insmod(); if (i == RETURN_BACK) return RETURN_BACK; return cdrom_prepare(); } if (count == 1) { results = try_with_device(*medias, *medias_models); if (results == RETURN_OK) return RETURN_OK; i = ask_insmod(); if (i == RETURN_BACK) return RETURN_BACK; return cdrom_prepare(); } unset_param(MODE_AUTOMATIC); } results = ask_from_list_comments("Please choose the drive to boot from.", medias, medias_models, &choice); if (results == RETURN_OK) { char ** model = medias_models; ptr = medias; while (ptr && *ptr && model && *model) { if (!strcmp(*ptr, choice)) break; ptr++; model++; } results = try_with_device(choice, *model); } else return results; if (results == RETURN_OK) { update_splash("found_media"); return RETURN_OK; } if (results == RETURN_BACK) return cdrom_prepare(); i = ask_insmod(); if (i == RETURN_BACK) return RETURN_BACK; return cdrom_prepare(); }