Patchwork [01/10] * gnu/system.scm (<boot-parameters>): Add 'store-device' and 'store-fs-mount-point'.

login
register
mail settings
Submitter Ludovic Courtès
Date Oct. 30, 2016, 12:12 a.m.
Message ID <87h97uu23b.fsf@gnu.org>
Download mbox | patch
Permalink /patch/17015/
State New
Headers show

Comments

Ludovic Courtès - Oct. 30, 2016, 12:12 a.m.
Hello,

I’ve browsed the whole patch series, and I think we’re pretty much
there.  I do have comments though, as always ;-), but I’m confident that
we’re doing the last round trip here.

If you’d like me to apply some of the the benign changes I suggest on
your behalf, let me know; I thought I’d rather get your opinion first,
and of course it’s always better for me if you do it yourself.  ;-)

cmmarusich@gmail.com skribis:

> From: Chris Marusich <cmmarusich@gmail.com>
>
> In a future commit, we will restructure the grub.cfg generation logic to use
> this information, to enable the implementation of 'guix system
> switch-generation' and 'guix system roll-back'.

General remark on commit logs: I can fix details there, but it would
help me if you could more closely follow conventions.

For instance, each commit needs a subject line prefixed by the area it
touches.  So this one would be “system: Add 'store-device' field to
<boot-parameters>.”

The commit log needs to list all the changes made.  In this case, it
should mention not only <boot-parameters> but also
‘operating-system-parameters-file’.  As a reviewer it helps to see which
parts are touched.

A simple way to get the conventions right is to run ‘git log’ on the
file and mimic what was previously done.

