Added boot process information to help someone find out what really happens.
[bootos.git] / stage2 / main.c
blob84e551bb9023de236714f5c6e546f5ced457aa91
1 /* main.c - AsbestOS Stage2 main C entrypoint
3 Copyright (C) 2010-2011 Hector Martin "marcan" <hector@marcansoft.com>
5 This code is licensed to you under the terms of the GNU GPL, version 2;
6 see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
7 */
9 #include "config.h"
10 #include "types.h"
11 #include "lv1call.h"
12 #include "debug.h"
13 #include "malloc.h"
14 #include "time.h"
15 #include "device.h"
16 #include "exceptions.h"
17 #include "mm.h"
18 #include "cleanup.h"
19 #include "kernel.h"
20 #include "kbootconf.h"
21 #include "zpipe.h"
23 #include "tftp.h"
25 #ifdef USE_NETWORK
26 # include "network.h"
27 #endif
28 #ifdef NETRPC_ENABLE
29 # include "netrpc.h"
30 #endif
32 #ifdef AUTO_HDD
33 # include "ff.h"
34 # include "diskio.h"
35 #endif
37 extern u64 _thread1_active;
39 static int boot_entry = 0;
40 static void *kernel_buf;
41 static u64 kernel_sz;
42 static void *initrd_buf;
44 extern u8 __vmlinux[], __vmlinux_end[1];
46 #ifdef USE_NETWORK
47 enum state_t {
48 STATE_START,
49 STATE_WAIT_NET,
50 STATE_GOT_NET,
51 STATE_GOT_CONF,
52 STATE_GOT_KERNEL,
53 STATE_GOT_INITRD,
54 STATE_BOOT,
55 STATE_WAIT_TFTP,
56 STATE_IDLE,
59 static enum state_t gstate;
61 static struct tftp_client *tftp = NULL;
62 static enum state_t t_next;
63 static enum tftp_status t_status;
64 static size_t t_recvd;
66 void shutdown_and_launch(void);
68 void tftp_cb(void *arg, struct tftp_client *clt, enum tftp_status status, size_t recvd)
70 printf("Transfer complete, status %d, size: %ld bytes\n", status, recvd);
72 t_recvd = recvd;
73 t_status = status;
74 gstate = t_next;
77 void seq_tftp_get(const char *name, void *buf, size_t bufsize, enum state_t next)
79 t_next = next;
80 gstate = STATE_WAIT_TFTP;
81 tftp_get(tftp, name, buf, bufsize, tftp_cb, NULL);
84 int sequence(void)
86 static int tick = 0, tack = 0;
87 switch (gstate) {
88 case STATE_START:
89 printf("Waiting for DHCP lease...\n");
90 gstate = STATE_WAIT_NET;
91 break;
92 case STATE_WAIT_NET:
93 if (!(tick & 0xFFFF))
95 tick = 0;
96 tack++;
98 tick++;
99 if (tack == 1000)
101 tftp = tftp_new();
102 printf("Timed out...\n");
103 return 1;
106 if (eth.dhcp->state == DHCP_BOUND) {
107 gstate = STATE_GOT_NET;
109 break;
110 case STATE_GOT_NET:
111 printf("Network is up:\n");
112 printf(" IP address: %d.%d.%d.%d\n", P_IP(eth.ip_addr.addr));
113 printf(" Netmask: %d.%d.%d.%d\n", P_IP(eth.netmask.addr));
114 printf(" Gateway: %d.%d.%d.%d\n", P_IP(eth.gw.addr));
115 printf(" TFTP server: %d.%d.%d.%d\n", P_IP(eth.dhcp->offered_si_addr.addr));
116 if (eth.dhcp->boot_file_name)
117 printf(" Bootfile: %s\n", eth.dhcp->boot_file_name);
118 else
119 printf(" Bootfile: NONE\n");
121 #ifdef NETRPC_ENABLE
122 netrpc_init();
123 #endif
124 #ifdef AUTO_TFTP
125 if (eth.dhcp->offered_si_addr.addr == 0 || !eth.dhcp->boot_file_name) {
126 tftp = tftp_new();
127 printf("Missing boot settings, falling back to embedded kernel...\n");
128 return 1;
131 tftp = tftp_new();
132 if (!tftp)
133 fatal("tftp alloc failed");
135 tftp_connect(tftp, &eth.dhcp->offered_si_addr, 69);
137 printf("Downloading configuration file...\n");
138 seq_tftp_get((char*)eth.dhcp->boot_file_name, conf_buf, MAX_KBOOTCONF_SIZE-1, STATE_GOT_CONF);
139 #else
140 gstate = STATE_IDLE;
141 #endif
142 break;
144 case STATE_GOT_CONF:
145 if (t_status != TFTP_STATUS_OK) {
146 printf("Transfer did not complete successfully\n");
147 printf("Rebooting...\n");
148 lv1_panic(1);
151 printf("Configuration: %ld bytes\n", t_recvd);
152 conf_buf[t_recvd] = 0;
154 kbootconf_parse();
156 if (conf.num_kernels == 0) {
157 printf("No kernels found in configuration file. Rebooting...\n");
158 lv1_panic(1);
161 boot_entry = conf.default_idx;
163 printf("Starting to boot '%s'\n", conf.kernels[boot_entry].label);
164 printf("Downloading kernel...\n");
166 kernel_buf = mm_highmem_freestart();
167 seq_tftp_get(conf.kernels[boot_entry].kernel, kernel_buf, mm_highmem_freesize(), STATE_GOT_KERNEL);
168 break;
170 case STATE_GOT_KERNEL:
171 if (t_status != TFTP_STATUS_OK) {
172 printf("Transfer did not complete successfully. Rebooting...\n");
173 lv1_panic(1);
176 if (kernel_load(kernel_buf, t_recvd) != 0) {
177 printf("Failed to load kernel. Rebooting...\n");
178 lv1_panic(1);
181 if (conf.kernels[boot_entry].initrd && conf.kernels[boot_entry].initrd[0]) {
182 printf("Downloading initrd...\n");
183 initrd_buf = mm_highmem_freestart();
184 seq_tftp_get(conf.kernels[boot_entry].initrd, initrd_buf, mm_highmem_freesize(), STATE_GOT_INITRD);
185 } else {
186 gstate = STATE_BOOT;
188 break;
190 case STATE_GOT_INITRD:
191 if (t_status != TFTP_STATUS_OK) {
192 printf("Transfer did not complete successfully. Rebooting...\n");
193 lv1_panic(1);
196 mm_highmem_reserve(t_recvd);
197 kernel_set_initrd(initrd_buf, t_recvd);
199 gstate = STATE_BOOT;
200 break;
202 case STATE_BOOT:
203 kernel_build_cmdline(conf.kernels[boot_entry].parameters, conf.kernels[boot_entry].root);
204 shutdown_and_launch();
205 break;
207 case STATE_WAIT_TFTP:
208 break;
210 case STATE_IDLE:
211 break;
214 return 0;
216 #endif
218 #ifdef AUTO_HDD
219 int readfile(char *name, void *buf, u32 maxlen)
221 static FIL fil;
222 FRESULT res;
223 u32 bytes_read;
225 res = f_open(&fil, name, FA_READ);
226 if (res != FR_OK)
227 return -res;
228 res = f_read(&fil, buf, maxlen, &bytes_read);
229 if (res != FR_OK)
230 return -res;
231 f_close(&fil);
232 return bytes_read;
234 #endif
236 int main(void)
238 int res;
239 udelay(2000000);
240 debug_init();
241 printf("\n\nBootOS Stage 2 starting.\n");
242 printf("Waiting for thread 1...\n");
243 while(!_thread1_active);
244 printf("Thread 1 is alive, all systems go.\n");
246 exceptions_init();
247 lv2_cleanup();
248 mm_init();
250 #ifdef USE_NETWORK
251 net_init();
253 gstate = STATE_START;
254 while(1) {
255 net_poll();
256 if(sequence())
257 break;
259 #endif
260 #ifdef AUTO_HDD
261 static FATFS fatfs;
262 DSTATUS stat;
264 stat = disk_initialize(0);
265 if (stat & ~STA_PROTECT)
266 fatal("disk_initialize() failed");
268 printf("Mounting filesystem...\n");
269 res = f_mount(0, &fatfs);
270 if (res != FR_OK)
271 fatal("f_mount() failed");
273 printf("Reading kboot.conf...\n");
274 res = readfile("/kboot.conf", conf_buf, MAX_KBOOTCONF_SIZE-1);
275 if (res <= 0) {
276 printf("Could not read kboot.conf (%d), panicking\n", res);
277 lv1_panic(0);
279 conf_buf[res] = 0;
280 kbootconf_parse();
282 if (conf.num_kernels == 0) {
283 printf("No kernels found in configuration file. Panicing...\n");
284 lv1_panic(0);
287 boot_entry = conf.default_idx;
289 printf("Starting to boot '%s'\n", conf.kernels[boot_entry].label);
290 printf("Loading kernel (%s)...\n", conf.kernels[boot_entry].kernel);
292 kernel_buf = mm_highmem_freestart();
293 res = readfile(conf.kernels[boot_entry].kernel, kernel_buf, mm_highmem_freesize());
294 if (res <= 0) {
295 printf("Could not read kernel (%d), panicking\n", res);
296 lv1_panic(0);
298 printf("Kernel size: %d\n", res);
300 if (kernel_load(kernel_buf, res) != 0) {
301 printf("Failed to load kernel. Rebooting...\n");
302 lv1_panic(1);
305 if (conf.kernels[boot_entry].initrd && conf.kernels[boot_entry].initrd[0]) {
306 initrd_buf = mm_highmem_freestart();
307 res = readfile(conf.kernels[boot_entry].initrd, initrd_buf, mm_highmem_freesize());
308 if (res <= 0) {
309 printf("Could not read initrd (%d), panicking\n", res);
310 lv1_panic(0);
312 printf("Initrd size: %d\n", res);
313 mm_highmem_reserve(res);
314 kernel_set_initrd(initrd_buf, res);
317 kernel_build_cmdline(conf.kernels[boot_entry].parameters, conf.kernels[boot_entry].root);
319 f_mount(0, NULL);
320 disk_shutdown(0);
321 mm_shutdown();
322 kernel_launch();
324 #endif
325 printf("Loading embedded kernel...\n");
326 kernel_buf = mm_highmem_freestart();
327 printf("Decompressing kernel to %lX...\n", (u64) kernel_buf);
328 res = unzpipe (kernel_buf, __vmlinux, &kernel_sz);
329 if (res)
331 printf("Cannot decompress kernel, error %d.\n", res);
332 lv1_panic(1);
334 printf("Kernel size: %ld\n", kernel_sz);
335 if (kernel_load(kernel_buf, kernel_sz) != 0)
337 printf("Failed to load embedded kernel. Rebooting...\n");
338 lv1_panic(1);
340 kernel_build_cmdline("video=ps3fb:mode:0 panic=5", "/dev/sda1");
341 shutdown_and_launch();
343 printf("End of main() reached! Rebooting...\n");
344 lv1_panic(1);
345 return 0;
348 #ifdef USE_NETWORK
349 void shutdown_and_launch(void)
351 #ifdef NETRPC_ENABLE
352 netrpc_shutdown();
353 #endif
354 if (tftp)
355 tftp_remove(tftp);
357 net_shutdown();
358 mm_shutdown();
359 kernel_launch();
361 #endif