loader: load all available file/partitioning system modules.
* This fixes booting on virtualbox with UEFI, where it fails to identify CDs as BOOT_METHOD_CD, such that the write_overlay driver doesn't get loaded, causing a panic in the kernel trying to mount the boot device. Change-Id: I63046d976661500227604bf01cc1631f1ae2b608 Reviewed-on: https://review.haiku-os.org/c/1406 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
3a75ef9ad1
commit
ce624c696f
@@ -5,20 +5,20 @@
|
||||
|
||||
|
||||
#include "loader.h"
|
||||
#include "elf.h"
|
||||
#include "RootFileSystem.h"
|
||||
#include "elf.h"
|
||||
|
||||
#include <directories.h>
|
||||
#include <OS.h>
|
||||
#include <util/list.h>
|
||||
#include <boot/stage2.h>
|
||||
#include <boot/vfs.h>
|
||||
#include <boot/platform.h>
|
||||
#include <boot/stdio.h>
|
||||
#include <boot/partitions.h>
|
||||
#include <boot/platform.h>
|
||||
#include <boot/stage2.h>
|
||||
#include <boot/stdio.h>
|
||||
#include <boot/vfs.h>
|
||||
#include <directories.h>
|
||||
#include <util/list.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#ifndef BOOT_ARCH
|
||||
@@ -45,14 +45,11 @@ static const char *sKernelPaths[][2] = {
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
static const char *sAddonPaths[] = {
|
||||
kVolumeLocalSystemKernelAddonsDirectory,
|
||||
static const char* sAddonPaths[] = {kVolumeLocalSystemKernelAddonsDirectory,
|
||||
kVolumeLocalCommonNonpackagedKernelAddonsDirectory,
|
||||
kVolumeLocalCommonKernelAddonsDirectory,
|
||||
kVolumeLocalUserNonpackagedKernelAddonsDirectory,
|
||||
kVolumeLocalUserKernelAddonsDirectory,
|
||||
NULL
|
||||
};
|
||||
kVolumeLocalUserKernelAddonsDirectory, NULL};
|
||||
|
||||
|
||||
static int
|
||||
@@ -163,7 +160,8 @@ load_modules_from(BootVolume& volume, const char* path)
|
||||
|
||||
status_t status = elf_load_image(modules, name);
|
||||
if (status != B_OK)
|
||||
dprintf("Could not load \"%s\" error %" B_PRIx32 "\n", name, status);
|
||||
dprintf("Could not load \"%s\" error %" B_PRIx32 "\n", name,
|
||||
status);
|
||||
}
|
||||
|
||||
modules->Close(cookie);
|
||||
@@ -173,67 +171,13 @@ load_modules_from(BootVolume& volume, const char* path)
|
||||
}
|
||||
|
||||
|
||||
/** Loads a module by module name. This basically works in the same
|
||||
* way as the kernel module loader; it will cut off the last part
|
||||
* of the module name until it could find a module and loads it.
|
||||
* It tests both, kernel and user module directories.
|
||||
*/
|
||||
|
||||
static status_t
|
||||
load_module(BootVolume& volume, const char* name)
|
||||
{
|
||||
char moduleName[B_FILE_NAME_LENGTH];
|
||||
if (strlcpy(moduleName, name, sizeof(moduleName)) > sizeof(moduleName))
|
||||
return B_NAME_TOO_LONG;
|
||||
|
||||
for (int32 i = 0; sAddonPaths[i]; i++) {
|
||||
// get base path
|
||||
int baseFD = open_maybe_packaged(volume, sAddonPaths[i], O_RDONLY);
|
||||
if (baseFD < B_OK)
|
||||
continue;
|
||||
|
||||
Directory *base = (Directory *)get_node_from(baseFD);
|
||||
if (base == NULL) {
|
||||
close(baseFD);
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
close(baseFD);
|
||||
return status;
|
||||
}
|
||||
|
||||
// cut off last name element (or stop trying if there are no more)
|
||||
|
||||
char *last = strrchr(moduleName, '/');
|
||||
if (last != NULL)
|
||||
last[0] = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
close(baseFD);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
load_modules(stage2_args* args, BootVolume& volume)
|
||||
{
|
||||
int32 failed = 0;
|
||||
|
||||
// ToDo: this should be mostly replaced by a hardware oriented detection mechanism
|
||||
// ToDo: this should be mostly replaced by a hardware oriented detection
|
||||
// mechanism
|
||||
|
||||
int32 i = 0;
|
||||
for (; sAddonPaths[i]; i++) {
|
||||
@@ -258,31 +202,12 @@ load_modules(stage2_args* args, BootVolume& volume)
|
||||
}
|
||||
|
||||
// and now load all partitioning and file system modules
|
||||
// needed to identify the boot volume
|
||||
|
||||
if (!gBootVolume.GetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, false)
|
||||
&& gBootVolume.GetInt32(BOOT_METHOD, BOOT_METHOD_DEFAULT)
|
||||
!= BOOT_METHOD_CD) {
|
||||
// iterate over the mounted volumes and load their file system
|
||||
Partition *partition;
|
||||
if (gRoot->GetPartitionFor(volume.RootDirectory(), &partition)
|
||||
== B_OK) {
|
||||
while (partition != NULL) {
|
||||
load_module(volume, partition->ModuleName());
|
||||
partition = partition->Parent();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The boot image should only contain the file system
|
||||
// needed to boot the system, so we just load it.
|
||||
// ToDo: this is separate from the fall back from above
|
||||
// as this piece will survive a more intelligent module
|
||||
// loading approach...
|
||||
char path[B_FILE_NAME_LENGTH];
|
||||
snprintf(path, sizeof(path), "%s/%s", sAddonPaths[0], "file_systems");
|
||||
load_modules_from(volume, path);
|
||||
}
|
||||
snprintf(
|
||||
path, sizeof(path), "%s/%s", sAddonPaths[0], "partitioning_systems");
|
||||
load_modules_from(volume, path);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user