Move header file for usr/autoboot.c to include/usr
[people/dverkamp/gpxe.git] / src / core / main.c
1 /**************************************************************************
2 Etherboot -  Network Bootstrap Program
3
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
14
15 **************************************************************************/
16
17 /* #define MDEBUG */
18
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 "cmdline.h"
26 #include "console.h"
27 #include <gpxe/init.h>
28 #include "image.h"
29 #include <stdarg.h>
30
31 #include <gpxe/device.h>
32 #include <gpxe/heap.h>
33 #include <gpxe/netdevice.h>
34 #include <gpxe/shell.h>
35 #include <gpxe/shell_banner.h>
36 #include <usr/autoboot.h>
37
38 /* Linker symbols */
39 extern char _bss[], _ebss[];
40
41 jmp_buf restart_etherboot;
42 int     url_port;               
43
44 char as_main_program = 1;
45
46 #if 0
47
48 static inline unsigned long ask_boot(unsigned *index)
49 {
50         unsigned long order = DEFAULT_BOOT_ORDER;
51         *index = DEFAULT_BOOT_INDEX;
52 #ifdef LINUXBIOS
53         order = get_boot_order(order, index);
54 #endif
55 #if defined(ASK_BOOT)
56 #if ASK_BOOT >= 0
57         while(1) {
58                 int c = 0;
59                 printf(ASK_PROMPT);
60 #if ASK_BOOT > 0
61                 {
62                         unsigned long time;
63                         for ( time = currticks() + ASK_BOOT*TICKS_PER_SEC;
64                               !c && !iskey(); ) {
65                                 if (currticks() > time) c = ANS_DEFAULT;
66                         }
67                 }
68 #endif /* ASK_BOOT > 0 */
69                 if ( !c ) c = getchar();
70                 if ((c >= 'a') && (c <= 'z')) c &= 0x5F;
71                 if ((c >= ' ') && (c <= '~')) putchar(c);
72                 putchar('\n');
73
74                 switch(c) {
75                 default:
76                         /* Nothing useful try again */
77                         continue;
78                 case ANS_QUIT:
79                         order = BOOT_NOTHING;
80                         *index = 0;
81                         break;
82                 case ANS_DEFAULT:
83                         /* Preserve the default boot order */
84                         break;
85                 case ANS_NETWORK:
86                         order = (BOOT_NIC     << (0*BOOT_BITS)) | 
87                                 (BOOT_NOTHING << (1*BOOT_BITS));
88                         *index = 0;
89                         break;
90                 case ANS_DISK:
91                         order = (BOOT_DISK    << (0*BOOT_BITS)) | 
92                                 (BOOT_NOTHING << (1*BOOT_BITS));
93                         *index = 0;
94                         break;
95                 case ANS_FLOPPY:
96                         order = (BOOT_FLOPPY  << (0*BOOT_BITS)) | 
97                                 (BOOT_NOTHING << (1*BOOT_BITS));
98                         *index = 0;
99                         break;
100                 }
101                 break;
102         }
103         putchar('\n');
104 #endif /* ASK_BOOT >= 0 */
105 #endif /* defined(ASK_BOOT) */
106         return order;
107 }
108
109 static inline void try_floppy_first(void)
110 {
111 #if (TRY_FLOPPY_FIRST > 0)
112         int i;
113         printf("Trying floppy");
114         disk_init();
115         for (i = TRY_FLOPPY_FIRST; i-- > 0; ) {
116                 putchar('.');
117                 if (pcbios_disk_read(0, 0, 0, 0, ((char *)FLOPPY_BOOT_LOCATION)) != 0x8000) {
118                         printf("using floppy\n");
119                         exit(0);
120                 }
121         }
122         printf("no floppy\n");
123 #endif /* TRY_FLOPPY_FIRST */   
124 }
125
126 static struct class_operations {
127         struct dev *dev;
128         int (*probe)(struct dev *dev);
129         int (*load_configuration)(struct dev *dev);
130         int (*load)(struct dev *dev);
131 }
132 operations[] = {
133         { &nic.dev,  eth_probe,  eth_load_configuration,  eth_load  },
134         { &disk.dev, disk_probe, disk_load_configuration, disk_load },
135         { &disk.dev, disk_probe, disk_load_configuration, disk_load },
136 };
137
138 #endif
139
140 #if 0
141 static int main_loop(int state);
142 static int exit_ok;
143 static int initialized;
144 #endif
145
146 static int exit_status;
147
148 /**************************************************************************
149 MAIN - Kick off routine
150 **************************************************************************/
151 int main ( void ) {
152
153         /* Call all registered initialisation functions */
154         init_heap();
155         call_init_fns ();
156         probe_devices();
157
158         /* Try autobooting if we're not going straight to the shell */
159         if ( ! shell_banner() ) {
160                 autoboot();
161         }
162         
163         /* Autobooting failed or the user wanted the shell */
164         shell();
165
166         remove_devices();
167         call_exit_fns ();
168
169         return exit_status;
170 }
171
172 #if 0
173
174 void exit(int status)
175 {
176         while(!exit_ok)
177                 ;
178         exit_status = status;
179         longjmp(restart_etherboot, 255);
180 }
181
182
183
184 static int main_loop(int state)
185 {
186         /* Splitting main into 2 pieces makes the semantics of 
187          * which variables are preserved across a longjmp clean
188          * and predictable.
189          */
190         static unsigned long order;
191         static unsigned boot_index;
192         static struct dev * dev = 0;
193         static struct class_operations *ops;
194         static int type;
195         static int i;
196
197         if (!initialized) {
198                 initialized = 1;
199                 if (dev && (state >= 1) && (state <= 2)) {
200                         dev->how_probe = PROBE_AWAKE;
201                         dev->how_probe = ops->probe(dev);
202                         if (dev->how_probe == PROBE_FAILED) {
203                                 state = -1;
204                         }
205                         if (state == 1) {
206                                 /* The bootp reply might have been changed, re-parse.  */
207                                 decode_rfc1533(bootp_data.bootp_reply.bp_vend, 0,
208 #ifdef  NO_DHCP_SUPPORT
209                                                BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, 
210 #else
211                                                DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 
212 #endif  /* NO_DHCP_SUPPORT */
213                                                1);
214                         }
215                 }
216         }
217         switch(state) {
218         case 0:
219         {
220                 static int firsttime = 1;
221                 /* First time through */
222                 if (firsttime) {
223                         cleanup();
224                         firsttime = 0;
225                 } 
226 #ifdef  EXIT_IF_NO_OFFER
227                 else {
228                         cleanup();
229                         exit(0);
230                 }
231 #endif
232                 i = -1;
233                 state = 4;
234                 dev = 0;
235
236                 /* We just called setjmp ... */
237                 order = ask_boot(&boot_index);
238                 try_floppy_first();
239                 break;
240         }
241         case 4:
242                 cleanup();
243                 call_reset_fns();
244                 /* Find a dev entry to probe with */
245                 if (!dev) {
246                         int boot;
247                         int failsafe;
248
249                         /* Advance to the next device type */
250                         i++;
251                         boot = (order >> (i * BOOT_BITS)) & BOOT_MASK;
252                         type = boot & BOOT_TYPE_MASK;
253                         failsafe = (boot & BOOT_FAILSAFE) != 0;
254                         if (i >= MAX_BOOT_ENTRIES) {
255                                 type = BOOT_NOTHING;
256                         }
257                         if ((i == 0) && (type == BOOT_NOTHING)) {
258                                 /* Return to caller */
259                                 exit(0);
260                         }
261                         if (type >= BOOT_NOTHING) {
262                                 interruptible_sleep(2);
263                                 state = 0;
264                                 break;
265                         }
266                         ops = &operations[type];
267                         dev = ops->dev;
268                         dev->how_probe = PROBE_FIRST;
269                         dev->type = type;
270                         dev->failsafe = failsafe;
271                         dev->type_index = 0;
272                 } else {
273                         /* Advance to the next device of the same type */
274                         dev->how_probe = PROBE_NEXT;
275                 }
276                 state = 3;
277                 break;
278         case 3:
279                 state = -1;
280                 /* Removed the following line because it was causing
281                  * heap.o to be dragged in unnecessarily.  It's also
282                  * slightly puzzling: by resetting heap_base, doesn't
283                  * this mean that we permanently leak memory?
284                  */
285                 /* heap_base = allot(0); */
286                 dev->how_probe = ops->probe(dev);
287                 if (dev->how_probe == PROBE_FAILED) {
288                         dev = 0;
289                         state = 4;
290                 } else if (boot_index && (i == 0) && (boot_index != (unsigned)dev->type_index)) {
291                         printf("Wrong index\n");
292                         state = 4;
293                 }
294                 else {
295                         state = 2;
296                 }
297                 break;
298         case 2:
299                 state = -1;
300                 if (ops->load_configuration(dev) >= 0) {
301                         state = 1;
302                 }
303                 break;
304         case 1:
305                 /* Any return from load is a failure */
306                 ops->load(dev);
307                 state = -1;
308                 break;
309         case 256:
310                 state = 0;
311                 break;
312         case -3:
313                 i = MAX_BOOT_ENTRIES;
314                 type = BOOT_NOTHING;
315                 /* fall through */
316         default:
317                 printf("<abort>\n");
318                 state = 4;
319                 /* At the end goto state 0 */
320                 if ((type >= BOOT_NOTHING) || (i >= MAX_BOOT_ENTRIES)) {
321                         state = 0;
322                 }
323                 break;
324         }
325         return state;
326 }
327
328
329 #endif
330
331
332 /**************************************************************************
333 LOADKERNEL - Try to load kernel image
334 **************************************************************************/
335 #if 0
336 /* To be split out into individual files */
337 static const struct proto protos[] = {
338         { "x-tftm", url_tftm },
339         { "x-slam", url_slam },
340         { "nfs", nfs },
341         { "file", url_file },
342         { "tftp", tftp },
343         { "http", http },
344 };
345 #endif
346
347 /**************************************************************************
348 CLEANUP - shut down networking and console so that the OS may be called 
349 **************************************************************************/
350 #if 0
351 void cleanup(void)
352 {
353         /* Stop receiving packets */
354         disable ( &dev );
355         initialized = 0;
356 }
357 #endif
358
359 /*
360  * Local variables:
361  *  c-basic-offset: 8
362  * End:
363  */