More than a year ago I was hired by Linux NetworX to work on LinuxBIOS, and I've been on a steep learning curve ever since. After working on LinuxBIOS, I am qualified to say that I have no question that the kernel code is high-level code and that C is a high-level language.
When a microprocessor powers up, it starts executing instructions located in a ROM chip. These initial instructions are responsible for initializing the hardware (especially enabling RAM) and loading an operating system. The implementations and interfaces to this functionality vary from machine to machine, but its basic responsibility remains the same.
Figure 1. Boot Process Stages
On the Alpha platform the microprocessor reads an entire serial ROM, referred to as the SROM, into the instruction cache and begins executing code. The code in the SROM initializes the processor and memory and loads the SRM from a Flash EEPROM. The SRM then loads the palcode (basically the real kernel on the Alpha), initializes a little more hardware and loads an operating system. Since the firmware is split into two pieces, the SRM can be upgraded or even replaced. In fact, the initial design of the Alpha architecture specified that there would be different firmware (at the SRM level) for each operating system.
The x86 microprocessor begins executing code in 16-bit mode at 16 bytes short of the end of the address space, with the CS register pointing to 64K below the end of the address space. On the 8086 this is at address 0xf000:0xfff0 == 0xffff0, just below 1MB. On the 80286 the address is 0xfffff0, just below 16MB. And on the 80386 and above, this space is at 0xfffffff0, just below 4GB. For the 286 and later Intel processors, the value in CS is not one that you can ever load again. To compensate for this, the hardware maps the ROM chip at both 0xffff0000 and 0xf0000.
Unlike the Alpha, x86 processors fetch instructions one at a time from the ROM chip. As ROM chips are essentially ISA devices, this leads to some interesting consequences, the first being that until some form of caching is enabled, the code runs quite slowly. The second effect is that the chipset must come up mostly enabled, as the usual path to the ROM chip is from the CPU to the Northbridge, to the PCI Bus to the Southbridge, to the ISA Bus to the ROM. When working with a known good board, this second fact makes the debugging of initial devices much easier.
The standard PC BIOS has the responsibilities of initializing the hardware, loading an operating system and providing a variety of services (mostly in the form of minimal device drivers) after an operating system has loaded.
SPARC and PowerPC architectures have specified firmware, also known as OpenBoot, Open Firmware or the defunct IEEE 1275. The standardized Forth firmware sits close to the same location that the SRM does on the Alpha. There are several unique things about Open Firmware: it runs on multiple processor and machine architectures; it uses a Forth-based byte code, so the binaries are processor-independent; and it does most of its system initialization from this Forth-base byte code.
The Itanium/IA64 architecture uses the EFI firmware and is more architecture-dependent than Open Firmware because its drivers are either IA32 or IA64 code. In scope it appears to be even more ambitious; EFI includes an IP stack and some filesystem drivers. As with Open Firmware, the early hardware initialization stage is not specified.
Requirements placed upon the firmware by the Linux kernel are minimal. The Linux kernel directly drives the hardware and does not use the BIOS. Since the Linux kernel does not use the BIOS, most of the hardware initialization is overkill. Linux is not alone in this respect; I don't know of a modern operating system that doesn't follow this trend. Modern operating systems require only basic system initialization services. Extra device drivers and system features that firmware like EFI, Open Firmware or even a PCBIOS provide are not necessary except to help load the operating system. Since these services are not necessary, the LinuxBIOS code does not provide them.
The LinuxBIOS code is sufficient to load a standalone program encoded as an ELF executable from a Flash ROM. A standalone program can be an operating system kernel like Linux, but most standalone programs are hardware diagnostics or boot loaders (e.g., Memtest86, Etherboot and RedBoot). LinuxBIOS is expected to be paired with a standalone boot loader in order to load the operating system.
The original idea of LinuxBIOS was to load the Linux kernel from the ROM and build a boot loader on top of that. The boot loader nbc implements this idea, loading a Linux kernel or a standalone program over the network and booting from Linux using the kexec kernel patch. This solution works fine when 512KB of ROM (or more) is available. Unfortunately, most standard motherboards shipping today have only 256KB of ROM. For the x86 platform it is nearly impossible to get a useable Linux kernel under 360KB.
Various strategies have been developed to address these systems limited by the amount of available ROM. Some of these strategies include Tiara, which appears to be a complete firmware and boot loader for the SiS630 chipset; Etherboot, which has been ported to work under LinuxBIOS; RedBoot, which runs under LinuxBIOS but is not yet useable; and some hacks on LinuxBIOS itself.
Alpha firmware requires a standalone program to be familiar with the motherboard it is running on, which can be problematic. While having this level of familiarity is nice, supporting a new motherboard can be extremely difficult because of the number of pieces of software that must be updated. With LinuxBIOS we do our best to avoid that problem.
We start with the traditional x86 approach: initialize the Super-IO chips to working and expected values (i.e., serial ports at their expected legacy address, IRQ, etc.) and then provide IRQ routing tables and mptables for SMP.
For the long term we need a table tracking the capabilities Plug-and-Play has identified. This software lists what hardware is present and configures which resources the hardware will use, or at a minimum it lists which resources an individual device uses. The solution I am working on involves creating a table of devices with information about how they are connected to each other on the motherboard. The table will list devices not currently participating in any kind of Plug-and-Play enumeration, as well as give enough information so that IRQ routing can be handled. Additionally the idea seems to fit in well with the struct device tree planned for the 2.5 kernel. ACPI appears to offer an alternative solution but it seems PC-centric, and the interpreted byte codes seem unnecessary and even dangerous.
Since the first IBM PC, the hardware architecture of the boot ROM has evolved considerably, so that today virtually every machine has a BIOS that can be upgraded in the field or recovered from a failed upgrade. The common technique to accomplish this is to have a socketed Flash ROM on the motherboard. The Flash chip allows software to update it while the socket allows replacement of the chip if the update somehow fails. With this type of hardware architecture, developing custom boot firmware is now possible. For production machines, you can update firmware with no special hardware, and during development you can recover if something goes wrong.
A downside to current PC hardware architectures is that normally boot ROMs, at 256KB, are too small. This is enough space for firmware, but it isn't large enough for the Linux kernel.
The Linux kernel can run from LinuxBIOS as well as it does from a standard PCBIOS, when the port is done correctly. To date I successfully have ported LinuxBIOS to three motherboards. On the latest board, the results of booting Linux from LinuxBIOS and the PCBIOS are indistinguishable. So while there are significant technical hurdles in porting LinuxBIOS to new platforms, these can be and have been overcome.
Having access to adequate documentation is a nontechnical factor to consider. Convincing hardware vendors to support LinuxBIOS, or to release the documentation for someone else to code it, has met limited success to date. Missing or limited vendor support is not a new issue for free software, and it has been overcome in the past—now is not the point in the game to be discouraged. It is worth remembering that without these kinds of efforts there would be no new hardware on which we could run free software.
Currently two different interest groups are working on LinuxBIOS: one working on embedded systems and one building large-scale computer clusters. For these applications the legacy x86 firmware is suboptimal.
LinuxBIOS has a lot to recommend itself for embedded applications. As it is released under the GPL, LinuxBIOS is royalty-free. LinuxBIOS generally weighs in under 64KB and doesn't waste ROM space with unnecessary functionality. Because it isn't a legacy design, LinuxBIOS starts up fast, even without code optimization.
In August 2001, General Software announced a 0.8-second boot to LILO on an embedded board after a hardware reset. This is a reasonable amount of time to do the job, but under LinuxBIOS such impressive results are routine. I can load the kernel over the network from a cold power-on in two seconds flat on a dual-processor server board—without optimizing LinuxBIOS.
The small footprint of LinuxBIOS has impressed SiS enough that they have devoted a developer to port LinuxBIOS to their chipsets, aiming at embedded applications. This demonstrates one well-supported platform.
For computer clusters, which is what Linux NetworX specializes in, LinuxBIOS has a lot to recommend itself as well. The serial port is the native console, so you don't need video hardware. Serial connections can be redirected easily into a terminal server for remote console access. The early setup of the serial console also brings benefits. For example, LinuxBIOS can report all errors and hardware failures over the serial console. A normal BIOS, even with serial console extensions, will initialize the serial port too late in the game for some failures to be detected, and it will usually fail if the CMOS is cleared.
LinuxBIOS also supports network booting on most hardware platforms, allowing changes to boot options to be made simply by altering a setting on a DHCP server. Since the code is open source, if the network booting policy is not to your liking it can be changed. The fast booting of LinuxBIOS means that if you are debugging something and have to reboot a node, the hardware doesn't waste the valuable time of the system administrator.
The openness of LinuxBIOS and its focus on Linux allow it to be configured and managed from user space under the Linux kernel. Anything done from user space also can be set up to be done remotely. This is a great advantage in homogeneous clusters, allowing firmware changes to be made and managed globally instead of one node at a time.
With large numbers of machines, the probability of hardware failure is much larger than for a single machine. The reduced hardware requirements of LinuxBIOS—such as unneeded floppy drives, CD-ROMs or hard drives to boot from, and no need for a video card and keyboard to control the system—can lead to a less expensive and more reliable system. Fewer hardware components lead to a reduced risk of hardware failures.
For clusters, LinuxBIOS also brings the potential to plug in to the cluster and, with nothing more than the firmware running, have a machine that acts as a single system, instead of a rack that looks like a collection of nodes.
In the LinuxBIOS tree there are currently ports to 13 different mainboards. LinuxBIOS has been ported to both x86 and the Alpha hardware architectures. It has run on the AMD Athlon, AMD Duron, Pentium II, Pentium III, Alpha 211264 CPUs, ALI m1631, Digital Tsunami, AMD 760, AMD 760MP, Intel 440BX, Intel 440GX, VIA VT8601, SiS540, SiS550, SiS630 and SiS730 chipsets. And this is just the code that has been finished and placed in the main LinuxBIOS tree. Other ports are still in progress and haven't been committed as of this writing. So while the hardware support is limited, the list is growing. LinuxBIOS currently is not tied to any specific chipset, vendor or processor architecture.
The quality of the hardware support varies. On the chipset front, support for SiS chipsets is very good. Both Intel and AMD have a standard policy of documenting their chipsets so the support at both is pretty good. Via does not publicly document their newer chipsets, making support here a challenge.
On the processor front, Compaq has made the important details public, so supporting Alpha processors is doable. Development for the Alpha has not been a high priority, however, because the Alpha is an expensive processor with a dubious future.
The Pentium II and Pentium III are fairly well documented in Intel manuals, except for the L2 cache initialization of their slot processors (the L2 cache initialization is now supported). The AMD Athlon and Duron are not well supported because AMD hasn't publicly documented everything that needs to be set up for their processors.
Support from the board manufacturer isn't necessary because, most of the time, components on a motherboard can be identified by just looking at it.
Board manufacturers generally are interested in supporting only one firmware for their motherboards. As LinuxBIOS currently does not provide a compatibility layer for booting other operating systems besides Linux (notably Windows), there hasn't been much interest from board manufacturers in deploying LinuxBIOS in its current form.
LinuxBIOS provides an innovative look at the job of firmware, how it is structured, written and licensed. As machines become increasingly integrated, LinuxBIOS is rising to meet the demand for greater code reuse and flexibility. If the snowballing interest in the technology is any indication, it looks to have a bright future.
Eric Biederman ([email protected]) is a software engineer for Linux NetworX, focusing on LinuxBIOS and helping with cluster management tool development. When not deeply involved in LinuxBIOS, Eric reads science fiction, plays with DOSEMU and hikes around the Wasatch Mountains just outside of Salt Lake City.