>  (define-record-type* <boot-parameters>
>    boot-parameters make-boot-parameters boot-parameters?
>    (label            boot-parameters-label)
> +  ;; Because we will use the 'store-device' to create the GRUB search command,
> +  ;; the 'store-device' has slightly different semantics than 'root-device'.
> +  ;; The 'store-device' can be a file system uuid, a file system label, or #f,
> +  ;; but it cannot be a device path such as "/dev/sda3", since GRUB would not
> +  ;; understand that.  The 'root-device', on the other hand, corresponds
> +  ;; exactly to the device field of the <file-system> object representing the
> +  ;; OS's root file system, so it might be a device path like "/dev/sda3".
>    (root-device      boot-parameters-root-device)
> +  (store-device     boot-parameters-store-device)
> +  (store-fs-mount-point boot-parameters-store-fs-mount-point)

In your patch series ‘store-fs-mount-point’ ends up being unused.

However, after rereading the whole series, I think what we need is a
‘device-mount-point’ in <menu-entry>, in a symmetrical fashion.

Attached is an updated patch.  I have grouped together the patches of
your series that touch this topic, including the documentation part
(this is all one logical change so it’s best to commit it as such), and
made the above change.

I’ve also followed my suggestion at
<https://lists.gnu.org/archive/html/guix-devel/2016-10/msg00568.html> to
not change the version of the <boot-parameters> sexp.

I’ve tested that the generated grub.cfg is what we expect in several
different scenario.

If that’s fine with you, I’d like to commit this version.  With that
done, the rest of the patch series will be rather easy.

WDYT?

Thank you!

Ludo’.
Chris Marusich - Oct. 30, 2016, 9:41 a.m.
ludo@gnu.org (Ludovic Courtès) writes:

> General remark on commit logs: I can fix details there, but it would
> help me if you could more closely follow conventions.

Understood.  I read the manual ((standards) Change Logs) and tried to
make it look like existing commits, but I see I missed some stuff, so
I'll do better next time.  Thank you for pointing out the spots that
need improvement.

>>  (define-record-type* <boot-parameters>
>>    boot-parameters make-boot-parameters boot-parameters?
>>    (label            boot-parameters-label)
>> +  ;; Because we will use the 'store-device' to create the GRUB search command,
>> +  ;; the 'store-device' has slightly different semantics than 'root-device'.
>> +  ;; The 'store-device' can be a file system uuid, a file system label, or #f,
>> +  ;; but it cannot be a device path such as "/dev/sda3", since GRUB would not
>> +  ;; understand that.  The 'root-device', on the other hand, corresponds
>> +  ;; exactly to the device field of the <file-system> object representing the
>> +  ;; OS's root file system, so it might be a device path like "/dev/sda3".
>>    (root-device      boot-parameters-root-device)
>> +  (store-device     boot-parameters-store-device)
>> +  (store-fs-mount-point boot-parameters-store-fs-mount-point)
>
> In your patch series ‘store-fs-mount-point’ ends up being unused.

Is this true?  I think we're using it.  For example, in commit
18813be0053b4797071e20f373a8a9e8d669e32a (Implement switch-generation
and roll-back), in procedure 'reinstall-grub', don't we use it to get
the mount point for each <boot-parameters>?

> However, after rereading the whole series, I think what we need is a
> ‘device-mount-point’ in <menu-entry>, in a symmetrical fashion.

That would work, and I'm open to it.  However, before we decide to do
that, what do you think about the alternative in which we simply require
that all the paths in the <boot-parameters> and <menu-entry> objects
must be relative paths?  By relative, I mean relative to the GRUB root.
If all the paths were relative, then we would not need a
'device-mount-point' field in the first place.

However, I suspect it might be tricky to get all the information we need
if we do it that way.  For example, during switch-generation, how would
we know the correct paths to use for the files in the GRUB
configuration's 'eye-candy' section?  In light of that, I suspect it
would be better to do what you've suggested: include the mount point in
both <boot-parameters> and <menu-entry>.

> Attached is an updated patch.  I have grouped together the patches of
> your series that touch this topic, including the documentation part
> (this is all one logical change so it’s best to commit it as such), and
> made the above change.

Thank you for doing this.  I've looked it over.  It looks good to me.
Unless you think strongly that we should use relative paths in the
<boot-parameters> and <menu-entry> objects, I think it's good as-is!

> I’ve also followed my suggestion at
> <https://lists.gnu.org/archive/html/guix-devel/2016-10/msg00568.html> to
> not change the version of the <boot-parameters> sexp.

OK.  FYI, I bumped the version number in my patch series because I
thought it would simplify the matching logic (it was still backwards
compatible).  However, looking at your version, I see now that it wasn't
too hard to keep the version number the same.  Your version looks good
to me!

> I’ve tested that the generated grub.cfg is what we expect in several
> different scenario.

Thank you for taking the extra time to test it.

> If that’s fine with you, I’d like to commit this version.  With that
> done, the rest of the patch series will be rather easy.
>
> WDYT?
>

Sounds good to me.  Unless you think strongly that we should use
relative paths in the <boot-parameters> and <menu-entry> objects, I will
re-submit my patches once you have committed this change to the official
repo.

> Thank you!

Thank you for all of your help and tips!  I really appreciate it, and
it's all been very helpful.
Ludovic Courtès - Oct. 30, 2016, 10:19 p.m.
Chris Marusich <cmmarusich@gmail.com> skribis:

> ludo@gnu.org (Ludovic Courtès) writes:

>> However, after rereading the whole series, I think what we need is a
>> ‘device-mount-point’ in <menu-entry>, in a symmetrical fashion.
>
> That would work, and I'm open to it.  However, before we decide to do
> that, what do you think about the alternative in which we simply require
> that all the paths in the <boot-parameters> and <menu-entry> objects
> must be relative paths?  By relative, I mean relative to the GRUB root.
> If all the paths were relative, then we would not need a
> 'device-mount-point' field in the first place.
>
> However, I suspect it might be tricky to get all the information we need
> if we do it that way.  For example, during switch-generation, how would
> we know the correct paths to use for the files in the GRUB
> configuration's 'eye-candy' section?  In light of that, I suspect it
> would be better to do what you've suggested: include the mount point in
> both <boot-parameters> and <menu-entry>.

Yeah, I’m not sure we could easily manage to have only relative file
names because most of them are computed when the derivations get built
(that’s why ‘strip-mount-point’ currently has to return a gexp instead
of stripping the mount point directly.)

>> Attached is an updated patch.  I have grouped together the patches of
>> your series that touch this topic, including the documentation part
>> (this is all one logical change so it’s best to commit it as such), and
>> made the above change.
>
> Thank you for doing this.  I've looked it over.  It looks good to me.
> Unless you think strongly that we should use relative paths in the
> <boot-parameters> and <menu-entry> objects, I think it's good as-is!

Good!

>> If that’s fine with you, I’d like to commit this version.  With that
>> done, the rest of the patch series will be rather easy.
>>
>> WDYT?
>>
>
> Sounds good to me.

Pushed as 1ef8b72a7f87afe7cffe52393d99e1b14e4770e1!

> Unless you think strongly that we should use relative paths in the
> <boot-parameters> and <menu-entry> objects, I will re-submit my
> patches once you have committed this change to the official repo.

That would be awesome.

Thanks again for all your work and patience!

Ludo’.
Chris Marusich - Nov. 2, 2016, 5:48 a.m.
This patch series builds on 1ef8b72a7f87afe7cffe52393d99e1b14e4770e1 to add
two new 'guix system' actions: roll-back and switch-generation.

I've verified that both 'make check' and 'make check-system' pass (with the
exception of the system tests 'nss-mdns' and 'encrypted-root-os', which both
fail on my system even without my patches).  I've manually verified the
following for a VM with a single disk and single partition, as well as for a
VM with multiple disks and the store on a separate partition:

* The grub.cfg file that 'roll-back' and 'switch-generation' generates looks
  correct and is correctly registered as a GC root.

* The system can boot after 'roll-back' and 'switch-generation', the default
  entry is correct, and the resources necessary for the GRUB theme are loaded
  without error.

* Any attempt to switch to a nonexistent generation fail, regardless
  of whether a relative or absolute generation spec is used.

* The existing 'list-generations' command continues to show the
  generations correctly, even after switching generations.

Hopefully everything is OK this time!  Thank you for taking the time to review
it.

--
Chris
Leo Famulari - Nov. 3, 2016, 12:19 a.m.
On Sun, Oct 30, 2016 at 11:19:56PM +0100, Ludovic Courtès wrote:
> Chris Marusich <cmmarusich@gmail.com> skribis:
> >> If that’s fine with you, I’d like to commit this version.  With that
> >> done, the rest of the patch series will be rather easy.
> >>
> >> WDYT?
> >>
> >
> > Sounds good to me.
> 
> Pushed as 1ef8b72a7f87afe7cffe52393d99e1b14e4770e1!

I wonder, has anybody besides ng0 tried using this with libreboot? They
recently reconfigured their GuixSD system after this was committed, and
since then they aren't able to boot.

The IRC discussion begins here:

https://gnunet.org/bot/log/guix/2016-11-02#T1191881
Chris Marusich - Nov. 3, 2016, 4:36 a.m.
Leo Famulari <leo@famulari.name> writes:

> I wonder, has anybody besides ng0 tried using this with libreboot? They
> recently reconfigured their GuixSD system after this was committed, and
> since then they aren't able to boot.
>
> The IRC discussion begins here:
>
> https://gnunet.org/bot/log/guix/2016-11-02#T1191881

I'm using Libreboot on a Lenovo X200 laptop.  I've reconfigured my
system using the change mentioned, and it boots without issue.

I reconfigured by running 'sudo guix system reconfigure config.scm'
after running 'sudo guix pull' to update root's Guix installation.  The
version of guix I used to do the reconfigure was definitely after commit
1ef8b72a7f87afe7cffe52393d99e1b14e4770e1.  I know this because I've
confirmed that the changes introduced by that commit are present in
/root/.config/guix/latest, and as I understand it that the code in that
directory is what gets used when running 'guix system reconfigure
config.scm' as root.

FWIW, my Libreboot details (as reported by running the command
'lscoreboot' after pressing "C" in the Libreboot GRUB menu when my
computer first boots) are as follows:

* version: `04f4afb-dirty'
* extra version: `'
* build: `Sat May 14 01:48:09 UTC 2016'

I hope that helps.
Chris Marusich - Nov. 3, 2016, 10:35 a.m.
Chris Marusich <cmmarusich@gmail.com> writes:

> Leo Famulari <leo@famulari.name> writes:
>
>> I wonder, has anybody besides ng0 tried using this with libreboot? They
>> recently reconfigured their GuixSD system after this was committed, and
>> since then they aren't able to boot.
>>
>> The IRC discussion begins here:
>>
>> https://gnunet.org/bot/log/guix/2016-11-02#T1191881
>
> I'm using Libreboot on a Lenovo X200 laptop.  I've reconfigured my
> system using the change mentioned, and it boots without issue.
>
> I reconfigured by running 'sudo guix system reconfigure config.scm'
> after running 'sudo guix pull' to update root's Guix installation.  The
> version of guix I used to do the reconfigure was definitely after commit
> 1ef8b72a7f87afe7cffe52393d99e1b14e4770e1.  I know this because I've
> confirmed that the changes introduced by that commit are present in
> /root/.config/guix/latest, and as I understand it that the code in that
> directory is what gets used when running 'guix system reconfigure
> config.scm' as root.
>
> FWIW, my Libreboot details (as reported by running the command
> 'lscoreboot' after pressing "C" in the Libreboot GRUB menu when my
> computer first boots) are as follows:
>
> * version: `04f4afb-dirty'
> * extra version: `'
> * build: `Sat May 14 01:48:09 UTC 2016'
>
> I hope that helps.

Additional info: I've just now upgraded my x200 laptop to the latest
release of Libreboot (r20160907), and I can still boot into GuixSD
normally.
Chris Marusich - Nov. 3, 2016, 1:10 p.m.
As you know, ng0 was having trouble booting into GuixSD after
1ef8b72a7f87afe7cffe52393d99e1b14e4770e1.  When I looked closely at the
change, I realized we were not doing the right thing in all cases.  Here is a
patch to fix that.

I've confirmed via manual testing in a QEMU image that when using a device
path for the file system containing the store, 'guix system reconfigure' does
the right thing: it uses a file-based GRUB root search in the new GRUB menu
entry.  That's what it originally did, but
1ef8b72a7f87afe7cffe52393d99e1b14e4770e1 broke that behavior.

I didn't catch this regression because our existing system tests did not catch
it, and in all my manual tests, I was using file system labels, not device
paths.

--
Chris
Danny Milosavljevic - Nov. 3, 2016, 10:34 p.m.
Hi,

On Thu, 03 Nov 2016 03:35:42 -0700
Chris Marusich <cmmarusich@gmail.com> wrote:
> Additional info: I've just now upgraded my x200 laptop to the latest
> release of Libreboot (r20160907), and I can still boot into GuixSD
> normally.

Really? I have an X200 with libreboot and I had to manually create a symlink /boot/grub/libreboot_grub.cfg -> /boot/grub/grub.cfg - otherwise I'd require complicated incantations for each boot.

Do you have such a symlink?
Chris Marusich - Nov. 4, 2016, 3:34 a.m.
Danny Milosavljevic <dannym@scratchpost.org> writes:

> Hi,
>
> On Thu, 03 Nov 2016 03:35:42 -0700
> Chris Marusich <cmmarusich@gmail.com> wrote:
>> Additional info: I've just now upgraded my x200 laptop to the latest
>> release of Libreboot (r20160907), and I can still boot into GuixSD
>> normally.
>
> Really? I have an X200 with libreboot and I had to manually create a
> symlink /boot/grub/libreboot_grub.cfg -> /boot/grub/grub.cfg -
> otherwise I'd require complicated incantations for each boot.
>
> Do you have such a symlink?

I do not:

--8<---------------cut here---------------start------------->8---
$ ls -l /boot/grub/
total 28
drwxr-xr-x 2 root root  4096 Mar 27  2016 fonts/
-r--r--r-- 1 root root  1877 Nov  3 00:03 grub.cfg
-rw-r--r-- 1 root root  1024 Mar 27  2016 grubenv
drwxr-xr-x 2 root root 12288 Nov  3 00:03 i386-pc/
drwxr-xr-x 2 root root  4096 Nov  3 00:03 locale/
--8<---------------cut here---------------end--------------->8---

I wonder if you are using a different version of Libreboot than me?  You
can check your version by following the instructions here:

https://libreboot.org/docs/index.html#version

Here is some other information which might help you figure out why my
Libreboot works without a libreboot_grub.cfg symlink, but yours doesn't:

* I use the GRUB payload (I presume you do, too).  Specifically, the ROM
I used was
libreboot_r20160907_grub_x200_8mb/x200_8mb_ukqwerty_vesafb.rom from the
release.

* My /boot/grub/grub.cfg file is on my root file system, which is ext4
and exists on the /dev/sda1 device.  I only have one disk in my laptop,
/dev/sda, and that's the one I installed GRUB onto (via 'guix system
reconfigure').  I encrypt my home partition (in my case, /dev/sda2) with
LUKS, but the rest is unencrypted.

I'm actually not sure what fancy tricks Libreboot (and its GRUB payload)
might be using to find the grub.cfg file.  But hopefully that
information helps.
Chris Marusich - Nov. 4, 2016, 3:55 a.m.
Chris Marusich <cmmarusich@gmail.com> writes:

> I'm actually not sure what fancy tricks Libreboot (and its GRUB payload)
> might be using to find the grub.cfg file.  But hopefully that
> information helps.

Upon further investigation, it seems that Libreboot searches for
grub.cfg in addition to a few other configuration files [1].  So, if
you've got a recent version, you shouldn't need a libreboot_grub.cfg
symlink.

[1] https://notabug.org/vimuser/libreboot/src/master/resources/grub/config/menuentries/common.cfg

Patch

From a8129e9282d673edb38fb52e7c373f3b380d35be Mon Sep 17 00:00:00 2001
From: Chris Marusich <cmmarusich@gmail.com>
Date: Fri, 28 Oct 2016 03:07:18 -0700
Subject: [PATCH] system: Record store file system info in each generation.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* gnu/system.scm (<boot-parameters>)[store-device, store-mount-point]:
New fields.
(read-boot-parameters): Initialize them.
(operating-system-grub.cfg): Likewise.  Remove STORE-FS argument from
call to 'grub-configuration-file'.
(operating-system-parameters-file): Add 'store' element in
'boot-parameters'.
* gnu/system/grub.scm (strip-mount-point): Replace 'store-fs' parameter
by 'mount-point'; adjust accordingly.  Adjust callers.
(<menu-entry>)[device, device-mount-point]: New fields.
(eye-candy): Replace 'root-fs' parameter by 'store-device'; add
'store-mount-point'.  Use keyword arguments for 'system' and 'port'.
(grub-root-search): Remove 'root-fs' by 'device' and adjust
accordingly.
(grub-configuration-file): Remove 'store-fs' parameter.  Adjust
accordingly.
* guix/scripts/system.scm (previous-grub-entries): Initialize 'device'
and 'device-mount-point' fields from PARAMS.
* doc/guix.texi (GRUB Configuration): Document 'device' and
'device-mount-point'.  Explain that 'linux' can be prefixed by a GRUB
device name.

Co-authored-by: Ludovic Courtès <ludo@gnu.org>
---
 doc/guix.texi           | 27 ++++++++++++++++
 gnu/system.scm          | 59 ++++++++++++++++++++++++++++------
 gnu/system/grub.scm     | 85 ++++++++++++++++++++++++++++---------------------
 guix/scripts/system.scm |  3 ++
 4 files changed, 128 insertions(+), 46 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 22d353c..a351964 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -11088,6 +11088,17 @@  The Linux kernel image to boot, for example:
 (file-append linux-libre "/bzImage")
 @end example
 
+It is also possible to specify a device explicitly in the file path
+using GRUB's device naming convention (@pxref{Naming convention,,, grub,
+GNU GRUB manual}), for example:
+
+@example
+"(hd0,msdos1)/boot/vmlinuz"
+@end example
+
+If the device is specified explicitly as above, then the @code{device}
+field is ignored entirely.
+
 @item @code{linux-arguments} (default: @code{()})
 The list of extra Linux kernel command-line arguments---e.g.,
 @code{("console=ttyS0")}.
