From ce250ffb37ec6fc6059c38fa4f23f598f0f50350 Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <eelco.dolstra@logicblox.com>
Date: Fri, 8 Feb 2008 15:59:15 +0000
Subject: [PATCH] * Installation CD: include a lot of modules (SATA, PATA,
 Firewire,   USB, some SCSI controllers) in the initrd for mounting the CD. *
 Add nix-hardware-scan to the system. * Upstart: don't use the -v flag. *
 Include the NixOS version in the ISO image filename. * Include testdisk and
 ms-sys in the CD. * Some bugfixes in the installer.

svn path=/nixos/trunk/; revision=10556
---
 boot/boot-stage-1-init.sh        |  1 +
 boot/boot-stage-1.nix            |  2 +-
 boot/boot-stage-2-init.sh        |  2 +-
 configuration/rescue-cd.nix      | 57 +++++++++++++++++++++++++++++---
 default.nix                      | 10 ++++--
 installer/default.nix            | 45 +++++++++++++++++++++++++
 installer/nixos-checkout.nix     |  8 -----
 installer/nixos-checkout.sh      | 13 ++++++++
 installer/nixos-hardware-scan.pl | 24 +++++++++-----
 installer/nixos-install.nix      | 19 -----------
 installer/nixos-install.sh       |  8 +++--
 installer/nixos-rebuild.nix      |  8 -----
 system/activate-configuration.sh |  2 +-
 system/options.nix               | 17 +++++++---
 system/system.nix                | 47 +++++++++-----------------
 15 files changed, 170 insertions(+), 93 deletions(-)
 create mode 100644 installer/default.nix
 delete mode 100644 installer/nixos-checkout.nix
 delete mode 100644 installer/nixos-install.nix
 delete mode 100644 installer/nixos-rebuild.nix

diff --git a/boot/boot-stage-1-init.sh b/boot/boot-stage-1-init.sh
index 3bde517a937..d412b31715a 100644
--- a/boot/boot-stage-1-init.sh
+++ b/boot/boot-stage-1-init.sh
@@ -60,6 +60,7 @@ done
 # Load some kernel modules.
 export MODULE_DIR=@modulesDir@/lib/modules/
 for i in @modules@; do
+    echo "trying to load $i..."
     modprobe $i
 done
 
diff --git a/boot/boot-stage-1.nix b/boot/boot-stage-1.nix
index 0c504e86469..a53b9d6c86b 100644
--- a/boot/boot-stage-1.nix
+++ b/boot/boot-stage-1.nix
@@ -42,7 +42,7 @@ let
 
 in
 
