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

Reply via email to