Pete:
Quote:
The simplest way I can think of is:-
- Have the different modules of the kernel (core, driver1, mm etc.) linked to archives with ar.
- Then write a stage2 boot loader with a simple linker built in which takes the object files and outputs the binary directly to a certain memory location and then jumps to it.
Sounds like the idea I had, but slightly different. A stage2 boot loader needs almost all the code a kernel does too when it is running, administering paging, segmentation, possibly multithreading (init one module while the other is loading, speed up your boot process, or let the user use the system in its basic form while the rest is still loading...). If stage2 is almost like a kernel, why not make it a kernel? Say, a kernel that is statically linked to a certain place in memory (like F0000000) and is thus loaded there, information about symbols going to a separate place in memory, for later linking, and all the modules being loadable (except for a certain core, which is the "stage2" loader). A single archive of those files is loaded by the real after-BS loader (that doesn't know linking nor other address spaces) to a specific place, and those objects are extracted and thereafter linked in the kernel, releasing their own objects etc. All other drivers are only loaded on request (by a driver most likely, in PnP fashion).
Those core drivers should suffice for the main tasks, and the core archive of driver files is constantly administered for new updates to those drivers, additions, and possible searching of new drivers for unrecognised devices. Some sort of sysadmin thread should do that work.
The end result of this system is that the kernel as itself is only the core, therefore having a "perfection-point", a point at which there is nothing to fix anymore. It should be a near-trivial end (trivial compared to a 20M monolithic kernel that is) so it can be fully tested to work. All other work should rely on that basis.
The second side of the "kernel" (speaking in old terms again) should be the interface between system modules that are loaded and the programs that want to use them. As always, drivers are present that release modules to the module space, and some types of modules (predefined by the end layer) are always taken by the end layer to be connected directly to the end point. So, during bootup, all physical drivers are loaded, then all logical drivers, and then the objects the logical drivers release are picked up by the upper layer.
The upper layer should be replaceable at run time, and should be constantly kept up to date. It stores all its data in a predefined format, which shall not be allowed to change. Only stable versions should be released.
After loading all this the one and only "startup program", like init, is loaded and is activated. It starts all its subprocesses, and possibly configures some devices that need configuration. All device drivers must place their devices in usable, always-working conditions (such as using the slowest form of DMA for harddisks etc). The configuration must always allow choice between this form and all faster forms. At the end of configuration, the system is up and running, and the login connections are made. Only at the point where the configurator is at a certain point in its function will there be any progress display.