implement a simple payload chooser for coreboot.

This is always built into coreboot, and is enabled by a static variable
in src/lib/hardwaremain.c. Payload choosing can be enabled at build
time, or at runtime via jtag/gdb.

The operation is simple. The chooser, if enabled, lists the payloads and puts
up a prompt.

Payloads:
fallback/payload
Pick one>

The user then types in the name of a payload, e.g.
Pick one>fallback/payload

The line is ended by newline or carriage return.

And the payload is booted.

If you get it wrong, no backspace
or correction. Just hit return and try again.

I started with Bayou but feel the need is low and the complexity
high for that solution; this is just much simpler.

So, let's think about some UI here. Some options:
- default to the first payload if the user hits return
- time out after 5 seconds or so
- Don't make people type the name;
	number the payloads as they are printed and let the user
	hit, say, 2, to get the second payload

What would you like to see?

BUG=None
TEST=Works on Nyan
BRANCH=None

Change-Id: I4f93633636abf73e65e1b14c1b9e77ac2e25c453
Signed-off-by: Ronald G. Minnich <rminnich@google.com>
Reviewed-on: https://chromium-review.googlesource.com/180343
Reviewed-by: Puneet Kumar <puneetster@chromium.org>
Commit-Queue: Ronald Minnich <rminnich@chromium.org>
Tested-by: Ronald Minnich <rminnich@chromium.org>
This commit is contained in:
Ronald G. Minnich 2013-12-11 11:40:17 -08:00 committed by chrome-internal-fetch
commit ec151d0a4e

View file

@ -222,15 +222,53 @@ static boot_state_t bs_write_tables(void *arg)
return BS_PAYLOAD_LOAD;
}
/* This is something we don't want to use most of the time.
* It is for debug only. Hence, it is not a config variable.
* It is done this way so people can control it from
* build or at runtime via gdb/jtag. The amount of code it
* adds is insignificant.
*/
static int chooser = 0;
static boot_state_t bs_payload_load(void *arg)
{
void *payload;
void *payload = NULL;
void *entry;
const char *payload_name = CONFIG_CBFS_PREFIX "/payload";
timestamp_add_now(TS_LOAD_PAYLOAD);
payload = cbfs_load_payload(CBFS_DEFAULT_MEDIA,
CONFIG_CBFS_PREFIX "/payload");
if (chooser) {
static char chosen[128];
static struct cbfs_payload_info info[16];
int i;
int npayloads;
printk(BIOS_SPEW, "Payloads:\n");
npayloads = cbfs_payload_headers(CBFS_DEFAULT_MEDIA,
info, ARRAY_SIZE(info));
for(i = 0; i < npayloads; i++)
printk(BIOS_INFO, "%s\n", info[i].name);
while (! payload) {
printk(BIOS_SPEW, "Pick one>");
for(i = 0; i < sizeof(chosen); i++) {
chosen[i] = console_rx_byte();
console_tx_byte(chosen[i]);
if ((chosen[i] == '\n') || (chosen[i] == '\r')) {
chosen[i] = 0;
break;
}
}
printk(BIOS_SPEW, "Try to get :%s:\n", chosen);
payload_name = chosen;
payload = cbfs_load_payload(CBFS_DEFAULT_MEDIA,
payload_name);
}
}
if (! payload)
payload = cbfs_load_payload(CBFS_DEFAULT_MEDIA,
payload_name);
if (! payload)
die("Could not find a payload\n");