;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016 Christopher Allan Webber <cwebber@dustycloud.org>
;;; Copyright © 2016, 2017 Leo Famulari <leo@famulari.name>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
#:use-module (ice-9 popen)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
+ #:use-module (srfi srfi-19)
#:use-module (srfi srfi-26)
#:export (qemu-command
load-in-linux-vm
(let ((cpu (substring system 0
(string-index system #\-))))
(string-append "qemu-system-"
- (if (string-match "^i[3456]86$" cpu)
- "i386"
- cpu))))
+ (cond
+ ((string-match "^i[3456]86$" cpu) "i386")
+ ((string-match "armhf" cpu) "arm")
+ (else cpu)))))
(define* (load-in-linux-vm builder
#:key
make-disk-image?
single-file-output?
target-arm32?
+ target-aarch64?
(disk-image-size (* 100 (expt 2 20)))
(disk-image-format "qcow2")
(references-graphs '()))
REFERENCES-GRAPHS can specify a list of reference-graph files as produced by
the #:references-graphs parameter of 'derivation'."
+ (define target-arm? (or target-arm32? target-aarch64?))
+
(define arch-specific-flags
`(;; On ARM, a machine has to be specified. Use "virt" machine to avoid
;; hardware limits imposed by other machines.
- ,@(if target-arm32? '("-M" "virt") '())
+ ,@(if target-arm?
+ '("-M" "virt")
+ '())
+
+ ;; On ARM32, if the kernel is built without LPAE support, ECAM conflicts
+ ;; with VIRT_PCIE_MMIO causing PCI devices not to show up. Disable
+ ;; explicitely highmem to fix it.
+ ;; See: https://bugs.launchpad.net/qemu/+bug/1790975.
+ ,@(if target-arm32?
+ '("-machine" "highmem=off")
+ '())
;; Only enable kvm if we see /dev/kvm exists. This allows users without
;; hardware virtualization to still use these commands. KVM support is
- ;; still buggy on some ARM32 boards. Do not use it even if available.
+ ;; still buggy on some ARM boards. Do not use it even if available.
,@(if (and (file-exists? "/dev/kvm")
- (not target-arm32?)
-
- ;; XXX: 32-bit 'qemu-system-i386 -enable-kvm' segfaults on
- ;; x86_64 hosts running Linux-libre 4.17:
- ;; <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31380#18> and
- ;; <https://lists.gnu.org/archive/html/qemu-devel/2018-07/msg01166.html>.
- (not (string-suffix? "-i386" qemu)))
+ (not target-arm?))
'("-enable-kvm")
'())
;; The serial port name differs between emulated
;; architectures/machines.
" console="
- (if target-arm32? "ttyAMA0" "ttyS0"))
-
- ;; NIC is not supported on ARM "virt" machine, so use a user mode
- ;; network stack instead.
- ,@(if target-arm32?
- '("-device" "virtio-net-pci,netdev=mynet"
- "-netdev" "user,id=mynet")
- '("-net" "nic,model=virtio"))))
+ (if target-arm? "ttyAMA0" "ttyS0"))))
(when make-disk-image?
(format #t "creating ~a image of ~,2f MiB...~%"
(_ #f))
(apply invoke qemu "-nographic" "-no-reboot"
+ ;; CPU "max" behaves as "host" when KVM is enabled, and like a system
+ ;; CPU with the maximum possible feature set otherwise.
+ "-cpu" "max"
"-m" (number->string memory-size)
+ "-nic" "user,model=virtio-net-pci"
"-object" "rng-random,filename=/dev/urandom,id=guixsd-vm-rng"
"-device" "virtio-rng-pci,rng=guixsd-vm-rng"
"-virtfs"
;; Graft the configuration file onto the image.
(string-append "boot/grub/grub.cfg=" config-file))))
-(define* (make-iso9660-image grub config-file os-drv target
- #:key (volume-id "GuixSD_image") (volume-uuid #f)
+(define* (make-iso9660-image xorriso grub-mkrescue-environment
+ grub config-file os-drv target
+ #:key (volume-id "Guix_image") (volume-uuid #f)
register-closures? (closures '()))
"Given a GRUB package, creates an iso image as TARGET, using CONFIG-FILE as
GRUB configuration and OS-DRV as the stuff in it."
(define grub-mkrescue
(string-append grub "/bin/grub-mkrescue"))
+ (define grub-mkrescue-sed.sh
+ (string-append xorriso "/bin/grub-mkrescue-sed.sh"))
+
(define target-store
(string-append "/tmp/root" (%store-directory)))
closures)
(register-bootcfg-root "/tmp/root" config-file))
+ ;; 'grub-mkrescue' calls out to mtools programs to create 'efi.img', a FAT
+ ;; file system image, and mtools honors SOURCE_DATE_EPOCH for the mtime of
+ ;; those files. The epoch for FAT is Jan. 1st 1980, not 1970, so choose
+ ;; that.
+ (setenv "SOURCE_DATE_EPOCH"
+ (number->string
+ (time-second
+ (date->time-utc (make-date 0 0 0 0 1 1 1980 0)))))
+
+ ;; Our patched 'grub-mkrescue' honors this environment variable and passes
+ ;; it to 'mformat', which makes it the serial number of 'efi.img'. This
+ ;; allows for deterministic builds.
+ (setenv "GRUB_FAT_SERIAL_NUMBER"
+ (number->string (if volume-uuid
+
+ ;; On 32-bit systems the 2nd argument must be
+ ;; lower than 2^32.
+ (string-hash (iso9660-uuid->string volume-uuid)
+ (- (expt 2 32) 1))
+
+ #x77777777)
+ 16))
+
+ (setenv "MKRESCUE_SED_MODE" "original")
+ (setenv "MKRESCUE_SED_XORRISO" (string-append xorriso
+ "/bin/xorriso"))
+ (setenv "MKRESCUE_SED_IN_EFI_NO_PT" "yes")
+ (for-each (match-lambda
+ ((name . value) (setenv name value)))
+ grub-mkrescue-environment)
+
(let ((pipe
(apply open-pipe* OPEN_WRITE
- grub-mkrescue "-o" target
+ grub-mkrescue
+ (string-append "--xorriso=" grub-mkrescue-sed.sh)
+ "-o" target
(string-append "boot/grub/grub.cfg=" config-file)
"etc=/tmp/root/etc"
"var=/tmp/root/var"
"-path-list" "-"
"--"
- ;; XXX: Add padding to avoid I/O errors on i686:
- ;; <https://bugs.gnu.org/33639>.
- "-padding" "10m"
+ ;; Set all timestamps to 1.
+ "-volume_date" "all_file_dates" "=1"
"-volid" (string-upcase volume-id)
(if volume-uuid
(lambda (port)
(format port
"insmod part_msdos~@
- search --set=root --label GuixSD_image~@
+ search --set=root --label Guix_image~@
configfile /boot/grub/grub.cfg~%")))
(display "creating EFI firmware image...")