This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
dev:devmanual [2006/07/16 09:25]
dev:devmanual [2006/07/16 09:45]
Line 223: Line 223:
 ===== Frequently asked questions ===== ===== Frequently asked questions =====
 ==== How portable is Etherboot ? ==== ==== How portable is Etherboot ? ====
 +Work leading up to 5.2 made Etherboot much more portable. The platforms on which Etherboot runs, other than the x86, are the Itanium and the Hammer. The portability issues can be looked at in two categories: ​
 +Support routines needed for platforms need to be written. Platform independent and dependent code have been separated and it should be straightforward to identify the support that is needed for running Etherboot on a new platform. ​
 +Byte order, operand size and alignment issues in the core routines and PCI drivers have been mostly dealt with, although there are some known places where the code has not been made portable, e.g. longword access of registers in the eepro100 driver. We hope to find these bugs as time goes by. In some cases, e.g. ISA bus NICs, there is no need to fix the problem as the ISA bus only exists on the PC platform (unless somebody attaches a NE2000 to a big-endian microcontroller and plans to run Etherboot on it). 
 +Here are the low-level services that need to provided: writing and reading from the console, determining the size of memory, obtaining the an elapsed time, inserting a boot vector to be called, and a microsecond timer for short delays. Depending on the target environment,​ these services may be provided in different ways.
 ==== How can I get Etherboot to boot a Cardbus (PCMICA) or a USB NIC? ==== ==== How can I get Etherboot to boot a Cardbus (PCMICA) or a USB NIC? ====
 +Cardbus (PCMCIA) and USB NICs are interfaced to the CPU through their respective bus controllers. Before Etherboot can address the registers and memory on these NICs, it must initialise the bus controller appropriately. In Linux this is done by the PCMCIA and USB subsystems. In Etherboot, all this must be done by the code in the ROM. What needs to be written is a subsystem like the PCI subsystem in Etherboot. Volunteers are most welcome.
 ===== Writing an EtherBoot Driver ===== ===== Writing an EtherBoot Driver =====
 ==== Preliminaries ==== ==== Preliminaries ====
 +So Etherboot does not have a driver for your network adapter and you want to write one. You should have a good grasp of C, especially with respect to bit operations. You should also understand hardware interfacing concepts, such as the fact that the x86 architecture has a separate I/O space and that peripherals are commanded with ''​out''​ instructions and their status read with ''​in''​ instructions. A microprocessor course such as those taught in engineering or computer science curricula would have given you the fundamentals. (Note to educators and students in computer engineering:​ An Etherboot driver should be feasible as a term project for a final year undergraduate student. I estimate about 40 hours of work is required. I am willing to be a source of technical advice.)
 +Next you need a development machine. This can be your normal Linux machine. You need another test machine, networked to the development machine. This should be a machine you will not feel upset rebooting very often. So the reset button should be in working condition. :-) It should have a floppy drive on it but does not need a hard disk, and in fact a hard disk will slow down rebooting. Alternatively,​ it should have another network adapter which can netboot; see discussion further down. Needless to say, you need a unit of the adapter you are trying to write a driver for. You should gather all the documentation you can find for the hardware, from the manufacturer and other sources. ​
 ==== Background information ==== ==== Background information ====
 +There are several types of network adapter architecture. The simplest to understand is probably programmed I/O. This where the controller reads incoming packets into memory that resides on the adapter and the driver uses ''​in''​ instructions to extract the packet data, word by word, or sometimes byte by byte. Similarly, packets are readied for transmission by writing the data into the adapter'​s memory using ''​out''​ instructions. This architecture is used on the NE2000 and 3C509. The disadvantage of this architecture is the load on the CPU imposed by the I/O. However this is of no import to Etherboot (who cares how loaded the CPU is during booting), but will be to Linux. Next in the sophistication scale are shared memory adapters such as the Western Digital or SMC series, of which the WD8013 is a good example. Here the adapter'​s memory is also accessible in the memory space of the main CPU. Transferring data between the driver and the adapter is done with memory copy instructions. Load on the CPU is light. Adapters in this category are some of the best performers for the ISA bus. Finally there are bus mastering cards such as the Lance series for the ISA bus and practically all good PCI adapters (but not the NE2000 PCI). Here the data is transferred between the main memory and the adapter controller using Direct Memory Access. Setting up the transfers usually involves a sequence of operations with the registers of the controller. ​
 ==== Structure of the code ==== ==== Structure of the code ====
 +Examine the file ''​skel.c'',​ in the ''​src''​ directory, which is a template for a driver. You may also want to examine a working driver. You will see that an Etherboot driver requires 4 functions to be provided:
 +  * A probe routine, that determines if the network adapter is present on the machine. This is passed a pointer to a ''​nic''​ struct, possibly a list of candidate addresses to probe, and possibly a pointer to a ''​pci''​ struct. This routine should initialise the network adapter if present. If a network adapter of the type the driver can handle is found, it should save the I/O address at which it was found for use by the other routines. In the case of ISA adapters, it may be passed a list of addresses to try, or if no list is passed in, it may use an internal list of candidate addresses. In the case of PCI adapters, the address has already been found by the PCI support routines. Then it should determine the Ethernet (MAC) address of the adapter and save it in ''​nic->​node_addr''​. It should then initialise the adapter. Finally it should fill in the function pointers for the other routines, and return the ''​nic''​ pointer. If it fails to find an adapter, it should return 0.\\ \\ The field ''​rom_info''​ in the ''​nic''​ struct contains, on entry to the probe routine, a pointer to the structure ''​rom_info'',​ defined in ''​etherboot.h''​. This contains the segment address and length in shorts of the ROM as detected by the BIOS. These can be used by the driver to discriminate between multiple instances of the same network adaptor on the bus, and choose to activate only the one the ROM is installed on. For example, the 3c509 hardware has a register indicating what address the ROM is mapped at. Note that the driver should not reject "ROM segment addresses"​ outside ''​0xC000''​ to ''​0xEE00''​ as this indicates booting from floppy disk or other non-ROM media.\\ \\ Initialising the adapter means programming the registers so that the chip is ready to send and receive packets. This includes enabling the appropriate hardware interface (10B2, 10BT) in the case of adapters with more than one interface, and setting the right speed (10Mb, 100Mb) if the hardware does not autosense and set it. It also includes setting up any memory buffers needed by the hardware, along with any necessary pointers.\\ \\ Note that you should program the receiver registers to allow broadcast Ethernet packets to be received. This is needed because other IP hosts will do an ARP request on the diskless computer when it boots. ​
 +  * A disable routine, which puts the adapter into a disabled state. This is passed a pointer to a ''​nic''​ struct. This is needed to leave the adapter in a suitable state for use by the operating system which will be run after Etherboot. Some adapters, if left in an active state, may crash the operating system at boot time, or cannot be found by the operating system. This can be called from the probe routine. ​
 +  * A transmit routine, to send an Ethernet packet. This is passed a pointer to a ''​nic''​ struct, the 6 byte Ethernet address of the destination,​ a packet type (IP, ARP, etc), the size of the data payload in bytes, and a pointer to the data payload. Remember the packet type and length fields are in x86 byte order (little-endian) and the adapter'​s byte order may be the reverse (big-endian). Note that the routine knows nothing about IP (or any other type) packets, the data payload is assumed to be a filled in packet, ready to transmit. ​
 +  * A poll routine, to check if a packet has been received and ready for processing. This is passed a pointer to a ''​nic''​ struct. If a packet is available, it should copy the packet from the adapter into the data area pointed to by ''​nic->​packet'',​ and set ''​nic->​packetlen''​ to the length of the data, and return 1, otherwise 0.\\ \\ A few Ethernet controller chips will receive packets from itself, as detected by having a source address of itself. You can throw these out immediately on reception and not bother the upper layer with them. 
 +No routine needs to be public, all routines should be static and private to the driver module. Similarly all global data in the driver should be static and private. ​
 +If the NIC is a PCI adapter, create a struct ''​pci_driver''​ (as in ''​skel.c''​) and an array of struct ''​pci_id'':​
 +static struct pci_id skel_nics[] = {
 +PCI_ROM(0x0000,​ 0x0000, "​skel-pci",​ "​Skeleton PCI Adaptor"​),​
 +Fill the ''​pci_id''​ array with one entry for each combination of pci vendor id and pci device id that your driver can handle. PCI_ROM is a a macro defined in ''​include/​pci.h''​. The arguments have the following meaning: vendor id, device id, rom name and short description. Since this information is also used to build the Makefile rules, you must use the PCI_ROM macro and can't fill in the values directly. Both the pci vendor and device id must be given in hex form, no ''​define''​ is allowed. Additionally PCI_ROM must occur only once in a line and one macro call must not span more than one line. You can obtain the vendor and device ids from the file ''/​usr/​include/​linux/​pci.h''​. It is also displayed by PCI BIOSes on bootup, or you can use the ''​lspci''​ program from the pciutils package to discover the ids. 
 +If the NIC is an ISA adapter, create a struct ''​isa_driver''​ (as in ''​skel.c''​) and one line like the following: ​
 +<​file>​ISA_ROM("​skel-isa",​ "​Skeleton ISA driver"​)</​file>​
 +in your driver source. The ISA_ROM macro is like the PCI_ROM without the vendor/​device ids. The same rules about formatting as in the PCI case apply.
 +Only for special cases where the automatic generation of build rules via the PCI_ROM and ISA_ROM entries does not work, add an entry to the here document in ''​genrules.pl''​ so that the build process will create ''​Makefile''​ rules for it in the file ''​bin/​Roms''​. ​
 + The above mentioned structs and macros hold all information that etherboot needs about your driver. In case you wonder how this works at all although everything is declared static: The special build process that is used by Etherboot (including linker scripts and some Perl magic) packs the necessary information into public segments. ​
 +The Etherboot build process places a few restrictions on your driver: If you need more than one ''​.c''​ file, the main file (that will contain the PCI_ROM or ISA_ROM macro call) must contain ''#​include''​ directives for the other files. They must not contain a PCI_ROM or ISA_ROM call. See ''​drivers/​net/​prism*''​ for an example.
 ==== Rom naming rules ==== ==== Rom naming rules ====
 +Currently there is no official rom naming convention in etherboot. Use some descriptive name, but note that two ore more consecutive hyphens (like in "''​my--rom''"​) are not allowed, since "​--"​ is the delimiter sign for multiple-driver-roms. Sometimes it is difficult to find a sensible name, for example for "​NICs"​ that are built in motherboard chipsets or if you don't know the model name. In this case we choose to name the corresponding roms "​driver-deviceid",​ like "​eepro100-1035"​. Of course you have to make sure that your rom name is unique in etherboot.
 ==== Booting the code from a floppy ==== ==== Booting the code from a floppy ====
 +Use the rule for ''​bin/​driver.fd0''​ to write another instance of the driver to the floppy for testing. Use lots of printf statements to track where execution has reached and to display the status of various variables and registers in the code. You should expect to do this dance with the development machine, floppy disk and target machine many many times. ​
 ==== Booting the test code with another EtherBoot ROM ==== ==== Booting the test code with another EtherBoot ROM ====
 ==== Writing the code ==== ==== Writing the code ====
Line 249: Line 295:
 ===== Appendix B. Compression algorithm, 1 July 1997 ===== ===== Appendix B. Compression algorithm, 1 July 1997 =====
 ===== Appendix C. Copying conditions of the compression code, 1 July 1997 ===== ===== Appendix C. Copying conditions of the compression code, 1 July 1997 =====

QR Code
QR Code dev:devmanual (generated for current page)