diff --git a/headers/private/kernel/boot/partitions.h b/headers/private/kernel/boot/partitions.h index 3f500bd727..728b382936 100644 --- a/headers/private/kernel/boot/partitions.h +++ b/headers/private/kernel/boot/partitions.h @@ -10,6 +10,8 @@ #include +struct file_system_module_info; + namespace boot { class Partition : public Node, public partition_data { @@ -25,8 +27,8 @@ class Partition : public Node, public partition_data { Partition *AddChild(); - status_t Mount(Directory **_fileSystem = NULL); - status_t Scan(bool mountFileSystems); + status_t Mount(Directory **_fileSystem = NULL, bool isBootDevice = false); + status_t Scan(bool mountFileSystems, bool isBootDevice = false); void SetParent(Partition *parent) { fParent = parent; } Partition *Parent() const { return fParent; } @@ -38,6 +40,8 @@ class Partition : public Node, public partition_data { int FD() const { return fFD; } private: + status_t _Mount(file_system_module_info *module, Directory **_fileSystem); + int fFD; NodeList fChildren; Partition *fParent; diff --git a/headers/private/kernel/boot/platform.h b/headers/private/kernel/boot/platform.h index e11b95ee96..729802bea5 100644 --- a/headers/private/kernel/boot/platform.h +++ b/headers/private/kernel/boot/platform.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ #ifndef KERNEL_BOOT_PLATFORM_H @@ -58,6 +58,7 @@ extern status_t platform_add_block_devices(struct stage2_args *args, NodeList *d extern status_t platform_get_boot_partition(struct stage2_args *args, Node *bootDevice, NodeList *partitions, boot::Partition **_partition); extern status_t platform_register_boot_device(Node *device); +extern bool platform_boot_device_is_image(); /* menu functions */ diff --git a/headers/private/kernel/boot/vfs.h b/headers/private/kernel/boot/vfs.h index 09a654d307..ae0e835873 100644 --- a/headers/private/kernel/boot/vfs.h +++ b/headers/private/kernel/boot/vfs.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ #ifndef KERNEL_BOOT_VFS_H @@ -84,8 +84,8 @@ extern int open_from(Directory *directory, const char *path, int mode); extern Node *get_node_from(int fd); -extern status_t add_partitions_for(int fd, bool mountFileSystems); -extern status_t add_partitions_for(Node *device, bool mountFileSystems); +extern status_t add_partitions_for(int fd, bool mountFileSystems, bool isBootDevice = false); +extern status_t add_partitions_for(Node *device, bool mountFileSystems, bool isBootDevice = false); #endif /* __cplusplus */ diff --git a/src/system/boot/loader/loader.cpp b/src/system/boot/loader/loader.cpp index e2a626194b..1b6925fefa 100644 --- a/src/system/boot/loader/loader.cpp +++ b/src/system/boot/loader/loader.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -129,6 +129,10 @@ load_module(Directory *volume, const char *name) while (true) { int fd = open_from(base, moduleName, O_RDONLY); if (fd >= B_OK) { + struct stat stat; + if (fstat(fd, &stat) != 0 || !S_ISREG(stat.st_mode)) + return B_BAD_VALUE; + status_t status = elf_load_image(base, moduleName); close(fd); @@ -155,22 +159,47 @@ load_module(Directory *volume, const char *name) status_t load_modules(stage2_args *args, Directory *volume) { + int32 failed = 0; + + // ToDo: this should be mostly replaced by a hardware oriented detection mechanism + for (int32 i = 0; sPaths[i]; i++) { char path[B_FILE_NAME_LENGTH]; sprintf(path, "%s/boot", sPaths[i]); - load_modules_from(volume, path); + if (load_modules_from(volume, path) != B_OK) + failed++; + } + + if (failed > 1) { + // couldn't load any boot modules + // fall back to load all modules (currently needed by the boot floppy) + const char *paths[] = { "bus_managers", "busses/ide", "busses/scsi", + "generic", "partitioning_systems", "drivers/bin", NULL}; + + for (int32 i = 0; paths[i]; i++) { + char path[B_FILE_NAME_LENGTH]; + sprintf(path, "%s/%s", sPaths[0], paths[i]); + load_modules_from(volume, path); + } } // and now load all partitioning and file system modules // needed to identify the boot volume - Partition *partition; - if (gRoot->GetPartitionFor(volume, &partition) == B_OK) { - while (partition != NULL) { - load_module(volume, partition->ModuleName()); - partition = partition->Parent(); + if (!platform_boot_device_is_image()) { + // iterate over the mounted volumes and load their file system + Partition *partition; + if (gRoot->GetPartitionFor(volume, &partition) == B_OK) { + while (partition != NULL) { + load_module(volume, partition->ModuleName()); + partition = partition->Parent(); + } } + } else { + // just make sure BFS is loaded - the boot file system + // does not help our decision of what's needed + load_module(volume, "file_systems/bfs"); } return B_OK; diff --git a/src/system/boot/loader/partitions.cpp b/src/system/boot/loader/partitions.cpp index a2d8b902fd..58dd4693b0 100644 --- a/src/system/boot/loader/partitions.cpp +++ b/src/system/boot/loader/partitions.cpp @@ -1,7 +1,7 @@ /* -** Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. -** Distributed under the terms of the Haiku License. -*/ + * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ #include "RootFileSystem.h" @@ -182,25 +182,37 @@ Partition::AddChild() status_t -Partition::Mount(Directory **_fileSystem) +Partition::_Mount(file_system_module_info *module, Directory **_fileSystem) { + TRACE(("check for file_system: %s\n", module->pretty_name)); + + Directory *fileSystem; + if (module->get_file_system(this, &fileSystem) == B_OK) { + gRoot->AddVolume(fileSystem, this); + if (_fileSystem) + *_fileSystem = fileSystem; + + // remember the module name that mounted us + fModuleName = module->module_name; + + fIsFileSystem = true; + return B_OK; + } + + return B_BAD_VALUE; +} + + +status_t +Partition::Mount(Directory **_fileSystem, bool isBootDevice) +{ + if (isBootDevice && platform_boot_device_is_image()) + return _Mount(&gTarFileSystemModule, _fileSystem); + for (int32 i = 0; i < sNumFileSystemModules; i++) { - file_system_module_info *module = sFileSystemModules[i]; - - TRACE(("check for file_system: %s\n", module->pretty_name)); - - Directory *fileSystem; - if (module->get_file_system(this, &fileSystem) == B_OK) { - gRoot->AddVolume(fileSystem, this); - if (_fileSystem) - *_fileSystem = fileSystem; - - // remember the module name that mounted us - fModuleName = module->module_name; - - fIsFileSystem = true; + status_t status = _Mount(sFileSystemModules[i], _fileSystem); + if (status == B_OK) return B_OK; - } } return B_ENTRY_NOT_FOUND; @@ -208,12 +220,18 @@ Partition::Mount(Directory **_fileSystem) status_t -Partition::Scan(bool mountFileSystems) +Partition::Scan(bool mountFileSystems, bool isBootDevice) { // scan for partitions first (recursively all eventual children as well) TRACE(("Partition::Scan()\n")); + // if we were not booted from the real boot device, we won't scan + // the device we were booted from (which is likely to be a slow + // floppy or CD) + if (isBootDevice && platform_boot_device_is_image()) + return B_ENTRY_NOT_FOUND; + const partition_module_info *bestModule = NULL; void *bestCookie = NULL; float bestPriority = -1; @@ -309,8 +327,13 @@ Partition::Scan(bool mountFileSystems) // #pragma mark - +/** Scans the device passed in for partitioning systems. If none are found, + * a partition containing the whole device is created. + * All created partitions are added to the gPartitions list. + */ + status_t -add_partitions_for(int fd, bool mountFileSystems) +add_partitions_for(int fd, bool mountFileSystems, bool isBootDevice) { TRACE(("add_partitions_for(fd = %d, mountFS = %s)\n", fd, mountFileSystems ? "yes" : "no")); @@ -322,7 +345,7 @@ add_partitions_for(int fd, bool mountFileSystems) // add this partition to the list of partitions, if it contains // or might contain a file system - if ((partition->Scan(mountFileSystems) == B_OK && partition->IsFileSystem()) + if ((partition->Scan(mountFileSystems, isBootDevice) == B_OK && partition->IsFileSystem()) || (!partition->IsPartitioningSystem() && !mountFileSystems)) { gPartitions.Add(partition); return B_OK; @@ -344,7 +367,7 @@ add_partitions_for(int fd, bool mountFileSystems) status_t -add_partitions_for(Node *device, bool mountFileSystems) +add_partitions_for(Node *device, bool mountFileSystems, bool isBootDevice) { TRACE(("add_partitions_for(%p, mountFS = %s)\n", device, mountFileSystems ? "yes" : "no")); @@ -352,7 +375,7 @@ add_partitions_for(Node *device, bool mountFileSystems) if (fd < B_OK) return fd; - status_t status = add_partitions_for(fd, mountFileSystems); + status_t status = add_partitions_for(fd, mountFileSystems, isBootDevice); if (status < B_OK) dprintf("add_partitions_for(%d) failed: %ld\n", fd, status); diff --git a/src/system/boot/loader/vfs.cpp b/src/system/boot/loader/vfs.cpp index 23370d2c47..4a2a9dfa18 100644 --- a/src/system/boot/loader/vfs.cpp +++ b/src/system/boot/loader/vfs.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -334,7 +334,7 @@ get_boot_file_system(stage2_args *args) // add the boot device to the list of devices gBootDevices.Add(device); - if (add_partitions_for(device, false) < B_OK) + if (add_partitions_for(device, false, true) < B_OK) return NULL; Partition *partition; @@ -342,7 +342,7 @@ get_boot_file_system(stage2_args *args) return NULL; Directory *fileSystem; - status_t status = partition->Mount(&fileSystem); + status_t status = partition->Mount(&fileSystem, true); if (status < B_OK) { // this partition doesn't contain any known file system; we diff --git a/src/system/boot/platform/bios_ia32/devices.cpp b/src/system/boot/platform/bios_ia32/devices.cpp index 9719f49186..cbbc2303e3 100644 --- a/src/system/boot/platform/bios_ia32/devices.cpp +++ b/src/system/boot/platform/bios_ia32/devices.cpp @@ -22,6 +22,7 @@ // exported from shell.S +extern uint8 gCDFloppyBoot; extern uint8 gBootDriveID; extern uint32 gBootPartitionOffset; @@ -571,3 +572,8 @@ platform_register_boot_device(Node *device) } +bool +platform_boot_device_is_image() +{ + return gCDFloppyBoot; +} diff --git a/src/system/boot/platform/bios_ia32/shell.S b/src/system/boot/platform/bios_ia32/shell.S index 231e01c2f7..a45c8156f5 100644 --- a/src/system/boot/platform/bios_ia32/shell.S +++ b/src/system/boot/platform/bios_ia32/shell.S @@ -71,6 +71,12 @@ floppy_start: #endif start_loader: + // indicate that we were booted from CD/floppy + .code32 + .byte 0x67 + movb $1, gCDFloppyBoot - 0x7c00 // %ds is 0x7c0 right now + .code16 + // set our environment and jump to the standard BFS boot block entry point xor %dx, %dx // boot device ID and partition offset to 0 xor %eax, %eax @@ -355,6 +361,9 @@ gdt_descriptor: .word 0x2f // 6 entries in the GDT (8 bytes each) .long gdt +GLOBAL(gCDFloppyBoot): + .byte 0 + GLOBAL(gBootDriveID): .byte 0