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