install.c revision 41558
1272343Sngie/* 2272343Sngie * The new sysinstall program. 3272343Sngie * 4272343Sngie * This is probably the last program in the `sysinstall' line - the next 5272343Sngie * generation being essentially a complete rewrite. 6272343Sngie * 7272343Sngie * $Id: install.c,v 1.219 1998/11/24 00:18:55 jkh Exp $ 8272343Sngie * 9272343Sngie * Copyright (c) 1995 10272343Sngie * Jordan Hubbard. All rights reserved. 11272343Sngie * 12272343Sngie * Redistribution and use in source and binary forms, with or without 13272343Sngie * modification, are permitted provided that the following conditions 14272343Sngie * are met: 15272343Sngie * 1. Redistributions of source code must retain the above copyright 16272343Sngie * notice, this list of conditions and the following disclaimer, 17272343Sngie * verbatim and that no modifications are made prior to this 18272343Sngie * point in the file. 19272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 20272343Sngie * notice, this list of conditions and the following disclaimer in the 21272343Sngie * documentation and/or other materials provided with the distribution. 22272343Sngie * 23272343Sngie * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 24272343Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25272343Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26272343Sngie * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 27272343Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29272343Sngie * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 30272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31272343Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32272343Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33272343Sngie * SUCH DAMAGE. 34272343Sngie * 35272343Sngie */ 36272343Sngie 37272343Sngie#include "sysinstall.h" 38272343Sngie#include "uc_main.h" 39272343Sngie#include <ctype.h> 40272343Sngie#include <sys/disklabel.h> 41272343Sngie#include <sys/errno.h> 42272343Sngie#include <sys/ioctl.h> 43272343Sngie#include <sys/fcntl.h> 44272343Sngie#include <sys/wait.h> 45272343Sngie#include <sys/param.h> 46272343Sngie#define MSDOSFS 47272343Sngie#include <sys/mount.h> 48272343Sngie#include <ufs/ufs/ufsmount.h> 49272343Sngie#include <msdosfs/msdosfsmount.h> 50272343Sngie#undef MSDOSFS 51272343Sngie#include <sys/stat.h> 52272343Sngie#include <sys/sysctl.h> 53272343Sngie#include <unistd.h> 54272343Sngie 55272343Sngiestatic void create_termcap(void); 56272343Sngiestatic void fixit_common(void); 57272343Sngie#ifdef SAVE_USERCONFIG 58272343Sngiestatic void save_userconfig_to_kernel(char *); 59272343Sngie#endif 60272343Sngie 61272343Sngie#define TERMCAP_FILE "/usr/share/misc/termcap" 62272343Sngie 63272343Sngiestatic void installConfigure(void); 64272343Sngie 65272343SngieBoolean 66272343SngiecheckLabels(Boolean whinge, Chunk **rdev, Chunk **sdev, Chunk **udev, Chunk **vdev) 67272343Sngie{ 68272343Sngie Device **devs; 69272343Sngie Boolean status; 70272343Sngie Disk *disk; 71272343Sngie Chunk *c1, *c2, *rootdev, *swapdev, *usrdev, *vardev; 72272343Sngie int i; 73272343Sngie 74272343Sngie /* Don't allow whinging if noWarn is set */ 75272343Sngie if (variable_get(VAR_NO_WARN)) 76272343Sngie whinge = FALSE; 77272343Sngie 78272343Sngie status = TRUE; 79272343Sngie *rdev = *sdev = *udev = *vdev = rootdev = swapdev = usrdev = vardev = NULL; 80272343Sngie 81272343Sngie /* We don't need to worry about root/usr/swap if we're already multiuser */ 82272343Sngie if (!RunningAsInit) 83272343Sngie return status; 84272343Sngie 85272343Sngie devs = deviceFind(NULL, DEVICE_TYPE_DISK); 86272343Sngie /* First verify that we have a root device */ 87272343Sngie for (i = 0; devs[i]; i++) { 88272343Sngie if (!devs[i]->enabled) 89272343Sngie continue; 90272343Sngie disk = (Disk *)devs[i]->private; 91272343Sngie msgDebug("Scanning disk %s for root filesystem\n", disk->name); 92272343Sngie if (!disk->chunks) 93272343Sngie msgFatal("No chunk list found for %s!", disk->name); 94272343Sngie for (c1 = disk->chunks->part; c1; c1 = c1->next) { 95272343Sngie if (c1->type == freebsd) { 96272343Sngie for (c2 = c1->part; c2; c2 = c2->next) { 97272343Sngie if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) { 98272343Sngie if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/")) { 99272343Sngie if (rootdev) { 100272343Sngie if (whinge) 101272343Sngie msgConfirm("WARNING: You have more than one root device set?!\n" 102272343Sngie "Using the first one found."); 103272343Sngie continue; 104272343Sngie } 105272343Sngie else { 106272343Sngie rootdev = c2; 107272343Sngie if (isDebug()) 108272343Sngie msgDebug("Found rootdev at %s!\n", rootdev->name); 109272343Sngie } 110272343Sngie } 111272343Sngie else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/usr")) { 112272343Sngie if (usrdev) { 113272343Sngie if (whinge) 114272343Sngie msgConfirm("WARNING: You have more than one /usr filesystem.\n" 115272343Sngie "Using the first one found."); 116272343Sngie continue; 117272343Sngie } 118272343Sngie else { 119272343Sngie usrdev = c2; 120272343Sngie if (isDebug()) 121272343Sngie msgDebug("Found usrdev at %s!\n", usrdev->name); 122272343Sngie } 123272343Sngie } 124272343Sngie else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/var")) { 125272343Sngie if (vardev) { 126272343Sngie if (whinge) 127272343Sngie msgConfirm("WARNING: You have more than one /var filesystem.\n" 128272343Sngie "Using the first one found."); 129272343Sngie continue; 130272343Sngie } 131272343Sngie else { 132272343Sngie vardev = c2; 133272343Sngie if (isDebug()) 134272343Sngie msgDebug("Found vardev at %s!\n", vardev->name); 135272343Sngie } 136272343Sngie } 137272343Sngie } 138272343Sngie } 139272343Sngie } 140272343Sngie } 141272343Sngie } 142272343Sngie 143272343Sngie /* Now check for swap devices */ 144272343Sngie for (i = 0; devs[i]; i++) { 145272343Sngie if (!devs[i]->enabled) 146272343Sngie continue; 147272343Sngie disk = (Disk *)devs[i]->private; 148272343Sngie msgDebug("Scanning disk %s for swap partitions\n", disk->name); 149272343Sngie if (!disk->chunks) 150272343Sngie msgFatal("No chunk list found for %s!", disk->name); 151272343Sngie for (c1 = disk->chunks->part; c1; c1 = c1->next) { 152272343Sngie if (c1->type == freebsd) { 153272343Sngie for (c2 = c1->part; c2; c2 = c2->next) { 154272343Sngie if (c2->type == part && c2->subtype == FS_SWAP && !swapdev) { 155272343Sngie swapdev = c2; 156272343Sngie if (isDebug()) 157272343Sngie msgDebug("Found swapdev at %s!\n", swapdev->name); 158272343Sngie break; 159272343Sngie } 160272343Sngie } 161272343Sngie } 162272343Sngie } 163272343Sngie } 164272343Sngie 165272343Sngie /* Copy our values over */ 166272343Sngie *rdev = rootdev; 167272343Sngie *sdev = swapdev; 168272343Sngie *udev = usrdev; 169272343Sngie *vdev = vardev; 170272343Sngie 171272343Sngie if (!rootdev && whinge) { 172272343Sngie msgConfirm("No root device found - you must label a partition as /\n" 173272343Sngie "in the label editor."); 174272343Sngie status = FALSE; 175272343Sngie } 176272343Sngie if (!swapdev && whinge) { 177272343Sngie msgConfirm("No swap devices found - you must create at least one\n" 178272343Sngie "swap partition."); 179272343Sngie status = FALSE; 180272343Sngie } 181272343Sngie if (!usrdev && whinge && !variable_get(VAR_NO_USR)) { 182272343Sngie msgConfirm("WARNING: No /usr filesystem found. This is not technically\n" 183272343Sngie "an error if your root filesystem is big enough (or you later\n" 184272343Sngie "intend to mount your /usr filesystem over NFS), but it may otherwise\n" 185272343Sngie "cause you trouble if you're not exactly sure what you are doing!"); 186272343Sngie } 187272343Sngie if (!vardev && whinge && variable_cmp(SYSTEM_STATE, "upgrade")) { 188272343Sngie msgConfirm("WARNING: No /var filesystem found. This is not technically\n" 189272343Sngie "an error if your root filesystem is big enough (or you later\n" 190272343Sngie "intend to link /var to someplace else), but it may otherwise\n" 191272343Sngie "cause your root filesystem to fill up if you receive lots of mail\n" 192272343Sngie "or edit large temporary files."); 193272343Sngie } 194272343Sngie return status; 195272343Sngie} 196272343Sngie 197272343Sngiestatic int 198272343SngieinstallInitial(void) 199272343Sngie{ 200272343Sngie static Boolean alreadyDone = FALSE; 201272343Sngie int status = DITEM_SUCCESS; 202272343Sngie 203272343Sngie if (alreadyDone) 204272343Sngie return DITEM_SUCCESS; 205272343Sngie 206272343Sngie if (!variable_get(DISK_LABELLED)) { 207272343Sngie msgConfirm("You need to assign disk labels before you can proceed with\n" 208272343Sngie "the installation."); 209272343Sngie return DITEM_FAILURE; 210272343Sngie } 211272343Sngie /* If it's labelled, assume it's also partitioned */ 212272343Sngie if (!variable_get(DISK_PARTITIONED)) 213272343Sngie variable_set2(DISK_PARTITIONED, "yes"); 214272343Sngie 215272343Sngie /* If we refuse to proceed, bail. */ 216272343Sngie dialog_clear_norefresh(); 217272343Sngie if (!variable_get(VAR_NO_WARN)) 218272343Sngie if (msgYesNo( 219272343Sngie "Last Chance! Are you SURE you want continue the installation?\n\n" 220272343Sngie "If you're running this on a disk with data you wish to save\n" 221272343Sngie "then WE STRONGLY ENCOURAGE YOU TO MAKE PROPER BACKUPS before\n" 222272343Sngie "proceeding!\n\n" 223272343Sngie "We can take no responsibility for lost disk contents!") != 0) 224272343Sngie return DITEM_FAILURE | DITEM_RESTORE; 225272343Sngie 226272343Sngie if (DITEM_STATUS(diskLabelCommit(NULL)) != DITEM_SUCCESS) { 227272343Sngie msgConfirm("Couldn't make filesystems properly. Aborting."); 228272343Sngie return DITEM_FAILURE; 229272343Sngie } 230272343Sngie 231272343Sngie if (!copySelf()) { 232272343Sngie msgConfirm("installInitial: Couldn't clone the boot floppy onto the\n" 233272343Sngie "root file system. Aborting!"); 234272343Sngie return DITEM_FAILURE; 235272343Sngie } 236272343Sngie 237272343Sngie if (chroot("/mnt") == -1) { 238272343Sngie msgConfirm("installInitial: Unable to chroot to %s - this is bad!", 239272343Sngie "/mnt"); 240272343Sngie return DITEM_FAILURE; 241272343Sngie } 242272343Sngie 243272343Sngie chdir("/"); 244272343Sngie variable_set2(RUNNING_ON_ROOT, "yes"); 245272343Sngie 246272343Sngie /* Configure various files in /etc */ 247272343Sngie if (DITEM_STATUS(configResolv(NULL)) == DITEM_FAILURE) 248272343Sngie status = DITEM_FAILURE; 249272343Sngie if (DITEM_STATUS(configFstab(NULL)) == DITEM_FAILURE) 250272343Sngie status = DITEM_FAILURE; 251272343Sngie 252272343Sngie /* stick a helpful shell over on the 4th VTY */ 253272343Sngie systemCreateHoloshell(); 254272343Sngie 255272343Sngie alreadyDone = TRUE; 256272343Sngie return status; 257272343Sngie} 258272343Sngie 259272343Sngieint 260272343SngieinstallFixitHoloShell(dialogMenuItem *self) 261272343Sngie{ 262272343Sngie systemCreateHoloshell(); 263272343Sngie return DITEM_SUCCESS; 264272343Sngie} 265272343Sngie 266272343Sngieint 267272343SngieinstallFixitCDROM(dialogMenuItem *self) 268272343Sngie{ 269272343Sngie struct stat sb; 270272343Sngie 271272343Sngie if (!RunningAsInit) 272272343Sngie return DITEM_SUCCESS; 273272343Sngie 274272343Sngie variable_set2(SYSTEM_STATE, "fixit"); 275272343Sngie (void)unlink("/mnt2"); 276272343Sngie (void)rmdir("/mnt2"); 277272343Sngie 278272343Sngie while (1) { 279272343Sngie msgConfirm("Please insert the second FreeBSD CDROM and press return"); 280272343Sngie if (DITEM_STATUS(mediaSetCDROM(NULL)) != DITEM_SUCCESS || !mediaDevice || !mediaDevice->init(mediaDevice)) { 281272343Sngie /* If we can't initialize it, it's probably not a FreeBSD CDROM so punt on it */ 282272343Sngie if (mediaDevice) { 283272343Sngie mediaDevice->shutdown(mediaDevice); 284272343Sngie mediaDevice = NULL; 285272343Sngie } 286272343Sngie if (msgYesNo("Unable to mount the CDROM - do you want to try again?") != 0) 287272343Sngie return DITEM_FAILURE; 288272343Sngie } 289272343Sngie else 290272343Sngie break; 291272343Sngie } 292272343Sngie 293272343Sngie /* Since the fixit code expects everything to be in /mnt2, and the CDROM mounting stuff /dist, do 294272343Sngie * a little kludge dance here.. 295272343Sngie */ 296272343Sngie if (symlink("/dist", "/mnt2")) { 297272343Sngie msgConfirm("Unable to symlink /mnt2 to the CDROM mount point. Please report this\n" 298272343Sngie "unexpected failure to freebsd-bugs@FreeBSD.org."); 299272343Sngie return DITEM_FAILURE; 300272343Sngie } 301272343Sngie 302272343Sngie /* 303272343Sngie * If /tmp points to /mnt2/tmp from a previous fixit floppy session, it's 304272343Sngie * not very good for us if we point it to the CDROM now. Rather make it 305272343Sngie * a directory in the root MFS then. Experienced admins will still be 306272343Sngie * able to mount their disk's /tmp over this if they need. 307272343Sngie */ 308272343Sngie if (lstat("/tmp", &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFLNK) 309272343Sngie (void)unlink("/tmp"); 310272343Sngie Mkdir("/tmp"); 311272343Sngie 312272343Sngie /* 313272343Sngie * Since setuid binaries ignore LD_LIBRARY_PATH, we indeed need the 314272343Sngie * ld.so.hints file. Fortunately, it's fairly small (~ 3 KB). 315272343Sngie */ 316272343Sngie if (!file_readable("/var/run/ld.so.hints")) { 317272343Sngie Mkdir("/var/run"); 318272343Sngie if (vsystem("/mnt2/sbin/ldconfig -s /mnt2/usr/lib")) { 319272343Sngie msgConfirm("Warning: ldconfig could not create the ld.so hints file.\n" 320272343Sngie "Dynamic executables from the CDROM likely won't work."); 321272343Sngie } 322272343Sngie } 323272343Sngie 324272343Sngie /* Yet another iggly hardcoded pathname. */ 325272343Sngie if (!file_readable("/usr/libexec/ld.so")) { 326272343Sngie Mkdir("/usr/libexec"); 327272343Sngie if (symlink("/mnt2/usr/libexec/ld.so", "/usr/libexec/ld.so")) { 328272343Sngie msgConfirm("Warning: could not create the symlink for ld.so.\n" 329272343Sngie "Dynamic executables from the CDROM likely won't work."); 330272343Sngie } 331272343Sngie } 332272343Sngie 333272343Sngie fixit_common(); 334272343Sngie 335272343Sngie mediaDevice->shutdown(mediaDevice); 336272343Sngie msgConfirm("Please remove the FreeBSD CDROM now."); 337272343Sngie return DITEM_SUCCESS; 338272343Sngie} 339272343Sngie 340272343Sngieint 341272343SngieinstallFixitFloppy(dialogMenuItem *self) 342272343Sngie{ 343272343Sngie struct ufs_args args; 344272343Sngie 345272343Sngie if (!RunningAsInit) 346272343Sngie return DITEM_SUCCESS; 347272343Sngie 348272343Sngie variable_set2(SYSTEM_STATE, "fixit"); 349272343Sngie Mkdir("/mnt2"); 350272343Sngie 351272343Sngie /* Try to open the floppy drive */ 352272343Sngie if (DITEM_STATUS(mediaSetFloppy(NULL)) == DITEM_FAILURE) { 353272343Sngie msgConfirm("Unable to set media device to floppy."); 354272343Sngie mediaClose(); 355272343Sngie return DITEM_FAILURE; 356 } 357 358 memset(&args, 0, sizeof(args)); 359 args.fspec = mediaDevice->devname; 360 361 while (1) { 362 msgConfirm("Please insert a writable fixit floppy and press return"); 363 mediaDevice->private = "/mnt2"; 364 if (!mediaDevice->init(mediaDevice)) { 365 if (msgYesNo("The attempt to mount the fixit floppy failed, bad floppy\n" 366 "or unclean filesystem. Do you want to try again?")) 367 return DITEM_FAILURE; 368 } 369 else 370 break; 371 } 372 if (!directory_exists("/tmp")) 373 (void)symlink("/mnt2/tmp", "/tmp"); 374 fixit_common(); 375 mediaDevice->shutdown(mediaDevice); 376 mediaDevice = NULL; 377 msgConfirm("Please remove the fixit floppy now."); 378 return DITEM_SUCCESS; 379} 380 381/* 382 * The common code for both fixit variants. 383 */ 384static void 385fixit_common(void) 386{ 387 pid_t child; 388 int waitstatus; 389 390 if (!directory_exists("/var/tmp/vi.recover")) { 391 if (DITEM_STATUS(Mkdir("/var/tmp/vi.recover")) != DITEM_SUCCESS) { 392 msgConfirm("Warning: Was unable to create a /var/tmp/vi.recover directory.\n" 393 "vi will kvetch and moan about it as a result but should still\n" 394 "be essentially usable."); 395 } 396 } 397 if (!directory_exists("/bin")) 398 (void)Mkdir("/bin"); 399 (void)symlink("/stand/sh", "/bin/sh"); 400 /* Link the /etc/ files */ 401 if (DITEM_STATUS(Mkdir("/etc")) != DITEM_SUCCESS) 402 msgConfirm("Unable to create an /etc directory! Things are weird on this floppy.."); 403 else if ((symlink("/mnt2/etc/spwd.db", "/etc/spwd.db") == -1 && errno != EEXIST) || 404 (symlink("/mnt2/etc/protocols", "/etc/protocols") == -1 && errno != EEXIST) || 405 (symlink("/mnt2/etc/services", "/etc/services") == -1 && errno != EEXIST)) 406 msgConfirm("Couldn't symlink the /etc/ files! I'm not sure I like this.."); 407 if (!file_readable(TERMCAP_FILE)) 408 create_termcap(); 409 if (!(child = fork())) { 410 int i, fd; 411 struct termios foo; 412 extern int login_tty(int); 413 414 ioctl(0, TIOCNOTTY, NULL); 415 for (i = getdtablesize(); i >= 0; --i) 416 close(i); 417 fd = open("/dev/ttyv3", O_RDWR); 418 ioctl(0, TIOCSCTTY, &fd); 419 dup2(0, 1); 420 dup2(0, 2); 421 DebugFD = 2; 422 if (login_tty(fd) == -1) 423 msgDebug("fixit: I can't set the controlling terminal.\n"); 424 425 signal(SIGTTOU, SIG_IGN); 426 if (tcgetattr(0, &foo) != -1) { 427 foo.c_cc[VERASE] = '\010'; 428 if (tcsetattr(0, TCSANOW, &foo) == -1) 429 msgDebug("fixit shell: Unable to set erase character.\n"); 430 } 431 else 432 msgDebug("fixit shell: Unable to get terminal attributes!\n"); 433 setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/stand:" 434 "/mnt2/stand:/mnt2/bin:/mnt2/sbin:/mnt2/usr/bin:/mnt2/usr/sbin", 1); 435 /* use the .profile from the fixit medium */ 436 setenv("HOME", "/mnt2", 1); 437 chdir("/mnt2"); 438 execlp("sh", "-sh", 0); 439 msgDebug("fixit shell: Failed to execute shell!\n"); 440 _exit(1);; 441 } 442 else { 443 msgNotify("Waiting for fixit shell to exit. Go to VTY4 now by\n" 444 "typing ALT-F4. When you are done, type ``exit'' to exit\n" 445 "the fixit shell and be returned here."); 446 (void)waitpid(child, &waitstatus, 0); 447 } 448 dialog_clear(); 449} 450 451 452int 453installExpress(dialogMenuItem *self) 454{ 455 int i; 456 457 variable_set2(SYSTEM_STATE, "express"); 458 if (DITEM_STATUS((i = diskPartitionEditor(self))) == DITEM_FAILURE) 459 return i; 460 461 if (DITEM_STATUS((i = diskLabelEditor(self))) == DITEM_FAILURE) 462 return i; 463 464 dialog_clear_norefresh(); 465 if (DITEM_STATUS((i = installCommit(self))) == DITEM_SUCCESS) { 466 i |= DITEM_LEAVE_MENU; 467 /* Give user the option of one last configuration spree */ 468 installConfigure(); 469 } 470 return i | DITEM_RESTORE; 471} 472 473/* Novice mode installation */ 474int 475installNovice(dialogMenuItem *self) 476{ 477 int i, tries = 0; 478 Device **devs; 479 480 variable_set2(SYSTEM_STATE, "novice"); 481 dialog_clear_norefresh(); 482 msgConfirm("In the next menu, you will need to set up a DOS-style (\"fdisk\") partitioning\n" 483 "scheme for your hard disk. If you simply wish to devote all disk space\n" 484 "to FreeBSD (overwriting anything else that might be on the disk(s) selected)\n" 485 "then use the (A)ll command to select the default partitioning scheme followed\n" 486 "by a (Q)uit. If you wish to allocate only free space to FreeBSD, move to a\n" 487 "partition marked \"unused\" and use the (C)reate command."); 488 489nodisks: 490 if (DITEM_STATUS(diskPartitionEditor(self)) == DITEM_FAILURE) 491 return DITEM_FAILURE; 492 493 if (diskGetSelectCount(&devs) <= 0 && tries < 3) { 494 msgConfirm("You need to select some disks to operate on! Be sure to use SPACE\n" 495 "instead of RETURN in the disk selection menu when selecting a disk."); 496 ++tries; 497 goto nodisks; 498 } 499 500 dialog_clear_norefresh(); 501 msgConfirm("Next, you need to create BSD partitions inside of the fdisk partition(s)\n" 502 "just created. If you have a reasonable amount of disk space (200MB or more)\n" 503 "and don't have any special requirements, simply use the (A)uto command to\n" 504 "allocate space automatically. If you have more specific needs or just don't\n" 505 "care for the layout chosen by (A)uto, press F1 for more information on\n" 506 "manual layout."); 507 508 if (DITEM_STATUS(diskLabelEditor(self)) == DITEM_FAILURE) 509 return DITEM_FAILURE; 510 511 dialog_clear_norefresh(); 512 if (DITEM_STATUS((i = installCommit(self))) == DITEM_FAILURE) { 513 dialog_clear_norefresh(); 514 msgConfirm("Installation completed with some errors. You may wish to\n" 515 "scroll through the debugging messages on VTY1 with the\n" 516 "scroll-lock feature. You can also chose \"No\" at the next\n" 517 "prompt and go back into the installation menus to try and retry\n" 518 "whichever operations have failed."); 519 return i | DITEM_RESTORE; 520 521 } 522 else { 523 dialog_clear_norefresh(); 524 msgConfirm("Congratulations! You now have FreeBSD installed on your system.\n\n" 525 "We will now move on to the final configuration questions.\n" 526 "For any option you do not wish to configure, simply select\n" 527 "No.\n\n" 528 "If you wish to re-enter this utility after the system is up, you\n" 529 "may do so by typing: /stand/sysinstall."); 530 } 531 if (mediaDevice->type != DEVICE_TYPE_FTP && mediaDevice->type != DEVICE_TYPE_NFS) { 532 if (!msgYesNo("Would you like to configure any Ethernet or SLIP/PPP network devices?")) { 533 Device *tmp; 534 535 dialog_clear_norefresh(); 536 tmp = tcpDeviceSelect(); 537 dialog_clear_norefresh(); 538 if (tmp && !msgYesNo("Would you like to bring the %s interface up right now?", tmp->name)) 539 if (!tmp->init(tmp)) 540 msgConfirm("Initialization of %s device failed.", tmp->name); 541 } 542 } 543 544 dialog_clear_norefresh(); 545 if (!msgYesNo("Will this machine be an IP gateway (e.g. will it forward packets\n" 546 "between interfaces)?")) 547 variable_set2("gateway_enable", "YES"); 548 549 dialog_clear_norefresh(); 550 if (!msgYesNo("Do you want to allow anonymous FTP connections to this machine?")) 551 configAnonFTP(self); 552 553 dialog_clear_norefresh(); 554 if (!msgYesNo("Do you want to configure this machine as an NFS server?")) 555 configNFSServer(self); 556 557 dialog_clear_norefresh(); 558 if (!msgYesNo("Do you want to configure this machine as an NFS client?")) 559 variable_set2("nfs_client_enable", "YES"); 560 561 dialog_clear_norefresh(); 562 if (!msgYesNo("Would you like to customize your system console settings?")) { 563 WINDOW *w = savescr(); 564 565 dmenuOpenSimple(&MenuSyscons, FALSE); 566 restorescr(w); 567 } 568 569 dialog_clear_norefresh(); 570 if (!msgYesNo("Would you like to set this machine's time zone now?")) { 571 WINDOW *w = savescr(); 572 573 dialog_clear(); 574 systemExecute("tzsetup"); 575 restorescr(w); 576 } 577 578 dialog_clear_norefresh(); 579 if (!msgYesNo("Does this system have a mouse attached to it?")) { 580 WINDOW *w = savescr(); 581 582 dmenuOpenSimple(&MenuMouse, FALSE); 583 restorescr(w); 584 } 585 586 /* Now would be a good time to checkpoint the configuration data */ 587 configRC_conf("/etc/rc.conf"); 588 sync(); 589 590 if (directory_exists("/usr/X11R6")) { 591 dialog_clear_norefresh(); 592 if (!msgYesNo("Would you like to configure your X server at this time?")) 593 configXEnvironment(self); 594 } 595 596 dialog_clear_norefresh(); 597 if (!msgYesNo("The FreeBSD package collection is a collection of hundreds of ready-to-run\n" 598 "applications, from text editors to games to WEB servers and more. Would you\n" 599 "like to browse the collection now?")) 600 configPackages(self); 601 602 dialog_clear_norefresh(); 603 if (!msgYesNo("Would you like to add any initial user accounts to the system?\n" 604 "Adding at least one account for yourself at this stage is suggested\n" 605 "since working as the \"root\" user is dangerous (it is easy to do\n" 606 "things which adversely affect the entire system).")) 607 configUsers(self); 608 609 dialog_clear_norefresh(); 610 msgConfirm("Now you must set the system manager's password.\n" 611 "This is the password you'll use to log in as \"root\"."); 612 { 613 WINDOW *w = savescr(); 614 615 if (!systemExecute("passwd root")) 616 variable_set2("root_password", "YES"); 617 restorescr(w); 618 } 619 620 dialog_clear_norefresh(); 621 if (!msgYesNo("Would you like to register your FreeBSD system at this time?\n\n" 622 "PLEASE, take just 5 minutes to do this. If we're ever to get any\n" 623 "significant base of commercial software for FreeBSD, we need to\n" 624 "be able to provide more information about the size of our user community.\n" 625 "This is where your registration can really help us, and you can also\n" 626 "sign up for the new FreeBSD newsletter (its free!) at the same time.\n")) 627 configRegister(NULL); 628 else { 629 dialog_clear_norefresh(); 630 msgConfirm("OK, but if you should change your mind then you always can register\n" 631 "later by typing ``/stand/sysinstall register'' or by simply visiting our\n" 632 "web site at http://www.freebsd.org/register.html"); 633 634 } 635 /* XXX Put whatever other nice configuration questions you'd like to ask the user here XXX */ 636 637 /* Give user the option of one last configuration spree */ 638 dialog_clear_norefresh(); 639 installConfigure(); 640 641 return DITEM_LEAVE_MENU | DITEM_RESTORE; 642} 643 644/* The version of commit we call from the Install Custom menu */ 645int 646installCustomCommit(dialogMenuItem *self) 647{ 648 int i; 649 650 dialog_clear_norefresh(); 651 i = installCommit(self); 652 if (DITEM_STATUS(i) == DITEM_SUCCESS) { 653 /* Give user the option of one last configuration spree */ 654 installConfigure(); 655 return i; 656 } 657 else 658 msgConfirm("The commit operation completed with errors. Not\n" 659 "updating /etc files."); 660 return i; 661} 662 663/* 664 * What happens when we finally decide to going ahead with the installation. 665 * 666 * This is broken into multiple stages so that the user can do a full 667 * installation but come back here again to load more distributions, 668 * perhaps from a different media type. This would allow, for 669 * example, the user to load the majority of the system from CDROM and 670 * then use ftp to load just the DES dist. 671 */ 672int 673installCommit(dialogMenuItem *self) 674{ 675 int i; 676 char *str; 677 678 if (!Dists) 679 distConfig(NULL); 680 681 if (!Dists) 682 if (!dmenuOpenSimple(&MenuDistributions, FALSE) && !Dists) 683 return DITEM_FAILURE | DITEM_RESTORE; 684 685 if (!mediaVerify()) 686 return DITEM_FAILURE | DITEM_RESTORE; 687 688 str = variable_get(SYSTEM_STATE); 689 if (isDebug()) 690 msgDebug("installCommit: System state is `%s'\n", str); 691 692 /* Installation stuff we wouldn't do to a running system */ 693 if (RunningAsInit && DITEM_STATUS((i = installInitial())) == DITEM_FAILURE) 694 return i; 695 696try_media: 697 if (!mediaDevice->init(mediaDevice)) { 698 if (!msgYesNo("Unable to initialize selected media. Would you like to\n" 699 "adjust your media configuration and try again?")) { 700 mediaDevice = NULL; 701 if (!mediaVerify()) 702 return DITEM_FAILURE | DITEM_RESTORE; 703 else 704 goto try_media; 705 } 706 else 707 return DITEM_FAILURE | DITEM_RESTORE; 708 } 709 710 /* Now go get it all */ 711 i = distExtractAll(self); 712 713 /* When running as init, *now* it's safe to grab the rc.foo vars */ 714 installEnvironment(); 715 716 variable_set2(SYSTEM_STATE, DITEM_STATUS(i) == DITEM_FAILURE ? "error-install" : "full-install"); 717 718 return i | DITEM_RESTORE; 719} 720 721static void 722installConfigure(void) 723{ 724 /* Final menu of last resort */ 725 dialog_clear_norefresh(); 726 if (!msgYesNo("Visit the general configuration menu for a chance to set\n" 727 "any last options?")) { 728 WINDOW *w = savescr(); 729 730 dmenuOpenSimple(&MenuConfigure, FALSE); 731 restorescr(w); 732 } 733 configRC_conf("/etc/rc.conf"); 734 sync(); 735} 736 737int 738installFixupBin(dialogMenuItem *self) 739{ 740 Device **devs; 741 int i; 742 743 /* All of this is done only as init, just to be safe */ 744 if (RunningAsInit) { 745 /* Fix up kernel first */ 746 if (!file_readable("/kernel")) { 747 if (file_readable("/kernel.GENERIC")) { 748 if (vsystem("cp -p /kernel.GENERIC /kernel")) { 749 msgConfirm("Unable to copy /kernel into place!"); 750 return DITEM_FAILURE; 751 } 752#ifdef SAVE_USERCONFIG 753 /* Snapshot any boot -c changes back to the new kernel */ 754 save_userconfig_to_kernel("/kernel"); 755#endif 756 } 757 else { 758 msgConfirm("Can't find a kernel image to link to on the root file system!\n" 759 "You're going to have a hard time getting this system to\n" 760 "boot from the hard disk, I'm afraid!"); 761 return DITEM_FAILURE; 762 } 763 } 764 765 /* BOGON #1: Resurrect /dev after bin distribution screws it up */ 766 msgNotify("Remaking all devices.. Please wait!"); 767 if (vsystem("cd /dev; sh MAKEDEV all")) { 768 msgConfirm("MAKEDEV returned non-zero status"); 769 return DITEM_FAILURE; 770 } 771 772 msgNotify("Resurrecting /dev entries for slices.."); 773 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 774 if (!devs) 775 msgFatal("Couldn't get a disk device list!"); 776 777 /* Resurrect the slices that the former clobbered */ 778 for (i = 0; devs[i]; i++) { 779 Disk *disk = (Disk *)devs[i]->private; 780 Chunk *c1; 781 782 if (!devs[i]->enabled) 783 continue; 784 if (!disk->chunks) 785 msgFatal("No chunk list found for %s!", disk->name); 786 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 787 if (c1->type == freebsd) { 788 msgNotify("Making slice entries for %s", c1->name); 789 if (vsystem("cd /dev; sh MAKEDEV %sh", c1->name)) { 790 msgConfirm("Unable to make slice entries for %s!", c1->name); 791 return DITEM_FAILURE; 792 } 793 } 794 } 795 } 796 797 /* BOGON #2: We leave /etc in a bad state */ 798 chmod("/etc", 0755); 799 800 /* BOGON #3: No /var/db/mountdtab complains */ 801 Mkdir("/var/db"); 802 creat("/var/db/mountdtab", 0644); 803 804 /* BOGON #4: /compat created by default in root fs */ 805 Mkdir("/usr/compat"); 806 vsystem("ln -s /usr/compat /compat"); 807 808 /* BOGON #5: aliases database not build for bin */ 809 vsystem("newaliases"); 810 811 /* BOGON #6: deal with new boot files */ 812 vsystem("touch /kernel.config"); 813 vsystem("touch /boot.config"); 814 if (file_readable("/stand/boot.help") && !file_readable("/boot.help")) 815 vsystem("mv /stand/boot.help /"); 816 817 /* Now run all the mtree stuff to fix things up */ 818 vsystem("mtree -deU -f /etc/mtree/BSD.root.dist -p /"); 819 vsystem("mtree -deU -f /etc/mtree/BSD.var.dist -p /var"); 820 vsystem("mtree -deU -f /etc/mtree/BSD.usr.dist -p /usr"); 821 822 /* Do all the last ugly work-arounds here */ 823 } 824 return DITEM_SUCCESS; 825} 826 827/* Fix side-effects from the the XFree86 installation */ 828int 829installFixupXFree(dialogMenuItem *self) 830{ 831 /* BOGON #1: XFree86 requires various specialized fixups */ 832 if (directory_exists("/usr/X11R6")) { 833 msgNotify("Fixing permissions in XFree86 tree.."); 834 vsystem("chmod -R a+r /usr/X11R6"); 835 vsystem("find /usr/X11R6 -type d | xargs chmod a+x"); 836 837 /* Also do bogus minimal package registration so ports don't whine */ 838 if (file_readable("/usr/X11R6/lib/X11/pkgreg.tar.gz")) { 839 msgNotify("Installing package metainfo.."); 840 vsystem("tar xpzf /usr/X11R6/lib/X11/pkgreg.tar.gz -C / && rm /usr/X11R6/lib/X11/pkgreg.tar.gz"); 841 } 842 } 843 return DITEM_SUCCESS; 844} 845 846/* Go newfs and/or mount all the filesystems we've been asked to */ 847int 848installFilesystems(dialogMenuItem *self) 849{ 850 int i; 851 Disk *disk; 852 Chunk *c1, *c2, *rootdev, *swapdev, *usrdev, *vardev; 853 Device **devs; 854 PartInfo *root; 855 char dname[80]; 856 extern int MakeDevChunk(Chunk *c, char *n); 857 Boolean upgrade = FALSE; 858 859 /* If we've already done this, bail out */ 860 if (!variable_cmp(DISK_LABELLED, "written")) 861 return DITEM_SUCCESS; 862 863 upgrade = !variable_cmp(SYSTEM_STATE, "upgrade"); 864 if (!checkLabels(TRUE, &rootdev, &swapdev, &usrdev, &vardev)) 865 return DITEM_FAILURE; 866 867 if (rootdev) 868 root = (PartInfo *)rootdev->private_data; 869 else 870 root = NULL; 871 872 command_clear(); 873 if (swapdev && RunningAsInit) { 874 /* As the very first thing, try to get ourselves some swap space */ 875 sprintf(dname, "/dev/%s", swapdev->name); 876 if (!Fake && (!MakeDevChunk(swapdev, "/dev") || !file_readable(dname))) { 877 msgConfirm("Unable to make device node for %s in /dev!\n" 878 "The creation of filesystems will be aborted.", dname); 879 return DITEM_FAILURE; 880 } 881 882 if (!Fake) { 883 if (!swapon(dname)) 884 msgNotify("Added %s as initial swap device", dname); 885 else 886 msgConfirm("WARNING! Unable to swap to %s: %s\n" 887 "This may cause the installation to fail at some point\n" 888 "if you don't have a lot of memory.", dname, strerror(errno)); 889 } 890 } 891 892 if (rootdev && RunningAsInit) { 893 /* Next, create and/or mount the root device */ 894 sprintf(dname, "/dev/r%s", rootdev->name); 895 if (!Fake && (!MakeDevChunk(rootdev, "/dev") || !file_readable(dname))) { 896 msgConfirm("Unable to make device node for %s in /dev!\n" 897 "The creation of filesystems will be aborted.", dname); 898 return DITEM_FAILURE; 899 } 900 if (strcmp(root->mountpoint, "/")) 901 msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", rootdev->name, root->mountpoint); 902 903 if (root->newfs && (!upgrade || !msgYesNo("You are upgrading - are you SURE you want to newfs the root partition?"))) { 904 int i; 905 906 msgNotify("Making a new root filesystem on %s", dname); 907 i = vsystem("%s %s", root->newfs_cmd, dname); 908 if (i) { 909 msgConfirm("Unable to make new root filesystem on %s!\n" 910 "Command returned status %d", dname, i); 911 return DITEM_FAILURE; 912 } 913 } 914 else { 915 if (!upgrade) { 916 msgConfirm("Warning: Using existing root partition. It will be assumed\n" 917 "that you have the appropriate device entries already in /dev."); 918 } 919 msgNotify("Checking integrity of existing %s filesystem.", dname); 920 i = vsystem("fsck -y %s", dname); 921 if (i) 922 msgConfirm("Warning: fsck returned status of %d for %s.\n" 923 "This partition may be unsafe to use.", i, dname); 924 } 925 926 /* Switch to block device */ 927 sprintf(dname, "/dev/%s", rootdev->name); 928 if (Mount("/mnt", dname)) { 929 msgConfirm("Unable to mount the root file system on %s! Giving up.", dname); 930 return DITEM_FAILURE; 931 } 932 } 933 934 /* Now buzz through the rest of the partitions and mount them too */ 935 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 936 for (i = 0; devs[i]; i++) { 937 if (!devs[i]->enabled) 938 continue; 939 940 disk = (Disk *)devs[i]->private; 941 if (!disk->chunks) { 942 msgConfirm("No chunk list found for %s!", disk->name); 943 return DITEM_FAILURE; 944 } 945 if (RunningAsInit && root && (root->newfs || upgrade)) { 946 Mkdir("/mnt/dev"); 947 if (!Fake) 948 MakeDevDisk(disk, "/mnt/dev"); 949 } 950 else if (!RunningAsInit && !Fake) 951 MakeDevDisk(disk, "/dev"); 952 953 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 954 if (c1->type == freebsd) { 955 for (c2 = c1->part; c2; c2 = c2->next) { 956 if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) { 957 PartInfo *tmp = (PartInfo *)c2->private_data; 958 959 /* Already did root */ 960 if (c2 == rootdev) 961 continue; 962 963 if (tmp->newfs && (!upgrade || !msgYesNo("You are upgrading - are you SURE you want to newfs /dev/%s?", c2->name))) 964 command_shell_add(tmp->mountpoint, "%s %s/dev/r%s", tmp->newfs_cmd, RunningAsInit ? "/mnt" : "", c2->name); 965 else 966 command_shell_add(tmp->mountpoint, "fsck -y %s/dev/r%s", RunningAsInit ? "/mnt" : "", c2->name); 967 command_func_add(tmp->mountpoint, Mount, c2->name); 968 } 969 else if (c2->type == part && c2->subtype == FS_SWAP) { 970 char fname[80]; 971 int i; 972 973 if (c2 == swapdev) 974 continue; 975 sprintf(fname, "%s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name); 976 i = (Fake || swapon(fname)); 977 if (!i) 978 msgNotify("Added %s as an additional swap device", fname); 979 else 980 msgConfirm("Unable to add %s as a swap device: %s", fname, strerror(errno)); 981 } 982 } 983 } 984 else if (c1->type == fat && c1->private_data && (root->newfs || upgrade)) { 985 char name[FILENAME_MAX]; 986 987 sprintf(name, "%s/%s", RunningAsInit ? "/mnt" : "", ((PartInfo *)c1->private_data)->mountpoint); 988 Mkdir(name); 989 } 990 } 991 } 992 993 if (RunningAsInit) { 994 msgNotify("Copying initial device files.."); 995 /* Copy the boot floppy's dev files */ 996 if ((root->newfs || upgrade) && vsystem("find -x /dev | cpio %s -pdum /mnt", cpioVerbosity())) { 997 msgConfirm("Couldn't clone the /dev files!"); 998 return DITEM_FAILURE; 999 } 1000 } 1001 1002 command_sort(); 1003 command_execute(); 1004 return DITEM_SUCCESS; 1005} 1006 1007static char * 1008getRelname(void) 1009{ 1010 static char buf[64]; 1011 int sz = (sizeof buf) - 1; 1012 1013 if (sysctlbyname("kern.osrelease", buf, &sz, NULL, 0) != -1) { 1014 buf[sz] = '\0'; 1015 return buf; 1016 } 1017 else 1018 return "<unknown>"; 1019} 1020 1021/* Initialize various user-settable values to their defaults */ 1022int 1023installVarDefaults(dialogMenuItem *self) 1024{ 1025 char *cp; 1026 1027 /* Set default startup options */ 1028 variable_set2(VAR_RELNAME, getRelname()); 1029 variable_set2(VAR_CPIO_VERBOSITY, "high"); 1030 variable_set2(VAR_TAPE_BLOCKSIZE, DEFAULT_TAPE_BLOCKSIZE); 1031 variable_set2(VAR_INSTALL_ROOT, "/"); 1032 variable_set2(VAR_INSTALL_CFG, "install.cfg"); 1033 cp = getenv("EDITOR"); 1034 if (!cp) 1035 cp = "/usr/bin/ee"; 1036 variable_set2(VAR_EDITOR, cp); 1037 variable_set2(VAR_FTP_USER, "ftp"); 1038 variable_set2(VAR_BROWSER_PACKAGE, "lynx"); 1039 variable_set2(VAR_BROWSER_BINARY, "/usr/local/bin/lynx"); 1040 variable_set2(VAR_FTP_STATE, "passive"); 1041 variable_set2(VAR_NFS_SECURE, "YES"); 1042 variable_set2(VAR_PKG_TMPDIR, "/usr/tmp"); 1043 variable_set2(VAR_GATED_PKG, "gated"); 1044 variable_set2(VAR_PCNFSD_PKG, "pcnfsd"); 1045 variable_set2(VAR_MEDIA_TIMEOUT, itoa(MEDIA_TIMEOUT)); 1046 if (getpid() != 1) 1047 variable_set2(SYSTEM_STATE, "update"); 1048 else 1049 variable_set2(SYSTEM_STATE, "init"); 1050 return DITEM_SUCCESS; 1051} 1052 1053/* Load the environment up from various system configuration files */ 1054void 1055installEnvironment(void) 1056{ 1057 if (file_readable("/etc/rc.conf")) 1058 configEnvironmentRC_conf("/etc/rc.conf"); 1059 if (file_readable("/etc/resolv.conf")) 1060 configEnvironmentResolv("/etc/resolv.conf"); 1061} 1062 1063/* Copy the boot floppy contents into /stand */ 1064Boolean 1065copySelf(void) 1066{ 1067 int i; 1068 1069 if (file_readable("/boot.help")) 1070 vsystem("cp /boot.help /mnt"); 1071 msgWeHaveOutput("Copying the boot floppy to /stand on root filesystem"); 1072 i = vsystem("find -x /stand | cpio %s -pdum /mnt", cpioVerbosity()); 1073 if (i) { 1074 msgConfirm("Copy returned error status of %d!", i); 1075 return FALSE; 1076 } 1077 1078 /* Copy the /etc files into their rightful place */ 1079 if (vsystem("cd /mnt/stand; find etc | cpio %s -pdum /mnt", cpioVerbosity())) { 1080 msgConfirm("Couldn't copy up the /etc files!"); 1081 return TRUE; 1082 } 1083 return TRUE; 1084} 1085 1086static void 1087create_termcap(void) 1088{ 1089 FILE *fp; 1090 1091 const char *caps[] = { 1092 termcap_vt100, termcap_cons25, termcap_cons25_m, termcap_cons25r, 1093 termcap_cons25r_m, termcap_cons25l1, termcap_cons25l1_m, NULL, 1094 }; 1095 const char **cp; 1096 1097 if (!file_readable(TERMCAP_FILE)) { 1098 Mkdir("/usr/share/misc"); 1099 fp = fopen(TERMCAP_FILE, "w"); 1100 if (!fp) { 1101 msgConfirm("Unable to initialize termcap file. Some screen-oriented\nutilities may not work."); 1102 return; 1103 } 1104 cp = caps; 1105 while (*cp) 1106 fprintf(fp, "%s\n", *(cp++)); 1107 fclose(fp); 1108 } 1109} 1110 1111#ifdef SAVE_USERCONFIG 1112static void 1113save_userconfig_to_kernel(char *kern) 1114{ 1115 struct kernel *core, *boot; 1116 struct list *c_isa, *b_isa, *c_dev, *b_dev; 1117 int i, d; 1118 1119 if ((core = uc_open("-incore")) == NULL) { 1120 msgDebug("save_userconf: Can't read in-core information for kernel.\n"); 1121 return; 1122 } 1123 1124 if ((boot = uc_open(kern)) == NULL) { 1125 msgDebug("save_userconf: Can't read device information for kernel image %s\n", kern); 1126 return; 1127 } 1128 1129 msgNotify("Saving any boot -c changes to new kernel..."); 1130 c_isa = uc_getdev(core, "-isa"); 1131 b_isa = uc_getdev(boot, "-isa"); 1132 if (isDebug()) 1133 msgDebug("save_userconf: got %d ISA device entries from core, %d from boot.\n", c_isa->ac, b_isa->ac); 1134 for (d = 0; d < c_isa->ac; d++) { 1135 if (isDebug()) 1136 msgDebug("save_userconf: ISA device loop, c_isa->av[%d] = %s\n", d, c_isa->av[d]); 1137 if (strcmp(c_isa->av[d], "npx0")) { /* special case npx0, which mucks with its id_irq member */ 1138 c_dev = uc_getdev(core, c_isa->av[d]); 1139 b_dev = uc_getdev(boot, b_isa->av[d]); 1140 if (!c_dev || !b_dev) { 1141 msgDebug("save_userconf: c_dev: %x b_dev: %x\n", c_dev, b_dev); 1142 continue; 1143 } 1144 if (isDebug()) 1145 msgDebug("save_userconf: ISA device %s: %d config parameters (core), %d (boot)\n", 1146 c_isa->av[d], c_dev->ac, b_dev->ac); 1147 for (i = 0; i < c_dev->ac; i++) { 1148 if (isDebug()) 1149 msgDebug("save_userconf: c_dev->av[%d] = %s, b_dev->av[%d] = %s\n", i, c_dev->av[i], i, b_dev->av[i]); 1150 if (strcmp(c_dev->av[i], b_dev->av[i])) { 1151 if (isDebug()) 1152 msgDebug("save_userconf: %s (boot) -> %s (core)\n", 1153 c_dev->av[i], b_dev->av[i]); 1154 isa_setdev(boot, c_dev); 1155 } 1156 } 1157 } 1158 else { 1159 if (isDebug()) 1160 msgDebug("skipping npx0\n"); 1161 } 1162 } 1163 if (isDebug()) 1164 msgDebug("Closing kernels\n"); 1165 uc_close(core, 0); 1166 uc_close(boot, 1); 1167} 1168#endif 1169