Update lfs-uefi hint (was: Re: [lfs-support] EFI grub.cfg)

Xi Ruoyao ryxi at stu.xidian.edu.cn
Mon Apr 9 03:12:06 PDT 2018


On 2018-04-08 10:33 -0500, Bruce Dubbs wrote:
> If someone wants to update the hint and send it to me, 
> than I will install it.

The attachment is an updated version based on my recent
LFS build.
-- 
Xi Ruoyao <ryxi at stu.xidian.edu.cn>
School of Aerospace Science and Technology, Xidian University
-------------- next part --------------
USING GRUB ON UEFI

AUTHOR: Dan McGhee, Kevin M. Buckley, and Xi Ruoyao

DATE: 2018-04-09

LICENSE: GNU Free Documentation License Version 1.2

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

PRIMARY URI: https://linux.xidian.edu.cn/git/xry111/LFS-book/wiki/lfs-uefi
(Markdown formatted, update once the author has built a new LFS version)

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.

This version, hereafter referred to as "the 2018-04-09 hint", updates Dan 
McGhee and Kevin M. Buckley's original, dated 2017-02-07.

The 2018-04-09 hint saw the UEFI packages built against an LFS 8.2 systemd
installation that was already being booted using the existing host system's 
bootloaders.

Where possible, changes to the 2018-04-09 hint have been made so that it
should be obvious where the the 2018-04-09 and 2017-02-07 hint's differ.

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.

The 2018-04-09 hint refers to an LFS 8.2 system, built onto an x86_64 
machine from within a LFS 7.9 host, that had had never had a version of
windows installed on it, indeed the host contained one EFI directories
below `/boot/efi/EFI/`, namely `boot`, that having been installed by
the vendor of the computer.

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:

1. 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.
2. UEFI firmware uses Boot Managers to select Boot Loaders like GRUB or
  LILO.  They, themselves do not boot the machine.
3. 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.
4. There are additional tools that LFS needs in order to accomplish
  this mode of booting.
5. LFS can be built and booted as the instructions are written up to
  and including LFS-8.2.  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-8.2, or earlier, system.  This involves uninstalling
`GRUB-2.02`, 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 `FreeType` 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:
`dosfstools`, `popt` and `pciutils`.   Build and install `FreeType`
if building grub with `grub-mkfont` enabled.

The BLFS 8.2 `FreeType` instructions recommend that it be built after 
`which` and `libpng` have been installed, so it was, however, as the 
recommendation for "HarfBuzz" notes that one builds `FreeType` without 
it first, and then do a re-install, it wasn't thought necessary to do 
the re-install.

The `libpng` install did include the "apng" patch.

The 2017-02-07 hint suggests we need static library of popt.  But
now `efivar` no longer needs it.  So we can just follow BLFS
instruction to build these packages.

The 2017-02-07 hint gives instruction to build `dosfstools`, now we can
just follow BLFS instruction.

EFIVAR-34

The 2017-02-07 hint uses `efivar-30`, but it's known to cause some issues.
So we update to `efivar-34`.

Dependencies:
* Required: popt

Download:
* https://github.com/rhboot/efivar/releases/download/34/efivar-34.tar.bz2

Compile the package:

    make libdir=/usr/lib
    
  The meaning of the make parameter:

* `libdir=/usr/lib`: This option overrides the default library directory
of the package (`/usr/lib64`).

  Despite the Makefile having a `test` target, albeit one which isn't run
  by default, you SHOULD NOT run that `make test`, as it has been found
  to cause firmware bugs. Here are the thoughts on, and the exhortation
  not to do, this from the `efivar` community: 
  https://github.com/rhboot/efivar/issues/78 .

Install the package:

  Now as the `root` user:

    make libdir=/usr/lib install

EFIBOOTMGR-14

Dependencies:
* Required: `pciutils` and `efivars`
* Required (runtime): `dosfstools`

Download:
* https://github.com/rhinstaller/efibootmgr/releases/download/14/efibootmgr-14.tar.bz2

Compile the package:

    make
    
Install the package:

  Now as the `root` user:

    install -v -D -m0755 src/efibootmgr /usr/sbin/efibootmgr &&
    install -v -D -m0644 src/efibootmgr.8 \
            /usr/share/man/man8/efibootmgr.8

