Add EFI support via --efi <device> option
authorMichael Prokop <mika@grml.org>
Wed, 2 Mar 2016 15:04:23 +0000 (16:04 +0100)
committerMichael Prokop <mika@grml.org>
Wed, 13 Apr 2016 13:48:01 +0000 (15:48 +0200)
This is useful for systems using (U)EFI, otherwise it needs
annoying manual work, so instead automate the steps, assuming
<device> is a valid EFI partition.

NOTE: we need /sys inside the target system, so ensure it's available.

Thanks: Darshaka Pathirana <dpat@syn-net.org> for the pair programming session

chroot-script
cmdlineopts.clp
grml-debootstrap
grml-debootstrap.8.txt

index 978eea3..256ae60 100755 (executable)
@@ -21,6 +21,7 @@ fi
 . /etc/debootstrap/variables || exit 1
 
 [ -r /proc/1 ] || mount -t proc none /proc
 . /etc/debootstrap/variables || exit 1
 
 [ -r /proc/1 ] || mount -t proc none /proc
+[ -r /sys/kernel ] || mount -t sysfs none /sys
 
 # variable checks {{{
 
 
 # variable checks {{{
 
@@ -481,6 +482,10 @@ else
    echo "${TARGET} /  auto    defaults,errors=remount-ro 0   1" > /etc/fstab
 fi
 
    echo "${TARGET} /  auto    defaults,errors=remount-ro 0   1" > /etc/fstab
 fi
 
+if [ -n "$EFI" ] ; then
+  echo "UUID=$(blkid -o value -s UUID $EFI)  /boot/efi       vfat    umask=0077      0       1" >> /etc/fstab
+fi
+
 cat >> /etc/fstab << EOF
 proc           /proc        proc    defaults                      0   0
 /dev/cdrom     /mnt/cdrom0  iso9660 ro,user,noauto                0   0
 cat >> /etc/fstab << EOF
 proc           /proc        proc    defaults                      0   0
 /dev/cdrom     /mnt/cdrom0  iso9660 ro,user,noauto                0   0
@@ -561,6 +566,24 @@ initrd() {
 }
 # }}}
 
 }
 # }}}
 
