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>
36 extern char _bss[], _ebss[];
38 jmp_buf restart_etherboot;
41 char as_main_program = 1;
45 static inline unsigned long ask_boot(unsigned *index)
47 unsigned long order = DEFAULT_BOOT_ORDER;
48 *index = DEFAULT_BOOT_INDEX;
50 order = get_boot_order(order, index);
60 for ( time = currticks() + ASK_BOOT*TICKS_PER_SEC;
62 if (currticks() > time) c = ANS_DEFAULT;
65 #endif /* ASK_BOOT > 0 */
66 if ( !c ) c = getchar();
67 if ((c >= 'a') && (c <= 'z')) c &= 0x5F;
68 if ((c >= ' ') && (c <= '~')) putchar(c);
73 /* Nothing useful try again */
80 /* Preserve the default boot order */
83 order = (BOOT_NIC << (0*BOOT_BITS)) |
84 (BOOT_NOTHING << (1*BOOT_BITS));
88 order = (BOOT_DISK << (0*BOOT_BITS)) |
89 (BOOT_NOTHING << (1*BOOT_BITS));
93 order = (BOOT_FLOPPY << (0*BOOT_BITS)) |
94 (BOOT_NOTHING << (1*BOOT_BITS));
101 #endif /* ASK_BOOT >= 0 */
102 #endif /* defined(ASK_BOOT) */
106 static inline void try_floppy_first(void)
108 #if (TRY_FLOPPY_FIRST > 0)
110 printf("Trying floppy");
112 for (i = TRY_FLOPPY_FIRST; i-- > 0; ) {
114 if (pcbios_disk_read(0, 0, 0, 0, ((char *)FLOPPY_BOOT_LOCATION)) != 0x8000) {
115 printf("using floppy\n");
119 printf("no floppy\n");
120 #endif /* TRY_FLOPPY_FIRST */
123 static struct class_operations {
125 int (*probe)(struct dev *dev);
126 int (*load_configuration)(struct dev *dev);
127 int (*load)(struct dev *dev);
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 },
139 static int main_loop(int state);
141 static int exit_status;
142 static int initialized;
145 /**************************************************************************
146 MAIN - Kick off routine
147 **************************************************************************/
149 struct net_device *netdev;
151 /* Call all registered initialisation functions */
156 netdev = next_netdev ();
158 test_dhcp ( netdev );
161 printf ( "No network device found\n" );
164 printf ( "Press any key to exit\n" );
175 void exit(int status)
179 exit_status = status;
180 longjmp(restart_etherboot, 255);
185 static int main_loop(int state)
187 /* Splitting main into 2 pieces makes the semantics of
188 * which variables are preserved across a longjmp clean
191 static unsigned long order;
192 static unsigned boot_index;
193 static struct dev * dev = 0;
194 static struct class_operations *ops;
200 if (dev && (state >= 1) && (state <= 2)) {
201 dev->how_probe = PROBE_AWAKE;
202 dev->how_probe = ops->probe(dev);
203 if (dev->how_probe == PROBE_FAILED) {
207 /* The bootp reply might have been changed, re-parse. */
208 decode_rfc1533(bootp_data.bootp_reply.bp_vend, 0,
209 #ifdef NO_DHCP_SUPPORT
210 BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN,
212 DHCP_OPT_LEN + MAX_BOOTP_EXTLEN,
213 #endif /* NO_DHCP_SUPPORT */
221 static int firsttime = 1;
222 /* First time through */
227 #ifdef EXIT_IF_NO_OFFER
237 /* We just called setjmp ... */
238 order = ask_boot(&boot_index);
245 /* Find a dev entry to probe with */
250 /* Advance to the next device type */
252 boot = (order >> (i * BOOT_BITS)) & BOOT_MASK;
253 type = boot & BOOT_TYPE_MASK;
254 failsafe = (boot & BOOT_FAILSAFE) != 0;
255 if (i >= MAX_BOOT_ENTRIES) {
258 if ((i == 0) && (type == BOOT_NOTHING)) {
259 /* Return to caller */
262 if (type >= BOOT_NOTHING) {
263 interruptible_sleep(2);
267 ops = &operations[type];
269 dev->how_probe = PROBE_FIRST;
271 dev->failsafe = failsafe;
274 /* Advance to the next device of the same type */
275 dev->how_probe = PROBE_NEXT;
281 /* Removed the following line because it was causing
282 * heap.o to be dragged in unnecessarily. It's also
283 * slightly puzzling: by resetting heap_base, doesn't
284 * this mean that we permanently leak memory?
286 /* heap_base = allot(0); */
287 dev->how_probe = ops->probe(dev);
288 if (dev->how_probe == PROBE_FAILED) {
291 } else if (boot_index && (i == 0) && (boot_index != (unsigned)dev->type_index)) {
292 printf("Wrong index\n");
301 if (ops->load_configuration(dev) >= 0) {
306 /* Any return from load is a failure */
314 i = MAX_BOOT_ENTRIES;
320 /* At the end goto state 0 */
321 if ((type >= BOOT_NOTHING) || (i >= MAX_BOOT_ENTRIES)) {
333 /**************************************************************************
334 LOADKERNEL - Try to load kernel image
335 **************************************************************************/
337 /* To be split out into individual files */
338 static const struct proto protos[] = {
339 { "x-tftm", url_tftm },
340 { "x-slam", url_slam },
342 { "file", url_file },
348 /**************************************************************************
349 CLEANUP - shut down networking and console so that the OS may be called
350 **************************************************************************/
354 /* Stop receiving packets */