bootloader.scm 4.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
  3. ;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
  4. ;;;
  5. ;;; This file is part of GNU Guix.
  6. ;;;
  7. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  8. ;;; under the terms of the GNU General Public License as published by
  9. ;;; the Free Software Foundation; either version 3 of the License, or (at
  10. ;;; your option) any later version.
  11. ;;;
  12. ;;; GNU Guix is distributed in the hope that it will be useful, but
  13. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;;; GNU General Public License for more details.
  16. ;;;
  17. ;;; You should have received a copy of the GNU General Public License
  18. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  19. (define-module (gnu build bootloader)
  20. #:use-module (guix build utils)
  21. #:use-module (guix utils)
  22. #:use-module (ice-9 binary-ports)
  23. #:use-module (ice-9 format)
  24. #:use-module (rnrs io ports)
  25. #:use-module (rnrs io simple)
  26. #:export (write-file-on-device
  27. install-efi-loader))
  28. ;;;
  29. ;;; Writing utils.
  30. ;;;
  31. (define (write-file-on-device file size device offset)
  32. "Write SIZE bytes from FILE to DEVICE starting at OFFSET."
  33. (call-with-input-file file
  34. (lambda (input)
  35. (let ((bv (get-bytevector-n input size)))
  36. (call-with-port
  37. (open-file-output-port device
  38. (file-options no-truncate no-create)
  39. (buffer-mode block)
  40. (native-transcoder))
  41. (lambda (output)
  42. (seek output offset SEEK_SET)
  43. (put-bytevector output bv)))))))
  44. ;;;
  45. ;;; EFI bootloader.
  46. ;;;
  47. (define (install-efi grub grub-config esp)
  48. "Write a self-contained GRUB EFI loader to the mounted ESP using GRUB-CONFIG."
  49. (let* ((system %host-type)
  50. ;; Hard code the output location to a well-known path recognized by
  51. ;; compliant firmware. See "3.5.1.1 Removable Media Boot Behaviour":
  52. ;; http://www.uefi.org/sites/default/files/resources/UEFI%20Spec%202_6.pdf
  53. (grub-mkstandalone (string-append grub "/bin/grub-mkstandalone"))
  54. (efi-directory (string-append esp "/EFI/BOOT"))
  55. ;; Map grub target names to boot file names.
  56. (efi-targets (cond ((string-prefix? "x86_64" system)
  57. '("x86_64-efi" . "BOOTX64.EFI"))
  58. ((string-prefix? "i686" system)
  59. '("i386-efi" . "BOOTIA32.EFI"))
  60. ((string-prefix? "armhf" system)
  61. '("arm-efi" . "BOOTARM.EFI"))
  62. ((string-prefix? "aarch64" system)
  63. '("arm64-efi" . "BOOTAA64.EFI")))))
  64. ;; grub-mkstandalone requires a TMPDIR to prepare the firmware image.
  65. (setenv "TMPDIR" esp)
  66. (mkdir-p efi-directory)
  67. (invoke grub-mkstandalone "-O" (car efi-targets)
  68. "-o" (string-append efi-directory "/"
  69. (cdr efi-targets))
  70. ;; Graft the configuration file onto the image.
  71. (string-append "boot/grub/grub.cfg=" grub-config))))
  72. (define (install-efi-loader grub-efi esp)
  73. "Install in ESP directory the given GRUB-EFI bootloader. Configure it to
  74. load the Grub bootloader located in the 'Guix_image' root partition."
  75. (let ((grub-config "grub.cfg"))
  76. (call-with-output-file grub-config
  77. (lambda (port)
  78. ;; Create a tiny configuration file telling the embedded grub where to
  79. ;; load the real thing. XXX This is quite fragile, and can prevent
  80. ;; the image from booting when there's more than one volume with this
  81. ;; label present. Reproducible almost-UUIDs could reduce the risk
  82. ;; (not eliminate it).
  83. (format port
  84. "insmod part_msdos~@
  85. search --set=root --label Guix_image~@
  86. configfile /boot/grub/grub.cfg~%")))
  87. (install-efi grub-efi grub-config esp)
  88. (delete-file grub-config)))