+efi_setup() {
+  if [ -z "$EFI" ] ; then
+    return 0
+  fi
+
+  if ! dpkg --list efibootmgr 2>/dev/null | grep -q '^ii' ; then
+    echo "Notice: efi option set but no efibootmgr package, installing it therefore."
+    DEBIAN_FRONTEND=$DEBIAN_FRONTEND $APTINSTALL efibootmgr
+  fi
+
+  mkdir -p /boot/efi
+  echo "Mounting $EFI on /boot/efi"
+  mount "$EFI" /boot/efi || return 1
+
+  echo "Invoking efibootmgr"
+  efibootmgr || return 1
+}
+
 # grub configuration/installation {{{
 grub_install() {
 
 # grub configuration/installation {{{
 grub_install() {
 
@@ -569,14 +592,22 @@ grub_install() {
     return 0
   fi
 
     return 0
   fi
 
+  efi_setup || return 1
+
+  if [ -n "$EFI" ] ; then
+    GRUB_PACKAGE=grub-efi-amd64
+  else
+    GRUB_PACKAGE=grub-pc
+  fi
+
   # make sure this is pre-defined so we have sane settings for automated
   # upgrades, see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=711019
   # make sure this is pre-defined so we have sane settings for automated
   # upgrades, see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=711019
-  echo "Setting grub-pc debconf configuration for install device to $GRUB"
-  echo "grub-pc grub-pc/install_devices multiselect $GRUB" | debconf-set-selections
+  echo "Setting ${GRUB_PACKAGE} debconf configuration for install device to $GRUB"
+  echo "${GRUB_PACKAGE} ${GRUB_PACKAGE}/install_devices multiselect $GRUB" | debconf-set-selections
 
 
-  if ! dpkg --list grub-pc 2>/dev/null | grep -q '^ii' ; then
-    echo "Notice: grub option set but no grub-pc package, installing it therefore."
-    DEBIAN_FRONTEND=$DEBIAN_FRONTEND $APTINSTALL grub-pc
+  if ! dpkg --list ${GRUB_PACKAGE} 2>/dev/null | grep -q '^ii' ; then
+    echo "Notice: grub option set but no ${GRUB_PACKAGE} package, installing it therefore."
+    DEBIAN_FRONTEND=$DEBIAN_FRONTEND $APTINSTALL ${GRUB_PACKAGE}
   fi
 
   if ! [ -x "$(which grub-install)" ] ; then
   fi
 
   if ! [ -x "$(which grub-install)" ] ; then
@@ -618,6 +649,8 @@ grub_install() {
     return 1
   fi
 
     return 1
   fi
 
+  mountpoint /boot/efi >/dev/null && umount /boot/efi
+
   $UPDATEGRUB
 }
 # }}}
   $UPDATEGRUB
 }
 # }}}
@@ -650,6 +683,7 @@ finalize() {
 
   [ -n "$POLICYRCD" ] && rm -f /usr/sbin/policy-rc.d
 
 
   [ -n "$POLICYRCD" ] && rm -f /usr/sbin/policy-rc.d
 
+  umount /sys >/dev/null 2>/dev/null || true
   umount /proc >/dev/null 2>/dev/null || true
 }
 # }}}
   umount /proc >/dev/null 2>/dev/null || true
 }
 # }}}
index 7e9ed45..68b241a 100644 (file)
@@ -12,7 +12,7 @@
 # should be handled in the main script, where it belongs.
 ################################################################################
 
 # should be handled in the main script, where it belongs.
 ################################################################################
 
-CMDLINE_OPTS=mirror:,iso:,release:,target:,mntpoint:,debopt:,defaultinterfaces,interactive,nodebootstrap,nointerfaces,nokernel,nopackages,filesystem:,config:,confdir:,packages:,chroot-scripts:,scripts:,post-scripts:,pre-scripts:,debconf:,vm,vmfile,vmsize:,keep_src_list,hostname:,password:,nopassword,grmlrepos,backportrepos,bootappend:,grub:,arch:,insecure,verbose,help,version,force,debug,contrib,non-free,remove-configs
+CMDLINE_OPTS=mirror:,iso:,release:,target:,mntpoint:,debopt:,defaultinterfaces,interactive,nodebootstrap,nointerfaces,nokernel,nopackages,filesystem:,config:,confdir:,packages:,chroot-scripts:,scripts:,post-scripts:,pre-scripts:,debconf:,vm,vmfile,vmsize:,keep_src_list,hostname:,password:,nopassword,grmlrepos,backportrepos,bootappend:,grub:,efi:,arch:,insecure,verbose,help,version,force,debug,contrib,non-free,remove-configs
 
 _opt_temp=`getopt --name grml-debootstrap -o +m:i:r:t:p:c:d:vhV --long \
     $CMDLINE_OPTS -- "$@"`
 
 _opt_temp=`getopt --name grml-debootstrap -o +m:i:r:t:p:c:d:vhV --long \
     $CMDLINE_OPTS -- "$@"`
@@ -138,6 +138,9 @@ while :; do
   --grub)              # Target for grub installation. Use grub syntax for specifying
     shift; _opt_grub="$1"
     ;;
   --grub)              # Target for grub installation. Use grub syntax for specifying
     shift; _opt_grub="$1"
     ;;
+  --efi)               # Target for EFI boot installation
+    shift; _opt_efi="$1"
+    ;;
   --contrib)           # Add 'contrib' to list of components
     _opt_contrib=T
     ;;
   --contrib)           # Add 'contrib' to list of components
     _opt_contrib=T
     ;;
index d3932f0..9a67754 100755 (executable)
@@ -111,6 +111,7 @@ Bootstrap options:
       --interactive      Use interactive mode (frontend).
       --nodebootstrap    Skip debootstrap, only do configuration to the target.
       --grub <device>    Target for grub installation. Usage example: /dev/sda
       --interactive      Use interactive mode (frontend).
       --nodebootstrap    Skip debootstrap, only do configuration to the target.
       --grub <device>    Target for grub installation. Usage example: /dev/sda
+      --efi <device>     Target for EFI installation. Usage example: /dev/sda1
       --arch <arch>      Set target architecture, use for installing i386 on amd64.
       --filesystem <fs>  Filesystem that should be used when target is a partition
                          or Virtual Machine (see --vmfile).
       --arch <arch>      Set target architecture, use for installing i386 on amd64.
       --filesystem <fs>  Filesystem that should be used when target is a partition
                          or Virtual Machine (see --vmfile).
@@ -395,6 +396,7 @@ fi
 [ "$_opt_nokernel" ]            && NOKERNEL="true"
 [ "$_opt_bootappend" ]          && BOOT_APPEND=$_opt_bootappend
 [ "$_opt_grub" ]                && GRUB=$_opt_grub
 [ "$_opt_nokernel" ]            && NOKERNEL="true"
 [ "$_opt_bootappend" ]          && BOOT_APPEND=$_opt_bootappend
 [ "$_opt_grub" ]                && GRUB=$_opt_grub
