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