xref: /haiku/src/system/boot/loader/main.cpp (revision 344ded80d400028c8f561b4b876257b94c12db4a)
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