Increase number of menu options to 20.
Add support for switching menu format between numbers and letters. Will prefer numbers, but will automatically switch to letters if > 9 options and timeout > 0 (i.e. need a single key press to choose). Menu format can be explicitly set in boot.cfg file. Add support for reading numeric choices of more than 1 digit.
This commit is contained in:
parent
094d45b30f
commit
c7b0526b9b
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: boot2.c,v 1.33 2008/08/08 07:48:32 simonb Exp $ */
|
/* $NetBSD: boot2.c,v 1.34 2008/08/12 17:56:05 sborrill Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||||
@ -108,7 +108,7 @@ static const char * const names[][2] = {
|
|||||||
|
|
||||||
#ifndef SMALL
|
#ifndef SMALL
|
||||||
#define BOOTCONF "boot.cfg"
|
#define BOOTCONF "boot.cfg"
|
||||||
#define MAXMENU 10
|
#define MAXMENU 20
|
||||||
#define MAXBANNER 12
|
#define MAXBANNER 12
|
||||||
#define COMMAND_SEPARATOR ';'
|
#define COMMAND_SEPARATOR ';'
|
||||||
#endif /* !SMALL */
|
#endif /* !SMALL */
|
||||||
@ -151,6 +151,11 @@ const struct bootblk_command commands[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifndef SMALL
|
#ifndef SMALL
|
||||||
|
|
||||||
|
#define MENUFORMAT_AUTO 0
|
||||||
|
#define MENUFORMAT_NUMBER 1
|
||||||
|
#define MENUFORMAT_LETTER 2
|
||||||
|
|
||||||
struct bootconf_def {
|
struct bootconf_def {
|
||||||
char *banner[MAXBANNER]; /* Banner text */
|
char *banner[MAXBANNER]; /* Banner text */
|
||||||
char *command[MAXMENU]; /* Menu commands per entry*/
|
char *command[MAXMENU]; /* Menu commands per entry*/
|
||||||
@ -159,6 +164,7 @@ struct bootconf_def {
|
|||||||
char *desc[MAXMENU]; /* Menu text per entry */
|
char *desc[MAXMENU]; /* Menu text per entry */
|
||||||
int nummenu; /* Number of menu items */
|
int nummenu; /* Number of menu items */
|
||||||
int timeout; /* Timeout in seconds */
|
int timeout; /* Timeout in seconds */
|
||||||
|
int menuformat; /* Print letters instead of numbers? */
|
||||||
} bootconf;
|
} bootconf;
|
||||||
#endif /* !SMALL */
|
#endif /* !SMALL */
|
||||||
|
|
||||||
@ -305,7 +311,7 @@ atoi(const char *in)
|
|||||||
* (if present) and populates the global boot configuration.
|
* (if present) and populates the global boot configuration.
|
||||||
*
|
*
|
||||||
* The file consists of a number of lines each terminated by \n
|
* The file consists of a number of lines each terminated by \n
|
||||||
* The lines are in the format keyword=value. There should be spaces
|
* The lines are in the format keyword=value. There should not be spaces
|
||||||
* around the = sign.
|
* around the = sign.
|
||||||
*
|
*
|
||||||
* The recognised keywords are:
|
* The recognised keywords are:
|
||||||
@ -314,6 +320,7 @@ atoi(const char *in)
|
|||||||
* timeout: Timeout in seconds (overrides that set by installboot)
|
* timeout: Timeout in seconds (overrides that set by installboot)
|
||||||
* default: the default menu option to use if Return is pressed
|
* default: the default menu option to use if Return is pressed
|
||||||
* consdev: the console device to use
|
* consdev: the console device to use
|
||||||
|
* format: how menu choices are displayed: (a)utomatic, (n)umbers or (l)etters
|
||||||
*
|
*
|
||||||
* Example boot.cfg file:
|
* Example boot.cfg file:
|
||||||
* banner=Welcome to NetBSD
|
* banner=Welcome to NetBSD
|
||||||
@ -344,6 +351,9 @@ parsebootconf(const char *conf)
|
|||||||
/* Set timeout to configured */
|
/* Set timeout to configured */
|
||||||
bootconf.timeout = boot_params.bp_timeout;
|
bootconf.timeout = boot_params.bp_timeout;
|
||||||
|
|
||||||
|
/* automatically switch between letter and numbers on menu */
|
||||||
|
bootconf.menuformat = MENUFORMAT_AUTO;
|
||||||
|
|
||||||
/* don't try to open BOOTCONF if the target fs is ustarfs */
|
/* don't try to open BOOTCONF if the target fs is ustarfs */
|
||||||
#ifdef SUPPORT_USTARFS
|
#ifdef SUPPORT_USTARFS
|
||||||
#if !defined(LIBSA_SINGLE_FILESYSTEM)
|
#if !defined(LIBSA_SINGLE_FILESYSTEM)
|
||||||
@ -442,10 +452,44 @@ parsebootconf(const char *conf)
|
|||||||
bootconf.def = atoi(value) - 1;
|
bootconf.def = atoi(value) - 1;
|
||||||
} else if (!strncmp(key, "consdev", 7)) {
|
} else if (!strncmp(key, "consdev", 7)) {
|
||||||
bootconf.consdev = value;
|
bootconf.consdev = value;
|
||||||
} else if (!strncmp(key, "load", 6)) {
|
} else if (!strncmp(key, "load", 4)) {
|
||||||
command_load(value);
|
command_load(value);
|
||||||
|
} else if (!strncmp(key, "format", 6)) {
|
||||||
|
printf("value:%c\n", *value);
|
||||||
|
switch (*value) {
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
bootconf.menuformat = MENUFORMAT_AUTO;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
case 'N':
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
bootconf.menuformat = MENUFORMAT_NUMBER;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
case 'L':
|
||||||
|
bootconf.menuformat = MENUFORMAT_LETTER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
switch (bootconf.menuformat) {
|
||||||
|
case MENUFORMAT_AUTO:
|
||||||
|
if (cmenu > 9 && bootconf.timeout > 0)
|
||||||
|
bootconf.menuformat = MENUFORMAT_LETTER;
|
||||||
|
else
|
||||||
|
bootconf.menuformat = MENUFORMAT_NUMBER;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MENUFORMAT_NUMBER:
|
||||||
|
if (cmenu > 9 && bootconf.timeout > 0)
|
||||||
|
cmenu = 9;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
bootconf.nummenu = cmenu;
|
bootconf.nummenu = cmenu;
|
||||||
if (bootconf.def < 0)
|
if (bootconf.def < 0)
|
||||||
bootconf.def = 0;
|
bootconf.def = 0;
|
||||||
@ -457,46 +501,74 @@ parsebootconf(const char *conf)
|
|||||||
* doboottypemenu will render the menu and parse any user input
|
* doboottypemenu will render the menu and parse any user input
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static int getchoicefrominput(char *input, int def)
|
||||||
|
{
|
||||||
|
int choice;
|
||||||
|
choice = -1;
|
||||||
|
if (*input == '\0' || *input == '\r' || *input == '\n')
|
||||||
|
choice = def;
|
||||||
|
else if (*input >= 'A' && *input < bootconf.nummenu + 'A')
|
||||||
|
choice = (*input) - 'A';
|
||||||
|
else if (*input >= 'a' && *input < bootconf.nummenu + 'a')
|
||||||
|
choice = (*input) - 'a';
|
||||||
|
else if (isnum(*input)) {
|
||||||
|
choice = atoi(input) - 1;
|
||||||
|
if (choice < 0 || choice >= bootconf.nummenu)
|
||||||
|
choice = -1;
|
||||||
|
}
|
||||||
|
return choice;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
doboottypemenu(void)
|
doboottypemenu(void)
|
||||||
{
|
{
|
||||||
int choice;
|
int choice;
|
||||||
char input[80], c, *ic, *oc;
|
char input[80], *ic, *oc;
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
/* Display menu */
|
/* Display menu */
|
||||||
for (choice = 0; choice < bootconf.nummenu; choice++)
|
if (bootconf.menuformat == MENUFORMAT_LETTER) {
|
||||||
printf(" %d. %s\n", choice+1, bootconf.desc[choice]);
|
for (choice = 0; choice < bootconf.nummenu; choice++)
|
||||||
|
printf(" %c. %s\n", choice + 'A',
|
||||||
|
bootconf.desc[choice]);
|
||||||
|
} else {
|
||||||
|
/* Can't use %2d format string with libsa */
|
||||||
|
for (choice = 0; choice < bootconf.nummenu; choice++)
|
||||||
|
printf(" %s%d. %s\n",
|
||||||
|
(choice < 9) ? " " : "",
|
||||||
|
choice + 1,
|
||||||
|
bootconf.desc[choice]);
|
||||||
|
}
|
||||||
choice = -1;
|
choice = -1;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
input[0] = '\0';
|
input[0] = '\0';
|
||||||
|
|
||||||
if (bootconf.timeout < 0) {
|
if (bootconf.timeout < 0) {
|
||||||
printf("\nOption: [%d]:", bootconf.def + 1);
|
if (bootconf.menuformat == MENUFORMAT_LETTER)
|
||||||
|
printf("\nOption: [%c]:",
|
||||||
|
bootconf.def + 'A');
|
||||||
|
else
|
||||||
|
printf("\nOption: [%d]:",
|
||||||
|
bootconf.def + 1);
|
||||||
|
|
||||||
gets(input);
|
gets(input);
|
||||||
if (input[0] == '\0') choice = bootconf.def;
|
choice = getchoicefrominput(input, bootconf.def);
|
||||||
if (input[0] >= '1' &&
|
|
||||||
input[0] <= bootconf.nummenu + '0')
|
|
||||||
choice = input[0] - '1';
|
|
||||||
} else if (bootconf.timeout == 0)
|
} else if (bootconf.timeout == 0)
|
||||||
choice = bootconf.def;
|
choice = bootconf.def;
|
||||||
else {
|
else {
|
||||||
printf("\nChoose an option; RETURN for default; "
|
printf("\nChoose an option; RETURN for default; "
|
||||||
"SPACE to stop countdown.\n");
|
"SPACE to stop countdown.\n");
|
||||||
printf("Option %d will be chosen in ",
|
if (bootconf.menuformat == MENUFORMAT_LETTER)
|
||||||
bootconf.def + 1);
|
printf("Option %d will be chosen in ",
|
||||||
c = awaitkey(bootconf.timeout, 1);
|
bootconf.def + 1);
|
||||||
if (c >= '1' && c <= bootconf.nummenu + '0')
|
printf("Option %c will be chosen in ",
|
||||||
choice = c - '1';
|
bootconf.def + 'A');
|
||||||
else if (c == '\r' || c == '\n' || c == '\0')
|
input[0] = awaitkey(bootconf.timeout, 1);
|
||||||
/* default if timed out or Return pressed */
|
input[1] = '\0';
|
||||||
choice = bootconf.def;
|
choice = getchoicefrominput(input, bootconf.def);
|
||||||
else {
|
/* If invalid key pressed, drop to menu */
|
||||||
/* If any other key pressed, drop to menu */
|
if (choice == -1)
|
||||||
bootconf.timeout = -1;
|
bootconf.timeout = -1;
|
||||||
choice = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (choice < 0)
|
if (choice < 0)
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
Reference in New Issue
Block a user