Removed vestigal FILO code
[gpxe.git] / src / core / main.c
blob2f76cc27d7e84b5054e96fedfd0578000e29014f
1 /**************************************************************************
2 Etherboot - Network Bootstrap Program
4 Literature dealing with the network protocols:
5 ARP - RFC826
6 RARP - RFC903
7 UDP - RFC768
8 BOOTP - RFC951, RFC2132 (vendor extensions)
9 DHCP - RFC2131, RFC2132 (options)
10 TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
11 RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
12 NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)
13 IGMP - RFC1112
15 **************************************************************************/
17 /* #define MDEBUG */
19 #include "etherboot.h"
20 #include "dev.h"
21 #include "nic.h"
22 #include "disk.h"
23 #include "timer.h"
24 #include "cpu.h"
25 #include "console.h"
26 #include <gpxe/init.h>
27 #include "image.h"
28 #include <stdarg.h>
30 #include <gpxe/device.h>
31 #include <gpxe/heap.h>
32 #include <gpxe/netdevice.h>
34 /* Linker symbols */
35 extern char _bss[], _ebss[];
37 jmp_buf restart_etherboot;
38 int url_port;
40 char as_main_program = 1;
42 #if 0
44 static inline unsigned long ask_boot(unsigned *index)
46 unsigned long order = DEFAULT_BOOT_ORDER;
47 *index = DEFAULT_BOOT_INDEX;
48 #ifdef LINUXBIOS
49 order = get_boot_order(order, index);
50 #endif
51 #if defined(ASK_BOOT)
52 #if ASK_BOOT >= 0
53 while(1) {
54 int c = 0;
55 printf(ASK_PROMPT);
56 #if ASK_BOOT > 0
58 unsigned long time;
59 for ( time = currticks() + ASK_BOOT*TICKS_PER_SEC;
60 !c && !iskey(); ) {
61 if (currticks() > time) c = ANS_DEFAULT;
64 #endif /* ASK_BOOT > 0 */
65 if ( !c ) c = getchar();
66 if ((c >= 'a') && (c <= 'z')) c &= 0x5F;
67 if ((c >= ' ') && (c <= '~')) putchar(c);
68 putchar('\n');
70 switch(c) {
71 default:
72 /* Nothing useful try again */
73 continue;
74 case ANS_QUIT:
75 order = BOOT_NOTHING;
76 *index = 0;
77 break;
78 case ANS_DEFAULT:
79 /* Preserve the default boot order */
80 break;
81 case ANS_NETWORK:
82 order = (BOOT_NIC << (0*BOOT_BITS)) |
83 (BOOT_NOTHING << (1*BOOT_BITS));
84 *index = 0;
85 break;
86 case ANS_DISK:
87 order = (BOOT_DISK << (0*BOOT_BITS)) |
88 (BOOT_NOTHING << (1*BOOT_BITS));
89 *index = 0;
90 break;
91 case ANS_FLOPPY:
92 order = (BOOT_FLOPPY << (0*BOOT_BITS)) |
93 (BOOT_NOTHING << (1*BOOT_BITS));
94 *index = 0;
95 break;
97 break;
99 putchar('\n');
100 #endif /* ASK_BOOT >= 0 */
101 #endif /* defined(ASK_BOOT) */
102 return order;
105 static inline void try_floppy_first(void)
107 #if (TRY_FLOPPY_FIRST > 0)
108 int i;
109 printf("Trying floppy");
110 disk_init();
111 for (i = TRY_FLOPPY_FIRST; i-- > 0; ) {
112 putchar('.');
113 if (pcbios_disk_read(0, 0, 0, 0, ((char *)FLOPPY_BOOT_LOCATION)) != 0x8000) {
114 printf("using floppy\n");
115 exit(0);
118 printf("no floppy\n");
119 #endif /* TRY_FLOPPY_FIRST */
122 static struct class_operations {
123 struct dev *dev;
124 int (*probe)(struct dev *dev);
125 int (*load_configuration)(struct dev *dev);
126 int (*load)(struct dev *dev);
128 operations[] = {
129 { &nic.dev, eth_probe, eth_load_configuration, eth_load },
130 { &disk.dev, disk_probe, disk_load_configuration, disk_load },
131 { &disk.dev, disk_probe, disk_load_configuration, disk_load },
134 #endif
138 static int main_loop(int state);
139 static int exit_ok;
140 static int exit_status;
141 static int initialized;
144 /**************************************************************************
145 MAIN - Kick off routine
146 **************************************************************************/
147 int main ( void ) {
148 struct net_device *netdev;
150 /* Call all registered initialisation functions */
151 init_heap();
152 call_init_fns ();
153 probe_devices();
155 netdev = next_netdev ();
156 if ( netdev ) {
157 test_aoeboot ( netdev );
158 } else {
159 printf ( "No network device found\n" );
162 printf ( "Press any key to exit\n" );
163 getchar();
165 remove_devices();
166 call_exit_fns ();
168 return exit_status;
171 #if 0
173 void exit(int status)
175 while(!exit_ok)
177 exit_status = status;
178 longjmp(restart_etherboot, 255);
183 static int main_loop(int state)
185 /* Splitting main into 2 pieces makes the semantics of
186 * which variables are preserved across a longjmp clean
187 * and predictable.
189 static unsigned long order;
190 static unsigned boot_index;
191 static struct dev * dev = 0;
192 static struct class_operations *ops;
193 static int type;
194 static int i;
196 if (!initialized) {
197 initialized = 1;
198 if (dev && (state >= 1) && (state <= 2)) {
199 dev->how_probe = PROBE_AWAKE;
200 dev->how_probe = ops->probe(dev);
201 if (dev->how_probe == PROBE_FAILED) {
202 state = -1;
204 if (state == 1) {
205 /* The bootp reply might have been changed, re-parse. */
206 decode_rfc1533(bootp_data.bootp_reply.bp_vend, 0,
207 #ifdef NO_DHCP_SUPPORT
208 BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN,
209 #else
210 DHCP_OPT_LEN + MAX_BOOTP_EXTLEN,
211 #endif /* NO_DHCP_SUPPORT */
216 switch(state) {
217 case 0:
219 static int firsttime = 1;
220 /* First time through */
221 if (firsttime) {
222 cleanup();
223 firsttime = 0;
225 #ifdef EXIT_IF_NO_OFFER
226 else {
227 cleanup();
228 exit(0);
230 #endif
231 i = -1;
232 state = 4;
233 dev = 0;
235 /* We just called setjmp ... */
236 order = ask_boot(&boot_index);
237 try_floppy_first();
238 break;
240 case 4:
241 cleanup();
242 call_reset_fns();
243 /* Find a dev entry to probe with */
244 if (!dev) {
245 int boot;
246 int failsafe;
248 /* Advance to the next device type */
249 i++;
250 boot = (order >> (i * BOOT_BITS)) & BOOT_MASK;
251 type = boot & BOOT_TYPE_MASK;
252 failsafe = (boot & BOOT_FAILSAFE) != 0;
253 if (i >= MAX_BOOT_ENTRIES) {
254 type = BOOT_NOTHING;
256 if ((i == 0) && (type == BOOT_NOTHING)) {
257 /* Return to caller */
258 exit(0);
260 if (type >= BOOT_NOTHING) {
261 interruptible_sleep(2);
262 state = 0;
263 break;
265 ops = &operations[type];
266 dev = ops->dev;
267 dev->how_probe = PROBE_FIRST;
268 dev->type = type;
269 dev->failsafe = failsafe;
270 dev->type_index = 0;
271 } else {
272 /* Advance to the next device of the same type */
273 dev->how_probe = PROBE_NEXT;
275 state = 3;
276 break;
277 case 3:
278 state = -1;
279 /* Removed the following line because it was causing
280 * heap.o to be dragged in unnecessarily. It's also
281 * slightly puzzling: by resetting heap_base, doesn't
282 * this mean that we permanently leak memory?
284 /* heap_base = allot(0); */
285 dev->how_probe = ops->probe(dev);
286 if (dev->how_probe == PROBE_FAILED) {
287 dev = 0;
288 state = 4;
289 } else if (boot_index && (i == 0) && (boot_index != (unsigned)dev->type_index)) {
290 printf("Wrong index\n");
291 state = 4;
293 else {
294 state = 2;
296 break;
297 case 2:
298 state = -1;
299 if (ops->load_configuration(dev) >= 0) {
300 state = 1;
302 break;
303 case 1:
304 /* Any return from load is a failure */
305 ops->load(dev);
306 state = -1;
307 break;
308 case 256:
309 state = 0;
310 break;
311 case -3:
312 i = MAX_BOOT_ENTRIES;
313 type = BOOT_NOTHING;
314 /* fall through */
315 default:
316 printf("<abort>\n");
317 state = 4;
318 /* At the end goto state 0 */
319 if ((type >= BOOT_NOTHING) || (i >= MAX_BOOT_ENTRIES)) {
320 state = 0;
322 break;
324 return state;
328 #endif
331 /**************************************************************************
332 LOADKERNEL - Try to load kernel image
333 **************************************************************************/
334 #if 0
335 /* To be split out into individual files */
336 static const struct proto protos[] = {
337 { "x-tftm", url_tftm },
338 { "x-slam", url_slam },
339 { "nfs", nfs },
340 { "file", url_file },
341 { "tftp", tftp },
342 { "http", http },
344 #endif
347 /**************************************************************************
348 CLEANUP - shut down networking and console so that the OS may be called
349 **************************************************************************/
350 void cleanup(void)
352 /* Stop receiving packets */
353 disable ( &dev );
354 initialized = 0;
358 * Local variables:
359 * c-basic-offset: 8
360 * End: