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 },
138 static int main_loop(int state);
140 static int initialized;
143 static int exit_status;
145 void test_dhcp ( struct net_device *netdev );
147 /**************************************************************************
148 MAIN - Kick off routine
149 **************************************************************************/
151 struct net_device *netdev;
153 /* Call all registered initialisation functions */
158 netdev = next_netdev ();
161 test_dhcp ( netdev );
163 printf ( "No network device found\n" );
166 printf ( "Press any key to exit\n" );
177 void exit(int status)
181 exit_status = status;
182 longjmp(restart_etherboot, 255);
187 static int main_loop(int state)
189 /* Splitting main into 2 pieces makes the semantics of
190 * which variables are preserved across a longjmp clean
193 static unsigned long order;
194 static unsigned boot_index;
195 static struct dev * dev = 0;
196 static struct class_operations *ops;
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) {
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,
214 DHCP_OPT_LEN + MAX_BOOTP_EXTLEN,
215 #endif /* NO_DHCP_SUPPORT */
223 static int firsttime = 1;
224 /* First time through */
229 #ifdef EXIT_IF_NO_OFFER
239 /* We just called setjmp ... */
240 order = ask_boot(&boot_index);
247 /* Find a dev entry to probe with */
252 /* Advance to the next device type */
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) {
260 if ((i == 0) && (type == BOOT_NOTHING)) {
261 /* Return to caller */
264 if (type >= BOOT_NOTHING) {
265 interruptible_sleep(2);
269 ops = &operations[type];
271 dev->how_probe = PROBE_FIRST;
273 dev->failsafe = failsafe;
276 /* Advance to the next device of the same type */
277 dev->how_probe = PROBE_NEXT;
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?
288 /* heap_base = allot(0); */
289 dev->how_probe = ops->probe(dev);
290 if (dev->how_probe == PROBE_FAILED) {
293 } else if (boot_index && (i == 0) && (boot_index != (unsigned)dev->type_index)) {
294 printf("Wrong index\n");
303 if (ops->load_configuration(dev) >= 0) {
308 /* Any return from load is a failure */
316 i = MAX_BOOT_ENTRIES;
322 /* At the end goto state 0 */
323 if ((type >= BOOT_NOTHING) || (i >= MAX_BOOT_ENTRIES)) {
335 /**************************************************************************
336 LOADKERNEL - Try to load kernel image
337 **************************************************************************/
339 /* To be split out into individual files */
340 static const struct proto protos[] = {
341 { "x-tftm", url_tftm },
342 { "x-slam", url_slam },
344 { "file", url_file },
350 /**************************************************************************
351 CLEANUP - shut down networking and console so that the OS may be called
352 **************************************************************************/
356 /* Stop receiving packets */