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