UNIFONT-10.0.07

Download:
* http://unifoundry.com/pub/unifont-10.0.07/font-builds/unifont-10.0.07.pcf.gz

Install the package:

  [NOTE] This package is not a tarball.  So DON'T (and you can't)
  `tar -xf` it and change to the unzipped directory like normal LFS/BLFS
  packages.

  As the `root` user:

    mkdir -pv /usr/share/fonts/unifont &&
    gunzip -c unifont-10.0.07.pcf.gz > \
     /usr/share/fonts/unifont/unifont.pcf

GRUB-2.02

Dependencies:
* Optional: `FreeType` (for `grub-mkfont` and `unicode.pf2`)
* Optional: `unifont` (for `unicode.pf2`)

  [NOTE] The 2017-02-07 hint installs `unicode.pf2` manually.
  However, if `freetype` and `unifont` are both installed, GRUB
  will build `unicode.pf2`, and `grub-install` will install the
  file automatically.  This is recommended in 2018-04-09 hint.

Download:
* https://ftp.gnu.org/gnu/grub/grub-2.02.tar.xz

Prepare for compilation:

  [NOTE] Some options in 2017-02-07 hint are no longer necessary.

	./configure --prefix=/usr  \
		--sbindir=/sbin        \
		--sysconfdir=/etc      \
		--disable-efiemu       \
		--enable-grub-mkfont   \
		--with-platform=efi    \
		--disable-werror

  The meaning of configure options:

* `--enable-grub-mkfont`: This ensures `grub-mkfont` to be built.
If `Freetype` is not installed, remove this option and then you
have to get `unicode.pf2` from other sources (either the host or
Internet).

* `--with-platform=efi`: This ensures `grub` to be built for EFI.

  If the optional dependencies are installed, `configure` should
  output the following information at last:

    grub-mkfont: Yes
    Build-time grub-mkfont: Yes
    With unifont from /usr/share/fonts/unifont/unifont.pcf
    
  That means `unicode.pf2` would be built and used.

Compile the package:

    make
    
Install the package:

  Now as the `root` user:

    make install
    
MODIFICATION OF /etc/fstab

  When constructing `/etc/fstab` in LFS chapter 8, add a line to
  mount EFI partition:

    /dev/<name of EFI partition>     /boot/efi    vfat     defaults            0     1
    
  Systemd would mount `efivarfs` automatically.  If using sysvinit,
  add another line to mount `efivarfs`:

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

  a) If you are going to be booting your UEFI-aware LFS system using a 
  non-LFS GRUB from your host AND if that GRUB is one (eg Fedora) 
  that allows for the kernel to be specified using that GRUB's  
  `linuxefi` attribute, so

     linuxefi  /path/to/kernel root=/path/to/root ro
     
  then you don't appear to need the `/etc/fstab` line, and indeed, 
  you'll get told during the boot that the mounter knows nothing
  about the efivars filesystem type. However, LFS's efibootmgr will
  still be capable of interrogating your UEFI environment.

  b) If the LFS system is booted from the LFS+Hint's grub, which doesn't
  appear to know about the "linuxefi" attribute so using

    linux  /path/to/kernel root=/path/to/root ro
    
  then, unless you have the efivars filesystem mounted, and you are
  able to, then LFS's efibootmgr will be **not** capable of interrogating
  your UEFI environment, and you'll be told that there is no `efivars`
  filesystem.

KERNEL CONFIGURATION OPTIONS FOR EFI

