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
16 #include "exceptions.h"
20 #include "kbootconf.h"
37 extern u64 _thread1_active
;
39 static int boot_entry
= 0;
40 static void *kernel_buf
;
42 static void *initrd_buf
;
44 extern u8 __vmlinux
[], __vmlinux_end
[1];
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
);
77 void seq_tftp_get(const char *name
, void *buf
, size_t bufsize
, enum state_t next
)
80 gstate
= STATE_WAIT_TFTP
;
81 tftp_get(tftp
, name
, buf
, bufsize
, tftp_cb
, NULL
);
86 static int tick
= 0, tack
= 0;
89 printf("Waiting for DHCP lease...\n");
90 gstate
= STATE_WAIT_NET
;
102 printf("Timed out...\n");
106 if (eth
.dhcp
->state
== DHCP_BOUND
) {
107 gstate
= 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
);
119 printf(" Bootfile: NONE\n");
125 if (eth
.dhcp
->offered_si_addr
.addr
== 0 || !eth
.dhcp
->boot_file_name
) {
127 printf("Missing boot settings, falling back to embedded kernel...\n");
133 fatal("tftp alloc failed");
135 tftp_connect(tftp
, ð
.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
);
145 if (t_status
!= TFTP_STATUS_OK
) {
146 printf("Transfer did not complete successfully\n");
147 printf("Rebooting...\n");
151 printf("Configuration: %ld bytes\n", t_recvd
);
152 conf_buf
[t_recvd
] = 0;
156 if (conf
.num_kernels
== 0) {
157 printf("No kernels found in configuration file. Rebooting...\n");
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
);
170 case STATE_GOT_KERNEL
:
171 if (t_status
!= TFTP_STATUS_OK
) {
172 printf("Transfer did not complete successfully. Rebooting...\n");
176 if (kernel_load(kernel_buf
, t_recvd
) != 0) {
177 printf("Failed to load kernel. Rebooting...\n");
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
);
190 case STATE_GOT_INITRD
:
191 if (t_status
!= TFTP_STATUS_OK
) {
192 printf("Transfer did not complete successfully. Rebooting...\n");
196 mm_highmem_reserve(t_recvd
);
197 kernel_set_initrd(initrd_buf
, t_recvd
);
203 kernel_build_cmdline(conf
.kernels
[boot_entry
].parameters
, conf
.kernels
[boot_entry
].root
);
204 shutdown_and_launch();
207 case STATE_WAIT_TFTP
:
219 int readfile(char *name
, void *buf
, u32 maxlen
)
225 res
= f_open(&fil
, name
, FA_READ
);
228 res
= f_read(&fil
, buf
, maxlen
, &bytes_read
);
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");
253 gstate
= STATE_START
;
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
);
271 fatal("f_mount() failed");
273 printf("Reading kboot.conf...\n");
274 res
= readfile("/kboot.conf", conf_buf
, MAX_KBOOTCONF_SIZE
-1);
276 printf("Could not read kboot.conf (%d), panicking\n", res
);
282 if (conf
.num_kernels
== 0) {
283 printf("No kernels found in configuration file. Panicing...\n");
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());
295 printf("Could not read kernel (%d), panicking\n", res
);
298 printf("Kernel size: %d\n", res
);
300 if (kernel_load(kernel_buf
, res
) != 0) {
301 printf("Failed to load kernel. Rebooting...\n");
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());
309 printf("Could not read initrd (%d), panicking\n", res
);
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
);
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
);
331 printf("Cannot decompress kernel, error %d.\n", res
);
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");
340 kernel_build_cmdline("video=ps3fb:mode:0 panic=5", "/dev/sda1");
341 shutdown_and_launch();
343 printf("End of main() reached! Rebooting...\n");
349 void shutdown_and_launch(void)