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