This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Xenopathic's profile picture

Yet Another Bootloader (but it might be different this time)

Started by Xenopathic, 24 February 2013 - 08:08 AM
Xenopathic #1
Posted 24 February 2013 - 09:08 AM
Introduction
One of the biggest problems with developing an OS in ComputerCraft is that you need to overwrite bios.lua for your OS, which is a problem in places such as multiplayer servers where you perhaps only want one computer to have this custom OS. A workaround is to run your OS from within CraftOS, but this leaves the APIs loaded along with all the other routines put in place by CraftOS. The only way to get an OS to run without the underlying system getting in the way is to use a bootloader.

There are a few bootloaders on these forums, but as far as I can tell only 1 implements it outside of CraftOS (that bootloader is ccBootMenu by max96at). From what I have seen, other bootloaders either use CraftOS functions or run as a startup file, which defeats the purpose of a true bootloader. So, here is my attempt at getting it right.

Design
I based the entire bootloader around GRUB, which I find to be a very good bootloader with plenty of configuration possibilities. This bootloader implements an interface similar to GRUB's, just lacking a recovery console. I used an XML file due to the very strict syntax making for easy parsing, with clear indication of the look of the final boot menu.

Installation
Bootloader 1.0

This needs to be extracted into the ComputerCraft mod file (an unfortunate side effect of moving all rom files into the mod file, rather than having them individually like in previous versions). The stock config.xml needs to be changed to suit your needs - see below in Configuration for help on how to do that.

Configuration
All configuration is done in rom/boot/bootloader/config.xml, or boot/bootloader/config.xml. The bootloader reads the local copy first, and falls back to the rom copy if the local one doesn't exist. This allows individual computers to have their own bootmenu. The stock bootmenu is an example of all the features on offer, so it includes entries that you probably won't need.

In the root element (<bootloader>) there must be 2 things - <version> and <menu>. The current config.xml version is 1.0, so don't change that or the bootloader will fail to load. There can also be 2 optional elements, <timeout> and <default>, which specify the timeout until the default is booted and the default itself, respectively.
Inside <menu> there can be two types of element. <title> is optional, and specifies the title that appears at the top of the menu. There can be multiple <entry>'s, which specify each individual entry. Inside each <entry> there can be a <title>, the name of the entry, and either <os> and <kernel> OR <menu>. In the case of a <menu>, the entry acts as a submenu, and the <menu> element follows the same rules as before. A bootable entry must have a <kernel> element, which specifies the path of the kernel file. In the stock config.xml there exists 1 kernel at rom/boot/ccos.lua, which is a copy of the CraftOS 1.4 kernel. For normal use you can ignore the <os> element, as it is optional.

If you keep the DOCTYPE declaration at the top of the XML file, then you can run the completed file through a markup validator, such as w3's validator, which will tell you if the XML file is valid (and will correctly work in the bootloader).

Advanced
The <os> element in a bootable entry is currently not used at all within the bootloader, but is designed to be a future feature for generating the config.xml file. Each bootable entry will have an <os> element, which must contain a <type> and can optionally contain a <version>. This data can be used to determine the ordering of kernels, such as in the stock config.xml file where older WolfOS's can be delegated to a submenu.

Future Ideas
In a future update I plan to add colour support for advanced computers, a recovery console with some basic commands, and possibly a mechanism to define root directories for kernels (like telling CraftOS that /rom/apis is actually /craftos/rom/apis, etc.). I also want to make a configuration generation program, which can be fed a list of kernels and their types/versions (see Advanced) and spit out a valid config.xml out the other side. This would make it extremely easy for OS developers to distribute their OS, since they only need to include one extra file for this bootloader to detect it. Of course, any suggestions to these ideas are welcome.
wilcomega #2
Posted 25 February 2013 - 05:05 AM
in CC you dont need to overwrite the bios.lua. just make an file called "startup"
Xenopathic #3
Posted 25 February 2013 - 11:52 AM
But as with the other bootloader methods, you are left with an unclean environment with many parts of CraftOS cluttering up the global table.
nachtfalter0460 #4
Posted 26 February 2013 - 08:03 AM
Nice Work.
Malte #5
Posted 27 February 2013 - 06:51 AM
Console crashes when opening an not existing program and then the computer shuts down
oeed #6
Posted 28 February 2013 - 09:53 AM
Nice idea, but I still don't see any real problem in just using startup. Could you give an example of this 'cluttering'?
Tiin57 #7
Posted 01 March 2013 - 12:58 AM
Good idea, but I see no code… I would use this.
TheVarmari #8
Posted 01 March 2013 - 03:38 AM
But as with the other bootloader methods, you are left with an unclean environment with many parts of CraftOS cluttering up the global table.

Or, you know, you could use the script which climbs to the top of the process list and then overwrite EVERYTHING…
Xenopathic #9
Posted 01 March 2013 - 06:58 AM
Nice idea, but I still don't see any real problem in just using startup. Could you give an example of this 'cluttering'?

CraftOS loads many APIs, such as io, bit, rednet etc. Running an OS from startup would leave those APIs still accessible. This may or may not cause problems, but it does leave an unclean environment for the OS. My bootloader actually writes nothing to the global table, and as such the OS gets an environment as if it were run in bios.lua directly. So if in your OS you lockdown the fs functions to stop arbitary file operations, then create new fs functions which may be in a sandbox or may implement privilages, but the io API from CraftOS is still loaded, malicious programs could still access the files directly.

But as with the other bootloader methods, you are left with an unclean environment with many parts of CraftOS cluttering up the global table.

Or, you know, you could use the script which climbs to the top of the process list and then overwrite EVERYTHING…

What script is this? And besides - it still wouldn't fix the global table, since by that point the APIs have already been loaded.

EDIT: @Malte:
Were you trying to open a non-existing kernel using an option in the config file? If so, then that is the expected behaviour of that version, since it is expected that the config.xml is actually valid. In the development version however I have added checks for that, so it will report an Unable to read kernel error (like manually inputting a kernel) instead of crashing.
TheVarmari #10
Posted 01 March 2013 - 08:05 AM
Nice idea, but I still don't see any real problem in just using startup. Could you give an example of this 'cluttering'?

CraftOS loads many APIs, such as io, bit, rednet etc. Running an OS from startup would leave those APIs still accessible. This may or may not cause problems, but it does leave an unclean environment for the OS. My bootloader actually writes nothing to the global table, and as such the OS gets an environment as if it were run in bios.lua directly. So if in your OS you lockdown the fs functions to stop arbitary file operations, then create new fs functions which may be in a sandbox or may implement privilages, but the io API from CraftOS is still loaded, malicious programs could still access the files directly.

But as with the other bootloader methods, you are left with an unclean environment with many parts of CraftOS cluttering up the global table.

Or, you know, you could use the script which climbs to the top of the process list and then overwrite EVERYTHING…

What script is this? And besides - it still wouldn't fix the global table, since by that point the APIs have already been loaded.

EDIT: @Malte:
Were you trying to open a non-existing kernel using an option in the config file? If so, then that is the expected behaviour of that version, since it is expected that the config.xml is actually valid. In the development version however I have added checks for that, so it will report an Unable to read kernel error (like manually inputting a kernel) instead of crashing.

Uhm… It would fix the issue as it goes before shell and you could overwrite the tables anyways
Malte #11
Posted 13 March 2013 - 04:23 AM
@Xenopathic: Oops, i meant CraftOS crashed when trying to run an non existent programm.
tenshae #12
Posted 29 August 2014 - 02:24 AM
Why replace bios.lua when you can just reset the global table in a startup file?