Deleted Added
full compact
main.c (302408) main.c (312318)
1/*-
2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/11/sys/boot/i386/loader/main.c 298230 2016-04-18 23:09:22Z allanjude $");
28__FBSDID("$FreeBSD: stable/11/sys/boot/i386/loader/main.c 312318 2017-01-17 01:29:03Z emaste $");
29
30/*
31 * MD bootstrap main() and assorted miscellaneous
32 * commands.
33 */
34
35#include <stand.h>
36#include <stddef.h>
37#include <string.h>
38#include <machine/bootinfo.h>
39#include <machine/cpufunc.h>
40#include <machine/psl.h>
41#include <sys/reboot.h>
42
43#include "bootstrap.h"
44#include "common/bootargs.h"
45#include "libi386/libi386.h"
46#include "libi386/smbios.h"
47#include "btxv86.h"
48
49#ifdef LOADER_ZFS_SUPPORT
50#include "../zfs/libzfs.h"
51#endif
52
53CTASSERT(sizeof(struct bootargs) == BOOTARGS_SIZE);
54CTASSERT(offsetof(struct bootargs, bootinfo) == BA_BOOTINFO);
55CTASSERT(offsetof(struct bootargs, bootflags) == BA_BOOTFLAGS);
56CTASSERT(offsetof(struct bootinfo, bi_size) == BI_SIZE);
57
58/* Arguments passed in from the boot1/boot2 loader */
59static struct bootargs *kargs;
60
61static u_int32_t initial_howto;
62static u_int32_t initial_bootdev;
63static struct bootinfo *initial_bootinfo;
64
65struct arch_switch archsw; /* MI/MD interface boundary */
66
67static void extract_currdev(void);
68static int isa_inb(int port);
69static void isa_outb(int port, int value);
70void exit(int code);
71#ifdef LOADER_GELI_SUPPORT
72struct geli_boot_args *gargs;
73#endif
74#ifdef LOADER_ZFS_SUPPORT
75struct zfs_boot_args *zargs;
76static void i386_zfs_probe(void);
77#endif
78
79/* from vers.c */
29
30/*
31 * MD bootstrap main() and assorted miscellaneous
32 * commands.
33 */
34
35#include <stand.h>
36#include <stddef.h>
37#include <string.h>
38#include <machine/bootinfo.h>
39#include <machine/cpufunc.h>
40#include <machine/psl.h>
41#include <sys/reboot.h>
42
43#include "bootstrap.h"
44#include "common/bootargs.h"
45#include "libi386/libi386.h"
46#include "libi386/smbios.h"
47#include "btxv86.h"
48
49#ifdef LOADER_ZFS_SUPPORT
50#include "../zfs/libzfs.h"
51#endif
52
53CTASSERT(sizeof(struct bootargs) == BOOTARGS_SIZE);
54CTASSERT(offsetof(struct bootargs, bootinfo) == BA_BOOTINFO);
55CTASSERT(offsetof(struct bootargs, bootflags) == BA_BOOTFLAGS);
56CTASSERT(offsetof(struct bootinfo, bi_size) == BI_SIZE);
57
58/* Arguments passed in from the boot1/boot2 loader */
59static struct bootargs *kargs;
60
61static u_int32_t initial_howto;
62static u_int32_t initial_bootdev;
63static struct bootinfo *initial_bootinfo;
64
65struct arch_switch archsw; /* MI/MD interface boundary */
66
67static void extract_currdev(void);
68static int isa_inb(int port);
69static void isa_outb(int port, int value);
70void exit(int code);
71#ifdef LOADER_GELI_SUPPORT
72struct geli_boot_args *gargs;
73#endif
74#ifdef LOADER_ZFS_SUPPORT
75struct zfs_boot_args *zargs;
76static void i386_zfs_probe(void);
77#endif
78
79/* from vers.c */
80extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
80extern char bootprog_info[];
81
82/* XXX debugging */
83extern char end[];
84
85static void *heap_top;
86static void *heap_bottom;
87
88int
89main(void)
90{
91 int i;
92
93 /* Pick up arguments */
94 kargs = (void *)__args;
95 initial_howto = kargs->howto;
96 initial_bootdev = kargs->bootdev;
97 initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL;
98
99 /* Initialize the v86 register set to a known-good state. */
100 bzero(&v86, sizeof(v86));
101 v86.efl = PSL_RESERVED_DEFAULT | PSL_I;
102
103 /*
104 * Initialise the heap as early as possible. Once this is done, malloc() is usable.
105 */
106 bios_getmem();
107
108#if defined(LOADER_BZIP2_SUPPORT) || defined(LOADER_FIREWIRE_SUPPORT) || \
109 defined(LOADER_GPT_SUPPORT) || defined(LOADER_ZFS_SUPPORT)
110 if (high_heap_size > 0) {
111 heap_top = PTOV(high_heap_base + high_heap_size);
112 heap_bottom = PTOV(high_heap_base);
113 if (high_heap_base < memtop_copyin)
114 memtop_copyin = high_heap_base;
115 } else
116#endif
117 {
118 heap_top = (void *)PTOV(bios_basemem);
119 heap_bottom = (void *)end;
120 }
121 setheap(heap_bottom, heap_top);
122
123 /*
124 * XXX Chicken-and-egg problem; we want to have console output early, but some
125 * console attributes may depend on reading from eg. the boot device, which we
126 * can't do yet.
127 *
128 * We can use printf() etc. once this is done.
129 * If the previous boot stage has requested a serial console, prefer that.
130 */
131 bi_setboothowto(initial_howto);
132 if (initial_howto & RB_MULTIPLE) {
133 if (initial_howto & RB_SERIAL)
134 setenv("console", "comconsole vidconsole", 1);
135 else
136 setenv("console", "vidconsole comconsole", 1);
137 } else if (initial_howto & RB_SERIAL)
138 setenv("console", "comconsole", 1);
139 else if (initial_howto & RB_MUTE)
140 setenv("console", "nullconsole", 1);
141 cons_probe();
142
143 /*
144 * Initialise the block cache. Set the upper limit.
145 */
146 bcache_init(32768, 512);
147
148 /*
149 * Special handling for PXE and CD booting.
150 */
151 if (kargs->bootinfo == 0) {
152 /*
153 * We only want the PXE disk to try to init itself in the below
154 * walk through devsw if we actually booted off of PXE.
155 */
156 if (kargs->bootflags & KARGS_FLAGS_PXE)
157 pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL);
158 else if (kargs->bootflags & KARGS_FLAGS_CD)
159 bc_add(initial_bootdev);
160 }
161
162 archsw.arch_autoload = i386_autoload;
163 archsw.arch_getdev = i386_getdev;
164 archsw.arch_copyin = i386_copyin;
165 archsw.arch_copyout = i386_copyout;
166 archsw.arch_readin = i386_readin;
167 archsw.arch_isainb = isa_inb;
168 archsw.arch_isaoutb = isa_outb;
169#ifdef LOADER_ZFS_SUPPORT
170 archsw.arch_zfs_probe = i386_zfs_probe;
171
172#ifdef LOADER_GELI_SUPPORT
173 if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) {
174 zargs = (struct zfs_boot_args *)(kargs + 1);
175 if (zargs != NULL && zargs->size >= offsetof(struct zfs_boot_args, gelipw)) {
176 if (zargs->gelipw[0] != '\0') {
177 setenv("kern.geom.eli.passphrase", zargs->gelipw, 1);
178 bzero(zargs->gelipw, sizeof(zargs->gelipw));
179 }
180 }
181 }
182#endif /* LOADER_GELI_SUPPORT */
183#else /* !LOADER_ZFS_SUPPORT */
184#ifdef LOADER_GELI_SUPPORT
185 if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) {
186 gargs = (struct geli_boot_args *)(kargs + 1);
187 if (gargs != NULL && gargs->size >= offsetof(struct geli_boot_args, gelipw)) {
188 if (gargs->gelipw[0] != '\0') {
189 setenv("kern.geom.eli.passphrase", gargs->gelipw, 1);
190 bzero(gargs->gelipw, sizeof(gargs->gelipw));
191 }
192 }
193 }
194#endif /* LOADER_GELI_SUPPORT */
195#endif /* LOADER_ZFS_SUPPORT */
196
197 /*
198 * March through the device switch probing for things.
199 */
200 for (i = 0; devsw[i] != NULL; i++)
201 if (devsw[i]->dv_init != NULL)
202 (devsw[i]->dv_init)();
203 printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024);
204 if (initial_bootinfo != NULL) {
205 initial_bootinfo->bi_basemem = bios_basemem / 1024;
206 initial_bootinfo->bi_extmem = bios_extmem / 1024;
207 }
208
209 /* detect ACPI for future reference */
210 biosacpi_detect();
211
212 /* detect SMBIOS for future reference */
213 smbios_detect(NULL);
214
215 /* detect PCI BIOS for future reference */
216 biospci_detect();
217
81
82/* XXX debugging */
83extern char end[];
84
85static void *heap_top;
86static void *heap_bottom;
87
88int
89main(void)
90{
91 int i;
92
93 /* Pick up arguments */
94 kargs = (void *)__args;
95 initial_howto = kargs->howto;
96 initial_bootdev = kargs->bootdev;
97 initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL;
98
99 /* Initialize the v86 register set to a known-good state. */
100 bzero(&v86, sizeof(v86));
101 v86.efl = PSL_RESERVED_DEFAULT | PSL_I;
102
103 /*
104 * Initialise the heap as early as possible. Once this is done, malloc() is usable.
105 */
106 bios_getmem();
107
108#if defined(LOADER_BZIP2_SUPPORT) || defined(LOADER_FIREWIRE_SUPPORT) || \
109 defined(LOADER_GPT_SUPPORT) || defined(LOADER_ZFS_SUPPORT)
110 if (high_heap_size > 0) {
111 heap_top = PTOV(high_heap_base + high_heap_size);
112 heap_bottom = PTOV(high_heap_base);
113 if (high_heap_base < memtop_copyin)
114 memtop_copyin = high_heap_base;
115 } else
116#endif
117 {
118 heap_top = (void *)PTOV(bios_basemem);
119 heap_bottom = (void *)end;
120 }
121 setheap(heap_bottom, heap_top);
122
123 /*
124 * XXX Chicken-and-egg problem; we want to have console output early, but some
125 * console attributes may depend on reading from eg. the boot device, which we
126 * can't do yet.
127 *
128 * We can use printf() etc. once this is done.
129 * If the previous boot stage has requested a serial console, prefer that.
130 */
131 bi_setboothowto(initial_howto);
132 if (initial_howto & RB_MULTIPLE) {
133 if (initial_howto & RB_SERIAL)
134 setenv("console", "comconsole vidconsole", 1);
135 else
136 setenv("console", "vidconsole comconsole", 1);
137 } else if (initial_howto & RB_SERIAL)
138 setenv("console", "comconsole", 1);
139 else if (initial_howto & RB_MUTE)
140 setenv("console", "nullconsole", 1);
141 cons_probe();
142
143 /*
144 * Initialise the block cache. Set the upper limit.
145 */
146 bcache_init(32768, 512);
147
148 /*
149 * Special handling for PXE and CD booting.
150 */
151 if (kargs->bootinfo == 0) {
152 /*
153 * We only want the PXE disk to try to init itself in the below
154 * walk through devsw if we actually booted off of PXE.
155 */
156 if (kargs->bootflags & KARGS_FLAGS_PXE)
157 pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL);
158 else if (kargs->bootflags & KARGS_FLAGS_CD)
159 bc_add(initial_bootdev);
160 }
161
162 archsw.arch_autoload = i386_autoload;
163 archsw.arch_getdev = i386_getdev;
164 archsw.arch_copyin = i386_copyin;
165 archsw.arch_copyout = i386_copyout;
166 archsw.arch_readin = i386_readin;
167 archsw.arch_isainb = isa_inb;
168 archsw.arch_isaoutb = isa_outb;
169#ifdef LOADER_ZFS_SUPPORT
170 archsw.arch_zfs_probe = i386_zfs_probe;
171
172#ifdef LOADER_GELI_SUPPORT
173 if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) {
174 zargs = (struct zfs_boot_args *)(kargs + 1);
175 if (zargs != NULL && zargs->size >= offsetof(struct zfs_boot_args, gelipw)) {
176 if (zargs->gelipw[0] != '\0') {
177 setenv("kern.geom.eli.passphrase", zargs->gelipw, 1);
178 bzero(zargs->gelipw, sizeof(zargs->gelipw));
179 }
180 }
181 }
182#endif /* LOADER_GELI_SUPPORT */
183#else /* !LOADER_ZFS_SUPPORT */
184#ifdef LOADER_GELI_SUPPORT
185 if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) {
186 gargs = (struct geli_boot_args *)(kargs + 1);
187 if (gargs != NULL && gargs->size >= offsetof(struct geli_boot_args, gelipw)) {
188 if (gargs->gelipw[0] != '\0') {
189 setenv("kern.geom.eli.passphrase", gargs->gelipw, 1);
190 bzero(gargs->gelipw, sizeof(gargs->gelipw));
191 }
192 }
193 }
194#endif /* LOADER_GELI_SUPPORT */
195#endif /* LOADER_ZFS_SUPPORT */
196
197 /*
198 * March through the device switch probing for things.
199 */
200 for (i = 0; devsw[i] != NULL; i++)
201 if (devsw[i]->dv_init != NULL)
202 (devsw[i]->dv_init)();
203 printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024);
204 if (initial_bootinfo != NULL) {
205 initial_bootinfo->bi_basemem = bios_basemem / 1024;
206 initial_bootinfo->bi_extmem = bios_extmem / 1024;
207 }
208
209 /* detect ACPI for future reference */
210 biosacpi_detect();
211
212 /* detect SMBIOS for future reference */
213 smbios_detect(NULL);
214
215 /* detect PCI BIOS for future reference */
216 biospci_detect();
217
218 printf("\n");
219 printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
220 printf("(%s, %s)\n", bootprog_maker, bootprog_date);
218 printf("\n%s", bootprog_info);
221
222 extract_currdev(); /* set $currdev and $loaddev */
223 setenv("LINES", "24", 1); /* optional */
224
225 bios_getsmap();
226
227 interact(NULL);
228
229 /* if we ever get here, it is an error */
230 return (1);
231}
232
233/*
234 * Set the 'current device' by (if possible) recovering the boot device as
235 * supplied by the initial bootstrap.
236 *
237 * XXX should be extended for netbooting.
238 */
239static void
240extract_currdev(void)
241{
242 struct i386_devdesc new_currdev;
243#ifdef LOADER_ZFS_SUPPORT
244 char buf[20];
245#endif
246 int biosdev = -1;
247
248 /* Assume we are booting from a BIOS disk by default */
249 new_currdev.d_dev = &biosdisk;
250
251 /* new-style boot loaders such as pxeldr and cdldr */
252 if (kargs->bootinfo == 0) {
253 if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) {
254 /* we are booting from a CD with cdboot */
255 new_currdev.d_dev = &bioscd;
256 new_currdev.d_unit = bc_bios2unit(initial_bootdev);
257 } else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) {
258 /* we are booting from pxeldr */
259 new_currdev.d_dev = &pxedisk;
260 new_currdev.d_unit = 0;
261 } else {
262 /* we don't know what our boot device is */
263 new_currdev.d_kind.biosdisk.slice = -1;
264 new_currdev.d_kind.biosdisk.partition = 0;
265 biosdev = -1;
266 }
267#ifdef LOADER_ZFS_SUPPORT
268 } else if ((kargs->bootflags & KARGS_FLAGS_ZFS) != 0) {
269 zargs = NULL;
270 /* check for new style extended argument */
271 if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0)
272 zargs = (struct zfs_boot_args *)(kargs + 1);
273
274 if (zargs != NULL &&
275 zargs->size >= offsetof(struct zfs_boot_args, primary_pool)) {
276 /* sufficient data is provided */
277 new_currdev.d_kind.zfs.pool_guid = zargs->pool;
278 new_currdev.d_kind.zfs.root_guid = zargs->root;
279 if (zargs->size >= sizeof(*zargs) && zargs->primary_vdev != 0) {
280 sprintf(buf, "%llu", zargs->primary_pool);
281 setenv("vfs.zfs.boot.primary_pool", buf, 1);
282 sprintf(buf, "%llu", zargs->primary_vdev);
283 setenv("vfs.zfs.boot.primary_vdev", buf, 1);
284 }
285 } else {
286 /* old style zfsboot block */
287 new_currdev.d_kind.zfs.pool_guid = kargs->zfspool;
288 new_currdev.d_kind.zfs.root_guid = 0;
289 }
290 new_currdev.d_dev = &zfs_dev;
291#endif
292 } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) {
293 /* The passed-in boot device is bad */
294 new_currdev.d_kind.biosdisk.slice = -1;
295 new_currdev.d_kind.biosdisk.partition = 0;
296 biosdev = -1;
297 } else {
298 new_currdev.d_kind.biosdisk.slice = B_SLICE(initial_bootdev) - 1;
299 new_currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev);
300 biosdev = initial_bootinfo->bi_bios_dev;
301
302 /*
303 * If we are booted by an old bootstrap, we have to guess at the BIOS
304 * unit number. We will lose if there is more than one disk type
305 * and we are not booting from the lowest-numbered disk type
306 * (ie. SCSI when IDE also exists).
307 */
308 if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) /* biosdev doesn't match major */
309 biosdev = 0x80 + B_UNIT(initial_bootdev); /* assume harddisk */
310 }
311 new_currdev.d_type = new_currdev.d_dev->dv_type;
312
313 /*
314 * If we are booting off of a BIOS disk and we didn't succeed in determining
315 * which one we booted off of, just use disk0: as a reasonable default.
316 */
317 if ((new_currdev.d_type == biosdisk.dv_type) &&
318 ((new_currdev.d_unit = bd_bios2unit(biosdev)) == -1)) {
319 printf("Can't work out which disk we are booting from.\n"
320 "Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev);
321 new_currdev.d_unit = 0;
322 }
323
324#ifdef LOADER_ZFS_SUPPORT
325 if (new_currdev.d_type == DEVT_ZFS)
326 init_zfs_bootenv(zfs_fmtdev(&new_currdev));
327#endif
328
329 env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev),
330 i386_setcurrdev, env_nounset);
331 env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset,
332 env_nounset);
333}
334
335COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
336
337static int
338command_reboot(int argc, char *argv[])
339{
340 int i;
341
342 for (i = 0; devsw[i] != NULL; ++i)
343 if (devsw[i]->dv_cleanup != NULL)
344 (devsw[i]->dv_cleanup)();
345
346 printf("Rebooting...\n");
347 delay(1000000);
348 __exit(0);
349}
350
351/* provide this for panic, as it's not in the startup code */
352void
353exit(int code)
354{
355 __exit(code);
356}
357
358COMMAND_SET(heap, "heap", "show heap usage", command_heap);
359
360static int
361command_heap(int argc, char *argv[])
362{
363 mallocstats();
364 printf("heap base at %p, top at %p, upper limit at %p\n", heap_bottom,
365 sbrk(0), heap_top);
366 return(CMD_OK);
367}
368
369#ifdef LOADER_ZFS_SUPPORT
370COMMAND_SET(lszfs, "lszfs", "list child datasets of a zfs dataset",
371 command_lszfs);
372
373static int
374command_lszfs(int argc, char *argv[])
375{
376 int err;
377
378 if (argc != 2) {
379 command_errmsg = "wrong number of arguments";
380 return (CMD_ERROR);
381 }
382
383 err = zfs_list(argv[1]);
384 if (err != 0) {
385 command_errmsg = strerror(err);
386 return (CMD_ERROR);
387 }
388
389 return (CMD_OK);
390}
391
392COMMAND_SET(reloadbe, "reloadbe", "refresh the list of ZFS Boot Environments",
393 command_reloadbe);
394
395static int
396command_reloadbe(int argc, char *argv[])
397{
398 int err;
399 char *root;
400
401 if (argc > 2) {
402 command_errmsg = "wrong number of arguments";
403 return (CMD_ERROR);
404 }
405
406 if (argc == 2) {
407 err = zfs_bootenv(argv[1]);
408 } else {
409 root = getenv("zfs_be_root");
410 if (root == NULL) {
411 /* There does not appear to be a ZFS pool here, exit without error */
412 return (CMD_OK);
413 }
414 err = zfs_bootenv(getenv("zfs_be_root"));
415 }
416
417 if (err != 0) {
418 command_errmsg = strerror(err);
419 return (CMD_ERROR);
420 }
421
422 return (CMD_OK);
423}
424#endif
425
426/* ISA bus access functions for PnP. */
427static int
428isa_inb(int port)
429{
430
431 return (inb(port));
432}
433
434static void
435isa_outb(int port, int value)
436{
437
438 outb(port, value);
439}
440
441#ifdef LOADER_ZFS_SUPPORT
442static void
443i386_zfs_probe(void)
444{
445 char devname[32];
446 int unit;
447
448 /*
449 * Open all the disks we can find and see if we can reconstruct
450 * ZFS pools from them.
451 */
452 for (unit = 0; unit < MAXBDDEV; unit++) {
453 if (bd_unit2bios(unit) == -1)
454 break;
455 sprintf(devname, "disk%d:", unit);
456 zfs_probe_dev(devname, NULL);
457 }
458}
459#endif
219
220 extract_currdev(); /* set $currdev and $loaddev */
221 setenv("LINES", "24", 1); /* optional */
222
223 bios_getsmap();
224
225 interact(NULL);
226
227 /* if we ever get here, it is an error */
228 return (1);
229}
230
231/*
232 * Set the 'current device' by (if possible) recovering the boot device as
233 * supplied by the initial bootstrap.
234 *
235 * XXX should be extended for netbooting.
236 */
237static void
238extract_currdev(void)
239{
240 struct i386_devdesc new_currdev;
241#ifdef LOADER_ZFS_SUPPORT
242 char buf[20];
243#endif
244 int biosdev = -1;
245
246 /* Assume we are booting from a BIOS disk by default */
247 new_currdev.d_dev = &biosdisk;
248
249 /* new-style boot loaders such as pxeldr and cdldr */
250 if (kargs->bootinfo == 0) {
251 if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) {
252 /* we are booting from a CD with cdboot */
253 new_currdev.d_dev = &bioscd;
254 new_currdev.d_unit = bc_bios2unit(initial_bootdev);
255 } else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) {
256 /* we are booting from pxeldr */
257 new_currdev.d_dev = &pxedisk;
258 new_currdev.d_unit = 0;
259 } else {
260 /* we don't know what our boot device is */
261 new_currdev.d_kind.biosdisk.slice = -1;
262 new_currdev.d_kind.biosdisk.partition = 0;
263 biosdev = -1;
264 }
265#ifdef LOADER_ZFS_SUPPORT
266 } else if ((kargs->bootflags & KARGS_FLAGS_ZFS) != 0) {
267 zargs = NULL;
268 /* check for new style extended argument */
269 if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0)
270 zargs = (struct zfs_boot_args *)(kargs + 1);
271
272 if (zargs != NULL &&
273 zargs->size >= offsetof(struct zfs_boot_args, primary_pool)) {
274 /* sufficient data is provided */
275 new_currdev.d_kind.zfs.pool_guid = zargs->pool;
276 new_currdev.d_kind.zfs.root_guid = zargs->root;
277 if (zargs->size >= sizeof(*zargs) && zargs->primary_vdev != 0) {
278 sprintf(buf, "%llu", zargs->primary_pool);
279 setenv("vfs.zfs.boot.primary_pool", buf, 1);
280 sprintf(buf, "%llu", zargs->primary_vdev);
281 setenv("vfs.zfs.boot.primary_vdev", buf, 1);
282 }
283 } else {
284 /* old style zfsboot block */
285 new_currdev.d_kind.zfs.pool_guid = kargs->zfspool;
286 new_currdev.d_kind.zfs.root_guid = 0;
287 }
288 new_currdev.d_dev = &zfs_dev;
289#endif
290 } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) {
291 /* The passed-in boot device is bad */
292 new_currdev.d_kind.biosdisk.slice = -1;
293 new_currdev.d_kind.biosdisk.partition = 0;
294 biosdev = -1;
295 } else {
296 new_currdev.d_kind.biosdisk.slice = B_SLICE(initial_bootdev) - 1;
297 new_currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev);
298 biosdev = initial_bootinfo->bi_bios_dev;
299
300 /*
301 * If we are booted by an old bootstrap, we have to guess at the BIOS
302 * unit number. We will lose if there is more than one disk type
303 * and we are not booting from the lowest-numbered disk type
304 * (ie. SCSI when IDE also exists).
305 */
306 if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) /* biosdev doesn't match major */
307 biosdev = 0x80 + B_UNIT(initial_bootdev); /* assume harddisk */
308 }
309 new_currdev.d_type = new_currdev.d_dev->dv_type;
310
311 /*
312 * If we are booting off of a BIOS disk and we didn't succeed in determining
313 * which one we booted off of, just use disk0: as a reasonable default.
314 */
315 if ((new_currdev.d_type == biosdisk.dv_type) &&
316 ((new_currdev.d_unit = bd_bios2unit(biosdev)) == -1)) {
317 printf("Can't work out which disk we are booting from.\n"
318 "Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev);
319 new_currdev.d_unit = 0;
320 }
321
322#ifdef LOADER_ZFS_SUPPORT
323 if (new_currdev.d_type == DEVT_ZFS)
324 init_zfs_bootenv(zfs_fmtdev(&new_currdev));
325#endif
326
327 env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev),
328 i386_setcurrdev, env_nounset);
329 env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset,
330 env_nounset);
331}
332
333COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
334
335static int
336command_reboot(int argc, char *argv[])
337{
338 int i;
339
340 for (i = 0; devsw[i] != NULL; ++i)
341 if (devsw[i]->dv_cleanup != NULL)
342 (devsw[i]->dv_cleanup)();
343
344 printf("Rebooting...\n");
345 delay(1000000);
346 __exit(0);
347}
348
349/* provide this for panic, as it's not in the startup code */
350void
351exit(int code)
352{
353 __exit(code);
354}
355
356COMMAND_SET(heap, "heap", "show heap usage", command_heap);
357
358static int
359command_heap(int argc, char *argv[])
360{
361 mallocstats();
362 printf("heap base at %p, top at %p, upper limit at %p\n", heap_bottom,
363 sbrk(0), heap_top);
364 return(CMD_OK);
365}
366
367#ifdef LOADER_ZFS_SUPPORT
368COMMAND_SET(lszfs, "lszfs", "list child datasets of a zfs dataset",
369 command_lszfs);
370
371static int
372command_lszfs(int argc, char *argv[])
373{
374 int err;
375
376 if (argc != 2) {
377 command_errmsg = "wrong number of arguments";
378 return (CMD_ERROR);
379 }
380
381 err = zfs_list(argv[1]);
382 if (err != 0) {
383 command_errmsg = strerror(err);
384 return (CMD_ERROR);
385 }
386
387 return (CMD_OK);
388}
389
390COMMAND_SET(reloadbe, "reloadbe", "refresh the list of ZFS Boot Environments",
391 command_reloadbe);
392
393static int
394command_reloadbe(int argc, char *argv[])
395{
396 int err;
397 char *root;
398
399 if (argc > 2) {
400 command_errmsg = "wrong number of arguments";
401 return (CMD_ERROR);
402 }
403
404 if (argc == 2) {
405 err = zfs_bootenv(argv[1]);
406 } else {
407 root = getenv("zfs_be_root");
408 if (root == NULL) {
409 /* There does not appear to be a ZFS pool here, exit without error */
410 return (CMD_OK);
411 }
412 err = zfs_bootenv(getenv("zfs_be_root"));
413 }
414
415 if (err != 0) {
416 command_errmsg = strerror(err);
417 return (CMD_ERROR);
418 }
419
420 return (CMD_OK);
421}
422#endif
423
424/* ISA bus access functions for PnP. */
425static int
426isa_inb(int port)
427{
428
429 return (inb(port));
430}
431
432static void
433isa_outb(int port, int value)
434{
435
436 outb(port, value);
437}
438
439#ifdef LOADER_ZFS_SUPPORT
440static void
441i386_zfs_probe(void)
442{
443 char devname[32];
444 int unit;
445
446 /*
447 * Open all the disks we can find and see if we can reconstruct
448 * ZFS pools from them.
449 */
450 for (unit = 0; unit < MAXBDDEV; unit++) {
451 if (bd_unit2bios(unit) == -1)
452 break;
453 sprintf(devname, "disk%d:", unit);
454 zfs_probe_dev(devname, NULL);
455 }
456}
457#endif