-assert !autoDetectRootDevice -> mountPoints != [];
+if !autoDetectRootDevice && mountPoints == [] then abort "You must specify the fileSystems option!" else
 
 substituteAll {
   src = ./boot-stage-1-init.sh;
diff --git a/boot/boot-stage-2-init.sh b/boot/boot-stage-2-init.sh
index eafd64a8dcd..e298a0d1c8b 100644
--- a/boot/boot-stage-2-init.sh
+++ b/boot/boot-stage-2-init.sh
@@ -119,4 +119,4 @@ fi
 # HUP signal.
 export UPSTART_CFG_DIR=/etc/event.d
 setPath "@upstartPath@"
-exec /var/run/current-system/upstart/sbin/init -v
+exec /var/run/current-system/upstart/sbin/init
diff --git a/configuration/rescue-cd.nix b/configuration/rescue-cd.nix
index 7aca76d0257..ebba167c6de 100644
--- a/configuration/rescue-cd.nix
+++ b/configuration/rescue-cd.nix
@@ -1,10 +1,14 @@
 { platform ? __currentSystem
+, relName ?
+    if builtins.pathExists ../relname
+    then builtins.readFile ../relname
+    else "nixos-${builtins.readFile ../VERSION}"
 }:
 
 rec {
 
   
-  nixpkgsRel = "nixpkgs-0.12pre10072";
+  nixpkgsRel = "nixpkgs-0.12pre10553";
 
 
   configuration = {
@@ -16,9 +20,50 @@ rec {
       rootLabel = "NIXOS";
       extraTTYs = [7 8]; # manual, rogue
       extraModulePackages = [pkgs.aufs];
+      
       initrd = {
         extraKernelModules = [
-          "aufs" # needed for live-CD operation
+          # The initrd should contain any modules necessary for
+          # mounting the CD.
+        
+          # SATA/PATA support.
+          "ahci"
+
+          "ata_piix"
+          
+          "sata_inic162x" "sata_nv" "sata_promise" "sata_qstor"
+          "sata_sil" "sata_sil24" "sata_sis" "sata_svw" "sata_sx4"
+          "sata_uli" "sata_via" "sata_vsc"
+
+          "pata_ali" "pata_amd" "pata_artop" "pata_atiixp"
+          "pata_cs5520" "pata_cs5530" "pata_cs5535" "pata_efar"
+          "pata_hpt366" "pata_hpt37x" "pata_hpt3x2n" "pata_hpt3x3"
+          "pata_it8213" "pata_it821x" "pata_jmicron" "pata_marvell"
+          "pata_mpiix" "pata_netcell" "pata_ns87410" "pata_oldpiix"
+          "pata_pcmcia" "pata_pdc2027x" "pata_qdi" "pata_rz1000"
+          "pata_sc1200" "pata_serverworks" "pata_sil680" "pata_sis"
+          "pata_sl82c105" "pata_triflex" "pata_via"
+          # "pata_winbond" <-- causes timeouts in sd_mod
+
+          # SCSI support (incomplete).
+          "3w-9xxx" "3w-xxxx" "aic79xx" "aic7xxx" "arcmsr" 
+        
+          # USB support, especially for booting from USB CD-ROM
+          # drives.  Also include USB keyboard support for when
+          # something goes wrong in stage 1.
+          "ehci_hcd"
+          "ohci_hcd"
+          "usbhid"
+          "usb_storage"
+
+          # Firewire support.  Not tested.
+          "ohci1394" "sbp2"
+
+          # Wait for SCSI devices to appear.
+          "scsi_wait_scan"
+
+          # Needed for live-CD operation.
+          "aufs"
         ];
       };
     };
@@ -47,6 +92,8 @@ rec {
             script
               export PATH=${pkgs.gnutar}/bin:${pkgs.bzip2}/bin:$PATH
 
+              mkdir -p /mnt
+
               ${system.nix}/bin/nix-store --load-db < /nix-path-registration
 
               mkdir -p /etc/nixos/nixos
@@ -130,6 +177,8 @@ rec {
         pkgs.subversion # for nixos-checkout
         pkgs.w3m # needed for the manual anyway
         pkgs.gdb # for debugging Nix
+        pkgs.testdisk # useful for repairing boot problems
+        pkgs.mssys # for writing Microsoft boot sectors / MBRs
       ];
     };
    
@@ -177,7 +226,7 @@ rec {
   # Get a recent copy of Nixpkgs.
   nixpkgsTarball = pkgs.fetchurl {
     url = configuration.installer.nixpkgsURL + "/" + nixpkgsRel + ".tar.bz2";
-    md5 = "6a793b877e2a4fa79827515902e1dfd8";
+    md5 = "a6f1cd8486b7d588ecc7d98f5baf6a73";
   };
 
 
@@ -200,7 +249,7 @@ rec {
   # the initrd produced above, and the closure of the stage 2 init.
   rescueCD = import ../helpers/make-iso9660-image.nix {
     inherit (pkgs) stdenv perl cdrkit;
-    isoName = "nixos-${platform}.iso";
+    isoName = "${relName}-${platform}.iso";
 
     # Single files to be copied to fixed locations on the CD.
     contents = [
diff --git a/default.nix b/default.nix
index 09c9a1569d8..fcf12b80479 100644
--- a/default.nix
+++ b/default.nix
@@ -18,14 +18,18 @@ in
     initialRamdisk
     kernel
     nix
-    nixosCheckout
-    nixosInstall
-    nixosRebuild
     system
     systemPath
     config
     ;
 
+  inherit (system.nixosTools)
+    nixosCheckout
+    nixosHardwareScan
+    nixosInstall
+    nixosRebuild
+    ;    
+    
   nixFallback = system.nix;
 
   manifests = system.config.installer.manifests; # exported here because nixos-rebuild uses it
diff --git a/installer/default.nix b/installer/default.nix
new file mode 100644
index 00000000000..314902e9aa2
--- /dev/null
+++ b/installer/default.nix
@@ -0,0 +1,45 @@
+{pkgs, config, nix}:
+
+let
+
+  makeProg = args: pkgs.substituteAll (args // {
+    dir = "bin";
+    isExecutable = true;
+  });
+
+in
+
+{
+
+  nixosInstall = makeProg {
+    name = "nixos-install";
+    src = ./nixos-install.sh;
+
+    inherit (pkgs) perl;
+    inherit nix;
+    nixpkgsURL = config.installer.nixpkgsURL;
+
+    pathsFromGraph = ../helpers/paths-from-graph.pl;
+
+    nixClosure = pkgs.runCommand "closure"
+      {exportReferencesGraph = ["refs" nix];}
+      "cp refs $out";
+  };
+
+  nixosRebuild = makeProg {
+    name = "nixos-rebuild";
+    src = ./nixos-rebuild.sh;
+  };
+
+  nixosCheckout = makeProg {
+    name = "nixos-checkout";
+    src = ./nixos-checkout.sh;
+   };
+
+  nixosHardwareScan = makeProg {
+    name = "nixos-hardware-scan";
+    src = ./nixos-hardware-scan.pl;
+    inherit (pkgs) perl;
+  };
+
+}
diff --git a/installer/nixos-checkout.nix b/installer/nixos-checkout.nix
deleted file mode 100644
index ce8038fffed..00000000000
--- a/installer/nixos-checkout.nix
+++ /dev/null
@@ -1,8 +0,0 @@
-{substituteAll}:
-
-substituteAll {
-  name = "nixos-checkout";
-  src = ./nixos-checkout.sh;
-  dir = "bin";
-  isExecutable = true;
-}
diff --git a/installer/nixos-checkout.sh b/installer/nixos-checkout.sh
index 339beeecacd..1551f009de2 100644
--- a/installer/nixos-checkout.sh
+++ b/installer/nixos-checkout.sh
@@ -1,6 +1,19 @@
 #! @shell@ -e
 set -x
 
+# Pull the manifests defined in the configuration (the "manifests"
+# attribute).  Wonderfully hacky *and* cut&pasted from nixos-installer.sh!!!
+if test -z "$NIXOS"; then NIXOS=/etc/nixos/nixos; fi
+if test -z "$NIXOS_NO_PULL"; then
+    manifests=$(nix-instantiate --eval-only --xml --strict $NIXOS -A manifests \
+        | grep '<string'  | sed 's^.*"\(.*\)".*^\1^g')
+
+    mkdir -p /nix/var/nix/channel-cache
+    for i in $manifests; do
+        NIX_DOWNLOAD_CACHE=/nix/var/nix/channel-cache nix-pull $i || true
+    done
+fi
+
 # Obtain Subversion.
 if test -z "$(type -tp svn)"; then
     #nix-channel --add http://nix.cs.uu.nl/dist/nix/channels-v3/nixpkgs-unstable
diff --git a/installer/nixos-hardware-scan.pl b/installer/nixos-hardware-scan.pl
index 00470a6e2fd..e3277fa035d 100644
--- a/installer/nixos-hardware-scan.pl
+++ b/installer/nixos-hardware-scan.pl
@@ -1,4 +1,4 @@
-#! @perl@ -w
+#! @perl@/bin/perl -w
 
 use File::Spec;
 use File::Basename;
@@ -8,6 +8,12 @@ my @kernelModules = ();
 my @initrdKernelModules = ();
 
 
+sub debug {
+    return unless defined $ENV{"DEBUG"};
+    print STDERR @_;
+}
+
+
 # Read a file, returning undef if the file cannot be opened.
 sub readFile {
     my $filename = shift;
@@ -66,9 +72,9 @@ sub pciCheck {
         chomp $module;
     }
     
-    print STDERR "$path: $vendor $device $class";
-    print STDERR " $module" if defined $module;
-    print STDERR "\n";
+    debug "$path: $vendor $device $class";
+    debug " $module" if defined $module;
+    debug "\n";
 
     if (defined $module) {
         # See the bottom of http://pciids.sourceforge.net/pci.ids for
@@ -144,9 +150,9 @@ sub usbCheck {
         chomp $module;
     }
     
-    print STDERR "$path: $class $subclass $protocol";
-    print STDERR " $module" if defined $module;
-    print STDERR "\n";
+    debug "$path: $class $subclass $protocol";
+    debug " $module" if defined $module;
+    debug "\n";
  
     if (defined $module) {
         if (# Mass-storage controller.  Definitely important.
@@ -195,9 +201,9 @@ my $initrdKernelModules = toNixExpr(removeDups @initrdKernelModules);
 my $kernelModules = toNixExpr(removeDups @kernelModules);
  
 
+## This is a generated file.  Do not modify!
+## Make changes to /etc/nixos/configuration.nix instead.
 print <<EOF ;
-# This is a generated file.  Do not modify!
-# Make changes to /etc/nixos/configuration.nix instead.
 {
   boot = {
     initrd = {
diff --git a/installer/nixos-install.nix b/installer/nixos-install.nix
deleted file mode 100644
index 298bf594c44..00000000000
--- a/installer/nixos-install.nix
+++ /dev/null
@@ -1,19 +0,0 @@
-{ perl, runCommand, substituteAll, nix
-, # URL of the Nixpkgs distribution that the installer will pull.
-  # Leave empty for a pure source distribution.
-  nixpkgsURL ? ""
-}:
-
-substituteAll {
-  name = "nixos-install";
-  src = ./nixos-install.sh;
-  dir = "bin";
-  isExecutable = true;
-  inherit nix nixpkgsURL perl;
-
-  pathsFromGraph = ../helpers/paths-from-graph.pl;
-
-  nixClosure = runCommand "closure"
-    {exportReferencesGraph = ["refs" nix];}
-    "cp refs $out";
-}
diff --git a/installer/nixos-install.sh b/installer/nixos-install.sh
index e7794f720a3..3686bc3147d 100644
--- a/installer/nixos-install.sh
+++ b/installer/nixos-install.sh
@@ -56,13 +56,13 @@ mount --bind /proc $mountPoint/proc
 mount --bind /sys $mountPoint/sys
 
 cleanup() {
-    # !!! don't umount any we didn't mount ourselves
+    # !!! don't umount anything we didn't mount ourselves
     for i in $(grep -F "$mountPoint" /proc/mounts \
         | @perl@/bin/perl -e 'while (<>) { /^\S+\s+(\S+)\s+/; print "$1\n"; }' \
         | sort -r);
     do
-        if test "$i" != "$mountPoint"; then
-            umount $i
+        if test "$i" != "$mountPoint" -a "$i" != / -a -e "$i"; then
+            umount $i || true
         fi
     done
 }
@@ -149,6 +149,8 @@ chroot $mountPoint @nix@/bin/nix-env \
 # Make a backup of the old NixOS/Nixpkgs sources.
 echo "copying NixOS/Nixpkgs sources to /etc/nixos...."
 
+backupTimestamp=$(date "+%Y%m%d%H%M%S")
+
 targetNixos=$mountPoint/etc/nixos/nixos
 if test -e $targetNixos; then
     mv $targetNixos $targetNixos.backup-$backupTimestamp
diff --git a/installer/nixos-rebuild.nix b/installer/nixos-rebuild.nix
deleted file mode 100644
index 2c8371a597c..00000000000
--- a/installer/nixos-rebuild.nix
+++ /dev/null
@@ -1,8 +0,0 @@
-{substituteAll}:
-
-substituteAll {
-  name = "nixos-rebuild";
-  src = ./nixos-rebuild.sh;
-  dir = "bin";
-  isExecutable = true;
-}
diff --git a/system/activate-configuration.sh b/system/activate-configuration.sh
index e07e8d295af..1e2eb44acad 100644
--- a/system/activate-configuration.sh
+++ b/system/activate-configuration.sh
@@ -26,7 +26,7 @@ for i in $(cd $staticEtc && find * -type l); do
     if test -e "$staticEtc/$i.mode"; then
         # Create a regular file in /etc.
         cp $staticEtc/$i /etc/$i
-        chown root.root /etc/$i
+        chown 0.0 /etc/$i
         chmod "$(cat "$staticEtc/$i.mode")" /etc/$i
     else
         # Create a symlink in /etc.
diff --git a/system/options.nix b/system/options.nix
index b2b7152d161..892003cf019 100644
--- a/system/options.nix
+++ b/system/options.nix
@@ -125,7 +125,7 @@
 
     extraModulePackages = mkOption {
       default = [];
-      example = [pkgs.aufs pkgs.nvidiaDriver];
+      example = [pkgs.aufs pkgs.nvidiaDrivers];
       description = ''
         A list of additional packages supplying kernel modules.
       '';
@@ -146,6 +146,12 @@
 
       kernelModules = mkOption {
         default = [
+          # Note: most of these (especially the SATA/PATA modules)
+          # shouldn't be included by default since nixos-hardware-scan
+          # detects them, but I'm keeping them for now for backwards
+          # compatibility.
+          
+          # Some SATA/PATA stuff.        
           "ahci"
           "sata_nv"
           "sata_via"
@@ -153,11 +159,14 @@
           "sata_uli"
           "ata_piix"
           "pata_marvell"
+          # Standard SCSI stuff.
           "sd_mod"
           "sr_mod"
-          "ide-cd"
-          "ide-disk"
-          "ide-generic"
+          # Standard IDE stuff.
+          "ide_cd"
+          "ide_disk"
+          "ide_generic"
+          # Filesystems.
           "ext3"
           # Support USB keyboards, in case the boot fails and we only have
           # a USB keyboard.
diff --git a/system/system.nix b/system/system.nix
index 4e793a5c039..3d4722cacb3 100644
--- a/system/system.nix
+++ b/system/system.nix
@@ -119,19 +119,9 @@ rec {
   };
 
 
-  # The installer.
-  nixosInstall = import ../installer/nixos-install.nix {
-    inherit (pkgs) perl runCommand substituteAll;
-    inherit nix;
-    nixpkgsURL = config.installer.nixpkgsURL;
-  };
-
-  nixosRebuild = import ../installer/nixos-rebuild.nix {
-    inherit (pkgs) substituteAll;
-  };
-
-  nixosCheckout = import ../installer/nixos-checkout.nix {
-    inherit (pkgs) substituteAll;
+  # NixOS installation/updating tools.
+  nixosTools = import ../installer {
+    inherit pkgs config nix;
   };
 
 
@@ -208,20 +198,18 @@ rec {
 
 
   # The packages you want in the boot environment.
-  systemPathList = (if config.environment.cleanStart then 
-  [
+  systemPathList = [
     # Better leave them here - they are small, needed,
     # and hard to refer from anywhere outside.
-    modprobe 
+    modprobe # must take precedence over module_init_tools
     nix
-    nixosInstall
-    nixosRebuild
-    nixosCheckout
+    nixosTools.nixosInstall
+    nixosTools.nixosRebuild
+    nixosTools.nixosCheckout
+    nixosTools.nixosHardwareScan
     setuidWrapper
   ]
-  else
-  [
-    modprobe # must take precedence over module_init_tools
+  ++ pkgs.lib.optionals (!config.environment.cleanStart) [
     pkgs.bashInteractive # bash with ncurses support
     pkgs.bzip2
     pkgs.coreutils
@@ -263,17 +251,12 @@ rec {
     pkgs.usbutils
     pkgs.utillinux
     pkgs.wirelesstools
-    nix
-    nixosInstall
-    nixosRebuild
-    nixosCheckout
-    setuidWrapper
-  ])
-  ++ pkgs.lib.optional (config.security.sudo.enable) pkgs.sudo
-  ++ pkgs.lib.optional (config.networking.defaultMailServer.directDelivery) pkgs.ssmtp 
+  ]
+  ++ pkgs.lib.optional config.security.sudo.enable pkgs.sudo
+  ++ pkgs.lib.optional config.networking.defaultMailServer.directDelivery pkgs.ssmtp 
   ++ pkgs.lib.concatLists (map (job: job.extraPath) upstartJobs.jobs)
-  ++ (config.environment.extraPackages) pkgs
-  ++ pkgs.lib.optional (config.fonts.enableFontDir) fontDir;
+  ++ config.environment.extraPackages pkgs
+  ++ pkgs.lib.optional config.fonts.enableFontDir fontDir;
 
 
   # We don't want to put all of `startPath' and `path' in $PATH, since