From 9121ce553d267e9fdd4c6b9a268ce9d8677dd234 Mon Sep 17 00:00:00 2001 From: Mathieu Othacehe Date: Tue, 9 May 2017 10:52:02 +0200 Subject: bootloader: Adapt vm to new bootloader API. * gnu/build/install.scm (install-boot-config): New procedure. (install-grub): Move to (gnu bootloader grub). * gnu/build/vm.scm (register-bootcfg-root): Rename register-grub.cfg-root and adjust accordingly. (initialize-hard-disk): Takes a bootloader-package, bootcfg, bootcfg-location and bootloader-installer procedure. Adjust accordingly. * gnu/system/vm.scm (qemu-image): Adjust to initialize-hard-disk. (system-disk-image, system-qemu-image, system-qemu-image/shared-store): Adjust to qemu-image. --- gnu/build/vm.scm | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'gnu/build/vm.scm') diff --git a/gnu/build/vm.scm b/gnu/build/vm.scm index 1eb9a4c45e..9a77bee72d 100644 --- a/gnu/build/vm.scm +++ b/gnu/build/vm.scm @@ -285,15 +285,18 @@ (define target-store (unless register-closures? (reset-timestamps target)))) -(define (register-grub.cfg-root target bootcfg) +(define (register-bootcfg-root target bootcfg) "On file system TARGET, register BOOTCFG as a GC root." (let ((directory (string-append target "/var/guix/gcroots"))) (mkdir-p directory) - (symlink bootcfg (string-append directory "/grub.cfg")))) + (symlink bootcfg (string-append directory "/bootcfg")))) (define* (initialize-hard-disk device #:key - grub.cfg + bootloader-package + bootcfg + bootcfg-location + bootloader-installer (partitions '())) "Initialize DEVICE as a disk containing all the objects listed in PARTITIONS, and using BOOTCFG as its bootloader configuration file. @@ -311,10 +314,12 @@ (define* (initialize-hard-disk device (display "mounting root partition...\n") (mkdir-p target) (mount (partition-device root) target (partition-file-system root)) - (install-grub grub.cfg device target) + (install-boot-config bootcfg bootcfg-location target) + (when bootloader-installer + (bootloader-installer bootloader-package device target)) - ;; Register GRUB.CFG as a GC root. - (register-grub.cfg-root target grub.cfg) + ;; Register BOOTCFG as a GC root. + (register-bootcfg-root target bootcfg) (umount target))) -- cgit v1.2.3 From 01cc84dadee4571e5793658e912ee05d60fbf060 Mon Sep 17 00:00:00 2001 From: Marius Bakke Date: Tue, 11 Apr 2017 10:47:38 +0200 Subject: vm: Support arbitrary partition flags. * gnu/build/vm.scm (): Change BOOTABLE? to FLAGS. (initialize-partition-table): Pass each flag to parted. (initialize-hard-disk): Locate boot partition. * gnu/system/vm.scm (qemu-image): Adjust partition flags. --- gnu/build/vm.scm | 17 ++++++++++++----- gnu/system/vm.scm | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'gnu/build/vm.scm') diff --git a/gnu/build/vm.scm b/gnu/build/vm.scm index 9a77bee72d..c7449cfbef 100644 --- a/gnu/build/vm.scm +++ b/gnu/build/vm.scm @@ -3,6 +3,7 @@ ;;; Copyright © 2016 Christopher Allan Webber ;;; Copyright © 2016 Leo Famulari ;;; Copyright © 2017 Mathieu Othacehe +;;; Copyright © 2017 Marius Bakke ;;; ;;; This file is part of GNU Guix. ;;; @@ -41,7 +42,7 @@ (define-module (gnu build vm) partition-size partition-file-system partition-label - partition-bootable? + partition-flags partition-initializer root-partition-initializer @@ -141,7 +142,7 @@ (define-record-type* partition make-partition (size partition-size) (file-system partition-file-system (default "ext4")) (label partition-label (default #f)) - (bootable? partition-bootable? (default #f)) + (flags partition-flags (default '())) (initializer partition-initializer (default (const #t)))) (define (fold2 proc seed1 seed2 lst) ;TODO: factorize @@ -168,9 +169,10 @@ (define (partition-options part offset index) (cons* "mkpart" "primary" "ext2" (format #f "~aB" offset) (format #f "~aB" (+ offset (partition-size part))) - (if (partition-bootable? part) - `("set" ,(number->string index) "boot" "on") - '()))) + (append-map (lambda (flag) + (list "set" (number->string index) + (symbol->string flag) "on")) + (partition-flags part)))) (define (options partitions offset) (let loop ((partitions partitions) @@ -303,6 +305,11 @@ (define* (initialize-hard-disk device Each partition is initialized by calling its 'initializer' procedure, passing it a directory name where it is mounted." + + (define (partition-bootable? partition) + "Return the first partition found with the boot flag set." + (member 'boot (partition-flags partition))) + (let* ((partitions (initialize-partition-table device partitions)) (root (find partition-bootable? partitions)) (target "/fs")) diff --git a/gnu/system/vm.scm b/gnu/system/vm.scm index 2ee5c2b1e7..e0e4d33d45 100644 --- a/gnu/system/vm.scm +++ b/gnu/system/vm.scm @@ -231,7 +231,7 @@ (define* (qemu-image #:key (* 10 (expt 2 20)))) (label #$file-system-label) (file-system #$file-system-type) - (bootable? #t) + (flags '(boot)) (initializer initialize))))) (initialize-hard-disk "/dev/vda" #:partitions partitions -- cgit v1.2.3 From 4d415f0c3c0cf4acbc1297ccf2b27121846a4289 Mon Sep 17 00:00:00 2001 From: Marius Bakke Date: Sat, 6 May 2017 22:53:58 +0200 Subject: vm: Support creating FAT partitions. * gnu/build/vm.scm (create-ext-file-system, create-fat-file-system): New procedures. (format-partition): Use them. Error for unknown file systems. * gnu/system/vm.scm (qemu-image): Include DOSFSTOOLS. * gnu/system/linux-initrd.scm (base-initrd): Always add nls_is8859-1.ko. --- gnu/build/vm.scm | 30 ++++++++++++++++++++++++++---- gnu/system/linux-initrd.scm | 4 +--- gnu/system/vm.scm | 2 +- 3 files changed, 28 insertions(+), 8 deletions(-) (limited to 'gnu/build/vm.scm') diff --git a/gnu/build/vm.scm b/gnu/build/vm.scm index c7449cfbef..7ce1ec8e1e 100644 --- a/gnu/build/vm.scm +++ b/gnu/build/vm.scm @@ -213,10 +213,10 @@ (define (options partitions offset) (define MS_BIND 4096) ; again! -(define* (format-partition partition type - #:key label) - "Create a file system TYPE on PARTITION. If LABEL is true, use that as the -volume name." +(define* (create-ext-file-system partition type + #:key label) + "Create an ext-family filesystem of TYPE on PARTITION. If LABEL is true, +use that as the volume name." (format #t "creating ~a partition...\n" type) (unless (zero? (apply system* (string-append "mkfs." type) "-F" partition @@ -225,6 +225,28 @@ (define* (format-partition partition type '()))) (error "failed to create partition"))) +(define* (create-fat-file-system partition + #:key label) + "Create a FAT filesystem on PARTITION. The number of File Allocation Tables +will be determined based on filesystem size. If LABEL is true, use that as the +volume name." + (format #t "creating FAT partition...\n") + (unless (zero? (apply system* "mkfs.fat" partition + (if label + `("-n" ,label) + '()))) + (error "failed to create FAT partition"))) + +(define* (format-partition partition type + #:key label) + "Create a file system TYPE on PARTITION. If LABEL is true, use that as the +volume name." + (cond ((string-prefix? "ext" type) + (create-ext-file-system partition type #:label label)) + ((or (string-prefix? "fat" type) (string= "vfat" type)) + (create-fat-file-system partition #:label label)) + (else (error "Unsupported file system.")))) + (define (initialize-partition partition) "Format PARTITION, a object with a non-#f 'device' field, mount it, run its initializer, and unmount it." diff --git a/gnu/system/linux-initrd.scm b/gnu/system/linux-initrd.scm index dfe198e43e..3a5e76034a 100644 --- a/gnu/system/linux-initrd.scm +++ b/gnu/system/linux-initrd.scm @@ -268,6 +268,7 @@ (define linux-modules "usbhid" "hid-generic" "hid-apple" ;keyboards during early boot "dm-crypt" "xts" "serpent_generic" "wp512" ;for encrypted root partitions "nvme" ;for new SSD NVMe devices + "nls_iso8859-1" ;for `mkfs.fat`, et.al ,@(if (string-match "^(x86_64|i[3-6]86)-" (%current-system)) '("pata_acpi" "pata_atiixp" ;for ATA controllers "isci") ;for SAS controllers like Intel C602 @@ -281,9 +282,6 @@ (define linux-modules ,@(if (find (file-system-type-predicate "9p") file-systems) virtio-9p-modules '()) - ,@(if (find (file-system-type-predicate "vfat") file-systems) - '("nls_iso8859-1") - '()) ,@(if (find (file-system-type-predicate "btrfs") file-systems) '("btrfs") '()) diff --git a/gnu/system/vm.scm b/gnu/system/vm.scm index e0e4d33d45..64770baf1c 100644 --- a/gnu/system/vm.scm +++ b/gnu/system/vm.scm @@ -203,7 +203,7 @@ (define* (qemu-image #:key (guix build utils)) (let ((inputs - '#$(append (list qemu parted e2fsprogs) + '#$(append (list qemu parted e2fsprogs dosfstools) (map canonical-package (list sed grep coreutils findutils gawk)) (if register-closures? (list guix) '()))) -- cgit v1.2.3 From ecf5d5376979fadd971559367bf553df89fcc62b Mon Sep 17 00:00:00 2001 From: Marius Bakke Date: Sun, 7 May 2017 15:31:30 +0200 Subject: vm: Add UEFI loader to disk images. * gnu/build/vm.scm (install-efi): New procedure. (initialize-hard-disk): Generate EFI blob when ESP is present. * gnu/system/vm.scm (qemu-image): Append 40MiB EFI System Partition. --- gnu/build/vm.scm | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ gnu/system/vm.scm | 18 ++++++++++++++-- 2 files changed, 77 insertions(+), 2 deletions(-) (limited to 'gnu/build/vm.scm') diff --git a/gnu/build/vm.scm b/gnu/build/vm.scm index 7ce1ec8e1e..57619764ce 100644 --- a/gnu/build/vm.scm +++ b/gnu/build/vm.scm @@ -27,6 +27,7 @@ (define-module (gnu build vm) #:use-module (gnu build linux-boot) #:use-module (gnu build install) #:use-module (guix records) + #:use-module (ice-9 format) #:use-module (ice-9 match) #:use-module (ice-9 regex) #:use-module (srfi srfi-1) @@ -315,12 +316,41 @@ (define (register-bootcfg-root target bootcfg) (mkdir-p directory) (symlink bootcfg (string-append directory "/bootcfg")))) +(define (install-efi grub esp config-file) + "Write a self-contained GRUB EFI loader to the mounted ESP using CONFIG-FILE." + (let* ((system %host-type) + ;; Hard code the output location to a well-known path recognized by + ;; compliant firmware. See "3.5.1.1 Removable Media Boot Behaviour": + ;; http://www.uefi.org/sites/default/files/resources/UEFI%20Spec%202_6.pdf + (grub-mkstandalone (string-append grub "/bin/grub-mkstandalone")) + (efi-directory (string-append esp "/EFI/BOOT")) + ;; Map grub target names to boot file names. + (efi-targets (cond ((string-prefix? "x86_64" system) + '("x86_64-efi" . "BOOTX64.EFI")) + ((string-prefix? "i686" system) + '("i386-efi" . "BOOTIA32.EFI")) + ((string-prefix? "armhf" system) + '("arm-efi" . "BOOTARM.EFI")) + ((string-prefix? "aarch64" system) + '("arm64-efi" . "BOOTAA64.EFI"))))) + ;; grub-mkstandalone requires a TMPDIR to prepare the firmware image. + (setenv "TMPDIR" esp) + + (mkdir-p efi-directory) + (unless (zero? (system* grub-mkstandalone "-O" (car efi-targets) + "-o" (string-append efi-directory "/" + (cdr efi-targets)) + ;; Graft the configuration file onto the image. + (string-append "boot/grub/grub.cfg=" config-file))) + (error "failed to create GRUB EFI image")))) + (define* (initialize-hard-disk device #:key bootloader-package bootcfg bootcfg-location bootloader-installer + (grub-efi #f) (partitions '())) "Initialize DEVICE as a disk containing all the objects listed in PARTITIONS, and using BOOTCFG as its bootloader configuration file. @@ -332,8 +362,13 @@ (define (partition-bootable? partition) "Return the first partition found with the boot flag set." (member 'boot (partition-flags partition))) + (define (partition-esp? partition) + "Return the first EFI System Partition." + (member 'esp (partition-flags partition))) + (let* ((partitions (initialize-partition-table device partitions)) (root (find partition-bootable? partitions)) + (esp (find partition-esp? partitions)) (target "/fs")) (unless root (error "no bootable partition specified" partitions)) @@ -345,8 +380,34 @@ (define (partition-bootable? partition) (mount (partition-device root) target (partition-file-system root)) (install-boot-config bootcfg bootcfg-location target) (when bootloader-installer + (display "installing bootloader...\n") (bootloader-installer bootloader-package device target)) + (when esp + ;; Mount the ESP somewhere and install GRUB UEFI image. + (let ((mount-point (string-append target "/boot/efi")) + (grub-config (string-append target "/tmp/grub-standalone.cfg"))) + (display "mounting EFI system partition...\n") + (mkdir-p mount-point) + (mount (partition-device esp) mount-point + (partition-file-system esp)) + + ;; Create a tiny configuration file telling the embedded grub + ;; where to load the real thing. + (call-with-output-file grub-config + (lambda (port) + (format port + "insmod part_msdos~@ + search --set=root --label gnu-disk-image~@ + configfile /boot/grub/grub.cfg~%"))) + + (display "creating EFI firmware image...") + (install-efi grub-efi mount-point grub-config) + (display "done.\n") + + (delete-file grub-config) + (umount mount-point))) + ;; Register BOOTCFG as a GC root. (register-bootcfg-root target bootcfg) diff --git a/gnu/system/vm.scm b/gnu/system/vm.scm index 64770baf1c..d282ba557a 100644 --- a/gnu/system/vm.scm +++ b/gnu/system/vm.scm @@ -3,6 +3,7 @@ ;;; Copyright © 2016 Christopher Allan Webber ;;; Copyright © 2016 Leo Famulari ;;; Copyright © 2017 Mathieu Othacehe +;;; Copyright © 2017 Marius Bakke ;;; ;;; This file is part of GNU Guix. ;;; @@ -228,13 +229,26 @@ (define* (qemu-image #:key #:system-directory #$os-drv)) (partitions (list (partition (size #$(- disk-image-size - (* 10 (expt 2 20)))) + (* 50 (expt 2 20)))) (label #$file-system-label) (file-system #$file-system-type) (flags '(boot)) - (initializer initialize))))) + (initializer initialize)) + ;; Append a small EFI System Partition for + ;; use with UEFI bootloaders. + (partition + ;; The standalone grub image is about 10MiB, but + ;; leave some room for custom or multiple images. + (size (* 40 (expt 2 20))) + (label "GNU-ESP") ;cosmetic only + ;; Use "vfat" here since this property is used + ;; when mounting. The actual FAT-ness is based + ;; on filesystem size (16 in this case). + (file-system "vfat") + (flags '(esp)))))) (initialize-hard-disk "/dev/vda" #:partitions partitions + #:grub-efi #$grub-efi #:bootloader-package #$(bootloader-package bootloader) #:bootcfg #$bootcfg-drv -- cgit v1.2.3