The boot loader now has special support for being booted from a boot image
like floppy or CD boot. This allows it to reduce the number of scans needed to identify the boot partition - when booted from a real floppy, this speeds up the boot process by a magnitude. Also, the loader now has a fall back in case there were no "boot" links on the disk - the current boot floppy script doesn't create them. With these changes, I was able to boot into a HD based Haiku installation from a floppy disk. It's not yet enough to boot from CD (as the boot device selection is a bit too simplistic right now), but it will eventually come next. Testing is a lot slower here, though, as neither qemu nor Bochs support multi-session CDs (at least I have no idea how to get them to do this). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14380 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
313ffb09da
commit
e3fcb58ebb
|
@ -10,6 +10,8 @@
|
||||||
#include <disk_device_manager.h>
|
#include <disk_device_manager.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct file_system_module_info;
|
||||||
|
|
||||||
namespace boot {
|
namespace boot {
|
||||||
|
|
||||||
class Partition : public Node, public partition_data {
|
class Partition : public Node, public partition_data {
|
||||||
|
@ -25,8 +27,8 @@ class Partition : public Node, public partition_data {
|
||||||
|
|
||||||
Partition *AddChild();
|
Partition *AddChild();
|
||||||
|
|
||||||
status_t Mount(Directory **_fileSystem = NULL);
|
status_t Mount(Directory **_fileSystem = NULL, bool isBootDevice = false);
|
||||||
status_t Scan(bool mountFileSystems);
|
status_t Scan(bool mountFileSystems, bool isBootDevice = false);
|
||||||
|
|
||||||
void SetParent(Partition *parent) { fParent = parent; }
|
void SetParent(Partition *parent) { fParent = parent; }
|
||||||
Partition *Parent() const { return fParent; }
|
Partition *Parent() const { return fParent; }
|
||||||
|
@ -38,6 +40,8 @@ class Partition : public Node, public partition_data {
|
||||||
int FD() const { return fFD; }
|
int FD() const { return fFD; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
status_t _Mount(file_system_module_info *module, Directory **_fileSystem);
|
||||||
|
|
||||||
int fFD;
|
int fFD;
|
||||||
NodeList fChildren;
|
NodeList fChildren;
|
||||||
Partition *fParent;
|
Partition *fParent;
|
||||||
|
|
|
@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef KERNEL_BOOT_PLATFORM_H
|
#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,
|
extern status_t platform_get_boot_partition(struct stage2_args *args, Node *bootDevice,
|
||||||
NodeList *partitions, boot::Partition **_partition);
|
NodeList *partitions, boot::Partition **_partition);
|
||||||
extern status_t platform_register_boot_device(Node *device);
|
extern status_t platform_register_boot_device(Node *device);
|
||||||
|
extern bool platform_boot_device_is_image();
|
||||||
|
|
||||||
/* menu functions */
|
/* menu functions */
|
||||||
|
|
||||||
|
|
|
@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef KERNEL_BOOT_VFS_H
|
#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 Node *get_node_from(int fd);
|
||||||
|
|
||||||
extern status_t add_partitions_for(int fd, 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);
|
extern status_t add_partitions_for(Node *device, bool mountFileSystems, bool isBootDevice = false);
|
||||||
|
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
|
@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -129,6 +129,10 @@ load_module(Directory *volume, const char *name)
|
||||||
while (true) {
|
while (true) {
|
||||||
int fd = open_from(base, moduleName, O_RDONLY);
|
int fd = open_from(base, moduleName, O_RDONLY);
|
||||||
if (fd >= B_OK) {
|
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);
|
status_t status = elf_load_image(base, moduleName);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -155,16 +159,36 @@ load_module(Directory *volume, const char *name)
|
||||||
status_t
|
status_t
|
||||||
load_modules(stage2_args *args, Directory *volume)
|
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++) {
|
for (int32 i = 0; sPaths[i]; i++) {
|
||||||
char path[B_FILE_NAME_LENGTH];
|
char path[B_FILE_NAME_LENGTH];
|
||||||
sprintf(path, "%s/boot", sPaths[i]);
|
sprintf(path, "%s/boot", sPaths[i]);
|
||||||
|
|
||||||
|
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);
|
load_modules_from(volume, path);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// and now load all partitioning and file system modules
|
// and now load all partitioning and file system modules
|
||||||
// needed to identify the boot volume
|
// needed to identify the boot volume
|
||||||
|
|
||||||
|
if (!platform_boot_device_is_image()) {
|
||||||
|
// iterate over the mounted volumes and load their file system
|
||||||
Partition *partition;
|
Partition *partition;
|
||||||
if (gRoot->GetPartitionFor(volume, &partition) == B_OK) {
|
if (gRoot->GetPartitionFor(volume, &partition) == B_OK) {
|
||||||
while (partition != NULL) {
|
while (partition != NULL) {
|
||||||
|
@ -172,6 +196,11 @@ load_modules(stage2_args *args, Directory *volume)
|
||||||
partition = partition->Parent();
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
** Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
* Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
** Distributed under the terms of the Haiku License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,11 +182,8 @@ Partition::AddChild()
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Partition::Mount(Directory **_fileSystem)
|
Partition::_Mount(file_system_module_info *module, Directory **_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));
|
TRACE(("check for file_system: %s\n", module->pretty_name));
|
||||||
|
|
||||||
Directory *fileSystem;
|
Directory *fileSystem;
|
||||||
|
@ -201,6 +198,21 @@ Partition::Mount(Directory **_fileSystem)
|
||||||
fIsFileSystem = true;
|
fIsFileSystem = true;
|
||||||
return B_OK;
|
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++) {
|
||||||
|
status_t status = _Mount(sFileSystemModules[i], _fileSystem);
|
||||||
|
if (status == B_OK)
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
@ -208,12 +220,18 @@ Partition::Mount(Directory **_fileSystem)
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Partition::Scan(bool mountFileSystems)
|
Partition::Scan(bool mountFileSystems, bool isBootDevice)
|
||||||
{
|
{
|
||||||
// scan for partitions first (recursively all eventual children as well)
|
// scan for partitions first (recursively all eventual children as well)
|
||||||
|
|
||||||
TRACE(("Partition::Scan()\n"));
|
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;
|
const partition_module_info *bestModule = NULL;
|
||||||
void *bestCookie = NULL;
|
void *bestCookie = NULL;
|
||||||
float bestPriority = -1;
|
float bestPriority = -1;
|
||||||
|
@ -309,8 +327,13 @@ Partition::Scan(bool mountFileSystems)
|
||||||
// #pragma mark -
|
// #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
|
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"));
|
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
|
// add this partition to the list of partitions, if it contains
|
||||||
// or might contain a file system
|
// 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)) {
|
|| (!partition->IsPartitioningSystem() && !mountFileSystems)) {
|
||||||
gPartitions.Add(partition);
|
gPartitions.Add(partition);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
@ -344,7 +367,7 @@ add_partitions_for(int fd, bool mountFileSystems)
|
||||||
|
|
||||||
|
|
||||||
status_t
|
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"));
|
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)
|
if (fd < B_OK)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
status_t status = add_partitions_for(fd, mountFileSystems);
|
status_t status = add_partitions_for(fd, mountFileSystems, isBootDevice);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
dprintf("add_partitions_for(%d) failed: %ld\n", fd, status);
|
dprintf("add_partitions_for(%d) failed: %ld\n", fd, status);
|
||||||
|
|
||||||
|
|
|
@ -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.
|
* 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
|
// add the boot device to the list of devices
|
||||||
gBootDevices.Add(device);
|
gBootDevices.Add(device);
|
||||||
|
|
||||||
if (add_partitions_for(device, false) < B_OK)
|
if (add_partitions_for(device, false, true) < B_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Partition *partition;
|
Partition *partition;
|
||||||
|
@ -342,7 +342,7 @@ get_boot_file_system(stage2_args *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Directory *fileSystem;
|
Directory *fileSystem;
|
||||||
status_t status = partition->Mount(&fileSystem);
|
status_t status = partition->Mount(&fileSystem, true);
|
||||||
|
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
// this partition doesn't contain any known file system; we
|
// this partition doesn't contain any known file system; we
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
// exported from shell.S
|
// exported from shell.S
|
||||||
|
extern uint8 gCDFloppyBoot;
|
||||||
extern uint8 gBootDriveID;
|
extern uint8 gBootDriveID;
|
||||||
extern uint32 gBootPartitionOffset;
|
extern uint32 gBootPartitionOffset;
|
||||||
|
|
||||||
|
@ -571,3 +572,8 @@ platform_register_boot_device(Node *device)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
platform_boot_device_is_image()
|
||||||
|
{
|
||||||
|
return gCDFloppyBoot;
|
||||||
|
}
|
||||||
|
|
|
@ -71,6 +71,12 @@ floppy_start:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
start_loader:
|
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
|
// 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 %dx, %dx // boot device ID and partition offset to 0
|
||||||
xor %eax, %eax
|
xor %eax, %eax
|
||||||
|
@ -355,6 +361,9 @@ gdt_descriptor:
|
||||||
.word 0x2f // 6 entries in the GDT (8 bytes each)
|
.word 0x2f // 6 entries in the GDT (8 bytes each)
|
||||||
.long gdt
|
.long gdt
|
||||||
|
|
||||||
|
GLOBAL(gCDFloppyBoot):
|
||||||
|
.byte 0
|
||||||
|
|
||||||
GLOBAL(gBootDriveID):
|
GLOBAL(gBootDriveID):
|
||||||
.byte 0
|
.byte 0
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue