USING GRUB ON UEFI

AUTHOR: Dan McGhee 

DATE: 2014-10-16

LICENSE: GNU Free Documentation License Version 1.2

SYNOPSIS: Boot LFS by default in a UEFI Environment using GRUB

DESCRIPTION:
This hint contains the information to direct the OS Boot Manager to default
to the GRUB in a UEFI environment employing EFI Mode.  This hint applies to
only x86_64 machines.


ATTACHMENTS:
*  None

PREREQUISITES:
Base LFS system before or after Ch. 8
Basic understanding of obtaining and building packages

HINT:

DISCLAIMER:  The recipes in this hint neither supplant nor supersede the
build instructions in a stable version of either the LFS or BLFS books.
They merely augment them for newer firmware.  If conflicts arise between
this hint and the instructions in the book, take the issue to the mailing
lists.  Additionally, this hint applies to only x86_64 machines packaged
with Windows 7 or Windows 8.  The recipes here can be used on Mac OS, but
have not been investigated at the initial writing of this hint.

USE OF TERMS:  The following is a use of terms in this hint.  Further
information for and amplification of them can be found in References 1-3.

BIOS Settings:  A firmware interface accessed by the keyboard after power
is applied.  In it a user can change the order and way of how the computer
boots.

BIOS System:  Firmware with an MBR

EFI Mode:  A condition of the booted system in which the EFI partition is
mounted and the uefi (efi) variable support in the kernel is working
properly.  It results from enabling UEFI Mode in BIOS Settings.

EFI Mount Point:  A user defined mount point for the EFI Partition.  In
this hint, and in most distros, it is /boot/efi.

EFI Partition:  A small partition, usually before any other partitions;
i.e., /dev/sda1 of  200-250 Mb, formatted in FAT32 with the /boot flag, in
parted, or ef00 (EF00) partition type in gdisk.  (NOTE: The boot flag has a
different function and meaning in MBR partitioned disks.)

efi variables (synonymous: uefi variables):  variables through which the
operating system can interact with the firmware.

Legacy Boot Option (Legacy Boot):  A boot process in BIOS Settings that
disables UEFI booting and uses CIM.

GUID Partition Table (GPT): A partitioning scheme that uses UUID's instead
of cylinders to identify partitions.


PRELIMINARY DISCUSSION:  Additional information and more in depth
discussion of the following concepts can be found using References 1-3.

Booting LFS is no longer as simple as "grub-install  /dev/sda."  There are
more options and more considerations.  With the advent and proliferation of
UEFI firmware, a user's knowledge and philosophy of the boot
process requires expansion:
    a) GPT partitioning is different from MBR partitioning.  The tool fdisk
       is not able to manipulate GPT partitions.  Parted and gdisk (from
       gptfdisk) are the tools to use.  Each has their pros and cons,
       supporters and detractors.  Either one or both can be used.
       (Update: fdisk now supports GPT partitioned disk drives.)
    b) UEFI firmware uses Boot Managers to select Boot Loaders like GRUB or
       LILO.  They, themselves do not boot the machine.
    c) The Boot Loaders are placed on the EFI partition rather than the
       MBR.  This concept is similar and parallel to the LFS procedures of
       using a separate /boot partition.
    d) There are additional tools that LFS needs in order to accomplish
       this mode of booting.
    e) LFS can be built and booted as the instructions are written up to
       and including LFS-7.6.  To do this on UEFI firmware, the BIOS
       Settings must be changed to Legacy Options from UEFI Options.

One of the hugely discussed issues surrounding UEFI is Secure Boot.  It is
necessary to understand that the terms "UEFI" and "Secure Boot" are NOT
synonymous.  UEFI is firmware.  Secure Boot is a process of using "keys" to
"guarantee" the safety and authenticity of a Boot Loader.  NOTE:  To use
the recipes in this hint, Secure Boot must be disabled in the BIOS Boot
Settings.

Please note that the recommended order for implementing these recipes is a
departure from the build order in LFS.  The most convenient, and arguably
the most practical way, to implement the recipes here is to use them in the
of build of an LFS System at the end of Ch. 6. Building the BLFS and
non-BLFS packages has been tested both inside and outside of the chroot
environment.  Then, following the book, proceed through Ch. 7, returning to
the recipes in Ch. 8.   The recipes are presented in that order.

The most inconvenient way to implement these recipes is in a completely
functional LFS-7.6, or earlier, system.  This involves uninstalling
grub-2.00, removing it from its location as a result of grub-install and
implementing the recipes.  Migrating from Legacy Boot to UEFI boot is
possible.  At the initial writing of this hint, however, it is not
included.  References 1-3 contain more information on this subject.

The last consideration in implementing the recipes here is GRUB's graphical
terminal.  In UEFI systems, if the GRUB video mode is not initialized, no
kernel boot messages will appear until the kernel video takes over.  The
GRUB package does not supply fonts, and GRUB defaults to unicode.pf2.
There are two ways to supply this font.  The first is to copy unicode.pf2
from the host system to /boot/grub on the LFS system.  The second method
involves configuring grub to build grub-mkfont, and this creates a build
dependency of Freetype2 for GRUB.  This hint addresses both situations.   

Finally, as of the initial writing of this hint, there is no standard for
the use of UEFI and the implementation of Secure Boot.  These are hugely
manufacturer dependent.  This hint uses terms used in the original author's
hardware.  They may be different in other manufacturers' implementations.
However, the capabilities to do the boot setup operations contained in this
hint will exist on each machine.  The terms may differ, and more than one
operation might be needed to achieve a desired goal.  For example, someone
may need to disable Secure Boot and remove Secure Keys.


RECIPES:
[NOTE] The recipes are written with the assumption that the packages are
being built in the chroot environment before the end of Ch. 8.  They can be
modified, with little difficulty, to be used in a functional system.

CHECKING EFI-MODE
    Before entering the chroot environment, check that the host booted in
    EFI Mode.

    ls /sys/firmware/efi

    If this directory exists and is populated, the host booted in EFI Mode.


MOUNT EFI PARTITION
	Determine which device is the EFI partition using gdisk or parted,
        enter the chroot environment, create /boot/efi if needed, and

	mount -vt vfat /dev/sda(x) /boot/efi

        where sda(x) is the device containing the EFI partition.

BUILD DEPENDENCIES:

Install the following BLFS packages, using the instructions in the book:
popt and pciutils.   Build and install Freetype2 if building grub with
grub-mkfont enabled.

      DOSFSTOOLS (runtime dependency of efibootmgr)
      Note: As of October 3, 2014, dosfstools was tagged "orphaned.
      It is still functional.]

      Download:
        http://daniel-baumann.ch/files/software/dosfstools/dosfstools-3.0.26.tar.xz

      Build and Installation:

	make
	make PREFIX=/usr SBINDIR=/usr/bin MANDIR=/usr/share/man  \
	DOCDIR=/usr/share/doc install


      EFIVAR-0.12 (depends on popt)

      Download:
        https://github.com/vathpela/efivar/releases/download/0.12/efivar-0.12.tar.bz2

      Compile the package:
        sed 's|-O0|-Os|g' -i Make.defaults
        sed 's|-rpath=$(TOPDIR)/src/|-rpath=$(libdir)|g' \
             -i src/test/Makefile
        make libdir="/usr/lib/" bindir="/usr/bin/" \
             mandir="/usr/share/man/"     \
             includedir=/usr/include/" V=1 -j1

      Install the package:
        make -j1 V=1 DESTDIR="${pkgdir}/" libdir="/usr/lib/" \
        bindir="/usr/bin/" mandir="/usr/share/man"   \
        includedir="/usr/include/" install
  
        install -v -D -m0755 src/test/tester /usr/bin/efivar-tester


      EFIBOOTMGR-0.9.0
      (depends on pciutils, efivars,zlib to build and dosfstools to run.)

      Download:  https://github.com/vathpela/efibootmgr/releases/download/
                 efibootmgr-0.9.0/efibootmgr-0.9.0.tar.bz2

      Compile the package:
      make EXTRA_CFLAGS="-Os"

      Install the package:
      install -v -D -m0755 src/efibootmgr/efibootmgr /usr/sbin/efibootmgr
      install -v -D -m0644 src/man/man8/efibootmgr.8 \
                /usr/share/man/man8/efibootmgr.8


      GRUB-2.02~beta2 (depends on freetype2 if grub-mkfont is desired
               and on efibootmgr, efivars and efivarfs at run time.) 

         Download: http://alpha.gnu.org/gnu/grub/grub-2.02~beta2.tar.xz

         Prepare for compilation:
         ./configure --prefix=/usr  \
            --sbindir=/sbin        \
            --sysconfdir=/etc      \
            --disable-grub-emu-usb \
            --disable-efiemu       \
            --enable-grub-mkfont   \
            --with-platform=efi    \
            --target=x86_64        \
            --program-prefix=""    \
            --with-bootdir="/boot" \
            --with-grubdir="grub" \
            --disable-werror       
 
         Command explanation:

          --enable-grub-mkfont  This creates the build dependency on
             Freetype2. To remove this dependency do not use this switch
             and copy unicode.pf2 from the host system to /boot/grub of the
             LFS partition.  Alternatively, it can be downloaded from the
             internet.

          --program-prefix="" is a matter of convenience.  If not used,
             "x86_64" is inserted in all the grub executables.  For
             example, "grub-install" and "grub-mkconfig" become
             x86_64-grub-install and x86_64-grub-mkconfig.

          --with-platform=efi and --target=x86_64 are mandatory for the efi
             and x86_64 build

         The other configure options added to the ones in LFS-7.6 and
         LFS-SVN were employed to insure that grub is built and installed
         in the directories used in this hint.  They may be used or
         eliminated based on individual use and preference.


         Compile the package:
    
          make

         Install the package:

          make install


LFS CHAPTER 7:

     When constructing the file /etc/fstab, add the following lines:

      /dev/sda(x)     /boot/efi    vfat     defaults            0     1

      efivarfs       /sys/firmware/efi/efivars  efivarfs  defaults  0      1

     where /dev/sda(x) is the EFI partion


LFS CHAPTER 8:

   KERNEL CONFIGURATION OPTIONS FOR EFI

	CONFIG_EFI_PARTITION=y
	CONFIG_EFI=y
	CONFIG_EFI_STUB=y
        (The above makes the kernel bootable from the EFI partition if
          necessary)
	CONFIG_FB_EFI=y
	CONFIG_FRAMEBUFFER_CONSOLE=y
	# CONFIG_EFI_VARS is not set
	 Do not enable this option.  It creates runtime conflicts with
         EFIVARFS which replaces it.
	CONFIG_EFIVAR_FS=y
	# CONFIG_UEFI_CPER is not set
	# CONFIG_EARLY_PRINTK_EFI is not set

    The module EFI_VARS will soon be deprecated and is not used except in
    older kernels.
    The last two options are included as of kernel 3.13.3 and may be enabled
    based on personal and system needs.


USING GRUB TO SET UP THE BOOT PROCESS

   If grub was built without grub-mkfont and unicode.pf2 is in /boot/grub,
   skip to the next section.

   Otherwise:
   Download and install unifont-7.0.05:

   wget http://unifoundry.com/pub/unifont-7.0.05/font-builds/unifont-7.0.05.pcf.gz
   mkdir -pv /usr/share/fonts/unifont
   gunzip -c  unifont-7.0.05.pcf.gz > /usr/share/fonts/unifont/unifont.pcf
   grub-mkfont -o /usr/share/grub/unicode.pf2 \
         /usr/share/fonts/unifont/unifont.pcf


INSTALLING GRUB TO THE EFI PARTITION

  Installing GRUB to the EFI partition and creating an OS Boot Manager
  entry is the major difference between the recipes in this hint and the
  procedures in the LFS book.  In concept, it is not actually a divergence
  from the concepts of the book.  The instructions there install GRUB to
  the MBR, the MBR protected layer of a GPT disk or to a dedicated /boot
  partition.  The recipes here install GRUB to the EFI partition and
  generate an entry in the system's Boot Manager.  It is for the single
  command here that this hint was written and for which all the non-LFS
  packages were installed.

    grub-install --target=x86_64-efi --efi-directory=/boot/efi  \
       --bootloader-id=LFS --recheck --debug

    --efi-directory=<EFI Mount Point> not the actual EFI partition
    --bootloader-id=<some name> is the directory on the EFI partition to
      which the GRUB image is written.

  Running this command generates lots of output.  But at the end it will
  indicate that it was successful.  This command installs the GRUB image to
  /boot/efi/EFI/LFS/grubx64.efi and creates the entry "LFS" in the system's
  Boot Manager.

  To check it, inspect the contents of /boot/efi/EFI/LFS and, as root, run
  <efibootmgr>.  The results of this command will list the Boot Order and
  all the Boot Entries.  If the entry "LFS" does not appear, read the
  efibootmgr man page, create an entry and change the Boot Order to what is
  desired.

CONFIGURING GRUB

  Generate grub.cfg:

  cat > /boot/grub/grub.cfg << "EOF"
  # Begin /boot/grub/grub.cfg
  set default=0
  set timeout=5

  insmod ext2
  set root=(hd[x], gpt[y])
  # hd[x] is the drive of the LFS partion and gpt[y] is the partition

  insmod efi_gop
  insmod efi_uga
  insmod font
  if loadfont /grub/unicode.pf2; then
    loadfont /grub/unicode.pf2
    set gfxmode=auto
    insmod gfxterm
    set gfxpayload=keep
    terminal_output gfxterm
  fi

  menuentry "GNU/Linux, Linux <kernel name>"  {
    linux   /boot/vmlinuz-<kernel name>; root=/dev/sda[x] ro
  }  
  EOF

  Note that in "menuentry" /dev/sda[x] is the device of the LFS partition.

FINAL DISCUSSION:

As stated before, the implementation of UEFI firmware and its manipulation
depends hugely on the manufacturer.  As of the initial writing of this
hint, there is no standard approach.  Therefore, while the recipes here all
do what is advertised, regrettably the system may not default to the grub
boot loader "out of the box."  In that case, reviewing References 1-3, will
provide information that will lead users to a solution to the situation.
As always, one of the best resources is the {,B}LFS mailing lists.

At this point, it is worth stating that there are other helpfultools:
gummiboot and rEFInd are two of them.  They are described as Boot Managers,
but in fact are a user space layer between the OS Boot Manager and the Boot
Loader.  Information about both is in the references.

REFERENCES:

1.  Rod's Books  A collection of web page articles that goes into great
    detail about the concepts of  UEFI booting, partitioning and tools.
    The below URL goes right to the efi information.  www.rodsbooks.com is
    the main page and has many, many good articles.
  URL:  http://www.rodsbooks.com/efi-bootloaders/index.html

2.   "Unified Extensible Firmware Interface-ArchWiki"
  URL:  https://wiki.archlinux.org/index.php/
          Unified_Extensible_Firmware_Interface

3.  "GRUB-ArchWiki"
  URL:  https://wiki.archlinux.org/index.php/GRUB

4.  Google


ACKNOWLEDGEMENTS:
  * Craig Magee <lfs-support at lists.linuxfromscratch.org> for comments and testing
  * Pierre Labastie <http://lists.linuxfromscratch.org/listinfo/lfs-dev> for testing,
    font manipulation and comments.

TODO:
  *  Add paragraph and section numbers and TOC to make searchable
  *  Add appendix for migration from Legacy Boot to UEFI boot
  *  Add appendix for more options to default to GRUB
  *  Add appendix for LVM
  *  Add appendix for "standalone" GRUB on EFI partition independent
     from distro

CHANGELOG:
[TBD]
  * Initial hint.
