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"
33 jmp_buf restart_etherboot;
36 char as_main_program = 1;
39 int freebsd_howto = 0;
40 char freebsd_kernel_env[FREEBSD_KERNEL_ENV_SIZE];
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 * initialise() - perform any C-level initialisation
148 * This does not include initialising the NIC, but it does include
149 * e.g. getting the memory map, relocating to high memory,
150 * initialising the console, etc.
151 **************************************************************************
153 void initialise ( void ) {
155 memset ( _bss, 0, _ebss - _bss );
157 /* Call all registered initialisation functions */
161 /**************************************************************************
162 MAIN - Kick off routine
163 **************************************************************************/
167 /* Print out configuration */
171 * Trivial main loop: we need to think about how we want to
172 * prompt the user etc.
175 for ( ; ; disable ( &dev ), call_reset_fns() ) {
177 /* Get next boot device */
178 if ( ! find_any_with_driver ( &dev, skip ) ) {
179 /* Reached end of device list */
180 printf ( "No more boot devices\n" );
186 /* Skip this device the next time we encounter it */
189 /* Print out device information */
190 printf ( "%s (%s) %s at %s\n",
191 dev.bus_driver->name_device ( &dev.bus_dev ),
192 dev.device_driver->name,
193 dev.type_driver->name,
194 dev.bus_driver->describe_device ( &dev.bus_dev ) );
196 /* Probe boot device */
197 if ( ! probe ( &dev ) ) {
198 /* Device found on bus, but probe failed */
199 printf ( "...probe failed\n" );
203 /* Print out device information */
204 printf ( "%s %s has %s\n",
205 dev.bus_driver->name_device ( &dev.bus_dev ),
206 dev.type_driver->name,
207 dev.type_driver->describe_device ( dev.type_dev ) );
209 /* Configure boot device */
210 if ( ! configure ( &dev ) ) {
211 /* Configuration (e.g. DHCP) failed */
212 printf ( "...configuration failed\n" );
216 /* Boot from the device */
217 load ( &dev, load_block );
221 /* Call registered per-object exit functions */
227 void exit(int status)
231 exit_status = status;
232 longjmp(restart_etherboot, 255);
238 static int main_loop(int state)
240 /* Splitting main into 2 pieces makes the semantics of
241 * which variables are preserved across a longjmp clean
244 static unsigned long order;
245 static unsigned boot_index;
246 static struct dev * dev = 0;
247 static struct class_operations *ops;
253 if (dev && (state >= 1) && (state <= 2)) {
254 dev->how_probe = PROBE_AWAKE;
255 dev->how_probe = ops->probe(dev);
256 if (dev->how_probe == PROBE_FAILED) {
264 static int firsttime = 1;
265 /* First time through */
270 #ifdef EXIT_IF_NO_OFFER
280 /* We just called setjmp ... */
281 order = ask_boot(&boot_index);
288 /* Find a dev entry to probe with */
293 /* Advance to the next device type */
295 boot = (order >> (i * BOOT_BITS)) & BOOT_MASK;
296 type = boot & BOOT_TYPE_MASK;
297 failsafe = (boot & BOOT_FAILSAFE) != 0;
298 if (i >= MAX_BOOT_ENTRIES) {
301 if ((i == 0) && (type == BOOT_NOTHING)) {
302 /* Return to caller */
305 if (type >= BOOT_NOTHING) {
306 interruptible_sleep(2);
310 ops = &operations[type];
312 dev->how_probe = PROBE_FIRST;
314 dev->failsafe = failsafe;
317 /* Advance to the next device of the same type */
318 dev->how_probe = PROBE_NEXT;
324 /* Removed the following line because it was causing
325 * heap.o to be dragged in unnecessarily. It's also
326 * slightly puzzling: by resetting heap_base, doesn't
327 * this mean that we permanently leak memory?
329 /* heap_base = allot(0); */
330 dev->how_probe = ops->probe(dev);
331 if (dev->how_probe == PROBE_FAILED) {
334 } else if (boot_index && (i == 0) && (boot_index != (unsigned)dev->type_index)) {
335 printf("Wrong index\n");
344 if (ops->load_configuration(dev) >= 0) {
349 /* Any return from load is a failure */
357 i = MAX_BOOT_ENTRIES;
363 /* At the end goto state 0 */
364 if ((type >= BOOT_NOTHING) || (i >= MAX_BOOT_ENTRIES)) {
376 /**************************************************************************
377 LOADKERNEL - Try to load kernel image
378 **************************************************************************/
380 /* To be split out into individual files */
381 static const struct proto protos[] = {
382 { "x-tftm", url_tftm },
383 { "x-slam", url_slam },
385 { "file", url_file },
392 /**************************************************************************
393 CLEANUP - shut down networking and console so that the OS may be called
394 **************************************************************************/
397 /* Stop receiving packets */