@@ -11096,6 +11107,22 @@  The list of extra Linux kernel command-line arguments---e.g.,
 A G-Expression or string denoting the file name of the initial RAM disk
 to use (@pxref{G-Expressions}).
 
+@item @code{device} (default: @code{#f})
+The device where the kernel and initrd are to be found---i.e., the GRUB
+@dfn{root} for this menu entry (@pxref{root,,, grub, GNU GRUB manual}).
+
+This may be a file system label (a string), a file system UUID (a
+bytevector, @pxref{File Systems}), or @code{#f}, in which case GRUB will
+search the device containing the file specified by the @code{linux}
+field (@pxref{search,,, grub, GNU GRUB manual}).  It must @emph{not} be
+an OS device name such as @file{/dev/sda1}.
+
+@item @code{device-mount-point} (default: @code{"/"})
+The mount point of the above device on the system.  You probably do not
+need to change the default value.  GuixSD uses it to strip the prefix of
+store file names for systems where @file{/gnu} or @file{/gnu/store} is
+on a separate partition.
+
 @end table
 @end deftp
 
diff --git a/gnu/system.scm b/gnu/system.scm
index 38ae8f1..259875d 100644
--- a/gnu/system.scm
+++ b/gnu/system.scm
@@ -2,6 +2,7 @@ 
 ;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2015, 2016 Alex Kost <alezost@gmail.com>
+;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -99,6 +100,8 @@ 
             boot-parameters?
             boot-parameters-label
             boot-parameters-root-device
+            boot-parameters-store-device
+            boot-parameters-store-mount-point
             boot-parameters-kernel
             boot-parameters-kernel-arguments
             boot-parameters-initrd
@@ -733,6 +736,12 @@  listed in OS.  The C library expects to find it under
                            (file-system-device root-fs)))
        (entries ->  (list (menu-entry
                            (label label)
+
+                           ;; The device where the kernel and initrd live.
+                           (device (file-system-device store-fs))
+                           (device-mount-point
+                            (file-system-mount-point store-fs))
+
                            (linux kernel)
                            (linux-arguments
                             (cons* (string-append "--root=" root-device)
@@ -741,8 +750,7 @@  listed in OS.  The C library expects to find it under
                                                     "/boot")
                                    (operating-system-kernel-arguments os)))
                            (initrd initrd)))))
