summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gnu/build/hurd-boot.scm202
-rw-r--r--gnu/build/linux-boot.scm48
-rw-r--r--gnu/local.mk1
-rw-r--r--gnu/packages/hurd.scm100
-rw-r--r--gnu/system/image.scm2
-rw-r--r--gnu/system/vm.scm5
6 files changed, 219 insertions, 139 deletions
diff --git a/gnu/build/hurd-boot.scm b/gnu/build/hurd-boot.scm
new file mode 100644
index 0000000000..729822dcbd
--- /dev/null
+++ b/gnu/build/hurd-boot.scm
@@ -0,0 +1,202 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2020 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu build hurd-boot)
+  #:use-module (system repl error-handling)
+  #:autoload   (system repl repl) (start-repl)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-26)
+  #:use-module (ice-9 match)
+  #:use-module (guix build utils)
+  #:use-module ((guix build syscalls)
+                #:hide (file-system-type))
+  #:export (make-hurd-device-nodes
+            boot-hurd-system))
+
+;;; Commentary:
+;;;
+;;; Utility procedures useful to boot a Hurd system.
+;;;
+;;; Code:
+
+;; XXX FIXME c&p from linux-boot.scm
+(define (find-long-option option arguments)
+  "Find OPTION among ARGUMENTS, where OPTION is something like \"--load\".
+Return the value associated with OPTION, or #f on failure."
+  (let ((opt (string-append option "=")))
+    (and=> (find (cut string-prefix? opt <>)
+                 arguments)
+           (lambda (arg)
+             (substring arg (+ 1 (string-index arg #\=)))))))
+
+;; XXX FIXME c&p from guix/utils.scm
+(define (readlink* file)
+  "Call 'readlink' until the result is not a symlink."
+  (define %max-symlink-depth 50)
+
+  (let loop ((file  file)
+             (depth 0))
+    (define (absolute target)
+      (if (absolute-file-name? target)
+          target
+          (string-append (dirname file) "/" target)))
+
+    (if (>= depth %max-symlink-depth)
+        file
+        (call-with-values
+            (lambda ()
+              (catch 'system-error
+                (lambda ()
+                  (values #t (readlink file)))
+                (lambda args
+                  (let ((errno (system-error-errno args)))
+                    (if (or (= errno EINVAL))
+                        (values #f file)
+                        (apply throw args))))))
+          (lambda (success? target)
+            (if success?
+                (loop (absolute target) (+ depth 1))
+                file))))))
+
+(define* (make-hurd-device-nodes #:optional (root "/"))
+  "Make some of the nodes needed on GNU/Hurd."
+  (define (scope dir)
+    (string-append root (if (string-suffix? "/" root) "" "/") dir))
+
+  (mkdir (scope "dev"))
+  (for-each (lambda (file)
+              (call-with-output-file (scope file)
+                (lambda (port)
+                  (display file port)   ;avoid hard-linking
+                  (chmod port #o666))))
+            '("dev/null"
+              "dev/zero"
+              "dev/full"
+              "dev/random"
+              "dev/urandom"))
+  ;; Don't create /dev/console, /dev/vcs, etc.: they are created by
+  ;; console-run on first boot.
+
+  (mkdir (scope "servers"))
+  (for-each (lambda (file)
+              (call-with-output-file (scope (string-append "servers/" file))
+                (lambda (port)
+                  (display file port)   ;avoid hard-linking
+                  (chmod port #o444))))
+            '("startup"
+              "exec"
+              "proc"
+              "password"
+              "default-pager"
+              "crash-dump-core"
+              "kill"
+              "suspend"))
+
+  (mkdir (scope "servers/socket"))
+  ;; Don't create /servers/socket/1 & co: runsystem does that on first boot.
+
+  ;; TODO: Set the 'gnu.translator' extended attribute for passive translator
+  ;; settings?
+  )
+
+
+(define* (boot-hurd-system #:key (on-error 'debug))
+  "This procedure is meant to be called from an early RC script.
+
+Install the relevant passive translators on the first boot.  Then, run system
+activation by using the kernel command-line options '--system' and '--load';
+starting the Shepherd.
+
+XXX TODO: see linux-boot.scm:boot-system.
+XXX TODO: add proper file-system checking, mounting
+XXX TODO: move bits to (new?) (hurd?) (activation?) services
+XXX TODO: use settrans/setxattr instead of MAKEDEV
+
+"
+  (define translators
+    '(("/servers/crash-dump-core" ("/hurd/crash" "--dump-core"))
+      ("/servers/crash-kill" ("/hurd/crash" "--kill"))
+      ("/servers/crash-suspend" ("/hurd/crash" "--suspend"))
+      ("/servers/password" ("/hurd/password"))
+      ("/servers/socket/1" ("/hurd/pflocal"))
+      ("/servers/socket/2" ("/hurd/pfinet" "--interface" "eth0"
+                            "--address" "10.0.2.15" ;the default QEMU guest IP
+                            "--netmask" "255.255.255.0"
+                            "--gateway" "10.0.2.2"
+                            "--ipv6" "/servers/socket/16"))))
+
+  (display "Welcome, this is GNU's early boot Guile.\n")
+  (display "Use '--repl' for an initrd REPL.\n\n")
+
+  (call-with-error-handling
+   (lambda ()
+
+     (define (translated? node)
+       ;; Return true if a translator is installed on NODE.
+       (with-output-to-port (%make-void-port "w")
+         (lambda ()
+           (with-error-to-port (%make-void-port "w")
+             (lambda ()
+               (zero? (system* "showtrans" "-s" node)))))))
+
+     (for-each (match-lambda
+                 ((node command)
+                  (unless (translated? node)
+                    (mkdir-p (dirname node))
+                    (apply invoke "settrans" "-c" node command))))
+               translators)
+
+     (format #t "Creating essential device nodes...\n")
+     (with-directory-excursion "/dev"
+       (invoke "MAKEDEV" "--devdir=/dev" "std")
+       (invoke "MAKEDEV" "--devdir=/dev" "vcs")
+       (invoke "MAKEDEV" "--devdir=/dev" "tty1""tty2" "tty3" "tty4" "tty5" "tty6")
+       (invoke "MAKEDEV" "--devdir=/dev" "ptyp0" "ptyp1" "ptyp2")
+       (invoke "MAKEDEV" "--devdir=/dev" "console"))
+
+     (let* ((args    (command-line))
+            (system  (find-long-option "--system" args))
+            (to-load (find-long-option "--load" args)))
+
+       (false-if-exception (delete-file "/hurd"))
+       (let ((hurd/hurd (readlink* (string-append system "/profile/hurd"))))
+         (symlink hurd/hurd "/hurd"))
+
+       (format #t "Starting pager...\n")
+       (unless (zero? (system* "/hurd/mach-defpager"))
+         (format #t "FAILED...Good luck!\n"))
+
+       (cond ((member "--repl" args)
+              (format #t "Starting repl...\n")
+              (start-repl))
+             (to-load
+              (format #t "loading '~a'...\n" to-load)
+              (primitive-load to-load)
+              (format (current-error-port)
+                      "boot program '~a' terminated, rebooting~%"
+                      to-load)
+              (sleep 2)
+              (reboot))
+             (else
+              (display "no boot file passed via '--load'\n")
+              (display "entering a warm and cozy REPL\n")
+              (start-repl)))))
+   #:on-error on-error))
+
+;;; hurd-boot.scm ends here
diff --git a/gnu/build/linux-boot.scm b/gnu/build/linux-boot.scm
index d62c670684..80fe0cfb9d 100644
--- a/gnu/build/linux-boot.scm
+++ b/gnu/build/linux-boot.scm
@@ -40,7 +40,6 @@
             find-long-option
             find-long-options
             make-essential-device-nodes
-            make-hurd-device-nodes
             make-static-device-nodes
             configure-qemu-networking
 
@@ -324,51 +323,6 @@ one specific hardware device. These we have to create."
   ;; File systems in user space (FUSE).
   (mknod (scope "dev/fuse") 'char-special #o666 (device-number 10 229)))
 
-(define* (make-hurd-device-nodes #:optional (root "/"))
-  "Make some of the nodes needed on GNU/Hurd."
-  (define (scope dir)
-    (string-append root
-                   (if (string-suffix? "/" root)
-                       ""
-                       "/")
-                   dir))
-
-  (mkdir (scope "dev"))
-  (for-each (lambda (file)
-              (call-with-output-file (scope file)
-                (lambda (port)
-                  (display file port)   ;avoid hard-linking
-                  (chmod port #o666))))
-            '("dev/null"
-              "dev/zero"
-              "dev/full"
-              "dev/random"
-              "dev/urandom"))
-  ;; Don't create /dev/console, /dev/vcs, etc.: they are created by
-  ;; console-run on first boot.
-
-  (mkdir (scope "servers"))
-  (for-each (lambda (file)
-              (call-with-output-file (scope (string-append "servers/" file))
-                (lambda (port)
-                  (display file port)   ;avoid hard-linking
-                  (chmod port #o444))))
-            '("startup"
-              "exec"
-              "proc"
-              "password"
-              "default-pager"
-              "crash-dump-core"
-              "kill"
-              "suspend"))
-
-  (mkdir (scope "servers/socket"))
-  ;; Don't create /servers/socket/1 & co: runsystem does that on first boot.
-
-  ;; TODO: Set the 'gnu.translator' extended attribute for passive translator
-  ;; settings?
-  )
-
 (define %host-qemu-ipv4-address
   (inet-pton AF_INET "10.0.2.10"))
 
@@ -610,4 +564,4 @@ upon error."
               (start-repl)))))
     #:on-error on-error))
 
-;;; linux-initrd.scm ends here
+;;; linux-boot.scm ends here
diff --git a/gnu/local.mk b/gnu/local.mk
index 442e981830..b4d7ba5174 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -638,6 +638,7 @@ GNU_SYSTEM_MODULES =				\
   %D%/build/cross-toolchain.scm			\
   %D%/build/image.scm				\
   %D%/build/file-systems.scm			\
+  %D%/build/hurd-boot.scm			\
   %D%/build/install.scm				\
   %D%/build/linux-boot.scm			\
   %D%/build/linux-container.scm			\
diff --git a/gnu/packages/hurd.scm b/gnu/packages/hurd.scm
index b341683afe..d02bbe6013 100644
--- a/gnu/packages/hurd.scm
+++ b/gnu/packages/hurd.scm
@@ -31,6 +31,7 @@
   #:use-module (guix utils)
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system trivial)
+  #:use-module (gnu build hurd-boot)
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages compression)
   #:use-module (gnu packages flex)
@@ -312,107 +313,26 @@ Hurd-minimal package which are needed for both glibc and GCC.")
 (define (hurd-rc-script)
   "Return a script to be installed as /libexec/rc in the 'hurd' package.  The
 script takes care of installing the relevant passive translators on the first
-boot, since this cannot be done from GNU/Linux."
-  (define translators
-    '(("/servers/crash-dump-core" ("/hurd/crash" "--dump-core"))
-      ("/servers/crash-kill" ("/hurd/crash" "--kill"))
-      ("/servers/crash-suspend" ("/hurd/crash" "--suspend"))
-      ("/servers/password" ("/hurd/password"))
-      ("/servers/socket/1" ("/hurd/pflocal"))
-      ("/servers/socket/2" ("/hurd/pfinet" "--interface" "eth0"
-                            "--address" "10.0.2.15" ;the default QEMU guest IP
-                            "--netmask" "255.255.255.0"
-                            "--gateway" "10.0.2.2"
-                            "--ipv6" "/servers/socket/16"))))
+boot, since this cannot be done from GNU/Linux.  Then, it runs system
+activation; starting the Shepherd."
 
   (define rc
-    (with-imported-modules '((guix build utils))
+    (with-imported-modules '((guix build utils)
+                             (gnu build hurd-boot)
+                             (guix build syscalls))
       #~(begin
           (use-modules (guix build utils)
+                       (gnu build hurd-boot)
+                       (guix build syscalls)
                        (ice-9 match)
                        (system repl repl)
                        (srfi srfi-1)
                        (srfi srfi-26))
 
-          (display "Welcome, this is GNU's early boot Guile.\n")
-          (display "Use '--repl' for an initrd REPL.\n\n")
-
-          ;; "@HURD@" and "@COREUTILS@" are a placeholders.
+          ;; "@HURD@" and "@COREUTILS@" are placeholders.
           (setenv "PATH" "@HURD@/bin:@HURD@/sbin:@COREUTILS@/bin")
 
-          ;; XXX FIXME c&p from linux-boot.scm
-          (define (find-long-option option arguments)
-            "Find OPTION among ARGUMENTS, where OPTION is something like \"--load\".
-Return the value associated with OPTION, or #f on failure."
-            (let ((opt (string-append option "=")))
-              (and=> (find (cut string-prefix? opt <>)
-                           arguments)
-                     (lambda (arg)
-                       (substring arg (+ 1 (string-index arg #\=)))))))
-
-          (define (translated? node)
-            ;; Return true if a translator is installed on NODE.
-            (with-output-to-port (%make-void-port "w")
-              (lambda ()
-                (with-error-to-port (%make-void-port "w")
-                  (lambda ()
-                    (zero? (system* "showtrans" "-s" node)))))))
-
-          (for-each (match-lambda
-                      ((node command)
-                       (unless (translated? node)
-                         (mkdir-p (dirname node))
-                         (apply invoke "settrans" "-c" node command))))
-                    '#$translators)
-
-          (format #t "Creating essential device nodes...\n")
-          (with-directory-excursion "/dev"
-            (invoke "MAKEDEV" "--devdir=/dev" "std")
-            (invoke "MAKEDEV" "--devdir=/dev" "vcs")
-            (invoke "MAKEDEV" "--devdir=/dev" "tty1""tty2" "tty3" "tty4" "tty5" "tty6")
-            (invoke "MAKEDEV" "--devdir=/dev" "ptyp0" "ptyp1" "ptyp2")
-            (invoke "MAKEDEV" "--devdir=/dev" "console"))
-
-          (let* ((args    (command-line))
-                 (system  (find-long-option "--system" args))
-                 (to-load (find-long-option "--load" args)))
-
-            (false-if-exception (delete-file "/hurd"))
-            (let ((hurd/hurd (string-append system "/profile/hurd")))
-              (symlink hurd/hurd "/hurd"))
-
-            (format #t "Starting pager...\n")
-            (unless (zero? (system* "/hurd/mach-defpager"))
-              (format #t "FAILED...Good luck!\n"))
-
-            (cond ((member "--repl" args)
-                   (format #t "Starting repl...\n")
-                   (start-repl))
-                  (to-load
-                   (format #t "loading '~a'...\n" to-load)
-                   (primitive-load to-load)
-                   (format (current-error-port)
-                           "boot program '~a' terminated, rebooting~%"
-                           to-load)
-                   (let ((shepherd.conf
-                          (if (file-exists? "/etc/shepherd.conf")
-                              "/etc/shepherd.conf"
-                              (let ((files (find-files "/gnu/store" ".*-shepherd.conf")))
-                                (and (pair? files) (car files))))))
-                     (unless shepherd.conf
-                       (format #t "No shepherd.conf found, dropping to a shell...\n")
-                       (invoke "/run/current-system/profile/bin/bash")
-                       (reboot))
-                     (false-if-exception (delete-file "/var/run/shepherd/socket"))
-                     (format #t "Starting the Shepherd... ~a\n" shepherd.conf)
-                     (execl "/run/current-system/profile/bin/shepherd" "shepherd"
-                            "--config" shepherd.conf))
-                   (sleep 2)
-                   (reboot))
-                  (else
-                   (display "no boot file passed via '--load'\n")
-                   (display "entering a warm and cozy REPL\n")
-                   (start-repl)))))))
+          (boot-hurd-system))))
 
   ;; FIXME: We want the program to use the cross-compiled Guile when
   ;; cross-compiling.  But why do we need to be explicit here?
diff --git a/gnu/system/image.scm b/gnu/system/image.scm
index 15dac8af57..a0e6bf31f1 100644
--- a/gnu/system/image.scm
+++ b/gnu/system/image.scm
@@ -167,6 +167,7 @@
     (with-imported-modules `(,@(source-module-closure
                                 '((gnu build vm)
                                   (gnu build image)
+                                  (gnu build hurd-boot)
                                   (gnu build linux-boot)
                                   (guix store database))
                                 #:select? not-config?)
@@ -174,6 +175,7 @@
       #~(begin
           (use-modules (gnu build vm)
                        (gnu build image)
+                       (gnu build hurd-boot)
                        (gnu build linux-boot)
                        (guix store database)
                        (guix build utils))
diff --git a/gnu/system/vm.scm b/gnu/system/vm.scm
index 038cce19b6..686e56348d 100644
--- a/gnu/system/vm.scm
+++ b/gnu/system/vm.scm
@@ -344,9 +344,10 @@ system that is passed to 'populate-root-file-system'."
        #~(begin
            (use-modules (gnu build bootloader)
                         (gnu build vm)
+                        ((gnu build hurd-boot)
+                         #:select (make-hurd-device-nodes))
                         ((gnu build linux-boot)
-                         #:select (make-essential-device-nodes
-                                   make-hurd-device-nodes))
+                         #:select (make-essential-device-nodes))
                         (guix store database)
                         (guix build utils)
                         (srfi srfi-26)