Home | History | Annotate | Line # | Download | only in efiboot
boot.c revision 1.5.2.3
      1 /*	$NetBSD: boot.c,v 1.5.2.3 2018/09/30 01:45:57 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 "efienv.h"
     34 
     35 #include <sys/bootblock.h>
     36 #include <sys/boot_flag.h>
     37 #include <machine/limits.h>
     38 
     39 #include <loadfile.h>
     40 
     41 extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
     42 
     43 extern char twiddle_toggle;
     44 
     45 static const char * const names[][2] = {
     46 	{ "netbsd", "netbsd.gz" },
     47 	{ "onetbsd", "onetbsd.gz" },
     48 	{ "netbsd.old", "netbsd.old.gz" },
     49 };
     50 
     51 #define NUMNAMES	__arraycount(names)
     52 #define DEFFILENAME	names[0][0]
     53 
     54 #define	DEFTIMEOUT	5
     55 
     56 static char default_device[32];
     57 static char initrd_path[255];
     58 static char dtb_path[255];
     59 
     60 void	command_boot(char *);
     61 void	command_dev(char *);
     62 void	command_dtb(char *);
     63 void	command_initrd(char *);
     64 void	command_ls(char *);
     65 void	command_printenv(char *);
     66 void	command_setenv(char *);
     67 void	command_clearenv(char *);
     68 void	command_resetenv(char *);
     69 void	command_reset(char *);
     70 void	command_version(char *);
     71 void	command_quit(char *);
     72 
     73 const struct boot_command commands[] = {
     74 	{ "boot",	command_boot,		"boot [dev:][filename] [args]\n     (ex. \"hd0a:\\netbsd.old -s\"" },
     75 	{ "dev",	command_dev,		"dev" },
     76 	{ "dtb",	command_dtb,		"dtb [dev:][filename]" },
     77 	{ "initrd",	command_initrd,		"initrd [dev:][filename]" },
     78 	{ "ls",		command_ls,		"ls [hdNn:/path]" },
     79 	{ "printenv",	command_printenv,	"printenv [key]" },
     80 	{ "setenv",	command_setenv,		"setenv <key> <value>" },
     81 	{ "clearenv",	command_clearenv,	"clearenv <key>" },
     82 	{ "resetenv",	command_resetenv,	"resetenv" },
     83 	{ "reboot",	command_reset,		"reboot|reset" },
     84 	{ "reset",	command_reset,		NULL },
     85 	{ "version",	command_version,	"version" },
     86 	{ "help",	command_help,		"help|?" },
     87 	{ "?",		command_help,		NULL },
     88 	{ "quit",	command_quit,		"quit" },
     89 	{ NULL,		NULL },
     90 };
     91 
     92 void
     93 command_help(char *arg)
     94 {
     95 	int n;
     96 
     97 	printf("commands are:\n");
     98 	for (n = 0; commands[n].c_name; n++) {
     99 		if (commands[n].c_help)
    100 			printf("%s\n", commands[n].c_help);
    101 	}
    102 }
    103 
    104 void
    105 command_boot(char *arg)
    106 {
    107 	char *fname = arg;
    108 	char *bootargs = gettrailer(arg);
    109 
    110 	exec_netbsd(*fname ? fname : DEFFILENAME, bootargs);
    111 }
    112 
    113 void
    114 command_dev(char *arg)
    115 {
    116 	if (arg && *arg) {
    117 		set_default_device(arg);
    118 	} else {
    119 		efi_block_show();
    120 		efi_net_show();
    121 		efi_pxe_show();
    122 	}
    123 
    124 	if (strlen(default_device) > 0) {
    125 		printf("\n");
    126 		printf("default: %s\n", default_device);
    127 	}
    128 }
    129 
    130 void
    131 command_dtb(char *arg)
    132 {
    133 	set_dtb_path(arg);
    134 }
    135 
    136 void
    137 command_initrd(char *arg)
    138 {
    139 	set_initrd_path(arg);
    140 }
    141 
    142 void
    143 command_ls(char *arg)
    144 {
    145 	ls(arg);
    146 }
    147 
    148 void
    149 command_printenv(char *arg)
    150 {
    151 	char *val;
    152 
    153 	if (arg && *arg) {
    154 		val = efi_env_get(arg);
    155 		if (val) {
    156 			printf("\"%s\" = \"%s\"\n", arg, val);
    157 			FreePool(val);
    158 		}
    159 	} else {
    160 		efi_env_print();
    161 	}
    162 }
    163 
    164 void
    165 command_setenv(char *arg)
    166 {
    167 	char *spc;
    168 
    169 	spc = strchr(arg, ' ');
    170 	if (spc == NULL || spc[1] == '\0') {
    171 		command_help("");
    172 		return;
    173 	}
    174 
    175 	*spc = '\0';
    176 	efi_env_set(arg, spc + 1);
    177 }
    178 
    179 void
    180 command_clearenv(char *arg)
    181 {
    182 	if (*arg == '\0') {
    183 		command_help("");
    184 		return;
    185 	}
    186 	efi_env_clear(arg);
    187 }
    188 
    189 void
    190 command_resetenv(char *arg)
    191 {
    192 	efi_env_reset();
    193 }
    194 
    195 void
    196 command_version(char *arg)
    197 {
    198 	char *ufirmware;
    199 	int rv;
    200 
    201 	printf("EFI version: %d.%02d\n",
    202 	    ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
    203 	ufirmware = NULL;
    204 	rv = ucs2_to_utf8(ST->FirmwareVendor, &ufirmware);
    205 	if (rv == 0) {
    206 		printf("EFI Firmware: %s (rev %d.%02d)\n", ufirmware,
    207 		    ST->FirmwareRevision >> 16,
    208 		    ST->FirmwareRevision & 0xffff);
    209 		FreePool(ufirmware);
    210 	}
    211 
    212 	efi_fdt_show();
    213 }
    214 
    215 void
    216 command_quit(char *arg)
    217 {
    218 	efi_exit();
    219 }
    220 
    221 void
    222 command_reset(char *arg)
    223 {
    224 	efi_reboot();
    225 }
    226 
    227 int
    228 set_default_device(char *arg)
    229 {
    230 	if (strlen(arg) + 1 > sizeof(default_device))
    231 		return ERANGE;
    232 	strcpy(default_device, arg);
    233 	return 0;
    234 }
    235 
    236 char *
    237 get_default_device(void)
    238 {
    239 	return default_device;
    240 }
    241 
    242 int
    243 set_initrd_path(char *arg)
    244 {
    245 	if (strlen(arg) + 1 > sizeof(initrd_path))
    246 		return ERANGE;
    247 	strcpy(initrd_path, arg);
    248 	return 0;
    249 }
    250 
    251 char *
    252 get_initrd_path(void)
    253 {
    254 	return initrd_path;
    255 }
    256 
    257 int
    258 set_dtb_path(char *arg)
    259 {
    260 	if (strlen(arg) + 1 > sizeof(dtb_path))
    261 		return ERANGE;
    262 	strcpy(dtb_path, arg);
    263 	return 0;
    264 }
    265 
    266 char *
    267 get_dtb_path(void)
    268 {
    269 	return dtb_path;
    270 }
    271 
    272 void
    273 print_banner(void)
    274 {
    275 	printf("\n\n"
    276 	    ">> %s, Revision %s (from NetBSD %s)\n",
    277 	    bootprog_name, bootprog_rev, bootprog_kernrev);
    278 }
    279 
    280 static void
    281 read_env(void)
    282 {
    283 	char *s;
    284 
    285 	s = efi_env_get("fdtfile");
    286 	if (s) {
    287 #ifdef EFIBOOT_DEBUG
    288 		printf(">> Setting DTB path to '%s' from environment\n", s);
    289 #endif
    290 		set_dtb_path(s);
    291 		FreePool(s);
    292 	}
    293 
    294 	s = efi_env_get("initrd");
    295 	if (s) {
    296 #ifdef EFIBOOT_DEBUG
    297 		printf(">> Setting initrd path to '%s' from environment\n", s);
    298 #endif
    299 		set_initrd_path(s);
    300 		FreePool(s);
    301 	}
    302 
    303 	s = efi_env_get("rootdev");
    304 	if (s) {
    305 #ifdef EFIBOOT_DEBUG
    306 		printf(">> Setting default device to '%s' from environment\n", s);
    307 #endif
    308 		set_default_device(s);
    309 		FreePool(s);
    310 	}
    311 }
    312 
    313 void
    314 boot(void)
    315 {
    316 	int currname, c;
    317 
    318 	read_env();
    319 
    320 	print_banner();
    321 
    322 	printf("Press return to boot now, any other key for boot prompt\n");
    323 	for (currname = 0; currname < NUMNAMES; currname++) {
    324 		printf("booting %s - starting in ", names[currname][0]);
    325 
    326 		c = awaitkey(DEFTIMEOUT, 1);
    327 		if ((c != '\r') && (c != '\n') && (c != '\0')) {
    328 			bootprompt(); /* does not return */
    329 		}
    330 
    331 		/*
    332 		 * try pairs of names[] entries, foo and foo.gz
    333 		 */
    334 		exec_netbsd(names[currname][0], "");
    335 		exec_netbsd(names[currname][1], "");
    336 	}
    337 
    338 	bootprompt();	/* does not return */
    339 }
    340