summary refs log tree commit diff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2013-09-05 00:45:53 +0200
committerLudovic Courtès <ludo@gnu.org>2013-09-05 00:46:09 +0200
commit1b89a66e1badbb8a597db0529e468f9950119a30 (patch)
tree1a008bbba2d37aaf005c0298ee1ce136f329b8a2
parent29804e6eb2a755c123f2a73fb843867846cb9111 (diff)
downloadguix-1b89a66e1badbb8a597db0529e468f9950119a30.tar.gz
gnu: vm: First stab at building a populated QEMU image.
* gnu/packages/linux-initrd.scm (gnu-system-initrd): New variable.
* gnu/system/vm.scm (qemu-image): Add #:linux-arguments parameter.
  [input->name+derivation]: Add case for 'store-path?' items.
  Remove LOADER from `inputs'.
-rw-r--r--gnu/packages/linux-initrd.scm66
-rw-r--r--gnu/system/vm.scm61
2 files changed, 104 insertions, 23 deletions
diff --git a/gnu/packages/linux-initrd.scm b/gnu/packages/linux-initrd.scm
index ab8787f02c..6dd2a10e53 100644
--- a/gnu/packages/linux-initrd.scm
+++ b/gnu/packages/linux-initrd.scm
@@ -332,4 +332,70 @@ the Linux kernel.")
    #:linux linux-libre
    #:linux-modules '("cifs.ko" "md4.ko" "ecb.ko")))
 
+(define-public gnu-system-initrd
+  ;; Initrd for the GNU system itself, with nothing QEMU-specific.
+  (expression->initrd
+   '(begin
+      (use-modules (srfi srfi-1)
+                   (srfi srfi-26)
+                   (ice-9 match)
+                   (guix build utils)
+                   (guix build linux-initrd))
+
+      (display "Welcome, this is GNU's early boot Guile.\n")
+      (display "Use '--repl' for an initrd REPL.\n\n")
+
+      (mount-essential-file-systems)
+      (let* ((args    (linux-command-line))
+             (option  (lambda (opt)
+                        (let ((opt (string-append opt "=")))
+                          (and=> (find (cut string-prefix? opt <>)
+                                       args)
+                                 (lambda (arg)
+                                   (substring arg (+ 1 (string-index arg #\=))))))))
+             (to-load (option "--load"))
+             (root    (option "--root")))
+
+        (when (member "--repl" args)
+          ((@ (system repl repl) start-repl)))
+
+        ;; Make /dev nodes.
+        (make-essential-device-nodes)
+
+        ;; Prepare the real root file system under /root.
+        (unless (file-exists? "/root")
+          (mkdir "/root"))
+        (if root
+            ;; Assume ROOT has a usable /dev tree.
+            (mount root "/root" "ext3")
+            (begin
+              (mount "none" "/root" "tmpfs")
+              (make-essential-device-nodes #:root "/root")))
+
+        (mount-essential-file-systems #:root "/root")
+
+        ;; XXX: We don't copy our fellow Guile modules to /root (see
+        ;; 'qemu-initrd'), so if TO-LOAD tries to load a module (which can
+        ;; happen if it throws, to display the exception!), then we're
+        ;; screwed.  Hopefully TO-LOAD is a simple expression that just does
+        ;; '(execlp ...)'.
+
+        (if to-load
+            (begin
+              (format #t "loading '~a'...\n" to-load)
+              (chroot "/root")
+              (primitive-load to-load)
+              (format (current-error-port)
+                      "boot program '~a' terminated, rebooting~%")
+              (sleep 2)
+              (reboot))
+            (begin
+              (display "no init file passed via '--exec'\n")
+              (display "entering a warm and cozy REPL\n")
+              ((@ (system repl repl) start-repl))))))
+   #:name "qemu-system-initrd"
+   #:modules '((guix build linux-initrd)
+               (guix build utils))
+   #:linux linux-libre))
+
 ;;; linux-initrd.scm ends here
diff --git a/gnu/system/vm.scm b/gnu/system/vm.scm
index 596a697738..86430ea168 100644
--- a/gnu/system/vm.scm
+++ b/gnu/system/vm.scm
@@ -21,7 +21,11 @@
   #:use-module (guix store)
   #:use-module (guix derivations)
   #:use-module (guix packages)
-  #:use-module ((gnu packages base) #:select (%final-inputs guile-final))
+  #:use-module ((gnu packages base) #:select (%final-inputs
+                                              guile-final
+                                              coreutils))
+  #:use-module (gnu packages guile)
+  #:use-module (gnu packages bash)
   #:use-module (gnu packages qemu)
   #:use-module (gnu packages parted)
   #:use-module (gnu packages grub)
@@ -30,7 +34,7 @@
   #:use-module ((gnu packages make-bootstrap)
                 #:select (%guile-static-stripped))
   #:use-module ((gnu packages system)
-                #:select (shadow))
+                #:select (mingetty))
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-26)
   #:use-module (ice-9 match)
@@ -177,11 +181,14 @@ made available under the /xchg CIFS share."
                      (system (%current-system))
                      (disk-image-size (* 100 (expt 2 20)))
                      (linux linux-libre)
+                     (linux-arguments '())
                      (initrd qemu-initrd)
                      (inputs '())
                      (inputs-to-copy '())
                      (boot-expression #f))
-  "Return a bootable, stand-alone QEMU image.
+  "Return a bootable, stand-alone QEMU image.  The returned image is a full
+disk image, with a GRUB installation whose default entry boots LINUX, with the
+arguments LINUX-ARGUMENTS, and using INITRD as its initial RAM disk.
 
 INPUTS-TO-COPY is a list of inputs (as for packages) whose closure is copied
 into the image being built.
@@ -197,13 +204,9 @@ process."
      ((name (? package? package) sub-drv)
       `(,name . ,(derivation-path->output-path
                   (package-derivation store package system)
-                  sub-drv)))))
-
-  (define loader
-    (and boot-expression
-         (add-text-to-store store "loader"
-                            (object->string boot-expression)
-                            '())))
+                  sub-drv)))
+     ((input (and (? string?) (? store-path?) file))
+      `(,input . ,file))))
 
   (expression->derivation-in-linux-vm
    store "qemu-image"
@@ -299,12 +302,10 @@ set timeout=5
 search.file /boot/bzImage
 
 menuentry \"Boot-to-Guile! (GNU System technology preview)\" {
-  linux /boot/bzImage --root=/dev/vda1 ~a
+  linux /boot/bzImage ~a
   initrd /boot/initrd
 }"
-                                  ,(if loader
-                                       (string-append "--load=" loader)
-                                       ""))))
+                                  ,(string-join linux-arguments))))
                       (and (zero?
                             (system* grub "--no-floppy"
                                      "--boot-directory" "/fs/boot"
@@ -319,10 +320,6 @@ menuentry \"Boot-to-Guile! (GNU System technology preview)\" {
               ("linux" ,linux-libre)
               ("initrd" ,initrd)
 
-              ,@(if loader
-                    `(("loader" ,loader))
-                    '())
-
               ;; For shell scripts.
               ("sed" ,(car (assoc-ref %final-inputs "sed")))
               ("grep" ,(car (assoc-ref %final-inputs "grep")))
@@ -367,13 +364,31 @@ menuentry \"Boot-to-Guile! (GNU System technology preview)\" {
         (set! store (open-connection)))
       (lambda ()
         (parameterize ((%guile-for-build (package-derivation store guile-final)))
-          (let* ((drv   (package-derivation store shadow))
-                 (login (string-append (derivation-path->output-path drv)
-                                       "/bin/login")))
+          (let* ((out   (derivation-path->output-path
+                         (package-derivation store mingetty)))
+                 (getty (string-append out "/sbin/mingetty"))
+                 (boot  (add-text-to-store store "boot"
+                                           (object->string
+                                            `(begin
+                                               ;; Become the session leader,
+                                               ;; so that mingetty can do
+                                               ;; 'TIOCSCTTY'.
+                                               (setsid)
+
+                                               ;; Directly into mingetty.
+                                               (execl ,getty "mingetty"
+                                                      "--noclear" "tty1")))
+                                           (list out))))
            (qemu-image store
-                       #:boot-expression `(execl ,login "login" "tty1")
+                       #:initrd gnu-system-initrd
+                       #:linux-arguments `("--root=/dev/vda1"
+                                           ,(string-append "--load=" boot))
                        #:disk-image-size (* 400 (expt 2 20))
-                       #:inputs-to-copy `(("shadow" ,shadow))))))
+                       #:inputs-to-copy `(("boot" ,boot)
+                                          ("coreutils" ,coreutils)
+                                          ("bash" ,bash)
+                                          ("guile" ,guile-2.0)
+                                          ("mingetty" ,mingetty))))))
       (lambda ()
         (close-connection store)))))