-    (grub-configuration-file (operating-system-bootloader os)
-                             store-fs entries
+    (grub-configuration-file (operating-system-bootloader os) entries
                              #:old-entries old-entries)))
 
 (define (operating-system-parameters-file os)
@@ -750,16 +758,24 @@  listed in OS.  The C library expects to find it under
 this file is the reconstruction of GRUB menu entries for old configurations."
   (mlet %store-monad ((initrd   (operating-system-initrd-file os))
                       (root ->  (operating-system-root-file-system os))
+                      (store -> (operating-system-store-file-system os))
                       (label -> (kernel->grub-label
                                  (operating-system-kernel os))))
     (gexp->file "parameters"
-                #~(boot-parameters (version 0)
-                                   (label #$label)
-                                   (root-device #$(file-system-device root))
-                                   (kernel #$(operating-system-kernel-file os))
-                                   (kernel-arguments
-                                    #$(operating-system-kernel-arguments os))
-                                   (initrd #$initrd))
+                #~(boot-parameters
+                   (version 0)
+                   (label #$label)
+                   (root-device #$(file-system-device root))
+                   (kernel #$(operating-system-kernel-file os))
+                   (kernel-arguments
+                    #$(operating-system-kernel-arguments os))
+                   (initrd #$initrd)
+                   (store
+                    (device #$(case (file-system-title store)
+                                ((uuid) (file-system-device store))
+                                ((label) (file-system-device store))
+                                (else #f)))
+                    (mount-point #$(file-system-mount-point store))))
                 #:set-load-path? #f)))
 
 
@@ -770,7 +786,16 @@  this file is the reconstruction of GRUB menu entries for old configurations."
 (define-record-type* <boot-parameters>
   boot-parameters make-boot-parameters boot-parameters?
   (label            boot-parameters-label)
+  ;; Because we will use the 'store-device' to create the GRUB search command,
+  ;; the 'store-device' has slightly different semantics than 'root-device'.
+  ;; The 'store-device' can be a file system uuid, a file system label, or #f,
+  ;; but it cannot be a device path such as "/dev/sda3", since GRUB would not
+  ;; understand that.  The 'root-device', on the other hand, corresponds
+  ;; exactly to the device field of the <file-system> object representing the
+  ;; OS's root file system, so it might be a device path like "/dev/sda3".
   (root-device      boot-parameters-root-device)
+  (store-device     boot-parameters-store-device)
+  (store-mount-point boot-parameters-store-mount-point)
   (kernel           boot-parameters-kernel)
   (kernel-arguments boot-parameters-kernel-arguments)
   (initrd           boot-parameters-initrd))
@@ -804,7 +829,21 @@  this file is the reconstruction of GRUB menu entries for old configurations."
          (('initrd ('string-append directory file)) ;the old format
           (string-append directory file))
          (('initrd (? string? file))
-          file)))))
+          file)))
+
+      (store-device
+       (match (assq 'store rest)
+         (('store ('device device) _ ...)
+          device)
+         (_                                       ;the old format
+          root)))
+
+      (store-mount-point
+       (match (assq 'store rest)
+         (('store ('device _) ('mount-point mount-point) _ ...)
+          mount-point)
+         (_                                       ;the old format
+          "/")))))
     (x                                            ;unsupported format
      (warning (_ "unrecognized boot parameters for '~a'~%")
               system)
diff --git a/gnu/system/grub.scm b/gnu/system/grub.scm
index 249b415..5c9d0f1 100644
--- a/gnu/system/grub.scm
+++ b/gnu/system/grub.scm
@@ -1,5 +1,6 @@ 
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -32,6 +33,7 @@ 
   #:use-module (ice-9 match)
   #:use-module (ice-9 regex)
   #:use-module (srfi srfi-1)
+  #:use-module (rnrs bytevectors)
   #:export (grub-image
             grub-image?
             grub-image-aspect-ratio
@@ -61,16 +63,15 @@ 
 ;;;
 ;;; Code:
 
-(define (strip-mount-point fs file)
-  "Strip the mount point of FS from FILE, which is a gexp or other lowerable
-object denoting a file name."
-  (let ((mount-point (file-system-mount-point fs)))
-    (if (string=? mount-point "/")
-	file
-	#~(let ((file #$file))
-            (if (string-prefix? #$mount-point file)
-                (substring #$file #$(string-length mount-point))
-                file)))))
+(define (strip-mount-point mount-point file)
+  "Strip MOUNT-POINT from FILE, which is a gexp or other lowerable object
+denoting a file name."
+  (if (string=? mount-point "/")
+      file
+      #~(let ((file #$file))
+          (if (string-prefix? #$mount-point file)
+              (substring #$file #$(string-length mount-point))
+              file))))
 
 (define-record-type* <grub-image>
   grub-image make-grub-image
@@ -121,6 +122,10 @@  object denoting a file name."
   menu-entry make-menu-entry
   menu-entry?
   (label           menu-entry-label)
+  (device          menu-entry-device       ; file system uuid, label, or #f
+                   (default #f))
+  (device-mount-point menu-entry-device-mount-point
+                      (default "/"))
   (linux           menu-entry-linux)
   (linux-arguments menu-entry-linux-arguments
                    (default '()))          ; list of string-valued gexps
@@ -162,12 +167,14 @@  WIDTH/HEIGHT, or #f if none was found."
         (with-monad %store-monad
           (return #f)))))
 
-(define (eye-candy config root-fs system port)
+(define* (eye-candy config store-device store-mount-point
+                    #:key system port)
   "Return in %STORE-MONAD a gexp that writes to PORT (a port-valued gexp) the
 'grub.cfg' part concerned with graphics mode, background images, colors, and
-all that.  ROOT-FS is a file-system object denoting the root file system where
-the store is.  SYSTEM must be the target system string---e.g.,
-\"x86_64-linux\"."
+all that.  STORE-DEVICE designates the device holding the store, and
+STORE-MOUNT-POINT is its mount point; these are used to determine where the
+background image and fonts must be searched for.  SYSTEM must be the target
+system string---e.g., \"x86_64-linux\"."
   (define setup-gfxterm-body
     ;; Intel systems need to be switched into graphics mode, whereas most
     ;; other modern architectures have no other mode and therefore don't need
@@ -191,7 +198,7 @@  the store is.  SYSTEM must be the target system string---e.g.,
                      (symbol->string (assoc-ref colors 'bg)))))
 
   (define font-file
-    (strip-mount-point root-fs
+    (strip-mount-point store-mount-point
                        (file-append grub "/share/grub/unicode.pf2")))
 
   (mlet* %store-monad ((image (grub-background-image config)))
@@ -215,10 +222,10 @@  else
   set menu_color_highlight=white/blue
 fi~%"
                            #$setup-gfxterm-body
-                           #$(grub-root-search root-fs font-file)
+                           #$(grub-root-search store-device font-file)
                            #$font-file
 
-                           #$(strip-mount-point root-fs image)
+                           #$(strip-mount-point store-mount-point image)
                            #$(theme-colors grub-theme-color-normal)
                            #$(theme-colors grub-theme-color-highlight))))))
 
@@ -227,8 +234,8 @@  fi~%"
 ;;; Configuration file.
 ;;;
 
-(define (grub-root-search root-fs file)
-  "Return the GRUB 'search' command to look for ROOT-FS, which contains FILE,
+(define (grub-root-search device file)
+  "Return the GRUB 'search' command to look for DEVICE, which contains FILE,
 a gexp.  The result is a gexp that can be inserted in the grub.cfg-generation
 code."
   ;; Usually FILE is a file name gexp like "/gnu/store/…-linux/vmlinuz", but
@@ -236,20 +243,18 @@  code."
   ;; custom menu entries.  In the latter case, don't emit a 'search' command.
   (if (and (string? file) (not (string-prefix? "/" file)))
       ""
-      (case (file-system-title root-fs)
-        ;; Preferably refer to ROOT-FS by its UUID or label.  This is more
+      (match device
+        ;; Preferably refer to DEVICE by its UUID or label.  This is more
         ;; efficient and less ambiguous, see <>.
-        ((uuid)
+        ((? bytevector? uuid)
          (format #f "search --fs-uuid --set ~a"
-                 (uuid->string (file-system-device root-fs))))
-        ((label)
-         (format #f "search --label --set ~a"
-                 (file-system-device root-fs)))
-        (else
-         ;; As a last resort, look for any device containing FILE.
+                 (uuid->string device)))
+        ((? string? label)
+         (format #f "search --label --set ~a" label))
+        (#f
          #~(format #f "search --file --set ~a" #$file)))))
 
-(define* (grub-configuration-file config store-fs entries
+(define* (grub-configuration-file config entries
                                   #:key
                                   (system (%current-system))
                                   (old-entries '()))
@@ -262,22 +267,30 @@  corresponding to old generations of the system."
 
   (define entry->gexp
     (match-lambda
-     (($ <menu-entry> label linux arguments initrd)
-      ;; Use the right file names for LINUX and STORE-FS in case STORE-FS is
-      ;; not the "/" file system.
-      (let ((linux  (strip-mount-point store-fs linux))
-            (initrd (strip-mount-point store-fs initrd)))
+     (($ <menu-entry> label device device-mount-point
+                      linux arguments initrd)
+      ;; Here DEVICE is the store and DEVICE-MOUNT-POINT is its mount point.
+      ;; Use the right file names for LINUX and INITRD in case
+      ;; DEVICE-MOUNT-POINT is not "/", meaning that the store is on a
+      ;; separate partition.
+      (let ((linux  (strip-mount-point device-mount-point linux))
+            (initrd (strip-mount-point device-mount-point initrd)))
         #~(format port "menuentry ~s {
   ~a
   linux ~a ~a
   initrd ~a
 }~%"
                   #$label
-                  #$(grub-root-search store-fs linux)
+                  #$(grub-root-search device linux)
                   #$linux (string-join (list #$@arguments))
                   #$initrd)))))
 
-  (mlet %store-monad ((sugar (eye-candy config store-fs system #~port)))
+  (mlet %store-monad ((sugar (eye-candy config
+                                        (menu-entry-device (first entries))
+                                        (menu-entry-device-mount-point
+                                         (first entries))
+                                        #:system system
+                                        #:port #~port)))
     (define builder
       #~(call-with-output-file #$output
           (lambda (port)
diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm
index 0519ab8..e548be6 100644
--- a/guix/scripts/system.scm
+++ b/guix/scripts/system.scm
@@ -1,6 +1,7 @@ 
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2016 Alex Kost <alezost@gmail.com>
+;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -384,6 +385,8 @@  it atomically, and then run OS's activation script."
         (label (string-append label " (#"
                               (number->string number) ", "
                               (seconds->string time) ")"))
+        (device (boot-parameters-store-device params))
+        (device-mount-point (boot-parameters-store-mount-point params))
         (linux kernel)
         (linux-arguments
          (cons* (string-append "--root=" root-device)
-- 
2.10.1