From ce624c696f5657395b63595c115cc341f2c5c488 Mon Sep 17 00:00:00 2001 From: Jessica Hamilton Date: Sat, 13 Apr 2019 02:27:46 +0000 Subject: [PATCH] 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 --- src/system/boot/loader/loader.cpp | 149 ++++++++---------------------- 1 file changed, 37 insertions(+), 112 deletions(-) diff --git a/src/system/boot/loader/loader.cpp b/src/system/boot/loader/loader.cpp index bfdd8620d3..f18199b370 100644 --- a/src/system/boot/loader/loader.cpp +++ b/src/system/boot/loader/loader.cpp @@ -5,61 +5,58 @@ #include "loader.h" -#include "elf.h" #include "RootFileSystem.h" +#include "elf.h" -#include #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include -#include #include +#include #ifndef BOOT_ARCH -# error BOOT_ARCH has to be defined to differentiate the kernel per platform +#error BOOT_ARCH has to be defined to differentiate the kernel per platform #endif -#define SYSTEM_DIRECTORY_PREFIX "system/" -#define KERNEL_IMAGE "kernel_" BOOT_ARCH -#define KERNEL_PATH SYSTEM_DIRECTORY_PREFIX KERNEL_IMAGE +#define SYSTEM_DIRECTORY_PREFIX "system/" +#define KERNEL_IMAGE "kernel_" BOOT_ARCH +#define KERNEL_PATH SYSTEM_DIRECTORY_PREFIX KERNEL_IMAGE #ifdef ALTERNATE_BOOT_ARCH -# define ALTERNATE_KERNEL_IMAGE "kernel_" ALTERNATE_BOOT_ARCH -# define ALTERNATE_KERNEL_PATH "system/" ALTERNATE_KERNEL_IMAGE +#define ALTERNATE_KERNEL_IMAGE "kernel_" ALTERNATE_BOOT_ARCH +#define ALTERNATE_KERNEL_PATH "system/" ALTERNATE_KERNEL_IMAGE #endif static const char* const kSystemDirectoryPrefix = SYSTEM_DIRECTORY_PREFIX; -static const char *sKernelPaths[][2] = { - { KERNEL_PATH, KERNEL_IMAGE }, +static const char* sKernelPaths[][2] = { + {KERNEL_PATH, KERNEL_IMAGE}, #ifdef ALTERNATE_BOOT_ARCH - { ALTERNATE_KERNEL_PATH, ALTERNATE_KERNEL_IMAGE }, + {ALTERNATE_KERNEL_PATH, ALTERNATE_KERNEL_IMAGE}, #endif - { NULL, NULL }, + {NULL, NULL}, }; -static const char *sAddonPaths[] = { - kVolumeLocalSystemKernelAddonsDirectory, +static const char* sAddonPaths[] = {kVolumeLocalSystemKernelAddonsDirectory, kVolumeLocalCommonNonpackagedKernelAddonsDirectory, kVolumeLocalCommonKernelAddonsDirectory, kVolumeLocalUserNonpackagedKernelAddonsDirectory, - kVolumeLocalUserKernelAddonsDirectory, - NULL -}; + kVolumeLocalUserKernelAddonsDirectory, NULL}; static int open_maybe_packaged(BootVolume& volume, const char* path, int openMode) { if (strncmp(path, kSystemDirectoryPrefix, strlen(kSystemDirectoryPrefix)) - == 0) { + == 0) { path += strlen(kSystemDirectoryPrefix); return open_from(volume.SystemDirectory(), path, openMode); } @@ -86,7 +83,7 @@ find_kernel(BootVolume& volume, const char** name = NULL) bool -is_bootable(Directory *volume) +is_bootable(Directory* volume) { if (volume->IsEmpty()) return false; @@ -109,7 +106,7 @@ is_bootable(Directory *volume) status_t load_kernel(stage2_args* args, BootVolume& volume) { - const char *name; + const char* name; int fd = find_kernel(volume, &name); if (fd < B_OK) return fd; @@ -117,7 +114,7 @@ load_kernel(stage2_args* args, BootVolume& volume) dprintf("load kernel %s...\n", name); elf_init(); - preloaded_image *image; + preloaded_image* image; status_t status = elf_load_image(fd, &image); close(fd); @@ -150,11 +147,11 @@ load_modules_from(BootVolume& volume, const char* path) if (fd < B_OK) return fd; - Directory *modules = (Directory *)get_node_from(fd); + Directory* modules = (Directory*)get_node_from(fd); if (modules == NULL) return B_ENTRY_NOT_FOUND; - void *cookie; + void* cookie; if (modules->Open(&cookie, O_RDONLY) == B_OK) { char name[B_FILE_NAME_LENGTH]; while (modules->GetNextEntry(cookie, name, sizeof(name)) == B_OK) { @@ -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++) { @@ -247,7 +191,7 @@ load_modules(stage2_args* args, BootVolume& volume) if (failed == i) { // 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", + const char* paths[] = {"bus_managers", "busses/ide", "busses/scsi", "generic", "partitioning_systems", "drivers/bin", NULL}; for (int32 i = 0; paths[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); - } + 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; } -