boot.c revision 1.4 1 /* $NetBSD: boot.c,v 1.4 2018/09/03 00:04:02 jmcneill 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
33 #include <sys/bootblock.h>
34 #include <sys/boot_flag.h>
35 #include <machine/limits.h>
36
37 #include <loadfile.h>
38
39 extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
40
41 extern char twiddle_toggle;
42
43 static const char * const names[][2] = {
44 { "netbsd", "netbsd.gz" },
45 { "onetbsd", "onetbsd.gz" },
46 { "netbsd.old", "netbsd.old.gz" },
47 };
48
49 #define NUMNAMES __arraycount(names)
50 #define DEFFILENAME names[0][0]
51
52 #define DEFTIMEOUT 5
53
54 static char default_device[32];
55
56 void command_boot(char *);
57 void command_dev(char *);
58 void command_ls(char *);
59 void command_reset(char *);
60 void command_version(char *);
61 void command_quit(char *);
62
63 const struct boot_command commands[] = {
64 { "boot", command_boot, "boot [fsN:][filename] [args]\n (ex. \"fs0:\\netbsd.old -s\"" },
65 { "dev", command_dev, "dev" },
66 { "ls", command_ls, "ls [hdNn:/path]" },
67 { "version", command_version, "version" },
68 { "help", command_help, "help|?" },
69 { "?", command_help, NULL },
70 { "quit", command_quit, "quit" },
71 { NULL, NULL },
72 };
73
74 void
75 command_help(char *arg)
76 {
77 int n;
78
79 printf("commands are:\n");
80 for (n = 0; commands[n].c_name; n++) {
81 if (commands[n].c_help)
82 printf("%s\n", commands[n].c_help);
83 }
84 }
85
86 void
87 command_boot(char *arg)
88 {
89 char *fname = arg;
90 char *bootargs = gettrailer(arg);
91
92 exec_netbsd(*fname ? fname : DEFFILENAME, bootargs);
93 }
94
95 void
96 command_dev(char *arg)
97 {
98 if (arg && *arg) {
99 set_default_device(arg);
100 } else {
101 efi_block_show();
102 efi_net_show();
103 efi_pxe_show();
104 }
105
106 if (strlen(default_device) > 0) {
107 printf("\n");
108 printf("default: %s\n", default_device);
109 }
110 }
111
112 void
113 command_ls(char *arg)
114 {
115 ls(arg);
116 }
117
118 void
119 command_version(char *arg)
120 {
121 char *ufirmware;
122 int rv;
123
124 printf("EFI version: %d.%02d\n",
125 ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
126 ufirmware = NULL;
127 rv = ucs2_to_utf8(ST->FirmwareVendor, &ufirmware);
128 if (rv == 0) {
129 printf("EFI Firmware: %s (rev %d.%02d)\n", ufirmware,
130 ST->FirmwareRevision >> 16,
131 ST->FirmwareRevision & 0xffff);
132 FreePool(ufirmware);
133 }
134 }
135
136 void
137 command_quit(char *arg)
138 {
139 efi_exit();
140 }
141
142 int
143 set_default_device(char *arg)
144 {
145 if (strlen(arg) + 1 > sizeof(default_device))
146 return ERANGE;
147 strcpy(default_device, arg);
148 return 0;
149 }
150
151 char *
152 get_default_device(void)
153 {
154 return default_device;
155 }
156
157 void
158 print_banner(void)
159 {
160 printf("\n\n"
161 ">> %s, Revision %s (from NetBSD %s)\n",
162 bootprog_name, bootprog_rev, bootprog_kernrev);
163 }
164
165 void
166 boot(void)
167 {
168 int currname, c;
169
170 print_banner();
171
172 printf("Press return to boot now, any other key for boot prompt\n");
173 for (currname = 0; currname < NUMNAMES; currname++) {
174 printf("booting %s - starting in ", names[currname][0]);
175
176 c = awaitkey(DEFTIMEOUT, 1);
177 if ((c != '\r') && (c != '\n') && (c != '\0')) {
178 bootprompt(); /* does not return */
179 }
180
181 /*
182 * try pairs of names[] entries, foo and foo.gz
183 */
184 exec_netbsd(names[currname][0], "");
185 exec_netbsd(names[currname][1], "");
186 }
187
188 bootprompt(); /* does not return */
189 }
190