store: Memoize 'add-to-store' based on the result of 'lstat', not 'stat'.
[guix.git] / gnu / system / grub.scm
blobe49b6dbe54cf3cb27d52520fdc0fc424e18f9daa
1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
3 ;;;
4 ;;; This file is part of GNU Guix.
5 ;;;
6 ;;; GNU Guix is free software; you can redistribute it and/or modify it
7 ;;; under the terms of the GNU General Public License as published by
8 ;;; the Free Software Foundation; either version 3 of the License, or (at
9 ;;; your option) any later version.
10 ;;;
11 ;;; GNU Guix is distributed in the hope that it will be useful, but
12 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ;;; GNU General Public License for more details.
15 ;;;
16 ;;; You should have received a copy of the GNU General Public License
17 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
19 (define-module (gnu system grub)
20   #:use-module (guix store)
21   #:use-module (guix packages)
22   #:use-module (guix derivations)
23   #:use-module (guix records)
24   #:use-module (guix monads)
25   #:use-module (guix gexp)
26   #:use-module (guix download)
27   #:use-module (gnu artwork)
28   #:autoload   (gnu packages grub) (grub)
29   #:autoload   (gnu packages inkscape) (inkscape)
30   #:autoload   (gnu packages imagemagick) (imagemagick)
31   #:autoload   (gnu packages compression) (gzip)
32   #:use-module (ice-9 match)
33   #:use-module (srfi srfi-1)
34   #:export (grub-image
35             grub-image?
36             grub-image-aspect-ratio
37             grub-image-file
39             grub-theme
40             grub-theme?
41             grub-theme-images
42             grub-theme-color-normal
43             grub-theme-color-highlight
45             %background-image
46             %default-theme
48             grub-configuration
49             grub-configuration?
50             grub-configuration-device
52             menu-entry
53             menu-entry?
55             grub-configuration-file))
57 ;;; Commentary:
58 ;;;
59 ;;; Configuration of GNU GRUB.
60 ;;;
61 ;;; Code:
63 (define-record-type* <grub-image>
64   grub-image make-grub-image
65   grub-image?
66   (aspect-ratio    grub-image-aspect-ratio        ;rational number
67                    (default 4/3))
68   (file            grub-image-file))              ;file-valued gexp (SVG)
70 (define-record-type* <grub-theme>
71   grub-theme make-grub-theme
72   grub-theme?
73   (images          grub-theme-images
74                    (default '()))                 ;list of <grub-image>
75   (color-normal    grub-theme-color-normal
76                    (default '((fg . cyan) (bg . blue))))
77   (color-highlight grub-theme-color-highlight
78                    (default '((fg . white) (bg . blue)))))
80 (define %background-image
81   (grub-image
82    (aspect-ratio 4/3)
83    (file #~(string-append #$%artwork-repository
84                           "/grub/GuixSD-fully-black-4-3.svg"))))
86 (define %default-theme
87   ;; Default theme contributed by Felipe López.
88   (grub-theme
89    (images (list %background-image))
90    (color-highlight '((fg . yellow) (bg . black)))
91    (color-normal    '((fg . light-gray) (bg . black))))) ;XXX: #x303030
93 (define-record-type* <grub-configuration>
94   grub-configuration make-grub-configuration
95   grub-configuration?
96   (grub            grub-configuration-grub           ; package
97                    (default (@ (gnu packages grub) grub)))
98   (device          grub-configuration-device)        ; string
99   (menu-entries    grub-configuration-menu-entries   ; list
100                    (default '()))
101   (default-entry   grub-configuration-default-entry  ; integer
102                    (default 0))
103   (timeout         grub-configuration-timeout        ; integer
104                    (default 5))
105   (theme           grub-configuration-theme          ; <grub-theme>
106                    (default %default-theme)))
108 (define-record-type* <menu-entry>
109   menu-entry make-menu-entry
110   menu-entry?
111   (label           menu-entry-label)
112   (linux           menu-entry-linux)
113   (linux-arguments menu-entry-linux-arguments
114                    (default '()))          ; list of string-valued gexps
115   (initrd          menu-entry-initrd))     ; file name of the initrd as a gexp
119 ;;; Background image & themes.
122 (define (svg->png svg)
123   "Build a PNG from SVG."
124   ;; Don't use #:local-build? so that it's substitutable.
125   (gexp->derivation "grub-image.png"
126                     #~(zero?
127                        (system* (string-append #$inkscape "/bin/inkscape")
128                                 "--without-gui"
129                                 (string-append "--export-png=" #$output)
130                                 #$svg))))
132 (define (resize-image image width height)
133   "Resize IMAGE to WIDTHxHEIGHT."
134   ;; Don't use #:local-build? so that it's substitutable.
135   (let ((size (string-append (number->string width)
136                              "x" (number->string height))))
137     (gexp->derivation "grub-image.resized.png"
138                       #~(zero?
139                          (system* (string-append #$imagemagick "/bin/convert")
140                                   "-resize" #$size #$image #$output)))))
142 (define* (grub-background-image config #:key (width 640) (height 480))
143   "Return the GRUB background image defined in CONFIG with a ratio of
144 WIDTH/HEIGHT, or #f if none was found."
145   (let* ((ratio (/ width height))
146          (image (find (lambda (image)
147                         (= (grub-image-aspect-ratio image) ratio))
148                       (grub-theme-images (grub-configuration-theme config)))))
149     (if image
150         (mlet %store-monad ((png (svg->png (grub-image-file image))))
151           (resize-image png width height))
152         (with-monad %store-monad
153           (return #f)))))
155 (define (eye-candy config port)
156   "Return in %STORE-MONAD a gexp that writes to PORT (a port-valued gexp) the
157 'grub.cfg' part concerned with graphics mode, background images, colors, and
158 all that."
159   (define (theme-colors type)
160     (let* ((theme  (grub-configuration-theme config))
161            (colors (type theme)))
162       (string-append (symbol->string (assoc-ref colors 'fg)) "/"
163                      (symbol->string (assoc-ref colors 'bg)))))
165   (mlet* %store-monad ((image (grub-background-image config)))
166     (return (and image #~(format #$port "
167 function load_video {
168   insmod vbe
169   insmod vga
170   insmod video_bochs
171   insmod video_cirrus
174 # Set 'root' to the partition that contains /gnu/store.
175 search --file --set ~a/share/grub/unicode.pf2
177 if loadfont ~a/share/grub/unicode.pf2; then
178   set gfxmode=640x480
179   load_video
180   insmod gfxterm
181   terminal_output gfxterm
184 insmod png
185 if background_image ~a; then
186   set color_normal=~a
187   set color_highlight=~a
188 else
189   set menu_color_normal=cyan/blue
190   set menu_color_highlight=white/blue
191 fi~%"
192                         #$grub #$grub
193                         #$image
194                         #$(theme-colors grub-theme-color-normal)
195                         #$(theme-colors grub-theme-color-highlight))))))
199 ;;; Configuration file.
202 (define* (grub-configuration-file config entries
203                                   #:key
204                                   (system (%current-system))
205                                   (old-entries '()))
206   "Return the GRUB configuration file corresponding to CONFIG, a
207 <grub-configuration> object.  OLD-ENTRIES is taken to be a list of menu
208 entries corresponding to old generations of the system."
209   (define all-entries
210     (append entries (grub-configuration-menu-entries config)))
212   (define entry->gexp
213     (match-lambda
214      (($ <menu-entry> label linux arguments initrd)
215       #~(format port "menuentry ~s {
216   # Set 'root' to the partition that contains the kernel.
217   search --file --set ~a/bzImage~%
219   linux ~a/bzImage ~a
220   initrd ~a
221 }~%"
222                 #$label
223                 #$linux #$linux (string-join (list #$@arguments))
224                 #$initrd))))
226   (mlet %store-monad ((sugar (eye-candy config #~port)))
227     (define builder
228       #~(call-with-output-file #$output
229           (lambda (port)
230             #$sugar
231             (format port "
232 set default=~a
233 set timeout=~a~%"
234                     #$(grub-configuration-default-entry config)
235                     #$(grub-configuration-timeout config))
236             #$@(map entry->gexp all-entries)
238             #$@(if (pair? old-entries)
239                    #~((format port "
240 submenu \"GNU system, old configurations...\" {~%")
241                       #$@(map entry->gexp old-entries)
242                       (format port "}~%"))
243                    #~()))))
245     (gexp->derivation "grub.cfg" builder)))
247 ;;; grub.scm ends here