diff options
author | Mystery Man <unknown@mandriva.org> | 2005-04-15 20:05:28 +0000 |
---|---|---|
committer | Mystery Man <unknown@mandriva.org> | 2005-04-15 20:05:28 +0000 |
commit | ce7f3fab2074c2bce53e02deb4d8f6484a70149a (patch) | |
tree | fdb875fd0efcd5aefc8bd9fc982169a4cc7e38cd /mdk-stage1 | |
parent | 6726d670fa36f61661b5a047a87a9ae4caa3190f (diff) | |
download | drakx-ce7f3fab2074c2bce53e02deb4d8f6484a70149a.tar drakx-ce7f3fab2074c2bce53e02deb4d8f6484a70149a.tar.gz drakx-ce7f3fab2074c2bce53e02deb4d8f6484a70149a.tar.bz2 drakx-ce7f3fab2074c2bce53e02deb4d8f6484a70149a.tar.xz drakx-ce7f3fab2074c2bce53e02deb4d8f6484a70149a.zip |
This commit was manufactured by cvs2svn to create branch
'MDK-10-update'.
Diffstat (limited to 'mdk-stage1')
-rw-r--r-- | mdk-stage1/partition.c | 171 | ||||
-rw-r--r-- | mdk-stage1/partition.h | 28 | ||||
-rw-r--r-- | mdk-stage1/thirdparty.c | 407 | ||||
-rw-r--r-- | mdk-stage1/thirdparty.h | 32 |
4 files changed, 638 insertions, 0 deletions
diff --git a/mdk-stage1/partition.c b/mdk-stage1/partition.c new file mode 100644 index 000000000..8fd581017 --- /dev/null +++ b/mdk-stage1/partition.c @@ -0,0 +1,171 @@ +/* + * 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 <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <libgen.h> +#include "stage1.h" +#include "frontend.h" +#include "modules.h" +#include "probing.h" +#include "log.h" +#include "mount.h" +#include "lomount.h" +#include "automatic.h" + +#include "disk.h" +#include "partition.h" + +struct partition_detection_anchor { + off_t offset; + const char * anchor; +}; + +static int seek_and_compare(int fd, struct partition_detection_anchor anch) +{ + char buf[500]; + size_t count; + if (lseek(fd, anch.offset, SEEK_SET) == (off_t)-1) { + log_perror("seek failed"); + return -1; + } + count = read(fd, buf, strlen(anch.anchor)); + if (count != strlen(anch.anchor)) { + log_perror("read failed"); + return -1; + } + buf[count] = '\0'; + if (strcmp(anch.anchor, buf)) + return 1; + return 0; +} + +static const char * detect_partition_type(char * dev) +{ + struct partition_detection_info { + const char * name; + struct partition_detection_anchor anchor0; + struct partition_detection_anchor anchor1; + struct partition_detection_anchor anchor2; + }; + struct partition_detection_info partitions_signatures[] = { + { "Linux Swap", { 4086, "SWAP-SPACE" }, { 0, NULL }, { 0, NULL } }, + { "Linux Swap", { 4086, "SWAPSPACE2" }, { 0, NULL }, { 0, NULL } }, + { "Ext2", { 0x438, "\x53\xEF" }, { 0, NULL }, { 0, NULL } }, + { "ReiserFS", { 0x10034, "ReIsErFs" }, { 0, NULL }, { 0, NULL } }, + { "ReiserFS", { 0x10034, "ReIsEr2Fs" }, { 0, NULL }, { 0, NULL } }, + { "XFS", { 0, "XFSB" }, { 0x200, "XAGF" }, { 0x400, "XAGI" } }, + { "JFS", { 0x8000, "JFS1" }, { 0, NULL }, { 0, NULL } }, + { "NTFS", { 0x1FE, "\x55\xAA" }, { 0x3, "NTFS" }, { 0, NULL } }, + { "FAT32", { 0x1FE, "\x55\xAA" }, { 0x52, "FAT32" }, { 0, NULL } }, + { "FAT", { 0x1FE, "\x55\xAA" }, { 0x36, "FAT" }, { 0, NULL } }, + { "Linux LVM", { 0, "HM\1\0" }, { 0, NULL }, { 0, NULL } } + }; + int partitions_signatures_nb = sizeof(partitions_signatures) / sizeof(struct partition_detection_info); + int i; + int fd; + const char *part_type = NULL; + + char device_fullname[50]; + strcpy(device_fullname, "/dev/"); + strcat(device_fullname, dev); + + if (ensure_dev_exists(device_fullname)) + return NULL; + log_message("guessing type of %s", device_fullname); + + if ((fd = open(device_fullname, O_RDONLY, 0)) < 0) { + log_perror("open"); + return NULL; + } + + for (i=0; i<partitions_signatures_nb; i++) { + int results = seek_and_compare(fd, partitions_signatures[i].anchor0); + if (results == -1) + goto detect_partition_type_end; + if (results == 1) + continue; + if (!partitions_signatures[i].anchor1.anchor) + goto detect_partition_found_it; + + results = seek_and_compare(fd, partitions_signatures[i].anchor1); + if (results == -1) + goto detect_partition_type_end; + if (results == 1) + continue; + if (!partitions_signatures[i].anchor2.anchor) + goto detect_partition_found_it; + + results = seek_and_compare(fd, partitions_signatures[i].anchor2); + if (results == -1) + goto detect_partition_type_end; + if (results == 1) + continue; + + detect_partition_found_it: + part_type = partitions_signatures[i].name; + break; + } + + detect_partition_type_end: + close(fd); + return part_type; +} + +int list_partitions(char * dev_name, char ** parts, char ** comments) +{ + int major, minor, blocks; + char name[100]; + FILE * f; + int i = 0; + char buf[512]; + + if (!(f = fopen("/proc/partitions", "rb")) || !fgets(buf, sizeof(buf), f) || !fgets(buf, sizeof(buf), f)) { + log_perror(dev_name); + return 1; + } + + while (fgets(buf, sizeof(buf), f)) { + memset(name, 0, sizeof(name)); + sscanf(buf, " %d %d %d %s", &major, &minor, &blocks, name); + if ((strstr(name, dev_name) == name) && (blocks > 1) && (name[strlen(dev_name)] != '\0')) { + const char * partition_type = detect_partition_type(name); + parts[i] = strdup(name); + comments[i] = (char *) malloc(sizeof(char) * 100); + sprintf(comments[i], "size: %d Mbytes", blocks >> 10); + if (partition_type) { + strcat(comments[i], ", type: "); + strcat(comments[i], partition_type); + } + i++; + } + } + parts[i] = NULL; + fclose(f); + + return 0; +} diff --git a/mdk-stage1/partition.h b/mdk-stage1/partition.h new file mode 100644 index 000000000..e901662df --- /dev/null +++ b/mdk-stage1/partition.h @@ -0,0 +1,28 @@ +/* + * Olivier Blin (oblin@mandrakesoft.com) + * + * Copyright 2005 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 + * + */ + +#ifndef _PARTITION_H_ +#define _PARTITION_H_ + +int list_partitions(char * dev_name, char ** parts, char ** comments); + +#endif + diff --git a/mdk-stage1/thirdparty.c b/mdk-stage1/thirdparty.c new file mode 100644 index 000000000..176a24f1c --- /dev/null +++ b/mdk-stage1/thirdparty.c @@ -0,0 +1,407 @@ +/* + * Guillaume Cottenceau (gc@mandrakesoft.com) + * Olivier Blin (oblin@mandrakesoft.com) + * + * Copyright 2005 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. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/mount.h> + +#include "stage1.h" +#include "log.h" +#include "insmod.h" +#include "modules.h" +#include "mount.h" +#include "frontend.h" +#include "partition.h" +#include "automatic.h" +#include "probing.h" + +#include "thirdparty.h" + +#define THIRDPARTY_MOUNT_LOCATION "/tmp/thirdparty" + +static struct pcitable_entry pcitable[100]; +static int pcitable_len = 0; + +static enum return_type thirdparty_choose_device(char ** device, int probe_only) +{ + char ** medias, ** medias_models; + char ** ptr, ** ptr_models; +#ifndef DISABLE_DISK + char ** disk_medias, ** disk_medias_models; + int disk_count; + char * parts[50]; + char * parts_comments[50]; +#endif +#ifndef DISABLE_CDROM + char ** cdrom_medias, ** cdrom_medias_models; + int cdrom_count; +#endif + char * floppy_dev; + enum return_type results; + int count = 0; + + wait_message("Looking for floppy, disk and cdrom devices ..."); + +#ifndef DISABLE_DISK + disk_count = get_disks(&disk_medias, &disk_medias_models); + count += disk_count; +#endif +#ifndef DISABLE_CDROM + cdrom_count = get_cdroms(&cdrom_medias, &cdrom_medias_models); + count += cdrom_count; +#endif + + floppy_dev = floppy_device(); + if (strstr(floppy_dev, "/dev/") == floppy_dev) { + floppy_dev = floppy_dev + 5; + } + if (floppy_dev) + count += 1; + + remove_wait_message(); + + if (count == 0) { + stg1_error_message("I can't find any floppy, disk or cdrom on this system. " + "No third-party kernel modules will be used."); + return RETURN_BACK; + } + + if (probe_only) { +#ifndef DISABLE_DISK + free(disk_medias); + free(disk_medias_models); +#endif +#ifndef DISABLE_CDROM + free(cdrom_medias); + free(cdrom_medias_models); +#endif + return RETURN_OK; + } + + ptr = medias = malloc((count + 1) * sizeof(char *)); + ptr_models =medias_models = malloc((count + 1) * sizeof(char *)); +#ifndef DISABLE_DISK + memcpy(ptr, disk_medias, disk_count * sizeof(char *)); + memcpy(ptr_models, disk_medias_models, disk_count * sizeof(char *)); + free(disk_medias); + free(disk_medias_models); + ptr += disk_count; + ptr_models += disk_count; +#endif +#ifndef DISABLE_CDROM + memcpy(ptr, cdrom_medias, cdrom_count * sizeof(char *)); + memcpy(ptr_models, cdrom_medias_models, cdrom_count * sizeof(char *)); + free(cdrom_medias); + free(cdrom_medias_models); + cdrom_medias = ptr; /* used later to know if a cdrom is selected */ + ptr += cdrom_count; + ptr_models += cdrom_count; +#endif + if (floppy_dev) { + ptr[0] = floppy_dev; + ptr_models[0] = "Floppy device"; + ptr++; + ptr_models++; + } + ptr[0] = NULL; + ptr_models[0] = NULL; + + if (count == 1) { + *device = medias[0]; + } else { + results = ask_from_list_comments("If you want to insert third-party kernel modules, " + "please select the disk containing the modules.", + medias, medias_models, device); + if (results != RETURN_OK) + return results; + } + + if (streq(*device, floppy_dev)) { + /* a floppy is selected, don't try to list partitions */ + return RETURN_OK; + } + +#ifndef DISABLE_CDROM + for (ptr = cdrom_medias; ptr < cdrom_medias + cdrom_count; ptr++) { + if (*device == *ptr) { + /* a cdrom is selected, don't try to list partitions */ + log_message("thirdparty: a cdrom is selected, using it (%s)", *device); + return RETURN_OK; + } + } +#endif + +#ifndef DISABLE_DISK + /* a disk or usb key is selected */ + if (list_partitions(*device, parts, parts_comments)) { + stg1_error_message("Could not read partitions information."); + return RETURN_ERROR; + } + + if (parts[0] == NULL) { + stg1_error_message("No partition found."); + return RETURN_ERROR; + } + + /* only one partition has been discovered, don't ask which one to use */ + if (parts[1] == NULL) { + log_message("thirdparty: found only one partition on device (%s)", parts[0]); + *device = parts[0]; + return RETURN_OK; + } + + results = ask_from_list_comments("Please select the partition containing " + "the third party modules.", + parts, parts_comments, device); + if (results == RETURN_OK) + return RETURN_OK; +#endif + + stg1_error_message("Sorry, no third party device can be used."); + + return RETURN_BACK; +} + + +static enum return_type thirdparty_mount_device(char * device) +{ + log_message("third party: trying to mount device %s", device); + if (try_mount(device, THIRDPARTY_MOUNT_LOCATION) != 0) { + stg1_error_message("I can't mount the selected device (%s).", device); + return RETURN_ERROR; + } + return RETURN_OK; +} + + +static enum return_type thirdparty_prompt_modules(const char *modules_location, char ** modules_list) +{ + enum return_type results; + char final_name[500]; + char *module_name; + int rc; + char * questions[] = { "Options", NULL }; + static char ** answers = NULL; + + while (1) { + results = ask_from_list("Which driver would you like to insmod?", modules_list, &module_name); + if (results != RETURN_OK) + break; + + sprintf(final_name, "%s/%s", modules_location, module_name); + + results = ask_from_entries("Please enter the options:", questions, &answers, 24, NULL); + if (results != RETURN_OK) + continue; + + rc = insmod_local_file(final_name, answers[0]); + if (rc) { + log_message("\tfailed"); + stg1_error_message("Insmod failed."); + } + } + return RETURN_OK; +} + + +static void thirdparty_load_pcitable(const char *modules_location) +{ + char pcitable_filename[100]; + FILE * f = NULL; + + sprintf(pcitable_filename, "%s/pcitable", modules_location); + if (!(f = fopen(pcitable_filename, "rb"))) { + log_message("third_party: no external pcitable found"); + return; + } + while (1) { + char buf[200]; + struct pcitable_entry *e; + if (!fgets(buf, sizeof(buf), f)) break; + e = &pcitable[pcitable_len++]; + sscanf(buf, "%hx\t%hx\t\"%[^ \"]\"\t\"%[^ \"]\"", &e->vendor, &e->device, e->module, e->description); + } + fclose(f); +} + + +static int thirdparty_is_detected(char *driver) { + int i, j; + + for (i = 0; i < detected_devices_len ; i++) { + /* first look for the IDs in the third-party pcitable */ + for (j = 0; j < pcitable_len ; j++) { + if (pcitable[j].vendor == detected_devices[i].vendor && + pcitable[j].device == detected_devices[i].device && + !strcmp(pcitable[j].module, driver)) { + log_message("probing: found device for module %s", driver); + return 1; + } + } + /* if not found, compare with the detected driver */ + if (!strcmp(detected_devices[i].module, driver)) { + log_message("probing: found device for module %s", driver); + return 1; + } + } + + return 0; +} + +static enum return_type thirdparty_autoload_modules(const char *modules_location, char ** modules_list, FILE *f, int load_detected_only) +{ + while (1) { + char final_name[500]; + char module[500]; + char * options; + char ** entry = modules_list; + + if (!fgets(module, sizeof(module), f)) break; + if (module[0] == '#' || strlen(module) == 0) + continue; + + while (module[strlen(module)-1] == '\n') + module[strlen(module)-1] = '\0'; + options = strchr(module, ' '); + if (options) { + options[0] = '\0'; + options++; + } + + if (load_detected_only && !thirdparty_is_detected(module)) { + log_message("third party: no device detected for module %s, skipping", module); + continue; + } + + log_message("third party: auto-loading module (%s) with options (%s)", module, options); + while (entry && *entry) { + if (!strncmp(*entry, module, strlen(module)) && (*entry)[strlen(module)] == '.') { + sprintf(final_name, "%s/%s", modules_location, *entry); + if (insmod_local_file(final_name, options)) { + log_message("\t%s (third party media): failed", *entry); + stg1_error_message("Insmod %s (third party media) failed.", *entry); + } + break; + } + entry++; + } + if (!entry || !*entry) { + enum insmod_return ret = my_insmod(module, ANY_DRIVER_TYPE, options, 0); + if (ret != INSMOD_OK) { + log_message("\t%s (marfile): failed", module); + stg1_error_message("Insmod %s (marfile) failed.", module); + } + } + } + + return RETURN_OK; +} + +static enum return_type thirdparty_try_directory(char * root_directory, int interactive) { + char modules_location[100]; + char list_filename[50]; + FILE *f_load, *f_detect; + char **modules_list; + + /* look first in the specific third-party directory */ + strcpy(modules_location, root_directory); + strcat(modules_location, THIRDPARTY_DIRECTORY); + modules_list = list_directory(modules_location); + + /* if it's empty, look in the root of selected device */ + if (!modules_list || !modules_list[0]) { + modules_location[strlen(root_directory)] = '\0'; + modules_list = list_directory(modules_location); + if (interactive) + add_to_env("THIRDPARTY_DIR", ""); + } else { + if (interactive) + add_to_env("THIRDPARTY_DIR", THIRDPARTY_DIRECTORY); + } + + log_message("third party: using modules location %s", modules_location); + + if (!modules_list || !*modules_list) { + log_message("third party: no modules found"); + if (interactive) + stg1_error_message("No modules found on selected device."); + return RETURN_ERROR; + } + + sprintf(list_filename, "%s/to_load", modules_location); + f_load = fopen(list_filename, "rb"); + if (f_load) { + thirdparty_autoload_modules(modules_location, modules_list, f_load, 0); + fclose(f_load); + } + + sprintf(list_filename, "%s/to_detect", modules_location); + f_detect = fopen(list_filename, "rb"); + if (f_detect) { + probing_detect_devices(); + thirdparty_load_pcitable(modules_location); + thirdparty_autoload_modules(modules_location, modules_list, f_detect, 1); + fclose(f_detect); + } + + if (f_load || f_detect) + return RETURN_OK; + else if (interactive) { + if (IS_AUTOMATIC) + stg1_error_message("I can't find a \"to_load\" file. Please select the modules manually."); + log_message("third party: no \"to_load\" file, prompting for modules"); + return thirdparty_prompt_modules(modules_location, modules_list); + } else { + return RETURN_OK; + } +} + +void thirdparty_load_media_modules(void) +{ + thirdparty_try_directory(IMAGE_LOCATION, 0); +} + +void thirdparty_load_modules(void) +{ + enum return_type results; + char * device; + + device = NULL; + if (IS_AUTOMATIC) { + device = get_auto_value("thirdparty"); + thirdparty_choose_device(NULL, 1); /* probe only to create devices */ + log_message("third party: trying automatic device %s", device); + if (thirdparty_mount_device(device) != RETURN_OK) + device = NULL; + } + + while (!device || streq(device, "")) { + results = thirdparty_choose_device(&device, 0); + if (results == RETURN_BACK) + return; + if (thirdparty_mount_device(device) != RETURN_OK) + device = NULL; + } + + log_message("third party: using device %s", device); + add_to_env("THIRDPARTY_DEVICE", device); + + results = thirdparty_try_directory(THIRDPARTY_MOUNT_LOCATION, 1); + umount(THIRDPARTY_MOUNT_LOCATION); + + if (results != RETURN_OK) + return thirdparty_load_modules(); +} diff --git a/mdk-stage1/thirdparty.h b/mdk-stage1/thirdparty.h new file mode 100644 index 000000000..23066374c --- /dev/null +++ b/mdk-stage1/thirdparty.h @@ -0,0 +1,32 @@ +/* + * Guillaume Cottenceau (gc@mandrakesoft.com) + * Olivier Blin (oblin@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. + * + */ + +#ifndef _THIRDPARTY_H_ +#define _THIRDPARTY_H_ + +#define THIRDPARTY_DIRECTORY "/install/thirdparty" + +/* load third party modules present on install media + * use to_load and to_detect files in /install/thirdparty + * do not prompt user + */ +void thirdparty_load_media_modules(void); + +/* load modules if to_load or to_detect files are present + * prompt user if no to_load file is present + */ +void thirdparty_load_modules(void); + +#endif |