Add boot.cfg support.

This commit is contained in:
jmcneill 2020-06-21 23:53:26 +00:00
parent b906de5d01
commit 2b6ae1af1d
6 changed files with 288 additions and 7 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile.efiboot,v 1.14 2020/06/21 17:24:26 jmcneill Exp $
# $NetBSD: Makefile.efiboot,v 1.15 2020/06/21 23:53:26 jmcneill Exp $
S= ${.CURDIR}/../../..
@ -21,8 +21,8 @@ AFLAGS.start.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
.PATH: ${EFIDIR}/gnuefi
SOURCES= crt0-efi-${GNUEFIARCH}.S reloc_${GNUEFIARCH}.c
SOURCES+= boot.c conf.c console.c dev_net.c devopen.c exec.c module.c \
panic.c prompt.c
SOURCES+= boot.c bootmenu.c conf.c console.c dev_net.c devopen.c exec.c \
module.c panic.c prompt.c
SOURCES+= efiboot.c efichar.c efidev.c efienv.c efigetsecs.c efifdt.c \
efifile.c efiblock.c efinet.c efipxe.c efiacpi.c efirng.c smbios.c

View File

@ -1,4 +1,4 @@
/* $NetBSD: boot.c,v 1.22 2020/06/21 17:24:26 jmcneill Exp $ */
/* $NetBSD: boot.c,v 1.23 2020/06/21 23:53:26 jmcneill Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <nonaka@netbsd.org>
@ -34,12 +34,14 @@
#include "efienv.h"
#include "efirng.h"
#include "module.h"
#include "bootmenu.h"
#include <sys/bootblock.h>
#include <sys/boot_flag.h>
#include <machine/limits.h>
#include <loadfile.h>
#include <bootcfg.h>
extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
@ -96,6 +98,7 @@ void command_load(char *);
void command_unload(char *);
void command_ls(char *);
void command_mem(char *);
void command_menu(char *);
void command_printenv(char *);
void command_setenv(char *);
void command_clearenv(char *);
@ -116,6 +119,7 @@ const struct boot_command commands[] = {
{ "unload", command_unload, "unload <module_name>" },
{ "ls", command_ls, "ls [hdNn:/path]" },
{ "mem", command_mem, "mem" },
{ "menu", command_menu, "menu" },
{ "printenv", command_printenv, "printenv [key]" },
{ "setenv", command_setenv, "setenv <key> <value>" },
{ "clearenv", command_clearenv, "clearenv <key>" },
@ -268,6 +272,17 @@ command_mem(char *arg)
}
}
void
command_menu(char *arg)
{
if (bootcfg_info.nummenu == 0) {
printf("No menu defined in boot.cfg\n");
return;
}
doboottypemenu(); /* Does not return */
}
void
command_printenv(char *arg)
{
@ -530,7 +545,20 @@ boot(void)
int currname, c;
read_env();
parsebootconf(BOOTCFG_FILENAME);
if (bootcfg_info.clear)
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
print_banner();
/* Display menu if configured */
twiddle_toggle = 1;
if (bootcfg_info.nummenu > 0) {
doboottypemenu(); /* No return */
}
printf("Press return to boot now, any other key for boot prompt\n");
if (netbsd_path[0] != '\0')

View File

@ -0,0 +1,215 @@
/* $NetBSD: bootmenu.c,v 1.1 2020/06/21 23:53:26 jmcneill Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SMALL
#include <sys/types.h>
#include <sys/reboot.h>
#include <sys/bootblock.h>
#include <lib/libsa/stand.h>
#include <lib/libsa/bootcfg.h>
#include <lib/libsa/ufs.h>
#include <lib/libkern/libkern.h>
#include "bootmenu.h"
#include "efiboot.h"
#include "module.h"
static void docommandchoice(int);
extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
#define MENUFORMAT_AUTO 0
#define MENUFORMAT_NUMBER 1
#define MENUFORMAT_LETTER 2
/*
* XXX
* if module_add, userconf_add are strictly mi they can be folded back
* into sys/lib/libsa/bootcfg.c:perform_bootcfg().
*/
static void
do_bootcfg_command(const char *cmd, char *arg)
{
if (strcmp(cmd, BOOTCFG_CMD_LOAD) == 0)
module_add(arg);
#if notyet
else if (strcmp(cmd, BOOTCFG_CMD_USERCONF) == 0)
userconf_add(arg);
#endif
}
int
parsebootconf(const char *conf)
{
return perform_bootcfg(conf, &do_bootcfg_command, 32768);
}
/*
* doboottypemenu will render the menu and parse any user input
*/
static int
getchoicefrominput(char *input, int def)
{
int choice, usedef;
choice = -1;
usedef = 0;
if (*input == '\0' || *input == '\r' || *input == '\n') {
choice = def;
usedef = 1;
} else if (*input >= 'A' && *input < bootcfg_info.nummenu + 'A')
choice = (*input) - 'A';
else if (*input >= 'a' && *input < bootcfg_info.nummenu + 'a')
choice = (*input) - 'a';
else if (isdigit(*input)) {
choice = atoi(input) - 1;
if (choice < 0 || choice >= bootcfg_info.nummenu)
choice = -1;
}
if (bootcfg_info.menuformat != MENUFORMAT_LETTER &&
!isdigit(*input) && !usedef)
choice = -1;
return choice;
}
static void
docommandchoice(int choice)
{
char input[80], *ic, *oc;
ic = bootcfg_info.command[choice];
/* Split command string at ; into separate commands */
do {
oc = input;
/* Look for ; separator */
for (; *ic && *ic != COMMAND_SEPARATOR; ic++)
*oc++ = *ic;
if (*input == '\0')
continue;
/* Strip out any trailing spaces */
oc--;
for (; *oc == ' ' && oc > input; oc--);
*++oc = '\0';
if (*ic == COMMAND_SEPARATOR)
ic++;
/* Stop silly command strings like ;;; */
if (*input != '\0')
docommand(input);
/* Skip leading spaces */
for (; *ic == ' '; ic++);
} while (*ic);
}
void
bootdefault(void)
{
int choice;
static int entered;
if (bootcfg_info.nummenu > 0) {
if (entered) {
printf("default boot twice, skipping...\n");
return;
}
entered = 1;
choice = bootcfg_info.def;
printf("command(s): %s\n", bootcfg_info.command[choice]);
docommandchoice(choice);
}
}
__dead void
doboottypemenu(void)
{
int choice;
char input[80];
printf("\n");
/* Display menu */
if (bootcfg_info.menuformat == MENUFORMAT_LETTER) {
for (choice = 0; choice < bootcfg_info.nummenu; choice++)
printf(" %c. %s\n", choice + 'A',
bootcfg_info.desc[choice]);
} else {
/* Can't use %2d format string with libsa */
for (choice = 0; choice < bootcfg_info.nummenu; choice++)
printf(" %s%d. %s\n",
(choice < 9) ? " " : "",
choice + 1,
bootcfg_info.desc[choice]);
}
choice = -1;
for (;;) {
input[0] = '\0';
if (bootcfg_info.timeout < 0) {
if (bootcfg_info.menuformat == MENUFORMAT_LETTER)
printf("\nOption: [%c]:",
bootcfg_info.def + 'A');
else
printf("\nOption: [%d]:",
bootcfg_info.def + 1);
kgets(input, sizeof(input));
choice = getchoicefrominput(input, bootcfg_info.def);
} else if (bootcfg_info.timeout == 0)
choice = bootcfg_info.def;
else {
printf("\nChoose an option; RETURN for default; "
"SPACE to stop countdown.\n");
if (bootcfg_info.menuformat == MENUFORMAT_LETTER)
printf("Option %c will be chosen in ",
bootcfg_info.def + 'A');
else
printf("Option %d will be chosen in ",
bootcfg_info.def + 1);
input[0] = awaitkey(bootcfg_info.timeout, 1);
input[1] = '\0';
choice = getchoicefrominput(input, bootcfg_info.def);
/* If invalid key pressed, drop to menu */
if (choice == -1)
bootcfg_info.timeout = -1;
}
if (choice < 0)
continue;
if (!strcmp(bootcfg_info.command[choice], "prompt")) {
printf("type \"?\" or \"help\" for help.\n");
bootprompt(); /* does not return */
} else {
docommandchoice(choice);
}
}
}
#endif /* !SMALL */

View File

@ -0,0 +1,38 @@
/* $NetBSD: bootmenu.h,v 1.1 2020/06/21 23:53:26 jmcneill Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _BOOTMENU_H
#define _BOOTMENU_H
#define COMMAND_SEPARATOR ';'
int parsebootconf(const char *);
void doboottypemenu(void);
void bootdefault(void);
#endif /* !_BOOTMENU_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: efiboot.c,v 1.18 2020/05/14 19:20:08 riastradh Exp $ */
/* $NetBSD: efiboot.c,v 1.19 2020/06/21 23:53:26 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
@ -72,7 +72,6 @@ efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable)
uefi_call_wrapper(ST->ConOut->Reset, 2, ST->ConOut, TRUE);
uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, 0);
uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, TRUE);
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiLoaderData, sz, &heap_start);
if (EFI_ERROR(status))

View File

@ -1,4 +1,4 @@
$NetBSD: version,v 1.16 2020/06/21 17:24:26 jmcneill Exp $
$NetBSD: version,v 1.17 2020/06/21 23:53:26 jmcneill Exp $
NOTE ANY CHANGES YOU MAKE TO THE EFI BOOTLOADER HERE. The format of this
file is important - make sure the entries are appended on end, last item
@ -20,3 +20,4 @@ is taken as the current.
1.13: Add rndseed support.
1.14: Add EFI RNG support.
1.15: Add module support.
2.0: Add boot.cfg support.