Home | History | Annotate | Line # | Download | only in efiboot
boot.c revision 1.5.2.4
      1 /*	$NetBSD: boot.c,v 1.5.2.4 2018/10/20 06:58:46 pgoyette Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2016 Kimihiro Nonaka <nonaka (at) netbsd.org>
      5  * Copyright (c) 2018 Jared McNeill <jmcneill (at) invisible.ca>
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  */
     29 
     30 #include "efiboot.h"
     31 #include "efiblock.h"
     32 #include "efifdt.h"
     33 #include "efiacpi.h"
     34 #include "efienv.h"
     35 
     36 #include <sys/bootblock.h>
     37 #include <sys/boot_flag.h>
     38 #include <machine/limits.h>
     39 
     40 #include <loadfile.h>
     41 
     42 extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
     43 
     44 extern char twiddle_toggle;
     45 
     46 static const char * const names[][2] = {
     47 	{ "netbsd", "netbsd.gz" },
     48 	{ "onetbsd", "onetbsd.gz" },
     49 	{ "netbsd.old", "netbsd.old.gz" },
     50 };
     51 
     52 #define NUMNAMES	__arraycount(names)
     53 #define DEFFILENAME	names[0][0]
     54 
     55 #define	DEFTIMEOUT	5
     56 
     57 static char default_device[32];
     58 static char initrd_path[255];
     59 static char dtb_path[255];
     60 
     61 void	command_boot(char *);
     62 void	command_dev(char *);
     63 void	command_dtb(char *);
     64 void	command_initrd(char *);
     65 void	command_ls(char *);
     66 void	command_printenv(char *);
     67 void	command_setenv(char *);
     68 void	command_clearenv(char *);
     69 void	command_resetenv(char *);
     70 void	command_reset(char *);
     71 void	command_version(char *);
     72 void	command_quit(char *);
     73 
     74 const struct boot_command commands[] = {
     75 	{ "boot",	command_boot,		"boot [dev:][filename] [args]\n     (ex. \"hd0a:\\netbsd.old -s\"" },
     76 	{ "dev",	command_dev,		"dev" },
     77 	{ "dtb",	command_dtb,		"dtb [dev:][filename]" },
     78 	{ "initrd",	command_initrd,		"initrd [dev:][filename]" },
     79 	{ "ls",		command_ls,		"ls [hdNn:/path]" },
     80 	{ "printenv",	command_printenv,	"printenv [key]" },
     81 	{ "setenv",	command_setenv,		"setenv <key> <value>" },
     82 	{ "clearenv",	command_clearenv,	"clearenv <key>" },
     83 	{ "resetenv",	command_resetenv,	"resetenv" },
     84 	{ "reboot",	command_reset,		"reboot|reset" },
     85 	{ "reset",	command_reset,		NULL },
     86 	{ "version",	command_version,	"version" },
     87 	{ "help",	command_help,		"help|?" },
     88 	{ "?",		command_help,		NULL },
     89 	{ "quit",	command_quit,		"quit" },
     90 	{ NULL,		NULL },
     91 };
     92 
     93 void
     94 command_help(char *arg)
     95 {
     96 	int n;
     97 
     98 	printf("commands are:\n");
     99 	for (n = 0; commands[n].c_name; n++) {
    100 		if (commands[n].c_help)
    101 			printf("%s\n", commands[n].c_help);
    102 	}
    103 }
    104 
    105 void
    106 command_boot(char *arg)
    107 {
    108 	char *fname = arg;
    109 	char *bootargs = gettrailer(arg);
    110 
    111 	exec_netbsd(*fname ? fname : DEFFILENAME, bootargs);
    112 }
    113 
    114 void
    115 command_dev(char *arg)
    116 {
    117 	if (arg && *arg) {
    118 		set_default_device(arg);
    119 	} else {
    120 		efi_block_show();
    121 		efi_net_show();
    122 		efi_pxe_show();
    123 	}
    124 
    125 	if (strlen(default_device) > 0) {
    126 		printf("\n");
    127 		printf("default: %s\n", default_device);
    128 	}
    129 }
    130 
    131 void
    132 command_dtb(char *arg)
    133 {
    134 	set_dtb_path(arg);
    135 }
    136 
    137 void
    138 command_initrd(char *arg)
    139 {
    140 	set_initrd_path(arg);
    141 }
    142 
    143 void
    144 command_ls(char *arg)
    145 {
    146 	ls(arg);
    147 }
    148 
    149 void
    150 command_printenv(char *arg)
    151 {
    152 	char *val;
    153 
    154 	if (arg && *arg) {
    155 		val = efi_env_get(arg);
    156 		if (val) {
    157 			printf("\"%s\" = \"%s\"\n", arg, val);
    158 			FreePool(val);
    159 		}
    160 	} else {
    161 		efi_env_print();
    162 	}
    163 }
    164 
    165 void
    166 command_setenv(char *arg)
    167 {
    168 	char *spc;
    169 
    170 	spc = strchr(arg, ' ');
    171 	if (spc == NULL || spc[1] == '\0') {
    172 		command_help("");
    173 		return;
    174 	}
    175 
    176 	*spc = '\0';
    177 	efi_env_set(arg, spc + 1);
    178 }
    179 
    180 void
    181 command_clearenv(char *arg)
    182 {
    183 	if (*arg == '\0') {
    184 		command_help("");
    185 		return;
    186 	}
    187 	efi_env_clear(arg);
    188 }
    189 
    190 void
    191 command_resetenv(char *arg)
    192 {
    193 	efi_env_reset();
    194 }
    195 
    196 void
    197 command_version(char *arg)
    198 {
    199 	char *ufirmware;
    200 	int rv;
    201 
    202 	printf("EFI version: %d.%02d\n",
    203 	    ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
    204 	ufirmware = NULL;
    205 	rv = ucs2_to_utf8(ST->FirmwareVendor, &ufirmware);
    206 	if (rv == 0) {
    207 		printf("EFI Firmware: %s (rev %d.%02d)\n", ufirmware,
    208 		    ST->FirmwareRevision >> 16,
    209 		    ST->FirmwareRevision & 0xffff);
    210 		FreePool(ufirmware);
    211 	}
    212 
    213 	efi_fdt_show();
    214 	efi_acpi_show();
    215 }
    216 
    217 void
    218 command_quit(char *arg)
    219 {
    220 	efi_exit();
    221 }
    222 
    223 void
    224 command_reset(char *arg)
    225 {
    226 	efi_reboot();
    227 }
    228 
    229 int
    230 set_default_device(char *arg)
    231 {
    232 	if (strlen(arg) + 1 > sizeof(default_device))
    233 		return ERANGE;
    234 	strcpy(default_device, arg);
    235 	return 0;
    236 }
    237 
    238 char *
    239 get_default_device(void)
    240 {
    241 	return default_device;
    242 }
    243 
    244 int
    245 set_initrd_path(char *arg)
    246 {
    247 	if (strlen(arg) + 1 > sizeof(initrd_path))
    248 		return ERANGE;
    249 	strcpy(initrd_path, arg);
    250 	return 0;
    251 }
    252 
    253 char *
    254 get_initrd_path(void)
    255 {
    256 	return initrd_path;
    257 }
    258 
    259 int
    260 set_dtb_path(char *arg)
    261 {
    262 	if (strlen(arg) + 1 > sizeof(dtb_path))
    263 		return ERANGE;
    264 	strcpy(dtb_path, arg);
    265 	return 0;
    266 }
    267 
    268 char *
    269 get_dtb_path(void)
    270 {
    271 	return dtb_path;
    272 }
    273 
    274 void
    275 print_banner(void)
    276 {
    277 	printf("\n\n"
    278 	    ">> %s, Revision %s (from NetBSD %s)\n",
    279 	    bootprog_name, bootprog_rev, bootprog_kernrev);
    280 }
    281 
    282 static void
    283 read_env(void)
    284 {
    285 	char *s;
    286 
    287 	s = efi_env_get("fdtfile");
    288 	if (s) {
    289 #ifdef EFIBOOT_DEBUG
    290 		printf(">> Setting DTB path to '%s' from environment\n", s);
    291 #endif
    292 		set_dtb_path(s);
    293 		FreePool(s);
    294 	}
    295 
    296 	s = efi_env_get("initrd");
    297 	if (s) {
    298 #ifdef EFIBOOT_DEBUG
    299 		printf(">> Setting initrd path to '%s' from environment\n", s);
    300 #endif
    301 		set_initrd_path(s);
    302 		FreePool(s);
    303 	}
    304 
    305 	s = efi_env_get("rootdev");
    306 	if (s) {
    307 #ifdef EFIBOOT_DEBUG
    308 		printf(">> Setting default device to '%s' from environment\n", s);
    309 #endif
    310 		set_default_device(s);
    311 		FreePool(s);
    312 	}
    313 }
    314 
    315 void
    316 boot(void)
    317 {
    318 	int currname, c;
    319 
    320 	read_env();
    321 
    322 	print_banner();
    323 
    324 	printf("Press return to boot now, any other key for boot prompt\n");
    325 	for (currname = 0; currname < NUMNAMES; currname++) {
    326 		printf("booting %s - starting in ", names[currname][0]);
    327 
    328 		c = awaitkey(DEFTIMEOUT, 1);
    329 		if ((c != '\r') && (c != '\n') && (c != '\0')) {
    330 			bootprompt(); /* does not return */
    331 		}
    332 
    333 		/*
    334 		 * try pairs of names[] entries, foo and foo.gz
    335 		 */
    336 		exec_netbsd(names[currname][0], "");
    337 		exec_netbsd(names[currname][1], "");
    338 	}
    339 
    340 	bootprompt();	/* does not return */
    341 }
    342