1 /**************************************************************************
2 Etherboot - Network Bootstrap Program
4 Literature dealing with the network protocols:
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)
15 **************************************************************************/
19 #include "etherboot.h"
27 #include <gpxe/init.h>
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>
38 extern char _bss[], _ebss[];
40 jmp_buf restart_etherboot;
43 char as_main_program = 1;
47 static inline unsigned long ask_boot(unsigned *index)
49 unsigned long order = DEFAULT_BOOT_ORDER;
50 *index = DEFAULT_BOOT_INDEX;
52 order = get_boot_order(order, index);
62 for ( time = currticks() + ASK_BOOT*TICKS_PER_SEC;
64 if (currticks() > time) c = ANS_DEFAULT;
67 #endif /* ASK_BOOT > 0 */
68 if ( !c ) c = getchar();
69 if ((c >= 'a') && (c <= 'z')) c &= 0x5F;
70 if ((c >= ' ') && (c <= '~')) putchar(c);
75 /* Nothing useful try again */
82 /* Preserve the default boot order */
85 order = (BOOT_NIC << (0*BOOT_BITS)) |
86 (BOOT_NOTHING << (1*BOOT_BITS));
90 order = (BOOT_DISK << (0*BOOT_BITS)) |
91 (BOOT_NOTHING << (1*BOOT_BITS));
95 order = (BOOT_FLOPPY << (0*BOOT_BITS)) |
96 (BOOT_NOTHING << (1*BOOT_BITS));
103 #endif /* ASK_BOOT >= 0 */
104 #endif /* defined(ASK_BOOT) */
108 static inline void try_floppy_first(void)
110 #if (TRY_FLOPPY_FIRST > 0)
112 printf("Trying floppy");
114 for (i = TRY_FLOPPY_FIRST; i-- > 0; ) {
116 if (pcbios_disk_read(0, 0, 0, 0, ((char *)FLOPPY_BOOT_LOCATION)) != 0x8000) {
117 printf("using floppy\n");
121 printf("no floppy\n");
122 #endif /* TRY_FLOPPY_FIRST */
125 static struct class_operations {
127 int (*probe)(struct dev *dev);
128 int (*load_configuration)(struct dev *dev);
129 int (*load)(struct dev *dev);
132 { &nic.dev, eth_probe, eth_load_configuration, eth_load },
133 { &disk.dev, disk_probe, disk_load_configuration, disk_load },
134 { &disk.dev, disk_probe, disk_load_configuration, disk_load },
140 static int main_loop(int state);
142 static int initialized;
145 static int exit_status;
147 void test_dhcp ( struct net_device *netdev );
149 /**************************************************************************
150 MAIN - Kick off routine
151 **************************************************************************/
153 struct net_device *netdev;
155 /* Call all registered initialisation functions */
160 if ( shell_banner() ) {
164 netdev = next_netdev ();
166 test_dhcp ( netdev );
168 printf ( "No network device found\n" );
171 printf ( "Press any key to exit\n" );
182 void exit(int status)
186 exit_status = status;
187 longjmp(restart_etherboot, 255);
192 static int main_loop(int state)
194 /* Splitting main into 2 pieces makes the semantics of
195 * which variables are preserved across a longjmp clean
198 static unsigned long order;
199 static unsigned boot_index;
200 static struct dev * dev = 0;
201 static struct class_operations *ops;
207 if (dev && (state >= 1) && (state <= 2)) {
208 dev->how_probe = PROBE_AWAKE;
209 dev->how_probe = ops->probe(dev);
210 if (dev->how_probe == PROBE_FAILED) {
214 /* The bootp reply might have been changed, re-parse. */
215 decode_rfc1533(bootp_data.bootp_reply.bp_vend, 0,
216 #ifdef NO_DHCP_SUPPORT
217 BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN,
219 DHCP_OPT_LEN + MAX_BOOTP_EXTLEN,
220 #endif /* NO_DHCP_SUPPORT */
228 static int firsttime = 1;
229 /* First time through */
234 #ifdef EXIT_IF_NO_OFFER
244 /* We just called setjmp ... */
245 order = ask_boot(&boot_index);
252 /* Find a dev entry to probe with */
257 /* Advance to the next device type */
259 boot = (order >> (i * BOOT_BITS)) & BOOT_MASK;
260 type = boot & BOOT_TYPE_MASK;
261 failsafe = (boot & BOOT_FAILSAFE) != 0;
262 if (i >= MAX_BOOT_ENTRIES) {
265 if ((i == 0) && (type == BOOT_NOTHING)) {
266 /* Return to caller */
269 if (type >= BOOT_NOTHING) {
270 interruptible_sleep(2);
274 ops = &operations[type];
276 dev->how_probe = PROBE_FIRST;
278 dev->failsafe = failsafe;
281 /* Advance to the next device of the same type */
282 dev->how_probe = PROBE_NEXT;
288 /* Removed the following line because it was causing
289 * heap.o to be dragged in unnecessarily. It's also
290 * slightly puzzling: by resetting heap_base, doesn't
291 * this mean that we permanently leak memory?
293 /* heap_base = allot(0); */
294 dev->how_probe = ops->probe(dev);
295 if (dev->how_probe == PROBE_FAILED) {
298 } else if (boot_index && (i == 0) && (boot_index != (unsigned)dev->type_index)) {
299 printf("Wrong index\n");
308 if (ops->load_configuration(dev) >= 0) {
313 /* Any return from load is a failure */
321 i = MAX_BOOT_ENTRIES;
327 /* At the end goto state 0 */
328 if ((type >= BOOT_NOTHING) || (i >= MAX_BOOT_ENTRIES)) {
340 /**************************************************************************
341 LOADKERNEL - Try to load kernel image
342 **************************************************************************/
344 /* To be split out into individual files */
345 static const struct proto protos[] = {
346 { "x-tftm", url_tftm },
347 { "x-slam", url_slam },
349 { "file", url_file },
355 /**************************************************************************
356 CLEANUP - shut down networking and console so that the OS may be called
357 **************************************************************************/
361 /* Stop receiving packets */