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