+[ "$_opt_efi" ]                 && EFI=$_opt_efi
 [ "$_opt_arch" ]                && ARCH=$_opt_arch
 [ "$_opt_insecure" ]            && echo "Warning: --insecure is deprecated, continuing anyway."
 [ "$_opt_force" ]               && FORCE=$_opt_force
 [ "$_opt_arch" ]                && ARCH=$_opt_arch
 [ "$_opt_insecure" ]            && echo "Warning: --insecure is deprecated, continuing anyway."
 [ "$_opt_force" ]               && FORCE=$_opt_force
@@ -759,9 +761,63 @@ Do you want to stop now?" 0 0 2>/dev/null
 }
 # }}}
 
 }
 # }}}
 
+format_efi_partition() {
+  if [ -z "$EFI" ] ; then
+    return 0
+  fi
+
+  if ! [ -b "$EFI" ] ; then
+    eerror "Specified efi argument [$EFI] not a valid block device."
+    bailout 1
+  fi
+
+  if fsck.vfat -bn "$EFI" >/dev/null; then
+    einfo "EFI partition $EFI seems to have a FAT filesystem, not modifying." ; eend 0
+  else
+    einfo "EFI partition $EFI doesn't seem to be formated, creating filesystem."
+    mkfs.fat -F32 -n "EFI System Partition" "$EFI"
+    RC=$?
+    if [ $RC -eq 0 ] ; then
+      eend 0
+    else
+      eerror "Error while creating filesystem on ${EFI}."
+      eend 1
+      bailout 1
+    fi
+  fi
+}
+
+# check for EFI support or try to enable it {{{
+efi_support() {
+  if lsmod | grep -q efivars ; then
+    einfo "EFI support detected." ; eend 0
+    return 0
+  fi
+
+  if modprobe efivars ; then
+    einfo "EFI support enabled now." ; eend 0
+    return 0
+  fi
+
+  return 1
+}
+# }}}
+
 # make sure the user is aware of the used configuration {{{
 checkconfiguration()
 {
 # make sure the user is aware of the used configuration {{{
 checkconfiguration()
 {
+
+if efi_support ; then
+  if [ -z "$_opt_efi" ] ; then
+    ewarn "EFI support detected but no --efi option given, please consider enabling it." ; eend 0
+  fi
+else
+  if [ -n "$_opt_efi" ] ; then
+     eerror "EFI option used but no EFI support detected." ; eend 0
+     bailout 1
+  fi
+fi
+
 if [ -n "$AUTOINSTALL" ] ; then
    if checkforrun ; then
       eerror "Exiting as requested" ; eend 0
 if [ -n "$AUTOINSTALL" ] ; then
    if checkforrun ; then
       eerror "Exiting as requested" ; eend 0
@@ -775,6 +831,8 @@ elif [ -n "$INTERACTIVE" ] ; then
    Target:          $TARGET"
    [ -n "$GRUB" ]    && INFOTEXT="$INFOTEXT
    Install grub:    $GRUB"
    Target:          $TARGET"
    [ -n "$GRUB" ]    && INFOTEXT="$INFOTEXT
    Install grub:    $GRUB"
+   [ -n "$EFI" ]    && INFOTEXT="$INFOTEXT
+   Install efi:     $EFI"
    [ -n "$RELEASE" ] && INFOTEXT="$INFOTEXT
    Using release:   $RELEASE"
    [ -n "$HOSTNAME" ] && INFOTEXT="$INFOTEXT
    [ -n "$RELEASE" ] && INFOTEXT="$INFOTEXT
    Using release:   $RELEASE"
    [ -n "$HOSTNAME" ] && INFOTEXT="$INFOTEXT
@@ -808,6 +866,7 @@ else # if not running automatic installation display configuration and prompt fo
       echo "   Install grub:    yes"
    else
      [ -n "$GRUB" ]     && echo "   Install grub:    $GRUB" || echo "   Install grub:    no"
       echo "   Install grub:    yes"
    else
      [ -n "$GRUB" ]     && echo "   Install grub:    $GRUB" || echo "   Install grub:    no"
+     [ -n "$EFI" ]      && echo "   Install efi:     $EFI"  || echo "   Install efi:     no"
    fi
 
    [ -n "$RELEASE" ]   && echo "   Using release:   $RELEASE"
    fi
 
    [ -n "$RELEASE" ]   && echo "   Using release:   $RELEASE"
@@ -1293,6 +1352,7 @@ preparechroot() {
   [ -n "$DEFAULT_LOCALES" ]     && echo "DEFAULT_LOCALES='$(sed "s,','\\\\'',g" <<<"${DEFAULT_LOCALES}")'"         >> "$CHROOT_VARIABLES"
   [ -n "$DEFAULT_LANGUAGE" ]    && echo "DEFAULT_LANGUAGE='$(sed "s,','\\\\'',g" <<<"${DEFAULT_LANGUAGE}")'"       >> "$CHROOT_VARIABLES"
   [ -n "$EXTRAPACKAGES" ]       && echo "EXTRAPACKAGES='$(sed "s,','\\\\'',g" <<<"${EXTRAPACKAGES}")'"             >> "$CHROOT_VARIABLES"
   [ -n "$DEFAULT_LOCALES" ]     && echo "DEFAULT_LOCALES='$(sed "s,','\\\\'',g" <<<"${DEFAULT_LOCALES}")'"         >> "$CHROOT_VARIABLES"
   [ -n "$DEFAULT_LANGUAGE" ]    && echo "DEFAULT_LANGUAGE='$(sed "s,','\\\\'',g" <<<"${DEFAULT_LANGUAGE}")'"       >> "$CHROOT_VARIABLES"
   [ -n "$EXTRAPACKAGES" ]       && echo "EXTRAPACKAGES='$(sed "s,','\\\\'',g" <<<"${EXTRAPACKAGES}")'"             >> "$CHROOT_VARIABLES"
+  [ -n "$EFI" ]                 && echo "EFI='$(sed "s,','\\\\'',g" <<<"${EFI}")'"                                 >> "$CHROOT_VARIABLES"
   [ -n "$FALLBACK_MIRROR" ]     && echo "FALLBACK_MIRROR='$(sed "s,','\\\\'',g" <<<"${FALLBACK_MIRROR}")'"         >> "$CHROOT_VARIABLES"
   [ -n "$FORCE" ]               && echo "FORCE='$(sed "s,','\\\\'',g" <<<"${FORCE}")'"                             >> "$CHROOT_VARIABLES"
   [ -n "$GRMLREPOS" ]           && echo "GRMLREPOS='$(sed "s,','\\\\'',g" <<<"${GRMLREPOS}")'"                     >> "$CHROOT_VARIABLES"
   [ -n "$FALLBACK_MIRROR" ]     && echo "FALLBACK_MIRROR='$(sed "s,','\\\\'',g" <<<"${FALLBACK_MIRROR}")'"         >> "$CHROOT_VARIABLES"
   [ -n "$FORCE" ]               && echo "FORCE='$(sed "s,','\\\\'',g" <<<"${FORCE}")'"                             >> "$CHROOT_VARIABLES"
   [ -n "$GRMLREPOS" ]           && echo "GRMLREPOS='$(sed "s,','\\\\'',g" <<<"${GRMLREPOS}")'"                     >> "$CHROOT_VARIABLES"
@@ -1590,7 +1650,7 @@ remove_configs() {
 # }}}
 
 # now execute all the functions {{{
 # }}}
 
 # now execute all the functions {{{
-for i in prepare_vm mkfs tunefs mount_target debootstrap_system \
+for i in format_efi_partition prepare_vm mkfs tunefs mount_target debootstrap_system \
          preparechroot execute_pre_scripts chrootscript execute_post_scripts \
          remove_configs umount_chroot finalize_vm fscktool ; do
     if stage "${i}" ; then
          preparechroot execute_pre_scripts chrootscript execute_post_scripts \
          remove_configs umount_chroot finalize_vm fscktool ; do
     if stage "${i}" ; then
index 8b78669..69af5f4 100644 (file)
@@ -83,6 +83,16 @@ Options and environment variables
    Execute in very verbose way. Useful for debugging possible problems
    with grml-debootstrap or identify what's actually executed.
 
    Execute in very verbose way. Useful for debugging possible problems
    with grml-debootstrap or identify what's actually executed.
 
+*--efi* _device_::
+
+    Partition where EFI boot manager should be installed to. If the
+    specified device doesn't use a FAT filesystem yet grml-debootstrap
+    automatically creates the filesystem. If a FAT filesystem is already
+    present the filesystem creation is skipped. Please ensure that it's
+    a valid FAT32 filesystem and the partition has the 'boot' and 'esp'
+    flags enabled. This option requires EFI support on the running system
+    and the option is NOT supported for Virtual Machine deployments.
+
 *--filesystem* _filesystem_::
 
     Filesystem that should be created when installing to a partition.
 *--filesystem* _filesystem_::
 
     Filesystem that should be created when installing to a partition.