Note: The NLNet NILO project has expanded requirements over the original NILO concept below. It need not follow the implementation suggestions below; that and others will be decisions to be taken by the implementor. Therefore the technical discussion below is for historic purposes and is not binding on the NLNet NILO project, and should be read in that light.
NILO is the Network Interface Loader project. It will build on the Etherboot and Netboot efforts. It will, in rough order of desirability:
Be Open Source
Use Linux network driver code.
Be written all in C except for assembly language bits for low level operations like interfacing to the BIOS.
Use GCC tools throughout
Run on 386 or better x86 processors
Autoprobe devices
Support BOOTP/DHCP for address resolution and TFTP for file loading
Try to fit with the GRUB effort.
Support chaining of network boot loaders by providing entry points to network services for subsequent loaders
Allow separate testing of the booting code and device drivers
Perhaps use memory protection to keep the boot code safe from the application and also to detect heap-stack collision.
Boot Linux initially. Legacy OSes like DOS and Windows may be supported later.
Support other processor architectures later
Have a small footprint
NILO will consist of three portions. The main part of the program will control the BOOTP/DHCP address resolution and the TFTP loading process. The second part comprises the protocol handlers and is interfaced through a jump table or interrupt entry points to the first part. The third part is the device driver.
Why three parts? In order to support many devices the device driver is separate, naturally. To support separate testing of the booting code and device drivers we need a split at the protocol level. This will allow a version of NILO to run as a user process on Linux, interfacing to Linux system calls.
NILO architecture
Additionally, by splitting off the protocol code, it will be possible to load secondary loaders that use these services. This will make it possible to move code for enhancements like menus and similar features into secondary loaders, thus keeping the primary loader small. It will always be possible to do basic netbooting with the primary loader though. In the diagram above, the secondary and following loaders will take over the role of the main control program but the protocol handlers and driver remain active. If the memory for the main control can be reclaimed, all the better.
The Linux network device drivers will be compiled from source. A goal is to not edit the driver source at all. So we have to provide stubs for the functions that the drivers call, or include files for macros. In other words a harness for the device driver needs to be built. I have done some initial experiments with the driver code and the main areas of difficulty seem to be:
Provide replacements for memory allocation routines. I propose that dynamic memory be allocated from the top of memory since this is available when the machine boots.
Provide routines to receive the incoming packets. Linux device drivers are interrupt driven and so we will need to interface to asynchronous code.
Provide support routines for timer ticks, etc.
A lot of code can be recycled from the Etherboot project. And of course, the mknbi utilities from Netboot will be used.
There seems to be some a package called OSKit here that could be used for wrapping the Linux device drivers. An alternative site for the old release until the new release appears.
I propose to run the project in a bazaar fashion, following the nomenclature that Eric Raymond used. I will keep the latest snapshot at this site. Each snapshot will be dated. (I do not expect to upload more than once per day.) Anybody is free to take the snapshot and hack on it and send me the changes. In addition, this Web page will contain a LOG and TODO section which can be updated by anybody so that people can see what is going on. I expect that in the beginning things will be very raw and then, depending on the level of hacking interest, useful things will emerge.
How does this datestamping of the distribution work? In the Makefile you will see a macro that uses a small Perl script to provide a 8 digit date code depending on the last update time of README. Therefore after edits have been made to the code, update the README and then run make clean archive which will remove the temp files, then produce the tarball.
Status: There are two main build targets in the Makefile at the moment. One builds nilo, which is a user level program (but needs to run with root privilege) that will go through the bootp and tftp steps, printing status. The server IP address and MAC address are set with environment variables. In the bootptab that MAC address must correspond to the IP address of host nilo is run on or the reply will not be seen. The other builds a bootrom for an arbitrary card. Lots of harness routines are missing. I want to get nilo working first so that people like Vlad can put in DHCP and other goodies. For sure I have made some mistakes in the partitioning of the mainline from the protocol handler (the latter must not rely on global variables or routines as it can be called from a secondary boot), but we can correct things as we go.
Started on version that runs as user level program on Linux
Got the first version which does bootp and tftp
Ok, I've started hacking NILO again. I'm going to try to get one NIC working. I've chosen the 3c509 as the first guinea pig NIC. I've got the probe routine working. I've hooked up the oskit memory manager routines, allocating from the top 1 MB of memory. Things that need attention: loops_per_sec needs to be set to a roughly correct value so that udelay works well (later). Need to hook up interrupt to handler. Need to figure out how to fill the skb before passing to the xmit routine. Then try to transmit one packet.
I think I have skbuffs and interrupts figured out. I have the concept down in my mind now. Currently stealing code from Linux kernel for IRQ handling. Also the RTC reprogramming is there too.
Put in more of the protocol handling code. Ironed out some problems with memory allocation. We need a different IDT for protected mode. Etherboot/32 skirted this issue by disabling interrupts in protected mode, so the RTC was only updated when calling real mode routines, like currticks.
Write the harness routines for Linux network device drivers. Need to figure out skbs, interrupt handlers and reprogramming the RTC for 100 Hz.
irq.o is rather large. We could omit the IRQ handlers that are never available to network cards (later).
Add code for DHCP.
The interface between the main control and the protocol handlers is via a jump table that will eventually be put at the top of 640k. This assumes that the secondary and subsequent loaders use the same subroutine calling protocol, which is the case if they are all compiled with the same compiler. I think this ok for now.
How do we simulate the jiffies variable in Linux, which is incremented regularly? How regularly and do we have to reprogram the RTC?
Maybe we can save precious memory by mallocing buffers (except for things like the bootp reply) in extended memory. Then the 32k from 0x98000 can be used mostly for code.
Etherboot suffers from these disadvantages:
Drivers must be written for each Ethernet chipset. While the effort is not large for an experienced driver programmer, it prevents wider spread of Etherboot. By recycling Linux drivers, we track the Linux effort. Any network device that Linux has a driver for we should be able to support. Additionally NILO may be able to assist the effort of writing Linux drivers.
Etherboot drivers are polling. This makes it more prone to miss packets in a large network.
The code is burdened with too many features that really belong in a secondary boot.
Etherboot requires both GCC and the as86/ld86 tools (and bcc, for the 16 bit version). Although there are now patches to GCC to assemble in 16-bit mode.
Netboot suffers from these disadvantages:
Not all cards come with Packet Drivers. NDIS drivers are the priority with card manufacturers. Also packet drivers require parts of the package to be written in assembler and this makes it harder to maintain. Packet drivers are also of variable quality.
Netboot doesn't autoprobe in all cases.
Not all Packet Drivers are interrupt driven for transmission. This introduces some dead time.
Netboot has a large footprint due to the need to provide a harness for Packet Drivers.
Netboot requires as86/ld86 tools.
Compiling packet drivers, if fixing problems is desired, requires a DOS environment and DOS assemblers.
NILO will have some disadvantages too:
It will be experimental until it matures. It will not initially support all the frills of Etherboot or Netboot.
It will not support 16 bit x86 processors (not a big loss).
It will have a larger footprint than Etherboot (but should still fit in 16kB).