1 /* 2 * Copyright 2003-2013, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "menu.h" 8 #include "loader.h" 9 #include "load_driver_settings.h" 10 11 #include <boot/stage2.h> 12 #include <boot/vfs.h> 13 #include <boot/platform.h> 14 #include <boot/heap.h> 15 #include <boot/PathBlocklist.h> 16 #include <boot/stdio.h> 17 #include <system_revision.h> 18 19 #include "file_systems/packagefs/packagefs.h" 20 21 22 //#define TRACE_MAIN 23 #ifdef TRACE_MAIN 24 # define TRACE(x) dprintf x 25 #else 26 # define TRACE(x) ; 27 #endif 28 29 30 void *__dso_handle; 31 32 33 extern "C" int 34 main(stage2_args *args) 35 { 36 TRACE(("boot(): enter\n")); 37 38 if (heap_init(args) < B_OK) 39 panic("Could not initialize heap!\n"); 40 41 TRACE(("boot(): heap initialized...\n")); 42 43 // set debug syslog default 44 #if KDEBUG_ENABLE_DEBUG_SYSLOG 45 gKernelArgs.keep_debug_output_buffer = true; 46 gKernelArgs.previous_debug_size = true; 47 // used as a boolean indicator until initialized for the kernel 48 #endif 49 50 add_stage2_driver_settings(args); 51 52 platform_init_video(); 53 54 // the main platform dependent initialisation 55 // has already taken place at this point. 56 57 if (vfs_init(args) < B_OK) 58 panic("Could not initialize VFS!\n"); 59 60 dprintf("Welcome to the Haiku boot loader!\n"); 61 dprintf("Haiku revision: %s\n", get_haiku_revision()); 62 63 bool mountedAllVolumes = false; 64 65 BootVolume bootVolume; 66 PathBlocklist pathBlocklist; 67 68 if (get_boot_file_system(args, bootVolume) != B_OK 69 || (platform_boot_options() & BOOT_OPTION_MENU) != 0) { 70 if (!bootVolume.IsValid()) 71 puts("\tno boot path found, scan for all partitions...\n"); 72 73 if (mount_file_systems(args) < B_OK) { 74 // That's unfortunate, but we still give the user the possibility 75 // to insert a CD-ROM or just rescan the available devices 76 puts("Could not locate any supported boot devices!\n"); 77 } 78 79 // ToDo: check if there is only one bootable volume! 80 81 mountedAllVolumes = true; 82 83 if (user_menu(bootVolume, pathBlocklist) < B_OK) { 84 // user requested to quit the loader 85 goto out; 86 } 87 } 88 89 if (bootVolume.IsValid()) { 90 // we got a volume to boot from! 91 92 // TODO: fix for riscv64 93 #ifndef __riscv 94 load_driver_settings(args, bootVolume.RootDirectory()); 95 #endif 96 status_t status; 97 while ((status = load_kernel(args, bootVolume)) < B_OK) { 98 // loading the kernel failed, so let the user choose another 99 // volume to boot from until it works 100 bootVolume.Unset(); 101 102 if (!mountedAllVolumes) { 103 // mount all other file systems, if not already happened 104 if (mount_file_systems(args) < B_OK) 105 panic("Could not locate any supported boot devices!\n"); 106 107 mountedAllVolumes = true; 108 } 109 110 if (user_menu(bootVolume, pathBlocklist) != B_OK 111 || !bootVolume.IsValid()) { 112 // user requested to quit the loader 113 goto out; 114 } 115 } 116 117 // if everything is okay, continue booting; the kernel 118 // is already loaded at this point and we definitely 119 // know our boot volume, too 120 if (status == B_OK) { 121 if (bootVolume.IsPackaged()) { 122 packagefs_apply_path_blocklist(bootVolume.SystemDirectory(), 123 pathBlocklist); 124 } 125 126 register_boot_file_system(bootVolume); 127 128 if ((platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) == 0) 129 platform_switch_to_logo(); 130 131 load_modules(args, bootVolume); 132 133 gKernelArgs.ucode_data = NULL; 134 gKernelArgs.ucode_data_size = 0; 135 platform_load_ucode(bootVolume); 136 137 // TODO: fix for riscv64 138 #ifndef __riscv 139 // apply boot settings 140 apply_boot_settings(); 141 #endif 142 143 // set up kernel args version info 144 gKernelArgs.kernel_args_size = sizeof(kernel_args); 145 gKernelArgs.version = CURRENT_KERNEL_ARGS_VERSION; 146 if (gKernelArgs.ucode_data == NULL) 147 gKernelArgs.kernel_args_size = kernel_args_size_v1; 148 149 // clone the boot_volume KMessage into kernel accessible memory 150 // note, that we need to 8-byte align the buffer and thus allocate 151 // 7 more bytes 152 void* buffer = kernel_args_malloc(gBootVolume.ContentSize() + 7); 153 if (!buffer) { 154 panic("Could not allocate memory for the boot volume kernel " 155 "arguments"); 156 } 157 158 buffer = (void*)(((addr_t)buffer + 7) & ~(addr_t)0x7); 159 memcpy(buffer, gBootVolume.Buffer(), gBootVolume.ContentSize()); 160 gKernelArgs.boot_volume = buffer; 161 gKernelArgs.boot_volume_size = gBootVolume.ContentSize(); 162 163 platform_cleanup_devices(); 164 // TODO: cleanup, heap_release() etc. 165 heap_print_statistics(); 166 platform_start_kernel(); 167 } 168 } 169 170 out: 171 heap_release(args); 172 return 0; 173 } 174