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