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

Simplest Bootloader

Started by Shefla, 28 May 2015 - 11:56 AM
Shefla #1
Posted 28 May 2015 - 01:56 PM
Hello guys,

Today I decided to share with you a small script that (I wish) will cover all your bootloading needs.
It's made to be the shortest and simplest possible startup script that allows you to launch anything you want in the top level coroutine.
This is the very first brick of my incoming OS and I would like to make it as robust as possible.
If you find a bug or a way to improve please let me know. ^^

Usage:
Press the key (f1…f10) corresponding to the boot entry you want to launch.
If there's only one boot option, the bootloader starts it automatically bypassing menu display.

Screenshot:
[attachment=2306:screenshot.png]

Install: 5zhkL3Sd

pastebin get 5zhkL3Sd startup

Configuration:
Boot entries are defined in a table at the top of the bootloader, comments should be self-explanatory.
Examples:
Spoiler

{
  name = 'LyqydOS'
, boot = function ()
	os.run({}, '/rom/programs/shell', '/LyqydOS/procman')
  end
}

{
  name = 'OneOS beta'
, boot = function ()
	os.run({}, '/rom/programs/shell', '/system/API/Bootstrap.lua')
  end
}

Tip:
Some OS installers tends to overwrite startup script, it's offen a good idea to keep a backup of your bootloader setup in safe place before installing a new OS.
Edited on 28 May 2015 - 01:49 PM
Creator #2
Posted 28 May 2015 - 02:35 PM
This is surprisingly well done. One remark only, you don't need _G.something, something is enough. Example:

_G.rednet
redent

Both point to the same table.

Just, fix the selecting system.
ry00000 #3
Posted 28 May 2015 - 02:39 PM
Oh hey! This is awesome! Can't wait to try it!
Creator #4
Posted 28 May 2015 - 02:40 PM
Oh hey! This is awesome! Can't wait to try it!

Try it, what are you waiting for?
Shefla #5
Posted 28 May 2015 - 03:09 PM
Thanks for your support, really appreciated :)/>

About using _G to reference global functions it appears to be needed when in main script scope but not inside the overwritten printError function.
For consistency and because it makes the code more readable (at least in my mind) I prefer to leave it as it is.
Shefla #6
Posted 28 May 2015 - 03:44 PM
Edited the first post to add a few config examples.

I'm not sure to understand what you mean by fix the selecting system.
Is there something not working?
Creator #7
Posted 28 May 2015 - 03:51 PM
No, my bad didn't read properly, lol.
Shefla #8
Posted 29 May 2015 - 04:12 PM
Bump to version 0.4 with a small change in default config to display correct CraftOS version.
I also did more tests in SSP: the bootloader works fine on turtle, computer & pocket either advanced or not.
Creator #9
Posted 29 May 2015 - 04:19 PM
This thing is awesome. I tried doing something similar once, and guess what, fail.
Pyuu #10
Posted 29 May 2015 - 05:38 PM
-snippy-

Nice work, but reviewing the script makes me wonder if OSes are compatible with all the environment stuff going on there. I'd have to experiment some to really find out the answer to that.
Some additional features you might consider:
  1. adding a configuration file separate from the code (however, this may limit the functionality because of function boot)
  2. GUI design (if you want to go beyond the shell look)
  3. Setting a filter on FS api calls to have partitions separate for each OS, that way LyqydOS doesn't interact with PearOS etc.
I have a small question, why do you queue "modem_message"?

Thanks~
Bomb Bloke #11
Posted 30 May 2015 - 01:44 AM
I have a small question, why do you queue "modem_message"?

Under the normal way of things, rednet.run() is constantly running in parallel with whichever shell you're using, in a separate coroutine. Among other things, that function inspects the event queue for modem_message events that it can translate into rednet_message events.

The event Shefla queues is invalid, causing rednet.run() to error out, which in turn leads to printError() being called, killing the coroutine manager handling the default shell. The bootloader, of course, implements a custom version of printError(), one which can pick up the pieces of the crash.
Pyuu #12
Posted 30 May 2015 - 02:11 AM
I have a small question, why do you queue "modem_message"?

Under the normal way of things, rednet.run() is constantly running in parallel with whichever shell you're using, in a separate coroutine. Among other things, that function inspects the event queue for modem_message events that it can translate into rednet_message events.

The event Shefla queues is invalid, causing rednet.run() to error out, which in turn leads to printError() being called, killing the coroutine manager handling the default shell. The bootloader, of course, implements a custom version of printError(), one which can pick up the pieces of the crash.
So basically, it kills the default coroutine and recreates it under a customized version?
Neat.
Bomb Bloke #13
Posted 30 May 2015 - 02:58 AM
Yep, that's it. If you dig into the assets folder within the ComputerCraft mod archive, you'll find a file called bios.lua - this is the script each system loads on boot. Down near the bottom of that you'll find the section where rednet.run() gets started up.
Shefla #14
Posted 30 May 2015 - 01:03 PM
Thanks for explaining Bomb Bloke, not sure if I could phrase it better.

(1) It's possible to store your config in external file(s) with a little help of the function dofile.
Here's an example with the whole config stored outside the bootloader:
Spoilerstartup
local entries = dofile('myBootConfig')

myBootConfig

-- return statement is required to make dofile do its job
return {
  {
	name = 'Any OS'
  , boot = function () end
  }
, {
	name = 'Other OS'
  , boot = function () end
  }
}

(2) I don't really want to add a GUI at the moment but the code is MIT licensed so feel free to build upon if you want to.
(3) Your idea of making partitions to install the different OSes properly is awesome!
However it seems beyond the bootloader mission to handle virtual filesystems.
With this program I would like to stick to the unix philosophy, do one thing and do it well.

And don't worry about global scope pollution, the only thing really added to _G is the bootloaded var you can see on line 1.
Functions rednet.run and printError are temporarily overwritten and returns to theirs original values after the trickery.
Only incompatibily I can imagine is an OS expecting rednet to be running and you forget to launch it from your boot function.
Edited on 30 May 2015 - 12:50 PM