First off, we need to start laying out CMOS. This is going to be required
for safe boot.
Here's a first cut, and I could use some more good comments.
CMOS is 256 bytes not addressable as memory. So this struct is descriptive
but can't be used as a pointer.
typedef unsigned char u8;
struct linuxbios_cmos {
u8 linux_booted_ok; // Linux booted into runlevel 3
u8 chipset_settings_index; // which chipset setting to use
u8 chipset_settings_last_known_good; // last "aggressive" good set
u8 pad[253];
};
linux_booted_ok is set by linux at the discretion of the user. In a
cluster, I would set it by issuing a command from the control node.
Cluster nodes are not really up until they can be controlled from a
control node. I would even do this for desktops; desktops aren't useful to
sysadmins until they can take a remote command.
chipset_settings_index is the index into an array that LinuxBIOS will use.
chipset_settings_last_known_good is the last non-zero index known to have
worked.
The arrays are in flash, cmos is too small to hold a useful number.
Array[0] is always the "safe" array. The arrays will vary in size,
depending on chipset.
The linux_booted_ok is set by a simple command in linux:
write_cmos <cmos offset> <value>
e.g.:
write_cmos 0 1
The LinuxBIOS code (which will have to be assemmbly) works like this:
#define LINUX_BOOTED_OK 0
#define CHIPSET_SETTINGS_INDEX 1
chipset_setup()
{
int index = 0;
if (read_cmos(LINUX_BOOTED_OK))
index = read_cmos(CHIPSET_SETTINGS_INDEX)
// is the index OK?
if (index > MAX_CHIPSET_INDEX)
index = 0; // need to indicate an error. how?
// should we use another cmos location for
// error?
// reset the linux_booted_ok. Linux has to set it.
write_cmos(LINUX_BOOTED_OK, 0);
setting = &setting_array[index];
chipset_init(setting);
}
comments?
ron