The LFS 8.2 kernel build's `make defconfig` populated a good number of
the EFI-related options on my UEFI-enabled hardware, however, so as to
make the 2014-10-16 hint's list of settings easier to find when coming 
to alter/set things, here is the list of the options along with the 
location of the various checkboxes and the settings they should have, 
as seen when starting from a `make menuconfig`:

     ## CONFIG_EFI_PARTITION=y

       Location:
         -> Enable the block layer
           -> Partition Types
             [*] Advanced partition selection
             ...
             [*] EFI GUID Partition support

     ## CONFIG_EFI=y
     ## CONFIG_EFI_STUB=y

       Location:
         -> Processor type and features
           [*] EFI runtime service support
           [*]   EFI stub support

     ## CONFIG_FB_EFI=y

       Location:
         -> Device Drivers
           -> Graphics support
             -> Frame buffer Devices
               [*] EFI-based Framebuffer Support

     ## CONFIG_FRAMEBUFFER_CONSOLE=y

       Location:
         -> Device Drivers
           -> Graphics support
             -> Console display driver support
               Framebuffer Console support      (Not available on mine)

     ## CONFIG_EFI_VARS is not set
     ## CONFIG_EFI_RUNTIME_MAP=y

       Location:
         -> Firmware Drivers
           -> EFI (Extensible Firmware Interface) Support
             < > EFI Variable Support via sysfs
             [*] Export efi runtime maps to sysfs


     ## CONFIG_EFIVAR_FS=y/m

        Location:
          -> File systems
            -> Pseudo filesystems
              [*] EFI Variable filesystem

Note: 

The only Kernel Config setting that a `make defconfig` didn't set on
the UEFI-enabled host was this one:

     ## CONFIG_EFI_STUB=y

and without that setting in the kernel, attempts to boot the LFS system
tell you that:

    Kernel doesn't support EFI handover

however, adding just that one Kernel Config setting sees you able to
boot into the LFS system using the host system's Grub.

`CONFIG_FB_EFI=y` seems not necessary if you have other FB devices
avaliable.  But without it you will lose some boot messages along
with the Tux logos on the FB.

USING GRUB TO SET UP THE BOOT PROCESS

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 --bootloader-id=LFS --recheck --debug &> grub.log

  `--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 (redirected to `grub.log`).
  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.
  
  If GRUB was built with `freetype` and `unifont`, `unicode.pf2` should be
  installed automatically now.  Issue:

    grep "unicode.pf2" grub.log
    
  You should see something like

    copying `/usr/share/grub/unicode.pf2' -> `/boot/grub/fonts/unicode.pf2'
    
  If not, you should get `unicode.pf2` from the host system or Internet,
  and install it into `/boot/grub/fonts`.

CONFIGURING GRUB

  Generate `grub.cfg`:

    cat > /boot/grub/grub.cfg << "EOF"
    # Begin /boot/grub/grub.cfg
    set default=0
    set timeout=5
    
    insmod gzio
    insmod part_gpt
    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 /boot/grub/fonts/unicode.pf2; then
      loadfont /boot/grub/fonts/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.

  [NOTE] From GRUB's perspective, the kernel files are relative
  to the partition used. If you used a separate `/boot` partition,
  remove `/boot` from the above linux line and path of `unicode.pf2`.
  You will also need to change the `set root` line to point to the
  boot 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 helpful tools:
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. URL:  https://google.com


ACKNOWLEDGEMENTS:
* Craig Magee for comments and testing.
* Pierre Labastie for testing, font manipulation and comments.
* Lei Niu for comments on efivar and grub.cfg issues.

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:
[2018-04-09]
    Updated for LFS 8.2
    Use BLFS-like format for package dependency list
    Use package name in BLFS (FreeType instead of Freetype2)
    Deleted dosfstools-3.0.28 (replaced by dosfstools-4.1 in BLFS)
    Updated efivar-30 to efivar-34
    Updated unifont-9.0.06 to unifont-10.0.07
    Updated GRUB-2.02~beta3 to GRUB-2.02
    Modified the hint to let GRUB install unicode.pf2 automatically
    Removed some options not necessary now
    Fixed path to unicode.pf2 in grub.cfg for those without /boot partition
    Copied note about seperated /boot partition for grub.cfg from LFS book
    Removed incorrect personal email addresses (they are LFS mail lists)
    Added URL of Google
    Adapted for checkHint script (AUTHORS to AUTHOR)

[2017-01-22]
    Updated for LFS 7.10 and "extra package" updates
    dosfstools-3.0.26 -> dosfstools-3.0.28
    efivar-0.12       -> efivar-30
    efibootmgr-0.9.0  -> efibootmgr-14
    unifont-7.0.05    -> unifont-9.0.06

[2014-10-16]
    Initial hint.


More information about the hints mailing list