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
|