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